一只海星的主页

ARM海思MQTT开发系列(一)最新MQTT客户端mosquitto交叉编译全记录

背景

设备和服务器通信,需要做设备管理和控制,在MQTT和私有协议间纠结,最终选定MQTT作为通信标准,更规范普及,功能也能满足需求。
开搞!

MQTT相比于TCP长连接的优势

1、协议更标准

MQTT是标准的RFC协议,相比于私有协议而言更加标准。好处在于:
(1)协议非常完整,能够马上用于生产。各端实现同一套协议之后,就能进行通信;私有协议还需要进行大量的验证,看有无缺陷或欠考虑的地方等。
(2)协议的标准化带来大量的开源组件,降低开发难度。随着物联网+5G生态越来越好,开源组件越来越多,可以减少重复编码量。
(3)标准协议利于第三方接入。当第三方设备、平台想要对接的时候,拿出一套标准的MQTT协议拍在他们脸上,再也没人有理由要求改接口了。

2、MQTT协议制定好了很多利于物联网的功能

当然TCP自己开发协议也能做到,但MQTT都已经把功能做好了,自己开发协议反而增加难度。有利的功能包括:
(1)心跳机制。不需要自己做业务协议层的心跳了。
(2)遗嘱消息。这对于经常掉线的物联网设备而言非常有用。
(3)QoS质量等级+离线消息。持久会话离线的消息也能接收到,对于网络不稳定但要求必须送达的物联网场景很有用。
(4)异步机制。MQTT将消息以QoS1/2发送出去后,设备端就不需要再管了,一切由云端负责失败重传。
(5)订阅发布机制。一次发布,多个客户端订阅,这对于M2M场景很省电、省流量。
(6)主题和安全。可以用主题来方便地控制客户端权限。
以上的功能基于TCP自己开发也能做到,如果自己都开发了,不就是实现了应用层的MQTT协议了吗

3、理解数据内容,用数据产生价值

IoT目前主流设计有两部分:
(1)设备影子价值
微软Azure叫设备孪生(Device Twins),亚马逊AWS叫设备影子(Device Shadow),阿里云叫设备影子(Device Shadow),腾讯云叫设备影子(Device Shadow),百度云叫物影子(Shadow)。为什么这么多大厂都要开发这个概念呢,设备影子包含了设备的状态,不用一个一个透传查询设备,直接在云端访问设备影子就能够得到当前所有设备的状态数据,这蕴含着巨大的利益,比如统计数据用于引导开发新产品和功能、统计数据用于修复bug等等。
(2)规则引擎价值
AWS、阿里云、腾讯云、百度云,都叫规则引擎(Rule Engine)。由于MQTT细分了具体的主题,当业务以主题区别的时候,直接将对应主题的数据通过规则引擎配置的规则自动分发给其他的数据接收者,比如阿里云可以发送给:
* 关系数据库RDS,进行普通存储
* 时序数据库TSDB,可用于时序分析
* 存储桶Bucket,当文件存储
* 消息队列MQ,可以转发给多个其他服务
* 函数计算,无服务器地处理某项工作
* 实时流,实时地发送给某些对时间敏感的服务
* 另一个主题,可以实现M2M通信

这些都可以有很多操作空间,随便举个例子,把所有的天猫精灵的语音数据发送到MQ,然后用后端服务慢慢分析,利用机器学习算法研究出什么样的用户群体喜欢使用什么样的功能,好针对性地卖产品,比如阉割一些功能,卖“青春版”天猫精灵,或者增加一些高端功能,卖“商务版”天猫精灵。
这些都是TCP透传这种云不理解业务数据内容做不到的(不要说TCP也可以解包然后分析业务数据然后转发,这样不就是变相地实现了MQTT了吗)。

一、环境和MQTT版本

mqtt开源框架非常的多,其中最大名鼎鼎的便是mosquitto,俗称蚊子。

选用最新稳定版本mosquitto-2.0.8,下载点我
当然可以从同性网站git拉取

git clone https://github.com/eclipse/mosquitto.git

交叉编译宿主机版本:Ubuntu16.04

二、交叉编译

1. openssl依赖

首先,mqtt依赖openssl,如果需要加密通道,先搞openssl交叉编译;
详细请参考我之前的文章 《超详细ARM平台curl交叉编译支持HTTPS+openssl 交叉编译》
不如需要,可以disable掉这个功能

2.交叉编译mosquitto

  • 解压文件
    tar czvf mosquitto-2.0.8.tar.gz
  • 调整配置文件
    可以在这里进行模块的增减,比如不需要json,就可以WITH_CJSON=no。
    我使用的是Ubuntu版本并无原生cjson支持,如不去掉会有如下报错:
In file included from mosquitto_ctrl.c:29:0:
mosquitto_ctrl.h:21:25: fatal error: cjson/cJSON.h: 没有那个文件或目录
 #include <cjson/cJSON.h>
  • 无json编译脚本
    根目录创建脚本build.sh内容如下:
#! /bin/bash
# 交叉编译工具链
ARM_CC=aarch64-himix100-linux-gcc
ARM_CXX=aarch64-himix100-linux-g++

#openssl依赖绝对路径
SSL_LIB=/work/data/tools/openssl-1.1.1g/__install

#输出
OUT_PUT=PWD/../mosquitto_arm
mkdir -pOUT_PUT

make clean
make CC=ARM_CC CXX=ARM_CXX WITH_CJSON=no CFLAGS="-ISSL_LIB/include/ -L/SSL_LIB/lib" LDFLAGS="-LSSL_LIB/lib -lssl -lcrypto" -j9

# 拷贝
cp ./include/mosquitto.h ./lib/libmosquitto.so.1 ./lib/libmosquitto.a ./client/mosquitto_sub ./client/mosquitto_pubOUT_PUT

2.支持json编译脚本

如果一定要硬上json,咋办!!!
选装以下内容:
1. 下载cjson

git clone https://github.com/DaveGamble/cJSON.git
  1. 交叉编译
    修改Makefile
    修改CC增加AR如下:
CC = aarch64-himix100-linux-gcc -std=c89
AR = aarch64-himix100-linux-ar
  1. 自建安装目录
mkdir -p _install/include/cjson
mkdir -p _install/lib
cp cJSON.h _install/include/cjson
cp libcjson.a  libcjson_utils.a _install/lib

带cJSON编译脚本:

#! /bin/bash
# 交叉编译工具链
ARM_CC=aarch64-himix100-linux-gcc
ARM_CXX=aarch64-himix100-linux-g++

#openssl依赖绝对路径
SSL_LIB=/work/data/tools/openssl-1.1.1g/__install
CJSON_LIB=/work/data/tools/cJSON/_install
#输出
OUT_PUT=PWD/../mosquitto_arm
mkdir -pOUT_PUT

make clean
make CC=ARM_CC CXX=ARM_CXX CFLAGS="-ISSL_LIB/include/ -L/SSL_LIB/lib -ICJSON_LIB/include/ -LCJSON_LIB/lib" LDFLAGS="-LSSL_LIB/lib -LCJSON_LIB/lib -lssl -lcrypto" -j9

# 拷贝
cp ./include/mosquitto.h ./lib/libmosquitto.so.1 ./lib/libmosquitto.a ./client/mosquitto_sub ./client/mosquitto_pub $OUT_PUT

执行build.sh 即可完成编译

参考

《为什么用MQTT不用TCP长连接透传》
《交叉编译mosquitto》

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注