xy/SensorDetector.py
2025-12-03 16:13:38 +08:00

131 lines
5.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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