# 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