luat_lib_sntp.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233
  1. /*
  2. @module socket
  3. @summary 网络接口
  4. @version 1.0
  5. @date 2022.11.13
  6. */
  7. #include "luat_base.h"
  8. #include "luat_network_adapter.h"
  9. #include "luat_rtos.h"
  10. #include "luat_msgbus.h"
  11. #include "luat_mcu.h"
  12. #include "luat_mem.h"
  13. #include "luat_rtc.h"
  14. #include "luat_sntp.h"
  15. #define LUAT_LOG_TAG "sntp"
  16. #include "luat_log.h"
  17. #define SNTP_SERVER_COUNT 3
  18. #define SNTP_SERVER_LEN_MAX 32
  19. #define NTP_UPDATE 1
  20. #define NTP_ERROR 2
  21. #define NTP_TIMEOUT 3
  22. extern sntp_ctx_t g_sntp_ctx;
  23. extern char* sntp_servers[];
  24. int luat_ntp_on_result(network_ctrl_t *sntp_netc, int result);
  25. int l_sntp_event_handle(lua_State* L, void* ptr) {
  26. (void)ptr;
  27. rtos_msg_t* msg = (rtos_msg_t*)lua_topointer(L, -1);
  28. // 清理现场
  29. if (msg->arg1 == NTP_TIMEOUT) {
  30. luat_ntp_on_result(g_sntp_ctx.ctrl, NTP_ERROR);
  31. return 0;
  32. }
  33. ntp_cleanup();
  34. if (lua_getglobal(L, "sys_pub") != LUA_TFUNCTION) {
  35. return 0;
  36. };
  37. switch (msg->arg1)
  38. {
  39. /*
  40. @sys_pub socket
  41. 时间已经同步
  42. NTP_UPDATE
  43. @usage
  44. sys.subscribe("NTP_UPDATE", function()
  45. log.info("socket", "sntp", os.date())
  46. end)
  47. */
  48. case NTP_UPDATE:
  49. lua_pushstring(L, "NTP_UPDATE");
  50. lua_pushinteger(L, 0); // 0代表通过socket.sntp同步的
  51. lua_call(L, 2, 0);
  52. return 0;
  53. /*
  54. @sys_pub socket
  55. 时间同步失败
  56. NTP_ERROR
  57. @usage
  58. sys.subscribe("NTP_ERROR", function()
  59. log.info("socket", "sntp error")
  60. end)
  61. */
  62. case NTP_ERROR:
  63. lua_pushstring(L, "NTP_ERROR");
  64. break;
  65. }
  66. lua_call(L, 1, 0);
  67. return 0;
  68. }
  69. /*
  70. sntp时间同步
  71. @api socket.sntp(sntp_server, adapter)
  72. @tag LUAT_USE_SNTP
  73. @string/table sntp服务器地址 选填
  74. @int 适配器序号,请参考socket库的常量表
  75. @usage
  76. socket.sntp()
  77. --socket.sntp("ntp.aliyun.com") --自定义sntp服务器地址
  78. --socket.sntp({"ntp.aliyun.com","ntp1.aliyun.com","ntp2.aliyun.com"}) --sntp自定义服务器地址
  79. --socket.sntp(nil, socket.ETH0) --sntp自定义适配器序号
  80. sys.subscribe("NTP_UPDATE", function()
  81. log.info("sntp", "time", os.date())
  82. end)
  83. sys.subscribe("NTP_ERROR", function()
  84. log.info("socket", "sntp error")
  85. socket.sntp()
  86. end)
  87. */
  88. int l_sntp_get(lua_State *L) {
  89. size_t len = 0;
  90. if (lua_isstring(L, 1)){
  91. const char * server_addr = luaL_checklstring(L, 1, &len);
  92. if (len < SNTP_SERVER_LEN_MAX - 1){
  93. memcpy(sntp_servers[0], server_addr, len + 1);
  94. }
  95. else if (len < 5) {
  96. LLOGE("server_addr too short %s", server_addr);
  97. return 0;
  98. }
  99. else{
  100. LLOGE("server_addr too long %s", server_addr);
  101. return 0;
  102. }
  103. }else if(lua_istable(L, 1)){
  104. size_t count = lua_rawlen(L, 1);
  105. if (count > SNTP_SERVER_COUNT){
  106. count = SNTP_SERVER_COUNT;
  107. }
  108. for (size_t i = 1; i <= count; i++){
  109. lua_geti(L, 1, i);
  110. const char * server_addr = luaL_checklstring(L, -1, &len);
  111. if (len < SNTP_SERVER_LEN_MAX - 1){
  112. memcpy(sntp_servers[i-1], server_addr, len + 1);
  113. }else{
  114. LLOGE("server_addr too long %s", server_addr);
  115. }
  116. lua_pop(L, 1);
  117. }
  118. }
  119. if (g_sntp_ctx.is_running) {
  120. LLOGI("sntp is running");
  121. return 0;
  122. }
  123. int adapter_index = luaL_optinteger(L, 2, network_register_get_default());
  124. int ret = ntp_get(adapter_index);
  125. if (ret) {
  126. #ifdef __LUATOS__
  127. rtos_msg_t msg;
  128. msg.handler = l_sntp_event_handle;
  129. msg.arg1 = NTP_ERROR;
  130. luat_msgbus_put(&msg, 0);
  131. #else
  132. ntp_cleanup();
  133. #endif
  134. }
  135. return 0;
  136. }
  137. /*
  138. 网络对时后的时间戳(ms级别)
  139. @api socket.ntptm()
  140. @return table 包含时间信息的数据
  141. @usage
  142. -- 本API于 2023.11.15 新增
  143. -- 注意, 本函数在执行socket.sntp()且获取到NTP时间后才有效
  144. -- 而且是2次sntp之后才是比较准确的值
  145. -- 网络波动越小, 该时间戳越稳定
  146. local tm = socket.ntptm()
  147. -- 对应的table包含多个数据, 均为整数值
  148. -- 标准数据
  149. -- tsec 当前秒数,从1900.1.1 0:0:0 开始算, UTC时间
  150. -- tms 当前毫秒数
  151. -- vaild 是否有效, true 或者 nil
  152. -- 调试数据, 调试用,一般用户不用管
  153. -- ndelay 网络延时平均值,单位毫秒
  154. -- ssec 系统启动时刻与1900.1.1 0:0:0的秒数偏移量
  155. -- sms 系统启动时刻与1900.1.1 0:0:0的毫秒偏移量
  156. -- lsec 本地秒数计数器,基于mcu.tick64()
  157. -- lms 本地毫秒数计数器,基于mcu.tick64()
  158. log.info("tm数据", json.encode(tm))
  159. log.info("时间戳", string.format("%u.%03d", tm.tsec, tm.tms))
  160. */
  161. int l_sntp_tm(lua_State *L) {
  162. lua_newtable(L);
  163. lua_pushinteger(L, g_sntp_ctx.network_delay_ms);
  164. lua_setfield(L, -2, "ndeley");
  165. lua_pushinteger(L, g_sntp_ctx.sysboot_diff_sec);
  166. lua_setfield(L, -2, "ssec");
  167. lua_pushinteger(L, g_sntp_ctx.sysboot_diff_ms);
  168. lua_setfield(L, -2, "sms");
  169. uint64_t tick64 = luat_mcu_tick64();
  170. uint32_t us_period = luat_mcu_us_period();
  171. uint64_t ll_sec = tick64 /us_period/ 1000 / 1000;
  172. uint64_t ll_ms = (tick64 /us_period/ 1000) % 1000;
  173. uint64_t tmp = ll_sec + g_sntp_ctx.sysboot_diff_sec;
  174. tmp *= 1000;
  175. tmp += ll_ms + g_sntp_ctx.sysboot_diff_ms;
  176. uint64_t tsec = tmp / 1000;
  177. uint64_t tms = (tmp % 1000) & 0xFFFF;
  178. lua_pushinteger(L, tsec);
  179. lua_setfield(L, -2, "tsec");
  180. lua_pushinteger(L, tms);
  181. lua_setfield(L, -2, "tms");
  182. lua_pushinteger(L, ll_sec);
  183. lua_setfield(L, -2, "lsec");
  184. lua_pushinteger(L, ll_ms);
  185. lua_setfield(L, -2, "lms");
  186. if (g_sntp_ctx.sysboot_diff_sec > 0) {
  187. lua_pushboolean(L, 1);
  188. lua_setfield(L, -2, "vaild");
  189. }
  190. return 1;
  191. }
  192. /*
  193. 设置SNTP服务器的端口号
  194. @api socket.sntp_port(port)
  195. @int port 端口号, 默认123
  196. @return int 返回当前的端口号
  197. @usage
  198. -- 本函数于2024.5.17新增
  199. -- 大部分情况下不需要设置NTP服务器的端口号,默认123即可
  200. */
  201. int l_sntp_port(lua_State *L) {
  202. if (lua_type(L, 1) == LUA_TNUMBER){
  203. uint16_t port = (uint16_t)luaL_checkinteger(L, 1);
  204. if (port > 0){
  205. g_sntp_ctx.port = port;
  206. }
  207. }
  208. lua_pushinteger(L, g_sntp_ctx.port ? g_sntp_ctx.port : 123);
  209. return 1;
  210. }