1 /**
2  * @file aiot_task_api.h
3  * @brief task模块头文件, 提供任务管理的能力
4  * @date 2020-11-25
5  *
6  * @copyright Copyright (C) 2015-2020 Alibaba Group Holding Limited
7  *
8  * @details
9  *
10  *
11  */
12 
13 #ifndef __AIOT_TASK_API_H__
14 #define __AIOT_TASK_API_H__
15 
16 #if defined(__cplusplus)
17 extern "C" {
18 #endif
19 
20 #include <stdint.h>
21 
22 /**
23  * @brief -0x0B00~-0x0BFF表达SDK在task模块内的状态码
24  *
25  */
26 #define STATE_TASK_BASE                                             (-0x0B00)
27 
28 /**
29  * @brief 销毁task会话实例时, 发现会话句柄为空, 中止销毁动作
30  *
31  */
32 #define STATE_TASK_DEINIT_HANDLE_IS_NULL                            (-0x0B01)
33 
34 /**
35  * @brief 配置task会话实例时, 发现会话句柄为空, 中止配置动作
36  *
37  */
38 #define STATE_TASK_SETOPT_HANDLE_IS_NULL                            (-0x0B02)
39 
40 /**
41  * @brief 接收到服务器notify下行消息时的日志状态码
42  */
43 #define STATE_TASK_RECV_NOTIFY                                      (-0x0B03)
44 
45 /**
46  * @brief 解析服务器下推的MQTT下行JSON报文时出错
47  */
48 #define STATE_TASK_PARSE_NOTIFY_FAILED                              (-0x0B04)
49 
50 /**
51  * @brief 为解析JSON报文而申请内存时, 未获取到所需内存而解析失败
52  */
53 #define STATE_TASK_PARSE_JSON_MALLOC_FAILED                         (-0x0B05)
54 
55 /**
56  * @brief 接收到服务器notify下行消息时的日志状态码
57  */
58 #define STATE_TASK_PARSE_JSON_ERROR                                 (-0x0B06)
59 
60 /**
61  * @brief 接收到查询task id是空
62  */
63 #define STATE_TASK_QUERY_TASK_ID_IS_NULL                            (-0x0B07)
64 
65 /**
66  * @brief 接收到服务器get list reply下行消息时的日志状态码
67  */
68 #define STATE_TASK_RECV_GET_LIST_REPLY                              (-0x0B08)
69 
70 /**
71  * @brief 配置task会话实例时, 发现会话句柄为空, 中止配置动作
72  *
73  */
74 #define STATE_TASK_SETOPT_DATA_IS_NULL                              (-0x0B09)
75 
76 /**
77  * @brief 配置task 描述时状态设置不对
78  *
79  */
80 #define STATE_TASK_UPDATE_STATUS_INVALID                            (-0x0B0A)
81 
82 /**
83  * @brief aiot_task_setopt 接口的option参数可选值.
84  */
85 
86 /**
87  * @brief update task的时候task status_details只能为NULL或者json字符串对象
88  *
89  */
90 #define STATE_TASK_UPDATE_STATUS_DETAILS_INVALID                     (-0x0B0B)
91 
92 typedef enum {
93     /**
94      * @brief 设置MQTT的handle
95      *
96      * @details
97      *
98      * OTA过程中使用MQTT的通道能力, 用以向云端上报版本号, 进度, 以及错误码
99      *
100      * 数据类型: (void *)
101      */
102     AIOT_TASKOPT_MQTT_HANDLE,
103 
104     /**
105      * @brief 设置处理task消息的用户回调函数
106      *
107      * @details
108      *
109      * 从云端下发或者返回的数据的处理函数
110      *
111      * 数据类型: (void *)
112      */
113     AIOT_TASKOPT_RECV_HANDLER,
114 
115     /**
116      * @brief 用户需要SDK暂存的上下文
117      *
118      * @details
119      *
120      * 这个上下文指针会在 AIOT_TASKOPT_RECV_HANDLER设置的回调被调用时, 由SDK传给用户
121      *
122      * 数据类型: (void *)
123      */
124     AIOT_TASKOPT_USERDATA,
125     AIOT_TASKOPT_MAX
126 } aiot_task_option_t;
127 
128 /**
129  * @brief 任务的状态.
130  */
131 typedef enum {
132     AIOT_TASK_STATUS_QUEUED,             /* 服务端设置的状态: 任务处于队列中, 还没有推送 */
133     AIOT_TASK_STATUS_SENT,               /* 服务端设置的状态: 任务已推送 */
134     AIOT_TASK_STATUS_IN_PROGRESS,        /* 设备端设置的状态: 任务进行中. 设备端开始执行一个任务后, 将 */
135     AIOT_TASK_STATUS_SUCCEEDED,          /* 设备端设置的状态: 任务完成 */
136     AIOT_TASK_STATUS_FAILED,             /* 设备端设置的状态: 任务执行失败 */
137     AIOT_TASK_STATUS_REJECTED,           /* 设备端设置的状态: 设备端拒绝执行任务 */
138     AIOT_TASK_STATUS_CANCELLED,          /* 服务端设置的状态: 任务被服务端取消 */
139     AIOT_TASK_STATUS_REMOVED,            /* 服务端设置的状态: 任务从服务端删除 */
140     AIOT_TASK_STATUS_TIMED_OUT,          /* 服务端设置的状态: 任务执行超时 */
141     AIOT_TASK_STATUS_NOT_FOUND           /* 服务端设置的状态: 没有找到此任务相关信息 */
142 } aiot_task_status_t;
143 
144 /**
145  * @brief 下行有关的数据结构
146  */
147 typedef enum {
148     AIOT_TASKRECV_NOTIFY,               /* 对应/sys/{productKey}/{deviceName}/thing/job/notify 这个下行topic, 云端主动下推, 带任务详情 */
149     AIOT_TASKRECV_GET_DETAIL_REPLY,     /* 对应/sys/{productKey}/{deviceName}/thing/job/get_reply 这个下行topic, 可以是单个任务的详情, 也可以是任务列表的简单描述 */
150     AIOT_TASKRECV_GET_LIST_REPLY,       /* 对应/sys/{productKey}/{deviceName}/thing/job/get_reply 这个下行topic, 可以是单个任务的详情, 也可以是任务列表的简单描述 */
151     AIOT_TASKRECV_UPDATE_REPLY          /* 对应/sys/{productKey}/{deviceName}/thing/job/update_reply 这个下行topic, 里面包含某个任务的update的结果, 即是否成功 */
152 } aiot_task_recv_type_t;
153 
154 /**
155  * @brief 任务描述的数据结构
156  */
157 typedef struct {
158     char *task_id;                      /* 任务ID */
159     aiot_task_status_t status;          /* 任务的状态 */
160     char *job_document;                 /* 任务执行规则 */
161     char *sign_method;                  /* 文件签名的方法 */
162     char *sign;                         /* 文件的签名 */
163     char *document_file_url;            /* 任务文件下载的url */
164     char *status_details;               /* 客户自定义状态,透传到云端, 注意格式为json对象,例如 "{\"key\": \"value\"", strlen("\"key\": \"value\"}"*/
165     uint8_t progress;                   /* 任务处理的进度,数字从0-100 */
166     void *handle;                       /* 任务处理的句柄 */
167 } task_desc_t;
168 
169 /**
170  * @brief 从云端拉取list时每个任务的简要描述
171  */
172 typedef struct {
173     char *task_id;                      /* 任务ID */
174     aiot_task_status_t status;          /* 任务的状态 */
175 } task_summary_t;
176 
177 /**
178  * @brief 从云端拉取list返回的数据
179  */
180 typedef struct {
181     uint32_t number;                    /* 从云端拉取的任务list的大小 */
182     task_summary_t *tasks;              /* 拉取的任务数组指针 */
183 } task_get_list_reply_t;
184 
185 /**
186  * @brief 从云端拉取任务详细信息时返回的数据
187  */
188 typedef struct {
189     uint32_t code;                      /* 云端返回的code */
190     task_desc_t task;                   /* 任务描述的详细信息 */
191 } task_get_detail_reply_t;
192 
193 /**
194  * @brief 更新任务状态到云端后,云端返回的数据
195  */
196 typedef struct {
197     uint32_t code;                      /* 云端返回的code */
198     char *task_id;                      /* 更新任务后返回的任务id */
199     aiot_task_status_t status;          /* 更新任务后返回的状态 */
200 } task_update_reply_t;
201 
202 /**
203  * @brief 云端主动下发或更新任务云端返回的数据
204  */
205 typedef struct {
206     aiot_task_recv_type_t type;                     /* 返回的数据类型 */
207     union {
208         task_desc_t notify;                         /* 云端主动推送任务的数据 */
209         task_get_list_reply_t get_list_reply;       /* 请求任务list返回的数据 */
210         task_get_detail_reply_t get_detail_reply;   /* 请求任务详细状态返回的数据 */
211         task_update_reply_t update_reply;           /* 更新任务状态返回的数据 */
212     } data;
213 } aiot_task_recv_t;
214 
215 /**
216  * @brief 设备收到task的mqtt下行报文时的接收回调函数
217  *
218  * @param[in] handle task实例句柄
219  * @param[in] recv 云端下行的消息
220  * @param[in] userdata 用户上下文
221  *
222  * @return void
223  */
224 typedef void (* aiot_task_recv_handler_t)(void *handle, const aiot_task_recv_t *recv, void *userdata);
225 
226 /**
227  * @brief 创建一个task实例
228  *
229  * @return void*
230  * @retval 非NULL task实例句柄
231  * @retval NULL 初始化失败, 或者是因为没有设置portfile, 或者是内存分配失败导致
232  *
233  */
234 void   *aiot_task_init(void);
235 
236 /**
237  * @brief 销毁task实例句柄
238  *
239  * @param[in] handle 指向task实例句柄的指针
240  *
241  * @return int32_t
242  * @retval STATE_USER_INPUT_NULL_POINTER handle或者handle所指向的地址为空
243  * @retval STATE_SUCCESS 执行成功
244  *
245  */
246 int32_t aiot_task_deinit(void **handle);
247 
248 /**
249  * @brief 设置task句柄的参数
250  *
251  * @details
252  *
253  * 对task会话进行配置, 常见的配置选项包括
254  *
255  * @param[in] handle task句柄
256  * @param[in] option 配置选项, 更多信息请参考@ref aiot_task_option_t
257  * @param[in] data   配置选项数据, 更多信息请参考@ref aiot_task_option_t
258  *
259  * @return int32_t
260  * @retval STATE_TASK_SETOPT_HANDLE_IS_NULL task句柄为空
261  * @retval STATE_TASK_SETOPT_DATA_IS_NULL 参数data字段为空
262  * @retval STATE_USER_INPUT_UNKNOWN_OPTION option不支持
263  * @retval STATE_SUCCESS 参数设置成功
264  *
265  */
266 int32_t aiot_task_setopt(void *handle, aiot_task_option_t option, void *data);
267 
268 /**
269  * @brief 从云端获取task列表
270  *
271  * @details
272  *
273  * 从云端获取task列表
274  *
275  * @param[in] handle task句柄
276  *
277  * @return int32_t
278  * @retval STATE_TASK_SETOPT_DATA_IS_NULL 参数的handle字段为空
279  * @retval STATE_SUCCESS                  发送成功
280  */
281 int32_t aiot_task_get_task_list(void *handle);
282 
283 /* 发送报文到/sys/{productKey}/{deviceName}/thing/job/get. 若函数入参user_task_id不为空, 则上行报文的payload为 "taskId": user_task_id, 返回该任务的详情; */
284 /* 若user_task_id为空, 则上行报文的payload为 "taskId": "$next", 云端返回未处于终态的任务队列中时间排在最前面一个任务, 该任务状态为QUEUED、SENT、IN_PROGRESS三者之一 */
285 
286 /**
287  * @brief 从云端获取task详细内容
288  *
289  * @details
290  *
291  * 从云端获取task详细内容
292  *
293  * @param[in] handle task句柄
294  * @param[in] user_task_id task的id或者$next
295  *
296  * @return int32_t
297  * @retval STATE_TASK_SETOPT_DATA_IS_NULL或user_task_id 参数的handle字段为空
298  * @retval STATE_SUCCESS 发送成功
299  *
300  */
301 int32_t aiot_task_get_task_detail(void *handle, char *user_task_id);
302 
303 /**
304  * @brief 更新任务状态到云端
305  *
306  * @details
307  *
308  * 更新任务状态到云端
309  *
310  * @param[in] handle task句柄
311  * @param[in] task task信息
312  *
313  * @return int32_t
314  * @retval STATE_TASK_SETOPT_DATA_IS_NULL或task 参数的handle字段为空
315  * @retval STATE_SUCCESS 更新成功
316  *
317  */
318 int32_t aiot_task_update(void *handle, task_desc_t *task);
319 #if defined(__cplusplus)
320 }
321 #endif
322 
323 #endif  /* #ifndef __AIOT_TASK_API_H__ */
324 
325 
326