v0.1.0
alicatlib v0.1.0
First public release of alicatlib — an async-first Python library for Alicat
mass flow meters and controllers. Tested against real hardware (M-series,
GP07R100, V10 firmware) and a captured-replies fake transport.
Highlights
- Async-first, sync-equivalent. Full
anyio-based core (Device,
FlowMeter,FlowController,PressureMeter,PressureController) with a
parity-tested sync facade (Alicat.open,SyncDevice,SyncFlowController,
…). CI fails if a new async method lands without its sync wrapper. - Bootstrap identification.
open_device(...)runsVE→??M*→??D*
with post-frameDCU(units) andFPF(full-scale) sweeps, so setpoint
bounds and per-field units are known before the first user call. GP07R100
and pre-VEfirmware are supported via fallback paths. - Streaming with backpressure.
Device.stream(...)yields a bounded,
overflow-policy-aware iterator (DROP_OLDESTdefault,BLOCK,
DROP_NEWEST). A protocol-levelis_streaminglatch fast-fails any
request/response command issued on the same bus while a stream is live. - Acquisition + sinks.
record()schedules absolute-target polling that
never accumulates drift;pipe()drives anySampleSink. In-tree sinks:
InMemorySink,CsvSink,JsonlSink,SqliteSink(WAL),
ParquetSink(alicatlib[parquet]),PostgresSink(alicatlib[postgres],
binaryCOPYwithexecutemanyfallback). - Multi-device orchestration.
AlicatManagercanonicalises port identity
(POSIXrealpath, Windows\\.\COM…strip), ref-counts shared buses, and
dispatches across ports concurrently while serialising same-port work.
Per-call error policy viaErrorPolicy.{RAISE,RETURN}+DeviceResult[T]. - Typed safety rails. Setpoint requests are validated against
DeviceInfo.full_scalebefore I/O. Destructive commands (HC,ADDR,
NCB, totalizer resets) requireconfirm=True. Capability gates raise
AlicatMissingHardwareErrorrather than letting the wire fail. - Registry from primer data. Build-time codegen produces 98 statistics,
150 gases, and 119 units across 8 categories from a primer-verified
codes.json; CI guards generated-file idempotency. - Observability. Structured DEBUG wire trace on
alicatlib.protocol
(tx/rxwith{direction, raw, len}), pre-I/O INFO events on
setpoint /LSS/LVwrite paths, and one capability summary per
identification.
Install
pip install alicatlib
# Optional sinks:
pip install 'alicatlib[parquet]'
pip install 'alicatlib[postgres]'Requires Python 3.13+. Serial transport is provided by
anyserial.
Quick start
import anyio
from alicatlib import open_device
async def main():
async with await open_device("/dev/ttyUSB0", unit_id="A") as dev:
frame = await dev.poll()
print(frame.as_dict())
anyio.run(main)Sync equivalent:
from alicatlib import Alicat
with Alicat.open("/dev/ttyUSB0", unit_id="A") as dev:
print(dev.poll().as_dict())Compatibility
- Python: 3.13, 3.14
- Platforms: Linux, macOS, Windows
- Firmware: V5 / V8 / V10 families, plus pre-
VEfallback and GP07R100
Docs
Full changelog: CHANGELOG.md
Status
Beta. Public API is stable; hardware coverage breadth is the active work.