cjson=require("cjson") MQTT=require("mqtt_library") base64=require("base64") bit=require("bit") lpack=require("lua_pack") syslog=require("syslog") require("utils") 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) syslog.openlog("GoodWe upgrade", syslog.LOG_PERROR + syslog.LOG_ODELAY, "LOG_USER") broker_addr = "localhost" broker_port = 1883 once_block_max = 64 upgrade_num = 1 --升级编号 process_total = 1 process_curr = 1 serial_num = 1001 time_last = 0 function on_mqtt_msg(topic, payload) -- application specific code -- print("receive ", topic, payload); payload_obj = cjson.decode(payload) if(string.find(payload_obj['src_identifier'],'__transparent') ~= nil)then coroutine.yield(topic, payload_obj) 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 function send_data_to_sn(mqtt_client, gw_sn, dev_sn, mi, data, obj_send) topic = obj_send['topic'] obj_send['mi'] = mi obj_send['len'] = #data obj_send['data_b64'] = base64.encode(data) obj_send['sn'] = dev_sn json_str = cjson.encode(obj_send) mqtt_client:publish(topic, json_str) -- print("send_data_to_dev",topic,json_str) time_last = os.time() end function send_upgrade_process(mqtt_client, gw_sn, dev_sn, mi, Upgrade_Status, Upgrade_Progress) 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-Upgrade_Progress%0.01 payload['tags'] = progress json_str = cjson.encode(payload) -- print(topic,json_str) mqtt_client:publish(topic, json_str) end function wait_response(dev_sn,mi) local received = false local loop = true while(loop)do repeat ret, topic, payload_obj = coroutine.resume(mqtt) if(payload_obj == nil or topic == nil)then syslog.syslog("LOG_WARNING", "miss resoponse,timeout") os.execute("sleep 1") loop = false break end if(payload_obj == nil or payload_obj.mi == nil or payload_obj.data_b64 == nil)then syslog.syslog("LOG_WARNING", string.format("miss resoponse,slave node not ack", topic)) os.execute("sleep 1") loop = false break end received = true loop = false until true end if(received == false)then return false,-1 end local rcv_bin = base64.decode(payload_obj.data_b64) local _,response = bunpack(rcv_bin,"C") if ret == true and payload_obj and payload_obj.sn == dev_sn and payload_obj.mi == mi then if response and response == 0x06 then return true elseif response and response == 0x01 then syslog.syslog("LOG_WARNING", "you need to resend the last 4096 bytes(64packs)") send_upgrade_process(mqtt_client, gw_sn, dev_sn, serial_num, "failed", process_curr*100/process_total) serial_num = serial_num + 1 return false,-6 elseif response and response == 0x15 then send_upgrade_process(mqtt_client, gw_sn, dev_sn, serial_num, "failed", process_curr*100/process_total) serial_num = serial_num + 1 syslog.syslog("LOG_WARNING", "flash process is failed") return false,-7 else syslog.syslog("LOG_WARNING", string.format("error response code %d",response or 0)) return false,-8 end end return false,-99 end function upgrade_node(json_str, gw_sn, firmware, send_out_json) local obj=cjson.decode(json_str) local dev_sn = obj['sn'] local obj_send = cjson.decode(send_out_json) local ret, topic, payload_obj mqtt_client = MQTT.client.create(broker_addr, broker_port, on_mqtt_msg) mqtt_client:connect("upgrade_GoogWe") local topic={} topic[1] = string.format("ipc/%s/+/device/+/data/raw_data", gw_sn) -- print(topic[1]) mqtt_client:subscribe(topic) mqtt = coroutine.create(mqtt_listen) -- 获取firmware的version信息 dev_type,_,firmware_version = string.match(firmware,"(.*)_(.-)-(.+)[(]") syslog.syslog("LOG_INFO", "firmware version:"..(firmware_version or "")) syslog.syslog("LOG_INFO", "device type version:"..(dev_type or "")) --  Read the BIN file; file = io.open(firmware, "r") if(file == nil)then syslog.syslog("LOG_WARNING", "fetch nodes config file failed!") return -1 end local bin_buf = file:read("*a") file:seek("set") local index = 0 local total = #bin_buf syslog.syslog("LOG_INFO", "firmware size %dbytes:"..total) blks={} blks.head=string.sub(bin_buf,1,32) bin_buf=string.sub(bin_buf,32 + 1,-1) total = total - 32 while (total > 0) do local blk_size if(total >= once_block_max) then blk_size = once_block_max else blk_size = total end blk={} blk['data']=string.sub(bin_buf,once_block_max*index + 1,once_block_max*index + blk_size) table.insert(blks,blk) if(#blks >= 20000)then syslog.syslog("LOG_ERR", string.format("upgread block too large %d",#blks)) return -2 end total = total-blk_size; index = index + 1; end syslog.syslog("LOG_INFO", string.format("block split done ,size:%d",#blks)) file:close() process_total = process_total + #blks send_upgrade_process(mqtt_client, gw_sn, dev_sn, serial_num, "start", 0) serial_num = serial_num + 1 -- Send string “FLASHDSP” to enter flash dsp mode; if obj.Dev_Type and string.upper(obj.Dev_Type) == "DSP" then syslog.syslog("LOG_INFO", string.format("send FLASHDSP")) local retry,i = 3,0 process_total = process_total + retry while (i < retry) do i=i+1 send_data_to_sn(mqtt_client, gw_sn, dev_sn, 900, "FLASHDSP", obj_send) local ret = wait_response(dev_sn,900) if ret then send_upgrade_process(mqtt_client, gw_sn, dev_sn, serial_num, "start", process_curr*100/process_total) serial_num = serial_num + 1 break else syslog.syslog("LOG_WARNING", string.format("FLASHDSP not response!")) end end if i >= retry then syslog.syslog("LOG_ERR", string.format("Upgrade exit,due to miss response!")) return -3 end end --  Send the first 32 bytes dates head, and wait for 0x06 local retry,i = 3,0 process_total = process_total + retry while (i < retry) do i=i+1 send_data_to_sn(mqtt_client, gw_sn, dev_sn, 901, blks.head, obj_send) local ret = wait_response(dev_sn,901) if ret then send_upgrade_process(mqtt_client, gw_sn, dev_sn, serial_num, "start", process_curr*100/process_total) serial_num = serial_num + 1 break else syslog.syslog("LOG_WARNING", string.format("Send head not response!")) end end if i >= retry then syslog.syslog("LOG_ERR", string.format("Upgrade exit,due to miss response!")) return -3 end -- Send the left dates as 64bytes packs, and wait for 0x06 for every packs that the ARM will local last_process = process_curr for key,value in ipairs(blks) do if process_curr - last_process >= 30 then --省流量 last_process = process_curr send_upgrade_process(mqtt_client, gw_sn, dev_sn, serial_num, 'upgrading', process_curr*100/process_total) serial_num = serial_num + 1 end local retry,i = 3,0 while (i < retry) do i=i+1 send_data_to_sn(mqtt_client, gw_sn, dev_sn, 902, value['data'], obj_send) local ret = wait_response(dev_sn,902) if ret then break else syslog.syslog("LOG_WARNING", string.format("Send binary file not response!")) end end if i >= retry then syslog.syslog("LOG_ERR", string.format("Upgrade exit,due to miss response!")) send_upgrade_process(mqtt_client, gw_sn, dev_sn, serial_num, 'failed', process_curr*100/process_total) serial_num = serial_num + 1 return -3 end process_curr = process_curr + 1 syslog.syslog("LOG_INFO", string.format("send upgrade data %d/%d",key,#blks)) end -- Send string “EXITFLASH” to enter flash dsp mode; if obj.Dev_Type and string.upper(obj.Dev_Type) == "DSP" then send_data_to_sn(mqtt_client, gw_sn, dev_sn, 900, "EXITFLASH", obj_send) end send_upgrade_process(mqtt_client, gw_sn, dev_sn, serial_num, "done", 100) serial_num = serial_num + 1 return 0 end -- json_str='{\ -- "identifier": "__Upgrade",\ -- "Action": "start",\ -- "Timeout": "0",\ -- "Dev_Type": "ARM",\ -- "sn": "YuM4OMud",\ -- "mi": 36684239,\ -- "URL": "http://10.3.1.229:8002/TEST1_26_V1084.bin",\ -- "MD5": "ac3ee42ae30ef8ce8bfa513ac22f1de1",\ -- "timestamp": 1586336532\ -- }' -- gw_sn='21012C000038' -- firmware= './ARM_410-02034-09_S00_new.bin' -- -- firmware= './DSP_410-04029-03(v124).bin' -- send_out_json= '{\ -- "data_b64": "",\ -- "len": 0,\ -- "period": 0,\ -- "port": "RS485_1",\ -- "mi": 0,\ -- "src_identifier": "__transparent",\ -- "sn": "YuM4OMud",\ -- "dtu_sn": "",\ -- "protocol": 1,\ -- "communication_timeout": 0,\ -- "term_addr": "00F7000000000000",\ -- "tcp_ip_addr": "",\ -- "tcp_port": 0,\ -- "topic": "ipc/21012C000038/RS485_1/device/7uaH0Lgo/data/Set_Rglt_Raw"\ -- } ' -- upgrade_node(json_str,gw_sn,firmware,send_out_json)