在Iot物联网中,有个关键点就是设备是否在线的判断。如果用传统的Http数据传输则通过轮询达到目的,具体就是通过不停的向服务器发送心跳包,让服务器知道设备在线;这种方式简单直接但粗爆,设备数量少可以,但如果设备上千或万,那么服务器基本只能靠分布式部署了。如果用MQTT则减少很多问题,因为MQTT有个遗嘱功能,就是当超过某时间数据断开后,就自动发送。一直以来我都没弄明白这个遗嘱的功能,因为误入了当断电或直接断线连遗嘱都发不出的矛盾圈。好在,最近看Iot的文章里面有个MQTT的说明,详细说了一下遗嘱的功能,其实在MQTT客户端与服务端链接时,就已经将遗嘱发给服务器,当服务器没再收到客户端的数据就将遗嘱拿出来。ok,其实遗嘱不是断气前发送,而是在链接时就签好的。那其实这个遗嘱在MQTT初始化时已经要写好。那么这个初始化是那个呢?经过一番找寻,终于发现签遗嘱是用setWill,怎么用好吧,上配置代码:
代码语言:javascript复制mqttAndroidClient = new MqttClient(AppInfoKeeper.getRootUrlString(), AppInfoKeeper.getMedchCode(), new MemoryPersistence());
//新建连接设置
MqttConnectOptions mqttConnectOptions = new MqttConnectOptions();
//断开后,是否自动连接
mqttConnectOptions.setAutomaticReconnect(true);
//是否清空客户端的连接记录。若为true,则断开后,broker将自动清除该客户端连接信息
mqttConnectOptions.setCleanSession(true);
//设置超时时间,单位为秒
mqttConnectOptions.setConnectionTimeout(15);
//心跳时间,单位为秒。即多长时间确认一次Client端是否在线
mqttConnectOptions.setKeepAliveInterval(10);
//允许同时发送几条消息(未收到broker确认信息)
//mqttConnectOptions.setMaxInflight(10);
mqttConnectOptions.setUserName("Username");//MQTT的账号
mqttConnectOptions.setPassword("Password".toCharArray());//MQTT的密码
//遗嘱内容
String message_d = "{"reported": {"TerminalNo":"" AppInfoKeeper.getMedchCode() "","Type":"API_OFFLINE"}}";
mqttConnectOptions.setWill(publishTopic, message_d.getBytes(),2, false);// 最后的遗嘱
//选择MQTT版本
mqttConnectOptions.setMqttVersion(MqttConnectOptions.MQTT_VERSION_3_1_1);
mqttAndroidClient.setCallback(mqttCallback);
if (!mqttAndroidClient.isConnected() && isConnectIsNomarl()) {
mqttAndroidClient.connect(mqttConnectOptions);
}
if (mqttAndroidClient.isConnected()) {
//订阅主题
mqttAndroidClient.subscribe("$baidu/iot/general/" AppInfoKeeper.getMedchCode(), 0, iMqttMessageListener);
}
关键点:mqttConnectOptions.setWill(publishTopic, message_d.getBytes(),2,false);// 最后的遗嘱
当MQTT服务器检测不到客户端的链接,则会自动将遗嘱的内容发出。然后根据其遗嘱进行处理就可以达到判断是否在线的目的。
我目前的做法是通过建一个在线表,当客户端与服务端有联系的时间则进行写表进行记录,如果收到遗嘱则对表进行删除;这样只要对数据表进行读取就知道在线的情况了。好吧,再给出在线进行更新的SQL存储过程。。
代码语言:javascript复制CREATE PROCEDURE [dbo].[TerminalNo_Online]
(
@TerminaNo nvarchar(2000)
)
AS
/*设备在线更新*/
BEGIN
if exists (select top 1 TerminalNo from TerminalOnline where TerminalNo=@TerminaNo)
update TerminalOnline set Onlinetime=GETDATE() where TerminalNo = @TerminaNo
ELSE
INSERT INTO TerminalOnline(TerminalNo,Onlinetime) VALUES (@TerminaNo,GETDATE())
END
GO
最后,总结一下MQTT确实是一个低流量的数据传输载体,怪不得Iot设备大多都用这个。
-完-