VitalServer HL7 v2 Spec

VitalServer HL7 v2 Protocol Specification

HL7 v2 protocol specification for VitalRecorder to transmit real-time vital data to the demo.vitaldb.net server. The server also follows this specification when providing data in the same format to clients for the open dataset service.


1. Communication

ItemValue
ProtocolWebSocket (RFC 6455) over TLS
Port443 (WSS)
Path/socket.io/?EIO=3&transport=websocket
Application LayerEngine.IO v3 / Socket.IO
Data FormatHL7 v2.6 (UTF-8)
Compressiongzip (zlib)

2. Connection Procedure

2.1 WebSocket Connection and Socket.IO Handshake

Client -> Server  [WS Upgrade]
Client -> Server  "40"                        <- engine.io MESSAGE(4) + socket.io CONNECT(0)
Server -> Client  [confirmation frame]
Client -> Server  42["join_vr","<vrcode>"]    <- socket.io EVENT: join room

vrcode is the unique identifier for the VitalRecorder device (e.g., VR_ABC123).

2.2 Data Transmission Loop (1-second interval)

Client -> Server  451-["send_data",{"_placeholder":true,"num":0}]   <- text frame, binary attachment announcement
Client -> Server  [binary frame] = 0x04 + gzip(HL7_payload)         <- binary frame
  • First frame: 451-[...] format to announce a binary attachment
    • 4 = engine.io MESSAGE, 5 = socket.io BINARY_EVENT, 1- = 1 binary attachment
  • Second frame: 0x04 (1-byte attachment header) + gzip-compressed HL7 text payload

2.3 Ping/Pong (Keep-alive)

Server -> Client  "2"    <- engine.io PING
Client -> Server  "3"    <- engine.io PONG

2.4 Server-to-Client Commands

The server can send commands in socket.io EVENT (42[...]) format:

CommandParameterDescription
update--Software update
restart--Restart
dt<unix_timestamp>Time synchronization
del_bed"<bedname>"Delete bed
new_bed"<bedname>"Add bed
edit_bed"{...}" (JSON string)Modify bed settings

3. HL7 v2 Message Structure

Each transmission payload is a concatenation of one or more HL7 messages (one per bed, sent consecutively).

3.1 Segment Delimiters

DelimiterValueDescription
Segment terminator\r (0x0D)HL7 standard CR
Field\|Field separator
Component^Component separator
Repetition~Repeat separator
Escape\\Escape character
Sub-component&Sub-component separator

3.2 Full Message Structure

MSH|^~\&|VitalRecorder|<vrcode>|||<datetime>||ORU^R01|<seq>|P|2.6\r
PID|||<patient_id>\r
PV1||I|<bedname>\r
OBR|1|||VITAL_SIGNS|||<from>|<to>\r
OBX|1|<type>|<code>^<identifier>||<value(s)>|<unit>|<refrange>||||R\r
OBX|2|...\r
...

4. Segment Details

4.1 MSH (Message Header)

FieldExampleDescription
MSH-3VitalRecorderSending application
MSH-4VR_ABC123Sending device vrcode
MSH-720250323143000Message creation time (YYYYMMDDHHmmss)
MSH-9ORU^R01Message type: Observation result
MSH-1012345Message sequence number (monotonically increasing)
MSH-11PProcessing ID: Production
MSH-122.6HL7 version

4.2 PID (Patient Identification)

FieldExampleDescription
PID-3PT-001Patient ID (empty string if unavailable)

4.3 PV1 (Patient Visit)

FieldExampleDescription
PV1-2IPatient Class: Inpatient
PV1-3OR-1Bed/room name

4.4 OBR (Observation Request)

FieldExampleDescription
OBR-11Set ID
OBR-4VITAL_SIGNSObservation identifier
OBR-720250323143000Observation start time
OBR-820250323143001Observation end time

4.5 OBX (Observation Result)

OBX|<set_id>|<value_type>|<observation_id>||<observation_value>|<units>|<refrange>||||R
FieldPositionDescription
OBX-1Set IDSequential from 1
OBX-2Value TypeNM (numeric), NA (numeric array/waveform), ST (string)
OBX-3Observation ID<code>^<device>/<track>[@<srate>]
OBX-5Observation ValueValue (see type-specific formats)
OBX-6UnitsUnit string (e.g., bpm, mmHg, mV)
OBX-7Reference Range<mindisp>^<maxdisp> (display range; empty if not applicable)
OBX-11Observation StatusR (Result)

5. OBX-3 Observation Identifier Format

<montype>^<device>/<track>[@<srate>]
PartExampleDescription
<montype>ECG_HR, ECG_WAVMonitor type code (see list below)
<device>BeneViewDevice name
<track>HR, ECG_IITrack name
@<srate>@250Appended to waveforms (NA) only: sampling rate (Hz)

Examples:

ECG_HR^BeneView/HR
ECG_WAV^BeneView/ECG_II@250
AWP_WAV^Ventilator/Paw@25

