├── README.md
├── docs
└── Tencent_AT_instruction_set_V3.1.3.pdf
├── include
├── at_client.h
├── at_log.h
├── at_sanity_check.h
├── at_utils.h
├── config.h
├── dev_config.h
├── hal_export.h
├── module_api_inf.h
├── qcloud_iot_api_export.h
├── qcloud_iot_export_data_template.h
├── qcloud_iot_export_error.h
├── qcloud_iot_export_method.h
├── qcloud_iot_export_mqtt.h
└── ringbuff.h
├── port
├── hal_at.c
└── hal_os.c
├── sample
├── light_data_template_sample.c
└── mqtt_sample.c
├── src
├── data_template
│ ├── data_template_aciton.c
│ ├── data_template_client.c
│ ├── data_template_client_common.c
│ ├── data_template_client_json.c
│ ├── data_template_client_manager.c
│ └── data_template_event.c
├── include
│ ├── data_template_action.h
│ ├── data_template_client.h
│ ├── data_template_client_common.h
│ ├── data_template_client_json.h
│ ├── data_template_event.h
│ ├── json_parser.h
│ ├── lite-list.h
│ ├── lite-utils.h
│ ├── utils_list.h
│ └── utils_timer.h
├── module_at
│ ├── at_client.c
│ ├── at_log.c
│ ├── at_timer.c
│ ├── at_utils.c
│ ├── iot_device.c
│ ├── module_api_inf.c
│ └── ringbuff.c
├── mqtt
│ └── mqtt.c
└── utils
│ ├── json_parser.c
│ ├── json_token.c
│ ├── string_utils.c
│ ├── utils_list.c
│ └── utils_timer.c
├── tools
├── codegen.py
└── example_config.json
└── usr_logic
├── action_config.c
├── data_config.c
├── data_template_usr_logic.c
└── events_config.c
/README.md:
--------------------------------------------------------------------------------
1 | ## qcloud-iot-sdk-tecent-at-based
2 |
3 | ### 介绍
4 |
5 | qcloud-iot-sdk-tecent-at-based 面向使用支持腾讯MQTT AT指令的模组(2/3/4/5G、NB、WIFI等)接入腾讯物联网平台的终端设备开发者,典型应用场景为MCU+腾讯定制AT模组,MCU侧集成AT_SDK,AT_SDK完成实现了MCU和模组数据交互的AT框架,并基于AT框架配合腾讯AT指令,实现了MQTT、影子及数据模板的功能,同时提供了示例sample。开发者需要实现的HAL层适配接口见hal_export.h,需要实现串口的收发接口(中断接收),延时函数,模组上下电及os相关接口适配(互斥锁、动态内存申请释放、线程创建),适配层接口单独剥离在port目录。
6 |
7 | ### qcloud-iot-sdk-tecent-at-based 软件架构
8 |
9 |
10 |
11 | ### 目录结构
12 |
13 | | 名称 | 说明 |
14 | | ---- | ---- |
15 | | docs | 文档目录,包含腾讯AT指令集定义 |
16 | | port | HAL层移植目录,需要实现串口的收发接口(中断接收),延时函数,模组上下电及os相关接口|
17 | | sample | 应用示例,示例使用MQTT、影子、数据模板的使用方式|
18 | | src | AT框架及协议逻辑实现 |
19 | | ├───── event | 事件功能协议封装 |
20 | | ├───── module_at |at client抽象,实现RX解析,命令下行,urc匹配,resp异步匹配|
21 | | ├───── data_template |基于AT框架的数据模板协议|
22 | | ├───── mqtt |基于AT框架的mqtt协议实现|
23 | | ├───── utils |json、timer、链表等应用|
24 | | ├───── include |SDK对外头文件及设备信息配置头文件|
25 | | tools | 代码生成脚本 |
26 | | README.md | SDK使用说明 |
27 |
28 | ### 定制腾讯MQTT AT指令模组说明
29 | 腾讯定义的MQTT AT指令见文档目录,模组侧把MQTT协议封装在模组固件中,各家模组商遵循统一的MQTT通信的AT指令名称、参数及命令返回,并实现了通过设置的设备参数及鉴权方式实现和平台的鉴权。已经支持的[模组列表](https://github.com/tencentyun/qcloud-iot-explorer-sdk-embedded-c/blob/master/docs/MCU%2B%E8%85%BE%E8%AE%AF%E4%BA%91%E5%AE%9A%E5%88%B6AT%E6%A8%A1%E7%BB%84.md)。
30 |
31 | ##### 1.1 使用MQTT AT定制模组实现MQTT通信
32 | AT_SDK中module_api_inf.c把docs目录下的《腾讯云IoT AT指令集-V3.1.3.pdf》各AT指令独立实现为单独的函数,在mqtt_sample.c中示例了如何组合这些命令序列,包括初始化、模组上下电、联网/注册网络、设备信息写入、MQTT连接、主题订阅、消息发布、订阅消息回调处理。如果不源移植AT_SDK,可以基于如下AT指令交互流程使用MQTT功能:
33 |
34 | 
35 |
36 | ##### 1.2 数据模板功能
37 | 数据模板功能是基于MQTT的基础上,通过订阅特定的topic,payload部分基于为json格式实现数据协议交互,AT_SDK已是实现数据协议的封装和示例模板,可以参考示例data_template_sample.c及light_data_template_sample.c。
38 |
39 | [数据模板协议说明](https://cloud.tencent.com/document/product/1081/34916)
40 |
41 | ### 移植指导
42 | 根据所选的嵌入式平台,适配 hal_export.h 头文件对应的hal层API的移植实现。主要有串口收发(中断接收)、模组开关机、任务/线程创建、动态内存申请/释放、时延、打印等API。可参考基于STM32+FreeRTOS的AT-SDK[移植示例](https://github.com/tencentyun/tc-iot-at-sdk-stm32-freertos-based-example.git)
43 |
44 | ##### 2.1 **hal_export.h**:
45 | hal层对外的API接口及HAL层宏开关控制。
46 |
47 | | 序号 | 宏定义 | 说明 |
48 | | ----| ---------------------------- | -----------------------------------|
49 | | 1 | PARSE_THREAD_STACK_SIZE | 串口at解析线程栈大小 |
50 | | 2 | OS_USED | 是否使用OS,目前的AT-SDK是基于多线程框架的,所以OS是必须的 |
51 | | 3 | AUTH_MODE_KEY | 认证方式,证书认证还是秘钥认证 |
52 | | 4 | DEBUG_DEV_INFO_USED | 默认使能该宏,设备信息使用调试信息,正式量产关闭该宏,并实现设备信息存取接口 |
53 |
54 | ##### 2.2 **hal_os.c**:
55 | 该源文件主要实现打印、延时、时间戳、锁、线程创建、设备信息存取等。
56 |
57 | | 序号 | HAL_API | 说明 |
58 | | ---- | -----------------------------------| ---------------------------------- |
59 | | 1 | HAL_Printf | 打印函数,log输出需要,可选实现 |
60 | | 2 | HAL_Snprintf | 格式化打印,json数据处理需要,必须实现 |
61 | | 3 | HAL_Vsnprintf | 格式化输出, 可选实现 |
62 | | 4 | HAL_DelayMs | 毫秒延时,必选实现 |
63 | | 5 | HAL_DelayUs | 微妙延时,可选实现 |
64 | | 6 | HAL_GetTimeMs | 获取毫秒数,必选实现 |
65 | | 7 | HAL_GetTimeSeconds | 获取时间戳,必须实现,时戳不需绝对准确,但不可重复 |
66 | | 8 | hal_thread_create | 线程创建,必选实现 |
67 | | 9 | hal_thread_destroy | 线程销毁,必选实现 |
68 | | 10 | HAL_SleepMs | 放权延时,必选实现 |
69 | | 11 | HAL_MutexCreate | 互斥锁创建,必选实现 |
70 | | 12 | HAL_MutexDestroy | 互斥锁销毁,必选实现 |
71 | | 13 | HAL_MutexLock | 获取互斥锁,必选实现 |
72 | | 14 | HAL_MutexUnlock | 释放互斥锁,必选实现 |
73 | | 15 | HAL_Malloc | 动态内存申请,必选实现 |
74 | | 16 | HAL_Free | 动态内存释放,必选实现 |
75 | | 17 | HAL_GetDevInfo | 获取设备信息,必选实现 |
76 | | 18 | HAL_SetDevInfo | 设置设备信息,必须存放在非易失性存储介质,必选实现 |
77 |
78 | ##### 2.3 **hal_at.c**:
79 | 该源文件主要实现AT串口初始化、串口收发、模组开关机。
80 |
81 | | 序号 | HAL_API | 说明 |
82 | | ---- | -------------------------------| ---------------------------------- |
83 | | 1 | module_power_on | 模组开机,AT串口初始化,必选实现 |
84 | | 1 | module_power_off | 模组关机,低功耗需要,可选实现 |
85 | | 2 | AT_UART_IRQHandler | 串口接收中断ISR,将收取到的数据放入ringbuff中,AT解析线程会实时解析数据,必选实现|
86 | | 3 | at_send_data | AT串口发送接口 |
87 |
88 | ##### 2.4 **module_api_inf.c**:
89 | 配网/注网 API业务适配,该源文件基于腾讯定义的AT指令实现了MQTT的交互,但有一个关于联网/注网的API(module_register_network)需要根据模组适配。代码基于[ESP8266腾讯定制AT固件](https://main.qcloudimg.com/raw/6811fc7631dcf0ce5509ccbdba5c72b7.zip)示例了WIFI直连的方式连接网络,但更常用的场景是根据特定事件(譬如按键)触发配网(softAP/一键配网),这块的逻辑各具体业务逻辑自行实现。ESP8266有封装配网指令和示例APP。对于蜂窝模组,则是使用特定的网络注册指令。开发者参照module_handshake应用AT-SDK的AT框架添加和模组的AT指令交互。
90 |
91 | ```
92 | //模组联网(NB/2/3/4G注册网络)、wifi配网(一键配网/softAP)暂时很难统一,需要用户根据具体模组适配。
93 | //开发者参照 module_handshake API使用AT框架的API和模组交互,实现适配。
94 | eAtResault module_register_network(eModuleType eType)
95 | {
96 | eAtResault result = AT_ERR_SUCCESS;
97 |
98 | #if (MODULE_TYPE == eMODULE_ESP8266)
99 | #define WIFI_SSID "youga_wifi"
100 | #define WIFI_PW "Iot@2018"
101 |
102 |
103 | /*此处示例传递热点名字直接联网,通常的做法是特定产品根据特定的事件(譬如按键)触发wifi配网(一键配网/softAP)*/
104 | result = wifi_connect(WIFI_SSID, WIFI_PW);
105 | //result |= wifi_set_test_server_ip("111.230.126.244");
106 | if(AT_ERR_SUCCESS != result)
107 | {
108 | Log_e("wifi connect fail,ret:%d", result);
109 | }
110 |
111 | #else
112 | /*模组网络注册、或者wifi配网需要用户根据所选模组实现*/
113 | #endif
114 |
115 | return result;
116 | }
117 | ```
118 |
119 | ##### 2.5 设备信息修改
120 | 调试时,在hal_export.h将设备信息调试宏定义打开。量产时需要关闭该宏定义,实现hal-os中序列17-26的设备信息存取API
121 | ```
122 | #define DEBUG_DEV_INFO_USED
123 | ```
124 | 修改下面宏定义的设备信息,则系统将会使用调试信息。
125 | ```
126 | #ifdef DEBUG_DEV_INFO_USED
127 |
128 | static char sg_product_id[MAX_SIZE_OF_PRODUCT_ID + 1] = "PRODUCT_ID";
129 | static char sg_device_name[MAX_SIZE_OF_DEVICE_NAME + 1] = "YOUR_DEVICE_NAME";
130 |
131 | #ifdef AUTH_MODE_CERT
132 | static char sg_device_cert_file_name[MAX_SIZE_OF_DEVICE_CERT_FILE_NAME + 1] = "YOUR_DEVICE_NAME_cert.crt";
133 | static char sg_device_privatekey_file_name[MAX_SIZE_OF_DEVICE_KEY_FILE_NAME + 1] = "YOUR_DEVICE_NAME_private.key";
134 | #else
135 | char sg_device_secret[MAX_SIZE_OF_DEVICE_SERC + 1] = "YOUR_IOT_PSK";
136 | #endif
137 |
138 | #endif
139 | ```
140 |
141 | ##### 2.6业务逻辑开发
142 | 自动生成的代码data_template_usr_logic.c,已实现数据、事件收发及响应的通用处理逻辑。但是具体的数据处理的业务逻辑需要用户自己根据业务逻辑添加,上下行业务逻辑添加的入口函数分别为deal_up_stream_user_logic 、deal_down_stream_user_logic,可以参考基于场景的示例light_data_template_sample.c添加业务处理逻辑。
143 |
144 | **下行业务逻辑实现:**
145 | ```
146 | /*用户需要实现的下行数据的业务逻辑,pData除字符串变量已实现用户定义的所有其他变量值解析赋值,待用户实现业务逻辑*/
147 | static void deal_down_stream_user_logic(ProductDataDefine * pData)
148 | {
149 | Log_d("someting about your own product logic wait to be done");
150 | }
151 | ```
152 |
153 | **上行业务逻辑实现:**
154 | ```
155 | /*用户需要实现的上行数据的业务逻辑,此处仅供示例*/
156 | static int deal_up_stream_user_logic(DeviceProperty *pReportDataList[], int *pCount)
157 | {
158 | int i, j;
159 |
160 | for (i = 0, j = 0; i < TOTAL_PROPERTY_COUNT; i++) {
161 | if(eCHANGED == sg_DataTemplate[i].state) {
162 | pReportDataList[j++] = &(sg_DataTemplate[i].data_property);
163 | sg_DataTemplate[i].state = eNOCHANGE;
164 | }
165 | }
166 | *pCount = j;
167 |
168 | return (*pCount > 0)?AT_ERR_SUCCESS:AT_ERR_FAILURE;
169 | }
170 | ```
171 |
172 | ##### 2.7 示例说明
173 | Smaple目录一共有3个示例,分别是mqtt_sample.c、data_template_sample.c、light_data_template_sample.c。
174 | 各示例说明如下:
175 |
176 | | 序号 | 示例名称 | 说明 |
177 | | ---- | -------------------------------| ---------------------------------- |
178 | | 1 | mqtt_sample.c | MQTT示例,该示例示例基于定制的AT指令如何便捷的接入腾讯物联网平台及收发数据|
179 | | 2 | data_template_sample.c | 通用数据模板及事件功能示例,示例如何基于腾讯物联网平台的数据模板功能快速开发产品|
180 | | 3 | light_data_template_sample.c | 基于智能灯的控制场景,示例具体的产品如何应用数据模板及事件功能 |
181 |
182 | ### SDK接口说明
183 | 关于 SDK 的更多使用方式及接口了解, 参见 qcloud_iot_api_export.h
184 |
185 |
186 |
187 |
--------------------------------------------------------------------------------
/docs/Tencent_AT_instruction_set_V3.1.3.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tencentyun/qcloud-iot-sdk-tencent-at-based/deef817aedb69f0465a57b16640e829e7f23057b/docs/Tencent_AT_instruction_set_V3.1.3.pdf
--------------------------------------------------------------------------------
/include/at_client.h:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file : at_client.h
4 | * @brief : at client header file
5 | ******************************************************************************
6 | *
7 | * Copyright (c) 2019 Tencent.
8 | * All rights reserved.
9 | ******************************************************************************
10 | */
11 |
12 | #ifndef __AT_CLIENT_H__
13 | #define __AT_CLIENT_H__
14 |
15 | #include "ringbuff.h"
16 | #include "module_api_inf.h"
17 |
18 | #ifdef __cplusplus
19 | extern "C" {
20 | #endif
21 |
22 | #define AT_FRAME_VERSION "1.0.0"
23 |
24 | #define AT_CMD_NAME_LEN 16
25 | #define AT_END_MARK_LEN 4
26 |
27 |
28 | //#define CLINET_BUFF_LEN (4*RING_BUFF_LEN)MAX_TOPIC_PAYLOAD_LEN
29 | #define CLINET_BUFF_LEN (MAX_TOPIC_PAYLOAD_LEN)
30 | #define GET_CHAR_TIMEOUT_MS (5000)
31 | #define CMD_TIMEOUT_MS (10000)
32 | #define CMD_RESPONSE_INTERVAL_MS (100)
33 |
34 |
35 | typedef void (*ParserFunc)(void *userContex);
36 |
37 | typedef enum
38 | {
39 | AT_STATUS_UNINITIALIZED = 0,
40 | AT_STATUS_INITIALIZED,
41 | AT_STATUS_BUSY,
42 | }at_status;
43 |
44 |
45 | enum at_resp_status
46 | {
47 | AT_RESP_OK = 0, /* AT response end is OK */
48 | AT_RESP_ERROR = -1, /* AT response end is ERROR */
49 | AT_RESP_TIMEOUT = -2, /* AT response is timeout */
50 | AT_RESP_BUFF_FULL= -3, /* AT response buffer is full */
51 | };
52 | typedef enum at_resp_status at_resp_status_t;
53 |
54 | typedef struct _at_response_
55 | {
56 | /* response buffer */
57 | char *buf;
58 | /* the maximum response buffer size */
59 | int buf_size;
60 | /* the number of setting response lines
61 | * == 0: the response data will auto return when received 'OK' or 'ERROR'
62 | * != 0: the response data will return when received setting lines number data */
63 | int line_num;
64 | /* the count of received response lines */
65 | int line_counts;
66 | /* the maximum response time */
67 | uint32_t timeout;
68 | }at_response;
69 |
70 |
71 | typedef at_response * at_response_t;
72 |
73 | /* URC(Unsolicited Result Code) object, such as: 'RING', 'READY' request by AT server */
74 | typedef struct _at_urc_
75 | {
76 | const char *cmd_prefix;
77 | const char *cmd_suffix;
78 | void (*func)(const char *data, uint32_t size);
79 | }at_urc;
80 |
81 | typedef at_urc *at_urc_t;
82 |
83 | typedef struct _at_client_
84 | {
85 | at_status status;
86 | char end_sign;
87 |
88 | ring_buff_t pRingBuff;
89 |
90 | char *recv_buffer;
91 | uint32_t recv_bufsz;
92 | uint32_t cur_recv_len;
93 | void *lock; //pre cmd take the lock wait for resp , another cmd need wait for unlock
94 |
95 | at_response_t resp;
96 | at_resp_status_t resp_status;
97 | bool resp_notice;
98 |
99 | const at_urc *urc_table;
100 | uint16_t urc_table_size;
101 |
102 | ParserFunc parser; //RX parser
103 | }at_client;
104 |
105 | typedef at_client *at_client_t;
106 |
107 |
108 | /* AT client initialize and start*/
109 | eAtResault at_client_init(at_client_t pClient);
110 |
111 | /* get AT client handle*/
112 | at_client_t at_client_get(void);
113 |
114 | /*AT connect detect*/
115 | eAtResault at_client_wait_connect(uint32_t timeout);
116 |
117 | /* ========================== multiple AT client function ============================ */
118 | /* set AT client a line end sign */
119 | void at_set_end_sign(char ch);
120 |
121 | /* Set URC(Unsolicited Result Code) table */
122 | void at_set_urc_table(at_client_t client, const at_urc_t table, uint32_t size);
123 |
124 | /* AT client send commands to AT server and waiter response */
125 | int at_client_send(at_client_t client, char *buf, int size);
126 |
127 | eAtResault at_obj_exec_cmd(at_response_t resp, const char *cmd_expr, ...);
128 | #define at_exec_cmd(resp, ...) at_obj_exec_cmd(resp, __VA_ARGS__)
129 |
130 | /* AT response object create and delete */
131 | at_response_t at_create_resp(uint32_t buf_size, uint32_t line_num, uint32_t timeout);
132 | void at_delete_resp(at_response_t resp);
133 |
134 |
135 | /* AT response line buffer get and parse response buffer arguments */
136 | const char *at_resp_get_line(at_response_t resp, uint32_t resp_line);
137 | const char *at_resp_get_line_by_kw(at_response_t resp, const char *keyword);
138 | int at_resp_parse_line_args(at_response_t resp, uint32_t resp_line, const char *resp_expr, ...);
139 | int at_resp_parse_line_args_by_kw(at_response_t resp, const char *keyword, const char *resp_expr, ...);
140 |
141 | /* ========================== single AT client function ============================ */
142 | #ifdef __cplusplus
143 | }
144 | #endif
145 |
146 | #endif /* __AT_H__ */
147 |
148 |
--------------------------------------------------------------------------------
/include/at_log.h:
--------------------------------------------------------------------------------
1 | #ifndef _AT_LOG_H_
2 | #define _AT_LOG_H_
3 |
4 | #ifdef __cplusplus
5 | extern "C" {
6 | #endif
7 |
8 | #include
9 | #include
10 | #include
11 | #include
12 | #include
13 |
14 | /**
15 | * 日志输出等级
16 | */
17 | typedef enum {
18 | LOG_DEBUG,
19 | LOG_INFO,
20 | LOG_WARN,
21 | LOG_ERROR
22 | } LOG_LEVEL;
23 |
24 | /**
25 | * 全局日志级别输出标志, 只输出小于或等于该等级的日志信息
26 | */
27 | extern LOG_LEVEL g_log_level;
28 |
29 |
30 | /**
31 | * @brief
32 | *
33 | * @param
34 | */
35 | void At_Log_Set_Level(LOG_LEVEL level);
36 |
37 | /**
38 | * @brief 获取当前日志等级
39 | *
40 | * @return
41 | */
42 | LOG_LEVEL At_Log_Get_Level(void);
43 |
44 |
45 | /**
46 | * @brief 日志打印函数,默认打印到标准输出
47 | *
48 | * @param file 源文件名
49 | * @param func 函数名
50 | * @param line 行号
51 | * @param level 日志等级
52 | */
53 | void Log_writter(const char *file, const char *func, const int line, const int level, const char *fmt, ...);
54 |
55 | /**
56 | * @brief buff数据dump
57 | *
58 | * @param pData 待dump的buff指针
59 | * @param len 待dump的buff数据长度
60 | */
61 | void HexDump(const uint8_t *pData, unsigned int len);
62 |
63 | #define Log_d(args...) Log_writter(__FILE__, __FUNCTION__, __LINE__, LOG_DEBUG, args)
64 | #define Log_i(args...) Log_writter(__FILE__, __FUNCTION__, __LINE__, LOG_INFO, args)
65 | #define Log_w(args...) Log_writter(__FILE__, __FUNCTION__, __LINE__, LOG_WARN, args)
66 | #define Log_e(args...) Log_writter(__FILE__, __FUNCTION__, __LINE__, LOG_ERROR, args)
67 |
68 | //#define DEBUG_EABLE
69 | #ifdef DEBUG_EABLE
70 | #define IOT_FUNC_ENTRY \
71 | {\
72 | printf("FUNC_ENTRY: %s L#%d \n", __FUNCTION__, __LINE__); \
73 | }
74 | #define IOT_FUNC_EXIT \
75 | {\
76 | printf("FUNC_EXIT: %s L#%d \n", __FUNCTION__, __LINE__); \
77 | return;\
78 | }
79 | #define IOT_FUNC_EXIT_RC(x) \
80 | {\
81 | printf("FUNC_EXIT: %s L#%d Return Code : %ld \n", __FUNCTION__, __LINE__, (long)(x)); \
82 | return x; \
83 | }
84 | #else
85 | #define IOT_FUNC_ENTRY
86 | #define IOT_FUNC_EXIT \
87 | {\
88 | return;\
89 | }
90 | #define IOT_FUNC_EXIT_RC(x) \
91 | {\
92 | return x; \
93 | }
94 | #endif
95 |
96 | #ifdef __cplusplus
97 | }
98 | #endif
99 |
100 | #endif /* QCLOUD_IOT_EXPORT_LOG_H_ */
101 |
--------------------------------------------------------------------------------
/include/at_sanity_check.h:
--------------------------------------------------------------------------------
1 | #ifndef _AT_SANITY_CHECK_H_
2 | #define _AT_SANITY_CHECK_H_
3 |
4 | #if defined(__cplusplus)
5 | extern "C" {
6 | #endif
7 |
8 | #include "at_log.h"
9 |
10 |
11 | #define NUMBERIC_SANITY_CHECK(num, err) \
12 | do { \
13 | if (0 == (num)) { \
14 | Log_e("Invalid argument, numeric 0"); \
15 | return (err); \
16 | } \
17 | } while(0)
18 |
19 | #define NUMBERIC_SANITY_CHECK_RTN(num) \
20 | do { \
21 | if (0 == (num)) { \
22 | Log_e("Invalid argument, numeric 0"); \
23 | return; \
24 | } \
25 | } while(0)
26 |
27 | #define POINTER_SANITY_CHECK(ptr, err) \
28 | do { \
29 | if (NULL == (ptr)) { \
30 | Log_e("Invalid argument, %s = %p", #ptr, ptr); \
31 | return (err); \
32 | } \
33 | } while(0)
34 |
35 | #define POINTER_SANITY_CHECK_RTN(ptr) \
36 | do { \
37 | if (NULL == (ptr)) { \
38 | Log_e("Invalid argument, %s = %p", #ptr, ptr); \
39 | return; \
40 | } \
41 | } while(0)
42 |
43 | #define STRING_PTR_SANITY_CHECK(ptr, err) \
44 | do { \
45 | if (NULL == (ptr)) { \
46 | Log_e("Invalid argument, %s = %p", #ptr, (ptr)); \
47 | return (err); \
48 | } \
49 | if (0 == strlen((ptr))) { \
50 | Log_e("Invalid argument, %s = '%s'", #ptr, (ptr)); \
51 | return (err); \
52 | } \
53 | } while(0)
54 |
55 | #define STRING_PTR_SANITY_CHECK_RTN(ptr) \
56 | do { \
57 | if (NULL == (ptr)) { \
58 | Log_e("Invalid argument, %s = %p", #ptr, (ptr)); \
59 | return; \
60 | } \
61 | if (0 == strlen((ptr))) { \
62 | Log_e("Invalid argument, %s = '%s'", #ptr, (ptr)); \
63 | return; \
64 | } \
65 | } while(0)
66 |
67 | #if defined(__cplusplus)
68 | }
69 | #endif
70 |
71 | #endif
72 |
--------------------------------------------------------------------------------
/include/at_utils.h:
--------------------------------------------------------------------------------
1 | /**
2 | ******************************************************************************
3 | * @file : at_utils.h
4 | * @brief : head file of api for at utils
5 | ******************************************************************************
6 | *
7 | * History: