sdk代码请点击这里获取
网关设备简介
对于 BLE、Zigbee 和485等不具备直接访问网络能力的设备,需要先接入网关,然后通过网关代理,间接实现设备接入腾讯物联网开发平台 IoT Explorer,具体流程框架图如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-laOq4Nby-1650454646545)(https://main.qcloudimg.com/raw/f419fff3725378c770b7264ddb93b170.svg)]
那么对于一个网关设备来讲,其基本的核心功能是:
-
网关设备自己是一个全功能的腾讯云物联网开发平台设备。在不做子设备代理时,完全可以将网关设备当作是一个普通腾讯云物联网开发平台的设备来操作。很多初学者有个误区,网关设备是代理子设备通讯的,自身没有和平台通讯的业务,这个理解是完全错误的。举个例子:网关设备可以是一个内置了433无线收发器的WiFi智能插座,那么作为一个插座,就应该先具备插座开关的功能,然后才是代理周围433子设备上下线。 -
动态绑定/解绑子设备。很明显,绑定和解绑子设备就是要子设备和网关建立一个拓扑关系。举个例子:就像孩子和父亲,一个父亲可能有两三个孩子,那么这个父亲就要对孩子的衣食住行负责,而对于其他不相干的孩子,则这位父亲是不需要负责的。绑定就是相当于承认了父子关系,解绑就相当于是断绝了父子关系。当然了,在现实世界中,这种父子关系不是动态的。 -
代理子设备上下线。举个例子,当一个蓝牙网关扫描到附近有子设备的蓝牙广播并建立了连接后,就可以通过网关来通知云平台,当前有子设备正在活动,可以上线。同样的,当一个子设备长时间没有和这个蓝牙网关通讯且发消息不回复时(具体的离线策略可以自行定义,如:一个小时收不到子设备消息且ping不通子设备)就可以认为当前子设备离线,从而通知云平台下线子设备。 -
代理子设备通讯。这个功能是网关设备存在的意义,之所以需要网关设备就是代理一些无法直接接入物联网设备的数据。网关在这里就起到一个传话的功能。腾讯云物联网的网关设备是完全透传子设备的消息。举个例子,我们知道腾讯云物联网开发平台的属性是通过这个mqtt topic 来传输的:
- 数据上行 Topic(用于发布):
$property/up/${productid}/${devicename} - 数据下行 Topic(用于订阅):
$property/down/${productid}/${devicename} 那么网关也不会重新再使用其他的topic来传输子设备的数据。换句话说,网关产品与子产品建立绑定,获取子设备的 Topic 权限后,网关设备可以使用子设备Topic代理进行收发消息,同时可以在设备调试-设备日志中查看通信信息。 -
代理子设备升级。子设备也有更新固件的需求,那么网关设备可以将子设备的固件从后台拉下来,然后发送给子设备升级,整个流程如图所示:
? 和普通设备升级相同的是,整个升级的流程会走普通设备升级的那一套流程,包括版本上报、升级url 的获取等等。但是,和普通设备升级不同的是,子设备升级需要网关设备先将子设备的固件存起来,然后通过私有协议(可以是BLE zigbee 433 等等)将固件发送给子设备,获取子设备的升级状态后,再将升级的结果告诉云平台。
具体的网关子设备拓扑关系管理协议,请点击这里获取。
网关设备代码设计
了解了网关设备的功能,我们来思考一下网关设备代码如何设计,然后来看看腾讯云物联网开发平台的设备端sdk 是如何设计网关功能的。
首先,子设备的数量是未知的,可能有的网关会带3个子设备,有的可能会带30个,所以网关设计的时候,就需要考虑使用列表功能来管理子设备。其次,网关设备必须具备管理子设备的功能,即可以代理子设备的绑定解绑、上下线数据通讯等;这就需要维护子设备的状态。我们来看一下网关结构体的构造:
typedef struct {
void *mqtt_client;
MQTTEventHandler evt_handle;
GatewayClientPriv *priv;
void *event_context;
gateway_event_handle_cb_t gateway_evt_cb;
char gateway_pub_topic[MAX_SIZE_OF_GATEWAY_PUB_TOPIC];
} GatewayClient;
我们再来看一下子设备的结构体构造:
typedef enum {
GATEWAY_SUBDEV_STATUS_ONLINE = 0,
GATEWAY_SUBDEV_STATUS_OFFLINE,
} GatewaySubStatus;
typedef struct {
DeviceInfo dev_info;
GatewaySubStatus status;
int is_binded;
void *node;
} GatewaySub;
Demo日志分析
网关设备上电后,会使用自己的三元组信息连接腾讯云物联网开发平台
INF|2022-04-20 17:48:42|mqtt_client.c|_qcloud_iot_mqtt_client_init(213): SDK_Ver: 4.0.0, Product_ID: 40FA6IALWV, Device_Name: gateway001
DBG|2022-04-20 17:48:42|qcloud_iot_tls_client.c|qcloud_iot_tls_client_connect(212): Setting up the SSL/TLS structure...
DBG|2022-04-20 17:48:42|qcloud_iot_tls_client.c|qcloud_iot_tls_client_connect(252): Performing the SSL/TLS handshake...
DBG|2022-04-20 17:48:42|qcloud_iot_tls_client.c|qcloud_iot_tls_client_connect(253): Connecting to /40FA6IALWV.iotcloud.tencentdevices.com/8883...
DBG|2022-04-20 17:48:43|qcloud_iot_tls_client.c|qcloud_iot_tls_client_connect(281): connected with /40FA6IALWV.iotcloud.tencentdevices.com/8883...
INF|2022-04-20 17:48:43|mqtt_client.c|IOT_MQTT_Construct(329): mqtt connect with id: C81F6 success
INF|2022-04-20 17:48:43|gateway_sample.c|main(303): Cloud Device Construct Success
连接成功后,会订阅网关topic,接受网关下行消息
DBG|2022-04-20 17:48:43|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(329): subscribe topic_name=$gateway/operation/result/40FA6IALWV/gateway001|packet_id=7041
INF|2022-04-20 17:48:43|gateway_sample.c|_mqtt_event_handler(75): subscribe success, packet-id=7041
发送describe_sub_devices消息,从云平台拉取当前网关设备的拓扑关系
DBG|2022-04-20 17:48:43|mqtt_client_publish.c|qcloud_iot_mqtt_publish(264): publish qos=0|packet_id=0|topic_name=$gateway/operation/40FA6IALWV/gateway001|payload={"type":"describe_sub_devices"}
云平台回复:
DBG|2022-04-20 17:48:43|gateway_message_handle.c|gateway_message_handler(204): receive gateway message {"type":"describe_sub_devices","payload":{"devices":[{"product_id":"KRLT1QGQW5","device_name":"subdev001"},{"product_id":"KRLT1QGQW5","device_name":"subdev002"},{"product_id":"KRLT1QGQW5","device_name":"subdev003"},{"product_id":"KRLT1QGQW5","device_name":"subdev004"}]}}
当前有四台子设备已经和网关设备绑定。
绑定子设备
绑定子设备需要网关设备知道子设备的三元组信息,这个三元组信息可以从子设备获取,或者从云平台获取。获取到三元组信息后,需要网关设备本地做一个签名,生成signature字段。
DBG|2022-04-20 17:48:43|gateway_sub_manage.c|IOT_Gateway_AddSub(332): Add 0x5647bd29fb70 KRLT1QGQW5:subdev006
DBG|2022-04-20 17:48:43|mqtt_client_publish.c|qcloud_iot_mqtt_publish(264): publish qos=0|packet_id=0|topic_name=$gateway/operation/40FA6IALWV/gateway001|payload={"type":"bind",
"payload":{"devices":[{"product_id":"KRLT1QGQW5","device_name":"subdev006","signature":"+j45scCBXI9qCDioF7m1NB4VuOU=","random":1603981974,"timestamp":1650448123,"signmethod":"hmacsha1","authtype":"psk"}]}}
云平台回复:
DBG|2022-04-20 17:48:43|gateway_message_handle.c|gateway_message_handler(204): receive gateway message {"type":"bind","payload":{"devices":[{"result":0,"product_id":"KRLT1QGQW5","device_name":"subdev006"}]}}
INF|2022-04-20 17:48:43|gateway_message_handle.c|gateway_message_handler(211): Get type 2 from server
DBG|2022-04-20 17:48:43|gateway_message_handle.c|_gateway_down_array_result_parse(113): bind device KRLT1QGQW5:subdev006
INF|2022-04-20 17:48:43|gateway_sample.c|_mqtt_event_handler(111): gateway topology changed --- subdev KRLT1QGQW5:subdev006 change to binded
同时我们也收到一条_mqtt_event_handler事件来通知有新设备加入当前网关设备的拓扑关系。当此设备上线后,就可以正常代理此子设备进行通讯了。
解绑子设备
解绑就比较简单,直接发送需要解绑的设备列表给云平台即可,同时本地也要更新拓扑关系
DBG|2022-04-20 17:49:02|mqtt_client_publish.c|qcloud_iot_mqtt_publish(264): publish qos=0|packet_id=0|topic_name=$gateway/operation/40FA6IALWV/gateway001|payload={"type":"unbind", "payload":{"devices":[{"product_id":"KRLT1QGQW5","device_name":"subdev006"}]}}
云平台回复:
DBG|2022-04-20 17:49:02|gateway_message_handle.c|gateway_message_handler(204): receive gateway message {"type":"unbind","payload":{"devices":[{"product_id":"KRLT1QGQW5","device_name":"subdev006","result":0}]}}
INF|2022-04-20 17:49:02|gateway_message_handle.c|gateway_message_handler(211): Get type 3 from server
DBG|2022-04-20 17:49:02|gateway_message_handle.c|_gateway_down_array_result_parse(117): del device KRLT1QGQW5:subdev006
INF|2022-04-20 17:49:02|gateway_sample.c|_mqtt_event_handler(111): gateway topology changed --- subdev KRLT1QGQW5:subdev006 change to unbinded
同时收到一条_mqtt_event_handler事件来通知有设备解绑,后续不应该再将此设备的消息通过网关代理。
代理子设备上线
DBG|2022-04-20 17:48:45|mqtt_client_publish.c|qcloud_iot_mqtt_publish(264): publish qos=0|packet_id=0|topic_name=$gateway/operation/40FA6IALWV/gateway001|payload={"type":"online", "payload":{"devices":[{"product_id":"KRLT1QGQW5","device_name":"subdev001"}]}}
当前子设备成功上线后,就可以和云平台做数据交互了。
代理子设备下线
DBG|2022-04-20 17:48:51|mqtt_client_publish.c|qcloud_iot_mqtt_publish(264): publish qos=0|packet_id=0|topic_name=$gateway/operation/40FA6IALWV/gateway001|payload={"type":"offline", "payload":{"devices":[{"product_id":"KRLT1QGQW5","device_name":"subdev001"}]}}
DBG|2022-04-20 17:48:51|gateway_sample.c|_test_array_cb(243): test return 0
DBG|2022-04-20 17:48:51|gateway_message_handle.c|gateway_message_handler(204): receive gateway message {"type":"offline","payload":{"devices":[{"product_id":"KRLT1QGQW5","device_name":"subdev001","result":0}]}}
INF|2022-04-20 17:48:51|gateway_message_handle.c|gateway_message_handler(211): Get type 1 from server
INF|2022-04-20 17:48:51|gateway_sample.c|_mqtt_event_handler(117): gateway status changed --- subdev KRLT1QGQW5:subdev001 change to offline
同时收到一条_mqtt_event_handler事件来通知有设备下线,后续不应该再上报子设备的信息到网关。
|