|
|
@@ -22,13 +22,14 @@ class DeviceInitData:
|
|
|
LowSpeed: float = 0.0 # 速度阈值,比如5.0(速度>5触发回调)
|
|
|
|
|
|
|
|
|
-# ========== 新增1:超时清空状态管理 ==========
|
|
|
+# ========== 新增1:超时清空状态管理(修复初始化+超大时间差) ==========
|
|
|
class ScreenClearManager:
|
|
|
- """屏幕超时清空管理器"""
|
|
|
+ """屏幕超时清空管理器(修复初始化问题)"""
|
|
|
|
|
|
def __init__(self, timeout_seconds: float = 2.0):
|
|
|
self.timeout_seconds = timeout_seconds # 超时时间(秒)
|
|
|
- self.last_valid_time = 0.0 # 最后一次收到有效数据的时间
|
|
|
+ # 初始化:使用当前时间,避免超大时间差
|
|
|
+ self.last_valid_time = time.time()
|
|
|
self.screen_cleared = False # 屏幕是否已清空
|
|
|
|
|
|
def update_valid_time(self):
|
|
|
@@ -38,34 +39,61 @@ class ScreenClearManager:
|
|
|
|
|
|
def check_and_clear(self, radar_screen: Optional[Screen]) -> bool:
|
|
|
"""
|
|
|
- 检查是否需要清空屏幕
|
|
|
+ 检查是否需要清空屏幕(修复清空逻辑+错误处理)
|
|
|
:return: 是否清空了屏幕
|
|
|
"""
|
|
|
- if radar_screen is None or not radar_screen.get_live_state():
|
|
|
+ # 1. 屏幕实例不存在/未连接,直接返回
|
|
|
+ if radar_screen is None or not hasattr(radar_screen, 'get_live_state') or not radar_screen.get_live_state():
|
|
|
return False
|
|
|
|
|
|
current_time = time.time()
|
|
|
time_since_last_valid = current_time - self.last_valid_time
|
|
|
|
|
|
+ # 2. 仅在超时且未清空时执行(修复超大时间差显示)
|
|
|
if time_since_last_valid > self.timeout_seconds and not self.screen_cleared:
|
|
|
- # 超时了,清空屏幕
|
|
|
- print(f"⏱️ 雷达超时:{time_since_last_valid:.1f}秒无有效数据,清空屏幕 {radar_screen.conn.getpeername()}")
|
|
|
+ # 限制最大显示时间差为timeout_seconds*2,避免超大数值
|
|
|
+ display_seconds = min(time_since_last_valid, self.timeout_seconds * 2)
|
|
|
+ # 获取屏幕地址(兼容不同Screen类实现)
|
|
|
+ screen_addr = ""
|
|
|
try:
|
|
|
- ff = FlashFile()
|
|
|
- ff.set_msg("00", 0) # 发送空内容
|
|
|
- ff.set_mode(4, 2)
|
|
|
- ff.set_origin(0, True, 0)
|
|
|
- ff.set_area(128, True, 96)
|
|
|
- radar_screen.text_ram(ff, False)
|
|
|
+ screen_addr = radar_screen.conn.getpeername() if hasattr(radar_screen, 'conn') else (
|
|
|
+ radar_screen.ip, radar_screen.port)
|
|
|
+ except:
|
|
|
+ screen_addr = "未知地址"
|
|
|
+
|
|
|
+ print(f"雷达超时:{display_seconds:.1f}秒无有效数据,清空屏幕 {screen_addr}")
|
|
|
+
|
|
|
+ try:
|
|
|
+ # 修复清空逻辑:优先使用安全的del_ram_text,兼容不同Screen实现
|
|
|
+ if hasattr(radar_screen, 'del_ram_text'):
|
|
|
+ radar_screen.del_ram_text(0)
|
|
|
+ # 备选方案:显示空内容(兼容无del_ram_text的情况)
|
|
|
+ elif hasattr(radar_screen, 'text_ram'):
|
|
|
+ ff = FlashFile()
|
|
|
+ ff.set_msg("", 0)
|
|
|
+ ff.set_mode(4, 2)
|
|
|
+ ff.set_origin(0, True, 0)
|
|
|
+ ff.set_area(128, True, 96)
|
|
|
+ radar_screen.text_ram(ff, False)
|
|
|
+
|
|
|
self.screen_cleared = True
|
|
|
return True
|
|
|
except Exception as e:
|
|
|
- print(f"❌ 清空屏幕失败:{e}")
|
|
|
+ # 精准捕获错误,避免'dyna_area_num'报错刷屏
|
|
|
+ if 'dyna_area_num' in str(e):
|
|
|
+ print(f"清空屏幕失败:屏幕实例无'dyna_area_num'属性(非致命错误)")
|
|
|
+ else:
|
|
|
+ print(f"清空屏幕失败:{str(e)[:50]}") # 限制错误信息长度
|
|
|
+ return False
|
|
|
+
|
|
|
+ # 3. 未超时但已清空(恢复数据后重置)
|
|
|
+ elif time_since_last_valid <= self.timeout_seconds and self.screen_cleared:
|
|
|
+ self.screen_cleared = False
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
-# 初始化全局的超时清空管理器
|
|
|
+# 初始化全局的超时清空管理器(确保启动时就初始化)
|
|
|
screen_clear_manager = ScreenClearManager(timeout_seconds=2.0)
|
|
|
|
|
|
|
|
|
@@ -132,8 +160,8 @@ def parse_radar_frame(frame: bytes) -> RadarData:
|
|
|
data.Speed = float(hundreds * 100 + tens * 10 + units) + float(decimal) / 10.0
|
|
|
data.Valid = True
|
|
|
|
|
|
- # ========== 新增2:打印解析到的原始数据(调试用) ==========
|
|
|
- print(f"📡 雷达解析成功:方向={data.Direction},速度={data.Speed:.1f},原始帧={frame!r}")
|
|
|
+ # ========== 调试用:打印解析到的原始数据 ==========
|
|
|
+ # print(f"📡 雷达解析成功:方向={data.Direction},速度={data.Speed:.1f},原始帧={frame!r}")
|
|
|
|
|
|
return data
|
|
|
|
|
|
@@ -169,7 +197,7 @@ def callback_with_data(
|
|
|
print(f"语音播报失败:{e}")
|
|
|
|
|
|
# 屏幕显示
|
|
|
- if radar_screen and radar_screen.get_live_state():
|
|
|
+ if radar_screen and hasattr(radar_screen, 'get_live_state') and radar_screen.get_live_state():
|
|
|
try:
|
|
|
ff = FlashFile()
|
|
|
ff.set_msg(rounded_speed, color)
|
|
|
@@ -178,10 +206,10 @@ def callback_with_data(
|
|
|
ff.set_area(128, True, 96)
|
|
|
radar_screen.text_ram(ff, False)
|
|
|
|
|
|
- # ========== 新增3:更新有效数据时间 ==========
|
|
|
+ # ========== 更新有效数据时间 ==========
|
|
|
screen_clear_manager.update_valid_time()
|
|
|
|
|
|
- print(f"✅ 雷达速度{rounded_speed}已发送到屏幕")
|
|
|
+ # print(f"雷达速度{rounded_speed}已发送到屏幕")
|
|
|
except Exception as e:
|
|
|
print(f"雷达屏幕显示失败:{e}")
|
|
|
|
|
|
@@ -192,7 +220,7 @@ def open_serial(
|
|
|
radar_screen: Optional[Screen] = None,
|
|
|
radar_serial_ref=None
|
|
|
):
|
|
|
- """打开雷达串口并监听(彻底解决残留数据问题)"""
|
|
|
+ """打开雷达串口并监听(彻底解决残留数据+初始化问题)"""
|
|
|
radar_serial = radar_serial_ref
|
|
|
|
|
|
serial_options = {
|
|
|
@@ -214,18 +242,23 @@ def open_serial(
|
|
|
send_len = radar_serial.write(radar_cmd)
|
|
|
if send_len != len(radar_cmd):
|
|
|
print(f"雷达配置指令发送不完整")
|
|
|
+
|
|
|
time.sleep(0.1)
|
|
|
|
|
|
read_buf: List[int] = []
|
|
|
buf = bytearray(1024)
|
|
|
last_clear_check = time.time()
|
|
|
+ # 初始化有效数据时间(双重保障)
|
|
|
last_valid_data_time = time.time()
|
|
|
+ # 重置屏幕清空管理器(确保每次重连都初始化)
|
|
|
+ screen_clear_manager.last_valid_time = time.time()
|
|
|
+ screen_clear_manager.screen_cleared = False
|
|
|
|
|
|
while True:
|
|
|
try:
|
|
|
n = radar_serial.readinto(buf)
|
|
|
|
|
|
- # 定期检查超时清空
|
|
|
+ # 定期检查超时清空(0.2秒一次,避免高频检查)
|
|
|
current_time = time.time()
|
|
|
if current_time - last_clear_check > 0.2:
|
|
|
screen_clear_manager.check_and_clear(radar_screen)
|
|
|
@@ -259,10 +292,12 @@ def open_serial(
|
|
|
# 更新时间
|
|
|
last_valid_data_time = data_time
|
|
|
last_clear_check = current_time
|
|
|
+ # 更新清空管理器的时间(核心修复:有数据时同步)
|
|
|
+ screen_clear_manager.update_valid_time()
|
|
|
|
|
|
# 日志显示
|
|
|
# local_time = time.strftime("%H:%M:%S", time.localtime(data_time))
|
|
|
- # print(f"📡 [{local_time}] 速度={radar_data.Speed:.1f} (距上次{time_since_last:.2f}秒)")
|
|
|
+ # print(f"[{local_time}] 速度={radar_data.Speed:.1f} (距上次{time_since_last:.2f}秒)")
|
|
|
if radar_data.Speed < 5:
|
|
|
continue
|
|
|
|