-
More reliable data exports. The Export Data page now exports one experiment at a time and starts exports as async tasks, so the UI can wait for large exports instead of tying up a web request. Exports now write directly into the zip file, clean up stale partial artifacts, and stop early if disk space, memory, or SQLite WAL growth gets too close to unsafe limits.
-
Automation schedules now live with the automation. Automations can choose the right trigger for their behavior: fixed timers, biomass updates, phase boundaries, or manual execution. For example,
turbidostatnow reacts to fresh biomass readings instead of polling every few seconds, whilelight_dark_cycleschedules exact light/dark phase boundaries. -
New repair workflow. Added
pio repair, richerpio status --jsonchecks, and a UI Repair system action under Inventory for fixing common local ownership, permission, and runtime-storage issues without rebooting or stopping running jobs.pio status --json pio repair
-
Removed the old
dosing_automation/media_throughputanddosing_automation/alt_media_throughputMQTT variables. Use the retained bioreactor cumulative dosing variables instead:pioreactor/<unit>/<experiment>/bioreactor/cumulative_media_added_ml pioreactor/<unit>/<experiment>/bioreactor/cumulative_alt_media_added_ml pioreactor/<unit>/<experiment>/bioreactor/cumulative_waste_removed_ml -
Removed the shared
--durationand--skip-first-runCLI flags frompio run dosing_automationandpio run led_automation. Timer-based automations now expose their own fields instead. For example:pio run dosing_automation --automation-name chemostat --duration 20 --skip-first-run 1 pio run led_automation --automation-name light_dark_cycle --light-duration-minutes 12.5 --dark-duration-minutes 12.5
-
Removed the old
pio update ...andpios update ...aliases. Use the explicit subcommand:pio update app --version <version> pios update app --version <version>
-
Moved passive Pioreactor card setting descriptors out of
ui/jobs/and into the newui/settings/descriptor directory. Plugin and custom UI descriptors for fields such as LED intensity, PWM intensity, and bioreactor state should now live under~/.pioreactor/plugins/ui/settings/. The old/api/bioreactor/descriptorsendpoint has been replaced by/api/settings/descriptorsand/api/workers/<unit>/settings/descriptors.
- Added retained
bioreactorvariables for cumulative dosing totals:cumulative_media_added_ml,cumulative_alt_media_added_ml, andcumulative_waste_removed_ml. These are updated from dosing events and can be used for media-use, alt-media-use, and waste-removal alerts. - Added YAML-backed UI settings descriptors, allowing built-in, plugin, and custom fields to control whether passive Pioreactor card fields are shown and how they appear in Manage / Settings.
- Improved automation start forms so each automation can define its own fields, including boolean options like
skip_first_run, and required fields now blockStartuntil valid. - Improved the Light/Dark Cycle LED automation to support fractional-minute light and dark phases and reschedule immediately when phase durations change.
- Added per-Pioreactor Stop all actions on Pioreactor cards, so a single unit can be stopped without broadcasting to every assigned unit.
- Added YAML download buttons for individual calibrations and estimators, alongside the existing source preview.
- Improved frontend load performance by lazily loading route-level UI pages.
- Fixed large exports that could exhaust memory or leave incomplete CSV/tmp files behind after interruption.
- Fixed experiment profile save and delete requests so the API waits for the underlying file operation and reports failures instead of returning success too early.
- Fixed experiment profile start errors so the UI keeps the dialog open and shows the backend error.
- Fixed Advanced Config dialogs to refresh config from the selected worker when opened, avoiding stale values after jobs persist updated settings.
- Fixed cluster fan-out reads so offline or slow workers resolve to per-unit failures instead of turning the whole request into a
ResultTimeout. - Fixed plugin pages for worker-specific views so offline workers show a clear
Could not reach this Pioreactor.error, and Install across cluster is shown only when there is more than one unit. - Fixed model-hardware checks to apply to HAT v1.x hardware generally, not just model version
1.5. - Fixed dosing automations to check required pump calibrations and PWM assignments before starting, so missing media or waste pump setup is reported immediately.
- New multi-pioreactor flow in the UI to run simultaneous protocols for stirring calibrations.
- Changed async task polling responses from
/unit_api/task_results/<task_id>and related leader callback helpers. Pending tasks now return202withstatus: pendingorstatus: running, while terminal task results now return200with eitherstatus: succeededplusresult, orstatus: failedplus error details. Failed task polls no longer use HTTP500just because the underlying task failed. - Fixed cluster-wide app updates so the leader is updated only once during broadcast updates, including both internet-based updates and release-archive updates.
- Fixed
dosing_automationto stop active pumps when the automation disconnects and fail custom multi-pump dosing requests before partially dosing if a required pump handler is missing. - Fixed crashes in the Experiment Profile editor
- Fixed an error when using
add_mediaoradd_alt_mediain an experiment profile
- Performance improvements in the UI frontend
- Improved software update reliability by avoiding temp-file name collisions between web-uploaded release archives and
pio update appdownloads. - Fixed duplicate
pio run od_readingstarts to fail before reinitializing ADC hardware, avoiding disruptions to an already-running OD reader and spurious noisy-reference warnings.
-
Updated
pio cache purgeto parse Python literals for cache keys, so tuple-shaped entries can be removed directly. For example:pio cache purge leader_multicast_get_cache "('multicast_get', 'calibrations', '/unit_api/calibrations', 'unit1')"
- Fix new worker images not having the correct data in ~/.pioreactor/ui
- Fix bioreactor diagram not responding to waste pump actions.
- Improved experiment profile validation to catch more semantic errors before execution or save, including conflicting action time fields and invalid profile expressions.
- Updated the Create/Edit Experiment Profile UI to show backend validation messages when a profile save fails, making profile errors easier to diagnose.
- Fix for blinking self-tests on the Pioreactors page
- Fix for Pioreactor page crashing.
- hot fix release to fix PWM bug.
- Unit-specific configuration is now owned by each worker’s local
unit_config.ini. The filename-based config editor APIs (/api/config/files*) have been removed; use/api/config/shared,/api/config/units/<unit>/specific, and/api/config/units/<unit>instead. pios sync-configs --specificnow refreshes leader-side snapshots from each worker’sunit_config.iniinstead of pushing leader-localconfig_<unit>.inifiles to workers.- Renamed the shared bioreactor volume setting
max_working_volume_mltoefflux_tube_volume_ml, including the UI label (Efflux tube level), MQTT/API state, and device config/cache migration during update. - Job and Automation controls now use worker-provided descriptors for individual Pioreactors, so worker-only plugin jobs automations appear in per-unit UI even if the leader doesn’t have that plugin installed. Bulk “Control All Pioreactors” automation flows remain leader-driven. A update script will attempt to add the necessary UI files to workers.
growth_rate_calculatingnow assumes the newgrpredicthidden-state filter and warmup-based initialization. It no longer supports--ignore-cache, cached growth-rate/filtered-OD startup state, orod_blankcorrection in this job. The parameters in[growth_rate_kalman]are no longer used.od_blankcorrection is now applied upstream inod_readingon a per-experiment basis before readings reachgrowth_rate_calculating. If a blank exists for the experiment,od_readingnow refuses to start with OD calibrations or fused estimators enabled, instead raising aValueError.- new version of
grpredictthat has significant changes to the responsiveness of the growth-rate model.
- Updated the config editor and worker-add flow for worker-owned unit configuration. The UI now edits shared cluster config separately from per-unit
unit_config.ini, and existing leaders update their add-worker helper so new workers receive shared config without overwriting their unit-specific config. - Added
pio config get <section> <parameter>andpio config set <section> <parameter> <value>for single-entry config access from the CLI.getdefaults to the effective merged value and also supports--shared/--specificfor file-specific reads.setuses--shared/--specificto targetconfig.iniorunit_config.ini. - Added short-lived leader-side caching for several fan-out metadata APIs, reducing repeated worker fetches and improving UI load times for calibrations, protocols, estimators, automations, jobs, and installed plugins.
- New growth-rate algorithm: designed the growth-rate EKF around a log-OD state model. You should see much faster convergence and better behaviour.
- Added
pio run stirring --measure-rpm-onlyto hold a fixed duty cycle while still measuring and publishingmeasured_rpm, making it easier to inspect fan RPM at settings like--duty-cycle 100.
- Fixed
dosing_automationsubdosing to emit only the top-levelDosingStartedandDosingStoppedevents, avoiding duplicate nested dosing events during recursive IO actions. - Fixed repeated in-process actions such as dosing/pump runs to clean up MQTT listeners, signal handlers, and short-lived MQTT clients more reliably, preventing runaway socket/file-descriptor growth in long-lived jobs.
- Fixed
fed_batchdosing to skip additions that would push the vial past the configured hard-stop safety volume, pausing the automation instead of risking overflow. - Fixed non-interactive SSH and
nohupcommand execution forpioandpiosby installing/usr/local/binwrappers that source/etc/pioreactor.envbefore execing the Pioreactor virtualenv binaries. - Fixed pump calibration
dosing_eventsfrom changing retained bioreactor state such as vial volume and alt-media fraction. - Fixed overview chart legends so relabelled aliases are truncated consistently and still hide/show the correct series when clicked.
- Fixed
pio update appdefault release installs to download and apply the singlerelease_<version>.ziparchive, reusing the same archive update path as uploaded release bundles instead of fetching individual release assets.
- Changed the leader API route for updating per-unit bioreactor values.
PATCH /api/workers/<unit>/experiments/<experiment>/bioreactorhas been removed; usePATCH /api/workers/<unit>/bioreactor/update/experiments/<experiment>instead.
- Fixed reassignment history tracking in the leader web app's SQLite connection by enabling recursive triggers, preventing stale open rows from accumulating in
experiment_worker_assignments_history. - Fixed worker reassignment so moving a Pioreactor from one experiment to another now stops jobs still running under the previous experiment.
- Fixed missed pump
dosing_eventsobservations by publishing them with MQTT QoS 2 (EXACTLY_ONCE), and updatedpio mqttto subscribe at the same QoS when tailing topics. - Fixed recent log tables in the UI so live MQTT log events stay sorted by timestamp even if they arrive slightly out of order, instead of appearing under older events until refresh.
- Fixed experiment profile previews so inline YAML comments like
# 1/h,# mL, and timing notes now appear in the human-readable display in the create, edit, and profile preview UIs.
- Adjusted the UI's "Assign Pioreactors" dialog so
Select all availableno longer includes workers already assigned to another experiment, reducing accidental bulk reassignments while preserving individual reassignment. - fixed new images now having the
experiment_tagstable - fixed some UI bugs
- Fix temperature automation not recognizing Pioreactor 20ml v1.0 correctly
- Fix bug that was causing
/api/bioreactor/descriptorsto fail on leader-only units.
Going forward, we are changing our versioning scheme from YY.M.D to YY.M.N, where N is a release counter within the month starting at 0.
We expect YY.M.0 releases to carry the larger changes, including system-level updates when needed. Subsequent releases in the same month, such as YY.M.1, YY.M.2, and so on, will typically be smaller bug-fix or incremental releases.
-
Redesigned the Experiments UI page into a management-focused table with search, status/tag filters, tag editing, and quick actions for exporting, ending, or deleting experiments.
-
Added experiment tags to the UI and API: tags can now be created when starting a new experiment, edited later from the Experiments and Overview page, and used to organize/filter experiments.
-
Calibration protocol sessions now persist a tab-scoped resume handle in the UI, so reloading the Protocols page in the same browser tab restores the existing
Resume protocolaction instead of losing the in-progress session. -
Added persisted bioreactor state for each experiment, including
current_volume_ml,max_working_volume_ml, andalt_media_fraction. These values are now exposed over MQTT plus new API endpoints:GET /api/bioreactor/descriptorsGET|PATCH /api/workers/<unit>/experiments/<experiment>/bioreactorGET /unit_api/bioreactor/experiments/<experiment>
-
Added live bioreactor controls to the Pioreactor UI so users can inspect and edit per-unit bioreactor values, with updated vessel diagrams for supported 20 mL and 40 mL models.
-
Added plugin hooks for custom self-tests. Plugins can now register additional checks that run with
pio run self_test, for example:from pioreactor.actions.self_test import register_self_tests def test_air_bubble_is_running(managed_state, logger, unit, experiment): assert ... register_self_tests(test_air_bubble_is_running)
-
Updated the leader UI's dosing-related chart and job descriptors to read live bioreactor state from
bioreactor/current_volume_mlandbioreactor/alt_media_fraction, and to stop exposing the hidden duplicate dosing-automation volume settings. The app update also refreshes the deployed YAML descriptors automatically on leaders. -
Removed the legacy dosing-automation MQTT settings/topic surface for bioreactor values.
current_volume_ml,max_working_volume_ml, andalt_media_fractionare no longer published asdosing_automationsettings or exposed as dosing-automation capability flags. Use the retainedbioreactortopics and APIs instead:pioreactor/<unit>/<experiment>/bioreactor/current_volume_ml pioreactor/<unit>/<experiment>/bioreactor/max_working_volume_ml pioreactor/<unit>/<experiment>/bioreactor/alt_media_fraction
- Fixed a UI crash when MQTT
button_downevents triggered tactile-button notifications. - Fix plugins not being loaded correctly in the background task worker. This affected mostly plugin-sourced calibrations.
- Added a
<System>experiment option in Export Data and mapped it to"$experiment"so users can export system logs from the UI. - Fixed calibration session resume so reopening a saved protocol session returns to the current step instead of accidentally starting the protocol from the beginning again.
- Fix leaking of self-test logs into the experiment.
pio update appnow always schedulessystemctl restart pioreactor-web.targetafter a successful default release-asset update, matching other update paths.- Actually ship the
HAT_PRESENTchange from last time - OD reading now correctly uses the smoothing penalizer.
pio statusnow handles unassigned experiments and other local check failures gracefully, leaving unassigned experiments blank and avoiding early aborts.- fix self-test "Reference photodiode is correct magnitude" for v1.5s
- Updated the REF-position self-test logic:
- Previously, it compared normalized variances over a time series.
- Now, it directly compares stirring ON/OFF deltas from controlled snapshots, aligned with the core idea: stirring should not materially change REF, while SIGNAL channels should respond.
ADCReader.tune_adcwas renamed toADCReader.tune_adc_with_ir_onto make the LED-on precondition explicit.
- Added
pios jobs listandpios jobs list runningto inspect worker job history and running jobs from the leader CLI. - Added
--config-override <section> <param> <value>topios runto temporarily override config values when launching worker jobs. - Added
GET /unit_api/jobsfor per-unit job history (ordered by newest first), complementing the existingGET /unit_api/jobs/runningendpoint. - Updated
pio cache viewto accept an optional key filter:pio cache view <cache> <key>now returns only that key when provided. - Added
pio update --sha <commit>(andpio update app --sha <commit>) to install from a specific git commit. - Added a new calibration coverage matrix page in the UI (linked from Calibrations) to show cluster-wide per-unit/per-device coverage and quick actions: open active calibration details, view available calibrations for a device, or create missing calibrations via
/protocols/<unit>/<device>. - Added card-level quick controls to both
/pioreactorsand/pioreactor/<unit>: clicking an activity state now runs contextual actions (start, stop, pause, resume), and shows an in-place spinner until MQTT reports the expected state transition. - Added inline quick-edit popovers for card settings values.
- Improved the UI's "Assign Pioreactors" dialog: units already assigned to another experiment can now be selected for reassignment, and "Select all" now applies consistently to all listed units.
- Automation advanced config now discovers and displays both
[<x>_automation.config]and per-automation sections like[<x>_automation.<automation_name>], enabling section-specific overrides from the UI.
- Changed Turbidostat biomass signal behavior:
- Default behavior is now
biomass_signal=auto, with selection order:- active
od_fusedestimator - active OD calibration for the configured angle (
od) - normalized OD
- active
- You can still explicitly override
biomass_signalin config (including via profiles). - Moved config from
[turbidostat.config]to[dosing_automation.turbidostat]. - Update scripts migrate existing values from the legacy section/key when present.
- Default behavior is now
- Renamed
pio cache cleartopio cache purge. - Renamed
/api/is_local_access_point_activeto/api/local_access_point(now returns{active: <bool>}). - Consolidated experiment profile routes:
- Kept
/api/experiment_profilesand/api/experiments/<experiment>/experiment_profiles/*. - Removed
/api/contrib/experiment_profilesand/api/experiment_profiles/running/experiments/<experiment>. PATCHnow targets/api/experiment_profiles/<filename>.
- Kept
- Consolidated config API routes under
/api/config/*:/api/units/<pioreactor_unit>/configurationis now/api/config/units/<pioreactor_unit>./api/configs+/api/configs/<filename>+/api/configs/<filename>/historyare now/api/config/files+/api/config/files/<filename>+/api/config/files/<filename>/history.
- Removed
/api/contrib/*endpoints in favor of resource-scoped routes:/api/automations/descriptors/<automation_type>,/api/jobs/descriptors,/api/charts/descriptors, and/api/datasets/exportable*. - Renamed
pio jobs removetopio jobs purge. - Replaced
pio jobs runningwithpio jobs list running(list runningis now a running-only filter ofpio jobs listoutput).
- Fixed usage of the
duration_between_led_off_and_od_readingconfig. - OD reading now uses a trimmed-mean + prior smoother on ADS1114-based units (v1.5s), while keeping sinusoidal regression on non-ADS1114 units where AC hum is present. This also skips unnecessary AC frequency detection on ADS1114 channels.
- Simplified ADS1114 reads in
pioreactor.utils.adcsto use continuous conversion mode, replacing per-sample config-write + ready-poll cycles with paced conversion-register reads. This reduces I2C traffic and lowers cross-process bus contention risk on ADS1114-based units. - Fixed
/api/config/units/$broadcastto correctly merge each unit's ownconfig_<unit>.iniinstead of using a shared (and wrong)config_$broadcast.inipath. - Bumped rpi_hardware_pwm to avoid a race condition setting up PWMs.
- Fixed calibration detail pages so
Set active/Set inactivewaits for backend task completion before refetching, preventing stale "Set active" and missing "Active" status until manual refresh. - Made IR reference-noise gating in OD reading scale with the configured reading interval (baseline
std <= 0.01at5.0s), including when the interval is changed at runtime. - Fixed Inventory model updates and active/inactive toggles to show success only after confirmed backend
2xxresponses, with explicit error feedback on failure. - Fixed an issue where changing RPM while stirring was paused would restart stirring.
self_testnow cleans up better when interrupted.- CLI change gives plugin-registered commands precedence, enabling intentional overrides to existing
pio runcommands. - Fixed UI bugs on the Configuration page
- Fixed
HAT_PRESENTnot being respected in the UI flow. - PWMs clean up better, and display a warning if something looks wrong.
- removed System tab from the Pioreactor's "Control" dialog. You can see (most) of this data on the Inventory page
- added a Self-test tab back to the Pioreactor's "Control" dialog, and to the "Control all Pioreactors"
- added
pio statusfor a quick local health summary (identity, versions, MQTT, web API, Huey, jobs, storage) - improved
pio db,pio cache, andpio loghelp output with clearer descriptions and examples - improved
pio workers statusto use unit API health checks for reachability and provide brief reasons when state/version are unknown - improved
pioshelp output with clearer descriptions and examples for cluster actions - removed the redundant
--jobflag frompios kill(use--job-name)
- reused cached IR LED reference normalization per experiment when
ref_normalization=unity, instead of always taking the first reading - improved unit API retry safety by returning in-progress responses when Huey task locks are held
- improved API error messages with structured causes and remediation hints for agents and UI clients
- fixed
pio runcommand resolution to load plugins before looking up job commands
- Run calibrations from the UI.
- New Protocols page with guided calibration sessions, step-by-step instructions, and live charts.
- Support for Pioreactor XR.
- Faster Stop commands in the UI, plugin listing, and data exports.
- Added dosing start/stop events to
dosing_automation_events, including exports. - Added unit-relative IR LED reference normalization for OD readings via
ref_normalization=unity. This should align different Pioreactors to similar starting values, especially v1.5 models. However, this changes OD levels, so existing OD calibrations are not adjusted automatically. - New query pattern for faster Experiment Overview chart loading; large datasets may show randomized sampling in time series. Let us know if this is too distracting. Max point targets per series increased to 1400.
- OD calibrations now support multiple photodiode angles;
pio calibrations run --device odcan emit per-angle calibrations for 45/90/135.- Added an update helper to migrate legacy OD calibrations into per-angle devices.
- Calibration protocols are now exposed via API.
- When a Pioreactor model is changed, a (non-blocking) hardware check is performed.
- You can now restart the web server (lighttpd) and the background task queue, Huey, from the UI. Go to Leader -> "Long-running jobs", and see the "web server and queue" line.
- Added spline and akima curve support for calibrations, including OD standards sessions and calibration charts.
pio calibrations analyzenow supports--fit poly|spline|akima. You can use this to refit a dataset to a spline or akima curve.- Added estimator artifacts alongside calibrations, including OD fusion estimators stored under
storage/estimatorsand managed via the calibration session flow. Estimators are a generalized calibration for more complex algorithms. Calibrations will be restricted to 1D models. - New unit APIs for estimators:
/unit_api/estimators/<device>/unit_api/estimators/<device>/<estimator_name>
- Faster startup and shutdown of Pioreactor jobs.
- Charts on Experiment Overview now scale with window size.
- New Estimators page in the UI.
- Moved Self-test to the Inventory page. Pioreactors no longer need to be assigned to an experiment to run self-test.
- Removed
/api/workers/<pioreactor_unit>/configuration; use/api/units/<pioreactor_unit>/configuration. - Self-test logs are now part of
$experiment. - Calibration flow modules were merged into protocol modules; old import paths like
pioreactor.calibrations.pump_calibrationandpioreactor.calibrations.od_calibration_*are removed. - Removed experimental pump-detection failure handling from chemostat and turbidostat.
- OD calibration devices are now per-angle (
od45,od90,od135) instead of justod. Physically, this changes the calibration directory in~/.pioreactor/storage/calibrations/odto~/.pioreactor/storage/calibrations/{od45,od90,od135}. Existingodcalibration files and active calibrations are migrated during the update. - Self-test no longer creates a stirring calibration.
- OD reading charts in the UI previously had a sensor label next to the unit, ex:
worker01-2. Now it is the corresponding angle fromconfig.ini. Note: only the globalconfig.iniis used, not specificunit_config.inifiles. - New OD and stirring calibrations are now fit with a akima, and not a polynomial.
- Calibration curve data is now serialized as tagged structs (
poly/spline/akima) instead of raw lists.curve_typeis removed and existing calibration files are migrated during the update. - Reorganized calibration protocol modules into
core/pioreactor/calibrations/protocols/and extracted aregistry.pyfor protocol registration. - Removed OD calibration using a single vial.
- Fix self-test logging closing prematurely.
- Fix floating point error at the boundary of OD calibrations.
- Fix runtime forward-reference errors in type annotations after dropping
__future__imports. - Fix timeouts being too short on some UI export operations.
- Re-save calibration files on
pio calibrations analyzeconfirmation even when the curve is unchanged. - UI now logs all warnings and errors, including from the web backend.
- Fix Mosquitto's pw.txt file.
- Added a
pio jobscommand group withrunning,list,info, andremovesubcommands to inspect and tidy job records, including published settings.
pio job-statushas been replaced bypio jobs info.- changed
/unit_api/jobs/stopfrom using query params to json body.
- fix OD blank not being able to be run.
- OD calibration now clamps out-of-range voltages to the OD values paired with the calibration’s voltage extrema, preventing inverted mappings on non-monotonic curves.
- Images ship with DAC43608 library (missed the previous OS jump!)
- Improvements to "Updating your model" on first boot.
- Fix /pioreactor page crashing if a worker is inactive in the experiment.
- Fixed clock syncing on the cluster
-
Added
pio job-statusfor a quick view of running jobs. -
Easier time syntax for experiment profiles!
- Use the
tfield to specify times using suffixes, like15s,1m,2.5h - In
repeatblocks,everyreplacesrepeat_every_hours, andmax_timereplacesmax_hours. Both the same time syntax above. - In
whenblocks,wait_untilreplacescondition.
experiment_profile_name: demo_stirring_repeat metadata: author: Cam Davidson-Pilon description: A simple profile that starts stirring, increases it every 5min, and stops when the RPM exceeds 2000. common: jobs: stirring: actions: - type: start t: 0 - type: repeat t: 5m every: 5m actions: - type: update t: 0.0s options: target_rpm: ${{::stirring:target_rpm + 100}} - type: when t: 0s wait_until: ${{::stirring:target_rpm > 2000}} actions: - type: stop t: 0sThis is now the preferred way (though the old syntax isn't going away), and docs will be updated to reflect this.
- Use the
- Cluster CLI commands now use
click.Abort()(instead of baresys.exit) so failed prompts, copy/install operations, and OD blanking exit cleanly with Click’s messaging. - Background jobs now only clear MQTT/db cache entries for attributes that were actually set, preventing accidental removal of unset metadata.
- Dodging jobs keep their OD-reading interval topic published even if a second OD reader attempts to start and fails, so dodging continues uninterrupted.
- Fix
pios update ...breaking the web server from starting. (pio updateis fine)
- Added support for Pioreactor v1.5.
- Upgrade to Trixie Debian 13!
- New Pioreactor architecture:
- New environment variable file /etc/pioreactor.env
- The old
pioreactoruiPython package is now part of thepioreactorPython package, underpioreactor.web - Moved temporary files from /tmp to /run/pioreactor/
- New
pioreactor-web.serviceto handle bothhuey.serviceandlighttpd.service
pioreactor.hardware: reworked GPIO, PWM, and I2C configuration to load from layered YAML mods so new HAT+model combinations can be described without code changes. See new ~/.pioreactor/hardware directories.pioreactor.hardware: constants are now resolved lazily through accessor functions (e.g., determine_gpiochip(), get_pwm_to_pin_map()); direct module constants remain but are deprecated shims that emit warnings.- Export images (PNGs and SVGs) of the Overview's and Calibrations' charts.
- MCP server: added tools for creating experiments and managing worker assignments.
- Show and hide calibration curves in Calibrations page by clicking the dot beside the calibration (similar to the Overview page).
- Adding
pio workers update-model <unit> -m <name> -v <version>to leader's CLI. - Added time-window and time-format options to the individual Pioreactors pages.
- New workflow to set your Pioreactor leader-worker model on first load of the UI.
- Add new APIs and MCP tools via plugins. Example: drop the following in your ~/.pioreactor/plugins folder:
from future import annotations from pioreactor.plugin_management import get_plugins from pioreactor.web.plugin_registry import register_mcp_tool
plugin_name = "mcp-plugins" plugin_version = "0.1.0" plugin_summary = "Adds convenience MCP utilities for Pioreactor plugin introspection." plugin_author = "Cam DP"
@register_mcp_tool() def list_installed_plugins(): """ Return metadata for installed Pioreactor plugins registered with the system. """ plugins = get_plugins() details = [ { "name": name, "version": plugin.version, "summary": plugin.description, "author": plugin.author, } for name, plugin in plugins.items() ] return {"plugins": details}
- New import of system files (the `~/.pioreactor` directory) into Pioreactors. This means that it's easy to "back up" a pioreactor (leader or worker), and then reupload this to a (new) pioreactor in your cluster via the import system. This is available on the Inventory page.
- support for up to four PDs.
#### Breaking changes
- Changed `start_od_reading` API. It now accepts a dict instead of args for each PD position.
### 25.9.18
- Experiment profile editor: added a searchable capabilities browser. You can now search across available jobs, automations, actions, and options directly in the editor. This should make building and editing profiles faster and reduce syntax errors.
- Experiment Overview charts: no longer hide older data on long experiments. Instead, each series is downsampled on the client to a maximum of 720 points while preserving trends, regardless of experiment length. For very large clusters this may increase initial load time — narrowing the time range or hiding unused series can help if you notice slowness.
- Eye-spy optics: initial support is included. If detected, the OD reading job can use it via the existing interfaces. Nothing changes if you don’t have this hardware connected; more documentation will follow.
- Inventory export: from the Inventory page, you can export a worker’s `~/.pioreactor` directory as a zip. The Leader page also includes an export for the leader’s `~/.pioreactor`. This is useful for backups, support, or migration. Review the archive before sharing — it may contain configuration and credentials.
- Pump scripting: `pio run pumps ...` now accepts a `sleep` step to pause between actions. Example: `pio run pumps --media 2 --sleep 1 --waste 1.5` runs media for 2 mL, waits 1 s, then runs waste for 1.5 mL. In experiment profiles, you can repeat actions by suffixing keys with `_`, for example:
```yaml
jobs:
pumps:
actions:
- type: start
options:
media: 2
sleep: 1
waste: 1.5
sleep_: 2 # repeat keys by adding underscores
waste_: 0.5
- Advanced config for automations: the UI’s “Advanced” menu (temporary config overrides at start) is now available when launching automations, not just individual jobs. The options shown come from the
[<job_name>.config]section. - CLI: added leader-only experiment management commands —
pio experiments create <NAME>,pio experiments list, andpio experiments delete <NAME>.
- Restored live updates in real‑time charts in the UI (regression fixed).
- Corrected timestamps on exported dataset folders in the archive.
- Removed cases of duplicate log lines shown in the UI.
- MCP now correctly respects configured notification methods.
- Fixed model selection in the “Add a new Pioreactor worker” dialog in Inventory.
- For leader-only Pioreactors, fixed leaders not showing up in "Cluster clocks" (and likely other places)
- Turbidostat now enforces
duration = 0.25sfor its frequent checks. The UI already used this value; CLI runs will now match it for more consistent behavior.
-
Custom Bioreactor Models Our community has been incredibly creative in adapting Pioreactor hardware and software for different vessel types. Now, you can officially add your own custom bioreactor models to the Pioreactor software! Place your model definitions as yaml files in the new
.pioreactor/models/directory. For example:model_name: custom_100ml model_version: "1.0" display_name: "Custom 100 mL, v1.0" reactor_capacity_ml: 100.0 reactor_max_fill_volume_ml: 95.0 reactor_diameter_mm: 50.0 max_temp_to_reduce_heating: 80.0 max_temp_to_disable_heating: 85.0 max_temp_to_shutdown: 90.0
Example file name:
custom_100ml.yamlThis information is used throughout the software (including the UI) to support different shapes, sizes, and safety limits. Tell us what else you’d like supported!
-
New MCP Server (Experimental) You can now run an MCP server alongside your leader’s web server. It adds a new SSE-based endpoint at:
http://<leader-address>/mcp/This exposes some Pioreactor tools in real time. It’s still experimental — your feedback and suggestions for additional tools/resources are welcome!
-
Added Time Range filter to the Export Data UI page.
-
The “Add a new Pioreactor worker” dialog now automatically scans for and lists local workers available to join your cluster.
-
New
config.inioption:[od_reading.config] duration_between_led_off_and_od_reading = <seconds>This adjusts the pause between turning off LEDs and taking an OD snapshot.
-
pios X --experiments <experiment>now lets you target workers by experiment from the leader CLI. -
More CLI options are available for jobs with
settable: Truepublished_settings. -
New API endpoints:
/unit_api/capabilities/api/units/<pioreactor_name>/capabilitiesThese provide detailed information about what each Pioreactor can run.
-
API changes:
-
api/units/<unit>/configurationresponse format updated. -
Settings endpoint now scoped to experiments:
/api/workers/unit1/jobs/settings/job_name/stirring/experiments/<exp> -
Removed:
/api/workers/jobs/stop/experiments/<exp>Use:/api/workers/$broadcast/jobs/stop/experiments/<exp> -
Removed:
/api/experiments/<experiment>/jobs/settings/job_name/<job_name>Use:/workers/$broadcast/jobs/settings/job_name/<job_name>/experiments/<experiment>
-
-
pio logsno longer follows by default — use-fto follow. -
Developers: We’ve merged our three main repositories (
pioreactor,pioreactorui,pioreactorui_frontend) into a single monorepo:pioreactor. The old repos will be archived, and update code inpio.pywill now point to the new repo. If you have branches on the old repos, rebase ontopioreactor. Discussion: GitHub issue #576.
- Fixed default sorting when exporting CSV.
- Fixed crash in UI profile editor.
- Fixed pumps not shutting down correctly if active when
dosing_automationstopped. - Fixed cleanup issue in growth rate calculation.
- Fixed plugins page crashing when a plugin doesn't have a homepage associated to it.
🔥 hot fix release
- Fix error when
target_rpm_during_od_readingis 0 and dodging is active. - Fix exporting pioreactor unit labels dataset.
- Fix LED not working when booting a fresh worker.
- Fix for plugins that use the "dodging" behaviour. Your air-bubbler plugin probably broke - this fixes it.
- We previously introduced the ability for stirring to "dodge" OD reading by turning itself off during an OD snapshot. This proved useful, but users wanted the generalized ability to modify the RPM to any value during a snapshot. For example, slow down the RPM during a snapshot, instead of stopping stirring. Another use case is to set the RPM during a snapshot to be equal to the RPM when an OD calibration was performed. We've introduced two new stirring configuration parameters, only used when dodging is active:
target_rpm_during_od_reading: the RPM when an OD snapshot is performed.target_rpm_outside_od_reading: the RPM outside a snapshot. We highly recommend having a stirring calibration active while using these.
- There's a new "Advanced" start option in the UI to modify configuration temporarily when starting a job. The options shown are from the section
[<job_name>.config]. This is useful for changing different configurations without changing the config files. - The above uses a new convention in
pio runCLI command. You can provide configuration overrides with the--config-overrideoption. Example:orpio run --config-override od_reading.config interval 0.1 od_readingpio run --config-override stirring.config initial_duty_cycle 25 --config-override mqtt username pp stirring - You can even use config overrides in experiment profiles (must be applied to the
startaction.)common: jobs: od_reading: actions: - type: start hours_elapsed: 0.5 config_overrides: samples_per_second: 0.1 ir_led_intensity: 70 ...
- We moved our Extended Kalman Filter code out of this repo into it's own Python library: grpredict.
- Chemostat modal in the UI now shows the computed dilution rate
- New "Duplicate" profiles button.
- Experimental: Adding an experimental new feature that will detect a pump malfunction by comparing the OD before and after dosing. If the post-OD falls outside some expected bound (default is 20%), the dosing is paused until a user comes to unpause it. To enable this feature, set
dosing_automation.configparameterexperimental_detect_pump_malfunctiontoTrue.- This only applies to the current implementations of
turbidostatandchemostatin our software. - This feature relies on 1) Accurate initial volume (inputted when you start the automation), 2) accurate pump calibrations, 3) clear media
- This only applies to the current implementations of
- Calibration charts have new crosshairs
- The config
[mqtt]broker_addresscan now be a list of addresses, separated by;. Example:[mqtt] broker_address=pio01.local;100.119.150.2;localhost - Performance improvements
- Backing up database now checks if the worker and local machine have enough disk space, and skips if not.
- In configuration,
[stirring.config]parametertarget_rpmis renamed toinitial_target_rpm. This is better for letting users know that the RPM can be changed during a run. - floats are rounded to 12 decimals points in data exports.
- localtime in data exports have subsecond precision.
- Changed dosing automation variables names:
max_volumetomax_working_volume_ml(also changed in config.ini)liquid_volumetocurrent_volume_ml- Chemostat and Turbidostat automations stopped using
volumekwarg and now useexchange_volume_ml. - the chart
liquid_volumesis renamedcurrent_volume_ml. This should be updated in your config.ini under[ui.overview.charts]if you are using that chary.
- included new export dataset yaml for raw OD readings. This was missed in a previous release.
- experiment profiles now check the syntax of nested actions before starting the execution.
(hotfix patch)
- update Adafruit-Blinka to fix USB issue.
- Fix for HardwarePWM on RPi5 on linux kernel 6.6
- new System logs under Inventory to track logs happening outside of experiments in your cluster.
- Better organization of logs in the UI. System logs, like calibrations, worker additions, etc. won't show up on the Overview page.
- Exported data zips have folders for each dataset requested.
- Improvements to the Kalman filter. For users using the growth-rate model with media dosing, you should see improvements to your growth-rate time series. We recommend the following configuration:
[growth_rate_kalman]
# obs_std ↑ smooths growth rate, rate_std ↑ more responsive growth rate
obs_std=1.5
od_std=0.0025
rate_std=0.25
Note: the acceleration term is removed
- Added the column
hours_since_experiment_createdto dataset exports that details hours since experiment was created. - A running pump now fires off an incremental dosing event every N seconds (N=0.5 currently) to tell the software its progress. Previously, we would fire off a single event that represented the total amount moved. This is most noticeable when watching the vial volume change over time (looks more accurate over a short period).
- When a pump runs, it first fires off a dosing_event, which stores information about how much liquid is moved. However, if the pump is stopped early, there was no correction issued to the amount of liquid actually moved. Now, when a pump is stopped early, a negative volume is sent s.t. the delta between the initial amount and new amount is equal to the dosed amount (so when you sum up the volume changes, you get the actual change, as expected).
- Performance optimizations
- New image installs only:
- updated base OS to the latest 25-05-06 Raspberry Pi OS. The big change is using Linux kernel 6.12.
- fixed stir bar not spinning on Pioreactor page (UI) in some cases
- alert user if their OD reading is constant before starting the growth-rate calculator, which would break things.
- alert user if their software is installed in a non-standard location. If so, try
pip uninstall pioreactor -y. - Added a warning if the OD calibration is invalid (ex: a constant line)
- Fix for Raspberry Pi 5 using upstream Adafruit libraries.
- new Upload Calibration dialog in the UI
- new OD calibrations are of type
od600(instead ofod). Nothing needs to change for the user.
- stirring calibration was using too many points from the lower bound, this is fixed.
- fix for stirring calibration in the self-test creating an empty file
- Fix custom charts that were not fetching from the database correctly due to the backend table being a sqlite3 view (VIEWs don't have ROWID, which was breaking a filter).
- Fix for heater PCB not shutting down correctly.
- Fix OD Reading not displaying correctly on Pioreactor pages
- Fix duplicates in Raw OD Reading chart's legend
- Improvements to pump calibration flow that will ask user what volumes they wish to calibrate for.
- Fix self-test "REF is correct magnitude"
- self-tests don't use calibrated OD readings anymore.
- Support for Pioreactor 40mL
- UI and backend now accommodates the new Pioreactor 40mL. Change the Pioreactor model on the Inventory page.
- Device models and versions now tracked in the database
- Models and versions for each Pioreactor are now stored in the
workersdatabase table. We're deprecating the[pioreactor]section inconfig.ini. You can manage models and versions on the Inventory page.
- Models and versions for each Pioreactor are now stored in the
- Improvements to dosing automation settings:
- When starting a dosing automation, you can set the initial and max culture volumes.
- Raw vs. calibrated OD readings now separated
- When a calibration is applied in the
ODReadingjob:- New MQTT topics are published:
od_reading/raw_od1andod_reading/raw_od2for raw (un-calibrated) valuesod_reading/calibrated_od1andod_reading/calibrated_od2for calibrated values
- New MQTT topics are published:
- The raw readings will be stored in new database tables,
raw_od_readings. The calibrated values still occupy the tableod_readings. - Existing topics like
od_reading/od1,od_reading/od2, andod_reading/odsremain unchanged, but note they may contain either calibrated or raw data depending on calibration status. - To display a chart of the raw OD readings when a calibration is being used, switch the config entry
raw_optical_densityfrom0to1in the section[ui.overview.charts]
- When a calibration is applied in the
- Changes to
pio workers add- This command has been updated to better reflect the new model/version management.
- Removed config parameter
max_volume_to_stop.- This is now hardcoded into the software. For 20ml, it's 18ml, and for 40ml, it's 38ml.
- Fixed occasional crash on the Overview page in the UI.
- Stirring dodging now correctly respects the first OD reading.
- Stirring (and other software PWM-based jobs) now clean up properly more often on disconnect.
- Fixed issue where dodging background jobs would run a final, incorrect
action_to_do_before_readingafter OD reading stops. - The OD calibration flow now correctly ignores existing calibrations when creating a new one.
- UI page
/pioreactors/<some_unit>now uses that unit's specific configuration fromconfig_<some_unit>.ini. - Fix error "cannot schedule new futures after shutdown" when stopping a dosing automation during a pump execution.
- Reverted a change to job's exit protocol introduced in 25.3.5 that would cause on_disconnected to run twice sometimes.
- Fixed "manual adjustments" pump actions not firing an MQTT event.
- Fixed OD calibrations using the wrong min, max thresholds.
pio calibrations analyze --device odwill use regression weights for OD calibrations (like they do during the OD calibration)
- New faster ADC firmware with less noise
- Upgraded ADC firmware improves signal processing speed and reduces measurement noise, leading to more reliable readings for all sensors.
led_intensityis now registered in our database- This means that running
pio kill --all-jobs(and relatedpio killcommands) will now also turn off all LEDs, ensuring a complete shutdown of active processes.
- This means that running
- New option in
pio workers addto specify an IPv4 address- When adding a new worker, you can now explicitly provide an IPv4 address instead of relying on the default
hostname.local. This is useful in networks where mDNS resolution is unreliable or unavailable. Ex:pio workers add <name> -a 192.168.0.3
- When adding a new worker, you can now explicitly provide an IPv4 address instead of relying on the default
- New time option on the Overview page: "Now" for only real-time data
- The UI now has a “Now” option that filters out historical data, displaying only real-time sensor readings and status updates.
- Logs for experiment profiles now include an action step number
- Each log entry related to an experiment profile now contains a step number, making it easier to track progress and diagnose issues in multi-step workflows.
- Improved outlier detection in nOD and growth rates
- Our outlier detection algorithms for normal optical density (nOD) and growth rates have been refined, reducing false positives and improving tracking accuracy during experiments.
- Changing OD readings interval programmatically
- OD Reading job now exposes
intervalas a editable published_setting. For example, you can PATCH tohttp://pioreactor.local/api/workers/<pioreactor_unit>/jobs/update/job_name/od_reading/experiments/<experiment>with body:to change OD readings interval to 10s.{ "settings": { "interval": 10 }, }
- OD Reading job now exposes
id→job_idinpio_metadata_settingstable- Database schema update: The primary identifier column in
pio_metadata_settingshas been renamed tojob_id.
- Database schema update: The primary identifier column in
- Changed the scaling of
smoothing_penalizer- The
smoothing_penalizerparameter now operates on a scale that is ~100x lower than before.
- The
- Deprecation of
/unit_api/jobs/stop/...endpoint- The
/unit_api/jobs/stop/...API endpoint is being deprecated in favor of using query parameters:- Instead of
/unit_api/jobs/stop/job_name, use/unit_api/jobs/stop/?job_name=.... - The special case
/unit_api/jobs/stop/allremains valid and unchanged.
- Instead of
- The
- Timestamp precision change: From
xxxxxmilliseconds →xxxmilliseconds- All timestamps will now be stored with three-digit millisecond precision instead of five. This change optimizes storage efficiency and speeds up queries while maintaining sufficient accuracy for most use cases.
- Fix for "More" button in the Logs UI page
- Previously, clicking "More" in the Logs UI would default to "Standard" log level instead of retaining the selected filter. Now, it correctly uses the log level chosen by the user.
- Multiple experiment profiles no longer overwrite each other in MQTT
- Previously, running multiple experiment profiles could cause MQTT messages to overwrite each other. This is now fixed, but note that the new MQTT topic format introduces
job_id, deviating from our usual topic structure.
- Previously, running multiple experiment profiles could cause MQTT messages to overwrite each other. This is now fixed, but note that the new MQTT topic format introduces
- Fix for API returning incorrect responses for Huey-related tasks
- API responses related to background tasks (e.g., adding a new Pioreactor, syncing configs, updating firmware) were sometimes incorrect or missing details. This has been fixed.
- Correction to
od_reading.config'ssmoothing_penalizerscaling error- A miscalculated scaling factor in
od_reading.configcaused the smoothing factor to be larger than intended. This has been corrected, and yourconfig.inifile has been automatically updated to reflect the new values.
- A miscalculated scaling factor in
- Fix for missing log events in Event Logs after worker unassignment
- Some log events (such as clean-up and assignment events) were missing when they occurred after a worker was unassigned. These now appear correctly. Additionally, some unrelated log entries that were mistakenly displayed have been removed.
- Scaling bug fix in the extended Kalman filter affecting nOD detection
- A bug in the extended Kalman filter was causing outlier detections too frequently. In extreme cases, these detections could compound, driving nOD values negative and corrupting the filter’s internal state. This issue has been fixed with a new, more stable filtering algorithm that significantly improves robustness.
Important, any OD calibrations made on software versions 25.1.21 and 25.2.10 have incorrect metadata, and it needs to be updated. Use this hot fix release to fix them. You'll still need to rerun:
pio calibrations analyze --device od --name <cal name>
to recreate the calibration curves.
- Hot fix for OD Calibrations bug.
-
New OD Calibration: Introduced a new OD calibration using standards (requires multiple vials). Run:
pio calibrations run --device odInspired by the plugin by @odcambc.
-
UI Improvements:
- Improved chart colors.
- Added the ability to choose the level of detail on the new Event Logs page.
-
New OD Reading Option: The OD reading CLI now includes a
--snapshotoption to start the job, take a single reading, and exit. This is useful for scripting. -
New Pump Control CLI: Introduced a new CLI for pumps:
pio run pumps --media 1 --waste 2This command will add 1ml of media and remove 2ml of waste. The order matters, and pumps can be specified multiple times:
pio run pumps --waste 2 --media 1 --waste 2This new CLI is really useful for experiment profiles. For example, a chemostat can be "programmed" as (but don't actually do this, using a dosing automation):
common: jobs: pumps: actions: - type: repeat hours_elapsed: 0 # start immediately repeat_every_hours: 0.5 # every 30m, run the following actions actions: - type: start hours_elapsed: 0 options: media: 1 waste: 2
-
Experiment & System Enhancements:
- Initial support for 40ml model.
- Ability to run multiple experiment profiles per experiment.
- Users can now specify which Pioreactor to update on the Updates page (available only with release archives).
- Stirring calibration is now included as part of the self-test.
- Improved stirring job handling when OD readings have long pauses.
-
Previously, if a worker’s web server was down, an update would be blocked. Now, the leader will first attempt the web server, and if a 5xx error is observed, it will attempt SSH communication instead.
- Introduced:
GET /unit_api/jobs/running/<job>GET /api/experiment_profiles/running/experiments/<experiment>
-
Calibration Structs:
predict→x_to_yipredict→y_to_x- This change makes naming clearer.
-
Plugin Migration (Upcoming):
- Plugins should migrate from
click_some_nameto auto-discovered plugins by importingrun. - Example migration:
import click from pioreactor.cli.run import run @run.command("my_name") @click.option("--my_option") def my_name(my_option): ...
- Plugins should migrate from
-
Select workers by experiment (Upcoming):
- Add
--experimentsoption to pios commands to select all active workers assigned to the specified experiment(s).
- Add
- Fixed UI not displaying third-party calibrations.
- Experiment profiles now directly use
unit_api/, potentially mitigating Huey worker stampedes when starting multiple jobs. - Fixed
pio calibrations run ... -ynot saving as active. - Fixed manual dosing issues in the UI.
- Fixed manual log recording in the UI.
- There was a race condition between
monitorand a db creation job that was preventing themonitorjob from starting. Awkwardly, this only seemed to happen on power cycles, and only sometimes. This escaped our testing. We've fixed it by improving how we initialize the dbs, and how we connect to them.
-
New UI updates:
- An
Event Logspage for seeing the logs generated by your Pioreactors - A detailed overview of your cluster's leader-specific duties on the new
Leader's page.- See the Leader's filesystem, logs, update cluster clocks, and view important running jobs.
- View different Pioreactors' plugins on the
Pluginspage, and install to specific Pioreactor vs entire cluster. - Manage your calibrations from the UI's new
Calibrationspage.- View existing calibrations, set active calibrations, and download calibration files.
- An
-
New calibrations API. A calibration now creates a YAML file as an artifact, stored in
~/.pioreactor/calibrations. This makes editing, creating, sharing, and transferring calibrations much easier. -
There's also a new CLI for calibrations:
Usage: pio calibrations [OPTIONS] COMMAND [ARGS]... interface for all calibration types. Options: --help Show this message and exit. Commands: delete Delete a calibration file from local storage. display Display the contents of a calibration YAML file. list List existing calibrations for the given device. run Run an interactive calibration assistant for a specific device. set-active Mark a specific calibration as 'active' for that device analyze Analyze the data from a calibration.For example, to run a pump calibration, use
pio calibrations run --device media_pump. View all your media pump calibrations with:pio calibrations list --device media_pump. -
For now, the actual calibrations are the same protocol as before, but in the near future, we'll be updating them with new features. Adding this unified CLI and YAML format was the first step.
- New API to retrieve and set clocks on Pioreactors
- GET
/api/units/<pioreactor_unit>/system/utc_clock - GET
/unit_api/system/utc_clock - POST
/api/system/utc_clock - POST
/unit_api/system/utc_clock
- GET
- New log APIs
- GET
/api/experiments/<experiment>/recent_logs - GET
/api/experiments/<experiment>/logs - GET
/api/logs - GET
/api/workers/<pioreactor_unit>/experiments/<experiment>/recent_logs - GET
/api/workers/<pioreactor_unit>/experiments/<experiment>/logs - GET
/api/units/<pioreactor_unit>/logs - POST
/workers/<pioreactor_unit>/experiments/<experiment>/logs
- GET
- New calibrations APIs
- GET
/api/workers/<pioreactor_unit>/calibrations - GET
/unit_api/calibrations - GET
/unit_api/active_calibrations - GET
/api/workers/<pioreactor_unit>/calibrations/<device> - GET
/unit_api/calibrations/<device> - PATCH
/api/workers/<pioreactor_unit>/active_calibrations/<device>/<cal_name> - PATCH
/unit_api/active_calibrations/<device>/<cal_name> - DELETE
/api/workers/<pioreactor_unit>/active_calibrations/<device>/<cal_name> - DELETE
/api/workers/<pioreactor_unit>/calibrations/<device>/<cal_name> - DELETE
/unit_api/active_calibrations/<device>/<cal_name> - DELETE
/unit_api/calibrations/<device>/<cal_name> - POST
/unit_api/calibrations/<device>
- GET
- New API for plugins
- GET
/api/units/<pioreactor_unit>/plugins/installed - PATCH
/api/units/<pioreactor_unit>/plugins/install - PATCH
/api/units/<pioreactor_unit>/plugins/uninstall
- GET
- Changed the
settingsAPI (see docs). - New
/api/unitsthat returns a list of units (this is workers & leader). If leader is also a worker, then it's identical to/api/workers - New
/api/experiments/<experiment>/historical_worker_assignmentsthat stores historical assignments to experiments - New Path API for getting the dir structure of
~/.pioreactor:/unit_api/system/path/<path>
- new SQL table for
historical_experiment_assignmentsthat stores historical assignments to experiments. - UI performance improvements
- Better terminal plots
- Customs charts in the UI are now downsampled like the other charts.
- More logging in experiment profiles
-
use_calibrationunderod_reading.configis deprecated. Use the calibrations "active" state instead. -
Note: by default, all calibrations are not active, even if they were "current" before. You must set them to be active.
-
removed Python library
diskcache. -
any stirring calibrations needs to be redone. On the command line, run
pio calibrations run --device stirringto start the calibration assistant. -
fixed typo
utils.local_persistant_storagetoutils.local_persistent_storage. -
Kalman Filter database table is no longer populated. There is a way to re-add it, lmk.
-
moved intermittent cache location to
/tmp/pioreactor_cache/local_intermittent_pioreactor_metadata.sqlite. This also determined by your configuration, see[storage]. -
removed
pioreactor.utils.gpio_helpers -
removed
calibrationsexport dataset. Use the export option on the /Calibrations page instead. -
persistent storage is now on single sqlite3 database in
/home/pioreactor/.pioreactor/storage/local_persistent_pioreactor_metadata.sqlite. This is configurable in your configuration. -
When checking for calibrations in custom Dosing automations, users may have added:
with local_persistant_storage("current_pump_calibration") as cache: if "media" not in cache: ...
This should be updated to (Note the spelling in
local_persistant_storagechanged, too!):with local_persistent_storage("active_calibrations") as cache: if "media_pump" not in cache: ...
- Fix PWM3 not cleaning up correctly
- Fixed Stirring not updating to best DC % when using a calibration after changing target RPM
- Fixed a bug that could cause OD calibrations to map a small voltage value to a max OD.
- Fixed bug where dataset exports were not sorted correctly.
- em-dashes are now replaced in config.ini on save.
- Fixed a bug where errors on the Experiment Profiles page weren't properly displayed.
- Hotfix for UI settings bug
- New export datasets improvements!
- new export dataset API. The datasets on the Export Data UI page are now provided via YAML files on the leader's disk. This makes it easy to add new datasets to that UI to be exported. These YAML files can be added to
~/.pioreactor/exportable_datasets. - new Export Data page in the UI. Preview datasets before you export them, and new partition options for the exported CSVs.
- Plugins can now add datasets to the Export Data page. The plugin's datasets are automatically added to the Export Data page when installed.
- new export dataset API. The datasets on the Export Data UI page are now provided via YAML files on the leader's disk. This makes it easy to add new datasets to that UI to be exported. These YAML files can be added to
- Stirring can now pause itself during an OD reading. This is accomplished by "dodging OD readings". You can activate this feature by setting the
enable_dodging_odtoTruein config.ini, under[stirring.config]. The replaces an older, less reliable plugin that was on our forums. Users have wanted this feature to have a very fast RPM between OD measurements (to get more aeration), and avoid noisy OD measurements. There's no reason to believe this will decrease the noise if using a "moderate" RPM though.
- improvements to Dodging background job code, including the ability to initialize the class based on dodging or not.
- better error handling for failed OD blank action.
- better button state management in the UI.
- a job YAMLs' published_settings can have a new field,
editable(bool), which controls whether it shows up on the Settings dialog or not. (False means it won't show up since it's not editable!). Default is true. This should align with thepublished_settingin Python's job classes. - you can add IPv4 addresses to the (new)
[cluster.addresses]section to specify IPs for pioreactors. Example:Note that the leader's address is automatically added in our software.[cluster.addresses] pio01=10.42.0.2 pio02=10.42.0.3 - new installs only: updated RPiOS to version 2024-11-19
- improvements to correlation self-tests
- Fixed "circulate X" actions in the Manage All dialog in the UI.
- moved all the temporary caches, which previously where their own sqlite3 dbs in
/tmp/to/tmp/local_intermittent_pioreactor_metadata.sqlite. This shouldn't break anything unless you update during an experiment - don't do that!
dosing_automation.vial_volumereplaced withdosing_automation.liquid_volume. You can see the values by watchingpio mqtt -t "pioreactor/+/+/dosing_automation/liquid_volume"after starting a dosing automation.- Adding a SQL table for tracking
liquid_volume. - Because we are now storing
liquid_volumein the database, you can add charts in the UI that track the volume over time:- Add the following yaml contents to
~/.pioreactor/plugins/ui/contrib/charts/liquid_volume.yaml: https://gist.github.com/CamDavidsonPilon/95eef30189101da69f706d02ef28d972 - In your config.ini, under
ui.overview.charts, add the lineliquid_volume=1.
- Add the following yaml contents to
- New dataset exports from the Export data page in the UI: calibrations and liquid-volumes.
- Added a "partition by unit" option to the Export data page that will create a csv per Pioreactor in the export, instead of grouping them all together.
- od calibrations can use the
--json-fileto edit calibration polynomial coefficients. In the json file, specifycurve_data_fields with values of the curve's polynomial coefficients (leading term first), and setcurve_typeas"poly". The routine will begin with that calibration curve displayed. - faster UI response times when starting jobs.
- faster syncing configs.
- faster copying files across cluster via
pio cp. - faster clean up of jobs using PWMs.
- new installs only: updated base RPiOS to 2024-10-22.
- new database table in
/tmp/local_intermittent_pioreactor_metadata.sqlitecalledpio_job_published_settingsthat stores the published settings for each job. This powers the next API endpoints: - New API endpoints for getting the current settings of a running job:
- Per pioreactor:
- GET:
/unit_api/jobs/settings/job_name/<job_name> - GET:
/unit_api/jobs/settings/job_name/<job_name>/setting/<setting>
- GET:
- Across the cluster:
- GET:
/api/jobs/settings/job_name/<job_name>/setting/<setting> - GET:
/api/jobs/settings/job_name/<job_name>/experiments/<experiment> - GET:
/api/jobs/settings/job_name/<job_name>/experiments/<experiment>/setting/<setting> - GET:
/api/jobs/settings/workers/<pioreactor_unit>/job_name/<job_name> - GET:
/api/jobs/settings/workers/<pioreactor_unit>/job_name/<job_name>/setting/<setting>Ex: query the temperature of a Pioreactor:curl http://pio01.local/unit_api/jobs/settings/job_name/temperature_automation/setting/temperature
- GET:
- Per pioreactor:
pio kill --name xis nowpio kill --job-name x- removed publishing published_settings metadata to mqtt. Ex
$properties,$settable,$unit,$datatypeare no longer being sent mqtt. This was never used, and just a bandwidth suck.
- fix for OD calibration graph showing "two lines" in the terminal display
- fix for updating over the internet when a Pioreactor is on a
A.devXorB.rcYrelease pio kill --all-jobswill no longer kill long-running jobs from plugins (specifically,logs2xjobs.)- updating the UI software won't prematurely stop any currently running activities
- correct ethernet mac address on RPi5s
- We weren't passing all the OS environment variables when jobs were started from the UI. This is fixed now.
- Fixed circulate media / alt. media in the UI.
- Fixed manual dosing updates in the UI.
- amount of data shown on charts is now a function of the OD sampling rate
- allow for showing more than 16 workers in a chart.
- Bug fix for "Manage all" that would start activities in all Pioreactors, whether they were in the experiment or not.
- Fix for bug when clicking a legend element it not hiding
led_intensity(i.e. changes to LEDs) now respect whether a worker is active or not.- Fix bug for UI crashing with "colors" error.
- If a worker is referenced in a profile, but is not part of the current experiment, the actions will not be schedualed for it.
- UI improvements to the experiment select box.
- Better clean up of configs when a worker is removed from the cluster.
- Improved UI loading time
- only show ipv4 in UI and in avahi aliases.
- fixed experiment profile plugin checks.
- fixed experiment profile display crashing the UI when editing plugins section.
pio clear-cacherenamed topio cache clearpio view-cacherenamed topio cache view- some more web API changes to endpoints that manage updates
- We no longer use
monitorto start jobs. This has a slowdown when changing LEDs or starting pumps, unfortunately, but generally better performance elsewhere. watchdogjob has been merged withmonitor.watchdogno longer exists.
- Workers now have a webserver on them. This is one of the largest architectural changes to Pioreactor, and lays the foundation for better plugin, version, and calibration cluster management, plus future features.
- As an example, in your browser, you can enter the url: http://some-worker.local/unit_api/jobs/running to see a list of jobs running on a worker.
- Note: there is no interactive user interface for workers, just a web API
- Previous actions that would involve SSHing from leader to a worker are replaced by web requests.
- fixed an issue where a calibrated OD reading would be mapped to max OD signal if it was too low.
- fixed an issue where the Pioreactor UI would lock up if trying to create a new experiment with an existing name.
- fixed Hours Elapsed not updating in Overview
- Lots and lots of web API changes. You'll want to review them on our docs: https://docs.pioreactor.com/developer-guide/web-ui-api
- We no longer recommend the Raspberry Pi Zero (the original Zero, not the Zero 2.) since supporting a web server + pioreactor functions is too much for a single core.
watchdogis neutered. It used to try to "wake-up" a job, but this was flaky and causing more problems than it solved.- removed python library dependency
sh - APIs that initiate a background task either return with the result, or return a task id that be be looked up at
/unit_api/task_status/. pios updatenow updates the UI too.
- Better MQTT re-connection logic.
- New
Manage Inventorymenu on the Inventory page that can be used for bulk actions. pio updateis a new command to update both the UI and app.- adding more network logs to
network_info.txt pioscommands now return quicker since they post to the workers servers and don't wait around. You can view the status of the worker's by using the output from including--json.
pio logsnow includes the UI logs (if run on leader).- introduce a new od_reading config,
turn_off_leds_during_reading, which enables / disables turning off the other LEDS during an OD snapshot. By default, it is set to 1 (enables). - leader-only Pioreactors also have a
config_<hostname>.localfile now. - a new top-level section in experiment profiles,
inputs, allows you to define parameters that can be used in expressions. This is useful if you are copy the same constant over an over again, and want a quick way to change it once. Example:
inputs:
growth_phase_temp: 37.0
stationary_phase_temp: 30.0
od_threshold: 1.6
common:
jobs:
temperature_automation:
actions:
...
- type: update
hours_elapsed: 12.0
if: ${{ ::od_reading:od1.od < od_threshold }}
options:
target_temperature: ${{ stationary_phase_temp }}
- type: update
hours_elapsed: 12.0
if: ${{ ::od_reading:od1.od >= od_threshold }}
options:
target_temperature: ${{ growth_phase_temp }}
- more resilience to "UI state" diverging from "bioreactor state". Often, this occurred when two jobs stared almost immediately (often a networking issue), and the last job would halt since it couldn't get the required resources, however any MQTT data would be overwritten by the last job. Now, multiple places in the request pipeline will reduce duplication and prevent two jobs from starting too close to each other.
- improved stirring clean up when stopped in quick succession after starting.
- if a network isn't found, the
monitorjob will not stall, but warn and continue. - fixed HAT warning for HAT-less leaders.
- the RP2040 firmware is now on i2c channel 0x2C (previously 0x30). This is to solve an annoying
i2cdetectissue where the i2c channel would lock up. - the web server now writes its logs to the same location as the app:
/var/log/pioreactor.log. Those wishing to keep the old location can use a new configuration parameterui_log_fileto[logging]section and set it to/var/log/pioreactorui.log. - removed
psutilandzeroconfPython packages from new images. We replaced their functionality with built-in routines. - in config.ini, the section
od_configrenamed tood_reading.config, andstirringisstirring.config. When you update, a script will run to automatically update these names in your config.inis.
- improvements to the UI's experiment profile preview.
hours_elapsed()is a function in profile expressions, which returns the hours since the profile started.unit()can be used in mqtt fetch expressions. Example:unit():stirring:target_rpmis identical to::stirring:target_rpm. The latter can be seen as a shortened version of the former.- experiment profiles can have a
descriptionin thejobfield (i.e. at the same level asactions). - Updated Raspberry Pi OS image to 2024-07-04.
- Vendoring the TMP1075 library, which also fixes the RPi5 error.
- In places where the ipv4 is displayed (Inventory page, System tab, pio workers status, etc), all ipv4 addresses are displayed.
-
remove the temperature_control, dosing_control, and led_control abstractions. These were introduced early in the Pioreactor software as a way to quickly change automations, but they have been more of a wort than a win. While working on the internals of experiment profiles recently, it became more and more clear how poor this abstraction was. The removal of them has some consequences and some backward incompatibilities:
-
updating experiment profiles: experiment profiles that have a
*_controljob will need to be updated to use*_automation, eventually. For now, we are allowing*_controlin profiles: in the backend, we are renaming*_controlto*_automations, but a warning will be produced. Later, we'll remove this renaming and profiles will need to be completely updated. Example:experiment_profile_name: start_temp_control metadata: author: Cam DP common: jobs: temperature_control: actions: - type: start hours_elapsed: 0 options: automation_name: thermostat target_temperature: 30 - type: stop hours_elapsed: 12 temperature_automation: actions: - type: update hours_elapsed: 6 options: target_temperature: 35
becomes:
experiment_profile_name: start_temp_control metadata: author: Cam DP common: jobs: temperature_automation: actions: - type: start hours_elapsed: 0 options: automation_name: thermostat target_temperature: 30 - type: stop hours_elapsed: 12 - type: update hours_elapsed: 6 options: target_temperature: 35
- update plugins. For users using, specifically, the high-temp plugin, or temperature-expansion-kit plugin, new plugins will be released. Look on the forums, or documentation, for update instructions.
The benefits of removing this abstraction is much less code, less overhead, easier developer experience, and overall simplification. Later, we may create a new abstraction, but now we are moving abstractions back to level 0.
login experiment profiles now uses expressions instead of Python string formatting. For example:The unit {unit} is running {job} in experiment {experiment}should be replaced by expressions in the string:The unit ${{unit()}} is running ${{job_name()}} in the experiment ${{experiment}}. Note:{job}is now${{job_name()}}.cycle_mediaandcycle_alt_medianow publish dosing events, and will be recorded by dosing automations, and the db.
- When pausing temperature automations, the heater now turns off and stays off until unpaused. This is the intended behaviour.
Hotfix release for 24.7.3. This pins blinka to a specific version which does not install numpy.
- A new live preview in the UI's experiment profile editor. This preview tool is useful for getting immediate feedback when writing a profile. We'll keep on adding to this to improve the edit-profile workflow - please send us feedback!
- new
whenaction type in experiment profiles that will execute an action (or list of actions) when some expression is true. For example, start a chemostat when a threshold OD is first achieved, log a message when event is triggered, or monitor a bioreactor parameter and execute an action if it goes out of bounds. - New config
turbidostat.configthat can be used to modify some internal turbidostat settings:[turbidostat.config] signal_channel=2 od_smoothing_ema=0.5 - Better user interaction on the Pioreactors page when the assigned experiment and "viewing" experiment are different.
- Select / Deselect all Pioreactors to assign to an experiment faster.
- Added
unit()function to experiment profiles expressions that returns the unit name the expression is evaluated for. Ex:if: ${{ unit() == worker01 }}. - Added
job_name()function to experiment profiles expressions that returns the job_name the expression is evaluated for. Ex:if: ${{ job_name() == stirring }}. - Added
experiment()function to experiment profiles expressions that returns the experiment the expression is evaluated for. Ex:if: ${{ experiment() == exp001 }}.
- significant web backend API changes! See list of rules in docs.
- Fix UI code editor from being unresponsive when all the text was removed.
- Experiment profiles won't be overwritten if providing the same filename as an existing profile.
- we changed the "auto" algorithm for picking a good
ir_led_intensity. We now try to maximize the intensity, up to some constraints around saturating ADCs, LED longevity, and signal. In general, we expect a higher IR intensity, but this will help with noise and detecting lower signals. - More improvements on the Pioreactor-specific page: added charts and a logs table.
- Added a "retry failed tests" to the UI's self-test dialog.
pio run self_testhas a new flag--retry-failedto only retry tests that failed in the previous run (if any).- better clean up when a worker is removed from a cluster.
- reduce the mosquitto logs to reduce writes to disk and speed up connections.
- Use lexicographical ordering for all displays of workers in the UI
- This only applies to new installed images, and not updates. Updated to the latest RPI image, 2024-03-15, -> linux kernel update to 6.6. Recent versions of linux have improved support for usb wifi devices.
- This only applies to new installed images, and not updates. leader-only images will install worker Python libraries.
- This only applies to new installed images, and not updates. all experiment data will be deleted when the experiment is deleted.
- performance improvements
- Changed the web backend API endpoints for time-series, logs, shutdown, reboot, and plugins to be more RESTful. See docs for updated rules in the docs.
- fix performing an "undo" when editing the config.ini and experiment profiles.
- fix Pioreactor v1.1 bug when change target temperature mid cycle causing the inferred temperature to change significantly.
- if a worker disconnected from the network, messages are queued in memory until the network reconnects. This has two problems. The first is that there is a finite amount of memory, and we don't want to OOM. The second is that when the worker(s) reconnect, there is a flurry of messages. For some jobs that use messages as events, this can cause multiple triggers in quick succession. We've added some logic that helps avoid these situations:
- we max the queue of unsent messages to 100 (arbitrary)
- in important jobs, like temperature automations, it will only respond to "recent" messages and not old messages.
- New /pioreactor/
worker-namepage in the UI for a detailed view of an individual Pioreactor, including a realtime visualization of the Pioreactor!
- UI backend now supports external MQTT broker. This configuration lives in the same place as the existing MQTT settings: in the config.ini, under
[mqtt]. - Added groupings on the Experiment drop down to organize "Active" and "Inactive" experiments. An active experiment has >= 1 Pioreactor assigned to it.
- New log topic that partitions by the level. This should make subscribers to the log topic slimmer (like the UI, who previously would have to accept all messages and filter to what they needed). Should result in a performance increase.
- Fix for Pioreactors page when no workers are added to the cluster.
- Fix for UI labels when trying to remove labels from Pioreactors.
- Improvements to REF self-tests.
- Significant performance increase by using
force_turbo=1in the Raspberry Pi. Expect a noticeable improvement in interacting with the Pioreactor. This pushes the Pi to always run "hot" (but we aren't overclocking). This does slightly increase the Pi's internal temperature, so be wary about putting the Pioreactor in very hot environment. This settings requires a reboot to take affect. - adding support for changing the port and protocol of the Pioreactor UI webserver in the software. Add the following to your config.ini:
This doesn't set the port and proto, that involves changing settings in the lighttpd configuration.
[ui] port=80 proto=http
- more sane defaults for OD reading for v1.1 when using
auto. - fix
pios plugins uninstall - fix leader not correctly being identified in
pio workers status - For RPi Zero W (first gen), sometimes the load_rp2040 script was failing. A new script will retry a few times. This only applies to new images.
- fix
pio workers update-activeusing the wrong HTTP verb. - Fix using ethernet cable to connect Pioreactor to a router: a new simple ethernet nmconnection has been added, and has higher connection priority than the PioreactorLocalLink nmconnection.
- Fix race conditions occurring between stirring and growth-rate when they were started too quickly.
- When the local access point would start on a fresh boot, the SSID would start as
pioreactor, and then change topioreactor-<leader-name>after the next reboot.
- UI chart legend's will support more than 8 Pioreactors.
- UI chart colors are consistent across charts in the Overview.
- reduce the severity of some messages, so there will be less pop-ups in the UI.
- UI performance improvements.
- Upgraded to React 18.3.1
- Removed unused dependencies
- UI's code sections use syntax-highlighting and other nicer features for editing yaml and ini files.
- App performance improvements
- Upgrade paho-mqtt to 2.1
- faster
pio kill - faster job start from UI
- more humane error messages.
- updated temperature inference model.
- added exponentiation
**to profile expressions. Ex:${{ pio1:growth_rate_calculating:growth_rate.growth_rate ** 0.5 }} - added
random()to profile expressions. This returns a number between 0 and 1. Ex:${{ 25 + 25 * random() }}
- fix
pio pluginsnot working on workers. - fix
enable_dodging_od=0for background jobs that can dodge OD. - fix PWM jobs not cleaning up correctly if too many jobs try to end at the same time.
- fix
pio killnot returning the correct count of jobs being killed. - fix older Pioreactor HATs, with the ADS1115 chip, not have the method
from_voltage_to_raw_precise. - fix "Manage all" not sending the correct dosing command to workers.
- initial support for Pioreactor 20ml v1.1! This is our latest iteration of Pioreactor. Even though it's a minor 0.x release, there's lots of positives about it. We encourage you to check out the upgrade kit here.
- some further support for tracking the model and version of the Pioreactor you are using. Users can change the version in the config file. For example:
If you have a mixed cluster (some 1.0, some 1.1), then you should put this configuration in the unit specific config files.
[pioreactor] model=pioreactor_20ml version=1.1 - For v1.1: New temperature inference algorithm makes reaching the
thermostatsetpoint quicker, and the Pioreactor can reach higher temperatures (our internal testing could easily reach up to 45C in a cool room). This algorithm uses the magic of ✨statistics✨. We may update the themostat PID values in the future, but the default ones work okay for now. A Pioreactor v1.0 update for this algorithm should come out soon, too.
-
When using
turbidostat, there is now a small moving average filter on the raw OD readings. This will prevent the turbidostat from firing when an OD outlier occurs. -
MQTT data is no long persisted between leader power-cycles. This was the cause of a lot of bad UI state issues where users couldn't interact with the Pioreactor via the UI after a power-cycle (intentional or not). We originally persisted the data since we previously used MQTT as more like a database, but our engineering style has moved away from that idea, and we now only use MQTT for "ephemeral" data. Taking out the persistent MQTT data forces this style change. Users shouldn't notice anything different.
-
The leader is now the source-of-truth for the cluster's clocks. For example, when a worker boots up, it will ask the leader what the time is, and will periodically continue asking. If the leader has access to the internet, it will pull the correct time (and periodically continue asking). If the leader doesn't have access to the internet, it will use the default time on the Pi. This solves the problem of workers' clocks getting out of sync when powered down, especially in a local-access-point network.
-
Lots of small UI improvements, including accessibility, empty-state, and loading improvements.
-
Previously, we would "kick" stirring by forcing the DC% to 100% for a moment, and then increasing the running DC% slightly. Going forward, we'll actually try the following when the sensor fails to read a signal: DC% to 0%, then DC% to 100%, and then a slight increase in the DC%. Why?
- If the mixing fan has stalled, setting the DC% to 0% does nothing, since the fan is already stopped.
- If the mixing fan is running, but the stir bar isn't in sync, this step will align the stir bar and fan again.
- If the mixing fan is running too fast, but the sensor isn't reading it, this allows for a small pause.
-
The recommend way to upgrade Pioreactors and clusters is now using release archives. We have more control over the upgrade process this way. However, users are still welcome use the command line,
pio update, which is what we use in house. -
A chart legend's in the UI now displays the entire name of the worker, if there is enough room.
- Temporary Pioreactor labels, set in the UI, are now unique across an experiment.
- config
max_volume_to_warnwas removed, it's now hardcoded as 90% ofmax_volume_to_stop
- Fix
pio ...commands that displayed the CLI options not working on workers. - Potential fix for heater continuing to be on after requested to be turned off.
- Faster app start-up performance, which should translate to faster response times.
- Log when workers change experiment assignments.
- Log when workers change active status.
- Adding
[pioreactor]section to config.inis - improvements to calibration charts
pio install-pluginis nowpio plugins install. Likewise foruninstall.pio list-pluginsis nowpio plugins list.pios install-pluginis nowpios plugins install. Likewise foruninstall.
- fixed Log table in the UI not showing all entries.
- fixed HAT button response in the UI.
- The Pioreactor leader can now support multiple experiments! If you have more than one Pioreactor, this change allows you to run multiple experiments simultaneously, assign Pioreactors to different experiments, and manage all experiments concurrently. No more multi-leader set ups - all you need is a single leader and multiple workers! See video here.
- Ability to delete experiments from the UI.
- Better control over your cluster, using the Inventory page in the UI.
- Ship with network configuration of local-link connections: plug in an ethernet from your Pioreactor to your computer, and after invoking
sudo nmcli c PioreactorLocalLink up, you should be able to visithttp://pioreactor.localin your browser.
- replace the
ipfile that is written to on startup with a newnetwork_info.txtfile that contains the hostname, IPv4 address, and MAC addresses. - Adding the ethernet (wired) mac address to the system tab.
- new Python module for controlling workers:
pioreactor.cluster_management - by default, for new installs, the local-access-point SSID is now
pioreactor_<hostname>. - UI performance improvements
- New database tables to handle workers (
workers) and experiments assignments (experiment_assignments). - New
pio workersCLI to mange your inventory. Trypio workers --helpto see all the commands available. - Better error messages when a self-test fails.
pio killhas new options to kill specific actions. Ex:pio kill --experiment this-exp,pio kill --job-source experiment_profile
- When a experiment profile stops early (i.e. via "stop early" in the UI), it now will halt any jobs that it started. This is a change from how they worked previously, but this new behaviour is less of a surprise to users.
pio add-pioreactor <name>is nowpio workers add <name>pio cluster-statusis nowpio workers statusutils.publish_ready_to_disconnected_statechanged names toutils.managed_lifecycleconfig.inventoryin the config.ini is no longer used. All that data is now handled in the database on the leader, and managed in the UI or CLI.pio kill <job_name>is removed, usepio kill --name <job_name>.
- fix for not being able to access
http://pioreactor.localreliably. - fix for multiple exporting datasets when selecting "All experiments"
- removing a Pioreactor leader from an experiment will stop any experiment profiles running that are associated to that experiment.
- For better consistency between Pioreactors, we've introduced a new configuration option that will automatically adjust the IR LED intensity to match a target value in the reference photodiode, at the start of OD reading. This means that if your IR LEDs are slightly different between Pioreactors, the IR LED output will be adjusted to match a hardcoded value. To enable this feature, change the
[od_config]config parameterir_led_intensityvalue toauto. For new installs, this is the default configuration. This shouldn't change your actual OD readings very much (since we normalize raw PD by REF, and increase or decrease in REF is balanced by increase or decrease in PD), but it will make analysis easier. - Significant UI performance improvements: we are use less MQTT clients, which should mean faster loading, less network overhead, and overall lower resource-usage.
- Fixes updating automations in experiment profiles
- reusing more MQTT clients internally => faster job startup and less network overhead
- using the archive upload method to update Pioreactors had a bug when distributing the archive to workers on the cluster. That has been fixed. The first time, you archive update may fail. But it should succeed the second time.
- fix UI bug that was preventing real-time data from showing up in some custom charts.
- fix UI bug that was causing a stale datum to appear in charts.
- To avoid downstream permission issues,
piocan't be run as root. That is,sudo pio ...will fail. - a typo prevented
od_config.smoothing_penalizerfrom being used internally. This is fixed. - some retry logic for fixing "lost" state in the UI.
- fixed numerous MQTT connections from accumulating in the UI
- Experimental introducing outlier filtering in growth rate calculations. This is tunable with the new
ekf_outlier_std_thresholdparameter under[growth_rate_calculating.config]. To turn off outlier filtering, set this parameter to some very large number (1000s). Don't put it less than 3.0 - that's silly. - With this new filtering, we can provide more reasonable values for the parameters of the growth rate Kalman filter. We previously had to artificially increase the measurement std. deviation (
obs_std) to allow for some outliers. This had the knock-on effect of hiding growth-rate changes, so we had to also increase that parameterrate_std. With better outlier protection in the model, we can move these values back. New installs will have the following parameters, and we encourage existing users to try these values if you plan to use the outlier filtering.
[growth_rate_kalman]
acc_std=0.0008
obs_std=1.5
od_std=0.0025
rate_std=0.1
- added configuration for alternative mqtt brokers with the new configuration
[mqtt] username=pioreactor password=raspberry broker_address= broker_ws_port=9001 broker_port=1883 ws_protocol=ws use_tls=0
- clear the growth-rate cache with
pio run growth_rate_cacluating clear_cache - added Pioreactor specific software version to the UI: Page Pioreactors -> Manage -> System -> Version. this requires a restart to display correctly
- new UI MQTT library. Is it faster? Maybe!
- increased the default
max_subdoseto 1.0.
- fixed a case where dosing automation IO execution would not run due to a floating point rounding error. Sorry!
- fixed a memory leak in long running dosing automations that had thousands of dosing events. Sorry!
- fixed a race condition that caused an error to occur when a software PWM channel was closed too quickly. Sorry!
- fixed bug that was partially crashing the UI if some bad syntax was entered into a custom yaml file. Sorry!
- fixed bug that was causing bad json from the server, causing empty / non-loading areas in the UI. Sorry!
- fixed
datumbug in the Overview that was crashing the UI. Sorry!
- boot-up performance improvements
- job start performance improvements
- improved RPM calculation for lower RPMs.
- Added buttons to the Overview UI to change common settings.
- profiles in the UI are sorted by their last edit time.
- Jobs can't run if
self_testis running - exporting
pioreactor_unit_activity_datano longer requires an experiment name to be included. - new config option:
samples_for_od_statisticsin[growth_rate_calculating.config]for specifying the number of OD samples to take for initial statistics. $can be used in expressions (this is used to specify the$statesetting).repeatdirective in experiment profiles.experiment_profile_name: demo_stirring_repeat common: jobs: stirring: actions: - type: start hours_elapsed: 0.0 options: target_rpm: 400.0 - type: repeat hours_elapsed: 0.001 while: ::stirring:target_rpm <= 1000 repeat_every_hours: 12 max_hours: 10 actions: - type: update hours_elapsed: 0.0 options: target_rpm: ${{::stirring:target_rpm + 100}}
- use expressions in
commonblock. Instead of the usualunit:job:settingsyntax, use::job:setting. For example:common: jobs: stirring: actions: - type: update hours_elapsed: 0.002 if: ::stirring:target_rpm > 600 options: target_rpm: ${{::stirring:target_rpm - 100}}
- fixed a bug in the chart of OD reading that was causing historical and realtime data to be different lines.
- fixed bug where a PWM wouldn't clean up correctly if the job was canceled too early.
- fix for self-test
test_REF_is_in_correct_position - accidentally appended text to the end of an old experiment profile in the last update. We've fixed that in this update.
- adding
ifdirectives to experiment_profiles, with dynamic expressions. See full docs here
...
stirring:
actions:
...
- type: update
hours_elapsed: 12.0
if: pio1:od_reading:od1.od > 2.0
options:
- target_rpm: 600- adding dynamic options via expressions, see full docs here
...
stirring:
actions:
...
- type: update
hours_elapsed: 12.0
options:
- target_rpm: ${{ pio1:stirring:target_rpm * 1.1 }}Breaking changes to experiment profiles:
-
the
commonblock requires ajobsblock. Previously:experiment_profile_name: demo_stirring_example metadata: author: Cam Davidson-Pilon description: common: stirring: actions: - type: start hours_elapsed: 0.0 options: target_rpm: 400.0Now:
experiment_profile_name: demo_stirring_example metadata: author: Cam Davidson-Pilon description: common: jobs: # this text is required stirring: actions: - type: start hours_elapsed: 0.0 options: target_rpm: 400.0 -
labelshas moved into thepioreactorsblock. Previously,experiment_profile_name: simple_stirring_example labels: worker1: PR-001 metadata: author: John Doe description: pioreactors: worker1: jobs: {}Now,
experiment_profile_name: simple_stirring_example metadata: author: John Doe description: pioreactors: worker1: label: PR-001 jobs: {}Related, you can't use the label as an alias in the
pioreactorblock.Need a hand updating your profiles? Let us know, support@pioreactor.com!
- removing
ODReadings.latest_od_readingand it's replaced byODReadings.ods. - removed the topic
pioreactor/{unit}/.../od_readings/od/{channel}. Usepioreactor/{unit}/.../od_readings/od1orpioreactor/{unit}/.../od_readings/od2. This change was made to fit more and more published data into the same format (and it makesod1andod2published settings onODReader)
ods,od1,od2now a published settings ofODReadings.- when a worker is first turned on, and pre-connected to a cluster, the LED is turned on to give some feedback to the user.
- using the 2023-12-11 RPi base image
- fixed the UI crashing if trying to edit a blank experiment profile
We've released new 64 bit builds, and a 64 bit "headful" build. These builds are experimental, and require a RPi4, RPi5, or RPi400 due to their larger memory requirements.
- 64 bit leader-worker and worker builds will be marginally more performant, at the cost of some additional memory consumption.
- The "headful" leader-worker build allows you to attach a monitor, keyboard, mouse, etc. to the Raspberry Pi and use it as an interface for your cluster.
These builds are available only on our nightly page.
- optimized performance and memory consumption of experiment profiles.
- fix initial state of boolean switches in UI.
- fix Raspberry Pi 5 not addressing PWMs correctly.
- Initial support for RPi5! To use an RPi5, we recommend not upgrading the software, but using a fresh image install. Under the hood:
- we are using a new route to load the firmware on the HATs RP2040 (using
linuxgpio) - the hardware PWMs on the RPi5 use a different chip location. This required a new
rpi_hardware_pwmrelease.
- we are using a new route to load the firmware on the HATs RP2040 (using
- new ENV variable,
HAT_PRESENT=1, can be set to skipis_HAT_presentchecks. - added the RPis unique MAC addresses to the
Manage -> Systemtab on the Pioreactors page. - added table
ir_led_intensitiesto be able to be exported on the Exports page. - added a new
smoothing_penalizerconfig option to[od_config]. This parameter, which has default value 700, controls how much smoothing to apply to optical density measurements. This smoothing has always been applied, but now it's a config option. - Cleaned up some UI interactions
PWMclass is no longer initialized with aduty_cycle, instead:PWMclass must be started withstart(initial_duty_cyle)- moved
get_rpi_machinetopioreactor.version
- Ack! I reintroduced a UI export bug. Fix is present going forward. For existing users, try the following: https://forum.pioreactor.com/t/new-pioreactor-release-23-11-18/179/2
- fixed a bug where stirring DC would jump up too high when RPM measured 0.
- Improvements to OD calibration and pump calibrations. Both now have a
-foption to provide a json file with calibration data, to skip rerunning data-gathering routines. For example:pio run pump_calibration -f pump_data.json. - Ability to update via our release_archives (available on the Github release page) via the UI. To turn this feature off (which is a recommended practice when you expose your UI publicly), add an empty file called
DISALLOW_UI_UPLOADSto the~/.pioreactordirectory. - A new config option to change the max volume to dose when a larger dose volume is split. For example, if your chemostat asks to dose 1.6 ml, our internal algorithm will dose 0.75, 0.75 and 0.1 (this is to avoid overflow). The 0.75 was previously hardcoded, but is now a config
max_subdoseunder section[dosing_automation.config](default is still 0.75 ml).
- Changes to
types.DosingProgram, now it requires an MQTT client. Usually this isautomation.pub_client. This is to avoid a memory leak!
- Fixed an problem where an automation would not successfully end due to it being "blocked" by a
whileloop in theexecute. - Fixed a memory leak in dosing control when the automation would pump many many times.
- fix for exporting data from the UI
- Merged the turbidostat automations into one. You can either select to target nOD or target OD, but not both!
ws_urlin the configuration now requires a fully qualified url. Example:ws://...orwss://....- Removed
morbidostatdosing automation, users should try to use pid_morbidostat. The morbidostat code is still available to be added as a custom plugin here: https://github.com/Pioreactor/automation-examples/blob/main/dosing/morbidostat.py - Removed
constant_duty_cycletemperature automation. Again, the code is available here: https://github.com/Pioreactor/automation-examples/blob/main/temperature/constant_duty_cycle.py pid_morbidostatnow explicitly uses the keyword argtarget_normalized_od, instead oftarget_od. It always has been nOD.
- Both "Target OD" and "Target nOD" displayed and editable in the UI.
- Previously, if the LED channel was locked (most common when OD reading was running), then any changes to the LED intensity (via the UI) would be silently rejected. This is changed: we have added retry logic that will attempt to keep changing it a few more times (hopefully to avoid the lock)
- Added some light form validation in the automations dialog in the UI.
- New environment variable to skip loading plugins,
SKIP_PLUGINS. Useful for debugging. Ex:SKIP_PLUGINS=1 pio run stirring - elements in the
fieldarray in automation yamls now can include atypeoption (numericorstringfor now). Default isnumericif not specified.
- Fix experiment profile validation error
- The "Stop" button is always available now in the "Dosing" tab for "Manage all Pioreactors".
- Fix for Ngrok remote access.
- Fixed a race condition between starting an automation and not getting OD data in time.
- The automation form in the UI for pid_morbidostat was missing
volume, that's been added now.
- No more waiting around for growth-rate-calculating to get to "Ready" state
- The "Label" step in the New Experiment flow is skipped if there is only 1 active Pioreactor in the cluster.
- Silenced the "LED is locked" warning - now it's a DEBUG level message.
- Fixed bug that wasn't passing lists correctly in
TopicToParserToTable - Faster boot times.
- Faster UI load times by gzip-ing assets.
- Fixed a bug where a plugin would not be loaded if it's name collided with a module in the stdlib. For example, putting
test.pyin.pioreactor/pluginswould not be loaded, since when we tried to importtest, it would load the stdlib'stest, not the local plugin. This has been fixed. - Simplify some UI elements.
- Security improvements.
- Reduce the default LED intensity in
light_dark_cyclefrom 50% to 5%. This is more appropriate for sparse cultures. - Fixed a race condition when starting a hotspot with boot config.ini.
- changed how
is_HAT_presentdetermine is the HAT is on the Pi. Previously, it used the i2c bus to check if the RP2040's firmware was active. This would fail if the HAT was present, but the firmware or i2c wasn't working. Now we check the EEPROM, which is a much more robust test.
-
fix bug in
timeoutinStirrer.block_until_rpm_is_close_to_targetthat wasn't using time correctly. -
Workers can now also be the local-access-point (aka the "router" in a network). Previously only leaders could.
-
Experiment profiles now support a
logdirective with some dynamic templating:- type: log hours_elapsed: 0.025 options: message: "{job} increasing to 800 RPM" # alerts the message: "stirring increasing to 800 RPM"See full example here.
-
Experiment profiles now supports changing LEDs like any other job (i.e. they can use
start,updateandstopdirectives). See example here. -
Experiment profile clean up. I think there are less bugs!
-
pio clear_cachenow has anas_intoption to look for ints - useful when clearing caches with ints as keys. -
fix issue where if an extra config.ini was provided in the /boot dir before a worker startup, adding the worker to a cluster would fail due to a permission issue.
-
potential fix for RPi 3B and RPi Zeros not connecting to hotspots: change the
prototowpain your config.ini on the Pioreactor with the local-access-point, and restart that Pioreactor. You config.ini should look like:[local_access_point] ssid=pioreactor passphrase=raspberry proto=wpaChanging to WPA does weaken the security however! It's easier for unwanted users to get onto this wifi.
A more robust solution is in the works for RPi 3B and Zeros.
-
Slight change to the API initialization of ADCReader. Take a look if you were using that class.
The Raspberry Pi Foundation provides new operating system every few years (built off of Debian's work). Earlier this month, they released RPi OS Bookworm. There are lots of nice changes, but the important details for us:
- New Python version
- New GPIO libraries
- New local-access-point improvements
We strongly recommend you upgrade to this release. However, upgrading to this new operating system requires a full SD rewrite. See steps below on how to preserve and transfer your data.
With some other optimizations, we have significantly improved the performance and responsiveness of the Pioreactor software. You should notice things will feel snappier! For example, the command-line responsiveness is about 33% faster, which means actions from the the UI will start faster. Because of this new performance, we can even squeeze some more data into our algorithms and get improved accuracy.
Along with Python being faster, our database is also faster now => faster inserts, UI graphs, and data exports.
Note: you don't need to do this. This is only if you want to move existing data to the new Pioreactor.
See instructions here.
- Replaced
RPi.GPIOwithlgpio - Python 3.9 is replaced by 3.11
- Ability to choose the x-axis scale in the UI Overview: clock time, or elapsed time. Use (or add)
time_display_modeunder section[ui.overview.settings], with valuesclock_timeorhoursrespectively. - Fixed bug that was not clearing OD blanks from the UI
- dropped RaspAP for a native solution. The native solution is much simpler, and should show up faster than our RaspAP solution.
- If your leader Raspberry Pi has an ethernet port, you can connect this into an internet-accessible router and give your cluster access to the internet!
- Updated lots of our Python dependencies
- Improved start up time by hiding dependencies
- Added database table to track experiment profile starts.
- Web server was crashing on start! Solution was to upgrade flask.
- Fix bug that wasn't allowing for manual dosing / LED updates.
- Fix bug that was disconnecting workers with using "stop all activity" in the UI when pumps were running.
pios updatenow has a--sourceparameter.
- Fix an OD calibration bug that would produce an extremely high value when the signal was below the minimum signal (the blank) during OD calibration.
- IPv4 is really IPv4 now.
- Adding ability to install plugins by name via the UI.
- New tools to update Pioreactors on a local access point. More docs coming soon!
- New
turbidostat_targeting_oddosing automation. This is just like the existingturbidostat, but targets the raw OD instead of normalized OD. This is most useful post-OD calibration. - In the UI, the dosing automation "Turbidostat" has been renamed "Turbidostat Targeting nOD"
The previous change:
- Base automations now subclass from
pioreactor.automations.BaseAutomationJob. You may need to change custom automation imports from, for example,from pioreactor.automations import DosingAutomationJobContribtofrom pioreactor.automations.dosing.base import DosingAutomationJobContrib
had an import error that we didn't see in testing. We changed this to:
- Base automations now subclass from
pioreactor.automations.base.AutomationJob. - Fix bug on /updates page.
- When installing plugins, any leader-only commands would not be run. This is fixed.
- Base automations now subclass from
pioreactor.automations.BaseAutomationJob. You may need to change custom automation imports from, for example,from pioreactor.automations import DosingAutomationJobContribtofrom pioreactor.automations.dosing.base import DosingAutomationJobContrib - Fixed bug that ignored
.ymlfiles in the UI. - Improvements to experiment profiles, both in the UI and in the backend. Executing now verifies common mistakes in experiment profiles before it runs.
- Fixed a bug that could cause controllers to have a disconnected automation. #422
- SPI is on by default on all new image installs
- Plugin author information is presented on the
/pluginspage in the UI.
- Pioreactor's IPv4 and hostname is now displayed under System in the UI.
- In configuration, renamed section
dosing_automationtodosing_automation.config(only applies to new installs). It's recommended for existing users to make this change, too. - new safety check that will stop automated dosing if vial liquid volume is above 18ml during dosing. This can be changed with
max_volume_to_stopunder[dosing_automation.config] - New configuration option
waste_removal_multiplierto run the waste pump for a different multiplier (default 2), under[dosing_automation.config] - A warning will appear if the reference PD is measuring too much noise.
- added another self-test test to confirm that an aturbid liquid in vial will produce a near 0 signal.
- general improvements to self-test
- New CLI command:
pio clear-cache <cache> <key>to remove a key from a cache. - New CLI subcommand
deleteofpio run od_blankto remove the current experiment's blank values. This is also exposed in the UI.
- Using builtin PID controller logic, instead of a 3rd party library. This shouldn't require any updates to PID code or parameters.
- Better error handling when the PioreactorUI API can't be reached.
- Some initial support for Basic Auth in the PioreactorUI
- improved sensitivity of self-test
test_REF_is_in_correct_position. - executing experiment profiles now checks for required plugins.
pio rmnow asks for confirmation before executing.- Some minor noise reduction in OD reading job.
- Plugins can be built with a flag file LEADER_ONLY to only be installed on the leader Pioreactor.
- Stirring now pauses and restart during OD calibration. Thanks @odcambc!
- Breaking: Light/Dark cycle LED automation uses minutes instead of hours now! Thanks @c-bun!
- The UI now offers a way to upgrade to the bleeding-edge Pioreactor app and UI software, called "development". This software is unstable (and fun!).
- Improved temperature inference accuracy.
- After some testing, we've found that the following set of PID parameters for
temperature_automation.thermostatworks better¹ than the previous set of parameters:
Kp=3.0
Ki=0.0
Kd=4.5
This set now ships with all new installations of Pioreactor software. Existing users can update their parameters in the config.ini
¹ Better == less thermal runaways, less sensitive to shocks, similar overshoot and settling time.
- On startup, the Raspberry Pi will write its IP address to a text file
/boot/ip. This means that if you (carefully) remove the SD card, you should be able see the IP address (hopefully it hasn't changed). - Fixed
sourceinBackgroundJobContrib- thanks @odcambc! pio add-pioreactorwill now accept an option that is the password of the RPi being added (default:raspberry). Ex:pio add-pioreactor worker1 -p mypass- Improved some warning and error messages.
- Improved watchdog detecting and fixing "lost" Pioreactors.
- Starting to test software against Python 3.11, in anticipation of a Python 3.11 coming to Raspberry Pi OS.
- Improvements to bash scripts to make them more robust.
- Adding
pios rm <filepath>to remove a file across the cluster. - Adding
-roption topio update. Example:pio update <x> -r <repo>to install from a repo (default is Pioreactor's repos). structs.ODCalibrationhas a new schema,inferred_od600sis nowod600s. Seepioreactor.structs.
- Support for viewing, starting and stopping experiment profiles in the UI!
- Adding manual dosing adjustment form under Dosing tab in the UI!
- New API for experiment profiles:
pio run experiment_profile, with subcommandsexecuteandverify. So what use to bepio run execute_experiment_profile <filename>is now:pio run experiment_profile execute <filename>. Theverifysubcommand is for checking the yaml file for errors. - new leader CLI command:
pios cp <filepath>will move a file on your leader to the entire cluster. This is useful for distributing plugins and Python wheels across your workers. - plugins can now add
post_install.shandpre_uninstall.shbash scripts. - added
[stirring]optionduration_between_updates_secondsto config, default is 23.0. - PIDMorbidostat has a configuration parameter
[dosing_automation.pid_morbidostat].minimum_dosing_volume_ml(default 0.1). If a calculated volume to be dosed is less than this parameter, then it's set to 0.0 instead. - adding
--manuallyflag to pump actions, ex:pio run add_media --ml 1 --manually. This doesn't run the pump, but still fires a dosing event, which downstream jobs listen to (ex: saves to database, will update metrics). See next change:
- UX improvements to
pio run pump_calibration monitoris more robust, so as to give users better access to information instead of hard-failing.monitornow checks for access to web servicemonitornow checks the voltage on the PWM rail and will alert if falls to much. If not using the an AUX power supply, this is directly tied to the RPi's power supply.monitoralso publishes the read voltage as a published setting. This is available in the /pioreactor card under System in the UI.- sqlite3worker is now vendored in the core app. This means we can publish on PyPI.
- improved
systemctlstart up. - added
[dosing_automation]section to config.ini (existing users will have to add this manually), with an optionpause_between_subdoses_secondsto control how long to wait between sub doses (these are the smaller doses that make up a larger dose, i.e. 0.5ml + 0.5ml = 1.0ml). Default is 5 seconds
Also shipping this version is early support for experiment profiles. What are they? They are "scripts" that will start, stop, pause, resume, update jobs and actions without user interaction. They are defined with a yaml file, according to the following spec (subject to change):
For examples of yaml files, see the repo: https://github.com/Pioreactor/experiment_profile_examples
To use a profile, save the yaml file to your leader Pioreactor. Run it with pio run execute_experiment_profile <path_to_yaml>. Note that killing the execute_experiment_profile will only stop execution of upcoming actions, and won't stop any jobs that have already started from the profile.
- improved detection of under-voltage, and power supply problems.
- pumps will halt if a MQTT disconnect occurs. This is to prevent the edge case when pumps are running on a worker, but not controllable from the UI due to an MQTT disconnect.
- improvements to backing up the SQLite3 database.
- improvements to self-test "Reference photodiode is correct magnitude"
- fix bug in
pio run od_calibration list
pio update appwill default to installing the succeeding release of Pioreactor app, which may or may not be the latest. This is to ensure that no update script is skipped.- Added new "Past Experiments" page
- Fix for "Reference photodiode is correct magnitude" self-test.
- Job growth_rate_calculating will dynamically choose initial values for its internal statistics.
- New entry in
stirringsection in config.ini:use_rpm(a boolean) can be used to engage or disengage the closed loop RPM system. - Calibration structs change
timestamp->created_at. - Backend work to complete calibrations utilities:
- Edits to the
calibrationstable in the database require a full drop and recreation. - New API endpoints on the webserver to store calibrations, get calibrations, set as current, etc.
- New CLI:
pio run <x>_calibration publishwill publish a calibration to the webserver
- Edits to the
- Python files in
plugins/folder on leader are viewable on the /plugins page in the UI. - Python files in
plugins/folder on leader are uninstallable (aka deleted) on the /plugins page in the UI. pio uninstall-pluginwill delete Python plugins in the .pioreactor/plugins/ dir if provided the python file name, sans.py.pios rebootshould now work for the leader.- Using the Pioreactor with an ethernet connection will provide the correct ip address.
- files in
~/.pioreactor/pluginsare now loaded lexographically. Previously it was up the the filesystem. - Performance improvements for PioreactorUI
- Added new indexes to the SQLite database to improve read performance. This change will only impact new installs of Pioreactor.
- Improvements in error handling when plugins can't load.
- fixed bug in adding new pioreactor not passing an avahi check.
- Removed the scaling difference between hardware versions in OD Reading.
- Moving some Python dependencies into this repo.
- More error handling around hardware versions
- fix
self_test.test_ambient_light_interferencetest failing for HAT 1.1.
- fix bug in ending experiments not cleaning up automations properly.
- Performance improvements
- Python dependencies for Pioreactor UI are now handled by this project.
- Better initialization of jobs from UI
- Version information now presented in UI
- More support for HAT version 1.1
- more Linux permission updates.
- Refactor internal pumping code. There's more flexibility that allows for solving parts of #384. Including:
- creating cleaning scripts
- creating cycling scripts, that also respect the rates of specific pumps vs waste (so that you don't overflow if addition rate > removal rate)
- Namely, new functions
circulate_mediaandcirculate_alt_mediaare introduced that will cycle both a pump and the waste pump simultaneously. The waste pump starts first and ends second. - removed the dosing automation
continuous cycling. It was redundant, and a leftover from an old feature.
- Fixed
pio kill <job>to actually kill a job - Fix for running PID morbidostat
- Fix "End experiment" killing all jobs.
- Fix
pio view-cachenot working outside the home directory. - Fixes for hardware HAT version 1.1.
led_intensitycleans itself up better.
- Fix error in growth rate calculating job that prevented it from starting.
- Watchdog job now listens for new workers that join the network and are not part of the cluster. A NOTICE message is logged and sent to the UI.
- Initial API support for adding more pumps to the Pioreactor. See docs here.
- Time series charts are now able to be added the the UI via
contribfolders. Put a yaml file under~/.pioreactor/plugins/ui/contrib/charts. See examples here. - New roll-up table available to be exported from the UI: Pioreactor unit activity data roll-up. This is a rolled-up of Pioreactor unit activity data rolled up to every minute, so it should be about one order of magnitude less data versus the original table.
- Pioreactor UI has a more RESTful API, so some internal urls have changed. See full new API here. UI version >= 23.2.0 required.
SummableListis replaced withSummableDictexecute_io_actionreturns a dictionary now (instead of a list).- Config: Removed
daily_growth_ratefrom[ui.overview.settings] - Config: Added
implied_daily_growth_rateunder[ui.overview.charts] - Dropped
pio run-always. Jobs just usepio runnow.
- Fix
dosing_eventstable not be populated caused by an incorrect SQLite3 trigger. - Running a pump continuously will produce MQTT events with new timestamps (previously it was the same timestamp.)
- Faster loading for some pages in Pioreactor UI
- Fix for RaspAP not turning on when requested using
local_access_pointfile - Caching in Pioreactor UI is improved.
- systemd services should boot in an even better order
- Bug fixes
- New 64bit images are available on the CustoPiZer release page. Default is still 32bit until more testing can be done.
- fix
pio updatebugs - new config for
[logging]section,console_log_levelwhich control which level of logging to show on the command line (does not effect logs in the database, or disk) - systemd services should boot in a better order
- the latest experiment from the database is always the most recently inserted experiment, ignoring the created_at column (i.e. we use ROWID). This is to avoid cases where users change times (or use a local access point).
- Fixes for
fraction_of_volume_that_is_alternative_mediachart in the UI
- fix
pio updatebugs
- early support for HATs with Pico hardware
- new modules
pioreactor.util.adcsandpioreactor.utils.dacsto abstract DACs and ADCs. pio updatehas a new api:pio update app <options>,pio update ui <options>.- added version of UI & firmware to
pio version -v - PioreactorUI has a different way to update, rather than using git. We now version the PioreactorUI, so it's easier to know if which version is being used.
pio update appnow has a--versionoption to specify a version of the Pioreactor software.pio update uinow has a--versionoption to specify a version of the Pioreactor UI.- power-saving improvements
- image size optimizations
- simplify logging, and avoid an eventual recursion error.
sourcein logging events is now correct.- experiment data is no longer published to MQTT. The source of truth is the db, via the web API.
- correctly publish
alt_media_fractionto MQTT in dosing jobs - dosing automations now keep track of vial volume, as attribute
vial_volume. This is also published to MQTT. - corrections to how
alt_media_fractionis calculated. It no longer assumes constant vial size, which was producing slightly incorrect results. execute_io_actionhas been changed to add the same ratio of media and alt_media before removing liquid. This satisfies:- If users asks to dose X, X will be dosed.
- Ratio between media and alt_media is constant between remove_waste actions.
- Not more than Y volume is added before liquid is removed. The catch is that if there is a lot of volume of one being added, and only a little of another, it's possible that accuracy of the latter one will be affected.
- users can now provide the initial ratio of media to alt_media (not yet from the UI or config.ini).
- users can specify, in their config.ini under section
bioreactor, valuesmax_volume_mlandinitial_volume_ml. The former is used to provide the stable limit of volume (i.e. the position of the outflow tube determines this). The latter is how much volume is in the bioreactor initially. This is useful for users who wish to add medias manually.
- fix for chemostat
- Remove some errant debugging statements
- Reduce MQTT's load on the leader by tuning the keepalive interval to something larger (for less sensitive connections).
pio rebootwill now work on leader, but will happen last.- More strict msgspec Structs
- fix od_blank error
- Added a last will to actions that will fire if the action disconnects ungracefully.
- Better handling of LED flashing from error codes.
- Support latest HAT version 1.0
- Serial number is available under
pioreactor.version.serial_number - Serial number is also printed with
pio version -v
- Fixed config.ini not being update in the UI.
- Fixed bug in adding worker to cluster
pio add-pioreactornow returns an error signal if the addition failed.- remove testing data from being added to database
- Improvements to UI
- Fix bug in leader's firstboot.sh
- Fix bug when temperature is changed too quickly in
thermostat
- PWM DC% changes are logged to MQTT under
pioreactor/<unit>/<exp>/pwms/dcas a JSON value (similar to LED intensities). - The pioreactor cards in the UI display the PWM DC %.
- user defined callbacks in ODReader have changed to be bound methods on the class (hence, you
can use
selfin the callback.) - New SQL table
pwm_dcs. - Performance improvements to the UI
- Adding authentication on mosquitto, the MQTT broker running on leader.
- Replace dbm with disk-cache in core. Benefits: makes storing types easier, comparable performance to dbm, promises of process-safety and thread-safety, align all datastores to sqlite3.
- Some caching in the UI now for common API calls.
- Improvements to UI
- Fixes for UI
- Smoother transitions in UI
- new ENV variable
LOCAL_ACCESS_POINTthat represents if local access point is online
- Fix bug in UI that wasn't letting users update software
- during
pio update --app, we now check for additional files in the github release that are to be executed. This provides a path of upgrading non-Python things. - Improvements to PioreactorUI
- Removing
parentfrom BackgroundSubJob - Make thermostat heuristic slightly better
- fix bug in OD Calibration
- If the ADC has an offset (due to hardware, or ambient light), it will now be removed from all inputs before being processed in OD Readings.
- Fix bug where users are not able to start a job.
- Revisit pump and od calibrations. Some changes to the CLI.
- Some improvements to stirring calibration.
- Fix stirring calibration not responding in the UI
- Fix uninstall plugin bug
- Fix booleans not showing correctly in the PioreactorUI
- removed the dbm storage
pio_jobs_running. Instead, each job will write metadata about its currently running state to the (tmp) filejob_metadata_<job_name>. This fixes issue #350. - Fixed UI issue where specific configs weren't being saved.
- no-op release
- no-op release
BackgroundJobWithDodgingnow looks for the config.ini section[<job_name>.config].
- New API for adding SQL tables via plugins, and for registering MQTT -> DB parsers.
- New topic for experiment name in MQTT:
pioreactor/latest_experiment/experiment. - New topic for experiment timestamp in MQTT:
pioreactor/latest_experiment/created_at. stablerenamed tothermostat- new callback API for pushing the HAT button down, see
Monitorclass.
- improve reliability of self-test
test_REF_is_in_correct_position - improve the early OD reading signal behaviour.
- new API on jobs for
job_name(class level now)
- The SQL triggers were not added to the images, so
pioreactor_unit_activity_datawas never populated. This is fixed. - New web server backend. Went from js/Node to python (Flask)/lighttp.
- Export datasets now cleans up its csvs.
- Bug fixes
- temperature automation
silentis nowonly_record_temperature. - using new official RPi image from 2022-09-06 as a source image.
- Bug fixes
- added subcommands
display_current,change_current,listto pump calibration - Pump calibration follows the same format as LED calibrations. Current calibrations can be replaced with previous.
- Adding calibration curves to calibrations'
display_current pio run export_experiment_datanow has an flag argument to partition csvs by unit.- pump calibrations are now keyed by
media,waste,alt_mediain storagecurrent_pump_calibrations - Dosing automation have access to
latest_odnow. - Bump plotext.
local_ac_hzis now optional- maybe fix bugs for local AP
- add retries for button detection
- Stirring now has the ability to restart itself if it detects it has stalled.
- od_normalization has been removed. Instead, there is a small routine
od_statisticsthat is called by bothod_blankandgrowth_rate_calculating. The latter also now stores the required od statistics to storage (previous it was theod_normalizationjob). - The LEDs in the pioreactor have been moved up 0.5mm.
- Error-handling and user improvements to
pump_calibration. pid_turbidostatwas removed, replaced with the simplerturbidostat.- Adding new table
pioreactor_unit_activity_datathat makes analysis much easier. - Adding new table
calibrations. - New action
od_calibrationthat easily allows you to add an OD600 calibration to your pioreactor. See docs: https://docs.pioreactor.com/user-guide/calibrate-od600 - paramiko library is no longer a dependency
- in
growth_rate_calculatingjob,kalman_filter_outputsis now included inpublished_settings - Fix bug that wasn't saving automation events to the database.
- new function
voltage_in_auxthat measures what voltage is in the AUX. od_readings_rawdb table renamed tood_readingsod_readings_raw.od_reading_vrenamed tood_readings- Changes to
structs.ODReadingsandstructs.ODReading - Changes to where job
od_readingpublishes data in MQTT: now.../od_reading/ods/and.../od_reading/od/<channel> - Rename
latest_odproperty in all automations tolatest_normalized_od. Later we will introducelatest_odwhich refers to data directly from od_reading job. turbidostatautomation now acceptstarget_normalized_odinstead oftarget_od. Likewise forpid_morbidostat.- new config option under
od_config:use_calibrationis a boolean to ask the od_reading job to use the current calibration or not. PIDTurbidostatautomation has been nuked completely.- New base background job,
BackgroundJobWithDodging, that makes it easy to change an action during od reading
- Subtle changes to how jobs disconnect and clean up.
job.set_state("disconnected")won't clean up connections to loggers, MQTT, etc, but will signal to the app that it's no longer available to use. - In
config.ini,ir_intensity->ir_led_intensity - caches that keep state (like
led_locks) now use absence and presence to determine state, instead of specific value in the cache. network.inventory->cluster.inventorynetwork.topology->cluster.topology- sql table
experiments.timestamp->experiments.created_at - sql table
pioreactor_unit_labelshas new columncreated_at - Added
TMPDIRthe env variables, which points to/tmp/ - Aided development on Windows machines
- Added new LED automation:
light_dark_cycle. This allows for LEDs to follow a day/night cycle, at a specific LED intensity. - Leader now accesses other machines always using the
.localTLD. - New config option
local_ac_hz - New self-test routine that checks if the REF is in the correct PD channel.
- IR REF now uses a moving average of the first few values, instead of only the initial value. This produces much more accurate normalization values.
- You can now edit the config.ini without having to boot a Pioreactor. By adding a file called
config.inito thebootfolder when the SD card is interested in a computer, the/boot/config.iniwill be merged with the Pioreactor'sconfig.ini. This is useful for changing settings before ever starting up your Pioreactor for the first time. See below. config.iniis now the place where the local-access-point's SSID and passphrase are stored.- new
piocommand on leader:pio discover-workersreturns a list of workers on the network (may be a superset ofinventoryin the config.ini) - new
pioscommand on leader:pios reboot. Reboots all active workers in the cluster. - self-test tests run in parallel
- Adding
NOTICElog level, which will appear in the UI. - New schemas for
kalman_filter_outputsandod_blankstables in the db.
- table
led_eventsis renamed toled_change_events - automation events returned from
executeare published to MQTT under the published settinglatest_event - new tables
led_automation_events,dosing_automation_events,temperature_automation_events pioreactor.automation.events.Eventrenamed topioreactor.automation.events.AutomationEvent. The have a second kwarg that accepts a dict of data (must be json-serializable).- new leader command
pios reboot: reboot RPis on the network, optionally specific ones with--unitflag. - new CLI tool:
pio log -m <message>which will post a message to the pioreactors logs (everywhere). Example: this is used internally after systemd finish to log to our system.
- Added ability to add callbacks to ODReader. See
add_pre_read_callbackandadd_post_read_callback. - Fix bug associated with user changes.
pio logsno longer uses MQTT. Also, it now prints their entire log file.- BETA: testing shipping with access-point capabilities. See docs.
- Fix bug associated with user changes.
- store more experiment metadata, like strain and media, in the database.
- adding temporary labels of Pioreactors into the database in
pioreactor_unit_labelstable - renaming some tables,
alt_media_fraction->alt_media_fractions,ir_led_intensity->ir_led_intensities - pumps now throw a
CalibrationErrorexception if their calibration is not defined. - default user is no longer
pi. It is nowpioreactor. Any coded paths like/home/pi/should be updated tohome/pioreactor/. - new image metadata file added to
home/pioreactor/.pioreactor/.image_metadata
- fixed memory leak in MQTT connections
- better clean up after a job disconnects
- If the temperature of the heating PCB gets too high, the automation switches to Silent (previously it did not switch at all.)
- "datatype" field in
published_settingsis now used to cast before being given toset_*methods. - Internally, the repo uses the
msgspeclibrary for complex MQTT message validation. This also introduces thepioreactor.structsmodule which details the structure of the messages. - Name change:
DosingAutomation->DosingAutomationJob,TemperatureAutomation->TemperatureAutomationJob,LEDAutomation->LEDAutomationJob. - New json-encoded datatype for changing automations over MQTT: see
pioreactor.struct.Automation pio run led_intensityhas new API: use the flags, ex:--A 10.0, to set the intensities on different channels.pioreactor.actions.led_intensityhas a new API that accepts the desired state as a dict.- pump actions are now under
pioreactor.actions.pumpinstead of their own files.
- Added more error codes for the ADC, network issues, and high temperature
- Reduce chance of running multiple growth_rate_calculating jobs
- Custom exceptions thrown in the Python software.
- New checks for HAT being present, and Heating PCB being present, before a job is run (if required in the job).
- QOL improvements to stirring calibration
- Calibrations now store the data locally, alongside the calibration results, in the local storage.
- New API in
DosingControllerto add custom pumps - Some
job_names are disallowed to avoid MQTT conflicts - ADCReader now will estimate the local AC hertz to get a better OD reading signal.
- Custom Python exceptions were introduced.
pioreactor.hardware_mappingsis renamed topioreactor.hardware- New
is_HAT_presentandis_heating_pcb_presentfunctions - ErrorCodes is gone - use global variables in error_codes
- Adding logic for 180° sensor to growth_rate_calculating
- Pumps now have a state broadcast to MQTT, and thus can be "disconnected" over MQTT.
- Improved the response time of stopping pumps from the web UI.
- improved temperature-recording frequency (10m to 4m)
- removed the PWM's DC maximum on the heating output.
- New
pioreactor.version.hardware_verionwhich reads from the HAT's EEPROM which version of board is being used. - removed PD channels 3 & 4.
anglecolumn inod_readings_rawtable in database is now an integer.
pid_stableautomation renamed tostable- jobs can now publish to
pioreactor/<unit>/+/monitor/flicker_led_with_error_code/<error code>to have the LED flash a specific error code. - fixed errors raised when not able to connect to leader's MQTT
- improvements to error handling in monitor job.
- replaced
turn_off_leds_temporarilywith the more useful and more generalchange_leds_intensities_temporarily - UX improvements to the
pump_calibrationaction - improving *-Controller jobs:
automationis now a dict attribute (json in MQTT)automation_nameis a new published_setting, with string. This is what is read from the UI.- CLI has a slightly changed API to pick the automation
pio_jobs_runningrenamed topio_processes_running
- a version cut to test building images
- too much to list
- New plugin architecture
- New database tables:
od_reading_statistics,stirring_rates - New
piocommands:install-plugin,uninstall-plugins - improvements to
continous_cycledosing automation. - hardware based PWM available on pins 1 & 3.
- IR LED now turns off between OD readings. This allows other LEDs to trigger and take readings.
- Removed leader jobs
time_series_aggregatingandlog_aggregating logstable in database has more metadata- New Kalman filter algorithm that includes an acceleration term
- New database table,
kalman_filter_outputs, stores the output of the internal Kalman Filter. - workers report back to leader additional system information including available memory and CPU usage.
- Added new temperature control and temperature automations for this app and to the UI.
- Added undervoltage alerts to logging
- Added initial version of a plugin system
pio run-alwaysfor jobs not tied to an experiment (monitor, watchdog, etc.)- faster database backup sync between Pioreactors
- Ability to measure your blank vials is available using the
pio run od_blank, and in the UI under "Calibrate" - Smarter algorithm for displaying time series in the UI
- Log table only shows the past 24 hours of events.
- new dosing automation:
continous_cycle. Designed for using the Pioreactor as an inline sensor. - stirring can now be dynamically adjusted between OD readings, for improved mixing (and hence more oxygen transfer). See settings in UI.
- custom timezone support is added in config.ini
download_experiment_datais now calledexport_experiment_data- this has been updated on the UI as well.- unpausing stirring will return the rate to the previous value, not necessarily the default value.
- fix GPIO mappings
- fix keyboard interrupts in pump actions
- fix race conditions in MQTT disconnects
- fixed a bug where a job's state would change to
lostwhen another job (of the same type) would try to start. - in
ADCReader, changed from windowed moving average to exp. moving average to be more sensitive to recent changes in signal. - Growth rate calculating is a bit more robust to i) users pausing the job to inspect the vial, and ii) to changing the stirring speed.
- mDNS alias is now configurable via the config.ini, so users could have multiple clusters without domain aliases colliding in the DNS.
- fixed GPIO mappings for PWM Amplifiers
inventoryin config.ini is now calledcluster.inventoryui.overview.renamein config.ini is now calledui.rename
- fixed reconnect issues when leader went offline and then online
- pausing
dosing_controlnow pauses sub jobsdosing_automation - renamed
_algorithmto_automationeverywhere. - ADC measurements are now run at exact time intervals (previously there was some drift). The
adcjob now publishes metadata about it's recording times. - Improved error handling in
od_reading
- The
logstable in the database now contains, by default, all the DEBUG and up logs from all Pioreactors. It also has a new column to denote the software source of the log. A separate topic is now set up for the logging in the UI. pioreactor.localis now the default URL of the PioreactorUI.- on Pioreactor install, a seed experiment is created so users aren't dropped into a "blank" UI.
pubsub.subscribe_and_callbackcan now filter retained messages.- "algorithms" is now called "automations" throughout
- reduced the number of threads per job
- new topic for raw ADC measurements:
pioreactor/<unit>/<experiment>/adc/<channel> - improved MQTT QOS for important jobs
pios syncis nowpios upgrade.pio upgraderequires flags:--appand / or--uito upgrade the PioreactorApp and PioreactorUI respectively.
- new SQL tables:
led_events,led_algorithm_settings dosing_algorithm_settingshas a new schema: a json blob to represent any editable settings.- new
piocommand:pio run led_intensity, ex:pio run led_intensity --channel B intensity 50 - new
piocommand:pio updatewill update the software to the latest code on Github (later will be latest released version), and if possible, update the UI code as well. - new library dependency
DAC43608that supports our LED driver. - config.ini now has abstracted any RaspberryPi pins: we only refer to the PCB labels now in config.ini
pio killcan accept multiple jobs, ex:pio kill stirring od_reading
