一、Android设备使用MQTT协议接入OneNet平台
1. 用到的MQTT库:eclipse.paho
直接在app的gradle内dependencies添加依赖
compile 'org.eclipse.paho:org.eclipse.paho.client.mqttv3:1.1.0'
compile 'org.eclipse.paho:org.eclipse.paho.android.service:1.1.1'
注意:使用eclipse.paho一定记得要在AndroidManifest.xml中添加服务
否则没有办法正常使用
2. 连接上OneNet的服务器
需要设置
clientId为deviceId,即创建设备时的设备号
userName为productId,即创建产品的产品号
password为APIkey或者authInfo(即自己设置鉴权信息字符串)
因为APIkey太长不好记忆,所以我选择鉴权
1) 首先配置连接设置
MqttConnectOptions option = newMqttConnectOptions();
option.setUserName(productId);
option.setPassword(authInfo.toCharArray());
option.setCleanSession(false);
2) 调用mqttclient的连接方法
MqttAndroidClient mqttClient = newMqttAndroidClient(mContext, ("tcp://" + serverIP + ":" +serverPort), deviceId);
mqttClient.connet(option);
//OneNet的ip为183.230.40.39
//mqtt端口为6002
这样基本上就连接上OneNet的服务器了,ConnAck包这些是paho库帮我们完成的接收确认,我们只需要调用连接的这个函数即可,非常方便。
ps.当初看开发文档的时候一开始没有看到设置用户名这些,因为照着接入流程做,看到了服务器的ip和端口就直接跑去连接了,发现一直连接不上。直到再次看了一遍开发文档,拖到文档下面的常见问题才发现还需要设置这些。感觉这些重要的设置内容应该写在前面比较好,第一次没注意看,很尴尬。
3.发布及订阅自己的topic
这个很简单,之前用自己的服务器也是这样做的,
1) 订阅:
mqttClient.subscribe("topic",0); //参数一为topic字符串, 参数二为QoS级别
2) 发布:
MqttMessage msg = new MqttMessage();
msg.setPayload(payload.getBytes()); //发布内容
msg.setQos(1); //设置发布级别
mqttClient.publish(topic, msg); //发布
我们的项目是以topic来区别设备的
譬如,Android应用就订阅一个topic为Android/id,id为编号
底层设备就订阅一个topic为Device/id
然后发送指令直接向对应的topic发送就行
4.使用mqtt上传数据点/获取数据
OneNet为每一个产品提供了数据流,在平台上记录并且可以生成数据的曲线,要想让我们通过mqtt协议上传的数据能够保存在数据流上,就得向$dp这个topic发送一串规定格式的数据。
试了几次向$dp这个topic发送数据,在设备数据界面看都没有成功更新到数据,最让人疑惑的是,一旦发送了数据,设备就会掉线,需要重连。不太清楚OneNet平台是不是有什么发布数据就让你强制下线的机制。并且因为平台不允许订阅$打头的数据。
起初我以为是OneNet服务器的问题,不过其他的topic还是可以正常的使用,并且换用平台提供的官方客户端,又可以成功发送且对数据进行更新。
(使用OneNet提供的mqtt测试程序上传数据点,同时可以看到平台上显示设备的数据更新了)
于是我在想是不是发送的格式还是不正确,就发现了这个
决定还是通过wireshark软件对OneNet平台提供的客户端进行抓包,看看他究竟发送的是什么。
可以看到确实是向$dp这个topic发送了消息,7b是”{”转为16进制,那么前面的01 00 5e就是协议文档里面提到的发送类型、长度高位、长度低位了。
附上我之前的代码:
这样问题就显而易见了。
协议中的格式讲的是发送16进制的01 00 length,而通过之前编写的这段代码发送出去的是字符串”01 00 length”。
故赶紧修改代码为:
这样就能成功地将数据库上传到OneNet平台了。