luat_sntp.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. #include "luat_base.h"
  2. #include "luat_network_adapter.h"
  3. #include "luat_rtos.h"
  4. #include "luat_msgbus.h"
  5. #include "luat_mcu.h"
  6. #include "luat_mem.h"
  7. #include "luat_rtc.h"
  8. #include "luat_sntp.h"
  9. #define LUAT_LOG_TAG "sntp"
  10. #include "luat_log.h"
  11. // 这里使用SNTP协议,非NTP协议,所以不需要传递本地时间戳
  12. // static const uint8_t sntp_packet[48]={0x1b};
  13. static char ntp1 [SNTP_SERVER_LEN_MAX] = "ntp.aliyun.com";
  14. static char ntp2 [SNTP_SERVER_LEN_MAX] = "ntp.ntsc.ac.cn";
  15. static char ntp3 [SNTP_SERVER_LEN_MAX] = "time1.cloud.tencent.com";
  16. char* sntp_servers[SNTP_SERVER_COUNT] = {
  17. ntp1, ntp2, ntp3
  18. };
  19. sntp_ctx_t g_sntp_ctx;
  20. int luat_ntp_on_result(network_ctrl_t *sntp_netc, int result);
  21. #ifdef __LUATOS__
  22. int l_sntp_event_handle(lua_State* L, void* ptr);
  23. #endif
  24. void ntp_cleanup(void) {
  25. g_sntp_ctx.is_running = 0;
  26. if (g_sntp_ctx.timer != NULL) {
  27. luat_rtos_timer_stop(g_sntp_ctx.timer);
  28. luat_rtos_timer_delete(g_sntp_ctx.timer);
  29. g_sntp_ctx.timer = NULL;
  30. }
  31. g_sntp_ctx.timer_running = 0;
  32. if (g_sntp_ctx.ctrl != NULL) {
  33. network_force_close_socket(g_sntp_ctx.ctrl);
  34. network_release_ctrl(g_sntp_ctx.ctrl);
  35. g_sntp_ctx.ctrl = NULL;
  36. }
  37. g_sntp_ctx.next_server_index = 0;
  38. }
  39. void ntp_timeout_cb(LUAT_RT_CB_PARAM) {
  40. (void)param;
  41. // LLOGD("ntp_timeout_cb");
  42. if (g_sntp_ctx.is_running && g_sntp_ctx.ctrl != NULL) {
  43. g_sntp_ctx.timer_running = 0;
  44. LLOGW("timeout send ntp_error");
  45. #ifdef __LUATOS__
  46. rtos_msg_t msg = {0};
  47. msg.handler = l_sntp_event_handle;
  48. msg.arg1 = NTP_TIMEOUT;
  49. luat_msgbus_put(&msg, 0);
  50. #else
  51. ntp_cleanup();
  52. #endif
  53. }
  54. }
  55. int luat_sntp_connect(network_ctrl_t *sntp_netc){
  56. int ret = 0;
  57. if (g_sntp_ctx.next_server_index >= SNTP_SERVER_COUNT) {
  58. return -1;
  59. }
  60. char* host = sntp_servers[g_sntp_ctx.next_server_index];
  61. g_sntp_ctx.next_server_index++;
  62. LLOGD("query %s", host);
  63. ret = network_connect(sntp_netc, host, strlen(host), NULL, g_sntp_ctx.port ? g_sntp_ctx.port : 123, 1000);
  64. if (ret < 0) {
  65. LLOGD("network_connect ret %d", ret);
  66. return -1;
  67. }
  68. ret = luat_rtos_timer_start(g_sntp_ctx.timer, NTP_TIMEOUT_MS, 0, ntp_timeout_cb, NULL);
  69. // LLOGD("启动 timer %d %s", ret, host);
  70. if (ret == 0) {
  71. g_sntp_ctx.timer_running = 1;
  72. }
  73. return ret;
  74. }
  75. int luat_ntp_on_result(network_ctrl_t *sntp_netc, int result) {
  76. #ifdef __LUATOS__
  77. rtos_msg_t msg = {0};
  78. #endif
  79. if (result == NTP_UPDATE) {
  80. #ifdef __LUATOS__
  81. msg.handler = l_sntp_event_handle;
  82. msg.arg1 = result;
  83. luat_msgbus_put(&msg, 0);
  84. #else
  85. ntp_cleanup();
  86. #endif
  87. return 0;
  88. }
  89. if (g_sntp_ctx.next_server_index < SNTP_SERVER_COUNT) {
  90. // 没有成功, 继续下一个
  91. if (g_sntp_ctx.next_server_index) {
  92. network_force_close_socket(sntp_netc);
  93. }
  94. if (g_sntp_ctx.timer_running) {
  95. LLOGD("timer在运行, 关闭之");
  96. luat_rtos_timer_stop(g_sntp_ctx.timer);
  97. g_sntp_ctx.timer_running = 0;
  98. }
  99. LLOGD("前一个ntp服务器未响应,尝试下一个");
  100. int ret = luat_sntp_connect(sntp_netc);
  101. if (ret == 0) {
  102. // 没问题, 可以继续下一个了
  103. return 0;
  104. }
  105. LLOGD("luat_sntp_connect %d", ret);
  106. }
  107. // 没救了,通知清理吧
  108. #ifdef __LUATOS__
  109. msg.handler = l_sntp_event_handle;
  110. msg.arg1 = result;
  111. luat_msgbus_put(&msg, 0);
  112. #else
  113. ntp_cleanup();
  114. #endif
  115. return 0;
  116. }
  117. static uint32_t ntptime2u32(const uint8_t* p, int plus) {
  118. if (plus && p[0] == 0 && p[1] == 0 && p[2] == 0 && p[3] == 0) {
  119. return 0;
  120. }
  121. // LLOGDUMP(p, 4);
  122. uint32_t t = ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | (uint32_t)p[3];
  123. if (plus == 0) {
  124. return t / 4295;
  125. }
  126. if (plus == 2) {
  127. return t;
  128. }
  129. if (t > 0x83AA7E80){
  130. t -= 0x83AA7E80;
  131. }else{
  132. t += 0x7C558180;
  133. }
  134. return t;
  135. }
  136. int32_t luat_sntp_callback(void *data, void *param) {
  137. OS_EVENT *event = (OS_EVENT *)data;
  138. network_ctrl_t *sntp_netc =(network_ctrl_t *)param;
  139. int ret = 0;
  140. uint32_t tx_len = 0;
  141. sntp_msg_t smsg = {0};
  142. // LLOGD("LINK %08X ON_LINE %08X EVENT %08X TX_OK %08X CLOSED %08X",EV_NW_RESULT_LINK & 0x0fffffff,EV_NW_RESULT_CONNECT & 0x0fffffff,EV_NW_RESULT_EVENT & 0x0fffffff,EV_NW_RESULT_TX & 0x0fffffff,EV_NW_RESULT_CLOSE & 0x0fffffff);
  143. if (g_sntp_ctx.is_running == 0) {
  144. // LLOGD("已经查询完了, 为啥还有回调 %08X", event->ID);
  145. return 0;
  146. }
  147. // LLOGD("network sntp cb %8X %s %8X",event->ID & 0x0ffffffff, event2str(event->ID & 0x0ffffffff) ,event->Param1);
  148. // LLOGD("luat_sntp_callback %08X", event->ID);
  149. if (event->ID == EV_NW_RESULT_LINK){
  150. return 0; // 这里应该直接返回, 不能往下调用network_wait_event
  151. }else if(event->ID == EV_NW_RESULT_CONNECT){
  152. memset(&smsg, 0, sizeof(smsg));
  153. smsg.li_vn_mode = 0x1B;
  154. if (g_sntp_ctx.sysboot_diff_sec > 0) {
  155. uint64_t tick64 = luat_mcu_tick64() / luat_mcu_us_period();
  156. uint64_t ll_sec = (uint32_t)(tick64 / 1000 / 1000);
  157. uint64_t ll_ms = (uint32_t)((tick64 / 1000) % 1000);
  158. uint64_t rt_ms = g_sntp_ctx.sysboot_diff_sec + ll_sec;
  159. rt_ms *= 1000;
  160. rt_ms += g_sntp_ctx.sysboot_diff_ms + ll_ms + g_sntp_ctx.network_delay_ms;
  161. uint64_t rt_sec = (rt_ms / 1000) - 0x7C558180;
  162. uint64_t rt_us = ((rt_ms % 1000) & 0xFFFFFFFF) * 1000;
  163. uint64_t rt_ush = rt_us * 4295; // 1/2us为单位
  164. uint8_t* ptr = (uint8_t*)smsg.transmit_timestamp;
  165. ptr[0] = (rt_sec >> 24) & 0xFF;
  166. ptr[1] = (rt_sec >> 16) & 0xFF;
  167. ptr[2] = (rt_sec >> 8) & 0xFF;
  168. ptr[3] = (rt_sec >> 0) & 0xFF;
  169. ptr[4] = (rt_ush >> 24) & 0xFF;
  170. ptr[5] = (rt_ush >> 16) & 0xFF;
  171. ptr[6] = (rt_ush >> 8) & 0xFF;
  172. ptr[7] = (rt_ush >> 0) & 0xFF;
  173. }
  174. ret = network_tx(sntp_netc, (const uint8_t*)&smsg, sizeof(smsg), 0, NULL, 0, &tx_len, 0);
  175. // LLOGD("network_tx %d", ret);
  176. if (tx_len != sizeof(smsg)) {
  177. LLOGI("请求包传输失败!!");
  178. luat_ntp_on_result(sntp_netc, NTP_ERROR);
  179. return -1;
  180. }
  181. // LLOGD("luat_sntp_callback tx_len:%d",tx_len);
  182. }else if(event->ID == EV_NW_RESULT_EVENT){
  183. uint32_t rx_len = 0;
  184. // uint8_t resp_buff[64] = {0};
  185. // 本地时间tick,尽早生成
  186. uint64_t tick64 = luat_mcu_tick64() / luat_mcu_us_period();
  187. uint32_t ll_sec = (uint32_t)(tick64 / 1000 / 1000);
  188. uint32_t ll_ms = (uint32_t)((tick64 / 1000) % 1000);
  189. int result = network_rx(sntp_netc, (uint8_t*)&smsg, sizeof(smsg), 0, NULL, NULL, &rx_len);
  190. if (result == 0 && rx_len >= NTP_RESP_SIZE) {
  191. const uint8_t *p = ((const uint8_t *)&smsg)+40;
  192. // LLOGD("reference_timestamp %d %08u", ntptime2u32((uint8_t*)&smsg.reference_timestamp[0], 1), ntptime2u32((uint8_t*)&smsg.reference_timestamp[1], 0));
  193. // LLOGD("originate_timestamp %d %06u", ntptime2u32((uint8_t*)&smsg.originate_timestamp[0], 1), ntptime2u32((uint8_t*)&smsg.originate_timestamp[1], 0));
  194. // LLOGD("receive_timestamp %d %06u", ntptime2u32((uint8_t*)&smsg.receive_timestamp[0], 1), ntptime2u32((uint8_t*)&smsg.receive_timestamp[1], 0));
  195. // LLOGD("transmit_timestamp %d %06u", ntptime2u32((uint8_t*)&smsg.transmit_timestamp[0], 1), ntptime2u32((uint8_t*)&smsg.transmit_timestamp[1], 0));
  196. // uint32_t time = ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) | ((uint32_t)p[2] << 8) | (uint32_t)p[3];
  197. uint32_t time = ntptime2u32(p, 1);
  198. luat_rtc_set_tamp32(time);
  199. // 计算误差
  200. // 参考时间戳reference_timestamp == rft
  201. // uint32_t rft_sec = ntptime2u32((uint8_t*)&smsg.reference_timestamp[0], 1);
  202. // uint32_t rft_us = ntptime2u32((uint8_t*)&smsg.reference_timestamp[1], 0);
  203. // uint32_t rft_ms = (uint32_t)((rft_us / 1000));
  204. // uint32_t rft_ms = ((((uint64_t)rft_us) * 1000L * 1000L) >> 32 & 0xFFFFFFFF) / 1000;
  205. // 原始时间戳originate_timestamp == ot
  206. uint32_t ot_sec = ntptime2u32((uint8_t*)&smsg.originate_timestamp[0], 1);
  207. uint32_t ot_us = ntptime2u32((uint8_t*)&smsg.originate_timestamp[1], 0);
  208. uint32_t ot_ms = (uint32_t)((ot_us / 1000));
  209. uint64_t ot_tt = ((uint64_t)ot_sec) * 1000 + ot_ms;
  210. // uint32_t ot_ms = ((((uint64_t)ot_us) * 1000L * 1000L) >> 32 & 0xFFFFFFFF) / 1000;
  211. // 服务器接收时间戳receive_timestamp == rt
  212. uint32_t rt_sec = ntptime2u32((uint8_t*)&smsg.receive_timestamp[0], 1);
  213. uint32_t rt_us = ntptime2u32((uint8_t*)&smsg.receive_timestamp[1], 0);
  214. uint32_t rt_ms = (uint32_t)((rt_us / 1000));
  215. uint64_t rt_tt = ((uint64_t)rt_sec) * 1000 + rt_ms;
  216. // uint32_t rt_ms = ((((uint64_t)rt_us) * 1000L * 1000L) >> 32 & 0xFFFFFFFF) / 1000;
  217. // 服务响应时间戳transmit_timestamp == tt
  218. uint32_t tt_sec = ntptime2u32((uint8_t*)&smsg.transmit_timestamp[0], 1);
  219. uint32_t tt_us = ntptime2u32((uint8_t*)&smsg.transmit_timestamp[1], 0);
  220. uint32_t tt_ms = (uint32_t)((tt_us / 1000));
  221. uint64_t tt_tt = ((uint64_t)tt_sec) * 1000 + tt_ms;
  222. // uint32_t tt_ms = ((((uint64_t)tt_us) * 1000L * 1000L) >> 32 & 0xFFFFFFFF) / 1000;
  223. // 名义接收时间戳 mean_timestamp == mt
  224. uint64_t mt_tt = (g_sntp_ctx.sysboot_diff_sec & 0xFFFFFFFF) + ll_sec;
  225. mt_tt = mt_tt * 1000 + g_sntp_ctx.sysboot_diff_ms + ll_ms;
  226. // uint32_t mt_sec = mt_tt / 1000;
  227. // uint32_t mt_ms = (mt_tt % 1000) & 0xFFFF;
  228. // 上行耗时
  229. int64_t uplink_diff_ms = rt_tt - ot_tt;
  230. int64_t downlink_diff_ms = mt_tt - tt_tt;
  231. int32_t total_diff_ms = (int32_t)(uplink_diff_ms + downlink_diff_ms) / 2;
  232. // LLOGD("下行差值(ms) %d", downlink_diff_ms);
  233. // LLOGD("上行差值(ms) %d", uplink_diff_ms);
  234. // LLOGD("上下行平均偏差 %d 差值 %d", total_diff_ms, total_diff_ms - g_sntp_ctx.network_delay_ms);
  235. g_sntp_ctx.sysboot_diff_sec = (uint32_t)(tt_sec - ll_sec);
  236. if (tt_ms < ll_ms) {
  237. g_sntp_ctx.sysboot_diff_sec --;
  238. g_sntp_ctx.sysboot_diff_ms = ll_ms - tt_ms;
  239. }
  240. else {
  241. g_sntp_ctx.sysboot_diff_ms = tt_ms - ll_ms;
  242. }
  243. // 1. 发起传输时, 使用0时间戳, 就是第一次
  244. if (ot_sec != 0) {
  245. // 修正本地偏移量
  246. if (g_sntp_ctx.ndelay_c == 0) {
  247. g_sntp_ctx.ndelay_c = NTP_NETWORK_DELAY_CMAX;
  248. }
  249. if (g_sntp_ctx.network_delay_ms == 0) {
  250. for (size_t ik = 0; ik < NTP_NETWORK_DELAY_CMAX; ik++)
  251. {
  252. g_sntp_ctx.ndelay_array[ik] = total_diff_ms;
  253. }
  254. }
  255. else {
  256. for (uint8_t ij = 0; ij < NTP_NETWORK_DELAY_CMAX - 1; ij++)
  257. {
  258. g_sntp_ctx.ndelay_array[ij] = g_sntp_ctx.ndelay_array[ij+1];
  259. }
  260. g_sntp_ctx.ndelay_array[NTP_NETWORK_DELAY_CMAX - 1] = total_diff_ms;
  261. }
  262. // LLOGD("ndelay %d %d %d %d %d %d %d %d", ndelay_array[0], ndelay_array[1], ndelay_array[2], ndelay_array[3] , ndelay_array[4], ndelay_array[5], ndelay_array[6], ndelay_array[7]);
  263. int32_t ttt = 0;
  264. for (size_t iv = 0; iv < g_sntp_ctx.ndelay_c; iv++)
  265. {
  266. ttt += g_sntp_ctx.ndelay_array[iv];
  267. }
  268. if (ttt < 0) {
  269. ttt = 0;
  270. }
  271. LLOGD("修正网络延时(ms) %d -> %d", g_sntp_ctx.network_delay_ms, ttt / g_sntp_ctx.ndelay_c);
  272. g_sntp_ctx.network_delay_ms = ttt / g_sntp_ctx.ndelay_c;
  273. }
  274. LLOGD("Unix timestamp: %d",time);
  275. luat_ntp_on_result(sntp_netc, NTP_UPDATE);
  276. return 0;
  277. }else{
  278. LLOGI("响应包不合法 result %d rx_len %d", result, rx_len);
  279. //luat_ntp_on_result(sntp_netc, NTP_ERROR);
  280. return -1;
  281. }
  282. }else if(event->ID == EV_NW_RESULT_TX){
  283. }else if(event->ID == EV_NW_RESULT_CLOSE){
  284. // LLOGD("closed");
  285. }
  286. if (event->Param1){
  287. // LLOGW("sntp_callback param1 %d, closing socket", event->Param1);
  288. luat_ntp_on_result(sntp_netc, NTP_ERROR);
  289. return -1;
  290. }
  291. ret = network_wait_event(sntp_netc, NULL, 0, NULL);
  292. if (ret < 0){
  293. // LLOGW("network_wait_event ret %d, closing socket", ret);
  294. luat_ntp_on_result(sntp_netc, NTP_ERROR);
  295. return -1;
  296. }
  297. return 0;
  298. }
  299. int ntp_get(int adapter_index){
  300. if (-1 == adapter_index){
  301. adapter_index = network_register_get_default();
  302. }
  303. if (adapter_index < 0 || adapter_index >= NW_ADAPTER_QTY){
  304. return -1;
  305. }
  306. network_ctrl_t *sntp_netc = network_alloc_ctrl((uint8_t)adapter_index);
  307. if (!sntp_netc){
  308. LLOGE("network_alloc_ctrl fail");
  309. return -1;
  310. }
  311. network_init_ctrl(sntp_netc, NULL, luat_sntp_callback, sntp_netc);
  312. network_set_base_mode(sntp_netc, 0, 10000, 0, 0, 0, 0);
  313. network_set_local_port(sntp_netc, 0);
  314. network_deinit_tls(sntp_netc);
  315. g_sntp_ctx.ctrl = sntp_netc;
  316. g_sntp_ctx.is_running = 1;
  317. int ret = 0;
  318. ret = luat_rtos_timer_create(&g_sntp_ctx.timer);
  319. if (ret) {
  320. return ret;
  321. }
  322. ret = luat_sntp_connect(sntp_netc);
  323. if (ret) {
  324. return ret;
  325. }
  326. return ret;
  327. }
  328. uint64_t luat_sntp_time64_ms() {
  329. uint64_t tick64 = luat_mcu_tick64();
  330. uint32_t us_period = luat_mcu_us_period();
  331. uint64_t ll_sec = tick64 /us_period/ 1000 / 1000;
  332. uint64_t ll_ms = (tick64 /us_period/ 1000) % 1000;
  333. uint64_t tmp = ll_sec + g_sntp_ctx.sysboot_diff_sec;
  334. //LLOGD("ntp sec: sec=%llu, ms=%u", tmp, ll_ms);
  335. tmp *= 1000;
  336. tmp += ll_ms + g_sntp_ctx.sysboot_diff_ms;
  337. return tmp;
  338. }