TG-PlatformPlus/interfaceSession/sessionSerial.py

159 lines
5.4 KiB
Python

#!/opt/homebrew/bin/python3
# -*- coding:utf-8 -*-
import sys
import time
from PyQt6 import *
from PyQt6.QtCore import *
import serial
from interfaceSession.sessionAbstract import SessionAbstract
from logs import log
class SerialWorker(QObject):
newDataArrive = pyqtSignal(bytearray)
connectSuccess = pyqtSignal()
connectClosed = pyqtSignal()
connectFailed = pyqtSignal()
closeSerial = pyqtSignal()
def __init__(self):
super().__init__()
self.running = False
self.serial = None
self.autoReconnectChecked = False
self.attrs = {}
def start(self):
try:
parity_map = {
'': 'N', # 默认值为 'N'
'None': 'N', # 无校验
'Odd': 'O', # 奇校验
'Even': 'E', # 偶校验
'Space': 'S' # 空格校验
}
bytesize_value = self.attrs.get('bytesize', '8') # 默认值为 '8'
if bytesize_value == '':
bytesize_value = '8' # 设置为默认值
bytesize = int(bytesize_value)
stopbits_value = self.attrs.get('stopbits', '1') # 默认值为 '1'
if stopbits_value == '':
stopbits_value = '1' # 设置为默认值
stopbits = float(stopbits_value)
self.serial = serial.Serial(self.attrs['port'],
self.attrs['baudrate'],
parity=parity_map.get(self.attrs['parity']),
bytesize=bytesize,
stopbits=stopbits,
timeout=1)
if self.serial.is_open:
self.connectSuccess.emit()
self.running = True
while self.running and self.serial.is_open:
if self.serial.in_waiting:
data = self.serial.read(self.serial.in_waiting)
self.newDataArrive.emit(bytearray(data))
#延迟1ms
time.sleep(0.001)
if self.serial and self.serial.is_open:
self.running = False
self.serial.close()
self.closeSerial.emit()
except serial.SerialException as e:
# log.info(f"Serial exception: {e}")
if self.autoReconnectChecked:
self.connectClosed.emit()
else:
self.connectFailed.emit()
finally:
if self.serial and self.serial.is_open:
self.serial.close()
self.running = False
self.closeSerial.emit()
def stop(self):
self.running = False
class SessionSerial(SessionAbstract):
newDataArrive = pyqtSignal(bytearray)
def __init__(self, id, name, attrs = {}):
super().__init__(id, name, "serial", attrs)
self.id = id
self.worker = SerialWorker()
self.worker.attrs = attrs
self.thread = QThread()
self.worker.moveToThread(self.thread)
self.thread.started.connect(self.worker.start)
self.worker.newDataArrive.connect(self.onNewDataArrive)
self.worker.connectSuccess.connect(self.onConnectSuccess)
self.worker.connectClosed.connect(self.onConnectClosed)
self.worker.connectFailed.connect(self.onConnectFailed)
self.worker.closeSerial.connect(self.close)
self.reconnect_timer = QTimer(self) # 创建一个定时器
self.reconnect_timer.timeout.connect(self.timerout_reconnect) # 连接定时器信号到重连函数
self.reconnect_interval = 10 # 设置重连间隔时间(毫秒)
def onNewDataArrive(self, data):
self.newDataArrive.emit(data)
def onConnectSuccess(self):
self.connectSuccess.emit(self.id)
def onConnectClosed(self):
self.connectClosed.emit(self.id)
def onConnectFailed(self):
self.connectFailed.emit(self.id)
self.close()
def setAttrs(self, attrs):
self._PROTECTED__attrs.update(attrs)
self.worker.attrs.update(attrs)
def timerout_reconnect(self):
if self.worker.autoReconnectChecked:
if self.worker.running:
self.connectSuccess.emit(self.id)
else:
self.open()
def stopAutoReconnect(self):
self.worker.autoReconnectChecked = False
self.reconnect_timer.stop()
return True
# 自动重连
def startAutoReconnect(self):
self.worker.autoReconnectChecked = True
self.reconnect_timer.start(self.reconnect_interval)
return True
def open(self):
if not self.thread.isRunning():
self.thread.start()
return self.worker.running
def close(self):
if self.thread.isRunning():
self.worker.stop()
self.thread.quit()
self.thread.wait()
def isOpen(self):
return self.thread.isRunning()
def isConnect(self):
return self.thread.isRunning()
@pyqtSlot(bytes)
def send(self, data):
if self.thread.isRunning():
if self.worker.serial and self.worker.serial.is_open:
self.worker.serial.write(data)
@pyqtSlot(dict)
def ioctrl(self, data: dict):
if isinstance(data, dict):
self.worker.attrs.update(data)
self.worker.serial.baudrate = data.get('baudrate', 9600)