第四章 应用层协议详解:HL7 v2.x、DICOM与POCT1-A

应用层协议,说白了就是医疗设备之间“说人话”的规则。我做了十几年嵌入式医疗系统,见过太多设备因为协议解析不对,导致数据传过来全是乱码。这一章咱们就掰开揉碎,把三个最常用的协议讲透。

4.1 HL7 v2.x 消息结构——医院信息系统的“通用语”

HL7 v2.x 是目前医院信息系统(HIS)里用得最广的协议。它的消息结构其实不复杂,核心就是“段(Segment)+ 字段(Field)+ 组件(Component)”三层嵌套。

核心概念:HL7 消息 = 多个段(Segment)拼接而成,每个段以三个大写字母开头,比如 MSH(消息头)、PID(患者信息)、OBX(观测结果)。

4.1.1 消息结构解剖

我习惯把 HL7 消息比作一封信:

  • MSH 段——信封,写明了发件人、收件人、消息类型、时间戳。
  • PID 段——收件人信息,患者姓名、ID、出生日期。
  • OBX 段——信的内容,具体的检验结果、生命体征数值。

来看一个实际的心电监护仪上报消息:

MSH|^~\&|监护仪|ICU_01|HIS|HOSP|202403151430||ORU^R01|MSG001|P|2.3
PID|||PAT001||张伟||19800515|M
OBX|1|NM|HR^心率||72|次/分|60-100|N||F
OBX|2|NM|SBP^收缩压||128|mmHg|90-140|N||F

注意看分隔符:| 是字段分隔符,^ 是组件分隔符。我在项目里遇到过最坑的事——有人把字段分隔符配成了 &,结果整个消息解析全乱套了。

我的经验:调试 HL7 消息时,先检查 MSH 段第 2 个字段(编码字符)。默认是 ^~\&,如果这里错了,后面所有解析都会偏移。我曾经花了一整天查一个“数据丢失”的 bug,最后发现是编码字符被意外修改了。

4.1.2 常见段类型速查表

段名 全称 用途 必选/可选
MSH Message Header 消息头,定义消息类型、发送方、接收方 必选
PID Patient Identification 患者身份信息 必选
OBX Observation Result 观测结果,如心率、血压、血糖值 可选(但常用)
EVN Event Type 事件类型,记录触发消息的事件 可选

4.2 DICOM 文件格式解析——医学影像的“通用底片”

DICOM 不只是文件格式,它是一整套通信协议。但咱们做嵌入式系统,最常打交道的是 DICOM 文件——也就是设备生成的影像文件。

DICOM 文件的结构很有意思:它把患者信息、设备参数、图像数据全塞进一个文件里。说白了,就是“自描述”的。

4.2.1 文件结构四要素

  1. 文件头(Preamble)——前 128 字节,通常全零,后面紧跟 "DICM" 四个字符。
  2. 元信息(Meta Information)——传输语法、SOP Class UID 等。
  3. 数据集(Data Set)——一堆 Tag(标签),每个 Tag 对应一个属性,比如患者姓名、检查日期。
  4. 像素数据(Pixel Data)——真正的图像数据,可能是 JPEG 压缩或原始 RAW。

注意:DICOM 的 Tag 是 4 字节的(组号+元素号),比如 (0010,0010) 表示患者姓名。解析时一定要按小端序读取,我见过有人用大端序解析,结果患者名字变成了乱码。

4.2.2 关键 Tag 速查

Tag (十六进制) 含义 VR (值表示法) 说明
(0008,0005) Specific Character Set CS 字符集,常用 ISO_IR 100(拉丁语)
(0010,0010) Patient Name PN 患者姓名,格式:姓^名
(0028,0010) Rows US 图像行数
(0028,0011) Columns US 图像列数
(7FE0,0010) Pixel Data OW/OB 像素数据本体

解析 DICOM 时,我建议先读 (0002,0010) 这个 Tag——它告诉你传输语法。如果是 1.2.840.10008.1.2(隐式 VR 小端序),那后面的 Tag 就没有 VR 字段,解析逻辑完全不同。

4.3 POCT1-A 协议——床旁检测的“现场指挥”

