/** * @file aiot_shadow_api.h * @brief shadow模块头文件, 提供更新, 删除, 获取设备影子的能力 * * @copyright Copyright (C) 2015-2020 Alibaba Group Holding Limited * * @details * * 请按照以下流程使用API * * 1. 在使用设备影子模块前, 用户应首先创建好一个MQTT实例 * * 2. 调用`aiot_shadow_init`创建一个设备影子实例, 保存实例句柄 * * 3. 调用`aiot_shadow_setopt`配置`AIOT_SHADOWOPT_MQTT_HANDLE`选项以设置MQTT句柄, 此选项为强制配置选项 * * 4. 调用`aiot_shadow_setopt`配置`AIOT_SHADOWOPT_RECV_HANDLER`和`AIOT_SHADOWOPT_USERDATA`选项以注册数据接受回调函数和用户上下文数据指针 * * 5. 在使用`aiot_shadow_send`发送消息前, 应先完成MQTT实例的建连 * * 6. 调动`aiot_shadow_send`发送更新设备影子, 获取设备影子或删除设备等消息到云平台, 在注册的回调函数中处理各种类型的云端应答消息或主动下推消息 * */ #ifndef __AIOT_SHADOW_API_H__ #define __AIOT_SHADOW_API_H__ #if defined(__cplusplus) extern "C" { #endif #include /** * @brief -0x1300~-0x13FF表达SDK在data-model模块内的状态码 */ #define STATE_SHADOW_BASE (-0x1300) /** * @brief 用户未调用@ref aiot_shadow_setopt 配置MQTT句柄 */ #define STATE_SHADOW_MQTT_HANDLE_IS_NULL (-0x1301) /** * @brief 用户上报@ref AIOT_SHADOWMSG_UPDATE 或 @ref AIOT_SHADOWMSG_DELETE_REPORTED 消息时, 消息结构体中的reported为NULL * */ #define STATE_SHADOW_REPORTED_DATA_IS_NULL (-0x1302) /** * @brief 解析下行数据对应的topic时发生错误 */ #define STATE_SHADOW_INTERNAL_TOPIC_ERROR (-0x1303) /** * @brief 接收到服务器下行消息时的日志状态码 */ #define STATE_SHADOW_LOG_RECV (-0x1304) /** * @brief 解析服务器下行消息失败时的日志状态码 */ #define SATAE_SHADOW_LOG_PARSE_RECV_MSG_FAILED (-0x1305) /** * @brief @ref aiot_shadow_setopt 接口的option参数可选值. * * @details 下文每个选项中的数据类型, 指的是@ref aiot_shadow_setopt 中, data参数的数据类型 * * 当data的数据类型是char *时, 以配置@ref AIOT_SHADOWOPT_PRODUCT_KEY 为例: * * char *product_key = "xxx"; * aiot_shadow_setopt(shadow_handle, AIOT_SHADOWOPT_PRODUCT_KEY, product_key); * */ typedef enum { /** * @brief 模块依赖的MQTT句柄 * * @details * * shadow模块依赖底层的MQTT模块, 用户必需配置正确的MQTT句柄, 否则无法正常工作, 数据类型为(void *) */ AIOT_SHADOWOPT_MQTT_HANDLE, /** * @brief 设置回调, 它在SDK收到网络报文的时候被调用, 告知用户, 数据类型为(aiot_shadow_recv_handler_t) */ AIOT_SHADOWOPT_RECV_HANDLER, /** * @brief 用户需要SDK暂存的上下文, 数据类型为(void *) * * @details 这个上下文指针会在 AIOT_SHADOWOPT_RECV_HANDLER 设置的回调被调用时, 由SDK传给用户 */ AIOT_SHADOWOPT_USERDATA, /** * @brief 配置选项数量最大值, 不可用作配置参数 */ AIOT_SHADOWOPT_MAX, } aiot_shadow_option_t; /** * @brief shadow模块发送消息类型 * * @details * * 这个枚举类型包括了shadow模块支持发送的所有数据类型, 不同的消息类型将对于不同的消息结构体 * */ typedef enum { /** * @brief 更新设备影子中的reported值, 消息结构体参考@ref aiot_shadow_msg_update_t * */ AIOT_SHADOWMSG_UPDATE, /** * @brief 清空设备影子的desired值, 消息结构体参考@ref aiot_shadow_msg_clean_desired_t * */ AIOT_SHADOWMSG_CLEAN_DESIRED, /** * @brief 获取设备影子, 消息结构体参考@ref aiot_shadow_msg_get_t * */ AIOT_SHADOWMSG_GET, /** * @brief 删除设备影子的部分或全部reported值, 消息结构体参考@ref aiot_shadow_msg_delete_reported_t * */ AIOT_SHADOWMSG_DELETE_REPORTED, /** * @brief 消息数量最大值, 不可用作消息类型 */ AIOT_SHADOWMSG_MAX, } aiot_shadow_msg_type_t; /** * @brief 用于更新设备影子中的reported数据的消息结构体 */ typedef struct { /** * @brief 设备影子reported object字符串, 必须为以结束符'\0'结尾的字符串, 如"{\"LightSwitch\": 1}" */ char *reported; /** * @brief 设备影子的目标版本, 必须大于设备影子的当前版本, 若设置为-1将清空设备影子数据, 并将设备影子版本更新为0 */ int64_t version; } aiot_shadow_msg_update_t; /** * @brief 用于清除设备影子中的desired数据的消息结构体 */ typedef struct { /** * @brief 设备影子的目标版本, 必须大于设备影子的当前版本 */ int64_t version; } aiot_shadow_msg_clean_desired_t; /** * @brief 用于获取设备影子的消息结构体, */ typedef struct { /** * @brief 保留字段 */ uint32_t resevered; } aiot_shadow_msg_get_t; /** * @brief 用于删除设备影子中的reported数据的消息结构体 */ typedef struct { /** * @brief 用户将要删除的reported数据, 必须为以结束符'\0'结尾的字符串. \n * 若要删除全部reported数据, 则应填写"\"null\""字符串 \n * 若要删除部分reported数据, 则将对应的值定义为null, 如只清除LightSwitch的值应填写"{\"LightSwitch\":\"null\"}" */ char *reported; /** * @brief 设备影子的目标版本, 必须大于设备影子的当前版本 */ int64_t version; } aiot_shadow_msg_delete_reported_t; /** * @brief data-model模块发送消息的消息结构体 */ typedef struct { /** * @brief 消息所属设备的product_key, 若为NULL则使用通过aiot_shadow_setopt配置的product_key \n * 在网关子设备场景下, 可通过指定为子设备的product_key来发送子设备的消息到云端 */ char *product_key; /** * @brief 消息所属设备的device_name, 若为NULL则使用通过aiot_shadow_setopt配置的device_name \n * 在网关子设备场景下, 可通过指定为子设备的product_key来发送子设备的消息到云端 */ char *device_name; /** * @brief 消息类型, 可参考@ref aiot_shadow_msg_type_t */ aiot_shadow_msg_type_t type; /** * @brief 消息数据联合体, 不同的消息类型将使用不同的消息结构体 */ union { aiot_shadow_msg_update_t update; aiot_shadow_msg_clean_desired_t clean_desired; aiot_shadow_msg_get_t get; aiot_shadow_msg_delete_reported_t delete_reporte; } data; } aiot_shadow_msg_t; /** * @brief shadow模块收到从网络上来的报文时, 通知用户的报文类型 */ typedef enum { /** * @brief 设备发送 @ref AIOT_SHADOWMSG_UPDATE, @ref AIOT_SHADOWMSG_CLEAN_DESIRED 或 @ref AIOT_SHADOWMSG_DELETE_REPORTED 这3这类型消息后, 云端返回的应答消息, \n * 消息数据结构体参考 @ref aiot_shadow_recv_generic_reply_t */ AIOT_SHADOWRECV_GENERIC_REPLY, /** * @brief 设备在线时, 云端自动下发的影子内容, 消息数据结构体参考 @ref aiot_shadow_recv_control_t */ AIOT_SHADOWRECV_CONTROL, /** * @brief 主动获取设备影子内容云端返回的影子内容, 消息数据结构体参考 @ref aiot_shadow_recv_get_reply_t */ AIOT_SHADOWRECV_GET_REPLY, } aiot_shadow_recv_type_t; /** * @brief 设备发送 @ref AIOT_SHADOWMSG_UPDATE, @ref AIOT_SHADOWMSG_CLEAN_DESIRED 或 @ref AIOT_SHADOWMSG_DELETE_REPORTED 类型消息后, 云端返回的应答消息 */ typedef struct { /** * @brief 指向应答数据的指针 */ char *payload; /** * @brief 应答数据长度 */ uint32_t payload_len; /** * @brief 应答状态字符串, 云端处理成功则为success, 发送消息错误则为error, 错误信息和错误码放在在payload中 */ char *status; /** * @brief 应答报文对应的时间戳 */ uint64_t timestamp; } aiot_shadow_recv_generic_reply_t; /** * @brief 如果设备在线, 用户应用调用云端APIUpdateDeviceShadow后云端下推的消息 */ typedef struct { /** * @brief 指向设备影子数据的指针 */ char *payload; /** * @brief 设备影子数据长度 */ uint32_t payload_len; /** * @brief 设备影子版本 */ uint64_t version; } aiot_shadow_recv_control_t; /** * @brief 设备发送 @ref AIOT_SHADOWMSG_GET 类型消息后, 云端返回的设备影子数据 */ typedef struct { /** * @brief 指向设备影子数据的指针 */ char *payload; /** * @brief 设备影子数据长度 */ uint32_t payload_len; /** * @brief 设备影子版本号 */ uint64_t version; } aiot_shadow_recv_get_reply_t; /** * @brief shadow模块收到从网络上来的报文时, 通知用户的报文内容 */ typedef struct { /** * @brief 消息所属设备的product_key */ char *product_key; /** * @brief 消息所属设备的device_name */ char *device_name; /** * @brief 报文内容所对应的报文类型, 更多信息请参考@ref aiot_shadow_recv_type_t */ aiot_shadow_recv_type_t type; /** * @brief 消息数据联合体, 不同的消息类型将使用不同的消息结构体 */ union { aiot_shadow_recv_generic_reply_t generic_reply; aiot_shadow_recv_control_t control; aiot_shadow_recv_get_reply_t get_reply; } data; } aiot_shadow_recv_t; /** * @brief shadow模块收到从网络上来的报文时, 通知用户所调用的数据回调函数 * * @param[in] handle shadow会话句柄 * @param[in] recv shadow接受消息结构体, 存放收到的shadow报文内容 * @param[in] userdata 指向用户上下文数据的指针, 这个指针由用户通过调用@ref aiot_shadow_setopt 配置@ref AIOT_SHADOWOPT_USERDATA 选项设置 * * @return void */ typedef void (* aiot_shadow_recv_handler_t)(void *handle, const aiot_shadow_recv_t *recv, void *userdata); /** * @brief 创建shadow会话实例, 并以默认值配置会话参数 * * @return void * * @retval 非NULL shadow实例的句柄 * @retval NULL 初始化失败, 一般是内存分配失败导致 * */ void *aiot_shadow_init(void); /** * @brief 配置shadow会话 * * @param[in] handle shadow会话句柄 * @param[in] option 配置选项, 更多信息请参考@ref aiot_shadow_option_t * @param[in] data 配置选项数据, 更多信息请参考@ref aiot_shadow_option_t * * @return int32_t * @retval STATE_SUCCESS 参数配置成功 * @retval STATE_USER_INPUT_NULL_POINTER 入参handle或data为NULL * @retval STATE_USER_INPUT_OUT_RANGE 入参optioin的枚举值>=AIOT_SHADOWOPT_MAX * @retval others 参考@ref aiot_state_api.h * */ int32_t aiot_shadow_setopt(void *handle, aiot_shadow_option_t option, void *data); /** * @brief 向服务器发送shadow消息请求 * * @param[in] handle shadow会话句柄 * @param[in] msg 消息结构体, 可指定发送消息的设备productKey, deviceName; 消息类型, 消息数据等, 更多信息请参考@ref aiot_shadow_msg_t * * @return int32_t * @retval STATE_SUCCESS 请求发送成功 * @retval STATE_USER_INPUT_NULL_POINTER 入参handlemsg为NULL * @retval STATE_USER_INPUT_OUT_RANGE 入参msg的结构体成员type >= AIOT_SHADOWMSG_MAX * @retval STATE_SYS_DEPEND_MALLOC_FAILED 内存分配失败 * @retval STATE_SHADOW_MQTT_HANDLE_IS_NULL 用户未调用@ref aiot_shadow_setopt 配置MQTT句柄 * @retval others 参考@ref aiot_state_api.h 或@ref STATE_SHADOW_BASE 中对应的错误码说明 * */ int32_t aiot_shadow_send(void *handle, aiot_shadow_msg_t *msg); /** * @brief 结束shadow会话, 销毁实例并回收资源 * * @param[in] handle 指向shadow会话句柄的指针 * * @return int32_t * @retval STATE_SUCCESS 执行成功 * @retval