VitalRecorder – All Versions

You can browse all available versions by OS and download any version directly.
Total downloads since Feb 2017: 178,479

Version Date Changes
1.18.41 2026-05-13 1.18.41 Hotfix: TCP-server protocol-initiator device (Intellivue/S5/Datex/Hamilton/MPS/Agilia/IAP) 가 open() 직후 보내는 첫 패킷이 wire 에 안 나가던 회귀. 1.18.34 의 PortRouter refactor 가 Serial::open_socket() 의 8초 handoff blocking 을 제거하고 비동기 모델로 전환했는데, protocol-initiator 의 open() 코드가 m_sock=INVALID 상태에서 write 를 시도해 silent fail (Linux 는 m_fd=0 이라 false 반환). Intellivue 케이스 production journald 의 Pi → ESP TX 700K~3M bytes 는 monitor 측 abort 로 늦게 트리거된 AB_SPDU_SI recovery assoc_req 후 request_thread 의 정상 polling 트래픽이지만 일부 베드 (abort 없는 monitor) 는 recovery 도 안 되어 영구 silent (RX 300 bytes). 수정 방향: open() 의 옛 contract ("return 시점에 통신 가능") 복구. (1) Serial::open_socket() TCP-server 분기가 PortRouter::subscribe 후 m_sock_cv 로 첫 client handoff 까지 block (timeout = device read_timeout, 기본 30s) — 옛 모델 그대로. lock_and_open 이 false 면 다음 tick 에서 retry. close 신호로 abort 가능. (2) Serial::close() 는 PortRouter::unsubscribe 안 함 — subscribe 는 device 생애 동안 sticky 라 read_timeout 으로 인한 close→re-open 사이클 동안 listen socket 이 유지되어 1.18.29/1.18.34 의 anti-churn 이익 보존. unsubscribe 는 ~Serial() 에서만. (3) Per-device lifecycle thread (DEVICE::m_thread_restart): 각 device 가 자기 open/close/timeout 재시작을 별도 thread 에서 관리. 옛 모델의 DISPLAY::bed_manager 가 베드의 모든 device 를 sequential iterate 하던 구조에선 한 device 의 blocking open() 이 같은 베드의 다른 device 의 lifecycle 을 차단했는데, per-device thread 로 분리하여 멀티 device 베드도 병렬 진행. add_dev 에서 start_lifecycle, del_dev / ~DISPLAY 에서 stop_lifecycle. (4) Serial::tcp_thread_func 단순화 — outer m_sock_cv wait 패턴 (1.18.34/1.18.39 가 추가했던 것) 제거. open_socket 이 m_sock valid 보장하므로 reader thread 시작 시점에 simple inner recv loop 만. accept_handoff 의 replace (zombie cleanup) 케이스는 recv error 후 m_sock 변경 확인 + retry 로 처리. (5) reading_thread_func 의 `else if (m_sock != INVALID_SOCKET) tcp_thread_func();` 가드 복원 (1.18.39 가 제거). (6) Serial::write 의 silent-fail 케이스에 WARN trace 추가 — 미래 동종 회귀 즉시 노출. (7) PortRouter::subscribe 가 같은 (port, type) 에서 같은 IP filter 또는 둘 이상 catch-all 발견 시 reject (config 실수 원천 차단, 옛 WARN-only 동작 강화). (8) DISPLAY::bed_manager_thread_func 의 restart 블록 제거 — ptcon + adt 만 담당. "Waiting for next patient" TRACE 가 Linux/console 에서 1초 → 60초마다 throttle (별개 journald 부풀림 fix). 영향 범위: Intellivue / S5 / Datex / Hamilton / MPS / Agilia / IAP TCP-server 모드 베드 전부. 1.18.34 이후 우회 방법은 race-win 케이스 (VRN 이 PortRouter::subscribe 직후 connect) 외엔 없었음. MFC + Qt + Pi (RPI64) + Ubuntu Qt + AppImage 빌드 모두 통과.
1.18.40 2026-05-12 Hotfix: Drager Medibus 프로토콜 사용 베드에서 1.15.11 이후 vr.service 가 SIGSEGV 로 무한 재시작하던 문제. 1.15.10 (a8c7b2a) 의 "Sampling rate estimation" 리팩터링이 m_ptrk_awp/awf/co2 트랙을 add_trks() 에서의 eager 생성 (default srate=62.5Hz) 에서 realtime data 100 샘플 모인 후 lazy 생성으로 바꿨는데, Medibus 핸드셰이크 순서 (0x51 ICC → 0x52 DeviceID → 0x53 RealtimeConfig 응답 → 0x54 → realtime data 시작) 상 0x53 응답 핸들러 (Drager.cpp:295-307) 가 트랙들이 아직 nullptr 인 시점에 `ptrk->m_srate = 1000000.0/interval` 로 NULL 역참조 → 즉시 SEGV. 그 베드의 vr.service 가 systemd Restart=on-failure 로 재시작 → 다시 connect → 동일 0x53 패킷 받고 동일 SEGV → 무한 루프 (journald 로그상 restart counter 61 까지 누적, code=killed status=11/SEGV). 1.15.9 까진 트랙이 add_trks() 에서 생성되어 0x53 도착 시 항상 non-NULL 이라 안전했음. 수정: (a) add_trks() 에서 m_ptrk_awp/awf/co2 eager 생성 복원 (srate=62.5Hz default) — 0x53 는 ptrk->m_srate 만 갱신 (트랙 재생성 X). (b) on_received() 의 lazy creation + packet-timing srate 추정 블록 제거 — 0x53 가 권위 있는 srate 소스이고 packet 타이밍 기반 추정은 network jitter 에 약해 불안정. (c) 0x53 핸들러에 `if (interval > 0)` guard 추가 — 페이로드 깨졌을 때 div-by-zero / inf srate 방지. 영향 범위: Drager Primus / Apollo / Perseus / Fabius 등 Medibus 사용 마취기 전부. 우회 방법은 1.15.9 다운그레이드 외엔 없었음 (그 베드의 모든 데이터 유실 + 환자 모니터링 불가). MFC + Qt + Pi (RPI64) + Ubuntu Qt + AppImage 빌드 모두 통과.
1.18.39 2026-05-08 Fixed: PortRouter (TCP server) 모드에서 reader thread 가 startup 시점에 죽어 client 데이터를 영구히 못 받던 문제. 1.18.34 (9bd252f) 의 PortRouter refactor 가 m_sock 세팅을 dispatch 시점으로 옮겼는데 reading_thread_func (Serial.cpp:354) 의 가드 `else if (m_sock != INVALID_SOCKET) tcp_thread_func();` 는 옛 모델 (open 시점 이미 connect 완료) 가정 그대로라 — 시작 직후 m_sock=INVALID 면 tcp_thread_func 진입 안 하고 reader thread 즉시 종료. 이후 VRN 이 connect → PortRouter::dispatch → accept_handoff 가 m_sock 채우고 m_sock_cv.notify_all() → 그러나 wait 중인 reader 가 없음 (이미 죽음) → kernel recv buffer 에만 데이터 적재. 증상은 ss -tn state established 의 Recv-Q 가 0 이 아닌 값 (수백 bytes) 으로 누적, 베드 화면에는 데이터 안 들어옴. 그 베드의 VRN 이 Serial::open() 의 PortRouter::subscribe 직후~reader thread spawn 사이의 짧은 윈도우 안에 connect 한 경우만 우연히 정상 동작 (race-win). 수정: 가드 제거 — TCP 분기에 항상 진입. tcp_thread_func 자체에 이미 m_sock_cv outer-wait 루프가 있어 m_sock 이 INVALID 인 동안 dispatch 가 깨워줄 때까지 안전하게 대기. Pi 핫스팟에 VRN 여러 대 (e.g. 10.42.0.21~25) 를 같은 (4343, Philips:Intellivue) 키로 묶고 IP filter 로 라우팅하는 시나리오에서 가장 자주 노출. Added: 진단 로그 보강 — PortRouter::accept_loop 의 accept 이벤트, dispatch 의 라우팅 결정 (ip_specific/catch_all subs 수, 어느 dev 가 받았는지), subscribe/unsubscribe 의 entry 생성/append/destroy, reading_thread / tcp_thread 의 시작·wait·wake 라이프사이클 — 이전엔 모두 m_bDebug 게이트 안에 있어서 production journald 에서 안 보였는데, 이제 항상 출력 (이번 같은 dispatch routing 문제 진단을 production 에서 바로 가능). MFC + Qt + Pi (RPI64) + Ubuntu Qt + AppImage 빌드 모두 통과.
1.18.38 2026-05-08 Fixed: 웹모니터링 우클릭 → 디바이스 세팅 (websocket edit_bed 명령) 으로 베드의 device/filter 를 변경할 때 베드 이름이 매번 "_2" suffix 로 자동 리네임되어 vr.conf (Pi: /data/vr.conf) 에 잘못된 이름으로 저장되던 문제. 원인은 1.18.22 (cda8aa5) 에서 add_bed 에 추가된 bedname dedup ("최후 방어선" 으로 forward_frame auto-create / 수동 편집된 conf 의 중복 이름 처리용). edit_bed 핸들러는 옛 pdel 이 m_pdisps 에 그대로 있는 상태에서 같은 bedname 으로 new DISPLAY 를 add_bed 하고 그 다음 del_bed(pdel) 하는 순서였는데, add_bed 가 dup 감지해 새 pdisp 를 bedname_2 로 자동 리네임 → save_settings 가 [BED/bedname_2] 로 직렬화 → 사용자 입장에선 "설정 적용 안됨" 으로 보였다. 추가로 옛/새 DISPLAY 가 잠깐 m_pdisps 에 공존하면서 같은 device 포트를 동시에 들고 있으려 해 로그가 dup 으로 찍히는 부수 증상도 있었음. 수정: del_bed(pdel) 를 add_bed(pdisp) 보다 앞으로 이동 — 옛 베드의 device 포트가 깨끗이 release 된 뒤 새 pdisp 가 같은 포트를 reopen, dedup 발동 안 함. 다른 베드의 recording 은 영향 없음 (인메모리 hot swap 설계 유지). 부수: edit_bed 핸들러의 데드 코드 (`break` 뒤의 unreachable olddevs populate 루프 + `if (olddevs.find(name) == olddevs.end())` 항상-true 래퍼) 정리. edit_conf 와 save_settings 는 손대지 않음. MFC + Qt + Pi (RPI64) 빌드 모두 통과.
1.18.37 2026-05-08 Refactored: 필터 다이얼로그의 python 런타임 — pyvital → openvital 0.3.0 로 교체 + 동봉 python.zip 슬림화. 핵심 동기 셋: (1) pyvital 0.6.0 이 tensorflow+torch+keras 를 hard-dep 으로 끌어들여 PyPI upgrade 가 사실상 깨짐, (2) 기존 zip 121 MB 안에 botocore/aiobotocore/s3fs/pyarrow/pandas/aiohttp 등 vitaldb 클라우드 업로드용 deps 가 ~250 MB unpacked 차지 — 필터 서버는 한 번도 쓴 적 없는 dead weight, (3) sanic 25.x 의 multi-process worker 가 openvital __main__.py 를 fork 후 재import 하면서 worker 가 module-top app instance 를 못 찾아 "Sanic app name not found" 로 죽음 — 단순 endpoint 2개 로컬호스트 서버에 async stack 자체가 과함. 해결: openvital 0.3.0 (commit b6f445b) 가 sanic 을 stdlib http.server (BaseHTTPRequestHandler + HTTPServer) 로 50 LOC 재작성 — wire protocol (GET / 필터목록 JSON, POST /<modname> gzip 본문) 동일해 VR 클라이언트 변경 0줄. 단일 스레드로 기존 sanic event loop semantics (cfgs/default_cfgs lock-free 변경) 보존. build_python_zip.py (NEW) 가 Python 3.11.9 embed + numpy + openecg + openvital (local checkout 우선, fallback PyPI) 만으로 27 MB zip 빌드 — 기존 121 MB 대비 78% 감소. ML 필터 (sv_dlapco/abp_hpi/ecg_classifier/ecg_beat_noise_detector) 는 [Hybrid 모델] 사용자가 Add filter 다이얼로그의 "Install ML filters" 버튼 누를 때 silent pip install openvital[all] (cmd 창 미노출 — VRApp::install_pip_package + run_pip_silent 이 자체 progress 다이얼로그에 stdout heartbeat 흘림). 버튼 라벨은 "Upgrade pyvital" → "Install ML filters" 로 의도 명시. openvital __main__.py 가 missing extras 를 graceful skip 하므로 base 환경에서도 11개 필터 (ECG QRS detector, HRV, MTWA, annotator, eeg_fft, nirs_cox, pkpd_3comp, pleth_dpop/ptt/pvi, resp_compliance) 즉시 사용 가능. Migration: 기존 사용자의 user_dir/python 폴더는 pyvital + 옛 deps 가 그대로 남아있고 vitaldb.net/python.zip 만 새로 올리면 (a) 기존 폴더 삭제 후 install_python 으로 새 zip 받으면 깔끔, (b) 폴더 유지 시 server 가 openvital 못 찾아 필터 다이얼로그 에러 → release note 에 명시 필요. MFC + Qt 양쪽 코드: VRGui.rc 의 IDC_UPGRADE 버튼 라벨 + DlgAddFilter.cpp 의 dist-info prefix 매칭 (pyvital- 8자 → openvital- 10자) + QtDlgAddFilter.cpp 도 동일 변경 + onUpgrade 가 cmd /k QProcess::startDetached 대신 theApp.install_pip_package("openvital[all]") 호출 (Linux Qt 빌드는 #ifdef _WIN32 가드). VRApp.cpp:318 의 python -m pyvital → -m openvital. install_pip_package 는 anonymous namespace 의 is_safe_pkg_spec 화이트리스트 검증 + run_pip_silent (CreateProcessA + CREATE_NO_WINDOW + 자식 stdout pipe) + CDlgProgress / QtDlgProgress 자체 progress UI. 빌드 검증: python -m openvital 이 GET / 로 11 필터 반환, sanic import 부재 확인. zip 27.5 MB.
1.18.36 2026-05-07 Fixed: 3-파티션 레이아웃 (boot/rootfs/data) 에서 websocket edit_conf / update 명령이 read-only fs 로 실패하던 문제. vr.conf 는 /data 폴더가 있으면 /data/vr.conf 로 자동 정착 — get_conf_path() 가 write target 으로 결정, load_settings() 는 primary 가 없으면 legacy /boot/firmware/vr.conf 또는 /boot/vr.conf 에서 fallback read 후 다음 save 부터 primary 로 자동 이전 (마이그레이션 step 없음, legacy 파일은 read-only fs 라 무해). binary update (upgrade_now) 는 RAII BootRwGuard 가 dirname(module_path) 를 잠시 rw remount, scope 종료 시 sync() + MS_REMOUNT|MS_RDONLY 로 자동 ro 복귀 — vfat 노출 윈도우 최소화 + exception/return 어디서든 복구 보장. statvfs ST_RDONLY 검사로 이미 rw 인 fs (x86 dev) 에서는 no-op, non-Linux (macOS) 는 stub 으로 통과. save_settings() 의 silent EROFS 실패가 TRACE 로 가시화 (이전엔 무시되어 conf 수정 안 먹는 원인 추적 불가). 부수: PortRouter.cpp 가 commit 9bd252f 이후 CMakeLists 의 RPI sources 목록에서 누락되어 Pi 빌드 link 에러 — 추가.
1.18.35 2026-05-01 Added: alarm parsing for Mindray HL7 (eGateway ORU^R40) and Nihon Kohden (NealTime HL7GW + ORF, BSM serial D-port, EGA UDP) - emits ALARM_STATUS / ALARM_MESSAGE / ALARM_PRIORITY tracks (same 3-track schema already used by Philips IntelliVue, GE Solar/Dash, GE/Datex S5); type info preserved via [T]/[A]/[ARR] message prefixes; Mindray facet 1/5/6/7 walker with 92-entry MDC+MNDRY alarm code lookup; NK HL7GW parses OBR-4=EVENT with arrhythmia/technical disambiguation by OBX-5; NK BSM serial decodes per-parameter * flags (edge-triggered to avoid 1Hz flooding) plus 32-bit Table 9 arrhythmia bitmap, D19 alarm-suspend nibble, and the VPC CODE byte; NK EGA UDP extracts Priority + Tech Alarm + Arrhythmia from JSON Vital Sign packets with edge-trigger cache for start/end inference; ACK^R40 reply added for Mindray alert messages; simulators gained periodic alarm cycling for end-to-end smoke testing
1.18.34 2026-04-27 Added: Linux Desktop Qt GUI build (VRQt) - first GUI build for Linux distributed as a self-contained AppImage (~32MB, Qt6 runtime + libGL/libEGL/libGLX/libOpenGL/libGLESv2/libGLdispatch bundled inside) so users on minimal Ubuntu/Debian/Fedora can run it without installing Qt or GL system packages; tested on AWS clean Ubuntu 22.04 cloud image; build via build_ubuntu_appimage.py which is now invoked by deploy.py; Fixed: Linux Qt right-side device/filter panels rendered with white background below cards because the inner listWidget did not autoFillBackground from parent palette on Linux Qt (Windows/macOS implicitly inherit, X11/Wayland do not); explicit stylesheet on listWidget; Added: Linux installation section in user manuals (EN/KO/ZH/ES) covering AppImage chmod+run flow and dialout group note for serial/USB device access
1.18.33 2026-04-25 Fixed: Demo device never started since 1.18.11 (bed_manager skipped empty port_name as passive but Demo has no port and still needs lock_and_open); Fixed: Qt fit-to-window button rendered at top-left (0,0) instead of right-aligned in bottom nav bar; Fixed: Qt crash when closing tab / deleting device / deleting filter - paint dereferenced freed pointer before panel timer rebuilt items (added MFC-style stale-pointer guard to QtDeviceItem and QtFilterItem); Added: macOS DMG main window now shown on launch (restoreWindowPos had no Mac/Linux branch); Added: macOS Homebrew dylibs (openssl) bundled in Contents/Frameworks; Added: macOS .app bundle now notarized + stapled (drag-to-Applications no longer needs xattr -cr on first launch); Changed: Qt MSI ~1MB smaller (dropped unused iconengines and imageformats plugins)
1.18.32 2026-04-23 Fixed: same-port multi-client TCP - primary now runs a continuous accept loop and hands off each connection to the matching sub by IP filter (previously second connection got rejected/listened closed); Added: @IP and #keyword port filters are now mutually exclusive per bed (IP wins, keyword dropped with WARN); Added: WARN log when two beds on the same port share an identical IP filter; Added: catch-all primary keeps its single connection and rejects extras (preserves broadcast mode)
1.18.31 2026-04-22 Added: drug slot shows DOSE_AMOUNT (mg etc) in preference to VOL (mL) when available; Added: DOSE_RATE / DOSE_AMOUNT montypes bound to BBraun tracks for monitor view; Added: HL7 MDC_DOSE_DRUG_DELIV_TOTAL unit picked up dynamically from UCUM
1.18.30 2026-04-21 Changed: monitor view pump layout - 8 slots with CE or RATE (CE-less pumps show infused volume as small annotation); Reverted: BBraun minimal=1 (1.18.29) - was dropping data from file, monitor view redesign handles display clutter instead
1.18.29 2026-04-21 Fixed: BBraun multi-rack auto-tab data drop, primary TCP churn, save_settings lock race, TCP reader spin on peer close; Added: BBraun minimal=1 option (display only drug name / rate / volume)
1.18.28 2026-04-20 Fixed: vr.conf on Pi/Linux now looked up next to executable (supports /boot/firmware); deploy.py --store auto-submits MSIX to Microsoft Store
1.18.27 2026-04-18 Fixed: vital file periodic flush (5000s→5s bug), Fit-to-Window icon redesigned to match navigation button style
1.18.26 2026-04-18 Fixed: periodic .vital file flush interval was 5000 seconds instead of 5 (unit-bug since comment said seconds but value was milliseconds). Data now actually reaches disk every 5 s during recording instead of only on close.
1.18.25 2026-04-18 Fixed: BBraun HL7 rec_timeout raised 10s→60s to prevent primary churn during DoseLink R42→R01 phase transition and long idle periods
1.18.24 2026-04-18 Fixed: GUI silently exits when another recorder running (now falls back to viewer mode), .vital file association written to HKCU (no admin required, auto-updates exe path on every run)
1.18.23 2026-04-18 Fixed: atof decimal-separator bug on non-English Windows locales (rates <1.0 recorded as 0 in Norwegian/German/French etc.), BBraun HL7 pump limit raised from 8 to 16
1.18.22 2026-04-18 Fixed: multi-bed TCP port bind race on restart (Mindray/BBraun HL7 auto-reconnect without manual Add device)
1.18.21 2026-04-18 Fixed: port name filter (#keyword@ip) lost on save, BBraun HL7 VMD-block parsing with single dt, Fit-to-Window button sizing (MFC) and added to Qt
1.18.20 2026-04-15 BBraun: comprehensive protocol parsing (dose rate, infusion time, syringe, weight, drug amounts, delivery status)
1.18.19 2026-04-13 Fixed: BBraun HL7 multi-pump identification (rack serial filtering), multi-bed forwarding, port filter parsing
1.18.18 2026-04-10 Added: GE alarm limits, S5 alarm/ext3/ext1 parsing
1.18.17 2026-04-04 Changed: TRACE debug-only guard, show_msg for file errors, deploy sequential builds
1.18.16 2026-04-04 Added: TCP port filtering (#keyword@ip), frame forwarding for multi-bed. Fixed: --debug conf file mistaken as vital file, device type ambiguity in forwarding
1.18.15 2026-04-04 Changed: Port to Port Name, keyword filter AND/OR (#kw1 kw2#kw3), IP postfix matching (@10.1), MEKICS SerialFramed
1.18.14 2026-04-03 Added: TCP port filtering (#keyword@ip), Fixed: devtypes not sent on boot
1.18.13 2026-04-02 Changed: Covidien company name to Medtronic (BIS, INVOS)
1.18.12 2026-04-02 Bug Fixed: NihonKohden EGA SpO2 waveform not displayed (channel name mapping)
1.18.11 2026-03-31 Added: Mindray HL7 multi-bed separation via PV1, auto-tab creation for EGA/Mindray
1.18.10 2026-03-31 Added: HL7 ZBR segment now includes ver, os, arch, dgmt
1.18.8 2026-03-25 Added: --demo mode for console operation with demo signals
1.18.7 2026-03-25 Added: --console mode for headless operation on Windows
1.18.6 2026-03-25 Added: Mindray eGateway HL7 protocol (IHE PCD-01, HL7 v2.6 over MLLP, waveform + numeric + infusion pump)
1.18.4 2026-03-24 Added: BBraun SpaceCom HL7 protocol (HL7 v2.6 over MLLP, TCP server mode)
1.18.3 2026-03-24 Added: HL7 OBX-14 per-track dtstart, ZBR segment with dtcase/dtapp timestamps
1.18.2 2026-03-24 Added: HL7 ZBR segment with dtcase (recording start) and dtapp (app start) timestamps
1.18.1 2026-03-23 Fixed: HL7 OBX-3 format (code^device/track@srate), OBX-7 refrange (min^max), NA null sample gaps
1.17.6 2026-03-22 Bug fixed: Resource ID conflicts WiX installer cleanup
1.17.5 2026-03-21 Bug fixed: Vital packed file loading MFC device button icon padding
1.17.4 2026-03-19 Bug fixed: NirsitON EEG 250Hz VRQt device minimize/rename
1.17.3 2026-03-18 Bug fixed: BBraun protocol NirsitON protocol VRQt
1.17.2 2026-03-14 Added: NirsitOn NDI protocol support.
1.17.1 2026-03-12 Added: VRQt
1.16.13 2026-03-07 Added: New Setup File with VRQt
1.16.12 2026-03-06 Added: Vector Type Icons
1.16.10 2026-03-02 Bug fixed: Autodetecting BBraun Stuffing feature.
1.16.8 2026-02-27 Bug fixed: Masimo IAP protocol.
1.16.6 2026-02-13 Added: Servo-u ventilator protocol
1.16.5 2026-02-09 Bug Fixed: NihonKohden HL7GW Pleth waveform gain correction.
1.16.4 2026-01-20 Bug Fixed: Serial communication.
1.16.3 2026-01-14 Bug Fixed: Masimo IAP Protocol.
1.16.2 2026-01-03 Added: BLE Support for Movesense devices on Raspberry Pi
1.16.1 2026-01-01 Added: BLE Support for Movesense devices on Raspberry Pi and Linux versions.
1.16.0 2025-12-31 Added: BLE Support for Movesense devices
1.15.16 2025-09-18 Bug Fixed: Restoring last window position.
1.15.15 2025-09-05 Added: CPU optimization Bug fixed: Masimo IAP protocol.
1.15.14 2025-09-04 Added: CPU optimization
1.15.13 2025-09-04 Bug Fixed: Masimo IAP Protocol.
1.15.12 2025-09-04 Bug Fixed: Hardware handshake for Link+ connection.
1.15.11 2025-09-01 Added: Recording alarm messages for Drager anesthesia machines
1.15.10 2025-07-14 Bug Fixed: Sampling rate estimation in Medibus protocol.
1.15.9 2025-06-03 Bug Fixed: EEG waveform labels from Philips monitors.
1.15.8 2025-05-26 Added: EM_UPLOAD option to upload vital files to server immediately
1.15.7 2025-05-26 Bug Fixed: Websocket connection error
1.15.6 2025-05-19 Bug Fixed: S5 checksum error
1.15.5 2025-04-17 Bug Fixed: saving the raw data
1.15.4 2025-04-15 Added: Recording alarms from Philips monitor
1.15.3 2025-04-14 Bug fixed: saving the raw data
1.15.2 2025-03-12 Fixed: bug in opening file
1.15.1 2025-01-30 Supporting for Fresenius Kabi Conox, Minor Bug fixes
1.14.13 2025-01-18 Fixed bug in handling non-ascii filepath
1.14.12 2024-11-20 Fixed: bug in 64bit ARM Architecture
1.14.11 2024-10-24 Added: feature for updating to a specific version
1.14.10 2024-10-22 Fixed: bug in json streamming
1.14.9 2024-10-17 Added: montype for drug rates
1.14.6 2024-09-20 Added: montype for drug rates
1.14.5 2024-09-13 Added: auto cutting by any of hr or spo2
1.14.4 2024-09-12 Fixed: bug in serial port mapping
1.14.3 2024-09-10 Added: temperature monitoring Fixed: bug in cpu usage calculation
1.14.2 2024-08-29 Added: DI-245 protocol
1.14.1 2024-07-26 Added: GE cardiac output parameters
1.14.0 2024-07-25 Added: GE Canvas device
1.13.10 2024-07-17 Fixed: NirsitOn protocol bug
1.13.9 2024-06-27 Bug fix for file loading
1.13.8 2024-06-05 Bug fix for file loading
1.13.7 2024-06-04 Bug fix for file loading
1.13.6 2024-06-03 Bug fix for the NirsitOn+ protocols with 32Hz
1.13.5 2024-05-30 Added support for the NirsitOn+ protocols with 32Hz
1.13.4 2024-05-23 Added fetal heart rate and uterine activity
1.13.3 2024-05-23 Tested for BIS vista protocol
1.13.2 2024-04-26 Support for BIS vista protocol
1.13.1 2024-04-26 Support for BIS vista protocol
1.12.12 2024-04-09 Deployment script updated
1.12.11 2024-04-06 Deployment script updated
1.12.10 2024-02-25 Deployment script updated
1.12.8.0 2024-02-25 Added support for GE Coro fetal monitor
1.12.8 2024-02-25 Added support for GE Coro fetal monitor
1.12.7.0 2024-02-24 Added support for GE Coro fetal monitor
1.12.6.0 2024-01-05 Minor bug fix
1.12.5.0 2023-12-22 Minor bug fix
1.12.4.0 2023-12-22 Minor bug fix Added support of Pleth(Left, Right) and Aortic pressure for the Intellivue protocol Added option for the cut by heart rate Added option for setting the waveform by its name - Intellivue: I, II, III, V, aVR, aVL, avF, MCL, MCL1, V1, V2, V3, V4, V5, V6, PLETH, ABP, ART, CVP, FAP, PAP, ICP, EEG, CO2, RESP, AWF, AWP - S5: ECG1, ECG2, EEGBIS, EEGENT, EEGENT400, IABP1, IABP2, IABP3, IABP4, IABP5, IABP6, IABP7, IABP8, EEG1, EEG2, PLETH, CO2, O2, N2O, AWP
1.12.1.0 2023-12-11 Minor bug fixes Improvement of the Bx50 protocol Improvement of the NIHONKOHDEN protocol
1.12.0.0 2023-12-05 Supported protocol for Drager B1x5M.
1.11.20.0 2023-11-07 Supported protocol for Daiwha TCI pump.
1.11.19.0 2023-10-23 Additional pleth waveforms for the Philips protocol Minor Bug fixes
1.11.18.0 2023-09-14 Bug fix for EGA protocol Minor Bug fixes
1.11.17.0 2023-09-08 Bug fix for EGA protocol
1.11.16.0 2023-08-30 Bug fix for EGA protocol
1.11.15.0 2023-08-29 Bug fix for EGA protocol
1.11.14.0 2023-08-29 Bug fix for EGA protocol
1.11.13.0 2023-08-28 Bug fix for EGA protocol
1.11.12.0 2023-08-08 EGA protocol supported PulsioFlex protocol supported
1.11.11.0 2023-07-12 Fixed bug for TOFCuff
1.11.10.0 2023-06-01 Fixed bug for VitalConnect
1.11.9.0 2023-05-30 Fixed bug for BUTTON
1.11.8.0 2023-05-27 Fixed bug for MEKICS Fixed bug for remote update
1.11.7.0 2023-05-24 Added support for NirsitOn+
1.11.6.0 2023-05-23 Added support for NirsitOn+
1.11.5.0 2023-05-22 Added support for NirsitOn+
1.11.4.0 2023-05-22 Added support for NirsitOn+
1.11.3.0 2023-05-21 Added support for SNUSensor
1.11.2.0 2023-05-16 Added support for SNUSensor
1.11.1.0 2023-05-03 Added support for TOFcuff
1.11.0.0 2023-03-29 Added support for TOFcuff
1.10.21.0 2023-02-16 Added support for TOFcuff
1.10.20.0 2023-02-05 Added support for file cutting based on SpO2
1.10.19.0 2023-01-12 Added support for file cutting based on SpO2
1.10.18.0 2022-12-16 Added support for AU protocol
1.10.17.0 2022-12-16 Added support for AU protocol
1.10.16.0 2022-12-14 Added support for AU protocol
1.10.15.0 2022-12-12 Added support for AU protocol
1.10.14.0 2022-12-08 Added support for AU protocol
1.10.13.0 2022-12-07 Added support for AU protocol
1.10.12.0 2022-12-05 Added support for AU protocol
1.10.11.0 2022-12-05 Added support for AU protocol
1.10.10.0 2022-12-02 Added support for AU protocol
1.10.9.0 2022-12-01 Fixed bug for Link+ protocol
1.10.8.0 2022-11-29 Fixed bug for Servo-i Ventilator Fixed bug for Hamilton Ventilator
1.10.7.0 2022-11-08 Improved support for Nihon kohden ADT
1.10.6.0 2022-11-04 Improved support for Nihon kohden HL7GW
1.10.4.0 2022-11-02 Hamiltonian ventilator supported
1.10.3.0 2022-10-21 Hamiltonian ventilator supported
1.10.2.0 2022-10-14 Hamiltonian ventilator supported
1.10.0.0 2022-09-15 Minor bug fix Added input dialog for patient ID when intranet server is used
1.9.11.0 2022-07-29 Minor bug fix Added input dialog for patient ID when intranet server is used
1.9.10.0 2022-06-26 Minor bug fix Added input dialog for patient ID when intranet server is used
1.9.9.0 2022-06-03 Minor bug fix Added input dialog for patient ID when intranet server is used
1.9.8.0 2022-05-17 Minor bug fix VitalSync compatible with VitalDB Platform API
1.9.7.0 2022-03-25 Display patient id on the title bar Support for barcode reader Minor bug fix
1.9.6.0 2022-03-25 Additional Parameter (RPVI) for Masimo Root Bug fix for VitlaUtils
1.9.4.0 2022-03-10 Batch running of filter on VitalUtils
1.9.3.0 2022-03-09 Local filter server as default Python Installer
1.9.2.0 2022-02-17 Added ABP montype to ClearSight
1.9.1.0 2022-02-16 Supported MedibusX protocol
1.9.0.0 2022-02-14 Supported LiDCO protocol
1.8.22.0 2022-02-10 Added filter server running on localhost Moved VC setting dialog to the Setting dialog Fixed minor bugs
1.8.21.1 2022-02-07 Fixed a bug with the Intellivue
1.8.21.0 2022-01-21 Fixed a bug with the Intellivue
1.8.20.1 2022-01-15 Fixed a bug with the Intellivue
1.8.20.0 2022-01-13 Requesting O2 and N2O waves to the Bx50. Fixed a bug with the channel names of FIO2 and FIO2 of the Bx50.
1.8.19.5 2021-12-17 Bug fix for Intellivue protorol
1.8.19.4 2021-12-09 Bug fix for Intellivue protorol
1.8.19.0 2021-11-15 Bug fix for Intellivue protorol
1.8.18.0 2021-10-09 New Installer
1.8.17.2 2021-10-06 New Installer
Version Date Changes
1.18.40 2026-05-12 Hotfix: Drager Medibus 프로토콜 사용 베드에서 1.15.11 이후 vr.service 가 SIGSEGV 로 무한 재시작하던 문제. 1.15.10 (a8c7b2a) 의 "Sampling rate estimation" 리팩터링이 m_ptrk_awp/awf/co2 트랙을 add_trks() 에서의 eager 생성 (default srate=62.5Hz) 에서 realtime data 100 샘플 모인 후 lazy 생성으로 바꿨는데, Medibus 핸드셰이크 순서 (0x51 ICC → 0x52 DeviceID → 0x53 RealtimeConfig 응답 → 0x54 → realtime data 시작) 상 0x53 응답 핸들러 (Drager.cpp:295-307) 가 트랙들이 아직 nullptr 인 시점에 `ptrk->m_srate = 1000000.0/interval` 로 NULL 역참조 → 즉시 SEGV. 그 베드의 vr.service 가 systemd Restart=on-failure 로 재시작 → 다시 connect → 동일 0x53 패킷 받고 동일 SEGV → 무한 루프 (journald 로그상 restart counter 61 까지 누적, code=killed status=11/SEGV). 1.15.9 까진 트랙이 add_trks() 에서 생성되어 0x53 도착 시 항상 non-NULL 이라 안전했음. 수정: (a) add_trks() 에서 m_ptrk_awp/awf/co2 eager 생성 복원 (srate=62.5Hz default) — 0x53 는 ptrk->m_srate 만 갱신 (트랙 재생성 X). (b) on_received() 의 lazy creation + packet-timing srate 추정 블록 제거 — 0x53 가 권위 있는 srate 소스이고 packet 타이밍 기반 추정은 network jitter 에 약해 불안정. (c) 0x53 핸들러에 `if (interval > 0)` guard 추가 — 페이로드 깨졌을 때 div-by-zero / inf srate 방지. 영향 범위: Drager Primus / Apollo / Perseus / Fabius 등 Medibus 사용 마취기 전부. 우회 방법은 1.15.9 다운그레이드 외엔 없었음 (그 베드의 모든 데이터 유실 + 환자 모니터링 불가). MFC + Qt + Pi (RPI64) + Ubuntu Qt + AppImage 빌드 모두 통과.
1.18.37 2026-05-08 Refactored: 필터 다이얼로그의 python 런타임 — pyvital → openvital 0.3.0 로 교체 + 동봉 python.zip 슬림화. 핵심 동기 셋: (1) pyvital 0.6.0 이 tensorflow+torch+keras 를 hard-dep 으로 끌어들여 PyPI upgrade 가 사실상 깨짐, (2) 기존 zip 121 MB 안에 botocore/aiobotocore/s3fs/pyarrow/pandas/aiohttp 등 vitaldb 클라우드 업로드용 deps 가 ~250 MB unpacked 차지 — 필터 서버는 한 번도 쓴 적 없는 dead weight, (3) sanic 25.x 의 multi-process worker 가 openvital __main__.py 를 fork 후 재import 하면서 worker 가 module-top app instance 를 못 찾아 "Sanic app name not found" 로 죽음 — 단순 endpoint 2개 로컬호스트 서버에 async stack 자체가 과함. 해결: openvital 0.3.0 (commit b6f445b) 가 sanic 을 stdlib http.server (BaseHTTPRequestHandler + HTTPServer) 로 50 LOC 재작성 — wire protocol (GET / 필터목록 JSON, POST /<modname> gzip 본문) 동일해 VR 클라이언트 변경 0줄. 단일 스레드로 기존 sanic event loop semantics (cfgs/default_cfgs lock-free 변경) 보존. build_python_zip.py (NEW) 가 Python 3.11.9 embed + numpy + openecg + openvital (local checkout 우선, fallback PyPI) 만으로 27 MB zip 빌드 — 기존 121 MB 대비 78% 감소. ML 필터 (sv_dlapco/abp_hpi/ecg_classifier/ecg_beat_noise_detector) 는 [Hybrid 모델] 사용자가 Add filter 다이얼로그의 "Install ML filters" 버튼 누를 때 silent pip install openvital[all] (cmd 창 미노출 — VRApp::install_pip_package + run_pip_silent 이 자체 progress 다이얼로그에 stdout heartbeat 흘림). 버튼 라벨은 "Upgrade pyvital" → "Install ML filters" 로 의도 명시. openvital __main__.py 가 missing extras 를 graceful skip 하므로 base 환경에서도 11개 필터 (ECG QRS detector, HRV, MTWA, annotator, eeg_fft, nirs_cox, pkpd_3comp, pleth_dpop/ptt/pvi, resp_compliance) 즉시 사용 가능. Migration: 기존 사용자의 user_dir/python 폴더는 pyvital + 옛 deps 가 그대로 남아있고 vitaldb.net/python.zip 만 새로 올리면 (a) 기존 폴더 삭제 후 install_python 으로 새 zip 받으면 깔끔, (b) 폴더 유지 시 server 가 openvital 못 찾아 필터 다이얼로그 에러 → release note 에 명시 필요. MFC + Qt 양쪽 코드: VRGui.rc 의 IDC_UPGRADE 버튼 라벨 + DlgAddFilter.cpp 의 dist-info prefix 매칭 (pyvital- 8자 → openvital- 10자) + QtDlgAddFilter.cpp 도 동일 변경 + onUpgrade 가 cmd /k QProcess::startDetached 대신 theApp.install_pip_package("openvital[all]") 호출 (Linux Qt 빌드는 #ifdef _WIN32 가드). VRApp.cpp:318 의 python -m pyvital → -m openvital. install_pip_package 는 anonymous namespace 의 is_safe_pkg_spec 화이트리스트 검증 + run_pip_silent (CreateProcessA + CREATE_NO_WINDOW + 자식 stdout pipe) + CDlgProgress / QtDlgProgress 자체 progress UI. 빌드 검증: python -m openvital 이 GET / 로 11 필터 반환, sanic import 부재 확인. zip 27.5 MB.
1.18.33 2026-04-25 Fixed: Demo device never started since 1.18.11 (bed_manager skipped empty port_name as passive but Demo has no port and still needs lock_and_open); Fixed: Qt fit-to-window button rendered at top-left (0,0) instead of right-aligned in bottom nav bar; Fixed: Qt crash when closing tab / deleting device / deleting filter - paint dereferenced freed pointer before panel timer rebuilt items (added MFC-style stale-pointer guard to QtDeviceItem and QtFilterItem); Added: macOS DMG main window now shown on launch (restoreWindowPos had no Mac/Linux branch); Added: macOS Homebrew dylibs (openssl) bundled in Contents/Frameworks; Added: macOS .app bundle now notarized + stapled (drag-to-Applications no longer needs xattr -cr on first launch); Changed: Qt MSI ~1MB smaller (dropped unused iconengines and imageformats plugins)
1.18.31 2026-04-22 Added: drug slot shows DOSE_AMOUNT (mg etc) in preference to VOL (mL) when available; Added: DOSE_RATE / DOSE_AMOUNT montypes bound to BBraun tracks for monitor view; Added: HL7 MDC_DOSE_DRUG_DELIV_TOTAL unit picked up dynamically from UCUM
Version Date Changes
1.15.10 2025-07-14 Bug Fixed: Sampling rate estimation in Medibus protocol.
1.15.9 2025-06-03 Bug Fixed: EEG waveform labels from Philips monitors.
1.15.8 2025-05-26 Added: EM_UPLOAD option to upload vital files to server immediately
1.15.7 2025-05-26 Bug Fixed: Websocket connection error
1.15.6 2025-05-19 Bug Fixed: S5 checksum error
1.15.5 2025-04-17 Bug Fixed: saving the raw data
1.15.4 2025-04-15 Added: Recording alarms from Philips monitor
1.15.3 2025-04-14 Bug fixed: saving the raw data
1.15.2 2025-03-12 Fixed: bug in opening file
1.15.1 2025-01-30 Supporting for Fresenius Kabi Conox, Minor Bug fixes
1.14.13 2025-01-18 Fixed bug in handling non-ascii filepath
1.14.12 2024-11-20 Fixed: bug in 64bit ARM Architecture
1.14.11 2024-10-24 Added: feature for updating to a specific version
1.14.10 2024-10-22 Fixed: bug in json streamming
1.14.9 2024-10-17 Added: montype for drug rates
1.14.6 2024-09-20 Added: montype for drug rates
1.14.5 2024-09-13 Added: auto cutting by any of hr or spo2
1.14.4 2024-09-12 Fixed: bug in serial port mapping
1.14.3 2024-09-10 Added: temperature monitoring Fixed: bug in cpu usage calculation
1.14.2 2024-08-29 Added: DI-245 protocol
1.14.1 2024-07-26 Added: GE cardiac output parameters
1.14.0 2024-07-25 Added: GE Canvas device
1.13.10 2024-07-17 Fixed: NirsitOn protocol bug
1.13.9 2024-06-27 Bug fix for file loading
1.13.8 2024-06-05 Bug fix for file loading
1.13.7 2024-06-04 Bug fix for file loading
1.13.6 2024-06-03 Bug fix for the NirsitOn+ protocols with 32Hz
1.13.5 2024-05-30 Added support for the NirsitOn+ protocols with 32Hz
1.13.4 2024-05-23 Added fetal heart rate and uterine activity
1.13.3 2024-05-23 Tested for BIS vista protocol
1.13.2 2024-04-26 Support for BIS vista protocol
1.13.1 2024-04-26 Support for BIS vista protocol
1.12.12 2024-04-09 Deployment script updated
1.12.11 2024-04-06 Deployment script updated
1.12.10 2024-02-25 Deployment script updated
1.12.8 2024-02-25 Added support for GE Coro fetal monitor
1.12.7.0 2024-02-24 Added support for GE Coro fetal monitor
1.12.6.0 2024-01-05 Minor bug fix
1.12.5.0 2023-12-22 Minor bug fix
1.12.4.0 2023-12-22 Minor bug fix Added support of Pleth(Left, Right) and Aortic pressure for the Intellivue protocol Added option for the cut by heart rate Added option for setting the waveform by its name - Intellivue: I, II, III, V, aVR, aVL, avF, MCL, MCL1, V1, V2, V3, V4, V5, V6, PLETH, ABP, ART, CVP, FAP, PAP, ICP, EEG, CO2, RESP, AWF, AWP - S5: ECG1, ECG2, EEGBIS, EEGENT, EEGENT400, IABP1, IABP2, IABP3, IABP4, IABP5, IABP6, IABP7, IABP8, EEG1, EEG2, PLETH, CO2, O2, N2O, AWP
1.12.3.0 2023-12-12 Minor bug fixes Improvement of the Bx50 protocol Improvement of the NIHONKOHDEN protocol
1.12.2.0 2023-12-11 Minor bug fixes Improvement of the Bx50 protocol Improvement of the NIHONKOHDEN protocol
1.12.1.0 2023-12-11 Minor bug fixes Improvement of the Bx50 protocol Improvement of the NIHONKOHDEN protocol
1.12.0.0 2023-12-05 Supported protocol for Drager B1x5M.
1.11.20.0 2023-11-07 Supported protocol for Daiwha TCI pump.
1.11.18.0 2023-09-14 Bug fix for EGA protocol Minor Bug fixes
1.11.17.0 2023-09-08 Bug fix for EGA protocol
1.11.11.0 2023-07-12 Fixed bug for TOFCuff
1.11.10.0 2023-06-01 Fixed bug for VitalConnect
1.11.9.0 2023-05-30 Fixed bug for BUTTON
1.11.8.0 2023-05-27 Fixed bug for MEKICS Fixed bug for remote update
1.11.7.0 2023-05-24 Added support for NirsitOn+
1.11.6.0 2023-05-23 Added support for NirsitOn+
1.11.4.0 2023-05-22 Added support for NirsitOn+
1.11.3.0 2023-05-21 Added support for SNUSensor
1.11.1.0 2023-05-03 Added support for TOFcuff
1.10.19.0 2023-01-12 Added support for file cutting based on SpO2
1.10.17.0 2022-12-16 Added support for AU protocol
1.10.15.0 2022-12-12 Added support for AU protocol
1.10.13.0 2022-12-07 Added support for AU protocol
1.10.11.0 2022-12-05 Added support for AU protocol
1.10.10.0 2022-12-02 Added support for AU protocol
1.10.9.0 2022-12-01 Fixed bug for Link+ protocol
1.10.8.0 2022-11-29 Fixed bug for Servo-i Ventilator Fixed bug for Hamilton Ventilator
1.10.7.0 2022-11-08 Improved support for Nihon kohden ADT
1.10.6.0 2022-11-04 Improved support for Nihon kohden HL7GW
1.10.4.0 2022-11-02 Hamiltonian ventilator supported
1.10.3.0 2022-10-21 Hamiltonian ventilator supported
1.10.2.0 2022-10-14 Hamiltonian ventilator supported
1.10.1.0 2022-10-07 Minor bug fix Added input dialog for patient ID when intranet server is used
1.10.0.0 2022-09-15 Minor bug fix Added input dialog for patient ID when intranet server is used
1.9.11.0 2022-07-29 Minor bug fix Added input dialog for patient ID when intranet server is used
1.9.10.0 2022-06-26 Minor bug fix Added input dialog for patient ID when intranet server is used
1.9.8.0 2022-05-17 Minor bug fix VitalSync compatible with VitalDB Platform API
1.9.7.0 2022-03-25 Display patient id on the title bar Support for barcode reader Minor bug fix
1.9.6.0 2022-03-25 Additional Parameter (RPVI) for Masimo Root Bug fix for VitlaUtils
1.9.2.0 2022-02-17 Added ABP montype to ClearSight
1.9.1.0 2022-02-16 Supported MedibusX protocol
1.9.0.0 2022-02-14 Supported LiDCO protocol
1.8.22.0 2022-02-10 Added filter server running on localhost Moved VC setting dialog to the Setting dialog Fixed minor bugs
1.8.21.1 2022-02-07 Fixed a bug with the Intellivue
1.8.21.0 2022-01-21 Fixed a bug with the Intellivue
1.8.20.1 2022-01-15 Fixed a bug with the Intellivue
1.8.20.0 2022-01-13 Requesting O2 and N2O waves to the Bx50. Fixed a bug with the channel names of FIO2 and FIO2 of the Bx50.
1.8.19.6 2021-12-24 ADT_SERVER_IP
1.8.19.5 2021-12-17 Bug fix for Intellivue protorol
Version Date Changes
1.18.41 2026-05-13 1.18.41 Hotfix: TCP-server protocol-initiator device (Intellivue/S5/Datex/Hamilton/MPS/Agilia/IAP) 가 open() 직후 보내는 첫 패킷이 wire 에 안 나가던 회귀. 1.18.34 의 PortRouter refactor 가 Serial::open_socket() 의 8초 handoff blocking 을 제거하고 비동기 모델로 전환했는데, protocol-initiator 의 open() 코드가 m_sock=INVALID 상태에서 write 를 시도해 silent fail (Linux 는 m_fd=0 이라 false 반환). Intellivue 케이스 production journald 의 Pi → ESP TX 700K~3M bytes 는 monitor 측 abort 로 늦게 트리거된 AB_SPDU_SI recovery assoc_req 후 request_thread 의 정상 polling 트래픽이지만 일부 베드 (abort 없는 monitor) 는 recovery 도 안 되어 영구 silent (RX 300 bytes). 수정 방향: open() 의 옛 contract ("return 시점에 통신 가능") 복구. (1) Serial::open_socket() TCP-server 분기가 PortRouter::subscribe 후 m_sock_cv 로 첫 client handoff 까지 block (timeout = device read_timeout, 기본 30s) — 옛 모델 그대로. lock_and_open 이 false 면 다음 tick 에서 retry. close 신호로 abort 가능. (2) Serial::close() 는 PortRouter::unsubscribe 안 함 — subscribe 는 device 생애 동안 sticky 라 read_timeout 으로 인한 close→re-open 사이클 동안 listen socket 이 유지되어 1.18.29/1.18.34 의 anti-churn 이익 보존. unsubscribe 는 ~Serial() 에서만. (3) Per-device lifecycle thread (DEVICE::m_thread_restart): 각 device 가 자기 open/close/timeout 재시작을 별도 thread 에서 관리. 옛 모델의 DISPLAY::bed_manager 가 베드의 모든 device 를 sequential iterate 하던 구조에선 한 device 의 blocking open() 이 같은 베드의 다른 device 의 lifecycle 을 차단했는데, per-device thread 로 분리하여 멀티 device 베드도 병렬 진행. add_dev 에서 start_lifecycle, del_dev / ~DISPLAY 에서 stop_lifecycle. (4) Serial::tcp_thread_func 단순화 — outer m_sock_cv wait 패턴 (1.18.34/1.18.39 가 추가했던 것) 제거. open_socket 이 m_sock valid 보장하므로 reader thread 시작 시점에 simple inner recv loop 만. accept_handoff 의 replace (zombie cleanup) 케이스는 recv error 후 m_sock 변경 확인 + retry 로 처리. (5) reading_thread_func 의 `else if (m_sock != INVALID_SOCKET) tcp_thread_func();` 가드 복원 (1.18.39 가 제거). (6) Serial::write 의 silent-fail 케이스에 WARN trace 추가 — 미래 동종 회귀 즉시 노출. (7) PortRouter::subscribe 가 같은 (port, type) 에서 같은 IP filter 또는 둘 이상 catch-all 발견 시 reject (config 실수 원천 차단, 옛 WARN-only 동작 강화). (8) DISPLAY::bed_manager_thread_func 의 restart 블록 제거 — ptcon + adt 만 담당. "Waiting for next patient" TRACE 가 Linux/console 에서 1초 → 60초마다 throttle (별개 journald 부풀림 fix). 영향 범위: Intellivue / S5 / Datex / Hamilton / MPS / Agilia / IAP TCP-server 모드 베드 전부. 1.18.34 이후 우회 방법은 race-win 케이스 (VRN 이 PortRouter::subscribe 직후 connect) 외엔 없었음. MFC + Qt + Pi (RPI64) + Ubuntu Qt + AppImage 빌드 모두 통과.
1.18.40 2026-05-12 Hotfix: Drager Medibus 프로토콜 사용 베드에서 1.15.11 이후 vr.service 가 SIGSEGV 로 무한 재시작하던 문제. 1.15.10 (a8c7b2a) 의 "Sampling rate estimation" 리팩터링이 m_ptrk_awp/awf/co2 트랙을 add_trks() 에서의 eager 생성 (default srate=62.5Hz) 에서 realtime data 100 샘플 모인 후 lazy 생성으로 바꿨는데, Medibus 핸드셰이크 순서 (0x51 ICC → 0x52 DeviceID → 0x53 RealtimeConfig 응답 → 0x54 → realtime data 시작) 상 0x53 응답 핸들러 (Drager.cpp:295-307) 가 트랙들이 아직 nullptr 인 시점에 `ptrk->m_srate = 1000000.0/interval` 로 NULL 역참조 → 즉시 SEGV. 그 베드의 vr.service 가 systemd Restart=on-failure 로 재시작 → 다시 connect → 동일 0x53 패킷 받고 동일 SEGV → 무한 루프 (journald 로그상 restart counter 61 까지 누적, code=killed status=11/SEGV). 1.15.9 까진 트랙이 add_trks() 에서 생성되어 0x53 도착 시 항상 non-NULL 이라 안전했음. 수정: (a) add_trks() 에서 m_ptrk_awp/awf/co2 eager 생성 복원 (srate=62.5Hz default) — 0x53 는 ptrk->m_srate 만 갱신 (트랙 재생성 X). (b) on_received() 의 lazy creation + packet-timing srate 추정 블록 제거 — 0x53 가 권위 있는 srate 소스이고 packet 타이밍 기반 추정은 network jitter 에 약해 불안정. (c) 0x53 핸들러에 `if (interval > 0)` guard 추가 — 페이로드 깨졌을 때 div-by-zero / inf srate 방지. 영향 범위: Drager Primus / Apollo / Perseus / Fabius 등 Medibus 사용 마취기 전부. 우회 방법은 1.15.9 다운그레이드 외엔 없었음 (그 베드의 모든 데이터 유실 + 환자 모니터링 불가). MFC + Qt + Pi (RPI64) + Ubuntu Qt + AppImage 빌드 모두 통과.
1.18.39 2026-05-08 Fixed: PortRouter (TCP server) 모드에서 reader thread 가 startup 시점에 죽어 client 데이터를 영구히 못 받던 문제. 1.18.34 (9bd252f) 의 PortRouter refactor 가 m_sock 세팅을 dispatch 시점으로 옮겼는데 reading_thread_func (Serial.cpp:354) 의 가드 `else if (m_sock != INVALID_SOCKET) tcp_thread_func();` 는 옛 모델 (open 시점 이미 connect 완료) 가정 그대로라 — 시작 직후 m_sock=INVALID 면 tcp_thread_func 진입 안 하고 reader thread 즉시 종료. 이후 VRN 이 connect → PortRouter::dispatch → accept_handoff 가 m_sock 채우고 m_sock_cv.notify_all() → 그러나 wait 중인 reader 가 없음 (이미 죽음) → kernel recv buffer 에만 데이터 적재. 증상은 ss -tn state established 의 Recv-Q 가 0 이 아닌 값 (수백 bytes) 으로 누적, 베드 화면에는 데이터 안 들어옴. 그 베드의 VRN 이 Serial::open() 의 PortRouter::subscribe 직후~reader thread spawn 사이의 짧은 윈도우 안에 connect 한 경우만 우연히 정상 동작 (race-win). 수정: 가드 제거 — TCP 분기에 항상 진입. tcp_thread_func 자체에 이미 m_sock_cv outer-wait 루프가 있어 m_sock 이 INVALID 인 동안 dispatch 가 깨워줄 때까지 안전하게 대기. Pi 핫스팟에 VRN 여러 대 (e.g. 10.42.0.21~25) 를 같은 (4343, Philips:Intellivue) 키로 묶고 IP filter 로 라우팅하는 시나리오에서 가장 자주 노출. Added: 진단 로그 보강 — PortRouter::accept_loop 의 accept 이벤트, dispatch 의 라우팅 결정 (ip_specific/catch_all subs 수, 어느 dev 가 받았는지), subscribe/unsubscribe 의 entry 생성/append/destroy, reading_thread / tcp_thread 의 시작·wait·wake 라이프사이클 — 이전엔 모두 m_bDebug 게이트 안에 있어서 production journald 에서 안 보였는데, 이제 항상 출력 (이번 같은 dispatch routing 문제 진단을 production 에서 바로 가능). MFC + Qt + Pi (RPI64) + Ubuntu Qt + AppImage 빌드 모두 통과.
1.18.38 2026-05-08 Fixed: 웹모니터링 우클릭 → 디바이스 세팅 (websocket edit_bed 명령) 으로 베드의 device/filter 를 변경할 때 베드 이름이 매번 "_2" suffix 로 자동 리네임되어 vr.conf (Pi: /data/vr.conf) 에 잘못된 이름으로 저장되던 문제. 원인은 1.18.22 (cda8aa5) 에서 add_bed 에 추가된 bedname dedup ("최후 방어선" 으로 forward_frame auto-create / 수동 편집된 conf 의 중복 이름 처리용). edit_bed 핸들러는 옛 pdel 이 m_pdisps 에 그대로 있는 상태에서 같은 bedname 으로 new DISPLAY 를 add_bed 하고 그 다음 del_bed(pdel) 하는 순서였는데, add_bed 가 dup 감지해 새 pdisp 를 bedname_2 로 자동 리네임 → save_settings 가 [BED/bedname_2] 로 직렬화 → 사용자 입장에선 "설정 적용 안됨" 으로 보였다. 추가로 옛/새 DISPLAY 가 잠깐 m_pdisps 에 공존하면서 같은 device 포트를 동시에 들고 있으려 해 로그가 dup 으로 찍히는 부수 증상도 있었음. 수정: del_bed(pdel) 를 add_bed(pdisp) 보다 앞으로 이동 — 옛 베드의 device 포트가 깨끗이 release 된 뒤 새 pdisp 가 같은 포트를 reopen, dedup 발동 안 함. 다른 베드의 recording 은 영향 없음 (인메모리 hot swap 설계 유지). 부수: edit_bed 핸들러의 데드 코드 (`break` 뒤의 unreachable olddevs populate 루프 + `if (olddevs.find(name) == olddevs.end())` 항상-true 래퍼) 정리. edit_conf 와 save_settings 는 손대지 않음. MFC + Qt + Pi (RPI64) 빌드 모두 통과.
1.18.37 2026-05-08 Refactored: 필터 다이얼로그의 python 런타임 — pyvital → openvital 0.3.0 로 교체 + 동봉 python.zip 슬림화. 핵심 동기 셋: (1) pyvital 0.6.0 이 tensorflow+torch+keras 를 hard-dep 으로 끌어들여 PyPI upgrade 가 사실상 깨짐, (2) 기존 zip 121 MB 안에 botocore/aiobotocore/s3fs/pyarrow/pandas/aiohttp 등 vitaldb 클라우드 업로드용 deps 가 ~250 MB unpacked 차지 — 필터 서버는 한 번도 쓴 적 없는 dead weight, (3) sanic 25.x 의 multi-process worker 가 openvital __main__.py 를 fork 후 재import 하면서 worker 가 module-top app instance 를 못 찾아 "Sanic app name not found" 로 죽음 — 단순 endpoint 2개 로컬호스트 서버에 async stack 자체가 과함. 해결: openvital 0.3.0 (commit b6f445b) 가 sanic 을 stdlib http.server (BaseHTTPRequestHandler + HTTPServer) 로 50 LOC 재작성 — wire protocol (GET / 필터목록 JSON, POST /<modname> gzip 본문) 동일해 VR 클라이언트 변경 0줄. 단일 스레드로 기존 sanic event loop semantics (cfgs/default_cfgs lock-free 변경) 보존. build_python_zip.py (NEW) 가 Python 3.11.9 embed + numpy + openecg + openvital (local checkout 우선, fallback PyPI) 만으로 27 MB zip 빌드 — 기존 121 MB 대비 78% 감소. ML 필터 (sv_dlapco/abp_hpi/ecg_classifier/ecg_beat_noise_detector) 는 [Hybrid 모델] 사용자가 Add filter 다이얼로그의 "Install ML filters" 버튼 누를 때 silent pip install openvital[all] (cmd 창 미노출 — VRApp::install_pip_package + run_pip_silent 이 자체 progress 다이얼로그에 stdout heartbeat 흘림). 버튼 라벨은 "Upgrade pyvital" → "Install ML filters" 로 의도 명시. openvital __main__.py 가 missing extras 를 graceful skip 하므로 base 환경에서도 11개 필터 (ECG QRS detector, HRV, MTWA, annotator, eeg_fft, nirs_cox, pkpd_3comp, pleth_dpop/ptt/pvi, resp_compliance) 즉시 사용 가능. Migration: 기존 사용자의 user_dir/python 폴더는 pyvital + 옛 deps 가 그대로 남아있고 vitaldb.net/python.zip 만 새로 올리면 (a) 기존 폴더 삭제 후 install_python 으로 새 zip 받으면 깔끔, (b) 폴더 유지 시 server 가 openvital 못 찾아 필터 다이얼로그 에러 → release note 에 명시 필요. MFC + Qt 양쪽 코드: VRGui.rc 의 IDC_UPGRADE 버튼 라벨 + DlgAddFilter.cpp 의 dist-info prefix 매칭 (pyvital- 8자 → openvital- 10자) + QtDlgAddFilter.cpp 도 동일 변경 + onUpgrade 가 cmd /k QProcess::startDetached 대신 theApp.install_pip_package("openvital[all]") 호출 (Linux Qt 빌드는 #ifdef _WIN32 가드). VRApp.cpp:318 의 python -m pyvital → -m openvital. install_pip_package 는 anonymous namespace 의 is_safe_pkg_spec 화이트리스트 검증 + run_pip_silent (CreateProcessA + CREATE_NO_WINDOW + 자식 stdout pipe) + CDlgProgress / QtDlgProgress 자체 progress UI. 빌드 검증: python -m openvital 이 GET / 로 11 필터 반환, sanic import 부재 확인. zip 27.5 MB.
1.18.36 2026-05-07 Fixed: 3-파티션 레이아웃 (boot/rootfs/data) 에서 websocket edit_conf / update 명령이 read-only fs 로 실패하던 문제. vr.conf 는 /data 폴더가 있으면 /data/vr.conf 로 자동 정착 — get_conf_path() 가 write target 으로 결정, load_settings() 는 primary 가 없으면 legacy /boot/firmware/vr.conf 또는 /boot/vr.conf 에서 fallback read 후 다음 save 부터 primary 로 자동 이전 (마이그레이션 step 없음, legacy 파일은 read-only fs 라 무해). binary update (upgrade_now) 는 RAII BootRwGuard 가 dirname(module_path) 를 잠시 rw remount, scope 종료 시 sync() + MS_REMOUNT|MS_RDONLY 로 자동 ro 복귀 — vfat 노출 윈도우 최소화 + exception/return 어디서든 복구 보장. statvfs ST_RDONLY 검사로 이미 rw 인 fs (x86 dev) 에서는 no-op, non-Linux (macOS) 는 stub 으로 통과. save_settings() 의 silent EROFS 실패가 TRACE 로 가시화 (이전엔 무시되어 conf 수정 안 먹는 원인 추적 불가). 부수: PortRouter.cpp 가 commit 9bd252f 이후 CMakeLists 의 RPI sources 목록에서 누락되어 Pi 빌드 link 에러 — 추가.
1.18.35 2026-05-01 Added: alarm parsing for Mindray HL7 (eGateway ORU^R40) and Nihon Kohden (NealTime HL7GW + ORF, BSM serial D-port, EGA UDP) - emits ALARM_STATUS / ALARM_MESSAGE / ALARM_PRIORITY tracks (same 3-track schema already used by Philips IntelliVue, GE Solar/Dash, GE/Datex S5); type info preserved via [T]/[A]/[ARR] message prefixes; Mindray facet 1/5/6/7 walker with 92-entry MDC+MNDRY alarm code lookup; NK HL7GW parses OBR-4=EVENT with arrhythmia/technical disambiguation by OBX-5; NK BSM serial decodes per-parameter * flags (edge-triggered to avoid 1Hz flooding) plus 32-bit Table 9 arrhythmia bitmap, D19 alarm-suspend nibble, and the VPC CODE byte; NK EGA UDP extracts Priority + Tech Alarm + Arrhythmia from JSON Vital Sign packets with edge-trigger cache for start/end inference; ACK^R40 reply added for Mindray alert messages; simulators gained periodic alarm cycling for end-to-end smoke testing
1.18.34 2026-04-27 Added: Linux Desktop Qt GUI build (VRQt) - first GUI build for Linux distributed as a self-contained AppImage (~32MB, Qt6 runtime + libGL/libEGL/libGLX/libOpenGL/libGLESv2/libGLdispatch bundled inside) so users on minimal Ubuntu/Debian/Fedora can run it without installing Qt or GL system packages; tested on AWS clean Ubuntu 22.04 cloud image; build via build_ubuntu_appimage.py which is now invoked by deploy.py; Fixed: Linux Qt right-side device/filter panels rendered with white background below cards because the inner listWidget did not autoFillBackground from parent palette on Linux Qt (Windows/macOS implicitly inherit, X11/Wayland do not); explicit stylesheet on listWidget; Added: Linux installation section in user manuals (EN/KO/ZH/ES) covering AppImage chmod+run flow and dialout group note for serial/USB device access
1.18.33 2026-04-25 Fixed: Demo device never started since 1.18.11 (bed_manager skipped empty port_name as passive but Demo has no port and still needs lock_and_open); Fixed: Qt fit-to-window button rendered at top-left (0,0) instead of right-aligned in bottom nav bar; Fixed: Qt crash when closing tab / deleting device / deleting filter - paint dereferenced freed pointer before panel timer rebuilt items (added MFC-style stale-pointer guard to QtDeviceItem and QtFilterItem); Added: macOS DMG main window now shown on launch (restoreWindowPos had no Mac/Linux branch); Added: macOS Homebrew dylibs (openssl) bundled in Contents/Frameworks; Added: macOS .app bundle now notarized + stapled (drag-to-Applications no longer needs xattr -cr on first launch); Changed: Qt MSI ~1MB smaller (dropped unused iconengines and imageformats plugins)
1.18.32 2026-04-23 Fixed: same-port multi-client TCP - primary now runs a continuous accept loop and hands off each connection to the matching sub by IP filter (previously second connection got rejected/listened closed); Added: @IP and #keyword port filters are now mutually exclusive per bed (IP wins, keyword dropped with WARN); Added: WARN log when two beds on the same port share an identical IP filter; Added: catch-all primary keeps its single connection and rejects extras (preserves broadcast mode)
1.18.31 2026-04-22 Added: drug slot shows DOSE_AMOUNT (mg etc) in preference to VOL (mL) when available; Added: DOSE_RATE / DOSE_AMOUNT montypes bound to BBraun tracks for monitor view; Added: HL7 MDC_DOSE_DRUG_DELIV_TOTAL unit picked up dynamically from UCUM
1.18.30 2026-04-21 Changed: monitor view pump layout - 8 slots with CE or RATE (CE-less pumps show infused volume as small annotation); Reverted: BBraun minimal=1 (1.18.29) - was dropping data from file, monitor view redesign handles display clutter instead
1.18.29 2026-04-21 Fixed: BBraun multi-rack auto-tab data drop, primary TCP churn, save_settings lock race, TCP reader spin on peer close; Added: BBraun minimal=1 option (display only drug name / rate / volume)
1.18.28 2026-04-20 Fixed: vr.conf on Pi/Linux now looked up next to executable (supports /boot/firmware); deploy.py --store auto-submits MSIX to Microsoft Store
1.18.27 2026-04-18 Fixed: vital file periodic flush (5000s→5s bug), Fit-to-Window icon redesigned to match navigation button style
1.18.26 2026-04-18 Fixed: periodic .vital file flush interval was 5000 seconds instead of 5 (unit-bug since comment said seconds but value was milliseconds). Data now actually reaches disk every 5 s during recording instead of only on close.
1.18.25 2026-04-18 Fixed: BBraun HL7 rec_timeout raised 10s→60s to prevent primary churn during DoseLink R42→R01 phase transition and long idle periods
1.18.24 2026-04-18 Fixed: GUI silently exits when another recorder running (now falls back to viewer mode), .vital file association written to HKCU (no admin required, auto-updates exe path on every run)
1.18.23 2026-04-18 Fixed: atof decimal-separator bug on non-English Windows locales (rates <1.0 recorded as 0 in Norwegian/German/French etc.), BBraun HL7 pump limit raised from 8 to 16
1.18.22 2026-04-18 Fixed: multi-bed TCP port bind race on restart (Mindray/BBraun HL7 auto-reconnect without manual Add device)
1.18.21 2026-04-18 Fixed: port name filter (#keyword@ip) lost on save, BBraun HL7 VMD-block parsing with single dt, Fit-to-Window button sizing (MFC) and added to Qt
1.18.20 2026-04-15 BBraun: comprehensive protocol parsing (dose rate, infusion time, syringe, weight, drug amounts, delivery status)
1.18.19 2026-04-13 Fixed: BBraun HL7 multi-pump identification (rack serial filtering), multi-bed forwarding, port filter parsing
1.18.18 2026-04-10 Added: GE alarm limits, S5 alarm/ext3/ext1 parsing
1.18.17 2026-04-04 Changed: TRACE debug-only guard, show_msg for file errors, deploy sequential builds
1.18.16 2026-04-04 Added: TCP port filtering (#keyword@ip), frame forwarding for multi-bed. Fixed: --debug conf file mistaken as vital file, device type ambiguity in forwarding
1.18.15 2026-04-04 Changed: Port to Port Name, keyword filter AND/OR (#kw1 kw2#kw3), IP postfix matching (@10.1), MEKICS SerialFramed
1.18.14 2026-04-03 Added: TCP port filtering (#keyword@ip), Fixed: devtypes not sent on boot
1.18.13 2026-04-02 Changed: Covidien company name to Medtronic (BIS, INVOS)
1.18.12 2026-04-02 Bug Fixed: NihonKohden EGA SpO2 waveform not displayed (channel name mapping)
1.18.11 2026-03-31 Added: Mindray HL7 multi-bed separation via PV1, auto-tab creation for EGA/Mindray
1.18.10 2026-03-31 Added: HL7 ZBR segment now includes ver, os, arch, dgmt
1.18.8 2026-03-25 Added: --demo mode for console operation with demo signals
1.18.7 2026-03-25 Added: --console mode for headless operation on Windows
1.18.6 2026-03-25 Added: Mindray eGateway HL7 protocol (IHE PCD-01, HL7 v2.6 over MLLP, waveform + numeric + infusion pump)
1.18.4 2026-03-24 Added: BBraun SpaceCom HL7 protocol (HL7 v2.6 over MLLP, TCP server mode)
1.18.3 2026-03-24 Added: HL7 OBX-14 per-track dtstart, ZBR segment with dtcase/dtapp timestamps
1.18.2 2026-03-24 Added: HL7 ZBR segment with dtcase (recording start) and dtapp (app start) timestamps
1.18.1 2026-03-23 Fixed: HL7 OBX-3 format (code^device/track@srate), OBX-7 refrange (min^max), NA null sample gaps
1.17.6 2026-03-22 Bug fixed: Resource ID conflicts WiX installer cleanup
1.17.5 2026-03-21 Bug fixed: Vital packed file loading MFC device button icon padding
1.17.4 2026-03-19 Bug fixed: NirsitON EEG 250Hz VRQt device minimize/rename
1.17.3 2026-03-18 Bug fixed: BBraun protocol NirsitON protocol VRQt
1.17.2 2026-03-14 Added: NirsitOn NDI protocol support.
1.17.1 2026-03-12 Added: VRQt
1.16.13 2026-03-07 Added: New Setup File with VRQt
1.16.12 2026-03-06 Added: Vector Type Icons
1.16.10 2026-03-02 Bug fixed: Autodetecting BBraun Stuffing feature.
1.16.8 2026-02-27 Bug fixed: Masimo IAP protocol.
1.16.6 2026-02-13 Added: Servo-u ventilator protocol
1.16.5 2026-02-09 Bug Fixed: NihonKohden HL7GW Pleth waveform gain correction.
1.16.4 2026-01-20 Bug Fixed: Serial communication.
1.16.3 2026-01-14 Bug Fixed: Masimo IAP Protocol.
1.16.2 2026-01-03 Added: BLE Support for Movesense devices on Raspberry Pi
1.16.1 2026-01-01 Added: BLE Support for Movesense devices on Raspberry Pi and Linux versions.
1.16.0 2025-12-31 Added: BLE Support for Movesense devices
1.15.16 2025-09-18 Bug Fixed: Restoring last window position.
1.15.15 2025-09-05 Added: CPU optimization Bug fixed: Masimo IAP protocol.
1.15.14 2025-09-04 Added: CPU optimization
1.15.13 2025-09-04 Bug Fixed: Masimo IAP Protocol.
1.15.12 2025-09-04 Bug Fixed: Hardware handshake for Link+ connection.
1.15.11 2025-09-01 Added: Recording alarm messages for Drager anesthesia machines
1.15.10 2025-07-14 Bug Fixed: Sampling rate estimation in Medibus protocol.
1.15.9 2025-06-03 Bug Fixed: EEG waveform labels from Philips monitors.
1.15.8 2025-05-26 Added: EM_UPLOAD option to upload vital files to server immediately
1.15.7 2025-05-26 Bug Fixed: Websocket connection error
1.15.6 2025-05-19 Bug Fixed: S5 checksum error
1.15.5 2025-04-17 Bug Fixed: saving the raw data
1.15.4 2025-04-15 Added: Recording alarms from Philips monitor
1.15.3 2025-04-14 Bug fixed: saving the raw data
1.15.2 2025-03-12 Fixed: bug in opening file
1.15.1 2025-01-30 Supporting for Fresenius Kabi Conox, Minor Bug fixes
1.14.13 2025-01-18 Fixed bug in handling non-ascii filepath
1.14.12 2024-11-20 Fixed: bug in 64bit ARM Architecture
1.14.11 2024-10-24 Added: feature for updating to a specific version
1.14.10 2024-10-22 Fixed: bug in json streamming
1.14.9 2024-10-17 Added: montype for drug rates
Version Date Changes
1.18.41 2026-05-13 1.18.41 Hotfix: TCP-server protocol-initiator device (Intellivue/S5/Datex/Hamilton/MPS/Agilia/IAP) 가 open() 직후 보내는 첫 패킷이 wire 에 안 나가던 회귀. 1.18.34 의 PortRouter refactor 가 Serial::open_socket() 의 8초 handoff blocking 을 제거하고 비동기 모델로 전환했는데, protocol-initiator 의 open() 코드가 m_sock=INVALID 상태에서 write 를 시도해 silent fail (Linux 는 m_fd=0 이라 false 반환). Intellivue 케이스 production journald 의 Pi → ESP TX 700K~3M bytes 는 monitor 측 abort 로 늦게 트리거된 AB_SPDU_SI recovery assoc_req 후 request_thread 의 정상 polling 트래픽이지만 일부 베드 (abort 없는 monitor) 는 recovery 도 안 되어 영구 silent (RX 300 bytes). 수정 방향: open() 의 옛 contract ("return 시점에 통신 가능") 복구. (1) Serial::open_socket() TCP-server 분기가 PortRouter::subscribe 후 m_sock_cv 로 첫 client handoff 까지 block (timeout = device read_timeout, 기본 30s) — 옛 모델 그대로. lock_and_open 이 false 면 다음 tick 에서 retry. close 신호로 abort 가능. (2) Serial::close() 는 PortRouter::unsubscribe 안 함 — subscribe 는 device 생애 동안 sticky 라 read_timeout 으로 인한 close→re-open 사이클 동안 listen socket 이 유지되어 1.18.29/1.18.34 의 anti-churn 이익 보존. unsubscribe 는 ~Serial() 에서만. (3) Per-device lifecycle thread (DEVICE::m_thread_restart): 각 device 가 자기 open/close/timeout 재시작을 별도 thread 에서 관리. 옛 모델의 DISPLAY::bed_manager 가 베드의 모든 device 를 sequential iterate 하던 구조에선 한 device 의 blocking open() 이 같은 베드의 다른 device 의 lifecycle 을 차단했는데, per-device thread 로 분리하여 멀티 device 베드도 병렬 진행. add_dev 에서 start_lifecycle, del_dev / ~DISPLAY 에서 stop_lifecycle. (4) Serial::tcp_thread_func 단순화 — outer m_sock_cv wait 패턴 (1.18.34/1.18.39 가 추가했던 것) 제거. open_socket 이 m_sock valid 보장하므로 reader thread 시작 시점에 simple inner recv loop 만. accept_handoff 의 replace (zombie cleanup) 케이스는 recv error 후 m_sock 변경 확인 + retry 로 처리. (5) reading_thread_func 의 `else if (m_sock != INVALID_SOCKET) tcp_thread_func();` 가드 복원 (1.18.39 가 제거). (6) Serial::write 의 silent-fail 케이스에 WARN trace 추가 — 미래 동종 회귀 즉시 노출. (7) PortRouter::subscribe 가 같은 (port, type) 에서 같은 IP filter 또는 둘 이상 catch-all 발견 시 reject (config 실수 원천 차단, 옛 WARN-only 동작 강화). (8) DISPLAY::bed_manager_thread_func 의 restart 블록 제거 — ptcon + adt 만 담당. "Waiting for next patient" TRACE 가 Linux/console 에서 1초 → 60초마다 throttle (별개 journald 부풀림 fix). 영향 범위: Intellivue / S5 / Datex / Hamilton / MPS / Agilia / IAP TCP-server 모드 베드 전부. 1.18.34 이후 우회 방법은 race-win 케이스 (VRN 이 PortRouter::subscribe 직후 connect) 외엔 없었음. MFC + Qt + Pi (RPI64) + Ubuntu Qt + AppImage 빌드 모두 통과.
1.18.40 2026-05-12 Hotfix: Drager Medibus 프로토콜 사용 베드에서 1.15.11 이후 vr.service 가 SIGSEGV 로 무한 재시작하던 문제. 1.15.10 (a8c7b2a) 의 "Sampling rate estimation" 리팩터링이 m_ptrk_awp/awf/co2 트랙을 add_trks() 에서의 eager 생성 (default srate=62.5Hz) 에서 realtime data 100 샘플 모인 후 lazy 생성으로 바꿨는데, Medibus 핸드셰이크 순서 (0x51 ICC → 0x52 DeviceID → 0x53 RealtimeConfig 응답 → 0x54 → realtime data 시작) 상 0x53 응답 핸들러 (Drager.cpp:295-307) 가 트랙들이 아직 nullptr 인 시점에 `ptrk->m_srate = 1000000.0/interval` 로 NULL 역참조 → 즉시 SEGV. 그 베드의 vr.service 가 systemd Restart=on-failure 로 재시작 → 다시 connect → 동일 0x53 패킷 받고 동일 SEGV → 무한 루프 (journald 로그상 restart counter 61 까지 누적, code=killed status=11/SEGV). 1.15.9 까진 트랙이 add_trks() 에서 생성되어 0x53 도착 시 항상 non-NULL 이라 안전했음. 수정: (a) add_trks() 에서 m_ptrk_awp/awf/co2 eager 생성 복원 (srate=62.5Hz default) — 0x53 는 ptrk->m_srate 만 갱신 (트랙 재생성 X). (b) on_received() 의 lazy creation + packet-timing srate 추정 블록 제거 — 0x53 가 권위 있는 srate 소스이고 packet 타이밍 기반 추정은 network jitter 에 약해 불안정. (c) 0x53 핸들러에 `if (interval > 0)` guard 추가 — 페이로드 깨졌을 때 div-by-zero / inf srate 방지. 영향 범위: Drager Primus / Apollo / Perseus / Fabius 등 Medibus 사용 마취기 전부. 우회 방법은 1.15.9 다운그레이드 외엔 없었음 (그 베드의 모든 데이터 유실 + 환자 모니터링 불가). MFC + Qt + Pi (RPI64) + Ubuntu Qt + AppImage 빌드 모두 통과.
1.18.39 2026-05-08 Fixed: PortRouter (TCP server) 모드에서 reader thread 가 startup 시점에 죽어 client 데이터를 영구히 못 받던 문제. 1.18.34 (9bd252f) 의 PortRouter refactor 가 m_sock 세팅을 dispatch 시점으로 옮겼는데 reading_thread_func (Serial.cpp:354) 의 가드 `else if (m_sock != INVALID_SOCKET) tcp_thread_func();` 는 옛 모델 (open 시점 이미 connect 완료) 가정 그대로라 — 시작 직후 m_sock=INVALID 면 tcp_thread_func 진입 안 하고 reader thread 즉시 종료. 이후 VRN 이 connect → PortRouter::dispatch → accept_handoff 가 m_sock 채우고 m_sock_cv.notify_all() → 그러나 wait 중인 reader 가 없음 (이미 죽음) → kernel recv buffer 에만 데이터 적재. 증상은 ss -tn state established 의 Recv-Q 가 0 이 아닌 값 (수백 bytes) 으로 누적, 베드 화면에는 데이터 안 들어옴. 그 베드의 VRN 이 Serial::open() 의 PortRouter::subscribe 직후~reader thread spawn 사이의 짧은 윈도우 안에 connect 한 경우만 우연히 정상 동작 (race-win). 수정: 가드 제거 — TCP 분기에 항상 진입. tcp_thread_func 자체에 이미 m_sock_cv outer-wait 루프가 있어 m_sock 이 INVALID 인 동안 dispatch 가 깨워줄 때까지 안전하게 대기. Pi 핫스팟에 VRN 여러 대 (e.g. 10.42.0.21~25) 를 같은 (4343, Philips:Intellivue) 키로 묶고 IP filter 로 라우팅하는 시나리오에서 가장 자주 노출. Added: 진단 로그 보강 — PortRouter::accept_loop 의 accept 이벤트, dispatch 의 라우팅 결정 (ip_specific/catch_all subs 수, 어느 dev 가 받았는지), subscribe/unsubscribe 의 entry 생성/append/destroy, reading_thread / tcp_thread 의 시작·wait·wake 라이프사이클 — 이전엔 모두 m_bDebug 게이트 안에 있어서 production journald 에서 안 보였는데, 이제 항상 출력 (이번 같은 dispatch routing 문제 진단을 production 에서 바로 가능). MFC + Qt + Pi (RPI64) + Ubuntu Qt + AppImage 빌드 모두 통과.
1.18.38 2026-05-08 Fixed: 웹모니터링 우클릭 → 디바이스 세팅 (websocket edit_bed 명령) 으로 베드의 device/filter 를 변경할 때 베드 이름이 매번 "_2" suffix 로 자동 리네임되어 vr.conf (Pi: /data/vr.conf) 에 잘못된 이름으로 저장되던 문제. 원인은 1.18.22 (cda8aa5) 에서 add_bed 에 추가된 bedname dedup ("최후 방어선" 으로 forward_frame auto-create / 수동 편집된 conf 의 중복 이름 처리용). edit_bed 핸들러는 옛 pdel 이 m_pdisps 에 그대로 있는 상태에서 같은 bedname 으로 new DISPLAY 를 add_bed 하고 그 다음 del_bed(pdel) 하는 순서였는데, add_bed 가 dup 감지해 새 pdisp 를 bedname_2 로 자동 리네임 → save_settings 가 [BED/bedname_2] 로 직렬화 → 사용자 입장에선 "설정 적용 안됨" 으로 보였다. 추가로 옛/새 DISPLAY 가 잠깐 m_pdisps 에 공존하면서 같은 device 포트를 동시에 들고 있으려 해 로그가 dup 으로 찍히는 부수 증상도 있었음. 수정: del_bed(pdel) 를 add_bed(pdisp) 보다 앞으로 이동 — 옛 베드의 device 포트가 깨끗이 release 된 뒤 새 pdisp 가 같은 포트를 reopen, dedup 발동 안 함. 다른 베드의 recording 은 영향 없음 (인메모리 hot swap 설계 유지). 부수: edit_bed 핸들러의 데드 코드 (`break` 뒤의 unreachable olddevs populate 루프 + `if (olddevs.find(name) == olddevs.end())` 항상-true 래퍼) 정리. edit_conf 와 save_settings 는 손대지 않음. MFC + Qt + Pi (RPI64) 빌드 모두 통과.
1.18.37 2026-05-08 Refactored: 필터 다이얼로그의 python 런타임 — pyvital → openvital 0.3.0 로 교체 + 동봉 python.zip 슬림화. 핵심 동기 셋: (1) pyvital 0.6.0 이 tensorflow+torch+keras 를 hard-dep 으로 끌어들여 PyPI upgrade 가 사실상 깨짐, (2) 기존 zip 121 MB 안에 botocore/aiobotocore/s3fs/pyarrow/pandas/aiohttp 등 vitaldb 클라우드 업로드용 deps 가 ~250 MB unpacked 차지 — 필터 서버는 한 번도 쓴 적 없는 dead weight, (3) sanic 25.x 의 multi-process worker 가 openvital __main__.py 를 fork 후 재import 하면서 worker 가 module-top app instance 를 못 찾아 "Sanic app name not found" 로 죽음 — 단순 endpoint 2개 로컬호스트 서버에 async stack 자체가 과함. 해결: openvital 0.3.0 (commit b6f445b) 가 sanic 을 stdlib http.server (BaseHTTPRequestHandler + HTTPServer) 로 50 LOC 재작성 — wire protocol (GET / 필터목록 JSON, POST /<modname> gzip 본문) 동일해 VR 클라이언트 변경 0줄. 단일 스레드로 기존 sanic event loop semantics (cfgs/default_cfgs lock-free 변경) 보존. build_python_zip.py (NEW) 가 Python 3.11.9 embed + numpy + openecg + openvital (local checkout 우선, fallback PyPI) 만으로 27 MB zip 빌드 — 기존 121 MB 대비 78% 감소. ML 필터 (sv_dlapco/abp_hpi/ecg_classifier/ecg_beat_noise_detector) 는 [Hybrid 모델] 사용자가 Add filter 다이얼로그의 "Install ML filters" 버튼 누를 때 silent pip install openvital[all] (cmd 창 미노출 — VRApp::install_pip_package + run_pip_silent 이 자체 progress 다이얼로그에 stdout heartbeat 흘림). 버튼 라벨은 "Upgrade pyvital" → "Install ML filters" 로 의도 명시. openvital __main__.py 가 missing extras 를 graceful skip 하므로 base 환경에서도 11개 필터 (ECG QRS detector, HRV, MTWA, annotator, eeg_fft, nirs_cox, pkpd_3comp, pleth_dpop/ptt/pvi, resp_compliance) 즉시 사용 가능. Migration: 기존 사용자의 user_dir/python 폴더는 pyvital + 옛 deps 가 그대로 남아있고 vitaldb.net/python.zip 만 새로 올리면 (a) 기존 폴더 삭제 후 install_python 으로 새 zip 받으면 깔끔, (b) 폴더 유지 시 server 가 openvital 못 찾아 필터 다이얼로그 에러 → release note 에 명시 필요. MFC + Qt 양쪽 코드: VRGui.rc 의 IDC_UPGRADE 버튼 라벨 + DlgAddFilter.cpp 의 dist-info prefix 매칭 (pyvital- 8자 → openvital- 10자) + QtDlgAddFilter.cpp 도 동일 변경 + onUpgrade 가 cmd /k QProcess::startDetached 대신 theApp.install_pip_package("openvital[all]") 호출 (Linux Qt 빌드는 #ifdef _WIN32 가드). VRApp.cpp:318 의 python -m pyvital → -m openvital. install_pip_package 는 anonymous namespace 의 is_safe_pkg_spec 화이트리스트 검증 + run_pip_silent (CreateProcessA + CREATE_NO_WINDOW + 자식 stdout pipe) + CDlgProgress / QtDlgProgress 자체 progress UI. 빌드 검증: python -m openvital 이 GET / 로 11 필터 반환, sanic import 부재 확인. zip 27.5 MB.
1.18.36 2026-05-07 Fixed: 3-파티션 레이아웃 (boot/rootfs/data) 에서 websocket edit_conf / update 명령이 read-only fs 로 실패하던 문제. vr.conf 는 /data 폴더가 있으면 /data/vr.conf 로 자동 정착 — get_conf_path() 가 write target 으로 결정, load_settings() 는 primary 가 없으면 legacy /boot/firmware/vr.conf 또는 /boot/vr.conf 에서 fallback read 후 다음 save 부터 primary 로 자동 이전 (마이그레이션 step 없음, legacy 파일은 read-only fs 라 무해). binary update (upgrade_now) 는 RAII BootRwGuard 가 dirname(module_path) 를 잠시 rw remount, scope 종료 시 sync() + MS_REMOUNT|MS_RDONLY 로 자동 ro 복귀 — vfat 노출 윈도우 최소화 + exception/return 어디서든 복구 보장. statvfs ST_RDONLY 검사로 이미 rw 인 fs (x86 dev) 에서는 no-op, non-Linux (macOS) 는 stub 으로 통과. save_settings() 의 silent EROFS 실패가 TRACE 로 가시화 (이전엔 무시되어 conf 수정 안 먹는 원인 추적 불가). 부수: PortRouter.cpp 가 commit 9bd252f 이후 CMakeLists 의 RPI sources 목록에서 누락되어 Pi 빌드 link 에러 — 추가.
1.18.35 2026-05-01 Added: alarm parsing for Mindray HL7 (eGateway ORU^R40) and Nihon Kohden (NealTime HL7GW + ORF, BSM serial D-port, EGA UDP) - emits ALARM_STATUS / ALARM_MESSAGE / ALARM_PRIORITY tracks (same 3-track schema already used by Philips IntelliVue, GE Solar/Dash, GE/Datex S5); type info preserved via [T]/[A]/[ARR] message prefixes; Mindray facet 1/5/6/7 walker with 92-entry MDC+MNDRY alarm code lookup; NK HL7GW parses OBR-4=EVENT with arrhythmia/technical disambiguation by OBX-5; NK BSM serial decodes per-parameter * flags (edge-triggered to avoid 1Hz flooding) plus 32-bit Table 9 arrhythmia bitmap, D19 alarm-suspend nibble, and the VPC CODE byte; NK EGA UDP extracts Priority + Tech Alarm + Arrhythmia from JSON Vital Sign packets with edge-trigger cache for start/end inference; ACK^R40 reply added for Mindray alert messages; simulators gained periodic alarm cycling for end-to-end smoke testing
1.18.34 2026-04-27 Added: Linux Desktop Qt GUI build (VRQt) - first GUI build for Linux distributed as a self-contained AppImage (~32MB, Qt6 runtime + libGL/libEGL/libGLX/libOpenGL/libGLESv2/libGLdispatch bundled inside) so users on minimal Ubuntu/Debian/Fedora can run it without installing Qt or GL system packages; tested on AWS clean Ubuntu 22.04 cloud image; build via build_ubuntu_appimage.py which is now invoked by deploy.py; Fixed: Linux Qt right-side device/filter panels rendered with white background below cards because the inner listWidget did not autoFillBackground from parent palette on Linux Qt (Windows/macOS implicitly inherit, X11/Wayland do not); explicit stylesheet on listWidget; Added: Linux installation section in user manuals (EN/KO/ZH/ES) covering AppImage chmod+run flow and dialout group note for serial/USB device access
1.18.33 2026-04-25 Fixed: Demo device never started since 1.18.11 (bed_manager skipped empty port_name as passive but Demo has no port and still needs lock_and_open); Fixed: Qt fit-to-window button rendered at top-left (0,0) instead of right-aligned in bottom nav bar; Fixed: Qt crash when closing tab / deleting device / deleting filter - paint dereferenced freed pointer before panel timer rebuilt items (added MFC-style stale-pointer guard to QtDeviceItem and QtFilterItem); Added: macOS DMG main window now shown on launch (restoreWindowPos had no Mac/Linux branch); Added: macOS Homebrew dylibs (openssl) bundled in Contents/Frameworks; Added: macOS .app bundle now notarized + stapled (drag-to-Applications no longer needs xattr -cr on first launch); Changed: Qt MSI ~1MB smaller (dropped unused iconengines and imageformats plugins)
1.18.32 2026-04-23 Fixed: same-port multi-client TCP - primary now runs a continuous accept loop and hands off each connection to the matching sub by IP filter (previously second connection got rejected/listened closed); Added: @IP and #keyword port filters are now mutually exclusive per bed (IP wins, keyword dropped with WARN); Added: WARN log when two beds on the same port share an identical IP filter; Added: catch-all primary keeps its single connection and rejects extras (preserves broadcast mode)
1.18.31 2026-04-22 Added: drug slot shows DOSE_AMOUNT (mg etc) in preference to VOL (mL) when available; Added: DOSE_RATE / DOSE_AMOUNT montypes bound to BBraun tracks for monitor view; Added: HL7 MDC_DOSE_DRUG_DELIV_TOTAL unit picked up dynamically from UCUM
1.18.30 2026-04-21 Changed: monitor view pump layout - 8 slots with CE or RATE (CE-less pumps show infused volume as small annotation); Reverted: BBraun minimal=1 (1.18.29) - was dropping data from file, monitor view redesign handles display clutter instead
1.18.29 2026-04-21 Fixed: BBraun multi-rack auto-tab data drop, primary TCP churn, save_settings lock race, TCP reader spin on peer close; Added: BBraun minimal=1 option (display only drug name / rate / volume)
1.18.28 2026-04-20 Fixed: vr.conf on Pi/Linux now looked up next to executable (supports /boot/firmware); deploy.py --store auto-submits MSIX to Microsoft Store
1.18.27 2026-04-18 Fixed: vital file periodic flush (5000s→5s bug), Fit-to-Window icon redesigned to match navigation button style
1.18.26 2026-04-18 Fixed: periodic .vital file flush interval was 5000 seconds instead of 5 (unit-bug since comment said seconds but value was milliseconds). Data now actually reaches disk every 5 s during recording instead of only on close.
1.18.25 2026-04-18 Fixed: BBraun HL7 rec_timeout raised 10s→60s to prevent primary churn during DoseLink R42→R01 phase transition and long idle periods
1.18.24 2026-04-18 Fixed: GUI silently exits when another recorder running (now falls back to viewer mode), .vital file association written to HKCU (no admin required, auto-updates exe path on every run)
1.18.23 2026-04-18 Fixed: atof decimal-separator bug on non-English Windows locales (rates <1.0 recorded as 0 in Norwegian/German/French etc.), BBraun HL7 pump limit raised from 8 to 16
1.18.22 2026-04-18 Fixed: multi-bed TCP port bind race on restart (Mindray/BBraun HL7 auto-reconnect without manual Add device)
1.18.21 2026-04-18 Fixed: port name filter (#keyword@ip) lost on save, BBraun HL7 VMD-block parsing with single dt, Fit-to-Window button sizing (MFC) and added to Qt
1.18.20 2026-04-15 BBraun: comprehensive protocol parsing (dose rate, infusion time, syringe, weight, drug amounts, delivery status)
1.18.19 2026-04-13 Fixed: BBraun HL7 multi-pump identification (rack serial filtering), multi-bed forwarding, port filter parsing
1.18.18 2026-04-10 Added: GE alarm limits, S5 alarm/ext3/ext1 parsing
1.18.17 2026-04-04 Changed: TRACE debug-only guard, show_msg for file errors, deploy sequential builds
1.18.16 2026-04-04 Added: TCP port filtering (#keyword@ip), frame forwarding for multi-bed. Fixed: --debug conf file mistaken as vital file, device type ambiguity in forwarding
1.18.15 2026-04-04 Changed: Port to Port Name, keyword filter AND/OR (#kw1 kw2#kw3), IP postfix matching (@10.1), MEKICS SerialFramed
1.18.14 2026-04-03 Added: TCP port filtering (#keyword@ip), Fixed: devtypes not sent on boot
1.18.13 2026-04-02 Changed: Covidien company name to Medtronic (BIS, INVOS)
1.18.12 2026-04-02 Bug Fixed: NihonKohden EGA SpO2 waveform not displayed (channel name mapping)
1.18.11 2026-03-31 Added: Mindray HL7 multi-bed separation via PV1, auto-tab creation for EGA/Mindray
1.18.10 2026-03-31 Added: HL7 ZBR segment now includes ver, os, arch, dgmt
1.18.8 2026-03-25 Added: --demo mode for console operation with demo signals
1.18.7 2026-03-25 Added: --console mode for headless operation on Windows
1.18.6 2026-03-25 Added: Mindray eGateway HL7 protocol (IHE PCD-01, HL7 v2.6 over MLLP, waveform + numeric + infusion pump)
1.18.4 2026-03-24 Added: BBraun SpaceCom HL7 protocol (HL7 v2.6 over MLLP, TCP server mode)
1.18.3 2026-03-24 Added: HL7 OBX-14 per-track dtstart, ZBR segment with dtcase/dtapp timestamps
1.18.2 2026-03-24 Added: HL7 ZBR segment with dtcase (recording start) and dtapp (app start) timestamps
1.18.1 2026-03-23 Fixed: HL7 OBX-3 format (code^device/track@srate), OBX-7 refrange (min^max), NA null sample gaps
1.17.6 2026-03-22 Bug fixed: Resource ID conflicts WiX installer cleanup
1.17.5 2026-03-21 Bug fixed: Vital packed file loading MFC device button icon padding
1.17.4 2026-03-19 Bug fixed: NirsitON EEG 250Hz VRQt device minimize/rename
1.17.3 2026-03-18 Bug fixed: BBraun protocol NirsitON protocol VRQt
1.17.2 2026-03-14 Added: NirsitOn NDI protocol support.
1.17.1 2026-03-12 Added: VRQt
1.16.13 2026-03-07 Added: New Setup File with VRQt
1.16.12 2026-03-06 Added: Vector Type Icons
1.16.10 2026-03-02 Bug fixed: Autodetecting BBraun Stuffing feature.
1.16.8 2026-02-27 Bug fixed: Masimo IAP protocol.
1.16.4 2026-01-20 Bug Fixed: Serial communication.
1.16.3 2026-01-14 Bug Fixed: Masimo IAP Protocol.
1.16.2 2026-01-03 Added: BLE Support for Movesense devices on Raspberry Pi
1.16.1 2026-01-01 Added: BLE Support for Movesense devices on Raspberry Pi and Linux versions.
1.16.0 2025-12-31 Added: BLE Support for Movesense devices
1.15.16 2025-09-18 Bug Fixed: Restoring last window position.
1.15.15 2025-09-05 Added: CPU optimization Bug fixed: Masimo IAP protocol.
1.15.14 2025-09-04 Added: CPU optimization
1.15.13 2025-09-04 Bug Fixed: Masimo IAP Protocol.
1.15.12 2025-09-04 Bug Fixed: Hardware handshake for Link+ connection.
1.15.11 2025-09-01 Added: Recording alarm messages for Drager anesthesia machines
1.15.10 2025-07-14 Bug Fixed: Sampling rate estimation in Medibus protocol.
1.15.9 2025-06-03 Bug Fixed: EEG waveform labels from Philips monitors.
1.15.8 2025-05-26 Added: EM_UPLOAD option to upload vital files to server immediately
1.15.7 2025-05-26 Bug Fixed: Websocket connection error
1.15.6 2025-05-19 Bug Fixed: S5 checksum error
1.15.5 2025-04-17 Bug Fixed: saving the raw data
1.15.4 2025-04-15 Added: Recording alarms from Philips monitor
1.15.3 2025-04-14 Bug fixed: saving the raw data
1.15.2 2025-03-12 Fixed: bug in opening file
1.15.1 2025-01-30 Supporting for Fresenius Kabi Conox, Minor Bug fixes
1.14.13 2025-01-18 Fixed bug in handling non-ascii filepath
1.14.12 2024-11-20 Fixed: bug in 64bit ARM Architecture
1.14.11 2024-10-24 Added: feature for updating to a specific version
1.14.10 2024-10-22 Fixed: bug in json streamming
1.14.9 2024-10-17 Added: montype for drug rates
1.14.6 2024-09-20 Added: montype for drug rates
1.14.5 2024-09-13 Added: auto cutting by any of hr or spo2
1.14.4 2024-09-12 Fixed: bug in serial port mapping
Version Date Changes
1.18.41 2026-05-13 1.18.41 Hotfix: TCP-server protocol-initiator device (Intellivue/S5/Datex/Hamilton/MPS/Agilia/IAP) 가 open() 직후 보내는 첫 패킷이 wire 에 안 나가던 회귀. 1.18.34 의 PortRouter refactor 가 Serial::open_socket() 의 8초 handoff blocking 을 제거하고 비동기 모델로 전환했는데, protocol-initiator 의 open() 코드가 m_sock=INVALID 상태에서 write 를 시도해 silent fail (Linux 는 m_fd=0 이라 false 반환). Intellivue 케이스 production journald 의 Pi → ESP TX 700K~3M bytes 는 monitor 측 abort 로 늦게 트리거된 AB_SPDU_SI recovery assoc_req 후 request_thread 의 정상 polling 트래픽이지만 일부 베드 (abort 없는 monitor) 는 recovery 도 안 되어 영구 silent (RX 300 bytes). 수정 방향: open() 의 옛 contract ("return 시점에 통신 가능") 복구. (1) Serial::open_socket() TCP-server 분기가 PortRouter::subscribe 후 m_sock_cv 로 첫 client handoff 까지 block (timeout = device read_timeout, 기본 30s) — 옛 모델 그대로. lock_and_open 이 false 면 다음 tick 에서 retry. close 신호로 abort 가능. (2) Serial::close() 는 PortRouter::unsubscribe 안 함 — subscribe 는 device 생애 동안 sticky 라 read_timeout 으로 인한 close→re-open 사이클 동안 listen socket 이 유지되어 1.18.29/1.18.34 의 anti-churn 이익 보존. unsubscribe 는 ~Serial() 에서만. (3) Per-device lifecycle thread (DEVICE::m_thread_restart): 각 device 가 자기 open/close/timeout 재시작을 별도 thread 에서 관리. 옛 모델의 DISPLAY::bed_manager 가 베드의 모든 device 를 sequential iterate 하던 구조에선 한 device 의 blocking open() 이 같은 베드의 다른 device 의 lifecycle 을 차단했는데, per-device thread 로 분리하여 멀티 device 베드도 병렬 진행. add_dev 에서 start_lifecycle, del_dev / ~DISPLAY 에서 stop_lifecycle. (4) Serial::tcp_thread_func 단순화 — outer m_sock_cv wait 패턴 (1.18.34/1.18.39 가 추가했던 것) 제거. open_socket 이 m_sock valid 보장하므로 reader thread 시작 시점에 simple inner recv loop 만. accept_handoff 의 replace (zombie cleanup) 케이스는 recv error 후 m_sock 변경 확인 + retry 로 처리. (5) reading_thread_func 의 `else if (m_sock != INVALID_SOCKET) tcp_thread_func();` 가드 복원 (1.18.39 가 제거). (6) Serial::write 의 silent-fail 케이스에 WARN trace 추가 — 미래 동종 회귀 즉시 노출. (7) PortRouter::subscribe 가 같은 (port, type) 에서 같은 IP filter 또는 둘 이상 catch-all 발견 시 reject (config 실수 원천 차단, 옛 WARN-only 동작 강화). (8) DISPLAY::bed_manager_thread_func 의 restart 블록 제거 — ptcon + adt 만 담당. "Waiting for next patient" TRACE 가 Linux/console 에서 1초 → 60초마다 throttle (별개 journald 부풀림 fix). 영향 범위: Intellivue / S5 / Datex / Hamilton / MPS / Agilia / IAP TCP-server 모드 베드 전부. 1.18.34 이후 우회 방법은 race-win 케이스 (VRN 이 PortRouter::subscribe 직후 connect) 외엔 없었음. MFC + Qt + Pi (RPI64) + Ubuntu Qt + AppImage 빌드 모두 통과.
1.18.40 2026-05-12 Hotfix: Drager Medibus 프로토콜 사용 베드에서 1.15.11 이후 vr.service 가 SIGSEGV 로 무한 재시작하던 문제. 1.15.10 (a8c7b2a) 의 "Sampling rate estimation" 리팩터링이 m_ptrk_awp/awf/co2 트랙을 add_trks() 에서의 eager 생성 (default srate=62.5Hz) 에서 realtime data 100 샘플 모인 후 lazy 생성으로 바꿨는데, Medibus 핸드셰이크 순서 (0x51 ICC → 0x52 DeviceID → 0x53 RealtimeConfig 응답 → 0x54 → realtime data 시작) 상 0x53 응답 핸들러 (Drager.cpp:295-307) 가 트랙들이 아직 nullptr 인 시점에 `ptrk->m_srate = 1000000.0/interval` 로 NULL 역참조 → 즉시 SEGV. 그 베드의 vr.service 가 systemd Restart=on-failure 로 재시작 → 다시 connect → 동일 0x53 패킷 받고 동일 SEGV → 무한 루프 (journald 로그상 restart counter 61 까지 누적, code=killed status=11/SEGV). 1.15.9 까진 트랙이 add_trks() 에서 생성되어 0x53 도착 시 항상 non-NULL 이라 안전했음. 수정: (a) add_trks() 에서 m_ptrk_awp/awf/co2 eager 생성 복원 (srate=62.5Hz default) — 0x53 는 ptrk->m_srate 만 갱신 (트랙 재생성 X). (b) on_received() 의 lazy creation + packet-timing srate 추정 블록 제거 — 0x53 가 권위 있는 srate 소스이고 packet 타이밍 기반 추정은 network jitter 에 약해 불안정. (c) 0x53 핸들러에 `if (interval > 0)` guard 추가 — 페이로드 깨졌을 때 div-by-zero / inf srate 방지. 영향 범위: Drager Primus / Apollo / Perseus / Fabius 등 Medibus 사용 마취기 전부. 우회 방법은 1.15.9 다운그레이드 외엔 없었음 (그 베드의 모든 데이터 유실 + 환자 모니터링 불가). MFC + Qt + Pi (RPI64) + Ubuntu Qt + AppImage 빌드 모두 통과.
1.18.39 2026-05-08 Fixed: PortRouter (TCP server) 모드에서 reader thread 가 startup 시점에 죽어 client 데이터를 영구히 못 받던 문제. 1.18.34 (9bd252f) 의 PortRouter refactor 가 m_sock 세팅을 dispatch 시점으로 옮겼는데 reading_thread_func (Serial.cpp:354) 의 가드 `else if (m_sock != INVALID_SOCKET) tcp_thread_func();` 는 옛 모델 (open 시점 이미 connect 완료) 가정 그대로라 — 시작 직후 m_sock=INVALID 면 tcp_thread_func 진입 안 하고 reader thread 즉시 종료. 이후 VRN 이 connect → PortRouter::dispatch → accept_handoff 가 m_sock 채우고 m_sock_cv.notify_all() → 그러나 wait 중인 reader 가 없음 (이미 죽음) → kernel recv buffer 에만 데이터 적재. 증상은 ss -tn state established 의 Recv-Q 가 0 이 아닌 값 (수백 bytes) 으로 누적, 베드 화면에는 데이터 안 들어옴. 그 베드의 VRN 이 Serial::open() 의 PortRouter::subscribe 직후~reader thread spawn 사이의 짧은 윈도우 안에 connect 한 경우만 우연히 정상 동작 (race-win). 수정: 가드 제거 — TCP 분기에 항상 진입. tcp_thread_func 자체에 이미 m_sock_cv outer-wait 루프가 있어 m_sock 이 INVALID 인 동안 dispatch 가 깨워줄 때까지 안전하게 대기. Pi 핫스팟에 VRN 여러 대 (e.g. 10.42.0.21~25) 를 같은 (4343, Philips:Intellivue) 키로 묶고 IP filter 로 라우팅하는 시나리오에서 가장 자주 노출. Added: 진단 로그 보강 — PortRouter::accept_loop 의 accept 이벤트, dispatch 의 라우팅 결정 (ip_specific/catch_all subs 수, 어느 dev 가 받았는지), subscribe/unsubscribe 의 entry 생성/append/destroy, reading_thread / tcp_thread 의 시작·wait·wake 라이프사이클 — 이전엔 모두 m_bDebug 게이트 안에 있어서 production journald 에서 안 보였는데, 이제 항상 출력 (이번 같은 dispatch routing 문제 진단을 production 에서 바로 가능). MFC + Qt + Pi (RPI64) + Ubuntu Qt + AppImage 빌드 모두 통과.
1.18.38 2026-05-08 Fixed: 웹모니터링 우클릭 → 디바이스 세팅 (websocket edit_bed 명령) 으로 베드의 device/filter 를 변경할 때 베드 이름이 매번 "_2" suffix 로 자동 리네임되어 vr.conf (Pi: /data/vr.conf) 에 잘못된 이름으로 저장되던 문제. 원인은 1.18.22 (cda8aa5) 에서 add_bed 에 추가된 bedname dedup ("최후 방어선" 으로 forward_frame auto-create / 수동 편집된 conf 의 중복 이름 처리용). edit_bed 핸들러는 옛 pdel 이 m_pdisps 에 그대로 있는 상태에서 같은 bedname 으로 new DISPLAY 를 add_bed 하고 그 다음 del_bed(pdel) 하는 순서였는데, add_bed 가 dup 감지해 새 pdisp 를 bedname_2 로 자동 리네임 → save_settings 가 [BED/bedname_2] 로 직렬화 → 사용자 입장에선 "설정 적용 안됨" 으로 보였다. 추가로 옛/새 DISPLAY 가 잠깐 m_pdisps 에 공존하면서 같은 device 포트를 동시에 들고 있으려 해 로그가 dup 으로 찍히는 부수 증상도 있었음. 수정: del_bed(pdel) 를 add_bed(pdisp) 보다 앞으로 이동 — 옛 베드의 device 포트가 깨끗이 release 된 뒤 새 pdisp 가 같은 포트를 reopen, dedup 발동 안 함. 다른 베드의 recording 은 영향 없음 (인메모리 hot swap 설계 유지). 부수: edit_bed 핸들러의 데드 코드 (`break` 뒤의 unreachable olddevs populate 루프 + `if (olddevs.find(name) == olddevs.end())` 항상-true 래퍼) 정리. edit_conf 와 save_settings 는 손대지 않음. MFC + Qt + Pi (RPI64) 빌드 모두 통과.
1.18.37 2026-05-08 Refactored: 필터 다이얼로그의 python 런타임 — pyvital → openvital 0.3.0 로 교체 + 동봉 python.zip 슬림화. 핵심 동기 셋: (1) pyvital 0.6.0 이 tensorflow+torch+keras 를 hard-dep 으로 끌어들여 PyPI upgrade 가 사실상 깨짐, (2) 기존 zip 121 MB 안에 botocore/aiobotocore/s3fs/pyarrow/pandas/aiohttp 등 vitaldb 클라우드 업로드용 deps 가 ~250 MB unpacked 차지 — 필터 서버는 한 번도 쓴 적 없는 dead weight, (3) sanic 25.x 의 multi-process worker 가 openvital __main__.py 를 fork 후 재import 하면서 worker 가 module-top app instance 를 못 찾아 "Sanic app name not found" 로 죽음 — 단순 endpoint 2개 로컬호스트 서버에 async stack 자체가 과함. 해결: openvital 0.3.0 (commit b6f445b) 가 sanic 을 stdlib http.server (BaseHTTPRequestHandler + HTTPServer) 로 50 LOC 재작성 — wire protocol (GET / 필터목록 JSON, POST /<modname> gzip 본문) 동일해 VR 클라이언트 변경 0줄. 단일 스레드로 기존 sanic event loop semantics (cfgs/default_cfgs lock-free 변경) 보존. build_python_zip.py (NEW) 가 Python 3.11.9 embed + numpy + openecg + openvital (local checkout 우선, fallback PyPI) 만으로 27 MB zip 빌드 — 기존 121 MB 대비 78% 감소. ML 필터 (sv_dlapco/abp_hpi/ecg_classifier/ecg_beat_noise_detector) 는 [Hybrid 모델] 사용자가 Add filter 다이얼로그의 "Install ML filters" 버튼 누를 때 silent pip install openvital[all] (cmd 창 미노출 — VRApp::install_pip_package + run_pip_silent 이 자체 progress 다이얼로그에 stdout heartbeat 흘림). 버튼 라벨은 "Upgrade pyvital" → "Install ML filters" 로 의도 명시. openvital __main__.py 가 missing extras 를 graceful skip 하므로 base 환경에서도 11개 필터 (ECG QRS detector, HRV, MTWA, annotator, eeg_fft, nirs_cox, pkpd_3comp, pleth_dpop/ptt/pvi, resp_compliance) 즉시 사용 가능. Migration: 기존 사용자의 user_dir/python 폴더는 pyvital + 옛 deps 가 그대로 남아있고 vitaldb.net/python.zip 만 새로 올리면 (a) 기존 폴더 삭제 후 install_python 으로 새 zip 받으면 깔끔, (b) 폴더 유지 시 server 가 openvital 못 찾아 필터 다이얼로그 에러 → release note 에 명시 필요. MFC + Qt 양쪽 코드: VRGui.rc 의 IDC_UPGRADE 버튼 라벨 + DlgAddFilter.cpp 의 dist-info prefix 매칭 (pyvital- 8자 → openvital- 10자) + QtDlgAddFilter.cpp 도 동일 변경 + onUpgrade 가 cmd /k QProcess::startDetached 대신 theApp.install_pip_package("openvital[all]") 호출 (Linux Qt 빌드는 #ifdef _WIN32 가드). VRApp.cpp:318 의 python -m pyvital → -m openvital. install_pip_package 는 anonymous namespace 의 is_safe_pkg_spec 화이트리스트 검증 + run_pip_silent (CreateProcessA + CREATE_NO_WINDOW + 자식 stdout pipe) + CDlgProgress / QtDlgProgress 자체 progress UI. 빌드 검증: python -m openvital 이 GET / 로 11 필터 반환, sanic import 부재 확인. zip 27.5 MB.
1.18.36 2026-05-07 Fixed: 3-파티션 레이아웃 (boot/rootfs/data) 에서 websocket edit_conf / update 명령이 read-only fs 로 실패하던 문제. vr.conf 는 /data 폴더가 있으면 /data/vr.conf 로 자동 정착 — get_conf_path() 가 write target 으로 결정, load_settings() 는 primary 가 없으면 legacy /boot/firmware/vr.conf 또는 /boot/vr.conf 에서 fallback read 후 다음 save 부터 primary 로 자동 이전 (마이그레이션 step 없음, legacy 파일은 read-only fs 라 무해). binary update (upgrade_now) 는 RAII BootRwGuard 가 dirname(module_path) 를 잠시 rw remount, scope 종료 시 sync() + MS_REMOUNT|MS_RDONLY 로 자동 ro 복귀 — vfat 노출 윈도우 최소화 + exception/return 어디서든 복구 보장. statvfs ST_RDONLY 검사로 이미 rw 인 fs (x86 dev) 에서는 no-op, non-Linux (macOS) 는 stub 으로 통과. save_settings() 의 silent EROFS 실패가 TRACE 로 가시화 (이전엔 무시되어 conf 수정 안 먹는 원인 추적 불가). 부수: PortRouter.cpp 가 commit 9bd252f 이후 CMakeLists 의 RPI sources 목록에서 누락되어 Pi 빌드 link 에러 — 추가.
1.18.35 2026-05-01 Added: alarm parsing for Mindray HL7 (eGateway ORU^R40) and Nihon Kohden (NealTime HL7GW + ORF, BSM serial D-port, EGA UDP) - emits ALARM_STATUS / ALARM_MESSAGE / ALARM_PRIORITY tracks (same 3-track schema already used by Philips IntelliVue, GE Solar/Dash, GE/Datex S5); type info preserved via [T]/[A]/[ARR] message prefixes; Mindray facet 1/5/6/7 walker with 92-entry MDC+MNDRY alarm code lookup; NK HL7GW parses OBR-4=EVENT with arrhythmia/technical disambiguation by OBX-5; NK BSM serial decodes per-parameter * flags (edge-triggered to avoid 1Hz flooding) plus 32-bit Table 9 arrhythmia bitmap, D19 alarm-suspend nibble, and the VPC CODE byte; NK EGA UDP extracts Priority + Tech Alarm + Arrhythmia from JSON Vital Sign packets with edge-trigger cache for start/end inference; ACK^R40 reply added for Mindray alert messages; simulators gained periodic alarm cycling for end-to-end smoke testing
1.18.34 2026-04-27 Added: Linux Desktop Qt GUI build (VRQt) - first GUI build for Linux distributed as a self-contained AppImage (~32MB, Qt6 runtime + libGL/libEGL/libGLX/libOpenGL/libGLESv2/libGLdispatch bundled inside) so users on minimal Ubuntu/Debian/Fedora can run it without installing Qt or GL system packages; tested on AWS clean Ubuntu 22.04 cloud image; build via build_ubuntu_appimage.py which is now invoked by deploy.py; Fixed: Linux Qt right-side device/filter panels rendered with white background below cards because the inner listWidget did not autoFillBackground from parent palette on Linux Qt (Windows/macOS implicitly inherit, X11/Wayland do not); explicit stylesheet on listWidget; Added: Linux installation section in user manuals (EN/KO/ZH/ES) covering AppImage chmod+run flow and dialout group note for serial/USB device access
1.18.33 2026-04-25 Fixed: Demo device never started since 1.18.11 (bed_manager skipped empty port_name as passive but Demo has no port and still needs lock_and_open); Fixed: Qt fit-to-window button rendered at top-left (0,0) instead of right-aligned in bottom nav bar; Fixed: Qt crash when closing tab / deleting device / deleting filter - paint dereferenced freed pointer before panel timer rebuilt items (added MFC-style stale-pointer guard to QtDeviceItem and QtFilterItem); Added: macOS DMG main window now shown on launch (restoreWindowPos had no Mac/Linux branch); Added: macOS Homebrew dylibs (openssl) bundled in Contents/Frameworks; Added: macOS .app bundle now notarized + stapled (drag-to-Applications no longer needs xattr -cr on first launch); Changed: Qt MSI ~1MB smaller (dropped unused iconengines and imageformats plugins)