Compare commits

..

2 Commits

Author SHA1 Message Date
fb2d4ffc00 update 2026-03-03 14:10:16 +08:00
b47962e5c8 增加日志功能,增加打包成exe功能,点击exe就可以使用 2026-03-03 14:07:54 +08:00
8 changed files with 1213 additions and 65 deletions

6
.gitignore vendored
View File

@@ -11,3 +11,9 @@
*.app
.snapshots/*
# PyInstaller 打包输出
dist/
build/
*.spec
remo_disp.log

View File

@@ -43,11 +43,34 @@ python remo_disp_server.py [装置IP]
python remo_disp_server.py 192.168.253.3
```
## 打包为 exeWindows
在项目目录下执行:
```bash
# 安装 PyInstaller 后打包
pip install pyinstaller
python -m PyInstaller remo_disp_server.spec --noconfirm
```
或直接双击运行 `build_exe.bat`
打包完成后可执行文件为 **dist\\remo_disp_server.exe**。双击运行,或在命令行:
```bash
dist\remo_disp_server.exe
dist\remo_disp_server.exe 192.168.253.3
```
运行后浏览器访问 http://localhost:8181。日志会输出到控制台同目录下会生成 `remo_disp.log`
## 项目结构
```
DTU-RemoteLCD/
├── remo_disp_server.py # Web 服务Flask + Socket.IO
├── remo_disp_server.spec # PyInstaller 打包配置
├── build_exe.bat # 一键打包脚本Windows
├── remo_disp_ui.html # Web 前端页面
├── requirements.txt # Python 依赖
├── static/ # 静态资源(可选)
@@ -55,9 +78,7 @@ DTU-RemoteLCD/
└── README.md
```
## 协议说明RemoDispBus
`HMI/RemoeDisp/RemoDispBus.c` 兼容:
## 协议说明
| 项目 | 说明 |
|------|------|
@@ -96,6 +117,15 @@ DTU-RemoteLCD/
| flask-socketio | WebSocket 支持 |
| python-socketio | Socket.IO 服务端 |
| Pillow | 1bpp 位图转 PNG |
| loguru | 结构化日志、错误追踪 |
## 日志与调试
- 后端使用 `loguru` 输出日志,默认会打印到控制台,并写入当前目录下的 `remo_disp.log`
-`remo_disp_server.py` 顶部有 `LOG_LEVEL` 常量:
- `LOG_LEVEL = "INFO"`:只输出 INFO/WARNING/ERROR 级别日志(默认)。
- `LOG_LEVEL = "DEBUG"`:输出包括 DEBUG 在内的详细调试信息。
- exe 版本(`remo_disp_server.exe`)同样会在运行目录生成 `remo_disp.log`,方便线下排查问题。
## 配置说明

17
build_exe.bat Normal file
View File

@@ -0,0 +1,17 @@
@echo off
chcp 65001 >nul
echo 正在打包 DTU-RemoteLCD 为 exe ...
echo.
rem 使用当前环境中的 python 和 pip而不是系统默认 pip
python -m pip install pyinstaller -q
python -m PyInstaller remo_disp_server.spec --noconfirm
if %ERRORLEVEL% equ 0 (
echo.
echo 打包完成。可执行文件: dist\remo_disp_server.exe
echo 直接双击运行,或在命令行: dist\remo_disp_server.exe [装置IP]
) else (
echo 打包失败,请检查错误信息。
exit /b 1
)

907
remo_disp.log Normal file
View File

@@ -0,0 +1,907 @@
2026-03-03 10:39:32.028 | INFO | __main__:main:408 - 远程显示服务: http://localhost:8181
2026-03-03 10:39:32.029 | INFO | __main__:main:409 - 使用 WebSocket 传输,在浏览器中打开上述地址
2026-03-03 10:39:32.623 | INFO | __main__:main:408 - 远程显示服务: http://localhost:8181
2026-03-03 10:39:32.623 | INFO | __main__:main:409 - 使用 WebSocket 传输,在浏览器中打开上述地址
2026-03-03 10:39:32.649 | INFO | __main__:on_connect:331 - [on_connect] WebSocket 客户端已连接 sid=KYbr0SIfA_Ge-yHjAAAB
2026-03-03 10:39:39.958 | INFO | __main__:on_disconnect_device:374 - [on_disconnect_device] 前端请求断开设备 sid=KYbr0SIfA_Ge-yHjAAAB
2026-03-03 10:39:39.959 | INFO | __main__:on_disconnect_device:380 - [on_disconnect_device] 设备已断开(若为最后一个客户端)
2026-03-03 10:39:42.887 | INFO | __main__:on_connect_device:353 - [on_connect_device] 请求连接 DTU: 192.168.253.3:7003
2026-03-03 10:39:42.891 | INFO | __main__:connect:137 - [connect] 连接 DTU 成功: 192.168.253.3:7003
2026-03-03 10:39:42.892 | INFO | __main__:_screen_refresh_loop:270 - [_screen_refresh_loop] 刷新线程启动
2026-03-03 10:39:42.892 | INFO | __main__:on_connect_device:361 - [on_connect_device] 已启动屏幕刷新线程
2026-03-03 10:39:42.892 | INFO | __main__:on_connect_device:363 - [on_connect_device] 连接 DTU 成功,已加入订阅 sid=KYbr0SIfA_Ge-yHjAAAB
2026-03-03 10:39:42.892 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:42.919 | ERROR | __main__:_recv:174 - [_recv] 数据不完整, 需要 3209 字节, 实际 2048 字节
2026-03-03 10:39:42.919 | ERROR | __main__:fetch_screen:211 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:39:43.025 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:43.026 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=1161
2026-03-03 10:39:43.026 | ERROR | __main__:parse_frame:97 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:39:43.026 | ERROR | __main__:fetch_screen:211 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:39:43.130 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:43.130 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:43.130 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:43.131 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:43.187 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:43.210 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=881
2026-03-03 10:39:43.312 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:43.312 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:43.313 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:43.313 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:43.314 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:43.320 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=881
2026-03-03 10:39:43.432 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:43.432 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:43.432 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:43.434 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:43.434 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:43.453 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=881
2026-03-03 10:39:43.569 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:43.570 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:43.570 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:43.570 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:43.570 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:43.577 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=881
2026-03-03 10:39:43.692 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:43.692 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:43.692 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:43.692 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:43.692 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:43.702 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=881
2026-03-03 10:39:43.813 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:43.813 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:43.814 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:43.814 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:43.814 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:43.822 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=881
2026-03-03 10:39:43.936 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:43.936 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:43.937 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:43.937 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:43.937 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:43.944 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=882
2026-03-03 10:39:44.057 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:44.057 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:44.057 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:44.059 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:44.059 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:44.065 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=882
2026-03-03 10:39:44.179 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:44.179 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:44.179 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:44.179 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:44.179 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:44.187 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=882
2026-03-03 10:39:44.301 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:44.302 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:44.302 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:44.302 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:44.302 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:44.307 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=882
2026-03-03 10:39:44.421 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:44.422 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:44.422 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:44.422 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:44.422 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:44.430 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=882
2026-03-03 10:39:44.542 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:44.542 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:44.543 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:44.543 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:44.543 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:44.549 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=882
2026-03-03 10:39:44.663 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:44.663 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:44.663 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:44.664 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:44.664 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:44.672 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=882
2026-03-03 10:39:44.784 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:44.784 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:44.784 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:44.784 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:44.786 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:44.792 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=882
2026-03-03 10:39:44.904 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:44.904 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:44.904 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:44.906 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:44.906 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:44.912 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=882
2026-03-03 10:39:45.026 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:45.026 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:45.027 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:45.027 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:45.027 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:45.033 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=882
2026-03-03 10:39:45.148 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:45.152 | ERROR | __main__:_recv:174 - [_recv] 数据不完整, 需要 3209 字节, 实际 1460 字节
2026-03-03 10:39:45.153 | ERROR | __main__:fetch_screen:211 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:39:45.269 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:45.269 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=4958
2026-03-03 10:39:45.270 | ERROR | __main__:parse_frame:97 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:39:45.270 | ERROR | __main__:fetch_screen:211 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:39:45.376 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:45.376 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:45.376 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:45.376 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:45.376 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:45.382 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=987
2026-03-03 10:39:45.495 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:45.497 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:45.497 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:45.497 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:45.498 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:45.506 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=987
2026-03-03 10:39:45.616 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:45.616 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:45.618 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:45.618 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:45.618 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:45.629 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=987
2026-03-03 10:39:45.739 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:45.740 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:45.740 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:45.740 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:45.740 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:45.746 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=987
2026-03-03 10:39:45.860 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:45.860 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:45.861 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:45.861 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:45.861 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:45.868 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=987
2026-03-03 10:39:45.982 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:45.982 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:45.983 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:45.983 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:45.983 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:45.990 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=987
2026-03-03 10:39:46.102 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:46.102 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:46.103 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:46.103 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:46.103 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:46.110 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=987
2026-03-03 10:39:46.223 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:46.224 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:46.224 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:46.224 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:46.224 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:46.233 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=987
2026-03-03 10:39:46.345 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:46.345 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:46.345 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:46.346 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:46.346 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:46.352 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=987
2026-03-03 10:39:46.453 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:46.453 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:46.454 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:46.454 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:46.454 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:46.460 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=987
2026-03-03 10:39:46.574 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:46.575 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:46.575 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:46.575 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:46.575 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:46.582 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=987
2026-03-03 10:39:46.695 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:46.695 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:46.696 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:46.696 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:46.696 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:46.704 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=987
2026-03-03 10:39:46.818 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:46.818 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:46.819 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:46.819 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:46.819 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:46.826 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=987
2026-03-03 10:39:46.937 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:46.938 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:46.938 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:46.939 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:46.939 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:46.947 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=987
2026-03-03 10:39:47.060 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:47.060 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:47.061 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:47.061 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:47.061 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:47.068 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=987
2026-03-03 10:39:47.180 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:47.180 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:47.180 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:47.180 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:47.180 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:47.190 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=990
2026-03-03 10:39:47.302 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:47.302 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:47.303 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:47.303 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:47.304 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:47.310 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=990
2026-03-03 10:39:47.423 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:47.423 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:47.424 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:47.424 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:47.424 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:47.431 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=990
2026-03-03 10:39:47.546 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:47.546 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:47.546 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:47.546 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:47.546 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:47.554 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=990
2026-03-03 10:39:47.668 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:47.668 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:47.668 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:47.668 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:47.668 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:47.675 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=990
2026-03-03 10:39:47.790 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:47.790 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:47.790 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:47.792 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:47.792 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:47.797 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=990
2026-03-03 10:39:47.910 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:47.919 | ERROR | __main__:_recv:174 - [_recv] 数据不完整, 需要 3209 字节, 实际 1460 字节
2026-03-03 10:39:47.919 | ERROR | __main__:fetch_screen:211 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:39:48.032 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:48.033 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=4958
2026-03-03 10:39:48.033 | ERROR | __main__:parse_frame:97 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:39:48.033 | ERROR | __main__:fetch_screen:211 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:39:48.137 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:48.137 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:48.137 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:48.138 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:48.138 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:48.148 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=990
2026-03-03 10:39:48.260 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:48.260 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:48.261 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:48.261 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:48.261 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:48.270 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=988
2026-03-03 10:39:48.381 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:48.381 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:48.382 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:48.382 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:48.382 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:48.387 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=988
2026-03-03 10:39:48.502 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:48.503 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:48.503 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:48.504 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:48.504 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:48.513 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=988
2026-03-03 10:39:48.624 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:48.624 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:48.625 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:48.625 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:48.625 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:48.632 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=988
2026-03-03 10:39:48.746 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:48.746 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:48.746 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:48.747 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:48.747 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:48.754 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=988
2026-03-03 10:39:48.866 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:48.866 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:48.866 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:48.867 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:48.867 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:48.873 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=988
2026-03-03 10:39:48.988 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:48.988 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:48.988 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:48.989 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:48.989 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:48.994 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=988
2026-03-03 10:39:49.109 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:49.119 | ERROR | __main__:_recv:174 - [_recv] 数据不完整, 需要 3209 字节, 实际 1460 字节
2026-03-03 10:39:49.119 | ERROR | __main__:fetch_screen:211 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:39:49.231 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:49.232 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=4958
2026-03-03 10:39:49.233 | ERROR | __main__:parse_frame:97 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:39:49.233 | ERROR | __main__:fetch_screen:211 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:39:49.338 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:49.338 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:49.339 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:49.339 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:49.339 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:49.347 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=990
2026-03-03 10:39:49.459 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:49.459 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:49.460 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:49.460 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:49.460 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:49.467 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=990
2026-03-03 10:39:49.581 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:49.582 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:49.582 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:49.582 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:49.582 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:49.589 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=990
2026-03-03 10:39:49.702 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:49.702 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:49.702 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:49.703 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:49.703 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:49.713 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=990
2026-03-03 10:39:49.822 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:49.823 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:49.823 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:49.823 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:49.823 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:49.830 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=990
2026-03-03 10:39:49.944 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:49.944 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:49.944 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:49.944 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:49.944 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:49.951 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=991
2026-03-03 10:39:50.066 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:50.066 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:50.066 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:50.067 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:50.067 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:50.080 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=991
2026-03-03 10:39:50.202 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:50.203 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:50.203 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:50.203 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:50.204 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:50.209 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=991
2026-03-03 10:39:50.323 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:50.323 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:50.323 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:50.323 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:50.325 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:50.331 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=991
2026-03-03 10:39:50.444 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:50.444 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:50.444 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:50.445 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:50.445 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:50.451 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=991
2026-03-03 10:39:50.566 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:50.567 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:50.568 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:50.568 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:50.568 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:50.575 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=991
2026-03-03 10:39:50.686 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:50.686 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:50.686 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:50.687 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:50.687 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:50.696 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=991
2026-03-03 10:39:50.808 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:50.808 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:50.808 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:50.808 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:50.808 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:50.814 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=991
2026-03-03 10:39:50.914 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:50.916 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:50.916 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:50.917 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:50.917 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:50.928 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=991
2026-03-03 10:39:51.036 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:51.037 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:51.038 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:51.038 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:51.038 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:51.043 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=991
2026-03-03 10:39:51.160 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:51.160 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:51.161 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:51.161 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:51.162 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:51.169 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=991
2026-03-03 10:39:51.281 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:51.281 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:51.281 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:51.281 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:51.282 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:51.288 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=991
2026-03-03 10:39:51.402 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:51.403 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:51.403 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:51.403 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:51.403 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:51.411 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=929
2026-03-03 10:39:51.524 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:51.524 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:51.525 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:51.525 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:51.525 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:51.533 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=929
2026-03-03 10:39:51.644 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:51.644 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:51.644 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:51.645 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:51.645 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:51.651 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=929
2026-03-03 10:39:51.751 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:51.752 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:51.752 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:51.752 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:51.752 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:51.761 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=929
2026-03-03 10:39:51.871 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:51.886 | ERROR | __main__:_recv:174 - [_recv] 数据不完整, 需要 3209 字节, 实际 1460 字节
2026-03-03 10:39:51.886 | ERROR | __main__:fetch_screen:211 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:39:51.991 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:51.991 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=4958
2026-03-03 10:39:51.992 | ERROR | __main__:parse_frame:97 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:39:51.992 | ERROR | __main__:fetch_screen:211 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:39:52.099 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:52.100 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:52.100 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:52.100 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:52.101 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:52.107 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=931
2026-03-03 10:39:52.221 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:52.222 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:52.222 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:52.222 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:52.222 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:52.230 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=931
2026-03-03 10:39:52.343 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:52.343 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:52.344 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:52.345 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:52.346 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:52.358 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=931
2026-03-03 10:39:52.463 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:52.463 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:52.465 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:52.465 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:52.466 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:52.474 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=931
2026-03-03 10:39:52.585 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:52.586 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:52.586 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:52.587 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:52.587 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:52.597 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=931
2026-03-03 10:39:52.708 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:52.708 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:52.708 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:52.708 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:52.709 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:52.717 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=931
2026-03-03 10:39:52.829 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:52.829 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:52.830 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:52.830 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:52.831 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:52.838 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=931
2026-03-03 10:39:52.950 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:52.950 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:52.951 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:52.951 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:52.951 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:52.958 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=931
2026-03-03 10:39:53.070 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:53.070 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:53.071 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:53.071 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:53.071 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:53.078 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:53.193 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:53.194 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:53.194 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:53.194 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:53.195 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:53.203 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:53.315 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:53.317 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:53.317 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:53.317 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:53.317 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:53.324 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:53.437 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:53.437 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:53.438 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:53.438 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:53.438 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:53.444 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:53.557 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:53.558 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:53.558 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:53.558 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:53.558 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:53.565 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:53.679 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:53.680 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:53.680 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:53.680 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:53.681 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:53.686 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:53.800 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:53.800 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:53.800 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:53.800 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:53.801 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:53.807 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:53.922 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:53.922 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:53.923 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:53.923 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:53.923 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:53.930 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:54.044 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:54.044 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:54.044 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:54.044 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:54.045 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:54.053 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:54.165 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:54.165 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:54.165 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:54.167 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:54.167 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:54.172 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:54.287 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:54.288 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:54.288 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:54.288 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:54.288 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:54.297 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:54.408 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:54.409 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:54.409 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:54.410 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:54.410 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:54.419 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:54.530 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:54.530 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:54.531 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:54.531 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:54.531 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:54.537 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:54.650 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:54.650 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:54.651 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:54.651 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:54.651 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:54.658 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:54.772 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:54.772 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:54.772 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:54.772 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:54.772 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:54.780 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:54.894 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:54.895 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:54.895 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:54.895 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:54.896 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:54.902 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:55.014 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:55.014 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:55.014 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:55.014 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:55.015 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:55.021 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:55.136 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:55.136 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:55.136 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:55.137 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:55.137 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:55.145 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:55.259 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:55.259 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:55.259 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:55.260 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:55.260 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:55.266 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:55.378 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:55.379 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:55.379 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:55.380 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:55.380 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:55.387 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:55.500 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:55.500 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:55.500 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:55.501 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:55.501 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:55.507 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:55.622 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:55.622 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:55.623 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:55.623 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:55.624 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:55.633 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:55.744 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:55.744 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:55.745 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:55.745 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:55.745 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:55.752 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:55.866 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:55.866 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:55.866 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:55.866 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:55.867 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:55.875 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:55.986 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:55.987 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:55.987 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:55.988 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:55.988 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:55.995 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:56.109 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:56.110 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:56.110 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:56.110 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:56.110 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:56.118 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=930
2026-03-03 10:39:56.229 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:56.253 | ERROR | __main__:_recv:174 - [_recv] 数据不完整, 需要 3209 字节, 实际 1460 字节
2026-03-03 10:39:56.253 | ERROR | __main__:fetch_screen:211 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:39:56.366 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:56.367 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=4958
2026-03-03 10:39:56.367 | ERROR | __main__:parse_frame:97 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:39:56.367 | ERROR | __main__:fetch_screen:211 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:39:56.472 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:56.473 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:56.473 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:56.474 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:56.474 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:56.481 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=928
2026-03-03 10:39:56.593 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:56.594 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:56.594 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:56.595 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:56.595 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:56.603 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=928
2026-03-03 10:39:56.715 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:56.715 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:56.716 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:56.716 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:56.716 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:56.724 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=928
2026-03-03 10:39:56.837 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:56.837 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:56.838 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:56.838 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:56.838 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:56.846 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=928
2026-03-03 10:39:56.960 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:56.960 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:56.960 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:56.960 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:56.961 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:56.968 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=928
2026-03-03 10:39:57.083 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:57.083 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:57.083 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:57.083 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:57.085 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:57.093 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=928
2026-03-03 10:39:57.203 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:57.203 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:57.204 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:57.204 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:57.204 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:57.212 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=928
2026-03-03 10:39:57.326 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:57.327 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:57.327 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:57.328 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:57.328 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:57.336 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=928
2026-03-03 10:39:57.447 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:57.453 | ERROR | __main__:_recv:174 - [_recv] 数据不完整, 需要 3209 字节, 实际 1460 字节
2026-03-03 10:39:57.454 | ERROR | __main__:fetch_screen:211 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:39:57.554 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:57.554 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=4958
2026-03-03 10:39:57.555 | ERROR | __main__:parse_frame:97 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:39:57.555 | ERROR | __main__:fetch_screen:211 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:39:57.660 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:57.661 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:57.661 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:57.661 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:57.662 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:57.669 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=928
2026-03-03 10:39:57.782 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:57.782 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:57.783 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:57.783 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:57.783 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:57.790 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=928
2026-03-03 10:39:57.904 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:57.904 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:57.904 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:57.905 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:57.905 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:57.915 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=928
2026-03-03 10:39:58.026 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:58.026 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:58.026 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:58.026 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:58.026 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:58.033 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=928
2026-03-03 10:39:58.147 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:58.147 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:58.147 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:58.147 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:58.147 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:58.154 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=928
2026-03-03 10:39:58.267 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:58.267 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:58.267 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:58.267 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:58.267 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:58.275 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=928
2026-03-03 10:39:58.389 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:58.389 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:58.389 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:58.391 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:58.391 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:58.396 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=928
2026-03-03 10:39:58.498 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:58.498 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=3209
2026-03-03 10:39:58.498 | DEBUG | __main__:parse_frame:115 - [parse_frame] 成功解析帧 cmd=0x3, length=3204
2026-03-03 10:39:58.498 | DEBUG | __main__:fetch_screen:207 - [fetch_screen] 收到 LCDMEMpayload_len=3204
2026-03-03 10:39:58.499 | DEBUG | __main__:mono_to_png:222 - [mono_to_png] 开始转换为 PNGwidth=160, height=160, data_len=3200
2026-03-03 10:39:58.508 | DEBUG | __main__:mono_to_png:238 - [mono_to_png] 转换 PNG 成功, png_len=928
2026-03-03 10:39:58.618 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:58.619 | ERROR | __main__:_recv:174 - [_recv] 数据不完整, 需要 3209 字节, 实际 2048 字节
2026-03-03 10:39:58.619 | ERROR | __main__:fetch_screen:211 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:39:58.724 | DEBUG | __main__:_send:152 - [_send] 已发送 cmd=0x3, data_len=4
2026-03-03 10:39:58.724 | DEBUG | __main__:_recv:180 - [_recv] 收到原始数据 len=4370
2026-03-03 10:39:58.724 | ERROR | __main__:parse_frame:97 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:39:58.726 | ERROR | __main__:fetch_screen:211 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:39:58.736 | INFO | __main__:on_disconnect_device:374 - [on_disconnect_device] 前端请求断开设备 sid=KYbr0SIfA_Ge-yHjAAAB
2026-03-03 10:39:58.736 | INFO | __main__:disconnect_device:253 - [disconnect_device] 正在关闭与 DTU 的连接
2026-03-03 10:39:58.736 | INFO | __main__:_screen_refresh_loop:296 - [_screen_refresh_loop] 刷新线程退出
2026-03-03 10:39:58.737 | INFO | __main__:on_disconnect_device:380 - [on_disconnect_device] 设备已断开(若为最后一个客户端)
2026-03-03 10:42:03.734 | INFO | __main__:main:408 - 远程显示服务: http://localhost:8181
2026-03-03 10:42:03.735 | INFO | __main__:main:409 - 使用 WebSocket 传输,在浏览器中打开上述地址
2026-03-03 10:42:03.764 | INFO | __main__:on_connect:331 - [on_connect] WebSocket 客户端已连接 sid=5WGcCeshP4VteYt8AAAB
2026-03-03 10:42:10.376 | INFO | __main__:main:423 - 日志级别: INFO设置环境变量 LOG_LEVEL=DEBUG 可显示调试信息)
2026-03-03 10:42:10.376 | INFO | __main__:main:424 - 远程显示服务: http://localhost:8181
2026-03-03 10:42:10.376 | INFO | __main__:main:425 - 使用 WebSocket 传输,在浏览器中打开上述地址
2026-03-03 10:42:10.403 | INFO | __main__:on_connect:331 - [on_connect] WebSocket 客户端已连接 sid=W8a_sM62XqavuiVCAAAB
2026-03-03 10:42:15.940 | INFO | __main__:main:426 - 日志级别: INFO设置环境变量 LOG_LEVEL=DEBUG 可显示调试信息)
2026-03-03 10:42:15.941 | INFO | __main__:main:427 - 远程显示服务: http://localhost:8181
2026-03-03 10:42:15.941 | INFO | __main__:main:428 - 使用 WebSocket 传输,在浏览器中打开上述地址
2026-03-03 10:42:15.970 | INFO | __main__:on_connect:334 - [on_connect] WebSocket 客户端已连接 sid=4EYcfW07jGHRZ4WmAAAB
2026-03-03 10:44:27.578 | INFO | __main__:main:425 - 日志级别: INFO设置环境变量 LOG_LEVEL=DEBUG 可显示调试信息)
2026-03-03 10:44:27.578 | INFO | __main__:main:426 - 远程显示服务: http://localhost:8181
2026-03-03 10:44:27.578 | INFO | __main__:main:427 - 使用 WebSocket 传输,在浏览器中打开上述地址
2026-03-03 10:44:27.914 | INFO | __main__:on_connect:333 - [on_connect] WebSocket 客户端已连接 sid=kpFFdwZQI9_UkdRVAAAB
2026-03-03 10:44:31.364 | INFO | __main__:main:432 - 日志级别: INFO设置环境变量 LOG_LEVEL=DEBUG 可显示调试信息)
2026-03-03 10:44:31.364 | INFO | __main__:main:433 - 远程显示服务: http://localhost:8181
2026-03-03 10:44:31.365 | INFO | __main__:main:434 - 使用 WebSocket 传输,在浏览器中打开上述地址
2026-03-03 10:44:31.389 | INFO | __main__:on_connect:340 - [on_connect] WebSocket 客户端已连接 sid=fWxaQlSu66H29I2kAAAB
2026-03-03 10:44:35.913 | INFO | __main__:main:428 - 日志级别: INFO
2026-03-03 10:44:35.914 | INFO | __main__:main:429 - 远程显示服务: http://localhost:8181
2026-03-03 10:44:35.914 | INFO | __main__:main:430 - 使用 WebSocket 传输,在浏览器中打开上述地址
2026-03-03 10:44:36.676 | INFO | __main__:on_connect:340 - [on_connect] WebSocket 客户端已连接 sid=MqqCHhOXdrL5TKhEAAAB
2026-03-03 10:45:10.479 | INFO | __main__:main:428 - 日志级别: INFO
2026-03-03 10:45:10.481 | INFO | __main__:main:429 - 远程显示服务: http://localhost:8181
2026-03-03 10:45:10.481 | INFO | __main__:main:430 - 使用 WebSocket 传输,在浏览器中打开上述地址
2026-03-03 10:45:10.930 | INFO | __main__:on_connect:340 - [on_connect] WebSocket 客户端已连接 sid=XFoaDsSCPcyC2O4CAAAB
2026-03-03 10:45:50.769 | INFO | __main__:main:428 - 日志级别: INFO
2026-03-03 10:45:50.769 | INFO | __main__:main:429 - 远程显示服务: http://localhost:8181
2026-03-03 10:45:50.771 | INFO | __main__:main:430 - 使用 WebSocket 传输,在浏览器中打开上述地址
2026-03-03 10:45:50.800 | INFO | __main__:on_connect:340 - [on_connect] WebSocket 客户端已连接 sid=x3LE0sEpg8ZaNOzsAAAB
2026-03-03 10:46:00.098 | INFO | __main__:on_connect_device:362 - [on_connect_device] 请求连接 DTU: 192.168.253.3:7003
2026-03-03 10:46:00.119 | INFO | __main__:connect:146 - [connect] 连接 DTU 成功: 192.168.253.3:7003
2026-03-03 10:46:00.120 | INFO | __main__:_screen_refresh_loop:279 - [_screen_refresh_loop] 刷新线程启动
2026-03-03 10:46:00.120 | INFO | __main__:on_connect_device:370 - [on_connect_device] 已启动屏幕刷新线程
2026-03-03 10:46:00.121 | INFO | __main__:on_connect_device:372 - [on_connect_device] 连接 DTU 成功,已加入订阅 sid=x3LE0sEpg8ZaNOzsAAAB
2026-03-03 10:46:00.167 | ERROR | __main__:_recv:183 - [_recv] 数据不完整, 需要 3209 字节, 实际 1460 字节
2026-03-03 10:46:00.167 | ERROR | __main__:fetch_screen:220 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:46:00.269 | ERROR | __main__:parse_frame:106 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:46:00.269 | ERROR | __main__:fetch_screen:220 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:46:02.032 | ERROR | __main__:_recv:183 - [_recv] 数据不完整, 需要 3209 字节, 实际 1460 字节
2026-03-03 10:46:02.033 | ERROR | __main__:fetch_screen:220 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:46:02.146 | ERROR | __main__:parse_frame:106 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:46:02.147 | ERROR | __main__:fetch_screen:220 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:46:04.367 | ERROR | __main__:_recv:183 - [_recv] 数据不完整, 需要 3209 字节, 实际 1460 字节
2026-03-03 10:46:04.367 | ERROR | __main__:fetch_screen:220 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:46:04.473 | ERROR | __main__:parse_frame:106 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:46:04.474 | ERROR | __main__:fetch_screen:220 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:46:04.833 | ERROR | __main__:_recv:183 - [_recv] 数据不完整, 需要 3209 字节, 实际 1460 字节
2026-03-03 10:46:04.833 | ERROR | __main__:fetch_screen:220 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:46:04.943 | ERROR | __main__:parse_frame:106 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:46:04.944 | ERROR | __main__:fetch_screen:220 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:46:06.801 | ERROR | __main__:_recv:183 - [_recv] 数据不完整, 需要 3209 字节, 实际 1460 字节
2026-03-03 10:46:06.801 | ERROR | __main__:fetch_screen:220 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:46:06.903 | ERROR | __main__:parse_frame:106 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:46:06.903 | ERROR | __main__:fetch_screen:220 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:46:07.711 | INFO | __main__:on_disconnect_device:383 - [on_disconnect_device] 前端请求断开设备 sid=x3LE0sEpg8ZaNOzsAAAB
2026-03-03 10:46:07.712 | INFO | __main__:disconnect_device:262 - [disconnect_device] 正在关闭与 DTU 的连接
2026-03-03 10:46:07.712 | INFO | __main__:_screen_refresh_loop:305 - [_screen_refresh_loop] 刷新线程退出
2026-03-03 10:46:07.712 | INFO | __main__:on_disconnect_device:389 - [on_disconnect_device] 设备已断开(若为最后一个客户端)
2026-03-03 10:48:17.165 | INFO | __main__:main:447 - 日志级别: INFO
2026-03-03 10:48:17.165 | INFO | __main__:main:448 - 远程显示服务: http://localhost:8181
2026-03-03 10:48:17.167 | INFO | __main__:main:449 - 使用 WebSocket 传输,在浏览器中打开上述地址
2026-03-03 10:48:17.894 | INFO | __main__:on_connect:359 - [on_connect] WebSocket 客户端已连接 sid=mRDPLRSJgqAGeYNnAAAB
2026-03-03 10:49:32.451 | INFO | __main__:main:447 - 日志级别: INFO
2026-03-03 10:49:32.451 | INFO | __main__:main:448 - 远程显示服务: http://localhost:8181
2026-03-03 10:49:32.451 | INFO | __main__:main:449 - 使用 WebSocket 传输,在浏览器中打开上述地址
2026-03-03 10:49:32.607 | INFO | __main__:on_connect:359 - [on_connect] WebSocket 客户端已连接 sid=f7ZyM2Ov63vgtKalAAAB
2026-03-03 10:49:35.851 | INFO | __main__:on_disconnect:367 - [on_disconnect] WebSocket 客户端断开 sid=f7ZyM2Ov63vgtKalAAAB
2026-03-03 10:49:35.983 | INFO | __main__:on_connect:359 - [on_connect] WebSocket 客户端已连接 sid=PFi1_1ZJ9M7nGGCFAAAD
2026-03-03 10:49:37.907 | INFO | __main__:on_connect_device:381 - [on_connect_device] 请求连接 DTU: 192.168.253.3:7003
2026-03-03 10:49:37.931 | INFO | __main__:connect:146 - [connect] 连接 DTU 成功: 192.168.253.3:7003
2026-03-03 10:49:37.931 | INFO | __main__:_screen_refresh_loop:298 - [_screen_refresh_loop] 刷新线程启动
2026-03-03 10:49:37.931 | INFO | __main__:on_connect_device:389 - [on_connect_device] 已启动屏幕刷新线程
2026-03-03 10:49:37.932 | INFO | __main__:on_connect_device:391 - [on_connect_device] 连接 DTU 成功,已加入订阅 sid=PFi1_1ZJ9M7nGGCFAAAD
2026-03-03 10:50:50.153 | INFO | __main__:main:447 - 日志级别: INFO
2026-03-03 10:50:50.153 | INFO | __main__:main:448 - 远程显示服务: http://localhost:8181
2026-03-03 10:50:50.153 | INFO | __main__:main:449 - 使用 WebSocket 传输,在浏览器中打开上述地址
2026-03-03 10:50:50.178 | INFO | __main__:on_connect:359 - [on_connect] WebSocket 客户端已连接 sid=v7jDucygwL-SI5UhAAAB
2026-03-03 10:50:58.018 | INFO | __main__:on_disconnect_device:402 - [on_disconnect_device] 前端请求断开设备 sid=v7jDucygwL-SI5UhAAAB
2026-03-03 10:50:58.018 | INFO | __main__:on_disconnect_device:408 - [on_disconnect_device] 设备已断开(若为最后一个客户端)
2026-03-03 10:50:59.618 | INFO | __main__:on_connect_device:381 - [on_connect_device] 请求连接 DTU: 192.168.253.3:7003
2026-03-03 10:50:59.621 | INFO | __main__:connect:146 - [connect] 连接 DTU 成功: 192.168.253.3:7003
2026-03-03 10:50:59.622 | INFO | __main__:_screen_refresh_loop:298 - [_screen_refresh_loop] 刷新线程启动
2026-03-03 10:50:59.622 | INFO | __main__:on_connect_device:389 - [on_connect_device] 已启动屏幕刷新线程
2026-03-03 10:50:59.622 | INFO | __main__:on_connect_device:391 - [on_connect_device] 连接 DTU 成功,已加入订阅 sid=v7jDucygwL-SI5UhAAAB
2026-03-03 10:51:14.877 | INFO | __main__:main:447 - 日志级别: INFO
2026-03-03 10:51:14.877 | INFO | __main__:main:448 - 远程显示服务: http://localhost:8181
2026-03-03 10:51:14.878 | INFO | __main__:main:449 - 使用 WebSocket 传输,在浏览器中打开上述地址
2026-03-03 10:51:15.157 | INFO | __main__:on_connect:359 - [on_connect] WebSocket 客户端已连接 sid=2DZB0uc0SIWIREuiAAAB
2026-03-03 10:52:45.587 | INFO | __main__:main:447 - 日志级别: INFO
2026-03-03 10:52:45.587 | INFO | __main__:main:448 - 远程显示服务: http://localhost:8181
2026-03-03 10:52:45.588 | INFO | __main__:main:449 - 使用 WebSocket 传输,在浏览器中打开上述地址
2026-03-03 10:52:46.054 | INFO | __main__:on_connect:359 - [on_connect] WebSocket 客户端已连接 sid=5QBk67LW-TFDL6tHAAAB
2026-03-03 10:52:47.445 | INFO | __main__:on_disconnect:367 - [on_disconnect] WebSocket 客户端断开 sid=5QBk67LW-TFDL6tHAAAB
2026-03-03 10:52:47.518 | INFO | __main__:on_connect:359 - [on_connect] WebSocket 客户端已连接 sid=RPNvfkDbk1Eonm-BAAAD
2026-03-03 10:52:51.425 | INFO | __main__:on_connect_device:381 - [on_connect_device] 请求连接 DTU: 192.168.253.3:7003
2026-03-03 10:52:51.442 | INFO | __main__:connect:146 - [connect] 连接 DTU 成功: 192.168.253.3:7003
2026-03-03 10:52:51.442 | INFO | __main__:_screen_refresh_loop:298 - [_screen_refresh_loop] 刷新线程启动
2026-03-03 10:52:51.442 | INFO | __main__:on_connect_device:389 - [on_connect_device] 已启动屏幕刷新线程
2026-03-03 10:52:51.443 | INFO | __main__:on_connect_device:391 - [on_connect_device] 连接 DTU 成功,已加入订阅 sid=RPNvfkDbk1Eonm-BAAAD
2026-03-03 10:53:08.347 | ERROR | __main__:parse_frame:106 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:53:08.347 | ERROR | __main__:fetch_screen:239 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:53:11.872 | ERROR | __main__:parse_frame:106 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:53:11.872 | ERROR | __main__:fetch_screen:239 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:53:13.715 | ERROR | __main__:parse_frame:106 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:53:13.716 | ERROR | __main__:fetch_screen:239 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:53:14.049 | ERROR | __main__:parse_frame:106 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:53:14.049 | ERROR | __main__:fetch_screen:239 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:53:15.355 | ERROR | __main__:parse_frame:106 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:53:15.355 | ERROR | __main__:fetch_screen:239 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:53:15.461 | ERROR | __main__:parse_frame:106 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:53:15.463 | ERROR | __main__:fetch_screen:239 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:53:17.394 | ERROR | __main__:parse_frame:106 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:53:17.395 | ERROR | __main__:fetch_screen:239 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:53:18.778 | ERROR | __main__:parse_frame:106 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:53:18.779 | ERROR | __main__:fetch_screen:239 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:53:20.549 | ERROR | __main__:parse_frame:106 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:53:20.549 | ERROR | __main__:fetch_screen:239 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:53:21.248 | ERROR | __main__:parse_frame:106 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:53:21.248 | ERROR | __main__:fetch_screen:239 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:53:22.066 | ERROR | __main__:parse_frame:106 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:53:22.066 | ERROR | __main__:fetch_screen:239 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:53:23.254 | ERROR | __main__:parse_frame:106 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:53:23.254 | ERROR | __main__:fetch_screen:239 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:53:44.448 | ERROR | __main__:parse_frame:106 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:53:44.448 | ERROR | __main__:fetch_screen:239 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:53:58.162 | ERROR | __main__:parse_frame:106 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:53:58.162 | ERROR | __main__:fetch_screen:239 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:53:59.088 | ERROR | __main__:parse_frame:106 - [parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len=5
2026-03-03 10:53:59.088 | ERROR | __main__:fetch_screen:239 - [fetch_screen] 未收到有效 LCDMEM 回复result=None
2026-03-03 10:54:51.004 | INFO | __main__:main:454 - 日志级别: INFO
2026-03-03 10:54:51.005 | INFO | __main__:main:455 - 远程显示服务: http://localhost:8181
2026-03-03 10:54:51.005 | INFO | __main__:main:456 - 使用 WebSocket 传输,在浏览器中打开上述地址
2026-03-03 10:54:51.038 | INFO | __main__:on_connect:366 - [on_connect] WebSocket 客户端已连接 sid=BRUqnH5JE_4q_ZfiAAAB
2026-03-03 10:55:00.524 | INFO | __main__:main:454 - 日志级别: INFO
2026-03-03 10:55:00.525 | INFO | __main__:main:455 - 远程显示服务: http://localhost:8181
2026-03-03 10:55:00.526 | INFO | __main__:main:456 - 使用 WebSocket 传输,在浏览器中打开上述地址
2026-03-03 10:55:00.561 | INFO | __main__:on_connect:366 - [on_connect] WebSocket 客户端已连接 sid=bIsKlXE2qx-4QLI3AAAB

View File

@@ -8,7 +8,9 @@
用法: python remo_disp_server.py [装置IP]
启动后访问 http://localhost:8181
依赖: pip install flask flask-socketio pillow
依赖: pip install flask flask-socketio pillow loguru
日志级别: 在代码中设置 LOG_LEVEL见下方"INFO" 不显示 DEBUG"DEBUG" 显示调试信息。
"""
# base64将二进制 PNG 编码为字符串,便于通过 JSON/WebSocket 传输
@@ -21,12 +23,21 @@ import struct
import threading
# sys读取命令行参数装置 IP
import sys
# os获取当前脚本目录,拼接 favicon 路径
# os获取当前脚本目录、路径与文件检查
import os
# ioBytesIO 用于在内存中保存 PNG
import io
def _get_base_path() -> str:
"""打包成 exe 时资源在 sys._MEIPASS否则为脚本所在目录。"""
if getattr(sys, "frozen", False):
return sys._MEIPASS # type: ignore[attr-defined]
return os.path.dirname(os.path.abspath(__file__))
# typing类型注解
from typing import Optional, Tuple, Set
# loguru结构化日志记录错误与调试信息
from loguru import logger
# FlaskWeb 框架,提供 HTTP 路由
from flask import Flask, request, send_file
@@ -47,6 +58,13 @@ PORT = 7003
# CMD_LCDMEM 3读取显存屏幕画面
CMD_KEEPLIVE, CMD_INIT, CMD_KEY, CMD_LCDMEM = 0, 1, 2, 3
# =============================================================================
# 日志级别(在代码中直接修改)
# =============================================================================
# "INFO":仅输出 INFO/WARNING/ERROR不显示 DEBUG
# "DEBUG":输出包括 DEBUG 在内的全部日志
LOG_LEVEL = "INFO"
# =============================================================================
# 全局状态
# =============================================================================
@@ -90,19 +108,29 @@ def parse_frame(raw: bytes) -> Optional[Tuple[int, bytes]]:
"""
解析设备回复帧,返回 (cmd, data) 或 None。
帧格式: [TAG(1)][cmd(1)][len_hi(1)][len_lo(1)][data(length)][crc(1)]
最短合法帧长度为 5 字节(长度为 0 时: 1+1+2+0+1
"""
if len(raw) < 6 or raw[0] != TAG_DEVICE: # 至少 6 字节且帧头为 TAG_DEVICE
print("[parse_frame] 错误: 帧太短或帧头不是 TAG_DEVICE(0xBB), len=%d" % len(raw))
if len(raw) < 5 or raw[0] != TAG_DEVICE: # 至少 5 字节且帧头为 TAG_DEVICE
logger.error(
"[parse_frame] 帧太短或帧头不是 TAG_DEVICE(0xBB), len={len_}",
len_=len(raw),
)
return None
length = (raw[2] << 8) | raw[3] # 大端序解析数据区长度
if len(raw) < 4 + length + 1: # 检查是否收齐整帧头4字节+数据+CRC1字节
print("[parse_frame] 错误: 数据不完整, 需要 %d 字节, 实际 %d 字节" % (4 + length + 1, len(raw)))
logger.error(
"[parse_frame] 数据不完整, 需要 {need} 字节, 实际 {actual} 字节",
need=4 + length + 1,
actual=len(raw),
)
return None
data = raw[4:4 + length] # 提取数据区
if calc_crc(data) != raw[4 + length]: # CRC 校验失败
print("[parse_frame] 错误: CRC 校验失败")
logger.error("[parse_frame] CRC 校验失败")
return None
return (raw[1], data) # 返回 (命令码, 数据)
cmd = raw[1]
logger.debug("[parse_frame] 成功解析帧 cmd={cmd:#x}, length={length}", cmd=cmd, length=length)
return (cmd, data) # 返回 (命令码, 数据)
# =============================================================================
@@ -118,49 +146,77 @@ def connect(host: str, port: int = PORT) -> bool:
try:
if _sock:
_sock.close() # 关闭旧连接
logger.info("[connect] 已关闭旧连接")
_sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 创建 TCP socket
_sock.settimeout(3.0) # 连接阶段超时 3 秒
_sock.connect((host, port)) # 连接目标主机和端口
_sock.settimeout(2.0) # 连接成功后收发超时 2 秒
logger.info("[connect] 连接 DTU 成功: {host}:{port}", host=host, port=port)
return True
except Exception as e:
print("[connect] 错误: 连接失败 - %s" % e)
logger.exception("[connect] 连接失败: {host}:{port} - {err}", host=host, port=port, err=e)
return False
def _send(cmd: int, data: bytes = b"") -> bool:
"""发送一帧到设备"""
if not _sock:
print("[_send] 错误: 未连接设备")
logger.error("[_send] 未连接设备,无法发送 cmd={cmd:#x}", cmd=cmd)
return False
try:
_sock.sendall(build_frame(cmd, data)) # 构造帧并一次性发送
frame = build_frame(cmd, data)
_sock.sendall(frame) # 构造帧并一次性发送
logger.debug("[_send] 已发送 cmd={cmd:#x}, data_len={length}", cmd=cmd, length=len(data))
return True
except Exception as e:
print("[_send] 错误: 发送失败 - %s" % e)
logger.exception("[_send] 发送失败 cmd={cmd:#x} - {err}", cmd=cmd, err=e)
return False
def _recv() -> Optional[Tuple[int, bytes]]:
"""
从设备接收一帧,一次性 recv 最多 256KB。
至少需 5 字节4 字节头+1 字节数据或 CRC根据头中 length 检查是否收齐整帧
从设备接收一帧。若首次接收长度不足,会再尝试接收最多 2 次(共 3 次),
拼齐整帧后再解析。单次 recv 最多 256KB
"""
if not _sock:
print("[_recv] 错误: 未连接设备")
logger.error("[_recv] 未连接设备,无法接收数据")
return None
try:
data = _sock.recv(256 * 1024) # 单次接收最多 256KB
if len(data) < 5: # 至少需要 5 字节4 头 + 1 数据/CRC
print("[_recv] 错误: 接收数据太短, len=%d" % len(data))
buffer = b""
max_attempts = 3 # 首次 + 最多再收 2 次
for attempt in range(max_attempts):
chunk = _sock.recv(256 * 1024)
if not chunk:
logger.debug("[_recv] 第 {n} 次 recv 收到空数据,连接可能已关闭", n=attempt + 1)
break
buffer += chunk
if len(buffer) < 5: # 至少需要 5 字节才能解析头
logger.debug("[_recv] 第 {n} 次 recv 后共 {len_} 字节,继续接收", n=attempt + 1, len_=len(buffer))
continue
data_len = (buffer[2] << 8) | buffer[3] # 数据区长度
need = 4 + data_len + 1 # 整帧长度
if len(buffer) >= need:
logger.debug("[_recv] 第 {n} 次 recv 后收齐整帧 len={len_}", n=attempt + 1, len_=need)
return parse_frame(buffer[:need])
logger.debug(
"[_recv] 第 {n} 次 recv 后共 {have} 字节,需要 {need} 字节,继续接收",
n=attempt + 1,
have=len(buffer),
need=need,
)
if len(buffer) < 5:
logger.error("[_recv] 接收数据太短, len={len_}", len_=len(buffer))
return None
length = (data[2] << 8) | data[3] # 解析数据区长度
if len(data) < 4 + length + 1: # 数据不完整
print("[_recv] 错误: 数据不完整, 需要 %d 字节, 实际 %d 字节" % (4 + length + 1, len(data)))
need = 4 + ((buffer[2] << 8) | buffer[3]) + 1
logger.error(
"[_recv] 尝试 {max_attempts} 次后数据不完整, 需要 {need} 字节, 实际 {actual} 字节",
max_attempts=max_attempts,
need=need,
actual=len(buffer),
)
return None
return parse_frame(data[:4 + length + 1]) # 解析并返回 (cmd, data)
except Exception as e:
print("[_recv] 错误: 接收异常 - %s" % e)
logger.exception("[_recv] 接收异常 - {err}", err=e)
return None
@@ -175,19 +231,26 @@ def fetch_screen() -> Optional[bytes]:
发送 CMD_LCDMEM + 起始地址 0设备回复 payload 前 4 字节为地址,后续为位图,返回 payload[4:]。
"""
if not _sock:
print("[fetch_screen] 错误: 未连接设备")
logger.error("[fetch_screen] 未连接设备,无法读取屏幕")
return None
if not _send(CMD_LCDMEM, struct.pack(">I", 0)): # 发送读取显存命令,起始地址 0大端 4 字节)
print("[fetch_screen] 错误: 发送 CMD_LCDMEM 失败")
logger.error("[fetch_screen] 发送 CMD_LCDMEM 失败")
return None
result = _recv() # 接收设备回复
if result and result[0] == CMD_LCDMEM: # 确认为 LCDMEM 回复
payload = result[1] # 数据区
if len(payload) >= 4: # 前 4 字节为地址,后面是位图
return payload[4:]
return payload or None
print("[fetch_screen] 错误: 未收到有效 LCDMEM 回复")
if not result:
logger.error("[fetch_screen] 未收到任何回复result=None")
return None
cmd, payload = result
if cmd != CMD_LCDMEM:
# 可能是按键 ACK、保活等其他短帧按键操作时较常见这里只做调试日志不视为错误
logger.debug("[fetch_screen] 收到非 LCDMEM 帧 cmd={cmd:#x},忽略", cmd=cmd)
return None
# 确认为 LCDMEM 回复
if len(payload) >= 4: # 前 4 字节为地址,后面是位图
logger.debug("[fetch_screen] 收到 LCDMEMpayload_len={len_}", len_=len(payload))
return payload[4:]
logger.debug("[fetch_screen] 收到 LCDMEMpayload_len={len_} (<4)", len_=len(payload))
return payload or None
def mono_to_png(data: bytes, width: int, height: int) -> Optional[bytes]:
@@ -197,18 +260,29 @@ def mono_to_png(data: bytes, width: int, height: int) -> Optional[bytes]:
"""
try:
from PIL import Image
logger.debug(
"[mono_to_png] 开始转换为 PNGwidth={width}, height={height}, data_len={len_}",
width=width,
height=height,
len_=len(data),
)
img = Image.new("1", (width, height)) # 创建 1bpp 黑白图像
pix = img.load() # 获取像素访问对象
for y in range(height):
for x in range(width):
bi = (y * width + x) // 8 # 字节索引:每 8 像素一字节
bit = 7 - (x % 8) # 位索引:高位在前
pix[x, y] = 255 if (bi < len(data) and (data[bi] >> bit) & 1) else 0 # 1→白 0→黑
pix[x, y] = 0 if (bi < len(data) and (data[bi] >> bit) & 1) else 255 # 1→白 0→黑
buf = io.BytesIO() # 内存缓冲区
img.save(buf, format="PNG") # 保存为 PNG 格式
return buf.getvalue() # 返回 PNG 字节流
png_bytes = buf.getvalue()
logger.debug("[mono_to_png] 转换 PNG 成功, png_len={len_}", len_=len(png_bytes))
return png_bytes # 返回 PNG 字节流
except ImportError:
print("[mono_to_png] 错误: 缺少 PIL/Pillow, 请执行 pip install pillow")
logger.error("[mono_to_png] 缺少 PIL/Pillow, 请执行 pip install pillow")
return None
except Exception as e:
logger.exception("[mono_to_png] 转换 PNG 失败 - {err}", err=e)
return None
@@ -217,10 +291,11 @@ def disconnect_device():
global _sock
try:
if _sock:
logger.info("[disconnect_device] 正在关闭与 DTU 的连接")
_sock.close() # 关闭 socket
_sock = None # 清空引用
except Exception as e:
print("[disconnect_device] 错误: 关闭连接时异常 - %s" % e)
logger.exception("[disconnect_device] 关闭连接时异常 - {err}", err=e)
# =============================================================================
@@ -233,21 +308,33 @@ def _screen_refresh_loop():
_refresh_stop.wait(0.1) 既作间隔,也便于收到 set 时快速退出。
"""
global _screen_clients, _refresh_stop
logger.info("[_screen_refresh_loop] 刷新线程启动")
try:
while not _refresh_stop.is_set(): # 未被要求停止时持续循环
if _screen_clients and _sock: # 有客户端且已连接设备
data = fetch_screen() # 拉取屏幕位图
if data:
info = {"width": 160, "height": 160} # 设置长宽 160x160
w, h = info.get("width", 160), info.get("height", 160)
# 当前协议未返回宽高,这里固定为 160x160可根据实际情况调整
w, h = 160, 160
png = mono_to_png(data, w, h) # 转为 PNG
if png:
b64 = base64.b64encode(png).decode("ascii") # base64 编码便于 JSON 传输
for sid in list(_screen_clients): # 复制列表避免迭代时修改
try:
socketio.emit("screen", {"png": b64, "w": w, "h": h}, room=sid) # 推送给该客户端
except Exception:
pass
socketio.emit(
"screen",
{"png": b64, "w": w, "h": h},
room=sid,
) # 推送给该客户端
except Exception as e:
logger.exception(
"[_screen_refresh_loop] 推送 screen 给 {sid} 失败 - {err}",
sid=sid,
err=e,
)
_refresh_stop.wait(timeout=0.1) # 等待 100ms若被 set 则立即返回
finally:
logger.info("[_screen_refresh_loop] 刷新线程退出")
# =============================================================================
@@ -258,7 +345,7 @@ app = Flask(__name__) # 创建 Flask 应用
app.config["SECRET_KEY"] = "remo_disp" # 会话密钥
socketio = SocketIO(app, cors_allowed_origins="*") # 创建 SocketIO允许跨域
FAVICON_PATH = os.path.join(os.path.dirname(__file__), "static", "favicon.ico") # favicon 文件路径
FAVICON_PATH = os.path.join(_get_base_path(), "static", "favicon.ico") # favicon 文件路径
@app.route("/favicon.ico")
@@ -274,7 +361,7 @@ def favicon():
def index():
"""主页,返回前端 HTML"""
return send_file(
os.path.join(os.path.dirname(__file__), "remo_disp_ui.html"),
os.path.join(_get_base_path(), "remo_disp_ui.html"),
mimetype="text/html; charset=utf-8",
)
@@ -282,7 +369,7 @@ def index():
@socketio.on("connect")
def on_connect():
"""WebSocket 客户端连接时触发(可留空)"""
pass
logger.info("[on_connect] WebSocket 客户端已连接 sid={sid}", sid=request.sid)
@socketio.on("disconnect")
@@ -290,6 +377,7 @@ def on_disconnect():
"""WebSocket 客户端断开(关标签页等)时,从 _screen_clients 移除,若无客户端则断开设备"""
global _screen_clients, _refresh_thread, _refresh_stop
sid = request.sid # 获取断开客户端的 session id
logger.info("[on_disconnect] WebSocket 客户端断开 sid={sid}", sid=sid)
if sid in _screen_clients:
_screen_clients.discard(sid) # 从订阅列表移除
if not _screen_clients: # 若无其他客户端
@@ -303,6 +391,7 @@ def on_connect_device(data):
global _screen_clients, _refresh_thread, _refresh_stop
host = (data.get("host") or "").strip() # 从 data 取 host去空格
port = int(data.get("port") or PORT) # 从 data 取 port缺省 7003
logger.info("[on_connect_device] 请求连接 DTU: {host}:{port}", host=host, port=port)
ok = connect(host, port) # 建立 TCP 连接
if ok:
_screen_clients.add(request.sid) # 将当前客户端加入屏幕订阅
@@ -310,8 +399,11 @@ def on_connect_device(data):
if _refresh_thread is None or not _refresh_thread.is_alive(): # 刷新线程未运行
_refresh_thread = threading.Thread(target=_screen_refresh_loop, daemon=True) # 创建后台线程
_refresh_thread.start() # 启动线程
logger.info("[on_connect_device] 已启动屏幕刷新线程")
emit("connect_result", {"success": True}) # 回复连接成功
logger.info("[on_connect_device] 连接 DTU 成功,已加入订阅 sid={sid}", sid=request.sid)
else:
logger.error("[on_connect_device] 连接 DTU 失败: {host}:{port}", host=host, port=port)
emit("connect_result", {"success": False, "error": "connect failed"}) # 回复连接失败
@@ -320,17 +412,20 @@ def on_disconnect_device():
"""前端请求断开设备:从 _screen_clients 移除,若无客户端则断开设备,回复 disconnect_result"""
global _screen_clients, _refresh_stop
sid = request.sid
logger.info("[on_disconnect_device] 前端请求断开设备 sid={sid}", sid=sid)
_screen_clients.discard(sid) # 从订阅列表移除
if not _screen_clients: # 若无其他客户端
_refresh_stop.set() # 通知刷新线程停止
disconnect_device() # 断开设备连接
emit("disconnect_result", {"ok": True}) # 回复断开成功
logger.info("[on_disconnect_device] 设备已断开(若为最后一个客户端)")
@socketio.on("key")
def on_key(data):
"""前端发送按键:从 data 取 code转发给设备"""
code = int(data.get("code", 0)) # 按键码,缺省 0
logger.debug("[on_key] 收到按键 code={code:#x}", code=code)
send_key(code) # 发送给 DTU 设备
@@ -338,14 +433,40 @@ def on_key(data):
# 启动
# =============================================================================
def _configure_log_level():
"""根据全局 LOG_LEVEL 配置日志级别(见文件顶部 LOG_LEVEL 常量)。"""
level = LOG_LEVEL.upper() if isinstance(LOG_LEVEL, str) else "INFO"
if level not in ("TRACE", "DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"):
level = "INFO"
logger.remove() # 移除默认的 stderr 输出
logger.add(sys.stderr, level=level, format="<green>{time:HH:mm:ss}</green> | <level>{level: <8}</level> | <level>{message}</level>")
logger.add(
"remo_disp.log",
rotation="1 week",
encoding="utf-8",
enqueue=True,
backtrace=True,
diagnose=False,
level=level,
)
return level
@logger.catch
def main():
"""主入口:启动 Web 服务"""
port = 8181 # HTTP 服务端口
print(f"远程显示服务: http://localhost:{port}")
print("使用 WebSocket 传输,在浏览器中打开上述地址")
log_level = _configure_log_level()
logger.info("日志级别: {level}", level=log_level)
logger.info("远程显示服务: http://localhost:{port}", port=port)
logger.info("使用 WebSocket 传输,在浏览器中打开上述地址")
if len(sys.argv) >= 2:
connect(sys.argv[1]) # 若命令行有 IP预连接
print(f"已预连接: {sys.argv[1]}")
host = sys.argv[1]
logger.info("[main] 尝试预连接 DTU: {host}", host=host)
if connect(host): # 若命令行有 IP预连接
logger.info("[main] 已预连接: {host}", host=host)
else:
logger.error("[main] 预连接失败: {host}", host=host)
socketio.run(app, host="0.0.0.0", port=port, debug=True, allow_unsafe_werkzeug=True) # 监听所有网卡

63
remo_disp_server.spec Normal file
View File

@@ -0,0 +1,63 @@
# -*- mode: python ; coding: utf-8 -*-
# PyInstaller 打包配置python -m PyInstaller remo_disp_server.spec
# 打包后运行 dist\remo_disp_server\remo_disp_server.exe [装置IP]
block_cipher = None
# 需要随 exe 一起打包的数据文件HTML、静态资源
added_files = [
('remo_disp_ui.html', '.'),
]
# 若存在 static 目录则打包favicon 等)
import os as _os
if _os.path.isdir('static'):
added_files.append(('static', 'static'))
a = Analysis(
['remo_disp_server.py'],
pathex=[],
binaries=[],
datas=added_files,
hiddenimports=[
'engineio.async_drivers.threading',
'flask_socketio',
'python_engineio',
'python_socketio',
'werkzeug',
'PIL',
'PIL._tkinter_finder',
'loguru',
],
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False,
)
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
exe = EXE(
pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='remo_disp_server',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)

View File

@@ -143,8 +143,12 @@
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
/* 垂直方向居中,与左侧显示区对齐 */
gap: 16px;
padding: 8px;
align-self: stretch;
/* 与 .main 同高,便于内容居中 */
}
/* ========== D-pad 方向键 ========== */
.dpad {

View File

@@ -1,6 +1,6 @@
# 远程显示 Web 服务依赖
# remo_disp_server.py 需要 Flask + flask-socketio + Pillow
# Dependencies for DTU-RemoteLCD web service
Flask>=2.0.0
Pillow>=9.0.0
flask-socketio>=5.0.0
python-socketio>=5.0.0
loguru>=0.7.0