mirror of
https://gitee.com/beecue/fastbee.git
synced 2025-12-21 18:35:54 +08:00
更新硬件SDK
This commit is contained in:
3
sdk/合宙/air780e/csdk/luatos-soc-2022/thirdparty/linksdk/components/shadow/README.md
vendored
Normal file
3
sdk/合宙/air780e/csdk/luatos-soc-2022/thirdparty/linksdk/components/shadow/README.md
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
Name: 设备影子模块
|
||||
SHADOW Component for Link SDK V4.0.0
|
||||
|
||||
438
sdk/合宙/air780e/csdk/luatos-soc-2022/thirdparty/linksdk/components/shadow/aiot_shadow_api.c
vendored
Normal file
438
sdk/合宙/air780e/csdk/luatos-soc-2022/thirdparty/linksdk/components/shadow/aiot_shadow_api.c
vendored
Normal file
@@ -0,0 +1,438 @@
|
||||
/**
|
||||
* @file aiot_shadow_api.c
|
||||
* @brief shadow模块的API接口实现, 提供更新, 删除, 获取设备影子的能力
|
||||
*
|
||||
* @copyright Copyright (C) 2015-2020 Alibaba Group Holding Limited
|
||||
*
|
||||
*/
|
||||
|
||||
#include "shadow_private.h"
|
||||
|
||||
#include "core_string.h"
|
||||
#include "core_log.h"
|
||||
#include "core_global.h"
|
||||
#include "core_mqtt.h"
|
||||
|
||||
|
||||
static int32_t _shadow_get_pk_dn(aiot_sysdep_portfile_t *sysdep, char *topic, uint16_t topic_len,
|
||||
char **product_key, char **device_name)
|
||||
{
|
||||
uint16_t pk_offset = 12; /* length of "/shadow/get/" */
|
||||
uint16_t idx = 0;
|
||||
uint16_t pk_len = 0, dn_len = 0;
|
||||
char *pk_pos = topic + pk_offset;
|
||||
char *dn_pos = NULL;
|
||||
char *tmp_pk = NULL, *tmp_dn = NULL;
|
||||
|
||||
for (idx = pk_offset; idx < topic_len - 1; idx++) {
|
||||
if (topic[idx] == '/') {
|
||||
dn_pos = topic + idx + 1;
|
||||
pk_len = dn_pos - pk_pos - 1;
|
||||
dn_len = topic_len - idx - 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (pk_len == 0 || dn_len == 0) {
|
||||
return STATE_SHADOW_INTERNAL_TOPIC_ERROR;
|
||||
}
|
||||
|
||||
tmp_pk = sysdep->core_sysdep_malloc(pk_len + 1, SHADOW_MODULE_NAME);
|
||||
if (tmp_pk == NULL) {
|
||||
return STATE_SYS_DEPEND_MALLOC_FAILED;
|
||||
}
|
||||
memset(tmp_pk, 0, pk_len + 1);
|
||||
memcpy(tmp_pk, pk_pos, pk_len);
|
||||
|
||||
tmp_dn = sysdep->core_sysdep_malloc(dn_len + 1, SHADOW_MODULE_NAME);
|
||||
if (tmp_dn == NULL) {
|
||||
sysdep->core_sysdep_free(tmp_pk);
|
||||
return STATE_SYS_DEPEND_MALLOC_FAILED;
|
||||
}
|
||||
memset(tmp_dn, 0, dn_len + 1);
|
||||
memcpy(tmp_dn, dn_pos, dn_len);
|
||||
|
||||
*product_key = tmp_pk;
|
||||
*device_name = tmp_dn;
|
||||
return STATE_SUCCESS;
|
||||
}
|
||||
|
||||
int32_t _shadow_int642str(int64_t input, char *output, uint8_t *output_len)
|
||||
{
|
||||
uint64_t temp = 0;
|
||||
uint8_t len = 0;
|
||||
|
||||
if (input < 0) {
|
||||
*output = '-';
|
||||
temp = -input;
|
||||
core_uint642str(temp, output + 1, &len);
|
||||
if (output_len != NULL) {
|
||||
*output_len = len + 1;
|
||||
}
|
||||
} else {
|
||||
temp = input;
|
||||
core_uint642str(temp, output, output_len);
|
||||
}
|
||||
|
||||
return STATE_SUCCESS;
|
||||
}
|
||||
|
||||
static void _shadow_recv_message_handler(void *handle, const aiot_mqtt_recv_t *msg, void *userdata)
|
||||
{
|
||||
shadow_handle_t *shadow_handle = (shadow_handle_t *)userdata;
|
||||
aiot_shadow_recv_t recv;
|
||||
char *value = NULL;
|
||||
uint32_t value_len = 0;
|
||||
char *pk = NULL;
|
||||
char *dn = NULL;
|
||||
int32_t res = STATE_SUCCESS;
|
||||
|
||||
char *method = NULL;
|
||||
uint32_t method_len = 0;
|
||||
char *payload = NULL;
|
||||
uint32_t payload_len = 0;
|
||||
uint64_t timestamp = 0;
|
||||
uint64_t version = 0;
|
||||
char status[10] = { 0 };
|
||||
char *version_str = NULL;
|
||||
uint32_t version_strlen = 0;
|
||||
|
||||
if (NULL == shadow_handle->recv_handler) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&recv, 0, sizeof(aiot_shadow_recv_t));
|
||||
|
||||
do {
|
||||
/* get pk & dn */
|
||||
if ((res = _shadow_get_pk_dn(shadow_handle->sysdep, msg->data.pub.topic, msg->data.pub.topic_len, &pk, &dn)) < 0) {
|
||||
break;
|
||||
}
|
||||
recv.product_key = pk;
|
||||
recv.device_name = dn;
|
||||
|
||||
/* parse the message */
|
||||
if ((res = core_json_value((char *)msg->data.pub.payload, msg->data.pub.payload_len,
|
||||
SHADOW_JSON_KEY_METHOD, strlen(SHADOW_JSON_KEY_METHOD), &method, &method_len) < 0) ||
|
||||
(res = core_json_value((char *)msg->data.pub.payload, msg->data.pub.payload_len,
|
||||
SHADOW_JSON_KEY_TIMESTAMP, strlen(SHADOW_JSON_KEY_TIMESTAMP), &value, &value_len) < 0) ||
|
||||
(res = core_str2uint64(value, value_len, ×tamp) < 0) ||
|
||||
(res = core_json_value((char *)msg->data.pub.payload, msg->data.pub.payload_len,
|
||||
SHADOW_JSON_KEY_PAYLOAD, strlen(SHADOW_JSON_KEY_PAYLOAD), &payload, &payload_len) < 0)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (core_json_value((char *)msg->data.pub.payload, msg->data.pub.payload_len,
|
||||
SHADOW_JSON_KEY_VERSION, strlen(SHADOW_JSON_KEY_VERSION), &version_str, &version_strlen) == STATE_SUCCESS) {
|
||||
core_str2uint64(version_str, version_strlen, &version);
|
||||
}
|
||||
|
||||
/* control message */
|
||||
if (method_len == strlen("control") && !memcmp(method, "control", method_len)) {
|
||||
/* get version */
|
||||
if (version_str == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
core_log(shadow_handle->sysdep, STATE_SHADOW_LOG_RECV, "SHADOW recv control message\r\n");
|
||||
recv.type = AIOT_SHADOWRECV_CONTROL;
|
||||
recv.data.control.payload = payload;
|
||||
recv.data.control.payload_len = payload_len;
|
||||
recv.data.control.version = version;
|
||||
} /* reply message */
|
||||
else if (method_len == strlen("reply") && !memcmp(method, "reply", method_len)) {
|
||||
/* get_reply */
|
||||
if (core_json_value((char *)msg->data.pub.payload, msg->data.pub.payload_len,
|
||||
SHADOW_JSON_KEY_STATE, strlen(SHADOW_JSON_KEY_STATE), &value, &value_len) < 0) {
|
||||
|
||||
if ((res = core_json_value((char *)msg->data.pub.payload, msg->data.pub.payload_len,
|
||||
SHADOW_JSON_KEY_STATUS, strlen(SHADOW_JSON_KEY_STATUS), &value, &value_len) < 0) ||
|
||||
(value_len >= sizeof(status))) {
|
||||
break;
|
||||
}
|
||||
|
||||
core_log(shadow_handle->sysdep, STATE_SHADOW_LOG_RECV, "SHADOW recv get_reply message\r\n");
|
||||
memcpy(status, value, value_len);
|
||||
recv.type = AIOT_SHADOWRECV_GENERIC_REPLY;
|
||||
recv.data.generic_reply.payload = payload;
|
||||
recv.data.generic_reply.payload_len = payload_len;
|
||||
recv.data.generic_reply.status = status;
|
||||
recv.data.generic_reply.timestamp = timestamp;
|
||||
} /* get_reply */
|
||||
else {
|
||||
if (version_str == NULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
core_log(shadow_handle->sysdep, STATE_SHADOW_LOG_RECV, "SHADOW recv generic_reply message\r\n");
|
||||
recv.type = AIOT_SHADOWRECV_GET_REPLY;
|
||||
recv.data.get_reply.payload = payload;
|
||||
recv.data.get_reply.payload_len = payload_len;
|
||||
recv.data.get_reply.version = version;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
|
||||
shadow_handle->recv_handler(shadow_handle, &recv, shadow_handle->userdata);
|
||||
shadow_handle->sysdep->core_sysdep_free(pk);
|
||||
shadow_handle->sysdep->core_sysdep_free(dn);
|
||||
return;
|
||||
} while (0);
|
||||
|
||||
/* invalid message log */
|
||||
core_log(shadow_handle->sysdep, SATAE_SHADOW_LOG_PARSE_RECV_MSG_FAILED, "SHADOW parse recv message failed\r\n");
|
||||
|
||||
if (pk != NULL) {
|
||||
shadow_handle->sysdep->core_sysdep_free(pk);
|
||||
}
|
||||
if (dn != NULL) {
|
||||
shadow_handle->sysdep->core_sysdep_free(dn);
|
||||
}
|
||||
}
|
||||
|
||||
static void _shadow_core_mqtt_process_handler(void *context, aiot_mqtt_event_t *event, core_mqtt_event_t *core_event)
|
||||
{
|
||||
shadow_handle_t *shadow_handle = (shadow_handle_t *)context;
|
||||
|
||||
if (core_event != NULL) {
|
||||
switch (core_event->type) {
|
||||
case CORE_MQTTEVT_DEINIT: {
|
||||
shadow_handle->mqtt_handle = NULL;
|
||||
return;
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int32_t _shadow_core_mqtt_operate_process_handler(shadow_handle_t *shadow_handle, core_mqtt_option_t option)
|
||||
{
|
||||
core_mqtt_process_data_t process_data;
|
||||
|
||||
memset(&process_data, 0, sizeof(core_mqtt_process_data_t));
|
||||
process_data.handler = _shadow_core_mqtt_process_handler;
|
||||
process_data.context = shadow_handle;
|
||||
|
||||
return core_mqtt_setopt(shadow_handle->mqtt_handle, option, &process_data);
|
||||
}
|
||||
|
||||
void *aiot_shadow_init(void)
|
||||
{
|
||||
aiot_sysdep_portfile_t *sysdep = aiot_sysdep_get_portfile();
|
||||
shadow_handle_t *shadow_handle = NULL;
|
||||
|
||||
if (NULL == sysdep) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
shadow_handle = sysdep->core_sysdep_malloc(sizeof(shadow_handle_t), SHADOW_MODULE_NAME);
|
||||
if (NULL == shadow_handle) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(shadow_handle, 0, sizeof(shadow_handle_t));
|
||||
shadow_handle->sysdep = sysdep;
|
||||
|
||||
return shadow_handle;
|
||||
}
|
||||
|
||||
int32_t aiot_shadow_setopt(void *handle, aiot_shadow_option_t option, void *data)
|
||||
{
|
||||
shadow_handle_t *shadow_handle;
|
||||
int32_t res = STATE_SUCCESS;
|
||||
|
||||
if (NULL == handle || NULL == data) {
|
||||
return STATE_USER_INPUT_NULL_POINTER;
|
||||
}
|
||||
if (option >= AIOT_SHADOWOPT_MAX) {
|
||||
return STATE_USER_INPUT_OUT_RANGE;
|
||||
}
|
||||
|
||||
shadow_handle = (shadow_handle_t *)handle;
|
||||
|
||||
switch (option) {
|
||||
case AIOT_SHADOWOPT_MQTT_HANDLE: {
|
||||
aiot_mqtt_topic_map_t topic_mapping;
|
||||
shadow_handle->mqtt_handle = data;
|
||||
|
||||
/* setup mqtt topic mapping */
|
||||
topic_mapping.topic = SHADOW_GET_TOPIC;
|
||||
topic_mapping.handler = _shadow_recv_message_handler;
|
||||
topic_mapping.userdata = handle;
|
||||
|
||||
res = aiot_mqtt_setopt(data, AIOT_MQTTOPT_APPEND_TOPIC_MAP, &topic_mapping);
|
||||
if (res >= STATE_SUCCESS) {
|
||||
res = _shadow_core_mqtt_operate_process_handler(shadow_handle, CORE_MQTTOPT_APPEND_PROCESS_HANDLER);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AIOT_SHADOWOPT_RECV_HANDLER: {
|
||||
shadow_handle->recv_handler = (aiot_shadow_recv_handler_t)data;
|
||||
}
|
||||
break;
|
||||
case AIOT_SHADOWOPT_USERDATA: {
|
||||
shadow_handle->userdata = data;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int32_t aiot_shadow_send(void *handle, aiot_shadow_msg_t *msg)
|
||||
{
|
||||
shadow_handle_t *shadow_handle = NULL;
|
||||
char *topic = NULL;
|
||||
char *payload = NULL;
|
||||
int32_t res = STATE_SUCCESS;
|
||||
|
||||
if (NULL == handle || NULL == msg) {
|
||||
return STATE_USER_INPUT_NULL_POINTER;
|
||||
}
|
||||
if (msg->type >= AIOT_SHADOWMSG_MAX) {
|
||||
return STATE_USER_INPUT_OUT_RANGE;
|
||||
}
|
||||
|
||||
shadow_handle = (shadow_handle_t *)handle;
|
||||
if (NULL == shadow_handle->mqtt_handle) {
|
||||
return STATE_SHADOW_MQTT_HANDLE_IS_NULL;
|
||||
}
|
||||
|
||||
/* construct mqtt topic */
|
||||
{
|
||||
char *src[2];
|
||||
char *pk = NULL, *dn = NULL;
|
||||
|
||||
pk = core_mqtt_get_product_key(shadow_handle->mqtt_handle);
|
||||
dn = core_mqtt_get_device_name(shadow_handle->mqtt_handle);
|
||||
|
||||
if (NULL == msg->product_key && NULL == pk) {
|
||||
return STATE_USER_INPUT_MISSING_PRODUCT_KEY;
|
||||
}
|
||||
if (NULL == msg->device_name && NULL == dn) {
|
||||
return STATE_USER_INPUT_MISSING_DEVICE_NAME;
|
||||
}
|
||||
|
||||
src[0] = (msg->product_key != NULL) ? msg->product_key : pk;
|
||||
src[1] = (msg->device_name != NULL) ? msg->device_name : dn;
|
||||
res = core_sprintf(shadow_handle->sysdep, &topic, SHADOW_UPDATE_TOPIC_FMT, src, sizeof(src) / sizeof(char *),
|
||||
SHADOW_MODULE_NAME);
|
||||
if (NULL == topic) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
/* construct payload */
|
||||
switch (msg->type) {
|
||||
case AIOT_SHADOWMSG_UPDATE: {
|
||||
char version_string[21] = { 0 };
|
||||
char *src[3] = { NULL };
|
||||
|
||||
if (NULL == msg->data.update.reported) {
|
||||
res = STATE_SHADOW_REPORTED_DATA_IS_NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
_shadow_int642str(msg->data.update.version, version_string, NULL);
|
||||
src[0] = "update";
|
||||
src[1] = msg->data.update.reported;
|
||||
src[2] = version_string;
|
||||
|
||||
res = core_sprintf(shadow_handle->sysdep, &payload, SHADOW_PAYLOAD_REQ_FMT,
|
||||
src, sizeof(src) / sizeof(char *), SHADOW_MODULE_NAME);
|
||||
if (res < STATE_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AIOT_SHADOWMSG_CLEAN_DESIRED: {
|
||||
char version_string[21] = { 0 };
|
||||
char *src[1] = { NULL };
|
||||
|
||||
_shadow_int642str(msg->data.clean_desired.version, version_string, NULL);
|
||||
src[0] = version_string;
|
||||
|
||||
res = core_sprintf(shadow_handle->sysdep, &payload, SHADOW_PAYLOAD_CLEAN_FMT,
|
||||
src, sizeof(src) / sizeof(char *), SHADOW_MODULE_NAME);
|
||||
if (res < STATE_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case AIOT_SHADOWMSG_GET: {
|
||||
payload = SHADOW_PAYLOAD_GET;
|
||||
}
|
||||
break;
|
||||
case AIOT_SHADOWMSG_DELETE_REPORTED: {
|
||||
char version_string[21] = { 0 };
|
||||
char *src[3] = { NULL };
|
||||
|
||||
if (NULL == msg->data.delete_reporte.reported) {
|
||||
res = STATE_SHADOW_REPORTED_DATA_IS_NULL;
|
||||
break;
|
||||
}
|
||||
|
||||
_shadow_int642str(msg->data.delete_reporte.version, version_string, NULL);
|
||||
src[0] = "delete";
|
||||
src[1] = msg->data.update.reported;
|
||||
src[2] = version_string;
|
||||
|
||||
res = core_sprintf(shadow_handle->sysdep, &payload, SHADOW_PAYLOAD_REQ_FMT,
|
||||
src, sizeof(src) / sizeof(char *), SHADOW_MODULE_NAME);
|
||||
if (res < STATE_SUCCESS) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default: {
|
||||
res = STATE_USER_INPUT_OUT_RANGE;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (NULL == payload) {
|
||||
shadow_handle->sysdep->core_sysdep_free(topic);
|
||||
return res;
|
||||
}
|
||||
|
||||
res = aiot_mqtt_pub(shadow_handle->mqtt_handle, topic, (uint8_t *)payload, strlen(payload), 0);
|
||||
|
||||
shadow_handle->sysdep->core_sysdep_free(topic);
|
||||
if (msg->type != AIOT_SHADOWMSG_GET) {
|
||||
shadow_handle->sysdep->core_sysdep_free(payload);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
int32_t aiot_shadow_deinit(void **p_handle)
|
||||
{
|
||||
shadow_handle_t *shadow_handle = NULL;
|
||||
aiot_sysdep_portfile_t *sysdep = NULL;
|
||||
aiot_mqtt_topic_map_t topic_mapping;
|
||||
|
||||
if (NULL == p_handle || NULL == *p_handle) {
|
||||
return STATE_USER_INPUT_NULL_POINTER;
|
||||
}
|
||||
|
||||
shadow_handle = *p_handle;
|
||||
sysdep = shadow_handle->sysdep;
|
||||
*p_handle = NULL;
|
||||
|
||||
_shadow_core_mqtt_operate_process_handler(shadow_handle, CORE_MQTTOPT_REMOVE_PROCESS_HANDLER);
|
||||
|
||||
/* remove mqtt topic mapping */
|
||||
memset(&topic_mapping, 0, sizeof(aiot_mqtt_topic_map_t));
|
||||
topic_mapping.topic = SHADOW_GET_TOPIC;
|
||||
topic_mapping.handler = _shadow_recv_message_handler;
|
||||
aiot_mqtt_setopt(shadow_handle->mqtt_handle, AIOT_MQTTOPT_REMOVE_TOPIC_MAP, &topic_mapping);
|
||||
|
||||
sysdep->core_sysdep_free(shadow_handle);
|
||||
return STATE_SUCCESS;
|
||||
}
|
||||
|
||||
411
sdk/合宙/air780e/csdk/luatos-soc-2022/thirdparty/linksdk/components/shadow/aiot_shadow_api.h
vendored
Normal file
411
sdk/合宙/air780e/csdk/luatos-soc-2022/thirdparty/linksdk/components/shadow/aiot_shadow_api.h
vendored
Normal file
@@ -0,0 +1,411 @@
|
||||
/**
|
||||
* @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 <stdint.h>
|
||||
|
||||
/**
|
||||
* @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 用于<b>更新设备影子中的reported数据</b>的消息结构体
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief 设备影子reported object字符串, <b>必须为以结束符'\0'结尾的字符串</b>, 如"{\"LightSwitch\": 1}"
|
||||
*/
|
||||
char *reported;
|
||||
|
||||
/**
|
||||
* @brief 设备影子的目标版本, <b>必须大于设备影子的当前版本</b>, 若设置为-1将清空设备影子数据, 并将设备影子版本更新为0
|
||||
*/
|
||||
int64_t version;
|
||||
} aiot_shadow_msg_update_t;
|
||||
|
||||
/**
|
||||
* @brief 用于<b>清除设备影子中的desired数据</b>的消息结构体
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief 设备影子的目标版本, <b>必须大于设备影子的当前版本</b>
|
||||
*/
|
||||
int64_t version;
|
||||
} aiot_shadow_msg_clean_desired_t;
|
||||
|
||||
/**
|
||||
* @brief 用于<b>获取设备影子</b>的消息结构体,
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief 保留字段
|
||||
*/
|
||||
uint32_t resevered;
|
||||
} aiot_shadow_msg_get_t;
|
||||
|
||||
/**
|
||||
* @brief 用于<b>删除设备影子中的reported数据</b>的消息结构体
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief 用户将要删除的reported数据, <b>必须为以结束符'\0'结尾的字符串</b>. \n
|
||||
* 若要删除全部reported数据, 则应填写"\"null\""字符串 \n
|
||||
* 若要删除部分reported数据, 则将对应的值定义为null, 如只清除LightSwitch的值应填写"{\"LightSwitch\":\"null\"}"
|
||||
*/
|
||||
char *reported;
|
||||
|
||||
/**
|
||||
* @brief 设备影子的目标版本, <b>必须大于设备影子的当前版本</b>
|
||||
*/
|
||||
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 应答状态字符串, 云端处理成功则为<b>success</b>, 发送消息错误则为<b>error</b>, 错误信息和错误码放在在payload中
|
||||
*/
|
||||
char *status;
|
||||
|
||||
/**
|
||||
* @brief 应答报文对应的时间戳
|
||||
*/
|
||||
uint64_t timestamp;
|
||||
} aiot_shadow_recv_generic_reply_t;
|
||||
|
||||
/**
|
||||
* @brief 如果设备在线, 用户应用调用云端API<a href="https://help.aliyun.com/document_detail/69954.html#doc-api-Iot-UpdateDeviceShadow">UpdateDeviceShadow</a>后云端下推的消息
|
||||
*/
|
||||
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 消息结构体, 可指定发送消息的设备<i>productKey</i>, <i>deviceName</i>; 消息类型, 消息数据等, 更多信息请参考@ref aiot_shadow_msg_t
|
||||
*
|
||||
* @return int32_t
|
||||
* @retval STATE_SUCCESS 请求发送成功
|
||||
* @retval STATE_USER_INPUT_NULL_POINTER 入参<i>handle</i>或<i>msg</i>为NULL
|
||||
* @retval STATE_USER_INPUT_OUT_RANGE 入参<i>msg</i>的结构体成员<i>type</i> >= 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 <STATE_SUCCESS 执行失败
|
||||
*
|
||||
*/
|
||||
int32_t aiot_shadow_deinit(void **handle);
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __AIOT_SHADOW_API_H__ */
|
||||
|
||||
53
sdk/合宙/air780e/csdk/luatos-soc-2022/thirdparty/linksdk/components/shadow/shadow_private.h
vendored
Normal file
53
sdk/合宙/air780e/csdk/luatos-soc-2022/thirdparty/linksdk/components/shadow/shadow_private.h
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* @file shadow_private.h
|
||||
* @brief shadow模块内部的宏定义和数据结构声明, 不面向其它模块, 更不面向用户
|
||||
*
|
||||
* @copyright Copyright (C) 2015-2020 Alibaba Group Holding Limited
|
||||
*
|
||||
*/
|
||||
#ifndef __SHADOW_PRIVATE_H__
|
||||
#define __SHADOW_PRIVATE_H__
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* 用这种方式包含标准C库的头文件 */
|
||||
#include "core_stdinc.h"
|
||||
|
||||
#include "aiot_state_api.h"
|
||||
#include "aiot_sysdep_api.h"
|
||||
#include "aiot_mqtt_api.h"
|
||||
#include "aiot_shadow_api.h"
|
||||
|
||||
/* shadow模块内部的会话句柄结构体, SDK用户不可见, 只能得到void *handle类型的指针 */
|
||||
typedef struct {
|
||||
aiot_sysdep_portfile_t *sysdep;
|
||||
void *mqtt_handle;
|
||||
|
||||
aiot_shadow_recv_handler_t recv_handler;
|
||||
void *userdata;
|
||||
} shadow_handle_t;
|
||||
|
||||
#define SHADOW_MODULE_NAME "shadow"
|
||||
|
||||
#define SHADOW_UPDATE_TOPIC_FMT "/shadow/update/%s/%s"
|
||||
#define SHADOW_GET_TOPIC "/shadow/get/+/+"
|
||||
|
||||
#define SHADOW_PAYLOAD_REQ_FMT "{\"method\":\"%s\",\"state\":{\"reported\":%s},\"version\":%s}"
|
||||
#define SHADOW_PAYLOAD_CLEAN_FMT "{\"method\":\"update\",\"state\":{\"desired\":\"null\"},\"version\":%s}"
|
||||
#define SHADOW_PAYLOAD_GET "{\"method\":\"get\"}"
|
||||
|
||||
#define SHADOW_JSON_KEY_METHOD "method"
|
||||
#define SHADOW_JSON_KEY_PAYLOAD "payload"
|
||||
#define SHADOW_JSON_KEY_STATUS "status"
|
||||
#define SHADOW_JSON_KEY_TIMESTAMP "timestamp"
|
||||
#define SHADOW_JSON_KEY_STATE "state"
|
||||
#define SHADOW_JSON_KEY_VERSION "version"
|
||||
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif /* __SHADOW_PRIVATE_H__ */
|
||||
|
||||
Reference in New Issue
Block a user