main.lua 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. PROJECT = "air780e_forwarder"
  2. VERSION = "1.0.0"
  3. log.setLevel("DEBUG")
  4. log.info("main", PROJECT, VERSION)
  5. log.info("main", "开机原因", pm.lastReson())
  6. sys = require "sys"
  7. sysplus = require "sysplus"
  8. -- 添加硬狗防止程序卡死
  9. wdt.init(9000)
  10. sys.timerLoopStart(wdt.feed, 3000)
  11. -- 设置电平输出 3.3V
  12. -- pm.ioVol(pm.IOVOL_ALL_GPIO, 3300)
  13. -- 设置 DNS
  14. socket.setDNS(nil, 1, "119.29.29.29")
  15. socket.setDNS(nil, 2, "223.5.5.5")
  16. -- SIM 自动恢复, 周期性获取小区信息, 网络遇到严重故障时尝试自动恢复等功能
  17. mobile.setAuto(10000, 30000, 8, true, 60000)
  18. -- 开启 IPv6
  19. -- mobile.ipv6(true)
  20. -- 初始化 fskv
  21. log.info("main", "fskv.init", fskv.init())
  22. -- POWERKEY
  23. local rtos_bsp = rtos.bsp()
  24. local pin_table = { ["EC618"] = 35, ["EC718P"] = 46, ["EC718PV"] = 46 }
  25. local powerkey_pin = pin_table[rtos_bsp]
  26. if powerkey_pin then
  27. local button_last_press_time, button_last_release_time = 0, 0
  28. gpio.setup(powerkey_pin, function()
  29. local current_time = mcu.ticks()
  30. -- 按下
  31. if gpio.get(powerkey_pin) == 0 then
  32. button_last_press_time = current_time -- 记录最后一次按下时间
  33. return
  34. end
  35. -- 释放
  36. if button_last_press_time == 0 then -- 开机前已经按下, 开机后释放
  37. return
  38. end
  39. if current_time - button_last_release_time < 250 then -- 防止连按
  40. return
  41. end
  42. local duration = current_time - button_last_press_time -- 按键持续时间
  43. button_last_release_time = current_time -- 记录最后一次释放时间
  44. if duration > 2000 then
  45. log.debug("EVENT.POWERKEY_LONG_PRESS", duration)
  46. sys.publish("POWERKEY_LONG_PRESS", duration)
  47. elseif duration > 50 then
  48. log.debug("EVENT.POWERKEY_SHORT_PRESS", duration)
  49. sys.publish("POWERKEY_SHORT_PRESS", duration)
  50. end
  51. end, gpio.PULLUP, gpio.FALLING)
  52. end
  53. -- 加载模块
  54. config = require "config"
  55. util_http = require "util_http"
  56. util_netled = require "util_netled"
  57. util_mobile = require "util_mobile"
  58. util_location = require "util_location"
  59. util_notify = require "util_notify"
  60. -- 由于 NOTIFY_TYPE 支持多个配置, 需按照包含来判断
  61. local containsValue = function(t, value)
  62. if t == value then return true end
  63. if type(t) ~= "table" then return false end
  64. for k, v in pairs(t) do if v == value then return true end end
  65. return false
  66. end
  67. if containsValue(config.NOTIFY_TYPE, "serial") then
  68. -- 串口配置
  69. uart.setup(1, 115200, 8, 1, uart.NONE)
  70. -- 串口接收回调
  71. uart.on(1, "receive", function(id, len)
  72. local data = uart.read(id, len)
  73. log.info("uart read:", id, len, data)
  74. if config.ROLE == "MASTER" then
  75. -- 主机, 通过队列发送数据
  76. util_notify.add(data)
  77. else
  78. -- 从机, 通过串口发送数据
  79. uart.write(1, data)
  80. end
  81. end)
  82. end
  83. -- 判断一个元素是否在一个表中
  84. local function isElementInTable(myTable, target)
  85. for _, value in ipairs(myTable) do
  86. if value == target then
  87. return true
  88. end
  89. end
  90. return false
  91. end
  92. -- 判断白名单号码是否符合触发短信控制的条件
  93. local function isWhiteListNumber(sender_number)
  94. -- 判断如果未设置白名单号码, 禁止所有号码触发
  95. if type(config.SMS_CONTROL_WHITELIST_NUMBERS) ~= "table" or #config.SMS_CONTROL_WHITELIST_NUMBERS == 0 then
  96. return false
  97. end
  98. -- 已设置白名单号码, 判断是否在白名单中
  99. return isElementInTable(config.SMS_CONTROL_WHITELIST_NUMBERS, sender_number)
  100. end
  101. -- 短信接收回调
  102. sms.setNewSmsCb(function(sender_number, sms_content, m)
  103. local time = string.format("%d/%02d/%02d %02d:%02d:%02d", m.year + 2000, m.mon, m.day, m.hour, m.min, m.sec)
  104. log.info("smsCallback", time, sender_number, sms_content)
  105. -- 短信控制
  106. local is_sms_ctrl = false
  107. -- 判断发送者是否为白名单号码
  108. if isWhiteListNumber(sender_number) then
  109. local receiver_number, sms_content_to_be_sent = sms_content:match("^SMS,(+?%d+),(.+)$")
  110. receiver_number, sms_content_to_be_sent = receiver_number or "", sms_content_to_be_sent or ""
  111. if sms_content_to_be_sent ~= "" and receiver_number ~= "" and #receiver_number >= 5 and #receiver_number <= 20 then
  112. sms.send(receiver_number, sms_content_to_be_sent)
  113. is_sms_ctrl = true
  114. end
  115. end
  116. -- 发送通知
  117. util_notify.add({ sms_content, "", "发件号码: " .. sender_number, "发件时间: " .. time, "#SMS" .. (is_sms_ctrl and " #CTRL" or "") })
  118. end)
  119. sys.taskInit(function()
  120. -- 等待网络环境准备就绪
  121. sys.waitUntil("IP_READY", 1000 * 60 * 5)
  122. util_netled.init()
  123. -- 开机通知
  124. if config.BOOT_NOTIFY then
  125. sys.timerStart(util_notify.add, 1000 * 5, "#BOOT_" .. pm.lastReson())
  126. end
  127. -- 定时同步时间
  128. if os.time() < 1714500000 then
  129. socket.sntp()
  130. end
  131. if type(config.SNTP_INTERVAL) == "number" and config.SNTP_INTERVAL >= 1000 * 60 then
  132. sys.timerLoopStart(socket.sntp, config.SNTP_INTERVAL)
  133. end
  134. -- 定时查询流量
  135. if type(config.QUERY_TRAFFIC_INTERVAL) == "number" and config.QUERY_TRAFFIC_INTERVAL >= 1000 * 60 then
  136. sys.timerLoopStart(util_mobile.queryTraffic, config.QUERY_TRAFFIC_INTERVAL)
  137. end
  138. -- 定时基站定位
  139. if type(config.LOCATION_INTERVAL) == "number" and config.LOCATION_INTERVAL >= 1000 * 60 then
  140. util_location.refresh(nil, true)
  141. sys.timerLoopStart(util_location.refresh, config.LOCATION_INTERVAL)
  142. end
  143. -- 定时上报
  144. if type(config.REPORT_INTERVAL) == "number" and config.REPORT_INTERVAL >= 1000 * 60 then
  145. sys.timerLoopStart(function() util_notify.add("#ALIVE_REPORT") end, config.REPORT_INTERVAL)
  146. end
  147. -- 电源键短按发送测试通知
  148. sys.subscribe("POWERKEY_SHORT_PRESS", function() util_notify.add("#ALIVE") end)
  149. -- 电源键长按查询流量
  150. sys.subscribe("POWERKEY_LONG_PRESS", util_mobile.queryTraffic)
  151. sys.wait(60000);
  152. -- EC618配置小区重选信号差值门限,不能大于15dbm,必须在飞行模式下才能用
  153. mobile.flymode(0, true)
  154. mobile.config(mobile.CONF_RESELTOWEAKNCELL, 10)
  155. mobile.config(mobile.CONF_STATICCONFIG, 1) -- 开启网络静态优化
  156. mobile.flymode(0, false)
  157. end)
  158. sys.taskInit(function()
  159. if type(config.PIN_CODE) ~= "string" or config.PIN_CODE == "" then
  160. return
  161. end
  162. -- 开机等待 5 秒仍未联网, 再进行 pin 验证
  163. if not sys.waitUntil("IP_READY", 1000 * 5) then
  164. util_mobile.pinVerify(config.PIN_CODE)
  165. end
  166. end)
  167. -- 定时开关飞行模式
  168. if type(config.FLYMODE_INTERVAL) == "number" and config.FLYMODE_INTERVAL >= 1000 * 60 then
  169. sys.timerLoopStart(function()
  170. sys.taskInit(function()
  171. log.info("main", "定时开关飞行模式")
  172. mobile.reset()
  173. sys.wait(1000)
  174. mobile.flymode(0, true)
  175. mobile.flymode(0, false)
  176. end)
  177. end, config.FLYMODE_INTERVAL)
  178. end
  179. -- 通话相关
  180. local is_calling = false
  181. sys.subscribe("CC_IND", function(status)
  182. if cc == nil then return end
  183. if status == "INCOMINGCALL" then
  184. -- 来电事件, 期间会重复触发
  185. if is_calling then return end
  186. is_calling = true
  187. log.info("cc_status", "INCOMINGCALL", "来电事件", cc.lastNum())
  188. -- 发送通知
  189. util_notify.add({ "来电号码: " .. cc.lastNum(), "来电时间: " .. os.date("%Y-%m-%d %H:%M:%S"), "#CALL #CALL_IN" })
  190. return
  191. end
  192. if status == "DISCONNECTED" then
  193. -- 挂断事件
  194. is_calling = false
  195. log.info("cc_status", "DISCONNECTED", "挂断事件", cc.lastNum())
  196. -- 发送通知
  197. util_notify.add({ "来电号码: " .. cc.lastNum(), "挂断时间: " .. os.date("%Y-%m-%d %H:%M:%S"), "#CALL #CALL_DISCONNECTED" })
  198. return
  199. end
  200. log.info("cc_status", status)
  201. end)
  202. sys.run()