# !/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' # 回车4次
if 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:
创建一个继承自 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() # 启动线程 #永久循环执行,可以接受多个客户端连接