基於Pub/Sub模式的阿里雲IoT同步呼叫詳解
1.同步呼叫場景
1.1 背景
MQTT協議是基於PUB/SUB的非同步通訊模式,無法實現服務端下發指令給裝置端,同時需要裝置端返回響應結果的場景。
IoT物聯網平臺基於MQTT協議制定了一套請求和響應的同步機制,無需改動MQTT協議即可實現同步通訊。應用伺服器通過POP API發起Rrpc呼叫,IoT裝置端只需要在Timeout內,按照固定的格式回覆Pub訊息,服務端即可同步獲取IoT裝置端的響應結果。
具體流程如下:
1.2 Topic格式約定
請求:/sys/${productKey}/${deviceName}/rrpc/request/${messageId}
響應:/sys/${productKey}/${deviceName}/rrpc/response/${messageId}
$表示變數,每個裝置不同messageId為IoT平臺生成的訊息ID,裝置端回覆responseTopic裡的messageId要與requestTopic一致
示例:
裝置端需要訂閱:
/sys/${productKey}/${deviceName}/rrpc/request/+
執行中裝置收到Topic:
/sys/PK100101/DN213452/rrpc/request/443859344534
收到訊息後,在timeout時間內回覆Topic:
/sys/PK100101/DN213452/rrpc/response/443859344534
2.同步呼叫RRPC示例
2.1 裝置端程式碼
const mqtt = require(`aliyun-iot-mqtt`);
//裝置屬性
const options = require("./iot-device-config.json");
//建立連線
const client = mqtt.getAliyunIotMqttClient(options);
client.subscribe(`/sys/${options.productKey}/${options.deviceName}/rrpc/request/+`)
client.on(`message`, function(topic, message) {
if(topic.indexOf(`/sys/${options.productKey}/${options.deviceName}/rrpc/request/`)>-1){
handleRrpc(topic, message)
}
})
function handleRrpc(topic, message){
topic = topic.replace(`/request/`,`/response/`);
console.log("topic=" + topic)
//普通Rrpc,響應payload自定義
const payloadJson = {code:200,msg:"handle ok"};
client.publish(topic, JSON.stringify(payloadJson));
}
2.2 服務端POP呼叫Rrpc
const co = require(`co`);
const RPCClient = require(`@alicloud/pop-core`).RPCClient;
const options = require("./iot-ak-config.json");
//1.初始化client
const client = new RPCClient({
accessKeyId: options.accessKey,
secretAccessKey: options.accessKeySecret,
endpoint: `https://iot.cn-shanghai.aliyuncs.com`,
apiVersion: `2017-04-20`
});
const payload = {
"msg": "hello Rrpc"
};
//2.構建request
const params = {
ProductKey:"a1gMu82K4m2",
DeviceName:"h5@nuwr5r9hf6l@1532088166923",
RequestBase64Byte:new Buffer(JSON.stringify(payload)).toString("base64"),
Timeout:3000
};
co(function*() {
//3.發起API呼叫
const response = yield client.request(`Rrpc`, params);
console.log(JSON.stringify(response));
});
rrpc響應:
{
"MessageId": "1037292594536681472",
"RequestId": "D2150496-2A61-4499-8B2A-4B3EC4B2A432",
"PayloadBase64Byte": "eyJjb2RlIjoyMDAsIm1zZyI6ImhhbmRsZSBvayJ9",
"Success": true,
"RrpcCode": "SUCCESS"
}
// PayloadBase64Byte 解碼: {"code":200,"msg":"handle ok"}
3.物模型-服務同步呼叫InvokeThingService示例
注意:物模型 服務呼叫 介面InvokeThingService,不是Rrpc
3.1 物模型-同步服務定義
3.2 裝置端實現
const mqtt = require(`aliyun-iot-mqtt`);
//裝置屬性
const options = require("./iot-device-config.json");
//建立連線
const client = mqtt.getAliyunIotMqttClient(options);
client.subscribe(`/sys/${options.productKey}/${options.deviceName}/rrpc/request/+`)
client.on(`message`, function(topic, message) {
if(topic.indexOf(`/sys/${options.productKey}/${options.deviceName}/rrpc/request/`)>-1){
handleRrpc(topic, message)
}
})
/*
* 如果存在多個同步呼叫服務,需要通過payload裡的method區分
*/
function handleRrpc(topic, message){
topic = topic.replace(`/request/`,`/response/`);
console.log("topic=" + topic)
//物模型 同步服務呼叫,響應payload結構:
const payloadJson = {
id: Date.now(),
code:200,
data: {
currentMode: Math.floor((Math.random() * 20) + 10)
}
}
client.publish(topic, JSON.stringify(payloadJson));
}
注意:裝置端響應的payload要滿足物模型定義的出參結構
3.3 服務端POP 介面InvokeThingService
const co = require(`co`);
const RPCClient = require(`@alicloud/pop-core`).RPCClient;
const options = require("./iot-ak-config.json");
//1.初始化client
const client = new RPCClient({
accessKeyId: options.accessKey,
secretAccessKey: options.accessKeySecret,
endpoint: `https://iot.cn-shanghai.aliyuncs.com`,
apiVersion: `2018-01-20`
});
const params = {
ProductKey: "a1gMu82K4m2",
DeviceName: "h5@nuwr5r9hf6l@1532088166923",
Args: JSON.stringify({ "mode": "1" }),
Identifier: "thing.service.setMode"
};
co(function*() {
try {
//3.發起API呼叫
const response = yield client.request(`InvokeThingService`, params);
console.log(JSON.stringify(response));
} catch (err) {
console.log(err);
}
});
呼叫結果:
{
"Data":{
"Result": "{"currentMode":12}",
"MessageId": "1536145625658"
},
"RequestId": "29FD78CE-D1FF-48F7-B0A7-BD52C142DD7F",
"Success": true
}
相關文章
- SpringBoot Redis 釋出訂閱模式 Pub/SubSpring BootRedis模式
- 【Lintcode】1786. Pub Sub Pattern
- 基於 ThinkPHP 呼叫阿里雲簡訊介面PHP阿里
- Redis的Pub/Sub客戶端實現Redis客戶端
- (一) 基於阿里雲安裝配置部署 docker 詳解阿里Docker
- Spotify如何從Apache kafka遷移到雲平臺的pub/sub系統ApacheKafka
- 阿里雲IoT物聯網平臺-日誌服務詳解阿里
- 阿里雲IoT初試阿里
- 阿里雲IoT物模型-屬性,服務,事件通訊的topic和payload詳解阿里模型事件
- 使用 EMQX Cloud 橋接資料到 GCP Pub/SubMQCloud橋接GC
- 不使用 MQ 如何實現 pub/sub 場景?MQ
- redis原始碼分析之釋出訂閱(pub/sub)Redis原始碼
- 【阿里雲IoT+YF3300】2.阿里雲IoT雲端通訊Alink協議介紹阿里協議
- 非同步呼叫和同步呼叫 及 spring的@Async註解非同步Spring
- 【阿里雲IoT+YF3300】1.時代大背景下的阿里雲IoT物聯網的現狀和未來阿里
- 非同步程式設計:基於事件的非同步程式設計模式(EAP)非同步程式設計事件設計模式
- 阿里雲AIoT正式釋出IoT安全中心和IoT Studio 3.0,進一步鞏固AIoT雲網邊端基礎能力阿里AI
- 基於ECS搭建FTP服務(阿里雲)FTP阿里
- Akka-Cluster(2)- distributed pub/sub mechanism 分散式釋出/訂閱機制分散式
- Redis 中使用 list,streams,pub/sub 幾種方式實現訊息佇列Redis佇列
- 阿里雲IoT流轉到postgresql資料庫方案阿里SQL資料庫
- 基於 ThinkJS 的 WebSocket 通訊詳解JSWeb
- 詳解阿里雲ECS上部署SSL證書的方法阿里
- 阿里雲基於全新 RocketMQ 5.0 核心的落地實踐阿里MQ
- 阿里雲、騰訊雲、CentOS下的MySQL的安裝與配置詳解阿里CentOSMySql
- 阿里雲IoT Studio升級版新增解決方案引擎 大幅提升方案交付效率阿里
- 阿里雲基於ALB實現灰度釋出阿里
- 基於EMR離線資料分析(阿里雲)阿里
- 基於nb-iot的物聯網構建
- 《Node.js設計模式》基於回撥的非同步控制流Node.js設計模式非同步
- MQTT協議與阿里雲IoT物聯網平臺MQQT協議阿里
- Nodejs裝置接入阿里雲IoT物聯網平臺NodeJS阿里
- 解釋一下這兩行 "pub": "pnpm --filter "./packages/*" run pub", "pub:beta": "pnpm --filter "./packages/*" run pub:beta"NPMFilterPackage
- 基於阿里雲 ASK 的 Istio 微服務應用部署初探阿里微服務
- 京東雲開發者|mysql基於binlake同步ES積壓解決方案MySql
- 阿里雲CDN基於雲邊協同的轉型創新實踐阿里
- EMQX + 阿里雲 Tablestore 多場景一站式 IoT 資料解決方案MQ阿里
- Nuxt SSR 阿里雲部署之nginx代理–詳解篇UX阿里Nginx