You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Merge branch 'main' of github.com:Pioreactor/docs.pioreactor
* 'main' of github.com:Pioreactor/docs.pioreactor:
note
more pds
new build
updates
update some docs
more about custom models
note on v1.5
Fix broken link
getting started page for v1.5
new modal on startup
new modal on startup
Copy file name to clipboardExpand all lines: developer-guide/09-Storage and the filesystem/01-data-stores/01-data-stores-intro.md
+5-5Lines changed: 5 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -18,13 +18,13 @@ The Pioreactor software will automatically backup the SQLite database via a sche
18
18
19
19
## Local key-value datastore
20
20
21
-
SQLite3 is also used by the library *diskcache*. This is essentially a fast key-value store on the Raspberry Pi. For Pioreactor, we use it to store "machine-specific" data, like calibration curves, locks on GPIOs, state of LEDs, jobs running, etc. Instead of one large file containing all these keys, we have split them into multiple locations based on category and level of persistence. The persistent databases are stored in `/home/pioreactor/.pioreactor/storage` and the temporary databases are in `/tmp`. You can access them from Python using `pioreactor.utils.local_persistent_storage` and `pioreactor.utils.local_intermittent_storage`, respectively.
21
+
SQLite3 is also used for simpler database (caches) on each Pioreactor (worker and leader). The persistent databases are stored in `/home/pioreactor/.pioreactor/storage` and the temporary databases are in `/run/pioreactor/cache`. You can access them from Python using `pioreactor.utils.local_persistent_storage` and `pioreactor.utils.local_intermittent_storage`, respectively.
22
22
23
23
:::info
24
24
What are temporary and persistent? Something like GPIO locks or LED state are physically reset between cycles of the Raspberry Pi. So when the Pi power-cycles, the state is wiped, and by have the database in `/tmp`, the databases are wiped as well.
25
25
:::
26
26
27
-
You can use `pio view-cache <name>` to view the contents of `<name>`, and `pio clear-cache <name> <key>` to clear contents.
27
+
You can use `pio cache view <name>` to view the contents of `<name>`, and `pio cache clear <name> <key>` to clear contents.
28
28
29
29
30
30
## MQTT
@@ -33,9 +33,9 @@ The inter- and intra-Pioreactor communications are handled by MQTT, a pub/sub se
33
33
34
34
A principle we have stood by is to not let MQTT turn into our database. That is,
35
35
36
-
1. we shouldn't store important information in MQTT _only_ (also use `mqtt_to_db_streaming` job to store important data in the SQLite3 database, or handle it locally using `local_intermitant_storage` or `local_persistance_storage`),
37
-
2. we shouldn't store information in MQTT that is "machine-specific", like calibrations (better to use `local_intermitant_storage` or `local_persistance_storage`)
38
-
3. we shouldn't use MQTT as a source of truth (trust the database, `local_intermitant_storage` or `local_persistance_storage` more).
36
+
1. we shouldn't store important information in MQTT _only_ (also use `mqtt_to_db_streaming` job to store important data in the SQLite3 database, or handle it locally using `local_intermittent_storage` or `local_persistent_storage`),
37
+
2. we shouldn't store information in MQTT that is "machine-specific", like calibrations (better to use `local_intermittent_storage` or `local_persistent_storage`)
38
+
3. we shouldn't use MQTT as a source of truth (trust the database, `local_intermittent_storage` or `local_persistent_storage` more).
Copy file name to clipboardExpand all lines: developer-guide/09-Storage and the filesystem/01-data-stores/02-sqlite.md
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -18,7 +18,7 @@ You can either use `.tables` in the sqlite shell, or visit all the tables [schem
18
18
19
19
### How can I add new SQL tables?
20
20
21
-
Using the sqlite shell (`pio db`), you can execute any SQL statements, including creating new tables. Plugins can also automatically create new tables when installed, [see instructions here](developer-guide/plugin-as-python-package#5-optional-adding-tables-to-the-sql-store).
21
+
Using the sqlite shell (`pio db`), you can execute any SQL statements, including creating new tables. Plugins can also automatically create new tables when installed, [see instructions here](plugin-as-python-package#5-optional-adding-tables-to-the-sql-store).
Copy file name to clipboardExpand all lines: developer-guide/09-Storage and the filesystem/02-filesystem.md
+26-46Lines changed: 26 additions & 46 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -4,49 +4,29 @@ slug: /filesystem-locations
4
4
hide_table_of_contents: true
5
5
---
6
6
7
-
8
-
Below is a list of important locations and files on the filesystem for the Pioreactor:
9
-
10
-
11
-
### UI
12
-
13
-
-`/var/www/pioreactorui/` is the source of the web-app.
14
-
-`/var/www/pioreactorui/.env` holds some configuration for the UI.
15
-
-`/var/www/pioreactorui/contrib/` holds yaml files that display automation data, job data, and chart data.
16
-
- Note: `/home/pioreactor/.pioreactor/plugins/ui/contrib/` also holds yaml files, like the above.
17
-
18
-
19
-
### Logs
20
-
21
-
-`/var/log/pioreactor.log` is the log file for the Pioreactor app
22
-
-`/var/log/pioreactorui.log` is the (deprecated) log file for the Pioreactor UI. It's now the same as above.
23
-
24
-
25
-
### Storage
26
-
27
-
-`/home/pioreactor/.pioreactor/storage/` holds the main database, backup of the database, and persistent caches.
28
-
-`/tmp/pioreactor_cache/` holds temporary caches. Files in here are not kept between reboots.
29
-
30
-
31
-
### Bash scripts
32
-
-`/usr/local/bin/` store bash scripts that are used when working with the filesystem: installing plugins, updating code, etc.
33
-
34
-
35
-
### Config
36
-
37
-
-`/home/pioreactor/.pioreactor/` holds all configuration files for the Pioreactor UI and app, the main one being `config.ini`
38
-
39
-
40
-
### Plugins
41
-
42
-
-`/home/pioreactor/.pioreactor/plugins/` is where Python files can be added.
43
-
-`/home/pioreactor/.pioreactor/plugins/ui/contrib/` also holds UI yaml files for custom Python code.
44
-
45
-
### Experiment profiles
46
-
47
-
-`/home/pioreactor/.pioreactor/experiment_profiles/` is where experiment profiles (yaml) are stored.
48
-
49
-
### Calibrations
50
-
51
-
-`/home/pioreactor/.pioreactor/storage/calibrations/` is where calibrations are stored.
52
-
7
+
# Important Raspberry Pi Locations for Pioreactor Images
8
+
9
+
Reference list of on-device paths that matter once a custom Pioreactor Raspberry Pi OS image is flashed and running.
10
+
11
+
| Path | What lives here | Notes |
12
+
| --- | --- | --- |
13
+
|`/etc/pioreactor.env`| Shared environment file exported to services | Provides canonical `DOT_PIOREACTOR`, `RUN_PIOREACTOR`, `LG_WD`, and virtualenv paths so systemd units pick up the same locations. |
14
+
|`/home/pioreactor/.pioreactor/`| Pioreactor home (`$DOT_PIOREACTOR`) | Contains configs, plugins, storage, hardware definitions, logs, and other per-device state. Ensure ownership stays `pioreactor:pioreactor`. |
15
+
|`/home/pioreactor/.pioreactor/config.ini`| Cluster-wide configuration | Holds network, MQTT, UI, logging, and automation settings replicated to workers. |
16
+
|`/home/pioreactor/.pioreactor/unit_config.ini`| Unit overrides | Optional per-device overrides synced from the leader when a worker is added. |
17
+
|`/home/pioreactor/.pioreactor/plugins/`| Plugin root | Mirrors the `.pioreactor` layout for plugin-provided files; typically subdivided into `python/`, `ui/`, `exportable_datasets/`, etc. |
18
+
|`/home/pioreactor/.pioreactor/plugins/ui/`| UI plugin assets | Static contrib YAML, templates, and other UI resources merged into the Pioreactor UI. |
19
+
|`/home/pioreactor/.pioreactor/plugins/exportable_datasets/`| Exportable dataset plugins | Each plugin ships SQL queries or serializers that surface new datasets to the UI. |
20
+
|`/home/pioreactor/.pioreactor/storage/`| Persistent databases | Holds SQLite data such as `pioreactor.sqlite` (experiments) and `local_persistent_pioreactor_metadata.sqlite`. |
21
+
|`/home/pioreactor/.pioreactor/storage/pioreactor.sqlite`| Primary experiment database | Used by the leader, replicated to workers for durability. Back up before major upgrades. |
|`/home/pioreactor/.pioreactor/hardware/`| Hardware definition packs | YAML that describes hats, models, sensors, and calibration values consumed by the Pioreactor hardware subsystem. |
24
+
|`/home/pioreactor/.pioreactor/experiment_profiles/`| User experiment profiles | Drop `.py` / `.json` profile definitions here so they show up in the UI for scheduling. |
25
+
|`/home/pioreactor/.ssh/`| Device SSH keys | Created during image build so leaders can add workers securely. |
26
+
|`/run/pioreactor/`| Runtime scratch space (`$RUN_PIOREACTOR`) | tmpfs directory for caches, sockets, Huey queues, and general runtime coordination. Cleared on reboot. |
27
+
|`/run/pioreactor/cache/`| Volatile caches | Includes `local_intermittent_pioreactor_metadata.sqlite` and UI/Huey cache files that can be safely discarded. |
28
+
|`/run/pioreactor/exports/`| Web export staging | Lighttpd serves `/exports/` from here so downloads never touch persistent storage. |
29
+
|`/var/log/pioreactor.log`| System log for Pioreactor services | Configured via `config.ini` and read by both CLI and UI. Rotate with journald/logrotate as needed. |
30
+
|`/opt/pioreactor/venv/`| System Python virtual environment | Hosts the Pioreactor Python installation (`pio`, `pios`, services). Activate manually for debugging. |
description: Extend or override Pioreactor hardware definitions by layering YAML files that hardware.py reads.
5
+
hide_table_of_contents: true
6
+
---
7
+
8
+
Pioreactor's hardware layer is intentionally data-driven. Everything in [`core/pioreactor/hardware.py`](https://github.com/pioreactor/pioreactor/blob/main/core/pioreactor/hardware.py) loads user-editable YAML files from `~/.pioreactor/hardware/` (or the folder pointed to by the `DOT_PIOREACTOR` env var). By editing these files you can rewire pins, add new peripherals, or describe an entirely new bioreactor model without touching the Python code. Pair these configs with [custom bioreactor model definitions](/developer-guide/custom-bioreactor-models) so the UI, safety limits, and wiring stay in sync.
9
+
10
+
## How the loader works
11
+
12
+
`hardware.py` deep-merges two directories for each **mod** (subsystem):
13
+
14
+
1.`~/.pioreactor/hardware/hats/<hat_version>/<mod>.yaml` – physical wiring that ships with a specific HAT revision (`hardware_version_info`).
15
+
2.`~/.pioreactor/hardware/models/<model>/<version>/<mod>.yaml` – intent for a particular bioreactor model returned by `get_pioreactor_model()`.
16
+
17
+
Later layers override earlier ones. Missing files are allowed; missing keys throw `HardwareError`s when helpers such as `get_pwm_to_pin_map()` run.
`get_adc_curriers()`will automatically expose `.keys()` for every entry (`pd1`, `aux`, `salty`). Downstream helpers, like `get_available_pd_channels()`, treat `pd*` names as photodiode channels.
65
+
66
+
4. **Reference new mods in code**. Anywhere in your plugin/automation you can import:
67
+
```python
68
+
from pioreactor.hardware import get_layered_mod_config
69
+
70
+
stir_cfg = get_layered_mod_config("stirrer") # merges hats/<hat>/stirrer.yaml and models/<model>/stirrer.yaml
71
+
if stir_cfg.get("controller") == "pico":
72
+
...
73
+
```
74
+
This keeps custom hardware logic outside Pioreactor core.
75
+
76
+
## Tips for customization
77
+
78
+
- Use integers for all addresses and pins; `hardware.py` casts everything via `int()` and will raise if parsing fails.
79
+
- Keep YAML minimal—only override keys that differ from the hat defaults to take advantage of deep-merge layering.
80
+
- The helper predicates (`is_ADC_present`, `is_heating_pcb_present`, etc.) are safe ways to gate optional hardware in your jobs.
81
+
82
+
83
+
Once you describe the hardware this way, the rest of the stack—jobs, automations, plugins—just asks `hardware.py` for the capabilities it needs, so new hardware becomes a configuration exercise instead of a fork of the core codebase.
This feature is actively under development - let us know what else you would like to see!
9
+
:::
10
+
11
+
If you are building a novel bioreactor on top of our software, you can use the `~/.pioreactor/models` dir to add your own bioreactors. This metadata flows into the Inventory UI, safety interlocks, analytics, and can be consumed from Python via `pioreactor.whoami.get_pioreactor_model()`.
12
+
13
+
## Directory layout
14
+
15
+
1. Create the models folder if it does not exist:
16
+
```bash
17
+
mkdir -p ~/.pioreactor/models
18
+
```
19
+
2. Add one YAML file per model+version, for example `~/.pioreactor/models/custom_100ml__v1_0.yaml`.
20
+
3. Restart the Pioreactor UI to pick up the new definition.
21
+
4. Assign pioreactors to this new model on the Inventory UI page or via `pio workers update-model ...` tool.
22
+
23
+
## Required fields
24
+
25
+
Each YAML is validated against `pioreactor.structs.Model`, so include at least:
After saving the file, the Inventory page will list “Custom 100 mL, v1.0” in each unit’s model dropdown. The same data becomes available to jobs and plugins:
50
+
51
+
```python
52
+
from pioreactor.whoami import get_pioreactor_model
53
+
54
+
model = get_pioreactor_model()
55
+
print(model.display_name)
56
+
print(model.reactor_capacity_ml)
57
+
```
58
+
59
+
## Coordinating with hardware profiles
60
+
61
+
Model definitions describe intent (volumes, limits), while the hardware loader handles wiring, pin assignments, and sensor addresses. When you introduce a new model, you usually need a matching directory under `~/.pioreactor/hardware/models/<model_name>/<model_version>/` so [`hardware.py` can layer the right YAMLs](/developer-guide/custom-hardware). Keeping the names and versions identical lets software map UI selections → hardware capabilities.
62
+
63
+
If you are basing your custom model off an existing Pioreactor model, can reuse the hardware for our Pioreactor models:
- Run `python -m pioreactor.models` to ensure your YAML parses; validation errors are also logged via the `models` logger.
74
+
- If a model is missing from the dropdown, confirm the filename ends with `.yaml`/`.yml`, the process has read permissions, and the Pioreactor services have restarted.
75
+
- Treat this directory like code: commit the YAMLs to version control alongside any CAD notes or lab SOPs so teammates understand the assumptions behind each model.
0 commit comments