Linkit 系列博文:
联发科Linkit 7688 (1) 上手及在Mac下搭建OpenWrt交叉编译环境,C语言编译Hello,World
联发科Linkit 7688 (2)GPIO基本操作与C语言编程
联发科Linkit 7688 DUO(3): 通过 Arduino 控制外设和传感器
Linkit 7688 DUO(4): 接上各种Arduino传感器和模块——基础篇
Linkit 7688 DUO(5) 接上各种Arduino传感器和模块—扩大篇
Linkit 7688 DUO(6) 加入MQTT物联网协议
本篇介绍 将 MQTT物联网协议加载到 Linkit 7688 DUO开发板上 ( 其中的源码和方法也适用于所有的Linux系统、也合适于Windows系统)
MQTT是IBM开发的1种物联网即时通讯协议,该协议支持所有平台,几近可以把所有联网物品、电脑APP、手机APP、网页等连接起来,让它们随时相互交换信息。
有了MQTT协议,Linkit 7688开发板就能够称得上物联网开发板了,可以实现很多场景,比如:手机远程控制、网页远程控制、服务器监测物体状态等等。
1、MQTT协议简介
1,MQTT是1种基于TCP的网络消息协议,用于发送和接收消息。
在1个MQTT网络中,有1个服务器和多个客户端。 每一个客户端以TCP Socket与服务器连接,并保持为长连接。
客户端可以是1个联网物体、电脑软件、手机APP、乃至是网页。以下图:
2, 消息传输采取发布/定阅(publish/subscribe)模式。
客户端可以发布(publish)消息, 每一个消息由1个主题(topic)和1个消息内容组成。比如:某温度传感器发布1个消息: topic = "sensor1/temperature", message="25“
客户端可以定阅(subscribe)1个或多个主题的消息。 当网络中有人发布了这些主题的消息,则客户端将收到这条消息。比如: 手机App定阅了 “sensor1/temperature"消息,则上述消息将被收到, 手机App就知道sensor1的温度值了。
由于客户端与服务器保持着Socket长连接,消息将立即实时推送到客户端,也就是说:PUSH到客户端。
MQTT服务器的主要作用是接收-转发:接收消息、判断哪些客户端定阅了该主题的消息,PUSH给相应客户端。
这类机制,可以实现1对1发送消息,也能够实现1对多发送消息(群发)。
利用场景举例:
场景1: 手机APP发布查温度的消息, 各个传感器装置收到消息后,发布温度消息。则手机就能够搜集到各个传感器的温度。
场景2: 当火警传感器装置检测到起火后,发布消息。 则定阅了该类型消息的手机、电脑等都可立即收到火警。
3,MQTT的消息包传输数据量很小(固定长度的头部仅为 2 字节),能充分下降网络流量,非常合适于低带宽、不可靠连接、嵌入式装备。
同时非常合适于手机等移动通讯环境,可以省流量、省电。因此,有人用MQTT作为手机PUSH使用。
4, 为保障消息有效力到达,MQTT定义了3种消息发布服务质量(Qos, Quality Of Service):
“最多1次”(At most once),开消最小,消息发布完全依赖底层 TCP/IP 网络,会产生消息丢失或重复。这1级别可用于以下情况,环境传感器数据,丢失1次读记录无所谓,由于不久后还会有第2次发送。
“最少1次”(At least once),确保消息到达,但消息重复可能会产生。
“只有1次”(Exactly once),确保消息到达1次。这1级别可用于以下情况,在计费系统中,消息重复或丢失会致使不正确的结果。经常使用于精确控制。
每条消息都可以有自己的Qos定义。每个客户端定阅某主题时,也能够指定Qos.
5, MQTT协议由IBM公司于1999年提出,经过量年发展已比较成熟,目前版本是3.1.1。服务器和客户端均有多个开源实现,支持各类操作系统和开发语言。
2、合适嵌入式装备的MQTT协议客户端(C语言实现)
对Linkit 7688开发板,我选取 “Eclipse Paho C” 的MQTT 客户端开源代码库 。其主页在这:https://www.eclipse.org/paho/clients/c/
这个代码库是IBM公司提供的,Eclipse项目组保护的,可以称为官方的。
我的使用方式是: 将它作为1个函数库, 在Linkit 7688上编写C语言程序,实现MQTT消息收发。
这个库有1点点复杂,需要对协议比较了解。如果你要完全弄懂它,需要先读它的文档(http://www.eclipse.org/paho/files/mqttdoc/Cclient/index.html)
我们1般总是喜欢把复杂的事情简单化,因此,我对这个库进行了封装, 变成几个函数, 不需要懂太多就能够用.
库和例程在我的资源中下载: MQTT客户端Paho C代码
解压后,其中mqtt目录是Paho C所有的库文件( 原本的文件都没改,我增加了 mqtt_client.c , mqtt_client.h 两个文件),使用时将mqtt目录复制到你的项目文件夹中便可。
在使用前,需要有1个测试用的MQTT服务器, 我用的是 IBM提供的测试服务器: messagesight.demos.ibm.com, 端口是1883 (1883是MQTT的默许端口)
同时需要有1个测试用的MQTT客户端作为对端,我用的是IBM提供的网页版MQTT客户端:http://m2m.demos.ibm.com/mqttclient/
1, 在Linkit 7688上编1个发送MQTT消息的程序:
用Eclipse 建立1个交叉编译项目 ( 开发环境搭建请见:联发科Linkit 7688 (1) 上手及在Mac下搭建OpenWrt交叉编译环境,C语言编译Hello,World)
将mqtt目录复制到你的项目文件夹下。
创建1个 mqtt_publish.c文件, 编写主程序以下:
主程序分为3个步骤:
1, 调用 mqtt_new()创建 客户端对象
2, 调用 mqtt_connect() 连接服务器
3, 调用 mqtt_publish() 发布消息
用Eclipse编译项目
如果出现毛病提示:
undefined reference to `pthread_create’
undefined reference to `pthread_mutexattr_init’
这是由于没有在编译连接时包括pthread库, 解决办法: 需在GCC中添加 -lpthread 参数。
如果出现毛病提示:
undefined reference to `dlclose’
undefined reference to `dlopen’
undefined reference to `dlsym
这是由于没有在编译连接时包括dl库, 解决办法: 需在GCC中添加 -ldl 参数
在eclipse中的操作是: 项目Property => C/C++ Build => Settings, 在"Tools Setting"页,选Cross GCC linker, 在 "Linker flags"编译框中填入: -lpthread -ldl
OK, 编译成功了。
用scp将 mqtt_publish 程序上传到 linkit 7688: scp mqtt_publish root@mylinkit.local:/root
先准备接收消息的网页客户端: 用阅读器打开 http://m2m.demos.ibm.com/mqttclient/
在Connect栏中, 点Connect.
在Subscribe栏中,将topic设为 test_topic, 按subscribe
OK, 网页客户端准备好接收主题(topic)为 test_topic的消息了。
用SSH登录入Linkit 7688, 运行 mqtt_publish 程序。
运行结果, 显示mqtt 创建、连接、发布消息的进程, return code >=0 表示成功:
mqtt client created
mqtt client connect
mqtt client publish, return code = 1
这时候,可以看到阅读器中的MQTT网页客户端收到了Linkit 7688发布的MQTT消息
成功了: Linkit 7688发布MQTT消息到服务器, 网页客户端实时收到服务器推送来的消息。
2, 在Linkit 7688上编1个接收MQTT消息的程序:
用Eclipse 建立1个交叉编译项目 ( 开发环境搭建请见:联发科Linkit 7688 (1) 上手及在Mac下搭建OpenWrt交叉编译环境,C语言编译Hello,World)
将mqtt目录复制到你的项目文件夹下。
创建1个 mqtt_subscribe.c文件, 编写主程序以下:
主程序分为几个步骤:
1, 调用 mqtt_new()创建 客户端对象
2, 调用 mqtt_connect() 连接服务器
3, 调用 mqtt_subscribe() 定阅消息
4, 进入循环:不断用 mqtt_receive()检测有否新消息,如有,则打印出来。
用Eclipse编译项目 (记得必须在GCC中加入连接选项: -lpthread -ldl )
OK, 编译成功了。
用scp将 mqtt_subscribe 程序上传到 linkit 7688: scp mqtt_subscribe root@mylinkit.local:/root
用SSH登录入Linkit 7688, 运行 mqtt_subscribe 程序。则此时出现:
mqtt client created
mqtt client connect
mqtt client subscribe, return code = 0
wait for message of topic: test_topic ...
显示程序在等待消息到来
准备发送消息的网页客户端: 用阅读器打开 http://m2m.demos.ibm.com/mqttclient/
在Connect栏中, 点Connect.
在Publish栏中,将topic设为 test_topic, 将Message设为 “Say hello to linkit 7688” 按publish, 则发出1条MQTT消息。
这时候, 看Linkit 7688 SSH客户端,可以看到,Linkit7688立即收到了这条MQTT消息
mqtt client created
mqtt client connect
mqtt client subscribe, return code = 0
wait for message of topic: test_topic ...
received Topic=test_topic, Message=Say hello to linkit 7688
成功了: Linkit 7688 实时收到了网页客户端发来的消息。
mqtt_subscribe 程序是死循环,1直在接收消息。 可按CTRL+C退出。
通用性: Eclipse Paho C 的 MQTT客户端代码,可以运行在Linux、Windows、Mac上。所以,上述的代码可以用于Linux、Windows、Mac操作系统,编写各种App。
对Android手机, Eclipse Paho另提供了Java的代码库。