pref: 版本说明
This commit is contained in:
2
app.yaml
2
app.yaml
@@ -1,6 +1,6 @@
|
|||||||
id: t11
|
id: t11
|
||||||
name: t11
|
name: t11
|
||||||
version: 2.15.3
|
version: 2.15.6
|
||||||
author: t11
|
author: t11
|
||||||
icon: ''
|
icon: ''
|
||||||
desc: t11
|
desc: t11
|
||||||
|
|||||||
@@ -309,7 +309,7 @@ LASER_THICKNESS = 1
|
|||||||
LASER_LENGTH = 2
|
LASER_LENGTH = 2
|
||||||
|
|
||||||
# ==================== 图像保存配置 ====================
|
# ==================== 图像保存配置 ====================
|
||||||
SAVE_IMAGE_ENABLED = False # 是否保存图像(True=保存,False=不保存)
|
SAVE_IMAGE_ENABLED = True # 是否保存图像(True=保存,False=不保存)
|
||||||
PHOTO_DIR = "/root/phot" # 照片存储目录
|
PHOTO_DIR = "/root/phot" # 照片存储目录
|
||||||
MAX_IMAGES = 1000
|
MAX_IMAGES = 1000
|
||||||
# Stage2 调试目录(默认 PHOTO_DIR/stage2_roi)内 JPEG 最多保留张数;None 表示与 MAX_IMAGES 相同
|
# Stage2 调试目录(默认 PHOTO_DIR/stage2_roi)内 JPEG 最多保留张数;None 表示与 MAX_IMAGES 相同
|
||||||
|
|||||||
119
network.py
119
network.py
@@ -8,7 +8,7 @@ import json
|
|||||||
import re
|
import re
|
||||||
from math import e
|
from math import e
|
||||||
import struct
|
import struct
|
||||||
from maix import time,network,err
|
from maix import time, network, err
|
||||||
import hmac
|
import hmac
|
||||||
import hashlib
|
import hashlib
|
||||||
import ujson
|
import ujson
|
||||||
@@ -24,7 +24,6 @@ from wifi import wifi_manager
|
|||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _wifi_tls_would_block(exc):
|
def _wifi_tls_would_block(exc):
|
||||||
"""
|
"""
|
||||||
非阻塞 TLS 下 recv/send 常抛出 WANT_READ / WANT_WRITE(或等价文案),
|
非阻塞 TLS 下 recv/send 常抛出 WANT_READ / WANT_WRITE(或等价文案),
|
||||||
@@ -84,7 +83,8 @@ class NetworkManager:
|
|||||||
try:
|
try:
|
||||||
import archery_netcore as _netcore
|
import archery_netcore as _netcore
|
||||||
self._netcore = _netcore
|
self._netcore = _netcore
|
||||||
if hasattr(self._netcore, "parse_packet") and hasattr(self._netcore, "make_packet") and hasattr(self._netcore, "actions_for_inner_cmd"):
|
if hasattr(self._netcore, "parse_packet") and hasattr(self._netcore, "make_packet") and hasattr(
|
||||||
|
self._netcore, "actions_for_inner_cmd"):
|
||||||
print("[NET] archery_netcore found")
|
print("[NET] archery_netcore found")
|
||||||
else:
|
else:
|
||||||
print("[NET] archery_netcore not found parse_packet or make_packet")
|
print("[NET] archery_netcore not found parse_packet or make_packet")
|
||||||
@@ -147,7 +147,6 @@ class NetworkManager:
|
|||||||
|
|
||||||
# ==================== 内部状态管理方法 ====================
|
# ==================== 内部状态管理方法 ====================
|
||||||
|
|
||||||
|
|
||||||
def set_manual_trigger(self, value=True):
|
def set_manual_trigger(self, value=True):
|
||||||
"""设置手动触发标志(公共方法)"""
|
"""设置手动触发标志(公共方法)"""
|
||||||
self._manual_trigger_flag = value
|
self._manual_trigger_flag = value
|
||||||
@@ -203,6 +202,7 @@ class NetworkManager:
|
|||||||
|
|
||||||
def read_device_id(self):
|
def read_device_id(self):
|
||||||
"""从 /device_key 文件读取设备唯一 ID,失败则使用默认值"""
|
"""从 /device_key 文件读取设备唯一 ID,失败则使用默认值"""
|
||||||
|
|
||||||
def _set_password_for_device_id(device_id):
|
def _set_password_for_device_id(device_id):
|
||||||
if getattr(config, "USE_TCP_SSL", False):
|
if getattr(config, "USE_TCP_SSL", False):
|
||||||
iccid = self.get_4g_mccid()
|
iccid = self.get_4g_mccid()
|
||||||
@@ -242,6 +242,7 @@ class NetworkManager:
|
|||||||
连接 Wi-Fi:委托 ``wifi_manager.connect_wifi``。
|
连接 Wi-Fi:委托 ``wifi_manager.connect_wifi``。
|
||||||
未指定 ``verify_host``/``verify_port`` 时,可达性校验使用本管理器配置的 ``_server_ip``/``_server_port``。
|
未指定 ``verify_host``/``verify_port`` 时,可达性校验使用本管理器配置的 ``_server_ip``/``_server_port``。
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def _verify(ip: str):
|
def _verify(ip: str):
|
||||||
v_host = verify_host if verify_host is not None else self._server_ip
|
v_host = verify_host if verify_host is not None else self._server_ip
|
||||||
v_port = verify_port if verify_port is not None else self._server_port
|
v_port = verify_port if verify_port is not None else self._server_port
|
||||||
@@ -552,7 +553,6 @@ class NetworkManager:
|
|||||||
self._session_force_4g = False
|
self._session_force_4g = False
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def _cmd200_detect_laser(self):
|
def _cmd200_detect_laser(self):
|
||||||
"""后台线程执行 cmd200 激光检测,避免阻塞主循环"""
|
"""后台线程执行 cmd200 激光检测,避免阻塞主循环"""
|
||||||
from laser_manager import laser_manager
|
from laser_manager import laser_manager
|
||||||
@@ -598,8 +598,24 @@ class NetworkManager:
|
|||||||
err.check_raise(e, "connect wifi failed")
|
err.check_raise(e, "connect wifi failed")
|
||||||
if self.logger:
|
if self.logger:
|
||||||
self.logger.info(f"[ota] Connect success, got ip{w.get_ip()}")
|
self.logger.info(f"[ota] Connect success, got ip{w.get_ip()}")
|
||||||
|
self.safe_enqueue(
|
||||||
|
{
|
||||||
|
"cmd": 300,
|
||||||
|
"result": "ota start...",
|
||||||
|
"wifi": w.get_ip(),
|
||||||
|
},
|
||||||
|
2,
|
||||||
|
)
|
||||||
subprocess.run(
|
subprocess.run(
|
||||||
["sh", "/maixapp/apps/t11/ota_curl.sh", ota_res_url])
|
["sh", "/maixapp/apps/t11/ota_curl.sh", ota_res_url])
|
||||||
|
self.safe_enqueue(
|
||||||
|
{
|
||||||
|
"cmd": 300,
|
||||||
|
"result": "success",
|
||||||
|
"wifi": w.get_ip(),
|
||||||
|
},
|
||||||
|
2,
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"[ota] cmd300 失败: {e}")
|
self.logger.error(f"[ota] cmd300 失败: {e}")
|
||||||
self.safe_enqueue(
|
self.safe_enqueue(
|
||||||
@@ -615,9 +631,6 @@ class NetworkManager:
|
|||||||
"""线程安全地将消息加入队列(公共方法)"""
|
"""线程安全地将消息加入队列(公共方法)"""
|
||||||
self._enqueue((msg_type, data_dict), high)
|
self._enqueue((msg_type, data_dict), high)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def connect_server(self):
|
def connect_server(self):
|
||||||
"""
|
"""
|
||||||
连接到服务器(自动选择WiFi或4G)
|
连接到服务器(自动选择WiFi或4G)
|
||||||
@@ -894,7 +907,6 @@ class NetworkManager:
|
|||||||
finally:
|
finally:
|
||||||
self._uart4g_lock.release()
|
self._uart4g_lock.release()
|
||||||
|
|
||||||
|
|
||||||
def tcp_send_raw(self, data: bytes, max_retries=2) -> bool:
|
def tcp_send_raw(self, data: bytes, max_retries=2) -> bool:
|
||||||
"""
|
"""
|
||||||
统一的TCP发送接口(自动选择WiFi或4G)
|
统一的TCP发送接口(自动选择WiFi或4G)
|
||||||
@@ -942,7 +954,7 @@ class NetworkManager:
|
|||||||
raise
|
raise
|
||||||
if sent == 0:
|
if sent == 0:
|
||||||
# socket连接已断开
|
# socket连接已断开
|
||||||
self.logger.warning(f"[WIFI-TCP] 发送失败,socket已断开(尝试 {attempt+1}/{max_retries})")
|
self.logger.warning(f"[WIFI-TCP] 发送失败,socket已断开(尝试 {attempt + 1}/{max_retries})")
|
||||||
raise OSError("wifi socket closed (send returned 0)")
|
raise OSError("wifi socket closed (send returned 0)")
|
||||||
total_sent += sent
|
total_sent += sent
|
||||||
|
|
||||||
@@ -953,7 +965,7 @@ class NetworkManager:
|
|||||||
time.sleep_ms(50)
|
time.sleep_ms(50)
|
||||||
|
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
self.logger.error(f"[WIFI-TCP] 发送异常: {e}(尝试 {attempt+1}/{max_retries})")
|
self.logger.error(f"[WIFI-TCP] 发送异常: {e}(尝试 {attempt + 1}/{max_retries})")
|
||||||
# 发送异常通常意味着连接已不可用,主动关闭以触发重连
|
# 发送异常通常意味着连接已不可用,主动关闭以触发重连
|
||||||
try:
|
try:
|
||||||
wifi_manager.wifi_socket.close()
|
wifi_manager.wifi_socket.close()
|
||||||
@@ -963,7 +975,7 @@ class NetworkManager:
|
|||||||
self._tcp_connected = False
|
self._tcp_connected = False
|
||||||
return False
|
return False
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"[WIFI-TCP] 未知错误: {e}(尝试 {attempt+1}/{max_retries})")
|
self.logger.error(f"[WIFI-TCP] 未知错误: {e}(尝试 {attempt + 1}/{max_retries})")
|
||||||
try:
|
try:
|
||||||
wifi_manager.wifi_socket.close()
|
wifi_manager.wifi_socket.close()
|
||||||
except:
|
except:
|
||||||
@@ -1054,7 +1066,6 @@ class NetworkManager:
|
|||||||
r = hardware_manager.at_client.send(f'AT+MSSLCERTRD="{cert_filename}"', "OK", 3000)
|
r = hardware_manager.at_client.send(f'AT+MSSLCERTRD="{cert_filename}"', "OK", 3000)
|
||||||
self.logger.info(f"[4G-TCP] AT+MSSLCERTRD=\"{cert_filename}\" response: {r}")
|
self.logger.info(f"[4G-TCP] AT+MSSLCERTRD=\"{cert_filename}\" response: {r}")
|
||||||
|
|
||||||
|
|
||||||
# 3) 引用根证书
|
# 3) 引用根证书
|
||||||
r = hardware_manager.at_client.send(f'AT+MSSLCFG="cert",{ssl_id},"{cert_filename}"', "OK", 3000)
|
r = hardware_manager.at_client.send(f'AT+MSSLCFG="cert",{ssl_id},"{cert_filename}"', "OK", 3000)
|
||||||
if "OK" not in r:
|
if "OK" not in r:
|
||||||
@@ -1112,7 +1123,8 @@ class NetworkManager:
|
|||||||
self.logger.error(f"[WIFI-TCP] 接收数据异常: {e}")
|
self.logger.error(f"[WIFI-TCP] 接收数据异常: {e}")
|
||||||
return b""
|
return b""
|
||||||
|
|
||||||
def _upload_log_file(self, upload_url, wifi_ssid=None, wifi_password=None, include_rotated=True, max_files=None, archive_format="tgz"):
|
def _upload_log_file(self, upload_url, wifi_ssid=None, wifi_password=None, include_rotated=True, max_files=None,
|
||||||
|
archive_format="tgz"):
|
||||||
"""上传日志文件到指定URL
|
"""上传日志文件到指定URL
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
@@ -1245,7 +1257,8 @@ class NetworkManager:
|
|||||||
staged_paths.append(dst)
|
staged_paths.append(dst)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"[LOG_UPLOAD] 复制日志快照失败: {e}")
|
self.logger.error(f"[LOG_UPLOAD] 复制日志快照失败: {e}")
|
||||||
self.safe_enqueue({"result": "log_upload_failed", "reason": "snapshot_failed", "detail": str(e)[:100]}, 2)
|
self.safe_enqueue({"result": "log_upload_failed", "reason": "snapshot_failed", "detail": str(e)[:100]},
|
||||||
|
2)
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(staging_dir)
|
shutil.rmtree(staging_dir)
|
||||||
except:
|
except:
|
||||||
@@ -1273,7 +1286,8 @@ class NetworkManager:
|
|||||||
self.logger.info(f"[LOG_UPLOAD] 日志压缩包已生成: {archive_path}")
|
self.logger.info(f"[LOG_UPLOAD] 日志压缩包已生成: {archive_path}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"[LOG_UPLOAD] 打包压缩失败: {e}")
|
self.logger.error(f"[LOG_UPLOAD] 打包压缩失败: {e}")
|
||||||
self.safe_enqueue({"result": "log_upload_failed", "reason": "archive_failed", "detail": str(e)[:100]}, 2)
|
self.safe_enqueue({"result": "log_upload_failed", "reason": "archive_failed", "detail": str(e)[:100]},
|
||||||
|
2)
|
||||||
try:
|
try:
|
||||||
shutil.rmtree(staging_dir)
|
shutil.rmtree(staging_dir)
|
||||||
except:
|
except:
|
||||||
@@ -1322,7 +1336,8 @@ class NetworkManager:
|
|||||||
"status_code": response.status_code
|
"status_code": response.status_code
|
||||||
}, 2)
|
}, 2)
|
||||||
else:
|
else:
|
||||||
self.logger.error(f"[LOG_UPLOAD] 上传失败! 状态码: {response.status_code}, 响应: {response.text[:200]}")
|
self.logger.error(
|
||||||
|
f"[LOG_UPLOAD] 上传失败! 状态码: {response.status_code}, 响应: {response.text[:200]}")
|
||||||
self.safe_enqueue({
|
self.safe_enqueue({
|
||||||
"result": "log_upload_failed",
|
"result": "log_upload_failed",
|
||||||
"reason": f"http_{response.status_code}",
|
"reason": f"http_{response.status_code}",
|
||||||
@@ -1458,7 +1473,8 @@ class NetworkManager:
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
return None, f"prepare_exception: {e}"
|
return None, f"prepare_exception: {e}"
|
||||||
|
|
||||||
def _upload_log_file_v2(self, upload_url, upload_token, key, outlink="", include_rotated=True, max_files=None, archive_format="tgz"):
|
def _upload_log_file_v2(self, upload_url, upload_token, key, outlink="", include_rotated=True, max_files=None,
|
||||||
|
archive_format="tgz"):
|
||||||
"""上传日志到 Qiniu(支持 WiFi 和 4G 双路径)
|
"""上传日志到 Qiniu(支持 WiFi 和 4G 双路径)
|
||||||
|
|
||||||
流程:准备日志归档 -> 自动检测网络 -> WiFi(requests) 或 4G(AT命令) 上传
|
流程:准备日志归档 -> 自动检测网络 -> WiFi(requests) 或 4G(AT命令) 上传
|
||||||
@@ -1793,7 +1809,8 @@ class NetworkManager:
|
|||||||
|
|
||||||
if not logged_in:
|
if not logged_in:
|
||||||
try:
|
try:
|
||||||
self.logger.debug(f"[TCP] rx link={link_id} len={len(payload)} head={payload[:12].hex()}")
|
self.logger.debug(
|
||||||
|
f"[TCP] rx link={link_id} len={len(payload)} head={payload[:12].hex()}")
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -1819,7 +1836,8 @@ class NetworkManager:
|
|||||||
pending_obj = json.load(f)
|
pending_obj = json.load(f)
|
||||||
except:
|
except:
|
||||||
pending_obj = {}
|
pending_obj = {}
|
||||||
self.safe_enqueue({"result": "ota_ok", "url": pending_obj.get("url", "")}, 2)
|
self.safe_enqueue({"result": "ota_ok", "url": pending_obj.get("url", "")},
|
||||||
|
2)
|
||||||
self.logger.info("[OTA] 已上报 ota_ok,等待心跳确认后删除 pending")
|
self.logger.info("[OTA] 已上报 ota_ok,等待心跳确认后删除 pending")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"[OTA] ota_ok 上报失败: {e}")
|
self.logger.error(f"[OTA] ota_ok 上报失败: {e}")
|
||||||
@@ -1838,7 +1856,8 @@ class NetworkManager:
|
|||||||
t = body.get('t', 0)
|
t = body.get('t', 0)
|
||||||
v = body.get('v')
|
v = body.get('v')
|
||||||
# 如果是第一个分片,清空之前的缓存
|
# 如果是第一个分片,清空之前的缓存
|
||||||
if len(self._raw_line_data) == 0 or (len(self._raw_line_data) > 0 and self._raw_line_data[0].get('v') != v):
|
if len(self._raw_line_data) == 0 or (
|
||||||
|
len(self._raw_line_data) > 0 and self._raw_line_data[0].get('v') != v):
|
||||||
self._raw_line_data.clear()
|
self._raw_line_data.clear()
|
||||||
# 或者更简单:每次收到命令40时,如果版本号不同,清空缓存
|
# 或者更简单:每次收到命令40时,如果版本号不同,清空缓存
|
||||||
if len(self._raw_line_data) > 0:
|
if len(self._raw_line_data) > 0:
|
||||||
@@ -1855,7 +1874,7 @@ class NetworkManager:
|
|||||||
file.write("\n".join(stock_array))
|
file.write("\n".join(stock_array))
|
||||||
ota_manager.apply_ota_and_reboot(None, local_filename)
|
ota_manager.apply_ota_and_reboot(None, local_filename)
|
||||||
else:
|
else:
|
||||||
self.safe_enqueue({'data':{'l': len(self._raw_line_data), 'v': v}, 'cmd': 41})
|
self.safe_enqueue({'data': {'l': len(self._raw_line_data), 'v': v}, 'cmd': 41})
|
||||||
self.logger.info(f"已下载{len(self._raw_line_data)} 全部:{t} 版本:{v}")
|
self.logger.info(f"已下载{len(self._raw_line_data)} 全部:{t} 版本:{v}")
|
||||||
|
|
||||||
elif logged_in and msg_type == 100:
|
elif logged_in and msg_type == 100:
|
||||||
@@ -1872,7 +1891,8 @@ class NetworkManager:
|
|||||||
# 验证必需字段
|
# 验证必需字段
|
||||||
if not upload_url or not upload_token or not shoot_id:
|
if not upload_url or not upload_token or not shoot_id:
|
||||||
self.logger.error("[IMAGE_UPLOAD] 缺少必需参数: uploadUrl, token 或 shootId")
|
self.logger.error("[IMAGE_UPLOAD] 缺少必需参数: uploadUrl, token 或 shootId")
|
||||||
self.safe_enqueue({"result": "image_upload_failed", "reason": "missing_params"}, 2)
|
self.safe_enqueue({"result": "image_upload_failed", "reason": "missing_params"},
|
||||||
|
2)
|
||||||
else:
|
else:
|
||||||
self.logger.info(f"[IMAGE_UPLOAD] 收到图片上传命令,shootId: {shoot_id}")
|
self.logger.info(f"[IMAGE_UPLOAD] 收到图片上传命令,shootId: {shoot_id}")
|
||||||
# 查找文件名中包含 shoot_id 的图片文件(文件名格式:shot_{shoot_id}_*.bmp)
|
# 查找文件名中包含 shoot_id 的图片文件(文件名格式:shot_{shoot_id}_*.bmp)
|
||||||
@@ -1893,15 +1913,19 @@ class NetworkManager:
|
|||||||
reverse=True
|
reverse=True
|
||||||
)
|
)
|
||||||
target_image = os.path.join(photo_dir, matched_images[0])
|
target_image = os.path.join(photo_dir, matched_images[0])
|
||||||
self.logger.info(f"[IMAGE_UPLOAD] 找到匹配shootId的图片: {matched_images[0]}")
|
self.logger.info(
|
||||||
|
f"[IMAGE_UPLOAD] 找到匹配shootId的图片: {matched_images[0]}")
|
||||||
else:
|
else:
|
||||||
self.logger.warning(f"[IMAGE_UPLOAD] 未找到包含shootId={shoot_id}的图片文件")
|
self.logger.warning(
|
||||||
|
f"[IMAGE_UPLOAD] 未找到包含shootId={shoot_id}的图片文件")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
self.logger.error(f"[IMAGE_UPLOAD] 查找图片失败: {e}")
|
self.logger.error(f"[IMAGE_UPLOAD] 查找图片失败: {e}")
|
||||||
|
|
||||||
if not target_image:
|
if not target_image:
|
||||||
self.logger.error(f"[IMAGE_UPLOAD] 未找到shootId={shoot_id}对应的图片文件")
|
self.logger.error(f"[IMAGE_UPLOAD] 未找到shootId={shoot_id}对应的图片文件")
|
||||||
self.safe_enqueue({"result": "image_upload_failed", "reason": "no_image_found", "shootId": shoot_id}, 2)
|
self.safe_enqueue(
|
||||||
|
{"result": "image_upload_failed", "reason": "no_image_found",
|
||||||
|
"shootId": shoot_id}, 2)
|
||||||
else:
|
else:
|
||||||
# 构建上传key
|
# 构建上传key
|
||||||
ext = os.path.splitext(target_image)[1].lower()
|
ext = os.path.splitext(target_image)[1].lower()
|
||||||
@@ -1933,14 +1957,16 @@ class NetworkManager:
|
|||||||
# 验证必需字段
|
# 验证必需字段
|
||||||
if not upload_url or not upload_token or not key:
|
if not upload_url or not upload_token or not key:
|
||||||
self.logger.error("[LOG_UPLOAD] 缺少必需参数: uploadUrl, token 或 key")
|
self.logger.error("[LOG_UPLOAD] 缺少必需参数: uploadUrl, token 或 key")
|
||||||
self.safe_enqueue({"result": "log_upload_failed", "reason": "missing_params"}, 2)
|
self.safe_enqueue({"result": "log_upload_failed", "reason": "missing_params"},
|
||||||
|
2)
|
||||||
else:
|
else:
|
||||||
self.logger.info(f"[LOG_UPLOAD] 收到日志上传命令,key: {key}")
|
self.logger.info(f"[LOG_UPLOAD] 收到日志上传命令,key: {key}")
|
||||||
# 在新线程中执行上传,避免阻塞主循环
|
# 在新线程中执行上传,避免阻塞主循环
|
||||||
import _thread
|
import _thread
|
||||||
_thread.start_new_thread(
|
_thread.start_new_thread(
|
||||||
self._upload_log_file_v2,
|
self._upload_log_file_v2,
|
||||||
(upload_url, upload_token, key, outlink, include_rotated, max_files, archive_format)
|
(upload_url, upload_token, key, outlink, include_rotated, max_files,
|
||||||
|
archive_format)
|
||||||
)
|
)
|
||||||
# 立即返回已入队确认
|
# 立即返回已入队确认
|
||||||
self.safe_enqueue({"result": "log_upload_queued"}, 2)
|
self.safe_enqueue({"result": "log_upload_queued"}, 2)
|
||||||
@@ -2040,10 +2066,12 @@ class NetworkManager:
|
|||||||
# 只有同时满足:WiFi已连接 且 提供了WiFi凭证,才使用WiFi
|
# 只有同时满足:WiFi已连接 且 提供了WiFi凭证,才使用WiFi
|
||||||
if self.is_wifi_connected() and ssid and password:
|
if self.is_wifi_connected() and ssid and password:
|
||||||
mode = "wifi"
|
mode = "wifi"
|
||||||
self.logger.info("ota auto-selected: wifi (WiFi connected and credentials provided)")
|
self.logger.info(
|
||||||
|
"ota auto-selected: wifi (WiFi connected and credentials provided)")
|
||||||
else:
|
else:
|
||||||
mode = "4g"
|
mode = "4g"
|
||||||
self.logger.info("ota auto-selected: 4g (WiFi not available or no credentials)")
|
self.logger.info(
|
||||||
|
"ota auto-selected: 4g (WiFi not available or no credentials)")
|
||||||
|
|
||||||
hardware_manager.stop_idle_timer() # 停表,注意OTA停表之后,就没有再开表,因为OTA后面会重启,会重新开表
|
hardware_manager.stop_idle_timer() # 停表,注意OTA停表之后,就没有再开表,因为OTA后面会重启,会重新开表
|
||||||
|
|
||||||
@@ -2059,10 +2087,12 @@ class NetworkManager:
|
|||||||
self.logger.info(f"ssid: {ssid}")
|
self.logger.info(f"ssid: {ssid}")
|
||||||
self.logger.info(f"password: {password}")
|
self.logger.info(f"password: {password}")
|
||||||
ota_manager._start_update_thread()
|
ota_manager._start_update_thread()
|
||||||
_thread.start_new_thread(ota_manager.handle_wifi_and_update, (ssid, password, ota_url))
|
_thread.start_new_thread(ota_manager.handle_wifi_and_update,
|
||||||
|
(ssid, password, ota_url))
|
||||||
elif inner_cmd == 6:
|
elif inner_cmd == 6:
|
||||||
try:
|
try:
|
||||||
ip = os.popen("ifconfig wlan0 2>/dev/null | grep 'inet ' | awk '{print $2}'").read().strip()
|
ip = os.popen(
|
||||||
|
"ifconfig wlan0 2>/dev/null | grep 'inet ' | awk '{print $2}'").read().strip()
|
||||||
ip = ip if ip else "no_ip"
|
ip = ip if ip else "no_ip"
|
||||||
except:
|
except:
|
||||||
ip = "error_getting_ip"
|
ip = "error_getting_ip"
|
||||||
@@ -2070,11 +2100,13 @@ class NetworkManager:
|
|||||||
elif inner_cmd == 44: # 读 4G 本机号码(AT+CNUM)
|
elif inner_cmd == 44: # 读 4G 本机号码(AT+CNUM)
|
||||||
cnum = self.get_4g_phone_number()
|
cnum = self.get_4g_phone_number()
|
||||||
self.logger.info(f"4G 本机号码: {cnum}")
|
self.logger.info(f"4G 本机号码: {cnum}")
|
||||||
self.safe_enqueue({"result": "cnum", "number": cnum if cnum is not None else ""}, 2)
|
self.safe_enqueue(
|
||||||
|
{"result": "cnum", "number": cnum if cnum is not None else ""}, 2)
|
||||||
elif inner_cmd == 45: # 读 MCCID(AT+MCCID)
|
elif inner_cmd == 45: # 读 MCCID(AT+MCCID)
|
||||||
mccid = self.get_4g_mccid()
|
mccid = self.get_4g_mccid()
|
||||||
self.logger.info(f"4G MCCID: {mccid}")
|
self.logger.info(f"4G MCCID: {mccid}")
|
||||||
self.safe_enqueue({"result": "mccid", "mccid": mccid if mccid is not None else ""}, 2)
|
self.safe_enqueue(
|
||||||
|
{"result": "mccid", "mccid": mccid if mccid is not None else ""}, 2)
|
||||||
elif inner_cmd == 41:
|
elif inner_cmd == 41:
|
||||||
self.logger.info(f"[TEST] 收到TCP射箭触发命令, {time.time()}")
|
self.logger.info(f"[TEST] 收到TCP射箭触发命令, {time.time()}")
|
||||||
self._manual_trigger_flag = True
|
self._manual_trigger_flag = True
|
||||||
@@ -2111,14 +2143,16 @@ class NetworkManager:
|
|||||||
|
|
||||||
if not upload_url:
|
if not upload_url:
|
||||||
self.logger.error("[LOG_UPLOAD] 缺少 url 参数")
|
self.logger.error("[LOG_UPLOAD] 缺少 url 参数")
|
||||||
self.safe_enqueue({"result": "log_upload_failed", "reason": "missing_url"}, 2)
|
self.safe_enqueue({"result": "log_upload_failed", "reason": "missing_url"},
|
||||||
|
2)
|
||||||
else:
|
else:
|
||||||
self.logger.info(f"[LOG_UPLOAD] 收到日志上传命令,目标URL: {upload_url}")
|
self.logger.info(f"[LOG_UPLOAD] 收到日志上传命令,目标URL: {upload_url}")
|
||||||
# 在新线程中执行上传,避免阻塞主循环
|
# 在新线程中执行上传,避免阻塞主循环
|
||||||
import _thread
|
import _thread
|
||||||
_thread.start_new_thread(
|
_thread.start_new_thread(
|
||||||
self._upload_log_file,
|
self._upload_log_file,
|
||||||
(upload_url, wifi_ssid, wifi_password, include_rotated, max_files, archive_format)
|
(upload_url, wifi_ssid, wifi_password, include_rotated, max_files,
|
||||||
|
archive_format)
|
||||||
)
|
)
|
||||||
elif inner_cmd == 200:
|
elif inner_cmd == 200:
|
||||||
self.logger.info("[LASER] cmd200 在后台线程执行检测")
|
self.logger.info("[LASER] cmd200 在后台线程执行检测")
|
||||||
@@ -2181,7 +2215,8 @@ class NetworkManager:
|
|||||||
current_time = time.ticks_ms()
|
current_time = time.ticks_ms()
|
||||||
if logged_in and current_time - last_heartbeat_send_time > config.HEARTBEAT_INTERVAL * 1000:
|
if logged_in and current_time - last_heartbeat_send_time > config.HEARTBEAT_INTERVAL * 1000:
|
||||||
vol_val = get_bus_voltage()
|
vol_val = get_bus_voltage()
|
||||||
if not self.tcp_send_raw(self._netcore.make_packet(4, {"vol": vol_val, "vol_per": voltage_to_percent(vol_val)})):
|
if not self.tcp_send_raw(
|
||||||
|
self._netcore.make_packet(4, {"vol": vol_val, "vol_per": voltage_to_percent(vol_val)})):
|
||||||
# if not self.tcp_send_raw(self.make_packet(4, {"vol": vol_val, "vol_per": voltage_to_percent(vol_val)})):
|
# if not self.tcp_send_raw(self.make_packet(4, {"vol": vol_val, "vol_per": voltage_to_percent(vol_val)})):
|
||||||
send_hartbeat_fail_count += 1
|
send_hartbeat_fail_count += 1
|
||||||
# 短暂波动可能导致一次发送失败:连续失败达到阈值才重连,避免重连风暴
|
# 短暂波动可能导致一次发送失败:连续失败达到阈值才重连,避免重连风暴
|
||||||
@@ -2241,38 +2276,44 @@ class NetworkManager:
|
|||||||
# 创建全局单例实例
|
# 创建全局单例实例
|
||||||
network_manager = NetworkManager()
|
network_manager = NetworkManager()
|
||||||
|
|
||||||
|
|
||||||
# ==================== 向后兼容的函数接口 ====================
|
# ==================== 向后兼容的函数接口 ====================
|
||||||
|
|
||||||
def tcp_main():
|
def tcp_main():
|
||||||
"""TCP主循环(向后兼容接口)"""
|
"""TCP主循环(向后兼容接口)"""
|
||||||
return network_manager.tcp_main()
|
return network_manager.tcp_main()
|
||||||
|
|
||||||
|
|
||||||
def read_device_id():
|
def read_device_id():
|
||||||
"""读取设备ID(向后兼容接口)"""
|
"""读取设备ID(向后兼容接口)"""
|
||||||
return network_manager.read_device_id()
|
return network_manager.read_device_id()
|
||||||
|
|
||||||
|
|
||||||
def safe_enqueue(data_dict, msg_type=2, high=False):
|
def safe_enqueue(data_dict, msg_type=2, high=False):
|
||||||
"""线程安全地加入队列(向后兼容接口)"""
|
"""线程安全地加入队列(向后兼容接口)"""
|
||||||
return network_manager.safe_enqueue(data_dict, msg_type, high)
|
return network_manager.safe_enqueue(data_dict, msg_type, high)
|
||||||
|
|
||||||
|
|
||||||
def connect_server():
|
def connect_server():
|
||||||
"""连接服务器(向后兼容接口)"""
|
"""连接服务器(向后兼容接口)"""
|
||||||
return network_manager.connect_server()
|
return network_manager.connect_server()
|
||||||
|
|
||||||
|
|
||||||
def disconnet_server():
|
def disconnet_server():
|
||||||
"""断开服务器连接(向后兼容接口)"""
|
"""断开服务器连接(向后兼容接口)"""
|
||||||
return network_manager.disconnect_server()
|
return network_manager.disconnect_server()
|
||||||
|
|
||||||
|
|
||||||
def is_wifi_connected():
|
def is_wifi_connected():
|
||||||
"""检查WiFi是否已连接(向后兼容接口)"""
|
"""检查WiFi是否已连接(向后兼容接口)"""
|
||||||
return network_manager.is_wifi_connected()
|
return network_manager.is_wifi_connected()
|
||||||
|
|
||||||
|
|
||||||
def connect_wifi(ssid, password):
|
def connect_wifi(ssid, password):
|
||||||
"""连接WiFi(向后兼容接口)"""
|
"""连接WiFi(向后兼容接口)"""
|
||||||
return network_manager.connect_wifi(ssid, password)
|
return network_manager.connect_wifi(ssid, password)
|
||||||
|
|
||||||
|
|
||||||
def is_server_reachable(host, port=80, timeout=5):
|
def is_server_reachable(host, port=80, timeout=5):
|
||||||
"""检查服务器是否可达(向后兼容接口)"""
|
"""检查服务器是否可达(向后兼容接口)"""
|
||||||
return network_manager.is_server_reachable(host, port, timeout)
|
return network_manager.is_server_reachable(host, port, timeout)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -14,4 +14,6 @@
|
|||||||
# 1.2.13 修改wifi连接
|
# 1.2.13 修改wifi连接
|
||||||
# 1.2.14 修改了icc登录部分
|
# 1.2.14 修改了icc登录部分
|
||||||
# 2.15.3 新版本ota,去除ai算环数方法
|
# 2.15.3 新版本ota,去除ai算环数方法
|
||||||
|
# 2.15.4 更新版本号
|
||||||
|
# 2.15.5 打印ota进度
|
||||||
|
# 2.15.6 更新版本号
|
||||||
|
|||||||
@@ -4,6 +4,6 @@
|
|||||||
应用版本号
|
应用版本号
|
||||||
每次 OTA 更新时,只需要更新这个文件中的版本号
|
每次 OTA 更新时,只需要更新这个文件中的版本号
|
||||||
"""
|
"""
|
||||||
VERSION = '2.15.3'
|
VERSION = '2.15.6'
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user