xy/SensorDetector.py

131 lines
5.2 KiB
Python
Raw Normal View History

2025-12-03 16:13:38 +08:00
import serial
import serial.tools.list_ports
import time
import datetime
import struct
import threading
import json
class SensorDetector:
def __init__(self, log_path, sensor_configs):
"""
初始化方法支持多传感器配置
:param log_path: 日志路径
:param sensor_configs: 传感器配置列表格式如[{"port": "COM6", "id": "X11223366S_1"}, {"port": "COM7", "id": "X11223366S_2"}]
"""
self.log_path = log_path
self.sensor_configs = sensor_configs # 新增:多传感器配置
self.serials = {} # 新增:存储多个串口连接
self.data3 = []
self.latest_data = {} # 新增:存储每个传感器的最新数据
self.running = True # 新增:轮询控制标志
# 确保日志目录存在
import os
if not os.path.exists(self.log_path):
os.makedirs(self.log_path)
def _open_serial_port(self, port, baudrate=38400, timeout=1):
"""修改:支持指定端口打开串口"""
try:
ser = serial.Serial(port=port, baudrate=baudrate, timeout=timeout)
if ser.isOpen():
print(f"Successfully open serial port {port}")
return ser
else:
print(f"Failure to open serial port {port}")
return None
except Exception as e:
now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open(f"{self.log_path}/Exception_log.txt", "a") as f:
f.write(f"{now} open serial port {port} error:{e}\n")
return None
def _send_command(self, ser, data):
"""修改:接受串口对象作为参数"""
try:
send_data = struct.pack("%dB" % (len(data)), *data)
ser.write(send_data)
except Exception as e:
now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open(f"{self.log_path}/Exception_log.txt", "a") as f:
f.write(f"{now} send command error:{e}\n")
def _sensor_worker(self, sensor_id, port, callback):
"""新增:单个传感器的工作线程"""
ser = self._open_serial_port(port)
if not ser:
return
self.serials[sensor_id] = ser
# 发送启动指令
self._send_command(ser, [0x8A])
current_second_data = []
last_second = time.time()
while self.running:
try:
count0 = ser.inWaiting()
current_time = time.time()
if count0 > 0:
read_buffer = ser.read(88)
if len(read_buffer) == 88 and read_buffer[0] == 0xff: # 增加长度校验,修复索引错误
sensor_data = {
'sensor_id': sensor_id, # 新增标记传感器ID
'heart_rate': read_buffer[65],
'blood_oxygen': read_buffer[66],
'micro_circulation': read_buffer[67],
'fatigue_index': read_buffer[68],
'systolic_pressure': read_buffer[71],
'diastolic_pressure': read_buffer[72],
'cardiac_output': read_buffer[73]
}
current_second_data.append(sensor_data)
# 每秒回调一次数据
if current_time - last_second >= 1:
callback(current_second_data)
current_second_data = []
last_second = current_time
time.sleep(0.01) # 降低CPU占用
except Exception as e:
now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open(f"{self.log_path}/Exception_log.txt", "a") as f:
f.write(f"{now} sensor {sensor_id} data reading error:{e}\n")
time.sleep(1)
def detect_sensors(self, callback):
"""修改:启动多传感器轮询线程"""
try:
ports = list(serial.tools.list_ports.comports())
for p in ports:
print(p)
# 为每个传感器启动工作线程
threads = []
for config in self.sensor_configs:
t = threading.Thread(
target=self._sensor_worker,
args=(config["id"], config["port"], callback),
daemon=True
)
threads.append(t)
t.start()
# 保持主线程运行
while self.running:
time.sleep(1)
except Exception as e:
now = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
with open(f"{self.log_path}/Exception_log.txt", "a") as f:
f.write(f"{now} overall sensor detection error:{e}\n")
def stop(self):
"""新增:停止所有传感器线程"""
self.running = False
for ser in self.serials.values():
if ser and ser.isOpen():
ser.close()