STM32+W5500+MQTT+Android實(shí)現(xiàn)遠(yuǎn)程數(shù)據(jù)采集及控制
最近在學(xué)習(xí)MQTT,發(fā)現(xiàn)MQTT還是挺好用的,于是花了點(diǎn)時(shí)間做了一個(gè)簡單的應(yīng)用示例,希望能給需要做這方面的人一些參考。
相關(guān)背景知識(shí):http://www.embed-net.com/thread-224-1-1.html
具體功能為:
1,STM32F405為主控芯片,它通過傳感器采集環(huán)境數(shù)據(jù),比如溫度,濕度,光照度,大氣壓強(qiáng)等;
2,主控芯片通過W5500模塊將測量的數(shù)據(jù)通過MQTT協(xié)議方式發(fā)布到MQTT服務(wù)器(服務(wù)器域名和IP見固件程序);
3,主控訂閱LED燈控制的消息,當(dāng)接收到對應(yīng)的控制指令后點(diǎn)亮或者熄滅對應(yīng)的LED燈;
4,安卓手機(jī)端訂閱傳感器數(shù)據(jù)的消息,當(dāng)接收到消息后將傳感器數(shù)據(jù)在界面顯示;
5,安卓手機(jī)可發(fā)送點(diǎn)亮或者熄滅LED燈的指令到服務(wù)器,然后服務(wù)器會(huì)將該指令轉(zhuǎn)發(fā)給STM32主控,然后STM32主控解析該指令并執(zhí)行指令。
1 單片機(jī)端實(shí)現(xiàn)
MQTT協(xié)議是基于TCP的協(xié)議,所以我們只需要在單片機(jī)端實(shí)現(xiàn)TCP客戶端代碼之后就很容易移植MQTT了,STM32F4+W5500實(shí)現(xiàn)TCP客戶端的代碼我們以前已經(jīng)實(shí)現(xiàn)過,代碼下載地址為:
http://www.embed-net.com/thread-87-1-1.html
當(dāng)然,如果你想在代碼里面直接使用服務(wù)器域名方式進(jìn)行連接,我們還得在TCP客戶端代碼里面集成DNS的代碼,當(dāng)然在上面這個(gè)連接里面也有相關(guān)的代碼。
MQTT代碼源碼下載地址:
http://www.eclipse.org/paho/
在STM32這邊我們使用的是C/C++ MQTT Embedded clients代碼。
硬件連接如下圖所示:
1.1 MQTT的移植
MQTT的移植非常簡單,將C/C++ MQTT Embedded clients的代碼添加到工程中,然后我們只需要再次封裝4個(gè)函數(shù)即可:
int transport_sendPacketBuffer(unsigned char* buf, int buflen);
int transport_getdata(unsigned char* buf, int count);
int transport_open(void);
int transport_close(void);
transport_sendPacketBuffer:通過網(wǎng)絡(luò)以TCP的方式發(fā)送數(shù)據(jù);
transport_getdata:TCP方式從服務(wù)器端讀取數(shù)據(jù),該函數(shù)目前屬于阻塞函數(shù);
transport_open:打開一個(gè)網(wǎng)絡(luò)接口,其實(shí)就是和服務(wù)器建立一個(gè)TCP連接;
transport_close:關(guān)閉網(wǎng)絡(luò)接口。
如果已經(jīng)移植好了socket方式的TCP客戶端的程序,那么這幾個(gè)函數(shù)的封裝也是非常簡單的,程序代碼如下所示:
int transport_sendPacketBuffer(unsigned char* buf, int buflen)
{
return send(SOCK_TCPS,buf,buflen);
}
int transport_getdata(unsigned char* buf, int count)
{
return recv(SOCK_TCPS,buf,count);
}
int transport_open(void)
{
int32_t ret;
//新建一個(gè)Socket并綁定本地端口5000
ret = socket(SOCK_TCPS,Sn_MR_TCP,5000,0×00);
if(ret != SOCK_TCPS){
printf(“%d:Socket Error”,SOCK_TCPS);
while(1);
}else{
printf(“%d:Opened”,SOCK_TCPS);
}
//連接TCP服務(wù)器
ret = connect(SOCK_TCPS,domain_ip,1883);//端口必須為1883
if(ret != SOCK_OK){
printf(“%d:Socket Connect Error”,SOCK_TCPS);
while(1);
}else{
printf(“%d:Connected”,SOCK_TCPS);
}
return 0;
}
int transport_close(void)
{
close(SOCK_TCPS);
return 0;
}
完成了這幾個(gè)函數(shù),然后我們就可以根據(jù)官方提供的示例代碼實(shí)現(xiàn)我們自己的代碼了,比如我們向代理服務(wù)器發(fā)送一個(gè)消息的代碼如下所示:
int mqtt_publish(char *pTopic,char *pMessage)
{
int32_t len,rc;
MQTTPacket_connectData data = MQTTPacket_connectData_initializer;
unsigned char buf[200];
MQTTString topicString = MQTTString_initializer;
int msglen = strlen(pMessage);
int buflen = sizeof(buf);
data.clientID.cstring = “me”;
data.keepAliveInterval = 5;
data.cleansession = 1;
len = MQTTSerialize_connect(buf, buflen, &data);
topicString.cstring = pTopic;
len += MQTTSerialize_publish(buf + len, buflen – len, 0, 0, 0, 0, topicString, (unsigned char*)pMessage, msglen);
len += MQTTSerialize_disconnect(buf + len, buflen – len);
transport_open();
rc = transport_sendPacketBuffer(buf,len);
transport_close();
if (rc == len)
printf(“Successfully published”);
else
printf(“Publish failed”);
return 0;
}
評論