IEEE 11073标准¶
学习目标¶
通过本文档的学习,你将能够:
- 理解核心概念和原理
- 掌握实际应用方法
- 了解最佳实践和注意事项
前置知识¶
在学习本文档之前,建议你已经掌握:
- 基础的嵌入式系统知识
- C/C++编程基础
- 相关领域的基本概念
概述¶
IEEE 11073是个人健康设备(Personal Health Devices, PHD)通信标准系列,定义了医疗和健康设备与计算机系统之间的数据交换。该标准特别适用于家庭和移动健康监护设备。
标准架构¶
IEEE 11073系列标准¶
| 标准编号 | 名称 | 内容 |
|---|---|---|
| 11073-10101 | 命名法 | 医疗设备术语和代码 |
| 11073-10201 | 域信息模型 | 抽象数据模型 |
| 11073-10404 | 脉搏血氧仪 | 血氧饱和度设备 |
| 11073-10407 | 血压计 | 血压测量设备 |
| 11073-10408 | 体温计 | 体温测量设备 |
| 11073-10415 | 体重秤 | 体重测量设备 |
| 11073-10417 | 血糖仪 | 血糖测量设备 |
| 11073-20601 | 应用配置文件 | 优化交换协议 |
域信息模型(DIM)¶
对象模型¶
示例:血压计模型¶
MDS (血压计系统)
└── VMD (血压测量模块)
└── Channel (血压通道)
├── Metric (收缩压)
│ ├── Unit: mmHg
│ └── Value: 120
├── Metric (舒张压)
│ ├── Unit: mmHg
│ └── Value: 80
└── Metric (平均压)
├── Unit: mmHg
└── Value: 93
命名法(Nomenclature)¶
MDC代码¶
// IEEE 11073-10101 术语代码
#define MDC_PART_SCADA 0x0002 // 监控和数据采集
#define MDC_PART_DIM 0x0004 // 域信息模型
// 生命体征
#define MDC_PRESS_BLD_NONINV 0x4A14 // 无创血压
#define MDC_PRESS_BLD_NONINV_SYS 0x4A15 // 收缩压
#define MDC_PRESS_BLD_NONINV_DIA 0x4A16 // 舒张压
#define MDC_PRESS_BLD_NONINV_MEAN 0x4A17 // 平均压
#define MDC_PULS_OXIM_SAT_O2 0x4A3C // 血氧饱和度
#define MDC_PULS_OXIM_PULS_RATE 0x4A3D // 脉率
#define MDC_TEMP_BODY 0x4A88 // 体温
#define MDC_MASS_BODY_ACTUAL 0x4A8C // 体重
#define MDC_CONC_GLU_CAPILLARY_WHOLEBLOOD 0x4A9C // 毛细血管全血血糖
// 单位
#define MDC_DIM_MMHG 0x0F0E // mmHg
#define MDC_DIM_PERCENT 0x0220 // %
#define MDC_DIM_DEGC 0x17A0 // 摄氏度
#define MDC_DIM_KG 0x1760 // 千克
#define MDC_DIM_MILLI_G_PER_DL 0x06A1 // mg/dL
IEEE 11073-20601协议¶
通信模型¶
Agent (医疗设备) <---> Manager (手机/网关)
状态机:
1. Unassociated (未关联)
2. Associating (关联中)
3. Associated (已关联)
4. Operating (运行中)
5. Disassociating (断开关联中)
协议数据单元(APDU)¶
关联请求(Association Request)¶
typedef struct {
uint16_t protocol_version;
uint16_t encoding_rules;
uint32_t nomenclature_version;
uint32_t functional_units;
uint32_t system_type;
uint8_t system_id[8];
uint16_t dev_config_id;
// ... 配置信息
} AssocReq;
测量数据(Measurement Data)¶
typedef struct {
uint16_t obj_handle; // 对象句柄
uint32_t rel_time_stamp; // 相对时间戳
uint16_t measure_type; // 测量类型(MDC代码)
float value; // 测量值
uint16_t unit; // 单位(MDC代码)
} ScanReportFixed;
实现示例¶
Python实现(使用Antidote)¶
from antidote import ieee11073
from antidote.hdp import HealthDevice
# 创建血压测量数据
def create_blood_pressure_measurement(systolic, diastolic, mean_pressure):
# 创建扫描报告
scan_report = {
'data-req-id': 0x1234,
'scan-report-no': 1,
'obs-scan-fixed': [
{
'obj-handle': 1,
'obs-val-data': {
'compound-simple-nu-observed-value': {
'count': 3,
'value': [
{
'attribute-id': MDC_PRESS_BLD_NONINV_SYS,
'attribute-value': systolic
},
{
'attribute-id': MDC_PRESS_BLD_NONINV_DIA,
'attribute-value': diastolic
},
{
'attribute-id': MDC_PRESS_BLD_NONINV_MEAN,
'attribute-value': mean_pressure
}
]
}
}
}
]
}
return scan_report
# 血压计Agent实现
class BloodPressureAgent(HealthDevice):
def __init__(self):
super().__init__()
self.device_config_id = 0x0190 # 血压计配置
def get_configuration(self):
"""返回设备配置"""
config = {
'dev-config-id': self.device_config_id,
'config-obj-list': [
{
'obj-class': MDC_MOC_VMO_METRIC_NU,
'obj-handle': 1,
'attributes': [
{
'attribute-id': MDC_ATTR_ID_TYPE,
'attribute-value': MDC_PRESS_BLD_NONINV
},
{
'attribute-id': MDC_ATTR_UNIT_CODE,
'attribute-value': MDC_DIM_MMHG
}
]
}
]
}
return config
def send_measurement(self, systolic, diastolic):
"""发送血压测量数据"""
mean_pressure = (systolic + 2 * diastolic) / 3
scan_report = create_blood_pressure_measurement(
systolic, diastolic, mean_pressure
)
self.send_data(scan_report)
# 使用示例
agent = BloodPressureAgent()
agent.connect('00:11:22:33:44:55') # 连接到Manager
agent.send_measurement(120, 80)
C实现¶
#include <stdint.h>
#include <string.h>
// IEEE 11073-20601 APDU类型
#define APDU_TYPE_ASSOC_REQ 0xE200
#define APDU_TYPE_ASSOC_RES 0xE300
#define APDU_TYPE_RLRQ 0xE400
#define APDU_TYPE_RLRE 0xE500
#define APDU_TYPE_PRST 0xE700
// 数据结构
typedef struct {
uint16_t choice;
uint16_t length;
uint8_t value[];
} APDU;
typedef struct {
uint16_t obj_handle;
uint16_t attribute_id;
uint16_t attribute_len;
uint8_t attribute_value[];
} AttributeList;
// 创建关联请求
APDU* create_association_request() {
APDU *apdu = malloc(sizeof(APDU) + 256);
apdu->choice = APDU_TYPE_ASSOC_REQ;
uint8_t *data = apdu->value;
uint16_t offset = 0;
// 协议版本
*(uint16_t*)(data + offset) = htons(0x8000); // Version 1
offset += 2;
// 编码规则
*(uint16_t*)(data + offset) = htons(0x8000); // MDER
offset += 2;
// 命名法版本
*(uint32_t*)(data + offset) = htonl(0x20000000);
offset += 4;
// 功能单元
*(uint32_t*)(data + offset) = htonl(0x00000000);
offset += 4;
// 系统类型
*(uint32_t*)(data + offset) = htonl(0x00800000); // Agent
offset += 4;
// 系统ID(8字节)
memcpy(data + offset, "\x11\x22\x33\x44\x55\x66\x77\x88", 8);
offset += 8;
// 设备配置ID
*(uint16_t*)(data + offset) = htons(0x0190); // 血压计
offset += 2;
apdu->length = htons(offset);
return apdu;
}
// 创建血压测量数据
APDU* create_blood_pressure_data(uint16_t systolic, uint16_t diastolic) {
APDU *apdu = malloc(sizeof(APDU) + 256);
apdu->choice = APDU_TYPE_PRST;
uint8_t *data = apdu->value;
uint16_t offset = 0;
// Invoke ID
*(uint16_t*)(data + offset) = htons(0x0001);
offset += 2;
// 数据请求ID
*(uint16_t*)(data + offset) = htons(0x1234);
offset += 2;
// 扫描报告编号
*(uint16_t*)(data + offset) = htons(0x0001);
offset += 2;
// 观察数量
*(uint16_t*)(data + offset) = htons(3); // 收缩压、舒张压、平均压
offset += 2;
// 收缩压
*(uint16_t*)(data + offset) = htons(1); // 对象句柄
offset += 2;
*(uint16_t*)(data + offset) = htons(MDC_PRESS_BLD_NONINV_SYS);
offset += 2;
*(uint16_t*)(data + offset) = htons(2); // 长度
offset += 2;
*(uint16_t*)(data + offset) = htons(systolic);
offset += 2;
// 舒张压
*(uint16_t*)(data + offset) = htons(1);
offset += 2;
*(uint16_t*)(data + offset) = htons(MDC_PRESS_BLD_NONINV_DIA);
offset += 2;
*(uint16_t*)(data + offset) = htons(2);
offset += 2;
*(uint16_t*)(data + offset) = htons(diastolic);
offset += 2;
// 平均压
uint16_t mean = (systolic + 2 * diastolic) / 3;
*(uint16_t*)(data + offset) = htons(1);
offset += 2;
*(uint16_t*)(data + offset) = htons(MDC_PRESS_BLD_NONINV_MEAN);
offset += 2;
*(uint16_t*)(data + offset) = htons(2);
offset += 2;
*(uint16_t*)(data + offset) = htons(mean);
offset += 2;
apdu->length = htons(offset);
return apdu;
}
// 发送APDU
void send_apdu(int socket, APDU *apdu) {
uint16_t total_len = sizeof(APDU) + ntohs(apdu->length);
send(socket, apdu, total_len, 0);
}
// 使用示例
void blood_pressure_agent_example() {
int sock = connect_to_manager("192.168.1.100", 9999);
// 发送关联请求
APDU *assoc_req = create_association_request();
send_apdu(sock, assoc_req);
free(assoc_req);
// 等待关联响应
// ... 接收和处理响应
// 发送测量数据
APDU *measurement = create_blood_pressure_data(120, 80);
send_apdu(sock, measurement);
free(measurement);
close(sock);
}
Continua设计指南¶
Continua认证¶
Continua Health Alliance(现为Personal Connected Health Alliance)定义了基于IEEE 11073的互操作性指南。
认证要求¶
- 传输层: 蓝牙HDP或BLE
- 应用层: IEEE 11073-20601
- 设备专用: 对应的IEEE 11073-104xx标准
- 安全: 蓝牙配对和加密
认证设备类型¶
- 血压计(Blood Pressure Monitor)
- 血糖仪(Glucose Meter)
- 体重秤(Weighing Scale)
- 脉搏血氧仪(Pulse Oximeter)
- 体温计(Thermometer)
- 心率监护仪(Heart Rate Monitor)
- 活动监测器(Activity Monitor)
与FHIR集成¶
# IEEE 11073到FHIR Observation的转换
def ieee11073_to_fhir_observation(ieee_data):
observation = {
'resourceType': 'Observation',
'status': 'final',
'category': [{
'coding': [{
'system': 'http://terminology.hl7.org/CodeSystem/observation-category',
'code': 'vital-signs'
}]
}]
}
# 映射MDC代码到LOINC
mdc_to_loinc = {
MDC_PRESS_BLD_NONINV_SYS: '8480-6', # 收缩压
MDC_PRESS_BLD_NONINV_DIA: '8462-4', # 舒张压
MDC_PULS_OXIM_SAT_O2: '59408-5', # 血氧
MDC_TEMP_BODY: '8310-5', # 体温
MDC_MASS_BODY_ACTUAL: '29463-7' # 体重
}
loinc_code = mdc_to_loinc.get(ieee_data['measure_type'])
if loinc_code:
observation['code'] = {
'coding': [{
'system': 'http://loinc.org',
'code': loinc_code
}]
}
# 映射单位
mdc_to_ucum = {
MDC_DIM_MMHG: 'mm[Hg]',
MDC_DIM_PERCENT: '%',
MDC_DIM_DEGC: 'Cel',
MDC_DIM_KG: 'kg'
}
ucum_unit = mdc_to_ucum.get(ieee_data['unit'])
observation['valueQuantity'] = {
'value': ieee_data['value'],
'unit': ucum_unit,
'system': 'http://unitsofmeasure.org',
'code': ucum_unit
}
return observation
测试与验证¶
Continua测试工具¶
# 使用Continua测试工具验证设备
def validate_continua_device(device):
tests = [
test_association(),
test_configuration(),
test_measurement_data(),
test_disconnection()
]
results = []
for test in tests:
result = test(device)
results.append(result)
print(f"{test.__name__}: {'PASS' if result else 'FAIL'}")
return all(results)
最佳实践¶
- ✅ 使用标准MDC代码
- ✅ 实施完整的状态机
- ✅ 支持配置协商
- ✅ 实施错误处理
- ✅ 考虑Continua认证
参考资源¶
相关章节: - 蓝牙HDP - HL7 FHIR集成
💬 讨论区
欢迎在这里分享您的想法、提出问题或参与讨论。需要 GitHub 账号登录。