POCT1-A 是专门为床旁检测设备(血糖仪、血气分析仪、凝血仪)设计的协议。它跟 HL7 不一样,HL7 是“医院内部通用”,POCT1-A 是“床边专用”。

这个协议的核心思想是:设备要能即插即用,数据要能实时上传,而且必须保证患者身份准确无误。

4.3.1 协议分层与消息类型

POCT1-A 分为三层:

  • 物理层——通常是 RS-232 串口或 USB 虚拟串口,波特率 9600 或 19200。
  • 数据链路层——用帧头帧尾(STX/ETX)和校验和(Checksum)保证数据完整。
  • 应用层——定义具体的操作命令,比如“上传结果”、“查询患者列表”。

消息类型主要有三种:

  1. 查询消息(Q)——设备向数据管理器请求信息。
  2. 响应消息(R)——数据管理器回复设备。
  3. 结果消息(R)——设备主动上传检测结果。

实际案例:我在一个血糖仪项目中,设备每次上传结果都要先发查询消息确认患者 ID 是否存在。如果数据管理器没响应,设备会重试 3 次,每次间隔 5 秒。这个机制避免了“测了血糖但找不到患者”的尴尬。

4.3.2 典型消息帧格式

STX | 长度 | 消息类型 | 设备ID | 数据 | 校验和 | ETX
 02  |  0A   |   51     | 01 02  | ...  |  XX    | 03
  • STX (0x02)——帧起始
  • 长度——从消息类型到校验和的字节数
  • 消息类型——0x51 表示结果上传
  • 设备ID——2 字节,唯一标识设备
  • 数据——具体内容,如血糖值 5.6 mmol/L
  • 校验和——从长度到数据的累加和取低 8 位
  • ETX (0x03)——帧结束

避坑指南:我曾经遇到一个设备,串口接收缓冲区只有 64 字节,但 POCT1-A 消息最长能到 128 字节。结果每次传长消息就丢帧。解决方案是:要么增大缓冲区,要么分帧传输。我建议直接上 256 字节环形缓冲区,一劳永逸。

4.4 三种协议对比与选型建议

维度 HL7 v2.x DICOM POCT1-A
主要用途 文本数据交换(检验、医嘱) 医学影像传输与存储 床旁检测设备数据上传
数据格式 纯文本,分隔符结构 二进制 + Tag 结构 二进制帧结构
传输层 TCP/IP(MLLP 协议) TCP/IP(DICOM 上层协议) 串口 / USB
实时性 中等(秒级) 低(影像传输较慢) 高(毫秒级)
嵌入式资源需求 低(文本解析简单) 高(需要解压图像) 极低(串口通信)

选型时我的建议是:如果设备只传文本数据(血糖、血压),用 POCT1-A 最轻量;如果需要对接医院信息系统,HL7 v2.x 是标配;如果涉及影像(超声、X 光),DICOM 绕不开。

4.5 本章知识结构图

下面这张图把三种协议的核心关系画清楚了:

应用层协议知识结构图 应用层协议知识结构 医疗嵌入式系统 HL7 v2.x DICOM POCT1-A MSH/PID/OBX 分隔符解析 Tag 结构 像素数据 帧结构 校验 选型建议 文本数据 → POCT1-A(轻量) | 系统对接 → HL7 v2.x(标准) | 影像数据 → DICOM(专用) 实际项目中常需要同时支持多种协议,建议用协议适配层做统一管理

嗯,这张图把三种协议的关系和子节点都标清楚了。实际项目中,一个设备可能同时支持 HL7 和 POCT1-A——比如床旁监护仪既要上传波形数据(DICOM 格式),又要上传生命体征(HL7 格式),还要跟血糖仪通信(POCT1-A)。这时候就需要一个协议适配层,把不同协议的数据统一转换成内部数据结构。

我的习惯:在嵌入式系统里,我会用一个“协议工厂”模式——根据配置文件的协议类型,动态创建对应的解析器。这样加新协议时,只需要写一个新的解析器类,不用改主流程。

好了,这一章的内容就到这儿。三种协议各有各的脾气,但只要掌握了它们的核心结构——HL7 的段、DICOM 的 Tag、POCT1-A 的帧——剩下的就是多写代码、多调试了。