IoT service,mqtt,publish topic different from subscribe topic

万万没想到,万万没想到~~


没想到的是IoT service不仅仅是一个MQTT Broker,”他“还”好心“帮你多做了一件事情,就是topic转换,哈哈,没想到吧,subscribe的topic竟然和publish的topic不一样!

神马?!是的,你没听错!当然,多加topic转换的一步是有一定原因的(至于为什么会有这样的顶层设计,我目前还无暇思考),也是容易实现的,因为app和device都是注册到”他“那里的,app和device的认证信息都在”他“那,做个topic转换还不简单!


至于”MQTT 连接成功订阅不成功“的难题也顺利解决了。因为IoT service不认识你publish的topic,所以MQTTListener不给你subscribe!所以有”一连一断(不断的循环往复connect和disconnect,就是不执行subscribe()方法)“。这个问题是不是socket closed by remote peer呢?好像还不一样。


MQTTGataway回调函数里subscribe的topic如下:

String topic = "iot-2/type/" + MqttUtil.DEFAULT_DEVICE_TYPE + "/id/+/evt/"

                                             + MqttUtil.DEFAULT_EVENT_ID + "/fmt/json";


MQTTListener的监听的onPublish中(用来监听device或者sensor端的publish的topic)的topic如下:

Pattern pattern = Pattern.compile("iot-2/type/"
+ MqttUtil.DEFAULT_DEVICE_TYPE + "/id/(.+)/evt/"
+ MqttUtil.DEFAULT_EVENT_ID + "/fmt/json");


XXDevice或者XXSensor端publish的topic如下(重要的事情说三遍,是的,你没看错!):

connection.publish("iot-2/evt/eid/fmt/json", data.getBytes(),
QoS.AT_LEAST_ONCE, false);




终于搞定了,监听端的console log:

debug: Connecting
debug: Transport connected
send: MQTTFrame { type: CONNECT, qos: AT_MOST_ONCE, dup:false }
debug: Logging in
recv: MQTTFrame { type: CONNACK, qos: AT_MOST_ONCE, dup:false }
debug: MQTT login accepted
subscribe topic: iot-2/type/devicecbs1/id/+/evt/eid/fmt/json
send: MQTTFrame { type: SUBSCRIBE, qos: AT_LEAST_ONCE, dup:false }
mqtt connected succeed
recv: MQTTFrame { type: SUBACK, qos: AT_MOST_ONCE, dup:false }
subscribe successfully[B@30ddb86
----------------------------------saveToDB--------------------------------------- = null
----------------------------------saveToDB--------------------------------------- = null
recv: MQTTFrame { type: PUBLISH, qos: AT_LEAST_ONCE, dup:false }
mqtt onPublic----------- :iot-2/type/devicecbs1/id/cbsdevicea/evt/eid/fmt/json
mqtt onPublic----------- :{"type" : "Feature", "geometry": {"coordinates": [0.4079238821522253, 51.58289257363429], "type":"Point"}} }
mqtt save data ....onPublish 
send: MQTTFrame { type: PUBACK, qos: AT_MOST_ONCE, dup:false }
----------------------------------saveToDB--------------------------------------- = {"type" : "Feature", "geometry": {"coordinates": [0.4079238821522253, 51.58289257363429], "type":"Point"}} }
save to cloudant DB succeeded!
----------------------------------saveToDB--------------------------------------- = null
----------------------------------saveToDB--------------------------------------- = null
----------------------------------saveToDB--------------------------------------- = null
send: MQTTFrame { type: PINGREQ, qos: AT_MOST_ONCE, dup:false }
recv: MQTTFrame { type: PINGRESP, qos: AT_MOST_ONCE, dup:false }
----------------------------------saveToDB--------------------------------------- = null
----------------------------------saveToDB--------------------------------------- = null
----------------------------------saveToDB--------------------------------------- = null
recv: MQTTFrame { type: PUBLISH, qos: AT_LEAST_ONCE, dup:false }
mqtt onPublic----------- :iot-2/type/devicecbs1/id/cbsdevicea/evt/eid/fmt/json
mqtt onPublic----------- :{"type" : "Feature", "geometry": {"coordinates": [0.4079238821522253, 51.58289257363429], "type":"Point"}} }
mqtt save data ....onPublish 
send: MQTTFrame { type: PUBACK, qos: AT_MOST_ONCE, dup:false }
----------------------------------saveToDB--------------------------------------- = {"type" : "Feature", "geometry": {"coordinates": [0.4079238821522253, 51.58289257363429], "type":"Point"}} }
save to cloudant DB succeeded!
----------------------------------saveToDB--------------------------------------- = null
----------------------------------saveToDB--------------------------------------- = null
----------------------------------saveToDB--------------------------------------- = null
----------------------------------saveToDB--------------------------------------- = null
----------------------------------saveToDB--------------------------------------- = null
send: MQTTFrame { type: PINGREQ, qos: AT_MOST_ONCE, dup:false }
recv: MQTTFrame { type: PINGRESP, qos: AT_MOST_ONCE, dup:false }
----------------------------------saveToDB--------------------------------------- = null
----------------------------------saveToDB--------------------------------------- = null
----------------------------------saveToDB--------------------------------------- = null
----------------------------------saveToDB--------------------------------------- = null
----------------------------------saveToDB--------------------------------------- = null
----------------------------------saveToDB--------------------------------------- = null
send: MQTTFrame { type: PINGREQ, qos: AT_MOST_ONCE, dup:false }
recv: MQTTFrame { type: PINGRESP, qos: AT_MOST_ONCE, dup:false }
----------------------------------saveToDB--------------------------------------- = null
----------------------------------saveToDB--------------------------------------- = null
----------------------------------saveToDB--------------------------------------- = null


