cjson=require("cjson") MQTT=require("mqtt_library") base64=require("base64") dyutils=require("dyutils") bit=require("bit") lpack=require("lua_pack") syslog=require("syslog") bcd=require("bcd") sqlite3=require("lsqlite3") bnot = bit.bnot band, bor, bxor = bit.band, bit.bor, bit.bxor lshift, rshift, rol = bit.lshift, bit.rshift, bit.rol --MQTT.Utility.set_debug(true) broker_addr = "localhost" broker_port = 1883 block_size = 96 time_last = 0 fail_cnt = 0 offset_Level1Id=2 offset_Level2Id=1 offset_Level3Id=0 stop_flag = 0 function on_mqtt_msg(topic, payload) -- application specific code --print("receive ", topic, payload); if string.match(topic, "Notify_Upgrade") ~= nil then if payload == "stop_upgrade" then stop_flag = 1 end else payload_obj = cjson.decode(payload) if (payload_obj['src_identifier'] == '__transparent') then coroutine.yield(topic, payload_obj) end end end function mqtt_listen() while(true) do if(time_last ~= 0 and os.time() >= (time_last + 5)) then coroutine.yield(nil, nil) end mqtt_client:handler() end end -- send data to dev_sn function send_data_to_sn(mqtt_client, gw_sn, dev_sn, mi, datas, obj_send) topic = obj_send['topic'] obj_send['mi'] = mi for key, value in ipairs(datas) do obj_send['len'] = #value obj_send['data_b64'] = base64.encode(value) json_str = cjson.encode(obj_send) --print(json_str) mqtt_client:publish(topic, json_str) --print("Publish, topic:"..topic.." data:"..json_str) end time_last = os.time() end -- send data to dev_sn function send_upgrade_process(mqtt_client, gw_sn, dev_sn, mi, Upgrade_Status, Upgrade_Progress) --ipc/[GW_SN]/+/device/+/data_filtered/event/+ topic = string.format("ipc/%s/upgrade/device/%s/data_filtered/event/__Upgrade_Progress", gw_sn, dev_sn) local payload={} payload['identifier'] = '__Upgrade_Progress' payload['sn'] = dev_sn payload['mi'] = mi payload['time'] = os.time() local progress = {} progress['Upgrade_Status'] = Upgrade_Status progress['Upgrade_Progress'] = Upgrade_Progress payload['tags'] = progress json_str = cjson.encode(payload) --print(json_str) mqtt_client:publish(topic, json_str) end function upgrade_node(json_str, gw_sn, firmware, send_out_json) local obj=cjson.decode(json_str) local obj_send = cjson.decode(send_out_json) local ret = 0 local mi = 1000 local can_id = nil syslog.syslog("LOG_WARNING", "json_str"..json_str) syslog.syslog("LOG_WARNING", "gw_sn"..gw_sn) syslog.syslog("LOG_WARNING", "firmware"..firmware) syslog.syslog("LOG_WARNING", "send_out_json"..send_out_json) mqtt_client = MQTT.client.create(broker_addr, broker_port, on_mqtt_msg) mqtt_client:connect("upgrade_xieneng") topic = string.format("ipc/%s/+/device/%s/data/raw_data", gw_sn, obj['sn']) mqtt_client:subscribe({topic}) topic = string.format("ipc/+/+/Notify_Upgrade") mqtt_client:subscribe({topic}) mqtt = coroutine.create(mqtt_listen) -- 获取firmware的version信息 print("firmware Version") L3_ID = obj.L1_DevId + offset_Level3Id -- L3从控-0; L2设备-1; L1设备-2; L3-均衡-3 if obj.Dev_Type == 0 then -- 从控设备 can_id = 0x7FF elseif obj.Dev_Type == 1 then -- 主控 elseif obj.Dev_Type == 2 then -- 总控 elseif obj.Dev_Type == 3 then -- 均衡设备 can_id = 0x7FA end if can_id == nil then syslog.syslog("LOG_ERR", "Wrong Dev_Type"..obj.Dev_Type) return -1 end addr = get_target_addr(obj) file = io.open(firmware, "r") local bin_buf = file:read("*a") local reminder = #bin_buf%4 reminder = 4 - reminder while (reminder ~= 0) do reminder=reminder-1 bin_buf=bpack("AC", bin_buf, 0) end print("bin_buf length:"..#bin_buf) -- send data file:seek("set") local offset = 0 local last_progress = 0 local crc=0 local can_groups = {} while (true) do if stop_flag == 1 then break end if (offset >= #bin_buf) then break end --Step2. 上位机从bin_buf中读出L字节数据, 记为data[L],最后一包不足L,按照实际剩余字节读取,后续为描述方便还是以L描述。 block_data = string.sub(bin_buf, offset+1, offset+block_size) if not block_data then print("read data failed") break end --Step3. 在data[L]前面用小端模式拼接offset(4Byte),offset是data[L]在bin文件中的起始地址,变成data[L+4]。 local block_pkt = bpack(" 10) then send_upgrade_process(mqtt_client, gw_sn, obj['sn'], mi, "failed", 0) syslog.syslog("LOG_ERR", "return -1, fail_cnt:%d", fail_cnt) return -1 end break end end end else fail_cnt = fail_cnt + 1 if (fail_cnt > 10) then send_upgrade_process(mqtt_client, gw_sn, obj['sn'], mi, "failed", 0) syslog.syslog("LOG_ERR", "return -2, fail_cnt:%d", fail_cnt) return -2 end break end end if this_pkt_pass ~= 0 then break end end end print("verify stage") --发送校验 --对应Step2,将bin内容发送完毕后,发送一个内容为4Byte校验码,校验码算法见附录3,对整个bin_buf的内容进行校验。 local file_check = dyutils.CalculateXorCrc(bin_buf, #bin_buf) file_check = tonumber(string.format("%u", file_check)) print(file_check) --Step3. 在data[L]前面用小端模式拼接offset(4Byte),offset是data[L]在bin文件中的起始地址,变成data[L+4]。 --对应Step3,偏移即为整个bin_buf长度。 local check_pkt = bpack(" 10) then send_upgrade_process(mqtt_client, gw_sn, obj['sn'], mi, "failed", 0) return -3 end ret = -1 end end end else fail_cnt = fail_cnt + 1 if (fail_cnt > 10) then send_upgrade_process(mqtt_client, gw_sn, obj['sn'], mi, "failed", 0) return -4 end end end if this_pkt_pass ~= 0 then break end end mi = mi + 1 if (ret == 0) then if (obj.Reset == 1) then print("reset") local cmdHwId = get_target_addr(obj) local data = string.format("0x%08X SetDebugPara 0x12345678 0 0x12345678", cmdHwId); syslog.syslog("LOG_WARNING", "===>data") can_frames = gen_raw_can_frame(can_id, data) send_data_to_sn(mqtt_client, gw_sn, obj['sn'], mi, can_frames, obj_send) local data = string.format("0x%08X reset", cmdHwId); syslog.syslog("LOG_WARNING", "===>data") can_frames = gen_raw_can_frame(can_id, data) send_data_to_sn(mqtt_client, gw_sn, obj['sn'], mi, can_frames, obj_send) end end mi = mi + 1 if (ret == 0) then send_upgrade_process(mqtt_client, gw_sn, obj['sn'], mi, "success", 100) else send_upgrade_process(mqtt_client, gw_sn, obj['sn'], mi, "failed", 0) end return ret end -- generate can frame with can_id function gen_raw_can_frame(can_id, data) local result = {} local header=0 local index = 0 local can_frame = 0 local crc=0 --组成消息头 header = lshift(1, 12) header = bor(header, lshift(6, 16)) header = bor(header, lshift(1, 21)) crc = dyutils.CRC16(data, #data) can_frame = bpack("= #data) then break end local block_data = string.sub(data, offset+1, offset+4) if not block_data then print("read data failed") break end header = 0 header = bor(lshift(2, 12), index) header = bor(header, lshift(6, 16)) header = bor(header, lshift(1, 21)) can_frame = bpack("