基于MQTT协议进行应用开发

官方协议有句如下的话来形容MQTT的设计思想:

“It is designed for connections with remote locations where a "small code footprint" is required or the network bandwidth is limited.”

MQTT:开源、可靠、轻巧、简单,MQTT的传输格式非常精小,最小的数据包只有2个比特,且无应用消息头。
MQTT可以保证消息的可 靠性,它包括三种不同的服务质量(最多只传一次、最少被传一次、一次且只传一次),如果客户端意外掉线,可以使用“遗愿”发布一条消息,同时支持持久订 阅。MQTT在物联网以及移动应用中的优势有:
  • 可靠传输。MQTT可以保证消息可靠安全的传输,并可以与企业应用简易集成。
  • 消息推送。支持消息实时通知、丰富的推送内容、灵活的Pub-Sub以及消息存储和过滤。
  • 低带宽、低耗能、低成本。占用移动应用程序带宽小,并且带宽利用率高,耗电量较少。  
    因此MQTT被广泛应用于物联网。

源码位置,可下载时间最新的CODE:http://mosquitto.org/files/source/

截止到2016年6月,最新的code为:
mosquitto-1.4.9.tar.gz 
 
虚拟机搭建MQTT环境,进行MQTT初体验
参考:http://blog.csdn.net/xukai871105/article/details/39252653
 
安装:
# 下载源代码包 
wget http://mosquitto.org/files/source/mosquitto-1.4.9.tar.gz
# 解压
tar zxfv mosquitto-1.4.9.tar.gz
# 进入目录
cd mosquitto-1.4.5
# 编译
make
# 安装
sudo make install
 
 
 
安装mosquitto时候出现这样的问题
1.mosquitto_internal.h:51:20: error: ares.h: No such file or directory
其实是因为它新加的功能的原因。打开config.mk文件。
吧WITH_SRV:=yes 改成WITH_SRV:=no 就可以编译了
 
或者sudo apt-get install libc-ares-dev
 
2,
找不到libmosquitto.so.1
error while loading shared libraries: libmosquitto.so.1: cannot open shared object file: No such file or directory
【解决方法】——修改libmosquitto.so位置
# 创建链接
sudo ln -s /usr/local/lib/libmosquitto.so.1 /usr/lib/libmosquitto.so.1
# 更新动态链接库
sudo ldconfig
 
简单测试
 一个完整的MQTT示例包括一个代理器,一个发布者和一个订阅者。测试分为以下几个步骤:
【1】启动服务mosquitto。
【2】订阅者通过mosquitto_sub订阅指定主题的消息。
【3】发布者通过mosquitto_pub发布指定主题的消息。
【4】代理服务器把该主题的消息推送到订阅者。
 
【测试说明】
    测试环境: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里面有初始化。

 

 

 

posted @ 2016-11-17 11:26  琳麻雀  阅读(2894)  评论(0编辑  收藏  举报