【测试说明】
测试环境:ubuntu 14.04 虚拟机
在本例中,发布者、代理和订阅者均为localhsot,但是在实际的情况下三种并不是同一个设备,在mosquitto中可通过-h(--host)设置主机名称(hostname)。为了实现这个简单的测试案例,需要在linux中打开三个控制台,分别代表代理服务器、发布者和订阅者。
启动代理服务
mosquitto -v
【-v】打印更多的调试信息
订阅主题
mosquitto_sub -v -t SmartAudio_zhangling
【-t】指定主题,此处为SmartAudio_zhangling
【-v】打印更多的调试信息
root@ubuntu:/opt/mqtt/mosquitto-1.4.10/src# ./mosquitto -c ../mosquitto.conf
1474336624: mosquitto version 1.4.10 (build date 2016-09-19 18:55:57-0700) starting
1474336624: Config loaded from ../mosquitto.conf.
1474336624: Opening ipv4 listen socket on port 1883.
1474336624: Opening ipv6 listen socket on port 1883.
1474336624: Error: Invalid user 'mosquitto'.
root@ubuntu:/opt/mqtt/mosquitto-1.4.10/src#
解决方法:
1.修改配置文件:mosquitto.conf ,增加登录的用户
2.执行 adduser mosquitto
发布消息
mosquitto_pub -t SmartAudio_zhangling -m 12
【-t】指定主题
【-m】指定消息内容
【-f】 是可以发送文件
通过-f传递的文件上限默认是256M。逻辑中有对文件大小的判断,超过256M的文件则不传。不知道这里如果吧这个值修改更大,会不会产生影响,笔者没有尝试,因为传7M的文件都感觉很慢。(这个问题在MQTT协议介绍中可以得到答案,MQTT文件长度的表示是用1至4个字节来表示,而其表示长度的方式又有特殊的加密方式,按照这种方式,其最大表示的长度为256M)
如果不是在同一个设备,可通过-h指定代理的IP。
(另外还有一个mosquitto_passwd,用于管理密码,应该是关闭SSL的原因)
运行结果
当发布者推送消息之后,订阅者获得以下内容
=======================mosquitto部分,嵌入音箱端及手机微信端,可实现广域网内手机微信对音箱的控制=================================
服务器部分
mosquitto服务器部分,肖同学负责搭建好。音箱端与手机端pub和sub都是通过服务器进行消息传递。IP地址为"120.76.30.18";
音箱部分
进入网络模式下,则需要开启一个线程,用来开启mosquitto subscribe 订阅一个主体。一个音箱实体对应一个主体。其他客户端可通过这个主题,来与音箱端实现链接。
本项目,定义的主题名字利用音箱的物理地址的唯一性,如SmartAudio_MacAddress。
手机微信部分
而,手机客户端如何得知音箱端这个主题,方法一,是微信客户端有提供对应开发包,局域网设备发现,但是这个功能依赖微信端,尚不稳定,最后并没采用;
方法二:将主题生成二维码,贴在音箱上。目前采用方法二。
而协议约定客户端名字,可以是b_MacAddress。
而手机微信部分是客户端IOS/Android同仁负责,这里不作介绍。
下面主要介绍音箱部分移植mosquitto进行应用开发的内容:
开启订阅主题线程
pthread_create(&mosquitto_client_thread_id, NULL, mosquitto_sub_start, NULL)
mosquitto_sub_start 是利用mosquitto sub的源码加以修改。
核心内容是,
两个回调函数的注册
mosquitto_connect_callback_set(mosq, my_connect_callback);
mosquitto_message_callback_set(mosq, my_message_callback);
其中my_connect_callback是mosquitto_loop_forever这个一直存在的循环函数在收到服务器传递回来CONNACK信息(见_mosquitto_handle_connack),则会被触发,用来呼叫mosquitto_subscribe完成订阅。
其中my_message_callback则是用于音箱端应用程序的开发,用来接收手机微信端传递过来的内容。与手机客户端定义交互的协议,用于控制音箱的推歌、上下首切换、音源切换、网络模式的切换、音量大小的改变等等。
交互的内容采用json包,因此需要进行json包的解析和封装。
正确完成音箱端的订阅,
注意设定好:
cfg.port = 1883;
cfg.topics[cfg.topic_count-1] = strdup(deviceName);
cfg.host = strdup(serverIp); //服务器地址
这里初始化了一个属于音箱端全局的mosq,可用它关联pub和sub;(pub和sub共用一个全局mosq即可,并不需要分别申请一个mosq)
音箱端部分,需要pub消息给手机微信端。采用mosquitto_pub_start发送消息。这个不同于sub是一个一直存在的线程,pub属于一次性,消息传递完毕即结束。
mosquitto_pub_start 中 全局变量pub_topic ,在mosquitto_sub_start里面有初始化。