1 缘由
- 公司的设备偶尔掉线且掉线间隔时间不正确(32秒,应该30~31才是正确的),但是不知道是什么原因
- 使用python模拟设备,每10秒钟发送mqtt消息
- 另外启动一个java客户端,收集所有mqtt消息并存入mongodb
- 最后比较真实设备与模拟,分析问题
2 基本架构
- iot server(SpringBoot...)—— 部署在云端
- EMQ(开源物联网MQTT消息服务)—— 部署在云端
- MQTT消息收集客户端(SpringBoot mqtt mongo)—— 部署在云端
- 嵌入式设备(真实设备)—— 部署在本地网络
- python脚本(模拟设备)—— 部署在本地网络
3 分析结果
- 模拟设备的mqtt消息完整收集,一直处于在线状态
- 真实设备的mqtt消息少了一条,代表真实设备存在丢弃消息的情况
- iot server的设备在线处理逻辑存在1s的误差,经过排查发现判断逻辑有误
4 iot server在线逻辑
- 设备登录或更新时,计数设置为30s。
- 秒定时器每次计数减1。
- 当计数减到0,则判断为掉线。
boolean flag = i-- > 0; //这里出错了,应该先减少再判断
5 Python
$ pip install virtualenv
$ mkdir python-mqtt
$ cd python-mqtt
$ virtualenv --no-site-packages venv
$ source venv/Scripts/activate
$ pip install paho-mqtt
$ pip list
Package Version
---------- -------
paho-mqtt 1.4.0
pip 18.0
setuptools 40.2.0
wheel 0.31.1
$ vi main.py
import time
import paho.mqtt.client as mqtt
import logging
logging.basicConfig(level=logging.DEBUG)
# 官网这里只有三个参数...,我直接复制下来一直报错,修改为4个才没问题的。
def on_connect(mosq, obj, msg, rc):
mqttc.subscribe("DEV/#", 0)
print("rc: " + str(rc))
def on_message(mosq, obj, msg):
print(msg.topic + " " + str(msg.qos) + " " + str(msg.payload))
def on_publish(mosq, obj, mid):
print("mid: " + str(mid))
def on_subscribe(mosq, obj, mid, granted_qos):
print("Subscribed: " + str(mid) + " " + str(granted_qos))
mqttc = mqtt.Client()
logger = logging.getLogger(__name__)
mqttc.enable_logger(logger)
mqttc.on_message = on_message
mqttc.on_connect = on_connect
mqttc.on_publish = on_publish
mqttc.on_subscribe = on_subscribe
mqttc.username_pw_set(
"username", "password")
mqttc.connect("url", 1883, 60)
mqttc.loop_start()
while 1:
(result, mid) = mqttc.publish("TOPIC/TEST", "", 0)
time.sleep(10) # 每10秒发送1条
mqttc.loop_stop()
mqttc.disconnect()
6 MQTT消息收集客户端
- 收集mqtt消息,不需要启动web服务,不需要加入web包且启动不需要指定为web项目
@SpringBootApplication
public class MqttMongoApplication {
public static void main(String[] args) {
new SpringApplicationBuilder(MqttMongoApplication.class)
.web(false) // 指定非web项目
.build()
.run(args);
}
}
7 总结
- 简单代码一不小心也可能出错
- python脚本编写方便适合用于测试