补充一点:

一般情况下在app端subscribe(是个listener),在device或者sensor端publish。

但是在特殊情况下,可能需要在同一端需要subscribe和publish,这里也说一下。

1. 如果subscribe和publish都在device端:

//Subscribe the Command events
//iot-2/cmd/<cmd-type>/fmt/<format-id>
handler.subscribe("iot-2/cmd/" + MqttUtil.DEFAULT_CMD_ID + "/fmt/json",0);

//Publish device events to the app
//iot-2/evt/<event-id>/fmt/<format> 
handler.publish("iot-2/evt/" + MqttUtil.DEFAULT_EVENT_ID
+ "/fmt/json", jsonObj.toString(), false, 0);


2. 如果subscribe和publish都在app端:

//Subscribe Device Events
//iot-2/type/<type-id>/id/<device-id>/evt/<event-id>/fmt/<format-id>
handler.subscribe("iot-2/type/" + MqttUtil.DEFAULT_DEVICE_TYPE
+ "/id/+/evt/" + MqttUtil.DEFAULT_EVENT_ID + "/fmt/json", 0);


//Publish command to one specific device
//iot-2/type/<type-id>/id/<device-id>/cmd/<cmd-id>/fmt/<format-id>
handler.publish("iot-2/type/" + MqttUtil.DEFAULT_DEVICE_TYPE
+ "/id/" + deviceid + "/cmd/" + MqttUtil.DEFAULT_CMD_ID
+ "/fmt/json", jsonObj.toString(), false, 0);


Note:这里仅指IoT service(一种特殊的MQTT Broker)!



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是基于Arduino平台,使用Arduino IDE编写的NB-IoT接入阿里云平台MQTT协议实现数据传输的示例代码。在使用前需要先在阿里云平台创建设备和Topic,并且获取对应的设备信息和证书。 ```C++ #include <SoftwareSerial.h> #include <PubSubClient.h> #include <ArduinoJson.h> #include <OneWire.h> #include <DallasTemperature.h> #include <DFRobot_SIM808.h> //定义NB-IoT模块相关参数 #define PIN_TX 7 #define PIN_RX 8 #define BAUDRATE 9600 //定义DS18B20温度传感器相关参数 #define ONE_WIRE_BUS 2 #define TEMPERATURE_PRECISION 9 //定义阿里云MQTT平台相关参数 #define MQTT_SERVER "xxx.mqtt.aliyuncs.com" //MQTT服务器地址 #define MQTT_PORT 1883 //MQTT服务器端口 #define MQTT_CLIENT_ID "GID_xxxxxxxxxxxxxx" //客户端ID #define MQTT_USERNAME "xxxxxxxxxxxxx" //MQTT用户名 #define MQTT_PASSWORD "xxxxxxxxxxxxx" //MQTT密码 #define MQTT_TOPIC "/xxxxxxxxxxxxx/xxxxxxxxxxxxx" //MQTT Topic SoftwareSerial mySerial(PIN_RX, PIN_TX); DFRobot_SIM808 sim808(&mySerial);//创建NB-IoT模块对象 OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); WiFiClient wifiClient; PubSubClient mqttClient(MQTT_SERVER, MQTT_PORT, wifiClient); void setup() { Serial.begin(9600); mySerial.begin(BAUDRATE); while(!sim808.init());//等待模块初始化完成 delay(2000); Serial.println("SIM808 init success!"); sensors.begin(); } void loop() { sim808.checkPowerUp();//检查模块是否开机 if (sim808.isNetworkRegistered()) { Serial.println("Network is registered."); if (sim808.isGprsActived()) { Serial.println("GPRS is actived."); if (!mqttClient.connected()) { Serial.println("MQTT client is not connected."); connectMqttServer(); } mqttClient.loop(); float temperature = readTemperature(); publishMqttMessage(temperature); } else { Serial.println("GPRS is not actived, trying to activate..."); sim808.activeGprs("CMNET");//激活GPRS } } else { Serial.println("Network is not registered, trying to register..."); sim808.waitForNetworkRegistered();//等待网络注册 } } float readTemperature() { sensors.requestTemperatures(); float temperature = sensors.getTempCByIndex(0); return temperature; } void connectMqttServer() { Serial.println("Connecting to MQTT server..."); if (mqttClient.connect(MQTT_CLIENT_ID, MQTT_USERNAME, MQTT_PASSWORD)) { Serial.println("MQTT server connected."); mqttClient.subscribe(MQTT_TOPIC);//订阅MQTT Topic } else { Serial.print("Failed to connect MQTT server, rc="); Serial.println(mqttClient.state()); } } void publishMqttMessage(float temperature) { StaticJsonDocument<200> jsonDoc; jsonDoc["temperature"] = temperature; char message[200]; serializeJson(jsonDoc, message, sizeof(message)); mqttClient.publish(MQTT_TOPIC, message);//发布MQTT消息 } ``` 此代码实现了以下功能: 1. 连接NB-IoT模块和DS18B20温度传感器; 2. 检查NB-IoT网络状态; 3. 激活GPRS连接; 4. 连接阿里云MQTT平台; 5. 订阅指定的MQTT Topic; 6. 读取DS18B20传感器数据; 7. 将温度数据以JSON格式发布到MQTT Topic。 注意:由于NB-IoT网络和阿里云MQTT平台的连接较为复杂,上述代码仅供参考,具体实现需要根据实际情况进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值