An open, redundant, multi-transport monitoring system for laboratory environments — freezers, fridges, incubators, cold rooms, LN₂ dewars, cleanrooms and the power that keeps them running.
Built to replace commercial lab-monitoring stacks whose recurring licence costs exceed their entire hardware BOM every year. A primary source puts one incumbent's service package at $458 per point per year on a 238-point estate, against a sensor module that cost $155.87 once.
Status: early. Design and core logic are real and tested; the server, storage and web portal are not yet written. See Where this actually is.
In short, this is not useful yet
A monitoring system has one job: when a −80 °C freezer fails at 03:00, the right person is woken. Everything else — the graphs, the reports, the dashboards — is secondary to that, and most of the design decisions here come from taking it literally.
Three consequences shape the whole codebase:
A bad sample must never clear an alarm. A thermocouple that falls out of a freezer and reads a plausible ambient temperature is the classic way a monitoring system lies to you. Sample quality is a first-class part of the data model, not a flag bolted on afterwards.
A system that cries wolf gets muted, and a muted system protects nothing. Every fridge in a lab is opened dozens of times a day. Without on-delays, deadbands and buffered probes, a naive configuration produces so many false alarms that people stop looking — and then it is worse than useless, because it provides false assurance. The simulator exists largely to prove this quantitatively.
Failures come in bunches. When a building loses power, twenty freezers start warming at once. Sending twenty alarms makes the on-call phone useless at exactly the wrong moment.
| Component | State |
|---|---|
labmon-core — units, quality, calibration, alarm engine, escalation |
Working, 74 tests |
labmon-sim — physics, sensor faults, gas, power, scenarios |
Working, 80 tests |
labmon-proto — LabLink frame codec, no_std |
Working, 27 tests |
| Firmware — ESP32-C6 and AVR senders | Drafted, not yet flashed to hardware |
| Design documents | Architecture, protocol, plan written; data model, frontend, security outstanding |
| Research | 8 reports, ~95,000 words, with explicit "what I could not determine" sections |
labmon-server, labmon-store, labmon-web |
Not started |
Nothing here has been run against real hardware yet. The numbers in the simulator are calibrated against published equipment behaviour, not against a freezer we measured.
The alarm engine is pure. No clock, no I/O, no randomness — time is always passed in. This is what lets a month of freezer behaviour be tested in milliseconds, lets two redundant servers reach identical conclusions without a consensus protocol, and lets you ask honestly whether a proposed new threshold would have caught last year's incident.
The simulator found a real design flaw. Rate-of-change alarms are the way to catch a failing freezer hours before it crosses a temperature limit. Computing that rate between consecutive samples does not work: it differentiates the sensor noise along with the signal, and the noise wins. Worse, a healthy freezer's compressor cycling produces apparent rates of 0.043 °C/min over 30 minutes — the passive warming phase of a normal cycle is the same physics as a failed compressor. Only over a window longer than one full control cycle (6 h → 0.0073 °C/min) does it separate cleanly from a genuine failure at 0.017. Both problems were found by simulation, not by argument.
The buffered-probe argument, quantified. Same simulated fridge, same rules, one week: a bare probe produces a stream of nuisance alarms, a glycol-buffered probe produces at most one — and that one is a true positive, with the contents genuinely above +8 °C for 19 minutes. This is why the CDC vaccine guidance requires a buffered probe rather than recommending one.
Amateur radio turned out to be legally blocked as a normal bearer. Telemetry itself is expressly legal (§97.111(b)(7), §97.217), and authenticating without encrypting is defensible. But §97.113(a)(3)'s pecuniary-interest ban and §97.113(a)(5)'s "could be furnished by another radio service" clause both cut against routine institutional use. ISM is the default; ham ships as a licensee-gated, alarm-only contingency. The genuinely valuable find was DAPNET — POCSAG paging to real pagers, off-grid, ~$200 of hardware, plaintext, and a better answer to "reach a human when the network is down" than any telemetry scheme.
crates/
labmon-core domain model, alarm state machine (ISA-18.2), escalation ladder
labmon-proto LabLink wire protocol — no_std, shared with firmware
labmon-sim physical models, sensor faults, fault injection, scenarios
firmware/
labmon-sender-esp32 ESP32-C6: thermocouple + door + mains, MQTT or LoRa
labmon-sender-avr ATmega328P: RS-485 only, collector is the trust boundary
docs/
00-PLAN.md the plan, including the simulator brief
research/ eight investigations, plus a synthesis of locked decisions
design/ architecture and protocol
cargo test --workspace # 181 tests
cargo clippy --workspace --all-targets
The scenario suite in crates/labmon-sim/tests/scenarios.rs is the most readable entry point:
each test is a failure you cannot stage in a real building.
a_healthy_freezer_produces_no_alarms_over_a_fortnight
a_failing_compressor_warns_on_rate_hours_before_it_breaches_the_limit
a_latched_sensor_is_caught_by_frozen_value_detection
an_open_circuit_does_not_clear_an_alarm_that_is_already_up
a_building_power_cut_is_one_cause_with_many_symptoms
a_freezer_failure_climbs_the_escalation_ladder_until_acknowledged
It is not a life-safety oxygen monitor. LN₂-room oxygen depletion is EN 50104 certified- instrument territory. LabMon ingests a certified monitor's 4–20 mA or relay output and escalates it. It does not replace it.
It does not measure incubator CO₂ with an air-quality sensor. An incubator runs at 5 % = 50 000 ppm. The SCD41 is specified to 5 000 ppm with extended output only to 40 000; it physically cannot report an incubator setpoint. Percent-range instruments (Vaisala GMP251, Sensirion STC31) are the only correct answer.
AGPL-3.0-or-later.