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.
100 lines
4.4 KiB
100 lines
4.4 KiB
# core/serial_manager.py
|
|
import serial
|
|
import serial.tools.list_ports
|
|
from utils.logger import logger
|
|
|
|
class SerialManager:
|
|
def __init__(self):
|
|
self.serial_port = serial.Serial()
|
|
self.serial_port.BaudRate = 115200 # 协议规定
|
|
self.serial_port.timeout = 1
|
|
|
|
def get_available_ports(self):
|
|
"""
|
|
扫描并返回当前系统中所有可用的串口端口名
|
|
"""
|
|
ports = serial.tools.list_ports.comports()
|
|
return [port.device for port in ports]
|
|
|
|
def _send_command(self, command_bytes):
|
|
"""
|
|
核心方法:发送指令到串口
|
|
:param command_bytes: 完整的指令字节列表,例如 [0x80, 0x74, 0x1B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]
|
|
"""
|
|
if self.serial_port.is_open:
|
|
try:
|
|
# 协议规定:连接命令盒时,需要发送8位数据,首字节是0x80
|
|
# 我们这里统一按连接命令盒的方式处理
|
|
self.serial_port.write(bytes(command_bytes))
|
|
print(f"✅ 指令已发送: {['0x{:02X}'.format(b) for b in command_bytes]}")
|
|
return True
|
|
except Exception as e:
|
|
print(f"❌ 串口发送失败: {e}")
|
|
return False
|
|
return False
|
|
|
|
# --- 以下为具体功能的指令封装 ---
|
|
# 1. 开关机相关
|
|
def power_on_all(self):
|
|
"""所有屏开机"""
|
|
# 协议:全选 + 开机
|
|
return self._send_command([0x80, 0x74, 0x1B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]) and \
|
|
self._send_command([0x80, 0x74, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
|
|
|
|
def power_off_all(self):
|
|
"""所有屏关机"""
|
|
return self._send_command([0x80, 0x74, 0x1B, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]) and \
|
|
self._send_command([0x80, 0x74, 0x40, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
|
|
|
|
def power_on_single(self, panel_number):
|
|
"""单屏开机"""
|
|
return self._send_command([0x80, 0x74, 0x19, panel_number, 0xFF, 0xFF, 0xFF, 0xFF]) and \
|
|
self._send_command([0x80, 0x74, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF])
|
|
|
|
# 2. 切换信号源相关
|
|
def switch_source_all(self, source_type, source_id):
|
|
"""
|
|
切换所有屏信号源
|
|
:param source_type: 0x31(VGA), 0x32(AV), 0x33(HDMI), 0x34(YPbPr), 0x35(DVI)
|
|
:param source_id: 信号源ID,例如 AV1=0x01, AV2=0x02
|
|
"""
|
|
# 协议:0x80 0x94 0x83 SourceType Sourceld 0xFF 0xFF 0xFF
|
|
command = [0x80, 0x94, 0x83, source_type, source_id, 0xFF, 0xFF, 0xFF]
|
|
return self._send_command(command)
|
|
|
|
def switch_source_single(self, panel_number, source_type):
|
|
"""
|
|
切换单屏信号源
|
|
:param panel_number: 屏编号
|
|
:param source_type: 信号源类型
|
|
"""
|
|
# 协议:单选 + 切换信号源
|
|
return self._send_command([0x80, 0x74, 0x19, panel_number, 0xFF, 0xFF, 0xFF, 0xFF]) and \
|
|
self._send_command([0x80, 0x94, 0x82, source_type, panel_number, 0xFF, 0xFF, 0xFF])
|
|
|
|
# 3. 拼接操作
|
|
def matrix_layout(self, start, v_count, h_count, big_pic_id, source_type, source_id):
|
|
"""
|
|
执行拼接操作
|
|
:param start: 拼接开始位置 (左上角第一块屏的 PanelNumber-1)
|
|
:param v_count: 垂直方向屏个数
|
|
:param h_count: 水平方向屏个数
|
|
:param big_pic_id: 拼接大画面序列号
|
|
:param source_type: 信号源类型
|
|
:param source_id: 信号源ID
|
|
"""
|
|
# 协议:取消全选 + 设置拼接数据 + 设置标志 + 切换信号源
|
|
return (self._send_command([0x80, 0x74, 0x46, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]) and
|
|
self._send_command([0x80, 0xD6, 0x10, start, v_count, h_count, big_pic_id, 0xFF]) and
|
|
self._send_command([0x80, 0x94, 0x5F, big_pic_id, 0xFF, 0xFF, 0xFF, 0xFF]) and
|
|
self._send_command([0x80, 0x94, 0x81, source_type, source_id, 0xFF, 0xFF, 0xFF]))
|
|
|
|
# 4. 单屏操作
|
|
def single_screen(self, start, v_count, h_count, big_pic_id):
|
|
"""
|
|
执行单屏操作 (还原拼接)
|
|
"""
|
|
# 协议:设置单屏数据 + 空命令 + 还原信号源
|
|
return (self._send_command([0x80, 0xD6, 0x11, start, v_count, h_count, big_pic_id, 0xFF]) and
|
|
self._send_command([0x80, 0x94, 0x3A, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF]) and
|
|
self._send_command([0x80, 0xD6, 0x12, start, v_count, h_count, big_pic_id, 0xFF]))
|