1 /*
2 * Copyright (C) 2015-2018 Alibaba Group Holding Limited
3 */
4 #include "iotx_dm_internal.h"
5
6 #ifdef DEPRECATED_LINKKIT
7
8 #include "linkkit/infra/infra_json_parser.h"
9 #include "linkkit/mqtt_api.h"
10 #include "impl_ntp.h"
11
12 #if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
13 extern "C" {
14 #endif
15
16 #ifdef INFRA_MEM_STATS
17 #include "linkkit/infra/infra_mem_stats.h"
18 #define IMPL_NTP_MALLOC(size) LITE_malloc(size, MEM_MAGIC, "impl.ntp")
19 #define IMPL_NTP_FREE(ptr) LITE_free(ptr)
20 #else
21 #define IMPL_NTP_MALLOC(size) HAL_Malloc(size)
22 #define IMPL_NTP_FREE(ptr) \
23 { \
24 HAL_Free((void *)ptr); \
25 ptr = NULL; \
26 }
27 #endif
28
29 typedef void (*ntp_reply_cb_t)(const char *);
30 static ntp_reply_cb_t g_ntp_reply_cb = NULL;
31 static char g_ntp_time[NTP_TIME_STR_MAX_LEN + 1] = { 0 };
32
linkkit_ntp_time_reply(void * pcontext,void * pclient,void * mesg)33 static void linkkit_ntp_time_reply(void *pcontext, void *pclient, void *mesg)
34 {
35 #define DEV_TX_TIME "deviceSendTime"
36 #define SERVER_RX_TIME "serverRecvTime"
37 #define SERVER_TX_TIME "serverSendTime"
38
39 int len = 0;
40 char *elem = NULL;
41 char server_rx_time[NTP_TIME_STR_MAX_LEN + 1] = { 0 };
42 char server_tx_time[NTP_TIME_STR_MAX_LEN + 1] = { 0 };
43 uint32_t payload_len;
44 char *payload;
45 uint32_t tx = 0;
46 uint32_t rx = 0;
47 uint32_t diff = 0;
48
49 iotx_mqtt_event_msg_pt msg = (iotx_mqtt_event_msg_pt)mesg;
50 iotx_mqtt_topic_info_pt ptopic_info = (iotx_mqtt_topic_info_pt)msg->msg;
51
52 switch (msg->event_type) {
53 case IOTX_MQTT_EVENT_PUBLISH_RECEIVED:
54 payload_len = ptopic_info->payload_len;
55 payload = (char *)ptopic_info->payload;
56 break;
57 default:
58 goto NTP_FAIL;
59 }
60
61 if (payload == NULL || payload_len == 0) {
62 goto NTP_FAIL;
63 }
64
65 memset(g_ntp_time, 0, sizeof(g_ntp_time));
66 log_debug("[ntp]", "ntp reply len:%u, payload:%s\r\n", payload_len,
67 payload);
68
69 /*
70 * get deviceSendTime, serverRecvTime, serverSendTime
71 */
72 elem = json_get_value_by_name(payload, payload_len, SERVER_TX_TIME, &len,
73 NULL);
74 if (elem == NULL || len <= 0 || len > NTP_TIME_STR_MAX_LEN) {
75 goto NTP_FAIL;
76 }
77
78 memcpy(server_tx_time, elem, len);
79
80 elem = json_get_value_by_name(payload, payload_len, SERVER_RX_TIME, &len,
81 NULL);
82 if (elem == NULL || len <= 0 || len > NTP_TIME_STR_MAX_LEN) {
83 goto NTP_FAIL;
84 }
85
86 memcpy(server_rx_time, elem, len);
87
88 elem =
89 json_get_value_by_name(payload, payload_len, DEV_TX_TIME, &len, NULL);
90 if (elem == NULL || len <= 0 || len > NTP_TIME_STR_MAX_LEN) {
91 goto NTP_FAIL;
92 }
93 /*
94 * atoi fails to convert string to integer
95 * so we convert manully
96 */
97 while (len-- > 0) {
98 tx *= 10;
99 tx += elem[0] - '0';
100 elem++;
101 }
102 rx = HAL_UptimeMs();
103 diff = (rx - tx) >> 1;
104 if (diff >= 1000000) {
105 goto NTP_FAIL;
106 }
107
108 len = strlen(server_tx_time);
109 elem = &server_tx_time[len > 9 ? len - 9 : 0];
110 tx = atoi(elem);
111 tx += diff;
112
113 if (tx > 999999999) {
114 tx = 999999999;
115 }
116
117 if (len > 9) {
118 sprintf(elem, "%09u", (unsigned int)tx);
119 } else {
120 sprintf(elem, "%u", (unsigned int)tx);
121 }
122
123 strncpy(g_ntp_time, (const char *)server_tx_time, sizeof(g_ntp_time) - 1);
124
125 NTP_FAIL:
126 if (g_ntp_reply_cb != NULL) {
127 g_ntp_reply_cb(g_ntp_time);
128 }
129 return;
130 }
131
linkkit_ntp_time_request(void (* ntp_reply)(const char * ntp_offset_time_ms))132 int linkkit_ntp_time_request(void (*ntp_reply)(const char *ntp_offset_time_ms))
133 {
134 int ret = -1;
135 int final_len = 0;
136 int packet_len = 64;
137 int topic_len = 128;
138 char *packet = NULL;
139 char *topic = NULL;
140
141 do {
142 char pk[IOTX_PRODUCT_KEY_LEN + 1] = { 0 };
143 char dn[IOTX_DEVICE_NAME_LEN + 1] = { 0 };
144
145 HAL_GetProductKey(pk);
146 HAL_GetDeviceName(dn);
147
148 topic = (char *)IMPL_NTP_MALLOC(topic_len + 1);
149 if (topic == NULL) {
150 goto NTP_REQ_ERR;
151 }
152 memset(topic, 0, topic_len + 1);
153
154 HAL_Snprintf(topic, topic_len, TOPIC_NTP_REPLY, pk, dn);
155 #ifdef MQTT_AUTO_SUBSCRIBE
156 ret = IOT_MQTT_Subscribe_Sync(
157 NULL, topic, IOTX_MQTT_QOS3_SUB_LOCAL,
158 (iotx_mqtt_event_handle_func_fpt)linkkit_ntp_time_reply, NULL,
159 1000);
160 #else
161 ret = IOT_MQTT_Subscribe_Sync(
162 NULL, topic, IOTX_MQTT_QOS0,
163 (iotx_mqtt_event_handle_func_fpt)linkkit_ntp_time_reply, NULL,
164 1000);
165 #endif
166 if (ret < 0) {
167 goto NTP_REQ_ERR;
168 }
169
170 memset(topic, 0, topic_len + 1);
171 HAL_Snprintf(topic, topic_len, TOPIC_NTP, pk, dn);
172 } while (0);
173
174 packet = (char *)IMPL_NTP_MALLOC(packet_len + 1);
175 if (packet == NULL) {
176 ret = -1;
177 goto NTP_REQ_ERR;
178 }
179 memset(packet, 0, packet_len + 1);
180
181 g_ntp_reply_cb = ntp_reply;
182 final_len = HAL_Snprintf(packet, packet_len, "{\"deviceSendTime\":\"%u\"}",
183 (unsigned int)(HAL_UptimeMs()));
184
185 log_debug("[ntp]", "report ntp:%s\r\n", packet);
186
187 ret =
188 IOT_MQTT_Publish_Simple(NULL, topic, IOTX_MQTT_QOS0, packet, final_len);
189
190 NTP_REQ_ERR:
191 if (topic) {
192 IMPL_NTP_FREE(topic);
193 }
194 if (packet) {
195 IMPL_NTP_FREE(packet);
196 }
197 return ret;
198 }
199
200 #if defined(__cplusplus) /* If this is a C++ compiler, use C linkage */
201 }
202 #endif
203 #endif
204
205