1 /**
2  * @file aiot_ntp_api.h
3  * @brief ntp模块头文件, 提供获取utc时间的能力
4  *
5  * @copyright Copyright (C) 2015-2020 Alibaba Group Holding Limited
6  *
7  * @details
8  *
9  * NTP模块用于从阿里云物联网平台上获取UTC时间, API的使用流程如下:
10  *
11  * 1. 首先参考 @ref aiot_mqtt_api.h 的说明, 保证成功建立与物联网平台的`MQTT`连接
12  *
13  * 2. 调用 @ref aiot_ntp_init 初始化ntp会话, 获取会话句柄
14  *
15  * 3. 调用 @ref aiot_ntp_setopt 配置NTP会话的参数, 常用配置项见 @ref aiot_ntp_setopt 的说明
16  *
17  * 4. 调用 @ref aiot_ntp_send_request 发送NTP请求
18  *
19  * 5. 收到的UTC时间经SDK处理后会调用由 @ref aiot_ntp_setopt 配置的 @ref AIOT_NTPOPT_RECV_HANDLER 回调函数, 通知用户当前的时间
20  *
21  */
22 #ifndef __AIOT_NTP_API_H__
23 #define __AIOT_NTP_API_H__
24 
25 #if defined(__cplusplus)
26 extern "C" {
27 #endif
28 
29 #include <stdint.h>
30 
31 /**
32  * @brief -0x1100~-0x11FF表达SDK在ntp模块内的状态码
33  */
34 #define STATE_NTP_BASE                                             (-0x1100)
35 
36 /**
37  * @brief MQTT会话句柄未设置, 请通过 @ref aiot_ntp_setopt 设置MQTT会话句柄
38  */
39 #define STATE_NTP_MISSING_MQTT_HANDLE                              (-0x1101)
40 
41 /**
42  * @brief ntp模块收到从网络上来的报文时, 通知用户的报文类型
43  */
44 typedef enum {
45     AIOT_NTPRECV_LOCAL_TIME
46 } aiot_ntp_recv_type_t;
47 
48 /**
49  * @brief ntp模块收到从网络上来的报文时, 通知用户的报文内容
50  */
51 typedef struct {
52     /**
53      * @brief 报文内容所对应的报文类型, 更多信息请参考@ref aiot_ntp_recv_type_t
54      */
55     aiot_ntp_recv_type_t  type;
56     union {
57         /**
58          * @brief utc事件戳以及时区换算后的日期, 以 @ref AIOT_NTPOPT_TIME_ZONE 设置的时区为准
59          */
60         struct {
61             uint64_t timestamp;
62             uint32_t year;
63             uint32_t mon;
64             uint32_t day;
65             uint32_t hour;
66             uint32_t min;
67             uint32_t sec;
68             uint32_t msec;
69         } local_time;
70     } data;
71 } aiot_ntp_recv_t;
72 
73 /**
74  * @brief ntp模块收到从网络上来的报文时, 通知用户所调用的数据回调函数
75  *
76  * @param[in] handle ntp会话句柄
77  * @param[in] packet ntp消息结构体, 存放收到的ntp报文内容
78  * @param[in] userdata 用户上下文
79  *
80  * @return void
81  */
82 typedef void (* aiot_ntp_recv_handler_t)(void *handle,
83         const aiot_ntp_recv_t *packet, void *userdata);
84 
85 /**
86  * @brief ntp内部事件类型
87  */
88 typedef enum {
89     /**
90      * @brief 收到的ntp应答中字段不合法
91      */
92     AIOT_NTPEVT_INVALID_RESPONSE,
93     /**
94      * @brief 收到的ntp应答中时间字段格式错误
95      */
96     AIOT_NTPEVT_INVALID_TIME_FORMAT,
97 } aiot_ntp_event_type_t;
98 
99 /**
100  * @brief NTP内部事件
101  */
102 typedef struct {
103     /**
104      * @brief NTP内部事件类型. 更多信息请参考@ref aiot_ntp_event_type_t
105      *
106      */
107     aiot_ntp_event_type_t type;
108 } aiot_ntp_event_t;
109 
110 /**
111  * @brief ntp事件回调函数
112  *
113  * @details
114  *
115  * 当NTP内部事件被触发时, 调用此函数
116  *
117  */
118 typedef void (*aiot_ntp_event_handler_t)(void *handle, const aiot_ntp_event_t *event, void *userdata);
119 
120 /**
121  * @brief @ref aiot_ntp_setopt 接口的option参数可选值.
122  *
123  * @details 下文每个选项中的数据类型, 指的是@ref aiot_ntp_setopt 中, data参数的数据类型
124  *
125  * 1. data的数据类型是char *时, 以配置@ref AIOT_NTPOPT_MQTT_HANDLE 为例:
126  *
127  *    void *mqtt_handle = aiot_mqtt_init();
128  *    aiot_ntp_setopt(ntp_handle, AIOT_NTPOPT_MQTT_HANDLE, mqtt_handle);
129  *
130  * 2. data的数据类型是其他数据类型时, 以配置@ref AIOT_NTPOPT_TIME_ZONE 为例:
131  *
132  *    int8_t time_zone = 8;
133  *    aiot_mqtt_setopt(ntp_handle, AIOT_NTPOPT_TIME_ZONE, (void *)&time_zone);
134  */
135 typedef enum {
136     /**
137      * @brief ntp会话 需要的MQTT句柄, 需要先建立MQTT连接, 再设置MQTT句柄
138      *
139      * @details
140      *
141      * 数据类型: (void *)
142      */
143     AIOT_NTPOPT_MQTT_HANDLE,
144 
145     /**
146      * @brief ntp会话 获取到utc时间后会根据此时区值转换成本地时间, 再通过 @ref aiot_ntp_recv_handler_t 通知
147      *
148      * @details
149      *
150      * 取值示例: 东8区, 取值为8; 西3区, 取值为-3
151      *
152      * 数据类型: (int8_t *)
153      */
154     AIOT_NTPOPT_TIME_ZONE,
155 
156     /**
157      * @brief 设置回调, 它在SDK收到网络报文的时候被调用, 告知用户
158      *
159      * @details
160      *
161      * 数据类型: ( @ref aiot_ntp_recv_handler_t )
162      */
163     AIOT_NTPOPT_RECV_HANDLER,
164 
165     /**
166      * @brief ntp内部发生的事件会从此回调函数进行通知
167      *
168      * @details
169      *
170      * 数据类型: ( @ref aiot_ntp_event_handler_t )
171      */
172     AIOT_NTPOPT_EVENT_HANDLER,
173 
174     /**
175      * @brief 用户需要SDK暂存的上下文
176      *
177      * @details 这个上下文指针会在 AIOT_NTPOPT_RECV_HANDLER 和 AIOT_NTPOPT_EVENT_HANDLER 设置的回调被调用时, 由SDK传给用户
178      *
179      * 数据类型: (void *)
180      */
181     AIOT_NTPOPT_USERDATA,
182 
183     /**
184      * @brief 销毁ntp实例时, 等待其他api执行完毕的时间
185      *
186      * @details
187      *
188      * 当调用@ref aiot_ntp_deinit 销毁NTP实例时, 若继续调用其他aiot_ntp_xxx API, API会返回@ref STATE_USER_INPUT_EXEC_DISABLED 错误
189      *
190      * 此时, 用户应该停止调用其他aiot_ntp_xxx API
191      *
192      * 数据类型: (uint32_t *) 默认值: (2 * 1000) ms
193      */
194     AIOT_NTPOPT_DEINIT_TIMEOUT_MS,
195     AIOT_NTPOPT_MAX
196 } aiot_ntp_option_t;
197 
198 /**
199  * @brief 创建ntp会话实例, 并以默认值配置会话参数
200  *
201  * @return void *
202  * @retval 非NULL ntp实例的句柄
203  * @retval NULL   初始化失败, 一般是内存分配失败导致
204  *
205  */
206 void *aiot_ntp_init(void);
207 
208 /**
209  * @brief 配置ntp会话
210  *
211  * @details
212  *
213  * 常见的配置项如下
214  *
215  * + `AIOT_NTPOPT_MQTT_HANDLE`: 已建立连接的MQTT会话句柄
216  *
217  * + `AIOT_NTPOPT_TIME_ZONE`: 时区设置, SDK会将收到的UTC时间按配置的时区进行转换
218  *
219  * + `AIOT_NTPOPT_RECV_HANDLER`: 时间数据接收回调函数, SDK将UTC时间转换完成后, 通过此回调函数输出
220  *
221  * @param[in] handle ntp会话句柄
222  * @param[in] option 配置选项, 更多信息请参考@ref aiot_ntp_option_t
223  * @param[in] data   配置选项数据, 更多信息请参考@ref aiot_ntp_option_t
224  *
225  * @return int32_t
226  * @retval <STATE_SUCCESS  参数配置失败
227  * @retval >=STATE_SUCCESS 参数配置成功
228  *
229  */
230 int32_t aiot_ntp_setopt(void *handle, aiot_ntp_option_t option, void *data);
231 
232 /**
233  * @brief 结束ntp会话, 销毁实例并回收资源
234  *
235  * @param[in] handle 指向ntp会话句柄的指针
236  *
237  * @return int32_t
238  * @retval <STATE_SUCCESS  执行失败
239  * @retval >=STATE_SUCCESS 执行成功
240  *
241  */
242 int32_t aiot_ntp_deinit(void **handle);
243 
244 /**
245  * @brief 向ntp服务器发送ntp消息请求
246  *
247  * @details
248  *
249  * 发送NTP请求, 然后SDK会调用通过 @ref aiot_ntp_setopt 配置的 @ref AIOT_NTPOPT_RECV_HANDLER 回调函数, 通知用户当前的时间
250  *
251  * @param handle ntp会话句柄
252  *
253  * @return int32_t
254  * @retval <STATE_SUCCESS  请求发送失败
255  * @retval >=STATE_SUCCESS 请求发送成功
256  */
257 int32_t aiot_ntp_send_request(void *handle);
258 
259 #if defined(__cplusplus)
260 }
261 #endif
262 
263 #endif  /* __AIOT_NTP_API_H__ */
264 
265