最终提交
This commit is contained in:
345
4G/源代码/lib/nvm.lua
Normal file
345
4G/源代码/lib/nvm.lua
Normal file
@@ -0,0 +1,345 @@
|
||||
--- 模块功能:参数管理
|
||||
-- @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
|
||||
Reference in New Issue
Block a user