1 /**
2  * @file aiot_devinfo_api.h
3  * @brief devinfo模块头文件, 提供更新和删除设备标签的能力
4  *
5  * @copyright Copyright (C) 2015-2020 Alibaba Group Holding Limited
6  *
7  * @details
8  *
9  * Devinfo模块用于向阿里云物联网平台更新或删除设备的标签, API的使用流程如下:
10  *
11  * 1. 首先参考 @ref aiot_mqtt_api.h 的说明, 保证成功建立与物联网平台的`MQTT`连接
12  *
13  * 2. 调用 @ref aiot_devinfo_init 初始化devinfo会话, 获取会话句柄
14  *
15  * 3. 调用 @ref aiot_devinfo_setopt 配置devinfo会话的参数, 常用配置项见 @ref aiot_devinfo_setopt 的说明
16  *
17  * 4. 调用 @ref aiot_devinfo_send 发送标签变更的请求, 比如更新或删除
18  *
19  * 5. 收到的应答经SDK处理后会调用由 @ref aiot_devinfo_setopt 配置的 @ref AIOT_DEVINFOOPT_RECV_HANDLER 回调函数, 通知用户云端的应答
20  *
21  */
22 #ifndef __AIOT_DEVINFO_API_H__
23 #define __AIOT_DEVINFO_API_H__
24 
25 #if defined(__cplusplus)
26 extern "C" {
27 #endif
28 
29 #include <stdint.h>
30 
31 /**
32  * @brief -0x1200~-0x12FF表达SDK在devinfo模块内的状态码
33  */
34 #define STATE_DEVINFO_BASE                                             (-0x1200)
35 
36 /**
37  * @brief MQTT会话句柄未设置, 请通过 @ref aiot_devinfo_setopt 设置MQTT会话句柄
38  */
39 #define STATE_DEVINFO_MISSING_MQTT_HANDLE                              (-0x1201)
40 
41 /**
42  * @brief devinfo模块收到从网络上来的报文时, 通知用户的报文类型
43  */
44 typedef enum {
45     AIOT_DEVINFORECV_GENERIC_REPLY,
46 } aiot_devinfo_recv_type_t;
47 
48 typedef struct {
49     /**
50      * @brief 消息标识符, uint64_t类型的整数, 与属性上报或事件上报的消息标示符一致
51      */
52     uint32_t msg_id;
53     /**
54      * @brief 设备端错误码, 200-请求成功, 更多错误码码查看<a href="https://help.aliyun.com/document_detail/120329.html">设备端错误码</a>
55      */
56     uint32_t code;
57     /**
58      * @brief 指向云端应答数据的指针
59      */
60     char *data;
61     /**
62      * @brief 云端应答数据的长度
63      */
64     uint32_t data_len;
65     /**
66      * @brief 指向状态消息字符串的指针, 当设备端上报请求成功时对应的应答消息为"success", 若请求失败则应答消息中包含错误信息
67      */
68     char *message;
69     /**
70      * @brief 消息字符串的长度
71      */
72     uint32_t message_len;
73 } aiot_devinfo_recv_generic_reply_t;
74 
75 /**
76  * @brief devinfo模块收到从网络上来的报文时, 通知用户的报文内容
77  */
78 typedef struct {
79     char *product_key;
80     char *device_name;
81     /**
82      * @brief 报文内容所对应的报文类型, 更多信息请参考@ref aiot_devinfo_recv_type_t
83      */
84     aiot_devinfo_recv_type_t  type;
85     union {
86         /**
87          * @brief 从云端收到的更新或删除设备标签的应答
88          */
89         aiot_devinfo_recv_generic_reply_t generic_reply;
90     } data;
91 } aiot_devinfo_recv_t;
92 
93 /**
94  * @brief devinfo模块收到从网络上来的报文时, 通知用户所调用的数据回调函数
95  *
96  * @param[in] handle devinfo会话句柄
97  * @param[in] packet devinfo消息结构体, 存放收到的devinfo报文内容
98  * @param[in] userdata 用户上下文
99  *
100  * @return void
101  */
102 typedef void (* aiot_devinfo_recv_handler_t)(void *handle, const aiot_devinfo_recv_t *packet, void *userdata);
103 
104 /**
105  * @brief devinfo模块内部发生值得用户关注的状态变化时, 通知用户的事件类型
106  */
107 typedef enum {
108     /**
109      * @brief 收到的应答中设备信息不合法, 无法获取product key和device name
110      */
111     AIOT_DEVINFOEVT_INVALID_DEVINFO,
112     /**
113      * @brief 收到的应答中字段不合法
114      */
115     AIOT_DEVINFOEVT_INVALID_RESPONSE,
116     /**
117      * @brief 收到的应答中字段格式错误
118      */
119     AIOT_DEVINFOEVT_INVALID_RESPONSE_FORMAT,
120 } aiot_devinfo_event_type_t;
121 
122 /**
123  * @brief devinfo模块内部发生值得用户关注的状态变化时, 通知用户的事件内容
124  */
125 typedef struct {
126     /**
127      * @brief 事件内容所对应的事件类型, 更多信息请参考@ref aiot_devinfo_event_type_t
128      */
129     aiot_devinfo_event_type_t  type;
130 } aiot_devinfo_event_t;
131 
132 /**
133  * @brief devinfo模块内部发生值得用户关注的状态变化时, 通知用户所调用的事件回调函数
134  *
135  * @param[in] handle, devinfo会话句柄
136  * @param[in] event, devinfo模块中发生的事件的内容
137  * @param[in] userdata, 用户上下文
138  *
139  * @return void
140  */
141 typedef void (*aiot_devinfo_event_handler_t)(void *handle, const aiot_devinfo_event_t *event, void *userdata);
142 
143 /**
144  * @brief @ref aiot_devinfo_msg_t 中的发送消息类型
145  *
146  * @details
147  *
148  * 消息类型有两个, 分别是更新设备标签和删除设备标签
149  */
150 typedef enum {
151     /**
152      * @brief 更新设备标签
153      */
154     AIOT_DEVINFO_MSG_UPDATE,
155     /**
156      * @brief 删除设备标签
157      */
158     AIOT_DEVINFO_MSG_DELETE
159 } aiot_devinfo_msg_type_t;
160 
161 /**
162  * @brief 更新或删除设备标签的params内容
163  */
164 typedef struct {
165     char *params;
166 } aiot_devinfo_msg_data_t;
167 
168 typedef struct {
169     /**
170      * @brief 设备的product key
171      */
172     char *product_key;
173     /**
174      * @brief 设备的device name
175      */
176     char *device_name;
177     /**
178      * @brief 消息类型, 更多信息请参考@ref aiot_devinfo_msg_type_t
179      */
180     aiot_devinfo_msg_type_t type;
181     union {
182         /**
183          * @brief 更新设备标签, 格式:"[{\"attrKey\":\"xxx\",\"attrValue\":\"yyy\"}]"
184          *
185          * @details
186          *
187          * 从上述格式可以看出,更新设备标签的格式是一个JSON数组,一次可按attrKey和attrValue上报多组设备标签
188          */
189         aiot_devinfo_msg_data_t update;
190         /**
191          * @brief 删除设备标签, 格式:"[{\"attrKey\":\"xxx\"}]"
192          *
193          * @details
194          *
195          * 从上述格式可以看出,删除设备标签的格式是一个JSON数组,一次可按attrKey删除多组设备标签
196          */
197         aiot_devinfo_msg_data_t delete;
198     } data;
199 } aiot_devinfo_msg_t;
200 
201 /**
202  * @brief @ref aiot_devinfo_setopt 接口的option参数可选值.
203  *
204  * @details 下文每个选项中的数据类型, 指的是@ref aiot_devinfo_setopt 中, data参数的数据类型
205  *
206  * 1. data的数据类型是void *时, 以配置@ref AIOT_DEVINFOOPT_MQTT_HANDLE 为例:
207  *
208  *    void *mqtt_handle = aiot_mqtt_init();
209  *    aiot_devinfo_setopt(devinfo_handle, AIOT_DEVINFOOPT_MQTT_HANDLE, mqtt_handle);
210  *
211  * 2. data的数据类型是其他数据类型时, 以配置@ref AIOT_DEVINFOOPT_DEINIT_TIMEOUT_MS 为例:
212  *
213  *    uint32_t deinit_timeout_ms = 443;
214  *    aiot_devinfo_setopt(devinfo_handle, AIOT_DEVINFOOPT_DEINIT_TIMEOUT_MS, (void *)&deinit_timeout_ms);
215  */
216 typedef enum {
217     /**
218      * @brief devinfo会话 需要的MQTT句柄, 需要先建立MQTT连接, 再设置MQTT句柄
219      */
220     AIOT_DEVINFOOPT_MQTT_HANDLE,
221 
222     /**
223      * @brief 设置回调, 它在SDK收到网络报文的时候被调用, 告知用户
224      *
225      * @details
226      *
227      * 数据类型: ( @ref aiot_devinfo_recv_handler_t)
228      */
229     AIOT_DEVINFOOPT_RECV_HANDLER,
230 
231     /**
232      * @brief 设置回调, 它在SDK发生内部状态变更时被调用, 告知用户
233      *
234      * @details
235      *
236      * 数据类型: ( @ref aiot_devinfo_event_handler_t)
237      */
238     AIOT_DEVINFOOPT_EVENT_HANDLER,
239 
240     /**
241      * @brief 用户需要SDK暂存的上下文, 数据类型为(void *)
242      *
243      * @details 这个上下文指针会在 AIOT_DEVINFOOPT_RECV_HANDLER 和 AIOT_DEVINFOOPT_EVENT_HANDLER 设置的回调被调用时, 由SDK传给用户
244      */
245     AIOT_DEVINFOOPT_USERDATA,
246 
247     /**
248      * @brief 销毁devinfo实例时, 等待其他api执行完毕的时间
249      *
250      * @details
251      *
252      * 当调用@ref aiot_devinfo_deinit 销毁devinfo实例时, 若继续调用其他aiot_devinfo_xxx API, API会返回@ref STATE_USER_INPUT_EXEC_DISABLED 错误
253      *
254      * 此时, 用户应该停止调用其他aiot_devinfo_xxx API
255      *
256      * 数据类型: (uint32_t *) 默认值: (2 * 1000) ms
257      */
258     AIOT_DEVINFOOPT_DEINIT_TIMEOUT_MS,
259     AIOT_DEVINFOOPT_MAX
260 } aiot_devinfo_option_t;
261 
262 /**
263  * @brief 创建devinfo会话实例, 并以默认值配置会话参数
264  *
265  * @return void *
266  * @retval 非NULL devinfo实例的句柄
267  * @retval NULL   初始化失败, 一般是内存分配失败导致
268  *
269  */
270 void *aiot_devinfo_init(void);
271 
272 /**
273  * @brief 配置devinfo会话
274  *
275  * @param[in] handle devinfo会话句柄
276  * @param[in] option 配置选项, 更多信息请参考@ref aiot_devinfo_option_t
277  * @param[in] data   配置选项数据, 更多信息请参考@ref aiot_devinfo_option_t
278  *
279  * @return int32_t
280  * @retval <STATE_SUCCESS  参数配置失败
281  * @retval >=STATE_SUCCESS 参数配置成功
282  *
283  */
284 int32_t aiot_devinfo_setopt(void *handle, aiot_devinfo_option_t option, void *data);
285 
286 /**
287  * @brief 结束devinfo会话, 销毁实例并回收资源
288  *
289  * @param[in] handle 指向devinfo会话句柄的指针
290  *
291  * @return int32_t
292  * @retval <STATE_SUCCESS  执行失败
293  * @retval >=STATE_SUCCESS 执行成功
294  *
295  */
296 int32_t aiot_devinfo_deinit(void **handle);
297 
298 /**
299  * @brief 向devinfo服务器发送devinfo消息请求
300  *
301  * @param handle devinfo会话句柄
302  * @param msg devinfo发送给云端的删除/更新设备标签信息的报文
303  *
304  * @return int32_t
305  * @retval <STATE_SUCCESS  请求发送失败
306  * @retval >=STATE_SUCCESS 请求发送成功
307  */
308 int32_t aiot_devinfo_send(void *handle, aiot_devinfo_msg_t *msg);
309 
310 #if defined(__cplusplus)
311 }
312 #endif
313 
314 #endif  /* __AIOT_DEVINFO_API_H__ */
315 
316