基于mini2440嵌入式linux上整合一套Domoticz智能家居系统(十一)使用domoticz+mosquitto+Android客户端实现控制STM32板上的LED(二)
2017-04-28 03:50
731 查看
本文在前一篇实现了STM32平台利用MQTT协议对接domoticz平台控制LED灯的基础上,完善了网络连接和MQTT的broker连接过程,实现了断网重连功能。
实现部分主要在rt-thread\components\external\paho-mqtt\MQTTClient-C\samples\domoticz\DomoticzThread.c中。
在前一篇的源码基础上稍作改动,如下所示:
DomoticzThread.c:
运行效果:
domoticz这边建立三个LED灯,idx分别为1,2,3
STM32开发板上的LED0的idx为2,LED1的idx为3。
也就是domoticz平台上的“LED灯2”对应开发板LED0;
domoticz平台上的“LED灯3”对应开发板LED1。
好了,现在在STM32开发板上看效果:
1、LED0亮:
2、LED1亮:
3、LED0、LED1都亮:
4、在mini2440板上运行前面做的mqtt客户端程序。
mini2440上也控制两个灯LED0,对应的idx为1;LED1,对应idx为2。
也就是说mini2440板上的LED1和STM32板上的LED0的idx是相同的,看看能不能同时点亮。
点亮mini2440的LED0:
下面将看到在domoticz上点亮LED2灯可以同时点亮mini2440上的LED1和STM32上的LED0:
都点亮:
5、Android手机实际控制效果:
6、当MQTT的broker被关闭并重新打开后,STM32板的反应:
在程序中,其实只要ping 10次没有结果,就会断开MQTT连接和socket连接,并重新连接。
如果有网络错误,连接不上会,延时一段时间,然后重新连接socket,然后连MQTT的broker,然后订阅。
具体如上述源码中处理那样。
附:STM32开发板的整个源码工程下载地址:
http://download.csdn.net/download/sqshining/9828049
实现部分主要在rt-thread\components\external\paho-mqtt\MQTTClient-C\samples\domoticz\DomoticzThread.c中。
在前一篇的源码基础上稍作改动,如下所示:
DomoticzThread.c:
#include <rtthread.h> #include "MQTTClient.h" //#include "led.h" #include "DomoticzMessageParser.h" //#define __DEBUG #ifdef __DEBUG #include <stdarg.h> #include <string.h> static const char *getCurrentFileName() { const char *p = strrchr(__FILE__,'\\'); return ++p; } #define dprintf(fmt,...) rt_kprintf("%s,line:%d,"fmt,getCurrentFileName(),__LINE__,##__VA_ARGS__) #else #define dprintf(fmt,...) #endif struct opts_struct { char* clientid; int nodelimiter; char* delimiter; enum QoS qos; char* username; char* password; char* host; int port; int showtopics; } opts = { (char*)"subscriber on STM32", 0, (char*)"\n", QOS2, NULL, NULL, (char*)"192.168.1.230", 1883, 0 }; int is_over; void quit_domoticz_thread(void) { is_over = 1; } //================== Added 2017-Apr-27 8:06:53 start ================== //处理连接的状态机结构 typedef struct { enum{ UNCONNECTED = 0, NETWORK_CONNECTED=1, MQTT_CONNECTED=2, SUBSCRIBING_SUCCESS=3, WAIT_TIME_OUT=4, //SUBSCRIBING_FAILURE = 4 }state; int timeout_s;//超时时间,单位为秒 int times_count;//累计连续尝试连接次数,在连接成功后清零 }Connection_t; void connect_time_out(void * data) { Connection_t* con =(Connection_t*)data; if(con && con->timeout_s>0) { con->timeout_s --; } } #define NETWORK_CONNECT_TIMEOUT 5 //5s #define MAX_NETWORK_CONNECT_TIMES 5 #define MQTT_CONNECT_TIMEOUT 1 //1s #define MAX_MQTT_CONNECT_TIMES 5 #define SUBSCRIB_TIMEOUT 1 //1s #define MAX_SUBSCRIB_TIMES 5 #define MAX_NO_PING_RESPONS_TIMES 10 Connection_t connection={UNCONNECTED,NETWORK_CONNECT_TIMEOUT,0}; //================== Added 2017-Apr-27 8:06:53 end =================== void messageArrived(MessageData* md) { MQTTMessage* message = md->message; #if 0 /* Commented @ 2017-Apr-23 1:18:29 */ if (opts.showtopics) rt_kprintf("%.*s\t", md->topicName->lenstring.len, md->topicName->lenstring.data); if (opts.nodelimiter) rt_kprintf("%.*s", (int)message->payloadlen, (char*)message->payload); else rt_kprintf("%.*s%s", (int)message->payloadlen, (char*)message->payload, opts.delimiter); #endif /* Commented */ dprintf("payloadlen=%d,%s\n",(int)message->payloadlen,(char*)message->payload); dprintf("strlen(payload)=%d\n",strlen((char*)message->payload)); //fflush(stdout); ParseDomoticzMessage((char*)message->payload); //dprintf("MSG: qos %d, retained %d, dup %d, packetid %d\n", message->qos, message->retained, message->dup, message->id); } void set_host(char *host) { opts.host = host; } void domoticz_thread_entry(void* parameter) { int rc = 0; unsigned char buf[512]={0};//buf[100]; unsigned char readbuf[512]={0};//readbuf[100]; char* topic = "domoticz/out"; Network n; MQTTClient c; MQTTPacket_connectData data = MQTTPacket_connectData_initializer; rt_timer_t timer = rt_timer_create("connect_timer", connect_time_out, &connection, RT_TICK_PER_SECOND, RT_TIMER_FLAG_PERIODIC); is_over = 0; rt_kprintf("domoticz_thread_entry\n"); //================== Added 2017-Apr-26 2:36:53 start ================== RegisterHardware(Create_LED0(),2); RegisterHardware(Create_LED1(),3); OpenHardwares(); SetupDomoitczMessageParser(); SetEnableParseItem(KEY_IDX); SetEnableParseItem(KEY_NVALUE); SetEnableParseItem(KEY_SWITCH_TYPE); initHardwareSettings(); //================== Added 2017-Apr-26 2:36:53 end =================== NetworkInit(&n); //dprintf("readbuf=%p,readbuf size=%u\n",readbuf,sizeof(readbuf)); data.willFlag = 0; data.MQTTVersion = 3; data.clientID.cstring = opts.clientid; data.username.cstring = opts.username; data.password.cstring = opts.password; data.keepAliveInterval = 60; data.cleansession = 1; rt_timer_start(timer); while(!is_over) { switch(connection.state) { case UNCONNECTED: if(connection.timeout_s>0) continue; rc = NetworkConnect(&n, opts.host, opts.port); if(rc==0) { connection.state = NETWORK_CONNECTED; connection.times_count = 0; rt_kprintf("NetworkConnect ok!\n"); rt_kprintf("Connecting to %s:%d\n", opts.host, opts.port); MQTTClientInit(&c, &n, 1000, buf, sizeof(buf), readbuf, sizeof(readbuf)); } else if(connection.times_count <MAX_NETWORK_CONNECT_TIMES) { connection.times_count++; connection.timeout_s = NETWORK_CONNECT_TIMEOUT; } else {//reset system cpu,restart connection.times_count=0; rt_thread_delay(RT_TICK_PER_SECOND*600);//10分钟后再连 //goto exit; } break; case NETWORK_CONNECTED: if(connection.timeout_s>0) continue; dprintf("\n"); rc = MQTTConnect(&c, &data); dprintf("\n"); if(rc == SUCCESS) { connection.state = MQTT_CONNECTED; connection.times_count = 0; rt_kprintf("MQTTConnected!\n"); dprintf("Subscribing to %s\n", topic); } else if(connection.times_count <MAX_MQTT_CONNECT_TIMES) { rt_kprintf("MQTTConnect times=%d, err:%d! \n",connection.times_count,rc); connection.times_count++; connection.timeout_s = MQTT_CONNECT_TIMEOUT; } else {//重新进行network连接 dprintf("\n"); NetworkDisconnect(&n); connection.state = UNCONNECTED; connection.times_count=0; rt_thread_delay(RT_TICK_PER_SECOND*600);//10分钟后再连 } break; case MQTT_CONNECTED: if(connection.timeout_s>0) continue; rc = MQTTSubscribe(&c, topic, opts.qos, messageArrived); if(rc == SUCCESS) { rt_kprintf("Subscribed %s\n", topic); connection.state = SUBSCRIBING_SUCCESS; connection.times_count = 0; } else if(connection.times_count <MAX_SUBSCRIB_TIMES) { rt_kprintf("MQTTSubscribe times=%d, err:%d! \n",connection.times_count,rc); connection.times_count++; connection.timeout_s = MQTT_CONNECT_TIMEOUT; } else { //1分钟后重新进行network连接 rt_kprintf("MQTTSubscribe err! reconnect after 1 min\n"); MQTTDisconnect(&c); NetworkDisconnect(&n); connection.state = UNCONNECTED; connection.times_count=0; rt_thread_delay(RT_TICK_PER_SECOND*60);//1分钟后再连 } break; case SUBSCRIBING_SUCCESS: MQTTYield(&c, 1000); if(c.ping_outstanding==1) { connection.times_count++; if(connection.times_count>MAX_NO_PING_RESPONS_TIMES) { rt_kprintf("network err! reconnecting ...\n"); MQTTDisconnect(&c); NetworkDisconnect(&n); connection.state = UNCONNECTED; connection.times_count = 0; //rt_thread_delay(RT_TICK_PER_SECOND*60);//1分钟后重连 } } else { connection.times_count = 0; } break; default: break; } } exit: rt_kprintf("Stopping\n"); MQTTDisconnect(&c); NetworkDisconnect(&n); rt_timer_delete(timer); } void domoticz_thread_init(void) { rt_thread_t domoticz_thread; domoticz_thread = rt_thread_create("DomoticzThread", domoticz_thread_entry, RT_NULL, 0xf00, 28, 10); if (domoticz_thread != RT_NULL) rt_thread_startup(domoticz_thread); } #ifdef RT_USING_FINSH #include <finsh.h> FINSH_FUNCTION_EXPORT(set_host, set domoticz host ip addr); FINSH_FUNCTION_EXPORT(domoticz_thread_init,to run domoticz thread ); FINSH_FUNCTION_EXPORT(quit_domoticz_thread,quit domoticz thread ); #endif
运行效果:
domoticz这边建立三个LED灯,idx分别为1,2,3
STM32开发板上的LED0的idx为2,LED1的idx为3。
也就是domoticz平台上的“LED灯2”对应开发板LED0;
domoticz平台上的“LED灯3”对应开发板LED1。
好了,现在在STM32开发板上看效果:
1、LED0亮:
2、LED1亮:
3、LED0、LED1都亮:
4、在mini2440板上运行前面做的mqtt客户端程序。
mini2440上也控制两个灯LED0,对应的idx为1;LED1,对应idx为2。
也就是说mini2440板上的LED1和STM32板上的LED0的idx是相同的,看看能不能同时点亮。
点亮mini2440的LED0:
下面将看到在domoticz上点亮LED2灯可以同时点亮mini2440上的LED1和STM32上的LED0:
都点亮:
5、Android手机实际控制效果:
6、当MQTT的broker被关闭并重新打开后,STM32板的反应:
在程序中,其实只要ping 10次没有结果,就会断开MQTT连接和socket连接,并重新连接。
如果有网络错误,连接不上会,延时一段时间,然后重新连接socket,然后连MQTT的broker,然后订阅。
具体如上述源码中处理那样。
附:STM32开发板的整个源码工程下载地址:
http://download.csdn.net/download/sqshining/9828049
相关文章推荐
- 基于mini2440嵌入式linux上整合一套Domoticz智能家居系统(九)使用domoticz+mosquitto+Android客户端实现控制mini2440上的LED(二)
- 基于mini2440嵌入式linux上整合一套Domoticz智能家居系统(八)使用domoticz+mosquitto+Android客户端实现控制mini2440上的LED(一)
- 基于mini2440嵌入式linux上整合一套Domoticz智能家居系统(六)使用domoticz联合arm上的mosquitto实现Android客户端远程控制
- 基于mini2440嵌入式linux上整合一套Domoticz智能家居系统(四)交叉编译OpenSSL、c-ares、e2fsprogs和mosquitto
- 《基于Android微博整合客户端的设计与实现》毕业设计中期考核表
- 基于mini2440嵌入式linux上整合一套Domoticz智能家居系统(五)交叉编译并安装zlib、curl、boost和domoticz
- 基于mini2440嵌入式linux上整合一套Domoticz智能家居系统(一)前言
- 基于mini2440嵌入式linux上整合一套Domoticz智能家居系统(七)交叉编译paho.mqtt.embedded-c库和嵌入式linux样例程序
- 《基于Android微博整合客户端的设计与实现》毕业设计论文任务书
- 基于mini2440嵌入式linux上整合一套Domoticz智能家居系统(三)编译并安装cmake和git工具
- 《基于Android微博整合客户端的设计与实现》毕业设计论文开题报告
- 基于Android的小巫新闻客户端开发---显示新闻详细内容业务逻辑实现
- 基于XMPP实现的Openfire的配置安装+Android客户端的实现
- Android基于XMPP Smack Openfire开发IM【四】初步实现两个客户端通信
- 基于Android的小巫新闻客户端开发---显示新闻详细内容业务逻辑实现
- android 使用shell command实现对设备控制,实现按坐标点击
- 基于XMPP实现的Openfire的配置安装+Android客户端的实现
- 使用input输入子系统实现对tiny6410LED灯的控制
- MVC学习十一:浅谈在ASP.NET MVC3中使用IClientValidatable接口实现客户端和服务器端同时验证
- 基于ichartjs图形库在android上使用HTML动态实现多数据源的面积图