from usr import modbus_rtu_serial from usr import ElectricFireDetector from umqtt import MQTTClient from misc import Power from machine import Pin from machine import UART import uos import sim import net import app_fota import request import modem import checkNet import ujson import utime import _thread PROJECT_NAME = "ElectricalGateway" PROJECT_VERSION = "0.0.1" with open('/usr/update_setting.json', mode='r') as f: local_update_setting = ujson.load(f) f.close() PROJECT_NAME = local_update_setting['app_name'] PROJECT_VERSION = local_update_setting['app_version'] checknet = checkNet.CheckNetwork(PROJECT_NAME, PROJECT_VERSION) usr_fota = app_fota.new() modbus_port = modbus_rtu_serial.Serial() config_port = UART(UART.UART0, 9600, 8, 0, 1, 0) STATUS_LED = Pin(Pin.GPIO2, Pin.OUT, Pin.PULL_DISABLE, 0) detectors = [] lock = _thread.allocate_lock() IMEI = modem.getDevImei() ICCID = sim.getIccid() CSQ = net.csqQueryPoll() settings = {} server = 'mqtt.vitalong.cn' port = 1883 mqtt_client = None publish_topic = "topic/W1/1/" + IMEI receive_topic = "topic/W1/2/" + IMEI sys_log = { 'stagecode': '', 'net_error': '', 'subcode': '', 'ICCID': ICCID, 'IMEI': IMEI, 'CSQ': CSQ, 'disconn_reason': 'no' } def update(): global local_update_setting print("开始检查更新...") try: response = request.get(url=local_update_setting['update_url'] + 'update_setting.json') server_update_setting = response.json() if local_update_setting['app_name'] == server_update_setting['app_name'] and local_update_setting[ 'app_version'] == \ server_update_setting['app_version']: print("已是最新版本,无需升级") elif local_update_setting['app_name'] == server_update_setting['app_name'] and local_update_setting[ 'app_version'] < \ server_update_setting['app_version']: print("检测到新版本:\r app name:\t{},\r app version:\t{},\r file list:\t{}\r开始升级...".format( server_update_setting['app_name'], server_update_setting['app_version'], server_update_setting['file_list'])) file_list = server_update_setting['file_list'].split(',') download_list = [] for file in file_list: dict_file = {'url': (local_update_setting['update_url'] + file).replace(" ", ''), 'file_name': ('/usr/' + file).replace(" ", '')} download_list.append(dict_file) print("下载文件列表: ", download_list) result = usr_fota.bulk_download(download_list) print("更新文件下载失败列表: ", result) local_update_setting = server_update_setting uos.remove("/usr/update_setting.json") with open("/usr/update_setting.json", mode="w") as fw: ujson.dump(local_update_setting, fw) fw.close() usr_fota.set_update_flag() print("更新下载完成,将在3秒后重启完成更新。") utime.sleep(3) Power.powerRestart() except Exception as e: print("更新失败,error:", e) def th_update(): global local_update_setting while True: utime.sleep(20) print("开始检查更新...") try: local_time = utime.localtime() if local_time[3] == 00 and local_time[4] == int(IMEI[-2:]) % 60: response = request.get(url=local_update_setting['update_url'] + 'update_setting.json') server_update_setting = response.json() if local_update_setting['app_name'] == server_update_setting['app_name'] and local_update_setting['app_version'] == \ server_update_setting['app_version']: print("已是最新版本,无需升级") elif local_update_setting['app_name'] == server_update_setting['app_name'] and local_update_setting['app_version'] < \ server_update_setting['app_version']: print("检测到新版本:\r app name:\t{},\r app version:\t{},\r file list:\t{}\r开始升级...".format( server_update_setting['app_name'], server_update_setting['app_version'], server_update_setting['file_list'])) file_list = server_update_setting['file_list'].split(',') download_list = [] for file in file_list: dict_file = {'url': (local_update_setting['update_url'] + file).replace(" ", ''), 'file_name': ('/usr/' + file).replace(" ", '')} download_list.append(dict_file) print("下载文件列表: ", download_list) result = usr_fota.bulk_download(download_list) print("更新文件下载失败列表: ", result) local_update_setting = server_update_setting uos.remove("/usr/update_setting.json") with open("/usr/update_setting.json", mode="w") as fw: ujson.dump(local_update_setting, fw) fw.close() usr_fota.set_update_flag() print("更新下载完成,将在3秒后重启完成更新。") utime.sleep(3) Power.powerRestart() except Exception as e: print("更新失败,error:", e) def init(): global settings global server global port global detectors global mqtt_client try: with open('/usr/setting.json', mode='r') as f: settings = ujson.load(f) server = settings['server'] port = settings['port'] mqtt_client = MQTTClient("FireDetectorGateway/" + IMEI, server, port, user="vitalong", password="vitalong@2019", keepalive=120, reconn=False) f.close() except Exception as e: print("加载用户设置失败: {},转为默认设置。".format(e)) config_port.write("Turn to default setting.") with open('/usr/setting_default.json', mode='r') as f: settings = ujson.load(f) server = settings['server'] port = settings['port'] mqtt_client = MQTTClient("FireDetectorGateway/" + IMEI, server, port, user="vitalong", password="vitalong@2019", keepalive=120, reconn=False) f.close() mqtt_client.set_callback(sub_cb) mqtt_client.connect(True) mqtt_client.subscribe(receive_topic) print("连接至:{}, 订阅主题: {}".format(server, receive_topic)) config_port.write("connect to server") utime.sleep_ms(20) print("Mqtt 客户端初始化成功!") STATUS_LED.write(1) if settings['start_addr'] <= 0 or settings['start_addr'] > 240 or settings['end_addr'] <= 0 or settings[ 'end_addr'] > 240 or settings['end_addr'] < settings['start_addr']: settings['start_addr'] = 1 settings['end_addr'] = 1 detectors = [] for i in range(settings['start_addr'], settings['end_addr'] + 1): try: detector_type = modbus_port.read_input_registers(i, 0, 1, signed=False) if detector_type[0] == 1 or detector_type[0] == 3: detector = ElectricFireDetector.Detector(device_id=i) detector.input_reg = ['{:0>4}'.format(j) for j in modbus_port.read_input_registers(detector.device_id, 0, 10, signed=False)] detector.input_reg.append('0000') detector.input_reg[1] = '{:0>4x}'.format(int(detector.input_reg[1])) detectors.append(detector) elif detector_type[0] == 8: detector = ElectricFireDetector.Detector(device_id=i) detector.state_temp = ['0000', '0000', '0001'] utime.sleep_ms(50) detector.input_reg = ['{:0>4}'.format(j) for j in modbus_port.read_input_registers(detector.device_id, 0, 20, signed=False)] detector.input_reg.append('0000') detector.input_reg[1] = '{:0>4x}'.format(int(detector.input_reg[1])) detector.input_reg[2] = '{:0>4x}'.format(int(detector.input_reg[2])) detector.input_reg[-2] = '{:0>4x}'.format(int(detector.input_reg[-2])) detectors.append(detector) except Exception as e: print(e, "当前地址: ", i) detector = ElectricFireDetector.Detector(device_id=i) detector.input_reg.append('0001') detectors.append(detector) if settings['has_host'] == 1: host = ElectricFireDetector.Host() try: utime.sleep_ms(50) host.input_reg = ['{:0>4}'.format(j) for j in modbus_port.read_input_registers(255, 0, 5, signed=False)] host.input_reg.append('0000') host.input_reg[0] = '{:0>4x}'.format(int(host.input_reg[0])) host.input_reg[-2] = '{:0>4x}'.format(int(host.input_reg[-2])) detectors.append(host) except Exception as e: print("主机初始化异常: ", e) host.input_reg.append('0001') detectors.append(host) def th_polling(): while True: utime.sleep_ms(100) lock.acquire() for idx, detector in enumerate(detectors): utime.sleep_ms(200) try: if detector.input_reg[-1] == '0000': if (detector.input_reg[0] == '1001' or detector.input_reg[0] == '1002' or detector.input_reg[0] == '1003'): detector.input_reg = ['{:0>4}'.format(i) for i in modbus_port.read_input_registers(255, 0, 5, signed=False)] detector.input_reg.append('0000') detector.input_reg[0] = '{:0>4x}'.format(int(detector.input_reg[0])) detector.input_reg[-2] = '{:0>4x}'.format(int(detector.input_reg[-2])) if detector.input_reg[-2:] != detector.state_temp: print("polling push Host.") utime.sleep_ms(20) push_msg = '{DeviceId:"255",Cmd:"83",Data:"' + str(detector.input_reg).replace('[', '').replace( ']', '').replace('\'', '').replace(' ', '') + '"}' mqtt_client.publish(publish_topic, push_msg) detector.state_temp = detector.input_reg[-2:] detectors[idx] = detector elif detector.input_reg[0] == '0001' or detector.input_reg[0] == '0003': detector.input_reg = ['{:0>4}'.format(i) for i in modbus_port.read_input_registers(detector.device_id, 0, 10, signed=False)] detector.input_reg.append('0000') detector.input_reg[1] = '{:0>4x}'.format(int(detector.input_reg[1])) if detector.input_reg[1:2] + detector.input_reg[-1:] != detector.state_temp: print("推送MDM(MDO)探测器,编号:", detector.device_id) push_msg = '{DeviceId:"' + '{:0>3d}'.format(detector.device_id) + '",Cmd:"83",Data:"' + str( detector.input_reg).replace('[', '').replace(']', '').replace('\'', '').replace(' ', '') + '"}' mqtt_client.publish(publish_topic, push_msg) detector.state_temp = detector.input_reg[1:2] + detector.input_reg[-1:] detectors[idx] = detector elif detector.input_reg[0] == '0008': detector.input_reg = ['{:0>4}'.format(i) for i in modbus_port.read_input_registers(detector.device_id, 0, 20, signed=False)] detector.input_reg.append('0000') detector.input_reg[1] = '{:0>4x}'.format(int(detector.input_reg[1])) detector.input_reg[2] = '{:0>4x}'.format(int(detector.input_reg[2])) detector.input_reg[-2] = '{:0>4x}'.format(int(detector.input_reg[-2])) if detector.input_reg[1:3] + detector.input_reg[-1:] != detector.state_temp: print("推送MDM_L型探测器,编号:{}".format(detector.device_id)) push_msg = '{DeviceId:"' + '{:0>3d}'.format(detector.device_id) + '",Cmd:"83",Data:"' + str( detector.input_reg).replace('[', '').replace(']', '').replace('\'', '').replace(' ', '') + '"}' mqtt_client.publish(publish_topic, push_msg) detector.state_temp = detector.input_reg[1:3] + detector.input_reg[-1:] detectors[idx] = detector elif detector.input_reg[-1] == '0001': if detector.input_reg[0] == '1001' or detector.input_reg[0] == '1002' or detector.input_reg[ 0] == '1003': detector.input_reg = ['{:0>4}'.format(i) for i in modbus_port.read_input_registers(255, 0, 5, signed=False)] detector.input_reg.append('0000') detector.input_reg[0] = '{:0>4x}'.format(int(detector.input_reg[0])) detector.input_reg[-2] = '{:0>4x}'.format(int(detector.input_reg[-2])) detectors[idx] = detector continue detector_type = modbus_port.read_input_registers(detector.device_id, 0, 1, signed=False) if detector_type[0] == 1 or detector_type[0] == 3: detector.input_reg = ['{:0>4}'.format(i) for i in modbus_port.read_input_registers(detector.device_id, 0, 10, signed=False)] detector.input_reg.append('0000') detector.input_reg[1] = '{:0>4x}'.format(int(detector.input_reg[1])) detectors[idx] = detector elif detector_type[0] == 8: detector.state_temp = ['0000', '0000', '0001'] utime.sleep(0.05) detector.input_reg = ['{:0>4}'.format(j) for j in modbus_port.read_input_registers(detector.device_id, 0, 20, signed=False)] detector.input_reg.append('0000') detector.input_reg[1] = '{:0>4x}'.format(int(detector.input_reg[1])) detector.input_reg[2] = '{:0>4x}'.format(int(detector.input_reg[2])) detector.input_reg[-2] = '{:0>4x}'.format(int(detector.input_reg[-2])) detectors[idx] = detector except Exception as e: if detector.input_reg[0] == '1001' or detector.input_reg[0] == '1002' or detector.input_reg[0] == '1003': print("轮询主机时出现异常: ", e) config_port.write("host polling error:{} ".format(e)) utime.sleep_ms(20) else: print("轮询探测器时出现异常: ", e, "地址: ", detector.device_id) config_port.write("detector polling error:{}, address:{}".format(e, detector.device_id)) utime.sleep_ms(20) detector.input_reg[-1] = '0001' detectors[idx] = detector lock.release() print("polling thread is running.\r") def sub_cb(topic, msg): global local_update_setting try: lock.acquire() print("receive thread receive a msg:\r") config_port.write("receive thread receive a msg:\r") utime.sleep_ms(20) if topic.decode() == receive_topic: recv_data = ujson.loads(msg.decode()) print(recv_data) if recv_data['Cmd'] == '1': print("设置目标服务器及端口(未实现)\r") print(recv_data['Data']) elif recv_data['Cmd'] == '2': print("设置探测器起止地址\r") config_port.write("set detector address range.\r") utime.sleep_ms(20) data = recv_data['Data'].split(',') settings['start_addr'] = int(data[0]) settings['end_addr'] = int(data[1]) settings['has_host'] = int(data[2]) print(settings) uos.remove("/usr/setting.json") with open("/usr/setting.json", mode="w") as fd: ujson.dump(settings, fd) fd.close() mqtt_client.publish(publish_topic, '{"DeviceId":"0","Cmd":"2","Data":"1"}') utime.sleep(0.5) Power.powerRestart() elif recv_data['Cmd'] == '3': print("全部探测器消音\r") config_port.write("mute all\r") utime.sleep_ms(20) modbus_port.write_single_coil(0, 2, 0) mqtt_client.publish(publish_topic, '{"DeviceId":"0","Cmd":"3","Data":"1"}') elif recv_data['Cmd'] == '4': print("探测器全部自检\r") config_port.write("self-inspection all\r") utime.sleep_ms(20) modbus_port.write_single_coil(0, 2, 0xFF00) mqtt_client.publish(publish_topic, '{"DeviceId":"0","Cmd":"4","Data":"1"}') elif recv_data['Cmd'] == '5': print("探测器单个自检\r") config_port.write("self-inspection single\r") utime.sleep_ms(20) modbus_port.write_single_coil(int(recv_data['DeviceId']), 2, 0xFF00) mqtt_client.publish(publish_topic, '{"DeviceId":"{}","Cmd":"5","Data":"1"}'.format(int(recv_data['DeviceId']))) elif recv_data['Cmd'] == '6': print("探测器全部复位\r") config_port.write("reset all\r") utime.sleep_ms(20) modbus_port.write_single_coil(0, 1, 0) mqtt_client.publish(publish_topic, '{"DeviceId":"0","Cmd":"6","Data":"1"}') elif recv_data['Cmd'] == '7': print("探测器单个复位\r") config_port.write("reset single\r") utime.sleep_ms(20) modbus_port.write_single_coil(int(recv_data['DeviceId']), 1, 0) mqtt_client.publish(publish_topic, '{"DeviceId":"{}","Cmd":"7","Data":"1"}'.format(int(recv_data['DeviceId']))) elif recv_data['Cmd'] == '8': print("网关上报时间间隔设置\r") config_port.write("upload interval set.\r") utime.sleep_ms(20) settings['upload_interval'] = int(recv_data['Data']) * 60 print(settings) try: uos.remove("usr/setting.json") except: pass with open("usr/setting.json", mode="w") as fd: ujson.dump(settings, fd) fd.close() mqtt_client.publish(publish_topic, '{"DeviceId":"0","Cmd":"8","Data":"1"}') utime.sleep(0.5) Power.powerRestart() elif recv_data['Cmd'] == '9': print("设置探测器报警阀值\r") config_port.write("set alarm value.\r") utime.sleep_ms(20) data = recv_data['Data'].split(',') detector_type = modbus_port.read_input_registers(int(recv_data['DeviceId']), 0, 1, signed=False) print("探测器型号:{}, 地址:{}, 通道:{}, 阀值:{} ".format(detector_type[0], recv_data['DeviceId'], data[0], data[1])) if detector_type[0] == 1 or detector_type[0] == 3: modbus_port.write_single_register(int(recv_data['DeviceId']), int(data[0]) + 1, int(data[1]), signed=False) elif detector_type[0] == 8: utime.sleep_ms(50) modbus_port.write_single_register(int(recv_data['DeviceId']), int(data[0]) + 2, int(data[1]), signed=False) elif recv_data['Cmd'] == '10': print("探测器阈值查询\rAddress: ", int(recv_data['DeviceId'])) config_port.write("check detector alarm value") utime.sleep_ms(20) detector_type = modbus_port.read_input_registers(int(recv_data['DeviceId']), 0, 1, signed=False) if detector_type[0] == 1 or detector_type[0] == 3: holding_reg = ['{:0>4}'.format(i) for i in modbus_port.read_holding_registers(int(recv_data['DeviceId']), 2, 5, signed=False)] push_msg = '{DeviceId:"' + recv_data['DeviceId'] + '",Cmd:"81",Data:"0001,' + str( holding_reg).replace('[', '').replace(']', '').replace('\'', '').replace(' ', '') + '"}' elif detector_type[0] == 8: utime.sleep_ms(50) holding_reg = ['{:0>4}'.format(i) for i in modbus_port.read_holding_registers(int(recv_data['DeviceId']), 3, 10, signed=False)] push_msg = '{DeviceId:"' + recv_data['DeviceId'] + '",Cmd:"81",Data:"0008,' + str( holding_reg).replace('[', '').replace(']', '').replace('\'', '').replace(' ', '') + '"}' mqtt_client.publish(publish_topic, push_msg) elif recv_data['Cmd'] == '11': print("时间校准\r") elif recv_data['Cmd'] == '12': print("远程重启\r") config_port.write("Remote restart\r") utime.sleep_ms(20) mqtt_client.publish(publish_topic, "received restart command, will restart after 1s...") utime.sleep(1) Power.powerRestart() elif recv_data['Cmd'] == '13': print("软件更新配置\r") config_port.write("firmware update setting\r") utime.sleep_ms(20) local_update_setting = recv_data['Data'] try: uos.remove("/usr/update_setting.json") except: pass with open("/usr/update_setting.json", mode='w') as fw: ujson.dump(local_update_setting, fw) fw.close() mqtt_client.publish(publish_topic, '{"DeviceId":"0","Cmd":"13","Data":"1"}') lock.release() except Exception as e: print("mqtt消息处理出现异常: ", e) config_port.write("mqtt message receive Exception: " + str(e)) utime.sleep_ms(20) lock.release() def th_push(): global mqtt_client while True: utime.sleep(settings['upload_interval']) try: for detector in detectors: if detector.input_reg[0] == '1001' or detector.input_reg[0] == '1002' or detector.input_reg[0] == '1003': push_msg = '{DeviceId:"255",Cmd:"82",Data:"' + str(detector.input_reg).replace('[', '').replace(']', '').replace('\'', '').replace(' ', '') + '"}' else: push_msg = '{DeviceId:"' + '{:0>3d}'.format(detector.device_id) + '",Cmd:"82",Data:"' + str( detector.input_reg).replace('[', '').replace(']', '').replace('\'', '').replace(' ', '') + '"}' mqtt_client.publish(publish_topic, push_msg) except Exception as e: print(e) config_port.write("push thread exception: " + str(e)) utime.sleep_ms(20) print("push thread is running.\r") def th_recv(): global mqtt_client while True: try: mqtt_client.wait_msg() except Exception as e: if e.args[0] == 0: pass else: print("mqtt消息接收线程出现异常:{}导致系统重启。".format(e)) sys_log['disconn_reason'] = 'mqtt except: ' + str(e) config_port.write(str(sys_log)) utime.sleep_ms(50) config_port.write("Reboot caused by mqtt receive exception.") utime.sleep_ms(50) Power.powerRestart() def th_log(): while True: try: if config_port.any() is not 0: msg = config_port.read(config_port.any()).decode('utf8').split(':') print('msg:', msg, 'command:', msg[0]) command = msg[0] print(command) if command is 'log': if sys_log['stagecode'] is 1: sys_log['net_error'] = 'SIM Card Error' elif sys_log['stagecode'] is 2: sys_log['net_error'] = 'Data Call Time Out' elif sys_log['stagecode'] is 3: sys_log['net_error'] = 'No NET Error' sys_log['ICCID'] = sim.getIccid() sys_log['CSQ'] = net.csqQueryPoll() config_port.write(str(sys_log)) if command is 'server': settings['server'] = msg[1] settings['port'] = msg[2] config_port.write(settings['server'] + ':' + settings['port']) uos.remove("/usr/setting.json") with open("/usr/setting.json", mode="w") as fw: ujson.dump(settings, fw) fw.close() utime.sleep(0.5) Power.powerRestart() except Exception as e: config_port.write(str(e)) utime.sleep(0.5) if __name__ == '__main__': try: utime.sleep(5) checknet.poweron_print_once() stagecode, subcode = checknet.wait_network_connected(180) sys_log['stagecode'] = stagecode sys_log['subcode'] = subcode # 启动232串口配置线程 _thread.start_new_thread(th_log, ()) if stagecode == 1 and subcode == 0: print("未插SIM卡,请检查。") config_port.write("no sim card.") utime.sleep_ms(20) while True: STATUS_LED.write(1) utime.sleep(0.5) STATUS_LED.write(0) utime.sleep(1) elif stagecode == 3 and subcode == 1: print('网络连接成功!\r') config_port.write('Network connection successful!') utime.sleep_ms(20) update() utime.sleep_ms(100) _thread.start_new_thread(th_update, ()) utime.sleep_ms(100) print("正在初始化...") init() _thread.start_new_thread(th_polling, ()) utime.sleep_ms(100) _thread.start_new_thread(th_recv, ()) utime.sleep_ms(100) while True: th_push() else: print('网络连接失败! stagecode = {}, subcode = {}\r'.format(stagecode, subcode)) config_port.write('Network connection failed! stagecode = {}, subcode = {}\r'.format(stagecode, subcode)) utime.sleep_ms(20) print("自动重启以尝试重新拨号...") config_port.write("reboot...") utime.sleep_ms(50) Power.powerRestart() except Exception as e: print("主线程出现异常: {},导致模组重启 ".format(e)) sys_log['disconn_reason'] = 'main thread exception: '+ str(e) config_port.write(str(sys_log)) utime.sleep_ms(50) config_port.write("reboot cased by main thread exception.") utime.sleep_ms(50) Power.powerRestart()