• 服务端代码


    # !/usr/bin/env python3
    # -*- coding:utf-8 -*-
    
    import re
    import json
    from shuncom_params_init import *
    from socketserver import StreamRequestHandler, ThreadingTCPServer
    from vbox_cloud import vbox_cloud
    import socket
    import sz_log
    import time
    import os
    from sz_tftp import sz_tftp_server
    import threading
    from sz_encrypt_mac import sz_encrypt
    from shuncom_fun import get_local_ip
    import paramiko
    
    
    
    ip = get_local_ip()
    host = ip  # 监听ip,串口服务器的指向 #host = '0.0.0.0'
    tftp_ip = ip  # tftp服务器IP
    
    local_firmware_name = "shuncom-juhe4-mt7621-sysupgrade.bin"  # 固件文件
    uboot_firmware_name = 'u-boot-mt7621-212.bin'  # uboot文件
    cmd_text = ''  # 下发串口服务器命令
    client_ip_list = []
    mutex = threading.Lock()
    
    
    
    class vbox_handle_t():
        def __init__(self, product, id, ip, port):
            self.id = id
            self.vbox_handle = vbox_cloud(product, id, ip, port, self.message_handle)
            self.vbox_handle.connect()
    
        def register_mssage_cb(self, process_message_function):
            self.process_message_function = process_message_function
    
        def message_handle(self, client, userdata, msg):
            print("message handle " + msg.topic + " " + str(msg.payload))
            mqtt_msg = json.loads(msg.payload)
            if msg.topic[-6:] == "invoke":
                print(" invoke ")
                firmware_url_para = mqtt_msg["inputs"][0]["value"]
                firmware_url_para["ip"] = "122.144.131.26"
                firmware_url_para["port"] = 6001
                # # linux命令
                # os.system("rm /tmp/tftp/" + local_firmware_name)
                # update_cmd = "lftp -p " + str(firmware_url_para["port"]) + " -u " \
                #              + firmware_url_para["username"] + "," \
                #              + firmware_url_para["password"] + " sftp://" \
                #              + firmware_url_para["ip"] + ":" + str(firmware_url_para["port"]) \
                #              + "  -e \"  set net:max-retries 3; && get  download/firmware/" + firmware_url_para["path"] \
                #              + "/firmware.bin -o %s" % tftp_path + local_firmware_name + "  && quit \" &"
                # sz_log.info("从平台下载的网关固件命令", update_cmd)
                # os.system(update_cmd)
    
                try:
                    if os.path.isfile(tftp_path + local_firmware_name):
                        os.remove(tftp_path + local_firmware_name)
                        sz_log.info('网关固件存在删除文件成功!')
                    sz_log.info("从平台下载网关新固件中...")
                    pt = paramiko.Transport(('122.144.131.26', 6001))
                    pt.connect(username='shuncom', password='shuncomgw')
                    sftp = paramiko.SFTPClient.from_transport(pt)  # sftp = t.open_sftp_client()
                    sftp.get('download/firmware/%s/firmware.bin' % firmware_url_para["path"],
                             (tftp_path + local_firmware_name))
                    sz_log.info("从平台下载网关新固件完成!")
                    self.vbox_handle.report_properties({"notice": ''})   # 清除下载固件错误提示
                    pt.close()
                except Exception as e:
                    sz_log.info("*************从平台下载网关新固件失败!!!*********** %s" % e)
                    self.vbox_handle.report_properties({"notice": '*从平台下载网关新固件失败*【请重新选择固件】%s'% e})
                self.vbox_handle.invoke_rsp(mqtt_msg, True)
            else:
                self.vbox_handle.write_properties_rsp(mqtt_msg, self.process_message_function(mqtt_msg["properties"]))
    
    
    class productor_t():
        global client_ip
    
        def __init__(self, product, id, ip, port):
            self.id = id
            self.vbox_obj = vbox_handle_t(product, id, ip, port)
            self.vbox_obj.register_mssage_cb(self.cloud_msg_cb)
            self.refresh_vars()
            config_ip_250 = config_init.get('CONFIG_SHUNCOM', 'config_ip_250')
            args = "".join(client_ip[0])  # client_ip = ('192.168.31.103', 41358)
            ip_ = '.'.join(args.split('.')[:-1])
            self.config = {}
            self.config["ip_addr"] = ip_ + config_ip_250  # "192.168.31.222" # 网关静态IP地址
            sz_log.info('设置的静态ip:',self.config["ip_addr"])
            self.config["gatewayip"] = ip_ + '.1'  # '192.168.31.1'   # 上级路由ip地址
            self.config["gwmac"] = "无"
            self.config["firmware_version"] = "请选择固件版本"
            self.config["bdinfo"] = "请选择bdinfo"
            self.bdinfo_value = {}
            self.config["running"] = False
            # os.system("mkdir -p /tmp/tftp")
            self.uboot_v = '2.01.02'  # uboot版本
    
        def refresh_vars(self):
            self.step = 0  # 生产状态
            self.device_status = ""  # 设备状态
            self.device_uboot_ver = ""  # 设备uboot版本
            self.firmware_login_step_last_cmd_time = None
            self.last_send_time = time.time()  # 上次发送时间
            self.status = "wait"  # WEB状态
            self.mac_exist_in_gw = ""  # 网关MAC
            self.mac_exist_in_gw_cal_passwd = ""  # 网关登录密码
            self.Request_bdinfo_mac = 0  # 向平台请求bdinfo的Mac地址标志位
            try:
                self.vbox_obj.vbox_handle.report_properties({"notice": ''})  # 告警提示停止
                self.vbox_obj.vbox_handle.report_properties({"info": ''})    # 提示停止
                mutex.release()
                sz_log.info('重置线程锁解锁完成')
            except:
                pass
    
        def get_status(self):
            return self.status
    
        def get_config(self):
            return self.config
    
        def get_step(self):
            return self.step
    
        def next_step_test(self):
            """没有使用的功能"""
            if self.status == "wait":
                self.status = "error"
            elif self.status == "error":
                self.status = "process"
            elif self.status == "process":
                self.status = "finish"
            elif self.status == "finish":
                self.status = "wait"
                self.step += 1
                if self.step >= 4:
                    self.step = 0
    
        def get_mac_exist_in_gw(self, splited_str):
            try:
                for tmp_line in splited_str:   # splited_str = ['Login incorrect2c:6a:6f:40:00:05\r', '']
                    if "2c:6a:6f" in tmp_line or "2C:6A:6F" in tmp_line:
                        p = re.compile(r'(?:[0-9a-fA-F]:?){12}')
                        tmp_line = re.findall(p, tmp_line)  # 匹配Mac地址
                        sz_log.info('匹配Mac地址:', tmp_line)
                        if tmp_line:
                            tmp_mac_split = tmp_line[0].split(':')
                            self.mac_exist_in_gw = ""
                            for tmp_mac_char in tmp_mac_split:
                                self.mac_exist_in_gw = self.mac_exist_in_gw + tmp_mac_char
                            self.mac_exist_in_gw_cal_passwd = sz_encrypt(self.mac_exist_in_gw).decode(encoding="utf-8",errors="strict")
                            sz_log.info("mac_exist_in_gw  " + self.mac_exist_in_gw)
                            sz_log.info("mac_exist_in_gw_password  " + self.mac_exist_in_gw_cal_passwd)
                            self.config["gwmac"] = self.mac_exist_in_gw  # 回显原mac地址
                            return True
                        else:
                            sz_log.info('mac地址异常', tmp_line)
                            return False
    
                    elif "00:c0:02:12:35:88" in tmp_line:
                        sz_log.info('上报Mac:00:c0:02:12:35:88,使用密码 回车')
                        # self.mac_exist_in_gw_cal_passwd = "5afc1d286cdcb137fcb234a962c19288" # 老板子密码
                        self.mac_exist_in_gw_cal_passwd = "\r"   # 新板子密码是回车
                        return True
    
                    elif "无" in tmp_line:
                        sz_log.info('上报Mac无,使用默认密码:5554f3ba30a3727c05d66e047c6acbe8')
                        self.mac_exist_in_gw_cal_passwd = "5554f3ba30a3727c05d66e047c6acbe8"
                        return True
    
                sz_log.info('获取串口中的mac地址:false')
                return False
            except Exception as e:
                sz_log.info('get_mac_exist_in_gw异常:',e)
                return False
    
    
        def cloud_msg_cb(self, properties):
            """web页面的用户设置"""
            global cmd_text
            try:
                sz_log.info("接收web页面【生产工具-配置参数】")
                sz_log.info('接收web页面【properties】 ', properties)
                # sz_log.info(self.config.keys())
                for obj_name in properties:
                    sz_log.info('接收web页面【obj_name】 ', obj_name)
                    sz_log.info('接收web页面【self.config】 ', self.config)
                    if obj_name in self.config:
                        if obj_name == "bdinfo":
                            sz_log.info('接收web页面【进入bdinfo】')
                            bdinfo_json = json.loads(properties[obj_name])
                            self.config["bdinfo"] = bdinfo_json["BOARD"] + "_" + bdinfo_json["VARIANT"]
                            self.bdinfo_value = properties[obj_name]
                            sz_log.info(" bdinfo " + self.config["bdinfo"])
                            sz_log.info(self.bdinfo_value)
                        else:
                            try:
                                self.config[obj_name] = properties[obj_name]
                            except:
                                sz_log.info('接收web页面【properties[obj_name] 处理错误】')
                            if obj_name == "running":
                                self.refresh_vars()
                    else:
                        if obj_name == "log":
                            sz_log.info('读取日志:不支持')
                            self.vbox_obj.vbox_handle.report_properties({"log": {"日志": '读取日志:不支持'}})
                        elif obj_name == "cmd":
                            cmd_text = properties['cmd']
                            sz_log.info('执行cmd命令:', cmd_text)
                            self.vbox_obj.vbox_handle.report_properties({"log": {"日志": '执行cmd命令:%s' % cmd_text}})
                        elif obj_name == "step":
                            sz_log.info('读取步骤:不支持')
                            self.vbox_obj.vbox_handle.report_properties({"log": {"日志": '读取步骤:不支持'}})
                        elif obj_name == "status":
                            sz_log.info('读取当前状态:不支持')
                            self.vbox_obj.vbox_handle.report_properties({"log": {"日志": '读取当前状态:不支持'}})
                        else:
                            sz_log.info("obj not exist,不存在")
                sz_log.info('接收web页面 self.config 修改后 ', self.config)
                return True
            except Exception as e:
                sz_log.info('接收web页面异常%s' % e)
                return False
    
        def bdinfo_save(self, mac_str):
            """平台下载bdinfo文件"""
            bdinfo_value_split = self.bdinfo_value.split('\n')
            last_split_str = ""
            tmp_line_num = 0
            for tmp_split_str in bdinfo_value_split:
                if "\"type\": \"wan\"," in last_split_str and "macaddr" in tmp_split_str:
                    tmp_i = 0
                    dst_split_str = "                        \"macaddr\":\""
                    sz_log.info('下载bdinfo,遍历出macaddr', tmp_split_str)  # 遍历出"macaddr": "2C:6A:6F:00:d4:12"
                    sz_log.info('下载bdinfo,传入的Mac地址', mac_str)
                    for tmp_char in mac_str:
                        tmp_i += 1
                        print('tmp_i', tmp_i)
                        if tmp_i < 13:
                            dst_split_str = dst_split_str + tmp_char
                            print('dst_split_str数据:', dst_split_str)
                            print("tmp i : " + str(tmp_i))
                            print("tmp i / 2: " + str(tmp_i % 2))
                            if (tmp_i % 2) == 0 and (tmp_i < 12):
                                dst_split_str += ":"
                                sz_log.info('下载bdinfo遍历12次,获取出Mac地址: ', dst_split_str)
                    dst_split_str += "\""  # "macaddr":"无"
                    bdinfo_value_split[tmp_line_num] = dst_split_str
                last_split_str = tmp_split_str  # "macaddr": "2C:6A:6F:00:d4:12"
                tmp_line_num += 1
            self.bdinfo_value = ""
            for tmp_split_str in bdinfo_value_split:
                self.bdinfo_value = self.bdinfo_value + tmp_split_str + "\n"
            sz_log.info('bdinfo_value值:', self.bdinfo_value)
            #os.system("mkdir -p /tmp/tftp/" + self.id)  # linux 命令
            print('判断bdinfo文件夹是否存在',os.path.exists(tftp_path + self.id))
            if not os.path.exists(tftp_path + self.id):
                sz_log.info('创建bdinfo文件夹')
                os.mkdir( tftp_path + self.id)
            with open(tftp_path + self.id + '/bdinfo.json', 'w+') as f:
                f.write(self.bdinfo_value)
    
        def firmware_login(self):
            if self.firmware_login_step == "username":
                if self.firmware_login_step_last_cmd_time is None:
                    self.firmware_login_step_last_cmd_time = time.time()
                    sz_log.info('发送登录root ')
                    return "root\r"
                else:
                    if time.time() - self.firmware_login_step_last_cmd_time > 2:
                        self.firmware_login_step_last_cmd_time = None
                        self.firmware_login_step = "passwd"
    
            if self.firmware_login_step == "passwd":
                if self.firmware_login_step_last_cmd_time is None:
                    self.firmware_login_step_last_cmd_time = time.time()
                    sz_log.info('发送ssh登录密码:' + self.mac_exist_in_gw_cal_passwd)
                    return self.mac_exist_in_gw_cal_passwd + '\r'
                else:
                    if time.time() - self.firmware_login_step_last_cmd_time > 2:
                        self.firmware_login_step_last_cmd_time = None
                        self.firmware_login_step = "finish"
    
        def do_step(self):
            """下发数据给串口服务器到网关"""
            if self.config["running"] == False:
                return None
            if self.step == 0:
                print('生产状态:检查并更新uboot')
            elif self.step == 1:
                print('生产状态:固件烧录中')
            elif self.step == 2:
                print('生产状态:bdinfo写入中')
            elif self.step == 3:
                print('生产状态:完成中')
            else:
                print('生产状态:未知%s' % self.step)
            if (time.time() - self.last_send_time) < 1:
                sz_log.info(" 时间间隔小于1秒不发送串口数据 last send too close")
                return None
            self.last_send_time = time.time()
    
            # 刷写网关uboot
            if self.step == 0:
                if self.status == "wait":
                    if self.device_status == "have_firmware_login":
                        if self.firmware_login_step is None:
                            self.firmware_login_step = "username"
                        elif self.firmware_login_step == "finish":
                            sz_log.info(" login cmd send finish")
                        else:
                            return self.firmware_login()
                    elif self.device_status == "have_firmware_shell":
                        return "reboot\n"
                    else:
                        return "\n"
                elif self.status == "process":
                    if self.device_status == "break_uboot":
                        return "0\n"
                    elif self.device_status == "check_uboot_version":
                        return "version\n"
                    elif self.device_status == 'updata_uboot':
                        sz_log.info('执行设置uboot参数,mtkupgrade')
                        self.updata_uboot_reset_num = 0
                        return "setenv gatewayip " + self.config["gatewayip"] + "\n" \
                               + "setenv ipaddr " + self.config["ip_addr"] + "\n" \
                               + "setenv serverip " + tftp_ip + "\n" \
                               + 'setenv bootfile.bootloader ' + uboot_firmware_name + '\n' \
                               + 'saveenv\n'
                    elif self.device_status == 'updata_uboot_2_1' and self.updata_uboot_reset_num ==0:
                        self.updata_uboot_reset_num = 1
                        sz_log.info('uboot 设置重启 reset ')
                        return 'reset\n'
                    elif self.device_status == 'updata_uboot_2':
                        return '4\n'
                    elif self.device_status == 'updata_uboot_3':
                        return '\n' * 4
                    elif self.device_status == 'updata_uboot_4':
                        return 'y\r'
                    elif self.device_status == 'updata_uboot_5':
                        sz_log.info('等待网关断电重启网关')
                        return 'reset\n'
    
    
            # 刷写网关固件
            elif self.step == 1:
                if self.status == "wait":
                    if self.device_status == "firmware_set_ip":
                        return " setenv gatewayip " + self.config["gatewayip"] + "\n" \
                               + "setenv ipaddr " + self.config["ip_addr"] + "\n" \
                               + "setenv serverip " + tftp_ip + "\n" \
                               + "setenv netmask " + "255.255.255.0\n" \
                               + "saveenv\n"
                    elif self.device_status == "firmware_tftp":
                        return "szupgradefw\n"
    
            # 刷写网关bdinfo
            elif self.step == 2:
                if self.status == "process":
                    if self.device_status == "bdinfo_init_login":
                        return "\n"
                    elif self.device_status == "bdinfo_login":
                        if self.firmware_login_step is None:
                            self.firmware_login_step = "username"
    
                        elif self.firmware_login_step == "finish":
                            sz_log.info(" login cmd send finish")
                            sz_log.info(" 登录命令发送完成")
                        else:
                            return self.firmware_login()
                    elif self.device_status == "bdinfo_shell":
                        return " tftp -g -r " + self.id + "/bdinfo.json " + tftp_ip + " && mv bdinfo.json /bdinfo/ && jffs2reset -y && reboot -f\n"
                elif self.status == "finish":
                    return " tftp -g -r " + self.id + "/bdinfo.json " + tftp_ip + " && mv bdinfo.json /bdinfo/ && rm -f /etc/config/datacenter.db &&  jffs2reset -y && reboot -f\n"
    
    
            # 完成中
            elif self.step == 3:
                if self.device_status == "uboot_error_tftp":
                    return "szboardboot\n"
    
                if self.device_status == "tty_usb_r":
                    return "\r"
    
                if self.device_status == 'tty_usb_root':
                    if self.firmware_login_step == "finish":
                        sz_log.info("查询usb登录命令发送成功")
                    else:
                        return self.firmware_login()
    
                if self.device_status == "tty_usb_shell":
                    sz_log.info('发送查询USB命令')
                    #return "uci show shuncom && lspci\r"
                    return "lspci\r"
    
                if self.device_status =='finish_reboot':
                    pass
                    # sz_log.info('发送换行命令')
                    # return '\n' # 可以修改为恢复出厂设置
    
    
        def process_uart_data(self, data):
            """根据接收的数据判断网关的状态"""
            global mutex
            if self.config["running"] == False:
                return None
    
            sz_log.info("device status 前:" + self.device_status)
            sz_log.info(data.split('\n'))
            splited_str = data.split('\n')
    
            # 计算登录密码
            gw_mac_key = self.get_mac_exist_in_gw(splited_str)
    
            # 网关检查更新uboot
            if self.step == 0:
                if self.status == "wait":
                    print("#########################################################splited_str#############",splited_str)
                    if "Shuncom login:" in splited_str[-1]:
                        sz_log.info(" shuncom登录存在 ")
                        self.device_status = "have_firmware_login"
                        self.firmware_login_step = None
                    # elif "-ash: root: not found" in splited_str[-1]:
                    # if "root@Shuncom:~#" in splited_str[-1]:
                    if "[\x1b[35;1mroot\x1b[0m@\x1b[31;1mshuncom\x1b[0m:\x1b[32;1m/root\x1b[0m]#" or "root@Shuncom:~#" in splited_str[-1]:
                        self.device_status = "have_firmware_shell"
                        self.firmware_login_step = None
                        self.firmware_login_step_last_cmd_time = None
    
                    if "Hit any key to stop autoboot" in data:  # 重启网关进入
                        self.status = "process"
                        self.device_status = "break_uboot"
                        self.vbox_obj.vbox_handle.report_properties({"notice": ''})
                    if "=>" in data:
                        self.status = "process"
                        self.device_status = "check_uboot_version"
                        self.vbox_obj.vbox_handle.report_properties({"notice": ''})
    
                elif self.status == "process":
                    if self.device_status == 'updata_uboot_5':
                        self.status = "wait"
                        self.device_status = ''
    
                    if self.device_status == "break_uboot":
                        if "=>" in data:
                            self.device_status = "check_uboot_version"
    
                    if self.device_status == "check_uboot_version":
                        for tmp_str in splited_str:
                            local_idx = tmp_str.find("SHUNCOM-U-BOOT-VERSION")
                            if local_idx >= 0:
                                self.device_uboot_ver = tmp_str[local_idx + len("SHUNCOM-U-BOOT-VERSION") + 1:]
                                sz_log.info("found uboot version:" + self.device_uboot_ver)
                                if self.device_uboot_ver >= self.uboot_v:  # 对比uboot版本 2.01.02
                                    sz_log.info('当前uboot版本不需要升级')
                                    self.status = "wait"
                                    self.step = 1
                                    self.device_status = "firmware_set_ip"
    
                                else:
                                    sz_log.info('需要升级uboot版本')
                                    self.device_status = 'updata_uboot'
                                    # self.uboot_v = '2.01.02'# 测试时候使用
    
                    if self.device_status == 'updata_uboot':
                        if "Saving Environment to SPI Flash" in data: # 保存成功
                            self.device_status = 'updata_uboot_2_1'
    
                    if self.device_status == 'updata_uboot_2_1':
                        if "Upgrade bootloader (advanced mode)" in data:
                            self.device_status = 'updata_uboot_2'  # 选择4 Upgrade bootloader (advanced mode)
    
                    if self.device_status == 'updata_uboot_2':
                        if "Select (enter for default)" in data:
                            self.device_status = 'updata_uboot_3'  # 回车4if self.device_status == 'updata_uboot_3':
                        if "Upgrade Bootblock? (N/y)" in data:     # 回复 y
                            self.device_status = 'updata_uboot_4'
                    if self.device_status == 'updata_uboot_4':     # 表示uboot更新完成。
                        if "Bootloader upgrade completed!" in data:
                            sz_log.info('++++ uboot 升级完成 +++++')
                            self.device_status = 'updata_uboot_5'
                            self.vbox_obj.vbox_handle.report_properties({"notice": 'uboot升级完成,请把网关断电重启,继续生产!'})
                        """
                        mUpgrade Bootblock? (N/y):[0m  y
                        Whole bootloader will be upgraded
                        Erasing from 0x0 to 0x2ffff, size 0x30000 ... OK
                        Writting from 0x80010000 to 0x0, size 0x2fca2 ... OK
                        [0;33m*** Bootloader upgrade completed! ***[0m
                        Hit any key to stop reboot:  3 
                        """
    
            # 刷写网关固件
            if self.step == 1:
                if self.status == "wait":
                    if self.device_status == "firmware_set_ip":
                        if "setenv serverip" in data:
                            self.device_status = "firmware_tftp"
                            mutex.acquire()
                            sz_log.info('线程锁生效')
                    elif self.device_status == "firmware_tftp":
                        if "Loading:" in data:
                            self.device_status = "firmware_tftping"
                            self.status = "process"
                            self.start_time = int(time.time())
    
                elif self.status == "process":
                    if self.device_status == "firmware_tftping":
                        now_time = int(time.time())
                        if now_time - self.start_time > 300:
                            self.vbox_obj.vbox_handle.report_properties({"notice": '固件下载下载超时,请把【控制台-生产状态】重新开始,网关断电重启'})
                            self.start_time = now_time
                        sz_log.info(" tftping 固件下载中")
    
                    if "Bytes transferred" in data:
                        sz_log.info("tftp finished ")
                        mutex.release()
                        sz_log.info('线程锁解锁')
                    if "init: Console is alive" in data:
                        self.device_status = "bdinfo_waiting"
                        self.status = "wait"
                        self.step = 2
    
            # 更新刷写bdinfo文件
            if self.step == 2:
                if self.status == "wait":
                    if gw_mac_key:
                        sz_log.info('根据Mac计算出的密码:', self.mac_exist_in_gw_cal_passwd)
                        self.status = "process"
                        self.device_status = "bdinfo_init_login"
                        self.firmware_login_step = None
                        self.Logintimedout = 0
    
    
                elif self.status == "process":
                    if "Login timed" in data or "Login timed out" in data or "timed out" in data:
                        self.device_status = "bdinfo_init_login"
                        sz_log.info('****刷写bdinfo文件登录失败超时,尝试重新登录****', data)
                        self.Logintimedout = 1
    
                    if ('Shuncom login:'in data and self.Logintimedout ==1)or('huncom login'in data and self.Logintimedout ==1):
                        # 发送root重新登录
                        self.device_status = "bdinfo_login"
                        self.firmware_login_step_last_cmd_time = None
                        self.firmware_login_step = "username"
                        self.Logintimedout = 0
                        sz_log.info('\n**** 登录超时,重新发送登录 root ****\n')
    
                    if self.device_status == "bdinfo_init_login":
                        if "IPv6: ADDRCONF(NETDEV_UP): br-lan:" in data:
                            self.device_status = "bdinfo_login"
                            self.bdinfo_save(self.config["gwmac"])
    
                    # if "root@Shuncom:~#" in data:
                    if "[\x1b[35;1mroot\x1b[0m@\x1b[31;1mshuncom\x1b[0m:\x1b[32;1m/root\x1b[0m]#" or "root@Shuncom:~#" in splited_str[-1]:
                        self.device_status = "bdinfo_shell"
                        self.firmware_login_step = None
                        self.firmware_login_step_last_cmd_time = None
                        sz_log.info(" bdinfo " + self.config["bdinfo"])
                        self.status = "finish"
                        self.step = 2
    
                elif self.status == "finish":
                    sz_log.info(" finishing")
                    if "SHUNCOM-U-BOOT" in data:
                        self.status = "wait"
                        self.step = 3
    
    
            # 完成中等待网关重启
            if self.step == 3:
                if self.status == "wait":
                    if "=>" in data:
                        sz_log.info(" 在uboot中错误输入了tftp ")
                        self.device_status = "uboot_error_tftp"
                    elif "Linux version" in data:
                        self.status = "process"
                        self.tty_usb = False
    
                elif self.status == "process":
                    if "first boot" in data:
                        # self.status = "finish"
    
                        self.device_status = 'tty_usb_r'  # 回车换行登录
                        self.tty_usb_num = 0
                        self.tty_usb = True
    
                    # 后加的代码++++++++++++++++++++++++++++++++++++++++++++++
                    if self.tty_usb:
                        if 'shuncom login:' in data:  # 输入root
                            self.device_status = 'tty_usb_root'
                            self.firmware_login_step = "username"
                            self.firmware_login_step_last_cmd_time = None
    
                        if "Login timed out" in data or "ogin timed ou" in data:
                            self.device_status = 'tty_usb_r'  # 回车换行登录
                            self.firmware_login_step = "username"
                            self.firmware_login_step_last_cmd_time = None
                            sz_log.info('****查询usb登录失败超时,尝试重新登录****', data)
    
                        # if "root@Shuncom:~#" in data:
                        if "[\x1b[35;1mroot\x1b[0m@\x1b[31;1mshuncom\x1b[0m:\x1b[32;1m/root\x1b[0m]#" or "root@Shuncom:~#" in splited_str[-1]:
                            self.device_status = "tty_usb_shell"
                            self.firmware_login_step = None
                            self.firmware_login_step_last_cmd_time = None
                            self.tty_usb = 'tty_usb_shell'
    
                        if self.tty_usb == 'tty_usb_shell':
                            """
                            root@Shuncom:~# lspci
                            00:00.0 Class 0604: 0e8d:0801
                            01:00.0 Class 0c03: 1912:0015
                            """
                            if '1912:0015' in data:
                                self.status = "finish"
                                sz_log.info('网关ttyUSB正常')
                            self.tty_usb_num += 1
                            print('检查ttyUSB运行次数',self.tty_usb_num)
                            time.sleep(1)
                            if self.tty_usb_num > 10:
                                self.vbox_obj.vbox_handle.report_properties({"notice": 'ttyUSB异常(pcie转usb3.0),请检查硬件问题!'})
    
                elif self.status == "finish":
                    self.device_status = 'finish_reboot'
                    sz_log.info('生产完成Mac地址:',self.config["gwmac"])
                    self.vbox_obj.vbox_handle.report_properties({"info": 'MAC:%s 生产完成,请更换下一台网关!!!'% self.config["gwmac"]})
                    if "SHUNCOM-U-BOOT" in data: # uboot
                        self.refresh_vars()
                        self.status = "process"
                        self.device_status = "break_uboot"
    
            sz_log.info("device status 后:" + self.device_status)
    
    
    
    class rev_tcp(StreamRequestHandler):
        """ https://zhuanlan.zhihu.com/p/50214470  tcp接收数据
            创建一个继承自 SocketServer.BaseRequestHandler 的类,类中必须定义一个名称为 handle 的方法
        """
        def handle(self):
            global client_ip
            global cmd_text
            global gwproductor_id
            try:
                client_ip = self.client_address
                sz_log.info('客户端地址', self.client_address)
                config_web_url = config_init.get('CONFIG_SHUNCOM', 'config_web_url')
                sz_log.info('生产平台是:',config_web_url)
                self.productor = productor_t("PRODUCTOR_GW_1", gwproductor_id, config_web_url, 8027)
                self.request.settimeout(1.0)
                #client_ip_list.append([self.client_address,self.request,self.wfile,self.rfile,self.productor,time.time()])
                client_ip_list.append([self.client_address])
                report_seqs = 0
                while True:
                    try:
                        data = self.request.recv(1024)
                    except socket.timeout:
                        pass
                    else:
                        if (len(data) == 0):
                            sz_log.info("客户端自动断开关闭,socket shut down")
                            self.productor.vbox_obj.vbox_handle.report_properties({"notice": '[串口服务器]自动断开了,【控制台-生产状态】重新开始'})
                            self.finish()
                            break
                        try:
                            splited_str = data.decode('utf-8').split('\n')
                            print('接收数据 splited_str: %s' % splited_str)
                            sz_log.info(splited_str)
                            print("#########################################################串口接收到的数据splited_str#############",splited_str)
                        except Exception as e:
                            splited_str = ''
                            sz_log.info("data.decode('utf-8')data异常,请检查串口线是否接触不良", e)
                            # self.productor.vbox_obj.vbox_handle.report_properties({"notice": '串口服务器异常,请检查串口线是否接触不良,【控制台-生产状态】重新开始'})
    
                        try:
                            if len(splited_str) > 0:
                                if 'gwproductor' in splited_str:
                                    # self.deviceId = splited_str[0]
                                    print('串口服务器的心跳包:', splited_str[0])
    
                                for tmp_log_line in splited_str:
                                    if 'MMC init failed' in tmp_log_line:
                                        self.productor.vbox_obj.vbox_handle.report_properties({"notice": 'EMMC初始化失败,【控制台-生产状态】网关重启,重新生产'})
                                    if 'ARP Retry count exceeded; starting again' in tmp_log_line:
                                        sz_log.info('tftp网络不通')
                                        # self.productor.vbox_obj.vbox_handle.report_properties({"notice": 'tftp网络不通,ARP Retry count exceeded; starting again'})
                                    if self.productor.config["running"] == True:
                                        self.productor.vbox_obj.vbox_handle.report_properties({"log": tmp_log_line})
                            else:
                                if self.productor.config["running"] == True:
                                    self.productor.vbox_obj.vbox_handle.report_properties({"log": data.decode('utf-8')})
                            if self.productor.config["running"] == True:
                                self.productor.process_uart_data(data.decode('utf-8'))
                        except:
                            sz_log.info('data数据无法解析')
    
                    if len(client_ip_list) > 1:
                        try:
                            sz_log.info('删除前客户端列表:', client_ip_list)
                            for x in range(len(client_ip_list) - 1):
                                self.finish()
                                client_ip_list.pop(x)
                        except:
                            pass
                        sz_log.info('删除后客户端列表:', client_ip_list)
                        break
    
                    if (report_seqs > 3):
                        self.productor.vbox_obj.vbox_handle.report_properties(
                            {"status": self.productor.get_status(), "step": self.productor.get_step()})
                        if self.productor.get_status() == "process" and self.productor.get_step() == 2:
                            if self.productor.Request_bdinfo_mac == 0:
                                if len(self.productor.mac_exist_in_gw) > 0:
                                    if self.productor.config["gwmac"] == "无":
                                        sz_log.info('检测到mac无 刷写过固件')
                                        self.productor.config["gwmac"] = self.productor.mac_exist_in_gw
                                else:
                                    if self.productor.config["gwmac"] == "无":
                                        sz_log.info('检测到mac无 没有刷写过固件')
                                        self.productor.vbox_obj.vbox_handle.report_properties(
                                            {"gwmac": "无", "bdinfo": self.productor.config["bdinfo"]})
                                self.productor.Request_bdinfo_mac = 1  # 请求平台分配bdinfo Mac一次
    
                        self.productor.vbox_obj.vbox_handle.report_properties(self.productor.get_config())
                        print("【主线程线程数量】:", len(threading.enumerate()))
                        sz_log.info("【主线程线程数量】:", len(threading.enumerate()))
                        report_seqs = 0
                    report_seqs += 1
    
                    data = self.productor.do_step()
                    if data:
                        sz_log.info(" 下发串口数据 write port:\n" + data)
                        self.request.sendall(data.encode('utf-8'))
                    if cmd_text:
                        sz_log.info(" 下发执行cmd命令: " + cmd_text)
                        if cmd_text == '回车':
                            self.request.sendall('\r'.encode('utf-8'))
                        elif cmd_text == '程序重启':
                            cmd_text = ''
                            client_ip_list.clear()
                            self.finish()
                            break
                        else:
                            self.request.sendall(cmd_text.encode('utf-8'))
                        cmd_text = ''
    
            except Exception as e:
                sz_log.info('rev_tcp程序异常', e)
                self.finish()
                client_ip_list.pop(0)
    
        def finish(self):
            """ wfile close,rfile close,mqtt close """
            try:
                self.request.close()
                if not self.wfile.closed:
                    try:
                        self.wfile.flush()
                    except socket.error:
                        pass
                self.wfile.close()
                self.rfile.close()
                self.productor.vbox_obj.vbox_handle.stop()
            except Exception as e:
                sz_log.info('finish异常', e)
    
    
    class ThreadingTCPServerA(ThreadingTCPServer):
        """ThreadingTCPServer从ThreadingMixIn和TCPServer继承
            继承SocketServer.ThreadingTCPServer,在init之前设置allow_reuse_address = True(默认为False)
        """
        allow_reuse_address = True
        sz_log.info('电脑ip地址:', host)
    
    
    
    
    class run_class():
        """运行和停止"""
    
        def run_(self,gw_id):
            global gwproductor_id
            gwproductor_id = gw_id # 聚盒基地生产ID
    
            self.tftp_server = sz_tftp_server(tftp_path, tftp_ip, 69)
            threading.Thread(target=self.tftp_server.sz_tftp_server, args=()).start()
            self.rev_tcp = rev_tcp
            config_ep = config_init.get('CONFIG_SHUNCOM', 'config_ep')
            addr = (host, int(config_ep))
            sz_log.info(('ip地址和端口:',addr, self.rev_tcp))
            self.TCP_server = ThreadingTCPServerA(addr, self.rev_tcp)
            self.TCP_server.serve_forever()  # 启动线程 #永久循环执行,可以接受多个客户端连接
    
    
        def run_stop(self):
            sz_log.info('+'*30 + '关闭程序' + '+'*30 + '\n\n')
            self.rev_tcp.finish()
            self.tftp_server.tftpy_close()
            self.TCP_server.server_close()
    
    
    
    if __name__ == '__main__':
        pass
    
        # t_path = os.path.split(os.path.realpath(__file__))[0]
        # if not os.path.exists(t_path + r'\tmp\tftp/'):
        #     os.mkdir(t_path + r'\tmp\tftp/')
        # tftp_path = os.path.split(os.path.realpath(__file__))[0]+ r'\tmp\tftp/'
        # tftp_server = sz_tftp_server(tftp_path, tftp_ip, 69)
        # threading.Thread(target=tftp_server.sz_tftp_server, args=()).start()
        # TCP_server = ThreadingTCPServerA(addr, rev_tcp)
        # TCP_server.serve_forever()  # 启动线程 #永久循环执行,可以接受多个客户端连接
    
    
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
    • 431
    • 432
    • 433
    • 434
    • 435
    • 436
    • 437
    • 438
    • 439
    • 440
    • 441
    • 442
    • 443
    • 444
    • 445
    • 446
    • 447
    • 448
    • 449
    • 450
    • 451
    • 452
    • 453
    • 454
    • 455
    • 456
    • 457
    • 458
    • 459
    • 460
    • 461
    • 462
    • 463
    • 464
    • 465
    • 466
    • 467
    • 468
    • 469
    • 470
    • 471
    • 472
    • 473
    • 474
    • 475
    • 476
    • 477
    • 478
    • 479
    • 480
    • 481
    • 482
    • 483
    • 484
    • 485
    • 486
    • 487
    • 488
    • 489
    • 490
    • 491
    • 492
    • 493
    • 494
    • 495
    • 496
    • 497
    • 498
    • 499
    • 500
    • 501
    • 502
    • 503
    • 504
    • 505
    • 506
    • 507
    • 508
    • 509
    • 510
    • 511
    • 512
    • 513
    • 514
    • 515
    • 516
    • 517
    • 518
    • 519
    • 520
    • 521
    • 522
    • 523
    • 524
    • 525
    • 526
    • 527
    • 528
    • 529
    • 530
    • 531
    • 532
    • 533
    • 534
    • 535
    • 536
    • 537
    • 538
    • 539
    • 540
    • 541
    • 542
    • 543
    • 544
    • 545
    • 546
    • 547
    • 548
    • 549
    • 550
    • 551
    • 552
    • 553
    • 554
    • 555
    • 556
    • 557
    • 558
    • 559
    • 560
    • 561
    • 562
    • 563
    • 564
    • 565
    • 566
    • 567
    • 568
    • 569
    • 570
    • 571
    • 572
    • 573
    • 574
    • 575
    • 576
    • 577
    • 578
    • 579
    • 580
    • 581
    • 582
    • 583
    • 584
    • 585
    • 586
    • 587
    • 588
    • 589
    • 590
    • 591
    • 592
    • 593
    • 594
    • 595
    • 596
    • 597
    • 598
    • 599
    • 600
    • 601
    • 602
    • 603
    • 604
    • 605
    • 606
    • 607
    • 608
    • 609
    • 610
    • 611
    • 612
    • 613
    • 614
    • 615
    • 616
    • 617
    • 618
    • 619
    • 620
    • 621
    • 622
    • 623
    • 624
    • 625
    • 626
    • 627
    • 628
    • 629
    • 630
    • 631
    • 632
    • 633
    • 634
    • 635
    • 636
    • 637
    • 638
    • 639
    • 640
    • 641
    • 642
    • 643
    • 644
    • 645
    • 646
    • 647
    • 648
    • 649
    • 650
    • 651
    • 652
    • 653
    • 654
    • 655
    • 656
    • 657
    • 658
    • 659
    • 660
    • 661
    • 662
    • 663
    • 664
    • 665
    • 666
    • 667
    • 668
    • 669
    • 670
    • 671
    • 672
    • 673
    • 674
    • 675
    • 676
    • 677
    • 678
    • 679
    • 680
    • 681
    • 682
    • 683
    • 684
    • 685
    • 686
    • 687
    • 688
    • 689
    • 690
    • 691
    • 692
    • 693
    • 694
    • 695
    • 696
    • 697
    • 698
    • 699
    • 700
    • 701
    • 702
    • 703
    • 704
    • 705
    • 706
    • 707
    • 708
    • 709
    • 710
    • 711
    • 712
    • 713
    • 714
    • 715
    • 716
    • 717
    • 718
    • 719
    • 720
    • 721
    • 722
    • 723
    • 724
    • 725
    • 726
    • 727
    • 728
    • 729
    • 730
    • 731
    • 732
    • 733
    • 734
    • 735
    • 736
    • 737
    • 738
    • 739
    • 740
    • 741
    • 742
    • 743
    • 744
    • 745
    • 746
    • 747
    • 748
    • 749
    • 750
    • 751
    • 752
    • 753
    • 754
    • 755
    • 756
    • 757
    • 758
    • 759
    • 760
    • 761
    • 762
    • 763
    • 764
    • 765
    • 766
    • 767
    • 768
    • 769
    • 770
    • 771
    • 772
    • 773
    • 774
    • 775
    • 776
    • 777
    • 778
    • 779
    • 780
    • 781
    • 782
    • 783
    • 784
    • 785
    • 786
    • 787
    • 788
    • 789
    • 790
    • 791
    • 792
    • 793
    • 794
    • 795
    • 796
    • 797
    • 798
    • 799
    • 800
    • 801
    • 802
    • 803
    • 804
    • 805
    • 806
    • 807
    • 808
    • 809
    • 810
    • 811
    • 812
    • 813
    • 814
    • 815
    • 816
    • 817
    • 818
    • 819
    • 820
    • 821
    • 822
    • 823
  • 相关阅读:
    我们的插件能力再升级:支持双声道,效果堪比同传!
    嵌入式软件工程师面试题——2025校招专题(四)
    福州大学《嵌入式系统综合设计》 实验八:FFMPEG视频编码
    Rasa 3.x 学习系列-非常荣幸成为 Rasa contributors 源码贡献者,和全世界的Rasa源码贡献者共建共享Rasa社区!
    社区买菜系统 毕业设计 JAVA+Vue+SpringBoot+MySQL
    [附源码]Python计算机毕业设计成绩管理与学情分析系统
    CentOS 7 中安装Kafka
    泰勒展开式
    [Python] pop()函数
    lstm时间序列 深度学习
  • 原文地址:https://blog.csdn.net/m0_43453199/article/details/127971467