medical_SDK/src/data_receiver/protocol_adapter/device_praser.cpp

357 lines
11 KiB
C++
Raw Normal View History

2025-07-28 11:56:50 +08:00
#include "headfile.h"
#include <cstring> // 添加 memcpy 头文件
// 辅助函数:从字节数组读取小端整数
template <typename T>
T read_le(const uint8_t* data) {
T value = 0;
for (size_t i = 0; i < sizeof(T); ++i) {
value |= static_cast<T>(data[i]) << (i * 8);
}
return value;
}
// 脑电设备解析 (0x4230)
SensorData parse_eeg(const uint8_t* data) {
SensorData result;
result.data_type = DataType::EEG;
result.packet_sn = read_le<uint16_t>(data);
// 跳过 DataType(2) 和 data_len(2)
const uint8_t* payload = data + 6;
// 导联状态
std::memcpy(result.lead_status.status, payload, 2);
payload += 2;
// 解析EEG数据 (6通道 × 14采样点)
auto& eeg_data = result.channel_data.emplace<std::vector<std::vector<float>>>();
eeg_data.resize(6);
for (int ch = 0; ch < 6; ++ch) {
eeg_data[ch].reserve(14);
for (int i = 0; i < 14; ++i) {
int16_t adc_value = read_le<int16_t>(payload);
payload += 2;
eeg_data[ch].push_back(adc_value * 0.318f); // 转换为μV
}
}
// 解析EOG数据 (2通道 × 14采样点)
for (int ch = 0; ch < 2; ++ch) {
eeg_data.push_back({}); // 添加新通道
for (int i = 0; i < 14; ++i) {
int16_t adc_value = read_le<int16_t>(payload);
payload += 2;
eeg_data.back().push_back(adc_value * 0.318f); // 转换为μV
}
}
// 跳过预留区 (6字节)
payload += 6;
// 赋值原始二进制数据
result.raw_data.assign(data, data + 6 + 2 + 6 * 14 * 2 + 2 * 14 * 2 + 6);
return result;
}
// 胸腹设备解析 (0x4211)
SensorData parse_ecg_emg(const uint8_t* data) {
SensorData result;
result.data_type = DataType::ECG_2LEAD;
result.packet_sn = read_le<uint16_t>(data);
// 跳过 data_type(2) 和 data_len(2)
const uint8_t* payload = data + 6;
// 导联状态
std::memcpy(result.lead_status.status, payload, 2);
payload += 2;
// 解析数据 (多通道混合)
auto& channels = result.channel_data.emplace<std::vector<std::vector<float>>>();
// ECG1 (25采样点)
channels.push_back({});
for (int i = 0; i < 25; ++i) {
int16_t adc_value = read_le<int16_t>(payload);
payload += 2;
channels.back().push_back(adc_value * 0.318f); // μV
}
// ECG2 (25采样点)
channels.push_back({});
for (int i = 0; i < 25; ++i) {
int16_t adc_value = read_le<int16_t>(payload);
payload += 2;
channels.back().push_back(adc_value * 0.318f); // μV
}
// EMG1 (25采样点)
channels.push_back({});
for (int i = 0; i < 25; ++i) {
int16_t adc_value = read_le<int16_t>(payload);
payload += 2;
channels.back().push_back(adc_value * 0.318f); // μV
}
// EMG2 (25采样点)
channels.push_back({});
for (int i = 0; i < 25; ++i) {
int16_t adc_value = read_le<int16_t>(payload);
payload += 2;
channels.back().push_back(adc_value * 0.318f); // μV
}
// 呼吸温度 (5采样点)
channels.push_back({});
for (int i = 0; i < 5; ++i) {
int16_t temp_value = read_le<int16_t>(payload);
payload += 2;
channels.back().push_back(temp_value * 0.477f); // 存储所有采样点
}
// 呼吸阻抗1 (5采样点)
channels.push_back({});
for (int i = 0; i < 5; ++i) {
int16_t imp_value = read_le<int16_t>(payload);
payload += 2;
channels.back().push_back(static_cast<float>(imp_value)); // 原始值
}
// 呼吸阻抗2 (5采样点)
channels.push_back({});
for (int i = 0; i < 5; ++i) {
int16_t imp_value = read_le<int16_t>(payload);
payload += 2;
channels.back().push_back(static_cast<float>(imp_value)); // 原始值
}
// 赋值原始二进制数据
result.raw_data.assign(data, data + 238); // 完整238字节
return result;
}
// 血氧设备解析 (0x4302)
SensorData parse_ppg(const uint8_t* data) {
SensorData result;
result.data_type = DataType::PPG;
result.packet_sn = read_le<uint16_t>(data);
// 跳过 DataType(2) 和 data_len(2)
const uint8_t* payload = data + 6;
// 读取生命体征
result.additional.hr = *payload++;
result.additional.spo2 = *payload++;
// 修正温度值扩大100倍存储需要除以100
int16_t temp_raw = read_le<int16_t>(payload);
result.additional.temperature = static_cast<float>(temp_raw) / 100.0f;
payload += 2;
// 解析红光数据 (57采样点)
auto& channels = result.channel_data.emplace<std::vector<std::vector<float>>>();
channels.push_back({});
for (int i = 0; i < 57; ++i) {
int16_t adc_value = read_le<int16_t>(payload);
payload += 2;
channels.back().push_back(adc_value * 0.879f); // mV
}
// 解析红外光数据 (57采样点)
channels.push_back({});
for (int i = 0; i < 57; ++i) {
int16_t adc_value = read_le<int16_t>(payload);
payload += 2;
channels.back().push_back(adc_value * 0.879f); // mV
}
// 赋值原始二进制数据
result.raw_data.assign(data, data + 6 + 4 + 57 * 2 * 2);
return result;
}
// 12导联心电解析 (0x4402)
SensorData parse_12lead_ecg(const uint8_t* data) {
SensorData result;
result.data_type = DataType::ECG_12LEAD;
result.packet_sn = read_le<uint16_t>(data);
// 跳过 DataType(2) 和 data_len(2)
const uint8_t* payload = data + 6;
// 导联状态 (按文档说明处理STAT寄存器)
uint8_t stat_dh = payload[0]; // STAT.DH
uint8_t stat_dm = payload[1]; // STAT.DM
// 正确拼接方式: (STAT.DH << 4) | (STAT.DM >> 4)
result.lead_status.status[0] = (stat_dh << 4) | (stat_dm >> 4) ;
result.lead_status.status[1] = 0; // 第二个字节未使用
payload += 2;
// 解析8通道ECG数据
auto& channels = result.channel_data.emplace<std::vector<std::vector<float>>>();
channels.resize(8);
for (int ch = 0; ch < 8; ++ch) {
channels[ch].reserve(14);
for (int i = 0; i < 14; ++i) {
int16_t adc_value = read_le<int16_t>(payload);
payload += 2;
channels[ch].push_back(adc_value); // raw_data
}
}
// GPIO状态 (取低4位)
result.additional.gpio_state = *payload & 0x0F;
payload += 1;
// 跳过预留区 (5字节)
payload += 5;
// 赋值原始二进制数据
result.raw_data.assign(data, data + 6 + 2 + 8 * 14 * 2 + 1 + 5);
return result;
}
// 数字听诊解析 (0x1102)
SensorData parse_stethoscope(const uint8_t* data) {
SensorData result;
result.data_type = DataType::STETHOSCOPE;
result.packet_sn = read_le<uint16_t>(data);
// 跳过 DataType(2) 和 data_len(2)
const uint8_t* payload = data + 6;
// 解析双通道音频数据
auto& channels = result.channel_data.emplace<std::vector<std::vector<float>>>();
channels.resize(2);
// 通道1数据 (116采样点)
for (int i = 0; i < 116; ++i) {
int8_t sample = static_cast<int8_t>(*payload++);
channels[0].push_back(sample * 0.146f); // mV
}
// 通道2数据 (116采样点)
for (int i = 0; i < 116; ++i) {
int8_t sample = static_cast<int8_t>(*payload++);
channels[1].push_back(sample * 0.146f); // mV
}
// 赋值原始二进制数据
result.raw_data.assign(data, data + 6 + 116 * 2);
return result;
}
// 鼾声解析 (0x4212)
SensorData parse_snore(const uint8_t* data) {
SensorData result;
result.data_type = DataType::SNORE;
result.packet_sn = read_le<uint16_t>(data);
// 跳过 DataType(2) + data_len(2)
const uint8_t* payload = data + 6;
// 解析鼾声数据 (232字节)
auto& channels = result.channel_data.emplace<std::vector<float>>();
// 高效转换: 直接使用 reinterpret_cast
const int8_t* snore_data = reinterpret_cast<const int8_t*>(payload);
for (int i = 0; i < 232; ++i) {
channels.push_back(static_cast<float>(snore_data[i]));
}
// 赋值原始二进制数据
result.raw_data.assign(data, data + 6 + 232);
return result;
}
// 呼吸/姿态/环境光解析 (0x4213)
SensorData parse_respiration(const uint8_t* data) {
SensorData result;
result.data_type = DataType::RESPIRATION;
result.packet_sn = read_le<uint16_t>(data);
// 跳过 DataType(2) 和 data_len(2)
const uint8_t* payload = data + 6;
// 解析呼吸气流数据 (114采样点)
auto& channels = result.channel_data.emplace<std::vector<std::vector<float>>>();
channels.push_back({});
for (int i = 0; i < 114; ++i) {
int16_t adc_value = read_le<int16_t>(payload);
payload += 2;
channels.back().push_back(adc_value * 0.1f); // 实际单位
}
// 解析附加数据
result.additional.movement = read_le<uint16_t>(payload); // 运动强度
payload += 2;
result.additional.posture = *payload++; // 姿态数据
result.additional.ambient_light = *payload++; // 环境光数据
// 赋值原始二进制数据
result.raw_data.assign(data, data + 6 + 114 * 2 + 2 + 1 + 1);
return result;
}
// 统一解析入口函数 - 修改为处理多个数据包
std::vector<SensorData> parse_device_data(const std::vector<uint8_t>& file_data) {
const size_t PACKET_SIZE = 238; // 每个数据包固定大小
const size_t file_size = file_data.size();
if (file_size % PACKET_SIZE != 0) {
throw std::runtime_error("文件大小不是238字节的整数倍可能已损坏");
}
const size_t packet_count = file_size / PACKET_SIZE;
std::vector<SensorData> results;
results.reserve(packet_count);
const uint8_t* ptr = file_data.data();
for (size_t i = 0; i < packet_count; i++) {
// 读取数据类型标识
const uint16_t data_type = read_le<uint16_t>(ptr + 2);
switch (data_type) {
case 0x4230:
results.push_back(parse_eeg(ptr));
break;
case 0x4211:
results.push_back(parse_ecg_emg(ptr));
break;
case 0x4212:
results.push_back(parse_snore(ptr));
break;
case 0x4213:
results.push_back(parse_respiration(ptr));
break;
case 0x4402:
results.push_back(parse_12lead_ecg(ptr));
break;
case 0x4302:
results.push_back(parse_ppg(ptr));
break;
case 0x1102:
results.push_back(parse_stethoscope(ptr));
// 其他设备类型可以继续添加
default:
throw std::runtime_error("未知设备类型");
}
ptr += PACKET_SIZE;
}
return results;
}