阿里云MQTT: 子设备上线流程

0. 背景

阿里云网关子设备上平台的资料很少。有些厂家直接配置每个子设备的DeviceSecret到网关里,显然太麻烦了!我经过阅读阿里文档,发现有些简化的方法,更便于客户使用,因此分享给大家。

1. 主要信息片段

子设备 ${SubProductKey} ${SubDeviceName}  ${SubDeviceSecret}
父网关 ${DadProductKey} ${DadDeviceName} ${DadDeviceSecret}

Product就是所有相同属性和操作的设备的集合或者类。Key就是一串唯一标识了。
Device就是具体一个产品的实例或对象了。
Name就是设备的唯一标识,阿里要求在自己的Product内唯一即可。这就是为什么我起个dev01的名字,系统不提示重名的原因。产品名字空间不同而已。
Secret就是一个密钥,加密用到。到底是公钥还是私钥没深入研究。

2. 阿里平台准备。

父网关必须已具备上线能力。子设备是依赖父网关的MQTT通道上线的。子设备至少已经在平台添加好产品和具体设备。剩下的工作就由父网关设备内部的软件,自动让设备注册,建立拓扑,上线

3.网关内部Alink流程

3.1 动态注册

名字起的不知所云,经过试验,说白了就是查询子设备的${SubDeviceSecret}

父网关发布主题:/sys/${DadProductKey}/${DadDeviceName}/thing/sub/register
父网关订阅主题:/sys/${DadProductKey}/${DadDeviceName}/thing/sub/register_reply

{
  "id": "123",
  "version": "1.0",
  "sys":{
      "ack":1
  },
  "params": [
    {  
      "deviceName": ${SubDeviceName}, 
      "productKey": ${SubProductKey}
    }
  ],
  "method": "thing.sub.register"
}

如果返回200,${SubDeviceSecret}也就抓取到手。

3.2 建立拓扑
说白了,目的是建立子设备与网关的父子关系(如果原先已建立,也会返回成功)

父网关发布主题:/sys/${DadProductKey}/${DadDeviceName}/thing/topo/add
父网关订阅主题:/sys/${DadProductKey}/${DadDeviceName}/thing/topo/add_reply

{
  "id": "123",
  "version": "1.0",
  "sys":{
      "ack":1
  },
  "params": [
    {  
      "deviceName": ${SubDeviceName},
      "productKey": ${SubProductKey},
      "sign": "3908C94C2D9F33AC50A4CC9B1C4BCD45093E3EA4",
      "signmethod": "hmacSha1",
      "timestamp": "1701008186820",
      "clientId":  ${SubProductKey} & ${SubDeviceName}
    }
  ],
  "method": "thing.topo.add"
}

sign这个字段怎么填呢?

这里给个提示:
第一步把参数输入到设备信息框。
第二步点击generate。
第三步:password框里的内容就是sign。

如果返回200,就是建好了父子关系。这样多好,不用在平台上操作费劲了。

3.3 子设备上线

网关应该有感知子设备上线下线的能力。如果子设备上线,父网关应该把子设备上线的事告知平台

父网关发布主题:/ext/session/${DadProductKey}/${DadDeviceName}/combine/login

{
  "id": "123",
  "params": {
      "deviceName": ${SubDeviceName},
      "productKey": ${SubProductKey},
      "timestamp": "1701008186820",
      "clientId": ${SubProductKey}&${SubDeviceName},
      "cleanSession": "true",
      "signMethod": "hmacmd5",
      "sign": "729FB99CA14B62BAD356A22F3B58AC78"
  }
}

注意,自己计算签名sign字段时,不能把"cleanSession"算进去,具体参考Alink协议文档。

3.4 子设备业务数据传输到平台

这个就又多种方法了,有完全透传的,有半透传半翻译的,有完全Alink物模型方式的。
我搞了个物模型方式的。

网关发布主题: /sys/${SubProductKey}/${SubDeviceName}/thing/event/property/post

