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()