131 lines
5.2 KiB
Python
131 lines
5.2 KiB
Python
|
|
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()
|