Functional · Pending regulatory approvalHealthcareDevice integrationCompliance & encryption10 min read

Pre-Trip Driver Medical Checkups

Digital pre-trip medical screening system with USB-synchronized breathalyzer integration.

Quick read

Ukrainian commercial drivers require a pre-trip medical check before each shift: pulse, blood pressure, temperature, and breathalyzer reading, all logged in a paper journal. As one of the physicians performing these checks, I built a digital system that replaces the journal — the medic enters readings on a web app, plugs the Drager iBlow 10 breathalyzer into USB at end-of-shift, and a desktop agent reconciles software-entered records with the device's onboard memory using time-windowed matching to confirm legitimacy. Production-grade: AES-256 encryption on medical fields, JWT auth, signed PDFs with JKS-based electronic signature, row-level multi-tenancy. Functional today; the regulatory path to replacing the paper journal is open but uncertain.

Context

Ukrainian law requires commercial drivers to undergo a pre-trip medical exam before each shift. The medic on duty measures pulse, blood pressure, body temperature, and uses a breathalyzer (Drager-brand or equivalent) to confirm sobriety. Each reading is logged in a paper journal with the driver's name, time, and the medic's signature.

The paper journal is the legal artifact. It's auditable by transport regulators, retained for years, and serves as proof that the check was performed correctly.

Two problems with the paper status quo:

  • Reconciliation is manual. The breathalyzer device stores its own internal readings log. The paper journal records what the medic wrote down. There's no enforced link between the two — a journal can be filled in without an actual breathalyzer test, or vice versa.
  • It's slow. Logging by hand across pulse, BP, temperature, BAC for each driver, multiplied across a shift, eats into the medic's time and increases transcription errors.

I perform these checks regularly as part of my work. I built the digital system to solve both problems for my own use, with a path to broader deployment if I can get it certified as a legal replacement for the paper journal.

Solution

A computer-based system where the medic logs each driver's pre-trip check digitally (pulse, BP, temperature, BAC reading, time, driver identity). At the end of a shift, the Drager breathalyzer plugs into USB and the system reads the device's internal log directly.

The system then reconciles: for every BAC reading the medic entered in software, the corresponding reading should exist in the device's onboard memory at approximately the same time. A check is "verified" only when both records match. Mismatches are flagged.

This produces a legitimacy claim that paper can't: the digital log isn't just what the medic claims happened — it's what the medic claimed and what the device recorded, cross-referenced.

The function works end-to-end today. What's open is regulatory: legally replacing the paper journal requires authorization from the institutions that mandated the paper form (Ministry of Health and Ministry of Internal Affairs). I've been through the initial outreach with MoH and NSZU, which directed me to file a formal public inquiry with the authorizing ministries — a process with a 30-day nominal response window but unreliable in practice.

Medic dashboard with reconciliation status per driver
Medic dashboard with reconciliation status per driver.

Impact

The system is in functional production at my own workplace but cannot yet legally replace the paper journal — so today it runs alongside paper rather than replacing it. The deployment story will be told properly once regulatory approval is in place.

What the system already proves:

  • The cross-referencing approach works technically. USB sync against the Drager iBlow 10's internal memory produces a clean time-windowed reconciliation log per shift.
  • A reverse-engineered USB protocol is a sustainable foundation. The vendor publishes Windows-only software; macOS support was traced manually with a USB sniffer. The protocol now lives in ~500 LOC of TypeScript inside an Electron menu-bar agent.
  • The compliance gap is regulatory, not technical. The paper journal exists because the law says so, not because the workflow needs it. The system already implements what a regulatory-ready electronic equivalent would need: AES-256-GCM encryption of medical fields, JWT auth with brute-force lockout, electronic signatures on PDF acts via JKS-based pyHanko signing, full audit log with signing IP and user-agent, row-level multi-tenancy via organization_id, and per-shift device memory dumps stored for verification.

Working code that's not legally usable is, for compliance products, indistinguishable from working code that doesn't exist.

Tech stack & architecture

The system is a three-tier application: a web app the medic uses during the shift, a backend handling business logic and storage, and a desktop USB agent that talks to the breathalyzer.

Backend

Python 3.12 · FastAPI · SQLAlchemy 2.0 (async) · asyncpg · Alembic (8 migrations) · Pydantic v2

Frontend

