require "log" require "sys" require "utils" require "patch" require "pack" siganl = require 'posix.signal' syswait = require 'posix.sys.wait' unistd = require 'posix.unistd' mqtt=require "mosquitto" base64=require("base64") dyutils=require("dyutils") lpack=require("lua_pack") require "internal_api" SELECT_SCHEDULES_FILE = "/app/sim_data/bms-rack.json" dev_sn="" gw_sn="" FILE_EXSIT = 1 ERROR_STATUS = 1 local vol_flag = "RackCellVoltage" local temp_flag = "RackCellTemperature" local addrs = 2 local rep_time = 30000 local devs = {} local bat_number_list = {} local temp_number_list = {} local bat_regaddr_index = {} local temp_regaddr_index = {} local vol_regaddr = 0x2400 local temp_regaddr = 0x2600 local connect_port = "RS485_1" LOG_LEVEL = log.LOG_LEVEL_DEBUG data={ RackCellVoltage={}, RackCellTemperature={} } local function handler() local pid, status, code = syswait.wait(-1, syswait.WNOHANG) log.error('system exit', pid, status, code) -- 打印不出来 os.exit(0) end function read_from_485cache(gw_sn,port,dev_sn,identifier,addr,regaddr,regsize,mi) local hex = ex_pack(addr,0x4,regaddr,regsize) log.info(gw_sn,dev_sn,port,identifier,hex,rep_time,mi) internal_api.pp2south(gw_sn,dev_sn,port,identifier,hex,rep_time,mi) end local function data2tag(data, flag) obj={} for i=0,(#data)/2-1 do local _, v= bunpack(data,">s") data = string.sub(data,2 + 1 ,-1) if flag == vol_flag then obj[string.format("TAG_C%X",848+i)] = 0.001*v elseif flag == temp_flag then obj[string.format("TAG_C%X",881+i)] = 0.1*v end end return obj end -- ! @brief 模块功能:485cache 组包 -- ! @param addr: 设备地址 -- ! @param func: 功能码 -- ! @param regaddr: 寄存器地址 -- ! @param regsize: 寄存个数 -- ! @param data: 写操作时:寄存器个数 *2 字节;读操作时:0 -- ! @return -- ! @retval raw_data: 返回二进制数据 function ex_pack(addr, func, regaddr, regsize, data) log.info("485cache_api", addr, func, string.format("0x%04X", regaddr),regsize, data and string.toHex(data)) local raw_data = nil if not addr or not func or not regaddr or not regsize then log.warn("ex_pack", "修改设备层级") return nil end raw_data = bpack("CC>S>S", addr, func, regaddr, regsize) -- 有数据增加二进制数据 if data and #data > 0 then if func == 0x01 and #data ~= regsize / 2 then log.warn("ex_pack",string.format("buff size and regsize are conflict, size:%d,regsize:%d",#data, regsize)) return nil end for i = 1, #data do raw_data = raw_data .. bpack("C", data:byte(i)) end end raw_data = raw_data .. bpack(">S", dyutils.CRC16(raw_data, #raw_data)) return raw_data end -- ! @brief 模块功能:485cache 拆包 -- ! @param raw_data: 输入二进制数据 -- ! @return -- ! @retval result: 返回结果 -- ! @retval level: 设备层级 -- ! @retval addr: 设备地址 -- ! @retval func: 功能码 -- ! @retval regaddr: 寄存器地址 -- ! @retval regsize: 寄存个数 -- ! @retval data: 写操作时:寄存器个数 *2 字节;读操作时:0 function ex_unpack(raw_data) -- 取出入参-- local obj = {} log.info("read responce:",string.toHex(raw_data)) local _, addr, func, regaddr, regsize, skip_len _, addr, func, bytes = bunpack(raw_data, "CCC") skip_len = 3 local crc = dyutils.CRC16(raw_data, #raw_data - 2) local _, crc_pack = bunpack(string.sub(raw_data, #raw_data - 1), ">S") if (crc ~= crc_pack) then log.warn("ex_unpack", string.format("Data crc check failed cal:0x%04X packet:0x%04X", crc,crc_pack)) return nil end if #raw_data - skip_len <= 2 then return nil end local data = string.sub(raw_data, skip_len + 1, -3) log.info("485cache_resopnse", addr, func, regaddr, regsize,string.toHex(data)) return true, addr, func, regaddr, regsize, data end local function iot2app(topic,payload) log.info(nil,"payload:",payload) ubuslog.log(ubuslog.LOG_NOTICE, "payload: ",payload) local obj = cjson.decode(payload) if string.find(topic,dev_sn) then local err_code = 0 local identifier = obj.identifier local server_period = obj.server_period local dev_sn = obj.sn if obj.identifier == "null" then log.warn("iot2pp", "Need device sn in payload") ubuslog.log(ubuslog.LOG_NOTICE, "iot2pp", "Need device sn in payload") return 0, "", 0 end local pack_index = tonumber(dev_sn:match(".+%_(%w+)$"),10) -- 不能直接解析,并发往端口,使用脚本的处理的内容 if obj.identifier == vol_flag then read_from_485cache(gw_sn, connect_port,devs[pack_index],vol_flag, addrs, bat_regaddr_index[pack_index],bat_number_list[pack_index],obj.mi) elseif obj.identifier == temp_flag then read_from_485cache(gw_sn, connect_port,devs[pack_index],temp_flag, addrs,temp_regaddr_index[pack_index],temp_number_list[pack_index],obj.mi) end return -1, nil, 0 end end local function port2pp(topic,payload) log.info(nil,"payload:",payload) local obj = cjson.decode(payload) if not obj or not obj.src_identifier then return end if not obj.data_b64 then return end local raw_data = base64.decode(obj.data_b64) if not raw_data then return end log.info("raw_data",raw_data) local result, addr, func, regaddr, regsize, data = ex_unpack(raw_data) log.info(result, addr, func, regaddr, regsize, data) local curr = os.time() if string.find(topic,dev_sn) then if result then if addr > 1 then if obj.src_identifier == vol_flag then internal_api.pp2north(gw_sn,obj.sn,connect_port,vol_flag,data2tag(data,vol_flag),0) elseif obj.src_identifier == temp_flag then internal_api.pp2north(gw_sn,obj.sn,connect_port,temp_flag,data2tag(data,temp_flag),0) end return end end end end function main(nodes_cfg, sn) ubuslog.log_reinit('bms_upgrade_process', true) ubuslog.loglevel_set(ubuslog.LOG_INFO) ubuslog.log(ubuslog.LOG_NOTICE, "main_loop", "================== rack upgrade ============") ubuslog.log(ubuslog.LOG_NOTICE, "nodes_cfg: ", nodes_cfg) ubuslog.log(ubuslog.LOG_NOTICE, "sn: ", sn) gw_sn = sn log.info(gw_sn) objs = cjson.decode(nodes_cfg) if objs and #objs > 0 then for _,obj in ipairs(objs) do if obj.ext_data and #obj.ext_data >2 then local ext = string.gsub(obj.ext_data,"\\\"","\"",99999) local ext_obj = cjson.decode(ext) local index = tonumber(obj.sn:match(".+%_(%w+)$"),10) devs[index] = obj.sn bat_number_list[index] = ext_obj["battery_number"] temp_number_list[index] = ext_obj["t_sensor_number"] end end bat_regaddr_index[1] = vol_regaddr temp_regaddr_index[1] = temp_regaddr for i=2, #devs do bat_regaddr_index[i] = bat_regaddr_index[i-1] + bat_number_list[i-1] temp_regaddr_index[i] = temp_regaddr_index[i-1] + temp_number_list[i-1] end ubuslog.log(ubuslog.LOG_NOTICE, "bat_number:",cjson.encode(bat_number_list)) ubuslog.log(ubuslog.LOG_NOTICE, "temp_number:",cjson.encode(temp_number_list)) end ubuslog.log(ubuslog.LOG_NOTICE, "device list:",cjson.encode(devs)) siganl.signal(siganl.SIGKILL,handler) siganl.signal(siganl.SIGHUP,handler) internal_api.local_mqtt_session(devs,"PP",iot2app,port2pp) --启动系统框架 sys.init(0, 0) sys.run() end main(arg[1],arg[2])