#include "headfile.h" #include // 添加 memcpy 头文件 // 辅助函数:从字节数组读取小端整数 template T read_le(const uint8_t* data) { T value = 0; for (size_t i = 0; i < sizeof(T); ++i) { value |= static_cast(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(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>>(); 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(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(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(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>>(); // ECG1 (25采样点) channels.push_back({}); for (int i = 0; i < 25; ++i) { int16_t adc_value = read_le(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(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(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(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(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(payload); payload += 2; channels.back().push_back(static_cast(imp_value)); // 原始值 } // 呼吸阻抗2 (5采样点) channels.push_back({}); for (int i = 0; i < 5; ++i) { int16_t imp_value = read_le(payload); payload += 2; channels.back().push_back(static_cast(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(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(payload); result.additional.temperature = static_cast(temp_raw) / 100.0f; payload += 2; // 解析红光数据 (57采样点) auto& channels = result.channel_data.emplace>>(); channels.push_back({}); for (int i = 0; i < 57; ++i) { int16_t adc_value = read_le(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(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(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>>(); 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(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(data); // 跳过 DataType(2) 和 data_len(2) const uint8_t* payload = data + 6; // 解析双通道音频数据 auto& channels = result.channel_data.emplace>>(); channels.resize(2); // 通道1数据 (116采样点) for (int i = 0; i < 116; ++i) { int8_t sample = static_cast(*payload++); channels[0].push_back(sample * 0.146f); // mV } // 通道2数据 (116采样点) for (int i = 0; i < 116; ++i) { int8_t sample = static_cast(*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(data); // 跳过 DataType(2) + data_len(2) const uint8_t* payload = data + 6; // 解析鼾声数据 (232字节) auto& channels = result.channel_data.emplace>(); // 高效转换: 直接使用 reinterpret_cast const int8_t* snore_data = reinterpret_cast(payload); for (int i = 0; i < 232; ++i) { channels.push_back(static_cast(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(data); // 跳过 DataType(2) 和 data_len(2) const uint8_t* payload = data + 6; // 解析呼吸气流数据 (114采样点) auto& channels = result.channel_data.emplace>>(); channels.push_back({}); for (int i = 0; i < 114; ++i) { int16_t adc_value = read_le(payload); payload += 2; channels.back().push_back(adc_value * 0.1f); // 实际单位 } // 解析附加数据 result.additional.movement = read_le(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 parse_device_data(const std::vector& 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 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(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; }