Skip to content

Commit

Permalink
Merge branch 'master-mirror' into 'master' (merge request !16)
Browse files Browse the repository at this point in the history
merge TME&gateway_scenario
  • Loading branch information
esma committed Aug 27, 2021
2 parents f5f097c + 6103521 commit 93674d6
Show file tree
Hide file tree
Showing 30 changed files with 1,949 additions and 519 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,5 @@
sdk-tests/certs/unittest_private.key
sdk-tests/certs/unittest_private.key
.vscode/settings.json
.vs/
/mplayer
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ set(BUILD_TYPE "release")
set(EXTRACT_SRC OFF)

# 编译工具链
set(COMPILE_TOOLS "gcc")
set(PLATFORM "linux")
set(COMPILE_TOOLS "gcc")
set(PLATFORM "linux")

#set(COMPILE_TOOLS "MSVC")
#set(PLATFORM "windows")
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ $(call CompLib_Map, OTA_COMM_ENABLED, \
$(call CompLib_Map, RESOURCE_UPDATE_ENABLED, \
$(SRC_DIR)/services/resource \
$(SRC_DIR)/services/service_com \
$(SRC_DIR)/services/device_bind \
)

$(call CompLib_Map, FILE_MANAGE_ENABLED, \
Expand Down
26 changes: 7 additions & 19 deletions device_info.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,19 @@
"devPrivateKeyFile": "YOUR_DEVICE_PRIVATE_KEY_FILE_NAME"
},
"subDev": {
"subdev_num": 6,
"subdev_num": 3,
"subdev_list": [
{
"sub_productId": "WPDA0S6S08",
"sub_devName": "dev001"
"sub_productId": "VQ2AWWC1R6",
"sub_devName": "subDev001"
},
{
"sub_productId": "WPDA0S6S08",
"sub_devName": "dev002"
"sub_productId": "VQ2AWWC1R6",
"sub_devName": "subDev002"
},
{
"sub_productId": "WPDA0S6S08",
"sub_devName": "dev003"
},
{
"sub_productId": "Y8T6NB8DM0",
"sub_devName": "test001"
},
{
"sub_productId": "Y8T6NB8DM0",
"sub_devName": "test002"
},
{
"sub_productId": "Y8T6NB8DM0",
"sub_devName": "test003"
"sub_productId": "VQ2AWWC1R6",
"sub_devName": "subDev003"
}
]
},
Expand Down
10 changes: 10 additions & 0 deletions docs/C-SDK_API及可变参数说明.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,13 @@ SDK对于MQTT接口在多线程环境下的使用有如下注意事项:
| 5 | IOT_Gateway_Subscribe | 订阅 MQTT 主题 |
| 6 | IOT_Gateway_Unsubscribe | 取消订阅已订阅的 MQTT 主题 |

### 8. 设备绑定/解绑接口

微信小程序/平台 删除设备时会触发设备解绑,设备也可以主动发起解绑

| 序号 | 函数名 | 说明 |
| ---- | ------------------------- | ----------------------------------------------------------- |
| 1 | IOT_Unbind_Device_ByCloud | 注册回调函数,当微信小程序/平台删除设备时,会调用该回调函数 |
| 2 | IOT_Unbind_Device_Request | 终端设备主动发起设备解绑请求 |
| 3 | | |

77 changes: 77 additions & 0 deletions docs/网关子设备场景示例说明.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
# 网关子设备场景示例说明
本文档将讲述如何在腾讯物联网开发平台(IoT Explorer)控制台申请网关设备并绑定子设备, 并通过C-SDK中的**gateway_sim_sample**,展示网关设备如何管理子设备**subdev_sim_sample**,并代理子设备的上下行消息。

## 一. 创建网关设备和子设备
这部分操作可参考[网关设备快速入门](./网关设备快速入门.md)

## 二. 运行示例
### 1. 编译
在CMakeLists.txt中把FEATURE_GATEWAY_ENABLED这个参数设置为ON,然后执行./cmake_build.sh,即可在output/release/bin下面生成gateway_sim_sample和subdev_sim_sample。
### 2. 运行
(1) 在device_info.json中填入网关的设备信息,包括:productId(对应着控制台的产品ID)、deviceName(对应着控制台的设备名称)、key_deviceinfo->deviceSecret(对应着控制台的设备密钥);
(2) 在控制台运行gateway_sim_sample,日志输出应该如下:
```
INF|2021-07-06 15:42:58|qcloud_iot_device.c|iot_device_info_set(56): SDK_Ver: 3.1.6, Product_ID: XKVP9QORAR, Device_Name: test001
DBG|2021-07-06 15:42:58|HAL_TLS_mbedtls.c|HAL_TLS_Connect(224): Setting up the SSL/TLS structure...
DBG|2021-07-06 15:42:58|HAL_TLS_mbedtls.c|HAL_TLS_Connect(266): Performing the SSL/TLS handshake...
DBG|2021-07-06 15:42:58|HAL_TLS_mbedtls.c|HAL_TLS_Connect(267): Connecting to /XKVP9QORAR.iotcloud.tencentdevices.com/8883...
DBG|2021-07-06 15:42:58|HAL_TLS_mbedtls.c|HAL_TLS_Connect(289): connected with /XKVP9QORAR.iotcloud.tencentdevices.com/8883...
INF|2021-07-06 15:42:58|mqtt_client.c|IOT_MQTT_Construct(125): mqtt connect with id: yfSdT success // 网关连接平台成功
DBG|2021-07-06 15:42:58|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(147): topicName=$gateway/operation/result/XKVP9QORAR/test001|packet_id=4444 // 订阅网关管理topic
DBG|2021-07-06 15:42:58|gateway_api.c|_gateway_event_handler(80): gateway sub|unsub(3) success, packet-id=4444 // 订阅成功
```
(3) 在另外一个控制台运行subdev_sim_sample,运行的格式为./output/release/bin/subdev_sim_sample -p QYEWBRB1PS -d dev1,其中-p后接的是子设备的产品ID,-d后是的子设备的设备名称,运行之后,子设备会和gateway_sim_sample建立连接,并通知网关设备子设备上线,然后会循环上报属性。子设备可运行多个,打开多个控制台,每个控制台运行1个,需要指定不同的productId或deviceName。

子设备的日志如下:
```
DBG|2021-07-06 15:49:36|subdev_sim_sample.c|main(164): connect gateway OK, subdev is going to be online // 通知网关设备子设备上线
DBG|2021-07-06 15:49:37|subdev_sim_sample.c|main(205): Report property {"subdev_type": "report","product_id": "QYEWBRB1PS","device_name": "dev1","msg": "{"method":"report","clientToken":"subdev-1871908611","timestamp":1625557777,"power_switch":0,"color":0,"brightness":0}} // 上报子设备属性到网关设备
DBG|2021-07-06 15:49:53|subdev_sim_sample.c|main(205): Report property {"subdev_type": "report","product_id": "QYEWBRB1PS","device_name": "dev1","msg": "{"method":"report","clientToken":"subdev-1836984528","timestamp":1625557793,"power_switch":0,"color":0,"brightness":0}}
DBG|2021-07-06 15:49:53|subdev_sim_sample.c|main(192): recv {"method":"report_reply","clientToken":"subdev-1836984528","code":0,"status":"success"} // 接收到平台返回的上报成功
```
网关设备的日志如下:
```
DBG|2021-07-06 15:46:45|gateway_sim_sample.c|_accept_new_subdev(339): Recv conn from 127.0.0.1 29285 // 发现新的子设备
DBG|2021-07-06 15:46:47|gateway_sim_sample.c|_deal_with_subdev_msg(382): Get msg {"subdev_type":"online","product_id":"QYEWBRB1PS","device_name":"dev1"} from subdev // 子设备上线
DBG|2021-07-06 15:46:47|gateway_sim_sample.c|_deal_with_subdev_msg(402): itype is 0, pid QYEWBRB1PS dname dev1
DBG|2021-07-06 15:46:47|gateway_api.c|IOT_Gateway_Subdev_Online(191): there is no session, create a new session // 网关新增子设备管理session
DBG|2021-07-06 15:46:47|mqtt_client_publish.c|qcloud_iot_mqtt_publish(347): publish packetID=0|topicName=$gateway/operation/XKVP9QORAR/test001|payload={"type":"online","payload":{"devices":[{"product_id":"QYEWBRB1PS","device_name":"dev1"}]}} // 通知平台子设备在线
INF|2021-07-06 15:46:47|gateway_common.c|_gateway_message_handler(387): client_id(QYEWBRB1PS/dev1), online result 0
DBG|2021-07-06 15:46:47|mqtt_client_subscribe.c|qcloud_iot_mqtt_subscribe(147): topicName=$thing/down/property/QYEWBRB1PS/dev1|packet_id=4445 // 代理子设备订阅属性下行topic
DBG|2021-07-06 15:46:47|gateway_api.c|_gateway_event_handler(80): gateway sub|unsub(3) success, packet-id=4445
INF|2021-07-06 15:46:47|gateway_sim_sample.c|_event_handler(94): subscribe success, packet-id=4445 // 订阅成功
DBG|2021-07-06 15:46:48|gateway_sim_sample.c|_deal_with_subdev_msg(421): sub subdev OK
DBG|2021-07-06 15:47:02|gateway_sim_sample.c|_deal_with_subdev_msg(382): Get msg {"subdev_type": "report","product_id": "QYEWBRB1PS","device_name": "dev1","msg": "{"method":"report","clientToken":"subdev-1531564604","timestamp":1625557622,"power_switch":0,"color":0,"brightness":0}} from subdev // 收到子设备的消息
DBG|2021-07-06 15:47:02|gateway_sim_sample.c|_deal_with_subdev_msg(402): itype is 2, pid QYEWBRB1PS dname dev1
DBG|2021-07-06 15:47:02|gateway_sim_sample.c|_deal_with_subdev_msg(425): msg {"subdev_type": "report","product_id": "QYEWBRB1PS","device_name": "dev1","msg": "{"method":"report","clientToken":"subdev-1531564604","timestamp":1625557622,"power_switch":0,"color":0,"brightness":0}}
DBG|2021-07-06 15:47:02|gateway_sim_sample.c|_property_topic_publish(246): pid QYEWBRB1PS dname dev1
DBG|2021-07-06 15:47:02|gateway_sim_sample.c|_property_topic_publish(259): topic $thing/up/property/QYEWBRB1PS/dev1
DBG|2021-07-06 15:47:02|gateway_sim_sample.c|_property_topic_publish(260): publish msg {"method":"report","clientToken":"subdev-1531564604","timestamp":1625557622,"params":{"power_switch":0,"color":0,"brightness":0}} // 代理子设备上报属性
DBG|2021-07-06 15:47:02|mqtt_client_publish.c|qcloud_iot_mqtt_publish(347): publish packetID=0|topicName=$thing/up/property/QYEWBRB1PS/dev1|payload={"method":"report","clientToken":"subdev-1531564604","timestamp":1625557622,"params":{"power_switch":0,"color":0,"brightness":0}}
INF|2021-07-06 15:47:03|gateway_sim_sample.c|_message_handler(154): Receive Message With topicName:$thing/down/property/QYEWBRB1PS/dev1, payload:{"method":"report_reply","clientToken":"subdev-1531564604","code":0,"status":"success"} // 接收到平台返回的上报返回消息
```
下发控制消息时,网关设备的日志如下:
```
INF|2021-07-06 15:51:02|gateway_sim_sample.c|_message_handler(154): Receive Message With topicName:$thing/down/property/QYEWBRB1PS/dev1, payload:{"method":"control","clientToken":"clientToken-2fd030d1-7f82-4708-ad5a-8905505ff197","params":{"power_switch":1,"color":0,"brightness":80}} // 收到子设备的下行消息,透传给子设备
DBG|2021-07-06 15:51:03|gateway_sim_sample.c|_deal_with_subdev_msg(382): Get msg {"method":"control_reply","clientToken":"clientToken-2fd030d1-7f82-4708-ad5a-8905505ff197","code":0} from subdev // 获取子设备的control回复消息
DBG|2021-07-06 15:51:03|gateway_sim_sample.c|_property_topic_publish(246): pid QYEWBRB1PS dname dev1
DBG|2021-07-06 15:51:03|gateway_sim_sample.c|_property_topic_publish(259): topic $thing/up/property/QYEWBRB1PS/dev1
DBG|2021-07-06 15:51:03|gateway_sim_sample.c|_property_topic_publish(260): publish msg {"method":"control_reply","clientToken":"clientToken-2fd030d1-7f82-4708-ad5a-8905505ff197","code":0}
DBG|2021-07-06 15:51:03|mqtt_client_publish.c|qcloud_iot_mqtt_publish(347): publish packetID=0|topicName=$thing/up/property/QYEWBRB1PS/dev1|payload={"method":"control_reply","clientToken":"clientToken-2fd030d1-7f82-4708-ad5a-8905505ff197","code":0} // 代理子设备回复control消息
```
子设备的日志如下:
```
DBG|2021-07-06 15:51:02|subdev_sim_sample.c|main(192): recv {"method":"control","clientToken":"clientToken-2fd030d1-7f82-4708-ad5a-8905505ff197","params":{"power_switch":1,"color":0,"brightness":80}} // 从网关设备透传下来的控制消息
[ lighting ]|[color: RED ]|[brightness:||||||||||||||||----] // 执行控制操作
DBG|2021-07-06 15:51:07|subdev_sim_sample.c|main(205): Report property {"subdev_type": "report","product_id": "QYEWBRB1PS","device_name": "dev1","msg": "{"method":"report","clientToken":"subdev-2058913913","timestamp":1625557867,"power_switch":1,"color":0,"brightness":80}} // 上报更新之后的属性
```
子设备在运行一段时间后,会离线,离线后网关设备会代理子设备向平台发送offline消息,网关设备的日志如下:
```
DBG|2021-07-06 16:01:30|gateway_sim_sample.c|_subdev_leave(371): unsubscribe $thing/down/property/QYEWBRB1PS/dev1 return 10391 // 解订阅对应的子设备下行topic
DBG|2021-07-06 16:01:30|mqtt_client_publish.c|qcloud_iot_mqtt_publish(347): publish packetID=0|topicName=$gateway/operation/XKVP9QORAR/test001|payload={"type":"offline","payload":{"devices":[{"product_id":"QYEWBRB1PS","device_name":"dev1"}]}} // 通知子设备离线
DBG|2021-07-06 16:01:30|gateway_api.c|_gateway_event_handler(80): gateway sub|unsub(6) success, packet-id=10391 // 解订阅成功
INF|2021-07-06 16:01:30|gateway_sim_sample.c|_event_handler(109): unsubscribe success, packet-id=10391
```
## 三. 代码说明
1. 网关和子设备之间使用了本地TCP socket通信来模拟,在实际的场景下,可以换成BLE通信、ZigBee通信等等;
2. 子设备只演示了Property上行和下行操作,如果要使用Event和Action,可以参考light_data_template_sample.c中的代码添加到网关设备和子设备的程序中,网关设备需要添加代理订阅对应下行topic的代码,子设备则需要添加上下行消息的处理代码。
30 changes: 15 additions & 15 deletions include/exports/qcloud_iot_export_data_template.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,14 +34,15 @@ extern "C" {
* @brief Data type of template
*/

#define TYPE_TEMPLATE_INT JINT32
#define TYPE_TEMPLATE_ENUM JINT32
#define TYPE_TEMPLATE_FLOAT JFLOAT
#define TYPE_TEMPLATE_BOOL JINT8
#define TYPE_TEMPLATE_STRING JSTRING
#define TYPE_TEMPLATE_TIME JUINT32
#define TYPE_TEMPLATE_JOBJECT JOBJECT
#define TYPE_TEMPLATE_STRINGENUM JSTRING
#define TYPE_TEMPLATE_INT JINT32
#define TYPE_TEMPLATE_ENUM JINT32
#define TYPE_TEMPLATE_FLOAT JFLOAT
#define TYPE_TEMPLATE_BOOL JINT8
#define TYPE_TEMPLATE_STRING JSTRING
#define TYPE_TEMPLATE_TIME JUINT32
#define TYPE_TEMPLATE_JOBJECT JOBJECT
#define TYPE_TEMPLATE_STRINGENUM JSTRING
#define TYPE_TEMPLATE_ARRAY JARRAY

typedef int32_t TYPE_DEF_TEMPLATE_INT;
typedef int32_t TYPE_DEF_TEMPLATE_ENUM;
Expand All @@ -52,7 +53,6 @@ typedef uint32_t TYPE_DEF_TEMPLATE_TIME;
typedef void * TYPE_DEF_TEMPLATE_OBJECT;
typedef char TYPE_DEF_TEMPLATE_STRINGENUM;


#ifdef EVENT_POST_ENABLED // enable event function of data_template

#define TYPE_STR_INFO "info"
Expand Down Expand Up @@ -85,10 +85,10 @@ typedef struct _sEvent_ {

#endif

typedef enum{
eGET_CTL,
eOPERATION_CTL,
}eControlType;
typedef enum {
eGET_CTL,
eOPERATION_CTL,
} eControlType;
typedef void (*ControlMsgCb)(void *pClient, char *control_str, eControlType type);

/* The structure of data_template init parameters */
Expand All @@ -114,8 +114,8 @@ typedef struct {
uint8_t auto_connect_enable; // flag of auto reconnection, 1 is enable and
// recommended

MQTTEventHandler event_handle; // event callback
ControlMsgCb usr_control_handle; // user can register cb to handle control msg instend of sdk's handle
MQTTEventHandler event_handle; // event callback
ControlMsgCb usr_control_handle; // user can register cb to handle control msg instend of sdk's handle
} TemplateInitParams;

#ifdef AUTH_MODE_CERT
Expand Down
17 changes: 13 additions & 4 deletions include/exports/qcloud_iot_export_device_bind.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,23 +23,32 @@ extern "C" {

/**
* @brief Register a callback function to receive the device unbinding message
* sent by the platform
* sent by the platform.
* before use it you must call qcloud_service_mqtt_init() to sub service topic
*
* @param callback [in] a callback function
* @param context [in] the program context
* @return QCLOUD_RET_SUCCESS for success, or err code for failure
*/
int IOT_Unbind_Device_Register(void *callback, void *context);
/**
* @brief Register a callback function to receive the device unbinding message
* sent by the platform
*
* @param mqtt_client the mqtt client
* @param callback [in] a callback function
* @param context [in] the program context
* @return QCLOUD_RET_SUCCESS for success, or err code for failure
*/
int IOT_Unbind_Device_ByCloud(void *mqtt_client, void *callback, void *context);
/**
* @brief Actively initiate a request to unbind the device to the platform
*
* @param mqtt_client the mqtt client
* @param productId deviceInfo.productId
* @param deviceName deviceInfo.deviceName
* @param timeout_ms timeout value (unit: ms) for this operation
* @return QCLOUD_RET_SUCCESS for success, or err code for failure
*/
int IOT_Unbind_Device_Request(void *mqtt_client, const char *productId, const char *deviceName, int timeout_ms);
int IOT_Unbind_Device_Request(void *mqtt_client, int timeout_ms);

#ifdef __cplusplus
}
Expand Down
3 changes: 3 additions & 0 deletions include/exports/qcloud_iot_export_gateway.h
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,9 @@ int IOT_Gateway_EnableLocalAutoMation(void *client, QCLOUD_IO_GATEWAY_AUTOMATION

#endif

int IOT_Gateway_Subdev_GetBindList(void *client, GatewayParam *param, SubdevBindList *subdev_bindlist);
void IOT_Gateway_Subdev_DestoryBindList(SubdevBindList *subdev_bindlist);

#ifdef __cplusplus
}
#endif
Expand Down
22 changes: 21 additions & 1 deletion include/exports/qcloud_iot_export_method.h
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -49,17 +49,37 @@ typedef enum {
/**
* @brief JSON data type
*/
typedef enum { JINT32, JINT16, JINT8, JUINT32, JUINT16, JUINT8, JFLOAT, JDOUBLE, JBOOL, JSTRING, JOBJECT } JsonDataType;
typedef enum {
JINT32,
JINT16,
JINT8,
JUINT32,
JUINT16,
JUINT8,
JFLOAT,
JDOUBLE,
JBOOL,
JSTRING,
JOBJECT,
JARRAY,
} JsonDataType;

/**
* @brief Define a device property, as a JSON document node
*/
#if defined(__CC_ARM)
#pragma anon_unions
#endif
typedef struct _JSONNode {
char *key; // Key of this JSON node
void *data; // Value of this JSON node
union {
uint16_t data_buff_len; // data buff len, for string type value update
uint16_t struct_obj_num; // member number of struct
struct {
uint16_t array_size;
JsonDataType array_type;
} array_info;
};
JsonDataType type; // Data type of this JSON node
} DeviceProperty;
Expand Down
Loading

0 comments on commit 93674d6

Please sign in to comment.