背景(不看也罢)
“预计2020年全球的物联网设备将达到500亿台”这句话已经被我无耻地在各种材料、PPT中引用过无数次了,但这并不妨碍物联网已经成为或即将成为下一个浪潮之巅的事实,各大、小公司都想借助物联网的风口再起飞一波。于是,很多公司纷纷推出各种物联网云平台争抢这个具有无限潜力的黄金市场(其实说钻石亦不过分,除了媒体的吹捧之外物联网还是有真功夫的)。典型的物联网云平台包括AWS IoT、IBM Watson、阿里物联网套件和中国移动OneNet等,每个平台都有各自的优势与不足。国外的云平台好用但访问速度慢。比如IBM Watson能够提供远程节点数据的实时记录服务,但其控制台入门繁琐而且访问速度缓慢(即使翻墙);国内云平台基本都能保证实时节点数据记录和快速的控制台访问。阿里的物联网套件入门复杂。众所周知阿里云提供诸多云服务包括数据存储(各类云数据库,Table Store)、数据分析(图像识别、人脸识别)、规则引擎、短信服务等,而物联网云平台的本质无非节点托管、数据存储、远程控制,所以阿里索性把物联云平台当做一种服务集成到阿里云中。比方说当你借助阿里云托管物联网应用时你可以选择阿里物联网套件服务+规则引擎服务+Table Store服务套餐,然后你再下个Table Store的桌面应用,你就可以在Table Store上实时查看由规则引擎根据自定义条件过滤后的远程节点数据了。阿里基于拥有的云服务结合物联网平台,以物联网应用=物联网平台+服务的方式让用户快速构建物联网应用,达到灵活按需定制具体服务的效果(说白了,就是不让你轻松入门)。中移OneNet平台简单易用、入门快,作为一个单纯的设备托管平台还是不错的。
但是,目前所有的物联网云平台都有共同的限制(对我而言,也许有些对你而言亦是):
1.这些云平台都提供各自公司规定的数据通信协议,比如IBM Watson是这样的
{
"temperature": 25,
"humidity": 60
}
而OneNet却是这样的
{
"datastreams": [
{
"id": "Temperature",
"datapoints": [
{
"value": 25
}
]
},
{
"id": "Humidity",
"datapoints": [
{
"value": 60
}
]
}
]
}
如果,你觉得以上平台的数据通信格式都没道理,那你得。。。自己造个平台
2.这些云平台的数据加密方式各不相同,很多公司的加密传输需要设备烧写对应平台提供的认证文件,如果,你觉得某公司的加密认证文件可能被破解,或者压根你认为加密算法应该由自己design,那你得。。。自己造个平台
3.如果你想基于平台收集的远程节点数据来DIY上层应用。很多平台提供了为第三方应用推送节点数据的API,例如OneNet的数据推送服务。首先,我用过之后发现推送的数据信息不完整,无法获取具体的用户信息(只能根据节点ID推算用户ID,前提是第三方应用要知道完整的节点ID和用户ID映射表)。不仅如此第三方应用被OneNet视为平台中的一个用户,无权获取其他用户的信息,所以要使用第三方应用的用户必须将自己在OneNet平台上的用户信息透漏给第三方应用;其次,云平台为第三方应用提供数据推送服务的API仅代表云平台制造商的协议,并不是一个标准,这样的第三方应用严重依赖云平台,数据推送服务的接口一旦发生变化第三方应用就不得不做修改;最后,节点数据要先上传到某个云平台,然后再转发到第三方应用的服务器,最后由第三方应用推送至手机,为什么不直接建立自己的云平台?
综上所述,你应该搭建一个私有的物联网云平台。
如何搭建(定睛半小时)
Step 1 选择开源代理
现支持mqtt和coAP协议的broker还是比较多的,我调研了emqttd和mosquitto,最终采纳mosquitto。
mosquitto是一款MQTT开源代理,也支持CoAP协议。
emqttd是一款国人做的(号称)支持百万连接的高并发MQTT开源代理,除了MQTT还支持CoAP, WebSocket等。产品做得非常赞,自带管理控制界面(如下所示,酷炫的不行)。
emqttd管理控制台为什么不选emqttd?
emqttd没有可编程的API支持(任何开源工具当然可以强行封装API了,但这里是缺少API编程文档的意思),所以对于个人开发来讲,数据数据处理支持还不够(至少达不到服务器数据存储的要求)。如果现在不清楚我的意思,看过Step 4中我修改过的源码你就明白了(并不是故意埋伏笔,迫于逻辑顺序)。而且,emqttd基于erlang语言实现,作为一个年少无知的学生党我还是第一次听说,如果根据需求在emqttd的实现基础上添加DIY功能还得掌握一门新语言(overhead太大,对不熟悉erlang的人亦是如此)。
Step 2 安装代理
Step 2.1 下载mosquitto源码,解压后编译安装。(以下流程在Ubuntu 14.04测试通过)
指令:
cd mosquitto-1.4.14/
make
sudo make install
可能遇到的问题:
make过程遇到:./mosquitto_internal.h:40:20: fatal error: ares.h: No such file or directory
找不到ares.h解决方法:
打开config.mk,把WITH_SRV:=yes改成WITH_SRV:=no,重新编译
Step 2.2 测试:
打开三个终端:
一号终端执行
mosquitto
二号终端执行
mosquitto_sub -t "my_topic"
三号终端执行
mosquitto_pub -t "my_topic" -m "IoT"
如果安装成功,在二号终端会收到“IoT”。
可能遇到的问题:
mosquitto_sub: error while loading shared libraries: libmosquitto.so.1: cannot open shared object file: No such file or directory
解决方法:
sudo cp /usr/local/lib/libmosquitto.so.1 /usr/lib/
Step 3 安装认证插件
Step 2完成后的版本仅仅是简单的mqtt代理功能展示,为了完善这个代理,我们要给它添加用户认证功能。
Step 3.1 下载Mosquitto认证插件,解压后配置:
指令:
cd mosquitto-auth-plug-master/
cp config.mk.in config.mk
配置:
在config.mk中,除了BACKEND_MYSQL这一行是yes,其余行都是no。MOSQUITTO_SRC一行输入mosquitto的源码路径,也即Step 2.1中mosquitto的解压后路径(例如MOSQUITTO_SRC = /home/jiaozhu/mosquitto-1.4.1)。在OPENSSLDIR一行输入openssl的路径,可用openssl version -a查看openssl路径,(例如OPENSSLDIR = /usr/lib/ssl)。
Step 3.2 编译mosquitto-auth-plug,将编译生成的动态库auth-plug.so移动到mosquitto的配置目录(/etc/mosquitto/)中,配置mosquitto认证插件:
指令:
cd mosquitto-auth-plug-master/
make
sudo cp auth-plug.so /etc/mosquitto/
配置:
可以在mosquitto插件目录中配置文件的基础上直接修改,然后将配置文件复制到mosquitto的配置目录(/etc/mosquitto/)中
cd mosquitto-auth-plug-master/
sudo cp examples/mosquitto-mysql.conf /etc/mosquitto/mosquitto.conf
修改/etc/mosquitto/mosquitto.conf,具体修改配置如下
auth_plugin /etc/mosquitto/auth-plug.so # 认证插件动态库位置
auth_opt_backends mysql # 插件支持的服务
#auth_opt_cdbname pwdb.cdb
auth_opt_host localhost # 数据库IP
auth_opt_port 3306 # 数据库端口
auth_opt_dbname mqtt_user # 数据库名称
auth_opt_user root # 数据库用户名
auth_opt_pass 12345 # 数据库密码
auth_opt_userquery SELECT pw FROM users WHERE username = '%s' # 用户认证查询语句
auth_opt_superquery SELECT IFNULL(COUNT(*), 0) FROM users WHERE username = ' %s' AND super = 1 # 超级用户查询语句
auth_opt_aclquery SELECT topic FROM acls WHERE username = '%s' # 话题查询语句
Step 3.3 建立用户数据库
在mysql中创建名为mqtt_user的数据库,并将mysql.sql导入
mysql -P 3306 -u root -p mqtt_user<~/mysql.sql
Step 3.4 测试
打开三个终端:
一号终端执行
mosquitto -c /etc/mosquitto/mosquitto.conf -v
二号终端执行
mosquitto_sub -t "mytopic" -u jiaozhu -P 12345
三号终端执行
mosquitto_pub -m "myIoT" -t "mytopic" -u jiaozhu -P 12345
这时候应该在二号终端会收到“myIoT”这个消息。而且一号终端会显示类似的verbose
一号终端verbose到此为止,只要对mqtt_user数据库内的表进行增删改查就可以达到用户、话题的管理效果。
But ! 这就完了吗?
最主要的数据存储功能还没有实现,上述获取的数据也是单个用户订阅自己的某个topic获取的,单个用户是无法订阅或发布其他用户topic上的数据的,这个模型有点像下图的描述。
数据交互模型作为一个云平台该如何获取所有用户所有topic的数据呢?为每个用户创建一个client去监听其所有的topic纵然能解决问题,但为每个用户分配一个client意味着N个用户会有N个本地tcp连接(mqtt是基于tcp实现的轻量级通信协议),这样迟早会耗尽资源(端口、内存)。
好在broker会获取client的连接信息(用户名,密码,数据),所以,我选择在broker源码上附加数据处理、数据存储功能。
Step 4 添加数据处理功能
Step 4.1 下载数据处理功能文件。
将source文件夹内的所有文件拷入mosquitto-1.4.14/src,将mylib文件夹内的libmysqlclient.a拷入mosquitto-1.4.14/lib,将config.mk替换掉mosquitto-1.4.14/config.mk。
Step 4.2 重新编译mosquitto
指令:
cd mosquitto-1.4.14/
make clean
make
sudo make install
Step 4.3:测试
打开三个终端:
一号终端执行
mosquitto -c /etc/mosquitto/mosquitto.conf -v
二号终端执行
mosquitto_sub -t "mytopic" -u jiaozhu -P 12345
三号终端执行
mosquitto_pub -m "{\"nodeID\":10001, \"humidity\":12.5}" -t "mytopic" -u jiaozhu -P 12345
打开数据库,查询recorddata表会有下面数据记录
数据库存储数据Step 4.4 真实节点测试
这里我们借用TinyLink来完成节点应用的快速开发(趁机宣传一波,其实这里完全可以用mqtt客户端测试或者使用paho的mqtt实现一个客户端),我们编写了下面TinyLink code
TL_MQTT mqtt;
int port = 1883;
char serverName[] = "10.214.149.119"; // mosquitto broker所部署服务器的IP,保证服务器和节点出于同一网段
char clientName[] = "jiaozhu"; // 随意
char topicName[] = "mytopic"; // 默认使用的topic
char userName[] = "jiaozhu"; // 用户名
char password[] = "12345"; // 密码
void setup() {
TL_WiFi.init();
bool b = TL_WiFi.join("SSID","PASS");
mqtt = TL_WiFi.fetchMQTT();
int a = mqtt.connect(serverName, port, clientName, userName, password);
}
void loop() {
TL_Humidity.read();
TL_Temperature.read();
String data = "{";
data += "\"nodeID\":";
data += "10001";
data += ",\"humidity\":";
data += TL_Humidity.data();
data += ",\"temperature\":";
data += TL_Temperature.data();
data += "}";
char buf[100];
data.toCharArray( buf,100 );
int res = mqtt.publish(topicName, buf, strlen(buf));
TL_Time.delayMillis(1000);
}
代码烧入节点,查询数据库会有下面数据记录
节点数据到此为止,私有物联网云平台已搭建完成。我搭建的这个私有物联网云平台也有缺陷之处,比方说我在修改源码的时候忽略了桥接模式的数据处理,所以有用到桥接功能的同学要注意去研究一下对应源码的桥接模式数据处理功能,实现过程中可以参见mosquitto客户端编程的一些API文档(这也是我之前提到的emqttd没有提供可编程API的问题)。
此致
原文地址: 和我一起搭建私有物联网云平台(知乎)