You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
158 lines
5.3 KiB
158 lines
5.3 KiB
|
3 months ago
|
# core/serial_protocol.py
|
||
|
|
import serial
|
||
|
|
import serial.tools.list_ports
|
||
|
|
from utils.logger import logger
|
||
|
|
|
||
|
|
class SerialProtocol:
|
||
|
|
def __init__(self):
|
||
|
|
self.serial_port = serial.Serial()
|
||
|
|
self.serial_port.BaudRate = 115200
|
||
|
|
|
||
|
|
def select_all(self):
|
||
|
|
"""
|
||
|
|
所有屏幕开机指令
|
||
|
|
"""
|
||
|
|
# 根据你的协议文档,这里填入真实的十六进制指令
|
||
|
|
# 示例: [Head, Cmd, Data...] -> bytes
|
||
|
|
cmd_bytes = [
|
||
|
|
0x80, # HEAD (假设)
|
||
|
|
0x74, # CMD (拼接命令)
|
||
|
|
0x1B, # 起始位置
|
||
|
|
0xFF, 0xFF, 0xFF, 0xFF # 填充位 (根据协议长度补齐)
|
||
|
|
]
|
||
|
|
return bytes(cmd_bytes)
|
||
|
|
|
||
|
|
def power_on_all(self):
|
||
|
|
"""所有屏幕开机指令"""
|
||
|
|
# 根据你的协议文档,这里填入真实的十六进制指令
|
||
|
|
# 示例: [Head, Cmd, Data...] -> bytes
|
||
|
|
cmd_bytes = [
|
||
|
|
0x80, # HEAD (假设)
|
||
|
|
0x74, # CMD (拼接命令)
|
||
|
|
0x40, # 起始位置
|
||
|
|
0xFF, 0xFF, 0xFF, 0xFF # 填充位 (根据协议长度补齐)
|
||
|
|
]
|
||
|
|
return bytes(cmd_bytes)
|
||
|
|
|
||
|
|
def power_off_panel(self, panel_id):
|
||
|
|
"""指定单屏关机"""
|
||
|
|
# 假设协议是: 80 74 19 [PanelNo] FF FF FF FF
|
||
|
|
# panel_id 是 1-12,转成16进制
|
||
|
|
hex_panel = f"{panel_id:02X}"
|
||
|
|
cmd_str = f"80 74 19 {hex_panel} FF FF FF FF"
|
||
|
|
return bytes.fromhex(cmd_str)
|
||
|
|
|
||
|
|
def switch_layout(self, start_pos, cols, rows, source_type=0x33):
|
||
|
|
"""切换拼接布局 (例如 2x2)"""
|
||
|
|
# 示例指令,具体根据你的附件协议调整
|
||
|
|
return bytes.fromhex(f"80 D6 10 {start_pos:02X} {rows:02X} {cols:02X} 01 FF")
|
||
|
|
|
||
|
|
def create_mosaic_window(self, start_id, rows, cols, source_id):
|
||
|
|
"""
|
||
|
|
生成拼接指令
|
||
|
|
硬件协议通常是:设置逻辑屏大小 -> 绑定信号源 -> 显示
|
||
|
|
"""
|
||
|
|
# 示例伪代码
|
||
|
|
cmd1 = bytes.fromhex(f"80 D6 10 {start_id} {rows} {cols} {source_id} FF")
|
||
|
|
return [cmd1]
|
||
|
|
|
||
|
|
def calculate_mosaic_params(self, selected_widgets):
|
||
|
|
"""
|
||
|
|
根据选中的屏幕控件,自动计算拼接参数
|
||
|
|
策略:取最左上角和最右下角,生成一个完整的矩形
|
||
|
|
"""
|
||
|
|
if not selected_widgets:
|
||
|
|
return None
|
||
|
|
|
||
|
|
# --- 第一步:找出边界 ---
|
||
|
|
# 假设屏幕ID是 1-12,排列为 3行 x 4列
|
||
|
|
# 我们需要根据ID计算坐标:行 = (ID-1) // 4, 列 = (ID-1) % 4
|
||
|
|
|
||
|
|
print("根据选中的屏幕控件,自动计算拼接参数")
|
||
|
|
|
||
|
|
positions = []
|
||
|
|
ids = [w.screen_id for w in selected_widgets] # 获取选中控件的ID列表
|
||
|
|
|
||
|
|
for screen_id in ids:
|
||
|
|
row = (screen_id - 1) // 4
|
||
|
|
col = (screen_id - 1) % 4
|
||
|
|
positions.append((row, col))
|
||
|
|
|
||
|
|
# --- 第二步:计算包围矩形 ---
|
||
|
|
if not positions:
|
||
|
|
# 处理无选中控件的情况,防止后续 min/max 报错
|
||
|
|
min_row = max_row = min_col = max_col = 0
|
||
|
|
else:
|
||
|
|
# 正确提取行号和列号
|
||
|
|
rows = [pos[0] for pos in positions]
|
||
|
|
cols = [pos[1] for pos in positions]
|
||
|
|
|
||
|
|
min_row, max_row = min(rows), max(rows)
|
||
|
|
min_col, max_col = min(cols), max(cols)
|
||
|
|
|
||
|
|
# --- 第三步:生成参数 ---
|
||
|
|
start_id = min_row * 4 + min_col + 1 # 转回物理ID
|
||
|
|
start_param = start_id - 1 # 协议参数:PanelNumber - 1
|
||
|
|
|
||
|
|
# Hcount (水平个数), Vcount (垂直个数)
|
||
|
|
Hcount = max_col - min_col + 1
|
||
|
|
Vcount = max_row - min_row + 1
|
||
|
|
|
||
|
|
|
||
|
|
BigPicID = 1
|
||
|
|
|
||
|
|
# --- 第四步:逻辑校验 ---
|
||
|
|
# 检查这个矩形区域内是否有未被选中的屏幕(缺角情况)
|
||
|
|
missing_screens = []
|
||
|
|
for r in range(min_row, max_row + 1):
|
||
|
|
for c in range(min_col, max_col + 1):
|
||
|
|
expected_id = r * 4 + c + 1
|
||
|
|
if expected_id not in ids:
|
||
|
|
missing_screens.append(expected_id)
|
||
|
|
|
||
|
|
return {
|
||
|
|
"start": start_param,
|
||
|
|
"Hcount": Hcount,
|
||
|
|
"Vcount": Vcount,
|
||
|
|
"BigPicID": BigPicID,
|
||
|
|
"missing_screens": missing_screens, # 用于提示用户
|
||
|
|
"min_row": min_row,
|
||
|
|
"min_col": min_col
|
||
|
|
}
|
||
|
|
|
||
|
|
|
||
|
|
def build_mosaic_packet(self, start, hcount, vcount, cmd_type=0x01):
|
||
|
|
"""
|
||
|
|
封装拼接指令包
|
||
|
|
:param start: 起始物理屏编号
|
||
|
|
:param hcount: 水平数量
|
||
|
|
:param vcount: 垂直数量
|
||
|
|
:param cmd_type: 命令字,0x01通常代表拼接
|
||
|
|
:return: bytes (指令字节流)
|
||
|
|
"""
|
||
|
|
|
||
|
|
print(hcount)
|
||
|
|
|
||
|
|
try:
|
||
|
|
# 限制数值范围,防止溢出
|
||
|
|
start = max(0, min(255, start))
|
||
|
|
hcount = max(1, min(16, hcount)) # 假设最大16屏
|
||
|
|
vcount = max(1, min(16, vcount))
|
||
|
|
|
||
|
|
# 组装数据包 [AA 55] [Cmd] [Start] [H] [V] [FF]
|
||
|
|
packet = [
|
||
|
|
0xAA, # 帧头1
|
||
|
|
0x55, # 帧头2
|
||
|
|
cmd_type, # 命令字
|
||
|
|
start, # 起始地址
|
||
|
|
hcount, # 横向数量
|
||
|
|
vcount, # 纵向数量
|
||
|
|
0xFF # 帧尾
|
||
|
|
]
|
||
|
|
|
||
|
|
# 转换为字节流
|
||
|
|
return bytes(packet)
|
||
|
|
|
||
|
|
except Exception as e:
|
||
|
|
print(f"协议封装错误: {e}")
|
||
|
|
return None
|