This folder contains stateful controllers that coordinate hardware drivers into “things the UI can do” (start camera streaming, set strobe timing, set pressure/flow targets, run heater PID, run droplet detection, etc.).
In the default app entrypoint (software/main.py), these controllers are instantiated first, then handed to the web layer (software/rio-webapp/) which exposes them via HTTP/WebSocket.
- Belongs here: long-lived state, orchestration across multiple drivers, “do the safe thing” guardrails, and any cross-cutting timing logic (e.g., camera↔strobe).
- Does not belong here: SPI/GPIO packet framing (belongs in
../drivers/), Flask routing and Socket.IO event registration (belongs in../rio-webapp/), and browser JS (belongs in../rio-webapp/static/).
-
camera.py—class Camera- Owns the camera capture thread and holds the current ROI (
Camera.get_roi()returns(x, y, w, h)orNone). - Owns droplet calibration values (
get_calibration()/set_calibration(...)). - Integrates strobe timing via
PiStrobeCam(seestrobe_cam.py). - Emits UI updates via Socket.IO (event names come from
software/config.py). - ROI modes: software ROI by default; hardware ROI optional via
RIO_ROI_MODE=hardwarewhen the camera backend supports it (falls back to software if not).
- Owns the camera capture thread and holds the current ROI (
-
strobe_cam.py—class PiStrobeCam- Composition of
drivers.strobe.PiStrobe+drivers.camera.BaseCamera. - Implements PIC-paced timing (strobe timing is the “clock”).
- Exposes camera selection via
set_camera_type(camera_type).
- Composition of
-
flow_web.py—class FlowWeb- Wraps the low-level
drivers.flow.PiFlowprotocol. - Tracks per-channel state and performs UI↔firmware control-mode mapping (canonical mapping lives in
flow_control_modes.pyin this folder and is re-exported byconfig.py; no local dicts here). - Typical calls:
set_pressure(index, mbar),set_flow(index, ul_hr),set_control_mode(index, firmware_mode).
- Wraps the low-level
-
flow_control_modes.py- Canonical mapping between firmware control modes and UI control modes (single source of truth).
- Defines
CONTROL_MODE_FIRMWARE_TO_UIandCONTROL_MODE_UI_TO_FIRMWAREdictionaries. - Defines
FLOW_CTRL_MODE_STRlist for UI display strings. - Imported by
config.pyand used throughout the codebase to ensure consistent mode mapping. - Why it exists: Historically, mode mapping logic lived in multiple places, causing drift. This file centralizes it.
-
heater_web.py—class heater_web- Wraps the low-level
drivers.heater.PiHolderprotocol. - Tracks display-ready strings and state flags (
pid_enabled,stir_enabled,autotuning). - Typical calls:
set_temp(temp_c),set_pid_running(on),set_autotune(on),set_stir_running(on),update().
- Wraps the low-level
-
droplet_detector_controller.py—class DropletDetectorController(optional)- Bridges the camera ROI + frames into the algorithm in
../droplet-detection/. - Public surface used by the web layer includes:
start(),stop(),reset(),update_config(dict),load_profile(path),get_histogram(),get_statistics(),get_performance_metrics(),export_data(format="csv"|"txt").
- Bridges the camera ROI + frames into the algorithm in
-
syringe_pump_controller.py—class SyringePumpController- Wraps USB serial pump driver (or simulation backend) and exposes safe methods for API/UI.
- Typical calls:
set_flow(),set_diameter(),set_direction(),set_state(),set_unit().
software/rio-webapp/controllers/*call these controllers from Socket.IO handlers.software/rio-webapp/routes.pyexposes a subset via HTTP endpoints (and also emits periodic UI updates).
Most tests should run in simulation mode (no physical hardware required):
cd software
export RIO_SIMULATION=true
pytest -vThis file was AI-generated and may contain errors. Please verify against the source code and runtime behavior.
- Date: 2025-12-30
- Model: GPT-5.2
- Maintenance: If you change controller behavior, public methods, or event/API contracts, update this document.