/* * Tencent is pleased to support the open source community by making IoT Hub available. * Copyright (C) 2016 THL A29 Limited, a Tencent company. All rights reserved. * Licensed under the MIT License (the "License"); you may not use this file except in * compliance with the License. You may obtain a copy of the License at * http://opensource.org/licenses/MIT * Unless required by applicable law or agreed to in writing, software distributed under the License is * distributed on an "AS IS" basis, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language governing permissions and * limitations under the License. * */ #ifndef _QCLOUD_COAP_H_ #define _QCLOUD_COAP_H_ #ifdef __cplusplus extern "C" { #endif static const char *qcloud_coap_server = "iotcloud.tencentdevices.com"; static const int qcloud_coap_port = 5684; typedef enum qcloud_coap_auth_state_en { QCLOUD_COAP_AUTH_STATE_NONE, QCLOUD_COAP_AUTH_STATE_SUCCESS, QCLOUD_COAP_AUTH_STATE_FAIL, } qcloud_coap_auth_state_t; /** * @brief COAP消息分类 */ typedef enum coap_code_class_en { COAP_CODE_CLASS_REQ = 0, // 请求包 COAP_CODE_CLASS_SUCCESS = 2, // 成功回包 COAP_CODE_CLASS_CLIENT_ERR = 4, // 客户端错误回包 COAP_CODE_CLASS_SERVER_ERR = 5, // 后台错误回包 COAP_CODE_CLASS_INTERNAL_ERR = 6, } coap_code_class_t; /** * @brief COAP消息请求方法 */ typedef enum coap_request_method_en { COAP_REQUEST_METHOD_GET = 1, // GET请求 COAP_REQUEST_METHOD_POST = 2, // POST请求 COAP_REQUEST_METHOD_PUT = 3, COAP_REQUEST_METHOD_DELETE = 4, } coap_request_method_t; typedef enum coap_code_detail_en { /* CoAP Success Response code detail */ COAP_CODE_DETAIL_201_CREATED = 01, /* Mapping to CoAP codeClass.codeDetail 2.01 */ COAP_CODE_DETAIL_202_DELETED = 02, /* Mapping to CoAP codeClass.codeDetail 2.02 */ COAP_CODE_DETAIL_203_VALID = 03, /* Mapping to CoAP codeClass.codeDetail 2.03 */ COAP_CODE_DETAIL_204_CHANGED = 04, /* Mapping to CoAP codeClass.codeDetail 2.04 */ COAP_CODE_DETAIL_205_CONTENT = 05, /* Mapping to CoAP codeClass.codeDetail 2.05 */ COAP_CODE_DETAIL_231_CONTINUE = 31, /* Mapping to CoAP codeClass.codeDetail 2.31 */ /* CoAP Client Error Response code detail */ COAP_CODE_DETAIL_400_BAD_REQUEST = 00, /* Mapping to CoAP codeClass.codeDetail 4.00 */ COAP_CODE_DETAIL_401_UNAUTHORIZED = 01, /* Mapping to CoAP codeClass.codeDetail 4.01 */ COAP_CODE_DETAIL_402_BAD_OPTION = 02, /* Mapping to CoAP codeClass.codeDetail 4.02 */ COAP_CODE_DETAIL_403_FORBIDDEN = 03, /* Mapping to CoAP codeClass.codeDetail 4.03 */ COAP_CODE_DETAIL_404_NOT_FOUND = 04, /* Mapping to CoAP codeClass.codeDetail 4.04 */ COAP_CODE_DETAIL_405_METHOD_NOT_ALLOWED = 05, /* Mapping to CoAP codeClass.codeDetail 4.05 */ COAP_CODE_DETAIL_406_NOT_ACCEPTABLE = 06, /* Mapping to CoAP codeClass.codeDetail 4.06 */ COAP_CODE_DETAIL_408_REQUEST_ENTITY_INCOMPLETE = 8, /* Mapping to CoAP codeClass.codeDetail 4.08 */ COAP_CODE_DETAIL_412_PRECONDITION_FAILED = 12, /* Mapping to CoAP codeClass.codeDetail 4.12 */ COAP_CODE_DETAIL_413_REQUEST_ENTITY_TOO_LARGE = 13, /* Mapping to CoAP codeClass.codeDetail 4.13 */ COAP_CODE_DETAIL_415_UNSUPPORTED_CONTENT_FORMAT = 15, /* Mapping to CoAP codeClass.codeDetail 4.15 */ /* CoAP Server Error Response code detail */ COAP_CODE_DETAIL_500_INTERNAL_SERVER_ERROR = 00, /* Mapping to CoAP codeClass.codeDetail 5.00 */ COAP_CODE_DETAIL_501_NOT_IMPLEMENTED = 01, /* Mapping to CoAP codeClass.codeDetail 5.01 */ COAP_CODE_DETAIL_502_BAD_GATEWAY = 02, /* Mapping to CoAP codeClass.codeDetail 5.02 */ COAP_CODE_DETAIL_503_SERVICE_UNAVAILABLE = 03, /* Mapping to CoAP codeClass.codeDetail 5.03 */ COAP_CODE_DETAIL_504_GATEWAY_TIMEOUT = 04, /* Mapping to CoAP codeClass.codeDetail 5.04 */ COAP_CODE_DETAIL_505_PROXYING_NOT_SUPPORTED = 05, /* Mapping to CoAP codeClass.codeDetail 5.05 */ COAP_CODE_DETAIL_600_TIMEOUT = 00, /* Mapping to self define CoAP codeClass.codeDetail 6.00 */ } coap_code_detail_t; /** * @brief Option number enumeration */ typedef enum coap_message_option_code_en { COAP_MSG_OPTION_CODE_IF_MATCH = 1, // If-Match option number COAP_MSG_OPTION_CODE_URI_HOST = 3, // URI-Host option number COAP_MSG_OPTION_CODE_ETAG = 4, // Entity-Tag option number COAP_MSG_OPTION_CODE_IF_NONE_MATCH = 5, // If-None-Match option number COAP_MSG_OPTION_CODE_URI_PORT = 7, // URI-Port option number COAP_MSG_OPTION_CODE_LOCATION_PATH = 8, // Location-Path option number COAP_MSG_OPTION_CODE_URI_PATH = 11, // URI-Path option number COAP_MSG_OPTION_CODE_CONTENT_FORMAT = 12, // Content-Format option number COAP_MSG_OPTION_CODE_MAX_AGE = 14, // Max-Age option number COAP_MSG_OPTION_CODE_URI_QUERY = 15, // URI-Query option number COAP_MSG_OPTION_CODE_ACCEPT = 17, // Accept option number COAP_MSG_OPTION_CODE_LOCATION_QUERY = 20, // Location-Query option number COAP_MSG_OPTION_CODE_BLOCK2 = 23, // Block2 option number COAP_MSG_OPTION_CODE_BLOCK1 = 27, // Block1 option number COAP_MSG_OPTION_CODE_SIZE2 = 28, // Size2 option number COAP_MSG_OPTION_CODE_PROXY_URI = 35, // Proxy-URI option number COAP_MSG_OPTION_CODE_PROXY_SCHEME = 39, // Proxy-Scheme option number COAP_MSG_OPTION_CODE_SIZE1 = 60, // Size1 option number COAP_MSG_OPTION_CODE_AUTH_TOKEN = 61, // 设备鉴权token option number COAP_MSG_OPTION_CODE_NEED_RESP = 62, // CoAP消息是否需要content response option number } coap_msg_opt_code_t; typedef enum coap_incoming_msg_type_en { COAP_INCOMING_MSG_TYPE_PIGGY, COAP_INCOMING_MSG_TYPE_ACK, COAP_INCOMING_MSG_TYPE_RESP, } coap_incoming_msg_type_t; /** * @brief CoAP needResp类型消息回调处理函数指针定义 * * @param message CoAP消息 * @param userContext 发送消息时携带的用户上下文 */ typedef void (*coap_resp_callback_t)(void *message, void *context); /** * @brief COAP发布消息结构体 */ typedef struct coap_send_option_st { char *payload; // COAP 消息负载 size_t payload_len; // MQTT 消息负载长度 void *context; // 用于用户传递的消息上下文,SDK不做处理在callback时返回 coap_resp_callback_t resp_cb; // 消息回包callback,仅对need_resp: true 有效 } coap_send_opt_t; /** * @brief CoAP Option结构体 */ typedef struct coap_message_option_st { qcloud_list_t list; uint16_t option_code; // Option code uint32_t val_len; // Option length char *val; // Pointer to a buffer containing the option value } coap_msg_option_t; typedef struct coap_message_sent_info_st { qcloud_list_t list; void *context; int is_acked; uint8_t token_len; uint8_t token[COAP_MSG_TOKEN_MAX]; uint8_t transmit_count; osal_timer_t timer; void *message; uint16_t message_id; uint32_t message_len; coap_resp_callback_t resp_cb; } coap_msg_sent_info_t; /** * @brief COAP消息类型 */ typedef enum coap_msg_type_en { COAP_MSG_TYPE_CON = 0x0, /**< 需要等待回包确认的消息 */ COAP_MSG_TYPE_NON = 0x1, /**< 无需等待回包确认的消息 */ COAP_MSG_TYPE_ACK = 0x2, /**< ACK消息 */ COAP_MSG_TYPE_RST = 0x3, /**< Reset消息 */ } coap_msg_type_t; /** * @brief CoAP消息结构体 */ typedef struct coap_message_st { uint32_t version; // CoAP协议版本号 uint8_t type; // 消息类型 uint32_t code_class; // Code class uint32_t code_detail; // Code detail uint16_t id; // 消息id char *payload; // 消息负载 size_t payload_len; // 消息负载长度 char token[COAP_MSG_TOKEN_MAX]; // 消息token uint8_t token_len; // 消息token长度 coap_resp_callback_t resp_cb; // CoAP Response消息回调处理函数 void *context; // 用户上下文 qcloud_list_t option_list; } coap_message_t; #define COAP_MESSAGE_INITIALIZER {COAP_VERSION, COAP_MSG_TYPE_CON, COAP_CODE_CLASS_REQ, COAP_REQUEST_METHOD_POST, 0, NULL, 0, {0}, 0, NULL, NULL, {NULL, NULL}} /** * CoAP 事件类型 */ typedef enum coap_event_type_en { COAP_EVENT_TYPE_RECEIVE_ACK = 0, // 收到消息ACK COAP_EVENT_TYPE_RECEIVE_RESPCONTENT = 1, // 收到消息回包响应 COAP_EVENT_TYPE_UNAUTHORIZED = -1, // 设备鉴权失败或鉴权token过期 COAP_EVENT_TYPE_FORBIDDEN = -2, // 设备topic无权限 COAP_EVENT_TYPE_INTERNAL_SERVER_ERROR = -3, // 服务端错误 COAP_EVENT_TYPE_ACK_TIMEOUT = -4, // 消息ACK超时 COAP_EVENT_TYPE_SEPRESP_TIMEOUT = -5, // 消息回包响应超时 } coap_event_type_t; typedef struct coap_event_st { coap_event_type_t type; /* 事件类型 */ void *message; /* 事件消息 or 内容消息 */ } coap_event_t; typedef void (*coap_event_handler_fn_t)(void *context, coap_event_t *event); typedef struct coap_event_handler_st { coap_event_handler_fn_t handler; void *context; } coap_event_handler_t; typedef struct qcloud_coap_client_st { qcloud_coap_auth_state_t auth_state; uint32_t message_token; // 标识请求响应条消息对应 uint16_t packet_id; // COAP报文标识符 uint8_t tx_buffer[QCLOUD_COAP_CLIENT_TX_BUF_LEN]; uint8_t rx_buffer[QCLOUD_COAP_CLIENT_RX_BUF_LEN]; void *tx_lock; // 输出流的锁 void *message_list_lock; // 等待发布消息ack列表的锁 qcloud_list_t message_list; // 请求消息列表 qcloud_network_t network; // 网络调用数据结构 uint32_t command_timeout; // CoAP消息超时时间, 单位:ms uint8_t retransmit_max; // CoAP消息最大重试次数 coap_event_handler_t event_handler; // 事件回调 char *auth_token; // 鉴权token int auth_token_len; char auth_id[QCLOUD_COAP_AUTH_ID_MAX + 1]; char auth_uri[QCLOUD_COAP_AUTH_URI_MAX + 1]; } qcloud_coap_client_t; __QCLOUD_API__ qcloud_err_t qcloud_coap_client_create(qcloud_coap_client_t *client, qcloud_device_t *device, coap_event_handler_fn_t handler); __QCLOUD_API__ qcloud_err_t qcloud_coap_client_destroy(qcloud_coap_client_t *client); __QCLOUD_API__ qcloud_err_t qcloud_coap_client_connect(qcloud_coap_client_t *client); __QCLOUD_API__ qcloud_err_t qcloud_coap_client_yield(qcloud_coap_client_t *client, uint32_t timeout_ms); __QCLOUD_API__ qcloud_err_t qcloud_coap_client_msg_send(qcloud_coap_client_t *client, char *topic, coap_send_opt_t *send_opt); __QCLOUD_API__ uint16_t qcloud_coap_msg_id_get(coap_message_t *message); __QCLOUD_API__ qcloud_err_t qcloud_coap_msg_payload_get(coap_message_t *message, char **payload, int *payload_len); __QCLOUD_API__ coap_event_type_t qcloud_coap_event_type_get(coap_message_t *message); __QCLOUD_INTERNAL__ int coap_message_token_get(qcloud_coap_client_t *client, char *buf); __QCLOUD_INTERNAL__ qcloud_err_t coap_message_type_set(coap_message_t *message, uint8_t type); __QCLOUD_INTERNAL__ qcloud_err_t coap_message_code_set(coap_message_t *message, uint32_t code_class, uint32_t code_detail); __QCLOUD_INTERNAL__ qcloud_err_t coap_message_id_set(coap_message_t *message, uint16_t id); __QCLOUD_INTERNAL__ qcloud_err_t coap_message_token_set(coap_message_t *message, char *buf, uint8_t len); __QCLOUD_INTERNAL__ qcloud_err_t coap_message_payload_set(coap_message_t *message, char *buf, size_t len); __QCLOUD_INTERNAL__ coap_msg_option_t *coap_message_option_construct(uint16_t option_code, uint32_t len, const char *val); __QCLOUD_INTERNAL__ qcloud_err_t coap_message_option_add(coap_message_t *message, coap_msg_opt_code_t option_code, uint32_t len, const char *val); __QCLOUD_INTERNAL__ qcloud_err_t coap_message_callback_set(coap_message_t *message, coap_resp_callback_t callback); __QCLOUD_INTERNAL__ qcloud_err_t coap_message_context_set(coap_message_t *message, void *context); __QCLOUD_INTERNAL__ void coap_message_init(coap_message_t *message); __QCLOUD_INTERNAL__ void coap_message_destroy(coap_message_t *message); __QCLOUD_INTERNAL__ void coap_message_dump(coap_message_t* message); __QCLOUD_INTERNAL__ void coap_glue_connect_id_generate(char *conn_id); __QCLOUD_INTERNAL__ uint16_t coap_glue_packet_id_generate(qcloud_coap_client_t *client); __QCLOUD_INTERNAL__ qcloud_err_t coap_glue_message_list_destroy(qcloud_coap_client_t *client); __QCLOUD_INTERNAL__ qcloud_err_t coap_glue_spin(qcloud_coap_client_t *client, uint32_t timeout_ms); __QCLOUD_INTERNAL__ qcloud_err_t coap_glue_msg_send(qcloud_coap_client_t *client, coap_message_t *message); __QCLOUD_INTERNAL__ qcloud_err_t coap_message_deserialize(coap_message_t *message, char *buf, size_t buf_len); __QCLOUD_INTERNAL__ int coap_message_serialize(coap_message_t *message, char *buf, size_t buf_len); __QCLOUD_INTERNAL__ qcloud_err_t coap_auth(qcloud_coap_client_t *client, char *connection_id); #ifdef __cplusplus } #endif #endif