您的位置:首页 > 运维架构 > Linux

基于mini2440嵌入式linux上整合一套Domoticz智能家居系统(八)使用domoticz+mosquitto+Android客户端实现控制mini2440上的LED(一)

2017-04-16 04:24 495 查看
本篇将在上一篇交叉编译paho.mqtt.embedded-c官方的源代码例程基础上,稍作修改,尝试实现domoticz+mosquitto联合做服务器,使用Android客户端APP或浏览器对mini2440上的LED做亮灭控制。

一、在stdoutsub.c上简单写一个domoticz/out的MQTT消息处理程序来控制mini2440上的LED0。

1、在stdoutsub.c中合适的位置添加以下代码:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>

char parse_buf[16][128];//char parse_buf[13][128];
int on;
int led_no = 0;
int led_fd;

int split(char dst[][128], char* str, const char* delim)
{
int n = 0;
char *result = NULL;
result = strtok(str, delim);
while( result != NULL )
{
strcpy(dst[n++], result);
//printf("result=%s\n",result);
result = strtok(NULL, delim);
}
return n;
}

int ParseDomoticzMessage(char* str)
{
int nCount = split(parse_buf,str,"\n");
//printf("---------------------------------------\n");
int i;
int idx;
int state;
for(i =0;i<nCount;i++)
{
if(sscanf(parse_buf[i],"   \"idx\" : %d,",&idx)>0)
{
printf("idx=%d\n",idx);
break;
}
}
if(idx==1)//domoticz分配的设备索引号为1
{
for(i =0;i<nCount;i++)
{
if(sscanf(parse_buf[i],"   \"nvalue\" : %d,",&state)>0)
{
printf("state=%d\n",state);
ioctl(led_fd, state, led_no);
break;
}
}
}
return 1;
}


2、在void messageArrived(MessageData* md)函数里最下面添加:

ParseDomoticzMessage((char*)message->payload);


3、在main函数最开始地方添加:

led_fd = open("/dev/leds0", 0);
if (led_fd < 0) {
led_fd = open("/dev/leds", 0);
}
if (led_fd < 0) {
perror("open device leds");
exit(1);
}
printf("led_fd=%d\n",led_fd);
ioctl(led_fd, 0, led_no);


4、然后在最下面返回0前加入两行:

close(led_fd);
exit(0);


注:之所以加入exit(0);是因为,源代码似乎还有点bug,运行起来后,结束进程使用ctrl+c会导致段错误:

Segmentation fault

原因不明,有待追踪,后面再解决吧。

如果不加exit目前不影响正常使用,能正常返回。

5、然后用重新make。

然后在mini2440上运行,首在浏览器上控制

假设初始化状态为led0是灭的,如下图所示:



现在点浏览器上灯泡,可以看到LED灯亮起来了:



再点一次,就灭掉了:



接下来,用Android手机测试一下:

开灯:



关灯:



测试成功!

二、关于源代码中控制实现部分的一些说明:

1、使用strtok函数把domoticz/out主题的消息按换行符分割成若干子字符串,存在parse_buf中,后续处理;

2、两次使用sscanf函数,分别读取idx值和nvalue值,这是个功能很强大的函数。后面还会使用到。

3、关于domoticz/out的MQTT主题消息格式,简抄mini2440串口打印实际值如下:

{
"Battery" : 255,
"RSSI" : 12,
"dtype" : "Light/Switch",
"id" : "00014051",
"idx" : 1,
"name" : "LED鐏,
"nvalue" : 1,
"stype" : "Switch",
"svalue1" : "0",
"switchType" : "On/Off",
"unit" : 1
}


我们在函数中,遍历整个二维数组parse_buf,对每一行在sscanf函数中进行匹配,连空格都要匹配,所以要严格按照这个格式到匹配字符串中。

在此次处理中连花括号算在内,分成了13行,所以parse_buf其实定义13行就够了。

我在处理过程中,犯过一个错误:只是关注了消息主体部分,忘了花括号,而定义了11行二维数组parse_buf,导致在分割字符串的时候,对数组越界写入,导致前面定义led_fd被意外改变。

所以需要注意这个问题。

后面将会写一个简单的处理框架,实现更加复杂的消息解析,并避免以上的种种问题。

domoticz/out的MQTT消息格式请参考:

https://www.domoticz.com/wiki/MQTT

$(".MathJax").remove();
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