dyutils=require("dyutils") bit=require("bit") lpack=require("lua_pack") cjson=require("cjson") base64=require("base64") -- syslog = require("syslog") bnot = bit.bnot band, bor, bxor = bit.band, bit.bor, bit.bxor lshift, rshift, rol = bit.lshift, bit.rshift, bit.rol -- syslog.openlog("peicheng.lua", syslog.LOG_PERROR + syslog.LOG_ODELAY, "LOG_USER") -- syslog.syslog("LOG_WARNING", "Hi all " .. os.time()) ----------------------[pack numbers]-------------------------- function requset_pack_number(obj) return "90","00" end function response_pack_number(raw_data, len) obj={} -- string.sub(raw_data, offset,offset-1+2 ) offset = offset + 2 -- LENID obj.pack_num = tonumber(string.sub(raw_data, 1,2 )) return obj end ----------------------[analog read]-------------------------- function requset_pack_analog(obj) return "42",string.format("%02X",obj.packid) end function response_pack_analog(raw_data, len) obj={} offset=1 string.sub(raw_data, offset,offset-1+2 ) offset = offset + 2 -- LENID pack_num = string.sub(raw_data, offset,offset-1+2 ) offset = offset + 2 if(pack_num == nil)then print("warning","pack_num == nil") return nil end obj.pack_num = tonumber(pack_num,16) ------------------------[采集电池单体]------------------------ obj.bat_unit_num = tonumber(string.sub(raw_data, offset,offset-1+2 ),16) offset = offset + 2 -- print("info:","bat num:",obj.bat_unit_num) -- if(obj.bat_unit_num)then -- for i=1,obj.bat_unit_num,1 do obj["bat_unit" .. tostring(i)] = tonumber(string.sub(raw_data, offset,offset-1+4 ),16) offset = offset + 4 end -- end obj.bat_unit={} if(obj.bat_unit_num)then for i=1,obj.bat_unit_num,1 do table.insert(obj.bat_unit,tonumber(string.sub(raw_data, offset,offset-1+4 ),16)) offset = offset + 4 end end ------------------------[采集温度]------------------------ obj.temp_unit_num = tonumber(string.sub(raw_data, offset,offset-1+2 ),16); offset = offset + 2 -- print("info:","temp num:",obj.temp_unit_num) -- if(obj.temp_unit_num)then -- for i=1,obj.temp_unit_num,1 do obj["temp_unit" .. tostring(i)] = (-2730 + tonumber(string.sub(raw_data, offset,offset-1+4 ),16))*0.1 offset = offset + 4 end -- end obj.temp_unit={} if(obj.temp_unit_num)then for i=1,obj.temp_unit_num,1 do table.insert(obj.temp_unit,(-2730 + tonumber(string.sub(raw_data, offset,offset-1+4 ),16))*0.1) offset = offset + 4 end end obj.pack_curr = 10 * tonumber(string.sub(raw_data, offset,offset-1+4 ),16) offset = offset + 4 obj.pack_vol = tonumber(string.sub(raw_data, offset,offset-1+4 ),16) offset = offset + 4 obj.pack_beleft_cap = 10 * tonumber(string.sub(raw_data, offset,offset-1+4 ),16) offset = offset + 4 obj.pack_user = tonumber(string.sub(raw_data, offset,offset-1+2 ),16) offset = offset + 2 obj.pack_total_cap = 10 * tonumber(string.sub(raw_data, offset,offset-1+4 ),16) offset = offset + 4 obj.pack_used_count = tonumber(string.sub(raw_data, offset,offset-1+4 ),16) offset = offset + 4 obj.pack_design_cap = 10 * tonumber(string.sub(raw_data, offset,offset-1+4 ),16) offset = offset + 4 return obj end ----------------------[analog capacity]-------------------------- function requset_pack_capacity(obj) return "A6",string.format("%02X",obj.packid) end function response_pack_capacity(raw_data, len) obj={} offset=1 -- string.sub(raw_data, offset,offset-1+2 ) offset = offset + 2 -- LENID obj.pack_beleft_cap = 10 * tonumber(string.sub(raw_data, offset,offset-1+4 ),16) offset = offset + 4 obj.pack_total_cap = 10 * tonumber(string.sub(raw_data, offset,offset-1+4 ),16) offset = offset + 4 obj.pack_design_cap = 10 * tonumber(string.sub(raw_data, offset,offset-1+4 ),16) offset = offset + 4 return obj end ----------------------[charge MOSFET control]-------------------------- function control_charge_mos(obj) return "9A",string.format("%02X",obj.disable) end function response_charge_mos(raw_data, len) obj={} offset=1 -- string.sub(raw_data, offset,offset-1+2 ) offset = offset + 2 -- LENID obj.pack_beleft_cap = 10 * tonumber(string.sub(raw_data, offset,offset-1+4 ),16) offset = offset + 4 obj.pack_total_cap = 10 * tonumber(string.sub(raw_data, offset,offset-1+4 ),16) offset = offset + 4 obj.pack_design_cap = 10 * tonumber(string.sub(raw_data, offset,offset-1+4 ),16) offset = offset + 4 return obj end ----------------------[discharge MOSFET control]-------------------------- function control_discharge_mos(obj) return "9B",string.format("%02X",obj.packid) end function response_discharge_mos(raw_data, len) obj={} offset=1 -- string.sub(raw_data, offset,offset-1+2 ) offset = offset + 2 -- LENID obj.pack_beleft_cap = 10 * tonumber(string.sub(raw_data, offset,offset-1+4 ),16) offset = offset + 4 obj.pack_total_cap = 10 * tonumber(string.sub(raw_data, offset,offset-1+4 ),16) offset = offset + 4 obj.pack_design_cap = 10 * tonumber(string.sub(raw_data, offset,offset-1+4 ),16) offset = offset + 4 return obj end ----------------------[request product info]-------------------------- function requset_product_info(obj) return "C2","00" end function response_product_info(raw_data, len) obj={} offset=1 lenid = string.sub(raw_data, offset,offset-1+2 ) offset = offset + 2 -- LENID if(lenid == "50")then obj.bms_info = string.sub(raw_data, offset,offset-1+20 ) offset = offset + 20 obj.pack_info = string.sub(raw_data, offset,offset-1+20 ) offset = offset + 20 elseif(lenid == "28")then obj.bms_info = string.sub(raw_data, offset,offset-1+20 ) offset = offset + 20 obj.pack_info = '' end return obj end global_identifier_func_tab = { { identifier="requset_pack_analog", create_bin_func=requset_pack_analog, parser_bin_func=response_pack_analog }, { identifier="requset_pack_number", create_bin_func=requset_pack_number, parser_bin_func=response_pack_number }, { identifier="requset_pack_capacity", create_bin_func=requset_pack_capacity, parser_bin_func=response_pack_capacity }, { identifier="control_charge_mos", create_bin_func=control_charge_mos, parser_bin_func=response_charge_mos }, { identifier="control_discharge_mos", create_bin_func=control_discharge_mos, parser_bin_func=response_discharge_mos }, { identifier="requset_product_info", create_bin_func=requset_product_info, parser_bin_func=response_product_info } } ----------------------[packet process]-------------------------- function lenghsum_calculate(raw_data) local datalen = string.format("%03X",raw_data)--转为3个字符 local check_code=0 for i=0,2,1 do check_code=check_code+bit.band(raw_data,0xf) raw_data = bit.rshift(raw_data,4) end check_code = bit.bnot(bit.band(check_code,0xf))+1 return string.format("%1X",bit.band(check_code,0xf) ) .. datalen --拼接校验和长度 end function check_calculate(raw_data, len) local check_code=0 for i=2,len-5,1 do check_code=check_code+string.byte(raw_data,i) end return string.format("%1X%1X%1X%1X",bit.band(bit.rshift(bit.bnot(bit.band(check_code,0xffff))+1,12),0xf),bit.band(bit.rshift(bit.bnot(bit.band(check_code,0xffff))+1,8),0xf),bit.band(bit.rshift(bit.bnot(bit.band(check_code,0xffff))+1,4),0xf),bit.band(bit.rshift(bit.bnot(bit.band(check_code,0xffff))+1,0),0xf) ) -- print(string.format("%1X%1X%1X%1X",bit.band(bit.rshift(bit.bnot(bit.band(check_code,0xffff))+1,12),0xf),bit.band(bit.rshift(bit.bnot(bit.band(check_code,0xffff))+1,8),0xf),bit.band(bit.rshift(bit.bnot(bit.band(check_code,0xffff))+1,4),0xf),bit.band(bit.rshift(bit.bnot(bit.band(check_code,0xffff))+1,0),0xf) ) ) end function protocol_encode(json_str, len) local err_code=0 --取出入参-- local obj=cjson.decode(json_str) local id=obj.identifier obj.term_addr=tonumber(obj.term_addr,16) --编码-- -- print(json_str) if (id == "null") then return 0, "", 0 end local raw_data='' raw_data=raw_data .. string.char(0x7E) .. "25" .. (string.format("%02X", obj.term_addr)) .. "46" for i,v in pairs(global_identifier_func_tab) do if (v["identifier"] == id) then local call_func = v["create_bin_func"] local cid2,datainfo = call_func(obj) data_info="01" local lensum = lenghsum_calculate(string.len(datainfo)) raw_data=raw_data .. cid2 .. lensum .. datainfo raw_data=raw_data .. "****" .. string.char(0x0D)--"****"4个字符校验,填充位置,因为check_calculate计算需要全字符长度 local check_code = check_calculate(raw_data,string.len(raw_data)) raw_data = (string.gsub(raw_data, "%+****", check_code))--加括号表示仅仅返回替换后字符串 -- print("raw:",raw_data,string.len(raw_data))--TODO :控制字符居然没有显示 local t_str='' for i=1, #raw_data do t_str=t_str .. (string.format("%02X", string.byte(string.sub(raw_data, i, i)))) end print(t_str,string.len(raw_data)) return err_code, t_str, #t_str end end return -1, 0, 0 end function protocol_decode(input_str, len) local err_code=0 -- print(input_str) --取出入参-- local obj={} local input_obj=cjson.decode(input_str) local bin_str=input_obj.raw_data local id=input_obj.identifier --入参中的raw_data的二进制转换-- local t_str='' -- print("raw:",bin_str,string.len(bin_str)) for i=1,#bin_str,2 do t_str=t_str .. string.char(tonumber(string.sub(bin_str, i, i+1),16)) end local bin_str_len bin_str=t_str bin_str_len = string.len(bin_str) if (string.char(0x7E) ~= string.sub( t_str,0,1 ) ) then -- SOI print("SOI check failed") return nil end if (string.char(0x0D) ~= string.sub( t_str,-1 ) ) then -- EOI print("EOI check failed") return nil end local check_code check_code = check_calculate(t_str,string.len(t_str)) -- print(check_code) local tran_check_code = string.sub(t_str ,-5,-2) -- print(tran_check_code) -- print(type(tran_check_code),#tran_check_code, type(check_code),#check_code) if (tran_check_code ~= check_code) then print("Data check failed",tran_check_code,check_code) return nil end data_info_len = tonumber(string.sub(t_str,11,13 ),16) data_info = string.sub(t_str,14,-6) -- 仅仅提取出 DATAINFO ,仍然是HEX STRING流 for i,v in pairs(global_identifier_func_tab) do if (v["identifier"] == id) then local call_func = v["parser_bin_func"] local json_obj = call_func(data_info,data_info_len)-- 调用不同的函数执行解析数据 json_obj.identifier=id -- 返回调用标识 local json_str=cjson.encode(json_obj) print(err_code, json_str, #json_str) return err_code,json_str,#json_str end end return nil end test_bin='{"raw_data":"7E3235303034363030463037413030303131303044343230443134304431333044313330443133304431333044313330443133304431313044313230443133304431313044313130443132304431303044313330363042423730424237304242383042423630424233304242443030303044313535313238453033313338383030303031333838453341430D","identifier":"requset_pack_analog"}' -- test_bin='{"raw_data":"7E32353030343634344530313635304545454545464646464647474747474848484848464432460D","identifier":"requset_product_info"}' test_json='{"identifier":"requset_pack_analog","mi":14700894,"sn":"210165000001","timestamp":1571650303,"term_addr":"01","packid":2}' -- protocol_encode(test_json,string.len(test_json)) protocol_decode(test_bin,string.len(test_bin)) -- syslog.closelog()