v1.2.5
This commit is contained in:
113
network.py
113
network.py
@@ -466,11 +466,29 @@ class NetworkManager:
|
||||
if not self._wifi_socket:
|
||||
return False
|
||||
try:
|
||||
# 尝试发送0字节来检测连接状态
|
||||
self._wifi_socket.send(b"", socket.MSG_DONTWAIT)
|
||||
# send(b"") 在很多实现里是 no-op,无法可靠探测断线。
|
||||
# 用非阻塞 peek 来判断:若对端已关闭,recv 会返回 b""。
|
||||
data = self._wifi_socket.recv(1, socket.MSG_PEEK | socket.MSG_DONTWAIT)
|
||||
if data == b"":
|
||||
raise OSError("wifi socket closed")
|
||||
return True
|
||||
except:
|
||||
# socket已断开
|
||||
except BlockingIOError:
|
||||
# 无数据可读但连接仍在(EAGAIN)
|
||||
return True
|
||||
except OSError as e:
|
||||
# 兼容不同平台的 EAGAIN / would block
|
||||
err = getattr(e, "errno", None)
|
||||
if err in (11, 35, 10035): # EAGAIN/EWOULDBLOCK on linux/mac/win
|
||||
return True
|
||||
# socket已断开或不可用,清理
|
||||
try:
|
||||
self._wifi_socket.close()
|
||||
except:
|
||||
pass
|
||||
self._wifi_socket = None
|
||||
self._tcp_connected = False
|
||||
return False
|
||||
except Exception:
|
||||
try:
|
||||
self._wifi_socket.close()
|
||||
except:
|
||||
@@ -524,6 +542,9 @@ class NetworkManager:
|
||||
|
||||
# 根据网络类型选择发送方式
|
||||
if self._network_type == "wifi":
|
||||
# 先快速校验 WiFi socket 是否仍有效,避免卡在半开连接上
|
||||
if not self._check_wifi_connection():
|
||||
return False
|
||||
return self._tcp_send_raw_via_wifi(data, max_retries)
|
||||
elif self._network_type == "4g":
|
||||
return self._tcp_send_raw_via_4g(data, max_retries)
|
||||
@@ -546,7 +567,7 @@ class NetworkManager:
|
||||
if sent == 0:
|
||||
# socket连接已断开
|
||||
self.logger.warning(f"[WIFI-TCP] 发送失败,socket已断开(尝试 {attempt+1}/{max_retries})")
|
||||
break
|
||||
raise OSError("wifi socket closed (send returned 0)")
|
||||
total_sent += sent
|
||||
|
||||
if total_sent == len(data):
|
||||
@@ -557,10 +578,23 @@ class NetworkManager:
|
||||
|
||||
except OSError as e:
|
||||
self.logger.error(f"[WIFI-TCP] 发送异常: {e}(尝试 {attempt+1}/{max_retries})")
|
||||
time.sleep_ms(50)
|
||||
# 发送异常通常意味着连接已不可用,主动关闭以触发重连
|
||||
try:
|
||||
self._wifi_socket.close()
|
||||
except:
|
||||
pass
|
||||
self._wifi_socket = None
|
||||
self._tcp_connected = False
|
||||
return False
|
||||
except Exception as e:
|
||||
self.logger.error(f"[WIFI-TCP] 未知错误: {e}(尝试 {attempt+1}/{max_retries})")
|
||||
time.sleep_ms(50)
|
||||
try:
|
||||
self._wifi_socket.close()
|
||||
except:
|
||||
pass
|
||||
self._wifi_socket = None
|
||||
self._tcp_connected = False
|
||||
return False
|
||||
|
||||
return False
|
||||
|
||||
@@ -743,6 +777,9 @@ class NetworkManager:
|
||||
temp_dir = "/tmp"
|
||||
temp_file_path = os.path.join(temp_dir, new_filename)
|
||||
|
||||
# 先 sync,确保所有日志都已写入磁盘
|
||||
os.system("sync")
|
||||
|
||||
# 复制日志文件到临时位置
|
||||
shutil.copy2(log_file_path, temp_file_path)
|
||||
self.logger.info(f"[LOG_UPLOAD] 日志文件已复制到: {temp_file_path}")
|
||||
@@ -853,6 +890,10 @@ class NetworkManager:
|
||||
# if not self.tcp_send_raw(self.make_packet(1, login_data)):
|
||||
if not self.tcp_send_raw(self._netcore.make_packet(1, login_data)):
|
||||
self._tcp_connected = False
|
||||
try:
|
||||
self.disconnect_server()
|
||||
except:
|
||||
pass
|
||||
time.sleep_ms(2000)
|
||||
continue
|
||||
|
||||
@@ -863,6 +904,10 @@ class NetworkManager:
|
||||
last_heartbeat_send_time = time.ticks_ms()
|
||||
|
||||
while True:
|
||||
# 如果底层连接已断开,尽快跳出内层循环触发重连/重选网络
|
||||
if not self._tcp_connected:
|
||||
break
|
||||
|
||||
# OTA 期间暂停 TCP 活动
|
||||
try:
|
||||
from ota_manager import ota_manager
|
||||
@@ -1090,6 +1135,8 @@ class NetworkManager:
|
||||
except:
|
||||
pass
|
||||
time.sleep_ms(2000)
|
||||
os.system("sync") # 刷新文件系统缓存到磁盘,防止数据丢失
|
||||
time.sleep_ms(500)
|
||||
os.system("poweroff")
|
||||
return
|
||||
elif inner_cmd == 43: # 上传日志命令
|
||||
@@ -1111,23 +1158,33 @@ class NetworkManager:
|
||||
time.sleep_ms(5)
|
||||
|
||||
# 发送队列中的业务数据
|
||||
if logged_in and (self._high_send_queue or self._normal_send_queue):
|
||||
msg_type = None
|
||||
data_dict = None
|
||||
if self.get_queue_lock().acquire(blocking=False):
|
||||
try:
|
||||
if self._high_send_queue:
|
||||
msg_type, data_dict = self._high_send_queue.pop(0)
|
||||
elif self._normal_send_queue:
|
||||
msg_type, data_dict = self._normal_send_queue.pop(0)
|
||||
finally:
|
||||
self.get_queue_lock().release()
|
||||
if logged_in:
|
||||
item = None
|
||||
item_is_high = False
|
||||
# 出队:发送失败时会把 item 放回队首,避免丢数据
|
||||
with self.get_queue_lock():
|
||||
if self._high_send_queue:
|
||||
item = self._high_send_queue.pop(0)
|
||||
item_is_high = True
|
||||
elif self._normal_send_queue:
|
||||
item = self._normal_send_queue.pop(0)
|
||||
item_is_high = False
|
||||
|
||||
if msg_type is not None and data_dict is not None:
|
||||
if item:
|
||||
msg_type, data_dict = item
|
||||
pkt = self._netcore.make_packet(msg_type, data_dict)
|
||||
# pkt = self.make_packet(msg_type, data_dict)
|
||||
if not self.tcp_send_raw(pkt):
|
||||
# 发送失败:将消息放回队首,触发重连(避免丢消息)
|
||||
with self.get_queue_lock():
|
||||
if item_is_high:
|
||||
self._high_send_queue.insert(0, item)
|
||||
else:
|
||||
self._normal_send_queue.insert(0, item)
|
||||
self._tcp_connected = False
|
||||
try:
|
||||
self.disconnect_server()
|
||||
except:
|
||||
pass
|
||||
break
|
||||
|
||||
# 发送激光校准结果
|
||||
@@ -1144,15 +1201,15 @@ class NetworkManager:
|
||||
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.make_packet(4, {"vol": vol_val, "vol_per": voltage_to_percent(vol_val)})):
|
||||
self.logger.error("心跳发送失败")
|
||||
time.sleep_ms(3000)
|
||||
# 心跳失败说明链路不可用:立刻触发重连,避免长时间卡住
|
||||
self.logger.error("心跳发送失败,准备重连")
|
||||
send_hartbeat_fail_count += 1
|
||||
if send_hartbeat_fail_count >= 3:
|
||||
send_hartbeat_fail_count = 0
|
||||
self.logger.error("连续3次发送心跳失败,重连")
|
||||
break
|
||||
else:
|
||||
continue
|
||||
self._tcp_connected = False
|
||||
try:
|
||||
self.disconnect_server()
|
||||
except:
|
||||
pass
|
||||
break
|
||||
else:
|
||||
send_hartbeat_fail_count = 0
|
||||
last_heartbeat_send_time = current_time
|
||||
|
||||
Reference in New Issue
Block a user