6. OBX-5 Observation Value Format

6.1 Numeric (NM)

Single float value:

72.5

6.2 Waveform (NA)

^-separated float sample array. Invalid samples (NaN) are represented as empty strings:

0.12^0.15^0.09^^0.11^0.20
  • Waveform data contains sequential samples for the OBR-7 (from) to OBR-8 (to) interval
  • Maximum transmission window per message is 60 seconds
  • Tracks with srate > 100 Hz are downsampled to 100 Hz
  • Airway pressure (AWP) and CO2 waveforms are downsampled to a fixed 25 Hz

6.3 String Event (ST)

OBX|<idx>|ST|EVENT^^||Induction Start||||||R
  • OBX-3: EVENT^^ (fixed)
  • Up to 3 most recent events are appended at the end of the message

7. montype Code List

Waveform (OBX-2 = NA)

CodeDescriptionDefault srate
ECG_WAVECG waveformup to 100 Hz
PLETH_WAVSpO2 pleth waveformup to 100 Hz
RESP_WAVRespiration waveformup to 100 Hz
CO2_WAVCO2 waveform25 Hz (fixed)
AWP_WAVAirway pressure waveform25 Hz (fixed)
IABP_WAVArterial BP waveformup to 100 Hz
CVP_WAVCVP waveformup to 100 Hz
EEG_WAVEEG waveformup to 100 Hz
ICP_WAVICP waveformup to 100 Hz
PAP_WAVPA waveformup to 100 Hz

Numeric (OBX-2 = NM)

CodeDescriptionUnit
ECG_HRHeart ratebpm
PLETH_SPO2SpO2%
RESP_RRRespiratory rate/min
CO2_CONCEtCO2mmHg
NIBP_SBPNIBP systolic pressuremmHg
NIBP_DBPNIBP diastolic pressuremmHg
NIBP_MBPNIBP mean pressuremmHg
IABP_SBPABP systolic pressuremmHg
IABP_DBPABP diastolic pressuremmHg
IABP_MBPABP mean pressuremmHg
BTBody temperatureC
EEG_BISBIS
TVTidal volumemL
MVMinute ventilationL/min
PIPPeak inspiratory pressurecmH2O
PEEPPEEPcmH2O

8. Full Examples

8.1 Numeric Tracks Only

MSH|^~\&|VitalRecorder|VR_ABC123|||20250323143001||ORU^R01|42|P|2.6\r
PID|||PT-2025-001\r
PV1||I|OR-3\r
OBR|1|||VITAL_SIGNS|||20250323143000|20250323143001\r
OBX|1|NM|ECG_HR^BeneView/HR||72|bpm|40^200||||R\r
OBX|2|NM|PLETH_SPO2^BeneView/SpO2||98|%|80^100||||R\r
OBX|3|NM|NIBP_SBP^BeneView/NIBP_SBP||118|mmHg|40^260||||R\r
OBX|4|NM|NIBP_DBP^BeneView/NIBP_DBP||74|mmHg|20^200||||R\r
OBX|5|NM|BT^BeneView/BT||36.7|C|30^42||||R\r

8.2 With Waveforms (ECG 250 -> 100 Hz downsampled)

MSH|^~\&|VitalRecorder|VR_ABC123|||20250323143001||ORU^R01|43|P|2.6\r
PID|||PT-2025-001\r
PV1||I|OR-3\r
OBR|1|||VITAL_SIGNS|||20250323143000|20250323143001\r
OBX|1|NA|ECG_WAV^BeneView/ECG_II@100||0.12^0.15^0.09^0.11^...(100 samples)...|mV|-1.5^1.5||||R\r
OBX|2|NA|AWP_WAV^Ventilator/Paw@25||12.1^12.3^12.0^11.9^...(25 samples)...|cmH2O|0^60||||R\r
OBX|3|NM|ECG_HR^BeneView/HR||72|bpm|40^200||||R\r
OBX|4|ST|EVENT^^||Induction Start||||||R\r

8.3 Multi-Bed Message (full payload)

Bed-specific messages are concatenated with segments separated by CR (\r):

MSH|...|OR-1|...\r PID|...\r PV1|...|OR-1\r OBR|...\r OBX|...\r
MSH|...|OR-2|...\r PID|...\r PV1|...|OR-2\r OBR|...\r OBX|...\r

9. Notes

ItemDetails
Time formatYYYYMMDDHHmmss (local time, second precision)
Waveform NaNInvalid sample values are empty strings (nothing between ^ delimiters)
Waveform srateTracks exceeding 100 Hz are automatically downsampled to 100 Hz
Transmission windowUp to 60 seconds of data per message
Transmission interval1 second (SENDWEBINTERVAL_SECS)
EncodingAll strings UTF-8
Ref RangeIf mindisp == maxdisp, OBX-7 is left empty
No dataIf a track has no data in the transmission window, the OBX row is omitted
No OBXIf a bed has no OBX rows, its entire message is not sent