Files
BR_YKC/4G/源代码/lib/nvm.lua
2026-05-21 13:24:05 +08:00

346 lines
11 KiB
Lua
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
--- 模块功能:参数管理
-- @module nvm
-- @author openLuat
-- @license MIT
-- @copyright openLuat
-- @release 2017.11.9
require "log"
module(..., package.seeall)
--实时参数配置存储在paraname文件中
--默认参数配置存储在configname文件中
--para实时参数表
--config默认参数表
paraname, paranamebak = "/nvm_para.lua", "/nvm_para_bak.lua"
para = {}
local libdftconfig, configname, cconfigname, econfigname
local sBurnSave
--[[
函数名serialize
功能 :根据不同的数据类型,按照不同的格式,写格式化后的数据到文件中
参数
pout文件句柄
o数据
返回值:无
]]
local function serialize(pout, o)
if type(o) == "number" then
--number类型直接写原始数据
pout:write(o)
elseif type(o) == "string" then
--string类型原始数据左右各加上双引号写入
pout:write(string.format("%q", o))
elseif type(o) == "boolean" then
--boolean类型转化为string写入
pout:write(tostring(o))
elseif type(o) == "table" then
--table类型加换行大括号中括号双引号写入
pout:write("{\n")
for k, v in pairs(o) do
-- if type(k) == "number" then
-- pout:write(" [" .. k .. "] = ")
-- elseif type(k) == "string" then
-- pout:write(" [\"" .. k .."\"] = ")
-- else
-- error("cannot serialize table key " .. type(o))
-- end
pout:write(" [")
serialize(pout, k)
pout:write("] = ")
serialize(pout, v)
pout:write(",\n")
end
pout:write("}\n")
else
error("cannot serialize a " .. type(o))
end
end
--[[
函数名upd
功能 :更新实时参数表
参数
overide是否用默认参数强制更新实时参数
返回值:无
]]
function upd(overide)
for k, v in pairs(libdftconfig) do
if k ~= "_M" and k ~= "_NAME" and k ~= "_PACKAGE" then
if overide or para[k] == nil then
para[k] = v
end
end
end
end
local function safePcall(file)
local oldPath = package.path
package.path = "/?.lua;".."/?.luae;".."/#lua_user#/?.lua;".."/#lua_user#/?.luae;"..package.path
local result, para = pcall(require, file)
package.path = oldPath
return result, para
end
--[[
函数名load
功能 :初始化参数
参数 :无
返回值如果参数文件异常会恢复出厂设置此时返回false其余情况返回nil
]]
local function load()
local f, fBak, fExist, fBakExist
f = io.open(paraname, "rb")
fBak = io.open(paranamebak, "rb")
if f then
fExist = f:read("*a") ~= ""
f:close()
end
if fBak then
fBakExist = fBak:read("*a") ~= ""
fBak:close()
end
print("load fExist fBakExist", fExist, fBakExist)
local fResult, fBakResult
if fExist then
if sBurnSave then
fResult, para = safePcall(paraname:match("/#lua_user#/(.+)%.lua"))
else
fResult, para = safePcall(paraname:match("/(.+)%.lua"))
end
end
print("load fResult,type(para)", fResult,type(para))
local fError,fBakError
if fResult then
if type(para)=="table" then
os.remove(paranamebak)
upd()
return
else
fError = true
end
end
if fBakExist then
if sBurnSave then
fBakResult, para = safePcall(paranamebak:match("/#lua_user#/(.+)%.lua"))
else
fBakResult, para = safePcall(paranamebak:match("/(.+)%.lua"))
end
end
print("load fBakResult,type(para)", fBakResult,type(para))
if fBakResult then
if type(para)=="table" then
os.remove(paraname)
upd()
return
else
fBakError = true
end
else
para = {}
restore()
end
--两种参数文件都不存在,不算异常,以下算是异常情况:
--1、参数文件存在备份参数文件不存在
-- (1)、参数文件require异常
--2、参数文件不存在备份参数文件存在
-- (1)、备份参数文件require异常
--3、参数文件存在备份参数文件存在
-- (1)、参数文件和备份参数文件require都异常
if fExist and not fBakExist then
if not fResult or fError then return false end
end
if not fExist and fBakExist then
if not fBakResult or fBakError then return false end
end
if fExist and fBakExist then
if (not fResult or fError) and (not fBakResult or fBakError) then return false end
end
end
--[[
函数名save
功能 :保存参数文件
参数
s是否真正保存true保存false或者nil不保存
返回值:无
]]
local function save(s)
if not s then return end
local f = {}
f.write = function(self, s)table.insert(self, s) end
f:write("module(...)\n")
for k, v in pairs(para) do
if k ~= "_M" and k ~= "_NAME" and k ~= "_PACKAGE" then
f:write(k .. " = ")
serialize(f, v)
f:write("\n")
end
end
local fparabak = io.open(paranamebak, 'wb')
fparabak:write(table.concat(f))
fparabak:close()
os.remove(paraname)
os.rename(paranamebak, paraname)
end
--- 初始化参数存储管理模块
-- @string defaultCfgFile 默认参数文件名
-- @bool burnSave 本地烧录时是否保留已有参数true为保留false或者nil为清除
-- 注意:在同一个项目,不同版本中,此参数必须保持前后版本一致
-- @return boolean result如果初始化异常会恢复出厂设置此时返回false其余情况返回nil
-- @usage
-- 初始化参数存储管理模块默认参数文件名为config.lua本地烧录时清除已有的参数
-- nvm.init("config.lua")
-- 初始化参数存储管理模块默认参数文件名为config.lua本地烧录时保留已有的参数
-- nvm.init("config.lua",true)
function init(defaultCfgFile,burnSave)
local f
f, libdftconfig = safePcall(defaultCfgFile:match("(.+)%.lua"))
configname, cconfigname, econfigname = "/lua/" .. defaultCfgFile, "/lua/" .. defaultCfgFile .. "c", "/lua/" .. defaultCfgFile .. "e"
sBurnSave = burnSave
if burnSave then
rtos.make_dir("/#lua_user#")
paraname, paranamebak = "/#lua_user#/nvm_para.lua", "/#lua_user#/nvm_para_bak.lua"
end
--初始化配置文件,从文件中把参数读取到内存中
return load()
end
--- 设置某个参数的值
-- @string k 参数名
-- @param v 参数的新值仅支持number、string、boolean、table类型
-- @param r 设置原因如果传入了非nil的有效参数并且v值和旧值相比发生了改变
-- 会产生一个PARA_CHANGED_IND内部消息携带 k,v,r 3个参数
-- @param s 是否立即写入到文件系统中false不写入其余的都写入
-- @return bool或者nil成功返回true失败返回nil
-- @usage
-- 参数name赋值为Luat立即写入文件系统
-- nvm.set("name","Luat")
--
-- 参数age赋值为12立即写入文件系统
-- 如果旧值不是12会产生一个PARA_CHANGED_IND消息携带 "age",12,"SVR" 3个参数
-- nvm.set("age",12,"SVR")
--
-- 参数class赋值为Class2不写入文件系统
-- nvm.set("class","Class2",nil,false)
--
-- 参数score赋值为{chinese=100,math=99,english=98},立即写入文件系统:
-- nvm.set("score",{chinese=100,math=99,english=98})
--
-- 连续写入4个参数前3个不保存到文件系统中写第4个时一次性全部保存到文件系统中
-- nvm.set("para1",1,nil,false)
-- nvm.set("para2",2,nil,false)
-- nvm.set("para3",3,nil,false)
-- nvm.set("para4",4)
function set(k, v, r, s)
local bchg = true
if type(v) ~= "table" then
bchg = (para[k] ~= v)
end
log.info("nvm.set", bchg, k, v, r, s)
if bchg then
para[k] = v
save(s or s == nil)
if r then sys.publish("PARA_CHANGED_IND", k, v, r) end
end
return true
end
--- 设置某个table类型参数的某一个索引的值
-- @string k table类型的参数名
-- @param kk table类型参数的某一个索引名
-- @param v table类型参数的某一个索引的新值
-- @param r 设置原因如果传入了非nil的有效参数并且v值和旧值相比发生了改变会产生一个TPARA_CHANGED_IND消息携带k,kk,v,r4个参数
-- @param s 是否立即写入到文件系统中false不写入其余的都写入
-- @return bool或者nil成功返回true失败返回nil
-- @usage nvm.sett("score","chinese",100)参数score["chinese"]赋值为100立即写入文件系统
-- @usage nvm.sett("score","chinese",100,"SVR")参数score["chinese"]赋值为100立即写入文件系统
-- 如果旧值不是100会产生一个TPARA_CHANGED_IND消息携带 "score","chinese",100,"SVR" 4个参数
-- @usage nvm.sett("score","chinese",100,nil,false)参数class赋值为Class2不写入文件系统
function sett(k, kk, v, r, s)
local bchg = true
if type(v) ~= "table" then
bchg = (para[k][kk] ~= v)
end
if bchg then
para[k][kk] = v
save(s or s == nil)
if r then sys.publish("TPARA_CHANGED_IND", k, kk, v, r) end
end
return true
end
--- 所有参数立即写入文件系统
-- @return nil
-- @usage nvm.flush()
function flush()
save(true)
end
--- 读取某个参数的值
-- @string k 参数名
-- @return 参数值
-- @usage
-- 读取参数名为name的参数值
-- nameValue = nvm.get("name")
function get(k)
return para[k]
end
--- 读取某个table类型参数的键名对应的值
-- @string k table类型的参数名
-- @param kk table类型参数的键名
-- @usage
-- 有一个table参数为score数据如下
-- score = {chinese=100, math=100, english=95}
-- 读取score中chinese对应的值
-- nvm.gett("score","chinese")
function gett(k, kk)
return para[k][kk]
end
--- 参数恢复出厂设置
-- @return nil
-- @usage nvm.restore()
function restore()
os.remove(paraname)
os.remove(paranamebak)
local fpara, fconfig = io.open(paraname, "wb"), io.open(configname, "rb")
if not fconfig then fconfig = io.open(cconfigname, "rb") end
if not fconfig then fconfig = io.open(econfigname, "rb") end
fpara:write(fconfig:read("*a"))
fpara:close()
fconfig:close()
upd(true)
end
--- 请求删除参数文件.
-- 此接口一般用在远程升级时需要用新的config.lua覆盖原来的参数文件的场景在此场景下远程升级包下载成功后在确定要重启前调用此接口
-- 下次开机执行nvm.init("config.lua")时会用新的config.lua文件自动覆盖参数文件以后再开机就不会自动覆盖了
-- 也就是说"nvm.remove()->重启->nvm.init("config.lua")"是一个仅执行一次的完整操作
-- @return nil
-- @usage nvm.remove()
function remove()
os.remove(paraname)
os.remove(paranamebak)
end