React 18 · TypeScript · Vite · Tailwind 3.4 · Zustand · react-signature-canvas

USB agent

Electron 33 · TypeScript · serialport 12 · ws (local WebSocket on port 8765)

Auth

JWT (access 30 min / refresh 14 days) · bcrypt · Brute-force lockout (5 attempts → 15 min)

Encryption

AES-256-GCM on medical fields (pulse, BP, temperature, BAC) · SQLAlchemy TypeDecorator · Key in env

Multi-tenancy

Row-level via organization_id on every table

PDF

WeasyPrint for generation · pyHanko + pyjks for electronic signature · JKS key held in RAM only

Email

aiosmtplib for SMTP notifications when a driver is ruled unfit

Storage

PostgreSQL 16

Codebase size: ~3,000 LOC Python backend (8 API modules + services + models + schemas), ~5,000 LOC TypeScript frontend (8 pages + ~12 components), ~500 LOC USB agent.

Reconciliation logic. The hardest design decision was how to match a medic-entered exam to the breathalyzer's onboard reading without trusting the medic's claim about which device record corresponds. The solution is time-windowing: when the medic clicks "start exam" in the web app, a window opens. The driver blows into the device during the window. The device stores its reading to onboard memory and resets to ready-state. The medic clicks "end exam", closing the window. At end-of-shift, when the device plugs into USB, the agent reads the device memory and the backend reconciles: for each medic-entered exam, find the device record whose timestamp falls inside that exam's window. Unmatched device records or unmatched exams get flagged. Matched pairs become the verified legal record.

The USB agent runs as a menu-bar Electron app on macOS (Intel + Apple Silicon, distributed as .dmg via electron-builder). The web frontend calls it over a local WebSocket on port 8765 to fetch device records on demand.

Deployment status. Currently runs locally on the workplace machine: PostgreSQL in Docker, backend via Uvicorn, frontend via Vite dev server. Production deployment (Caddy + HTTPS, containerized backend, backups) is scoped but not done — gated on the regulatory question described below.

What I learned

  • Reverse-engineering a vendor USB protocol is a tractable solo project if you commit to the boring part. Drager publishes the iBlow 10 with macOS no-go status — software exists only for Windows. To map the protocol I borrowed a Windows laptop, installed a USB sniffer, and ran traffic between the official client and the device for several hours while triggering every operation I could. With enough capture data, the protocol shape emerged. The lesson isn't about USB — it's about timeboxing: most "we'd need vendor access" problems are actually "we'd need a weekend with a sniffer" problems.
  • Time-windowing was the right abstraction for cross-device reconciliation. I started by trying to match by content (BAC value) and quickly realized that two consecutive drivers with similar readings would alias. Matching by timestamp alone has the same issue if device clock drifts. The breakthrough was reframing: don't match individual records, match windows-and-records. Each exam is a window owned by the medic's UI; each device record is a point in time; one window owns one point. Mismatches are anomalies. This generalized into a clean audit log: every legal record has a verifiable provenance pair.
  • Regulatory inertia is a real product risk and worth pricing in early. Working code that's not legally usable is, for compliance products, indistinguishable from working code that doesn't exist. To replace the paper journal, an electronic system needs sign-off from the institutions that authorized the paper form — Ministry of Health and Ministry of Internal Affairs. The official channel is a public inquiry; the official response window is ~30 days. In practice, my previous public inquiry to MoH went unanswered for months. I now treat regulatory feedback time as a hard input to the product roadmap, not a polite assumption. For future compliance-bound builds, I'd start the regulatory conversation before the code.

Next steps

The technical product is functionally complete and could go to production today on the deployment track that's already scoped (Caddy + HTTPS, containerized backend, backups). What's blocking that is regulatory: until MoH and MIA respond to the public inquiry defining requirements for an electronic equivalent of the paper journal, the system can't legally replace the journal, and parallel running has limited value over the paper alone.

Honestly, this is the part of the project I'm reassessing. Months of unresponsive regulatory channels make the path forward unclear, and I'm weighing whether to pause the build and revisit when conditions change, or to look for a different product surface where the same architecture (encrypted medical fields, signed PDFs, USB device sync, multi-tenancy) maps to a use case that doesn't require ministerial approval. An idea in the back of my mind is extending the agent to handle a Bluetooth pulse oximeter — same reconciliation model, broader applicability — but it's speculation, not a plan.

Read next