{
    "id": "123",
    "version": "1.0",
    "sys":{
        "ack":0
    },
    "params": {
        "temperature": 24
    },
    "method": "thing.event.property.post"
}
这里发布一个温度值24度,给平台。

3.5 其他问题
子设备下线,父子关系解除,应该举一反三,自己研究就会了吧?

3.6 异类子设备混编在一个网关下
网关应能识别子设备属于哪种产品。当子设备的产品变更后,网关应能重新处理。
例如modbus网关下,1号从机,原先是灯控开关产品,重新给1号设备分配到智能插座上。
首先在阿里平台上,删除1号(笔者写作时,平台禁止设备改产品),在添加一次1号。
然后,网关设备与1号设备重新配对一次,1号现在是智能插座了,网关因为知道智能插座的
ProducyKey,就会触发注册,拓扑这一套流程,执行后,要记住最重要的一点,把子设备的${SubDeviceSecret}写到E2ROM存起来。也就是如果存过这个密钥,说明执行过一次注册流程。
还有一点补充一下,如果阿里平台手动操作加的父子拓扑,并且网关设备里存的子设备密钥有效,则网关里认为的子设备类型,与平台认为的子设备类型可能不一致,造成传输错误。有一个解决方案,就是网关下的子设备透传自己定义的数据,传到平台后,用平台的”消息解析“功能做物模型翻译。反正路子非常多,体现了阿里云设计的精妙之处。

4.  今天继续。发现很多问题。
4.1 子设备限制太多,平台下发的属性设置,服务调用等Alink协议(JSON大包),里面没有子设备的描述。我只能通过主题,截取里面的deviceName信息,抓取子设备身份。但是如果用透传产品需要消息解析,则无法通过预定义的function protocolToRawData(jsonObj)函数,抓取deviceName(因为参数里,只有jsonObj一个,缺个Topic,是否给阿里提工单呢?)。

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是使用C++ paho mqtt库中的mqtt::topic发布json对象的示例代码: ```c++ #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <json/json.h> #include "mqtt/async_client.h" using namespace std; const string ADDRESS("tcp://localhost:1883"); const string CLIENTID("AsyncPublisher"); const string TOPIC("test"); const int QOS = 1;const int TIMEOUT = 10000L; class callback : public virtual mqtt::callback { public: virtual void connection_lost(const std::string& cause) { cout << "\nConnection lost" << endl; if (!cause.empty()) cout << "\tcause: " << cause << endl; } virtual void delivery_complete(mqtt::delivery_token_ptr token) { cout << "\n\tDelivery complete for token: " << (token ? token->get_message_id() : -1) << endl; } }; int main(int argc, char* argv[]) { mqtt::async_client client(ADDRESS, CLIENTID); mqtt::connect_options connOpts; connOpts.set_keep_alive_interval(20); connOpts.set_clean_session(true); callback cb; client.set_callback(cb); try { mqtt::token_ptr conntok = client.connect(connOpts); conntok->wait_for_completion(); Json::Value root; root["name"] = "John"; root["age"] = 25; root["email"] = "[email protected]"; string json_str = root.toStyledString(); mqtt::message_ptr pubmsg = mqtt::make_message(TOPIC, json_str); pubmsg->set_qos(QOS); mqtt::delivery_token_ptr pubtok = client.publish(pubmsg); pubtok->wait_for_completion(TIMEOUT); cout << "Message '" << json_str << "' published to topic '" << TOPIC << "'" << endl; client.disconnect()->wait_for_completion(); } catch (const mqtt::exception& exc) { cerr << exc.what() << endl; return 1; } return 0; } ``` 在这个示例中,我们使用了Jsoncpp库来创建一个Json对象,并将其转换为字符串。然后,我们使用mqtt::make_message()函数创建一个mqtt::message_ptr对象,该对象包含要发布的主题和消息。最后,我们使用mqtt::async_client类的publish()函数将消息发布到主题上。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值