代码拉取完成,页面将自动刷新
同步操作将从 稀饭放姜/iRTU 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
--- 模块功能:Luat协程调度框架
-- @module sys
-- @author openLuat
-- @license MIT
-- @copyright openLuat
-- @release 2017.9.13
require "utils"
require "log"
require "patch"
module(..., package.seeall)
-- lib脚本版本号,只要lib中的任何一个脚本做了修改,都需要更新此版本号
SCRIPT_LIB_VER = "2.3.0"
-- TaskID最大值
local TASK_TIMER_ID_MAX = 0x1FFFFFFF
-- msgId 最大值(请勿修改否则会发生msgId碰撞的危险)
local MSG_TIMER_ID_MAX = 0x7FFFFFFF
-- 任务定时器id
local taskTimerId = 0
-- 消息定时器id
local msgId = TASK_TIMER_ID_MAX
-- 定时器id表
local timerPool = {}
local taskTimerPool = {}
--消息定时器参数表
local para = {}
--定时器是否循环表
local loop = {}
-- 启动GSM协议栈。例如在充电开机未启动GSM协议栈状态下,如果用户长按键正常开机,此时调用此接口启动GSM协议栈即可
-- @return 无
-- @usage sys.powerOn()
function powerOn()
rtos.poweron(1)
end
--- 软件重启
-- @string r 重启原因,用户自定义,一般是string类型,重启后的trace中会打印出此重启原因
-- @return 无
-- @usage sys.restart('程序超时软件重启')
function restart(r)
assert(r and r ~= "", "sys.restart cause null")
if errDump and errDump.appendErr and type(errDump.appendErr) == "function" then errDump.appendErr("restart[" .. r .. "];") end
log.warn("sys.restart", r)
rtos.restart()
end
--- Task任务延时函数,只能用于任务函数中
-- @number ms 整数,最大等待126322567毫秒
-- @return 定时结束返回nil,被其他线程唤起返回调用线程传入的参数
-- @usage sys.wait(30)
function wait(ms)
-- 参数检测,参数不能为负值
assert(ms > 0, "The wait time cannot be negative!")
--4G底层不支持小于5ms的定时器
if ms < 5 then ms = 5 end
-- 选一个未使用的定时器ID给该任务线程
if taskTimerId >= TASK_TIMER_ID_MAX then taskTimerId = 0 end
taskTimerId = taskTimerId + 1
local timerid = taskTimerId
taskTimerPool[coroutine.running()] = timerid
timerPool[timerid] = coroutine.running()
-- 调用core的rtos定时器
if 1 ~= rtos.timer_start(timerid, ms) then log.debug("rtos.timer_start error") return end
-- 挂起调用的任务线程
local message = {coroutine.yield()}
if #message ~= 0 then
rtos.timer_stop(timerid)
taskTimerPool[coroutine.running()] = nil
timerPool[timerid] = nil
return unpack(message)
end
end
--- Task任务的条件等待函数(包括事件消息和定时器消息等条件),只能用于任务函数中。
-- @param id 消息ID
-- @number ms 等待超时时间,单位ms,最大等待126322567毫秒
-- @return result 接收到消息返回true,超时返回false
-- @return data 接收到消息返回消息参数
-- @usage result, data = sys.waitUntil("SIM_IND", 120000)
function waitUntil(id, ms)
subscribe(id, coroutine.running())
local message = ms and {wait(ms)} or {coroutine.yield()}
unsubscribe(id, coroutine.running())
return message[1] ~= nil, unpack(message, 2, #message)
end
--- Task任务的条件等待函数扩展(包括事件消息和定时器消息等条件),只能用于任务函数中。
-- @param id 消息ID
-- @number ms 等待超时时间,单位ms,最大等待126322567毫秒
-- @return message 接收到消息返回message,超时返回false
-- @return data 接收到消息返回消息参数
-- @usage result, data = sys.waitUntilExt("SIM_IND", 120000)
function waitUntilExt(id, ms)
subscribe(id, coroutine.running())
local message = ms and {wait(ms)} or {coroutine.yield()}
unsubscribe(id, coroutine.running())
if message[1] ~= nil then return unpack(message) end
return false
end
--- 创建一个任务线程,在模块最末行调用该函数并注册模块中的任务函数,main.lua导入该模块即可
-- @param fun 任务函数名,用于resume唤醒时调用
-- @param ... 任务函数fun的可变参数
-- @return co 返回该任务的线程号
-- @usage sys.taskInit(task1,'a','b')
function taskInit(fun, ...)
local co = coroutine.create(fun)
coroutine.resume(co, unpack(arg))
return co
end
--- Luat平台初始化
-- @param mode 充电开机是否启动GSM协议栈,1不启动,否则启动
-- @param lprfnc 用户应用脚本中定义的“低电关机处理函数”,如果有函数名,则低电时,本文件中的run接口不会执行任何动作,否则,会延时1分钟自动关机
-- @return 无
-- @usage sys.init(1,0)
function init(mode, lprfnc)
-- 用户应用脚本中必须定义PROJECT和VERSION两个全局变量,否则会死机重启,如何定义请参考各个demo中的main.lua
assert(PROJECT and PROJECT ~= "" and VERSION and VERSION ~= "", "Undefine PROJECT or VERSION")
collectgarbage("setpause", 80)
-- 设置AT命令的虚拟串口
uart.setup(uart.ATC, 0, 0, uart.PAR_NONE, uart.STOP_1)
log.info("poweron reason:", rtos.poweron_reason(), PROJECT, VERSION, SCRIPT_LIB_VER, rtos.get_version())
pcall(rtos.set_lua_info,"\r\n"..rtos.get_version().."\r\n"..(_G.PROJECT or "NO PROJECT").."\r\n"..(_G.VERSION or "NO VERSION"))
if type(rtos.get_build_time)=="function" then log.info("core build time", rtos.get_build_time()) end
if mode == 1 then
-- 充电开机
if rtos.poweron_reason() == rtos.POWERON_CHARGER then
-- 关闭GSM协议栈
rtos.poweron(0)
end
end
end
------------------------------------------ rtos消息回调处理部分 ------------------------------------------
--[[
函数名:cmpTable
功能 :比较两个table的内容是否相同,注意:table中不能再包含table
参数 :
t1:第一个table
t2:第二个table
返回值:相同返回true,否则false
]]
local function cmpTable(t1, t2)
if not t2 then return #t1 == 0 end
if #t1 == #t2 then
for i = 1, #t1 do
if unpack(t1, i, i) ~= unpack(t2, i, i) then
return false
end
end
return true
end
return false
end
--- 关闭定时器
-- @param val 值为number时,识别为定时器ID,值为回调函数时,需要传参数
-- @param ... val值为函数时,函数的可变参数
-- @return 无
-- @usage timerStop(1)
function timerStop(val, ...)
-- val 为定时器ID
if type(val) == 'number' then
timerPool[val], para[val], loop[val] = nil
rtos.timer_stop(val)
else
for k, v in pairs(timerPool) do
-- 回调函数相同
if type(v) == 'table' and v.cb == val or v == val then
-- 可变参数相同
if cmpTable(arg, para[k]) then
rtos.timer_stop(k)
timerPool[k], para[k], loop[val] = nil
break
end
end
end
end
end
--- 关闭同一回调函数的所有定时器
-- @param fnc 定时器回调函数
-- @return 无
-- @usage timerStopAll(cbFnc)
function timerStopAll(fnc)
for k, v in pairs(timerPool) do
if type(v) == "table" and v.cb == fnc or v == fnc then
rtos.timer_stop(k)
timerPool[k], para[k], loop[k] = nil
end
end
end
--- 开启一个定时器
-- @param fnc 定时器回调函数
-- @number ms 整数,最大定时126322567毫秒
-- @param ... 可变参数 fnc的参数
-- @return number 定时器ID,如果失败,返回nil
function timerStart(fnc, ms, ...)
--回调函数和时长检测
assert(fnc ~= nil, "sys.timerStart(first param) is nil !")
assert(ms > 0, "sys.timerStart(Second parameter) is <= zero !")
--4G底层不支持小于5ms的定时器
if ms < 5 then ms = 5 end
-- 关闭完全相同的定时器
if arg.n == 0 then
timerStop(fnc)
else
timerStop(fnc, unpack(arg))
end
-- 为定时器申请ID,ID值 1-20 留给任务,20-30留给消息专用定时器
while true do
if msgId >= MSG_TIMER_ID_MAX then msgId = TASK_TIMER_ID_MAX end
msgId = msgId + 1
if timerPool[msgId] == nil then
timerPool[msgId] = fnc
break
end
end
--调用底层接口启动定时器
if rtos.timer_start(msgId, ms) ~= 1 then log.debug("rtos.timer_start error") return end
--如果存在可变参数,在定时器参数表中保存参数
if arg.n ~= 0 then
para[msgId] = arg
end
--返回定时器id
return msgId
end
--- 开启一个循环定时器
-- @param fnc 定时器回调函数
-- @number ms 整数,最大定时126322567毫秒
-- @param ... 可变参数 fnc的参数
-- @return number 定时器ID,如果失败,返回nil
function timerLoopStart(fnc, ms, ...)
local tid = timerStart(fnc, ms, unpack(arg))
if tid then loop[tid] = (ms<5 and 5 or ms) end
return tid
end
--- 判断某个定时器是否处于开启状态
-- @param val 有两种形式
--一种是开启定时器时返回的定时器id,此形式时不需要再传入可变参数...就能唯一标记一个定时器
--另一种是开启定时器时的回调函数,此形式时必须再传入可变参数...才能唯一标记一个定时器
-- @param ... 可变参数
-- @return number 开启状态返回true,否则nil
function timerIsActive(val, ...)
if type(val) == "number" then
return timerPool[val]
else
for k, v in pairs(timerPool) do
if v == val then
if cmpTable(arg, para[k]) then return true end
end
end
end
end
------------------------------------------ LUA应用消息订阅/发布接口 ------------------------------------------
-- 订阅者列表
local subscribers = {}
--内部消息队列
local messageQueue = {}
--- 订阅消息
-- @param id 消息id
-- @param callback 消息回调处理
-- @usage subscribe("NET_STATUS_IND", callback)
function subscribe(id, callback)
if type(id) ~= "string" or (type(callback) ~= "function" and type(callback) ~= "thread") then
log.warn("warning: sys.subscribe invalid parameter", id, callback)
return
end
if not subscribers[id] then subscribers[id] = {} end
subscribers[id][callback] = true
end
--- 取消订阅消息
-- @param id 消息id
-- @param callback 消息回调处理
-- @usage unsubscribe("NET_STATUS_IND", callback)
function unsubscribe(id, callback)
if type(id) ~= "string" or (type(callback) ~= "function" and type(callback) ~= "thread") then
log.warn("warning: sys.unsubscribe invalid parameter", id, callback)
return
end
if subscribers[id] then subscribers[id][callback] = nil end
end
--- 发布内部消息,存储在内部消息队列中
-- @param ... 可变参数,用户自定义
-- @return 无
-- @usage publish("NET_STATUS_IND")
function publish(...)
table.insert(messageQueue, arg)
end
-- 分发消息
local function dispatch()
while true do
if #messageQueue == 0 then
break
end
local message = table.remove(messageQueue, 1)
if subscribers[message[1]] then
for callback, _ in pairs(subscribers[message[1]]) do
if type(callback) == "function" then
callback(unpack(message, 2, #message))
elseif type(callback) == "thread" then
coroutine.resume(callback, unpack(message))
end
end
end
end
end
-- rtos消息回调
local handlers = {}
setmetatable(handlers, {__index = function() return function() end end, })
--- 注册rtos消息回调处理函数
-- @number id 消息类型id
-- @param handler 消息处理函数
-- @return 无
-- @usage rtos.on(rtos.MSG_KEYPAD, function(param) handle keypad message end)
rtos.on = function(id, handler)
handlers[id] = handler
end
------------------------------------------ Luat 主调度框架 ------------------------------------------
--- run()从底层获取core消息并及时处理相关消息,查询定时器并调度各注册成功的任务线程运行和挂起
-- @return 无
-- @usage sys.run()
function run()
while true do
-- 分发内部消息
dispatch()
-- 阻塞读取外部消息
local msg, param = rtos.receive(rtos.INF_TIMEOUT)
-- 判断是否为定时器消息,并且消息是否注册
if msg == rtos.MSG_TIMER and timerPool[param] then
if param < TASK_TIMER_ID_MAX then
local taskId = timerPool[param]
timerPool[param] = nil
if taskTimerPool[taskId] == param then
taskTimerPool[taskId] = nil
coroutine.resume(taskId)
end
else
local cb = timerPool[param]
--如果不是循环定时器,从定时器id表中删除此定时器
if not loop[param] then timerPool[param] = nil end
if para[param] ~= nil then
cb(unpack(para[param]))
if not loop[param] then para[param] = nil end
else
cb()
end
--如果是循环定时器,继续启动此定时器
if loop[param] then rtos.timer_start(param, loop[param]) end
end
--其他消息(音频消息、充电管理消息、按键消息等)
elseif type(msg) == "number" then
handlers[msg](param)
else
handlers[msg.id](msg)
end
end
end
require "clib"
if type(rtos.openSoftDog)=="function" then
rtos.openSoftDog(60000)
sys.timerLoopStart(rtos.eatSoftDog,20000)
end
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。