mirror of
https://gitee.com/beecue/fastbee.git
synced 2025-12-17 16:36:03 +08:00
1.新增esp-idf设备端sdk
This commit is contained in:
@@ -0,0 +1,910 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "alcs_internal.h"
|
||||
#include "alcs_api.h"
|
||||
#include "alcs_coap.h"
|
||||
#include "alcs_mqtt.h"
|
||||
#include "CoAPInternal.h"
|
||||
#include "CoAPExport.h"
|
||||
#include "CoAPServer.h"
|
||||
#include "alcs_adapter.h"
|
||||
#include "alcs_mqtt.h"
|
||||
#include "alcs_localsetup.h"
|
||||
#include "CoAPPlatform.h"
|
||||
|
||||
static iotx_alcs_adapter_t g_alcs_adapter;
|
||||
|
||||
static void alcs_heartbeat(void *handle);
|
||||
|
||||
static iotx_alcs_adapter_t *__iotx_alcs_get_ctx(void)
|
||||
{
|
||||
return &g_alcs_adapter;
|
||||
}
|
||||
|
||||
static char *iotx_alcs_topic_parse_pk(char *topic, uint16_t *length)
|
||||
{
|
||||
char *pos = NULL;
|
||||
uint8_t slash_count = 0;
|
||||
uint16_t idx = 0;
|
||||
uint16_t topic_len = 0;
|
||||
|
||||
if (topic == NULL || length == NULL) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
topic_len = strlen(topic);
|
||||
|
||||
while (idx < topic_len) {
|
||||
if (topic[idx] == '/') {
|
||||
slash_count++;
|
||||
if (slash_count == 2) {
|
||||
pos = topic + idx + 1;
|
||||
}
|
||||
if (slash_count == 3) {
|
||||
*length = topic + idx - pos;
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static char *iotx_alcs_topic_parse_dn(char *topic, uint16_t *length)
|
||||
{
|
||||
char *pos = NULL;
|
||||
uint8_t slash_count = 0;
|
||||
uint16_t idx = 0;
|
||||
uint16_t topic_len = 0;
|
||||
|
||||
if (topic == NULL || length == NULL) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
topic_len = strlen(topic);
|
||||
|
||||
while (idx < topic_len) {
|
||||
if (topic[idx] == '/') {
|
||||
slash_count++;
|
||||
if (slash_count == 3) {
|
||||
pos = topic + idx + 1;
|
||||
}
|
||||
if (slash_count == 4) {
|
||||
*length = topic + idx - pos;
|
||||
}
|
||||
}
|
||||
idx++;
|
||||
}
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static int _iotx_alcs_send_list_search_and_remove(iotx_alcs_adapter_t *adapter, CoAPMessage *message,
|
||||
iotx_alcs_send_msg_t **send_msg)
|
||||
{
|
||||
iotx_alcs_send_msg_t *node = NULL;
|
||||
iotx_alcs_send_msg_t *next = NULL;
|
||||
|
||||
list_for_each_entry_safe(node, next, &adapter->alcs_send_list, linked_list, iotx_alcs_send_msg_t) {
|
||||
if (message->header.tokenlen == node->token_len &&
|
||||
memcmp(message->token, node->token, node->token_len) == 0) {
|
||||
*send_msg = node;
|
||||
list_del(&node->linked_list);
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
}
|
||||
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
void iotx_alcs_coap_adapter_send_msg_handle(CoAPContext *context,
|
||||
CoAPReqResult result,
|
||||
void *userdata,
|
||||
NetworkAddr *remote,
|
||||
CoAPMessage *message)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = (iotx_alcs_adapter_t *)userdata;
|
||||
iotx_alcs_event_msg_t event;
|
||||
memset(&event, 0, sizeof(iotx_alcs_event_msg_t));
|
||||
|
||||
switch (result) {
|
||||
case COAP_REQUEST_SUCCESS: {
|
||||
iotx_alcs_transfer_msg_t transfer_msg;
|
||||
iotx_alcs_send_msg_t *send_msg = NULL;
|
||||
|
||||
memset(&transfer_msg, 0, sizeof(iotx_alcs_transfer_msg_t));
|
||||
|
||||
transfer_msg.ip = (char *)remote->addr;
|
||||
transfer_msg.port = remote->port;
|
||||
HAL_MutexLock(adapter->mutex);
|
||||
res = _iotx_alcs_send_list_search_and_remove(adapter, message, &send_msg);
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return;
|
||||
}
|
||||
|
||||
transfer_msg.uri = send_msg->uri;
|
||||
transfer_msg.token_len = send_msg->token_len;
|
||||
transfer_msg.token = send_msg->token;
|
||||
transfer_msg.payload_len = message->payloadlen;
|
||||
transfer_msg.payload = message->payload;
|
||||
|
||||
event.event_type = IOTX_ALCS_EVENT_MSG_SEND_MESSAGE_SUCCESS;
|
||||
event.msg = &transfer_msg;
|
||||
|
||||
adapter->alcs_event_handle->h_fp(adapter->alcs_event_handle->pcontext, (void *)adapter, &event);
|
||||
|
||||
ALCS_free(send_msg->token);
|
||||
ALCS_free(send_msg->uri);
|
||||
ALCS_free(send_msg);
|
||||
}
|
||||
break;
|
||||
case COAP_RECV_RESP_TIMEOUT: {
|
||||
iotx_alcs_transfer_msg_t transfer_msg;
|
||||
iotx_alcs_send_msg_t *send_msg = NULL;
|
||||
|
||||
memset(&transfer_msg, 0, sizeof(iotx_alcs_transfer_msg_t));
|
||||
|
||||
transfer_msg.ip = (char *)remote->addr;
|
||||
transfer_msg.port = remote->port;
|
||||
HAL_MutexLock(adapter->mutex);
|
||||
res = _iotx_alcs_send_list_search_and_remove(adapter, message, &send_msg);
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return;
|
||||
}
|
||||
|
||||
transfer_msg.uri = send_msg->uri;
|
||||
transfer_msg.token_len = send_msg->token_len;
|
||||
transfer_msg.token = send_msg->token;
|
||||
transfer_msg.payload_len = 0;
|
||||
transfer_msg.payload = NULL;
|
||||
|
||||
event.event_type = IOTX_ALCS_EVENT_MSG_SEND_MESSAGE_RESP_TIMEOUT;
|
||||
event.msg = &transfer_msg;
|
||||
|
||||
adapter->alcs_event_handle->h_fp(adapter->alcs_event_handle->pcontext, (void *)adapter, &event);
|
||||
|
||||
ALCS_free(send_msg->token);
|
||||
ALCS_free(send_msg->uri);
|
||||
ALCS_free(send_msg);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
COAP_WRN("Unknown Coap Request Result: %d", result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void iotx_alcs_coap_adapter_event_notifier(unsigned int event, NetworkAddr *remote, void *message)
|
||||
{
|
||||
COAP_INFO("ALCS Coap Event: %d, Remote Device Address: %s, Remote Device Port: %d",
|
||||
event, remote->addr, remote->port);
|
||||
}
|
||||
|
||||
int iotx_alcs_adapter_list_init(iotx_alcs_adapter_t *adapter)
|
||||
{
|
||||
/* initialze send list */
|
||||
INIT_LIST_HEAD(&adapter->alcs_send_list);
|
||||
INIT_LIST_HEAD(&adapter->alcs_subdev_list);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
static void _iotx_alcs_adapter_send_list_destroy(iotx_alcs_adapter_t *adapter)
|
||||
{
|
||||
iotx_alcs_send_msg_t *node = NULL;
|
||||
iotx_alcs_send_msg_t *next = NULL;
|
||||
|
||||
list_for_each_entry_safe(node, next, &adapter->alcs_send_list, linked_list, iotx_alcs_send_msg_t) {
|
||||
list_del(&node->linked_list);
|
||||
ALCS_free(node->token);
|
||||
ALCS_free(node->uri);
|
||||
ALCS_free(node);
|
||||
}
|
||||
}
|
||||
|
||||
static void _iotx_alcs_adapter_subdev_list_destroy(iotx_alcs_adapter_t *adapter)
|
||||
{
|
||||
iotx_alcs_send_msg_t *node = NULL;
|
||||
iotx_alcs_send_msg_t *next = NULL;
|
||||
|
||||
list_for_each_entry_safe(node, next, &adapter->alcs_subdev_list, linked_list, iotx_alcs_send_msg_t) {
|
||||
list_del(&node->linked_list);
|
||||
ALCS_free(node);
|
||||
}
|
||||
}
|
||||
|
||||
int iotx_alcs_adapter_deinit(void)
|
||||
{
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
iotx_alcs_adapter_t *adapter = __iotx_alcs_get_ctx();
|
||||
|
||||
HAL_GetProductKey(product_key);
|
||||
HAL_GetDeviceName(device_name);
|
||||
|
||||
HAL_MutexLock(adapter->mutex);
|
||||
_iotx_alcs_adapter_send_list_destroy(adapter);
|
||||
_iotx_alcs_adapter_subdev_list_destroy(adapter);
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
|
||||
if (adapter->alcs_event_handle) {
|
||||
ALCS_free(adapter->alcs_event_handle);
|
||||
}
|
||||
|
||||
HAL_MutexDestroy(adapter->mutex);
|
||||
|
||||
alcs_mqtt_deinit(adapter->coap_ctx, product_key, device_name);
|
||||
|
||||
/* if (adapter->coap_ctx) CoAPContext_free(adapter->coap_ctx); */
|
||||
|
||||
alcs_context_deinit();
|
||||
alcs_deinit();
|
||||
alcs_auth_deinit();
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int iotx_alcs_adapter_init(iotx_alcs_adapter_t *adapter, iotx_alcs_param_t *param)
|
||||
{
|
||||
int res;
|
||||
CoAPInitParam coap_param;
|
||||
CoAPContext *coap_ctx = NULL;
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
|
||||
COAP_INFO("iotx_alcs_adapter_init");
|
||||
memset(&coap_param, 0, sizeof(CoAPInitParam));
|
||||
|
||||
adapter->mutex = HAL_MutexCreate();
|
||||
if (adapter->mutex == NULL) {
|
||||
COAP_ERR("Mutex Init Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
coap_param.send_maxcount = param->send_maxcount;
|
||||
coap_param.obs_maxcount = param->obs_maxcount;
|
||||
coap_param.port = param->port;
|
||||
coap_param.group = param->group;
|
||||
coap_param.waittime = param->waittime;
|
||||
coap_param.res_maxcount = param->res_maxcount;
|
||||
coap_param.appdata = NULL;
|
||||
coap_param.notifier = iotx_alcs_coap_adapter_event_notifier;
|
||||
|
||||
coap_ctx = alcs_context_init(&coap_param);
|
||||
if (coap_ctx == NULL) {
|
||||
COAP_ERR("Coap Context Init Failed");
|
||||
HAL_MutexDestroy(adapter->mutex);
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
adapter->coap_ctx = coap_ctx;
|
||||
|
||||
res = HAL_GetProductKey(product_key);
|
||||
if (res <= 0 || res > IOTX_PRODUCT_KEY_LEN + 1 - 1) {
|
||||
iotx_alcs_adapter_deinit();
|
||||
COAP_ERR("Get Product Key Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
res = HAL_GetDeviceName(device_name);
|
||||
if (res <= 0 || res > IOTX_DEVICE_NAME_LEN + 1 - 1) {
|
||||
iotx_alcs_adapter_deinit();
|
||||
COAP_ERR("Get Device Name Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
alcs_init();
|
||||
|
||||
res = alcs_auth_init(coap_ctx, product_key, device_name, param->role);
|
||||
if (res != COAP_SUCCESS) {
|
||||
iotx_alcs_adapter_deinit();
|
||||
COAP_ERR("ALCS Auth Init Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
adapter->role = param->role;
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
{
|
||||
extern void on_svr_auth_timer(CoAPContext *);
|
||||
if (adapter->role & IOTX_ALCS_ROLE_SERVER) {
|
||||
adapter->alcs_server_auth_timer_func = on_svr_auth_timer;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
{
|
||||
extern void on_client_auth_timer(CoAPContext *);
|
||||
if (adapter->role & IOTX_ALCS_ROLE_CLIENT) {
|
||||
adapter->alcs_client_auth_timer_func = on_client_auth_timer;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
adapter->alcs_event_handle = (iotx_alcs_event_handle_t *)ALCS_ADAPTER_malloc(sizeof(iotx_alcs_event_handle_t));
|
||||
if (adapter->alcs_event_handle == NULL) {
|
||||
iotx_alcs_adapter_deinit();
|
||||
COAP_ERR("ALCS Event Handle Init Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
memcpy(adapter->alcs_event_handle, param->handle_event, sizeof(iotx_alcs_event_handle_t));
|
||||
|
||||
if (iotx_alcs_adapter_list_init(adapter) != SUCCESS_RETURN) {
|
||||
iotx_alcs_adapter_deinit();
|
||||
COAP_ERR("ALCS Linked List Init Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
alcs_localsetup_init(adapter, coap_ctx, product_key, device_name);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
static int _iotx_alcs_subdev_list_search(const char *pk, const char *dn, iotx_alcs_subdev_item_t **subdev_item)
|
||||
{
|
||||
iotx_alcs_adapter_t *adapter = __iotx_alcs_get_ctx();
|
||||
iotx_alcs_subdev_item_t *node = NULL;
|
||||
|
||||
if (pk == NULL || dn == NULL) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
list_for_each_entry(node, &adapter->alcs_subdev_list, linked_list, iotx_alcs_subdev_item_t) {
|
||||
if (strlen(node->product_key) == strlen(pk) &&
|
||||
memcmp(node->product_key, pk, strlen(pk)) == 0 &&
|
||||
strlen(node->device_name) == strlen(dn) &&
|
||||
memcmp(node->device_name, dn, strlen(dn)) == 0) {
|
||||
*subdev_item = node;
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
}
|
||||
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
int iotx_alcs_subdev_remove(const char *pk, const char *dn)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = __iotx_alcs_get_ctx();
|
||||
iotx_alcs_subdev_item_t *subdev_item = NULL;
|
||||
|
||||
if (pk == NULL || dn == NULL) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
HAL_MutexLock(adapter->mutex);
|
||||
res = _iotx_alcs_subdev_list_search(pk, dn, &subdev_item);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
COAP_ERR("No Matched Item");
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
list_del(&subdev_item->linked_list);
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
|
||||
ALCS_free(subdev_item);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int iotx_alcs_subdev_update_stage(iotx_alcs_subdev_item_t *item)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = __iotx_alcs_get_ctx();
|
||||
iotx_alcs_subdev_item_t *subdev_item = NULL;
|
||||
|
||||
if (item == NULL) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
HAL_MutexLock(adapter->mutex);
|
||||
res = _iotx_alcs_subdev_list_search(item->product_key, item->device_name, &subdev_item);
|
||||
|
||||
if (res < SUCCESS_RETURN) {
|
||||
COAP_WRN("No Matched Item");
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
subdev_item->stage = item->stage;
|
||||
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
void iotx_alcs_subdev_stage_check(void)
|
||||
{
|
||||
iotx_alcs_adapter_t *adapter = __iotx_alcs_get_ctx();
|
||||
iotx_alcs_subdev_item_t *node = NULL;
|
||||
uint64_t time_now = HAL_UptimeMs();
|
||||
|
||||
HAL_MutexLock(adapter->mutex);
|
||||
list_for_each_entry(node, &adapter->alcs_subdev_list, linked_list, iotx_alcs_subdev_item_t) {
|
||||
if (node->stage == IOTX_ALCS_SUBDEV_DISCONNCET_CLOUD) {
|
||||
if (((time_now > node->retry_ms) &&
|
||||
(time_now - node->retry_ms >= IOTX_ALCS_SUBDEV_RETRY_INTERVAL_MS)) ||
|
||||
((time_now <= node->retry_ms) &&
|
||||
((0xFFFFFFFFFFFFFFFF - node->retry_ms) + time_now >= IOTX_ALCS_SUBDEV_RETRY_INTERVAL_MS))) {
|
||||
/* Get Prefix And Secret From Cloud */
|
||||
alcs_mqtt_subdev_prefix_get(node->product_key, node->device_name);
|
||||
node->retry_ms = time_now;
|
||||
}
|
||||
}
|
||||
}
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
}
|
||||
|
||||
void *iotx_alcs_construct(iotx_alcs_param_t *params)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = __iotx_alcs_get_ctx();
|
||||
|
||||
COAP_INFO("iotx_alcs_construct enter");
|
||||
|
||||
if (params == NULL || params->group == NULL ||
|
||||
strlen(params->group) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(adapter, 0, sizeof(iotx_alcs_adapter_t));
|
||||
|
||||
res = iotx_alcs_adapter_init(adapter, params);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
COAP_ERR("Adapter Init Failed");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return (void *)adapter;
|
||||
}
|
||||
|
||||
int iotx_alcs_cloud_init(void *handle)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = __iotx_alcs_get_ctx();
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
|
||||
COAP_INFO("Start ALCS Cloud Init");
|
||||
|
||||
if (adapter->local_cloud_inited == 1) {
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
if (handle == NULL) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
res = HAL_GetProductKey(product_key);
|
||||
if (res <= 0 || res > IOTX_PRODUCT_KEY_LEN + 1 - 1) {
|
||||
iotx_alcs_adapter_deinit();
|
||||
COAP_ERR("Get Product Key Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
res = HAL_GetDeviceName(device_name);
|
||||
if (res <= 0 || res > IOTX_DEVICE_NAME_LEN + 1 - 1) {
|
||||
iotx_alcs_adapter_deinit();
|
||||
COAP_ERR("Get Device Name Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
if (alcs_mqtt_init(adapter->coap_ctx, product_key, device_name) != ALCS_MQTT_STATUS_SUCCESS) {
|
||||
/*solve the prpblem of hard fault when mqtt connection fails once*/
|
||||
COAP_ERR("ALCS MQTT Init Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
adapter->local_cloud_inited = 1;
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int iotx_alcs_destroy(void **phandle)
|
||||
{
|
||||
if (phandle == NULL || *phandle == NULL) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
iotx_alcs_adapter_deinit();
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
static void alcs_heartbeat(void *handle)
|
||||
{
|
||||
iotx_alcs_adapter_t *adapter = (iotx_alcs_adapter_t *)handle;
|
||||
|
||||
if (adapter->role & IOTX_ALCS_ROLE_SERVER && adapter->alcs_server_auth_timer_func != NULL) {
|
||||
adapter->alcs_server_auth_timer_func(adapter->coap_ctx);
|
||||
}
|
||||
|
||||
if (adapter->role & IOTX_ALCS_ROLE_CLIENT && adapter->alcs_client_auth_timer_func != NULL) {
|
||||
adapter->alcs_client_auth_timer_func(adapter->coap_ctx);
|
||||
}
|
||||
}
|
||||
int iotx_alcs_yield(void *handle)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = (iotx_alcs_adapter_t *)handle;
|
||||
|
||||
if (adapter == NULL || adapter->coap_ctx == NULL) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
alcs_heartbeat(handle);
|
||||
|
||||
iotx_alcs_subdev_stage_check();
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int iotx_alcs_send(void *handle, iotx_alcs_msg_t *msg)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = (iotx_alcs_adapter_t *)handle;
|
||||
CoAPMessage coap_msg;
|
||||
CoAPLenString coap_payload;
|
||||
NetworkAddr network_addr;
|
||||
|
||||
AlcsDeviceKey devKey;
|
||||
char productKey[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char deviceName[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
char *uri_pk = NULL;
|
||||
char *uri_dn = NULL;
|
||||
uint16_t uri_pk_len = 0;
|
||||
uint16_t uri_dn_len = 0;
|
||||
iotx_alcs_send_msg_t *alcs_send_msg = NULL;
|
||||
|
||||
if (adapter == NULL || adapter->coap_ctx ||
|
||||
msg == NULL || msg->payload == NULL ||
|
||||
msg->ip == NULL || strlen(msg->ip) == 0 ||
|
||||
msg->uri == NULL || strlen(msg->uri) == 0) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
if (strlen(msg->ip) > NETWORK_ADDR_LEN) {
|
||||
COAP_ERR("Invalid Ip Address Length");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
memset(&coap_msg, 0, sizeof(CoAPMessage));
|
||||
memset(&coap_payload, 0, sizeof(CoAPLenString));
|
||||
|
||||
coap_payload.len = msg->payload_len;
|
||||
coap_payload.data = msg->payload;
|
||||
|
||||
alcs_msg_init(adapter->coap_ctx, &coap_msg, msg->msg_code, msg->msg_type, 0, &coap_payload, (void *)adapter);
|
||||
|
||||
res = alcs_msg_setAddr(&coap_msg, msg->uri, NULL);
|
||||
if (res != COAP_SUCCESS) {
|
||||
COAP_ERR("ALCS Message Set URI Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
memset(&network_addr, 0, sizeof(NetworkAddr));
|
||||
memcpy(network_addr.addr, msg->ip, strlen(msg->ip));
|
||||
network_addr.port = msg->port;
|
||||
|
||||
|
||||
memset(&devKey, 0, sizeof(AlcsDeviceKey));
|
||||
memcpy(&devKey.addr, &network_addr, sizeof(NetworkAddr));
|
||||
|
||||
uri_pk = iotx_alcs_topic_parse_pk(msg->uri, &uri_pk_len);
|
||||
uri_dn = iotx_alcs_topic_parse_dn(msg->uri, &uri_dn_len);
|
||||
|
||||
if (uri_pk == NULL || uri_pk_len >= IOTX_PRODUCT_KEY_LEN + 1 ||
|
||||
uri_dn == NULL || uri_dn_len >= IOTX_DEVICE_NAME_LEN + 1) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
memcpy(productKey, uri_pk, uri_pk_len);
|
||||
memcpy(deviceName, uri_dn, uri_dn_len);
|
||||
|
||||
devKey.pk = productKey;
|
||||
devKey.dn = deviceName;
|
||||
|
||||
res = alcs_sendmsg_secure(adapter->coap_ctx, &devKey, &coap_msg, 2, iotx_alcs_coap_adapter_send_msg_handle);
|
||||
alcs_msg_deinit(&coap_msg);
|
||||
|
||||
if (res != COAP_SUCCESS) {
|
||||
COAP_ERR("ALCS Message Send Message Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
alcs_send_msg = (iotx_alcs_send_msg_t *)ALCS_ADAPTER_malloc(sizeof(iotx_alcs_send_msg_t));
|
||||
if (alcs_send_msg == NULL) {
|
||||
COAP_WRN("Not Enough Memory");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
memset(alcs_send_msg, 0, sizeof(iotx_alcs_send_msg_t));
|
||||
|
||||
alcs_send_msg->token = (uint8_t *)ALCS_ADAPTER_malloc(coap_msg.header.tokenlen + 1);
|
||||
if (alcs_send_msg->token == NULL) {
|
||||
ALCS_free(alcs_send_msg);
|
||||
COAP_WRN("Not Enough Memory");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
alcs_send_msg->token_len = coap_msg.header.tokenlen;
|
||||
|
||||
memset(alcs_send_msg->token, 0, alcs_send_msg->token_len + 1);
|
||||
memcpy(alcs_send_msg->token, coap_msg.token, alcs_send_msg->token_len);
|
||||
|
||||
alcs_send_msg->uri = (char *)ALCS_ADAPTER_malloc(strlen(msg->uri) + 1);
|
||||
if (alcs_send_msg->uri == NULL) {
|
||||
ALCS_free(alcs_send_msg->token);
|
||||
ALCS_free(alcs_send_msg);
|
||||
COAP_WRN("ALCS Message Buffer Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
memset(alcs_send_msg->uri, 0, strlen(msg->uri) + 1);
|
||||
memcpy(alcs_send_msg->uri, msg->uri, strlen(msg->uri));
|
||||
INIT_LIST_HEAD(&alcs_send_msg->linked_list);
|
||||
|
||||
HAL_MutexLock(adapter->mutex);
|
||||
list_add_tail(&alcs_send_msg->linked_list, &adapter->alcs_send_list);
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int iotx_alcs_send_Response(void *handle, iotx_alcs_msg_t *msg, uint8_t token_len, uint8_t *token)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = (iotx_alcs_adapter_t *)handle;
|
||||
CoAPMessage coap_msg;
|
||||
CoAPLenString coap_payload;
|
||||
CoAPLenString token_payload;
|
||||
NetworkAddr network_addr;
|
||||
|
||||
AlcsDeviceKey devKey;
|
||||
char productKey[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char deviceName[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
char *uri_pk = NULL;
|
||||
char *uri_dn = NULL;
|
||||
uint16_t uri_pk_len = 0;
|
||||
uint16_t uri_dn_len = 0;
|
||||
|
||||
if (adapter == NULL || adapter->coap_ctx == NULL ||
|
||||
msg == NULL || msg->payload == NULL ||
|
||||
msg->ip == NULL || strlen(msg->ip) == 0 ||
|
||||
msg->uri == NULL || strlen(msg->uri) == 0) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
if (token_len == 0 || token == NULL) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
|
||||
if (strlen(msg->ip) > NETWORK_ADDR_LEN) {
|
||||
COAP_ERR("Invalid Ip Address Length");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
memset(&coap_msg, 0, sizeof(CoAPMessage));
|
||||
memset(&coap_payload, 0, sizeof(CoAPLenString));
|
||||
memset(&token_payload, 0, sizeof(CoAPLenString));
|
||||
|
||||
coap_payload.len = msg->payload_len;
|
||||
coap_payload.data = msg->payload;
|
||||
|
||||
alcs_msg_init(adapter->coap_ctx, &coap_msg, msg->msg_code, msg->msg_type, 0, &coap_payload, (void *)adapter);
|
||||
|
||||
res = alcs_msg_setAddr(&coap_msg, msg->uri, NULL);
|
||||
if (res != COAP_SUCCESS) {
|
||||
COAP_ERR("ALCS Message Set URI Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
memset(&network_addr, 0, sizeof(NetworkAddr));
|
||||
memcpy(network_addr.addr, msg->ip, strlen(msg->ip));
|
||||
network_addr.port = msg->port;
|
||||
|
||||
token_payload.len = token_len;
|
||||
token_payload.data = token;
|
||||
|
||||
memset(&devKey, 0, sizeof(AlcsDeviceKey));
|
||||
memcpy(&devKey.addr, &network_addr, sizeof(NetworkAddr));
|
||||
|
||||
uri_pk = iotx_alcs_topic_parse_pk(msg->uri, &uri_pk_len);
|
||||
uri_dn = iotx_alcs_topic_parse_dn(msg->uri, &uri_dn_len);
|
||||
|
||||
if (uri_pk == NULL || uri_pk_len >= IOTX_PRODUCT_KEY_LEN + 1 ||
|
||||
uri_dn == NULL || uri_dn_len >= IOTX_DEVICE_NAME_LEN + 1) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
memcpy(productKey, uri_pk, uri_pk_len);
|
||||
memcpy(deviceName, uri_dn, uri_dn_len);
|
||||
|
||||
devKey.pk = productKey;
|
||||
devKey.dn = deviceName;
|
||||
|
||||
if (alcs_resource_need_auth(adapter->coap_ctx, msg->uri)) {
|
||||
res = alcs_sendrsp_secure(adapter->coap_ctx, &devKey, &coap_msg, 0, 0, &token_payload);
|
||||
} else {
|
||||
res = alcs_sendrsp(adapter->coap_ctx, &network_addr, &coap_msg, 0, 0, &token_payload);
|
||||
}
|
||||
|
||||
alcs_msg_deinit(&coap_msg);
|
||||
|
||||
if (res != COAP_SUCCESS) {
|
||||
COAP_ERR("ALCS Message Send Message Failed");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int iotx_alcs_register_resource(void *handle, iotx_alcs_res_t *resource)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = (iotx_alcs_adapter_t *)handle;
|
||||
char productKey[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char deviceName[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
char *uri_pk = NULL;
|
||||
char *uri_dn = NULL;
|
||||
uint16_t uri_pk_len = 0;
|
||||
uint16_t uri_dn_len = 0;
|
||||
int needAuth = 0;
|
||||
|
||||
if (adapter == NULL || adapter->coap_ctx == NULL ||
|
||||
resource->uri == NULL || strlen(resource->uri) == 0) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
uri_pk = iotx_alcs_topic_parse_pk(resource->uri, &uri_pk_len);
|
||||
uri_dn = iotx_alcs_topic_parse_dn(resource->uri, &uri_dn_len);
|
||||
|
||||
if (uri_pk == NULL || uri_pk_len >= IOTX_PRODUCT_KEY_LEN + 1 ||
|
||||
uri_dn == NULL || uri_dn_len >= IOTX_DEVICE_NAME_LEN + 1) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
memcpy(productKey, uri_pk, uri_pk_len);
|
||||
memcpy(deviceName, uri_dn, uri_dn_len);
|
||||
|
||||
COAP_INFO("alcs register resource, uri:%s", resource->uri);
|
||||
needAuth = resource->need_auth; /* strcmp (resource->uri, "/dev/core/service/dev"); */
|
||||
|
||||
res = alcs_resource_register(adapter->coap_ctx,
|
||||
productKey,
|
||||
deviceName,
|
||||
resource->uri,
|
||||
resource->msg_perm,
|
||||
resource->msg_ct,
|
||||
resource->maxage,
|
||||
needAuth,
|
||||
(void (*)(CoAPContext * context, const char *paths, NetworkAddr * remote,
|
||||
CoAPMessage * message))resource->callback);
|
||||
|
||||
if (res != COAP_SUCCESS) {
|
||||
COAP_ERR("ALCS Register Resource Failed, Code: %d", res);
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int iotx_alcs_observe_notify(void *handle, const char *uri, uint32_t payload_len, uint8_t *payload)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = (iotx_alcs_adapter_t *)handle;
|
||||
CoAPLenString coap_payload;
|
||||
|
||||
coap_payload.len = (int32_t)payload_len;
|
||||
coap_payload.data = payload;
|
||||
|
||||
res = alcs_observe_notify(adapter->coap_ctx, uri, &coap_payload);
|
||||
if (res != COAP_SUCCESS) {
|
||||
COAP_ERR("ALCS Observe Notify Failed, Code: %d", res);
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int iotx_alcs_unregister_resource(void *handle, char *uri)
|
||||
{
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int iotx_alcs_add_sub_device(void *handle, const char *pk, const char *dn)
|
||||
{
|
||||
int res = 0;
|
||||
iotx_alcs_adapter_t *adapter = (iotx_alcs_adapter_t *)handle;
|
||||
iotx_alcs_subdev_item_t *subdev_item = NULL;
|
||||
char prefix[ALCS_MQTT_PREFIX_MAX_LEN] = {0};
|
||||
char secret[ALCS_MQTT_SECRET_MAX_LEN] = {0};
|
||||
|
||||
if (handle == NULL || pk == NULL || strlen(pk) >= IOTX_PRODUCT_KEY_LEN + 1 ||
|
||||
dn == NULL || strlen(dn) >= IOTX_DEVICE_NAME_LEN + 1) {
|
||||
COAP_ERR("Invalid Argument");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
if (adapter->coap_ctx != NULL) {
|
||||
alcs_auth_subdev_init(adapter->coap_ctx, pk, dn);
|
||||
}
|
||||
|
||||
/* Search Subdev In Linked List */
|
||||
HAL_MutexLock(adapter->mutex);
|
||||
res = _iotx_alcs_subdev_list_search(pk, dn, &subdev_item);
|
||||
if (res == SUCCESS_RETURN) {
|
||||
COAP_INFO("This Product Key And Device Name Have Been Added");
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
|
||||
/* Insert New Subdev Into Linked List */
|
||||
subdev_item = (iotx_alcs_subdev_item_t *)ALCS_ADAPTER_malloc(sizeof(iotx_alcs_subdev_item_t));
|
||||
if (subdev_item == NULL) {
|
||||
COAP_ERR("No Enough Memory");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
memset(subdev_item, 0, sizeof(iotx_alcs_subdev_item_t));
|
||||
|
||||
/* Set Product Key And Device Name */
|
||||
memcpy(subdev_item->product_key, pk, strlen(pk));
|
||||
memcpy(subdev_item->device_name, dn, strlen(dn));
|
||||
subdev_item->stage = IOTX_ALCS_SUBDEV_DISCONNCET_CLOUD;
|
||||
subdev_item->retry_ms = HAL_UptimeMs();
|
||||
INIT_LIST_HEAD(&subdev_item->linked_list);
|
||||
|
||||
HAL_MutexLock(adapter->mutex);
|
||||
list_add_tail(&subdev_item->linked_list, &adapter->alcs_subdev_list);
|
||||
HAL_MutexUnlock(adapter->mutex);
|
||||
|
||||
alcs_localsetup_add_sub_device(adapter, subdev_item->product_key, subdev_item->device_name);
|
||||
|
||||
/* Get Prefix And Secret From KV */
|
||||
res = alcs_mqtt_prefix_secret_load(pk, strlen(pk), dn, strlen(dn), prefix, secret);
|
||||
if (res == SUCCESS_RETURN) {
|
||||
memcpy(subdev_item->prefix, prefix, strlen(prefix));
|
||||
memcpy(subdev_item->secret, secret, strlen(secret));
|
||||
alcs_mqtt_add_srv_key(prefix, secret);
|
||||
}
|
||||
|
||||
/* Get Prefix And Secret From Cloud */
|
||||
alcs_mqtt_subdev_prefix_get(pk, dn);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int iotx_alcs_remove_sub_device(void *handle, const char *pk, const char *dn)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
if (handle == NULL || pk == NULL || strlen(pk) >= IOTX_PRODUCT_KEY_LEN + 1 ||
|
||||
dn == NULL || strlen(dn) >= IOTX_DEVICE_NAME_LEN + 1) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
res = iotx_alcs_subdev_remove(pk, dn);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Remove Subdev Item From KV */
|
||||
alcs_mqtt_prefix_secret_del(pk, strlen(pk), dn, strlen(dn));
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef __ALCS_ADAPTER_H__
|
||||
#define __ALCS_ADAPTER_H__
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "alcs_internal.h"
|
||||
#include "mqtt_api.h"
|
||||
#include "CoAPExport.h"
|
||||
#include "alcs_mqtt.h"
|
||||
#include "iotx_alcs.h"
|
||||
|
||||
typedef struct iotx_alcs_send_msg_st {
|
||||
uint8_t token_len;
|
||||
uint8_t *token;
|
||||
char *uri;
|
||||
struct list_head linked_list;
|
||||
} iotx_alcs_send_msg_t, *iotx_alcs_send_msg_pt;
|
||||
|
||||
typedef enum {
|
||||
IOTX_ALCS_SUBDEV_DISCONNCET_CLOUD,
|
||||
IOTX_ALCS_SUBDEV_CONNECT_CLOUD
|
||||
} iotx_alcs_subdev_stage_t;
|
||||
|
||||
#define IOTX_ALCS_SUBDEV_RETRY_INTERVAL_MS (10000)
|
||||
|
||||
typedef struct iotx_alcs_subdev_item_st {
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1];
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1];
|
||||
char prefix[ALCS_MQTT_PREFIX_MAX_LEN];
|
||||
char secret[ALCS_MQTT_SECRET_MAX_LEN];
|
||||
uint8_t stage;
|
||||
uint64_t retry_ms;
|
||||
struct list_head linked_list;
|
||||
} iotx_alcs_subdev_item_t, *iotx_alcs_subdev_item_pt;
|
||||
|
||||
typedef void (*iotx_alcs_auth_timer_fnuc_t)(CoAPContext *);
|
||||
|
||||
typedef struct iotx_alcs_adapter_st {
|
||||
void *mutex;
|
||||
int local_cloud_inited;
|
||||
CoAPContext *coap_ctx;
|
||||
uint8_t role;
|
||||
iotx_alcs_auth_timer_fnuc_t alcs_client_auth_timer_func;
|
||||
iotx_alcs_auth_timer_fnuc_t alcs_server_auth_timer_func;
|
||||
iotx_alcs_event_handle_t *alcs_event_handle;
|
||||
struct list_head alcs_send_list;
|
||||
struct list_head alcs_subdev_list;
|
||||
char local_ip[NETWORK_ADDR_LEN];
|
||||
uint16_t local_port;
|
||||
} iotx_alcs_adapter_t, *iotx_alcs_adapter_pt;
|
||||
|
||||
int iotx_alcs_subdev_insert(iotx_alcs_subdev_item_t *item);
|
||||
int iotx_alcs_subdev_remove(const char *pk, const char *dn);
|
||||
int iotx_alcs_subdev_search(const char *pk, const char *dn, iotx_alcs_subdev_item_t **item);
|
||||
int iotx_alcs_subdev_update_stage(iotx_alcs_subdev_item_t *item);
|
||||
void iotx_alcs_send_list_handle(void *list_node, va_list *params);
|
||||
int iotx_alcs_adapter_list_init(iotx_alcs_adapter_t *adapter);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,718 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include "alcs_internal.h"
|
||||
#include "alcs_api.h"
|
||||
#include "alcs_coap.h"
|
||||
#include "alcs_api_internal.h"
|
||||
#include "CoAPPlatform.h"
|
||||
#include "CoAPObserve.h"
|
||||
|
||||
ALIYUN_LIST_HEAD(secure_resource_cb_head);
|
||||
|
||||
static bool is_inited = 0;
|
||||
#ifdef SUPPORT_MULTI_DEVICES
|
||||
ALIYUN_LIST_HEAD(device_list);
|
||||
|
||||
device_auth_list *get_device(CoAPContext *context)
|
||||
{
|
||||
device_auth_list *node = NULL, *next = NULL;
|
||||
list_for_each_entry_safe(node, next, &device_list, lst, device_auth_list) {
|
||||
if (node->context == context) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
auth_list *get_list(CoAPContext *context)
|
||||
{
|
||||
device_auth_list *dev_lst = get_device(context);
|
||||
return dev_lst ? &dev_lst->lst_auth : NULL;
|
||||
}
|
||||
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
struct list_head *get_ctl_session_list(CoAPContext *context)
|
||||
{
|
||||
device_auth_list *dev_lst = get_device(context);
|
||||
if (!dev_lst || !(dev_lst->role & ROLE_CLIENT)) {
|
||||
return NULL;
|
||||
}
|
||||
return &dev_lst->lst_ctl_sessions;
|
||||
}
|
||||
#endif
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
struct list_head *get_svr_session_list(CoAPContext *context)
|
||||
{
|
||||
device_auth_list *dev_lst = get_device(context);
|
||||
return dev_lst && (dev_lst->role & ROLE_SERVER) ? &dev_lst->lst_svr_sessions : NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#else
|
||||
device_auth_list _device;
|
||||
#endif
|
||||
|
||||
void remove_session(CoAPContext *ctx, session_item *session)
|
||||
{
|
||||
COAP_INFO("remove_session");
|
||||
if (session) {
|
||||
CoapObsServerAll_delete(ctx, &session->addr);
|
||||
list_del(&session->lst);
|
||||
coap_free(session);
|
||||
}
|
||||
}
|
||||
|
||||
session_item *get_session_by_checksum(struct list_head *sessions, NetworkAddr *addr, char ck[PK_DN_CHECKSUM_LEN])
|
||||
{
|
||||
session_item *node = NULL, *next = NULL;
|
||||
if (!sessions || !ck) {
|
||||
return NULL;
|
||||
}
|
||||
list_for_each_entry_safe(node, next, sessions, lst, session_item) {
|
||||
if (is_networkadd_same(addr, &node->addr)
|
||||
&& strncmp(node->pk_dn, ck, PK_DN_CHECKSUM_LEN) == 0) {
|
||||
COAP_DEBUG("find node, sessionid:%d", node->sessionId);
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static session_item *get_session(struct list_head *sessions, AlcsDeviceKey *devKey)
|
||||
{
|
||||
char ck[PK_DN_CHECKSUM_LEN] = {0};
|
||||
char path[100] = {0};
|
||||
if (!sessions || !devKey || !devKey->pk || !devKey->dn) {
|
||||
return NULL;
|
||||
}
|
||||
HAL_Snprintf(path, sizeof(path), "%s%s", devKey->pk, devKey->dn);
|
||||
CoAPPathMD5_sum(path, strlen(path), ck, PK_DN_CHECKSUM_LEN);
|
||||
|
||||
return get_session_by_checksum(sessions, &devKey->addr, ck);
|
||||
}
|
||||
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
session_item *get_ctl_session(CoAPContext *ctx, AlcsDeviceKey *devKey)
|
||||
{
|
||||
struct list_head *sessions = get_ctl_session_list(ctx);
|
||||
COAP_DEBUG("get_ctl_session");
|
||||
return get_session(sessions, devKey);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
session_item *get_svr_session(CoAPContext *ctx, AlcsDeviceKey *devKey)
|
||||
{
|
||||
struct list_head *sessions = get_svr_session_list(ctx);
|
||||
return get_session(sessions, devKey);
|
||||
}
|
||||
#endif
|
||||
|
||||
static session_item *get_auth_session(CoAPContext *ctx, AlcsDeviceKey *devKey)
|
||||
{
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
session_item *node = get_ctl_session(ctx, devKey);
|
||||
if (node && node->sessionId) {
|
||||
return node;
|
||||
}
|
||||
#endif
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
session_item *node1 = get_svr_session(ctx, devKey);
|
||||
if (node1 && node1->sessionId) {
|
||||
return node1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static session_item *get_auth_session_by_checksum(CoAPContext *ctx, NetworkAddr *addr, char ck[])
|
||||
{
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
struct list_head *sessions = get_ctl_session_list(ctx);
|
||||
session_item *node = get_session_by_checksum(sessions, addr, ck);
|
||||
if (node && node->sessionId) {
|
||||
return node;
|
||||
}
|
||||
#endif
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
struct list_head *sessions1 = get_svr_session_list(ctx);
|
||||
session_item *node1 = get_session_by_checksum(sessions1, addr, ck);
|
||||
if (node1 && node1->sessionId) {
|
||||
return node1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void gen_random_key(unsigned char random[], int len)
|
||||
{
|
||||
int i = 0, flag = 0;
|
||||
|
||||
memset(random, 0x00, len);
|
||||
srand((unsigned)time(NULL));
|
||||
|
||||
for (i = 0; i < len - 1; i++) {
|
||||
flag = rand() % 3;
|
||||
switch (flag) {
|
||||
case 0:
|
||||
random[i] = 'A' + rand() % 26;
|
||||
break;
|
||||
case 1:
|
||||
random[i] = 'a' + rand() % 26;
|
||||
break;
|
||||
case 2:
|
||||
random[i] = '0' + rand() % 10;
|
||||
break;
|
||||
default:
|
||||
random[i] = 'x';
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
extern void alcs_rec_auth_select(CoAPContext *context, const char *paths, NetworkAddr *remote, CoAPMessage *request);
|
||||
extern void alcs_rec_auth(CoAPContext *context, const char *paths, NetworkAddr *remote, CoAPMessage *request);
|
||||
extern void alcs_rec_heart_beat(CoAPContext *context, const char *paths, NetworkAddr *remote, CoAPMessage *request);
|
||||
#endif
|
||||
|
||||
int alcs_auth_init(CoAPContext *ctx, const char *productKey, const char *deviceName, char role)
|
||||
{
|
||||
device_auth_list *dev;
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
char path[256];
|
||||
#endif
|
||||
if (is_inited) {
|
||||
return 0;
|
||||
}
|
||||
is_inited = 1;
|
||||
|
||||
/* auth_list* lst_auth; */
|
||||
|
||||
#ifdef SUPPORT_MULTI_DEVICES
|
||||
INIT_LIST_HEAD(&device_list);
|
||||
|
||||
dev = coap_malloc(sizeof(device_auth_list));
|
||||
list_add_tail(&dev->lst, &device_list);
|
||||
#else
|
||||
dev = &_device;
|
||||
#endif
|
||||
dev->context = ctx;
|
||||
dev->seq = 1;
|
||||
dev->role = role;
|
||||
memset(&dev->lst_auth, 0, sizeof(auth_list));
|
||||
/* strcpy (dev->deviceName, deviceName); */
|
||||
/* strcpy (dev->productKey, productKey); */
|
||||
|
||||
INIT_LIST_HEAD(&dev->lst);
|
||||
INIT_LIST_HEAD(&secure_resource_cb_head);
|
||||
|
||||
if (role & ROLE_SERVER) {
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
INIT_LIST_HEAD(&dev->lst_svr_sessions);
|
||||
INIT_LIST_HEAD(&dev->lst_auth.lst_svr);
|
||||
|
||||
HAL_Snprintf(path, sizeof(path), "/dev/%s/%s/core/service/auth", productKey, deviceName);
|
||||
alcs_resource_register(ctx, productKey, deviceName, path, COAP_PERM_GET, COAP_CT_APP_JSON, 60, 0, alcs_rec_auth);
|
||||
strcat(path, "/select");
|
||||
alcs_resource_register(ctx, productKey, deviceName, path, COAP_PERM_GET, COAP_CT_APP_JSON, 60, 0, alcs_rec_auth_select);
|
||||
alcs_resource_register(ctx, productKey, deviceName, "/dev/core/service/heartBeat", COAP_PERM_GET, COAP_CT_APP_JSON, 60,
|
||||
0, alcs_rec_heart_beat);
|
||||
#endif
|
||||
}
|
||||
|
||||
if (role & ROLE_CLIENT) {
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
INIT_LIST_HEAD(&dev->lst_ctl_sessions);
|
||||
INIT_LIST_HEAD(&dev->lst_auth.lst_ctl);
|
||||
#endif
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&dev->lst_auth.lst_ctl_group);
|
||||
INIT_LIST_HEAD(&dev->lst_auth.lst_svr_group);
|
||||
dev->lst_auth.list_mutex = HAL_MutexCreate();
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
void alcs_auth_subdev_init(CoAPContext *ctx, const char *productKey, const char *deviceName)
|
||||
{
|
||||
char path[256];
|
||||
HAL_Snprintf(path, sizeof(path), "/dev/%s/%s/core/service/auth", productKey, deviceName);
|
||||
alcs_resource_register(ctx, productKey, deviceName, path, COAP_PERM_GET, COAP_CT_APP_JSON, 60, 0, alcs_rec_auth);
|
||||
strcat(path, "/select");
|
||||
alcs_resource_register(ctx, productKey, deviceName, path, COAP_PERM_GET, COAP_CT_APP_JSON, 60, 0, alcs_rec_auth_select);
|
||||
}
|
||||
|
||||
void alcs_auth_deinit(void)
|
||||
{
|
||||
#ifdef SUPPORT_MULTI_DEVICES
|
||||
device_auth_list *node = NULL, *next = NULL;
|
||||
#endif
|
||||
|
||||
alcs_resource_cb_deinit();
|
||||
alcs_auth_list_deinit();
|
||||
|
||||
#ifdef SUPPORT_MULTI_DEVICES
|
||||
list_for_each_entry_safe(node, next, &device_list, lst, device_auth_list) {
|
||||
if (node->lst_auth.list_mutex) {
|
||||
HAL_MutexDestroy(node->lst_auth.list_mutex);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (_device.lst_auth.list_mutex) {
|
||||
HAL_MutexDestroy(_device.lst_auth.list_mutex);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
bool is_networkadd_same(NetworkAddr *addr1, NetworkAddr *addr2)
|
||||
{
|
||||
if (!addr1 || !addr2) {
|
||||
return 0;
|
||||
}
|
||||
COAP_DEBUG("compare addr1:%s,addr2:%s", addr1->addr, addr2->addr);
|
||||
return addr1->port == addr2->port && !strcmp((const char *)addr1->addr, (const char *)addr2->addr);
|
||||
}
|
||||
|
||||
int alcs_encrypt(const char *src, int len, const char *key, void *out)
|
||||
{
|
||||
char *iv = "a1b1c1d1e1f1g1h1";
|
||||
|
||||
int len1 = len & 0xfffffff0;
|
||||
int len2 = len1 + 16;
|
||||
int pad = len2 - len;
|
||||
int ret = 0;
|
||||
|
||||
if (len1) {
|
||||
p_HAL_Aes128_t aes_e_h = HAL_Aes128_Init((uint8_t *)key, (uint8_t *)iv, HAL_AES_ENCRYPTION);
|
||||
ret = HAL_Aes128_Cbc_Encrypt(aes_e_h, src, len1 >> 4, out);
|
||||
HAL_Aes128_Destroy(aes_e_h);
|
||||
}
|
||||
if (!ret && pad) {
|
||||
char buf[16];
|
||||
p_HAL_Aes128_t aes_e_h = NULL;
|
||||
memcpy(buf, src + len1, len - len1);
|
||||
memset(buf + len - len1, pad, pad);
|
||||
aes_e_h = HAL_Aes128_Init((uint8_t *)key, (uint8_t *)iv, HAL_AES_ENCRYPTION);
|
||||
ret = HAL_Aes128_Cbc_Encrypt(aes_e_h, buf, 1, (uint8_t *)out + len1);
|
||||
HAL_Aes128_Destroy(aes_e_h);
|
||||
}
|
||||
|
||||
COAP_DEBUG("to encrypt src:%s, len:%d", src, len2);
|
||||
return ret == 0 ? len2 : 0;
|
||||
}
|
||||
|
||||
int alcs_decrypt(const char *src, int len, const char *key, void *out)
|
||||
{
|
||||
char *iv = "a1b1c1d1e1f1g1h1";
|
||||
p_HAL_Aes128_t aes_d_h;
|
||||
int n = len >> 4;
|
||||
char *out_c = NULL;
|
||||
int offset = 0;
|
||||
int ret = 0;
|
||||
char pad = 0;
|
||||
|
||||
COAP_DEBUG("to decrypt len:%d", len);
|
||||
|
||||
do {
|
||||
if (n > 1) {
|
||||
aes_d_h = HAL_Aes128_Init((uint8_t *)key, (uint8_t *)iv, HAL_AES_DECRYPTION);
|
||||
if (!aes_d_h) {
|
||||
COAP_ERR("fail to decrypt init");
|
||||
break;
|
||||
}
|
||||
|
||||
ret = HAL_Aes128_Cbc_Decrypt(aes_d_h, src, n - 1, out);
|
||||
HAL_Aes128_Destroy(aes_d_h);
|
||||
|
||||
if (ret != 0) {
|
||||
COAP_ERR("fail to decrypt");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out_c = (char *)out;
|
||||
offset = n > 0 ? ((n - 1) << 4) : 0;
|
||||
out_c[offset] = 0;
|
||||
|
||||
aes_d_h = HAL_Aes128_Init((uint8_t *)key, (uint8_t *)iv, HAL_AES_DECRYPTION);
|
||||
if (!aes_d_h) {
|
||||
COAP_ERR("fail to decrypt init");
|
||||
break;
|
||||
}
|
||||
|
||||
ret = HAL_Aes128_Cbc_Decrypt(aes_d_h, src + offset, 1, out_c + offset);
|
||||
HAL_Aes128_Destroy(aes_d_h);
|
||||
|
||||
if (ret != 0) {
|
||||
COAP_ERR("fail to decrypt remain data");
|
||||
break;
|
||||
}
|
||||
|
||||
pad = out_c[len - 1];
|
||||
out_c[len - pad] = 0;
|
||||
COAP_DEBUG("decrypt data:%s, len:%d", out_c, len - pad);
|
||||
return len - pad;
|
||||
} while (0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool alcs_is_auth(CoAPContext *ctx, AlcsDeviceKey *devKey)
|
||||
{
|
||||
return get_auth_session(ctx, devKey) != NULL;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------*/
|
||||
typedef struct {
|
||||
void *orig_user_data;
|
||||
char pk_dn[PK_DN_CHECKSUM_LEN];
|
||||
CoAPSendMsgHandler orig_handler;
|
||||
} secure_send_item;
|
||||
|
||||
static int do_secure_send(CoAPContext *ctx, NetworkAddr *addr, CoAPMessage *message, const char *key, char *buf)
|
||||
{
|
||||
int ret = COAP_SUCCESS;
|
||||
void *payload_old = message->payload;
|
||||
int len_old = message->payloadlen;
|
||||
|
||||
COAP_DEBUG("do_secure_send");
|
||||
|
||||
message->payload = (unsigned char *)buf;
|
||||
message->payloadlen = alcs_encrypt((const char *)payload_old, len_old, key, message->payload);
|
||||
ret = CoAPMessage_send(ctx, addr, message);
|
||||
|
||||
message->payload = payload_old;
|
||||
message->payloadlen = len_old;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void secure_sendmsg_handler(CoAPContext *context, CoAPReqResult result, void *userdata, NetworkAddr *remote,
|
||||
CoAPMessage *message);
|
||||
int internal_secure_send(CoAPContext *ctx, session_item *session, NetworkAddr *addr, CoAPMessage *message, char observe,
|
||||
CoAPSendMsgHandler handler)
|
||||
{
|
||||
int encryptlen = 0;
|
||||
|
||||
COAP_DEBUG("internal_secure_send");
|
||||
if (!ctx || !session || !addr || !message) {
|
||||
COAP_ERR("parameter is null");
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (handler) {
|
||||
secure_send_item *item = (secure_send_item *)coap_malloc(sizeof(secure_send_item));
|
||||
item->orig_user_data = message->user;
|
||||
item->orig_handler = handler;
|
||||
memcpy(item->pk_dn, session->pk_dn, PK_DN_CHECKSUM_LEN);
|
||||
|
||||
message->handler = secure_sendmsg_handler;
|
||||
message->user = item;
|
||||
}
|
||||
|
||||
if (observe == 0) {
|
||||
CoAPUintOption_add(message, COAP_OPTION_OBSERVE, observe);
|
||||
}
|
||||
CoAPUintOption_add(message, COAP_OPTION_CONTENT_FORMAT, COAP_CT_APP_OCTET_STREAM);
|
||||
CoAPUintOption_add(message, COAP_OPTION_SESSIONID, session->sessionId);
|
||||
COAP_DEBUG("secure_send sessionId:%d", session->sessionId);
|
||||
|
||||
encryptlen = (message->payloadlen & 0xfffffff0) + 16;
|
||||
if (encryptlen > 64) {
|
||||
char *buf = (char *)coap_malloc(encryptlen);
|
||||
int rt = do_secure_send(ctx, addr, message, session->sessionKey, buf);
|
||||
coap_free(buf);
|
||||
return rt;
|
||||
} else {
|
||||
char buf[64];
|
||||
return do_secure_send(ctx, addr, message, session->sessionKey, buf);
|
||||
}
|
||||
}
|
||||
|
||||
static void call_cb(CoAPContext *context, NetworkAddr *remote, CoAPMessage *message, const char *key, char *buf,
|
||||
secure_send_item *send_item)
|
||||
{
|
||||
if (send_item->orig_handler) {
|
||||
int len = alcs_decrypt((const char *)message->payload, message->payloadlen, key, buf);
|
||||
CoAPMessage tmpMsg;
|
||||
memcpy(&tmpMsg, message, sizeof(CoAPMessage));
|
||||
tmpMsg.payload = (unsigned char *)buf;
|
||||
tmpMsg.payloadlen = len;
|
||||
send_item->orig_handler(context, COAP_REQUEST_SUCCESS, send_item->orig_user_data, remote, &tmpMsg);
|
||||
}
|
||||
}
|
||||
|
||||
void secure_sendmsg_handler(CoAPContext *context, CoAPReqResult result, void *userdata, NetworkAddr *remote,
|
||||
CoAPMessage *message)
|
||||
{
|
||||
secure_send_item *send_item = (secure_send_item *)userdata;
|
||||
session_item *session = NULL;
|
||||
unsigned int obsVal;
|
||||
|
||||
if (!context || !userdata || !remote) {
|
||||
return;
|
||||
}
|
||||
if (result == COAP_RECV_RESP_TIMEOUT) {
|
||||
if (send_item->orig_handler) {
|
||||
send_item->orig_handler(context, COAP_RECV_RESP_TIMEOUT, send_item->orig_user_data, remote, NULL);
|
||||
}
|
||||
COAP_INFO("secure_sendmsg_handler timeout");
|
||||
} else {
|
||||
unsigned int sessionId = 0;
|
||||
CoAPUintOption_get(message, COAP_OPTION_SESSIONID, &sessionId);
|
||||
COAP_DEBUG("secure_sendmsg_handler, sessionID:%d", (int)sessionId);
|
||||
|
||||
session = get_auth_session_by_checksum(context, remote, send_item->pk_dn);
|
||||
|
||||
if (!session || session->sessionId != sessionId) {
|
||||
COAP_ERR("secure_sendmsg_handler, need auth, from:%s", remote->addr);
|
||||
/* todo */
|
||||
} else {
|
||||
session->heart_time = HAL_UptimeMs();
|
||||
if (message->payloadlen < 128) {
|
||||
char buf[128];
|
||||
call_cb(context, remote, message, session->sessionKey, buf, send_item);
|
||||
} else {
|
||||
char *buf = (char *)coap_malloc(message->payloadlen);
|
||||
if (buf) {
|
||||
call_cb(context, remote, message, session->sessionKey, buf, send_item);
|
||||
coap_free(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (CoAPUintOption_get(message, COAP_OPTION_OBSERVE, &obsVal) != COAP_SUCCESS) {
|
||||
coap_free(send_item);
|
||||
}
|
||||
}
|
||||
|
||||
int alcs_sendmsg_secure(CoAPContext *ctx, AlcsDeviceKey *devKey, CoAPMessage *message, char observe,
|
||||
CoAPSendMsgHandler handler)
|
||||
{
|
||||
session_item *session = NULL;
|
||||
|
||||
if (!ctx || !devKey || !message) {
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
session = get_auth_session(ctx, devKey);
|
||||
if (!session) {
|
||||
COAP_DEBUG("alcs_sendmsg_secure, session not found");
|
||||
return ALCS_ERR_AUTH_UNAUTH;
|
||||
}
|
||||
|
||||
return internal_secure_send(ctx, session, &devKey->addr, message, observe, handler);
|
||||
}
|
||||
|
||||
int alcs_sendrsp_secure(CoAPContext *ctx, AlcsDeviceKey *devKey, CoAPMessage *message, char observe,
|
||||
unsigned short msgid, CoAPLenString *token)
|
||||
{
|
||||
session_item *session = NULL;
|
||||
|
||||
COAP_DEBUG("alcs_sendrsp_secure");
|
||||
if (!ctx || !devKey || !message) {
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (msgid == 0) {
|
||||
message->header.msgid = CoAPMessageId_gen(ctx);
|
||||
} else {
|
||||
message->header.msgid = msgid;
|
||||
}
|
||||
|
||||
if (token) {
|
||||
message->header.tokenlen = token->len;
|
||||
memcpy(&message->token, token->data, token->len);
|
||||
}
|
||||
|
||||
session = get_auth_session(ctx, devKey);
|
||||
if (!session) {
|
||||
COAP_DEBUG("alcs_sendrsp_secure, session not found");
|
||||
return ALCS_ERR_AUTH_UNAUTH;
|
||||
}
|
||||
|
||||
return internal_secure_send(ctx, session, &devKey->addr, message, observe, NULL);
|
||||
}
|
||||
|
||||
bool req_payload_parser(const char *payload, int len, char **seq, int *seqlen, char **data, int *datalen)
|
||||
{
|
||||
if (!payload || !len || !seq || !seqlen || !datalen || !data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
*seq = json_get_value_by_name((char *)payload, len, "id", seqlen, NULL);
|
||||
|
||||
*data = json_get_value_by_name((char *)payload, len, "params", datalen, NULL);
|
||||
return *data && datalen;
|
||||
}
|
||||
|
||||
void on_auth_timer(void *param)
|
||||
{
|
||||
CoAPContext *ctx = NULL;
|
||||
if (!is_inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
ctx = (CoAPContext *) param;
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
{
|
||||
extern void on_client_auth_timer(CoAPContext *);
|
||||
on_client_auth_timer(ctx);
|
||||
}
|
||||
#endif
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
{
|
||||
extern void on_svr_auth_timer(CoAPContext *);
|
||||
on_svr_auth_timer(ctx);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int alcs_add_ctl_group(CoAPContext *context, const char *groupid, const char *accesskey, const char *accesstoken)
|
||||
{
|
||||
ctl_group_item *item = NULL;
|
||||
auth_list *lst = get_list(context);
|
||||
if (!lst || lst->ctl_group_count >= KEY_MAXCOUNT) {
|
||||
return COAP_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
item = (ctl_group_item *) coap_malloc(sizeof(ctl_group_item));
|
||||
if (!item) {
|
||||
return COAP_ERROR_MALLOC;
|
||||
}
|
||||
memset(item, 0, sizeof(ctl_group_item));
|
||||
|
||||
do {
|
||||
item->id = (char *) coap_malloc(strlen(groupid) + 1);
|
||||
if (!item->id) {
|
||||
break;
|
||||
}
|
||||
|
||||
item->accessKey = (char *) coap_malloc(strlen(accesskey) + 1);
|
||||
if (!item->accessKey) {
|
||||
break;
|
||||
}
|
||||
|
||||
item->accessToken = (char *) coap_malloc(strlen(accesstoken) + 1);
|
||||
if (!item->accessToken) {
|
||||
break;
|
||||
}
|
||||
|
||||
strcpy(item->accessKey, accesskey);
|
||||
strcpy(item->accessToken, accesstoken);
|
||||
strcpy(item->id, groupid);
|
||||
|
||||
HAL_MutexLock(lst->list_mutex);
|
||||
list_add_tail(&item->lst, &lst->lst_ctl_group);
|
||||
++lst->ctl_group_count;
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
} while (0);
|
||||
|
||||
if (item->id) {
|
||||
coap_free(item->id);
|
||||
}
|
||||
if (item->accessKey) {
|
||||
coap_free(item->accessKey);
|
||||
}
|
||||
if (item->accessToken) {
|
||||
coap_free(item->accessToken);
|
||||
}
|
||||
coap_free(item);
|
||||
|
||||
return COAP_ERROR_MALLOC;
|
||||
}
|
||||
|
||||
int alcs_remove_ctl_group(CoAPContext *context, const char *groupid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int alcs_add_svr_group(CoAPContext *context, const char *groupid, const char *keyprefix, const char *secret)
|
||||
{
|
||||
svr_group_item *item = NULL;
|
||||
auth_list *lst = get_list(context);
|
||||
if (!lst || lst->svr_group_count >= KEY_MAXCOUNT) {
|
||||
return COAP_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
item = (svr_group_item *) coap_malloc(sizeof(svr_group_item));
|
||||
if (!item) {
|
||||
return COAP_ERROR_MALLOC;
|
||||
}
|
||||
memset(item, 0, sizeof(svr_group_item));
|
||||
|
||||
do {
|
||||
item->id = (char *) coap_malloc(strlen(groupid) + 1);
|
||||
if (!item->id) {
|
||||
break;
|
||||
}
|
||||
|
||||
item->keyInfo.secret = (char *) coap_malloc(strlen(secret) + 1);
|
||||
if (!item->keyInfo.secret) {
|
||||
break;
|
||||
}
|
||||
|
||||
strncpy(item->keyInfo.keyprefix, keyprefix, sizeof(item->keyInfo.keyprefix) - 1);
|
||||
strcpy(item->keyInfo.secret, secret);
|
||||
strcpy(item->id, groupid);
|
||||
|
||||
HAL_MutexLock(lst->list_mutex);
|
||||
list_add_tail(&item->lst, &lst->lst_svr_group);
|
||||
++lst->svr_group_count;
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
|
||||
return 0;
|
||||
|
||||
} while (0);
|
||||
|
||||
if (item->id) {
|
||||
coap_free(item->id);
|
||||
}
|
||||
if (item->keyInfo.secret) {
|
||||
coap_free(item->keyInfo.secret);
|
||||
}
|
||||
coap_free(item);
|
||||
|
||||
return COAP_ERROR_MALLOC;
|
||||
}
|
||||
|
||||
int alcs_remove_svr_group(CoAPContext *context, const char *groupid)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void alcs_utils_md5_hexstr(unsigned char input[16], unsigned char output[32])
|
||||
{
|
||||
unsigned char idx = 0;
|
||||
unsigned char output_char = 0;
|
||||
|
||||
for (idx = 0; idx < 16; idx++) {
|
||||
if (((input[idx] >> 4) & 0x0F) <= 0x09) {
|
||||
output_char = ((input[idx] >> 4) & 0x0F) + '0';
|
||||
} else if (((input[idx] >> 4) & 0x0F) >= 0x0A) {
|
||||
output_char = ((input[idx] >> 4) & 0x0F) + 'a' - 0x0A;
|
||||
}
|
||||
output[2 * idx] = output_char;
|
||||
|
||||
if (((input[idx]) & 0x0F) <= 0x09) {
|
||||
output_char = ((input[idx]) & 0x0F) + '0';
|
||||
} else if (((input[idx]) & 0x0F) >= 0x0A) {
|
||||
output_char = ((input[idx]) & 0x0F) + 'a' - 0x0A;
|
||||
}
|
||||
output[2 * idx + 1] = output_char;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "alcs_coap.h"
|
||||
|
||||
#ifndef __ALCS_API_H__
|
||||
#define __ALCS_API_H__
|
||||
|
||||
#define SESSIONID_LEN 8
|
||||
#define SESSIONKEY_MAXLEN 30
|
||||
|
||||
#define ALCS_ERR_AUTH_BASE (COAP_ERROR_BASE | 100)
|
||||
#define ALCS_ERR_AUTH_AUTHING (ALCS_ERR_AUTH_BASE | 1)
|
||||
#define ALCS_ERR_AUTH_NOCTLKEY (ALCS_ERR_AUTH_BASE | 2)
|
||||
#define ALCS_ERR_AUTH_UNAUTH (ALCS_ERR_AUTH_BASE | 3)
|
||||
#define ALCS_ERR_ENCRYPT_FAILED (ALCS_ERR_AUTH_BASE | 5)
|
||||
|
||||
typedef enum {
|
||||
ALCS_AUTH_OK = 200,
|
||||
ALCS_AUTH_REVOCATE = 501,
|
||||
ALCS_AUTH_UNMATCHPREFIX,
|
||||
ALCS_AUTH_INVALIDPARAM,
|
||||
ALCS_AUTH_AUTHLISTEMPTY,
|
||||
ALCS_AUTH_VERNOTSUPPORT,
|
||||
ALCS_AUTH_ILLEGALSIGN,
|
||||
ALCS_HEART_FAILAUTH,
|
||||
} Auth_Result_Code;
|
||||
|
||||
#include "iotx_alcs_config.h"
|
||||
|
||||
typedef struct {
|
||||
int code;
|
||||
char *msg;/* MUST call coap_free to free memory */
|
||||
} ResponseMsg;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
/*
|
||||
typedef struct
|
||||
{
|
||||
ResponseMsg msg;
|
||||
char sessionId [SESSIONID_LEN];
|
||||
char sessionKey[SESSIONKEY_MAXLEN];
|
||||
NetworkAddr addr;
|
||||
} AuthResult;
|
||||
*/
|
||||
|
||||
typedef void (*AuthHandler)(CoAPContext *context, NetworkAddr *addr, void *user_data, ResponseMsg *result);
|
||||
typedef struct {
|
||||
char *productKey;
|
||||
char *deviceName;
|
||||
char *accessKey;
|
||||
char *accessToken;
|
||||
void *user_data;
|
||||
AuthHandler handler;
|
||||
} AuthParam;
|
||||
|
||||
typedef struct {
|
||||
NetworkAddr addr;
|
||||
char *pk;
|
||||
char *dn;
|
||||
} AlcsDeviceKey;
|
||||
|
||||
/* 初始化认证模块
|
||||
* context: 为当前设备生成的CoAPContext对象指针
|
||||
* productKey:当前设备的productKey,可以为空
|
||||
* deviceName: 当前设备的deviceName,可以为空
|
||||
* role: 1 --client
|
||||
* 2 --server
|
||||
* 3 --client&server
|
||||
*/
|
||||
int alcs_auth_init(CoAPContext *context, const char *productKey, const char *deviceName, char role);
|
||||
void alcs_auth_subdev_init(CoAPContext *ctx, const char *productKey, const char *deviceName);
|
||||
void alcs_auth_deinit(void);
|
||||
|
||||
bool alcs_is_auth(CoAPContext *ctx, AlcsDeviceKey *devKey);
|
||||
int alcs_sendmsg_secure(CoAPContext *ctx, AlcsDeviceKey *devKey, CoAPMessage *message, char observe,
|
||||
CoAPSendMsgHandler handler);
|
||||
int alcs_sendrsp_secure(CoAPContext *ctx, AlcsDeviceKey *devKey, CoAPMessage *message, char observe,
|
||||
unsigned short msgid, CoAPLenString *token);
|
||||
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
/* 身份认证-- 直接传入accesskey&accesstoken
|
||||
* context: 当前设备生成的CoAPContext对象指针
|
||||
* addr: 待连设备地址
|
||||
* auth_param:包含待连设备的信息和回调接口
|
||||
*/
|
||||
void alcs_auth_has_key(CoAPContext *ctx, NetworkAddr *addr, AuthParam *auth_param);
|
||||
|
||||
/* 身份认证--通过productkey&devicename在缓存的accesskey列表中查找合适accesskey
|
||||
* 此函数需要和alcs_add_client_key 配合使用
|
||||
* 若不知道准确的accessKey,认证前client会和server协商合适的accessKey
|
||||
*
|
||||
* context: 为当前设备生成的CoAPContext对象指针
|
||||
* addr: 待连设备地址
|
||||
* productKey:待连设备的productKey
|
||||
* deviceName:待连设备的deviceName
|
||||
* handler: 结果回调接口
|
||||
*/
|
||||
void alcs_auth_nego_key(CoAPContext *ctx, AlcsDeviceKey *devKey, AuthHandler handler);
|
||||
/*
|
||||
*
|
||||
*
|
||||
*/
|
||||
int alcs_add_client_key(CoAPContext *context, const char *accesskey, const char *accesstoken, const char *productKey,
|
||||
const char *deviceName);
|
||||
int alcs_remove_client_key(CoAPContext *context, const char *key, char isfullkey);
|
||||
/*
|
||||
*
|
||||
*
|
||||
*/
|
||||
bool alcs_device_online(CoAPContext *context, AlcsDeviceKey *devKey);
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
typedef enum {
|
||||
LOCALDEFAULT,
|
||||
LOCALSETUP,
|
||||
FROMCLOUDSVR
|
||||
} ServerKeyPriority;
|
||||
|
||||
int alcs_add_svr_key(CoAPContext *context, const char *keyprefix, const char *secret, ServerKeyPriority priority);
|
||||
int alcs_remove_svr_key(CoAPContext *context, const char *keyprefix);
|
||||
/* 设置吊销列表*
|
||||
* context: 为当前设备生成的CoAPContext对象指针
|
||||
* seqlist: 吊销列表字符串,每个被吊销设备占用三字节
|
||||
*/
|
||||
int alcs_set_revocation(CoAPContext *context, const char *seqlist);
|
||||
#endif
|
||||
|
||||
int alcs_add_ctl_group(CoAPContext *context, const char *groupid, const char *accesskey, const char *accesstoken);
|
||||
int alcs_remove_ctl_group(CoAPContext *context, const char *groupid);
|
||||
|
||||
int alcs_add_svr_group(CoAPContext *context, const char *groupid, const char *keyprefix, const char *secret);
|
||||
int alcs_remove_svr_group(CoAPContext *context, const char *groupid);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __ALCS_API_INTERNAL_H__
|
||||
#define __ALCS_API_INTERNAL_H__
|
||||
#include "CoAPExport.h"
|
||||
#include "alcs_api.h"
|
||||
#include "alcs_internal.h"
|
||||
|
||||
#define KEY_MAXCOUNT 10
|
||||
#define RANDOMKEY_LEN 16
|
||||
#define KEYSEQ_LEN 3
|
||||
#define COAP_OPTION_SESSIONID 71
|
||||
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
typedef struct {
|
||||
char *accessKey;
|
||||
char *accessToken;
|
||||
char *deviceName;
|
||||
char *productKey;
|
||||
struct list_head lst;
|
||||
} ctl_key_item;
|
||||
#endif
|
||||
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
|
||||
typedef struct {
|
||||
char keyprefix[KEYPREFIX_LEN + 1];
|
||||
char *secret;
|
||||
ServerKeyPriority priority;
|
||||
} svr_key_info;
|
||||
|
||||
typedef struct {
|
||||
svr_key_info keyInfo;
|
||||
struct list_head lst;
|
||||
} svr_key_item;
|
||||
|
||||
typedef struct {
|
||||
char *id;
|
||||
char *revocation;
|
||||
svr_key_info keyInfo;
|
||||
struct list_head lst;
|
||||
} svr_group_item;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
char *id;
|
||||
char *accessKey;
|
||||
char *accessToken;
|
||||
struct list_head lst;
|
||||
} ctl_group_item;
|
||||
|
||||
typedef struct {
|
||||
void *list_mutex;
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
struct list_head lst_ctl;
|
||||
unsigned char ctl_count;
|
||||
#endif
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
struct list_head lst_svr;
|
||||
unsigned char svr_count;
|
||||
char *revocation;
|
||||
#endif
|
||||
struct list_head lst_ctl_group;
|
||||
int ctl_group_count;
|
||||
struct list_head lst_svr_group;
|
||||
int svr_group_count;
|
||||
} auth_list;
|
||||
|
||||
#define PK_DN_CHECKSUM_LEN 6
|
||||
typedef struct {
|
||||
char randomKey[RANDOMKEY_LEN + 1];
|
||||
int sessionId;
|
||||
char sessionKey[32];
|
||||
int authed_time;
|
||||
int heart_time;
|
||||
int interval;
|
||||
NetworkAddr addr;
|
||||
char pk_dn[PK_DN_CHECKSUM_LEN];
|
||||
struct list_head lst;
|
||||
} session_item;
|
||||
|
||||
#define ROLE_SERVER 2
|
||||
#define ROLE_CLIENT 1
|
||||
|
||||
typedef struct {
|
||||
CoAPContext *context;
|
||||
int seq;
|
||||
auth_list lst_auth;
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
struct list_head lst_svr_sessions;
|
||||
#endif
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
struct list_head lst_ctl_sessions;
|
||||
#endif
|
||||
char role;
|
||||
struct list_head lst;
|
||||
} device_auth_list;
|
||||
|
||||
#ifdef SUPPORT_MULTI_DEVICES
|
||||
extern struct list_head device_list;
|
||||
|
||||
device_auth_list *get_device(CoAPContext *context);
|
||||
|
||||
auth_list *get_list(CoAPContext *context);
|
||||
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
struct list_head *get_ctl_session_list(CoAPContext *context);
|
||||
#endif
|
||||
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
struct list_head *get_svr_session_list(CoAPContext *context);
|
||||
#endif
|
||||
|
||||
#else
|
||||
extern device_auth_list _device;
|
||||
#define get_device(v) (&_device)
|
||||
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
#define get_svr_session_list(v) (_device.role&ROLE_SERVER? &_device.lst_svr_sessions : NULL)
|
||||
#endif
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
#define get_ctl_session_list(v) (_device.role&ROLE_CLIENT? &_device.lst_ctl_sessions : NULL)
|
||||
#endif
|
||||
|
||||
#define get_list(v) (&_device.lst_auth)
|
||||
#endif
|
||||
|
||||
void remove_session(CoAPContext *ctx, session_item *session);
|
||||
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
session_item *get_ctl_session(CoAPContext *ctx, AlcsDeviceKey *key);
|
||||
#endif
|
||||
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
session_item *get_svr_session(CoAPContext *ctx, AlcsDeviceKey *key);
|
||||
session_item *get_session_by_checksum(struct list_head *sessions, NetworkAddr *addr, char ck[PK_DN_CHECKSUM_LEN]);
|
||||
|
||||
#define MAX_PATH_CHECKSUM_LEN (5)
|
||||
typedef struct {
|
||||
char path[MAX_PATH_CHECKSUM_LEN];
|
||||
char pk_dn[PK_DN_CHECKSUM_LEN];
|
||||
char *filter_path;
|
||||
path_type_t path_type;
|
||||
CoAPRecvMsgHandler cb;
|
||||
struct list_head lst;
|
||||
} secure_resource_cb_item;
|
||||
|
||||
extern struct list_head secure_resource_cb_head;
|
||||
#endif
|
||||
|
||||
int alcs_encrypt(const char *src, int len, const char *key, void *out);
|
||||
int alcs_decrypt(const char *src, int len, const char *key, void *out);
|
||||
int observe_data_encrypt(CoAPContext *ctx, const char *paths, NetworkAddr *addr,
|
||||
CoAPMessage *message, CoAPLenString *src, CoAPLenString *dest);
|
||||
|
||||
bool is_networkadd_same(NetworkAddr *addr1, NetworkAddr *addr2);
|
||||
void gen_random_key(unsigned char random[], int len);
|
||||
bool req_payload_parser(const char *payload, int len, char **seq, int *seqlen, char **data, int *datalen);
|
||||
int internal_secure_send(CoAPContext *ctx, session_item *session, NetworkAddr *addr,
|
||||
CoAPMessage *message, char observe, CoAPSendMsgHandler handler);
|
||||
|
||||
int alcs_resource_register_secure(CoAPContext *context, const char *pk, const char *dn, const char *path,
|
||||
unsigned short permission,
|
||||
unsigned int ctype, unsigned int maxage, CoAPRecvMsgHandler callback);
|
||||
void alcs_resource_cb_deinit(void);
|
||||
void alcs_auth_list_deinit(void);
|
||||
void alcs_utils_md5_hexstr(unsigned char input[16], unsigned char output[32]);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,132 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include "infra_types.h"
|
||||
#include "infra_defs.h"
|
||||
#include "alcs_base64.h"
|
||||
|
||||
static int8_t g_encodingTable[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H',
|
||||
'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P',
|
||||
'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X',
|
||||
'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f',
|
||||
'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
|
||||
'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
|
||||
'w', 'x', 'y', 'z', '0', '1', '2', '3',
|
||||
'4', '5', '6', '7', '8', '9', '+', '/'
|
||||
};
|
||||
|
||||
static int8_t g_decodingTable[256];
|
||||
static int32_t g_modTable[] = { 0, 2, 1 };
|
||||
|
||||
static void build_decoding_table()
|
||||
{
|
||||
static int32_t signal = 0;
|
||||
int32_t i = 0;
|
||||
|
||||
if (signal != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < 64; i++) {
|
||||
g_decodingTable[(uint8_t) g_encodingTable[i]] = i;
|
||||
}
|
||||
|
||||
signal = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
int utils_base64encode(const uint8_t *data, uint32_t inputLength, uint32_t outputLenMax,
|
||||
uint8_t *encodedData, uint32_t *outputLength)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t j = 0;
|
||||
|
||||
if (NULL == encodedData) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
*outputLength = 4 * ((inputLength + 2) / 3);
|
||||
|
||||
if (outputLenMax < *outputLength) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
for (i = 0, j = 0; i < inputLength;) {
|
||||
uint32_t octet_a = i < inputLength ? (uint8_t) data[i++] : 0;
|
||||
uint32_t octet_b = i < inputLength ? (uint8_t) data[i++] : 0;
|
||||
uint32_t octet_c = i < inputLength ? (uint8_t) data[i++] : 0;
|
||||
|
||||
uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c;
|
||||
|
||||
encodedData[j++] = g_encodingTable[(triple >> 3 * 6) & 0x3F];
|
||||
encodedData[j++] = g_encodingTable[(triple >> 2 * 6) & 0x3F];
|
||||
encodedData[j++] = g_encodingTable[(triple >> 1 * 6) & 0x3F];
|
||||
encodedData[j++] = g_encodingTable[(triple >> 0 * 6) & 0x3F];
|
||||
}
|
||||
|
||||
for (i = 0; i < g_modTable[inputLength % 3]; i++) {
|
||||
encodedData[*outputLength - 1 - i] = '=';
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int utils_base64decode(const uint8_t *data, uint32_t inputLength, uint32_t outputLenMax,
|
||||
uint8_t *decodedData, uint32_t *outputLength)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t j = 0;
|
||||
uint32_t sextet_a = 0;
|
||||
uint32_t sextet_b = 0;
|
||||
uint32_t sextet_c = 0;
|
||||
uint32_t sextet_d = 0;
|
||||
uint32_t triple = 0;
|
||||
|
||||
build_decoding_table();
|
||||
|
||||
if (inputLength % 4 != 0) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
*outputLength = inputLength / 4 * 3;
|
||||
|
||||
|
||||
if (data[inputLength - 1] == '=') {
|
||||
(*outputLength)--;
|
||||
}
|
||||
|
||||
if (data[inputLength - 2] == '=') {
|
||||
(*outputLength)--;
|
||||
}
|
||||
|
||||
if (outputLenMax < *outputLength) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
for (i = 0, j = 0; i < inputLength;) {
|
||||
sextet_a = data[i] == '=' ? 0 & i++ : g_decodingTable[data[i++]];
|
||||
sextet_b = data[i] == '=' ? 0 & i++ : g_decodingTable[data[i++]];
|
||||
sextet_c = data[i] == '=' ? 0 & i++ : g_decodingTable[data[i++]];
|
||||
sextet_d = data[i] == '=' ? 0 & i++ : g_decodingTable[data[i++]];
|
||||
|
||||
triple = (sextet_a << 3 * 6) + (sextet_b << 2 * 6) + (sextet_c << 1 * 6) + (sextet_d << 0 * 6);
|
||||
|
||||
if (j < *outputLength) {
|
||||
decodedData[j++] = (triple >> 2 * 8) & 0xFF;
|
||||
}
|
||||
|
||||
if (j < *outputLength) {
|
||||
decodedData[j++] = (triple >> 1 * 8) & 0xFF;
|
||||
}
|
||||
|
||||
if (j < *outputLength) {
|
||||
decodedData[j++] = (triple >> 0 * 8) & 0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#ifndef _ALCS_BASE64_H_
|
||||
#define _ALCS_BASE64_H_
|
||||
|
||||
#include "infra_types.h"
|
||||
|
||||
int utils_base64encode(const uint8_t *data, uint32_t inputLength, uint32_t outputLenMax,
|
||||
uint8_t *encodedData, uint32_t *outputLength);
|
||||
int utils_base64decode(const uint8_t *data, uint32_t inputLength, uint32_t outputLenMax,
|
||||
uint8_t *decodedData, uint32_t *outputLength);
|
||||
#endif
|
||||
@@ -0,0 +1,587 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
#include "alcs_internal.h"
|
||||
#include "alcs_api_internal.h"
|
||||
#include "CoAPPlatform.h"
|
||||
#include "CoAPResource.h"
|
||||
|
||||
#ifdef ALCS_CLIENT_ENABLED
|
||||
static int default_heart_interval = 30000;
|
||||
char match_key(const char *accesskey, const char *keyprefix)
|
||||
{
|
||||
if (strlen(keyprefix) == KEYPREFIX_LEN && strstr(accesskey, keyprefix) == accesskey) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int do_auth(CoAPContext *ctx, NetworkAddr *addr, ctl_key_item *ctl_item, void *userdata, AuthHandler handler);
|
||||
bool res_parse(const char *payload, int len, int *seq, ResponseMsg *res_msg, char **data, int *datalen)
|
||||
{
|
||||
if (!payload || !len || !seq || !res_msg || !data) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
COAP_DEBUG("payload:%.*s", len, payload);
|
||||
|
||||
int tmplen;
|
||||
char *tmp;
|
||||
|
||||
tmp = json_get_value_by_name((char *)payload, len, "id", &tmplen, NULL);
|
||||
if (!tmp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
char back;
|
||||
backup_json_str_last_char(tmp, tmplen, back);
|
||||
*seq = atoi(tmp);
|
||||
restore_json_str_last_char(tmp, tmplen, back);
|
||||
|
||||
tmp = json_get_value_by_name((char *)payload, len, "code", &tmplen, NULL);
|
||||
if (!tmp) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
backup_json_str_last_char(tmp, tmplen, back);
|
||||
res_msg->code = atoi(tmp);
|
||||
restore_json_str_last_char(tmp, tmplen, back);
|
||||
|
||||
tmp = json_get_value_by_name((char *)payload, len, "msg", &tmplen, NULL);
|
||||
if (tmp && tmplen) {
|
||||
res_msg->msg = (char *)coap_malloc(tmplen);
|
||||
memcpy(res_msg->msg, tmp, tmplen);
|
||||
} else {
|
||||
res_msg->msg = NULL;
|
||||
}
|
||||
|
||||
*data = json_get_value_by_name((char *)payload, len, "data", datalen, NULL);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool fillAccessKey(CoAPContext *ctx, char *buf)
|
||||
{
|
||||
auth_list *lst = get_list(ctx);
|
||||
if (!lst) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
HAL_MutexLock(lst->list_mutex);
|
||||
|
||||
if (list_empty(&lst->lst_ctl)) {
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
return 0;
|
||||
}
|
||||
strcpy(buf, ",\"accessKeys\":[");
|
||||
ctl_key_item *node = NULL, *next = NULL;
|
||||
list_for_each_entry_safe(node, next, &lst->lst_ctl, lst, ctl_key_item) {
|
||||
char *format;
|
||||
if (lst->ctl_group_count || !list_is_last(&node->lst, &lst->lst_ctl)) {
|
||||
format = "\"%s\",";
|
||||
} else {
|
||||
format = "\"%s\"]";
|
||||
}
|
||||
sprintf(buf + strlen(buf), format, node->accessKey);
|
||||
}
|
||||
|
||||
ctl_group_item *gnode = NULL, *gnext = NULL;
|
||||
list_for_each_entry_safe(gnode, gnext, &lst->lst_ctl_group, lst, ctl_group_item) {
|
||||
char *format;
|
||||
if (!list_is_last(&gnode->lst, &lst->lst_ctl_group)) {
|
||||
format = "\"%s\",";
|
||||
} else {
|
||||
format = "\"%s\"]";
|
||||
}
|
||||
sprintf(buf + strlen(buf), format, gnode->accessKey);
|
||||
}
|
||||
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define payload_format "{\"version\":\"1.0\",\"method\":\"%s\",\"id\":%d,\"params\":{\"prodKey\":\"%s\", \"deviceName\":\"%s\"%s}}"
|
||||
void nego_cb(CoAPContext *ctx, CoAPReqResult result, void *userdata, NetworkAddr *remote, CoAPMessage *message)
|
||||
{
|
||||
COAP_INFO("nego_cb, message addr:%p, networkaddr:%p!", message, remote);
|
||||
AuthParam *auth_param = (AuthParam *)userdata;
|
||||
|
||||
if (COAP_RECV_RESP_TIMEOUT == result) {
|
||||
ResponseMsg msg = {-1, "response time!"};
|
||||
auth_param->handler(ctx, remote, auth_param->user_data, &msg);
|
||||
coap_free(auth_param->productKey);
|
||||
coap_free(auth_param->deviceName);
|
||||
coap_free(auth_param);
|
||||
|
||||
} else {
|
||||
COAP_DEBUG("recv response message");
|
||||
int seq, datalen;
|
||||
ResponseMsg msg;
|
||||
char *data;
|
||||
|
||||
res_parse((const char *)message->payload, message->payloadlen, &seq, &msg, &data, &datalen);
|
||||
do {
|
||||
if (msg.code != 200) {
|
||||
break;
|
||||
}
|
||||
|
||||
int keylen;
|
||||
char *accessKey = json_get_value_by_name(data, datalen, "accessKey", &keylen, NULL);
|
||||
if (!accessKey || !keylen) {
|
||||
break;
|
||||
}
|
||||
COAP_DEBUG("accesskey:%.*s", keylen, accessKey);
|
||||
|
||||
auth_list *lst = get_list(ctx);
|
||||
ctl_key_item *node = NULL, *next = NULL;
|
||||
char *accessTokenFound = NULL;
|
||||
HAL_MutexLock(lst->list_mutex);
|
||||
|
||||
list_for_each_entry_safe(node, next, &lst->lst_ctl, lst, ctl_key_item) {
|
||||
COAP_DEBUG("node:%s", node->accessKey);
|
||||
if (strncmp(node->accessKey, accessKey, keylen) == 0) {
|
||||
accessTokenFound = node->accessToken;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!accessTokenFound) {
|
||||
ctl_group_item *gnode = NULL, *gnext = NULL;
|
||||
list_for_each_entry_safe(gnode, gnext, &lst->lst_ctl_group, lst, ctl_group_item) {
|
||||
COAP_DEBUG("node:%s", gnode->accessKey);
|
||||
if (strncmp(gnode->accessKey, accessKey, keylen) == 0) {
|
||||
accessTokenFound = gnode->accessKey;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
|
||||
if (accessTokenFound) {
|
||||
ctl_key_item item;
|
||||
item.deviceName = auth_param->deviceName;
|
||||
item.productKey = auth_param->productKey;
|
||||
|
||||
item.accessKey = accessKey;
|
||||
item.accessToken = accessTokenFound;
|
||||
char back;
|
||||
backup_json_str_last_char(accessKey, keylen, back);
|
||||
do_auth(ctx, remote, &item, auth_param->user_data, auth_param->handler);
|
||||
restore_json_str_last_char(accessKey, keylen, back);
|
||||
|
||||
coap_free(auth_param->productKey);
|
||||
coap_free(auth_param->deviceName);
|
||||
coap_free(auth_param);
|
||||
return;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
/* todo */
|
||||
ResponseMsg tmp = {-1, ""};
|
||||
auth_param->handler(ctx, remote, auth_param->user_data, &tmp);
|
||||
coap_free(auth_param->productKey);
|
||||
coap_free(auth_param->deviceName);
|
||||
coap_free(auth_param);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static int CoAPServerPath_2_option(char *uri, CoAPMessage *message)
|
||||
{
|
||||
char *ptr = NULL;
|
||||
char *pstr = NULL;
|
||||
char path[COAP_MSG_MAX_PATH_LEN] = {0};
|
||||
|
||||
if (NULL == uri || NULL == message) {
|
||||
COAP_ERR("Invalid paramter p_path %p, p_message %p", uri, message);
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
if (256 < strlen(uri)) {
|
||||
COAP_ERR("The uri length is too loog,len = %d", (int)strlen(uri));
|
||||
return COAP_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
COAP_DEBUG("The uri is %s", uri);
|
||||
ptr = pstr = uri;
|
||||
while ('\0' != *ptr) {
|
||||
if ('/' == *ptr) {
|
||||
if (ptr != pstr) {
|
||||
memset(path, 0x00, sizeof(path));
|
||||
strncpy(path, pstr, ptr - pstr);
|
||||
COAP_DEBUG("path: %s,len=%d", path, (int)(ptr - pstr));
|
||||
CoAPStrOption_add(message, COAP_OPTION_URI_PATH,
|
||||
(unsigned char *)path, (int)strlen(path));
|
||||
}
|
||||
pstr = ptr + 1;
|
||||
|
||||
}
|
||||
if ('\0' == *(ptr + 1) && '\0' != *pstr) {
|
||||
memset(path, 0x00, sizeof(path));
|
||||
strncpy(path, pstr, sizeof(path) - 1);
|
||||
COAP_DEBUG("path: %s,len=%d", path, (int)strlen(path));
|
||||
CoAPStrOption_add(message, COAP_OPTION_URI_PATH,
|
||||
(unsigned char *)path, (int)strlen(path));
|
||||
}
|
||||
ptr ++;
|
||||
}
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
void auth_cb(CoAPContext *ctx, CoAPReqResult result, void *userdata, NetworkAddr *remote, CoAPMessage *message)
|
||||
{
|
||||
AlcsDeviceKey devKey;
|
||||
COAP_DEBUG("recv auth_cb response message");
|
||||
|
||||
AuthParam *auth_param = (AuthParam *)userdata;
|
||||
memset(&devKey, 0x00, sizeof(AlcsDeviceKey));
|
||||
memcpy(&devKey.addr, remote, sizeof(NetworkAddr));
|
||||
devKey.pk = auth_param->productKey;
|
||||
devKey.dn = auth_param->deviceName;
|
||||
session_item *session = get_ctl_session(ctx, &devKey);
|
||||
|
||||
if (!session) {
|
||||
COAP_INFO("receive unknown auth_cb response, pk:%s, dn:%s", devKey.pk, devKey.dn);
|
||||
ResponseMsg msg = {-1, "no session found!"};
|
||||
auth_param->handler(ctx, remote, auth_param->user_data, &msg);
|
||||
} else if (COAP_RECV_RESP_TIMEOUT == result) {
|
||||
COAP_ERR("response time!");
|
||||
ResponseMsg msg = {-1, "response time!"};
|
||||
auth_param->handler(ctx, remote, auth_param->user_data, &msg);
|
||||
remove_session(ctx, session);
|
||||
} else {
|
||||
int seq, datalen;
|
||||
ResponseMsg msg;
|
||||
char *data;
|
||||
|
||||
res_parse((const char *)message->payload, message->payloadlen, &seq, &msg, &data, &datalen);
|
||||
if (msg.code == 200) {
|
||||
do {
|
||||
int tmplen;
|
||||
char *tmp;
|
||||
|
||||
tmp = json_get_value_by_name(data, datalen, "sessionId", &tmplen, NULL);
|
||||
if (!tmp) {
|
||||
msg.code = -1;
|
||||
msg.msg = "sessionid = NULL!";
|
||||
COAP_ERR("sessionid = NULL!");
|
||||
auth_param->handler(ctx, remote, auth_param->user_data, &msg);
|
||||
break;
|
||||
}
|
||||
char back;
|
||||
backup_json_str_last_char(tmp, tmplen, back);
|
||||
session->sessionId = atoi(tmp);
|
||||
restore_json_str_last_char(tmp, tmplen, back);
|
||||
COAP_INFO("sessionId:%d", session->sessionId);
|
||||
|
||||
tmp = json_get_value_by_name(data, datalen, "randomKey", &tmplen, NULL);
|
||||
if (!tmp) {
|
||||
msg.code = -1;
|
||||
msg.msg = "randomKey = NULL!";
|
||||
COAP_ERR("randomKey = NULL!");
|
||||
auth_param->handler(ctx, remote, auth_param->user_data, &msg);
|
||||
break;
|
||||
}
|
||||
|
||||
char buf[32];
|
||||
HAL_Snprintf(buf, sizeof(buf), "%s%.*s", session->randomKey, tmplen, tmp);
|
||||
utils_hmac_sha1_hex(buf, strlen(buf), session->sessionKey, auth_param->accessToken, strlen(auth_param->accessToken));
|
||||
session->authed_time = HAL_UptimeMs();
|
||||
session->heart_time = session->authed_time;
|
||||
session->interval = default_heart_interval;
|
||||
COAP_INFO("sessionKey is created");
|
||||
} while (0);
|
||||
} else {
|
||||
remove_session(ctx, session);
|
||||
COAP_ERR("message code :%d", msg.code);
|
||||
}
|
||||
auth_param->handler(ctx, remote, auth_param->user_data, &msg);
|
||||
}
|
||||
|
||||
coap_free(auth_param->productKey);
|
||||
coap_free(auth_param->deviceName);
|
||||
coap_free(auth_param->accessToken);
|
||||
coap_free(auth_param);
|
||||
}
|
||||
|
||||
#define auth_payload_format "{\"version\":\"1.0\",\"method\":\"core/service/auth\",\"id\":%d,\"params\":{\"prodKey\":\"%s\", \"deviceName\":\"%s\",\"encrypt\":\"payload\",\"randomKey\":\"%s\",\"sign\":\"%s\",\"accessKey\":\"%s\"}}"
|
||||
|
||||
int do_auth(CoAPContext *ctx, NetworkAddr *addr, ctl_key_item *ctl_item, void *user_data, AuthHandler handler)
|
||||
{
|
||||
int ret = COAP_SUCCESS;
|
||||
AlcsDeviceKey devKey;
|
||||
device_auth_list *dev = get_device(ctx);
|
||||
if (!dev) {
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
memset(&devKey, 0x00, sizeof(AlcsDeviceKey));
|
||||
memcpy(&devKey.addr, addr, sizeof(NetworkAddr));
|
||||
devKey.pk = ctl_item->productKey;
|
||||
devKey.dn = ctl_item->deviceName;
|
||||
|
||||
session_item *session = get_ctl_session(ctx, &devKey);
|
||||
if (session) {
|
||||
if (session->sessionId) {
|
||||
COAP_INFO("no need to reauth!");
|
||||
ResponseMsg res = {COAP_SUCCESS, NULL};
|
||||
handler(ctx, addr, user_data, &res);
|
||||
return COAP_SUCCESS;
|
||||
} else {
|
||||
COAP_INFO("is authing, no need to reauth!");
|
||||
return ALCS_ERR_AUTH_AUTHING;
|
||||
}
|
||||
}
|
||||
|
||||
/* create&save session item */
|
||||
{
|
||||
session = (session_item *)coap_malloc(sizeof(session_item));
|
||||
memset(session, 0, sizeof(session_item));
|
||||
|
||||
char path[100] = {0};
|
||||
strncpy(path, ctl_item->productKey, sizeof(path) - 1);
|
||||
strncat(path, ctl_item->deviceName, sizeof(path) - strlen(path) - 1);
|
||||
CoAPPathMD5_sum(path, strlen(path), session->pk_dn, PK_DN_CHECKSUM_LEN);
|
||||
COAP_INFO("pk:%s, dn:%s, checksum:%s", devKey.pk, devKey.dn, session->pk_dn);
|
||||
memcpy(&session->addr, addr, sizeof(NetworkAddr));
|
||||
gen_random_key((unsigned char *)session->randomKey, RANDOMKEY_LEN);
|
||||
|
||||
struct list_head *ctl_head = get_ctl_session_list(ctx);
|
||||
list_add_tail(&session->lst, ctl_head);
|
||||
}
|
||||
|
||||
char sign[64] = {0};
|
||||
int sign_len = sizeof(sign);
|
||||
utils_hmac_sha1_base64(session->randomKey, RANDOMKEY_LEN, ctl_item->accessToken,
|
||||
strlen(ctl_item->accessToken), sign, &sign_len);
|
||||
COAP_INFO("calc randomKey:%s,token:%s,sign:%.*s", session->randomKey, ctl_item->accessToken, sign_len, sign);
|
||||
|
||||
char payloadbuf[512];
|
||||
sprintf(payloadbuf, auth_payload_format, ++dev->seq, ctl_item->productKey, ctl_item->deviceName, session->randomKey,
|
||||
sign, ctl_item->accessKey);
|
||||
COAP_INFO("payload:%s", payloadbuf);
|
||||
|
||||
CoAPLenString payload;
|
||||
payload.data = (unsigned char *)payloadbuf;
|
||||
payload.len = strlen(payloadbuf);
|
||||
CoAPMessage message;
|
||||
alcs_msg_init(ctx, &message, COAP_MSG_CODE_GET, COAP_MESSAGE_TYPE_CON, 0, &payload, NULL);
|
||||
|
||||
char path[120];
|
||||
sprintf(path, "/dev/%s/%s/core/service/auth", ctl_item->productKey, ctl_item->deviceName);
|
||||
CoAPServerPath_2_option(path, &message);
|
||||
|
||||
AuthParam *authParam = (AuthParam *) coap_malloc(sizeof(AuthParam));
|
||||
authParam->handler = handler;
|
||||
authParam->user_data = user_data;
|
||||
authParam->productKey = (char *) coap_malloc(strlen(ctl_item->productKey) + 1);
|
||||
strcpy(authParam->productKey, ctl_item->productKey);
|
||||
authParam->deviceName = (char *) coap_malloc(strlen(ctl_item->deviceName) + 1);
|
||||
strcpy(authParam->deviceName, ctl_item->deviceName);
|
||||
authParam->accessToken = (char *) coap_malloc(strlen(ctl_item->accessToken) + 1);
|
||||
strcpy(authParam->accessToken, ctl_item->accessToken);
|
||||
message.user = authParam;
|
||||
message.handler = auth_cb;
|
||||
|
||||
ret = CoAPMessage_send(ctx, addr, &message);
|
||||
CoAPMessage_destory(&message);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void alcs_auth_has_key(CoAPContext *ctx, NetworkAddr *addr, AuthParam *auth_param)
|
||||
{
|
||||
ctl_key_item item;
|
||||
item.accessKey = auth_param->accessKey;
|
||||
item.deviceName = auth_param->deviceName;
|
||||
item.productKey = auth_param->productKey;
|
||||
item.accessToken = auth_param->accessToken;/* (char*) coap_malloc (strlen(auth_param->accessToken) + 1); */
|
||||
/* strcpy (item.accessToken, auth_param->accessToken); */
|
||||
do_auth(ctx, addr, &item, auth_param->user_data, auth_param->handler);
|
||||
}
|
||||
|
||||
void alcs_auth_nego_key(CoAPContext *ctx, AlcsDeviceKey *devKey, AuthHandler handler)
|
||||
{
|
||||
COAP_DEBUG("alcs_auth_nego_key");
|
||||
|
||||
device_auth_list *dev = get_device(ctx);
|
||||
if (!dev) {
|
||||
COAP_INFO("no device!");
|
||||
return;
|
||||
}
|
||||
|
||||
char accesskeys[1024] = {0};
|
||||
if (!fillAccessKey(ctx, accesskeys)) {
|
||||
COAP_INFO("no ctl key!");
|
||||
return;
|
||||
}
|
||||
COAP_INFO("accesskeys:%s", accesskeys);
|
||||
|
||||
const char *method = "core/service/auth/select";
|
||||
char payloadbuf[1024];
|
||||
sprintf(payloadbuf, payload_format, method, ++dev->seq, devKey->pk, devKey->dn, accesskeys);
|
||||
|
||||
CoAPLenString payload;
|
||||
payload.data = (unsigned char *)payloadbuf;
|
||||
payload.len = strlen(payloadbuf);
|
||||
CoAPMessage message;
|
||||
alcs_msg_init(ctx, &message, COAP_MSG_CODE_GET, COAP_MESSAGE_TYPE_CON, 0, &payload, NULL);
|
||||
|
||||
char path[120];
|
||||
sprintf(path, "/dev/%s/%s/core/service/auth/select", devKey->pk, devKey->dn);
|
||||
CoAPServerPath_2_option(path, &message);
|
||||
|
||||
AuthParam *authParam = (AuthParam *) coap_malloc(sizeof(AuthParam));
|
||||
memset(authParam, 0, sizeof(AuthParam));
|
||||
|
||||
authParam->handler = handler;
|
||||
authParam->productKey = (char *) coap_malloc(strlen(devKey->pk) + 1);
|
||||
strcpy(authParam->productKey, devKey->pk);
|
||||
authParam->deviceName = (char *) coap_malloc(strlen(devKey->dn) + 1);
|
||||
strcpy(authParam->deviceName, devKey->dn);
|
||||
|
||||
message.user = authParam;
|
||||
message.handler = nego_cb;
|
||||
CoAPMessage_send(ctx, &devKey->addr, &message);
|
||||
CoAPMessage_destory(&message);
|
||||
}
|
||||
|
||||
int alcs_add_client_key(CoAPContext *ctx, const char *accesskey, const char *accesstoken, const char *productKey,
|
||||
const char *deviceName)
|
||||
{
|
||||
auth_list *lst = get_list(ctx);
|
||||
if (!lst || lst->ctl_count >= KEY_MAXCOUNT) {
|
||||
return COAP_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
ctl_key_item *item = (ctl_key_item *) coap_malloc(sizeof(ctl_key_item));
|
||||
if (!item) {
|
||||
return COAP_ERROR_MALLOC;
|
||||
}
|
||||
item->accessKey = (char *) coap_malloc(strlen(accesskey) + 1);
|
||||
item->accessToken = (char *) coap_malloc(strlen(accesstoken) + 1);
|
||||
|
||||
if (!item->accessKey || !item->accessToken) {
|
||||
coap_free(item);
|
||||
return COAP_ERROR_MALLOC;
|
||||
}
|
||||
strcpy(item->accessKey, accesskey);
|
||||
strcpy(item->accessToken, accesstoken);
|
||||
|
||||
if (deviceName) {
|
||||
item->deviceName = (char *) coap_malloc(strlen(deviceName) + 1);
|
||||
strcpy(item->deviceName, deviceName);
|
||||
}
|
||||
|
||||
HAL_MutexLock(lst->list_mutex);
|
||||
list_add_tail(&item->lst, &lst->lst_ctl);
|
||||
++lst->ctl_count;
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int alcs_remove_client_key(CoAPContext *ctx, const char *key, char isfullkey)
|
||||
{
|
||||
auth_list *lst = get_list(ctx);
|
||||
if (!lst) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
|
||||
ctl_key_item *node = NULL, *next = NULL;
|
||||
HAL_MutexLock(lst->list_mutex);
|
||||
|
||||
list_for_each_entry_safe(node, next, &lst->lst_ctl, lst, ctl_key_item) {
|
||||
if (match_key(node->accessKey, key)) {
|
||||
coap_free(node->accessKey);
|
||||
coap_free(node->accessToken);
|
||||
list_del(&node->lst);
|
||||
coap_free(node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
bool alcs_device_online(CoAPContext *ctx, AlcsDeviceKey *devKey)
|
||||
{
|
||||
session_item *session = get_ctl_session(ctx, devKey);
|
||||
return session && session->sessionId ? 1 : 0;
|
||||
}
|
||||
|
||||
void heart_beat_cb(CoAPContext *ctx, CoAPReqResult result, void *userdata, NetworkAddr *remote, CoAPMessage *message)
|
||||
{
|
||||
COAP_DEBUG("heart_beat_cb, message addr:%p, networkaddr:%p!", message, remote);
|
||||
|
||||
struct list_head *ctl_head = get_ctl_session_list(ctx);
|
||||
if (!ctl_head || list_empty(ctl_head)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (result == COAP_RECV_RESP_TIMEOUT) {
|
||||
COAP_ERR("heart beat timeout");
|
||||
session_item *node = NULL, *next = NULL;
|
||||
list_for_each_entry_safe(node, next, ctl_head, lst, session_item) {
|
||||
if (node->sessionId && is_networkadd_same(&node->addr, remote)) {
|
||||
remove_session(ctx, node);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
session_item *node = NULL, *next = NULL;
|
||||
list_for_each_entry_safe(node, next, ctl_head, lst, session_item) {
|
||||
|
||||
if (node->sessionId && is_networkadd_same(&node->addr, remote)) {
|
||||
unsigned int sessionId = 0;
|
||||
CoAPUintOption_get(message, COAP_OPTION_SESSIONID, &sessionId);
|
||||
|
||||
if (node->sessionId != sessionId) {
|
||||
COAP_INFO("receive stale heart beat response");
|
||||
remove_session(ctx, node);
|
||||
} else {
|
||||
node->heart_time = HAL_UptimeMs();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void on_client_auth_timer(CoAPContext *ctx)
|
||||
{
|
||||
struct list_head *ctl_head = get_ctl_session_list(ctx);
|
||||
if (!ctl_head || list_empty(ctl_head)) {
|
||||
return;
|
||||
}
|
||||
COAP_DEBUG("on_client_auth_timer:%d", (int)HAL_UptimeMs());
|
||||
|
||||
device_auth_list *dev = get_device(ctx);
|
||||
char payloadbuf[64];
|
||||
sprintf(payloadbuf, "{\"id\":%d,\"version\":\"1.0\",\"params\":{\"delayTime\":%d}}", ++dev->seq, 5000);
|
||||
|
||||
CoAPLenString payload;
|
||||
payload.data = (unsigned char *)payloadbuf;
|
||||
payload.len = strlen(payloadbuf);
|
||||
int tick = HAL_UptimeMs();
|
||||
|
||||
session_item *node = NULL, *next = NULL;
|
||||
list_for_each_entry_safe(node, next, ctl_head, lst, session_item) {
|
||||
if (!node->sessionId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (node->heart_time + node->interval > tick) {
|
||||
CoAPMessage message;
|
||||
alcs_msg_init(ctx, &message, COAP_MSG_CODE_GET, COAP_MESSAGE_TYPE_CON, 0, &payload, NULL);
|
||||
CoAPServerPath_2_option("/dev/core/service/heartBeat", &message);
|
||||
message.handler = heart_beat_cb;
|
||||
CoAPMessage_send(ctx, &node->addr, &message);
|
||||
COAP_DEBUG("send heartbeat to :%s", node->addr.addr);
|
||||
CoAPMessage_destory(&message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -0,0 +1,405 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "alcs_internal.h"
|
||||
#include "alcs_coap.h"
|
||||
#include "CoAPPlatform.h"
|
||||
#include "CoAPResource.h"
|
||||
#include "alcs_api_internal.h"
|
||||
#include "CoAPServer.h"
|
||||
|
||||
#define MAX_PATH_CHECKSUM_LEN (5)
|
||||
typedef struct {
|
||||
char path[MAX_PATH_CHECKSUM_LEN];
|
||||
CoAPRecvMsgHandler cb;
|
||||
struct list_head lst;
|
||||
} resource_cb_item;
|
||||
|
||||
ALIYUN_LIST_HEAD(resource_cb_head);
|
||||
|
||||
static uint32_t tokenSeed = 0;
|
||||
uint32_t getToken()
|
||||
{
|
||||
if (tokenSeed == 0) {
|
||||
HAL_Srandom((uint32_t)HAL_UptimeMs());
|
||||
tokenSeed = HAL_Random(0xffffffff);
|
||||
} else {
|
||||
++tokenSeed;
|
||||
}
|
||||
|
||||
return tokenSeed;
|
||||
}
|
||||
|
||||
void alcs_msg_init(CoAPContext *ctx, CoAPMessage *message, int code, unsigned char type,
|
||||
int keep, CoAPLenString *payload, void *userdata)
|
||||
{
|
||||
uint32_t token = 0;
|
||||
|
||||
CoAPMessage_init(message);
|
||||
message->header.code = code;
|
||||
message->header.type = type;
|
||||
message->user = userdata;
|
||||
message->payload = payload->data;
|
||||
message->payloadlen = payload->len;
|
||||
message->keep = keep;
|
||||
|
||||
message->header.msgid = CoAPMessageId_gen(ctx);
|
||||
message->header.tokenlen = 4;
|
||||
token = getToken();
|
||||
memcpy(&message->token, &token, 4);
|
||||
}
|
||||
|
||||
void alcs_msg_deinit(CoAPMessage *message)
|
||||
{
|
||||
CoAPMessage_destory(message);
|
||||
}
|
||||
|
||||
static int do_sendmsg(CoAPContext *context, NetworkAddr *addr, CoAPMessage *message, char observe, unsigned short msgid,
|
||||
CoAPLenString *token)
|
||||
{
|
||||
int ret = COAP_SUCCESS;
|
||||
if (!context || !addr || !message) {
|
||||
return COAP_ERROR_NULL;
|
||||
}
|
||||
|
||||
if (msgid == 0) {
|
||||
message->header.msgid = CoAPMessageId_gen(context);
|
||||
} else {
|
||||
message->header.msgid = msgid;
|
||||
}
|
||||
|
||||
if (observe == 0) {
|
||||
CoAPUintOption_add(message, COAP_OPTION_OBSERVE, observe);
|
||||
}
|
||||
|
||||
if (token) {
|
||||
message->header.tokenlen = token->len;
|
||||
memcpy(&message->token, token->data, token->len);
|
||||
}
|
||||
|
||||
ret = CoAPMessage_send(context, addr, message);
|
||||
CoAPMessage_destory(message);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int alcs_sendmsg(CoAPContext *context, NetworkAddr *addr, CoAPMessage *message, char observe,
|
||||
CoAPSendMsgHandler handler)
|
||||
{
|
||||
message->handler = handler;
|
||||
return do_sendmsg(context, addr, message, observe, message->header.msgid, NULL);
|
||||
}
|
||||
|
||||
int alcs_sendrsp(CoAPContext *context, NetworkAddr *addr, CoAPMessage *message, char observe, unsigned short msgid,
|
||||
CoAPLenString *token)
|
||||
{
|
||||
return do_sendmsg(context, addr, message, observe, msgid, token);
|
||||
}
|
||||
|
||||
/* observe */
|
||||
int alcs_observe_notify(CoAPContext *context, const char *path, CoAPLenString *payload)
|
||||
{
|
||||
int needAuth = 0;
|
||||
#ifdef USE_ALCS_SECURE
|
||||
needAuth = alcs_resource_need_auth(context, path);
|
||||
#endif
|
||||
COAP_DEBUG("payload:%s", payload->data);
|
||||
/* HEXDUMP_DEBUG(payload->data, payload->len); */
|
||||
return CoAPObsServer_notify(context, path, payload->data, payload->len,
|
||||
needAuth ? &observe_data_encrypt : NULL);
|
||||
}
|
||||
|
||||
static void send_err_rsp(CoAPContext *ctx, NetworkAddr *addr, int code, CoAPMessage *fromMsg)
|
||||
{
|
||||
CoAPMessage sendMsg;
|
||||
CoAPLenString payload = {0};
|
||||
CoAPLenString token = {fromMsg->header.tokenlen, fromMsg->token};
|
||||
|
||||
alcs_msg_init(ctx, &sendMsg, code, COAP_MESSAGE_TYPE_ACK, 0, &payload, NULL);
|
||||
alcs_sendrsp(ctx, addr, &sendMsg, 1, fromMsg->header.msgid, &token);
|
||||
}
|
||||
|
||||
static void recv_msg_handler(CoAPContext *context, const char *path, NetworkAddr *remote, CoAPMessage *message)
|
||||
{
|
||||
unsigned int obsVal;
|
||||
resource_cb_item *node = NULL, *next = NULL;
|
||||
char path_calc[MAX_PATH_CHECKSUM_LEN] = {0};
|
||||
CoAPPathMD5_sum(path, strlen(path), path_calc, MAX_PATH_CHECKSUM_LEN);
|
||||
|
||||
list_for_each_entry_safe(node, next, &resource_cb_head, lst, resource_cb_item) {
|
||||
if (0 == memcmp(path_calc, node->path, MAX_PATH_CHECKSUM_LEN)) {
|
||||
if (CoAPUintOption_get(message, COAP_OPTION_OBSERVE, &obsVal) == COAP_SUCCESS) {
|
||||
if (obsVal == 0) {
|
||||
CoAPObsServer_add(context, path, remote, message);
|
||||
}
|
||||
}
|
||||
COAP_INFO("recv_msg_handler call callback");
|
||||
node->cb(context, path, remote, message);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
COAP_ERR("receive unknown request, path:%s", path);
|
||||
send_err_rsp(context, remote, COAP_MSG_CODE_401_UNAUTHORIZED, message);
|
||||
}
|
||||
|
||||
/* resource */
|
||||
int alcs_resource_register(CoAPContext *context, const char *pk, const char *dn, const char *path,
|
||||
unsigned short permission,
|
||||
unsigned int ctype, unsigned int maxage, char needAuth, CoAPRecvMsgHandler callback)
|
||||
{
|
||||
COAP_DEBUG("alcs_resource_register, ctx:%p", context);
|
||||
COAP_DEBUG("ALCS Resource Register: %s", path);
|
||||
|
||||
if (!needAuth) {
|
||||
resource_cb_item *item = (resource_cb_item *)coap_malloc(sizeof(resource_cb_item));
|
||||
CoAPPathMD5_sum(path, strlen(path), item->path, MAX_PATH_CHECKSUM_LEN);
|
||||
item->cb = callback;
|
||||
list_add_tail(&item->lst, &resource_cb_head);
|
||||
|
||||
return CoAPResource_register(context, path, permission, ctype, maxage, &recv_msg_handler);
|
||||
} else {
|
||||
#ifdef USE_ALCS_SECURE
|
||||
return alcs_resource_register_secure(context, pk, dn, path, permission, ctype, maxage, callback);
|
||||
#else
|
||||
return -1;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
int alcs_resource_need_auth(CoAPContext *context, const char *path)
|
||||
{
|
||||
resource_cb_item *node = NULL, *next = NULL;
|
||||
char path_calc[MAX_PATH_CHECKSUM_LEN] = {0};
|
||||
CoAPPathMD5_sum(path, strlen(path), path_calc, MAX_PATH_CHECKSUM_LEN);
|
||||
|
||||
list_for_each_entry_safe(node, next, &resource_cb_head, lst, resource_cb_item) {
|
||||
if (memcmp(path_calc, node->path, MAX_PATH_CHECKSUM_LEN) == 0) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef struct {
|
||||
CoAPContext *ctx;
|
||||
char loop;
|
||||
bool inited;
|
||||
struct list_head lst;
|
||||
} ALCSContext;
|
||||
|
||||
#ifdef SUPPORT_MULTI_DEVICES
|
||||
ALIYUN_LIST_HEAD(context_head);
|
||||
|
||||
ALCSContext *get_context(CoAPContext *ctx)
|
||||
{
|
||||
ALCSContext *node = NULL, *next = NULL;
|
||||
|
||||
list_for_each_entry_safe(node, next, &context_head, lst, ALCSContext) {
|
||||
if (node->ctx == ctx) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
CoAPContext *alcs_context_create(CoAPInitParam *param)
|
||||
{
|
||||
ALCSContext *alcs_ctx = (ALCSContext *) coap_malloc(sizeof(ALCSContext));
|
||||
alcs_ctx->ctx = CoAPContext_create(param);
|
||||
COAP_INFO("CoAPContext_create return :%p", alcs_ctx->ctx);
|
||||
alcs_ctx->loop = 0;
|
||||
alcs_ctx->inited = 0;
|
||||
|
||||
list_add_tail(&alcs_ctx->lst, &context_head);
|
||||
return alcs_ctx->ctx;
|
||||
}
|
||||
|
||||
void alcs_context_free(CoAPContext *ctx)
|
||||
{
|
||||
ALCSContext *alcs_ctx = get_context(ctx);
|
||||
if (alcs_ctx) {
|
||||
CoAPContext_free(alcs_ctx->ctx);
|
||||
coap_free(alcs_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
ALCSContext *g_alcs_ctx = NULL;
|
||||
ALCSContext *get_context(CoAPContext *ctx)
|
||||
{
|
||||
return g_alcs_ctx;
|
||||
}
|
||||
|
||||
CoAPContext *alcs_context_init(CoAPInitParam *param)
|
||||
{
|
||||
if (g_alcs_ctx) {
|
||||
return g_alcs_ctx->ctx;
|
||||
}
|
||||
|
||||
g_alcs_ctx = (ALCSContext *)coap_malloc(sizeof(ALCSContext));
|
||||
if (g_alcs_ctx) {
|
||||
g_alcs_ctx->loop = 0;
|
||||
g_alcs_ctx->inited = 0;
|
||||
g_alcs_ctx->ctx = CoAPServer_init();
|
||||
COAP_INFO("CoAPServer_init return :%p", g_alcs_ctx->ctx);
|
||||
if (!g_alcs_ctx->ctx) {
|
||||
coap_free(g_alcs_ctx);
|
||||
g_alcs_ctx = NULL;
|
||||
return NULL;
|
||||
}
|
||||
return g_alcs_ctx->ctx;
|
||||
} else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void alcs_context_deinit()
|
||||
{
|
||||
if (g_alcs_ctx) {
|
||||
if (g_alcs_ctx->ctx) {
|
||||
CoAPServer_deinit(g_alcs_ctx->ctx);
|
||||
}
|
||||
coap_free(g_alcs_ctx);
|
||||
g_alcs_ctx = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CoAPContext *alcs_get_context()
|
||||
{
|
||||
return g_alcs_ctx ? g_alcs_ctx->ctx : NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
extern void on_auth_timer(void *arg);
|
||||
|
||||
void *thread_routine(void *arg)
|
||||
{
|
||||
ALCSContext *ctx = (ALCSContext *)arg;
|
||||
ctx->loop = 1;
|
||||
|
||||
COAP_INFO("thread_routine");
|
||||
|
||||
while (ctx->loop) {
|
||||
CoAPMessage_cycle(ctx->ctx);
|
||||
#ifdef USE_ALCS_SECURE
|
||||
on_auth_timer(ctx->ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void alcs_start_loop(CoAPContext *ctx, int newThread)
|
||||
{
|
||||
#ifdef SUPPORT_MULTI_DEVICES
|
||||
void *handle = NULL;
|
||||
ALCSContext *alcs_ctx = get_context(ctx);
|
||||
if (alcs_ctx && !alcs_ctx->loop) {
|
||||
int stack_used = 0;
|
||||
if (!newThread || 0 != HAL_ThreadCreate(&handle, thread_routine, alcs_ctx, NULL, &stack_used)) {
|
||||
thread_routine(alcs_ctx);
|
||||
}
|
||||
}
|
||||
#else
|
||||
|
||||
#ifdef USE_ALCS_SECURE
|
||||
CoAPServer_add_timer(on_auth_timer);
|
||||
#endif
|
||||
CoAPServer_loop(ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
void alcs_stop_loop(CoAPContext *ctx)
|
||||
{
|
||||
#ifdef SUPPORT_MULTI_DEVICES
|
||||
ALCSContext *alcs_ctx = get_context(ctx);
|
||||
if (alcs_ctx) {
|
||||
alcs_ctx->loop = 0;
|
||||
}
|
||||
#else
|
||||
CoAPServer_deinit(ctx);
|
||||
#endif
|
||||
}
|
||||
|
||||
void alcs_init()
|
||||
{
|
||||
#ifdef SUPPORT_MULTI_DEVICES
|
||||
INIT_LIST_HEAD(&context_head);
|
||||
#endif
|
||||
INIT_LIST_HEAD(&resource_cb_head);
|
||||
}
|
||||
|
||||
void alcs_deinit()
|
||||
{
|
||||
resource_cb_item *del_item = NULL;
|
||||
|
||||
list_for_each_entry(del_item, &resource_cb_head, lst, resource_cb_item) {
|
||||
list_del(&del_item->lst);
|
||||
coap_free(del_item);
|
||||
del_item = list_entry(&resource_cb_head, resource_cb_item, lst);
|
||||
}
|
||||
}
|
||||
|
||||
static int path_2_option(const char *uri, CoAPMessage *message)
|
||||
{
|
||||
const char *ptr = NULL;
|
||||
const char *pstr = NULL;
|
||||
char path[COAP_MSG_MAX_PATH_LEN] = {0};
|
||||
|
||||
if (256 < strlen(uri)) {
|
||||
COAP_ERR("The uri length is too loog,len = %d", (int)strlen(uri));
|
||||
return COAP_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
COAP_DEBUG("The uri is %s", uri);
|
||||
ptr = pstr = uri;
|
||||
while ('\0' != *ptr) {
|
||||
if ('/' == *ptr) {
|
||||
if (ptr != pstr) {
|
||||
memset(path, 0x00, sizeof(path));
|
||||
strncpy(path, pstr, ptr - pstr);
|
||||
COAP_DEBUG("path: %s,len=%d", path, (int)(ptr - pstr));
|
||||
CoAPStrOption_add(message, COAP_OPTION_URI_PATH,
|
||||
(unsigned char *)path, (int)strlen(path));
|
||||
}
|
||||
pstr = ptr + 1;
|
||||
|
||||
}
|
||||
if ('\0' == *(ptr + 1) && '\0' != *pstr) {
|
||||
memset(path, 0x00, sizeof(path));
|
||||
strncpy(path, pstr, sizeof(path) - 1);
|
||||
COAP_DEBUG("path: %s,len=%d", path, (int)strlen(path));
|
||||
CoAPStrOption_add(message, COAP_OPTION_URI_PATH,
|
||||
(unsigned char *)path, (int)strlen(path));
|
||||
}
|
||||
ptr ++;
|
||||
}
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int alcs_msg_setAddr(CoAPMessage *message, const char *path, const char *query)
|
||||
{
|
||||
int rt = 0;
|
||||
|
||||
if (NULL == path || NULL == message) {
|
||||
COAP_ERR("Invalid paramter p_path %p, p_message %p", path, message);
|
||||
return COAP_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (255 < strlen(path)) {
|
||||
COAP_ERR("The uri length is too loog,len = %d", (int)strlen(path));
|
||||
return COAP_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
|
||||
rt = path_2_option(path, message);
|
||||
if (query) {
|
||||
CoAPStrOption_add(message, COAP_OPTION_URI_QUERY, (unsigned char *)query, strlen(query));
|
||||
}
|
||||
|
||||
return rt;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "CoAPExport.h"
|
||||
|
||||
#ifndef __COAP_ALCS_H__
|
||||
#define __COAP_ALCS_H__
|
||||
|
||||
#define OPTSESESSION 62
|
||||
#define ALCSPORT 5683
|
||||
#define ALCSPORT_SECURE 5684
|
||||
#define MULTICAST_ADDRESS "224.0.1.187"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifndef bool
|
||||
#define bool char
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
NetworkAddr addr;
|
||||
char *path;
|
||||
char *query;
|
||||
} ResourceAddr;
|
||||
|
||||
/* 会自动生成msgid & token */
|
||||
void alcs_msg_init(CoAPContext *ctx, CoAPMessage *message, int code, unsigned char type, int keep,
|
||||
CoAPLenString *payload, void *userdata);
|
||||
void alcs_msg_deinit(CoAPMessage *message);
|
||||
int alcs_msg_setAddr(CoAPMessage *message, const char *path, const char *query);
|
||||
|
||||
/* observe: 0 register */
|
||||
/* observer:1 deregister */
|
||||
/* observer:other 没意义 */
|
||||
int alcs_sendmsg(CoAPContext *ctx, NetworkAddr *addr, CoAPMessage *message, char observe, CoAPSendMsgHandler handler);
|
||||
|
||||
/* msgid & token从接收到CoAPMessage获取, 若发送的是事件通知,msgid设置为0 */
|
||||
/* observe: 0: accept register */
|
||||
/* observe: other: 没意义 */
|
||||
int alcs_sendrsp(CoAPContext *ctx, NetworkAddr *addr, CoAPMessage *message, char observe, unsigned short msgid,
|
||||
CoAPLenString *token);
|
||||
|
||||
void alcs_start_loop(CoAPContext *ctx, int newThread);
|
||||
void alcs_stop_loop(CoAPContext *ctx);
|
||||
|
||||
/* 服务端接口
|
||||
*
|
||||
*/
|
||||
/* observe */
|
||||
int alcs_observe_notify(CoAPContext *context, const char *path, CoAPLenString *payload);
|
||||
|
||||
/* resource */
|
||||
int alcs_resource_register(CoAPContext *context, const char *pk, const char *dn, const char *path,
|
||||
unsigned short permission,
|
||||
unsigned int ctype, unsigned int maxage, char needAuth, CoAPRecvMsgHandler callback);
|
||||
|
||||
int alcs_resource_need_auth(CoAPContext *context, const char *path);
|
||||
|
||||
|
||||
/* init */
|
||||
void alcs_init();
|
||||
void alcs_deinit();
|
||||
|
||||
#ifdef SUPPORT_MULTI_DEVICES
|
||||
CoAPContext *alcs_context_create(CoAPInitParam *param);
|
||||
void alcs_context_free(CoAPContext *ctx);
|
||||
#else
|
||||
CoAPContext *alcs_context_init(CoAPInitParam *param);
|
||||
void alcs_context_deinit();
|
||||
CoAPContext *alcs_get_context();
|
||||
#endif
|
||||
|
||||
/* option */
|
||||
extern int CoAPUintOption_add(CoAPMessage *message, unsigned short optnum, unsigned int data);
|
||||
extern int CoAPUintOption_get(CoAPMessage *message, unsigned short optnum, unsigned int *data);
|
||||
extern int CoAPStrOption_add(CoAPMessage *message, unsigned short optnum,
|
||||
unsigned char *data, unsigned short datalen);
|
||||
extern int CoAPMessage_cancel(CoAPContext *context, CoAPMessage *message);
|
||||
|
||||
uint32_t getToken();
|
||||
|
||||
/* */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
#ifndef _ALCS_INTERNAL_H_
|
||||
#define _ALCS_INTERNAL_H_
|
||||
|
||||
#include "infra_config.h"
|
||||
#include "infra_types.h"
|
||||
#include "infra_defs.h"
|
||||
#include "infra_md5.h"
|
||||
#include "infra_sha1.h"
|
||||
#include "infra_json_parser.h"
|
||||
#include "alcs_base64.h"
|
||||
#include "dm_wrapper.h"
|
||||
|
||||
#ifdef INFRA_MEM_STATS
|
||||
#include "infra_mem_stats.h"
|
||||
#define ALCS_malloc(size) LITE_malloc(size, MEM_MAGIC, "alcs")
|
||||
#define ALCS_ADAPTER_malloc(size) LITE_malloc(size, MEM_MAGIC, "alcs_adapter")
|
||||
#define ALCS_free(ptr) LITE_free(ptr)
|
||||
#else
|
||||
#define ALCS_malloc(size) HAL_Malloc(size)
|
||||
#define ALCS_ADAPTER_malloc(size) HAL_Malloc(size)
|
||||
#define ALCS_free(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,306 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "alcs_internal.h"
|
||||
#include "alcs_api_internal.h"
|
||||
#include "CoAPExport.h"
|
||||
#include "alcs_api.h"
|
||||
#include "alcs_mqtt.h"
|
||||
#include "alcs_adapter.h"
|
||||
#include "CoAPPlatform.h"
|
||||
#include "CoAPExport.h"
|
||||
#include "iotx_alcs.h"
|
||||
|
||||
char *DEFAULT_AC = "Xtau@iot";
|
||||
char *DEFAULT_AS = "Yx3DdsyetbSezlvc";
|
||||
void *g_adapter_handle = NULL;
|
||||
void *g_coap_handle = NULL;
|
||||
|
||||
typedef enum {
|
||||
ALCS_LOCALSETUP_SUCCESS,
|
||||
ALCS_LOCALSETUP_ERROR
|
||||
} localsetup_status;
|
||||
|
||||
static localsetup_status __alcs_localsetup_kv_set(const char *key, const void *val, int len, int sync)
|
||||
{
|
||||
if (HAL_Kv_Set(key, val, len, sync) != 0) {
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
|
||||
COAP_INFO("ALCS KV Set, Key: %s, Val: %s, Len: %d", key, (char *)val, len);
|
||||
return ALCS_LOCALSETUP_SUCCESS;
|
||||
}
|
||||
|
||||
static localsetup_status __alcs_localsetup_kv_get(const char *key, void *buffer, int *buffer_len)
|
||||
{
|
||||
int rc = -1;
|
||||
|
||||
if ((rc = HAL_Kv_Get(key, buffer, buffer_len)) != 0) {
|
||||
COAP_WRN("HAL_Kv_Get('%s') = %d (!= 0), return %d", key, rc, ALCS_LOCALSETUP_ERROR);
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
|
||||
COAP_INFO("ALCS KV Get, Key: %s", key);
|
||||
|
||||
return ALCS_LOCALSETUP_SUCCESS;
|
||||
}
|
||||
|
||||
static localsetup_status __alcs_localsetup_kv_del(const char *key)
|
||||
{
|
||||
if (HAL_Kv_Del(key) != 0) {
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
|
||||
COAP_INFO("ALCS KV Del, Key: %s", key);
|
||||
|
||||
return ALCS_LOCALSETUP_SUCCESS;
|
||||
}
|
||||
|
||||
static localsetup_status __fill_key(const char *pk, uint16_t pk_len,
|
||||
const char *dn, uint16_t dn_len, char key_md5_hexstr[33])
|
||||
{
|
||||
uint8_t key_md5[16] = {0};
|
||||
char key_source[IOTX_PRODUCT_KEY_LEN + 1 + IOTX_DEVICE_NAME_LEN + 1 + 3];
|
||||
|
||||
if (pk == NULL || pk_len >= IOTX_PRODUCT_KEY_LEN + 1 ||
|
||||
dn == NULL || dn_len >= IOTX_DEVICE_NAME_LEN + 1) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
|
||||
/* Calculate Key */
|
||||
HAL_Snprintf(key_source, sizeof(key_source), "%.*s%.*s.l", pk_len, pk, dn_len, dn);
|
||||
|
||||
utils_md5((const unsigned char *)key_source, strlen(key_source), key_md5);
|
||||
alcs_utils_md5_hexstr(key_md5, (unsigned char *)key_md5_hexstr);
|
||||
return ALCS_LOCALSETUP_SUCCESS;
|
||||
}
|
||||
|
||||
static localsetup_status __alcs_localsetup_ac_as_save(const char *pk, uint16_t pk_len,
|
||||
const char *dn, uint16_t dn_len,
|
||||
const char *prefix, uint16_t prefix_len,
|
||||
const char *secret, uint16_t secret_len)
|
||||
{
|
||||
char key_md5_hexstr[33] = {0};
|
||||
char *value = NULL;
|
||||
int rt;
|
||||
if (prefix == NULL || secret == NULL) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
|
||||
rt = __fill_key(pk, pk_len, dn, dn_len, key_md5_hexstr);
|
||||
if (rt != ALCS_LOCALSETUP_SUCCESS) {
|
||||
return rt;
|
||||
}
|
||||
|
||||
/* Calculate Value */
|
||||
value = ALCS_ADAPTER_malloc(prefix_len + secret_len + 3);
|
||||
if (value == NULL) {
|
||||
COAP_ERR("No Enough Memory");
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
memset(value, 0, prefix_len + secret_len + 3);
|
||||
|
||||
value[0] = prefix_len;
|
||||
value[1] = secret_len;
|
||||
HAL_Snprintf(&value[2], prefix_len + secret_len + 1, "%.*s%.*s", prefix_len, prefix, secret_len, secret);
|
||||
|
||||
if (ALCS_LOCALSETUP_SUCCESS != __alcs_localsetup_kv_set(key_md5_hexstr, value, prefix_len + secret_len + 3, 1)) {
|
||||
COAP_WRN("ALCS KV Set Prefix And Secret Fail");
|
||||
ALCS_free(value);
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
|
||||
ALCS_free(value);
|
||||
return ALCS_LOCALSETUP_SUCCESS;
|
||||
}
|
||||
|
||||
localsetup_status alcs_localsetup_ac_as_load(const char *pk, uint16_t pk_len,
|
||||
const char *dn, uint16_t dn_len,
|
||||
char *prefix, int prefix_len, char *secret, int secret_len)
|
||||
{
|
||||
char key_md5_hexstr[33] = {0};
|
||||
char value[128] = {0};
|
||||
int value_len = sizeof(value);
|
||||
|
||||
int rt;
|
||||
if (prefix == NULL || secret == NULL) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
|
||||
rt = __fill_key(pk, pk_len, dn, dn_len, key_md5_hexstr);
|
||||
if (rt != ALCS_LOCALSETUP_SUCCESS) {
|
||||
return rt;
|
||||
}
|
||||
|
||||
/* Get Value */
|
||||
if (ALCS_LOCALSETUP_SUCCESS != __alcs_localsetup_kv_get(key_md5_hexstr, value, &value_len)) {
|
||||
COAP_WRN("ALCS KV Get local Prefix And Secret Fail");
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
|
||||
if (value[0] >= prefix_len || value[1] >= secret_len) {
|
||||
COAP_ERR("insuffient buffer!");
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
|
||||
memset(prefix, 0, prefix_len);
|
||||
memcpy(prefix, &value[2], value[0]);
|
||||
memset(secret, 0, secret_len);
|
||||
memcpy(secret, &value[2 + value[0]], value[1]);
|
||||
return ALCS_LOCALSETUP_SUCCESS;
|
||||
}
|
||||
|
||||
static localsetup_status __alcs_localsetup_ac_as_del(const char *pk, uint16_t pk_len,
|
||||
const char *dn, uint16_t dn_len)
|
||||
{
|
||||
char key_md5_hexstr[33] = {0};
|
||||
int rt;
|
||||
rt = __fill_key(pk, pk_len, dn, dn_len, key_md5_hexstr);
|
||||
if (rt != ALCS_LOCALSETUP_SUCCESS) {
|
||||
return rt;
|
||||
}
|
||||
|
||||
if (ALCS_LOCALSETUP_SUCCESS != __alcs_localsetup_kv_del(key_md5_hexstr)) {
|
||||
COAP_ERR("ALCS KV Get local Prefix And Secret Fail");
|
||||
return ALCS_LOCALSETUP_ERROR;
|
||||
}
|
||||
|
||||
return ALCS_LOCALSETUP_SUCCESS;
|
||||
}
|
||||
|
||||
static void alcs_service_cb_setup(CoAPContext *context, const char *paths, NetworkAddr *remote, CoAPMessage *message)
|
||||
{
|
||||
char payload[128];
|
||||
char *id = NULL, *p;
|
||||
int idlen = 0, len, aclen, aslen, pklen, dnlen;
|
||||
char *ac = NULL, *as = NULL, *pk = NULL, *dn = dn;
|
||||
bool success = 0;
|
||||
char *err_msg = NULL;
|
||||
char configValueBack, acBack, asBack;
|
||||
char *str_pos, *entry;
|
||||
int entry_len, type;
|
||||
iotx_alcs_msg_t rsp_msg;
|
||||
|
||||
COAP_DEBUG("alcs_service_cb_setup, path:%s", paths);
|
||||
do {
|
||||
if (!remote || !message) {
|
||||
COAP_DEBUG("alcs_service_cb_setup, param is NULL!");
|
||||
err_msg = "invalid package";
|
||||
break;
|
||||
}
|
||||
|
||||
id = json_get_value_by_name((char *)message->payload, message->payloadlen, "id", &idlen, (int *)NULL);
|
||||
p = json_get_value_by_name((char *)message->payload, message->payloadlen, "params", &len, (int *)NULL);
|
||||
if (!p || !len) {
|
||||
err_msg = "params is not found";
|
||||
break;
|
||||
}
|
||||
|
||||
p = json_get_value_by_name(p, len, "configValue", &len, (int *)NULL);
|
||||
if (!p || !len) {
|
||||
err_msg = "configValue is not found";
|
||||
break;
|
||||
}
|
||||
|
||||
backup_json_str_last_char(p, len, configValueBack);
|
||||
|
||||
json_array_for_each_entry(p, len, str_pos, entry, entry_len, type) {
|
||||
COAP_DEBUG("entry:%.*s", entry_len, entry);
|
||||
ac = json_get_value_by_name(entry, entry_len, "authCode", &aclen, (int *)NULL);
|
||||
as = json_get_value_by_name(entry, entry_len, "authSecret", &aslen, (int *)NULL);
|
||||
pk = json_get_value_by_name(entry, entry_len, "productKey", &pklen, (int *)NULL);
|
||||
dn = json_get_value_by_name(entry, entry_len, "deviceName", &dnlen, (int *)NULL);
|
||||
break;
|
||||
} /* end json_array_for_each_entry */
|
||||
restore_json_str_last_char(p, len, configValueBack);
|
||||
|
||||
if (!ac || !aclen || !as || !aslen || !pk || !pklen || !dn || !dnlen) {
|
||||
err_msg = "authinfo is not found";
|
||||
break;
|
||||
}
|
||||
|
||||
/* save */
|
||||
backup_json_str_last_char(ac, aclen, acBack);
|
||||
backup_json_str_last_char(as, aslen, asBack);
|
||||
__alcs_localsetup_ac_as_del(pk, pklen, dn, dnlen);
|
||||
__alcs_localsetup_ac_as_save(pk, pklen, dn, dnlen, ac, aclen, as, aslen);
|
||||
|
||||
alcs_add_svr_key(g_coap_handle, ac, as, LOCALSETUP);
|
||||
|
||||
restore_json_str_last_char(ac, aclen, acBack);
|
||||
restore_json_str_last_char(as, aslen, asBack)
|
||||
success = 1;
|
||||
|
||||
} while (0);
|
||||
|
||||
if (success) {
|
||||
HAL_Snprintf(payload, sizeof(payload), "{\"id\":\"%.*s\",\"code\":200}", idlen, id ? id : "");
|
||||
} else {
|
||||
HAL_Snprintf(payload, sizeof(payload), "{\"id\":\"%.*s\",\"code\":400,\"msg\":\"%s\"}", idlen, id ? id : "", err_msg);
|
||||
COAP_ERR("alcs_service_cb_setup, %s", err_msg);
|
||||
}
|
||||
|
||||
memset(&rsp_msg, 0, sizeof(iotx_alcs_msg_t));
|
||||
|
||||
rsp_msg.msg_code = ITOX_ALCS_COAP_MSG_CODE_205_CONTENT;
|
||||
rsp_msg.msg_type = IOTX_ALCS_MESSAGE_TYPE_CON;
|
||||
rsp_msg.payload = (unsigned char *)payload;
|
||||
rsp_msg.payload_len = strlen(payload);
|
||||
rsp_msg.ip = (char *)(remote ? remote->addr : NULL);
|
||||
rsp_msg.port = remote ? remote->port : 5683;
|
||||
rsp_msg.uri = (char *)paths;
|
||||
|
||||
if (message) {
|
||||
iotx_alcs_send_Response(g_adapter_handle, &rsp_msg, message->header.tokenlen, message->token);
|
||||
}
|
||||
}
|
||||
|
||||
static void alcs_localsetup_register_resource(void *adapter_handle, char *pk, char *dn)
|
||||
{
|
||||
iotx_alcs_res_t alcs_res;
|
||||
char uri [IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 24];
|
||||
|
||||
if (adapter_handle == NULL || pk == NULL || strlen(pk) > IOTX_PRODUCT_KEY_LEN ||
|
||||
dn == NULL || strlen(dn) > IOTX_DEVICE_NAME_LEN) {
|
||||
return;
|
||||
}
|
||||
|
||||
HAL_Snprintf(uri, sizeof(uri), "/dev/%s/%s/core/service/setup", pk, dn);
|
||||
|
||||
memset(&alcs_res, 0, sizeof(iotx_alcs_res_t));
|
||||
alcs_res.uri = uri;
|
||||
alcs_res.msg_ct = IOTX_ALCS_MESSAGE_CT_APP_JSON;
|
||||
alcs_res.msg_perm = IOTX_ALCS_MESSAGE_PERM_GET | IOTX_ALCS_MESSAGE_PERM_PUT;
|
||||
alcs_res.maxage = 60;
|
||||
alcs_res.need_auth = 1;
|
||||
alcs_res.callback = alcs_service_cb_setup;
|
||||
|
||||
iotx_alcs_register_resource(adapter_handle, &alcs_res);
|
||||
}
|
||||
|
||||
void alcs_localsetup_init(void *adapter_handle, void *coap_handler, char *pk, char *dn)
|
||||
{
|
||||
char prefix [10];
|
||||
char secret [64];
|
||||
g_adapter_handle = adapter_handle;
|
||||
g_coap_handle = coap_handler;
|
||||
alcs_localsetup_register_resource(adapter_handle, pk, dn);
|
||||
|
||||
if (alcs_localsetup_ac_as_load(pk, strlen(pk), dn, strlen(dn), prefix, sizeof(prefix), secret,
|
||||
sizeof(secret)) != ALCS_LOCALSETUP_SUCCESS) {
|
||||
alcs_add_svr_key(g_coap_handle, DEFAULT_AC, DEFAULT_AS, LOCALDEFAULT);
|
||||
} else {
|
||||
alcs_add_svr_key(g_coap_handle, prefix, secret, LOCALSETUP);
|
||||
}
|
||||
}
|
||||
|
||||
void alcs_localsetup_add_sub_device(void *adapter_handle, char *pk, char *dn)
|
||||
{
|
||||
alcs_localsetup_register_resource(adapter_handle, pk, dn);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _ALCS_LOCALSETUP_H_
|
||||
#define _ALCS_LOCALSETUP_H_
|
||||
|
||||
void alcs_localsetup_init(void *adapter_handle, void* coap_handler, char *product_key,char *device_name);
|
||||
void alcs_localsetup_add_sub_device (void *adapter_handle,char *product_key,char *device_name);
|
||||
void alcs_localsetup_deinit(void *handle);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,618 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "alcs_internal.h"
|
||||
#include "alcs_api_internal.h"
|
||||
#include "CoAPExport.h"
|
||||
#include "alcs_api.h"
|
||||
#include "alcs_adapter.h"
|
||||
#include "alcs_mqtt.h"
|
||||
#include "alcs_adapter.h"
|
||||
#include "CoAPPlatform.h"
|
||||
|
||||
static alcs_mqtt_ctx_t g_alcs_mqtt_ctx;
|
||||
|
||||
static alcs_mqtt_ctx_t *__alcs_mqtt_get_ctx(void)
|
||||
{
|
||||
return &g_alcs_mqtt_ctx;
|
||||
}
|
||||
|
||||
static alcs_mqtt_status_e __alcs_mqtt_publish(char *topic, int qos, void *data, int len)
|
||||
{
|
||||
return (IOT_MQTT_Publish_Simple(NULL, topic, qos, data, len) < 0) ? ALCS_MQTT_STATUS_ERROR : ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static alcs_mqtt_status_e __alcs_mqtt_send_response(char *topic, int id, int code, char *data)
|
||||
{
|
||||
char *msg_pub = NULL;
|
||||
uint16_t msg_len = 0;
|
||||
alcs_mqtt_status_e status = ALCS_MQTT_STATUS_SUCCESS;
|
||||
|
||||
if (data == NULL || strlen(data) == 0) {
|
||||
data = "{}";
|
||||
}
|
||||
|
||||
msg_len = strlen(ALCS_MQTT_THING_LAN_PREFIX_RESPONSE_FMT) + 20 + strlen(data) + 1;
|
||||
|
||||
if ((msg_pub = ALCS_ADAPTER_malloc(msg_len)) == NULL) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
HAL_Snprintf(msg_pub, msg_len, ALCS_MQTT_THING_LAN_PREFIX_RESPONSE_FMT, id, code, data);
|
||||
|
||||
status = __alcs_mqtt_publish(topic, 1, msg_pub, strlen(msg_pub));
|
||||
|
||||
ALCS_free(msg_pub);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static alcs_mqtt_status_e __alcs_mqtt_kv_set(const char *key, const void *val, int len, int sync)
|
||||
{
|
||||
if (HAL_Kv_Set(key, val, len, sync) != 0) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
COAP_INFO("ALCS KV Set, Key: %s, Val: %s, Len: %d", key, (char *)val, len);
|
||||
return ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static alcs_mqtt_status_e __alcs_mqtt_kv_get(const char *key, void *buffer, int *buffer_len)
|
||||
{
|
||||
if (HAL_Kv_Get(key, buffer, buffer_len) != 0) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
COAP_INFO("ALCS KV Get, Key: %s", key);
|
||||
|
||||
return ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static alcs_mqtt_status_e __alcs_mqtt_kv_del(const char *key)
|
||||
{
|
||||
if (HAL_Kv_Del(key) != 0) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
COAP_INFO("ALCS KV Del, Key: %s", key);
|
||||
|
||||
return ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
alcs_mqtt_status_e __alcs_mqtt_prefix_secret_save(const char *pk, uint16_t pk_len,
|
||||
const char *dn, uint16_t dn_len,
|
||||
const char *prefix, uint16_t prefix_len,
|
||||
const char *secret, uint16_t secret_len)
|
||||
{
|
||||
char *key_source = NULL;
|
||||
uint8_t key_md5[16] = {0};
|
||||
char key_md5_hexstr[33] = {0};
|
||||
char *value = NULL;
|
||||
|
||||
if (pk == NULL || pk_len >= IOTX_PRODUCT_KEY_LEN + 1 ||
|
||||
dn == NULL || dn_len >= IOTX_DEVICE_NAME_LEN + 1 ||
|
||||
prefix == NULL || secret == NULL) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* Calculate Key */
|
||||
key_source = ALCS_ADAPTER_malloc(pk_len + dn_len + 1);
|
||||
if (key_source == NULL) {
|
||||
COAP_ERR("No Enough Memory");
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
memset(key_source, 0, pk_len + dn_len + 1);
|
||||
|
||||
HAL_Snprintf(key_source, pk_len + dn_len + 1, "%.*s%.*s", pk_len, pk, dn_len, dn);
|
||||
|
||||
utils_md5((const unsigned char *)key_source, strlen(key_source), key_md5);
|
||||
alcs_utils_md5_hexstr(key_md5, (unsigned char *)key_md5_hexstr);
|
||||
|
||||
/* Calculate Value */
|
||||
value = ALCS_ADAPTER_malloc(prefix_len + secret_len + 3);
|
||||
if (value == NULL) {
|
||||
COAP_ERR("No Enough Memory");
|
||||
ALCS_free(key_source);
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
memset(value, 0, prefix_len + secret_len + 3);
|
||||
|
||||
value[0] = prefix_len;
|
||||
value[1] = secret_len;
|
||||
HAL_Snprintf(&value[2], prefix_len + secret_len + 1, "%.*s%.*s", prefix_len, prefix, secret_len, secret);
|
||||
|
||||
if (ALCS_MQTT_STATUS_SUCCESS != __alcs_mqtt_kv_set(key_md5_hexstr, value, prefix_len + secret_len + 3, 1)) {
|
||||
COAP_ERR("ALCS KV Set Prefix And Secret Fail");
|
||||
ALCS_free(key_source);
|
||||
ALCS_free(value);
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
ALCS_free(key_source);
|
||||
ALCS_free(value);
|
||||
return ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
alcs_mqtt_status_e alcs_mqtt_prefix_secret_load(const char *pk, uint16_t pk_len,
|
||||
const char *dn, uint16_t dn_len,
|
||||
char *prefix, char *secret)
|
||||
{
|
||||
char *key_source = NULL;
|
||||
uint8_t key_md5[16] = {0};
|
||||
char key_md5_hexstr[33] = {0};
|
||||
char value[128] = {0};
|
||||
int value_len = sizeof(value);
|
||||
|
||||
if (pk == NULL || strlen(pk) >= IOTX_PRODUCT_KEY_LEN + 1 ||
|
||||
dn == NULL || strlen(dn) >= IOTX_DEVICE_NAME_LEN + 1 ||
|
||||
prefix == NULL || secret == NULL) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* Calculate Key */
|
||||
key_source = ALCS_ADAPTER_malloc(pk_len + dn_len + 1);
|
||||
if (key_source == NULL) {
|
||||
COAP_ERR("No Enough Memory");
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
memset(key_source, 0, pk_len + dn_len + 1);
|
||||
|
||||
HAL_Snprintf(key_source, pk_len + dn_len + 1, "%.*s%.*s", pk_len, pk, dn_len, dn);
|
||||
|
||||
utils_md5((const unsigned char *)key_source, strlen(key_source), key_md5);
|
||||
alcs_utils_md5_hexstr(key_md5, (unsigned char *)key_md5_hexstr);
|
||||
|
||||
/* Get Value */
|
||||
if (ALCS_MQTT_STATUS_SUCCESS != __alcs_mqtt_kv_get(key_md5_hexstr, value, &value_len)) {
|
||||
COAP_ERR("ALCS KV Get Prefix And Secret Fail");
|
||||
ALCS_free(key_source);
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
memcpy(prefix, &value[2], value[0]);
|
||||
memcpy(secret, &value[2 + value[0]], value[1]);
|
||||
ALCS_free(key_source);
|
||||
|
||||
return ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
alcs_mqtt_status_e alcs_mqtt_prefix_secret_del(const char *pk, uint16_t pk_len,
|
||||
const char *dn, uint16_t dn_len)
|
||||
{
|
||||
char *key_source = NULL;
|
||||
uint8_t key_md5[16] = {0};
|
||||
char key_md5_hexstr[33] = {0};
|
||||
|
||||
if (pk == NULL || strlen(pk) >= IOTX_PRODUCT_KEY_LEN + 1 ||
|
||||
dn == NULL || strlen(dn) >= IOTX_DEVICE_NAME_LEN + 1) {
|
||||
COAP_ERR("Invalid Parameter");
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* Calculate Key */
|
||||
key_source = ALCS_ADAPTER_malloc(pk_len + dn_len + 1);
|
||||
if (key_source == NULL) {
|
||||
COAP_ERR("No Enough Memory");
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
memset(key_source, 0, pk_len + dn_len + 1);
|
||||
|
||||
HAL_Snprintf(key_source, pk_len + dn_len + 1, "%.*s%.*s", pk_len, pk, dn_len, dn);
|
||||
|
||||
utils_md5((const unsigned char *)key_source, strlen(key_source), key_md5);
|
||||
alcs_utils_md5_hexstr(key_md5, (unsigned char *)key_md5_hexstr);
|
||||
|
||||
if (ALCS_MQTT_STATUS_SUCCESS != __alcs_mqtt_kv_del(key_md5_hexstr)) {
|
||||
COAP_ERR("ALCS KV Get Prefix And Secret Fail");
|
||||
ALCS_free(key_source);
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
ALCS_free(key_source);
|
||||
return ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static void __alcs_mqtt_subscribe_callback(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
|
||||
{
|
||||
char topic_compare[ALCS_MQTT_TOPIC_MAX_LEN] = {0};
|
||||
char reqid[16] = {0};
|
||||
char *topic;
|
||||
int topic_len;
|
||||
void *payload;
|
||||
int payload_len;
|
||||
alcs_mqtt_ctx_t *alcs_mqtt_ctx = NULL;
|
||||
iotx_mqtt_topic_info_pt ptopic_info = NULL;
|
||||
|
||||
if (msg == NULL) {
|
||||
return;
|
||||
}
|
||||
alcs_mqtt_ctx = (alcs_mqtt_ctx_t *)pcontext;
|
||||
ptopic_info = (iotx_mqtt_topic_info_pt) msg->msg;
|
||||
|
||||
switch (msg->event_type) {
|
||||
case IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS:
|
||||
return;
|
||||
case IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT:
|
||||
return;
|
||||
case IOTX_MQTT_EVENT_SUBCRIBE_NACK:
|
||||
return;
|
||||
case IOTX_MQTT_EVENT_PUBLISH_RECEIVED:
|
||||
topic = (char *)ptopic_info->ptopic;
|
||||
topic_len = ptopic_info->topic_len;
|
||||
payload = (char *)ptopic_info->payload;
|
||||
payload_len = ptopic_info->payload_len;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (topic == NULL || payload == NULL || topic_len == 0 || payload_len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(topic_compare, 0, ALCS_MQTT_TOPIC_MAX_LEN);
|
||||
HAL_Snprintf(topic_compare, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_GET_REPLY_FMT,
|
||||
alcs_mqtt_ctx->product_key, alcs_mqtt_ctx->device_name);
|
||||
|
||||
COAP_INFO("Receivce Message, Topic: %.*s\n", topic_len, topic);
|
||||
|
||||
if ((strlen(topic_compare) == topic_len) && (strncmp(topic_compare, topic, topic_len) == 0)) {
|
||||
int data_len = 0, prefix_len = 0, secret_len = 0, productKey_len = 0, deviceName_len = 0;
|
||||
char *data = NULL, *prefix = NULL, *secret = NULL, *productKey = NULL, *deviceName = NULL;
|
||||
data = json_get_value_by_name((char *)payload, payload_len, "data", &data_len, NULL);
|
||||
|
||||
if (NULL != data && 0 != data_len) {
|
||||
char back1, back2;
|
||||
prefix = json_get_value_by_name(data, data_len, ALCS_MQTT_JSON_KEY_PREFIX, &prefix_len, NULL);
|
||||
secret = json_get_value_by_name(data, data_len, ALCS_MQTT_JSON_KEY_SECRET, &secret_len, NULL);
|
||||
productKey = json_get_value_by_name(data, data_len, ALCS_MQTT_JSON_KEY_PRODUCT_KEY, &productKey_len, NULL);
|
||||
deviceName = json_get_value_by_name(data, data_len, ALCS_MQTT_JSON_KEY_DEVICE_NAME, &deviceName_len, NULL);
|
||||
|
||||
COAP_INFO("Get Reply, Product Key: %.*s, Device Name: %.*s\n", productKey_len, productKey, deviceName_len, deviceName);
|
||||
|
||||
if (NULL != alcs_mqtt_ctx->coap_ctx && prefix && secret) {
|
||||
back1 = prefix[prefix_len];
|
||||
prefix[prefix_len] = 0;
|
||||
back2 = secret[secret_len];
|
||||
secret[secret_len] = 0;
|
||||
alcs_add_svr_key(alcs_mqtt_ctx->coap_ctx, prefix, secret, FROMCLOUDSVR);
|
||||
prefix[prefix_len] = back1;
|
||||
secret[secret_len] = back2;
|
||||
|
||||
if (productKey && deviceName) {
|
||||
if (__alcs_mqtt_prefix_secret_save(productKey, productKey_len, deviceName, deviceName_len, prefix, prefix_len, secret,
|
||||
secret_len) == ALCS_MQTT_STATUS_SUCCESS) {
|
||||
iotx_alcs_subdev_item_t subdev_item;
|
||||
memset(&subdev_item, 0, sizeof(iotx_alcs_subdev_item_t));
|
||||
|
||||
memcpy(subdev_item.product_key, productKey, productKey_len);
|
||||
memcpy(subdev_item.device_name, deviceName, deviceName_len);
|
||||
subdev_item.stage = IOTX_ALCS_SUBDEV_CONNECT_CLOUD;
|
||||
|
||||
iotx_alcs_subdev_update_stage(&subdev_item);
|
||||
}
|
||||
} else {
|
||||
iotx_alcs_subdev_remove(alcs_mqtt_ctx->product_key, alcs_mqtt_ctx->device_name);
|
||||
if (ALCS_MQTT_STATUS_SUCCESS != __alcs_mqtt_kv_set(ALCS_MQTT_JSON_KEY_PREFIX, prefix, prefix_len, 1)) {
|
||||
COAP_ERR("ALCS KV Set Prefix Fail");
|
||||
}
|
||||
if (ALCS_MQTT_STATUS_SUCCESS != __alcs_mqtt_kv_set(ALCS_MQTT_JSON_KEY_SECRET, secret, secret_len, 1)) {
|
||||
COAP_ERR("ALCS KV Set Secret Fail");
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (ALCS_MQTT_STATUS_SUCCESS == __alcs_mqtt_kv_get(ALCS_MQTT_JSON_KEY_PREFIX, prefix, &prefix_len) &&
|
||||
ALCS_MQTT_STATUS_SUCCESS == __alcs_mqtt_kv_get(ALCS_MQTT_JSON_KEY_SECRET, secret, &secret_len)) {
|
||||
if (NULL != alcs_mqtt_ctx->coap_ctx && prefix_len && secret_len) {
|
||||
alcs_add_svr_key(alcs_mqtt_ctx->coap_ctx, prefix, secret, FROMCLOUDSVR);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
memset(topic_compare, 0, ALCS_MQTT_TOPIC_MAX_LEN);
|
||||
HAL_Snprintf(topic_compare, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_UPDATE_FMT,
|
||||
alcs_mqtt_ctx->product_key, alcs_mqtt_ctx->device_name);
|
||||
|
||||
if ((strlen(topic_compare) == topic_len) && (strncmp(topic_compare, topic, topic_len) == 0)) {
|
||||
int param_len = 0, prefix_len = 0, id_len = 0;
|
||||
char *param = NULL, *prefix = NULL, *id = NULL;
|
||||
id = json_get_value_by_name((char *)payload, payload_len, "id", &id_len, NULL);
|
||||
|
||||
if (NULL != id && 0 != id_len) {
|
||||
strncpy(reqid, id, sizeof(reqid) - 1);
|
||||
}
|
||||
param = json_get_value_by_name((char *)payload, payload_len, "params", ¶m_len, NULL);
|
||||
if (NULL != param && 0 != param_len) {
|
||||
char reply_topic[ALCS_MQTT_TOPIC_MAX_LEN] = {0};
|
||||
prefix = json_get_value_by_name(param, param_len, ALCS_MQTT_JSON_KEY_PREFIX, &prefix_len, NULL);
|
||||
|
||||
if (NULL != alcs_mqtt_ctx->coap_ctx && prefix)
|
||||
if (0 != alcs_remove_svr_key(alcs_mqtt_ctx->coap_ctx, prefix)) {
|
||||
}
|
||||
if (ALCS_MQTT_STATUS_SUCCESS != __alcs_mqtt_kv_del(ALCS_MQTT_JSON_KEY_PREFIX)) {
|
||||
COAP_ERR("Remove the keyprefix from aos_kv fail");
|
||||
;
|
||||
}
|
||||
|
||||
HAL_Snprintf(reply_topic, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_UPDATE_REPLY_FMT,
|
||||
alcs_mqtt_ctx->product_key, alcs_mqtt_ctx->device_name);
|
||||
__alcs_mqtt_send_response(reply_topic, atoi(reqid), 200, NULL);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
memset(topic_compare, 0, ALCS_MQTT_TOPIC_MAX_LEN);
|
||||
HAL_Snprintf(topic_compare, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_BLACKLIST_UPDATE_FMT,
|
||||
alcs_mqtt_ctx->product_key, alcs_mqtt_ctx->device_name);
|
||||
|
||||
if ((strlen(topic_compare) == topic_len) && (strncmp(topic_compare, topic, topic_len) == 0)) {
|
||||
int param_len = 0, blacklist_len = 0, id_len = 0;
|
||||
char *param = NULL, *blacklist = NULL, *id = NULL;
|
||||
id = json_get_value_by_name((char *)payload, payload_len, "id", &id_len, NULL);
|
||||
|
||||
if (NULL != id && 0 != id_len) {
|
||||
strncpy(reqid, id, sizeof(reqid) - 1);
|
||||
}
|
||||
param = json_get_value_by_name((char *)payload, payload_len, "params", ¶m_len, NULL);
|
||||
if (NULL != param && 0 != param_len) {
|
||||
char reply_topic[ALCS_MQTT_TOPIC_MAX_LEN] = {0};
|
||||
blacklist = json_get_value_by_name(param, param_len, ALCS_MQTT_JSON_KEY_BLACK, &blacklist_len, NULL);
|
||||
if (NULL != alcs_mqtt_ctx->coap_ctx && blacklist) {
|
||||
alcs_set_revocation(alcs_mqtt_ctx->coap_ctx, blacklist);
|
||||
if (ALCS_MQTT_STATUS_SUCCESS != __alcs_mqtt_kv_set(ALCS_MQTT_JSON_KEY_BLACK, blacklist, blacklist_len, 1)) {
|
||||
COAP_ERR("aos_kv_set set blacklist fail");
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
HAL_Snprintf(reply_topic, ALCS_MQTT_TOPIC_MAX_LEN,
|
||||
ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_BLACKLIST_UPDATE_REPLY_FMT,
|
||||
alcs_mqtt_ctx->product_key, alcs_mqtt_ctx->device_name);
|
||||
__alcs_mqtt_send_response(reply_topic, atoi(reqid), 200, NULL);
|
||||
} else {
|
||||
if (ALCS_MQTT_STATUS_SUCCESS == __alcs_mqtt_kv_get(ALCS_MQTT_JSON_KEY_BLACK, blacklist, &blacklist_len)) {
|
||||
if (NULL != alcs_mqtt_ctx->coap_ctx) {
|
||||
alcs_set_revocation(alcs_mqtt_ctx->coap_ctx, blacklist);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static alcs_mqtt_status_e __alcs_mqtt_subscribe(void *ctx, char *topic)
|
||||
{
|
||||
return (IOT_MQTT_Subscribe(NULL, topic, 0, __alcs_mqtt_subscribe_callback,
|
||||
ctx) < 0) ? ALCS_MQTT_STATUS_ERROR : ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static alcs_mqtt_status_e __alcs_mqtt_unsubscribe(void *ctx, char *topic)
|
||||
{
|
||||
return (mqtt_unsubscribe(topic) != 0) ? ALCS_MQTT_STATUS_ERROR : ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
alcs_mqtt_status_e alcs_mqtt_init(void *handle, char *product_key, char *device_name)
|
||||
{
|
||||
char topic[ALCS_MQTT_TOPIC_MAX_LEN] = {0};
|
||||
alcs_mqtt_status_e status = ALCS_MQTT_STATUS_SUCCESS;
|
||||
alcs_mqtt_ctx_t *ctx = __alcs_mqtt_get_ctx();
|
||||
|
||||
if (handle == NULL || product_key == NULL || strlen(product_key) > IOTX_PRODUCT_KEY_LEN ||
|
||||
device_name == NULL || strlen(device_name) > IOTX_DEVICE_NAME_LEN) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
memset(ctx, 0, sizeof(alcs_mqtt_ctx_t));
|
||||
ctx->coap_ctx = (CoAPContext *)handle;
|
||||
memcpy(ctx->product_key, product_key, strlen(product_key));
|
||||
memcpy(ctx->device_name, device_name, strlen(device_name));
|
||||
|
||||
memset(topic, 0, ALCS_MQTT_TOPIC_MAX_LEN);
|
||||
HAL_Snprintf(topic, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_GET_REPLY_FMT,
|
||||
ctx->product_key, ctx->device_name);
|
||||
if (__alcs_mqtt_subscribe((void *)ctx, topic) != ALCS_MQTT_STATUS_SUCCESS) {
|
||||
COAP_ERR("ALCS Subscribe Failed, Topic: %s", topic);
|
||||
status = ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
memset(topic, 0, ALCS_MQTT_TOPIC_MAX_LEN);
|
||||
HAL_Snprintf(topic, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_UPDATE_FMT,
|
||||
ctx->product_key, ctx->device_name);
|
||||
if (__alcs_mqtt_subscribe((void *)ctx, topic) != ALCS_MQTT_STATUS_SUCCESS) {
|
||||
COAP_ERR("ALCS Subscribe Failed, Topic: %s", topic);
|
||||
status = ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
memset(topic, 0, ALCS_MQTT_TOPIC_MAX_LEN);
|
||||
HAL_Snprintf(topic, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_BLACKLIST_UPDATE_FMT,
|
||||
ctx->product_key, ctx->device_name);
|
||||
if (__alcs_mqtt_subscribe((void *)ctx, topic) != ALCS_MQTT_STATUS_SUCCESS) {
|
||||
COAP_ERR("ALCS Subscribe Failed, Topic: %s", topic);
|
||||
status = ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
alcs_mqtt_prefixkey_update((void *)ctx->coap_ctx);
|
||||
alcs_mqtt_blacklist_update((void *)ctx->coap_ctx);
|
||||
|
||||
alcs_prefixkey_get(ctx->product_key, ctx->device_name);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
alcs_mqtt_status_e alcs_mqtt_deinit(void *handle, char *product_key, char *device_name)
|
||||
{
|
||||
#if 0
|
||||
char topic[ALCS_MQTT_TOPIC_MAX_LEN] = {0};
|
||||
alcs_mqtt_status_e status = ALCS_MQTT_STATUS_SUCCESS;
|
||||
alcs_mqtt_ctx_t *ctx = __alcs_mqtt_get_ctx();
|
||||
|
||||
ARGUMENT_SANITY_CHECK(product_key && strlen(product_key), FAIL_RETURN);
|
||||
ARGUMENT_SANITY_CHECK(device_name && strlen(device_name), FAIL_RETURN);
|
||||
|
||||
if (handle == NULL || product_key == NULL || strlen(product_key) > IOTX_PRODUCT_KEY_LEN ||
|
||||
device_name == NULL || strlen(device_name) > IOTX_DEVICE_NAME_LEN || ctx == NULL) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
memset(topic, 0, ALCS_MQTT_TOPIC_MAX_LEN);
|
||||
HAL_Snprintf(topic, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_GET_REPLY_FMT,
|
||||
ctx->product_key, ctx->device_name);
|
||||
if (__alcs_mqtt_unsubscribe((void *)ctx, topic) != ALCS_MQTT_STATUS_SUCCESS) {
|
||||
COAP_ERR("ALCS Subscribe Failed, Topic: %s", topic);
|
||||
status = ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
memset(topic, 0, ALCS_MQTT_TOPIC_MAX_LEN);
|
||||
HAL_Snprintf(topic, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_UPDATE_FMT,
|
||||
ctx->product_key, ctx->device_name);
|
||||
if (__alcs_mqtt_unsubscribe((void *)ctx, topic) != ALCS_MQTT_STATUS_SUCCESS) {
|
||||
COAP_ERR("ALCS Subscribe Failed, Topic: %s", topic);
|
||||
status = ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
memset(topic, 0, ALCS_MQTT_TOPIC_MAX_LEN);
|
||||
HAL_Snprintf(topic, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_BLACKLIST_UPDATE_FMT,
|
||||
ctx->product_key, ctx->device_name);
|
||||
if (__alcs_mqtt_unsubscribe((void *)ctx, topic) != ALCS_MQTT_STATUS_SUCCESS) {
|
||||
COAP_ERR("ALCS Subscribe Failed, Topic: %s", topic);
|
||||
status = ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
#endif
|
||||
return ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
void alcs_mqtt_add_srv_key(const char *prefix, const char *secret)
|
||||
{
|
||||
alcs_mqtt_ctx_t *alcs_mqtt_ctx = __alcs_mqtt_get_ctx();
|
||||
alcs_add_svr_key(alcs_mqtt_ctx->coap_ctx, prefix, secret, FROMCLOUDSVR);
|
||||
}
|
||||
|
||||
alcs_mqtt_status_e alcs_mqtt_blacklist_update(void *ctx)
|
||||
{
|
||||
CoAPContext *context = (CoAPContext *)ctx;
|
||||
char blacklist[ALCS_MQTT_BLACK_MAX_LEN] = {0};
|
||||
int blacklist_len = ALCS_MQTT_BLACK_MAX_LEN;
|
||||
|
||||
if (NULL == context) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ALCS_MQTT_STATUS_SUCCESS == __alcs_mqtt_kv_get(ALCS_MQTT_JSON_KEY_BLACK, blacklist, &blacklist_len)) {
|
||||
COAP_INFO("The blacklist is %.*s", blacklist_len, blacklist);
|
||||
if (blacklist_len) {
|
||||
alcs_set_revocation(context, blacklist);
|
||||
return ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
alcs_mqtt_status_e alcs_mqtt_prefixkey_update(void *ctx)
|
||||
{
|
||||
CoAPContext *context = (CoAPContext *)ctx;
|
||||
char prefix[ALCS_MQTT_PREFIX_MAX_LEN] = {0};
|
||||
char secret[ALCS_MQTT_SECRET_MAX_LEN] = {0};
|
||||
int prefix_len = ALCS_MQTT_PREFIX_MAX_LEN, secret_len = ALCS_MQTT_SECRET_MAX_LEN;
|
||||
|
||||
if (NULL == context) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
COAP_INFO("start alcs_prefixkey_update\n");
|
||||
|
||||
if (ALCS_MQTT_STATUS_SUCCESS == __alcs_mqtt_kv_get(ALCS_MQTT_JSON_KEY_PREFIX, prefix, &prefix_len) &&
|
||||
ALCS_MQTT_STATUS_SUCCESS == __alcs_mqtt_kv_get(ALCS_MQTT_JSON_KEY_SECRET, secret, &secret_len)) {
|
||||
COAP_INFO("The prefix is %.*s, deviceSecret is %.*s", prefix_len, prefix, secret_len, secret);
|
||||
if (prefix_len && secret_len) {
|
||||
alcs_add_svr_key(context, prefix, secret, FROMCLOUDSVR);
|
||||
return ALCS_MQTT_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
alcs_mqtt_status_e alcs_prefixkey_get(const char *product_key, const char *device_name)
|
||||
{
|
||||
/* int ret = 0; */
|
||||
char *msg_pub = NULL;
|
||||
uint16_t msg_len = 0;
|
||||
char topic[ALCS_MQTT_TOPIC_MAX_LEN] = {0};
|
||||
alcs_mqtt_ctx_t *ctx = __alcs_mqtt_get_ctx();
|
||||
alcs_mqtt_status_e status = ALCS_MQTT_STATUS_SUCCESS;
|
||||
int id = ctx->send_id++;
|
||||
|
||||
if (product_key == NULL || strlen(product_key) > IOTX_PRODUCT_KEY_LEN ||
|
||||
device_name == NULL || strlen(device_name) > IOTX_DEVICE_NAME_LEN) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
HAL_Snprintf(topic, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_GET_FMT,
|
||||
product_key, device_name);
|
||||
|
||||
msg_len = strlen(ALCS_MQTT_THING_ALCS_REQUEST) + 10 + 1;
|
||||
if ((msg_pub = ALCS_ADAPTER_malloc(msg_len)) == NULL) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
HAL_Snprintf(msg_pub, msg_len, ALCS_MQTT_THING_ALCS_REQUEST, id);
|
||||
|
||||
COAP_INFO("ALCS Prefix Get, Topic: %s, Payload: %s", topic, msg_pub);
|
||||
status = __alcs_mqtt_publish(topic, 1, msg_pub, strlen(msg_pub));
|
||||
|
||||
ALCS_free(msg_pub);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
alcs_mqtt_status_e alcs_mqtt_subdev_prefix_get(const char *product_key, const char *device_name)
|
||||
{
|
||||
/* int ret = 0; */
|
||||
char *msg_pub = NULL;
|
||||
uint16_t msg_len = 0;
|
||||
char topic[ALCS_MQTT_TOPIC_MAX_LEN] = {0};
|
||||
alcs_mqtt_ctx_t *ctx = __alcs_mqtt_get_ctx();
|
||||
alcs_mqtt_status_e status = ALCS_MQTT_STATUS_SUCCESS;
|
||||
int id = ctx->send_id++;
|
||||
|
||||
if (product_key == NULL || strlen(product_key) > IOTX_PRODUCT_KEY_LEN ||
|
||||
device_name == NULL || strlen(device_name) > IOTX_DEVICE_NAME_LEN) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
COAP_INFO("Subdevice, PK: %s, DN: %s\n", product_key, device_name);
|
||||
HAL_Snprintf(topic, ALCS_MQTT_TOPIC_MAX_LEN, ALCS_MQTT_PREFIX ALCS_MQTT_THING_LAN_PREFIX_GET_FMT,
|
||||
ctx->product_key, ctx->device_name);
|
||||
|
||||
msg_len = strlen(ALCS_MQTT_THING_ALCS_SUBDEV_REQUEST) + 10 + strlen(product_key) + strlen(device_name) + 1;
|
||||
if ((msg_pub = ALCS_ADAPTER_malloc(msg_len)) == NULL) {
|
||||
return ALCS_MQTT_STATUS_ERROR;
|
||||
}
|
||||
|
||||
HAL_Snprintf(msg_pub, msg_len, ALCS_MQTT_THING_ALCS_SUBDEV_REQUEST, id,
|
||||
(int)strlen(product_key), product_key, (int)strlen(device_name), device_name);
|
||||
|
||||
COAP_ERR("ALCS Prefix Get, Topic: %s, Payload: %s", topic, msg_pub);
|
||||
status = __alcs_mqtt_publish(topic, 1, msg_pub, strlen(msg_pub));
|
||||
|
||||
ALCS_free(msg_pub);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _ALCS_MQTT_H_
|
||||
#define _ALCS_MQTT_H_
|
||||
|
||||
#include "alcs_internal.h"
|
||||
|
||||
typedef enum {
|
||||
ALCS_MQTT_STATUS_SUCCESS,
|
||||
ALCS_MQTT_STATUS_ERROR
|
||||
} alcs_mqtt_status_e;
|
||||
|
||||
typedef struct {
|
||||
CoAPContext *coap_ctx;
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1];
|
||||
char device_name[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 2];
|
||||
uint32_t send_id;
|
||||
} alcs_mqtt_ctx_t;
|
||||
|
||||
#define ALCS_MQTT_PREFIX "/sys/%s/%s"
|
||||
|
||||
#define ALCS_MQTT_THING_LAN_PREFIX_GET_REPLY_FMT "/thing/lan/prefix/get_reply"
|
||||
#define ALCS_MQTT_THING_LAN_PREFIX_GET_FMT "/thing/lan/prefix/get"
|
||||
#define ALCS_MQTT_THING_LAN_PREFIX_UPDATE_FMT "/thing/lan/prefix/update"
|
||||
#define ALCS_MQTT_THING_LAN_PREFIX_UPDATE_REPLY_FMT "/thing/lan/prefix/update_reply"
|
||||
#define ALCS_MQTT_THING_LAN_PREFIX_BLACKLIST_UPDATE_FMT "/thing/lan/blacklist/update"
|
||||
#define ALCS_MQTT_THING_LAN_PREFIX_BLACKLIST_UPDATE_REPLY_FMT "/thing/lan/blacklist/update_reply"
|
||||
|
||||
#define ALCS_MQTT_THING_ALCS_REQUEST "{\"id\":\"%d\",\"version\":\"1.0\",\"params\":\"{}\",\"method\":\"thing.lan.prefix.get\"}"
|
||||
#define ALCS_MQTT_THING_LAN_PREFIX_RESPONSE_FMT "{\"id\": \"%d\", \"code\": %d, \"data\": %s}"
|
||||
#define ALCS_MQTT_THING_ALCS_SUBDEV_REQUEST "{\"id\":\"%d\",\"version\":\"1.0\",\"params\":{\"productKey\":\"%.*s\",\"deviceName\":\"%.*s\"},\"method\":\"thing.lan.prefix.get\"}"
|
||||
|
||||
#define ALCS_MQTT_TOPIC_MAX_LEN (128)
|
||||
|
||||
#define ALCS_MQTT_JSON_KEY_PRODUCT_KEY "productKey"
|
||||
#define ALCS_MQTT_JSON_KEY_DEVICE_NAME "deviceName"
|
||||
#define ALCS_MQTT_JSON_KEY_PREFIX "prefix"
|
||||
#define ALCS_MQTT_JSON_KEY_SECRET "deviceSecret"
|
||||
#define ALCS_MQTT_JSON_KEY_BLACK "blacklist"
|
||||
|
||||
#define ALCS_MQTT_PREFIX_MAX_LEN (40)
|
||||
#define ALCS_MQTT_SECRET_MAX_LEN (40)
|
||||
#define ALCS_MQTT_BLACK_MAX_LEN (100)
|
||||
|
||||
alcs_mqtt_status_e alcs_mqtt_init(void *handle, char *product_key, char *device_name);
|
||||
alcs_mqtt_status_e alcs_mqtt_deinit(void *handle, char *product_key, char *device_name);
|
||||
alcs_mqtt_status_e alcs_mqtt_blacklist_update(void *ctx);
|
||||
alcs_mqtt_status_e alcs_mqtt_prefixkey_update(void *ctx);
|
||||
void alcs_mqtt_add_srv_key(const char *prefix, const char *secret);
|
||||
alcs_mqtt_status_e alcs_mqtt_prefix_secret_load(const char *pk, uint16_t pk_len,
|
||||
const char *dn, uint16_t dn_len,
|
||||
char *prefix, char *secret);
|
||||
alcs_mqtt_status_e alcs_mqtt_prefix_secret_del(const char *pk, uint16_t pk_len,
|
||||
const char *dn, uint16_t dn_len);
|
||||
alcs_mqtt_status_e alcs_mqtt_subdev_prefix_get(const char *product_key, const char *device_name);
|
||||
alcs_mqtt_status_e alcs_prefixkey_get(const char *product_key, const char *device_name);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,702 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
#include "alcs_internal.h"
|
||||
#include "alcs_api_internal.h"
|
||||
#include "CoAPPlatform.h"
|
||||
#include "CoAPResource.h"
|
||||
#ifdef LOG_REPORT_TO_CLOUD
|
||||
#include "iotx_log_report.h"
|
||||
#endif
|
||||
#define RES_FORMAT "{\"id\":\"%.*s\",\"code\":%d,\"data\":{%s}}"
|
||||
|
||||
#ifdef ALCS_SERVER_ENABLED
|
||||
|
||||
int sessionid_seed = 0xff;
|
||||
static int default_heart_expire = 120000;
|
||||
|
||||
void utils_hmac_sha1_base64(const char *msg, int msg_len, const char *key, int key_len, char *digest, int *digest_len)
|
||||
{
|
||||
char buf[20];
|
||||
uint32_t outlen;
|
||||
utils_hmac_sha1_hex(msg, msg_len, buf, key, key_len);
|
||||
|
||||
utils_base64encode((unsigned char *)buf, 20, *digest_len, (unsigned char *)digest, &outlen);
|
||||
*digest_len = outlen;
|
||||
}
|
||||
|
||||
void alcs_rec_auth_select(CoAPContext *ctx, const char *paths, NetworkAddr *from, CoAPMessage *resMsg)
|
||||
{
|
||||
int seqlen, datalen;
|
||||
char *seq, *data;
|
||||
char *targetKey = "";
|
||||
int targetLen = 0;
|
||||
auth_list *lst = NULL;
|
||||
char *accesskeys;
|
||||
int keylen;
|
||||
char back;
|
||||
char *str_pos, *entry;
|
||||
int entry_len, type;
|
||||
CoAPMessage msg;
|
||||
char keybuf[32];
|
||||
char payloadbuf[512];
|
||||
CoAPLenString token = {resMsg->header.tokenlen, resMsg->token};
|
||||
CoAPLenString payload;
|
||||
|
||||
/* int res_code = 200; */
|
||||
COAP_DEBUG("receive data:%.*s", resMsg->payloadlen, resMsg->payload);
|
||||
|
||||
do {
|
||||
|
||||
if (!req_payload_parser((const char *)resMsg->payload, resMsg->payloadlen, &seq, &seqlen, &data, &datalen)) {
|
||||
break;
|
||||
}
|
||||
lst = get_list(ctx);
|
||||
|
||||
accesskeys = json_get_value_by_name(data, datalen, "accessKeys", &keylen, NULL);
|
||||
if (!accesskeys || !keylen) {
|
||||
break;
|
||||
}
|
||||
COAP_DEBUG("accessKeys:%.*s", keylen, accesskeys);
|
||||
|
||||
backup_json_str_last_char(accesskeys, keylen, back);
|
||||
json_array_for_each_entry(accesskeys, keylen, str_pos, entry, entry_len, type) {
|
||||
svr_key_item *node = NULL, *next = NULL;
|
||||
svr_group_item *gnode = NULL, *gnext = NULL;
|
||||
COAP_DEBUG("entry:%.*s", entry_len, entry);
|
||||
list_for_each_entry_safe(node, next, &lst->lst_svr, lst, svr_key_item) {
|
||||
COAP_DEBUG("keyprefix:%s", node->keyInfo.keyprefix);
|
||||
if (strstr(entry, node->keyInfo.keyprefix) == entry) {
|
||||
COAP_DEBUG("target keyprefix:%s", entry);
|
||||
targetKey = entry;
|
||||
targetLen = entry_len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (targetKey) {
|
||||
break;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(gnode, gnext, &lst->lst_svr_group, lst, svr_group_item) {
|
||||
COAP_DEBUG("keyprefix:%s", gnode->keyInfo.keyprefix);
|
||||
if (strstr(entry, gnode->keyInfo.keyprefix) == entry) {
|
||||
COAP_DEBUG("target keyprefix:%s", entry);
|
||||
targetKey = entry;
|
||||
targetLen = entry_len;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (targetKey) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
restore_json_str_last_char(accesskeys, keylen, back);
|
||||
|
||||
} while (0);
|
||||
|
||||
COAP_DEBUG("key:%s", targetKey);
|
||||
|
||||
|
||||
HAL_Snprintf(keybuf, sizeof(keybuf), "\"accessKey\":\"%.*s\"", targetLen, targetKey);
|
||||
|
||||
HAL_Snprintf(payloadbuf, sizeof(payloadbuf), RES_FORMAT, seqlen, seq, targetKey ? 200 : COAP_MSG_CODE_401_UNAUTHORIZED,
|
||||
keybuf);
|
||||
payload.data = (unsigned char *)payloadbuf;
|
||||
payload.len = strlen(payloadbuf);
|
||||
|
||||
alcs_msg_init(ctx, &msg, COAP_MSG_CODE_205_CONTENT, COAP_MESSAGE_TYPE_ACK, 0, &payload, NULL);
|
||||
alcs_sendrsp(ctx, from, &msg, 1, resMsg->header.msgid, &token);
|
||||
}
|
||||
|
||||
svr_key_info *is_legal_key(CoAPContext *ctx, const char *keyprefix, int prefixlen, const char *keyseq, int seqlen,
|
||||
int *res_code)
|
||||
{
|
||||
auth_list *lst = get_list(ctx);
|
||||
COAP_INFO("islegal prefix:%.*s, seq:%.*s", prefixlen, keyprefix, seqlen, keyseq);
|
||||
|
||||
if (lst) {
|
||||
COAP_DEBUG("find devices");
|
||||
HAL_MutexLock(lst->list_mutex);
|
||||
|
||||
if (lst->revocation) {
|
||||
int len = strlen(lst->revocation);
|
||||
int i;
|
||||
for (i = 0; i < len; i += KEYSEQ_LEN) {
|
||||
if (strncmp(keyseq, lst->revocation + i, seqlen) == 0) {
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
*res_code = ALCS_AUTH_REVOCATE;
|
||||
COAP_INFO("accesskey is revocated");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (list_empty(&lst->lst_svr)) {
|
||||
COAP_INFO("ALCS_AUTH_AUTHLISTEMPTY:%d\r\n", ALCS_AUTH_AUTHLISTEMPTY);
|
||||
*res_code = ALCS_AUTH_AUTHLISTEMPTY;
|
||||
} else {
|
||||
svr_key_item *node = NULL, *next = NULL;
|
||||
svr_group_item *gnode = NULL, *gnext = NULL;
|
||||
list_for_each_entry_safe(node, next, &lst->lst_svr, lst, svr_key_item) {
|
||||
COAP_DEBUG("node prefix:%s", node->keyInfo.keyprefix);
|
||||
if (strlen(node->keyInfo.keyprefix) == prefixlen && strncmp(keyprefix, node->keyInfo.keyprefix, prefixlen) == 0) {
|
||||
*res_code = ALCS_AUTH_OK;
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
return &node->keyInfo;
|
||||
}
|
||||
}
|
||||
list_for_each_entry_safe(gnode, gnext, &lst->lst_svr_group, lst, svr_group_item) {
|
||||
COAP_DEBUG("node prefix:%s", gnode->keyInfo.keyprefix);
|
||||
if (strlen(gnode->keyInfo.keyprefix) == prefixlen && strncmp(keyprefix, gnode->keyInfo.keyprefix, prefixlen) == 0) {
|
||||
*res_code = ALCS_AUTH_OK;
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
return &gnode->keyInfo;
|
||||
}
|
||||
}
|
||||
|
||||
COAP_INFO("ALCS_AUTH_UNMATCHPREFIX:%d\r\n", ALCS_AUTH_UNMATCHPREFIX);
|
||||
*res_code = ALCS_AUTH_UNMATCHPREFIX;
|
||||
}
|
||||
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void alcs_rec_auth(CoAPContext *ctx, const char *paths, NetworkAddr *from, CoAPMessage *resMsg)
|
||||
{
|
||||
int seqlen, datalen;
|
||||
char *seq, *data;
|
||||
int res_code = 200;
|
||||
char body[200] = {0};
|
||||
char *accesskey, *randomkey, *sign;
|
||||
int tmplen;
|
||||
char *keyprefix;
|
||||
char *keyseq;
|
||||
char accessToken[64];
|
||||
int tokenlen;
|
||||
int randomkeylen;
|
||||
char buf[40];
|
||||
int calc_sign_len;
|
||||
int pklen, dnlen;
|
||||
char *pk;
|
||||
char *dn;
|
||||
char tmp1;
|
||||
char tmp2;
|
||||
svr_key_info *item;
|
||||
AlcsDeviceKey devKey;
|
||||
session_item *session;
|
||||
CoAPMessage message;
|
||||
char payloadbuf[512];
|
||||
CoAPLenString payload;
|
||||
CoAPLenString token;
|
||||
COAP_INFO("receive data:%.*s, from:%s", resMsg->payloadlen, resMsg->payload, from->addr);
|
||||
|
||||
do {
|
||||
if (!req_payload_parser((const char *)resMsg->payload, resMsg->payloadlen, &seq, &seqlen, &data, &datalen)) {
|
||||
break;
|
||||
}
|
||||
|
||||
accesskey = json_get_value_by_name(data, datalen, "accessKey", &tmplen, NULL);
|
||||
COAP_INFO("accesskey:%.*s", tmplen, accesskey);
|
||||
|
||||
if (!accesskey || tmplen != KEYPREFIX_LEN + 1 + 1 + KEYSEQ_LEN) {
|
||||
break;
|
||||
}
|
||||
|
||||
keyprefix = accesskey;
|
||||
keyseq = accesskey + KEYPREFIX_LEN + 1 + 1;
|
||||
|
||||
item = is_legal_key(ctx, keyprefix, KEYPREFIX_LEN, keyseq, KEYSEQ_LEN, &res_code);
|
||||
if (!item) {
|
||||
COAP_INFO("islegal return null");
|
||||
break;
|
||||
}
|
||||
|
||||
tokenlen = sizeof(accessToken);
|
||||
utils_hmac_sha1_base64(accesskey, tmplen, item->secret, strlen(item->secret), accessToken, &tokenlen);
|
||||
|
||||
COAP_INFO("accessToken:%.*s", tokenlen, accessToken);
|
||||
randomkey = json_get_value_by_name(data, datalen, "randomKey", &randomkeylen, NULL);
|
||||
if (!randomkey || !randomkeylen) {
|
||||
res_code = ALCS_AUTH_INVALIDPARAM;
|
||||
break;
|
||||
}
|
||||
|
||||
/*calc sign, save in buf*/
|
||||
|
||||
calc_sign_len = sizeof(buf);
|
||||
utils_hmac_sha1_base64(randomkey, randomkeylen, accessToken, tokenlen, buf, &calc_sign_len);
|
||||
|
||||
COAP_INFO("calc randomKey:%.*s,token:%.*s,sign:%.*s", randomkeylen, randomkey, tokenlen,
|
||||
accessToken, calc_sign_len, buf);
|
||||
|
||||
sign = json_get_value_by_name(data, datalen, "sign", &tmplen, NULL);
|
||||
if (!sign || tmplen != calc_sign_len || strncmp(sign, buf, calc_sign_len)) {
|
||||
res_code = ALCS_AUTH_ILLEGALSIGN;
|
||||
break;
|
||||
}
|
||||
|
||||
pk = json_get_value_by_name(data, datalen, "prodKey", &pklen, NULL);
|
||||
dn = json_get_value_by_name(data, datalen, "deviceName", &dnlen, NULL);
|
||||
|
||||
if (!pk || !pklen || !dn || !dnlen) {
|
||||
res_code = ALCS_AUTH_INVALIDPARAM;
|
||||
break;
|
||||
}
|
||||
tmp1 = pk[pklen];
|
||||
tmp2 = dn[dnlen];
|
||||
pk[pklen] = 0;
|
||||
dn[dnlen] = 0;
|
||||
|
||||
|
||||
memset(&devKey, 0x00, sizeof(AlcsDeviceKey));
|
||||
memcpy(&devKey.addr, from, sizeof(NetworkAddr));
|
||||
devKey.pk = pk;
|
||||
devKey.dn = dn;
|
||||
session = get_svr_session(ctx, &devKey);
|
||||
|
||||
if (!session) {
|
||||
char path[100] = {0};
|
||||
struct list_head *svr_head;
|
||||
session = (session_item *)coap_malloc(sizeof(session_item));
|
||||
gen_random_key((unsigned char *)session->randomKey, RANDOMKEY_LEN);
|
||||
session->sessionId = ++sessionid_seed;
|
||||
|
||||
strncpy(path, pk, sizeof(path));
|
||||
strncat(path, dn, sizeof(path) - strlen(path) - 1);
|
||||
CoAPPathMD5_sum(path, strlen(path), session->pk_dn, PK_DN_CHECKSUM_LEN);
|
||||
|
||||
memcpy(&session->addr, from, sizeof(NetworkAddr));
|
||||
COAP_INFO("new session, addr:%s, port:%d", session->addr.addr, session->addr.port);
|
||||
svr_head = get_svr_session_list(ctx);
|
||||
list_add_tail(&session->lst, svr_head);
|
||||
}
|
||||
|
||||
pk[pklen] = tmp1;
|
||||
dn[dnlen] = tmp2;
|
||||
|
||||
HAL_Snprintf(buf, sizeof(buf), "%.*s%s", randomkeylen, randomkey, session->randomKey);
|
||||
utils_hmac_sha1_hex(buf, strlen(buf), session->sessionKey, accessToken, tokenlen);
|
||||
|
||||
/*calc sign, save in buf*/
|
||||
calc_sign_len = sizeof(buf);
|
||||
utils_hmac_sha1_base64(session->randomKey, RANDOMKEY_LEN, accessToken, tokenlen, buf, &calc_sign_len);
|
||||
HAL_Snprintf(body, sizeof(body), "\"sign\":\"%.*s\",\"randomKey\":\"%s\",\"sessionId\":%d,\"expire\":86400",
|
||||
calc_sign_len, buf, session->randomKey, session->sessionId);
|
||||
|
||||
session->authed_time = HAL_UptimeMs();
|
||||
session->heart_time = session->authed_time;
|
||||
/* ??? */
|
||||
/* result = 1; */
|
||||
|
||||
} while (0);
|
||||
|
||||
HAL_Snprintf(payloadbuf, sizeof(payloadbuf), RES_FORMAT, seqlen, seq, res_code, body);
|
||||
payload.len = strlen(payloadbuf);
|
||||
payload.data = (unsigned char *)payloadbuf;
|
||||
alcs_msg_init(ctx, &message, COAP_MSG_CODE_205_CONTENT, COAP_MESSAGE_TYPE_ACK, 0, &payload, NULL);
|
||||
token.len = resMsg->header.tokenlen;
|
||||
token.data = resMsg->token;
|
||||
alcs_sendrsp(ctx, from, &message, 1, resMsg->header.msgid, &token);
|
||||
}
|
||||
|
||||
static int alcs_remove_low_priority_key(CoAPContext *ctx, ServerKeyPriority priority)
|
||||
{
|
||||
auth_list *lst = get_list(ctx);
|
||||
svr_key_item *node = NULL, *next = NULL;
|
||||
|
||||
HAL_MutexLock(lst->list_mutex);
|
||||
|
||||
list_for_each_entry_safe(node, next, &lst->lst_svr, lst, svr_key_item) {
|
||||
if (node->keyInfo.priority < priority) {
|
||||
coap_free(node->keyInfo.secret);
|
||||
list_del(&node->lst);
|
||||
coap_free(node);
|
||||
--lst->svr_count;
|
||||
}
|
||||
}
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
static int add_svr_key(CoAPContext *ctx, const char *keyprefix, const char *secret, bool isGroup,
|
||||
ServerKeyPriority priority)
|
||||
{
|
||||
auth_list *lst = get_list(ctx);
|
||||
svr_key_item *node = NULL, *next = NULL;
|
||||
svr_key_item *item;
|
||||
COAP_INFO("add_svr_key\n");
|
||||
if (!lst || lst->svr_count >= KEY_MAXCOUNT || strlen(keyprefix) != KEYPREFIX_LEN) {
|
||||
return COAP_ERROR_INVALID_LENGTH;
|
||||
}
|
||||
alcs_remove_low_priority_key(ctx, priority);
|
||||
|
||||
HAL_MutexLock(lst->list_mutex);
|
||||
list_for_each_entry_safe(node, next, &lst->lst_svr, lst, svr_key_item) {
|
||||
if (node->keyInfo.priority > priority) {
|
||||
/* find high priority key */
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
return COAP_ERROR_UNSUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
item = (svr_key_item *) coap_malloc(sizeof(svr_key_item));
|
||||
if (!item) {
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
return COAP_ERROR_MALLOC;
|
||||
}
|
||||
|
||||
item->keyInfo.secret = (char *) coap_malloc(strlen(secret) + 1);
|
||||
if (!item->keyInfo.secret) {
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
coap_free(item);
|
||||
return COAP_ERROR_MALLOC;
|
||||
}
|
||||
strcpy(item->keyInfo.secret, secret);
|
||||
memcpy(item->keyInfo.keyprefix, keyprefix, KEYPREFIX_LEN);
|
||||
item->keyInfo.priority = priority;
|
||||
|
||||
list_add_tail(&item->lst, &lst->lst_svr);
|
||||
++lst->svr_count;
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int alcs_add_svr_key(CoAPContext *ctx, const char *keyprefix, const char *secret, ServerKeyPriority priority)
|
||||
{
|
||||
COAP_INFO("alcs_add_svr_key, priority=%d", priority);
|
||||
return add_svr_key(ctx, keyprefix, secret, 0, priority);
|
||||
}
|
||||
|
||||
|
||||
int alcs_remove_svr_key(CoAPContext *ctx, const char *keyprefix)
|
||||
{
|
||||
auth_list *lst = get_list(ctx);
|
||||
svr_key_item *node = NULL, *next = NULL;
|
||||
|
||||
HAL_MutexLock(lst->list_mutex);
|
||||
|
||||
list_for_each_entry_safe(node, next, &lst->lst_svr, lst, svr_key_item) {
|
||||
if (strcmp(node->keyInfo.keyprefix, keyprefix) == 0) {
|
||||
coap_free(node->keyInfo.secret);
|
||||
list_del(&node->lst);
|
||||
coap_free(node);
|
||||
--lst->svr_count;
|
||||
break;
|
||||
}
|
||||
}
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
int alcs_set_revocation(CoAPContext *ctx, const char *seqlist)
|
||||
{
|
||||
auth_list *lst = get_list(ctx);
|
||||
int len;
|
||||
|
||||
HAL_MutexLock(lst->list_mutex);
|
||||
|
||||
len = seqlist ? strlen(seqlist) : 0;
|
||||
if (lst->revocation) {
|
||||
coap_free(lst->revocation);
|
||||
lst->revocation = NULL;
|
||||
}
|
||||
|
||||
if (len > 0) {
|
||||
lst->revocation = (char *)coap_malloc(len + 1);
|
||||
strcpy(lst->revocation, seqlist);
|
||||
}
|
||||
HAL_MutexUnlock(lst->list_mutex);
|
||||
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
/* ----------------------------------------- */
|
||||
|
||||
void send_err_rsp(CoAPContext *ctx, NetworkAddr *addr, int code, CoAPMessage *request)
|
||||
{
|
||||
CoAPMessage sendMsg;
|
||||
CoAPLenString payload = {0};
|
||||
CoAPLenString token;
|
||||
alcs_msg_init(ctx, &sendMsg, code, COAP_MESSAGE_TYPE_ACK, 0, &payload, NULL);
|
||||
token.len = request->header.tokenlen;
|
||||
token.data = request->token;
|
||||
alcs_sendrsp(ctx, addr, &sendMsg, 1, request->header.msgid, &token);
|
||||
}
|
||||
|
||||
void call_cb(CoAPContext *context, const char *path, NetworkAddr *remote, CoAPMessage *message, const char *key,
|
||||
char *buf, CoAPRecvMsgHandler cb)
|
||||
{
|
||||
CoAPMessage tmpMsg;
|
||||
memcpy(&tmpMsg, message, sizeof(CoAPMessage));
|
||||
|
||||
if (key && buf) {
|
||||
int len = alcs_decrypt((const char *)message->payload, message->payloadlen, key, buf);
|
||||
tmpMsg.payload = (unsigned char *)buf;
|
||||
tmpMsg.payloadlen = len;
|
||||
#ifdef LOG_REPORT_TO_CLOUD
|
||||
get_msgid(buf, 0);
|
||||
#endif
|
||||
} else {
|
||||
tmpMsg.payload = NULL;
|
||||
tmpMsg.payloadlen = 0;
|
||||
}
|
||||
|
||||
cb(context, path, remote, &tmpMsg);
|
||||
}
|
||||
|
||||
static secure_resource_cb_item *get_resource_by_path(const char *path)
|
||||
{
|
||||
secure_resource_cb_item *node, *next;
|
||||
char path_calc[MAX_PATH_CHECKSUM_LEN] = {0};
|
||||
CoAPPathMD5_sum(path, strlen(path), path_calc, MAX_PATH_CHECKSUM_LEN);
|
||||
|
||||
list_for_each_entry_safe(node, next, &secure_resource_cb_head, lst, secure_resource_cb_item) {
|
||||
if (node->path_type == PATH_NORMAL) {
|
||||
if (memcmp(node->path, path_calc, MAX_PATH_CHECKSUM_LEN) == 0) {
|
||||
return node;
|
||||
}
|
||||
} else if (strlen(node->filter_path) > 0) {
|
||||
if (strncmp(node->filter_path, path, strlen(node->filter_path) - 1) == 0) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
COAP_ERR("receive unknown request, path:%s", path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void recv_msg_handler(CoAPContext *context, const char *path, NetworkAddr *remote, CoAPMessage *message)
|
||||
{
|
||||
secure_resource_cb_item *node = get_resource_by_path(path);
|
||||
struct list_head *sessions;
|
||||
session_item *session;
|
||||
unsigned int obsVal;
|
||||
|
||||
unsigned int sessionId = 0;
|
||||
CoAPUintOption_get(message, COAP_OPTION_SESSIONID, &sessionId);
|
||||
COAP_DEBUG("recv_msg_handler, sessionID:%d", (int)sessionId);
|
||||
if (!node) {
|
||||
return;
|
||||
}
|
||||
sessions = get_svr_session_list(context);
|
||||
session = get_session_by_checksum(sessions, remote, node->pk_dn);
|
||||
if (!session || session->sessionId != sessionId) {
|
||||
send_err_rsp(context, remote, COAP_MSG_CODE_401_UNAUTHORIZED, message);
|
||||
COAP_ERR("need auth, path:%s, from:%s", path, remote->addr);
|
||||
return;
|
||||
}
|
||||
|
||||
if (CoAPUintOption_get(message, COAP_OPTION_OBSERVE, &obsVal) == COAP_SUCCESS) {
|
||||
if (obsVal == 0) {
|
||||
CoAPObsServer_add(context, path, remote, message);
|
||||
}
|
||||
}
|
||||
|
||||
if (message->payloadlen < 256) {
|
||||
char buf[256];
|
||||
call_cb(context, path, remote, message, session->sessionKey, buf, node->cb);
|
||||
} else {
|
||||
char *buf = (char *)coap_malloc(message->payloadlen);
|
||||
if (buf) {
|
||||
call_cb(context, path, remote, message, session->sessionKey, buf, node->cb);
|
||||
coap_free(buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int alcs_resource_register_secure(CoAPContext *context, const char *pk, const char *dn, const char *path,
|
||||
unsigned short permission,
|
||||
unsigned int ctype, unsigned int maxage, CoAPRecvMsgHandler callback)
|
||||
{
|
||||
secure_resource_cb_item *node = NULL, *next_node = NULL;
|
||||
char pk_dn[100] = {0};
|
||||
int dup = 0;
|
||||
secure_resource_cb_item *item;
|
||||
|
||||
COAP_INFO("alcs_resource_register_secure");
|
||||
item = (secure_resource_cb_item *)coap_malloc(sizeof(secure_resource_cb_item));
|
||||
if (item == NULL) {
|
||||
return -1;
|
||||
}
|
||||
memset(item, 0, sizeof(secure_resource_cb_item));
|
||||
item->cb = callback;
|
||||
item->path_type = PATH_NORMAL;
|
||||
if (strstr(path, "/#") != NULL) {
|
||||
item->path_type = PATH_FILTER;
|
||||
} else {
|
||||
CoAPPathMD5_sum(path, strlen(path), item->path, MAX_PATH_CHECKSUM_LEN);
|
||||
}
|
||||
list_for_each_entry_safe(node, next_node, &secure_resource_cb_head, lst, secure_resource_cb_item) {
|
||||
if (item->path_type == PATH_NORMAL && node->path_type == PATH_NORMAL) {
|
||||
if (memcmp(node->path, item->path, MAX_PATH_CHECKSUM_LEN) == 0) {
|
||||
dup = 1;
|
||||
}
|
||||
} else if (item->path_type == PATH_FILTER && node->path_type == PATH_FILTER) {
|
||||
if (strncpy(node->filter_path, item->filter_path, strlen(item->filter_path)) == 0) {
|
||||
dup = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dup == 0) {
|
||||
if (item->path_type == PATH_FILTER) {
|
||||
item->filter_path = coap_malloc(strlen(path) + 1);
|
||||
if (item->filter_path == NULL) {
|
||||
coap_free(item);
|
||||
return -1;
|
||||
}
|
||||
memset(item->filter_path, 0, strlen(path) + 1);
|
||||
strncpy(item->filter_path, path, strlen(path));
|
||||
}
|
||||
|
||||
strncpy(pk_dn, pk, sizeof(pk_dn) - 1);
|
||||
strncat(pk_dn, dn, sizeof(pk_dn) - strlen(pk_dn) - 1);
|
||||
|
||||
CoAPPathMD5_sum(pk_dn, strlen(pk_dn), item->pk_dn, PK_DN_CHECKSUM_LEN);
|
||||
|
||||
list_add_tail(&item->lst, &secure_resource_cb_head);
|
||||
} else {
|
||||
coap_free(item);
|
||||
}
|
||||
|
||||
return CoAPResource_register(context, path, permission, ctype, maxage, &recv_msg_handler);
|
||||
}
|
||||
|
||||
void alcs_resource_cb_deinit(void)
|
||||
{
|
||||
secure_resource_cb_item *del_item = NULL;
|
||||
|
||||
list_for_each_entry(del_item, &secure_resource_cb_head, lst, secure_resource_cb_item) {
|
||||
list_del(&del_item->lst);
|
||||
if (del_item->path_type == PATH_FILTER) {
|
||||
coap_free(del_item->filter_path);
|
||||
}
|
||||
coap_free(del_item);
|
||||
del_item = list_entry(&secure_resource_cb_head, secure_resource_cb_item, lst);
|
||||
}
|
||||
}
|
||||
|
||||
void alcs_auth_list_deinit(void)
|
||||
{
|
||||
auth_list *auth_list_ctx = get_list(ctx);
|
||||
svr_key_item *del_item = NULL, *next_item = NULL;
|
||||
|
||||
list_for_each_entry_safe(del_item, next_item, &auth_list_ctx->lst_svr, lst, svr_key_item) {
|
||||
list_del(&del_item->lst);
|
||||
if (del_item->keyInfo.secret) {
|
||||
coap_free(del_item->keyInfo.secret);
|
||||
}
|
||||
coap_free(del_item);
|
||||
}
|
||||
}
|
||||
|
||||
void alcs_rec_heart_beat(CoAPContext *ctx, const char *path, NetworkAddr *remote, CoAPMessage *request)
|
||||
{
|
||||
struct list_head *ctl_head = get_svr_session_list(ctx);
|
||||
session_item *session = NULL;
|
||||
session_item *node = NULL, *next = NULL;
|
||||
int seqlen, datalen;
|
||||
char *seq, *data;
|
||||
CoAPMessage msg;
|
||||
char databuf[32];
|
||||
char payloadbuf[128];
|
||||
CoAPLenString payload;
|
||||
|
||||
COAP_DEBUG("alcs_rec_heart_beat");
|
||||
if (!ctl_head || list_empty(ctl_head)) {
|
||||
return;
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(node, next, ctl_head, lst, session_item) {
|
||||
if (node->sessionId && is_networkadd_same(&node->addr, remote)) {
|
||||
node->heart_time = HAL_UptimeMs();
|
||||
session = node;
|
||||
}
|
||||
}
|
||||
|
||||
if (!session) {
|
||||
COAP_INFO("receive stale heart beat");
|
||||
}
|
||||
|
||||
|
||||
if (!req_payload_parser((const char *)request->payload, request->payloadlen, &seq, &seqlen, &data, &datalen)) {
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
if (session) {
|
||||
HAL_Snprintf(databuf, sizeof(databuf), "\"delayTime\":%d", default_heart_expire / 1000);
|
||||
HAL_Snprintf(payloadbuf, sizeof(payloadbuf), RES_FORMAT, seqlen, seq, 200, databuf);
|
||||
} else {
|
||||
HAL_Snprintf(payloadbuf, sizeof(payloadbuf), RES_FORMAT, seqlen, seq, ALCS_HEART_FAILAUTH, "");
|
||||
}
|
||||
|
||||
payload.data = (unsigned char *)payloadbuf;
|
||||
payload.len = strlen(payloadbuf);
|
||||
alcs_msg_init(ctx, &msg, COAP_MSG_CODE_205_CONTENT, COAP_MESSAGE_TYPE_CON, 0, &payload, NULL);
|
||||
if (session) {
|
||||
msg.header.msgid = request->header.msgid;
|
||||
msg.header.tokenlen = request->header.tokenlen;
|
||||
memcpy(&msg.token, request->token, request->header.tokenlen);
|
||||
internal_secure_send(ctx, session, remote, &msg, 1, NULL);
|
||||
} else {
|
||||
CoAPLenString token = {request->header.tokenlen, request->token};
|
||||
alcs_sendrsp(ctx, remote, &msg, 1, request->header.msgid, &token);
|
||||
}
|
||||
alcs_msg_deinit(&msg);
|
||||
}
|
||||
|
||||
int observe_data_encrypt(CoAPContext *ctx, const char *path, NetworkAddr *from, CoAPMessage *message,
|
||||
CoAPLenString *src, CoAPLenString *dest)
|
||||
{
|
||||
secure_resource_cb_item *node = get_resource_by_path(path);
|
||||
struct list_head *sessions;
|
||||
session_item *session;
|
||||
COAP_DEBUG("observe_data_encrypt, src:%.*s", src->len, src->data);
|
||||
if (!node) {
|
||||
return COAP_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
sessions = get_svr_session_list(ctx);
|
||||
session = get_session_by_checksum(sessions, from, node->pk_dn);
|
||||
|
||||
if (session) {
|
||||
dest->len = (src->len & 0xfffffff0) + 16;
|
||||
dest->data = (unsigned char *)coap_malloc(dest->len);
|
||||
alcs_encrypt((const char *)src->data, src->len, session->sessionKey, dest->data);
|
||||
CoAPUintOption_add(message, COAP_OPTION_SESSIONID, session->sessionId);
|
||||
return COAP_SUCCESS;
|
||||
}
|
||||
|
||||
return COAP_ERROR_NOT_FOUND;
|
||||
}
|
||||
|
||||
void on_svr_auth_timer(CoAPContext *ctx)
|
||||
{
|
||||
struct list_head *head = get_svr_session_list(ctx);
|
||||
int tick;
|
||||
session_item *node = NULL, *next = NULL;
|
||||
|
||||
if (!head || list_empty(head)) {
|
||||
return;
|
||||
}
|
||||
/* COAP_INFO ("on_svr_auth_timer:%d", (int)HAL_UptimeMs()); */
|
||||
|
||||
/* device_auth_list* dev = get_device (ctx); */
|
||||
tick = HAL_UptimeMs();
|
||||
|
||||
list_for_each_entry_safe(node, next, head, lst, session_item) {
|
||||
if (node->sessionId && node->heart_time + default_heart_expire < tick) {
|
||||
COAP_ERR("heart beat timeout");
|
||||
remove_session(ctx, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef _IOT_EXPORT_LINKKIT_H_
|
||||
#define _IOT_EXPORT_LINKKIT_H_
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "infra_types.h"
|
||||
#include "infra_defs.h"
|
||||
|
||||
typedef enum {
|
||||
IOTX_LINKKIT_DEV_TYPE_MASTER,
|
||||
IOTX_LINKKIT_DEV_TYPE_SLAVE,
|
||||
IOTX_LINKKIT_DEV_TYPE_MAX
|
||||
} iotx_linkkit_dev_type_t;
|
||||
|
||||
typedef struct {
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1];
|
||||
char product_secret[IOTX_PRODUCT_SECRET_LEN + 1];
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1];
|
||||
char device_secret[IOTX_DEVICE_SECRET_LEN + 1];
|
||||
} iotx_linkkit_dev_meta_info_t;
|
||||
|
||||
typedef enum {
|
||||
/* post property value to cloud */
|
||||
ITM_MSG_POST_PROPERTY,
|
||||
|
||||
/* post device info update message to cloud */
|
||||
ITM_MSG_DEVICEINFO_UPDATE,
|
||||
|
||||
/* post device info delete message to cloud */
|
||||
ITM_MSG_DEVICEINFO_DELETE,
|
||||
|
||||
/* post raw data to cloud */
|
||||
ITM_MSG_POST_RAW_DATA,
|
||||
|
||||
/* only for slave device, send login request to cloud */
|
||||
ITM_MSG_LOGIN,
|
||||
|
||||
/* only for slave device, send logout request to cloud */
|
||||
ITM_MSG_LOGOUT,
|
||||
|
||||
/* only for slave device, send delete topo request to cloud */
|
||||
ITM_MSG_DELETE_TOPO,
|
||||
|
||||
/* query ntp time from cloud */
|
||||
ITM_MSG_QUERY_TIMESTAMP,
|
||||
|
||||
/* only for master device, query topo list */
|
||||
ITM_MSG_QUERY_TOPOLIST,
|
||||
|
||||
/* only for master device, qurey firmware ota data */
|
||||
ITM_MSG_QUERY_FOTA_DATA,
|
||||
|
||||
/* only for master device, qurey config ota data */
|
||||
ITM_MSG_QUERY_COTA_DATA,
|
||||
|
||||
/* only for master device, request config ota data from cloud */
|
||||
ITM_MSG_REQUEST_COTA,
|
||||
|
||||
/* only for master device, request fota image from cloud */
|
||||
ITM_MSG_REQUEST_FOTA_IMAGE,
|
||||
|
||||
/* report subdev's firmware version */
|
||||
ITM_MSG_REPORT_SUBDEV_FIRMWARE_VERSION,
|
||||
|
||||
/* get a device's desired property */
|
||||
ITM_MSG_PROPERTY_DESIRED_GET,
|
||||
|
||||
/* delete a device's desired property */
|
||||
ITM_MSG_PROPERTY_DESIRED_DELETE,
|
||||
|
||||
IOTX_LINKKIT_MSG_MAX
|
||||
} iotx_linkkit_msg_type_t;
|
||||
|
||||
/**
|
||||
* @brief create a new device
|
||||
*
|
||||
* @param dev_type. type of device which will be created. see iotx_linkkit_dev_type_t
|
||||
* @param meta_info. The product key, product secret, device name and device secret of new device.
|
||||
*
|
||||
* @return success: device id (>=0), fail: -1.
|
||||
*
|
||||
*/
|
||||
DLL_IOT_API int IOT_Linkkit_Open(iotx_linkkit_dev_type_t dev_type, iotx_linkkit_dev_meta_info_t *meta_info);
|
||||
|
||||
/**
|
||||
* @brief start device network connection.
|
||||
* for master device, start to connect aliyun server.
|
||||
* for slave device, send message to cloud for register new device and add topo with master device
|
||||
*
|
||||
* @param devid. device identifier.
|
||||
*
|
||||
* @return success: device id (>=0), fail: -1.
|
||||
*
|
||||
*/
|
||||
DLL_IOT_API int IOT_Linkkit_Connect(int devid);
|
||||
|
||||
/**
|
||||
* @brief try to receive message from cloud and dispatch these message to user event callback
|
||||
*
|
||||
* @param timeout_ms. timeout for waiting new message arrived
|
||||
*
|
||||
* @return void.
|
||||
*
|
||||
*/
|
||||
DLL_IOT_API void IOT_Linkkit_Yield(int timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief close device network connection and release resources.
|
||||
* for master device, disconnect with aliyun server and release all local resources.
|
||||
* for slave device, send message to cloud for delete topo with master device and unregister itself, then release device's resources.
|
||||
*
|
||||
* @param devid. device identifier.
|
||||
*
|
||||
* @return success: 0, fail: -1.
|
||||
*
|
||||
*/
|
||||
DLL_IOT_API int IOT_Linkkit_Close(int devid);
|
||||
|
||||
/**
|
||||
* @brief Report message to cloud
|
||||
*
|
||||
* @param devid. device identifier.
|
||||
* @param msg_type. message type. see iotx_linkkit_msg_type_t, as follows:
|
||||
* ITM_MSG_POST_PROPERTY
|
||||
* ITM_MSG_DEVICEINFO_UPDATE
|
||||
* ITM_MSG_DEVICEINFO_DELETE
|
||||
* ITM_MSG_POST_RAW_DATA
|
||||
* ITM_MSG_LOGIN
|
||||
* ITM_MSG_LOGOUT
|
||||
*
|
||||
* @param payload. message payload.
|
||||
* @param payload_len. message payload length.
|
||||
*
|
||||
* @return success: 0 or message id (>=1), fail: -1.
|
||||
*
|
||||
*/
|
||||
DLL_IOT_API int IOT_Linkkit_Report(int devid, iotx_linkkit_msg_type_t msg_type, unsigned char *payload,
|
||||
int payload_len);
|
||||
|
||||
/**
|
||||
* @brief post message to cloud
|
||||
*
|
||||
* @param devid. device identifier.
|
||||
* @param msg_type. message type. see iotx_linkkit_msg_type_t, as follows:
|
||||
* ITM_MSG_QUERY_TIMESTAMP
|
||||
* ITM_MSG_QUERY_TOPOLIST
|
||||
* ITM_MSG_QUERY_FOTA_DATA
|
||||
* ITM_MSG_QUERY_COTA_DATA
|
||||
* ITM_MSG_REQUEST_COTA
|
||||
* ITM_MSG_REQUEST_FOTA_IMAGE
|
||||
*
|
||||
* @param payload. message payload.
|
||||
* @param payload_len. message payload length.
|
||||
*
|
||||
* @return success: 0 or message id (>=1), fail: -1.
|
||||
*
|
||||
*/
|
||||
DLL_IOT_API int IOT_Linkkit_Query(int devid, iotx_linkkit_msg_type_t msg_type, unsigned char *payload,
|
||||
int payload_len);
|
||||
|
||||
/**
|
||||
* @brief post event to cloud
|
||||
*
|
||||
* @param devid. device identifier.
|
||||
* @param eventid. tsl event id.
|
||||
* @param eventid_len. length of tsl event id.
|
||||
* @param payload. event payload.
|
||||
* @param payload_len. event payload length.
|
||||
*
|
||||
* @return success: message id (>=1), fail: -1.
|
||||
*
|
||||
*/
|
||||
DLL_IOT_API int IOT_Linkkit_TriggerEvent(int devid, char *eventid, int eventid_len, char *payload, int payload_len);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,738 @@
|
||||
#include "iotx_dm_internal.h"
|
||||
|
||||
#ifdef DEV_BIND_ENABLED
|
||||
#include "dev_bind_api.h"
|
||||
#endif
|
||||
#ifdef LOG_REPORT_TO_CLOUD
|
||||
#include "iotx_log_report.h"
|
||||
#endif
|
||||
|
||||
static dm_client_uri_map_t g_dm_client_uri_map[] = {
|
||||
#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
|
||||
{DM_URI_THING_EVENT_POST_REPLY_WILDCARD, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_event_post_reply },
|
||||
#ifdef DEVICE_MODEL_SHADOW
|
||||
{DM_URI_THING_PROPERTY_DESIRED_DELETE_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_property_desired_delete_reply},
|
||||
{DM_URI_THING_PROPERTY_DESIRED_GET_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_property_desired_get_reply },
|
||||
{DM_URI_THING_SERVICE_PROPERTY_GET, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_service_property_get },
|
||||
#endif
|
||||
{DM_URI_THING_SERVICE_PROPERTY_SET, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_service_property_set },
|
||||
{DM_URI_THING_SERVICE_REQUEST_WILDCARD, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_service_request },
|
||||
{DM_URI_THING_DEVICEINFO_UPDATE_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_deviceinfo_update_reply },
|
||||
{DM_URI_THING_DEVICEINFO_DELETE_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_deviceinfo_delete_reply },
|
||||
{DM_URI_THING_DYNAMICTSL_GET_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_dynamictsl_get_reply },
|
||||
{DM_URI_RRPC_REQUEST_WILDCARD, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_rrpc_request_wildcard },
|
||||
{DM_URI_NTP_RESPONSE, DM_URI_EXT_NTP_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_ntp_response },
|
||||
{NULL, DM_URI_EXT_ERROR_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_ext_error },
|
||||
#endif
|
||||
{DM_URI_THING_MODEL_DOWN_RAW, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_model_down_raw },
|
||||
{DM_URI_THING_MODEL_UP_RAW_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_ALL, (void *)dm_client_thing_model_up_raw_reply },
|
||||
|
||||
#ifdef DEVICE_MODEL_GATEWAY
|
||||
{DM_URI_THING_TOPO_ADD_NOTIFY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_topo_add_notify },
|
||||
{DM_URI_THING_GATEWAY_PERMIT, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_gateway_permit },
|
||||
{DM_URI_THING_SUB_REGISTER_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_sub_register_reply },
|
||||
{DM_URI_THING_SUB_UNREGISTER_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_sub_unregister_reply },
|
||||
{DM_URI_THING_TOPO_ADD_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_topo_add_reply },
|
||||
{DM_URI_THING_TOPO_DELETE_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_topo_delete_reply },
|
||||
{DM_URI_THING_TOPO_GET_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_topo_get_reply },
|
||||
{DM_URI_THING_LIST_FOUND_REPLY, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_list_found_reply },
|
||||
{DM_URI_COMBINE_LOGIN_REPLY, DM_URI_EXT_SESSION_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_combine_login_reply },
|
||||
{DM_URI_COMBINE_LOGOUT_REPLY, DM_URI_EXT_SESSION_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_combine_logout_reply },
|
||||
{DM_URI_THING_DISABLE, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_disable },
|
||||
{DM_URI_THING_ENABLE, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_enable },
|
||||
{DM_URI_THING_DELETE, DM_URI_SYS_PREFIX, IOTX_DM_DEVICE_GATEWAY, (void *)dm_client_thing_delete },
|
||||
#endif
|
||||
};
|
||||
|
||||
static int _dm_client_subscribe_filter(char *uri, char *uri_name, char product_key[IOTX_PRODUCT_KEY_LEN + 1],
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1])
|
||||
{
|
||||
#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
|
||||
int res = 0;
|
||||
#endif
|
||||
if (uri_name == NULL) {
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
|
||||
if (strlen(uri_name) == strlen(DM_URI_THING_EVENT_POST_REPLY_WILDCARD) &&
|
||||
memcmp(uri_name, DM_URI_THING_EVENT_POST_REPLY_WILDCARD, strlen(uri_name)) == 0) {
|
||||
int event_post_reply_opt = 0;
|
||||
res = dm_opt_get(DM_OPT_DOWNSTREAM_EVENT_POST_REPLY, &event_post_reply_opt);
|
||||
if (res == SUCCESS_RETURN && event_post_reply_opt == 0) {
|
||||
dm_client_unsubscribe(uri);
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_client_subscribe_all(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1],
|
||||
int dev_type)
|
||||
{
|
||||
int res = 0, index = 0, fail_count = 0;
|
||||
int number = sizeof(g_dm_client_uri_map) / sizeof(dm_client_uri_map_t);
|
||||
char *uri = NULL;
|
||||
uint8_t local_sub = 0;
|
||||
#ifdef SUB_PERSISTENCE_ENABLED
|
||||
char device_key[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 4] = {0};
|
||||
#endif
|
||||
|
||||
#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
|
||||
index = 1;
|
||||
|
||||
for (fail_count = 0; fail_count < IOTX_DM_CLIENT_SUB_RETRY_MAX_COUNTS; fail_count++) {
|
||||
|
||||
res = dm_utils_service_name((char *)g_dm_client_uri_map[0].uri_prefix, (char *)g_dm_client_uri_map[0].uri_name,
|
||||
product_key, device_name, &uri);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
continue;
|
||||
}
|
||||
res = _dm_client_subscribe_filter(uri, (char *)g_dm_client_uri_map[0].uri_name, product_key, device_name);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
DM_free(uri);
|
||||
continue;
|
||||
}
|
||||
|
||||
res = dm_client_subscribe(uri, (iotx_cm_data_handle_cb)g_dm_client_uri_map[0].callback, 0);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
DM_free(uri);
|
||||
continue;
|
||||
}
|
||||
|
||||
DM_free(uri);
|
||||
break;
|
||||
}
|
||||
#else
|
||||
index = 0;
|
||||
#endif
|
||||
fail_count = 0;
|
||||
#ifdef SUB_PERSISTENCE_ENABLED
|
||||
{
|
||||
int len = 1;
|
||||
HAL_Snprintf(device_key, IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN, "qub_%s%s", product_key, device_name);
|
||||
HAL_Kv_Get(device_key, &local_sub, &len);
|
||||
}
|
||||
#endif
|
||||
|
||||
for (; index < number; index++) {
|
||||
if ((g_dm_client_uri_map[index].dev_type & dev_type) == 0) {
|
||||
continue;
|
||||
}
|
||||
dm_log_info("index: %d", index);
|
||||
|
||||
if (fail_count >= IOTX_DM_CLIENT_SUB_RETRY_MAX_COUNTS) {
|
||||
fail_count = 0;
|
||||
continue;
|
||||
}
|
||||
res = dm_utils_service_name((char *)g_dm_client_uri_map[index].uri_prefix, (char *)g_dm_client_uri_map[index].uri_name,
|
||||
product_key, device_name, &uri);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
index--;
|
||||
continue;
|
||||
}
|
||||
|
||||
res = _dm_client_subscribe_filter(uri, (char *)g_dm_client_uri_map[index].uri_name, product_key, device_name);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
DM_free(uri);
|
||||
continue;
|
||||
}
|
||||
|
||||
res = dm_client_subscribe(uri, (iotx_cm_data_handle_cb)g_dm_client_uri_map[index].callback, &local_sub);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
index--;
|
||||
fail_count++;
|
||||
DM_free(uri);
|
||||
continue;
|
||||
}
|
||||
|
||||
fail_count = 0;
|
||||
DM_free(uri);
|
||||
}
|
||||
#ifdef SUB_PERSISTENCE_ENABLED
|
||||
local_sub = 1;
|
||||
HAL_Kv_Set(device_key, &local_sub, 1, 1);
|
||||
#endif
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
static void _dm_client_event_cloud_connected_handle(void)
|
||||
{
|
||||
dm_log_info("IOTX_CM_EVENT_CLOUD_CONNECTED");
|
||||
|
||||
#ifdef DEV_BIND_ENABLED
|
||||
awss_report_cloud();
|
||||
#endif
|
||||
dm_msg_cloud_connected();
|
||||
}
|
||||
|
||||
static void _dm_client_event_cloud_disconnect_handle(void)
|
||||
{
|
||||
dm_log_info("IOTX_CM_EVENT_CLOUD_DISCONNECT");
|
||||
|
||||
dm_msg_cloud_disconnect();
|
||||
}
|
||||
|
||||
void dm_client_event_handle(int fd, iotx_cm_event_msg_t *event, void *context)
|
||||
{
|
||||
switch (event->type) {
|
||||
case IOTX_CM_EVENT_CLOUD_CONNECTED: {
|
||||
_dm_client_event_cloud_connected_handle();
|
||||
}
|
||||
break;
|
||||
case IOTX_CM_EVENT_CLOUD_CONNECT_FAILED: {
|
||||
|
||||
}
|
||||
break;
|
||||
case IOTX_CM_EVENT_CLOUD_DISCONNECT: {
|
||||
_dm_client_event_cloud_disconnect_handle();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void dm_client_thing_model_down_raw(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context)
|
||||
{
|
||||
dm_msg_source_t source;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dm_msg_proc_thing_model_down_raw(&source);
|
||||
}
|
||||
|
||||
void dm_client_thing_model_up_raw_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context)
|
||||
{
|
||||
dm_msg_source_t source;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dm_msg_proc_thing_model_up_raw_reply(&source);
|
||||
}
|
||||
#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
|
||||
void dm_client_thing_service_property_set(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_source_t source;
|
||||
dm_msg_dest_t dest;
|
||||
dm_msg_request_payload_t request;
|
||||
dm_msg_response_t response;
|
||||
int prop_set_reply_opt = 0;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
memset(&dest, 0, sizeof(dm_msg_dest_t));
|
||||
memset(&request, 0, sizeof(dm_msg_request_payload_t));
|
||||
memset(&response, 0, sizeof(dm_msg_response_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dest.uri_name = DM_URI_THING_SERVICE_PROPERTY_SET_REPLY;
|
||||
|
||||
res = dm_msg_proc_thing_service_property_set(&source, &dest, &request, &response);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return;
|
||||
}
|
||||
|
||||
prop_set_reply_opt = 0;
|
||||
res = dm_opt_get(DM_OPT_UPSTREAM_PROPERTY_SET_REPLY, &prop_set_reply_opt);
|
||||
if (res == SUCCESS_RETURN) {
|
||||
if (prop_set_reply_opt) {
|
||||
dm_msg_response(DM_MSG_DEST_CLOUD, &request, &response, "{}", strlen("{}"), NULL);
|
||||
#ifdef LOG_REPORT_TO_CLOUD
|
||||
if (SUCCESS_RETURN == check_target_msg(request.id.value, request.id.value_length)) {
|
||||
send_permance_info(request.id.value, request.id.value_length, "2", 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEVICE_MODEL_SHADOW
|
||||
void dm_client_thing_service_property_get(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_source_t source;
|
||||
dm_msg_dest_t dest;
|
||||
dm_msg_request_payload_t request;
|
||||
dm_msg_response_t response;
|
||||
unsigned char *data = NULL;
|
||||
int data_len = 0;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
memset(&dest, 0, sizeof(dm_msg_dest_t));
|
||||
memset(&request, 0, sizeof(dm_msg_request_payload_t));
|
||||
memset(&response, 0, sizeof(dm_msg_response_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dest.uri_name = DM_URI_THING_SERVICE_PROPERTY_GET_REPLY;
|
||||
|
||||
res = dm_msg_proc_thing_service_property_get(&source, &dest, &request, &response, &data, &data_len);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void dm_client_thing_service_request(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context)
|
||||
{
|
||||
dm_msg_source_t source;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dm_msg_proc_thing_service_request(&source);
|
||||
}
|
||||
|
||||
void dm_client_thing_event_post_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context)
|
||||
{
|
||||
dm_msg_source_t source;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dm_msg_proc_thing_event_post_reply(&source);
|
||||
}
|
||||
#ifdef DEVICE_MODEL_SHADOW
|
||||
void dm_client_thing_property_desired_get_reply(int fd, const char *topic, const char *payload,
|
||||
unsigned int payload_len, void *context)
|
||||
{
|
||||
dm_msg_source_t source;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dm_msg_proc_thing_property_desired_get_reply(&source);
|
||||
}
|
||||
|
||||
void dm_client_thing_property_desired_delete_reply(int fd, const char *topic, const char *payload,
|
||||
unsigned int payload_len, void *context)
|
||||
{
|
||||
dm_msg_source_t source;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dm_msg_proc_thing_property_desired_delete_reply(&source);
|
||||
}
|
||||
#endif
|
||||
|
||||
void dm_client_thing_deviceinfo_update_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context)
|
||||
{
|
||||
dm_msg_source_t source;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dm_msg_proc_thing_deviceinfo_update_reply(&source);
|
||||
}
|
||||
|
||||
void dm_client_thing_deviceinfo_delete_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context)
|
||||
{
|
||||
dm_msg_source_t source;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dm_msg_proc_thing_deviceinfo_delete_reply(&source);
|
||||
}
|
||||
|
||||
void dm_client_thing_dynamictsl_get_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context)
|
||||
{
|
||||
dm_msg_source_t source;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dm_msg_proc_thing_dynamictsl_get_reply(&source);
|
||||
}
|
||||
|
||||
void dm_client_rrpc_request_wildcard(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context)
|
||||
{
|
||||
dm_msg_source_t source;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dm_msg_proc_rrpc_request(&source);
|
||||
}
|
||||
|
||||
void dm_client_ntp_response(int fd, const char *topic, const char *payload, unsigned int payload_len, void *context)
|
||||
{
|
||||
dm_msg_source_t source;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dm_disp_ntp_response(&source);
|
||||
}
|
||||
|
||||
void dm_client_ext_error(int fd, const char *topic, const char *payload, unsigned int payload_len, void *context)
|
||||
{
|
||||
dm_msg_source_t source;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dm_disp_ext_error_response(&source);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEVICE_MODEL_GATEWAY
|
||||
int dm_client_subdev_unsubscribe(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1])
|
||||
{
|
||||
int res = 0, index = 0;
|
||||
int number = sizeof(g_dm_client_uri_map) / sizeof(dm_client_uri_map_t);
|
||||
char *uri = NULL;
|
||||
|
||||
for (index = 0; index < number; index++) {
|
||||
if ((g_dm_client_uri_map[index].dev_type & IOTX_DM_DEVICE_SUBDEV) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
res = dm_utils_service_name((char *)g_dm_client_uri_map[index].uri_prefix, (char *)g_dm_client_uri_map[index].uri_name,
|
||||
product_key, device_name, &uri);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
index--;
|
||||
continue;
|
||||
}
|
||||
|
||||
dm_client_unsubscribe(uri);
|
||||
DM_free(uri);
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
void dm_client_thing_topo_add_notify(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_source_t source;
|
||||
dm_msg_dest_t dest;
|
||||
dm_msg_request_payload_t request;
|
||||
dm_msg_response_t response;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
memset(&dest, 0, sizeof(dm_msg_dest_t));
|
||||
memset(&request, 0, sizeof(dm_msg_request_payload_t));
|
||||
memset(&response, 0, sizeof(dm_msg_response_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dest.uri_name = DM_URI_THING_TOPO_ADD_NOTIFY_REPLY;
|
||||
|
||||
res = dm_msg_proc_thing_topo_add_notify(&source, &dest, &request, &response);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return;
|
||||
}
|
||||
|
||||
dm_msg_response(DM_MSG_DEST_CLOUD, &request, &response, "{}", strlen("{}"), NULL);
|
||||
}
|
||||
|
||||
void dm_client_thing_disable(int fd, const char *topic, const char *payload, unsigned int payload_len, void *context)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_source_t source;
|
||||
dm_msg_dest_t dest;
|
||||
dm_msg_request_payload_t request;
|
||||
dm_msg_response_t response;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
memset(&dest, 0, sizeof(dm_msg_dest_t));
|
||||
memset(&request, 0, sizeof(dm_msg_request_payload_t));
|
||||
memset(&response, 0, sizeof(dm_msg_response_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dest.uri_name = DM_URI_THING_DISABLE_REPLY;
|
||||
|
||||
res = dm_msg_proc_thing_disable(&source, &dest, &request, &response);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return;
|
||||
}
|
||||
|
||||
dm_msg_response(DM_MSG_DEST_CLOUD, &request, &response, "{}", strlen("{}"), NULL);
|
||||
}
|
||||
|
||||
void dm_client_thing_enable(int fd, const char *topic, const char *payload, unsigned int payload_len, void *context)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_source_t source;
|
||||
dm_msg_dest_t dest;
|
||||
dm_msg_request_payload_t request;
|
||||
dm_msg_response_t response;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
memset(&dest, 0, sizeof(dm_msg_dest_t));
|
||||
memset(&request, 0, sizeof(dm_msg_request_payload_t));
|
||||
memset(&response, 0, sizeof(dm_msg_response_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dest.uri_name = DM_URI_THING_ENABLE_REPLY;
|
||||
|
||||
res = dm_msg_proc_thing_enable(&source, &dest, &request, &response);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return;
|
||||
}
|
||||
|
||||
dm_msg_response(DM_MSG_DEST_CLOUD, &request, &response, "{}", strlen("{}"), NULL);
|
||||
}
|
||||
|
||||
void dm_client_thing_delete(int fd, const char *topic, const char *payload, unsigned int payload_len, void *context)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_source_t source;
|
||||
dm_msg_dest_t dest;
|
||||
dm_msg_request_payload_t request;
|
||||
dm_msg_response_t response;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
memset(&dest, 0, sizeof(dm_msg_dest_t));
|
||||
memset(&request, 0, sizeof(dm_msg_request_payload_t));
|
||||
memset(&response, 0, sizeof(dm_msg_response_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dest.uri_name = DM_URI_THING_DELETE_REPLY;
|
||||
|
||||
res = dm_msg_proc_thing_delete(&source, &dest, &request, &response);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return;
|
||||
}
|
||||
|
||||
dm_msg_response(DM_MSG_DEST_CLOUD, &request, &response, "{}", strlen("{}"), NULL);
|
||||
}
|
||||
|
||||
void dm_client_thing_gateway_permit(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_source_t source;
|
||||
dm_msg_dest_t dest;
|
||||
dm_msg_request_payload_t request;
|
||||
dm_msg_response_t response;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
memset(&dest, 0, sizeof(dm_msg_dest_t));
|
||||
memset(&request, 0, sizeof(dm_msg_request_payload_t));
|
||||
memset(&response, 0, sizeof(dm_msg_response_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dest.uri_name = DM_URI_THING_GATEWAY_PERMIT_REPLY;
|
||||
|
||||
res = dm_msg_proc_thing_gateway_permit(&source, &dest, &request, &response);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return;
|
||||
}
|
||||
|
||||
dm_msg_response(DM_MSG_DEST_CLOUD, &request, &response, "{}", strlen("{}"), NULL);
|
||||
}
|
||||
|
||||
void dm_client_thing_sub_register_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context)
|
||||
{
|
||||
dm_msg_source_t source;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dm_msg_proc_thing_sub_register_reply(&source);
|
||||
}
|
||||
|
||||
void dm_client_thing_sub_unregister_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context)
|
||||
{
|
||||
dm_msg_source_t source;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dm_msg_proc_thing_sub_unregister_reply(&source);
|
||||
}
|
||||
|
||||
void dm_client_thing_topo_add_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context)
|
||||
{
|
||||
dm_msg_source_t source;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dm_msg_proc_thing_topo_add_reply(&source);
|
||||
}
|
||||
|
||||
void dm_client_thing_topo_delete_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context)
|
||||
{
|
||||
dm_msg_source_t source;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dm_msg_proc_thing_topo_delete_reply(&source);
|
||||
}
|
||||
|
||||
void dm_client_thing_topo_get_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context)
|
||||
{
|
||||
dm_msg_source_t source;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dm_msg_proc_thing_topo_get_reply(&source);
|
||||
}
|
||||
|
||||
void dm_client_thing_list_found_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context)
|
||||
{
|
||||
dm_msg_source_t source;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dm_msg_proc_thing_list_found_reply(&source);
|
||||
}
|
||||
|
||||
void dm_client_combine_login_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context)
|
||||
{
|
||||
dm_msg_source_t source;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dm_msg_proc_combine_login_reply(&source);
|
||||
}
|
||||
|
||||
void dm_client_combine_logout_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context)
|
||||
{
|
||||
dm_msg_source_t source;
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
|
||||
source.uri = topic;
|
||||
source.payload = (unsigned char *)payload;
|
||||
source.payload_len = payload_len;
|
||||
source.context = NULL;
|
||||
|
||||
dm_msg_proc_combine_logout_reply(&source);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,75 @@
|
||||
#ifndef _DM_CLIENT_H_
|
||||
#define _DM_CLIENT_H_
|
||||
|
||||
typedef struct {
|
||||
const char *uri_name;
|
||||
const char *uri_prefix;
|
||||
int dev_type;
|
||||
void *callback;
|
||||
} dm_client_uri_map_t;
|
||||
|
||||
void dm_client_event_handle(int fd, iotx_cm_event_msg_t *event, void *context);
|
||||
|
||||
int dm_client_subscribe_all(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1], int dev_type);
|
||||
|
||||
void dm_client_thing_model_down_raw(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
void dm_client_thing_model_up_raw_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
|
||||
#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
|
||||
void dm_client_thing_property_desired_get_reply(int fd, const char *topic, const char *payload,
|
||||
unsigned int payload_len, void *context);
|
||||
void dm_client_thing_property_desired_delete_reply(int fd, const char *topic, const char *payload,
|
||||
unsigned int payload_len, void *context);
|
||||
void dm_client_thing_service_property_set(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
void dm_client_thing_service_property_get(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
void dm_client_thing_service_property_post(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
void dm_client_thing_event_property_post_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
void dm_client_thing_deviceinfo_update_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
void dm_client_thing_deviceinfo_delete_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
void dm_client_thing_dynamictsl_get_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
void dm_client_thing_service_request(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
void dm_client_thing_event_post_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
void dm_client_rrpc_request_wildcard(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
void dm_client_ntp_response(int fd, const char *topic, const char *payload, unsigned int payload_len, void *context);
|
||||
void dm_client_ext_error(int fd, const char *topic, const char *payload, unsigned int payload_len, void *context);
|
||||
#endif
|
||||
|
||||
#ifdef DEVICE_MODEL_GATEWAY
|
||||
int dm_client_subdev_unsubscribe(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1]);
|
||||
void dm_client_thing_topo_add_notify(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
void dm_client_thing_disable(int fd, const char *topic, const char *payload, unsigned int payload_len, void *context);
|
||||
void dm_client_thing_enable(int fd, const char *topic, const char *payload, unsigned int payload_len, void *context);
|
||||
void dm_client_thing_delete(int fd, const char *topic, const char *payload, unsigned int payload_len, void *context);
|
||||
void dm_client_thing_gateway_permit(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
void dm_client_thing_sub_register_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
void dm_client_thing_sub_unregister_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
void dm_client_thing_topo_add_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
void dm_client_thing_topo_delete_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
void dm_client_thing_topo_get_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
void dm_client_thing_list_found_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
void dm_client_combine_login_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
void dm_client_combine_logout_reply(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,145 @@
|
||||
#include "iotx_dm_internal.h"
|
||||
|
||||
static dm_client_ctx_t g_dm_client_ctx = {0};
|
||||
|
||||
static dm_client_ctx_t *dm_client_get_ctx(void)
|
||||
{
|
||||
return &g_dm_client_ctx;
|
||||
}
|
||||
|
||||
int dm_client_open(void)
|
||||
{
|
||||
int res = 0;
|
||||
dm_client_ctx_t *ctx = dm_client_get_ctx();
|
||||
iotx_cm_init_param_t cm_param;
|
||||
|
||||
memset(ctx, 0, sizeof(dm_client_ctx_t));
|
||||
memset(&cm_param, 0, sizeof(iotx_cm_init_param_t));
|
||||
|
||||
cm_param.request_timeout_ms = IOTX_DM_CLIENT_REQUEST_TIMEOUT_MS;
|
||||
cm_param.keepalive_interval_ms = IOTX_DM_CLIENT_KEEPALIVE_INTERVAL_MS;
|
||||
cm_param.write_buf_size = CONFIG_MQTT_TX_MAXLEN;
|
||||
cm_param.read_buf_size = CONFIG_MQTT_RX_MAXLEN;
|
||||
#if defined(COAP_COMM_ENABLED) && !defined(MQTT_COMM_ENABLED)
|
||||
cm_param.protocol_type = IOTX_CM_PROTOCOL_TYPE_COAP;
|
||||
#else
|
||||
cm_param.protocol_type = IOTX_CM_PROTOCOL_TYPE_MQTT;
|
||||
#endif
|
||||
cm_param.handle_event = dm_client_event_handle;
|
||||
|
||||
res = iotx_cm_open(&cm_param);
|
||||
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return res;
|
||||
}
|
||||
ctx->fd = res;
|
||||
|
||||
dm_log_info("CM Fd: %d", ctx->fd);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_client_connect(int timeout_ms)
|
||||
{
|
||||
int res = 0;
|
||||
dm_client_ctx_t *ctx = dm_client_get_ctx();
|
||||
|
||||
res = iotx_cm_connect(ctx->fd, timeout_ms);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return res;
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_client_close(void)
|
||||
{
|
||||
dm_client_ctx_t *ctx = dm_client_get_ctx();
|
||||
|
||||
return iotx_cm_close(ctx->fd);
|
||||
}
|
||||
|
||||
int dm_client_subscribe(char *uri, iotx_cm_data_handle_cb callback, void *context)
|
||||
{
|
||||
int res = 0;
|
||||
uint8_t local_sub = 0;
|
||||
dm_client_ctx_t *ctx = dm_client_get_ctx();
|
||||
iotx_cm_ext_params_t sub_params;
|
||||
|
||||
memset(&sub_params, 0, sizeof(iotx_cm_ext_params_t));
|
||||
if (context != NULL) {
|
||||
local_sub = *((uint8_t *)context);
|
||||
}
|
||||
|
||||
if (local_sub == 1) {
|
||||
sub_params.ack_type = IOTX_CM_MESSAGE_SUB_LOCAL;
|
||||
sub_params.sync_mode = IOTX_CM_ASYNC;
|
||||
} else {
|
||||
sub_params.ack_type = IOTX_CM_MESSAGE_NO_ACK;
|
||||
sub_params.sync_mode = IOTX_CM_SYNC;
|
||||
}
|
||||
|
||||
sub_params.sync_timeout = IOTX_DM_CLIENT_SUB_TIMEOUT_MS;
|
||||
sub_params.ack_cb = NULL;
|
||||
|
||||
res = iotx_cm_sub(ctx->fd, &sub_params, (const char *)uri, callback, NULL);
|
||||
dm_log_info("Subscribe Result: %d", res);
|
||||
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return res;
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_client_unsubscribe(char *uri)
|
||||
{
|
||||
int res = 0;
|
||||
dm_client_ctx_t *ctx = dm_client_get_ctx();
|
||||
|
||||
res = iotx_cm_unsub(ctx->fd, uri);
|
||||
|
||||
dm_log_info("Unsubscribe Result: %d", res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int dm_client_publish(char *uri, unsigned char *payload, int payload_len, iotx_cm_data_handle_cb callback)
|
||||
{
|
||||
int res = 0;
|
||||
char *pub_uri = NULL;
|
||||
dm_client_ctx_t *ctx = dm_client_get_ctx();
|
||||
iotx_cm_ext_params_t pub_param;
|
||||
|
||||
memset(&pub_param, 0, sizeof(iotx_cm_ext_params_t));
|
||||
pub_param.ack_type = IOTX_CM_MESSAGE_NO_ACK;
|
||||
pub_param.sync_mode = IOTX_CM_ASYNC;
|
||||
pub_param.sync_timeout = 0;
|
||||
pub_param.ack_cb = NULL;
|
||||
|
||||
#if defined(COAP_COMM_ENABLED) && !defined(MQTT_COMM_ENABLED)
|
||||
pub_param.ack_cb = callback;
|
||||
res = dm_utils_uri_add_prefix("/topic", uri, &pub_uri);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
#else
|
||||
pub_uri = uri;
|
||||
#endif
|
||||
|
||||
res = iotx_cm_pub(ctx->fd, &pub_param, (const char *)pub_uri, (const char *)payload, (unsigned int)payload_len);
|
||||
dm_log_info("Publish Result: %d", res);
|
||||
|
||||
#if defined(COAP_COMM_ENABLED) && !defined(MQTT_COMM_ENABLED)
|
||||
DM_free(pub_uri);
|
||||
#endif
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int dm_client_yield(unsigned int timeout)
|
||||
{
|
||||
dm_client_ctx_t *ctx = dm_client_get_ctx();
|
||||
|
||||
return iotx_cm_yield(ctx->fd, timeout);
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#ifndef _DM_CLIENT_ADAPTER_H_
|
||||
#define _DM_CLIENT_ADAPTER_H_
|
||||
|
||||
typedef struct {
|
||||
int fd;
|
||||
iotx_conn_info_t *conn_info;
|
||||
void *callback;
|
||||
} dm_client_ctx_t;
|
||||
|
||||
int dm_client_open(void);
|
||||
int dm_client_connect(int timeout_ms);
|
||||
int dm_client_close(void);
|
||||
int dm_client_subscribe(char *uri, iotx_cm_data_handle_cb callback, void *context);
|
||||
int dm_client_unsubscribe(char *uri);
|
||||
int dm_client_publish(char *uri, unsigned char *payload, int payload_len, iotx_cm_data_handle_cb callback);
|
||||
int dm_client_yield(unsigned int timeout);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,236 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
#include "iotx_dm_internal.h"
|
||||
|
||||
#if defined(OTA_ENABLED) && !defined(BUILD_AOS)
|
||||
|
||||
#ifdef INFRA_MEM_STATS
|
||||
#include "infra_mem_stats.h"
|
||||
#define DM_COTA_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "dm.cota")
|
||||
#define DM_COTA_FREE(ptr) LITE_free(ptr)
|
||||
#else
|
||||
#define DM_COTA_MALLOC(size) HAL_Malloc(size)
|
||||
#define DM_COTA_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
|
||||
#endif
|
||||
|
||||
static dm_cota_ctx_t g_dm_cota_ctx;
|
||||
|
||||
static dm_cota_ctx_t *_dm_cota_get_ctx(void)
|
||||
{
|
||||
return &g_dm_cota_ctx;
|
||||
}
|
||||
|
||||
int dm_cota_init(void)
|
||||
{
|
||||
dm_cota_ctx_t *ctx = _dm_cota_get_ctx();
|
||||
|
||||
memset(ctx, 0, sizeof(dm_cota_ctx_t));
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_cota_deinit(void)
|
||||
{
|
||||
dm_cota_ctx_t *ctx = _dm_cota_get_ctx();
|
||||
|
||||
memset(ctx, 0, sizeof(dm_cota_ctx_t));
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
static int _dm_cota_send_new_config_to_user(void *ota_handle)
|
||||
{
|
||||
int res = 0, message_len = 0;
|
||||
char *message = NULL;
|
||||
uint32_t config_size = 0;
|
||||
char *config_id = NULL, *sign = NULL, *sign_method = NULL, *url = NULL, *get_type = NULL;
|
||||
const char *cota_new_config_fmt =
|
||||
"{\"configId\":\"%s\",\"configSize\":%d,\"getType\":\"%s\",\"sign\":\"%s\",\"signMethod\":\"%s\",\"url\":\"%s\"}";
|
||||
|
||||
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_COTA_CONFIG_ID, (void *)&config_id, 1);
|
||||
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_COTA_CONFIG_SIZE, &config_size, 4);
|
||||
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_COTA_SIGN, (void *)&sign, 1);
|
||||
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_COTA_SIGN_METHOD, (void *)&sign_method, 1);
|
||||
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_COTA_URL, (void *)&url, 1);
|
||||
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_COTA_GETTYPE, (void *)&get_type, 1);
|
||||
|
||||
if (config_id == NULL || sign == NULL || sign_method == NULL || url == NULL || get_type == NULL) {
|
||||
res = FAIL_RETURN;
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
message_len = strlen(cota_new_config_fmt) + strlen(config_id) + DM_UTILS_UINT32_STRLEN + strlen(get_type) +
|
||||
strlen(sign) + strlen(sign_method) + strlen(url) + 1;
|
||||
|
||||
message = DM_malloc(message_len);
|
||||
if (message == NULL) {
|
||||
res = DM_MEMORY_NOT_ENOUGH;
|
||||
goto ERROR;
|
||||
}
|
||||
memset(message, 0, message_len);
|
||||
HAL_Snprintf(message, message_len, cota_new_config_fmt, config_id, config_size, get_type, sign, sign_method, url);
|
||||
|
||||
dm_log_info("Send To User: %s", message);
|
||||
|
||||
res = _dm_msg_send_to_user(IOTX_DM_EVENT_COTA_NEW_CONFIG, message);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
if (message) {
|
||||
DM_free(message);
|
||||
}
|
||||
res = FAIL_RETURN;
|
||||
goto ERROR;
|
||||
}
|
||||
|
||||
res = SUCCESS_RETURN;
|
||||
ERROR:
|
||||
if (config_id) {
|
||||
DM_COTA_FREE(config_id);
|
||||
}
|
||||
if (sign) {
|
||||
DM_COTA_FREE(sign);
|
||||
}
|
||||
if (sign_method) {
|
||||
DM_COTA_FREE(sign_method);
|
||||
}
|
||||
if (url) {
|
||||
DM_COTA_FREE(url);
|
||||
}
|
||||
if (get_type) {
|
||||
DM_COTA_FREE(get_type);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int dm_cota_perform_sync(_OU_ char *output, _IN_ int output_len)
|
||||
{
|
||||
int res = 0, file_download = 0;
|
||||
uint32_t file_size = 0, file_downloaded = 0;
|
||||
uint32_t percent_pre = 0, percent_now = 0;
|
||||
unsigned long long report_pre = 0, report_now = 0;
|
||||
dm_cota_ctx_t *ctx = _dm_cota_get_ctx();
|
||||
void *ota_handle = NULL;
|
||||
uint32_t ota_type = IOT_OTAT_NONE;
|
||||
|
||||
if (output == NULL || output_len <= 0) {
|
||||
return DM_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Get Ota Handle */
|
||||
res = dm_ota_get_ota_handle(&ota_handle);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
if (ota_handle == NULL) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_OTA_TYPE, &ota_type, 4);
|
||||
|
||||
if (ota_type != IOT_OTAT_COTA) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* reset the size_fetched in ota_handle to be 0 */
|
||||
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_RESET_FETCHED_SIZE, ota_handle, 4);
|
||||
/* Prepare Write Data To Storage */
|
||||
HAL_Firmware_Persistence_Start();
|
||||
|
||||
while (1) {
|
||||
file_download = IOT_OTA_FetchYield(ota_handle, output, output_len, 1);
|
||||
if (file_download < 0) {
|
||||
IOT_OTA_ReportProgress(ota_handle, IOT_OTAP_FETCH_FAILED, NULL);
|
||||
HAL_Firmware_Persistence_Stop();
|
||||
ctx->is_report_new_config = 0;
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Write Config File Into Stroage */
|
||||
HAL_Firmware_Persistence_Write(output, file_download);
|
||||
|
||||
/* Get OTA information */
|
||||
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_FETCHED_SIZE, &file_downloaded, 4);
|
||||
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_FILE_SIZE, &file_size, 4);
|
||||
|
||||
/* Calculate Download Percent And Update Report Timestamp*/
|
||||
percent_now = (file_downloaded * 100) / file_size;
|
||||
report_now = HAL_UptimeMs();
|
||||
|
||||
/* Report Download Process To Cloud */
|
||||
if (report_now < report_pre) {
|
||||
report_pre = report_now;
|
||||
}
|
||||
if ((((percent_now - percent_pre) > 5) &&
|
||||
((report_now - report_pre) > 50)) || (percent_now >= IOT_OTAP_FETCH_PERCENTAGE_MAX)) {
|
||||
IOT_OTA_ReportProgress(ota_handle, percent_now, NULL);
|
||||
percent_pre = percent_now;
|
||||
report_pre = report_now;
|
||||
}
|
||||
|
||||
/* Check If OTA Finished */
|
||||
if (IOT_OTA_IsFetchFinish(ota_handle)) {
|
||||
uint32_t file_isvalid = 0;
|
||||
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_CHECK_CONFIG, &file_isvalid, 4);
|
||||
if (file_isvalid == 0) {
|
||||
HAL_Firmware_Persistence_Stop();
|
||||
ctx->is_report_new_config = 0;
|
||||
return FAIL_RETURN;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HAL_Firmware_Persistence_Stop();
|
||||
ctx->is_report_new_config = 0;
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_cota_get_config(const char *config_scope, const char *get_type, const char *attribute_keys)
|
||||
{
|
||||
int res = 0;
|
||||
void *ota_handle = NULL;
|
||||
|
||||
/* Get Ota Handle */
|
||||
res = dm_ota_get_ota_handle(&ota_handle);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
return iotx_ota_get_config(ota_handle, config_scope, get_type, attribute_keys);
|
||||
}
|
||||
|
||||
int dm_cota_status_check(void)
|
||||
{
|
||||
int res = 0;
|
||||
dm_cota_ctx_t *ctx = _dm_cota_get_ctx();
|
||||
void *ota_handle = NULL;
|
||||
|
||||
/* Get Ota Handle */
|
||||
res = dm_ota_get_ota_handle(&ota_handle);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
if (IOT_OTA_IsFetching(ota_handle)) {
|
||||
uint32_t ota_type = IOT_OTAT_NONE;
|
||||
|
||||
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_OTA_TYPE, &ota_type, 4);
|
||||
|
||||
if (ota_type == IOT_OTAT_COTA) {
|
||||
/* Send New Config Information To User */
|
||||
if (ctx->is_report_new_config == 0) {
|
||||
dm_log_debug("Cota Status Check");
|
||||
res = _dm_cota_send_new_config_to_user(ota_handle);
|
||||
if (res == SUCCESS_RETURN) {
|
||||
ctx->is_report_new_config = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _DM_COTA_H_
|
||||
#define _DM_COTA_H_
|
||||
|
||||
typedef struct {
|
||||
int is_report_new_config;
|
||||
} dm_cota_ctx_t;
|
||||
|
||||
int dm_cota_init(void);
|
||||
int dm_cota_deinit(void);
|
||||
int dm_cota_perform_sync(_OU_ char *output, _IN_ int output_len);
|
||||
int dm_cota_get_config(const char *config_scope, const char *get_type, const char *attribute_keys);
|
||||
int dm_cota_status_check(void);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,225 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
#include "iotx_dm_internal.h"
|
||||
|
||||
#if defined(OTA_ENABLED) && !defined(BUILD_AOS)
|
||||
|
||||
static dm_fota_ctx_t g_dm_fota_ctx;
|
||||
|
||||
static dm_fota_ctx_t *_dm_fota_get_ctx(void)
|
||||
{
|
||||
return &g_dm_fota_ctx;
|
||||
}
|
||||
|
||||
int dm_fota_init(void)
|
||||
{
|
||||
dm_fota_ctx_t *ctx = _dm_fota_get_ctx();
|
||||
|
||||
memset(ctx, 0, sizeof(dm_fota_ctx_t));
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_fota_deinit(void)
|
||||
{
|
||||
dm_fota_ctx_t *ctx = _dm_fota_get_ctx();
|
||||
|
||||
memset(ctx, 0, sizeof(dm_fota_ctx_t));
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
static int _dm_fota_send_new_config_to_user(void *ota_handle)
|
||||
{
|
||||
int res = 0, message_len = 0;
|
||||
char *message = NULL;
|
||||
char version[128] = {0};
|
||||
const char *fota_new_config_fmt = "{\"version\":\"%s\"}";
|
||||
|
||||
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_VERSION, version, 128);
|
||||
|
||||
message_len = strlen(fota_new_config_fmt) + strlen(version) + 1;
|
||||
|
||||
message = DM_malloc(message_len);
|
||||
if (message == NULL) {
|
||||
return DM_MEMORY_NOT_ENOUGH;
|
||||
}
|
||||
memset(message, 0, message_len);
|
||||
HAL_Snprintf(message, message_len, fota_new_config_fmt, version);
|
||||
|
||||
dm_log_info("Send To User: %s", message);
|
||||
|
||||
res = _dm_msg_send_to_user(IOTX_DM_EVENT_FOTA_NEW_FIRMWARE, message);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
if (message) {
|
||||
DM_free(message);
|
||||
}
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_fota_perform_sync(_OU_ char *output, _IN_ int output_len)
|
||||
{
|
||||
int res = 0, file_download = 0;
|
||||
uint32_t file_size = 0, file_downloaded = 0;
|
||||
uint32_t percent_pre = 0, percent_now = 0;
|
||||
unsigned long long report_pre = 0, report_now = 0;
|
||||
dm_fota_ctx_t *ctx = _dm_fota_get_ctx();
|
||||
void *ota_handle = NULL;
|
||||
uint32_t ota_type = IOT_OTAT_NONE;
|
||||
int ret = 0;
|
||||
uint8_t is_header = 1;
|
||||
|
||||
if (output == NULL || output_len <= 0) {
|
||||
return DM_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Get Ota Handle */
|
||||
res = dm_ota_get_ota_handle(&ota_handle);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
if (ota_handle == NULL) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_OTA_TYPE, &ota_type, 4);
|
||||
|
||||
if (ota_type != IOT_OTAT_FOTA) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* reset the size_fetched in ota_handle to be 0 */
|
||||
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_RESET_FETCHED_SIZE, ota_handle, 4);
|
||||
/* Prepare Write Data To Storage */
|
||||
HAL_Firmware_Persistence_Start();
|
||||
while (1) {
|
||||
file_download = IOT_OTA_FetchYield(ota_handle, output, output_len, 1);
|
||||
if (file_download < 0) {
|
||||
IOT_OTA_ReportProgress(ota_handle, IOT_OTAP_FETCH_FAILED, NULL);
|
||||
HAL_Firmware_Persistence_Stop();
|
||||
ctx->is_report_new_config = 0;
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
#ifdef SUPPORT_SECURITY_OTA
|
||||
/* Check safe upgrade word in image */
|
||||
if (is_header) {
|
||||
if (HAL_Firmware_Check_Rsa_Key(output, file_download)) {
|
||||
IOT_OTA_ReportProgress(ota_handle, IOT_OTAP_CHECK_FALIED, NULL);
|
||||
HAL_Firmware_Persistence_Stop();
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
is_header = 0;
|
||||
}
|
||||
#endif
|
||||
/* Write Config File Into Stroage */
|
||||
ret = HAL_Firmware_Persistence_Write(output, file_download);
|
||||
if (-1 == ret) {
|
||||
IOT_OTA_ReportProgress(ota_handle, IOT_OTAP_BURN_FAILED, NULL);
|
||||
dm_log_err("Fota write firmware failed");
|
||||
}
|
||||
|
||||
/* Get OTA information */
|
||||
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_FETCHED_SIZE, &file_downloaded, 4);
|
||||
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_FILE_SIZE, &file_size, 4);
|
||||
|
||||
/* Calculate Download Percent And Update Report Timestamp*/
|
||||
percent_now = (file_downloaded * 100) / file_size;
|
||||
report_now = HAL_UptimeMs();
|
||||
|
||||
/* Report Download Process To Cloud */
|
||||
if (report_now < report_pre) {
|
||||
report_pre = report_now;
|
||||
}
|
||||
if ((((percent_now - percent_pre) > 5) &&
|
||||
((report_now - report_pre) > 50)) || (percent_now >= IOT_OTAP_FETCH_PERCENTAGE_MAX)) {
|
||||
IOT_OTA_ReportProgress(ota_handle, percent_now, NULL);
|
||||
percent_pre = percent_now;
|
||||
report_pre = report_now;
|
||||
}
|
||||
|
||||
/* Check If OTA Finished */
|
||||
if (IOT_OTA_IsFetchFinish(ota_handle)) {
|
||||
uint32_t file_isvalid = 0;
|
||||
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_CHECK_CONFIG, &file_isvalid, 4);
|
||||
if (file_isvalid == 0) {
|
||||
HAL_Firmware_Persistence_Stop();
|
||||
ctx->is_report_new_config = 0;
|
||||
return FAIL_RETURN;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HAL_Firmware_Persistence_Stop();
|
||||
ctx->is_report_new_config = 0;
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_fota_status_check(void)
|
||||
{
|
||||
int res = 0;
|
||||
dm_fota_ctx_t *ctx = _dm_fota_get_ctx();
|
||||
void *ota_handle = NULL;
|
||||
|
||||
/* Get Ota Handle */
|
||||
res = dm_ota_get_ota_handle(&ota_handle);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
if (IOT_OTA_IsFetching(ota_handle)) {
|
||||
uint32_t ota_type = IOT_OTAT_NONE;
|
||||
|
||||
IOT_OTA_Ioctl(ota_handle, IOT_OTAG_OTA_TYPE, &ota_type, 4);
|
||||
|
||||
if (ota_type == IOT_OTAT_FOTA) {
|
||||
/* Send New Config Information To User */
|
||||
if (ctx->is_report_new_config == 0) {
|
||||
dm_log_debug("Fota Status Check");
|
||||
res = _dm_fota_send_new_config_to_user(ota_handle);
|
||||
if (res == SUCCESS_RETURN) {
|
||||
ctx->is_report_new_config = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_fota_request_image(const char *version, int buffer_len)
|
||||
{
|
||||
int res = 0;
|
||||
void *ota_handle = NULL;
|
||||
char *version_str = NULL;
|
||||
|
||||
if (NULL == version || buffer_len <= 0) {
|
||||
dm_log_info("invalid input");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Get Ota Handle */
|
||||
res = dm_ota_get_ota_handle(&ota_handle);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
version_str = DM_malloc(buffer_len + 1);
|
||||
if (NULL == version_str) {
|
||||
dm_log_info("failed to malloc");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
memset(version_str, 0, buffer_len + 1);
|
||||
memcpy(version_str, version, buffer_len);
|
||||
|
||||
res = iotx_req_image(ota_handle, version_str);
|
||||
DM_free(version_str);
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _DM_FOTA_H_
|
||||
#define _DM_FOTA_H_
|
||||
|
||||
typedef struct {
|
||||
int is_report_new_config;
|
||||
} dm_fota_ctx_t;
|
||||
|
||||
int dm_fota_init(void);
|
||||
int dm_fota_deinit(void);
|
||||
int dm_fota_perform_sync(_OU_ char *output, _IN_ int output_len);
|
||||
int dm_fota_status_check(void);
|
||||
int dm_fota_request_image(_IN_ const char *version, _IN_ int buffer_len);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _IOT_DM_API_H_
|
||||
#define _IOT_DM_API_H_
|
||||
|
||||
typedef struct {
|
||||
void *mutex;
|
||||
void *cloud_connectivity;
|
||||
void *local_connectivity;
|
||||
iotx_dm_event_callback event_callback;
|
||||
} dm_api_ctx_t;
|
||||
|
||||
#if defined(DEPRECATED_LINKKIT)
|
||||
typedef struct {
|
||||
void *mutex;
|
||||
int devid;
|
||||
lite_cjson_item_t *lite;
|
||||
} dm_api_property_t;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "iotx_dm_internal.h"
|
||||
|
||||
dm_ipc_t g_dm_ipc;
|
||||
|
||||
static dm_ipc_t *_dm_ipc_get_ctx(void)
|
||||
{
|
||||
return &g_dm_ipc;
|
||||
}
|
||||
|
||||
static void _dm_ipc_lock(void)
|
||||
{
|
||||
dm_ipc_t *ctx = _dm_ipc_get_ctx();
|
||||
if (ctx->mutex) {
|
||||
HAL_MutexLock(ctx->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static void _dm_ipc_unlock(void)
|
||||
{
|
||||
dm_ipc_t *ctx = _dm_ipc_get_ctx();
|
||||
if (ctx->mutex) {
|
||||
HAL_MutexUnlock(ctx->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
int dm_ipc_init(int max_size)
|
||||
{
|
||||
dm_ipc_t *ctx = _dm_ipc_get_ctx();
|
||||
|
||||
memset(ctx, 0, sizeof(dm_ipc_t));
|
||||
|
||||
/* Create Mutex */
|
||||
ctx->mutex = HAL_MutexCreate();
|
||||
if (ctx->mutex == NULL) {
|
||||
return DM_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
/* Init List */
|
||||
ctx->msg_list.max_size = max_size;
|
||||
INIT_LIST_HEAD(&ctx->msg_list.message_list);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
void dm_ipc_deinit(void)
|
||||
{
|
||||
dm_ipc_t *ctx = _dm_ipc_get_ctx();
|
||||
dm_ipc_msg_node_t *del_node = NULL;
|
||||
dm_ipc_msg_node_t *next_node = NULL;
|
||||
dm_ipc_msg_t *del_msg = NULL;
|
||||
|
||||
if (ctx->mutex) {
|
||||
HAL_MutexDestroy(ctx->mutex);
|
||||
}
|
||||
|
||||
list_for_each_entry_safe(del_node, next_node, &ctx->msg_list.message_list, linked_list, dm_ipc_msg_node_t) {
|
||||
/* Free Message */
|
||||
del_msg = (dm_ipc_msg_t *)del_node->data;
|
||||
if (del_msg->data) {
|
||||
DM_free(del_msg->data);
|
||||
}
|
||||
DM_free(del_msg);
|
||||
del_msg = NULL;
|
||||
|
||||
/* Free Node */
|
||||
list_del(&del_node->linked_list);
|
||||
DM_free(del_node);
|
||||
}
|
||||
}
|
||||
|
||||
int dm_ipc_msg_insert(void *data)
|
||||
{
|
||||
dm_ipc_t *ctx = _dm_ipc_get_ctx();
|
||||
dm_ipc_msg_node_t *node = NULL;
|
||||
|
||||
if (data == NULL) {
|
||||
return DM_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
_dm_ipc_lock();
|
||||
dm_log_debug("dm msg list size: %d, max size: %d", ctx->msg_list.size, ctx->msg_list.max_size);
|
||||
if (ctx->msg_list.size >= ctx->msg_list.max_size) {
|
||||
dm_log_warning("dm ipc list full");
|
||||
_dm_ipc_unlock();
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
node = DM_malloc(sizeof(dm_ipc_msg_node_t));
|
||||
if (node == NULL) {
|
||||
_dm_ipc_unlock();
|
||||
return DM_MEMORY_NOT_ENOUGH;
|
||||
}
|
||||
memset(node, 0, sizeof(dm_ipc_msg_node_t));
|
||||
|
||||
node->data = data;
|
||||
INIT_LIST_HEAD(&node->linked_list);
|
||||
ctx->msg_list.size++;
|
||||
list_add_tail(&node->linked_list, &ctx->msg_list.message_list);
|
||||
|
||||
_dm_ipc_unlock();
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_ipc_msg_next(void **data)
|
||||
{
|
||||
dm_ipc_t *ctx = _dm_ipc_get_ctx();
|
||||
dm_ipc_msg_node_t *node = NULL;
|
||||
|
||||
if (data == NULL || *data != NULL) {
|
||||
return DM_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
_dm_ipc_lock();
|
||||
|
||||
if (list_empty(&ctx->msg_list.message_list)) {
|
||||
_dm_ipc_unlock();
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
node = list_first_entry(&ctx->msg_list.message_list, dm_ipc_msg_node_t, linked_list);
|
||||
list_del(&node->linked_list);
|
||||
ctx->msg_list.size--;
|
||||
|
||||
*data = node->data;
|
||||
DM_free(node);
|
||||
|
||||
_dm_ipc_unlock();
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _DM_IPC_H_
|
||||
#define _DM_IPC_H_
|
||||
|
||||
#include "iotx_dm_internal.h"
|
||||
|
||||
typedef struct {
|
||||
iotx_dm_event_types_t type;
|
||||
char *data;
|
||||
} dm_ipc_msg_t;
|
||||
|
||||
typedef struct {
|
||||
void *data;
|
||||
struct list_head linked_list;
|
||||
} dm_ipc_msg_node_t;
|
||||
|
||||
typedef struct {
|
||||
int max_size;
|
||||
int size;
|
||||
struct list_head message_list;
|
||||
} dm_ipc_msg_list_t;
|
||||
|
||||
typedef struct {
|
||||
void *mutex;
|
||||
dm_ipc_msg_list_t msg_list;
|
||||
} dm_ipc_t;
|
||||
|
||||
int dm_ipc_init(int max_size);
|
||||
void dm_ipc_deinit(void);
|
||||
int dm_ipc_msg_insert(void *data);
|
||||
int dm_ipc_msg_next(void **data);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#include "iotx_dm_internal.h"
|
||||
|
||||
#ifdef LOG_REPORT_TO_CLOUD
|
||||
|
||||
#include "dev_model_api.h"
|
||||
|
||||
const char THING_LOG_POST_PARAMS_HEAD[] =
|
||||
"\"%.*s %s %ld ";
|
||||
const char THING_LOG_POST_PARAMS_BODY[] =
|
||||
"%s %ld ";
|
||||
const char THING_LOG_POST_PARAMS_END[] =
|
||||
"%s %ld\",";
|
||||
|
||||
char *g_log_poll = NULL;
|
||||
static char *current_log_pos = NULL;
|
||||
|
||||
int remove_log_poll()
|
||||
{
|
||||
if (NULL != g_log_poll) {
|
||||
HAL_Free(g_log_poll);
|
||||
g_log_poll = NULL;
|
||||
current_log_pos = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
unsigned int push_log(const char *input_log, int input_log_size)
|
||||
{
|
||||
if (NULL == current_log_pos || NULL == input_log || input_log_size <= 0) {
|
||||
dm_log_debug("invalid params");
|
||||
return -1;
|
||||
}
|
||||
memcpy(current_log_pos, input_log, input_log_size);
|
||||
current_log_pos += input_log_size;
|
||||
return (current_log_pos - g_log_poll);
|
||||
}
|
||||
|
||||
unsigned int add_tail()
|
||||
{
|
||||
const char *tail = "]}";
|
||||
current_log_pos -= 1;
|
||||
return push_log(tail, strlen(tail));
|
||||
}
|
||||
|
||||
void add_log_header()
|
||||
{
|
||||
const char *subprefix = "{\"template\": \"traceContext logContent\",\"contents\":[";
|
||||
int sublen = strlen(subprefix);
|
||||
push_log(subprefix, sublen);
|
||||
}
|
||||
|
||||
int reset_log_poll()
|
||||
{
|
||||
if (NULL == g_log_poll) {
|
||||
dm_log_err("log buffer is NULL");
|
||||
return -1;
|
||||
}
|
||||
memset(g_log_poll, 0, LOG_POLL_SIZE);
|
||||
current_log_pos = g_log_poll;
|
||||
add_log_header();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int create_log_poll()
|
||||
{
|
||||
int ret;
|
||||
remove_log_poll();
|
||||
g_log_poll = HAL_Malloc(LOG_POLL_SIZE);
|
||||
ret = reset_log_poll();
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int switch_status = 0; /* 0 for switch off; 1 for switch on */
|
||||
static unsigned int sample_interval = 5;
|
||||
static unsigned int sample_count = 1000;
|
||||
|
||||
#define MSG_ID_LEN (64)
|
||||
char msg_array[MSG_ID_LEN] = {0};
|
||||
int check_target_msg(const char *input, int len)
|
||||
{
|
||||
/* do not upload log when swith is off */
|
||||
if (0 == switch_status) {
|
||||
return -1;
|
||||
}
|
||||
if (NULL == input || len <= 0) {
|
||||
dm_log_err("invalid params");
|
||||
return -1;
|
||||
}
|
||||
return strncmp(input, msg_array, len);
|
||||
}
|
||||
|
||||
static unsigned int msg_num = 0;
|
||||
/* return 0 for success; -1 for failure */
|
||||
int set_target_msg(const char *input, int len)
|
||||
{
|
||||
if (0 == switch_status) {
|
||||
return -1;
|
||||
}
|
||||
if ((msg_num % sample_interval == 0) && (msg_num < sample_count)) {
|
||||
if (NULL == input || len <= 0) {
|
||||
dm_log_err("invalid params");
|
||||
return -1;
|
||||
}
|
||||
strncpy(msg_array, input, len);
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
void parse_msg_id(_IN_ char *payload, _IN_ int payload_len, _OU_ dm_msg_request_payload_t *request)
|
||||
{
|
||||
lite_cjson_t lite;
|
||||
|
||||
if (payload == NULL || payload_len <= 0 || request == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
dm_utils_json_parse(payload, payload_len, cJSON_Object, &lite);
|
||||
dm_utils_json_object_item(&lite, DM_MSG_KEY_ID, strlen(DM_MSG_KEY_ID), cJSON_String, &request->id);
|
||||
}
|
||||
|
||||
int stop_sample()
|
||||
{
|
||||
if (current_log_pos > g_log_poll) {
|
||||
dm_mgr_upstream_thing_log_post(0, NULL, 0, 1);
|
||||
}
|
||||
switch_status = 0;
|
||||
dm_log_info("stop sample");
|
||||
return remove_log_poll();
|
||||
}
|
||||
|
||||
void parse_switch_info(_IN_ char *payload, _IN_ int payload_len)
|
||||
{
|
||||
lite_cjson_t lite, lite_sample_count, lite_sample_interval, lite_sample_target;
|
||||
const char *c1 = "Count";
|
||||
const char *c2 = "Interval";
|
||||
const char *c3 = "ProfileTarget";
|
||||
char *sample_target;
|
||||
int sample_target_len;
|
||||
const char *target = "propSet";
|
||||
int ret = -1;
|
||||
|
||||
if (payload == NULL || payload_len <= 0) {
|
||||
return;
|
||||
}
|
||||
dm_utils_json_parse(payload, payload_len, cJSON_Object, &lite);
|
||||
ret = lite_cjson_object_item(&lite, c1, strlen(c1), &lite_sample_count);
|
||||
if (ret < SUCCESS_RETURN) {
|
||||
return;
|
||||
}
|
||||
|
||||
ret = lite_cjson_object_item(&lite, c2, strlen(c2), &lite_sample_interval);
|
||||
if (ret < SUCCESS_RETURN) {
|
||||
return;
|
||||
}
|
||||
|
||||
ret = lite_cjson_object_item(&lite, c3, strlen(c3), &lite_sample_target);
|
||||
if (ret < SUCCESS_RETURN) {
|
||||
return;
|
||||
}
|
||||
|
||||
sample_count = lite_sample_count.value_int;
|
||||
sample_interval = lite_sample_interval.value_int;
|
||||
sample_target = lite_sample_target.value;
|
||||
sample_target_len = lite_sample_target.value_length;
|
||||
dm_log_info("switch count is %d, interval is %d, target is %.*s\n", sample_count, sample_interval,
|
||||
sample_target_len, sample_target);
|
||||
/* if the target is not property set, return */
|
||||
if (0 != strncmp(sample_target, target, sample_target_len)) {
|
||||
dm_log_info("target is not propSet, return\n");
|
||||
return;
|
||||
}
|
||||
if (sample_interval <= 0) {
|
||||
dm_log_err("invalid sample interval\n");
|
||||
return;
|
||||
}
|
||||
msg_num = 0;
|
||||
/* when it switch off, force upload the remaining log */
|
||||
if (0 == sample_count) {
|
||||
ret = stop_sample();
|
||||
} else {
|
||||
switch_status = 1;
|
||||
ret = create_log_poll();
|
||||
}
|
||||
|
||||
dm_log_info("log switch run status is %d\n", ret);
|
||||
}
|
||||
|
||||
REPORT_STATE g_report_status = READY;
|
||||
|
||||
void send_permance_info(char *input, int input_len, char *comments, int report_format)
|
||||
{
|
||||
#define LOCAL_POST_LEN (150)
|
||||
char data[LOCAL_POST_LEN] = {0};
|
||||
const char *format = NULL;
|
||||
if (0 == switch_status) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (report_format) {
|
||||
case 0:
|
||||
if (NULL == input || input_len <= 0) {
|
||||
dm_log_err("invalid params");
|
||||
return;
|
||||
}
|
||||
format = THING_LOG_POST_PARAMS_HEAD;
|
||||
HAL_Snprintf(data, sizeof(data), format, input_len, input,
|
||||
comments, (long)HAL_UptimeMs());
|
||||
break;
|
||||
case 1:
|
||||
format = THING_LOG_POST_PARAMS_BODY;
|
||||
HAL_Snprintf(data, sizeof(data), format,
|
||||
comments, (long)HAL_UptimeMs());
|
||||
break;
|
||||
case 2:
|
||||
format = THING_LOG_POST_PARAMS_END;
|
||||
HAL_Snprintf(data, sizeof(data), format,
|
||||
comments, (long)HAL_UptimeMs());
|
||||
g_report_status = DONE;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
iotx_dm_log_post(0, data, strlen((const char *)data));
|
||||
if (2 == report_format) {
|
||||
g_report_status = READY;
|
||||
}
|
||||
}
|
||||
|
||||
void get_msgid(char *payload, int is_cloud)
|
||||
{
|
||||
const char *interest = "\"method\":\"thing.service.property.set";
|
||||
char *found;
|
||||
dm_msg_request_payload_t request;
|
||||
if (0 == switch_status || NULL == payload) {
|
||||
return;
|
||||
}
|
||||
|
||||
found = strstr(payload, interest);
|
||||
if (NULL == found) {
|
||||
return;
|
||||
}
|
||||
found = strstr(payload, "{");
|
||||
if (NULL == found) {
|
||||
return;
|
||||
}
|
||||
msg_num++;
|
||||
parse_msg_id(found, strlen(found), &request);
|
||||
if (RUNNING == g_report_status) {
|
||||
dm_log_info("current working on a sample, return");
|
||||
return;
|
||||
}
|
||||
|
||||
if (sample_count <= msg_num) {
|
||||
stop_sample();
|
||||
return;
|
||||
}
|
||||
|
||||
/* if it does not meet the sample conditions, do NOT take sample */
|
||||
if (SUCCESS_RETURN != set_target_msg(request.id.value, request.id.value_length)) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_report_status = RUNNING;
|
||||
|
||||
if (1 == is_cloud) {
|
||||
send_permance_info(request.id.value, request.id.value_length, "1_cloud", 0);
|
||||
} else if (0 == is_cloud) {
|
||||
send_permance_info(request.id.value, request.id.value_length, "1_alcs", 0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _DM_MANAGER_H_
|
||||
#define _DM_MANAGER_H_
|
||||
|
||||
#include "iotx_dm_internal.h"
|
||||
|
||||
typedef struct {
|
||||
int devid;
|
||||
int dev_type;
|
||||
#if defined(DEPRECATED_LINKKIT)
|
||||
dm_shw_t *dev_shadow;
|
||||
iotx_dm_tsl_source_t tsl_source;
|
||||
#endif
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1];
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1];
|
||||
char device_secret[IOTX_DEVICE_SECRET_LEN + 1];
|
||||
iotx_dm_dev_avail_t status;
|
||||
iotx_dm_dev_status_t dev_status;
|
||||
struct list_head linked_list;
|
||||
} dm_mgr_dev_node_t;
|
||||
|
||||
typedef struct {
|
||||
void *mutex;
|
||||
int global_devid;
|
||||
struct list_head dev_list;
|
||||
} dm_mgr_ctx;
|
||||
|
||||
int dm_mgr_init(void);
|
||||
int dm_mgr_deinit(void);
|
||||
int dm_mgr_device_create(_IN_ int dev_type, _IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
|
||||
_IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1], _IN_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1], _OU_ int *devid);
|
||||
int dm_mgr_device_destroy(_IN_ int devid);
|
||||
int dm_mgr_device_number(void);
|
||||
int dm_mgr_get_devid_by_index(_IN_ int index, _OU_ int *devid);
|
||||
int dm_mgr_get_next_devid(_IN_ int devid, _OU_ int *devid_next);
|
||||
int dm_mgr_search_device_by_devid(_IN_ int devid, _OU_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
|
||||
_OU_ char device_name[IOTX_DEVICE_NAME_LEN + 1], _OU_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1]);
|
||||
int dm_mgr_search_device_by_pkdn(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
|
||||
_OU_ int *devid);
|
||||
int dm_mgr_search_device_node_by_devid(_IN_ int devid, _OU_ void **node);
|
||||
|
||||
int dm_mgr_get_dev_type(_IN_ int devid, _OU_ int *dev_type);
|
||||
int dm_mgr_set_dev_enable(_IN_ int devid);
|
||||
int dm_mgr_set_dev_disable(_IN_ int devid);
|
||||
int dm_mgr_get_dev_avail(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
|
||||
_OU_ iotx_dm_dev_avail_t *status);
|
||||
int dm_mgr_set_dev_status(_IN_ int devid, _IN_ iotx_dm_dev_status_t status);
|
||||
int dm_mgr_get_dev_status(_IN_ int devid, _OU_ iotx_dm_dev_status_t *status);
|
||||
int dm_mgr_set_device_secret(_IN_ int devid, _IN_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1]);
|
||||
int dm_mgr_dev_initialized(int devid);
|
||||
int dm_mgr_upstream_thing_property_desired_get(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
|
||||
int dm_mgr_upstream_thing_property_desired_delete(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
|
||||
|
||||
#ifdef DEVICE_MODEL_GATEWAY
|
||||
int dm_mgr_upstream_thing_sub_register(_IN_ int devid);
|
||||
int dm_mgr_upstream_thing_sub_unregister(_IN_ int devid);
|
||||
int dm_mgr_upstream_thing_topo_add(_IN_ int devid);
|
||||
int dm_mgr_upstream_thing_topo_delete(_IN_ int devid);
|
||||
int dm_mgr_upstream_thing_topo_get(void);
|
||||
int dm_mgr_upstream_thing_list_found(_IN_ int devid);
|
||||
int dm_mgr_upstream_combine_login(_IN_ int devid);
|
||||
int dm_mgr_upstream_combine_logout(_IN_ int devid);
|
||||
#endif
|
||||
int dm_mgr_upstream_thing_model_up_raw(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
|
||||
#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
|
||||
int dm_mgr_upstream_thing_property_post(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
|
||||
#ifdef LOG_REPORT_TO_CLOUD
|
||||
int dm_mgr_upstream_thing_log_post(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len, int force_update);
|
||||
#endif
|
||||
int dm_mgr_upstream_thing_event_post(_IN_ int devid, _IN_ char *identifier, _IN_ int identifier_len, _IN_ char *method,
|
||||
_IN_ char *payload, _IN_ int payload_len);
|
||||
int dm_mgr_upstream_thing_deviceinfo_update(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
|
||||
int dm_mgr_upstream_thing_deviceinfo_delete(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
|
||||
int dm_mgr_upstream_thing_dsltemplate_get(_IN_ int devid);
|
||||
int dm_mgr_upstream_thing_dynamictsl_get(_IN_ int devid);
|
||||
int dm_mgr_upstream_ntp_request(void);
|
||||
int dm_mgr_upstream_thing_service_response(_IN_ int devid, _IN_ char *msgid, _IN_ int msgid_len,
|
||||
_IN_ iotx_dm_error_code_t code,
|
||||
_IN_ char *identifier, _IN_ int identifier_len, _IN_ char *payload, _IN_ int payload_len, void *ctx);
|
||||
int dm_mgr_upstream_thing_property_get_response(_IN_ int devid, _IN_ char *msgid, _IN_ int msgid_len,
|
||||
_IN_ iotx_dm_error_code_t code,
|
||||
_IN_ char *payload, _IN_ int payload_len, _IN_ void *ctx);
|
||||
int dm_mgr_upstream_rrpc_response(_IN_ int devid, _IN_ char *msgid, _IN_ int msgid_len, _IN_ iotx_dm_error_code_t code,
|
||||
_IN_ char *rrpcid, _IN_ int rrpcid_len, _IN_ char *payload, _IN_ int payload_len);
|
||||
#ifdef DEVICE_MODEL_SUBDEV_OTA
|
||||
int dm_mgr_upstream_thing_firmware_version_update(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
|
||||
#endif
|
||||
#endif
|
||||
#ifdef DEPRECATED_LINKKIT
|
||||
int dm_mgr_deprecated_set_tsl_source(_IN_ int devid, _IN_ iotx_dm_tsl_source_t tsl_source);
|
||||
int dm_mgr_deprecated_get_tsl_source(_IN_ int devid, _IN_ iotx_dm_tsl_source_t *tsl_source);
|
||||
int dm_mgr_deprecated_search_devid_by_device_node(_IN_ void *node, _OU_ int *devid);
|
||||
int dm_mgr_deprecated_set_tsl(int devid, iotx_dm_tsl_type_t tsl_type, const char *tsl, int tsl_len);
|
||||
int dm_mgr_deprecated_get_property_data(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _OU_ void **data);
|
||||
int dm_mgr_deprecated_get_service_input_data(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _OU_ void **data);
|
||||
int dm_mgr_deprecated_get_service_output_data(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _OU_ void **data);
|
||||
int dm_mgr_deprecated_get_event_output_data(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _OU_ void **data);
|
||||
int dm_mgr_deprecated_get_data_type(_IN_ void *property, _OU_ dm_shw_data_type_e *type);
|
||||
int dm_mgr_deprecated_get_property_number(_IN_ int devid, _OU_ int *number);
|
||||
int dm_mgr_deprecated_get_service_number(_IN_ int devid, _OU_ int *number);
|
||||
int dm_mgr_deprecated_get_event_number(_IN_ int devid, _OU_ int *number);
|
||||
int dm_mgr_deprecated_get_property_by_index(_IN_ int devid, _IN_ int index, _OU_ void **property);
|
||||
int dm_mgr_deprecated_get_service_by_index(_IN_ int devid, _IN_ int index, _OU_ void **service);
|
||||
int dm_mgr_deprecated_get_event_by_index(_IN_ int devid, _IN_ int index, _OU_ void **event);
|
||||
int dm_mgr_deprecated_get_service_by_identifier(_IN_ int devid, _IN_ char *identifier, _OU_ void **service);
|
||||
int dm_mgr_deprecated_get_event_by_identifier(_IN_ int devid, _IN_ char *identifier, _OU_ void **event);
|
||||
int dm_mgr_deprecated_get_property_identifier(_IN_ void *property, _OU_ char **identifier);
|
||||
int dm_mgr_deprecated_get_service_method(_IN_ void *service, _OU_ char **method);
|
||||
int dm_mgr_deprecated_get_event_method(_IN_ void *event, _OU_ char **method);
|
||||
int dm_mgr_deprecated_set_property_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
|
||||
_IN_ int value_len);
|
||||
int dm_mgr_deprecated_get_property_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value);
|
||||
int dm_mgr_deprecated_set_event_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
|
||||
_IN_ int value_len);
|
||||
int dm_mgr_deprecated_get_event_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value);
|
||||
int dm_mgr_deprecated_set_service_input_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
|
||||
_IN_ int value_len);
|
||||
int dm_mgr_deprecated_get_service_input_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value);
|
||||
int dm_mgr_deprecated_set_service_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
|
||||
_IN_ int value_len);
|
||||
int dm_mgr_deprecated_get_service_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value);
|
||||
int dm_mgr_deprecated_assemble_property(_IN_ int devid, _IN_ char *identifier, _IN_ int identifier_len,
|
||||
_IN_ lite_cjson_item_t *lite);
|
||||
int dm_mgr_deprecated_assemble_event_output(_IN_ int devid, _IN_ char *identifier, _IN_ int identifier_len,
|
||||
_IN_ lite_cjson_item_t *lite);
|
||||
int dm_mgr_deprecated_assemble_service_output(_IN_ int devid, _IN_ char *identifier, _IN_ int identifier_len,
|
||||
_IN_ lite_cjson_item_t *lite);
|
||||
int dm_mgr_deprecated_upstream_thing_service_response(_IN_ int devid, _IN_ int msgid, _IN_ iotx_dm_error_code_t code,
|
||||
_IN_ char *identifier, _IN_ int identifier_len, _IN_ char *payload, _IN_ int payload_len);
|
||||
#endif
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _DM_MESSAGE_H_
|
||||
#define _DM_MESSAGE_H_
|
||||
|
||||
#include "iotx_dm_internal.h"
|
||||
|
||||
#define DM_MSG_KEY_ID "id"
|
||||
#define DM_MSG_KEY_VERSION "version"
|
||||
#define DM_MSG_KEY_METHOD "method"
|
||||
#define DM_MSG_KEY_PARAMS "params"
|
||||
#define DM_MSG_KEY_CODE "code"
|
||||
#define DM_MSG_KEY_DATA "data"
|
||||
#define DM_MSG_KEY_MESSAGE "message"
|
||||
|
||||
#define DM_MSG_VERSION "1.0"
|
||||
|
||||
#define DM_MSG_KEY_PRODUCT_KEY "productKey"
|
||||
#define DM_MSG_KEY_DEVICE_NAME "deviceName"
|
||||
#define DM_MSG_KEY_DEVICE_SECRET "deviceSecret"
|
||||
#define DM_MSG_KEY_TIME "time"
|
||||
|
||||
#define DM_MSG_SIGN_METHOD_SHA256 "Sha256"
|
||||
#define DM_MSG_SIGN_METHOD_HMACMD5 "hmacMd5"
|
||||
#define DM_MSG_SIGN_METHOD_HMACSHA1 "hmacSha1"
|
||||
#define DM_MSG_SIGN_METHOD_HMACSHA256 "hmacSha256"
|
||||
|
||||
typedef enum {
|
||||
DM_MSG_DEST_CLOUD = 0x01,
|
||||
DM_MSG_DEST_LOCAL = 0x02,
|
||||
DM_MSG_DEST_ALL = 0x03
|
||||
} dm_msg_dest_type_t;
|
||||
|
||||
typedef struct {
|
||||
const char *uri;
|
||||
unsigned char *payload;
|
||||
unsigned int payload_len;
|
||||
void *context;
|
||||
} dm_msg_source_t;
|
||||
|
||||
typedef struct {
|
||||
const char *uri_name;
|
||||
} dm_msg_dest_t;
|
||||
|
||||
typedef struct {
|
||||
lite_cjson_t id;
|
||||
lite_cjson_t version;
|
||||
lite_cjson_t method;
|
||||
lite_cjson_t params;
|
||||
} dm_msg_request_payload_t;
|
||||
|
||||
typedef struct {
|
||||
lite_cjson_t id;
|
||||
lite_cjson_t code;
|
||||
lite_cjson_t data;
|
||||
lite_cjson_t message;
|
||||
} dm_msg_response_payload_t;
|
||||
|
||||
typedef struct {
|
||||
int msgid;
|
||||
int devid;
|
||||
const char *service_prefix;
|
||||
const char *service_name;
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1];
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1];
|
||||
char *params;
|
||||
int params_len;
|
||||
char *method;
|
||||
iotx_cm_data_handle_cb callback;
|
||||
} dm_msg_request_t;
|
||||
|
||||
typedef struct {
|
||||
const char *service_prefix;
|
||||
const char *service_name;
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1];
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1];
|
||||
iotx_dm_error_code_t code;
|
||||
} dm_msg_response_t;
|
||||
|
||||
typedef struct {
|
||||
int id;
|
||||
} dm_msg_ctx_t;
|
||||
|
||||
|
||||
int dm_msg_init(void);
|
||||
int dm_msg_deinit(void);
|
||||
int _dm_msg_send_to_user(iotx_dm_event_types_t type, char *message);
|
||||
int dm_msg_send_msg_timeout_to_user(int msg_id, int devid, iotx_dm_event_types_t type);
|
||||
int dm_msg_uri_parse_pkdn(_IN_ char *uri, _IN_ int uri_len, _IN_ int start_deli, _IN_ int end_deli,
|
||||
_OU_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _OU_ char device_name[IOTX_DEVICE_NAME_LEN + 1]);
|
||||
int dm_msg_request_parse(_IN_ char *payload, _IN_ int payload_len, _OU_ dm_msg_request_payload_t *request);
|
||||
int dm_msg_response_parse(_IN_ char *payload, _IN_ int payload_len, _OU_ dm_msg_response_payload_t *response);
|
||||
int dm_msg_request(dm_msg_dest_type_t type, _IN_ dm_msg_request_t *request);
|
||||
int dm_msg_response(dm_msg_dest_type_t type, _IN_ dm_msg_request_payload_t *request, _IN_ dm_msg_response_t *response,
|
||||
_IN_ char *data, _IN_ int data_len, _IN_ void *user_data);
|
||||
int dm_msg_thing_model_down_raw(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
|
||||
_IN_ char *payload, _IN_ int payload_len);
|
||||
int dm_msg_thing_model_up_raw_reply(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
|
||||
_IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1], char *payload, int payload_len);
|
||||
#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
|
||||
int dm_msg_property_set(int devid, dm_msg_request_payload_t *request);
|
||||
#ifndef DEPRECATED_LINKKIT
|
||||
int dm_msg_property_get(_IN_ int devid, _IN_ dm_msg_request_payload_t *request, _IN_ void *ctx);
|
||||
#else
|
||||
int dm_msg_property_get(_IN_ int devid, _IN_ dm_msg_request_payload_t *request, _IN_ char **payload,
|
||||
_IN_ int *payload_len);
|
||||
#endif
|
||||
int dm_msg_thing_service_request(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
|
||||
char *identifier, int identifier_len, dm_msg_request_payload_t *request, _IN_ void *ctx);
|
||||
int dm_msg_rrpc_request(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
|
||||
char *messageid, int messageid_len, dm_msg_request_payload_t *request);
|
||||
int dm_msg_thing_event_property_post_reply(dm_msg_response_payload_t *response);
|
||||
int dm_msg_thing_event_post_reply(_IN_ char *identifier, _IN_ int identifier_len,
|
||||
_IN_ dm_msg_response_payload_t *response);
|
||||
int dm_msg_thing_deviceinfo_update_reply(dm_msg_response_payload_t *response);
|
||||
int dm_msg_thing_property_desired_get_reply(dm_msg_response_payload_t *response);
|
||||
int dm_msg_thing_property_desired_delete_reply(dm_msg_response_payload_t *response);
|
||||
int dm_msg_thing_deviceinfo_delete_reply(dm_msg_response_payload_t *response);
|
||||
int dm_msg_thing_dsltemplate_get_reply(dm_msg_response_payload_t *response);
|
||||
int dm_msg_thing_dynamictsl_get_reply(dm_msg_response_payload_t *response);
|
||||
int dm_msg_ntp_response(char *payload, int payload_len);
|
||||
int dm_msg_ext_error_reply(dm_msg_response_payload_t *response);
|
||||
#endif
|
||||
|
||||
#ifdef DEVICE_MODEL_GATEWAY
|
||||
int dm_msg_topo_add_notify(_IN_ char *payload, _IN_ int payload_len);
|
||||
int dm_msg_thing_disable(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1]);
|
||||
int dm_msg_thing_enable(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1]);
|
||||
int dm_msg_thing_delete(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1]);
|
||||
int dm_msg_thing_gateway_permit(_IN_ char *payload, _IN_ int payload_len);
|
||||
int dm_msg_thing_sub_register_reply(dm_msg_response_payload_t *response);
|
||||
int dm_msg_thing_sub_unregister_reply(dm_msg_response_payload_t *response);
|
||||
int dm_msg_thing_topo_add_reply(dm_msg_response_payload_t *response);
|
||||
int dm_msg_thing_topo_delete_reply(dm_msg_response_payload_t *response);
|
||||
int dm_msg_topo_get_reply(dm_msg_response_payload_t *response);
|
||||
int dm_msg_thing_list_found_reply(dm_msg_response_payload_t *response);
|
||||
int dm_msg_combine_login_reply(dm_msg_response_payload_t *response);
|
||||
int dm_msg_combine_logout_reply(dm_msg_response_payload_t *response);
|
||||
#endif
|
||||
#ifdef ALCS_ENABLED
|
||||
int dm_msg_dev_core_service_dev(char **payload, int *payload_len);
|
||||
#endif
|
||||
int dm_msg_cloud_connected(void);
|
||||
int dm_msg_cloud_disconnect(void);
|
||||
int dm_msg_cloud_reconnect(void);
|
||||
#if 0
|
||||
int dm_msg_found_device(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1]);
|
||||
int dm_msg_remove_device(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1]);
|
||||
int dm_msg_unregister_result(_IN_ char *uri, _IN_ int result);
|
||||
int dm_msg_send_result(_IN_ char *uri, _IN_ int result);
|
||||
int dm_msg_add_service_result(_IN_ char *uri, _IN_ int result);
|
||||
int dm_msg_remove_service_result(_IN_ char *uri, _IN_ int result);
|
||||
#endif
|
||||
int dm_msg_register_result(_IN_ char *uri, _IN_ int result);
|
||||
|
||||
#ifdef DEVICE_MODEL_GATEWAY
|
||||
int dm_msg_thing_sub_register(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
|
||||
_OU_ dm_msg_request_t *request);
|
||||
int dm_msg_thing_sub_unregister(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
|
||||
_OU_ dm_msg_request_t *request);
|
||||
int dm_msg_thing_topo_add(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
|
||||
_IN_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1], _OU_ dm_msg_request_t *request);
|
||||
int dm_msg_thing_topo_delete(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
|
||||
_OU_ dm_msg_request_t *request);
|
||||
int dm_msg_thing_topo_get(_OU_ dm_msg_request_t *request);
|
||||
int dm_msg_thing_list_found(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
|
||||
_OU_ dm_msg_request_t *request);
|
||||
int dm_msg_combine_login(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
|
||||
_IN_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1], _OU_ dm_msg_request_t *request);
|
||||
int dm_msg_combine_logout(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
|
||||
_OU_ dm_msg_request_t *request);
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
#include "iotx_dm_internal.h"
|
||||
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
|
||||
dm_msg_cache_ctx_t g_dm_msg_cache_ctx;
|
||||
|
||||
dm_msg_cache_ctx_t *_dm_msg_cache_get_ctx(void)
|
||||
{
|
||||
return &g_dm_msg_cache_ctx;
|
||||
}
|
||||
|
||||
static void _dm_msg_cache_mutex_lock(void)
|
||||
{
|
||||
dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
|
||||
if (ctx->mutex) {
|
||||
HAL_MutexLock(ctx->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
static void _dm_msg_cache_mutex_unlock(void)
|
||||
{
|
||||
dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
|
||||
if (ctx->mutex) {
|
||||
HAL_MutexUnlock(ctx->mutex);
|
||||
}
|
||||
}
|
||||
|
||||
int dm_msg_cache_init(void)
|
||||
{
|
||||
dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
|
||||
|
||||
memset(ctx, 0, sizeof(dm_msg_cache_ctx_t));
|
||||
|
||||
/* Create Mutex */
|
||||
ctx->mutex = HAL_MutexCreate();
|
||||
if (ctx->mutex == NULL) {
|
||||
return DM_MEMORY_NOT_ENOUGH;
|
||||
}
|
||||
|
||||
/* Init Message Cache List */
|
||||
INIT_LIST_HEAD(&ctx->dmc_list);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_cache_deinit(void)
|
||||
{
|
||||
dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
|
||||
dm_msg_cache_node_t *node = NULL;
|
||||
dm_msg_cache_node_t *next = NULL;
|
||||
|
||||
_dm_msg_cache_mutex_lock();
|
||||
list_for_each_entry_safe(node, next, &ctx->dmc_list, linked_list, dm_msg_cache_node_t) {
|
||||
list_del(&node->linked_list);
|
||||
if (node->data) {
|
||||
DM_free(node->data);
|
||||
}
|
||||
DM_free(node);
|
||||
_dm_msg_cache_mutex_unlock();
|
||||
}
|
||||
_dm_msg_cache_mutex_unlock();
|
||||
|
||||
if (ctx->mutex) {
|
||||
HAL_MutexDestroy(ctx->mutex);
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_cache_insert(int msgid, int devid, iotx_dm_event_types_t type, char *data)
|
||||
{
|
||||
dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
|
||||
dm_msg_cache_node_t *node = NULL;
|
||||
|
||||
dm_log_debug("dmc list size: %d", ctx->dmc_list_size);
|
||||
if (ctx->dmc_list_size >= CONFIG_MSGCACHE_QUEUE_MAXLEN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
node = DM_malloc(sizeof(dm_msg_cache_node_t));
|
||||
if (node == NULL) {
|
||||
return DM_MEMORY_NOT_ENOUGH;
|
||||
}
|
||||
memset(node, 0, sizeof(dm_msg_cache_node_t));
|
||||
|
||||
node->msgid = msgid;
|
||||
node->devid = devid;
|
||||
node->response_type = type;
|
||||
node->data = data;
|
||||
node->ctime = HAL_UptimeMs();
|
||||
INIT_LIST_HEAD(&node->linked_list);
|
||||
|
||||
_dm_msg_cache_mutex_lock();
|
||||
list_add_tail(&node->linked_list, &ctx->dmc_list);
|
||||
ctx->dmc_list_size++;
|
||||
_dm_msg_cache_mutex_unlock();
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_cache_search(_IN_ int msgid, _OU_ dm_msg_cache_node_t **node)
|
||||
{
|
||||
dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
|
||||
dm_msg_cache_node_t *search_node = NULL;
|
||||
|
||||
if (msgid <= 0 || node == NULL || *node != NULL) {
|
||||
return DM_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
_dm_msg_cache_mutex_lock();
|
||||
list_for_each_entry(search_node, &ctx->dmc_list, linked_list, dm_msg_cache_node_t) {
|
||||
if (search_node->msgid == msgid) {
|
||||
*node = search_node;
|
||||
_dm_msg_cache_mutex_unlock();
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
}
|
||||
|
||||
_dm_msg_cache_mutex_unlock();
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_cache_remove(int msgid)
|
||||
{
|
||||
dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
|
||||
dm_msg_cache_node_t *node = NULL;
|
||||
dm_msg_cache_node_t *next = NULL;
|
||||
|
||||
_dm_msg_cache_mutex_lock();
|
||||
list_for_each_entry_safe(node, next, &ctx->dmc_list, linked_list, dm_msg_cache_node_t) {
|
||||
if (node->msgid == msgid) {
|
||||
list_del(&node->linked_list);
|
||||
if (node->data) {
|
||||
DM_free(node->data);
|
||||
}
|
||||
ctx->dmc_list_size--;
|
||||
DM_free(node);
|
||||
dm_log_debug("Remove Message ID: %d", msgid);
|
||||
_dm_msg_cache_mutex_unlock();
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
}
|
||||
|
||||
_dm_msg_cache_mutex_unlock();
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
void dm_msg_cache_tick(void)
|
||||
{
|
||||
dm_msg_cache_ctx_t *ctx = _dm_msg_cache_get_ctx();
|
||||
dm_msg_cache_node_t *node = NULL;
|
||||
dm_msg_cache_node_t *next = NULL;
|
||||
uint64_t current_time = HAL_UptimeMs();
|
||||
|
||||
_dm_msg_cache_mutex_lock();
|
||||
list_for_each_entry_safe(node, next, &ctx->dmc_list, linked_list, dm_msg_cache_node_t) {
|
||||
if (current_time < node->ctime) {
|
||||
node->ctime = current_time;
|
||||
}
|
||||
if (current_time - node->ctime >= DM_MSG_CACHE_TIMEOUT_MS_DEFAULT) {
|
||||
dm_log_debug("Message ID Timeout: %d", node->msgid);
|
||||
/* Send Timeout Message To User */
|
||||
dm_msg_send_msg_timeout_to_user(node->msgid, node->devid, node->response_type);
|
||||
list_del(&node->linked_list);
|
||||
if (node->data) {
|
||||
DM_free(node->data);
|
||||
}
|
||||
DM_free(node);
|
||||
ctx->dmc_list_size--;
|
||||
}
|
||||
}
|
||||
_dm_msg_cache_mutex_unlock();
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
#ifndef _DM_MESSAGE_CACHE_H_
|
||||
#define _DM_MESSAGE_CACHE_H_
|
||||
|
||||
#include "iotx_dm_internal.h"
|
||||
|
||||
#define DM_MSG_CACHE_TIMEOUT_MS_DEFAULT (10000)
|
||||
|
||||
typedef struct {
|
||||
int msgid;
|
||||
int devid;
|
||||
iotx_dm_event_types_t response_type;
|
||||
char *data;
|
||||
uint64_t ctime;
|
||||
struct list_head linked_list;
|
||||
} dm_msg_cache_node_t;
|
||||
|
||||
typedef struct {
|
||||
void *mutex;
|
||||
int dmc_list_size;
|
||||
struct list_head dmc_list;
|
||||
} dm_msg_cache_ctx_t;
|
||||
|
||||
int dm_msg_cache_init(void);
|
||||
int dm_msg_cache_deinit(void);
|
||||
int dm_msg_cache_insert(int msg_id, int devid, iotx_dm_event_types_t type, char *data);
|
||||
int dm_msg_cache_search(_IN_ int msg_id, _OU_ dm_msg_cache_node_t **node);
|
||||
int dm_msg_cache_remove(int msg_id);
|
||||
void dm_msg_cache_tick(void);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,974 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "iotx_dm_internal.h"
|
||||
|
||||
const char DM_URI_SYS_PREFIX[] DM_READ_ONLY = "/sys/%s/%s/";
|
||||
const char DM_URI_EXT_SESSION_PREFIX[] DM_READ_ONLY = "/ext/session/%s/%s/";
|
||||
const char DM_URI_EXT_NTP_PREFIX[] DM_READ_ONLY = "/ext/ntp/%s/%s/";
|
||||
const char DM_URI_EXT_ERROR_PREFIX[] DM_READ_ONLY = "/ext/error/%s/%s";
|
||||
const char DM_URI_REPLY_SUFFIX[] DM_READ_ONLY = "_reply";
|
||||
const char DM_URI_OTA_DEVICE_INFORM[] DM_READ_ONLY = "/ota/device/inform/%s/%s";
|
||||
|
||||
/* From Cloud To Local Request And Response*/
|
||||
const char DM_URI_THING_MODEL_DOWN_RAW[] DM_READ_ONLY = "thing/model/down_raw";
|
||||
const char DM_URI_THING_MODEL_DOWN_RAW_REPLY[] DM_READ_ONLY = "thing/model/down_raw_reply";
|
||||
|
||||
/* From Local To Cloud Request And Response*/
|
||||
const char DM_URI_THING_MODEL_UP_RAW[] DM_READ_ONLY = "thing/model/up_raw";
|
||||
const char DM_URI_THING_MODEL_UP_RAW_REPLY[] DM_READ_ONLY = "thing/model/up_raw_reply";
|
||||
|
||||
#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
|
||||
const char DM_URI_RRPC_REQUEST_WILDCARD[] DM_READ_ONLY = "rrpc/request/+";
|
||||
|
||||
/* From Cloud To Local Request And Response*/
|
||||
const char DM_URI_THING_SERVICE_PROPERTY_SET[] DM_READ_ONLY = "thing/service/property/set";
|
||||
const char DM_URI_THING_SERVICE_PROPERTY_SET_REPLY[] DM_READ_ONLY = "thing/service/property/set_reply";
|
||||
const char DM_URI_THING_SERVICE_PROPERTY_GET[] DM_READ_ONLY = "thing/service/property/get";
|
||||
const char DM_URI_THING_SERVICE_PROPERTY_GET_REPLY[] DM_READ_ONLY = "thing/service/property/get_reply";
|
||||
const char DM_URI_THING_SERVICE_REQUEST_WILDCARD[] DM_READ_ONLY = "thing/service/+";
|
||||
const char DM_URI_THING_SERVICE_REQUEST_WILDCARD2[] DM_READ_ONLY = "thing/service/#";
|
||||
const char DM_URI_THING_SERVICE_REQUEST[] DM_READ_ONLY = "thing/service/%s";
|
||||
const char DM_URI_THING_SERVICE_RESPONSE[] DM_READ_ONLY = "thing/service/%.*s_reply";
|
||||
#ifdef DEVICE_MODEL_SHADOW
|
||||
const char DM_URI_THING_PROPERTY_DESIRED_GET[] DM_READ_ONLY = "thing/property/desired/get";
|
||||
const char DM_URI_THING_PROPERTY_DESIRED_DELETE[] DM_READ_ONLY = "thing/property/desired/delete";
|
||||
const char DM_URI_THING_PROPERTY_DESIRED_GET_REPLY[] DM_READ_ONLY = "thing/property/desired/get_reply";
|
||||
const char DM_URI_THING_PROPERTY_DESIRED_DELETE_REPLY[] DM_READ_ONLY = "thing/property/desired/delete_reply";
|
||||
#endif
|
||||
/* From Local To Cloud Request And Response*/
|
||||
#ifdef LOG_REPORT_TO_CLOUD
|
||||
const char DM_URI_THING_LOG_POST[] DM_READ_ONLY = "thing/log/post";
|
||||
#endif
|
||||
const char DM_URI_THING_EVENT_PROPERTY_POST[] DM_READ_ONLY = "thing/event/property/post";
|
||||
const char DM_URI_THING_EVENT_PROPERTY_POST_REPLY[] DM_READ_ONLY = "thing/event/property/post_reply";
|
||||
const char DM_URI_THING_EVENT_POST[] DM_READ_ONLY = "thing/event/%.*s/post";
|
||||
const char DM_URI_THING_EVENT_POST_REPLY[] DM_READ_ONLY = "thing/event/%s/post_reply";
|
||||
const char DM_URI_THING_EVENT_POST_REPLY_WILDCARD[] DM_READ_ONLY = "thing/event/+/post_reply";
|
||||
const char DM_URI_THING_DEVICEINFO_UPDATE[] DM_READ_ONLY = "thing/deviceinfo/update";
|
||||
const char DM_URI_THING_DEVICEINFO_UPDATE_REPLY[] DM_READ_ONLY = "thing/deviceinfo/update_reply";
|
||||
const char DM_URI_THING_DEVICEINFO_DELETE[] DM_READ_ONLY = "thing/deviceinfo/delete";
|
||||
const char DM_URI_THING_DEVICEINFO_DELETE_REPLY[] DM_READ_ONLY = "thing/deviceinfo/delete_reply";
|
||||
const char DM_URI_THING_DSLTEMPLATE_GET[] DM_READ_ONLY = "thing/dsltemplate/get";
|
||||
const char DM_URI_THING_DSLTEMPLATE_GET_REPLY[] DM_READ_ONLY = "thing/dsltemplate/get_reply";
|
||||
const char DM_URI_THING_DYNAMICTSL_GET[] DM_READ_ONLY = "thing/dynamicTsl/get";
|
||||
const char DM_URI_THING_DYNAMICTSL_GET_REPLY[] DM_READ_ONLY = "thing/dynamicTsl/get_reply";
|
||||
const char DM_URI_NTP_REQUEST[] DM_READ_ONLY = "request";
|
||||
const char DM_URI_NTP_RESPONSE[] DM_READ_ONLY = "response";
|
||||
#endif
|
||||
|
||||
const char DM_URI_DEV_CORE_SERVICE_DEV[] DM_READ_ONLY = "/dev/core/service/dev";
|
||||
|
||||
#ifdef DEVICE_MODEL_GATEWAY
|
||||
/* From Cloud To Local Request And Response*/
|
||||
const char DM_URI_THING_TOPO_ADD_NOTIFY[] DM_READ_ONLY = "thing/topo/add/notify";
|
||||
const char DM_URI_THING_TOPO_ADD_NOTIFY_REPLY[] DM_READ_ONLY = "thing/topo/add/notify_reply";
|
||||
const char DM_URI_THING_DELETE[] DM_READ_ONLY = "thing/delete";
|
||||
const char DM_URI_THING_DELETE_REPLY[] DM_READ_ONLY = "thing/delete_reply";
|
||||
const char DM_URI_THING_DISABLE[] DM_READ_ONLY = "thing/disable";
|
||||
const char DM_URI_THING_DISABLE_REPLY[] DM_READ_ONLY = "thing/disable_reply";
|
||||
const char DM_URI_THING_ENABLE[] DM_READ_ONLY = "thing/enable";
|
||||
const char DM_URI_THING_ENABLE_REPLY[] DM_READ_ONLY = "thing/enable_reply";
|
||||
const char DM_URI_THING_GATEWAY_PERMIT[] DM_READ_ONLY = "thing/gateway/permit";
|
||||
const char DM_URI_THING_GATEWAY_PERMIT_REPLY[] DM_READ_ONLY = "thing/gateway/permit_reply";
|
||||
|
||||
/* From Local To Cloud Request And Response*/
|
||||
const char DM_URI_THING_SUB_REGISTER[] DM_READ_ONLY = "thing/sub/register";
|
||||
const char DM_URI_THING_SUB_REGISTER_REPLY[] DM_READ_ONLY = "thing/sub/register_reply";
|
||||
const char DM_URI_THING_SUB_UNREGISTER[] DM_READ_ONLY = "thing/sub/unregister";
|
||||
const char DM_URI_THING_SUB_UNREGISTER_REPLY[] DM_READ_ONLY = "thing/sub/unregister_reply";
|
||||
const char DM_URI_THING_TOPO_ADD[] DM_READ_ONLY = "thing/topo/add";
|
||||
const char DM_URI_THING_TOPO_ADD_REPLY[] DM_READ_ONLY = "thing/topo/add_reply";
|
||||
const char DM_URI_THING_TOPO_DELETE[] DM_READ_ONLY = "thing/topo/delete";
|
||||
const char DM_URI_THING_TOPO_DELETE_REPLY[] DM_READ_ONLY = "thing/topo/delete_reply";
|
||||
const char DM_URI_THING_TOPO_GET[] DM_READ_ONLY = "thing/topo/get";
|
||||
const char DM_URI_THING_TOPO_GET_REPLY[] DM_READ_ONLY = "thing/topo/get_reply";
|
||||
const char DM_URI_THING_LIST_FOUND[] DM_READ_ONLY = "thing/list/found";
|
||||
const char DM_URI_THING_LIST_FOUND_REPLY[] DM_READ_ONLY = "thing/list/found_reply";
|
||||
const char DM_URI_COMBINE_LOGIN[] DM_READ_ONLY = "combine/login";
|
||||
const char DM_URI_COMBINE_LOGIN_REPLY[] DM_READ_ONLY = "combine/login_reply";
|
||||
const char DM_URI_COMBINE_LOGOUT[] DM_READ_ONLY = "combine/logout";
|
||||
const char DM_URI_COMBINE_LOGOUT_REPLY[] DM_READ_ONLY = "combine/logout_reply";
|
||||
#endif
|
||||
|
||||
int dm_msg_proc_thing_model_down_raw(_IN_ dm_msg_source_t *source)
|
||||
{
|
||||
int res = 0;
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
|
||||
/* Parse Product Key And Device Name */
|
||||
res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
|
||||
device_name);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
return dm_msg_thing_model_down_raw(product_key, device_name, (char *)source->payload, source->payload_len);
|
||||
}
|
||||
|
||||
int dm_msg_proc_thing_model_up_raw_reply(_IN_ dm_msg_source_t *source)
|
||||
{
|
||||
int res = 0;
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
|
||||
dm_log_info(DM_URI_THING_MODEL_UP_RAW_REPLY);
|
||||
|
||||
res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
|
||||
device_name);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
res = dm_msg_thing_model_up_raw_reply(product_key, device_name, (char *)source->payload, source->payload_len);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
|
||||
int dm_msg_proc_thing_service_property_set(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
|
||||
_OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response)
|
||||
{
|
||||
int res = 0, devid = 0;
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
|
||||
dm_log_info(DM_URI_THING_SERVICE_PROPERTY_SET);
|
||||
|
||||
/* Request */
|
||||
res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
|
||||
device_name);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return res;
|
||||
}
|
||||
|
||||
res = dm_mgr_search_device_by_pkdn(product_key, device_name, &devid);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return res;
|
||||
}
|
||||
|
||||
res = dm_msg_request_parse((char *)source->payload, source->payload_len, request);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return res ;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
res = dm_msg_property_set(devid, request);
|
||||
|
||||
/* Response */
|
||||
response->service_prefix = DM_URI_SYS_PREFIX;
|
||||
response->service_name = dest->uri_name;
|
||||
memcpy(response->product_key, product_key, strlen(product_key));
|
||||
memcpy(response->device_name, device_name, strlen(device_name));
|
||||
response->code = (res == SUCCESS_RETURN) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_proc_thing_service_property_get(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
|
||||
_OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response,
|
||||
_OU_ unsigned char **data, int *data_len)
|
||||
{
|
||||
int res = 0, devid = 0;
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
|
||||
dm_log_info(DM_URI_THING_SERVICE_PROPERTY_GET);
|
||||
|
||||
/* Request */
|
||||
res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
|
||||
device_name);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return res;
|
||||
}
|
||||
|
||||
res = dm_mgr_search_device_by_pkdn(product_key, device_name, &devid);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return res;
|
||||
}
|
||||
|
||||
res = dm_msg_request_parse((char *)source->payload, source->payload_len, request);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return res ;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
#ifndef DEPRECATED_LINKKIT
|
||||
res = dm_msg_property_get(devid, request, source->context);
|
||||
#else
|
||||
res = dm_msg_property_get(devid, request, (char **)data, data_len);
|
||||
#endif
|
||||
|
||||
#ifdef DEPRECATED_LINKKIT
|
||||
/* Response */
|
||||
response->service_prefix = DM_URI_SYS_PREFIX;
|
||||
response->service_name = dest->uri_name;
|
||||
memcpy(response->product_key, product_key, strlen(product_key));
|
||||
memcpy(response->device_name, device_name, strlen(device_name));
|
||||
response->code = (res == SUCCESS_RETURN) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
|
||||
|
||||
if (res != SUCCESS_RETURN) {
|
||||
*data = DM_malloc(strlen("{}") + 1);
|
||||
if (*data == NULL) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
memset(*data, 0, strlen("{}") + 1);
|
||||
memcpy(*data, "{}", strlen("{}"));
|
||||
|
||||
*data_len = strlen((char *)*data);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (res != SUCCESS_RETURN) {
|
||||
dm_log_err("DM Property Get Failed");
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int dm_msg_proc_thing_service_property_post(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
|
||||
_OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response)
|
||||
{
|
||||
int res = 0;
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
|
||||
dm_log_info(DM_URI_THING_EVENT_PROPERTY_POST);
|
||||
|
||||
/* Request */
|
||||
res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
|
||||
device_name);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
res = dm_msg_request_parse((char *)source->payload, source->payload_len, request);
|
||||
|
||||
/* Response */
|
||||
response->service_prefix = DM_URI_SYS_PREFIX;
|
||||
response->service_name = dest->uri_name;
|
||||
memcpy(response->product_key, product_key, strlen(product_key));
|
||||
memcpy(response->device_name, device_name, strlen(device_name));
|
||||
response->code = (res == SUCCESS_RETURN) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_proc_thing_service_request(_IN_ dm_msg_source_t *source)
|
||||
{
|
||||
int res = 0, serviceid_pos = 0;
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
dm_msg_request_payload_t request;
|
||||
|
||||
memset(&request, 0, sizeof(dm_msg_request_payload_t));
|
||||
|
||||
res = dm_utils_memtok((char *)source->uri, strlen(source->uri), DM_URI_SERVICE_DELIMITER, 6, &serviceid_pos);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
dm_log_info("Service Identifier: %.*s", (int)(strlen(source->uri) - serviceid_pos - 1),
|
||||
source->uri + serviceid_pos + 1);
|
||||
|
||||
/* Parse Product Key And Device Name */
|
||||
res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
|
||||
device_name);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Request */
|
||||
res = dm_msg_request_parse((char *)source->payload, source->payload_len, &request);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
return dm_msg_thing_service_request(product_key, device_name, (char *)source->uri + serviceid_pos + 1,
|
||||
strlen(source->uri) - serviceid_pos - 1, &request, source->context);
|
||||
}
|
||||
|
||||
int dm_msg_proc_thing_event_post_reply(_IN_ dm_msg_source_t *source)
|
||||
{
|
||||
int res = 0, eventid_start_pos = 0, eventid_end_pos = 0;
|
||||
dm_msg_response_payload_t response;
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
char int_id[DM_UTILS_UINT32_STRLEN] = {0};
|
||||
#endif
|
||||
|
||||
res = dm_utils_memtok((char *)source->uri, strlen(source->uri), DM_URI_SERVICE_DELIMITER, 6 + DM_URI_OFFSET,
|
||||
&eventid_start_pos);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
res = dm_utils_memtok((char *)source->uri, strlen(source->uri), DM_URI_SERVICE_DELIMITER, 7 + DM_URI_OFFSET,
|
||||
&eventid_end_pos);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
dm_log_info("Event Id: %.*s", eventid_end_pos - eventid_start_pos - 1, source->uri + eventid_start_pos + 1);
|
||||
|
||||
/* Response */
|
||||
res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
if ((strlen("property") == eventid_end_pos - eventid_start_pos - 1) &&
|
||||
(memcmp("property", source->uri + eventid_start_pos + 1, eventid_end_pos - eventid_start_pos - 1) == 0)) {
|
||||
dm_msg_thing_event_property_post_reply(&response);
|
||||
} else {
|
||||
dm_msg_thing_event_post_reply((char *)source->uri + eventid_start_pos + 1, eventid_end_pos - eventid_start_pos - 1,
|
||||
&response);
|
||||
}
|
||||
|
||||
/* Remove Message From Cache */
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
memcpy(int_id, response.id.value, response.id.value_length);
|
||||
dm_msg_cache_remove(atoi(int_id));
|
||||
#endif
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
#ifdef DEVICE_MODEL_SHADOW
|
||||
int dm_msg_proc_thing_property_desired_get_reply(_IN_ dm_msg_source_t *source)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_response_payload_t response;
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
char int_id[DM_UTILS_UINT32_STRLEN] = {0};
|
||||
#endif
|
||||
|
||||
dm_log_info(DM_URI_THING_PROPERTY_DESIRED_GET_REPLY);
|
||||
|
||||
/* Response */
|
||||
res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
res = dm_msg_thing_property_desired_get_reply(&response);
|
||||
|
||||
/* Remove Message From Cache */
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
memcpy(int_id, response.id.value, response.id.value_length);
|
||||
dm_msg_cache_remove(atoi(int_id));
|
||||
#endif
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_proc_thing_property_desired_delete_reply(_IN_ dm_msg_source_t *source)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_response_payload_t response;
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
char int_id[DM_UTILS_UINT32_STRLEN] = {0};
|
||||
#endif
|
||||
|
||||
dm_log_info(DM_URI_THING_PROPERTY_DESIRED_DELETE_REPLY);
|
||||
|
||||
/* Response */
|
||||
res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
res = dm_msg_thing_property_desired_delete_reply(&response);
|
||||
|
||||
/* Remove Message From Cache */
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
memcpy(int_id, response.id.value, response.id.value_length);
|
||||
dm_msg_cache_remove(atoi(int_id));
|
||||
#endif
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
#endif
|
||||
|
||||
int dm_msg_proc_thing_deviceinfo_update_reply(_IN_ dm_msg_source_t *source)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_response_payload_t response;
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
char int_id[DM_UTILS_UINT32_STRLEN] = {0};
|
||||
#endif
|
||||
|
||||
dm_log_info(DM_URI_THING_DEVICEINFO_UPDATE_REPLY);
|
||||
|
||||
/* Response */
|
||||
res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
dm_msg_thing_deviceinfo_update_reply(&response);
|
||||
|
||||
/* Remove Message From Cache */
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
memcpy(int_id, response.id.value, response.id.value_length);
|
||||
dm_msg_cache_remove(atoi(int_id));
|
||||
#endif
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_proc_thing_deviceinfo_delete_reply(_IN_ dm_msg_source_t *source)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_response_payload_t response;
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
char int_id[DM_UTILS_UINT32_STRLEN] = {0};
|
||||
#endif
|
||||
|
||||
dm_log_info(DM_URI_THING_DEVICEINFO_DELETE_REPLY);
|
||||
|
||||
/* Response */
|
||||
res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
dm_msg_thing_deviceinfo_delete_reply(&response);
|
||||
|
||||
/* Remove Message From Cache */
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
memcpy(int_id, response.id.value, response.id.value_length);
|
||||
dm_msg_cache_remove(atoi(int_id));
|
||||
#endif
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_proc_thing_dynamictsl_get_reply(_IN_ dm_msg_source_t *source)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_response_payload_t response;
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
char int_id[DM_UTILS_UINT32_STRLEN] = {0};
|
||||
#endif
|
||||
|
||||
dm_log_info(DM_URI_THING_DYNAMICTSL_GET_REPLY);
|
||||
|
||||
/* Response */
|
||||
res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
dm_msg_thing_dynamictsl_get_reply(&response);
|
||||
|
||||
/* Remove Message From Cache */
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
memcpy(int_id, response.id.value, response.id.value_length);
|
||||
dm_msg_cache_remove(atoi(int_id));
|
||||
#endif
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_proc_rrpc_request(_IN_ dm_msg_source_t *source)
|
||||
{
|
||||
int res = 0, rrpcid_pos = 0;
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
dm_msg_request_payload_t request;
|
||||
|
||||
memset(&request, 0, sizeof(dm_msg_request_payload_t));
|
||||
|
||||
res = dm_utils_memtok((char *)source->uri, strlen(source->uri), DM_URI_SERVICE_DELIMITER, 6, &rrpcid_pos);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
dm_log_info("Rrpc Id: %.*s", (int)(strlen(source->uri) - rrpcid_pos - 1), source->uri + rrpcid_pos + 1);
|
||||
|
||||
/* Parse Product Key And Device Name */
|
||||
res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
|
||||
device_name);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Request */
|
||||
res = dm_msg_request_parse((char *)source->payload, source->payload_len, &request);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
return dm_msg_rrpc_request(product_key, device_name, (char *)source->uri + rrpcid_pos + 1,
|
||||
strlen(source->uri) - rrpcid_pos - 1, &request);
|
||||
}
|
||||
|
||||
int dm_disp_ntp_response(_IN_ dm_msg_source_t *source)
|
||||
{
|
||||
dm_log_info(DM_URI_NTP_RESPONSE);
|
||||
|
||||
/* Operation */
|
||||
return dm_msg_ntp_response((char *)source->payload, source->payload_len);
|
||||
}
|
||||
|
||||
int dm_disp_ext_error_response(_IN_ dm_msg_source_t *source)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_response_payload_t response;
|
||||
/* char int_id[DM_UTILS_UINT32_STRLEN] = {0}; */
|
||||
|
||||
/* Response */
|
||||
res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
return dm_msg_ext_error_reply(&response);
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef DEVICE_MODEL_GATEWAY
|
||||
int dm_msg_proc_thing_topo_add_notify(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
|
||||
_OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response)
|
||||
{
|
||||
int res = 0;
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
|
||||
dm_log_info(DM_URI_THING_TOPO_ADD_NOTIFY);
|
||||
|
||||
/* Request */
|
||||
res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
|
||||
device_name);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return res;
|
||||
}
|
||||
|
||||
res = dm_msg_request_parse((char *)source->payload, source->payload_len, request);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return res ;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
res = dm_msg_topo_add_notify(request->params.value, request->params.value_length);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return res ;
|
||||
}
|
||||
|
||||
/* Response */
|
||||
response->service_prefix = DM_URI_SYS_PREFIX;
|
||||
response->service_name = dest->uri_name;
|
||||
memcpy(response->product_key, product_key, strlen(product_key));
|
||||
memcpy(response->device_name, device_name, strlen(device_name));
|
||||
response->code = (res == SUCCESS_RETURN) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_proc_thing_disable(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
|
||||
_OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response)
|
||||
{
|
||||
int res = 0;
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
|
||||
dm_log_info(DM_URI_THING_DISABLE);
|
||||
|
||||
/* Request */
|
||||
res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
|
||||
device_name);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return res;
|
||||
}
|
||||
|
||||
res = dm_msg_request_parse((char *)source->payload, source->payload_len, request);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
res = dm_msg_thing_disable(product_key, device_name);
|
||||
|
||||
/* Response */
|
||||
response->service_prefix = DM_URI_SYS_PREFIX;
|
||||
response->service_name = dest->uri_name;
|
||||
memcpy(response->product_key, product_key, strlen(product_key));
|
||||
memcpy(response->device_name, device_name, strlen(device_name));
|
||||
response->code = (res == SUCCESS_RETURN) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_proc_thing_enable(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
|
||||
_OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response)
|
||||
{
|
||||
int res = 0;
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
|
||||
dm_log_info(DM_URI_THING_DISABLE);
|
||||
|
||||
/* Request */
|
||||
res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
|
||||
device_name);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return res;
|
||||
}
|
||||
|
||||
res = dm_msg_request_parse((char *)source->payload, source->payload_len, request);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
res = dm_msg_thing_enable(product_key, device_name);
|
||||
|
||||
/* Response */
|
||||
response->service_prefix = DM_URI_SYS_PREFIX;
|
||||
response->service_name = dest->uri_name;
|
||||
memcpy(response->product_key, product_key, strlen(product_key));
|
||||
memcpy(response->device_name, device_name, strlen(device_name));
|
||||
response->code = (res == SUCCESS_RETURN) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_proc_thing_delete(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
|
||||
_OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response)
|
||||
{
|
||||
int res = 0;
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
|
||||
dm_log_info(DM_URI_THING_DELETE);
|
||||
|
||||
/* Request */
|
||||
res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
|
||||
device_name);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return res;
|
||||
}
|
||||
|
||||
res = dm_msg_request_parse((char *)source->payload, source->payload_len, request);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
res = dm_msg_thing_delete(product_key, device_name);
|
||||
|
||||
/* Response */
|
||||
response->service_prefix = DM_URI_SYS_PREFIX;
|
||||
response->service_name = dest->uri_name;
|
||||
memcpy(response->product_key, product_key, strlen(product_key));
|
||||
memcpy(response->device_name, device_name, strlen(device_name));
|
||||
response->code = (res == SUCCESS_RETURN) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_proc_thing_gateway_permit(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
|
||||
_OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response)
|
||||
{
|
||||
int res = 0;
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
|
||||
dm_log_info(DM_URI_THING_DELETE);
|
||||
|
||||
/* Request */
|
||||
res = dm_msg_uri_parse_pkdn((char *)source->uri, strlen(source->uri), 2 + DM_URI_OFFSET, 4 + DM_URI_OFFSET, product_key,
|
||||
device_name);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return res;
|
||||
}
|
||||
|
||||
res = dm_msg_request_parse((char *)source->payload, source->payload_len, request);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
res = dm_msg_thing_gateway_permit(request->params.value, request->params.value_length);
|
||||
|
||||
/* Response */
|
||||
response->service_prefix = DM_URI_SYS_PREFIX;
|
||||
response->service_name = dest->uri_name;
|
||||
memcpy(response->product_key, product_key, strlen(product_key));
|
||||
memcpy(response->device_name, device_name, strlen(device_name));
|
||||
response->code = (res == SUCCESS_RETURN) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_proc_thing_sub_register_reply(_IN_ dm_msg_source_t *source)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_response_payload_t response;
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
char int_id[DM_UTILS_UINT32_STRLEN] = {0};
|
||||
#endif
|
||||
|
||||
dm_log_info(DM_URI_THING_SUB_REGISTER_REPLY);
|
||||
|
||||
memset(&response, 0, sizeof(dm_msg_response_payload_t));
|
||||
|
||||
/* Response */
|
||||
res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
dm_msg_thing_sub_register_reply(&response);
|
||||
|
||||
/* Remove Message From Cache */
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
memcpy(int_id, response.id.value, response.id.value_length);
|
||||
dm_msg_cache_remove(atoi(int_id));
|
||||
#endif
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_proc_thing_sub_unregister_reply(_IN_ dm_msg_source_t *source)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_response_payload_t response;
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
char int_id[DM_UTILS_UINT32_STRLEN] = {0};
|
||||
#endif
|
||||
|
||||
dm_log_info(DM_URI_THING_SUB_UNREGISTER_REPLY);
|
||||
|
||||
memset(&response, 0, sizeof(dm_msg_response_payload_t));
|
||||
|
||||
/* Response */
|
||||
res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
dm_msg_thing_sub_unregister_reply(&response);
|
||||
|
||||
/* Remove Message From Cache */
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
memcpy(int_id, response.id.value, response.id.value_length);
|
||||
dm_msg_cache_remove(atoi(int_id));
|
||||
#endif
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_proc_thing_topo_add_reply(_IN_ dm_msg_source_t *source)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_response_payload_t response;
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
char int_id[DM_UTILS_UINT32_STRLEN] = {0};
|
||||
#endif
|
||||
|
||||
dm_log_info(DM_URI_THING_TOPO_ADD_REPLY);
|
||||
|
||||
memset(&response, 0, sizeof(dm_msg_response_payload_t));
|
||||
|
||||
/* Response */
|
||||
res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
dm_msg_thing_topo_add_reply(&response);
|
||||
|
||||
/* Remove Message From Cache */
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
memcpy(int_id, response.id.value, response.id.value_length);
|
||||
dm_msg_cache_remove(atoi(int_id));
|
||||
#endif
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_proc_thing_topo_delete_reply(_IN_ dm_msg_source_t *source)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_response_payload_t response;
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
char int_id[DM_UTILS_UINT32_STRLEN] = {0};
|
||||
#endif
|
||||
|
||||
dm_log_info(DM_URI_THING_TOPO_DELETE_REPLY);
|
||||
|
||||
memset(&response, 0, sizeof(dm_msg_response_payload_t));
|
||||
|
||||
/* Response */
|
||||
res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
dm_msg_thing_topo_delete_reply(&response);
|
||||
|
||||
/* Remove Message From Cache */
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
memcpy(int_id, response.id.value, response.id.value_length);
|
||||
dm_msg_cache_remove(atoi(int_id));
|
||||
#endif
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_proc_thing_topo_get_reply(_IN_ dm_msg_source_t *source)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_response_payload_t response;
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
char int_id[DM_UTILS_UINT32_STRLEN] = {0};
|
||||
#endif
|
||||
|
||||
dm_log_info(DM_URI_THING_TOPO_GET_REPLY);
|
||||
|
||||
memset(&response, 0, sizeof(dm_msg_response_payload_t));
|
||||
|
||||
/* Response */
|
||||
res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
dm_msg_topo_get_reply(&response);
|
||||
|
||||
/* Remove Message From Cache */
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
memcpy(int_id, response.id.value, response.id.value_length);
|
||||
dm_msg_cache_remove(atoi(int_id));
|
||||
#endif
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_proc_thing_list_found_reply(_IN_ dm_msg_source_t *source)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_response_payload_t response;
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
char int_id[DM_UTILS_UINT32_STRLEN] = {0};
|
||||
#endif
|
||||
|
||||
dm_log_info(DM_URI_THING_TOPO_GET_REPLY);
|
||||
|
||||
memset(&response, 0, sizeof(dm_msg_response_payload_t));
|
||||
|
||||
/* Response */
|
||||
res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
dm_msg_thing_list_found_reply(&response);
|
||||
|
||||
/* Remove Message From Cache */
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
memcpy(int_id, response.id.value, response.id.value_length);
|
||||
dm_msg_cache_remove(atoi(int_id));
|
||||
#endif
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_proc_combine_login_reply(_IN_ dm_msg_source_t *source)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_response_payload_t response;
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
char int_id[DM_UTILS_UINT32_STRLEN] = {0};
|
||||
#endif
|
||||
|
||||
dm_log_info(DM_URI_THING_TOPO_GET_REPLY);
|
||||
|
||||
memset(&response, 0, sizeof(dm_msg_response_payload_t));
|
||||
|
||||
/* Response */
|
||||
res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
dm_msg_combine_login_reply(&response);
|
||||
|
||||
/* Remove Message From Cache */
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
memcpy(int_id, response.id.value, response.id.value_length);
|
||||
dm_msg_cache_remove(atoi(int_id));
|
||||
#endif
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_msg_proc_combine_logout_reply(_IN_ dm_msg_source_t *source)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_response_payload_t response;
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
char int_id[DM_UTILS_UINT32_STRLEN] = {0};
|
||||
#endif
|
||||
|
||||
dm_log_info(DM_URI_THING_TOPO_GET_REPLY);
|
||||
|
||||
memset(&response, 0, sizeof(dm_msg_response_payload_t));
|
||||
|
||||
/* Response */
|
||||
res = dm_msg_response_parse((char *)source->payload, source->payload_len, &response);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
dm_msg_combine_logout_reply(&response);
|
||||
|
||||
/* Remove Message From Cache */
|
||||
#if !defined(DM_MESSAGE_CACHE_DISABLED)
|
||||
memcpy(int_id, response.id.value, response.id.value_length);
|
||||
dm_msg_cache_remove(atoi(int_id));
|
||||
#endif
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef ALCS_ENABLED
|
||||
int dm_msg_proc_thing_dev_core_service_dev(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
|
||||
_OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response,
|
||||
_OU_ unsigned char **data, int *data_len)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
dm_log_info(DM_URI_DEV_CORE_SERVICE_DEV);
|
||||
|
||||
/* Request */
|
||||
res = dm_msg_request_parse((char *)source->payload, source->payload_len, request);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return res ;
|
||||
}
|
||||
|
||||
/* Operation */
|
||||
res = dm_msg_dev_core_service_dev((char **)data, data_len);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Response */
|
||||
response->service_prefix = NULL;
|
||||
response->service_name = dest->uri_name;
|
||||
response->code = (res == SUCCESS_RETURN) ? (IOTX_DM_ERR_CODE_SUCCESS) : (IOTX_DM_ERR_CODE_REQUEST_ERROR);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _DM_MSG_PROCESS_H_
|
||||
#define _DM_MSG_PROCESS_H_
|
||||
|
||||
#define DM_URI_SERVICE_DELIMITER '/'
|
||||
|
||||
extern const char DM_URI_SYS_PREFIX[] DM_READ_ONLY;
|
||||
extern const char DM_URI_EXT_SESSION_PREFIX[] DM_READ_ONLY;
|
||||
extern const char DM_URI_EXT_NTP_PREFIX[] DM_READ_ONLY;
|
||||
extern const char DM_URI_EXT_ERROR_PREFIX[] DM_READ_ONLY;
|
||||
extern const char DM_URI_REPLY_SUFFIX[] DM_READ_ONLY;
|
||||
extern const char DM_URI_OTA_DEVICE_INFORM[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_PROPERTY_DESIRED_GET[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_PROPERTY_DESIRED_DELETE[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_PROPERTY_DESIRED_GET_REPLY[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_PROPERTY_DESIRED_DELETE_REPLY[] DM_READ_ONLY;
|
||||
/* From Cloud To Local Request And Response*/
|
||||
extern const char DM_URI_THING_MODEL_DOWN_RAW[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_MODEL_DOWN_RAW_REPLY[] DM_READ_ONLY;
|
||||
|
||||
/* From Local To Cloud Request And Response*/
|
||||
extern const char DM_URI_THING_MODEL_UP_RAW[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_MODEL_UP_RAW_REPLY[] DM_READ_ONLY;
|
||||
|
||||
#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
|
||||
extern const char DM_URI_RRPC_REQUEST_WILDCARD[] DM_READ_ONLY;
|
||||
/* From Cloud To Local Request And Response*/
|
||||
extern const char DM_URI_THING_SERVICE_PROPERTY_SET[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_SERVICE_PROPERTY_SET_REPLY[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_SERVICE_PROPERTY_GET[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_SERVICE_PROPERTY_GET_REPLY[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_SERVICE_REQUEST_WILDCARD[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_SERVICE_REQUEST_WILDCARD2[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_SERVICE_REQUEST[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_SERVICE_RESPONSE[] DM_READ_ONLY;
|
||||
|
||||
|
||||
/* From Local To Cloud Request And Response*/
|
||||
extern const char DM_URI_THING_EVENT_PROPERTY_POST[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_EVENT_PROPERTY_POST_REPLY[] DM_READ_ONLY;
|
||||
#ifdef LOG_REPORT_TO_CLOUD
|
||||
extern const char DM_URI_THING_LOG_POST[] DM_READ_ONLY;
|
||||
#endif
|
||||
extern const char DM_URI_THING_EVENT_POST[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_EVENT_POST_REPLY[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_EVENT_POST_REPLY_WILDCARD[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_DEVICEINFO_UPDATE[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_DEVICEINFO_UPDATE_REPLY[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_DEVICEINFO_DELETE[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_DEVICEINFO_DELETE_REPLY[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_DSLTEMPLATE_GET[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_DSLTEMPLATE_GET_REPLY[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_DYNAMICTSL_GET[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_DYNAMICTSL_GET_REPLY[] DM_READ_ONLY;
|
||||
extern const char DM_URI_NTP_REQUEST[] DM_READ_ONLY;
|
||||
extern const char DM_URI_NTP_RESPONSE[] DM_READ_ONLY;
|
||||
#endif
|
||||
|
||||
extern const char DM_URI_DEV_CORE_SERVICE_DEV[] DM_READ_ONLY;
|
||||
|
||||
#ifdef DEVICE_MODEL_GATEWAY
|
||||
/* From Cloud To Local Request And Response*/
|
||||
extern const char DM_URI_THING_TOPO_ADD_NOTIFY[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_TOPO_ADD_NOTIFY_REPLY[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_DISABLE[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_DISABLE_REPLY[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_ENABLE[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_ENABLE_REPLY[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_DELETE[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_DELETE_REPLY[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_GATEWAY_PERMIT[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_GATEWAY_PERMIT_REPLY[] DM_READ_ONLY;
|
||||
|
||||
/* From Local To Cloud Request And Response*/
|
||||
extern const char DM_URI_THING_SUB_REGISTER[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_SUB_REGISTER_REPLY[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_SUB_UNREGISTER[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_SUB_UNREGISTER_REPLY[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_TOPO_ADD[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_TOPO_ADD_REPLY[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_TOPO_DELETE[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_TOPO_DELETE_REPLY[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_TOPO_GET[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_TOPO_GET_REPLY[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_LIST_FOUND[] DM_READ_ONLY;
|
||||
extern const char DM_URI_THING_LIST_FOUND_REPLY[] DM_READ_ONLY;
|
||||
extern const char DM_URI_COMBINE_LOGIN[] DM_READ_ONLY;
|
||||
extern const char DM_URI_COMBINE_LOGIN_REPLY[] DM_READ_ONLY;
|
||||
extern const char DM_URI_COMBINE_LOGOUT[] DM_READ_ONLY;
|
||||
extern const char DM_URI_COMBINE_LOGOUT_REPLY[] DM_READ_ONLY;
|
||||
#endif
|
||||
|
||||
int dm_disp_uri_prefix_split(_IN_ const char *prefix, _IN_ char *uri, _IN_ int uri_len, _OU_ int *start, _OU_ int *end);
|
||||
int dm_disp_uri_pkdn_split(_IN_ char *uri, _IN_ int uri_len, _OU_ int *start, _OU_ int *end);
|
||||
int dm_disp_uri_service_specific_split(_IN_ char *uri, _IN_ int uri_len, _OU_ int *start, _OU_ int *end);
|
||||
int dm_disp_uri_rrpc_request_split(_IN_ char *uri, _IN_ int uri_len, _OU_ int *start, _OU_ int *end);
|
||||
int dm_disp_uri_event_specific_split(_IN_ char *uri, _IN_ int uri_len, _OU_ int *start, _OU_ int *end);
|
||||
|
||||
int dm_msg_proc_thing_model_down_raw(_IN_ dm_msg_source_t *source);
|
||||
int dm_msg_proc_thing_model_up_raw_reply(_IN_ dm_msg_source_t *source);
|
||||
|
||||
#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
|
||||
int dm_msg_proc_thing_service_property_set(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
|
||||
_OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response);
|
||||
int dm_msg_proc_thing_service_property_get(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
|
||||
_OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response,
|
||||
_OU_ unsigned char **data, int *data_len);
|
||||
int dm_msg_proc_thing_property_desired_get_reply(_IN_ dm_msg_source_t *source);
|
||||
int dm_msg_proc_thing_property_desired_delete_reply(_IN_ dm_msg_source_t *source);
|
||||
int dm_msg_proc_thing_service_property_post(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
|
||||
_OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response);
|
||||
int dm_msg_proc_thing_service_request(_IN_ dm_msg_source_t *source);
|
||||
int dm_msg_proc_thing_event_post_reply(_IN_ dm_msg_source_t *source);
|
||||
int dm_msg_proc_thing_deviceinfo_update_reply(_IN_ dm_msg_source_t *source);
|
||||
int dm_msg_proc_thing_deviceinfo_delete_reply(_IN_ dm_msg_source_t *source);
|
||||
int dm_msg_proc_thing_dynamictsl_get_reply(_IN_ dm_msg_source_t *source);
|
||||
int dm_msg_proc_rrpc_request(_IN_ dm_msg_source_t *source);
|
||||
int dm_disp_ntp_response(_IN_ dm_msg_source_t *source);
|
||||
int dm_disp_ext_error_response(_IN_ dm_msg_source_t *source);
|
||||
#endif
|
||||
|
||||
#ifdef DEVICE_MODEL_GATEWAY
|
||||
int dm_msg_proc_thing_topo_add_notify(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
|
||||
_OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response);
|
||||
int dm_msg_proc_thing_disable(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
|
||||
_OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response);
|
||||
int dm_msg_proc_thing_enable(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
|
||||
_OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response);
|
||||
int dm_msg_proc_thing_delete(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
|
||||
_OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response);
|
||||
int dm_msg_proc_thing_gateway_permit(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
|
||||
_OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response);
|
||||
int dm_msg_proc_thing_sub_register_reply(_IN_ dm_msg_source_t *source);
|
||||
int dm_msg_proc_thing_sub_unregister_reply(_IN_ dm_msg_source_t *source);
|
||||
int dm_msg_proc_thing_topo_add_reply(_IN_ dm_msg_source_t *source);
|
||||
int dm_msg_proc_thing_topo_delete_reply(_IN_ dm_msg_source_t *source);
|
||||
int dm_msg_proc_thing_topo_get_reply(_IN_ dm_msg_source_t *source);
|
||||
int dm_msg_proc_thing_list_found_reply(_IN_ dm_msg_source_t *source);
|
||||
int dm_msg_proc_combine_login_reply(_IN_ dm_msg_source_t *source);
|
||||
int dm_msg_proc_combine_logout_reply(_IN_ dm_msg_source_t *source);
|
||||
#endif
|
||||
|
||||
#ifdef ALCS_ENABLED
|
||||
int dm_msg_proc_thing_dev_core_service_dev(_IN_ dm_msg_source_t *source, _IN_ dm_msg_dest_t *dest,
|
||||
_OU_ dm_msg_request_payload_t *request, _OU_ dm_msg_response_t *response,
|
||||
_OU_ unsigned char **data, int *data_len);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
#include "iotx_dm_internal.h"
|
||||
|
||||
#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
|
||||
|
||||
static dm_opt_ctx g_dm_opt = {
|
||||
0, 0, 1, 1, 1
|
||||
};
|
||||
|
||||
int dm_opt_set(dm_opt_t opt, void *data)
|
||||
{
|
||||
int res = SUCCESS_RETURN;
|
||||
|
||||
if (data == NULL) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
switch (opt) {
|
||||
case DM_OPT_DOWNSTREAM_PROPERTY_POST_REPLY: {
|
||||
int opt = *(int *)(data);
|
||||
g_dm_opt.prop_post_reply_opt = opt;
|
||||
}
|
||||
break;
|
||||
case DM_OPT_DOWNSTREAM_EVENT_POST_REPLY: {
|
||||
int opt = *(int *)(data);
|
||||
g_dm_opt.event_post_reply_opt = opt;
|
||||
}
|
||||
break;
|
||||
case DM_OPT_UPSTREAM_PROPERTY_SET_REPLY: {
|
||||
int opt = *(int *)(data);
|
||||
g_dm_opt.prop_set_reply_opt = opt;
|
||||
}
|
||||
break;
|
||||
#ifdef DEVICE_MODEL_SHADOW
|
||||
case DM_OPT_DOWNSTREAM_EVENT_PROPERTY_DESIRED_GET_REPLY: {
|
||||
int opt = *(int *)(data);
|
||||
g_dm_opt.prop_desired_get_reply_opt = opt;
|
||||
}
|
||||
break;
|
||||
case DM_OPT_DOWNSTREAM_EVENT_PROPERTY_DESIRED_DELETE_REPLY: {
|
||||
int opt = *(int *)(data);
|
||||
g_dm_opt.prop_desired_delete_reply_opt = opt;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default: {
|
||||
res = FAIL_RETURN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int dm_opt_get(dm_opt_t opt, void *data)
|
||||
{
|
||||
int res = SUCCESS_RETURN;
|
||||
|
||||
if (data == NULL) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
switch (opt) {
|
||||
case DM_OPT_DOWNSTREAM_PROPERTY_POST_REPLY: {
|
||||
*(int *)(data) = g_dm_opt.prop_post_reply_opt;
|
||||
}
|
||||
break;
|
||||
case DM_OPT_DOWNSTREAM_EVENT_POST_REPLY: {
|
||||
*(int *)(data) = g_dm_opt.event_post_reply_opt;
|
||||
}
|
||||
break;
|
||||
case DM_OPT_UPSTREAM_PROPERTY_SET_REPLY: {
|
||||
*(int *)(data) = g_dm_opt.prop_set_reply_opt;
|
||||
}
|
||||
break;
|
||||
#ifdef DEVICE_MODEL_SHADOW
|
||||
case DM_OPT_DOWNSTREAM_EVENT_PROPERTY_DESIRED_DELETE_REPLY: {
|
||||
*(int *)(data) = g_dm_opt.prop_desired_delete_reply_opt;
|
||||
}
|
||||
break;
|
||||
case DM_OPT_DOWNSTREAM_EVENT_PROPERTY_DESIRED_GET_REPLY: {
|
||||
*(int *)(data) = g_dm_opt.prop_desired_get_reply_opt;
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
default: {
|
||||
res = FAIL_RETURN;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
|
||||
#ifndef _DM_OPT_H
|
||||
#define _DM_OPT_H
|
||||
|
||||
typedef enum {
|
||||
DM_OPT_DOWNSTREAM_PROPERTY_POST_REPLY,
|
||||
DM_OPT_DOWNSTREAM_EVENT_POST_REPLY,
|
||||
DM_OPT_UPSTREAM_PROPERTY_SET_REPLY,
|
||||
DM_OPT_DOWNSTREAM_EVENT_PROPERTY_DESIRED_DELETE_REPLY,
|
||||
DM_OPT_DOWNSTREAM_EVENT_PROPERTY_DESIRED_GET_REPLY
|
||||
} dm_opt_t;
|
||||
|
||||
typedef struct {
|
||||
int prop_post_reply_opt;
|
||||
int event_post_reply_opt;
|
||||
int prop_set_reply_opt;
|
||||
int prop_desired_get_reply_opt;
|
||||
int prop_desired_delete_reply_opt;
|
||||
} dm_opt_ctx;
|
||||
|
||||
int dm_opt_set(dm_opt_t opt, void *data);
|
||||
int dm_opt_get(dm_opt_t opt, void *data);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
#include "iotx_dm_internal.h"
|
||||
|
||||
#if defined(OTA_ENABLED) && !defined(BUILD_AOS)
|
||||
|
||||
static dm_ota_ctx_t g_dm_ota_ctx;
|
||||
|
||||
static dm_ota_ctx_t *_dm_ota_get_ctx(void)
|
||||
{
|
||||
return &g_dm_ota_ctx;
|
||||
}
|
||||
|
||||
int dm_ota_init(void)
|
||||
{
|
||||
dm_ota_ctx_t *ctx = _dm_ota_get_ctx();
|
||||
memset(ctx, 0, sizeof(dm_ota_ctx_t));
|
||||
|
||||
HAL_GetProductKey(ctx->product_key);
|
||||
HAL_GetDeviceName(ctx->device_name);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_ota_sub(void)
|
||||
{
|
||||
dm_ota_ctx_t *ctx = _dm_ota_get_ctx();
|
||||
void *handle = NULL;
|
||||
|
||||
/* Init OTA Handle */
|
||||
handle = IOT_OTA_Init(ctx->product_key, ctx->device_name, NULL);
|
||||
if (handle == NULL) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
ctx->ota_handle = handle;
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_ota_deinit(void)
|
||||
{
|
||||
dm_ota_ctx_t *ctx = _dm_ota_get_ctx();
|
||||
|
||||
if (ctx->ota_handle) {
|
||||
IOT_OTA_Deinit(ctx->ota_handle);
|
||||
ctx->ota_handle = NULL;
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
#ifdef DEVICE_MODEL_GATEWAY
|
||||
#ifdef DEVICE_MODEL_SUBDEV_OTA
|
||||
int dm_ota_switch_device(int devid)
|
||||
{
|
||||
char pk[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char dn[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
char ds[IOTX_DEVICE_SECRET_LEN + 1] = {0};
|
||||
int ret = dm_mgr_search_device_by_devid(devid, pk, dn, ds);
|
||||
void *ota_handle = NULL;
|
||||
int res = -1;
|
||||
dm_ota_ctx_t *ctx = NULL;
|
||||
|
||||
if (SUCCESS_RETURN != ret) {
|
||||
dm_log_err("could not find device by id, ret is %d", ret);
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
dm_log_info("do subdevice ota, pk, dn is %s, %s", pk, dn);
|
||||
|
||||
ota_handle = NULL;
|
||||
res = dm_ota_get_ota_handle(&ota_handle);
|
||||
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
/* if currently a device is doing OTA, do not interrupt */
|
||||
if (IOT_OTA_IsFetching(ota_handle)) {
|
||||
dm_log_info("OTA is processing, can not switch to another device");
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
dm_ota_deinit();
|
||||
ctx = _dm_ota_get_ctx();
|
||||
memset(ctx, 0, sizeof(dm_ota_ctx_t));
|
||||
|
||||
memcpy(ctx->product_key, pk, strlen(pk) + 1);
|
||||
memcpy(ctx->device_name, dn, strlen(dn) + 1);
|
||||
ret = dm_ota_sub();
|
||||
if (ret < 0) {
|
||||
dm_log_err("dm_ota_sub ret is %d, %s, %s\n", ret, pk, dn);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
int dm_ota_get_ota_handle(void **handle)
|
||||
{
|
||||
dm_ota_ctx_t *ctx = _dm_ota_get_ctx();
|
||||
|
||||
if (handle == NULL || *handle != NULL) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
if (ctx->ota_handle == NULL) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
*handle = ctx->ota_handle;
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _DM_OTA_H_
|
||||
#define _DM_OTA_H_
|
||||
|
||||
typedef struct {
|
||||
void *ota_handle;
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1];
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1];
|
||||
} dm_ota_ctx_t;
|
||||
|
||||
int dm_ota_init(void);
|
||||
int dm_ota_sub(void);
|
||||
int dm_ota_deinit(void);
|
||||
int dm_ota_get_ota_handle(void **handle);
|
||||
#ifdef DEVICE_MODEL_GATEWAY
|
||||
#ifdef DEVICE_MODEL_SUBDEV_OTA
|
||||
int dm_ota_switch_device(int devid);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,284 @@
|
||||
#include "iotx_dm_internal.h"
|
||||
|
||||
#ifdef ALCS_ENABLED
|
||||
|
||||
#ifdef LOG_REPORT_TO_CLOUD
|
||||
#include "iotx_log_report.h"
|
||||
#endif
|
||||
static int _dm_server_malloc_context(_IN_ NetworkAddr *remote, _IN_ CoAPMessage *message,
|
||||
_OU_ dm_server_alcs_context_t **context)
|
||||
{
|
||||
dm_server_alcs_context_t *alcs_context = NULL;
|
||||
|
||||
alcs_context = DM_malloc(sizeof(dm_server_alcs_context_t));
|
||||
if (alcs_context == NULL) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
memset(alcs_context, 0, sizeof(dm_server_alcs_context_t));
|
||||
|
||||
alcs_context->ip = DM_malloc(strlen((char *)remote->addr) + 1);
|
||||
if (alcs_context->ip == NULL) {
|
||||
DM_free(alcs_context);
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
memset(alcs_context->ip, 0, strlen((char *)remote->addr) + 1);
|
||||
memcpy(alcs_context->ip, (char *)remote->addr, strlen((char *)remote->addr) + 1);
|
||||
|
||||
alcs_context->port = remote->port;
|
||||
dm_log_info("alcs_context->ip: %s", alcs_context->ip);
|
||||
dm_log_info("alcs_context->port: %d", alcs_context->port);
|
||||
|
||||
alcs_context->token = DM_malloc(message->header.tokenlen);
|
||||
if (alcs_context->token == NULL) {
|
||||
DM_free(alcs_context->ip);
|
||||
DM_free(alcs_context);
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
memset(alcs_context->token, 0, message->header.tokenlen);
|
||||
memcpy(alcs_context->token, message->token, message->header.tokenlen);
|
||||
|
||||
alcs_context->token_len = message->header.tokenlen;
|
||||
|
||||
*context = alcs_context;
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
void dm_server_free_context(_IN_ void *ctx)
|
||||
{
|
||||
dm_server_alcs_context_t *context = (dm_server_alcs_context_t *)ctx;
|
||||
DM_free(context->ip);
|
||||
DM_free(context->token);
|
||||
DM_free(context);
|
||||
}
|
||||
|
||||
static dm_server_uri_map_t g_dm_server_uri_map[] = {
|
||||
#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
|
||||
{DM_URI_THING_SERVICE_PROPERTY_SET, DM_URI_SYS_PREFIX, IOTX_DM_LOCAL_AUTH, dm_server_thing_service_property_set },
|
||||
{DM_URI_THING_SERVICE_PROPERTY_GET, DM_URI_SYS_PREFIX, IOTX_DM_LOCAL_AUTH, dm_server_thing_service_property_get },
|
||||
{DM_URI_THING_EVENT_PROPERTY_POST, DM_URI_SYS_PREFIX, IOTX_DM_LOCAL_AUTH, dm_server_thing_service_property_post },
|
||||
{DM_URI_THING_SERVICE_REQUEST_WILDCARD2, DM_URI_SYS_PREFIX, IOTX_DM_LOCAL_AUTH, dm_server_thing_service_request },
|
||||
#endif
|
||||
{DM_URI_DEV_CORE_SERVICE_DEV, NULL, IOTX_DM_LOCAL_NO_AUTH, dm_server_thing_dev_core_service_dev },
|
||||
};
|
||||
|
||||
int dm_server_subscribe_all(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1])
|
||||
{
|
||||
int res = 0, index = 0, auth = 0;
|
||||
int number = sizeof(g_dm_server_uri_map) / sizeof(dm_server_uri_map_t);
|
||||
char *uri = NULL;
|
||||
|
||||
for (index = 0; index < number; index++) {
|
||||
res = dm_utils_service_name((char *)g_dm_server_uri_map[index].uri_prefix, (char *)g_dm_server_uri_map[index].uri_name,
|
||||
product_key, device_name, &uri);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
index--;
|
||||
continue;
|
||||
}
|
||||
|
||||
auth = (g_dm_server_uri_map[index].auth_type & IOTX_DM_SERVICE_LOCAL_AUTH) ? (IOTX_DM_MESSAGE_AUTH) :
|
||||
(IOTX_DM_MESSAGE_NO_AUTH);
|
||||
res = dm_server_subscribe(uri, (void *)g_dm_server_uri_map[index].callback, auth);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
index--;
|
||||
DM_free(uri);
|
||||
continue;
|
||||
}
|
||||
DM_free(uri);
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
void dm_server_alcs_event_handler(void *pcontext, void *phandle, iotx_alcs_event_msg_t *msg)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
|
||||
void dm_server_thing_service_property_set(CoAPContext *context, const char *paths, NetworkAddr *remote,
|
||||
CoAPMessage *message)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_source_t source;
|
||||
dm_msg_dest_t dest;
|
||||
dm_msg_request_payload_t request;
|
||||
dm_msg_response_t response;
|
||||
dm_server_alcs_context_t *alcs_context = NULL;
|
||||
|
||||
res = _dm_server_malloc_context(remote, message, &alcs_context);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
memset(&dest, 0, sizeof(dm_msg_dest_t));
|
||||
memset(&request, 0, sizeof(dm_msg_request_payload_t));
|
||||
memset(&response, 0, sizeof(dm_msg_response_t));
|
||||
|
||||
source.uri = paths;
|
||||
source.payload = (unsigned char *)message->payload;
|
||||
source.payload_len = message->payloadlen;
|
||||
source.context = alcs_context;
|
||||
|
||||
dest.uri_name = DM_URI_THING_SERVICE_PROPERTY_SET;
|
||||
|
||||
res = dm_msg_proc_thing_service_property_set(&source, &dest, &request, &response);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
dm_server_free_context(alcs_context);
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef LOG_REPORT_TO_CLOUD
|
||||
{
|
||||
extern void send_permance_info(char *input, int input_len, char *comments, int report_format);
|
||||
if (SUCCESS_RETURN == check_target_msg(request.id.value, request.id.value_length)) {
|
||||
send_permance_info(request.id.value, request.id.value_length, "2", 1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
dm_msg_response(DM_MSG_DEST_LOCAL, &request, &response, "{}", strlen("{}"), (void *)alcs_context);
|
||||
dm_server_free_context(alcs_context);
|
||||
}
|
||||
|
||||
void dm_server_thing_service_request(CoAPContext *context, const char *paths, NetworkAddr *remote,
|
||||
CoAPMessage *message)
|
||||
{
|
||||
int res = 0;
|
||||
dm_msg_source_t source;
|
||||
|
||||
dm_server_alcs_context_t *alcs_context = NULL;
|
||||
|
||||
res = _dm_server_malloc_context(remote, message, &alcs_context);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
|
||||
source.uri = paths;
|
||||
source.payload = (unsigned char *)message->payload;
|
||||
source.payload_len = message->payloadlen;
|
||||
source.context = alcs_context;
|
||||
|
||||
if (dm_msg_proc_thing_service_request(&source) < 0) {
|
||||
dm_server_free_context(alcs_context);
|
||||
}
|
||||
}
|
||||
|
||||
void dm_server_thing_service_property_get(CoAPContext *context, const char *paths, NetworkAddr *remote,
|
||||
CoAPMessage *message)
|
||||
{
|
||||
int res = 0;
|
||||
dm_server_alcs_context_t *alcs_context = NULL;
|
||||
dm_msg_source_t source;
|
||||
dm_msg_dest_t dest;
|
||||
dm_msg_request_payload_t request;
|
||||
dm_msg_response_t response;
|
||||
unsigned char *data = NULL;
|
||||
int data_len = 0;
|
||||
|
||||
res = _dm_server_malloc_context(remote, message, &alcs_context);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
memset(&dest, 0, sizeof(dm_msg_dest_t));
|
||||
memset(&request, 0, sizeof(dm_msg_request_payload_t));
|
||||
memset(&response, 0, sizeof(dm_msg_response_t));
|
||||
|
||||
source.uri = paths;
|
||||
source.payload = (unsigned char *)message->payload;
|
||||
source.payload_len = message->payloadlen;
|
||||
source.context = alcs_context;
|
||||
|
||||
dest.uri_name = DM_URI_THING_SERVICE_PROPERTY_GET;
|
||||
|
||||
dm_msg_proc_thing_service_property_get(&source, &dest, &request, &response, &data, &data_len);
|
||||
|
||||
#ifdef DEPRECATED_LINKKIT
|
||||
dm_msg_response(DM_MSG_DEST_LOCAL, &request, &response, (char *)data, data_len, alcs_context);
|
||||
DM_free(data);
|
||||
dm_server_free_context(alcs_context);
|
||||
#endif
|
||||
}
|
||||
|
||||
void dm_server_thing_service_property_post(CoAPContext *context, const char *paths, NetworkAddr *remote,
|
||||
CoAPMessage *message)
|
||||
{
|
||||
int res = 0;
|
||||
dm_server_alcs_context_t *alcs_context = NULL;
|
||||
dm_msg_source_t source;
|
||||
dm_msg_dest_t dest;
|
||||
dm_msg_request_payload_t request;
|
||||
dm_msg_response_t response;
|
||||
|
||||
res = _dm_server_malloc_context(remote, message, &alcs_context);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
memset(&dest, 0, sizeof(dm_msg_dest_t));
|
||||
memset(&request, 0, sizeof(dm_msg_request_payload_t));
|
||||
memset(&response, 0, sizeof(dm_msg_response_t));
|
||||
|
||||
source.uri = paths;
|
||||
source.payload = (unsigned char *)message->payload;
|
||||
source.payload_len = message->payloadlen;
|
||||
source.context = alcs_context;
|
||||
|
||||
dest.uri_name = DM_URI_THING_EVENT_PROPERTY_POST;
|
||||
|
||||
dm_msg_proc_thing_service_property_post(&source, &dest, &request, &response);
|
||||
|
||||
dm_msg_response(DM_MSG_DEST_LOCAL, &request, &response, "{}", strlen("{}"), alcs_context);
|
||||
dm_server_free_context(alcs_context);
|
||||
}
|
||||
|
||||
#endif
|
||||
void dm_server_thing_dev_core_service_dev(CoAPContext *context, const char *paths, NetworkAddr *remote,
|
||||
CoAPMessage *message)
|
||||
{
|
||||
int res = 0;
|
||||
dm_server_alcs_context_t *alcs_context = NULL;
|
||||
dm_msg_source_t source;
|
||||
dm_msg_dest_t dest;
|
||||
dm_msg_request_payload_t request;
|
||||
dm_msg_response_t response;
|
||||
unsigned char *data = NULL;
|
||||
int data_len = 0;
|
||||
|
||||
res = _dm_server_malloc_context(remote, message, &alcs_context);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&source, 0, sizeof(dm_msg_source_t));
|
||||
memset(&dest, 0, sizeof(dm_msg_dest_t));
|
||||
memset(&request, 0, sizeof(dm_msg_request_payload_t));
|
||||
memset(&response, 0, sizeof(dm_msg_response_t));
|
||||
|
||||
source.uri = paths;
|
||||
source.payload = (unsigned char *)message->payload;
|
||||
source.payload_len = message->payloadlen;
|
||||
source.context = alcs_context;
|
||||
|
||||
dest.uri_name = DM_URI_DEV_CORE_SERVICE_DEV;
|
||||
|
||||
res = dm_msg_proc_thing_dev_core_service_dev(&source, &dest, &request, &response, &data, &data_len);
|
||||
if (res < SUCCESS_RETURN) {
|
||||
dm_server_free_context(alcs_context);
|
||||
return;
|
||||
}
|
||||
|
||||
dm_msg_response(DM_MSG_DEST_LOCAL, &request, &response, (char *)data, data_len, alcs_context);
|
||||
|
||||
if (response.code == IOTX_DM_ERR_CODE_SUCCESS) {
|
||||
DM_free(data);
|
||||
}
|
||||
dm_server_free_context(alcs_context);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,29 @@
|
||||
#ifndef _DM_SERVER_H_
|
||||
#define _DM_SERVER_H_
|
||||
|
||||
#ifdef ALCS_ENABLED
|
||||
typedef struct {
|
||||
const char *uri_name;
|
||||
const char *uri_prefix;
|
||||
int auth_type;
|
||||
CoAPRecvMsgHandler callback;
|
||||
} dm_server_uri_map_t;
|
||||
|
||||
#define DM_SERVER_ALCS_NO_AUTH (0)
|
||||
#define DM_SERVER_ALCS_AUTH (1)
|
||||
|
||||
void dm_server_alcs_event_handler(void *pcontext, void *phandle, iotx_alcs_event_msg_t *msg);
|
||||
|
||||
int dm_server_subscribe_all(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1]);
|
||||
void dm_server_thing_service_property_set(CoAPContext *context, const char *paths, NetworkAddr *remote,
|
||||
CoAPMessage *message);
|
||||
void dm_server_thing_service_property_get(CoAPContext *context, const char *paths, NetworkAddr *remote,
|
||||
CoAPMessage *message);
|
||||
void dm_server_thing_service_property_post(CoAPContext *context, const char *paths, NetworkAddr *remote,
|
||||
CoAPMessage *message);
|
||||
void dm_server_thing_dev_core_service_dev(CoAPContext *context, const char *paths, NetworkAddr *remote,
|
||||
CoAPMessage *message);
|
||||
void dm_server_thing_service_request(CoAPContext *context, const char *paths, NetworkAddr *remote,
|
||||
CoAPMessage *message);
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,140 @@
|
||||
#include "iotx_dm_internal.h"
|
||||
|
||||
#ifdef ALCS_ENABLED
|
||||
|
||||
static dm_server_ctx_t g_dm_server_ctx = {0};
|
||||
|
||||
static dm_server_ctx_t *dm_server_get_ctx(void)
|
||||
{
|
||||
return &g_dm_server_ctx;
|
||||
}
|
||||
|
||||
int dm_server_open(void)
|
||||
{
|
||||
dm_server_ctx_t *ctx = dm_server_get_ctx();
|
||||
iotx_alcs_param_t alcs_param;
|
||||
iotx_alcs_event_handle_t event_handle;
|
||||
|
||||
memset(&alcs_param, 0x0, sizeof(iotx_alcs_param_t));
|
||||
memset(&event_handle, 0x0, sizeof(iotx_alcs_event_handle_t));
|
||||
|
||||
alcs_param.group = (char *)DM_SERVER_ALCS_ADDR;
|
||||
alcs_param.port = DM_SERVER_ALCS_PORT;
|
||||
alcs_param.send_maxcount = DM_SERVER_ALCS_SEND_MAXCOUNT;
|
||||
alcs_param.waittime = DM_SERVER_ALCS_WAITTIME;
|
||||
alcs_param.obs_maxcount = DM_SERVER_ALCS_OBS_MAXCOUNT;
|
||||
alcs_param.res_maxcount = DM_SERVER_ALCS_RES_MAXCOUNT;
|
||||
alcs_param.role = IOTX_ALCS_ROLE_CLIENT | IOTX_ALCS_ROLE_SERVER;
|
||||
event_handle.h_fp = dm_server_alcs_event_handler;
|
||||
event_handle.pcontext = NULL;
|
||||
|
||||
alcs_param.handle_event = &event_handle;
|
||||
|
||||
ctx->conn_handle = iotx_alcs_construct(&alcs_param);
|
||||
if (ctx->conn_handle == NULL) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_server_connect(void)
|
||||
{
|
||||
|
||||
dm_server_ctx_t *ctx = dm_server_get_ctx();
|
||||
|
||||
return iotx_alcs_cloud_init(ctx->conn_handle);
|
||||
}
|
||||
|
||||
int dm_server_close(void)
|
||||
{
|
||||
dm_server_ctx_t *ctx = dm_server_get_ctx();
|
||||
|
||||
return iotx_alcs_destroy(&ctx->conn_handle);
|
||||
}
|
||||
|
||||
int dm_server_send(char *uri, unsigned char *payload, int payload_len, void *context)
|
||||
{
|
||||
int res = 0;
|
||||
dm_server_ctx_t *ctx = dm_server_get_ctx();
|
||||
iotx_alcs_msg_t alcs_msg;
|
||||
dm_server_alcs_context_t *alcs_context = (dm_server_alcs_context_t *)context;
|
||||
|
||||
memset(&alcs_msg, 0, sizeof(iotx_alcs_msg_t));
|
||||
|
||||
alcs_msg.group_id = 0;
|
||||
alcs_msg.ip = alcs_context ? alcs_context->ip : NULL;
|
||||
alcs_msg.port = alcs_context ? alcs_context->port : 0;
|
||||
alcs_msg.msg_code = (alcs_context && alcs_context->token_len
|
||||
&& alcs_context->token) ? ITOX_ALCS_COAP_MSG_CODE_205_CONTENT : ITOX_ALCS_COAP_MSG_CODE_GET;
|
||||
alcs_msg.msg_type = IOTX_ALCS_MESSAGE_TYPE_CON;
|
||||
alcs_msg.uri = uri;
|
||||
alcs_msg.payload = payload;
|
||||
alcs_msg.payload_len = payload_len;
|
||||
|
||||
if (alcs_context == NULL) {
|
||||
res = iotx_alcs_observe_notify(ctx->conn_handle, alcs_msg.uri, alcs_msg.payload_len, alcs_msg.payload);
|
||||
dm_log_info("Send Observe Notify Result %d", res);
|
||||
} else if (alcs_context->ip && alcs_context->port && NULL == alcs_context->token) {
|
||||
res = iotx_alcs_send(ctx->conn_handle, &alcs_msg);
|
||||
dm_log_info("Send Result %d", res);
|
||||
} else if (alcs_context->ip && alcs_context->port && alcs_context->token_len && alcs_context->token) {
|
||||
res = iotx_alcs_send_Response(ctx->conn_handle, &alcs_msg, (uint8_t)alcs_context->token_len,
|
||||
(uint8_t *)alcs_context->token);
|
||||
dm_log_info("Send Response Result %d", res);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int dm_server_subscribe(char *uri, CoAPRecvMsgHandler callback, int auth_type)
|
||||
{
|
||||
int res = 0;
|
||||
dm_server_ctx_t *ctx = dm_server_get_ctx();
|
||||
iotx_alcs_res_t alcs_res;
|
||||
|
||||
memset(&alcs_res, 0, sizeof(iotx_alcs_res_t));
|
||||
|
||||
alcs_res.uri = uri;
|
||||
alcs_res.msg_ct = IOTX_ALCS_MESSAGE_CT_APP_JSON;
|
||||
alcs_res.msg_perm = IOTX_ALCS_MESSAGE_PERM_GET;
|
||||
alcs_res.maxage = 60;
|
||||
alcs_res.need_auth = auth_type;
|
||||
alcs_res.callback = callback;
|
||||
|
||||
res = iotx_alcs_register_resource(ctx->conn_handle, &alcs_res);
|
||||
|
||||
dm_log_info("Register Resource Result: %d", res);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int dm_server_add_device(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1])
|
||||
{
|
||||
int res = 0;
|
||||
dm_server_ctx_t *ctx = dm_server_get_ctx();
|
||||
|
||||
res = iotx_alcs_add_sub_device(ctx->conn_handle, (const char *)product_key, (const char *)device_name);
|
||||
dm_log_info("Add Device Result: %d, Product Key: %s, Device Name: %s", res, product_key, device_name);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int dm_server_del_device(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1])
|
||||
{
|
||||
int res = 0;
|
||||
dm_server_ctx_t *ctx = dm_server_get_ctx();
|
||||
|
||||
res = iotx_alcs_remove_sub_device(ctx->conn_handle, (const char *)product_key, (const char *)device_name);
|
||||
dm_log_info("Del Device Result: %d, Product Key: %s, Device Name: %s", res, product_key, device_name);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int dm_server_yield(void)
|
||||
{
|
||||
dm_server_ctx_t *ctx = dm_server_get_ctx();
|
||||
|
||||
return iotx_alcs_yield(ctx->conn_handle);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,34 @@
|
||||
#ifndef _DM_SERVER_ADAPTER_H_
|
||||
#define _DM_SERVER_ADAPTER_H_
|
||||
|
||||
#ifdef ALCS_ENABLED
|
||||
|
||||
#define DM_SERVER_ALCS_ADDR "224.0.1.187"
|
||||
#define DM_SERVER_ALCS_PORT (5863)
|
||||
#define DM_SERVER_ALCS_SEND_MAXCOUNT (16)
|
||||
#define DM_SERVER_ALCS_WAITTIME (200)
|
||||
#define DM_SERVER_ALCS_OBS_MAXCOUNT (16)
|
||||
#define DM_SERVER_ALCS_RES_MAXCOUNT (255)
|
||||
|
||||
typedef struct {
|
||||
void *conn_handle;
|
||||
} dm_server_ctx_t;
|
||||
|
||||
typedef struct {
|
||||
char *ip;
|
||||
uint16_t port;
|
||||
char *token;
|
||||
int token_len;
|
||||
} dm_server_alcs_context_t;
|
||||
|
||||
int dm_server_open(void);
|
||||
int dm_server_connect(void);
|
||||
int dm_server_close(void);
|
||||
int dm_server_send(char *uri, unsigned char *payload, int payload_len, void *context);
|
||||
int dm_server_subscribe(char *uri, CoAPRecvMsgHandler callback, int auth_type);
|
||||
int dm_server_add_device(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1]);
|
||||
int dm_server_del_device(char product_key[IOTX_PRODUCT_KEY_LEN + 1], char device_name[IOTX_DEVICE_NAME_LEN + 1]);
|
||||
int dm_server_yield(void);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,533 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
#if defined(DEPRECATED_LINKKIT)
|
||||
#ifndef _DM_SHADOW_H_
|
||||
#define _DM_SHADOW_H_
|
||||
|
||||
#include "iotx_dm_internal.h"
|
||||
|
||||
#define DM_SHW_KEY_SCHEMA "schema"
|
||||
#define DM_SHW_KEY_LINK "link"
|
||||
#define DM_SHW_KEY_PROFILE "profile"
|
||||
#define DM_SHW_KEY_PROPERTIES "properties"
|
||||
#define DM_SHW_KEY_EVENTS "events"
|
||||
#define DM_SHW_KEY_SERVICES "services"
|
||||
|
||||
#define DM_SHW_KEY_PROFILE_PK "productKey"
|
||||
#define DM_SHW_KEY_PROFILE_DN "deviceName"
|
||||
#define DM_SHW_KEY_IDENTIFIER "identifier"
|
||||
#define DM_SHW_KEY_NAME "name"
|
||||
#define DM_SHW_KEY_DESC "desc"
|
||||
#define DM_SHW_KEY_ACCESS_MODE "accessMode"
|
||||
#define DM_SHW_KEY_REQUIRED "required"
|
||||
#define DM_SHW_KEY_METHOD "method"
|
||||
#define DM_SHW_KEY_CALLTYPE "callType"
|
||||
#define DM_SHW_KEY_OUTPUTDATA "outputData"
|
||||
#define DM_SHW_KEY_INPUTDATA "inputData"
|
||||
#define DM_SHW_KEY_DATATYPE "dataType"
|
||||
#define DM_SHW_KEY_TYPE "type"
|
||||
#define DM_SHW_KEY_SPECS "specs"
|
||||
#define DM_SHW_KEY_UNIT "unit"
|
||||
#define DM_SHW_KEY_UNITNAME "unitName"
|
||||
#define DM_SHW_KEY_MIN "min"
|
||||
#define DM_SHW_KEY_MAX "max"
|
||||
#define DM_SHW_KEY_LENGTH "length"
|
||||
#define DM_SHW_KEY_SIZE "size"
|
||||
#define DM_SHW_KEY_ITEM "item"
|
||||
|
||||
/* Special Service And Event */
|
||||
#define DM_SHW_SPECIAL_SERVICE_SET_IDENTIFIER "set"
|
||||
#define DM_SHW_SPECIAL_SERVICE_SET_METHOD "thing.service.property.set"
|
||||
#define DM_SHW_SPECIAL_SERVICE_GET_IDENTIFIER "get"
|
||||
#define DM_SHW_SPECIAL_SERVICE_GET_METHOD "thing.service.property.get"
|
||||
#define DM_SHW_SPECIAL_EVENT_POST_IDENTIFIER "post"
|
||||
#define DM_SHW_SPECIAL_EVENT_POST_METHOD "thing.event.property.post"
|
||||
|
||||
#define DM_SHW_KEY_DELIMITER '.'
|
||||
|
||||
typedef enum {
|
||||
DM_SHW_DATA_TYPE_NONE, /* none */
|
||||
DM_SHW_DATA_TYPE_INT, /* int */
|
||||
DM_SHW_DATA_TYPE_FLOAT, /* float */
|
||||
DM_SHW_DATA_TYPE_DOUBLE, /* double */
|
||||
DM_SHW_DATA_TYPE_TEXT, /* string */
|
||||
DM_SHW_DATA_TYPE_ENUM, /* int */
|
||||
DM_SHW_DATA_TYPE_DATE, /* string */
|
||||
DM_SHW_DATA_TYPE_BOOL, /* bool,0 or 1 */
|
||||
DM_SHW_DATA_TYPE_ARRAY, /* support int, float, double, text */
|
||||
DM_SHW_DATA_TYPE_STRUCT, /* support above 8 data types */
|
||||
} dm_shw_data_type_e;
|
||||
|
||||
typedef enum {
|
||||
DM_SHW_DATA_TARGET_SERVICE_INPUT_DATA,
|
||||
DM_SHW_DATA_TARGET_SERVICE_OUTPUT_DATA
|
||||
} dm_shw_data_target_e;
|
||||
|
||||
typedef struct {
|
||||
dm_shw_data_type_e type;
|
||||
int size;
|
||||
void *value;
|
||||
} dm_shw_data_value_complex_t;
|
||||
|
||||
typedef struct {
|
||||
dm_shw_data_type_e type;
|
||||
union {
|
||||
int value_int;
|
||||
float value_float;
|
||||
double value_double;
|
||||
void *value; /* string or complex type accroding to data type */
|
||||
};
|
||||
} dm_shw_data_value_t;
|
||||
|
||||
typedef struct {
|
||||
dm_shw_data_type_e type;
|
||||
int specs_number; /* used when type is enum and struct */
|
||||
void *specs; /* nerver be used by struct */
|
||||
} dm_shw_data_type_t;
|
||||
|
||||
typedef struct {
|
||||
char *identifier;
|
||||
dm_shw_data_value_t data_value;
|
||||
} dm_shw_data_t;
|
||||
|
||||
typedef struct {
|
||||
char *identifier;
|
||||
int input_data_number; /* input_data Number */
|
||||
dm_shw_data_t *input_datas; /* input_data array, type is dm_shw_data_t */
|
||||
int output_data_number; /* ouput_data Number */
|
||||
dm_shw_data_t *output_datas; /* output_data array, type is dm_shw_data_t */
|
||||
} dm_shw_event_t;
|
||||
|
||||
typedef struct {
|
||||
char *identifier; /* synchronized or asynchronized */
|
||||
int input_data_number; /* input_data_number */
|
||||
dm_shw_data_t *input_datas; /* input_data array, type is dm_shw_data_t */
|
||||
int output_data_number; /* ouput_data Number */
|
||||
dm_shw_data_t *output_datas; /* output_data array, type is dm_shw_data_t */
|
||||
} dm_shw_service_t;
|
||||
|
||||
typedef struct {
|
||||
int property_number;
|
||||
dm_shw_data_t *properties; /* property array, type is dm_shw_data_t */
|
||||
int event_number;
|
||||
dm_shw_event_t *events; /* event array, type is dm_shw_event_t */
|
||||
int service_number;
|
||||
dm_shw_service_t *services; /* service array, type is dm_shw_service_t */
|
||||
} dm_shw_t;
|
||||
|
||||
/**
|
||||
* @brief Create TSL struct from TSL string.
|
||||
* This function used to parse TSL string into TSL struct.
|
||||
*
|
||||
* @param tsl. The TSL string in JSON format.
|
||||
* @param tsl_len. The length of tsl
|
||||
* @param shadow. The pointer of TSL Struct pointer, will be malloc memory.
|
||||
* This memory should be free by dm_shw_destroy.
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_create(_IN_ iotx_dm_tsl_type_t type, _IN_ const char *tsl, _IN_ int tsl_len, _OU_ dm_shw_t **shadow);
|
||||
|
||||
/**
|
||||
* @brief Get property from TSL struct.
|
||||
* This function used to get property from TSL struct.
|
||||
*
|
||||
* @param shadow. The pointer of TSL Struct.
|
||||
* @param key. The property compound string, format decided by data type of property as follows:
|
||||
* int,float,double,text,enum,date,bool type: property_id
|
||||
* array type: property_id(array)[index]
|
||||
* struct type: property_id(struct).property_id or property_id(struct).property_id[index]
|
||||
*
|
||||
* @param key_len. The length of key.
|
||||
* @param property. The property in TSL Struct.
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_get_property_data(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _OU_ void **data);
|
||||
|
||||
int dm_shw_get_service_input_output_data(_IN_ dm_shw_data_target_e type, _IN_ dm_shw_t *shadow, _IN_ char *key,
|
||||
_IN_ int key_len, _OU_ void **data);
|
||||
|
||||
/**
|
||||
* @brief Get event output data from TSL struct.
|
||||
* This function used to get event output data from TSL struct.
|
||||
*
|
||||
* @param shadow. The pointer of TSL Struct.
|
||||
* @param key. The property compound string, format decided by data type of property as follows:
|
||||
* int,float,double,text,enum,date,bool type: property_id
|
||||
* array type: property_id(array)[index]
|
||||
* struct type: property_id(struct).property_id or property_id(struct).property_id[index]
|
||||
*
|
||||
* @param key_len. The length of key.
|
||||
* @param property. The property in TSL Struct.
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_get_event_output_data(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _OU_ void **data);
|
||||
|
||||
/**
|
||||
* @brief Get property type from TSL struct.
|
||||
* This function used to get property type from TSL struct.
|
||||
*
|
||||
* @param property. The handle of property.
|
||||
* @param type. The data type of property
|
||||
*
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_get_data_type(_IN_ void *data, _OU_ dm_shw_data_type_e *type);
|
||||
|
||||
/**
|
||||
* @brief Get event from TSL struct.
|
||||
* This function used to get property from TSL struct.
|
||||
*
|
||||
* @param service. The handle of event.
|
||||
* @param key. The property compound string, format decided by data type of property as follows:
|
||||
* int,float,double,text,enum,date,bool type: event_id
|
||||
*
|
||||
* @param key_len. The length of key.
|
||||
* @param property. The event in TSL Struct.
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_get_event(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _OU_ void **event);
|
||||
|
||||
/**
|
||||
* @brief Get service from TSL struct.
|
||||
* This function used to get property from TSL struct.
|
||||
*
|
||||
* @param shadow. The pointer of TSL Struct.
|
||||
* @param key. The property compound string, format decided by data type of property as follows:
|
||||
* int,float,double,text,enum,date,bool type: service_id
|
||||
*
|
||||
* @param key_len. The length of key.
|
||||
* @param property. The service in TSL Struct.
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_get_service(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _OU_ void **service);
|
||||
|
||||
/**
|
||||
* @brief Get property number from TSL struct.
|
||||
* This function used to get property number from TSL struct.
|
||||
*
|
||||
* @param shadow. The pointer of TSL Struct.
|
||||
* @param number. The property number in TSL Struct.
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_get_property_number(_IN_ dm_shw_t *shadow, _OU_ int *number);
|
||||
|
||||
/**
|
||||
* @brief Get service number from TSL struct.
|
||||
* This function used to get property number from TSL struct.
|
||||
*
|
||||
* @param shadow. The pointer of TSL Struct.
|
||||
* @param number. The service number in TSL Struct.
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_get_service_number(_IN_ dm_shw_t *shadow, _OU_ int *number);
|
||||
|
||||
/**
|
||||
* @brief Get event number from TSL struct.
|
||||
* This function used to get property number from TSL struct.
|
||||
*
|
||||
* @param shadow. The pointer of TSL Struct.
|
||||
* @param number. The event number in TSL Struct.
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_get_event_number(_IN_ dm_shw_t *shadow, _OU_ int *number);
|
||||
|
||||
/**
|
||||
* @brief Get property reference from TSL struct by index.
|
||||
* This function used to get property reference from TSL struct by index.
|
||||
*
|
||||
* @param shadow. The pointer of TSL Struct.
|
||||
* @param index. The index of property
|
||||
* @param property. The property reference in TSL Struct.
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_get_property_by_index(_IN_ dm_shw_t *shadow, _IN_ int index, _OU_ void **property);
|
||||
|
||||
/**
|
||||
* @brief Get service reference from TSL struct by index.
|
||||
* This function used to get service reference from TSL struct by index.
|
||||
*
|
||||
* @param shadow. The pointer of TSL Struct.
|
||||
* @param index. The index of service
|
||||
* @param service. The service reference in TSL Struct.
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_get_service_by_index(_IN_ dm_shw_t *shadow, _IN_ int index, _OU_ void **service);
|
||||
|
||||
/**
|
||||
* @brief Get event reference from TSL struct by index.
|
||||
* This function used to get event reference from TSL struct by index.
|
||||
*
|
||||
* @param shadow. The pointer of TSL Struct.
|
||||
* @param index. The index of event
|
||||
* @param event. The event reference in TSL Struct.
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_get_event_by_index(_IN_ dm_shw_t *shadow, _IN_ int index, _OU_ void **event);
|
||||
|
||||
/**
|
||||
* @brief Get service reference from TSL struct by identifier.
|
||||
* This function used to get service reference from TSL struct by identifier.
|
||||
*
|
||||
* @param shadow. The pointer of TSL Struct.
|
||||
* @param identifier. The identifier of event
|
||||
* @param service. The service reference in TSL Struct.
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_get_service_by_identifier(_IN_ dm_shw_t *shadow, _IN_ char *identifier, _OU_ void **service);
|
||||
|
||||
/**
|
||||
* @brief Get event reference from TSL struct by identifier.
|
||||
* This function used to get event reference from TSL struct by identifier.
|
||||
*
|
||||
* @param shadow. The pointer of TSL Struct.
|
||||
* @param identifier. The identifier of event
|
||||
* @param event. The event reference in TSL Struct.
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_get_event_by_identifier(_IN_ dm_shw_t *shadow, _IN_ char *identifier, _OU_ void **event);
|
||||
|
||||
/**
|
||||
* @brief Get property identifier from TSL struct by service handle.
|
||||
* This function used to get property identifier from TSL struct by service handle.
|
||||
*
|
||||
* @param service. The handle of property.
|
||||
* @param method. The reference to property identifier in TSL Struct
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_get_property_identifier(_IN_ void *property, _OU_ char **identifier);
|
||||
|
||||
/**
|
||||
* @brief Get service method from TSL struct by service handle.
|
||||
* This function used to get service method from TSL struct by service handle.
|
||||
*
|
||||
* @param service. The handle of service.
|
||||
* @param method. Generate method from service identifier
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_get_service_method(_IN_ void *service, _OU_ char **method);
|
||||
|
||||
/**
|
||||
* @brief Get event method from TSL struct by event handle.
|
||||
* This function used to get event method from TSL struct by event handle.
|
||||
*
|
||||
* @param service. The handle of event.
|
||||
* @param method. Generate method from event identifier
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_get_event_method(_IN_ void *event, _OU_ char **method);
|
||||
|
||||
/**
|
||||
* @brief Set Property Value Into TSL Struct.
|
||||
* This function used to set property value into TSL Struct.
|
||||
*
|
||||
* @param tsl. The pointer of TSL Struct.
|
||||
* @param key. The property compound string, format decided by data type of property as follows:
|
||||
* int,float,double,text,enum,date,bool type: property_id
|
||||
* array type: property_id(array)[index]
|
||||
* struct type: property_id(struct).property_id or property_id(struct).property_id[index]
|
||||
*
|
||||
* @param key_len. The length of key
|
||||
* @param value. The value to be set, data type decided by data type of property as follows:
|
||||
* int: int*, float: float*, double: double*,
|
||||
* text: char*, enum: int*, date: char*, bool: int*
|
||||
* attention! value can be NULL to clear property value
|
||||
* @param value_len. The length of value, only be used when type is text or data
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_set_property_value(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
|
||||
_IN_ int value_len);
|
||||
|
||||
/**
|
||||
* @brief Get Property Value From TSL Struct.
|
||||
* This function used to get property value from TSL Struct.
|
||||
*
|
||||
* @param tsl. The pointer of TSL Struct.
|
||||
* @param key. The property compound string, format decided by data type of property as follows:
|
||||
* int,float,double,text,enum,date,bool type: property_id
|
||||
* array type: property_id(array)[index]
|
||||
* struct type: property_id(struct).property_id or property_id(struct).property_id[index]
|
||||
*
|
||||
* @param key_len. The length of key
|
||||
* @param value. The variable to store value, data type decided by data type of property as follows:
|
||||
* int: int*, float: float*, double: double*,
|
||||
* text: char**, enum: int*, date: char**, bool: int*
|
||||
* attention! value can not be NULL
|
||||
*
|
||||
* @warning if data type is text or date, *value well be end with '\0'.
|
||||
* the memory allocated to *value must be free by user.
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_get_property_value(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _OU_ void *value);
|
||||
|
||||
/**
|
||||
* @brief Set event output value into TSL struct.
|
||||
* This function used to set event output value into TSL struct.
|
||||
*
|
||||
* @param tsl. The pointer of TSL Struct.
|
||||
* @param key. The property compound string, format decided by data type of property as follows:
|
||||
* int,float,double,text,enum,date,bool type: event_id.event_data_id
|
||||
* array type: event_id.event_data_id(array)[index]
|
||||
* struct type: event_id.event_data_id(struct).property_id
|
||||
* or event_id.event_data_id(struct).property_id[index]
|
||||
*
|
||||
* @param key_len. The length of key
|
||||
* @param value. The value to be set, data type decided by data type of property as follows:
|
||||
* int: int*, float: float*, double: double*,
|
||||
* text: char*, enum: int*, date: char*, bool: int*
|
||||
* attention! value can be NULL to clear property value
|
||||
* @param value_len. The length of value, only be used when type is text or data
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_set_event_output_value(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
|
||||
_IN_ int value_len);
|
||||
|
||||
/**
|
||||
* @brief Get event output value from TSL struct.
|
||||
* This function used to get event output value from TSL struct.
|
||||
*
|
||||
* @param tsl. The pointer of TSL Struct.
|
||||
* @param key. The property compound string, format decided by data type of property as follows:
|
||||
* int,float,double,text,enum,date,bool type: event_id.event_data_id
|
||||
* array type: event_id.event_data_id(array)[index]
|
||||
* struct type: event_id.event_data_id(struct).property_id
|
||||
* or event_id.event_data_id(struct).property_id[index]
|
||||
*
|
||||
* @param key_len. The length of key
|
||||
* @param value. The variable to store value, data type decided by data type of property as follows:
|
||||
* int: int*, float: float*, double: double*,
|
||||
* text: char**, enum: int*, date: char**, bool: int*
|
||||
* attention! value can not be NULL
|
||||
*
|
||||
* @warning if data type is text or date, *value well be end with '\0'.
|
||||
* the memory allocated to *value must be free by user.
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_get_event_output_value(_IN_ dm_shw_t *shadow, _IN_ char *key, _IN_ int key_len, _IN_ void *value);
|
||||
|
||||
int dm_shw_set_service_input_output_value(_IN_ dm_shw_data_target_e type, _IN_ dm_shw_t *shadow, _IN_ char *key,
|
||||
_IN_ int key_len, _IN_ void *value, _IN_ int value_len);
|
||||
int dm_shw_get_service_input_output_value(_IN_ dm_shw_data_target_e type, _IN_ dm_shw_t *shadow, _IN_ char *key,
|
||||
_IN_ int key_len, _IN_ void *value);
|
||||
|
||||
/**
|
||||
* @brief Get property payload from TSL struct.
|
||||
* This function used to get property payload from TSL struct.
|
||||
*
|
||||
* @param shadow. The pointer of TSL Struct
|
||||
* @param identifier. The Property Identifier
|
||||
* @param identifier_len. The Property Identifier Length
|
||||
* @param lite. The pointer to json array where to store property value
|
||||
*
|
||||
* @warning The payload malloc by this function and need to be free manully.
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_assemble_property(_IN_ dm_shw_t *shadow, _IN_ char *identifier, _IN_ int identifier_len,
|
||||
_IN_ lite_cjson_item_t *lite);
|
||||
|
||||
/**
|
||||
* @brief Get event output payload from TSL struct.
|
||||
* This function used to get event output payload from TSL struct.
|
||||
*
|
||||
* @param shadow. The pointer of TSL Struct
|
||||
* @param identifier. The Event Identifier
|
||||
* @param identifier_len. The Event Identifier Length
|
||||
* @param lite. The pointer to json array where to store event output value
|
||||
*
|
||||
* @warning The payload malloc by this function and need to be free manully.
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_assemble_event_output(_IN_ dm_shw_t *shadow, _IN_ char *identifier, _IN_ int identifier_len,
|
||||
_IN_ lite_cjson_item_t *lite);
|
||||
|
||||
/**
|
||||
* @brief Get service output payload from TSL struct.
|
||||
* This function used to get service output payload from TSL struct.
|
||||
*
|
||||
* @param shadow. The pointer of TSL Struct
|
||||
* @param identifier. The Service Identifier
|
||||
* @param identifier_len. The Service Identifier Length
|
||||
* @param lite. The pointer to json array where to store service output value
|
||||
*
|
||||
* @warning The payload malloc by this function and need to be free manully.
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_shw_assemble_service_output(_IN_ dm_shw_t *shadow, _IN_ char *identifier, _IN_ int identifier_len,
|
||||
_IN_ lite_cjson_item_t *lite);
|
||||
|
||||
/**
|
||||
* @brief Free TSL struct.
|
||||
* This function used to free TSL struct.
|
||||
*
|
||||
* @param shadow. The pointer of TSL Struct.
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
void dm_shw_destroy(_IN_ dm_shw_t **shadow);
|
||||
|
||||
#if 0
|
||||
/**
|
||||
* @brief Print detailed information of TSL struct.
|
||||
* This function used to print detailed information of TSL struct.
|
||||
*
|
||||
* @param shadow. The pointer of TSL Struct.
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
void dm_shw_print(_IN_ dm_shw_t *shadow);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#if defined(DEPRECATED_LINKKIT)
|
||||
#ifndef _DM_TSL_ALINK_H_
|
||||
#define _DM_TSL_ALINK_H_
|
||||
|
||||
/**
|
||||
* @brief Create TSL struct from TSL string.
|
||||
* This function used to parse TSL string into TSL struct.
|
||||
*
|
||||
* @param tsl. The TSL string in JSON format.
|
||||
* @param tsl_len. The length of tsl
|
||||
* @param shadow. The pointer of TSL Struct pointer, will be malloc memory.
|
||||
* This memory should be free by dm_shw_destroy.
|
||||
*
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_tsl_alink_create(_IN_ const char *tsl, _IN_ int tsl_len, _OU_ dm_shw_t **shadow);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,428 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "iotx_dm_internal.h"
|
||||
|
||||
int dm_utils_copy_direct(_IN_ void *input, _IN_ int input_len, _OU_ void **output, _IN_ int output_len)
|
||||
{
|
||||
if (input == NULL || output == NULL || *output != NULL) {
|
||||
return DM_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*output = HAL_Malloc(output_len);
|
||||
if (*output == NULL) {
|
||||
return DM_MEMORY_NOT_ENOUGH;
|
||||
}
|
||||
memset(*output, 0, output_len);
|
||||
memcpy(*output, input, input_len);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_utils_copy(_IN_ void *input, _IN_ int input_len, _OU_ void **output, _IN_ int output_len)
|
||||
{
|
||||
if (input == NULL || output == NULL || *output != NULL) {
|
||||
return DM_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*output = DM_malloc(output_len);
|
||||
if (*output == NULL) {
|
||||
return DM_MEMORY_NOT_ENOUGH;
|
||||
}
|
||||
memset(*output, 0, output_len);
|
||||
memcpy(*output, input, input_len);
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_utils_strarr_index(_IN_ char *input, _IN_ int input_len,
|
||||
_OU_ int *partial_input_len, _OU_ int *array_input_len, _OU_ int *array_index)
|
||||
{
|
||||
int index = 0;
|
||||
int deep = 0;
|
||||
char *bracket_pre = NULL;
|
||||
char *bracket_suf = NULL;
|
||||
char array_index_str[10] = {0};
|
||||
|
||||
if (input == NULL || input_len <= 1 || array_index == NULL) {
|
||||
return DM_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
for (index = 0; index < input_len; index++) {
|
||||
switch (input[index]) {
|
||||
case '[': {
|
||||
if (deep != 0) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
deep++;
|
||||
if (!bracket_pre) {
|
||||
bracket_pre = (char *)&input[index];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ']': {
|
||||
if (deep != 1) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
deep--;
|
||||
if (input[index - 1] == '[') {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
if (!bracket_suf) {
|
||||
bracket_suf = (char *)&input[index];
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bracket_pre && bracket_suf && ((bracket_suf - input + 1) == input_len)) {
|
||||
if (partial_input_len) {
|
||||
*partial_input_len = bracket_pre - input;
|
||||
}
|
||||
if (array_input_len) {
|
||||
*array_input_len = bracket_suf - input + 1;
|
||||
}
|
||||
|
||||
/* Get Index */
|
||||
memcpy(array_index_str, bracket_pre + 1, bracket_suf - bracket_pre - 1);
|
||||
*array_index = atoi(array_index_str);
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
int dm_utils_itoa_direct(_IN_ int input, _OU_ char **output)
|
||||
{
|
||||
int res = 0;
|
||||
char temp_output[10 + 1] = {0};
|
||||
|
||||
if (output == NULL || *output != NULL) {
|
||||
return DM_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
res = HAL_Snprintf(temp_output, 10, "%d", input);
|
||||
if (res < 0) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
*output = HAL_Malloc(strlen(temp_output) + 1);
|
||||
if (*output == NULL) {
|
||||
return DM_MEMORY_NOT_ENOUGH;
|
||||
}
|
||||
memset(*output, 0, strlen(temp_output) + 1);
|
||||
memcpy(*output, temp_output, strlen(temp_output));
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_utils_itoa(_IN_ int input, _OU_ char **output)
|
||||
{
|
||||
int res = 0;
|
||||
char temp_output[10 + 1] = {0};
|
||||
|
||||
if (output == NULL || *output != NULL) {
|
||||
return DM_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
res = HAL_Snprintf(temp_output, 10, "%d", input);
|
||||
if (res < 0) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
*output = DM_malloc(strlen(temp_output) + 1);
|
||||
if (*output == NULL) {
|
||||
return DM_MEMORY_NOT_ENOUGH;
|
||||
}
|
||||
memset(*output, 0, strlen(temp_output) + 1);
|
||||
memcpy(*output, temp_output, strlen(temp_output));
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_utils_ftoa_direct(_IN_ double input, _OU_ char **output)
|
||||
{
|
||||
int res = 0;
|
||||
char temp_output[30 + 1] = {0};
|
||||
|
||||
if (output == NULL || *output != NULL) {
|
||||
return DM_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
res = HAL_Snprintf(temp_output, 30, "%f", input);
|
||||
if (res < 0) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
*output = HAL_Malloc(strlen(temp_output) + 1);
|
||||
if (*output == NULL) {
|
||||
return DM_MEMORY_NOT_ENOUGH;
|
||||
}
|
||||
memset(*output, 0, strlen(temp_output) + 1);
|
||||
memcpy(*output, temp_output, strlen(temp_output));
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_utils_ftoa(_IN_ double input, _OU_ char **output)
|
||||
{
|
||||
int res = 0;
|
||||
char temp_output[30 + 1] = {0};
|
||||
|
||||
if (output == NULL || *output != NULL) {
|
||||
return DM_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
res = HAL_Snprintf(temp_output, 30, "%f", input);
|
||||
if (res < 0) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
*output = DM_malloc(strlen(temp_output) + 1);
|
||||
if (*output == NULL) {
|
||||
return DM_MEMORY_NOT_ENOUGH;
|
||||
}
|
||||
memset(*output, 0, strlen(temp_output) + 1);
|
||||
memcpy(*output, temp_output, strlen(temp_output));
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_utils_hex_to_str(_IN_ unsigned char *input, _IN_ int input_len, _OU_ char **output)
|
||||
{
|
||||
int index = 0, output_len = 0;
|
||||
unsigned char iter_char = 0;
|
||||
|
||||
if (input == NULL || input_len <= 0 || output == NULL || *output != NULL) {
|
||||
return DM_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
output_len = input_len * 2;
|
||||
*output = DM_malloc(output_len + 1);
|
||||
if (*output == NULL) {
|
||||
return DM_MEMORY_NOT_ENOUGH;
|
||||
}
|
||||
memset(*output, 0, output_len + 1);
|
||||
|
||||
for (index = 0; index < input_len; index++) {
|
||||
iter_char = (input[index] >> 4) & 0x0F;
|
||||
if (iter_char <= 0x09) {
|
||||
iter_char += '0';
|
||||
} else if (iter_char >= 0x0A && iter_char <= 0x0F) {
|
||||
iter_char += 'A' - 0x0A;
|
||||
}
|
||||
(*output)[index * 2] = iter_char;
|
||||
|
||||
iter_char = (input[index]) & 0x0F;
|
||||
if (iter_char <= 0x09) {
|
||||
iter_char += '0';
|
||||
} else if (iter_char >= 0x0A && iter_char <= 0x0F) {
|
||||
iter_char += 'A' - 0x0A;
|
||||
}
|
||||
(*output)[index * 2 + 1] = iter_char;
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_utils_str_to_hex(_IN_ char *input, _IN_ int input_len, _OU_ unsigned char **output, _OU_ int *output_len)
|
||||
{
|
||||
int index = 0;
|
||||
char iter_char = 0;
|
||||
|
||||
if (input == NULL || input_len <= 0 || input_len % 2 != 0 ||
|
||||
output == NULL || *output != NULL || output_len == NULL) {
|
||||
return DM_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*output_len = input_len / 2;
|
||||
*output = DM_malloc(*output_len);
|
||||
if (*output == NULL) {
|
||||
return DM_MEMORY_NOT_ENOUGH;
|
||||
}
|
||||
memset(*output, 0, *output_len);
|
||||
|
||||
for (index = 0; index < input_len; index += 2) {
|
||||
if (input[index] >= '0' && input[index] <= '9') {
|
||||
iter_char = input[index] - '0';
|
||||
} else if (input[index] >= 'A' && input[index] <= 'F') {
|
||||
iter_char = input[index] - 'A' + 0x0A;
|
||||
}
|
||||
(*output)[index / 2] |= (iter_char << 4) & 0xF0;
|
||||
|
||||
if (input[index + 1] >= '0' && input[index + 1] <= '9') {
|
||||
iter_char = input[index + 1] - '0';
|
||||
} else if (input[index + 1] >= 'A' && input[index + 1] <= 'F') {
|
||||
iter_char = input[index + 1] - 'A' + 0x0A;
|
||||
}
|
||||
(*output)[index / 2] |= (iter_char) & 0x0F;
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_utils_memtok(_IN_ char *input, _IN_ int input_len, _IN_ char delimiter, _IN_ int index, _OU_ int *offset)
|
||||
{
|
||||
int item_index = 0;
|
||||
int count = 0;
|
||||
|
||||
if (input == NULL || input_len <= 0 || offset == NULL) {
|
||||
return DM_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
for (item_index = 0; item_index < input_len; item_index++) {
|
||||
if (input[item_index] == delimiter && (item_index + 1) < input_len) {
|
||||
count++;
|
||||
if (count == index) {
|
||||
*offset = item_index;
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
int dm_utils_replace_char(_IN_ char *input, _IN_ int input_len, _IN_ char src, _IN_ char dest)
|
||||
{
|
||||
int index = 0;
|
||||
|
||||
if (input == NULL || input_len <= 0) {
|
||||
return DM_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
for (index = 0; index < input_len; index++) {
|
||||
if (input[index] == src) {
|
||||
input[index] = dest;
|
||||
}
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_utils_service_name(_IN_ const char *prefix, _IN_ const char *name, _IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
|
||||
_IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1], _OU_ char **service_name)
|
||||
{
|
||||
int prefix_len = (prefix == NULL) ? (0) : (strlen(prefix));
|
||||
int name_len = (name == NULL) ? (0) : (strlen(name));
|
||||
int service_name_len = 0;
|
||||
if ((prefix == NULL && name == NULL) || product_key == NULL || device_name == NULL ||
|
||||
service_name == NULL || *service_name != NULL) {
|
||||
return DM_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
service_name_len = prefix_len + name_len + strlen(product_key) + strlen(device_name) + 1;
|
||||
*service_name = DM_malloc(service_name_len);
|
||||
if (*service_name == NULL) {
|
||||
return DM_MEMORY_NOT_ENOUGH;
|
||||
}
|
||||
memset(*service_name, 0, service_name_len);
|
||||
|
||||
if (prefix != NULL) {
|
||||
HAL_Snprintf(*service_name, service_name_len, prefix, product_key, device_name);
|
||||
}
|
||||
|
||||
if (name != NULL) {
|
||||
memcpy(*service_name + strlen(*service_name), name, name_len);
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_utils_uri_add_prefix(_IN_ const char *prefix, _IN_ char *uri, _OU_ char **new_uri)
|
||||
{
|
||||
int new_uri_len = 0;
|
||||
|
||||
if (prefix == NULL || uri == NULL || new_uri == NULL || *new_uri != NULL) {
|
||||
return DM_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
new_uri_len = strlen(prefix) + strlen(uri) + 1;
|
||||
*new_uri = DM_malloc(new_uri_len);
|
||||
if (*new_uri == NULL) {
|
||||
return DM_MEMORY_NOT_ENOUGH;
|
||||
}
|
||||
memset(*new_uri, 0, new_uri_len);
|
||||
|
||||
memcpy(*new_uri, prefix, strlen(prefix));
|
||||
memcpy(*new_uri + strlen(*new_uri), uri, strlen(uri));
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_utils_json_parse(_IN_ const char *payload, _IN_ int payload_len, _IN_ int type, _OU_ lite_cjson_t *lite)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
if (payload == NULL || payload_len <= 0 || type < 0 || lite == NULL) {
|
||||
return DM_INVALID_PARAMETER;
|
||||
}
|
||||
memset(lite, 0, sizeof(lite_cjson_t));
|
||||
|
||||
res = lite_cjson_parse(payload, payload_len, lite);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
memset(lite, 0, sizeof(lite_cjson_t));
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
if (type != cJSON_Invalid && lite->type != type) {
|
||||
memset(lite, 0, sizeof(lite_cjson_t));
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
int dm_utils_json_object_item(_IN_ lite_cjson_t *lite, _IN_ const char *key, _IN_ int key_len, _IN_ int type,
|
||||
_OU_ lite_cjson_t *lite_item)
|
||||
{
|
||||
int res = 0;
|
||||
|
||||
if (lite == NULL || lite->type != cJSON_Object || key == NULL || key_len <= 0 || type < 0 || lite_item == NULL) {
|
||||
return DM_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (lite->type != cJSON_Object) {
|
||||
dm_log_err("lite->type != cJSON_Object, %d", lite->type);
|
||||
}
|
||||
|
||||
memset(lite_item, 0, sizeof(lite_cjson_t));
|
||||
|
||||
res = lite_cjson_object_item(lite, key, key_len, lite_item);
|
||||
if (res != SUCCESS_RETURN) {
|
||||
/* dm_log_err(DM_UTILS_LOG_JSON_PARSE_FAILED, lite->value_length, lite->value); */
|
||||
memset(lite_item, 0, sizeof(lite_cjson_t));
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
if (type != cJSON_Invalid && lite_item->type != type) {
|
||||
memset(lite_item, 0, sizeof(lite_cjson_t));
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
return SUCCESS_RETURN;
|
||||
}
|
||||
|
||||
void *dm_utils_malloc(unsigned int size)
|
||||
{
|
||||
#ifdef INFRA_MEM_STATS
|
||||
return LITE_malloc(size, MEM_MAGIC, "lite_cjson");
|
||||
#else
|
||||
return HAL_Malloc(size);
|
||||
#endif
|
||||
}
|
||||
|
||||
void dm_utils_free(void *ptr)
|
||||
{
|
||||
#ifdef INFRA_MEM_STATS
|
||||
LITE_free(ptr);
|
||||
#else
|
||||
HAL_Free((void *)ptr);
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _DM_UTILS_H_
|
||||
#define _DM_UTILS_H_
|
||||
|
||||
#define DM_UTILS_UINT16_STRLEN (5)
|
||||
#define DM_UTILS_UINT32_STRLEN (10)
|
||||
#define DM_UTILS_UINT64_STRLEN (20)
|
||||
|
||||
int dm_utils_copy_direct(void *input, int input_len, void **output, int output_len);
|
||||
|
||||
int dm_utils_copy(void *input, int input_len, void **output, int output_len);
|
||||
|
||||
/**
|
||||
* @brief search array index in a string.
|
||||
* This function used to search array index in a string.
|
||||
*
|
||||
* @param input. The string to be searched
|
||||
* @param input_len. The length of input
|
||||
* @param partial_input_len. The length of input except [xx]
|
||||
* @param array_input_len. The length of input include [xx]
|
||||
* @param array_index. The array index in [xx]
|
||||
*
|
||||
* @warning input must be type of "xxxxx[xx]"
|
||||
* @return success or fail.
|
||||
*
|
||||
*/
|
||||
int dm_utils_strarr_index(char *input, int input_len,
|
||||
int *partial_input_len, int *array_input_len, int *array_index);
|
||||
|
||||
int dm_utils_itoa_direct(int input, char **output);
|
||||
int dm_utils_itoa(int input, char **output);
|
||||
int dm_utils_ftoa_direct(double input, char **output);
|
||||
int dm_utils_ftoa(double input, char **output);
|
||||
int dm_utils_hex_to_str(unsigned char *input, int input_len, char **output);
|
||||
int dm_utils_str_to_hex(char *input, int input_len, unsigned char **output, int *output_len);
|
||||
int dm_utils_memtok(char *input, int input_len, char delimiter, int index, int *offset);
|
||||
int dm_utils_replace_char(char *input, int input_len, char src, char dest);
|
||||
int dm_utils_service_name(const char *prefix, const char *name, char product_key[IOTX_PRODUCT_KEY_LEN + 1],
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1], char **service_name);
|
||||
int dm_utils_uri_add_prefix(const char *prefix, char *uri, char **new_uri);
|
||||
int dm_utils_json_parse(const char *payload, int payload_len, int type, lite_cjson_t *lite);
|
||||
int dm_utils_json_object_item(lite_cjson_t *lite, const char *key, int key_len, int type,
|
||||
lite_cjson_t *lite_item);
|
||||
void *dm_utils_malloc(unsigned int size);
|
||||
void dm_utils_free(void *ptr);
|
||||
#endif
|
||||
@@ -0,0 +1,81 @@
|
||||
#ifndef _DM_WRAPPER_H_
|
||||
#define _DM_WRAPPER_H_
|
||||
|
||||
#include "infra_compat.h"
|
||||
#include "wrappers_defs.h"
|
||||
|
||||
int HAL_GetProductKey(char product_key[IOTX_PRODUCT_KEY_LEN + 1]);
|
||||
int HAL_GetProductSecret(char product_secret[IOTX_PRODUCT_SECRET_LEN + 1]);
|
||||
int HAL_GetDeviceName(char device_name[IOTX_DEVICE_NAME_LEN + 1]);
|
||||
int HAL_GetDeviceSecret(char device_secret[IOTX_DEVICE_SECRET_LEN + 1]);
|
||||
|
||||
void *HAL_MutexCreate(void);
|
||||
void HAL_MutexDestroy(void *mutex);
|
||||
void HAL_MutexLock(void *mutex);
|
||||
void HAL_MutexUnlock(void *mutex);
|
||||
|
||||
void *HAL_Malloc(uint32_t size);
|
||||
void HAL_Free(void *ptr);
|
||||
uint64_t HAL_UptimeMs(void);
|
||||
void HAL_SleepMs(uint32_t ms);
|
||||
void HAL_Srandom(uint32_t seed);
|
||||
uint32_t HAL_Random(uint32_t region);
|
||||
void HAL_Printf(const char *fmt, ...);
|
||||
int HAL_Snprintf(char *str, const int len, const char *fmt, ...);
|
||||
|
||||
#ifdef INFRA_LOG
|
||||
#include <stdarg.h>
|
||||
int HAL_Vsnprintf(char *str, const int len, const char *format, va_list ap);
|
||||
#endif
|
||||
|
||||
int HAL_ThreadCreate(
|
||||
void **thread_handle,
|
||||
void *(*work_routine)(void *),
|
||||
void *arg,
|
||||
hal_os_thread_param_t *hal_os_thread_param,
|
||||
int *stack_used);
|
||||
void HAL_ThreadDelete(void *thread_handle);
|
||||
|
||||
void *HAL_SemaphoreCreate(void);
|
||||
void HAL_SemaphoreDestroy(void *sem);
|
||||
void HAL_SemaphorePost(void *sem);
|
||||
int HAL_SemaphoreWait(void *sem, uint32_t timeout_ms);
|
||||
int HAL_Kv_Set(const char *key, const void *val, int len, int sync);
|
||||
int HAL_Kv_Get(const char *key, void *val, int *buffer_len);
|
||||
int HAL_Kv_Del(const char *key);
|
||||
#if defined(OTA_ENABLED) && !defined(BUILD_AOS)
|
||||
void HAL_Firmware_Persistence_Start(void);
|
||||
int HAL_Firmware_Persistence_Write(char *buffer, uint32_t length);
|
||||
int HAL_Firmware_Persistence_Stop(void);
|
||||
#ifdef SUPPORT_SECURITY_OTA
|
||||
int HAL_Firmware_Check_Rsa_Key(char *buffer, uint32_t length);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
//#ifdef DEPRECATED_LINKKIT
|
||||
#if 1
|
||||
int HAL_SetProductKey(char *product_key);
|
||||
int HAL_SetProductSecret(char *product_secret);
|
||||
int HAL_SetDeviceName(char *device_name);
|
||||
int HAL_SetDeviceSecret(char *device_secret);
|
||||
#endif
|
||||
|
||||
#ifdef ALCS_ENABLED
|
||||
p_HAL_Aes128_t HAL_Aes128_Init(
|
||||
const uint8_t *key,
|
||||
const uint8_t *iv,
|
||||
AES_DIR_t dir);
|
||||
int HAL_Aes128_Cbc_Encrypt(
|
||||
p_HAL_Aes128_t aes,
|
||||
const void *src,
|
||||
size_t blockNum,
|
||||
void *dst);
|
||||
int HAL_Aes128_Destroy(p_HAL_Aes128_t aes);
|
||||
int HAL_Aes128_Cbc_Decrypt(
|
||||
p_HAL_Aes128_t aes,
|
||||
const void *src,
|
||||
size_t blockNum,
|
||||
void *dst);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef _LINKKIT_GATEWAY_LEGACY_H_
|
||||
#define _LINKKIT_GATEWAY_LEGACY_H_
|
||||
|
||||
#include "infra_list.h"
|
||||
#include "linkkit_gateway_export.h"
|
||||
|
||||
#define LINKKIT_GATEWAY_LEGACY_KEY_ID "id"
|
||||
#define LINKKIT_GATEWAY_LEGACY_KEY_CODE "code"
|
||||
#define LINKKIT_GATEWAY_LEGACY_KEY_DEVID "devid"
|
||||
#define LINKKIT_GATEWAY_LEGACY_KEY_SERVICEID "serviceid"
|
||||
#define LINKKIT_GATEWAY_LEGACY_KEY_PROPERTYID "propertyid"
|
||||
#define LINKKIT_GATEWAY_LEGACY_KEY_EVENTID "eventid"
|
||||
#define LINKKIT_GATEWAY_LEGACY_KEY_PAYLOAD "payload"
|
||||
#define LINKKIT_GATEWAY_LEGACY_KEY_PRODUCT_KEY "productKey"
|
||||
#define LINKKIT_GATEWAY_LEGACY_KEY_TIME "time"
|
||||
#define LINKKIT_GATEWAY_LEGACY_KEY_VERSION "version"
|
||||
|
||||
#define LINKKIT_GATEWAY_LEGACY_SYNC_DEFAULT_TIMEOUT_MS (10000)
|
||||
|
||||
typedef struct {
|
||||
int devid;
|
||||
linkkit_cbs_t *callback;
|
||||
void *callback_ctx;
|
||||
struct list_head linked_list;
|
||||
} linkkit_gateway_dev_callback_node_t;
|
||||
|
||||
typedef void (*linkkit_gateway_upstream_async_callback)(int retval, void *ctx);
|
||||
typedef struct {
|
||||
int msgid;
|
||||
void *semaphore;
|
||||
int code;
|
||||
struct list_head linked_list;
|
||||
} linkkit_gateway_upstream_sync_callback_node_t;
|
||||
|
||||
typedef struct {
|
||||
int msgid;
|
||||
int timeout_ms;
|
||||
uint64_t timestamp_ms;
|
||||
linkkit_gateway_upstream_async_callback callback;
|
||||
void *callback_ctx;
|
||||
struct list_head linked_list;
|
||||
} linkkit_gateway_upstream_async_callback_node_t;
|
||||
|
||||
typedef struct {
|
||||
void *mutex;
|
||||
void *upstream_mutex;
|
||||
int is_inited;
|
||||
int is_started;
|
||||
linkkit_params_t init_params;
|
||||
void *dispatch_thread;
|
||||
handle_service_fota_callback_fp_t fota_callback;
|
||||
struct list_head dev_callback_list;
|
||||
struct list_head upstream_sync_callback_list;
|
||||
struct list_head upstream_async_callback_list;
|
||||
} linkkit_gateway_legacy_ctx_t;
|
||||
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
#include "iotx_dm_internal.h"
|
||||
|
||||
#ifdef DEPRECATED_LINKKIT
|
||||
|
||||
#include "infra_json_parser.h"
|
||||
#include "mqtt_api.h"
|
||||
#include "impl_ntp.h"
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef INFRA_MEM_STATS
|
||||
#include "infra_mem_stats.h"
|
||||
#define IMPL_NTP_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "impl.ntp")
|
||||
#define IMPL_NTP_FREE(ptr) LITE_free(ptr)
|
||||
#else
|
||||
#define IMPL_NTP_MALLOC(size) HAL_Malloc(size)
|
||||
#define IMPL_NTP_FREE(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
|
||||
#endif
|
||||
|
||||
typedef void (*ntp_reply_cb_t)(const char *);
|
||||
static ntp_reply_cb_t g_ntp_reply_cb = NULL;
|
||||
static char g_ntp_time[NTP_TIME_STR_MAX_LEN + 1] = {0};
|
||||
|
||||
static void linkkit_ntp_time_reply(void *pcontext, void *pclient, void *mesg)
|
||||
{
|
||||
#define DEV_TX_TIME "deviceSendTime"
|
||||
#define SERVER_RX_TIME "serverRecvTime"
|
||||
#define SERVER_TX_TIME "serverSendTime"
|
||||
|
||||
int len = 0;
|
||||
char *elem = NULL;
|
||||
char server_rx_time[NTP_TIME_STR_MAX_LEN + 1] = {0};
|
||||
char server_tx_time[NTP_TIME_STR_MAX_LEN + 1] = {0};
|
||||
uint32_t payload_len;
|
||||
char *payload;
|
||||
uint32_t tx = 0;
|
||||
uint32_t rx = 0;
|
||||
uint32_t diff = 0;
|
||||
|
||||
iotx_mqtt_event_msg_pt msg = (iotx_mqtt_event_msg_pt)mesg;
|
||||
iotx_mqtt_topic_info_pt ptopic_info = (iotx_mqtt_topic_info_pt) msg->msg;
|
||||
|
||||
switch (msg->event_type) {
|
||||
case IOTX_MQTT_EVENT_PUBLISH_RECEIVED:
|
||||
payload_len = ptopic_info->payload_len;
|
||||
payload = (char *)ptopic_info->payload;
|
||||
break;
|
||||
default:
|
||||
goto NTP_FAIL;
|
||||
}
|
||||
|
||||
if (payload == NULL || payload_len == 0) {
|
||||
goto NTP_FAIL;
|
||||
}
|
||||
|
||||
memset(g_ntp_time, 0, sizeof(g_ntp_time));
|
||||
log_debug("[ntp]", "ntp reply len:%u, payload:%s\r\n", payload_len, payload);
|
||||
|
||||
/*
|
||||
* get deviceSendTime, serverRecvTime, serverSendTime
|
||||
*/
|
||||
elem = json_get_value_by_name(payload, payload_len, SERVER_TX_TIME, &len, NULL);
|
||||
if (elem == NULL || len <= 0 || len > NTP_TIME_STR_MAX_LEN) {
|
||||
goto NTP_FAIL;
|
||||
}
|
||||
|
||||
memcpy(server_tx_time, elem, len);
|
||||
|
||||
elem = json_get_value_by_name(payload, payload_len, SERVER_RX_TIME, &len, NULL);
|
||||
if (elem == NULL || len <= 0 || len > NTP_TIME_STR_MAX_LEN) {
|
||||
goto NTP_FAIL;
|
||||
}
|
||||
|
||||
memcpy(server_rx_time, elem, len);
|
||||
|
||||
elem = json_get_value_by_name(payload, payload_len, DEV_TX_TIME, &len, NULL);
|
||||
if (elem == NULL || len <= 0 || len > NTP_TIME_STR_MAX_LEN) {
|
||||
goto NTP_FAIL;
|
||||
}
|
||||
/*
|
||||
* atoi fails to convert string to integer
|
||||
* so we convert manully
|
||||
*/
|
||||
while (len -- > 0) {
|
||||
tx *= 10;
|
||||
tx += elem[0] - '0';
|
||||
elem ++;
|
||||
}
|
||||
rx = HAL_UptimeMs();
|
||||
diff = (rx - tx) >> 1;
|
||||
if (diff >= 1000000) {
|
||||
goto NTP_FAIL;
|
||||
}
|
||||
|
||||
len = strlen(server_tx_time);
|
||||
elem = &server_tx_time[len > 9 ? len - 9 : 0];
|
||||
tx = atoi(elem);
|
||||
tx += diff;
|
||||
|
||||
if (tx > 999999999) {
|
||||
tx = 999999999;
|
||||
}
|
||||
|
||||
if (len > 9) {
|
||||
sprintf(elem, "%09u", (unsigned int)tx);
|
||||
} else {
|
||||
sprintf(elem, "%u", (unsigned int)tx);
|
||||
}
|
||||
|
||||
strncpy(g_ntp_time, (const char *)server_tx_time, sizeof(g_ntp_time) - 1);
|
||||
|
||||
NTP_FAIL:
|
||||
if (g_ntp_reply_cb != NULL) {
|
||||
g_ntp_reply_cb(g_ntp_time);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
int linkkit_ntp_time_request(void (*ntp_reply)(const char *ntp_offset_time_ms))
|
||||
{
|
||||
int ret = -1;
|
||||
int final_len = 0;
|
||||
int packet_len = 64;
|
||||
int topic_len = 128;
|
||||
char *packet = NULL;
|
||||
char *topic = NULL;
|
||||
|
||||
do {
|
||||
char pk[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char dn[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
|
||||
HAL_GetProductKey(pk);
|
||||
HAL_GetDeviceName(dn);
|
||||
|
||||
topic = (char *)IMPL_NTP_MALLOC(topic_len + 1);
|
||||
if (topic == NULL) {
|
||||
goto NTP_REQ_ERR;
|
||||
}
|
||||
memset(topic, 0, topic_len + 1);
|
||||
|
||||
HAL_Snprintf(topic, topic_len, TOPIC_NTP_REPLY, pk, dn);
|
||||
ret = IOT_MQTT_Subscribe_Sync(NULL, topic, IOTX_MQTT_QOS0,
|
||||
(iotx_mqtt_event_handle_func_fpt)linkkit_ntp_time_reply, NULL, 1000);
|
||||
if (ret < 0) {
|
||||
goto NTP_REQ_ERR;
|
||||
}
|
||||
|
||||
memset(topic, 0, topic_len + 1);
|
||||
HAL_Snprintf(topic, topic_len, TOPIC_NTP, pk, dn);
|
||||
} while (0);
|
||||
|
||||
packet = (char *)IMPL_NTP_MALLOC(packet_len + 1);
|
||||
if (packet == NULL) {
|
||||
ret = -1;
|
||||
goto NTP_REQ_ERR;
|
||||
}
|
||||
memset(packet, 0, packet_len + 1);
|
||||
|
||||
g_ntp_reply_cb = ntp_reply;
|
||||
final_len = HAL_Snprintf(packet, packet_len, "{\"deviceSendTime\":\"%u\"}", (unsigned int)(HAL_UptimeMs()));
|
||||
|
||||
log_debug("[ntp]", "report ntp:%s\r\n", packet);
|
||||
|
||||
|
||||
ret = IOT_MQTT_Publish_Simple(NULL, topic, IOTX_MQTT_QOS0, packet, final_len);
|
||||
|
||||
NTP_REQ_ERR:
|
||||
if (topic) {
|
||||
IMPL_NTP_FREE(topic);
|
||||
}
|
||||
if (packet) {
|
||||
IMPL_NTP_FREE(packet);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
#ifndef NTP_H
|
||||
#define NTP_H
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define TOPIC_NTP "/ext/ntp/%s/%s/request"
|
||||
#define TOPIC_NTP_REPLY "/ext/ntp/%s/%s/response"
|
||||
|
||||
#define NTP_TIME_STR_MAX_LEN (20)
|
||||
|
||||
int linkkit_ntp_time_request(void (*)(const char *ntp_offset_time_ms));
|
||||
|
||||
#if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef _LINKKIT_SOLO_LEGACY_H_
|
||||
#define _LINKKIT_SOLO_LEGACY_H_
|
||||
|
||||
#include "linkkit_export.h"
|
||||
|
||||
#define LINKKIT_SOLO_LEGACY_KEY_ID "id"
|
||||
#define LINKKIT_SOLO_LEGACY_KEY_CODE "code"
|
||||
#define LINKKIT_SOLO_LEGACY_KEY_DEVID "devid"
|
||||
#define LINKKIT_SOLO_LEGACY_KEY_SERVICEID "serviceid"
|
||||
#define LINKKIT_SOLO_LEGACY_KEY_PROPERTYID "propertyid"
|
||||
#define LINKKIT_SOLO_LEGACY_KEY_EVENTID "eventid"
|
||||
#define LINKKIT_SOLO_LEGACY_KEY_PAYLOAD "payload"
|
||||
#define LINKKIT_SOLO_LEGACY_KEY_CONFIG_ID "configId"
|
||||
#define LINKKIT_SOLO_LEGACY_KEY_CONFIG_SIZE "configSize"
|
||||
#define LINKKIT_SOLO_LEGACY_KEY_GET_TYPE "getType"
|
||||
#define LINKKIT_SOLO_LEGACY_KEY_SIGN "sign"
|
||||
#define LINKKIT_SOLO_LEGACY_KEY_SIGN_METHOD "signMethod"
|
||||
#define LINKKIT_SOLO_LEGACY_KEY_URL "url"
|
||||
#define LINKKIT_SOLO_LEGACY_KEY_VERSION "version"
|
||||
|
||||
typedef struct {
|
||||
int msgid;
|
||||
handle_post_cb_fp_t callback;
|
||||
struct list_head linked_list;
|
||||
} linkkit_solo_upstream_callback_node_t;
|
||||
|
||||
typedef struct {
|
||||
void *mutex;
|
||||
void *upstream_mutex;
|
||||
int is_started;
|
||||
int is_leaved;
|
||||
linkkit_ops_t *user_callback;
|
||||
void *user_context;
|
||||
handle_service_cota_callback_fp_t cota_callback;
|
||||
handle_service_fota_callback_fp_t fota_callback;
|
||||
struct list_head callback_list;
|
||||
} linkkit_solo_legacy_ctx_t;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef _IOT_EXPORT_LINKKIT_H_
|
||||
#define _IOT_EXPORT_LINKKIT_H_
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "dm_wrapper.h"
|
||||
|
||||
typedef enum {
|
||||
IOTX_LINKKIT_DEV_TYPE_MASTER,
|
||||
IOTX_LINKKIT_DEV_TYPE_SLAVE,
|
||||
IOTX_LINKKIT_DEV_TYPE_MAX
|
||||
} iotx_linkkit_dev_type_t;
|
||||
|
||||
typedef struct {
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1];
|
||||
char product_secret[IOTX_PRODUCT_SECRET_LEN + 1];
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1];
|
||||
char device_secret[IOTX_DEVICE_SECRET_LEN + 1];
|
||||
} iotx_linkkit_dev_meta_info_t;
|
||||
|
||||
typedef enum {
|
||||
/* post property value to cloud */
|
||||
ITM_MSG_POST_PROPERTY,
|
||||
|
||||
/* post device info update message to cloud */
|
||||
ITM_MSG_DEVICEINFO_UPDATE,
|
||||
|
||||
/* post device info delete message to cloud */
|
||||
ITM_MSG_DEVICEINFO_DELETE,
|
||||
|
||||
/* post raw data to cloud */
|
||||
ITM_MSG_POST_RAW_DATA,
|
||||
|
||||
/* only for slave device, send login request to cloud */
|
||||
ITM_MSG_LOGIN,
|
||||
|
||||
/* only for slave device, send logout request to cloud */
|
||||
ITM_MSG_LOGOUT,
|
||||
|
||||
/* only for slave device, send delete topo request to cloud */
|
||||
ITM_MSG_DELETE_TOPO,
|
||||
|
||||
/* query ntp time from cloud */
|
||||
ITM_MSG_QUERY_TIMESTAMP,
|
||||
|
||||
/* only for master device, query topo list */
|
||||
ITM_MSG_QUERY_TOPOLIST,
|
||||
|
||||
/* only for master device, qurey firmware ota data */
|
||||
ITM_MSG_QUERY_FOTA_DATA,
|
||||
|
||||
/* only for master device, qurey config ota data */
|
||||
ITM_MSG_QUERY_COTA_DATA,
|
||||
|
||||
/* only for master device, request config ota data from cloud */
|
||||
ITM_MSG_REQUEST_COTA,
|
||||
|
||||
/* only for master device, request fota image from cloud */
|
||||
ITM_MSG_REQUEST_FOTA_IMAGE,
|
||||
|
||||
/* report subdev's firmware version */
|
||||
ITM_MSG_REPORT_SUBDEV_FIRMWARE_VERSION,
|
||||
|
||||
/* get a device's desired property */
|
||||
ITM_MSG_PROPERTY_DESIRED_GET,
|
||||
|
||||
/* delete a device's desired property */
|
||||
ITM_MSG_PROPERTY_DESIRED_DELETE,
|
||||
|
||||
IOTX_LINKKIT_MSG_MAX
|
||||
} iotx_linkkit_msg_type_t;
|
||||
|
||||
/**
|
||||
* @brief create a new device
|
||||
*
|
||||
* @param dev_type. type of device which will be created. see iotx_linkkit_dev_type_t
|
||||
* @param meta_info. The product key, product secret, device name and device secret of new device.
|
||||
*
|
||||
* @return success: device id (>=0), fail: -1.
|
||||
*
|
||||
*/
|
||||
DLL_IOT_API int IOT_Linkkit_Open(iotx_linkkit_dev_type_t dev_type, iotx_linkkit_dev_meta_info_t *meta_info);
|
||||
|
||||
/**
|
||||
* @brief start device network connection.
|
||||
* for master device, start to connect aliyun server.
|
||||
* for slave device, send message to cloud for register new device and add topo with master device
|
||||
*
|
||||
* @param devid. device identifier.
|
||||
*
|
||||
* @return success: device id (>=0), fail: -1.
|
||||
*
|
||||
*/
|
||||
DLL_IOT_API int IOT_Linkkit_Connect(int devid);
|
||||
|
||||
/**
|
||||
* @brief try to receive message from cloud and dispatch these message to user event callback
|
||||
*
|
||||
* @param timeout_ms. timeout for waiting new message arrived
|
||||
*
|
||||
* @return void.
|
||||
*
|
||||
*/
|
||||
DLL_IOT_API void IOT_Linkkit_Yield(int timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief close device network connection and release resources.
|
||||
* for master device, disconnect with aliyun server and release all local resources.
|
||||
* for slave device, send message to cloud for delete topo with master device and unregister itself, then release device's resources.
|
||||
*
|
||||
* @param devid. device identifier.
|
||||
*
|
||||
* @return success: 0, fail: -1.
|
||||
*
|
||||
*/
|
||||
DLL_IOT_API int IOT_Linkkit_Close(int devid);
|
||||
|
||||
/**
|
||||
* @brief Report message to cloud
|
||||
*
|
||||
* @param devid. device identifier.
|
||||
* @param msg_type. message type. see iotx_linkkit_msg_type_t, as follows:
|
||||
* ITM_MSG_POST_PROPERTY
|
||||
* ITM_MSG_DEVICEINFO_UPDATE
|
||||
* ITM_MSG_DEVICEINFO_DELETE
|
||||
* ITM_MSG_POST_RAW_DATA
|
||||
* ITM_MSG_LOGIN
|
||||
* ITM_MSG_LOGOUT
|
||||
*
|
||||
* @param payload. message payload.
|
||||
* @param payload_len. message payload length.
|
||||
*
|
||||
* @return success: 0 or message id (>=1), fail: -1.
|
||||
*
|
||||
*/
|
||||
DLL_IOT_API int IOT_Linkkit_Report(int devid, iotx_linkkit_msg_type_t msg_type, unsigned char *payload,
|
||||
int payload_len);
|
||||
|
||||
/**
|
||||
* @brief post message to cloud
|
||||
*
|
||||
* @param devid. device identifier.
|
||||
* @param msg_type. message type. see iotx_linkkit_msg_type_t, as follows:
|
||||
* ITM_MSG_QUERY_TIMESTAMP
|
||||
* ITM_MSG_QUERY_TOPOLIST
|
||||
* ITM_MSG_QUERY_FOTA_DATA
|
||||
* ITM_MSG_QUERY_COTA_DATA
|
||||
* ITM_MSG_REQUEST_COTA
|
||||
* ITM_MSG_REQUEST_FOTA_IMAGE
|
||||
*
|
||||
* @param payload. message payload.
|
||||
* @param payload_len. message payload length.
|
||||
*
|
||||
* @return success: 0 or message id (>=1), fail: -1.
|
||||
*
|
||||
*/
|
||||
DLL_IOT_API int IOT_Linkkit_Query(int devid, iotx_linkkit_msg_type_t msg_type, unsigned char *payload,
|
||||
int payload_len);
|
||||
|
||||
/**
|
||||
* @brief post event to cloud
|
||||
*
|
||||
* @param devid. device identifier.
|
||||
* @param eventid. tsl event id.
|
||||
* @param eventid_len. length of tsl event id.
|
||||
* @param payload. event payload.
|
||||
* @param payload_len. event payload length.
|
||||
*
|
||||
* @return success: message id (>=1), fail: -1.
|
||||
*
|
||||
*/
|
||||
DLL_IOT_API int IOT_Linkkit_TriggerEvent(int devid, char *eventid, int eventid_len, char *payload, int payload_len);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _IOT_EXPORT_ALCS_BACKUP_H_
|
||||
#define _IOT_EXPORT_ALCS_BACKUP_H_
|
||||
|
||||
#define IOTX_ALCS_ROLE_CLIENT (0x01)
|
||||
#define IOTX_ALCS_ROLE_SERVER (0x02)
|
||||
|
||||
#define ALCS_MSG_MAX_TOKEN_LEN (8)
|
||||
|
||||
typedef enum {
|
||||
|
||||
/*iotx_alcs_send Message Result And Receive Message*/
|
||||
IOTX_ALCS_EVENT_MSG_SEND_MESSAGE_SUCCESS,
|
||||
IOTX_ALCS_EVENT_MSG_SEND_MESSAGE_RESP_TIMEOUT,
|
||||
IOTX_ALCS_EVENT_MSG_RECV_MESSAGE,
|
||||
/*Its data type is @iotx_alcs_transfer_msg_t and see detail at the declare of this type.*/
|
||||
|
||||
} iotx_alcs_event_type_t;
|
||||
|
||||
typedef struct iotx_alcs_event_msg_st {
|
||||
|
||||
/* Specify the event type */
|
||||
iotx_alcs_event_type_t event_type;
|
||||
|
||||
void *msg;
|
||||
} iotx_alcs_event_msg_t, *iotx_alcs_event_msg_pt;
|
||||
|
||||
typedef struct iotx_alcs_transfer_msg_st {
|
||||
char *ip;
|
||||
uint16_t port;
|
||||
char *uri;
|
||||
uint8_t token_len;
|
||||
uint8_t *token;
|
||||
uint16_t payload_len;
|
||||
uint8_t *payload;
|
||||
} iotx_alcs_transfer_msg_t, *iotx_alcs_transfer_msg_pt;
|
||||
|
||||
typedef void (*iotx_alcs_event_handle_func_fpt)(void *pcontext, void *phandle, iotx_alcs_event_msg_t *msg);
|
||||
|
||||
typedef struct {
|
||||
iotx_alcs_event_handle_func_fpt h_fp;
|
||||
void *pcontext;
|
||||
} iotx_alcs_event_handle_t;
|
||||
|
||||
typedef struct iotx_alcs_param_st {
|
||||
uint8_t role; /*can be client, server or both*/
|
||||
|
||||
uint8_t send_maxcount; /*list maximal count*/
|
||||
uint8_t obs_maxcount; /*observe maximal count*/
|
||||
uint16_t port; /* Local port */
|
||||
char *group; /* Multicast address */
|
||||
uint32_t waittime;
|
||||
uint8_t res_maxcount;
|
||||
|
||||
iotx_alcs_event_handle_t *handle_event;
|
||||
} iotx_alcs_param_t, *iotx_alcs_param_pt;
|
||||
|
||||
#define ITOX_ALCS_COAP_MSG_CODE_DEF(N) (((N)/100 << 5) | (N)%100)
|
||||
|
||||
/*CoAP Message codes*/
|
||||
typedef enum {
|
||||
/* CoAP Empty Message */
|
||||
ITOX_ALCS_COAP_MSG_CODE_EMPTY_MESSAGE = ITOX_ALCS_COAP_MSG_CODE_DEF(0), /* Mapping to CoAP code 0.00 */
|
||||
|
||||
/* CoAP Method Codes */
|
||||
ITOX_ALCS_COAP_MSG_CODE_GET = ITOX_ALCS_COAP_MSG_CODE_DEF(1), /* CoAP Get method */
|
||||
ITOX_ALCS_COAP_MSG_CODE_POST = ITOX_ALCS_COAP_MSG_CODE_DEF(2), /* CoAP Post method */
|
||||
ITOX_ALCS_COAP_MSG_CODE_PUT = ITOX_ALCS_COAP_MSG_CODE_DEF(3), /* CoAP Put method */
|
||||
ITOX_ALCS_COAP_MSG_CODE_DELETE = ITOX_ALCS_COAP_MSG_CODE_DEF(4), /* CoAP Delete method */
|
||||
|
||||
/* CoAP Success Response Codes */
|
||||
ITOX_ALCS_COAP_MSG_CODE_201_CREATED = ITOX_ALCS_COAP_MSG_CODE_DEF(201), /* Mapping to CoAP code 2.01, Hex:0x41, Created */
|
||||
ITOX_ALCS_COAP_MSG_CODE_202_DELETED = ITOX_ALCS_COAP_MSG_CODE_DEF(202), /* Mapping to CoAP code 2.02, Hex:0x42, Deleted*/
|
||||
ITOX_ALCS_COAP_MSG_CODE_203_VALID = ITOX_ALCS_COAP_MSG_CODE_DEF(203), /* Mapping to CoAP code 2.03, Hex:0x43, Valid*/
|
||||
ITOX_ALCS_COAP_MSG_CODE_204_CHANGED = ITOX_ALCS_COAP_MSG_CODE_DEF(204), /* Mapping to CoAP code 2.04, Hex:0x44, Changed*/
|
||||
ITOX_ALCS_COAP_MSG_CODE_205_CONTENT = ITOX_ALCS_COAP_MSG_CODE_DEF(205), /* Mapping to CoAP code 2.05, Hex:0x45, Content*/
|
||||
ITOX_ALCS_COAP_MSG_CODE_231_CONTINUE = ITOX_ALCS_COAP_MSG_CODE_DEF(231), /* Mapping to CoAP code 2.31, Hex:0x5F, Continue*/
|
||||
|
||||
/* CoAP Client Error Response Codes */
|
||||
ITOX_ALCS_COAP_MSG_CODE_400_BAD_REQUEST = ITOX_ALCS_COAP_MSG_CODE_DEF(400), /* Mapping to CoAP code 4.00, Hex:0x80, Bad Request */
|
||||
ITOX_ALCS_COAP_MSG_CODE_401_UNAUTHORIZED = ITOX_ALCS_COAP_MSG_CODE_DEF(401), /* Mapping to CoAP code 4.01, Hex:0x81, Unauthorized */
|
||||
ITOX_ALCS_COAP_MSG_CODE_402_BAD_OPTION = ITOX_ALCS_COAP_MSG_CODE_DEF(402), /* Mapping to CoAP code 4.02, Hex:0x82, Bad Option */
|
||||
ITOX_ALCS_COAP_MSG_CODE_403_FORBIDDEN = ITOX_ALCS_COAP_MSG_CODE_DEF(403), /* Mapping to CoAP code 4.03, Hex:0x83, Forbidden */
|
||||
ITOX_ALCS_COAP_MSG_CODE_404_NOT_FOUND = ITOX_ALCS_COAP_MSG_CODE_DEF(404), /* Mapping to CoAP code 4.04, Hex:0x84, Not Found */
|
||||
ITOX_ALCS_COAP_MSG_CODE_405_METHOD_NOT_ALLOWED = ITOX_ALCS_COAP_MSG_CODE_DEF(405), /* Mapping to CoAP code 4.05, Hex:0x85, Method Not Allowed */
|
||||
ITOX_ALCS_COAP_MSG_CODE_406_NOT_ACCEPTABLE = ITOX_ALCS_COAP_MSG_CODE_DEF(406), /* Mapping to CoAP code 4.06, Hex:0x86, Not Acceptable */
|
||||
ITOX_ALCS_COAP_MSG_CODE_408_REQUEST_ENTITY_INCOMPLETE = ITOX_ALCS_COAP_MSG_CODE_DEF(408), /* Mapping to CoAP code 4.08, Hex:0x88, Request Entity Incomplete */
|
||||
ITOX_ALCS_COAP_MSG_CODE_412_PRECONDITION_FAILED = ITOX_ALCS_COAP_MSG_CODE_DEF(412), /* Mapping to CoAP code 4.12, Hex:0x8C, Precondition Failed */
|
||||
ITOX_ALCS_COAP_MSG_CODE_413_REQUEST_ENTITY_TOO_LARGE = ITOX_ALCS_COAP_MSG_CODE_DEF(413), /* Mapping to CoAP code 4.13, Hex:0x8D, Request Entity Too Large */
|
||||
ITOX_ALCS_COAP_MSG_CODE_415_UNSUPPORTED_CONTENT_FORMAT = ITOX_ALCS_COAP_MSG_CODE_DEF(415), /* Mapping to CoAP code 4.15, Hex:0x8F, Unsupported Content-Format */
|
||||
|
||||
/* CoAP Server Error Response Codes */
|
||||
ITOX_ALCS_COAP_MSG_CODE_500_INTERNAL_SERVER_ERROR = ITOX_ALCS_COAP_MSG_CODE_DEF(500), /* Mapping to CoAP code 5.00, Hex:0xA0, Internal Server Error */
|
||||
ITOX_ALCS_COAP_MSG_CODE_501_NOT_IMPLEMENTED = ITOX_ALCS_COAP_MSG_CODE_DEF(501), /* Mapping to CoAP code 5.01, Hex:0xA1, Not Implemented */
|
||||
ITOX_ALCS_COAP_MSG_CODE_502_BAD_GATEWAY = ITOX_ALCS_COAP_MSG_CODE_DEF(502), /* Mapping to CoAP code 5.02, Hex:0xA2, Bad Gateway */
|
||||
ITOX_ALCS_COAP_MSG_CODE_503_SERVICE_UNAVAILABLE = ITOX_ALCS_COAP_MSG_CODE_DEF(503), /* Mapping to CoAP code 5.03, Hex:0xA3, Service Unavailable */
|
||||
ITOX_ALCS_COAP_MSG_CODE_504_GATEWAY_TIMEOUT = ITOX_ALCS_COAP_MSG_CODE_DEF(504), /* Mapping to CoAP code 5.04, Hex:0xA4, Gateway Timeout */
|
||||
ITOX_ALCS_COAP_MSG_CODE_505_PROXYING_NOT_SUPPORTED = ITOX_ALCS_COAP_MSG_CODE_DEF(505) /* Mapping to CoAP code 5.05, Hex:0xA5, Proxying Not Supported */
|
||||
|
||||
} iotx_alcs_message_code_t;
|
||||
|
||||
typedef enum {
|
||||
IOTX_ALCS_MESSAGE_TYPE_CON = 0,
|
||||
IOTX_ALCS_MESSAGE_TYPE_NON = 1,
|
||||
IOTX_ALCS_MESSAGE_TYPE_ACK = 2,
|
||||
IOTX_ALCS_MESSAGE_TYPE_RST = 3
|
||||
} iotx_alcs_message_type_t;
|
||||
|
||||
typedef enum {
|
||||
IOTX_ALCS_MESSAGE_PERM_NONE = 0x0000,
|
||||
IOTX_ALCS_MESSAGE_PERM_GET = 0x0001,
|
||||
IOTX_ALCS_MESSAGE_PERM_POST = 0x0002,
|
||||
IOTX_ALCS_MESSAGE_PERM_PUT = 0x0004,
|
||||
IOTX_ALCS_MESSAGE_PERM_DEL = 0x0008,
|
||||
IOTX_ALCS_MESSAGE_PERM_OBSERVE = 0x0100
|
||||
} iotx_alcs_message_perm_t;
|
||||
|
||||
typedef enum {
|
||||
IOTX_ALCS_MESSAGE_CT_TEXT_PLAIN = 0, /* text/plain (UTF-8) */
|
||||
IOTX_ALCS_MESSAGE_CT_APP_LINK_FORMAT = 40, /* application/link-format */
|
||||
IOTX_ALCS_MESSAGE_CT_APP_XML = 41, /* application/xml */
|
||||
IOTX_ALCS_MESSAGE_CT_APP_OCTET_STREAM = 42, /* application/octet-stream */
|
||||
IOTX_ALCS_MESSAGE_CT_APP_RDF_XML = 43, /* application/rdf+xml */
|
||||
IOTX_ALCS_MESSAGE_CT_APP_EXI = 47, /* application/exi */
|
||||
IOTX_ALCS_MESSAGE_CT_APP_JSON = 50, /* application/json */
|
||||
IOTX_ALCS_MESSAGE_CT_APP_CBOR = 60 /* application/cbor */
|
||||
} iotx_alcs_message_content_type_t;
|
||||
|
||||
typedef struct iotx_alcs_msg_st {
|
||||
uint16_t group_id; /*multicast group id, used as unicast when 0*/
|
||||
char *ip; /*dotted decimal notation, max len 16*/
|
||||
uint16_t port;
|
||||
iotx_alcs_message_code_t msg_code;
|
||||
iotx_alcs_message_type_t msg_type;
|
||||
char *uri;
|
||||
uint32_t payload_len;
|
||||
uint8_t *payload;
|
||||
} iotx_alcs_msg_t, *iotx_alcs_msg_pt;
|
||||
|
||||
typedef struct iotx_alcs_res_st {
|
||||
char *uri;
|
||||
int32_t need_auth;
|
||||
iotx_alcs_message_perm_t msg_perm;
|
||||
iotx_alcs_message_content_type_t msg_ct;
|
||||
uint32_t maxage; /*0~60*/
|
||||
CoAPRecvMsgHandler callback;
|
||||
} iotx_alcs_res_t, *iotx_alcs_res_pt;
|
||||
|
||||
/**
|
||||
* @brief Construct the ALCS handle
|
||||
* This function initialize the data structures, initialize ALCS information.
|
||||
*
|
||||
* @param [in] params: specify the ALCS initialize parameter.
|
||||
*
|
||||
* @retval NULL : Construct failed.
|
||||
* @retval NOT_NULL : The handle of ALCS.
|
||||
* @see None.
|
||||
*/
|
||||
void *iotx_alcs_construct(iotx_alcs_param_t *params);
|
||||
|
||||
/**
|
||||
* @brief Init Cloud Part
|
||||
* This function initialize the cloud part.
|
||||
*
|
||||
* @param [in] params: specify the ALCS initialize parameter.
|
||||
*
|
||||
* @retval NULL : Construct failed.
|
||||
* @retval NOT_NULL : The handle of ALCS.
|
||||
* @see None.
|
||||
*/
|
||||
int iotx_alcs_cloud_init(void *handle);
|
||||
|
||||
/**
|
||||
* @brief Deconstruct the ALCS handle
|
||||
* This function distroy ALCS handle and release the related resource.
|
||||
*
|
||||
* @param [in] phandle: pointer of handle, specify the MQTT client.
|
||||
*
|
||||
* @retval 0 : Deconstruct success.
|
||||
* @retval -1 : Deconstruct failed.
|
||||
* @see None.
|
||||
*/
|
||||
int iotx_alcs_destroy(void **phandle);
|
||||
|
||||
/**
|
||||
* @brief Handle ALCS message from specific udp port
|
||||
*
|
||||
* @param [in] handle: specify the ALCS handle.
|
||||
*
|
||||
* @return status.
|
||||
* @see None.
|
||||
*/
|
||||
int iotx_alcs_yield(void *handle);
|
||||
|
||||
/**
|
||||
* @brief Send Message To Secific Deivce
|
||||
*
|
||||
* @param [in] handle: specify the ALCS handle.
|
||||
*
|
||||
* @return status.
|
||||
* @see None.
|
||||
*/
|
||||
int iotx_alcs_send(void *handle, iotx_alcs_msg_t *msg);
|
||||
|
||||
/**
|
||||
* @brief Send Response Message To Secific Deivce
|
||||
*
|
||||
* @param [in] handle: specify the ALCS handle.
|
||||
*
|
||||
* @return status.
|
||||
* @see None.
|
||||
*/
|
||||
int iotx_alcs_send_Response(void *handle, iotx_alcs_msg_t *msg, uint8_t token_len, uint8_t *token);
|
||||
|
||||
/**
|
||||
* @brief Register Resource
|
||||
*
|
||||
* @param [in] handle: specify the ALCS handle.
|
||||
* @param [in] handle: the resource need to be registered.
|
||||
*
|
||||
* @return status.
|
||||
* @see None.
|
||||
*/
|
||||
int iotx_alcs_register_resource(void *handle, iotx_alcs_res_t *resource);
|
||||
|
||||
/**
|
||||
* @brief ALCS Observe Notify
|
||||
*
|
||||
* @param [in] handle: specify the ALCS handle.
|
||||
* @param [in] uri: the resource need to notify.
|
||||
*
|
||||
* @return status.
|
||||
* @see None.
|
||||
*/
|
||||
int iotx_alcs_observe_notify(void *handle, const char *uri, uint32_t payload_len, uint8_t *payload);
|
||||
|
||||
/**
|
||||
* @brief Unregister Resource
|
||||
*
|
||||
* @param [in] handle: specify the ALCS handle.
|
||||
* @param [in] handle: the resource need to be registered.
|
||||
*
|
||||
* @return status.
|
||||
* @see None.
|
||||
*/
|
||||
int iotx_alcs_unregister_resource(void *handle, char *uri);
|
||||
|
||||
/**
|
||||
* @brief Add sub device
|
||||
*
|
||||
* @param [in] handle: specify the ALCS handle.
|
||||
* @param [in] pk: the productkey of device.
|
||||
* @param [in] dn: the deviceName of device.
|
||||
*
|
||||
* @return status.
|
||||
* @see None.
|
||||
*/
|
||||
int iotx_alcs_add_sub_device(void *handle, const char *pk, const char *dn);
|
||||
|
||||
/**
|
||||
* @brief remove sub device
|
||||
*
|
||||
* @param [in] handle: specify the ALCS handle.
|
||||
* @param [in] pk: the productkey of device.
|
||||
* @param [in] dn: the deviceName of device.
|
||||
*
|
||||
* @return status.
|
||||
* @see None.
|
||||
*/
|
||||
int iotx_alcs_remove_sub_device(void *handle, const char *pk, const char *dn);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef __IOTX_ALCS_CONFIG_H__
|
||||
#define __IOTX_ALCS_CONFIG_H__
|
||||
|
||||
#if 0
|
||||
#ifndef ALCS_CLIENT_ENABLED
|
||||
#define ALCS_CLIENT_ENABLED (1)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef ALCS_SERVER_ENABLED
|
||||
#define ALCS_SERVER_ENABLED (1)
|
||||
#endif
|
||||
|
||||
#ifndef USE_ALCS_SECURE
|
||||
#define USE_ALCS_SECURE (1)
|
||||
#endif
|
||||
|
||||
#ifndef KEYPREFIX_LEN
|
||||
#define KEYPREFIX_LEN (8)
|
||||
#endif
|
||||
|
||||
#ifndef GROUPID_LEN
|
||||
#define GROUPID_LEN (8)
|
||||
#endif
|
||||
|
||||
#endif /* #ifndef __IOTX_ALCS_CONFIG_H__ */
|
||||
@@ -0,0 +1,304 @@
|
||||
#include "iotx_cm_internal.h"
|
||||
|
||||
#if defined(MQTT_COMM_ENABLED) || defined(MAL_ENABLED)
|
||||
#include "iotx_cm_mqtt.h"
|
||||
#endif
|
||||
#ifdef COAP_COMM_ENABLED
|
||||
#include "iotx_cm_coap.h"
|
||||
#endif
|
||||
|
||||
|
||||
static void *fd_lock = NULL;
|
||||
static iotx_cm_connection_t *_cm_fd[CM_MAX_FD_NUM] = {NULL};
|
||||
static int _get_fd(iotx_cm_connection_t *handle);
|
||||
static int _recycle_fd(int fd);
|
||||
static int inline _fd_is_valid(int fd);
|
||||
static int inited_conn_num = 0;
|
||||
|
||||
#ifdef DEVICE_MODEL_GATEWAY
|
||||
static void *_iotx_cm_yield_thread_func(void *params);
|
||||
static void *yield_thread = NULL;
|
||||
static int yield_task_leave = 1;
|
||||
#endif
|
||||
|
||||
const char ERR_INVALID_PARAMS[] = "invalid parameter";
|
||||
int iotx_cm_open(iotx_cm_init_param_t *params)
|
||||
{
|
||||
int fd;
|
||||
iotx_cm_connection_t *connection = NULL;
|
||||
|
||||
switch (params->protocol_type) {
|
||||
case IOTX_CM_PROTOCOL_TYPE_MQTT:
|
||||
#if defined(MQTT_COMM_ENABLED) || defined(MAL_ENABLED)
|
||||
connection = iotx_cm_open_mqtt(params);
|
||||
#endif
|
||||
break;
|
||||
case IOTX_CM_PROTOCOL_TYPE_COAP:
|
||||
#ifdef COAP_COMM_ENABLED
|
||||
connection = iotx_cm_open_coap(params);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (connection == NULL) {
|
||||
cm_err("cm opon failed");
|
||||
return -1;
|
||||
}
|
||||
fd = _get_fd(connection);
|
||||
if (fd < 0) {
|
||||
cm_err("get fd failed");
|
||||
connection->close_func();
|
||||
return -1;
|
||||
}
|
||||
connection->fd = fd;
|
||||
return fd;
|
||||
}
|
||||
|
||||
int iotx_cm_connect(int fd, uint32_t timeout)
|
||||
{
|
||||
iotx_cm_connect_fp connect_func;
|
||||
int ret;
|
||||
|
||||
if (_fd_is_valid(fd) == -1) {
|
||||
cm_err(ERR_INVALID_PARAMS);
|
||||
return -1;
|
||||
}
|
||||
HAL_MutexLock(fd_lock);
|
||||
connect_func = _cm_fd[fd]->connect_func;
|
||||
HAL_MutexUnlock(fd_lock);
|
||||
|
||||
iotx_event_post(IOTX_CONN_CLOUD);
|
||||
|
||||
ret = connect_func(timeout);
|
||||
|
||||
if (ret == 0) {
|
||||
inited_conn_num++;
|
||||
if (inited_conn_num == 1) {
|
||||
|
||||
#ifdef DEVICE_MODEL_GATEWAY
|
||||
int stack_used;
|
||||
hal_os_thread_param_t task_parms = {0};
|
||||
task_parms.stack_size = 6144;
|
||||
task_parms.name = "cm_yield";
|
||||
ret = HAL_ThreadCreate(&yield_thread, _iotx_cm_yield_thread_func, NULL,
|
||||
&task_parms, &stack_used);
|
||||
if (ret < 0) {
|
||||
inited_conn_num--;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
iotx_event_post(IOTX_CONN_CLOUD_SUC);
|
||||
} else {
|
||||
iotx_event_post(IOTX_CONN_CLOUD_FAIL);
|
||||
}
|
||||
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _iotx_cm_yield(int fd, unsigned int timeout)
|
||||
{
|
||||
iotx_cm_yield_fp yield_func;
|
||||
|
||||
if (fd_lock == NULL) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
if (fd == -1) {
|
||||
int i;
|
||||
for (i = 0; i < CM_MAX_FD_NUM; i++) {
|
||||
yield_func = NULL;
|
||||
HAL_MutexLock(fd_lock);
|
||||
if (_cm_fd[i] != NULL) {
|
||||
yield_func = _cm_fd[i]->yield_func;
|
||||
}
|
||||
HAL_MutexUnlock(fd_lock);
|
||||
if (yield_func != NULL) {
|
||||
yield_func(timeout);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (_fd_is_valid(fd) == -1) {
|
||||
cm_err(ERR_INVALID_PARAMS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
HAL_MutexLock(fd_lock);
|
||||
yield_func = _cm_fd[fd]->yield_func;
|
||||
HAL_MutexUnlock(fd_lock);
|
||||
return yield_func(timeout);
|
||||
|
||||
}
|
||||
#ifdef DEVICE_MODEL_GATEWAY
|
||||
static void *_iotx_cm_yield_thread_func(void *params)
|
||||
{
|
||||
yield_task_leave = 0;
|
||||
while (inited_conn_num > 0) {
|
||||
_iotx_cm_yield(-1, CM_DEFAULT_YIELD_TIMEOUT);
|
||||
}
|
||||
yield_task_leave = 1;
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
int iotx_cm_yield(int fd, unsigned int timeout)
|
||||
{
|
||||
#ifdef DEVICE_MODEL_GATEWAY
|
||||
return 0;
|
||||
#else
|
||||
return _iotx_cm_yield(fd, timeout);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int iotx_cm_sub(int fd, iotx_cm_ext_params_t *ext, const char *topic,
|
||||
iotx_cm_data_handle_cb topic_handle_func, void *pcontext)
|
||||
{
|
||||
iotx_cm_sub_fp sub_func;
|
||||
|
||||
if (_fd_is_valid(fd) == -1) {
|
||||
cm_err(ERR_INVALID_PARAMS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
HAL_MutexLock(fd_lock);
|
||||
sub_func = _cm_fd[fd]->sub_func;
|
||||
HAL_MutexUnlock(fd_lock);
|
||||
return sub_func(ext, topic, topic_handle_func, pcontext);
|
||||
}
|
||||
|
||||
int iotx_cm_unsub(int fd, const char *topic)
|
||||
{
|
||||
iotx_cm_unsub_fp unsub_func;
|
||||
|
||||
if (_fd_is_valid(fd) == -1) {
|
||||
cm_err(ERR_INVALID_PARAMS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
HAL_MutexLock(fd_lock);
|
||||
unsub_func = _cm_fd[fd]->unsub_func;
|
||||
HAL_MutexUnlock(fd_lock);
|
||||
return unsub_func(topic);
|
||||
}
|
||||
|
||||
|
||||
|
||||
int iotx_cm_pub(int fd, iotx_cm_ext_params_t *ext, const char *topic, const char *payload, unsigned int payload_len)
|
||||
{
|
||||
iotx_cm_pub_fp pub_func;
|
||||
|
||||
if (_fd_is_valid(fd) == -1) {
|
||||
cm_err(ERR_INVALID_PARAMS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
HAL_MutexLock(fd_lock);
|
||||
pub_func = _cm_fd[fd]->pub_func;
|
||||
HAL_MutexUnlock(fd_lock);
|
||||
return pub_func(ext, topic, payload, payload_len);
|
||||
}
|
||||
|
||||
int iotx_cm_close(int fd)
|
||||
{
|
||||
iotx_cm_close_fp close_func;
|
||||
|
||||
if (_fd_is_valid(fd) != 0) {
|
||||
cm_err(ERR_INVALID_PARAMS);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (inited_conn_num > 0 && --inited_conn_num == 0) {
|
||||
#ifdef DEVICE_MODEL_GATEWAY
|
||||
while (!yield_task_leave) {
|
||||
HAL_SleepMs(10);
|
||||
}
|
||||
HAL_ThreadDelete(yield_thread);
|
||||
#endif
|
||||
}
|
||||
|
||||
HAL_MutexLock(fd_lock);
|
||||
close_func = _cm_fd[fd]->close_func;
|
||||
HAL_MutexUnlock(fd_lock);
|
||||
if (close_func() != 0) {
|
||||
return -1;
|
||||
}
|
||||
if (_recycle_fd(fd) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (inited_conn_num == 0) {
|
||||
if (fd_lock != NULL) {
|
||||
HAL_MutexDestroy(fd_lock);
|
||||
fd_lock = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int inline _fd_is_valid(int fd)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (fd_lock == NULL) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
HAL_MutexLock(fd_lock);
|
||||
ret = (fd >= 0 && fd < CM_MAX_FD_NUM && _cm_fd[fd] != NULL) ? 0 : -1;
|
||||
HAL_MutexUnlock(fd_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _recycle_fd(int fd)
|
||||
{
|
||||
if (fd_lock == NULL) {
|
||||
fd_lock = HAL_MutexCreate();
|
||||
if (fd_lock == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (fd < 0 || fd > CM_MAX_FD_NUM - 1) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
HAL_MutexLock(fd_lock);
|
||||
_cm_fd[fd] = NULL;
|
||||
HAL_MutexUnlock(fd_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _get_fd(iotx_cm_connection_t *handle)
|
||||
{
|
||||
int i;
|
||||
if (handle == NULL) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
if (fd_lock == NULL) {
|
||||
fd_lock = HAL_MutexCreate();
|
||||
if (fd_lock == NULL) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
HAL_MutexLock(fd_lock);
|
||||
for (i = 0; i < CM_MAX_FD_NUM; i++) {
|
||||
if (_cm_fd[i] == NULL) {
|
||||
_cm_fd[i] = handle;
|
||||
HAL_MutexUnlock(fd_lock);
|
||||
return i;
|
||||
}
|
||||
}
|
||||
HAL_MutexUnlock(fd_lock);
|
||||
cm_err("cm fd reached the limit");
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _IOTX_CM_H_
|
||||
#define _IOTX_CM_H_
|
||||
|
||||
#include "infra_types.h"
|
||||
|
||||
#define CM_MAX_FD_NUM 3
|
||||
#define CM_DEFAULT_YIELD_TIMEOUT 200
|
||||
/* message confirmation type */
|
||||
typedef enum {
|
||||
/* non ACK */
|
||||
/* MQTT: QoS is 0 */
|
||||
/* CoAP: NON */
|
||||
/* default */
|
||||
IOTX_CM_MESSAGE_NO_ACK,
|
||||
/* need ACK */
|
||||
/* MQTT: QoS is 1 */
|
||||
/* CoAP: CON */
|
||||
IOTX_CM_MESSAGE_NEED_ACK,
|
||||
/* non ACK */
|
||||
/* MQTT: QoS is 3 */
|
||||
/* CoAP: NONE*/
|
||||
IOTX_CM_MESSAGE_SUB_LOCAL,
|
||||
/* Maximum number of ack type */
|
||||
IOTX_CM_MESSAGE_ACK_MAX
|
||||
} iotx_cm_ack_types_t;
|
||||
|
||||
/* message confirmation type */
|
||||
typedef enum {
|
||||
/* non ACK */
|
||||
/* MQTT: QoS is 0 */
|
||||
/* CoAP: NON */
|
||||
/* default */
|
||||
IOTX_CM_ASYNC,
|
||||
/* need ACK */
|
||||
/* MQTT: QoS is 1 */
|
||||
/* CoAP: CON */
|
||||
IOTX_CM_SYNC,
|
||||
/* Maximum number of ack type */
|
||||
IOTX_CM_SYNC_MAX
|
||||
} iotx_cm_sync_mode_types_t;
|
||||
|
||||
/* protocol type */
|
||||
typedef enum IOTX_CM_PROTOCOL_TYPES {
|
||||
/* MQTT */
|
||||
IOTX_CM_PROTOCOL_TYPE_MQTT = 1,
|
||||
/* COAP */
|
||||
IOTX_CM_PROTOCOL_TYPE_COAP = 2,
|
||||
/* HTTP */
|
||||
IOTX_CM_PROTOCOL_TYPE_HTTP = 3,
|
||||
/* HTTP2 */
|
||||
IOTX_CM_PROTOCOL_TYPE_HTTP2 = 4,
|
||||
/* Maximum number of protocol type */
|
||||
IOTX_CM_PROTOCOL_TYPE_MAX
|
||||
} iotx_cm_protocol_types_t;
|
||||
|
||||
|
||||
/* event type */
|
||||
typedef enum IOTX_CM_EVENT_TYPES {
|
||||
/* cloud connected */
|
||||
IOTX_CM_EVENT_CLOUD_CONNECTED = 0,
|
||||
/* cloud: disconnect */
|
||||
/* event_msg is null */
|
||||
IOTX_CM_EVENT_CLOUD_CONNECT_FAILED,
|
||||
/* cloud: disconnect */
|
||||
/* event_msg is null */
|
||||
IOTX_CM_EVENT_CLOUD_DISCONNECT,
|
||||
/* event_msg is iotx_cm_event_result_pt */
|
||||
IOTX_CM_EVENT_SUBCRIBE_SUCCESS,
|
||||
IOTX_CM_EVENT_SUBCRIBE_FAILED,
|
||||
IOTX_CM_EVENT_UNSUB_SUCCESS,
|
||||
IOTX_CM_EVENT_UNSUB_FAILED,
|
||||
IOTX_CM_EVENT_PUBLISH_SUCCESS,
|
||||
IOTX_CM_EVENT_PUBLISH_FAILED,
|
||||
/* Maximum number of event */
|
||||
IOTX_CM_EVENT_MAX
|
||||
} iotx_cm_event_types_t;
|
||||
|
||||
/* The structure of cloud Connection event struct */
|
||||
typedef struct {
|
||||
iotx_cm_event_types_t type;
|
||||
void *msg;
|
||||
} iotx_cm_event_msg_t;
|
||||
|
||||
typedef struct {
|
||||
char *topic;
|
||||
uint8_t *payload;
|
||||
uint32_t payload_len;
|
||||
} event_msg_data_t;
|
||||
|
||||
#ifdef DEVICE_MODEL_ALINK2
|
||||
typedef void (*iotx_cm_data_handle_cb)(int fd, const char *topic, uint32_t topic_len, const char *payload, unsigned int payload_len, void *context);
|
||||
#else
|
||||
typedef void (*iotx_cm_data_handle_cb)(int fd, const char *topic, const char *payload, unsigned int payload_len,
|
||||
void *context);
|
||||
#endif
|
||||
|
||||
typedef void (*iotx_cm_event_handle_cb)(int fd, iotx_cm_event_msg_t *event, void *context);
|
||||
|
||||
|
||||
/* IoTx initializa parameters */
|
||||
typedef struct {
|
||||
uint32_t request_timeout_ms;
|
||||
uint32_t keepalive_interval_ms;
|
||||
uint32_t write_buf_size;
|
||||
uint32_t read_buf_size;
|
||||
iotx_cm_protocol_types_t protocol_type;
|
||||
iotx_cm_event_handle_cb handle_event; /* Specify MQTT event handle */
|
||||
void *context;
|
||||
#ifdef DEVICE_MODEL_ALINK2
|
||||
iotx_dev_meta_info_t *dev_info;
|
||||
iotx_mqtt_region_types_t region;
|
||||
#endif
|
||||
} iotx_cm_init_param_t;
|
||||
|
||||
typedef struct {
|
||||
iotx_cm_ack_types_t ack_type;
|
||||
iotx_cm_sync_mode_types_t sync_mode;
|
||||
uint32_t sync_timeout;
|
||||
iotx_cm_data_handle_cb ack_cb;
|
||||
void *cb_context;
|
||||
} iotx_cm_ext_params_t;
|
||||
|
||||
int iotx_cm_open(iotx_cm_init_param_t *params);
|
||||
int iotx_cm_connect(int fd, uint32_t timeout);
|
||||
int iotx_cm_yield(int fd, unsigned int timeout);
|
||||
int iotx_cm_sub(int fd, iotx_cm_ext_params_t *ext, const char *topic,
|
||||
iotx_cm_data_handle_cb topic_handle_func, void *pcontext);
|
||||
int iotx_cm_unsub(int fd, const char *topic);
|
||||
int iotx_cm_pub(int fd, iotx_cm_ext_params_t *ext, const char *topic, const char *payload, unsigned int payload_len);
|
||||
int iotx_cm_close(int fd);
|
||||
#endif /* _LINKKIT_CM_H_ */
|
||||
@@ -0,0 +1,408 @@
|
||||
#include "iotx_cm_internal.h"
|
||||
|
||||
#ifdef COAP_COMM_ENABLED
|
||||
#include "iotx_cm.h"
|
||||
#include "iotx_cm_coap.h"
|
||||
#include "infra_timer.h"
|
||||
|
||||
#ifdef COAP_DTLS_SUPPORT /* DTLS */
|
||||
#ifdef ON_DAILY
|
||||
#define IOTX_COAP_SERVER_URI "coaps://11.239.164.238:5684"
|
||||
#else
|
||||
#ifdef ON_PRE
|
||||
#define IOTX_COAP_SERVER_URI "coaps://pre.coap.cn-shanghai.link.aliyuncs.com:5684"
|
||||
|
||||
#else /* online */
|
||||
#define IOTX_COAP_SERVER_URI "coaps://%s.coap.cn-shanghai.link.aliyuncs.com:5684"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#else
|
||||
#ifdef COAP_PSK_SUPPORT /* PSK */
|
||||
#ifdef ON_DAILY
|
||||
#define IOTX_COAP_SERVER_URI "coap-psk://10.101.83.159:5682"
|
||||
#else
|
||||
#ifdef ON_PRE
|
||||
#define IOTX_COAP_SERVER_URI "coap-psk://pre.coap.cn-shanghai.link.aliyuncs.com:5682"
|
||||
#else /* online */
|
||||
#define IOTX_COAP_SERVER_URI "coap-psk://%s.coap.cn-shanghai.link.aliyuncs.com:5682"
|
||||
#endif
|
||||
#endif
|
||||
#else /* UDP */
|
||||
#ifdef ON_DAILY
|
||||
#define IOTX_COAP_SERVER_URI ""
|
||||
#else
|
||||
#ifdef ON_PRE
|
||||
#define IOTX_COAP_SERVER_URI "coap://pre.iot-as-coap.cn-shanghai.aliyuncs.com:5683"
|
||||
#else /* online */
|
||||
#define IOTX_COAP_SERVER_URI "coap://%s.coap.cn-shanghai.link.aliyuncs.com:5683"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
extern uint32_t IOT_CoAP_GetCurToken(iotx_coap_context_t *p_context);
|
||||
int IOT_CoAP_GetMessageToken(void *p_message, unsigned int *token);
|
||||
static struct list_head g_coap_response_list = LIST_HEAD_INIT(g_coap_response_list);
|
||||
|
||||
static iotx_cm_connection_t *_coap_conncection = NULL;
|
||||
static int iotx_set_devinfo(iotx_device_info_t *p_devinfo);
|
||||
|
||||
static int _coap_connect(uint32_t timeout);
|
||||
static int _coap_publish(iotx_cm_ext_params_t *params, const char *topic, const char *payload,
|
||||
unsigned int payload_len);
|
||||
static int _coap_sub(iotx_cm_ext_params_t *params, const char *topic,
|
||||
iotx_cm_data_handle_cb topic_handle_func, void *pcontext);
|
||||
static iotx_msg_type_t _get_coap_qos(iotx_cm_ack_types_t ack_type);
|
||||
static int _coap_unsub(const char *topic);
|
||||
static int _coap_close();
|
||||
static void _set_common_handlers();
|
||||
|
||||
iotx_cm_connection_t *iotx_cm_open_coap(iotx_cm_init_param_t *params)
|
||||
{
|
||||
iotx_coap_config_t *coap_config = NULL;
|
||||
iotx_device_info_t *deviceinfo = NULL;
|
||||
|
||||
if (_coap_conncection != NULL) {
|
||||
cm_warning("mqtt connection is opened already,return it");
|
||||
return _coap_conncection;
|
||||
}
|
||||
|
||||
_coap_conncection = (iotx_cm_connection_t *)cm_malloc(sizeof(iotx_cm_connection_t));
|
||||
if (_coap_conncection == NULL) {
|
||||
cm_err("_coap_conncection malloc failed!");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
_coap_conncection->list_lock = HAL_MutexCreate();
|
||||
if (_coap_conncection->list_lock == NULL) {
|
||||
cm_err("list_lock create failed!");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
coap_config = (iotx_coap_config_t *)cm_malloc(sizeof(iotx_coap_config_t));
|
||||
if (coap_config == NULL) {
|
||||
cm_err("coap_config malloc failed!");
|
||||
goto failed;
|
||||
}
|
||||
memset(coap_config, 0, sizeof(iotx_coap_config_t));
|
||||
deviceinfo = (iotx_device_info_t *)cm_malloc(sizeof(iotx_device_info_t));
|
||||
if (deviceinfo == NULL) {
|
||||
cm_err("deviceinfo malloc failed!");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
_coap_conncection->open_params = coap_config;
|
||||
|
||||
memset(deviceinfo, 0, sizeof(iotx_device_info_t));
|
||||
|
||||
iotx_set_devinfo(deviceinfo);
|
||||
coap_config->wait_time_ms = params->request_timeout_ms;
|
||||
coap_config->p_devinfo = deviceinfo;
|
||||
/* coap_config->p_url = IOTX_COAP_SERVER_URI; */
|
||||
|
||||
_coap_conncection->event_handler = params->handle_event;
|
||||
|
||||
_set_common_handlers();
|
||||
|
||||
return _coap_conncection;
|
||||
|
||||
failed:
|
||||
if (_coap_conncection != NULL) {
|
||||
if (_coap_conncection->list_lock != NULL) {
|
||||
HAL_MutexDestroy(_coap_conncection->list_lock);
|
||||
}
|
||||
cm_free(_coap_conncection);
|
||||
_coap_conncection = NULL;
|
||||
}
|
||||
|
||||
if (coap_config != NULL) {
|
||||
cm_free(coap_config);
|
||||
}
|
||||
if (deviceinfo != NULL) {
|
||||
cm_free(deviceinfo);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int iotx_set_devinfo(iotx_device_info_t *p_devinfo)
|
||||
{
|
||||
if (NULL == p_devinfo) {
|
||||
return IOTX_ERR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
memset(p_devinfo, 0x00, sizeof(iotx_device_info_t));
|
||||
|
||||
/**< get device info*/
|
||||
HAL_GetProductKey(p_devinfo->product_key);
|
||||
HAL_GetDeviceName(p_devinfo->device_name);
|
||||
HAL_GetDeviceSecret(p_devinfo->device_secret);
|
||||
HAL_Snprintf(p_devinfo->device_id, IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 2, "%s.%s", p_devinfo->product_key, p_devinfo->device_name);
|
||||
p_devinfo->device_id[IOTX_PRODUCT_KEY_LEN + IOTX_DEVICE_NAME_LEN + 1] = '\0';
|
||||
/**< end*/
|
||||
cm_info("*****The Product Key : %s *****\r\n", p_devinfo->product_key);
|
||||
cm_info("*****The Device Name : %s *****\r\n", p_devinfo->device_name);
|
||||
cm_info("*****The Device Secret: %s *****\r\n", p_devinfo->device_secret);
|
||||
cm_info("*****The Device ID : %s *****\r\n", p_devinfo->device_id);
|
||||
return IOTX_SUCCESS;
|
||||
}
|
||||
|
||||
static int _coap_connect(uint32_t timeout)
|
||||
{
|
||||
int ret;
|
||||
char url[100] = {0};
|
||||
iotx_time_t timer;
|
||||
iotx_coap_config_t *config = NULL;
|
||||
iotx_coap_context_t *p_ctx = NULL;
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
|
||||
if (_coap_conncection == NULL) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
HAL_GetProductKey(product_key);
|
||||
config = _coap_conncection->open_params;
|
||||
if (config == NULL) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
HAL_Snprintf(url, 100, IOTX_COAP_SERVER_URI, product_key);
|
||||
config->p_url = url;
|
||||
|
||||
iotx_time_init(&timer);
|
||||
utils_time_countdown_ms(&timer, timeout);
|
||||
do {
|
||||
if (p_ctx == NULL) {
|
||||
p_ctx = IOT_CoAP_Init(config);
|
||||
if (NULL == p_ctx) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ret = IOT_CoAP_DeviceNameAuth(p_ctx);
|
||||
if (ret == 0) {
|
||||
iotx_cm_event_msg_t event;
|
||||
event.type = IOTX_CM_EVENT_CLOUD_CONNECTED;
|
||||
event.msg = NULL;
|
||||
_coap_conncection->context = p_ctx;
|
||||
|
||||
if (_coap_conncection->event_handler) {
|
||||
_coap_conncection->event_handler(_coap_conncection->fd, &event, (void *)_coap_conncection);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
} while (!utils_time_is_expired(&timer));
|
||||
|
||||
{
|
||||
iotx_cm_event_msg_t event;
|
||||
event.type = IOTX_CM_EVENT_CLOUD_CONNECT_FAILED;
|
||||
event.msg = NULL;
|
||||
|
||||
if (_coap_conncection->event_handler) {
|
||||
_coap_conncection->event_handler(_coap_conncection->fd, &event, (void *)_coap_conncection);
|
||||
}
|
||||
}
|
||||
cm_err("mqtt connect failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void _coap_response_default(void *p_arg, void *p_message)
|
||||
{
|
||||
int ret;
|
||||
int len = 0;
|
||||
unsigned char *p_payload = NULL;
|
||||
unsigned int token;
|
||||
iotx_coap_resp_code_t resp_code;
|
||||
coap_response_node_t *node = NULL;
|
||||
coap_response_node_t *next = NULL;
|
||||
|
||||
if (_coap_conncection == NULL || p_message == NULL) {
|
||||
cm_err("paras err");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = IOT_CoAP_GetMessageCode(p_message, &resp_code);
|
||||
if (ret < 0) {
|
||||
cm_err("get msg code err");
|
||||
return;
|
||||
}
|
||||
|
||||
cm_info("resp_code = %d", resp_code);
|
||||
|
||||
ret = IOT_CoAP_GetMessagePayload(p_message, &p_payload, &len);
|
||||
if (ret < 0) {
|
||||
cm_err("get msg payload err");
|
||||
return;
|
||||
}
|
||||
|
||||
ret = IOT_CoAP_GetMessageToken(p_message, &token);
|
||||
if (ret < 0) {
|
||||
cm_err("get msg token err");
|
||||
return;
|
||||
}
|
||||
|
||||
HAL_MutexLock(_coap_conncection->list_lock);
|
||||
list_for_each_entry_safe(node, next, &g_coap_response_list, linked_list, coap_response_node_t) {
|
||||
if (node->token_num == token) {
|
||||
iotx_cm_data_handle_cb recieve_cb = node->responce_cb;
|
||||
void *context = node->context;
|
||||
unsigned int topic_len = strlen(node->topic) + 1;
|
||||
char *topic = cm_malloc(topic_len);
|
||||
if (topic == NULL) {
|
||||
cm_err("topic malloc failed");
|
||||
continue;
|
||||
}
|
||||
memset(topic, 0, topic_len);
|
||||
strncpy(topic, node->topic, topic_len);
|
||||
list_del(&node->linked_list);
|
||||
cm_free(node->topic);
|
||||
cm_free(node);
|
||||
HAL_MutexUnlock(_coap_conncection->list_lock); /* do not lock while callback */
|
||||
|
||||
recieve_cb(_coap_conncection->fd, topic, (const char *)p_payload, len, context);
|
||||
/* recieve_cb(_coap_conncection->fd, &msg, context); */
|
||||
cm_free(topic);
|
||||
HAL_MutexLock(_coap_conncection->list_lock);
|
||||
}
|
||||
}
|
||||
HAL_MutexUnlock(_coap_conncection->list_lock);
|
||||
}
|
||||
|
||||
|
||||
static int _coap_publish(iotx_cm_ext_params_t *ext, const char *topic, const char *payload, unsigned int payload_len)
|
||||
{
|
||||
iotx_msg_type_t qos = 0;
|
||||
iotx_message_t message;
|
||||
uint32_t token;
|
||||
int topic_len;
|
||||
int ret;
|
||||
|
||||
if (_coap_conncection == NULL) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
if (ext != NULL) {
|
||||
qos = _get_coap_qos(ext->ack_type);
|
||||
}
|
||||
memset(&message, 0, sizeof(iotx_message_t));
|
||||
|
||||
message.p_payload = (unsigned char *)payload;
|
||||
message.payload_len = payload_len;
|
||||
message.resp_callback = _coap_response_default;
|
||||
message.msg_type = qos;
|
||||
message.content_type = IOTX_CONTENT_TYPE_JSON;
|
||||
|
||||
token = IOT_CoAP_GetCurToken((iotx_coap_context_t *)_coap_conncection->context);
|
||||
ret = IOT_CoAP_SendMessage((iotx_coap_context_t *)_coap_conncection->context, (char *)topic, &message);
|
||||
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (ext != NULL && ext->ack_cb != NULL) {
|
||||
coap_response_node_t *node;
|
||||
node = (coap_response_node_t *)cm_malloc(sizeof(coap_response_node_t));
|
||||
if (node == NULL) {
|
||||
return -1;
|
||||
}
|
||||
memset(node, 0, sizeof(coap_response_node_t));
|
||||
topic_len = strlen(topic) + 1;
|
||||
node->topic = (char *)cm_malloc(topic_len);
|
||||
if (node->topic == NULL) {
|
||||
cm_free(node);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(node->topic, 0, topic_len);
|
||||
strncpy(node->topic, topic, topic_len);
|
||||
|
||||
node->user_data = _coap_conncection;
|
||||
node->responce_cb = ext->ack_cb;
|
||||
node->context = ext->cb_context;
|
||||
node->token_num = token;
|
||||
|
||||
HAL_MutexLock(_coap_conncection->list_lock);
|
||||
list_add_tail(&node->linked_list, &g_coap_response_list);
|
||||
HAL_MutexUnlock(_coap_conncection->list_lock);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _coap_yield(uint32_t timeout)
|
||||
{
|
||||
if (_coap_conncection == NULL) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
return IOT_CoAP_Yield((iotx_coap_context_t *)_coap_conncection->context);
|
||||
}
|
||||
|
||||
static int _coap_sub(iotx_cm_ext_params_t *ext, const char *topic,
|
||||
iotx_cm_data_handle_cb topic_handle_func, void *pcontext)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _coap_unsub(const char *topic)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _coap_close()
|
||||
{
|
||||
coap_response_node_t *node = NULL;
|
||||
coap_response_node_t *next = NULL;
|
||||
iotx_coap_config_t *coap_config = NULL;
|
||||
|
||||
if (_coap_conncection == NULL) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
coap_config = (iotx_coap_config_t *)_coap_conncection->open_params;
|
||||
|
||||
HAL_MutexLock(_coap_conncection->list_lock);
|
||||
list_for_each_entry_safe(node, next, &g_coap_response_list, linked_list, coap_response_node_t) {
|
||||
cm_free(node->topic);
|
||||
list_del(&node->linked_list);
|
||||
cm_free(node);
|
||||
}
|
||||
HAL_MutexUnlock(_coap_conncection->list_lock);
|
||||
|
||||
if (_coap_conncection->list_lock != NULL) {
|
||||
HAL_MutexDestroy(_coap_conncection->list_lock);
|
||||
}
|
||||
cm_free(coap_config->p_devinfo);
|
||||
cm_free(coap_config);
|
||||
IOT_CoAP_Deinit(&_coap_conncection->context);
|
||||
|
||||
cm_free(_coap_conncection);
|
||||
_coap_conncection = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static iotx_msg_type_t _get_coap_qos(iotx_cm_ack_types_t ack_type)
|
||||
{
|
||||
switch (ack_type) {
|
||||
case IOTX_CM_MESSAGE_NO_ACK:
|
||||
return IOTX_MESSAGE_NON;
|
||||
|
||||
case IOTX_CM_MESSAGE_NEED_ACK:
|
||||
return IOTX_MESSAGE_CON;
|
||||
|
||||
default:
|
||||
return IOTX_MESSAGE_CON;
|
||||
}
|
||||
}
|
||||
|
||||
static void _set_common_handlers()
|
||||
{
|
||||
if (_coap_conncection != NULL) {
|
||||
_coap_conncection->connect_func = _coap_connect;
|
||||
_coap_conncection->sub_func = _coap_sub;
|
||||
_coap_conncection->unsub_func = _coap_unsub;
|
||||
_coap_conncection->pub_func = _coap_publish;
|
||||
_coap_conncection->yield_func = _coap_yield;
|
||||
_coap_conncection->close_func = _coap_close;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef _IOTX_CM_COAP_H_
|
||||
#define _IOTX_CM_COAP_H_
|
||||
#include "iotx_cm.h"
|
||||
#include "iotx_cm_internal.h"
|
||||
#include "coap_api.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
uint32_t token_num;
|
||||
void *user_data;
|
||||
char *topic;
|
||||
iotx_cm_data_handle_cb responce_cb;
|
||||
void *context;
|
||||
dlist_t linked_list;
|
||||
} coap_response_node_t;
|
||||
|
||||
iotx_cm_connection_t *iotx_cm_open_coap(iotx_cm_init_param_t *params);
|
||||
|
||||
#endif /* _LINKKIT_CM_H_ */
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _IOTX_CM_INTERNAL_H_
|
||||
#define _IOTX_CM_INTERNAL_H_
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "infra_config.h"
|
||||
#include "infra_types.h"
|
||||
#include "infra_defs.h"
|
||||
#include "infra_list.h"
|
||||
#include "infra_compat.h"
|
||||
#include "infra_timer.h"
|
||||
|
||||
#include "dm_wrapper.h"
|
||||
#include "mqtt_api.h"
|
||||
|
||||
#include "iotx_cm.h"
|
||||
|
||||
#ifdef INFRA_MEM_STATS
|
||||
#include "infra_mem_stats.h"
|
||||
#define cm_malloc(size) LITE_malloc(size, MEM_MAGIC, "cm")
|
||||
#define cm_free(ptr) LITE_free(ptr)
|
||||
#else
|
||||
#define cm_malloc(size) HAL_Malloc(size)
|
||||
#define cm_free(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
|
||||
#endif
|
||||
|
||||
#ifdef INFRA_LOG
|
||||
#include "infra_log.h"
|
||||
#define cm_debug(...) log_debug("CM", __VA_ARGS__)
|
||||
#define cm_info(...) log_info("CM", __VA_ARGS__)
|
||||
#define cm_warning(...) log_warning("CM", __VA_ARGS__)
|
||||
#define cm_err(...) log_err("CM", __VA_ARGS__)
|
||||
#else
|
||||
#define cm_debug(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
|
||||
#define cm_info(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
|
||||
#define cm_warning(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
|
||||
#define cm_err(...) do{HAL_Printf(__VA_ARGS__);HAL_Printf("\r\n");}while(0)
|
||||
#endif
|
||||
|
||||
typedef int (*iotx_cm_connect_fp)(uint32_t timeout);
|
||||
typedef int (*iotx_cm_yield_fp)(unsigned int timeout);
|
||||
typedef int (*iotx_cm_sub_fp)(iotx_cm_ext_params_t *params, const char *topic,
|
||||
iotx_cm_data_handle_cb topic_handle_func, void *pcontext);
|
||||
typedef int (*iotx_cm_unsub_fp)(const char *topic);
|
||||
typedef int (*iotx_cm_pub_fp)(iotx_cm_ext_params_t *params, const char *topic, const char *payload,
|
||||
unsigned int payload_len);
|
||||
typedef int (*iotx_cm_close_fp)();
|
||||
|
||||
|
||||
typedef struct iotx_connection_st {
|
||||
int fd;
|
||||
void *open_params;
|
||||
void *context;
|
||||
void *list_lock;
|
||||
iotx_cm_protocol_types_t protocol_type;
|
||||
iotx_cm_connect_fp connect_func;
|
||||
iotx_cm_sub_fp sub_func;
|
||||
iotx_cm_unsub_fp unsub_func;
|
||||
iotx_cm_pub_fp pub_func;
|
||||
iotx_cm_yield_fp yield_func;
|
||||
iotx_cm_close_fp close_func;
|
||||
iotx_cm_event_handle_cb event_handler;
|
||||
void *cb_data;
|
||||
|
||||
} iotx_cm_connection_t;
|
||||
|
||||
#include "iotx_cm_mqtt.h"
|
||||
|
||||
extern const char ERR_INVALID_PARAMS[];
|
||||
#endif /* _LINKKIT_CM_H_ */
|
||||
@@ -0,0 +1,404 @@
|
||||
#include "iotx_cm_internal.h"
|
||||
|
||||
#if defined(MQTT_COMM_ENABLED) || defined(MAL_ENABLED)
|
||||
|
||||
static iotx_cm_connection_t *_mqtt_conncection = NULL;
|
||||
static void iotx_cloud_conn_mqtt_event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg);
|
||||
static int _mqtt_connect(uint32_t timeout);
|
||||
static int _mqtt_publish(iotx_cm_ext_params_t *params, const char *topic, const char *payload,
|
||||
unsigned int payload_len);
|
||||
static int _mqtt_sub(iotx_cm_ext_params_t *params, const char *topic,
|
||||
iotx_cm_data_handle_cb topic_handle_func, void *pcontext);
|
||||
static iotx_mqtt_qos_t _get_mqtt_qos(iotx_cm_ack_types_t ack_type);
|
||||
static int _mqtt_unsub(const char *topic);
|
||||
static int _mqtt_close();
|
||||
static void _set_common_handlers();
|
||||
|
||||
iotx_cm_connection_t *iotx_cm_open_mqtt(iotx_cm_init_param_t *params)
|
||||
{
|
||||
iotx_mqtt_param_t *mqtt_param = NULL;
|
||||
|
||||
if (_mqtt_conncection != NULL) {
|
||||
cm_warning("mqtt connection is opened already,return it");
|
||||
return _mqtt_conncection;
|
||||
}
|
||||
|
||||
_mqtt_conncection = (iotx_cm_connection_t *)cm_malloc(sizeof(iotx_cm_connection_t));
|
||||
if (_mqtt_conncection == NULL) {
|
||||
cm_err("_mqtt_conncection malloc failed!");
|
||||
goto failed;
|
||||
}
|
||||
|
||||
mqtt_param = (iotx_mqtt_param_t *)cm_malloc(sizeof(iotx_mqtt_param_t));
|
||||
if (mqtt_param == NULL) {
|
||||
cm_err("mqtt_param malloc failed!");
|
||||
goto failed;
|
||||
}
|
||||
_mqtt_conncection->open_params = mqtt_param;
|
||||
|
||||
mqtt_param->request_timeout_ms = params->request_timeout_ms;
|
||||
mqtt_param->clean_session = 0;
|
||||
mqtt_param->keepalive_interval_ms = params->keepalive_interval_ms;
|
||||
mqtt_param->read_buf_size = params->read_buf_size;
|
||||
mqtt_param->write_buf_size = params->write_buf_size;
|
||||
|
||||
mqtt_param->handle_event.h_fp = iotx_cloud_conn_mqtt_event_handle;
|
||||
mqtt_param->handle_event.pcontext = NULL;
|
||||
|
||||
_mqtt_conncection->event_handler = params->handle_event;
|
||||
_mqtt_conncection->cb_data = params->context;
|
||||
_set_common_handlers();
|
||||
|
||||
return _mqtt_conncection;
|
||||
|
||||
failed:
|
||||
|
||||
if (_mqtt_conncection != NULL) {
|
||||
cm_free(_mqtt_conncection);
|
||||
_mqtt_conncection = NULL;
|
||||
}
|
||||
|
||||
if (mqtt_param != NULL) {
|
||||
cm_free(mqtt_param);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
static void iotx_cloud_conn_mqtt_event_handle(void *pcontext, void *pclient, iotx_mqtt_event_msg_pt msg)
|
||||
{
|
||||
uintptr_t packet_id = (uintptr_t)msg->msg;
|
||||
if (_mqtt_conncection == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
switch (msg->event_type) {
|
||||
|
||||
case IOTX_MQTT_EVENT_DISCONNECT: {
|
||||
iotx_cm_event_msg_t event;
|
||||
cm_info("disconnected,fd = %d", _mqtt_conncection->fd);
|
||||
event.type = IOTX_CM_EVENT_CLOUD_DISCONNECT;
|
||||
event.msg = NULL;
|
||||
if (_mqtt_conncection->event_handler) {
|
||||
_mqtt_conncection->event_handler(_mqtt_conncection->fd, &event, _mqtt_conncection->cb_data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IOTX_MQTT_EVENT_RECONNECT: {
|
||||
iotx_cm_event_msg_t event;
|
||||
cm_info("connected,fd = %d", _mqtt_conncection->fd);
|
||||
event.type = IOTX_CM_EVENT_CLOUD_CONNECTED;
|
||||
event.msg = NULL;
|
||||
/* cm_info(cm_log_info_MQTT_reconnect); */
|
||||
|
||||
if (_mqtt_conncection->event_handler) {
|
||||
_mqtt_conncection->event_handler(_mqtt_conncection->fd, &event, _mqtt_conncection->cb_data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IOTX_MQTT_EVENT_SUBCRIBE_SUCCESS: {
|
||||
iotx_cm_event_msg_t event;
|
||||
event.type = IOTX_CM_EVENT_SUBCRIBE_SUCCESS;
|
||||
event.msg = (void *)packet_id;
|
||||
|
||||
if (_mqtt_conncection->event_handler) {
|
||||
_mqtt_conncection->event_handler(_mqtt_conncection->fd, &event, _mqtt_conncection->cb_data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IOTX_MQTT_EVENT_SUBCRIBE_NACK:
|
||||
case IOTX_MQTT_EVENT_SUBCRIBE_TIMEOUT: {
|
||||
iotx_cm_event_msg_t event;
|
||||
event.type = IOTX_CM_EVENT_SUBCRIBE_FAILED;
|
||||
event.msg = (void *)packet_id;
|
||||
|
||||
if (_mqtt_conncection->event_handler) {
|
||||
_mqtt_conncection->event_handler(_mqtt_conncection->fd, &event, _mqtt_conncection->cb_data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IOTX_MQTT_EVENT_UNSUBCRIBE_SUCCESS: {
|
||||
iotx_cm_event_msg_t event;
|
||||
event.type = IOTX_CM_EVENT_UNSUB_SUCCESS;
|
||||
event.msg = (void *)packet_id;
|
||||
|
||||
if (_mqtt_conncection->event_handler) {
|
||||
_mqtt_conncection->event_handler(_mqtt_conncection->fd, &event, _mqtt_conncection->cb_data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IOTX_MQTT_EVENT_UNSUBCRIBE_NACK:
|
||||
case IOTX_MQTT_EVENT_UNSUBCRIBE_TIMEOUT: {
|
||||
iotx_cm_event_msg_t event;
|
||||
event.type = IOTX_CM_EVENT_UNSUB_FAILED;
|
||||
event.msg = (void *)packet_id;
|
||||
|
||||
if (_mqtt_conncection->event_handler) {
|
||||
_mqtt_conncection->event_handler(_mqtt_conncection->fd, &event, _mqtt_conncection->cb_data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IOTX_MQTT_EVENT_PUBLISH_SUCCESS: {
|
||||
iotx_cm_event_msg_t event;
|
||||
event.type = IOTX_CM_EVENT_PUBLISH_SUCCESS;
|
||||
event.msg = (void *)packet_id;
|
||||
|
||||
if (_mqtt_conncection->event_handler) {
|
||||
_mqtt_conncection->event_handler(_mqtt_conncection->fd, &event, _mqtt_conncection->cb_data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IOTX_MQTT_EVENT_PUBLISH_NACK:
|
||||
case IOTX_MQTT_EVENT_PUBLISH_TIMEOUT: {
|
||||
iotx_cm_event_msg_t event;
|
||||
event.type = IOTX_CM_EVENT_PUBLISH_FAILED;
|
||||
event.msg = (void *)packet_id;
|
||||
|
||||
if (_mqtt_conncection->event_handler) {
|
||||
_mqtt_conncection->event_handler(_mqtt_conncection->fd, &event, _mqtt_conncection->cb_data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IOTX_MQTT_EVENT_PUBLISH_RECEIVED: {
|
||||
iotx_mqtt_topic_info_pt topic_info = (iotx_mqtt_topic_info_pt)msg->msg;
|
||||
iotx_cm_data_handle_cb topic_handle_func = (iotx_cm_data_handle_cb)pcontext;
|
||||
#ifndef DEVICE_MODEL_ALINK2
|
||||
char *topic = NULL;
|
||||
#endif
|
||||
if (topic_handle_func == NULL) {
|
||||
cm_warning("bypass %d bytes on [%.*s]", topic_info->payload_len, topic_info->topic_len, topic_info->ptopic);
|
||||
return;
|
||||
}
|
||||
#ifdef DEVICE_MODEL_ALINK2
|
||||
topic_handle_func(_mqtt_conncection->fd, topic_info->ptopic, topic_info->topic_len, topic_info->payload,
|
||||
topic_info->payload_len, NULL);
|
||||
#else
|
||||
topic = cm_malloc(topic_info->topic_len + 1);
|
||||
if (topic == NULL) {
|
||||
cm_err("topic malloc failed");
|
||||
return;
|
||||
}
|
||||
memset(topic, 0, topic_info->topic_len + 1);
|
||||
memcpy(topic, topic_info->ptopic, topic_info->topic_len);
|
||||
|
||||
topic_handle_func(_mqtt_conncection->fd, topic, topic_info->payload, topic_info->payload_len, NULL);
|
||||
|
||||
cm_free(topic);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
|
||||
case IOTX_MQTT_EVENT_BUFFER_OVERFLOW:
|
||||
cm_warning("buffer overflow", msg->msg);
|
||||
break;
|
||||
|
||||
default:
|
||||
cm_warning("msg type unkown, type = %d", msg->event_type);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static int _mqtt_connect(uint32_t timeout)
|
||||
{
|
||||
void *pclient;
|
||||
iotx_time_t timer;
|
||||
iotx_mqtt_param_t *mqtt_param = NULL;
|
||||
iotx_conn_info_pt pconn_info = NULL;
|
||||
iotx_cm_event_msg_t event;
|
||||
|
||||
char product_key[IOTX_PRODUCT_KEY_LEN + 1] = {0};
|
||||
char device_name[IOTX_DEVICE_NAME_LEN + 1] = {0};
|
||||
char device_secret[IOTX_DEVICE_SECRET_LEN + 1] = {0};
|
||||
|
||||
if (_mqtt_conncection == NULL) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
mqtt_param = _mqtt_conncection->open_params;
|
||||
|
||||
HAL_GetProductKey(product_key);
|
||||
HAL_GetDeviceName(device_name);
|
||||
HAL_GetDeviceSecret(device_secret);
|
||||
|
||||
if (strlen(product_key) == 0 || strlen(device_name) == 0) {
|
||||
return FAIL_RETURN;
|
||||
}
|
||||
|
||||
iotx_time_init(&timer);
|
||||
utils_time_countdown_ms(&timer, timeout);
|
||||
/* Device AUTH */
|
||||
do {
|
||||
if (0 == IOT_SetupConnInfo(product_key, device_name, device_secret, (void **)&pconn_info)) {
|
||||
mqtt_param->port = pconn_info->port;
|
||||
mqtt_param->host = pconn_info->host_name;
|
||||
mqtt_param->client_id = pconn_info->client_id;
|
||||
mqtt_param->username = pconn_info->username;
|
||||
mqtt_param->password = pconn_info->password;
|
||||
mqtt_param->pub_key = pconn_info->pub_key;
|
||||
break;
|
||||
}
|
||||
cm_err("IOT_SetupConnInfo failed");
|
||||
HAL_SleepMs(500);
|
||||
} while (!utils_time_is_expired(&timer));
|
||||
|
||||
do {
|
||||
pclient = IOT_MQTT_Construct((iotx_mqtt_param_t *)_mqtt_conncection->open_params);
|
||||
if (pclient != NULL) {
|
||||
iotx_cm_event_msg_t event;
|
||||
_mqtt_conncection->context = pclient;
|
||||
event.type = IOTX_CM_EVENT_CLOUD_CONNECTED;
|
||||
event.msg = NULL;
|
||||
|
||||
if (_mqtt_conncection->event_handler) {
|
||||
_mqtt_conncection->event_handler(_mqtt_conncection->fd, &event, (void *)_mqtt_conncection);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
HAL_SleepMs(500);
|
||||
} while (!utils_time_is_expired(&timer));
|
||||
|
||||
event.type = IOTX_CM_EVENT_CLOUD_CONNECT_FAILED;
|
||||
event.msg = NULL;
|
||||
|
||||
if (_mqtt_conncection->event_handler) {
|
||||
_mqtt_conncection->event_handler(_mqtt_conncection->fd, &event, (void *)_mqtt_conncection);
|
||||
}
|
||||
cm_err("mqtt connect failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int _mqtt_publish(iotx_cm_ext_params_t *ext, const char *topic, const char *payload, unsigned int payload_len)
|
||||
{
|
||||
int qos = 0;
|
||||
|
||||
if (_mqtt_conncection == NULL) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
if (ext != NULL) {
|
||||
qos = (int)_get_mqtt_qos(ext->ack_type);
|
||||
}
|
||||
return IOT_MQTT_Publish_Simple(_mqtt_conncection->context, topic, qos, (void *)payload, payload_len);
|
||||
}
|
||||
|
||||
static int _mqtt_yield(uint32_t timeout)
|
||||
{
|
||||
if (_mqtt_conncection == NULL) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
return IOT_MQTT_Yield(_mqtt_conncection->context, timeout);
|
||||
}
|
||||
|
||||
static int _mqtt_sub(iotx_cm_ext_params_t *ext, const char *topic,
|
||||
iotx_cm_data_handle_cb topic_handle_func, void *pcontext)
|
||||
{
|
||||
|
||||
int sync = 0;
|
||||
int qos = 0;
|
||||
int timeout = 0;
|
||||
int ret;
|
||||
|
||||
if (_mqtt_conncection == NULL || topic == NULL || topic_handle_func == NULL) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
if (ext != NULL) {
|
||||
if (ext->sync_mode == IOTX_CM_ASYNC) {
|
||||
sync = 0;
|
||||
} else {
|
||||
sync = 1;
|
||||
timeout = ext->sync_timeout;
|
||||
}
|
||||
qos = (int)_get_mqtt_qos(ext->ack_type);
|
||||
}
|
||||
|
||||
if (sync != 0) {
|
||||
ret = IOT_MQTT_Subscribe_Sync(_mqtt_conncection->context,
|
||||
topic,
|
||||
qos,
|
||||
iotx_cloud_conn_mqtt_event_handle,
|
||||
(void *)topic_handle_func,
|
||||
timeout);
|
||||
} else {
|
||||
ret = IOT_MQTT_Subscribe(_mqtt_conncection->context,
|
||||
topic,
|
||||
qos,
|
||||
iotx_cloud_conn_mqtt_event_handle,
|
||||
(void *)topic_handle_func);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _mqtt_unsub(const char *topic)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (_mqtt_conncection == NULL) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
ret = IOT_MQTT_Unsubscribe(_mqtt_conncection->context, topic);
|
||||
|
||||
if (ret < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int _mqtt_close()
|
||||
{
|
||||
if (_mqtt_conncection == NULL) {
|
||||
return NULL_VALUE_ERROR;
|
||||
}
|
||||
|
||||
cm_free(_mqtt_conncection->open_params);
|
||||
IOT_MQTT_Destroy(&_mqtt_conncection->context);
|
||||
cm_free(_mqtt_conncection);
|
||||
_mqtt_conncection = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static iotx_mqtt_qos_t _get_mqtt_qos(iotx_cm_ack_types_t ack_type)
|
||||
{
|
||||
switch (ack_type) {
|
||||
case IOTX_CM_MESSAGE_NO_ACK:
|
||||
return IOTX_MQTT_QOS0;
|
||||
|
||||
case IOTX_CM_MESSAGE_NEED_ACK:
|
||||
return IOTX_MQTT_QOS1;
|
||||
|
||||
case IOTX_CM_MESSAGE_SUB_LOCAL:
|
||||
return IOTX_MQTT_QOS3_SUB_LOCAL;
|
||||
|
||||
default:
|
||||
return IOTX_MQTT_QOS0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void _set_common_handlers()
|
||||
{
|
||||
if (_mqtt_conncection != NULL) {
|
||||
_mqtt_conncection->connect_func = _mqtt_connect;
|
||||
_mqtt_conncection->sub_func = _mqtt_sub;
|
||||
_mqtt_conncection->unsub_func = _mqtt_unsub;
|
||||
_mqtt_conncection->pub_func = _mqtt_publish;
|
||||
_mqtt_conncection->yield_func = (iotx_cm_yield_fp)_mqtt_yield;
|
||||
_mqtt_conncection->close_func = _mqtt_close;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _IOTX_CM_MQTT_H_
|
||||
#define _IOTX_CM_MQTT_H_
|
||||
|
||||
#include "iotx_cm.h"
|
||||
#include "iotx_cm_internal.h"
|
||||
|
||||
|
||||
typedef struct {
|
||||
uintptr_t packet_id;
|
||||
char * topic;
|
||||
void * user_data;
|
||||
iotx_mqtt_event_handle_func_fpt sub_state_cb;
|
||||
iotx_cm_data_handle_cb sub_recieve_cb;
|
||||
dlist_t linked_list;
|
||||
} mqtt_sub_node_t;
|
||||
|
||||
iotx_cm_connection_t *iotx_cm_open_mqtt(iotx_cm_init_param_t *params);
|
||||
|
||||
|
||||
#endif /* _LINKKIT_CM_H_ */
|
||||
@@ -0,0 +1,286 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _IOT_EXPORT_DM_H_
|
||||
#define _IOT_EXPORT_DM_H_
|
||||
|
||||
#ifndef _IN_
|
||||
#define _IN_
|
||||
#endif
|
||||
|
||||
#ifndef _OU_
|
||||
#define _OU_
|
||||
#endif
|
||||
|
||||
#ifdef DEVICE_MODEL_GATEWAY
|
||||
#define IOTX_DM_DEVICE_TYPE IOTX_DM_DEVICE_GATEWAY
|
||||
#else
|
||||
#define IOTX_DM_DEVICE_TYPE IOTX_DM_DEVICE_SINGLE
|
||||
#endif
|
||||
|
||||
#define IOTX_DM_LOCAL_NODE_DEVID (0)
|
||||
|
||||
#define IOTX_DM_DEVICE_SINGLE (0x01)
|
||||
#define IOTX_DM_DEVICE_SUBDEV (0x02)
|
||||
#define IOTX_DM_DEVICE_GATEWAY (0x04)
|
||||
#define IOTX_DM_DEVICE_MAIN (IOTX_DM_DEVICE_SINGLE|IOTX_DM_DEVICE_GATEWAY)
|
||||
#define IOTX_DM_DEVICE_ALL (IOTX_DM_DEVICE_SINGLE|IOTX_DM_DEVICE_SUBDEV|IOTX_DM_DEVICE_GATEWAY)
|
||||
|
||||
/* Service Type 0~7bit: type, 8~15bit: extended*/
|
||||
#define IOTX_DM_SERVICE_CLOUD (0x0001)
|
||||
#define IOTX_DM_SERVICE_LOCAL (0x0002)
|
||||
#define IOTX_DM_SERVICE_LOCAL_NO_AUTH (0x0000)
|
||||
#define IOTX_DM_SERVICE_LOCAL_AUTH (0x0100)
|
||||
|
||||
#define IOTX_DM_LOCAL_AUTH (IOTX_DM_SERVICE_LOCAL|IOTX_DM_SERVICE_LOCAL_AUTH)
|
||||
#define IOTX_DM_LOCAL_NO_AUTH (IOTX_DM_SERVICE_LOCAL|IOTX_DM_SERVICE_LOCAL_NO_AUTH)
|
||||
|
||||
#define IOTX_DM_SERVICE_ALL (IOTX_DM_SERVICE_CLOUD|IOTX_DM_LOCAL_AUTH)
|
||||
|
||||
typedef enum {
|
||||
IOTX_DM_ERR_CODE_SUCCESS = 200,
|
||||
IOTX_DM_ERR_CODE_REQUEST_ERROR = 400,
|
||||
IOTX_DM_ERR_CODE_REQUEST_PARAMS_ERROR = 460,
|
||||
IOTX_DM_ERR_CODE_REQUEST_TOO_MANY = 429,
|
||||
IOTX_DM_ERR_CODE_NO_ACTIVE_SESSION = 520,
|
||||
IOTX_DM_ERR_CODE_TIMEOUT = 100000
|
||||
} iotx_dm_error_code_t;
|
||||
|
||||
typedef enum {
|
||||
IOTX_DM_EVENT_CLOUD_CONNECTED = 0,
|
||||
IOTX_DM_EVENT_CLOUD_DISCONNECT,
|
||||
IOTX_DM_EVENT_CLOUD_RECONNECT,
|
||||
IOTX_DM_EVENT_LOCAL_CONNECTED,
|
||||
IOTX_DM_EVENT_LOCAL_DISCONNECT,
|
||||
IOTX_DM_EVENT_LOCAL_RECONNECT,
|
||||
IOTX_DM_EVENT_FOUND_DEVICE,
|
||||
IOTX_DM_EVENT_REMOVE_DEVICE,
|
||||
IOTX_DM_EVENT_REGISTER_RESULT,
|
||||
IOTX_DM_EVENT_UNREGISTER_RESULT,
|
||||
IOTX_DM_EVENT_INITIALIZED,
|
||||
IOTX_DM_EVENT_SEND_RESULT,
|
||||
IOTX_DM_EVENT_ADD_SERVICE_RESULT,
|
||||
IOTX_DM_EVENT_REMOVE_SERVICE_RESULT,
|
||||
IOTX_DM_EVENT_NEW_DATA_RECEIVED,
|
||||
IOTX_DM_EVENT_PROPERTY_SET,
|
||||
IOTX_DM_EVENT_PROPERTY_GET,
|
||||
IOTX_DM_EVENT_PROPERTY_DESIRED_GET_REPLY,
|
||||
IOTX_DM_EVENT_PROPERTY_DESIRED_DELETE_REPLY,
|
||||
IOTX_DM_EVENT_TOPO_ADD_NOTIFY,
|
||||
IOTX_DM_EVENT_THING_SERVICE_REQUEST,
|
||||
IOTX_DM_EVENT_THING_DISABLE,
|
||||
IOTX_DM_EVENT_THING_ENABLE,
|
||||
IOTX_DM_EVENT_THING_DELETE,
|
||||
IOTX_DM_EVENT_MODEL_DOWN_RAW,
|
||||
IOTX_DM_EVENT_GATEWAY_PERMIT,
|
||||
IOTX_DM_EVENT_SUBDEV_REGISTER_REPLY,
|
||||
IOTX_DM_EVENT_SUBDEV_UNREGISTER_REPLY,
|
||||
IOTX_DM_EVENT_TOPO_ADD_REPLY,
|
||||
IOTX_DM_EVENT_TOPO_DELETE_REPLY,
|
||||
IOTX_DM_EVENT_TOPO_GET_REPLY,
|
||||
IOTX_DM_EVENT_TOPO_ADD_NOTIFY_REPLY,
|
||||
IOTX_DM_EVENT_EVENT_PROPERTY_POST_REPLY,
|
||||
IOTX_DM_EVENT_EVENT_SPECIFIC_POST_REPLY,
|
||||
IOTX_DM_EVENT_DEVICEINFO_UPDATE_REPLY,
|
||||
IOTX_DM_EVENT_DEVICEINFO_DELETE_REPLY,
|
||||
IOTX_DM_EVENT_DSLTEMPLATE_GET_REPLY,
|
||||
IOTX_DM_EVENT_COMBINE_LOGIN_REPLY,
|
||||
IOTX_DM_EVENT_COMBINE_LOGOUT_REPLY,
|
||||
IOTX_DM_EVENT_MODEL_UP_RAW_REPLY,
|
||||
IOTX_DM_EVENT_LEGACY_THING_CREATED,
|
||||
IOTX_DM_EVENT_COTA_NEW_CONFIG,
|
||||
IOTX_DM_EVENT_FOTA_NEW_FIRMWARE,
|
||||
IOTX_DM_EVENT_NTP_RESPONSE,
|
||||
IOTX_DM_EVENT_RRPC_REQUEST,
|
||||
IOTX_DM_EVENT_MAX
|
||||
} iotx_dm_event_types_t;
|
||||
|
||||
typedef void (*iotx_dm_event_callback)(iotx_dm_event_types_t type, char *payload);
|
||||
|
||||
typedef enum {
|
||||
IOTX_DM_DEVICE_SECRET_PRODUCT,
|
||||
IOTX_DM_DEVICE_SECRET_DEVICE,
|
||||
IOTX_DM_DEVICE_SECRET_TYPES_MAX
|
||||
} iotx_dm_device_secret_types_t;
|
||||
|
||||
typedef enum {
|
||||
IOTX_DM_CLOUD_DOMAIN_SHANGHAI,
|
||||
IOTX_DM_CLOUD_DOMAIN_SINGAPORE,
|
||||
IOTX_DM_CLOUD_DOMAIN_JAPAN,
|
||||
IOTX_DM_CLOUD_DOMAIN_AMERICA,
|
||||
IOTX_DM_CLOUD_DOMAIN_GERMANY,
|
||||
IOTX_DM_CLOUD_DOMAIN_MAX
|
||||
} iotx_dm_cloud_domain_types_t;
|
||||
|
||||
typedef enum {
|
||||
IOTX_DM_MESSAGE_NO_AUTH,
|
||||
IOTX_DM_MESSAGE_AUTH,
|
||||
IOTX_DM_MESSAGE_AUTH_MAX
|
||||
} iotx_dm_message_auth_types_t;
|
||||
|
||||
typedef enum {
|
||||
IOTX_DM_TSL_SOURCE_LOCAL,
|
||||
IOTX_DM_TSL_SOURCE_CLOUD
|
||||
} iotx_dm_tsl_source_t;
|
||||
|
||||
typedef enum {
|
||||
IOTX_DM_TSL_TYPE_ALINK,
|
||||
IOTX_DM_TSL_TYPE_TLV
|
||||
} iotx_dm_tsl_type_t;
|
||||
|
||||
typedef struct {
|
||||
iotx_dm_device_secret_types_t secret_type;
|
||||
iotx_dm_cloud_domain_types_t domain_type;
|
||||
iotx_dm_event_callback event_callback;
|
||||
} iotx_dm_init_params_t;
|
||||
|
||||
typedef enum {
|
||||
IOTX_DM_DEV_AVAIL_ENABLE,
|
||||
IOTX_DM_DEV_AVAIL_DISABLE
|
||||
} iotx_dm_dev_avail_t;
|
||||
|
||||
typedef enum {
|
||||
IOTX_DM_DEV_STATUS_UNAUTHORIZED, /* Subdev Created */
|
||||
IOTX_DM_DEV_STATUS_AUTHORIZED, /* Receive Topo Add Notify */
|
||||
IOTX_DM_DEV_STATUS_REGISTERED, /* Receive Subdev Registered */
|
||||
IOTX_DM_DEV_STATUS_ATTACHED, /* Receive Subdev Topo Add Reply */
|
||||
IOTX_DM_DEV_STATUS_LOGINED, /* Receive Subdev Login Reply */
|
||||
IOTX_DM_DEV_STATUS_ONLINE /* After All Topic Subscribed */
|
||||
} iotx_dm_dev_status_t;
|
||||
|
||||
typedef enum {
|
||||
DM_TSL_SERVICE_GET_FAILED = -13,
|
||||
DM_TSL_SERVICE_SET_FAILED = -12,
|
||||
DM_TSL_EVENT_GET_FAILED = -11,
|
||||
DM_TSL_EVENT_SET_FAILED = -10,
|
||||
DM_TSL_PROPERTY_GET_FAILED = -9,
|
||||
DM_TSL_PROPERTY_SET_FAILED = -8,
|
||||
DM_TSL_EVENT_NOT_EXIST = -7,
|
||||
DM_TSL_PROPERTY_NOT_EXIST = -6,
|
||||
DM_TSL_SERVICE_NOT_EXIST = -5,
|
||||
DM_JSON_PARSE_FAILED = -4,
|
||||
DM_MEMORY_NOT_ENOUGH = -3,
|
||||
DM_INVALID_PARAMETER = -2
|
||||
} dm_error_code_t;
|
||||
|
||||
#define IOTX_DM_POST_PROPERTY_ALL (NULL)
|
||||
|
||||
int iotx_dm_open(void);
|
||||
int iotx_dm_connect(_IN_ iotx_dm_init_params_t *init_params);
|
||||
int iotx_dm_subscribe(_IN_ int devid);
|
||||
int iotx_dm_close(void);
|
||||
int iotx_dm_yield(int timeout_ms);
|
||||
void iotx_dm_dispatch(void);
|
||||
|
||||
int iotx_dm_post_rawdata(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
|
||||
|
||||
#if !defined(DEVICE_MODEL_RAWDATA_SOLO)
|
||||
int iotx_dm_set_opt(int opt, void *data);
|
||||
int iotx_dm_get_opt(int opt, void *data);
|
||||
#ifdef LOG_REPORT_TO_CLOUD
|
||||
int iotx_dm_log_post(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
|
||||
#endif
|
||||
int iotx_dm_post_property(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
|
||||
int iotx_dm_property_desired_get(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
|
||||
int iotx_dm_property_desired_delete(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
|
||||
int iotx_dm_post_event(_IN_ int devid, _IN_ char *identifier, _IN_ int identifier_len, _IN_ char *payload,
|
||||
_IN_ int payload_len);
|
||||
|
||||
int iotx_dm_send_service_response(_IN_ int devid, _IN_ char *msgid, _IN_ int msgid_len, _IN_ iotx_dm_error_code_t code,
|
||||
_IN_ char *identifier,
|
||||
_IN_ int identifier_len, _IN_ char *payload, _IN_ int payload_len, void *ctx);
|
||||
int iotx_dm_send_property_get_response(_IN_ int devid, _IN_ char *msgid, _IN_ int msgid_len,
|
||||
_IN_ iotx_dm_error_code_t code,
|
||||
_IN_ char *payload, _IN_ int payload_len, _IN_ void *ctx);
|
||||
int iotx_dm_send_rrpc_response(_IN_ int devid, _IN_ char *msgid, _IN_ int msgid_len, _IN_ iotx_dm_error_code_t code,
|
||||
_IN_ char *rrpcid, _IN_ int rrpcid_len, _IN_ char *payload, _IN_ int payload_len);
|
||||
int iotx_dm_deviceinfo_update(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
|
||||
int iotx_dm_deviceinfo_delete(_IN_ int devid, _IN_ char *payload, _IN_ int payload_len);
|
||||
int iotx_dm_qurey_ntp(void);
|
||||
int iotx_dm_send_aos_active(int devid);
|
||||
#endif
|
||||
|
||||
int iotx_dm_cota_perform_sync(_OU_ char *buffer, _IN_ int buffer_len);
|
||||
int iotx_dm_cota_get_config(_IN_ const char *config_scope, const char *get_type, const char *attribute_keys);
|
||||
int iotx_dm_fota_perform_sync(_OU_ char *buffer, _IN_ int buffer_len);
|
||||
int iotx_dm_fota_request_image(_IN_ const char *version, _IN_ int buffer_len);
|
||||
|
||||
#ifdef DEVICE_MODEL_GATEWAY
|
||||
int iotx_dm_query_topo_list(void);
|
||||
int iotx_dm_subdev_create(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1], _IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1],
|
||||
_IN_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1], _OU_ int *devid);
|
||||
int iotx_dm_subdev_destroy(_IN_ int devid);
|
||||
int iotx_dm_subdev_number(void);
|
||||
int iotx_dm_subdev_register(_IN_ int devid);
|
||||
int iotx_dm_subdev_unregister(_IN_ int devid);
|
||||
int iotx_dm_subdev_topo_add(_IN_ int devid);
|
||||
int iotx_dm_subdev_topo_del(_IN_ int devid);
|
||||
int iotx_dm_subdev_login(_IN_ int devid);
|
||||
int iotx_dm_subdev_logout(_IN_ int devid);
|
||||
int iotx_dm_get_device_type(_IN_ int devid, _OU_ int *type);
|
||||
int iotx_dm_get_device_avail_status(_IN_ int devid, _OU_ iotx_dm_dev_avail_t *status);
|
||||
int iotx_dm_get_device_status(_IN_ int devid, _OU_ iotx_dm_dev_status_t *status);
|
||||
#ifdef DEVICE_MODEL_SUBDEV_OTA
|
||||
int iotx_dm_send_firmware_version(int devid, const char *firmware_version);
|
||||
int iotx_dm_ota_switch_device(_IN_ int devid);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef DEPRECATED_LINKKIT
|
||||
int iotx_dm_deprecated_subdev_register(_IN_ int devid, _IN_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1]);
|
||||
int iotx_dm_deprecated_set_tsl(_IN_ int devid, _IN_ iotx_dm_tsl_source_t source, _IN_ const char *tsl,
|
||||
_IN_ int tsl_len);
|
||||
int iotx_dm_deprecated_set_property_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
|
||||
_IN_ int value_len);
|
||||
int iotx_dm_deprecated_get_property_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value);
|
||||
int iotx_dm_deprecated_set_event_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
|
||||
_IN_ int value_len);
|
||||
int iotx_dm_deprecated_get_event_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value);
|
||||
int iotx_dm_deprecated_get_service_input_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value);
|
||||
int iotx_dm_deprecated_set_service_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
|
||||
_IN_ int value_len);
|
||||
int iotx_dm_deprecated_get_service_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value);
|
||||
|
||||
int iotx_dm_deprecated_post_property_start(_IN_ int devid, _OU_ void **handle);
|
||||
int iotx_dm_deprecated_post_property_add(_IN_ void *handle, _IN_ char *identifier, _IN_ int identifier_len);
|
||||
int iotx_dm_deprecated_post_property_end(_IN_ void **handle);
|
||||
int iotx_dm_deprecated_post_event(_IN_ int devid, _IN_ char *identifier, _IN_ int identifier_len);
|
||||
int iotx_dm_deprecated_send_service_response(_IN_ int devid, _IN_ int msgid, _IN_ iotx_dm_error_code_t code,
|
||||
_IN_ char *identifier,
|
||||
_IN_ int identifier_len);
|
||||
|
||||
int iotx_dm_deprecated_legacy_set_property_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
|
||||
_IN_ char *value_str);
|
||||
int iotx_dm_deprecated_legacy_get_property_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
|
||||
_IN_ char **value_str);
|
||||
int iotx_dm_deprecated_legacy_set_event_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
|
||||
_IN_ char *value_str);
|
||||
int iotx_dm_deprecated_legacy_get_event_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len, _IN_ void *value,
|
||||
_IN_ char **value_str);
|
||||
int iotx_dm_deprecated_legacy_get_service_input_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len,
|
||||
_IN_ void *value,
|
||||
_IN_ char **value_str);
|
||||
int iotx_dm_deprecated_legacy_set_service_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len,
|
||||
_IN_ void *value,
|
||||
_IN_ char *value_str);
|
||||
int iotx_dm_deprecated_legacy_get_service_output_value(_IN_ int devid, _IN_ char *key, _IN_ int key_len,
|
||||
_IN_ void *value,
|
||||
_IN_ char **value_str);
|
||||
|
||||
int iotx_dm_deprecated_legacy_get_pkdn_by_devid(_IN_ int devid, _OU_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
|
||||
_OU_ char device_name[IOTX_DEVICE_NAME_LEN + 1]);
|
||||
int iotx_dm_deprecated_legacy_get_devid_by_pkdn(_IN_ char product_key[IOTX_PRODUCT_KEY_LEN + 1],
|
||||
_IN_ char device_name[IOTX_DEVICE_NAME_LEN + 1], _OU_ int *devid);
|
||||
int iotx_dm_deprecated_legacy_get_thingid_by_devid(_IN_ int devid, _OU_ void **thing_id);
|
||||
int iotx_dm_deprecated_legacy_get_devid_by_thingid(_IN_ void *thing_id, _OU_ int *devid);
|
||||
int iotx_dm_deprecated_legacy_get_pkdn_ptr_by_devid(_IN_ int devid, _OU_ char **product_key, _OU_ char **device_name);
|
||||
int iotx_dm_deprecated_legacy_send_service_response(_IN_ int devid, _IN_ int msgid, _IN_ iotx_dm_error_code_t code,
|
||||
_IN_ char *identifier, _IN_ int identifier_len, _IN_ char *payload, _IN_ int payload_len);
|
||||
#ifdef DEVICE_MODEL_GATEWAY
|
||||
int iotx_dm_deprecated_subdev_register(_IN_ int devid, _IN_ char device_secret[IOTX_DEVICE_SECRET_LEN + 1]);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#ifndef _IOTX_DM_CONFIG_H_
|
||||
#define _IOTX_DM_CONFIG_H_
|
||||
|
||||
#define IOTX_DM_CLIENT_CONNECT_TIMEOUT_MS (10000)
|
||||
#define IOTX_DM_CLIENT_SUB_RETRY_MAX_COUNTS (3)
|
||||
#define IOTX_DM_CLIENT_SUB_TIMEOUT_MS (5000)
|
||||
#define IOTX_DM_CLIENT_REQUEST_TIMEOUT_MS (2000)
|
||||
#define IOTX_DM_CLIENT_KEEPALIVE_INTERVAL_MS (30000)
|
||||
|
||||
#ifndef CONFIG_MQTT_TX_MAXLEN
|
||||
#define CONFIG_MQTT_TX_MAXLEN (1024)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_MQTT_RX_MAXLEN
|
||||
#define CONFIG_MQTT_RX_MAXLEN (1024)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DISPATCH_QUEUE_MAXLEN
|
||||
#define CONFIG_DISPATCH_QUEUE_MAXLEN (50)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_DISPATCH_PACKET_MAXCOUNT
|
||||
#define CONFIG_DISPATCH_PACKET_MAXCOUNT (0)
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_MSGCACHE_QUEUE_MAXLEN
|
||||
#define CONFIG_MSGCACHE_QUEUE_MAXLEN (50)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef _IOTX_DM_INTERNAL_H_
|
||||
#define _IOTX_DM_INTERNAL_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "infra_config.h"
|
||||
#include "infra_types.h"
|
||||
#include "infra_defs.h"
|
||||
#include "infra_list.h"
|
||||
#include "infra_cjson.h"
|
||||
#include "infra_report.h"
|
||||
#include "infra_string.h"
|
||||
#if defined(DEVICE_MODEL_GATEWAY)
|
||||
#include "infra_sha1.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef _IN_
|
||||
#define _IN_
|
||||
#endif
|
||||
|
||||
#ifndef _OU_
|
||||
#define _OU_
|
||||
#endif
|
||||
|
||||
#ifndef DM_READ_ONLY
|
||||
#define DM_READ_ONLY
|
||||
#endif
|
||||
|
||||
#define _BSD_SOURCE
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#if defined(OTA_ENABLED) && !defined(BUILD_AOS)
|
||||
#include "iotx_ota.h"
|
||||
#include "ota_api.h"
|
||||
#endif
|
||||
|
||||
/* CM Header File */
|
||||
#include "iotx_cm.h"
|
||||
|
||||
/* ALCS Header File */
|
||||
#ifdef ALCS_ENABLED
|
||||
#include "CoAPExport.h"
|
||||
#include "iotx_alcs.h"
|
||||
#endif
|
||||
|
||||
/* DM Header File */
|
||||
#include "dm_wrapper.h"
|
||||
#include "iotx_dm_config.h"
|
||||
#include "iotx_dm.h"
|
||||
#include "dm_utils.h"
|
||||
#include "dm_shadow.h"
|
||||
#include "dm_tsl_alink.h"
|
||||
#include "dm_message_cache.h"
|
||||
#include "dm_opt.h"
|
||||
#include "dm_ota.h"
|
||||
#include "dm_cota.h"
|
||||
#include "dm_fota.h"
|
||||
#include "dm_ipc.h"
|
||||
#include "dm_message.h"
|
||||
#include "dm_msg_process.h"
|
||||
#include "dm_manager.h"
|
||||
#include "dm_client_adapter.h"
|
||||
#include "dm_client.h"
|
||||
#include "dm_server_adapter.h"
|
||||
#include "dm_server.h"
|
||||
#include "dm_intf.h"
|
||||
|
||||
#ifdef INFRA_MEM_STATS
|
||||
#include "infra_mem_stats.h"
|
||||
#define DM_malloc(size) LITE_malloc(size, MEM_MAGIC, "dm")
|
||||
#define DM_free(ptr) LITE_free(ptr)
|
||||
#else
|
||||
#define DM_malloc(size) HAL_Malloc(size)
|
||||
#define DM_free(ptr) {HAL_Free((void *)ptr);ptr = NULL;}
|
||||
#endif
|
||||
|
||||
#if defined(COAP_COMM_ENABLED) && !defined(MQTT_COMM_ENABLED)
|
||||
#define DM_URI_OFFSET 1
|
||||
#else
|
||||
#define DM_URI_OFFSET 0
|
||||
#endif
|
||||
|
||||
#ifdef INFRA_LOG
|
||||
#include "infra_log.h"
|
||||
#define dm_log_emerg(...) log_emerg("DM", __VA_ARGS__)
|
||||
#define dm_log_crit(...) log_crit("DM", __VA_ARGS__)
|
||||
#define dm_log_err(...) log_err("DM", __VA_ARGS__)
|
||||
#define dm_log_warning(...) log_warning("DM", __VA_ARGS__)
|
||||
#define dm_log_info(...) log_info("DM", __VA_ARGS__)
|
||||
#define dm_log_debug(...) log_debug("DM", __VA_ARGS__)
|
||||
#else
|
||||
#define dm_log_emerg(...)
|
||||
#define dm_log_crit(...)
|
||||
#define dm_log_err(...)
|
||||
#define dm_log_warning(...)
|
||||
#define dm_log_info(...)
|
||||
#define dm_log_debug(...)
|
||||
#define HEXDUMP_INFO(...)
|
||||
#define HEXDUMP_DEBUG(...)
|
||||
#endif
|
||||
|
||||
#ifdef LOG_REPORT_TO_CLOUD
|
||||
#define LOG_POLL_SIZE (CONFIG_MQTT_TX_MAXLEN - 174)
|
||||
#define REPORT_LEN (LOG_POLL_SIZE - 110)
|
||||
#define OVERFLOW_LEN (LOG_POLL_SIZE - 10)
|
||||
|
||||
typedef enum {
|
||||
READY,
|
||||
RUNNING,
|
||||
DONE
|
||||
} REPORT_STATE;
|
||||
unsigned int add_tail();
|
||||
int reset_log_poll();
|
||||
int remove_log_poll();
|
||||
unsigned int push_log(const char *perform_data, int perform_data_size);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,3 @@
|
||||
void get_msgid(char *payload, int is_cloud);
|
||||
int check_target_msg(const char *input, int len);
|
||||
void send_permance_info(char *input, int input_len, char *comments, int report_format);
|
||||
@@ -0,0 +1,370 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef LINKKIT_EXPORT_H
|
||||
#define LINKKIT_EXPORT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef void (*handle_post_cb_fp_t)(const void *thing_id, int respons_id, int code, const char *response_message,
|
||||
void *ctx);
|
||||
typedef void (*handle_subdev_cb_fp_t)(const void *thing_id, int code, const char *response_message, int success,
|
||||
void *ctx);
|
||||
|
||||
typedef struct _linkkit_ops {
|
||||
#ifdef LOCAL_CONN_ENABLE
|
||||
int (*on_connect)(void *ctx, int cloud); /* true: cloud connection; false: local connection */
|
||||
int (*on_disconnect)(void *ctx, int cloud); /* true: cloud connection; false: local connection */
|
||||
#else
|
||||
int (*on_connect)(void *ctx); /* true: cloud connection; false: local connection */
|
||||
int (*on_disconnect)(void *ctx); /* true: cloud connection; false: local connection */
|
||||
#endif
|
||||
int (*raw_data_arrived)(const void *thing_id, const void *data, int len, void *ctx);
|
||||
int (*thing_create)(const void *thing_id, void *ctx);
|
||||
int (*thing_enable)(const void *thing_id, void *ctx);
|
||||
int (*thing_disable)(const void *thing_id, void *ctx);
|
||||
int (*thing_call_service)(const void *thing_id, const char *service, int request_id, void *ctx);
|
||||
int (*thing_prop_changed)(const void *thing_id, const char *property, void *ctx);
|
||||
int (*linkit_data_arrived)(const void *thing_id, const void *data, int len, void *ctx);
|
||||
} linkkit_ops_t;
|
||||
|
||||
typedef enum _linkkit_loglevel {
|
||||
linkkit_loglevel_emerg = 0,
|
||||
linkkit_loglevel_crit,
|
||||
linkkit_loglevel_error,
|
||||
linkkit_loglevel_warning,
|
||||
linkkit_loglevel_info,
|
||||
linkkit_loglevel_debug,
|
||||
} linkkit_loglevel_t;
|
||||
|
||||
/* domain type */
|
||||
/* please sync with dm_cloud_domain_type_t */
|
||||
typedef enum {
|
||||
/* shanghai */
|
||||
linkkit_cloud_domain_shanghai,
|
||||
/* singapore */
|
||||
linkkit_cloud_domain_singapore,
|
||||
/* japan */
|
||||
linkkit_cloud_domain_japan,
|
||||
/* america */
|
||||
linkkit_cloud_domain_america,
|
||||
/* germany */
|
||||
linkkit_cloud_domain_germany,
|
||||
|
||||
linkkit_cloud_domain_max,
|
||||
} linkkit_cloud_domain_type_t;
|
||||
|
||||
/* device info related operation */
|
||||
typedef enum {
|
||||
linkkit_extended_info_operate_update,
|
||||
linkkit_extended_info_operate_delete,
|
||||
|
||||
linkkit_deviceinfo_operate_max,
|
||||
} linkkit_extended_info_operate_t;
|
||||
|
||||
/**
|
||||
* @brief dispatch message of queue for further process.
|
||||
*
|
||||
* @return void*
|
||||
*/
|
||||
DLL_IOT_API void *linkkit_dispatch(void);
|
||||
|
||||
typedef enum {
|
||||
linkkit_opt_property_post_reply, /* data type: int */
|
||||
linkkit_opt_event_post_reply, /* data type: int */
|
||||
linkkit_opt_property_set_reply /* data type: int */
|
||||
} linkkit_opt_t;
|
||||
|
||||
/**
|
||||
* @brief get leave signal.
|
||||
*
|
||||
*
|
||||
* @return int,0 no leave signal, 1 get a leave signal
|
||||
*/
|
||||
DLL_IOT_API int being_deprecated linkkit_is_try_leave();
|
||||
|
||||
/**
|
||||
* @brief start linkkit routines, and install callback funstions(async type for cloud connecting).
|
||||
*
|
||||
* @param opt, specify the option need to be set.
|
||||
* @param data, specify the option value.
|
||||
*
|
||||
* @return int, 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int being_deprecated linkkit_set_opt(linkkit_opt_t opt, void *data);
|
||||
|
||||
/**
|
||||
* @brief start linkkit routines, and install callback funstions(async type for cloud connecting).
|
||||
*
|
||||
* @param max_buffered_msg, specify max buffered message size.
|
||||
* @param ops, callback function struct to be installed.
|
||||
* @param get_tsl_from_cloud, config if device need to get tsl from cloud(!0) or local(0), if local selected, must invoke linkkit_set_tsl to tell tsl to dm after start complete.
|
||||
* @param log_level, config log level.
|
||||
* @param user_context, user context pointer.
|
||||
* @param domain_type, specify the could server domain.
|
||||
*
|
||||
* @return int, 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int being_deprecated linkkit_start(int max_buffered_msg, int get_tsl_from_cloud,
|
||||
linkkit_loglevel_t log_level,
|
||||
linkkit_ops_t *ops,
|
||||
linkkit_cloud_domain_type_t domain_type, void *user_context);
|
||||
|
||||
/**
|
||||
* @brief stop linkkit routines.
|
||||
*
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int being_deprecated linkkit_end(void);
|
||||
|
||||
/**
|
||||
* @brief install user tsl.
|
||||
*
|
||||
* @param tsl, tsl string that contains json description for thing object.
|
||||
* @param tsl_len, tsl string length.
|
||||
*
|
||||
* @return pointer to thing object, NULL when fails.
|
||||
*/
|
||||
DLL_IOT_API void *linkkit_set_tsl(const char *tsl, int tsl_len);
|
||||
|
||||
/* patterns: */
|
||||
/* method:
|
||||
* set_property_/event_output_/service_output_value:
|
||||
* method_set, thing_id, identifier, value */
|
||||
|
||||
typedef enum {
|
||||
linkkit_method_set_property_value = 0,
|
||||
linkkit_method_set_event_output_value,
|
||||
linkkit_method_set_service_output_value,
|
||||
|
||||
linkkit_method_set_number,
|
||||
} linkkit_method_set_t;
|
||||
|
||||
/**
|
||||
* @brief set value to property, event output, service output items.
|
||||
* if identifier is struct type or service output type or event output type, use '.' as delimeter like "identifier1.ientifier2"
|
||||
* to point to specific item.
|
||||
* value and value_str could not be NULL at the same time;
|
||||
* if value and value_str both as not NULL, value shall be used and value_str will be ignored.
|
||||
* if value is NULL, value_str not NULL, value_str will be used.
|
||||
* in brief, value will be used if not NULL, value_str will be used only if value is NULL.
|
||||
*
|
||||
* @param method_set, specify set value type.
|
||||
* @param thing_id, pointer to thing object, specify which thing to set.
|
||||
* @param identifier, property, event output, service output identifier.
|
||||
* @param value. The value to be set, data type decided by data type of property as follows:
|
||||
* int: int*, float: float*, double: double*,
|
||||
* text: char*, enum: int*, date: char*, bool: int*
|
||||
*
|
||||
* @param value_str, value to set in string format if value is null.
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int being_deprecated linkkit_set_value(linkkit_method_set_t method_set, const void *thing_id,
|
||||
const char *identifier,
|
||||
const void *value, const char *value_str);
|
||||
|
||||
typedef enum {
|
||||
linkkit_method_get_property_value = 0,
|
||||
linkkit_method_get_event_output_value,
|
||||
linkkit_method_get_service_input_value,
|
||||
linkkit_method_get_service_output_value,
|
||||
|
||||
linkkit_method_get_number,
|
||||
} linkkit_method_get_t;
|
||||
|
||||
/**
|
||||
* @brief get value from property, event output, service input/output items.
|
||||
* if identifier is struct type or service input/output type or event output type, use '.' as delimeter like "identifier1.ientifier2"
|
||||
* to point to specific item.
|
||||
* value and value_str could not be NULL at the same time;
|
||||
* if value and value_str both as not NULL, value shall be used and value_str will be ignored.
|
||||
* if value is NULL, value_str not NULL, value_str will be used.
|
||||
* in brief, value will be used if not NULL, value_str will be used only if value is NULL.
|
||||
* @param method_get, specify get value type.
|
||||
* @param thing_id, pointer to thing object, specify which thing to get.
|
||||
* @param identifier, property, event output, service input/output identifier.
|
||||
* @param value. The variable to store value, data type decided by data type of property as follows:
|
||||
* int: int*, float: float*, double: double*,
|
||||
* text: char**, enum: int*, date: char**, bool: int*
|
||||
*
|
||||
* @param value_str, value to get in string format. If success, memory of *value_str will be allocated,
|
||||
* user should free the memory.
|
||||
*
|
||||
* @warning if data type is text or date, *value well be end with '\0'.
|
||||
* the memory allocated to *value must be free by user.
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int being_deprecated linkkit_get_value(linkkit_method_get_t method_get, const void *thing_id,
|
||||
const char *identifier,
|
||||
void *value, char **value_str);
|
||||
|
||||
|
||||
/**
|
||||
* @brief answer to a service when a service requested by cloud.
|
||||
*
|
||||
* @param thing_id, pointer to thing object.
|
||||
* @param service_identifier, service identifier to answer, user should get this identifier from handle_dm_callback_fp_t type callback
|
||||
* report that "dm_callback_type_service_requested" happened, use this function to generate response to the service sender.
|
||||
* @param response_id, id value in response payload. its value is from "dm_callback_type_service_requested" type callback function.
|
||||
* use the same id as the request to send response as the same communication session.
|
||||
* @param code, code value in response payload. for example, 200 when service successfully executed, 400 when not successfully executed.
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int being_deprecated linkkit_answer_service(const void *thing_id, const char *service_identifier,
|
||||
int response_id, int code);
|
||||
|
||||
/**
|
||||
* @brief answer a down raw service when a raw service requested by cloud, or invoke a up raw service to cloud.
|
||||
*
|
||||
* @param thing_id, pointer to thing object.
|
||||
* @param is_up_raw, specify up raw(not 0) or down raw reply(0).
|
||||
* @param raw_data, raw data that sent to cloud.
|
||||
* @param raw_data_length, raw data length that sent to cloud.
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int being_deprecated linkkit_invoke_raw_service(const void *thing_id, int is_up_raw, void *raw_data,
|
||||
int raw_data_length);
|
||||
|
||||
/**
|
||||
* @brief trigger extended info update procedure.
|
||||
*
|
||||
* @param thing_id, pointer to thing object.
|
||||
* @param params, json type string that user to send to cloud.
|
||||
* @param linkkit_extended_info_operation, specify update type or delete type.
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
|
||||
DLL_IOT_API int being_deprecated linkkit_trigger_extended_info_operate(const void *thing_id, const char *params,
|
||||
linkkit_extended_info_operate_t linkkit_extended_info_operation);
|
||||
|
||||
/**
|
||||
* @brief trigger a event to post to cloud.
|
||||
*
|
||||
* @param thing_id, pointer to thing object.
|
||||
* @param event_identifier, event identifier to trigger.
|
||||
* @param cb, callback function of event post.
|
||||
*
|
||||
* @return >=0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int being_deprecated linkkit_trigger_event(const void *thing_id, const char *event_identifier,
|
||||
handle_post_cb_fp_t cb);
|
||||
|
||||
/**
|
||||
* @brief post property to cloud.
|
||||
*
|
||||
* @param thing_id, pointer to thing object.
|
||||
* @param property_identifier, used when trigger event with method "event.property.post", if set, post specified property, if NULL, post all.
|
||||
* @param cb, callback function of property post.
|
||||
*
|
||||
* @return >=0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int being_deprecated linkkit_post_property(const void *thing_id, const char *property_identifier,
|
||||
handle_post_cb_fp_t cb);
|
||||
|
||||
/**
|
||||
* @brief this function used to yield when want to receive or send data.
|
||||
* if multi-thread enabled, user should NOT call this function.
|
||||
*
|
||||
* @param timeout_ms, timeout value in ms.
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int being_deprecated linkkit_yield(int timeout_ms);
|
||||
|
||||
typedef enum {
|
||||
service_cota_callback_type_new_version_detected = 10,
|
||||
|
||||
service_cota_callback_type_number,
|
||||
} service_cota_callback_type_t;
|
||||
|
||||
typedef void (*handle_service_cota_callback_fp_t)(service_cota_callback_type_t callback_type, const char *configid,
|
||||
uint32_t configsize,
|
||||
const char *gettype,
|
||||
const char *sign,
|
||||
const char *signmethod,
|
||||
const char *cota_url);
|
||||
|
||||
/**
|
||||
* @brief this function used to register callback for config ota.
|
||||
*
|
||||
* @param callback_fp, user callback which register to cota.
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int being_deprecated linkkit_cota_init(handle_service_cota_callback_fp_t callback_fp);
|
||||
|
||||
/**
|
||||
* @brief this function used to execute cota process.
|
||||
*
|
||||
* @param data_buf, data buf that used to do ota. ota service will use this buffer to download bin.
|
||||
* @param data_buf_length, data buf length that used to do ota.
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int being_deprecated linkkit_invoke_cota_service(void *data_buf, int data_buf_length);
|
||||
|
||||
/**
|
||||
* @brief this function used to trigger cota process.
|
||||
*
|
||||
* @param config_scope, remote config scope, should be "product".
|
||||
* @param get_type, remote config file type, should be "file".
|
||||
* @param attribute_Keys, reserved.
|
||||
* @param option, reserved.
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int being_deprecated linkkit_invoke_cota_get_config(const char *config_scope, const char *get_type,
|
||||
const char *attribute_Keys, void *option);
|
||||
|
||||
typedef enum {
|
||||
service_fota_callback_type_new_version_detected = 10,
|
||||
|
||||
service_fota_callback_type_number,
|
||||
} service_fota_callback_type_t;
|
||||
|
||||
typedef void (*handle_service_fota_callback_fp_t)(service_fota_callback_type_t callback_type, const char *version);
|
||||
|
||||
/**
|
||||
* @brief this function used to register callback for firmware ota.
|
||||
*
|
||||
* @param callback_fp, user callback which register to fota.
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int being_deprecated linkkit_fota_init(handle_service_fota_callback_fp_t callback_fp);
|
||||
|
||||
/**
|
||||
* @brief this function used to execute fota process.
|
||||
*
|
||||
* @param data_buf, data buf that used to do ota. ota service will use this buffer to download bin.
|
||||
* @param data_buf_length, data buf length that used to do ota.
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int being_deprecated linkkit_invoke_fota_service(void *data_buf, int data_buf_length);
|
||||
|
||||
/**
|
||||
* @brief this function used to get NTP time from cloud.
|
||||
*
|
||||
* @param ntp_reply_cb, user callback which register to ntp request.
|
||||
* when cloud returns ntp reply, sdk would trigger the callback function
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int being_deprecated linkkit_ntp_time_request(void (*ntp_reply_cb)(const char *ntp_offset_time_ms));
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* LINKKIT_EXPORT_H */
|
||||
@@ -0,0 +1,444 @@
|
||||
/*
|
||||
* Copyright (C) 2015-2018 Alibaba Group Holding Limited
|
||||
*/
|
||||
|
||||
#ifndef LINKKIT_GATEWAY_EXPORT_H
|
||||
#define LINKKIT_GATEWAY_EXPORT_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef DLL_IOT_EXPORTS
|
||||
#define DLL_IOT_API __declspec(dllexport)
|
||||
#else
|
||||
#define DLL_IOT_API __declspec(dllimport)
|
||||
#endif
|
||||
#else
|
||||
#define DLL_IOT_API
|
||||
#endif
|
||||
|
||||
#if defined (__CC_ARM)
|
||||
#define ssize_t int
|
||||
#elif defined (__ICCARM__)
|
||||
#define ssize_t int
|
||||
#endif
|
||||
|
||||
/***************************Gateway Interface***************************/
|
||||
|
||||
enum {
|
||||
LINKKIT_EVENT_CLOUD_DISCONNECTED = 0, /* cloud disconnected */
|
||||
LINKKIT_EVENT_CLOUD_CONNECTED = 1, /* cloud connected */
|
||||
LINKKIT_EVENT_SUBDEV_DELETED = 2, /* subdev deleted */
|
||||
LINKKIT_EVENT_SUBDEV_PERMITED = 3, /* subdev permit join */
|
||||
LINKKIT_EVENT_SUBDEV_SETUP = 4, /* subdev install */
|
||||
};
|
||||
|
||||
/*
|
||||
* option | default | minimum | maximum
|
||||
*--------------------------------|---------|---------|---------
|
||||
* LINKKIT_OPT_MAX_MSG_SIZE | 20480 | 512 | 51200
|
||||
* LINKKIT_OPT_MAX_MSG_QUEUE_SIZE | 16 | 2 | 32
|
||||
* LINKKIT_OPT_THREAD_POOL_SIZE | 4 | 1 | 16
|
||||
* LINKKIT_OPT_THREAD_STACK_SIZE | 8192 | 1024 | 8388608
|
||||
* LINKKIT_OPT_LOG_LEVEL | 3 | 0 | 5
|
||||
*/
|
||||
|
||||
enum {
|
||||
LINKKIT_OPT_MAX_MSG_SIZE = 1,
|
||||
LINKKIT_OPT_MAX_MSG_QUEUE_SIZE = 2,
|
||||
LINKKIT_OPT_THREAD_POOL_SIZE = 3,
|
||||
LINKKIT_OPT_THREAD_STACK_SIZE = 4,
|
||||
LINKKIT_OPT_PROPERTY_POST_REPLY = 5, /* data type: int */
|
||||
LINKKIT_OPT_EVENT_POST_REPLY = 6, /* data type: int */
|
||||
LINKKIT_OPT_PROPERTY_SET_REPLY = 7 /* data type: int */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
int event_type; /* see LINKKIT_EVENT_XXX for more details */
|
||||
|
||||
union {
|
||||
struct {
|
||||
char *productKey;
|
||||
char *deviceName;
|
||||
} subdev_deleted;
|
||||
|
||||
struct {
|
||||
char *productKey;
|
||||
int timeoutSec;
|
||||
} subdev_permited;
|
||||
|
||||
struct {
|
||||
char *subdevList; /* json format:[{"productKey":"","deviceName":""},...] */
|
||||
} subdev_install;
|
||||
} event_data;
|
||||
} linkkit_event_t;
|
||||
|
||||
typedef struct linkkit_params_s {
|
||||
int maxMsgSize; /* max message size */
|
||||
int maxMsgQueueSize; /* max message queue size */
|
||||
|
||||
int threadPoolSize; /* number threads in pool */
|
||||
int threadStackSize; /* default thread stack size */
|
||||
|
||||
int (*event_cb)(linkkit_event_t *ev, void *ctx);
|
||||
|
||||
/* user private data */
|
||||
void *ctx;
|
||||
} linkkit_params_t;
|
||||
|
||||
/**
|
||||
* @brief get default initialize parameters
|
||||
*
|
||||
* @return linkkit default parameters.
|
||||
*/
|
||||
linkkit_params_t *linkkit_gateway_get_default_params(void);
|
||||
|
||||
/**
|
||||
* @brief set option in paremeters
|
||||
*
|
||||
* @param params, linkkit initialize parameters, return from linkkit_gateway_get_default_params().
|
||||
* @param option, see LINKKIT_OPT_XXX for more detail.
|
||||
* @param value, value of option.
|
||||
* @param value_len, value length.
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_setopt(linkkit_params_t *params, int option, void *value, int value_len);
|
||||
|
||||
/**
|
||||
* @brief set event callback
|
||||
*
|
||||
* @param params, linkkit initialize parameters, return from linkkit_gateway_get_default_params().
|
||||
* @param event_cb, event callback.
|
||||
* @param ctx, user private data.
|
||||
*
|
||||
* @return 0 when success, < 0 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_set_event_callback(linkkit_params_t *params, int (*event_cb)(linkkit_event_t *ev,
|
||||
void *ctx),
|
||||
void *ctx);
|
||||
|
||||
/**
|
||||
* @brief linkkit initialization.
|
||||
*
|
||||
* @param initParams, linkkit initialize parameters, see linkkit_params_t for more detail.
|
||||
*
|
||||
* @return 0 when success, < 0 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_init(linkkit_params_t *initParams);
|
||||
|
||||
/**
|
||||
* @brief linkkit deinitialization.
|
||||
*
|
||||
* @return 0 when success, < 0 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_exit(void);
|
||||
|
||||
typedef struct {
|
||||
|
||||
int (*register_complete)(void *ctx);
|
||||
/**
|
||||
* @brief get property callback.
|
||||
*
|
||||
* @param in, properties to be get, in JSON array format, terminated by NULL.
|
||||
* @param out, output buffer fill by user, in json format, terminated by NULL.
|
||||
* @param out_len, out buffer length.
|
||||
* @param ctx, user private data passed by linkkit_gateway_start() or linkkit_gateway_subdev_create()
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
int (*get_property)(char *in, char *out, int out_len, void *ctx);
|
||||
|
||||
/**
|
||||
* @brief set property callback.
|
||||
*
|
||||
* @param in, properties to be set, in JSON object format, terminated by NULL.
|
||||
* @param ctx, user private data passed by linkkit_gateway_start() or linkkit_gateway_subdev_create()
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
int (*set_property)(char *in, void *ctx);
|
||||
|
||||
/**
|
||||
* @brief call service callback.
|
||||
*
|
||||
* @param identifier, service identifier, available services define in TSL file.
|
||||
* @param in, service input data, in JSON object format, terminated by NULL.
|
||||
* @param out, service output, this buffer will be filled by user, in json format, terminated by NULL.
|
||||
* @param out_len, out buffer length.
|
||||
* @param ctx, user private data passed by linkkit_gateway_start() or linkkit_gateway_subdev_create().
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
int (*call_service)(char *identifier, char *in, char *out, int out_len, void *ctx);
|
||||
|
||||
/**
|
||||
* @brief raw data from cloud.
|
||||
*
|
||||
* @param in, input data from cloud.
|
||||
* @param in_len, input data length.
|
||||
* @param out, output data to cloud, allocated by linkkit fill by user, no need to be free.
|
||||
* @param out_len, out buffer length.
|
||||
* @param ctx, user private data passed by linkkit_gateway_start() or linkkit_gateway_subdev_create().
|
||||
*
|
||||
* @return output data size. < 0 when fail.
|
||||
*/
|
||||
int (*down_rawdata)(const void *in, int in_len, void *out, int out_len, void *ctx);
|
||||
|
||||
/**
|
||||
* @brief return data from cloud when calling linkkit_gateway_post_rawdata().
|
||||
*
|
||||
* @param data, return raw data from cloud.
|
||||
* @param len, data length.
|
||||
* @param ctx, user private data passed by linkkit_gateway_start() or linkkit_gateway_subdev_create().
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
int (*post_rawdata_reply)(const void *data, int len, void *ctx);
|
||||
} linkkit_cbs_t;
|
||||
|
||||
/**
|
||||
* @brief start linkkit gateway routines and install callback funstions.
|
||||
*
|
||||
* @param cbs, callback function struct to be installed.
|
||||
* @param ctx, user context pointer.
|
||||
*
|
||||
* @return device id, 0 > when success, < 0 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_start(linkkit_cbs_t *cbs, void *ctx);
|
||||
|
||||
/**
|
||||
* @brief stop linkkit gateway.
|
||||
|
||||
* @param devid, device id return from linkkit_gateway_start().
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_stop(int devid);
|
||||
|
||||
/**
|
||||
* @brief register subdev to gateway.
|
||||
|
||||
* @param productKey, subdev's product key.
|
||||
* @param deviceName, subdev's device name.
|
||||
* @param deviceSecret, subdev's device secret.
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_subdev_register(char *productKey, char *deviceName, char *deviceSecret);
|
||||
|
||||
/**
|
||||
* @brief deregister subdev from gateway.
|
||||
|
||||
* @param productKey, subdev's product key.
|
||||
* @param deviceName, subdev's device name.
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_subdev_unregister(char *productKey, char *deviceName);
|
||||
|
||||
/**
|
||||
* @brief create subdev and install callback funstions.
|
||||
*
|
||||
* @param productKey, subdev's product key.
|
||||
* @param deviceName, subdev's device name.
|
||||
* @param cbs, callback function struct to be installed.
|
||||
* @param ctx, user context pointer.
|
||||
*
|
||||
* @return device id, 0 > when success, < 0 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_subdev_create(char *productKey, char *deviceName, linkkit_cbs_t *cbs, void *ctx);
|
||||
|
||||
/**
|
||||
* @brief destroy subdev by device id.
|
||||
|
||||
* @param devid, device id return from linkkit_gateway_subdev_create().
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_subdev_destroy(int devid);
|
||||
|
||||
/**
|
||||
* @brief make subdev accessible from cloud.
|
||||
|
||||
* @param devid, device id return from linkkit_gateway_subdev_create().
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_subdev_login(int devid);
|
||||
|
||||
/**
|
||||
* @brief make subdev inaccessible on cloud.
|
||||
|
||||
* @param devid, device id return from linkkit_gateway_subdev_create().
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_subdev_logout(int devid);
|
||||
|
||||
enum {
|
||||
LINKKIT_STATE_ENABLED = 0, /* device is enabled by cloud */
|
||||
LINKKIT_STATE_DISABLED, /* device is disabled by cloud */
|
||||
LINKKIT_STATE_REMOVED, /* device is deleted by cloud */
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
char *productKey; /* device's product key */
|
||||
char *deviceName; /* device's device name */
|
||||
|
||||
int devtype; /* Device Type: 0 - gateway, 1 - subdev */
|
||||
int login; /* Login State: 0 - logout, 1 - login */
|
||||
int state; /* Device State: see LINKKIT_STATE_xxx */
|
||||
int online; /* 0 - offline, 1 - online */
|
||||
} linkkit_devinfo_t;
|
||||
|
||||
/**
|
||||
* @brief get device infomation specific by devid.
|
||||
*
|
||||
* @param devinfo, device information, see linkkit_devinfo_t for more detail.
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_get_devinfo(int devid, linkkit_devinfo_t *devinfo);
|
||||
|
||||
/**
|
||||
* @brief post event to cloud.
|
||||
*
|
||||
* @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create().
|
||||
* @param identifier, event identifier, see tsl file for more detail.
|
||||
* @param event, event data, in JSON format.
|
||||
* @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response.
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_trigger_event_json_sync(int devid, char *identifier, char *event, int timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief post event to cloud asynchronously.
|
||||
*
|
||||
* @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create().
|
||||
* @param identifier, event identifier, see tsl file for more detail.
|
||||
* @param event, event data, in JSON format.
|
||||
* @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response.
|
||||
* @param func, callback function when success(retval > 0), timeout(retval = 0) or failed(retval < 0).
|
||||
* @param ctx, user data passed to 'func'.
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_trigger_event_json(int devid, char *identifier, char *event, int timeout_ms,
|
||||
void (*func)(int retval, void *ctx), void *ctx);
|
||||
|
||||
|
||||
/**
|
||||
* @brief post property to cloud.
|
||||
*
|
||||
* @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create().
|
||||
* @param property, property data, in JSON format.
|
||||
* @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response.
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_post_property_json_sync(int devid, char *property, int timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief post property to cloud asynchronously.
|
||||
*
|
||||
* @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create().
|
||||
* @param property, property data, in JSON format.
|
||||
* @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response.
|
||||
* @param func, callback function when success(retval > 0), timeout(retval = 0) or failed(retval < 0).
|
||||
* @param ctx, user data passed to 'func'.
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_post_property_json(int devid, char *property, int timeout_ms,
|
||||
void (*func)(int retval, void *ctx),
|
||||
void *ctx);
|
||||
|
||||
/**
|
||||
* @brief post raw data to cloud.
|
||||
*
|
||||
* @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create().
|
||||
* @param data, raw data buffer pointer.
|
||||
* @param len, raw data length.
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_post_rawdata(int devid, void *data, int len);
|
||||
|
||||
typedef enum {
|
||||
LINKKIT_OTA_EVENT_NEW_VERSION_DETECTED = 1,
|
||||
} linkkit_ota_event_t;
|
||||
|
||||
typedef enum {
|
||||
service_fota_callback_type_new_version_detected = 10,
|
||||
|
||||
service_fota_callback_type_number,
|
||||
} service_fota_callback_type_t;
|
||||
|
||||
typedef void (*handle_service_fota_callback_fp_t)(service_fota_callback_type_t callback_type, const char *version);
|
||||
|
||||
/**
|
||||
* @brief this function used to register callback for firmware ota.
|
||||
*
|
||||
* @param callback_fp, user callback which register to fota. (NULL for unregister)
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_fota_init(handle_service_fota_callback_fp_t callback_fp);
|
||||
|
||||
/**
|
||||
* @brief this function used to execute fota process.
|
||||
*
|
||||
* @param data_buf, data buf that used to do ota. ota service will use this buffer to download bin.
|
||||
* @param data_buf_length, data buf length that used to do ota.
|
||||
*
|
||||
* @return 0 when success, -1 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_invoke_fota_service(void *data_buf, int data_buf_length);
|
||||
|
||||
typedef struct {
|
||||
char *attrKey; /* the key of extend info. */
|
||||
char *attrValue; /* the value of extend info. */
|
||||
} linkkit_extinfo_t;
|
||||
|
||||
/**
|
||||
* @brief post group of extend info to cloud
|
||||
*
|
||||
* @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create().
|
||||
* @param extinfos, group of extend info to be post.
|
||||
* @param nb_extinfos, number of extend infos in extinfos.
|
||||
* @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response.
|
||||
*
|
||||
* @return 0 when success, < 0 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_post_extinfos(int devid, linkkit_extinfo_t *extinfos, int nb_extinfos,
|
||||
int timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief delete extend info specific by key
|
||||
*
|
||||
* @param devid, device id return from linkkit_gateway_start() or linkkit_gateway_subdev_create().
|
||||
* @param extinfos, group of extend info to be deleted, attrValue in linkkit_extinfo_t will be ignore.
|
||||
* @param nb_extinfos, number of extend infos in extinfos.
|
||||
* @param timeout_ms, transmission timeout, in milliseconds. when timeout_ms is 0, wait no response.
|
||||
*
|
||||
* @return 0 when success, < 0 when fail.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_delete_extinfos(int devid, linkkit_extinfo_t *extinfos, int nb_extinfos,
|
||||
int timeout_ms);
|
||||
|
||||
/**
|
||||
* @brief get number devices currently in gateway
|
||||
*
|
||||
* @return number devinfos.
|
||||
*/
|
||||
DLL_IOT_API int linkkit_gateway_get_num_devices(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* LINKKIT_GATEWAY_EXPORT_H */
|
||||
Reference in New Issue
Block a user