#!/opt/lnxall_app/bin/lua -- Created by jiaqiang.ye@lnxall.com -- Simple Cell Configuration JSON file generation script -- 2024/06/20 local cjson = require "cjson" local invoker = require "invoker" local g_name = nil -- Name of script, without suffix local g_vnum, g_tnum = 240, 130 -- Number of Voltage/Temperature tags local g_ptnum = 10 -- Number of Positive temperature tags local g_ntnum = 10 -- Number of Negative temperature tags local g_vaddr_start = 0x1401 -- Starting register address for Voltage local g_taddr_start = 0x1801 -- Starting register address for Temperature local g_ptaddr_start = 0x2201 -- Starting register address for Positive Temperature local g_ptaddr_start2 = 0x2281 -- Starting register address for Negative Temperature local g_poll_maxnum = 100 -- Number of registers read at a time local g_md5sum = 'd41d8cd98f00b204e9800998ecf8427e' -- default MD5sum for user_def local g_args = {} -- global parsed arguments local function json_skeleton() local rval = { info = { protocol = { [1] = "modbus_tcp", [2] = "modbus_rtu", }, type = "CELL", vendor = "协能", model = "level2", version = "0.0.0-alpha", compatible = "5.312.0000", }, read_reg = { }, poll_list = { }, } return rval end local function find_argval(prefix) local i, rval = 1, nil local plen = string.len(prefix) while i < 64 do local argn = g_args[i] if argn == nil then break end if #argn > plen and argn:sub(1, plen) == prefix then rval = argn:sub(plen + 1) break end i = i + 1 end return rval end local function parse_args(arg1) if type(arg1) == "string" then if #arg1 > 0 then if string.find(arg1, "'", 1, true) then io.stderr:write(string.format("Error, single quote found in arg1: %s\n", arg1)) io.stderr:flush() os.exit(1) end local md5val = nil local _, output = invoker.invoke(invoker.OUTPUT, "/bin/sh", "-c", string.format("echo -n '%s' | md5sum -b", arg1)) if type(output) == "string" then local md5 = string.match(output, "^([%x]+)") if md5 and #md5 == 32 then md5val = md5 end end if not md5val then io.stderr:write(string.format("Error, failed to compute md5sum for '%s'\n", arg1)) io.stderr:flush() os.exit(2) end g_md5sum = md5val end local idx = 0 for argi in string.gmatch(arg1, "[^;]+") do idx = idx + 1 g_args[idx] = argi end end local vn, tn, ptn = -1, -1, -1 local vnum, tnum, ptnum, ntn = find_argval("tplt_v="), find_argval("tplt_t="), find_argval("tplt_pt="), find_argval("tplt_nt=") if vnum then vn = tonumber(vnum) end if tnum then tn = tonumber(tnum) end if ptnum then ptn = tonumber(ptnum) end if vn and vn >= 0 then g_vnum = vn end if tn and tn >= 0 then g_tnum = tn end if ptn and ptn >= 0 then g_ptnum = ptn end if ntn and ntn >= 0 then g_ntnum = ntn end io.stdout:write(string.format("Voltage number: %d, temperature number: %d, poll temp number: %d nt: %d \n", g_vnum, g_tnum, g_ptnum, g_ntnum)) io.stdout:flush() return true end local function parse_name(arg0) if type(arg0) ~= "string" or #arg0 == 0 then io.stderr:write("Error, invalid script name!\n") io.stderr:flush() return false end local name = string.match(arg0, "([^/]+)%.lua$") if not name then io.stderr:write(string.format("Error, invalid script path: %s\n", arg0)) io.stderr:flush() return false end g_name = name io.stdout:write(string.format("Script base name: %s\n", g_name)) io.stdout:flush() return true end local function poll_list(addr, num) local haddr = string.format("%05d", addr) local rval = { scan_rate = 10000, prot = { [1] = 4, [2] = haddr, [3] = num } } return rval end local function reg_voltage(addr, i) local haddr = string.format("%05d", addr) local rval = { tag = string.format("RkCeVolt%03d", i), name = string.format("单体电压%03d(mV)", i), desc = "", property = "realdata", history = "period", type = "int", offset = 0, scale = 1, prot = { [1] = 4, [2] = haddr, [3] = "uint", [4] = "AB", [5] = 0, [6] = 1, [7] = 0 }, } return rval end local function reg_temperature(addr, i) local haddr = string.format("%05d", addr) local rval = { tag = string.format("RkCeTemp%03d", i), name = string.format("单体温度%03d(℃)", i), desc = "", property = "realdata", history = "period", type = "float", offset = 0, scale = 0.1, prot = { [1] = 4, [2] = haddr, [3] = "int", [4] = "AB", [5] = 0, [6] = 1, [7] = 0 }, } return rval end local function reg_pole_temp(addr, i) local haddr = string.format("%d", addr) local rval = { tag = string.format("PositivePoleTemp%d+", i), name = string.format("正极柱温度%d+(℃)", i), desc = "", property = "realdata", history = "period", type = "float", offset = 0, scale = 0.1, prot = { [1] = 4, [2] = haddr, [3] = "int", [4] = "AB", [5] = 0, [6] = 0, [7] = 0 }, } return rval end local function reg_pole_temp2(addr, i) local haddr = string.format("%d", addr) local rval = { tag = string.format("NegativePoleTemp%d-", i), name = string.format("负极柱温度%d-(℃)", i), desc = "", property = "realdata", history = "period", type = "float", offset = 0, scale = 0.1, prot = { [1] = 4, [2] = haddr, [3] = "int", [4] = "AB", [5] = 0, [6] = 0, [7] = 0 }, } return rval end local function mainfunc() local jcfg = json_skeleton() -- add Voltage address poll list local addr, cnt = g_vaddr_start, 0 while cnt < g_vnum do local numr = g_vnum - cnt if numr > g_poll_maxnum then numr = g_poll_maxnum end local plist = jcfg.poll_list plist[#plist + 1] = poll_list(addr, numr) cnt, addr = cnt + numr, addr + numr end -- add Temperature address poll list addr, cnt = g_taddr_start, 0 while cnt < g_tnum do local numr = g_tnum - cnt if numr > g_poll_maxnum then numr = g_poll_maxnum end local plist = jcfg.poll_list plist[#plist + 1] = poll_list(addr, numr) cnt, addr = cnt + numr, addr + numr end -- add Pole Temperature address poll list addr, cnt = g_ptaddr_start, 0 while cnt < g_ptnum do local numr = g_ptnum - cnt if numr > g_poll_maxnum then numr = g_poll_maxnum end local plist = jcfg.poll_list plist[#plist + 1] = poll_list(addr, numr) cnt, addr = cnt + numr, addr + numr end -- add Pole Temperature address poll list addr, cnt = g_ptaddr_start2, 0 while cnt < g_ntnum do local numr = g_ntnum - cnt if numr > g_poll_maxnum then numr = g_poll_maxnum end local plist = jcfg.poll_list plist[#plist + 1] = poll_list(addr, numr) cnt, addr = cnt + numr, addr + numr end -- add Voltage tags addr, cnt = g_vaddr_start, 1 while cnt <= g_vnum do local rreg = jcfg.read_reg rreg[#rreg + 1] = reg_voltage(addr, cnt) cnt, addr = cnt + 1, addr + 1 end -- add Temperature tags addr, cnt = g_taddr_start, 1 while cnt <= g_tnum do local rreg = jcfg.read_reg rreg[#rreg + 1] = reg_temperature(addr, cnt) cnt, addr = cnt + 1, addr + 1 end -- local addr1, addr2 = g_ptaddr_start, g_ptaddr_start2 -- local cnt = 1 -- while cnt <= g_ptnum/2 do -- local rreg = jcfg.read_reg -- -- 交替写入两个地址的数据 -- rreg[#rreg + 1] = reg_pole_temp(addr1, cnt) -- rreg[#rreg + 1] = reg_pole_temp2(addr2, cnt) -- cnt = cnt + 1 -- addr1, addr2 = addr1 + 1, addr2 + 1 -- end -- add pt Temperature tags addr, cnt = g_ptaddr_start, 1 while cnt <= g_ptnum do local rreg = jcfg.read_reg rreg[#rreg + 1] = reg_pole_temp(addr, cnt) cnt, addr = cnt + 1, addr + 1 end -- add pt Temperature tags addr, cnt = g_ptaddr_start2, 1 while cnt <= g_ntnum do local rreg = jcfg.read_reg rreg[#rreg + 1] = reg_pole_temp2(addr, cnt) cnt, addr = cnt + 1, addr + 1 end local output = cjson.encode(jcfg) local outfile = string.format("/app/template/%s-LUAGEN-%s.json", g_name, g_md5sum:sub(1, 12)) io.stdout:write(string.format("Writing configuration file: %s\n", outfile)) io.stdout:flush() local out = io.open(outfile, "wb") if out then out:write(output) out:close() else io.stderr:write(string.format("Error, failed to open '%s' for writing.\n", outfile)) io.stderr:flush() return false end return true end function fetch_info() local retval = json_skeleton() return cjson.encode(retval.info) end if type(arg) == "table" then if not parse_name(arg[0]) then os.exit(1) end if not parse_args(arg[1]) then os.exit(2) end os.exit(mainfunc() and 0 or 3) end