-
Notifications
You must be signed in to change notification settings - Fork 12
Expand file tree
/
Copy pathmain.lua
More file actions
375 lines (312 loc) · 13.1 KB
/
main.lua
File metadata and controls
375 lines (312 loc) · 13.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
PROJECT = "air780epv_forwarder"
VERSION = "1.2.0"
log.setLevel("DEBUG")
log.info("main", PROJECT, VERSION)
log.info("main", "开机原因", pm.lastReson())
sys = require "sys"
sysplus = require "sysplus"
-- 添加硬狗防止程序卡死
wdt.init(9000)
sys.timerLoopStart(wdt.feed, 3000)
-- 在这里加上回收内存的代码
sys.timerLoopStart(function()
log.info("回收一次内存")
collectgarbage("collect")
end,3600000) -- 每小时回收一次内存
-- 设置 DNS
socket.setDNS(nil, 1, "119.29.29.29")
socket.setDNS(nil, 2, "223.5.5.5")
-- SIM 自动恢复, 周期性获取小区信息, 网络遇到严重故障时尝试自动恢复等功能
mobile.setAuto(10000, 300000, 8, true, 120000)
-- 初始化 fskv
log.info("main", "fskv.init", fskv.init())
-- POWERKEY
local rtos_bsp = rtos.bsp()
local pin_table = {
["EC618"] = 35,
["EC718P"] = 46,
["AIR780E"] = 35,
["AIR780EP"] = 35,
["AIR780E4G"] = 35
}
local powerkey_pin = pin_table[rtos_bsp]
log.info("main", "硬件平台:", rtos_bsp, "电源键引脚:", powerkey_pin or "未找到")
if powerkey_pin then
local button_last_press_time, button_last_release_time = 0, 0
log.info("main", "配置电源键引脚:", powerkey_pin)
local gpio_result = gpio.setup(powerkey_pin, function()
local current_time = mcu.ticks()
local pin_state = gpio.get(powerkey_pin)
log.debug("main", "电源键中断触发,引脚状态:", pin_state)
-- 按下
if pin_state == 0 then
button_last_press_time = current_time -- 记录最后一次按下时间
log.debug("main", "电源键按下")
return
end
-- 释放
if button_last_press_time == 0 then -- 开机前已经按下, 开机后释放
log.debug("main", "电源键释放,但按下时间为0,忽略")
return
end
if current_time - button_last_release_time < 250 then -- 防止连按
log.debug("main", "电源键连按,忽略")
return
end
local duration = current_time - button_last_press_time -- 按键持续时间
button_last_release_time = current_time -- 记录最后一次释放时间
log.info("main", "电源键释放,持续时间:", duration, "ms")
if duration > 2000 then
log.info("main", "电源键长按事件")
sys.publish("POWERKEY_LONG_PRESS", duration)
elseif duration > 50 then
log.info("main", "电源键短按事件")
sys.publish("POWERKEY_SHORT_PRESS", duration)
end
end, gpio.PULLUP)
log.info("main", "电源键GPIO配置结果:", gpio_result)
else
log.warn("main", "未找到支持的平台电源键引脚配置")
end
-- 加载模块
config = require "config"
util_http = require "util_http"
util_netled = require "util_netled"
util_mobile = require "util_mobile"
util_location = require "util_location"
util_notify = require "util_notify"
util_forward = require "util_forward"
TaskManager = require "task_manager"
if config.ROLE == "SLAVE" then
-- 串口配置
uart.setup(1, 115200, 8, 1, uart.NONE)
-- 串口接收回调
uart.on(1, "receive", function(id, len)
-- 限制单次读取最大数据量,防止内存溢出
local max_read_len = 1024 -- 最大1KB
if len > max_read_len then
len = max_read_len
log.warn("uart", "数据量过大,截断处理", len)
end
local data = uart.read(id, len)
if not data or data == "" then
return
end
log.info("uart read:", id, len, data)
-- 从机, 通过串口发送数据
uart.write(1, data)
end)
end
-- 短信接收回调
sms.setNewSmsCb(function(sender_number, sms_content, m)
local time = string.format("%d/%02d/%02d %02d:%02d:%02d", m.year + 2000, m.mon, m.day, m.hour, m.min, m.sec)
log.info("smsCallback", time, sender_number, sms_content)
-- 短信控制
local is_sms_ctrl = false
-- 改进的正则表达式,支持国际号码格式
local receiver_number, sms_content_to_be_sent = sms_content:match("^SMS,([%+]?%d%d%d%d%d%d?%d?%d?%d?%d?%d?%d?%d?%d?),(.+)$")
receiver_number, sms_content_to_be_sent = receiver_number or "", sms_content_to_be_sent or ""
-- 增强号码验证
if sms_content_to_be_sent ~= "" and receiver_number ~= "" then
-- 去除可能的空格和分隔符
receiver_number = receiver_number:gsub("[%s%-]", "")
-- 验证号码格式(5-20位数字,可含+号开头)
if string.match(receiver_number, "^%+?%d%d%d%d%d%d?%d?%d?%d?%d?%d?%d?%d?%d?$") and
#receiver_number >= 5 and #receiver_number <= 20 then
sms.send(receiver_number, sms_content_to_be_sent)
is_sms_ctrl = true
log.info("smsCtrl", "发送短信", receiver_number, sms_content_to_be_sent)
else
log.warn("smsCtrl", "号码格式无效", receiver_number)
end
end
-- 使用转发模块处理短信
local msg_with_tag = sms_content .. (is_sms_ctrl and " #CTRL" or "")
util_forward.forwardSms(msg_with_tag, sender_number, time)
end)
sys.taskInit(function()
-- 等待网络环境准备就绪
sys.waitUntil("IP_READY", config.NETWORK_TIMEOUT_LONG)
util_netled.init()
-- 初始化转发模块
if util_forward.init() then
log.info("main", "转发模块初始化成功")
else
log.error("main", "转发模块初始化失败")
end
-- 开机通知
if config.BOOT_NOTIFY then
local boot_reason = pm.lastReson()
local boot_msg = "#BOOT_" .. boot_reason
-- 添加设备信息到开机通知
if config.NOTIFY_APPEND_MORE_INFO then
boot_msg = boot_msg .. util_mobile.appendDeviceInfo()
end
log.info("main", "准备发送开机通知", "BOOT_NOTIFY", config.BOOT_NOTIFY, "开机原因", boot_reason, "消息", boot_msg)
local timer_id = sys.timerStart(function()
log.info("main", "定时器触发,开始发送开机通知", "消息", boot_msg, "定时器ID", timer_id)
-- 尝试使用转发规则发送开机通知
local forward_success = util_forward.forwardMessage(boot_msg, "BOOT")
if forward_success then
log.info("main", "开机通知通过转发规则发送成功")
else
log.info("main", "转发规则发送失败或无规则,使用默认通知方式")
local result = util_notify.add(boot_msg)
log.info("main", "开机通知发送结果", result)
end
end, 1000 * 5)
log.info("main", "定时器已启动", "ID", timer_id, "延迟", 5000, "毫秒")
else
log.info("main", "开机通知已禁用", "BOOT_NOTIFY", config.BOOT_NOTIFY)
end
-- 定时同步时间
if os.time() < 1714500000 then
socket.sntp()
end
if type(config.SNTP_INTERVAL) == "number" and config.SNTP_INTERVAL >= 1000 * 60 then
sys.timerLoopStart(socket.sntp, config.SNTP_INTERVAL)
end
-- 定时查询流量
if type(config.QUERY_TRAFFIC_INTERVAL) == "number" and config.QUERY_TRAFFIC_INTERVAL >= 1000 * 60 then
sys.timerLoopStart(util_mobile.queryTraffic, config.QUERY_TRAFFIC_INTERVAL)
end
-- 定时基站定位
if type(config.LOCATION_INTERVAL) == "number" and config.LOCATION_INTERVAL >= 1000 * 60 then
util_location.refresh(nil, true)
sys.timerLoopStart(util_location.refresh, config.LOCATION_INTERVAL)
end
-- 定时上报
if type(config.REPORT_INTERVAL) == "number" and config.REPORT_INTERVAL >= 1000 * 60 then
sys.timerLoopStart(function() util_notify.add("#ALIVE_REPORT") end, config.REPORT_INTERVAL)
end
-- 设备重启管理(增加状态检查)
local restart_enabled = config.RESTART_ENABLED -- 从配置读取重启开关
local restart_interval = config.RESTART_INTERVAL -- 从配置读取重启间隔
if restart_enabled then
sys.timerLoopStart(function()
log.info("main", "准备重启设备", "重启间隔", restart_interval / 1000 / 60, "分钟")
-- 检查是否有正在进行的操作
local task_list = TaskManager.list()
if #task_list > 0 then
log.info("main", "发现活跃任务,延迟重启", "任务数量", #task_list)
for _, task_name in ipairs(task_list) do
log.info("main", "活跃任务", task_name)
end
-- 等待1分钟后再尝试
sys.timerStart(function()
log.info("main", "延迟重启设备")
cleanupAllTasks()
sys.wait(2000) -- 等待任务清理完成
rtos.restart()
end, 60000)
else
-- 没有活跃任务,直接重启
log.info("main", "无活跃任务,立即重启设备")
cleanupAllTasks()
sys.wait(1000) -- 等待清理完成
rtos.restart()
end
end, restart_interval)
else
log.info("main", "设备自动重启已禁用")
end
-- 电源键处理(短按/双击功能,带延迟区分)
local single_click_timer = nil
log.info("main", "注册电源键短按事件订阅")
sys.subscribe("POWERKEY_SHORT_PRESS", function()
log.info("main", "收到电源键短按事件")
if single_click_timer then
-- 双击:取消单击定时器,执行双击动作
sys.timerStop(single_click_timer)
single_click_timer = nil
log.info("main", "检测到双击,发送开机通知测试")
local boot_test_msg = "#BOOT_TEST_" .. pm.lastReson()
local forward_success = util_forward.forwardMessage(boot_test_msg, "BOOT_TEST")
if forward_success then
log.info("main", "开机测试通知通过转发规则发送成功")
else
log.info("main", "转发规则发送失败,使用默认通知方式")
util_notify.add(boot_test_msg)
end
else
-- 首次按下:延迟500ms执行单击,等待可能的第二次按下
single_click_timer = sys.timerStart(function()
single_click_timer = nil
log.info("main", "短按电源键,发送测试通知")
local test_msg = "#ALIVE"
local forward_success = util_forward.forwardMessage(test_msg, "TEST")
if forward_success then
log.info("main", "测试通知通过转发规则发送成功")
else
log.info("main", "转发规则发送失败,使用默认通知方式")
util_notify.add(test_msg)
end
end, 500)
end
end)
-- 电源键长按查询流量
log.info("main", "注册电源键长按事件订阅")
sys.subscribe("POWERKEY_LONG_PRESS", function(duration)
log.info("main", "收到电源键长按事件,持续时间:", duration, "ms")
util_mobile.queryTraffic()
end)
end)
sys.taskInit(function()
if type(config.PIN_CODE) ~= "string" or config.PIN_CODE == "" then
return
end
-- 开机等待短时间仍未联网, 再进行 pin 验证
if not sys.waitUntil("IP_READY", config.NETWORK_TIMEOUT_SHORT) then
util_mobile.pinVerify(config.PIN_CODE)
end
end)
-- 定时开关飞行模式
if type(config.FLYMODE_INTERVAL) == "number" and config.FLYMODE_INTERVAL >= 1000 * 60 then
sys.timerLoopStart(function()
mobile.flymode(0, true)
mobile.flymode(0, false)
end, config.FLYMODE_INTERVAL)
end
-- 通话相关
local is_calling = false
sys.subscribe("CC_IND", function(status)
if cc == nil then return end
if status == "INCOMINGCALL" then
-- 来电事件, 期间会重复触发
if is_calling then return end
is_calling = true
log.info("cc_status", "INCOMINGCALL", "来电事件", cc.lastNum())
-- 发送通知
util_notify.add({ "来电号码: " .. cc.lastNum(), "来电时间: " .. os.date("%Y-%m-%d %H:%M:%S"), "#CALL #CALL_IN" })
return
end
if status == "DISCONNECTED" then
-- 挂断事件
is_calling = false
log.info("cc_status", "DISCONNECTED", "挂断事件", cc.lastNum())
-- 发送通知
util_notify.add({ "来电号码: " .. cc.lastNum(), "挂断时间: " .. os.date("%Y-%m-%d %H:%M:%S"), "#CALL #CALL_DISCONNECTED" })
return
end
log.info("cc_status", status)
end)
-- 全局任务清理函数
function cleanupAllTasks()
log.info("main", "开始清理所有任务")
-- 清理各模块任务
if util_notify.cleanup then
util_notify.cleanup()
end
if util_location.cleanup then
util_location.cleanup()
end
if util_netled.cleanup then
util_netled.cleanup()
end
-- 清理任务管理器中的所有任务
TaskManager.cleanup()
log.info("main", "所有任务清理完成")
end
-- 设置调试模式
TaskManager.setDebug(false) -- 可设置为true查看详细日志
sys.run()