util_notify.lua 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. local util_notify_channel = require "util_notify_channel"
  2. local util_notify = {}
  3. -- 消息队列
  4. local msg_queue = {}
  5. -- 发送计数
  6. local msg_count = 0
  7. local error_count = 0
  8. --- 发送通知
  9. -- @param msg 消息内容
  10. -- @param channel 通知渠道
  11. -- @return true: 无需重发, false: 需要重发
  12. local function send(msg, channel)
  13. log.info("util_notify.send", "发送通知", channel)
  14. -- 判断消息内容 msg
  15. if type(msg) ~= "string" or msg == "" then
  16. log.error("util_notify.send", "发送通知失败", "msg 参数错误", type(msg))
  17. return true
  18. end
  19. -- 判断通知渠道 channel
  20. if channel and util_notify_channel[channel] == nil then
  21. log.error("util_notify.send", "发送通知失败", "未知通知渠道", channel)
  22. return true
  23. end
  24. -- 发送通知
  25. local code, headers, body = util_notify_channel[channel](msg)
  26. if code == nil then
  27. log.info("util_notify.send", "发送通知失败, 无需重发", "code:", code, "body:", body)
  28. return true
  29. end
  30. if code >= 200 and code < 500 and code ~= 408 and code ~= 409 and code ~= 425 and code ~= 429 then
  31. log.info("util_notify.send", "发送通知成功", "code:", code, "body:", body)
  32. return true
  33. end
  34. log.error("util_notify.send", "发送通知失败, 等待重发", "code:", code, "body:", body)
  35. return false
  36. end
  37. --- 添加到消息队列
  38. -- @param msg 消息内容
  39. -- @param channels 通知渠道
  40. -- @param id 消息唯一标识
  41. function util_notify.add(msg, channels, id)
  42. msg_count = msg_count + 1
  43. if id == nil or id == "" then
  44. id = "msg-t" .. os.time() .. "c" .. msg_count .. "r" .. math.random(9999)
  45. end
  46. if type(msg) == "table" then
  47. msg = table.concat(msg, "\n")
  48. end
  49. channels = channels or config.NOTIFY_TYPE
  50. if type(channels) ~= "table" then
  51. channels = { channels }
  52. end
  53. for _, channel in ipairs(channels) do
  54. table.insert(msg_queue, { id = id, channel = channel, msg = msg, retry = 0 })
  55. end
  56. sys.publish("NEW_MSG")
  57. log.debug("util_notify.add", "添加到消息队列, 当前队列长度:", #msg_queue, "消息内容:", msg:gsub("\r", "\\r"):gsub("\n", "\\n"))
  58. end
  59. --- 轮询消息队列, 发送成功则从队列中删除, 发送失败则等待下次
  60. local function poll()
  61. -- 打印网络状态
  62. if mobile.status() ~= 1 then
  63. log.warn("util_notify.poll", "mobile.status", mobile_status, util_mobile.status())
  64. end
  65. -- 消息队列非空
  66. if next(msg_queue) == nil then
  67. sys.waitUntil("NEW_MSG", 1000 * 10)
  68. return
  69. end
  70. local item = msg_queue[1]
  71. table.remove(msg_queue, 1)
  72. local msg = item.msg
  73. log.info("util_notify.poll", "轮询消息队列中", "总长度: " .. #msg_queue, "当前ID: " .. item.id, "当前重发次数: " .. item.retry, "连续失败次数: " .. error_count)
  74. -- 通知内容添加设备信息
  75. if config.NOTIFY_APPEND_MORE_INFO and not string.find(msg, "开机时长:") then
  76. msg = msg .. util_mobile.appendDeviceInfo()
  77. end
  78. -- 通知内容添加重发次数
  79. if error_count > 0 then
  80. msg = msg .. "\n重发次数: " .. error_count
  81. end
  82. -- 超过最大重发次数
  83. if item.retry > (config.NOTIFY_RETRY_MAX or 20) then
  84. log.warn("util_notify.poll", "超过最大重发次数, 放弃重发", item.msg)
  85. return
  86. end
  87. -- 开始发送
  88. local result = send(msg, item.channel)
  89. -- 发送成功
  90. if result then
  91. error_count = 0
  92. -- 检查 fskv 中如果存在则删除
  93. if fskv.get(item.id) then
  94. fskv.del(item.id)
  95. end
  96. return
  97. end
  98. -- 发送失败
  99. error_count = error_count + 1
  100. item.retry = item.retry + 1
  101. table.insert(msg_queue, item)
  102. log.info("util_notify.poll", "等待下次重发", "当前重发次数", item.retry, "连续失败次数", error_count)
  103. sys.waitUntil("IP_READY", 1000 * 5)
  104. -- 每连续失败 2 次, 开关飞行模式
  105. if error_count % 2 == 0 then
  106. -- 开关飞行模式
  107. log.warn("util_notify.poll", "连续失败次数过多, 开关飞行模式")
  108. mobile.flymode(0, true)
  109. mobile.flymode(0, false)
  110. sys.wait(1000)
  111. end
  112. -- 每条消息第 1 次重发失败后, 保存到 fskv, 断电开机可恢复重发
  113. if item.retry == 1 then
  114. if not (string.find(item.msg, "#SMS") or string.find(item.msg, "#CALL")) then
  115. return
  116. end
  117. log.info("util_notify.poll", "当前第 1 次重发失败, 保存到 fskv", item.id)
  118. if fskv.get(item.id) then
  119. log.info("util_notify.poll", "fskv 已存在, 跳过写入", item.id)
  120. return
  121. end
  122. local kv_set_result = fskv.set(item.id, item.msg)
  123. log.info("util_notify.poll", "fskv.set", kv_set_result, "used,total,count:", fskv.status())
  124. end
  125. end
  126. sys.taskInit(function()
  127. while true do
  128. poll()
  129. sys.wait(100)
  130. end
  131. end)
  132. sys.taskInit(function()
  133. sys.waitUntil("IP_READY")
  134. sys.wait(10000)
  135. local iter = fskv.iter()
  136. while iter do
  137. local k = fskv.next(iter)
  138. if not k then
  139. break
  140. end
  141. local v = fskv.get(k)
  142. if not (v and v ~= "" and string.find(k, "msg-")) then
  143. break
  144. end
  145. log.info("util_notify", "检查到 fskv 中有历史消息", k, v:gsub("\r", "\\r"):gsub("\n", "\\n"))
  146. util_notify.add(v, nil, k)
  147. end
  148. end)
  149. return util_notify