require "log" require "sys" require "utils" require "patch" lpack=require("lua_pack") MQTT=require("mqtt_library") base64=require("base64") dyutils=require("dyutils") ----------------------[MODBUS write data]-------------------------- local function write_once_register(obj,start,data,cmd) return 0x05,start,nil,nil,data end local function read_coil(obj,start,len,cmd) return cmd or 0x02,start,len end ----------------------[控制服务]-------------------------- local function control_general(obj) local field={"","TAG_520","TAG_51E"} for i,key in ipairs(field) do if key and #key > 0 and obj[key] then local data = bpack(">S",obj[key]) return write_once_register(obj,i-1,data) end end end local function response_general(raw_data, len) local obj={} return obj end local list={} local last={} local function response_DIRead(raw_data, len) local DEEP = 2 local obj={} local field={"","TAG_579","TAG_4B2","TAG_519","TAG_6A5","TAG_6A6","TAG_6A7"} local _, DIRead= bunpack(raw_data," 0 then -- log.info(nil,DIRead,key) obj[key] = bit.band(bit.rshift(DIRead,i-1),1) end end local out={} table.insert(list,obj) if #list > DEEP then table.remove(list,1) end -- log.info(nil,"==============",#list) if #list < DEEP then out = obj else for i,key in ipairs(field) do --每个key都经行比对 if key and #key > 0 then local diff for _,hist in ipairs(list) do if hist[key] ~= obj[key] then diff = true break end end if diff then out[key] = last[key] else out[key] = obj[key] end end end end last = out return out end global_identifier_func_tab = { { identifier="DIRead", create_bin_func=read_coil, create_bin_args={0,0x10,0x02}, parser_bin_func=response_DIRead }, { identifier="DOfireall", create_bin_func=control_general, create_bin_args={nil,nil}, parser_bin_func=response_general }, { identifier="DOfire1", create_bin_func=control_general, create_bin_args={nil,nil}, parser_bin_func=response_general }, } function protocol_encode(json_str, len) local err_code=0 -- 取出入参-- local obj=cjson.decode(json_str) local id=obj.identifier local server_period=obj.server_period local dev_sn=obj.sn local addr=1 local raw_data=nil for i,v in pairs(global_identifier_func_tab) do if v.identifier == id then local call_func = v.create_bin_func local func,start,len,data_len,data = call_func(obj,v.create_bin_args[1],v.create_bin_args[2],v.create_bin_args[3]) if not func then log.error(nil, "invalid function code") return end local bin=nil if not len then raw_data = bpack("CC>S",addr,func,start) for i = 1, #data do raw_data = raw_data .. bpack("c",data:byte(i)) end elseif not data then raw_data = bpack("CC>S>S",addr,func,start,len) else raw_data = bpack("CC>S>SC",addr,func,start,len,data_len) 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)) 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,#t_str) return err_code, t_str, #t_str end end return -1, nil, 0 end function protocol_decode(input_str, len) -- log.info(nil,input_str); local err_code=0 --取出入参-- local obj={} local input_obj=cjson.decode(input_str) local id=input_obj.identifier local bin_str=input_obj.raw_data --入参中的raw_data的二进制转换-- --入参中的raw_data的二进制转换-- if not bin_str or #bin_str < 6 then print(string.format( "Input args failed,args:%s",input_str)) return nil end local t_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 raw_data=t_str _,addr,func = bunpack(raw_data,"CC") local addr = 1 local crc = dyutils.CRC16(raw_data,#raw_data - 2) _,crc_pack = bunpack(string.sub(raw_data,#raw_data - 1),">S") if (crc ~= crc_pack) then log.info(nil,string.format( "Data crc check failed cal:%04X packet:%04X",crc,crc_pack)) return nil end for i,v in pairs(global_identifier_func_tab) do log.info(nil,v.identifier ,id) if v.identifier == id then local call_func = v.parser_bin_func local data,data_len = nil,0 if func == 0x05 then data_len = #raw_data - 5 - 1 data = string.sub(raw_data,5,-3) elseif func == 0x01 or func == 0x02 or func == 0x03 or func == 0x04 then data_len = #raw_data - 4 - 1 data = string.sub(raw_data,4,-3) elseif func == 0x10 then data_len = 0 data = nil else log.info(string.format( "unknow function code %02X",func)) return -1 end log.info(nil,"protocol_decode","protocol_decode raw_data ",string.toHex(data) ) local json_obj = call_func(data,data_len)-- 调用不同的函数执行解析数据 if not json_obj then -- log.info("decode failed,raw_data",string.toHex(data),data_len) log.warn("protocol_decode","decode failed,raw_data:",string.toHex(data)) return end json_obj.identifier=id -- 返回调用标识 json_obj.term_addr=string.format( "%02X",addr) 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 -- protocol_encode('{"sn":"21880A0002FE_DI","identifier":"DIRead","server_period":2000,"term_addr":"01"}'); -- protocol_decode('{"raw_data":"0102020000B9B8","identifier":"DIRead","sn":"21880A0002FE_DI"}') -- protocol_encode('{"identifier":"DOfireall","sn":"21880A0002FE_DI","mi":84724073,"TAG_520":6,"timestamp":1658220984,"term_addr":"01"}')