Debugging
If something here does not match what you see on your unit, please open an issue with the output.
Get a shell
ssh pi@seedypod.localCheck the hardware daemon
hald --check # validate /etc/seedypod/hal.toml and print the planned devices
journalctl -u hald -f # follow the daemon's log
curl localhost:3001/health # {ok, uptime_s, mqtt_connected}
curl localhost:3001/state # every sensor, actuator and alert in one snapshotTo see everything hald publishes:
mosquitto_sub -t 'seedypod/#' -vLogs only last until reboot
install-hal keeps the system journal in RAM to spare the SD card (ADR 0021). Alerts and faults are still in the database (the Alerts screen, GET /api/alerts). To chase a crash that needs logs from before a reboot, keep the journal on the card for a while, then turn it back off:
sudo mkdir -p /etc/systemd/journald.conf.d
printf '[Journal]\nStorage=persistent\n' | sudo tee /etc/systemd/journald.conf.d/99-debug-persistent.conf
sudo systemctl restart systemd-journald # logs now survive reboots
# … reproduce, reboot, then: journalctl -b -1 -u hald -u seedypod-core
sudo rm /etc/systemd/journald.conf.d/99-debug-persistent.conf && sudo systemctl restart systemd-journaldCheck core
journalctl -u seedypod-core -f
curl localhost:3000/api/systemThe About section at the bottom of Settings shows the core and daemon versions and the unit id. If it says the hardware daemon is offline, core cannot reach hald over MQTT; check HAL_MQTT_URL in /etc/systemd/system/seedypod-core.service.
Probe the I²C bus
sudo i2cdetect -y 1Expect 0x40 (INA219 pump power monitor), 0x48 (PCT2075 board temperature), and 0x38 (DHT20 air sensor, Gardyn 3.0 and later). The AM2320 used in Gardyn 1.0 and 2.0 sits at 0x5C but does not answer i2cdetect; that is expected.
The pump will not start
If the pump state shows fault: "dry-run" or fault: "over-temp", the fault is latched: the pump stays off until a person acknowledges it. Refill the tank or let the board cool, then acknowledge from any of:
- the Alerts screen in the web UI;
- the Acknowledge pump fault button in Home Assistant;
- a long press of the physical button;
- the API:
POST /api/alerts/{id}/acknowledgewith the alert’s id fromGET /api/alerts.
If there is no latched fault but the pump still refuses, the tank probably reads low: check the Water screen’s distance against your tank calibration in Settings.
A restore that didn’t finish
The restore helper logs each step to /var/lib/seedypod-restore/status.json, and sudo seedypod-restore --status prints the last run. A restore started from the web UI runs as its own transient unit:
journalctl -u 'seedypod-restore-*'If the web UI says restore isn’t installed, scripts/install hasn’t put the helper and its sudoers rule in place. Run as core’s user, sudo -n -l /usr/local/sbin/seedypod-restore should print the path. A failed restore puts the old files back by itself, and sudo seedypod-restore --undo reverses the last restore that did finish.
SD card writes
Settings → Storage (or GET /api/storage/flash) shows how much the unit writes to its card per day. To see which process is writing, use sudo iotop -ao or cat /proc/<pid>/io. swapon --show should list only /dev/zram0.
Reproduce without hardware
Run the daemon against simulated hardware, with time running 60 times faster, and core against it:
hald --sim --time-scale 60
HAL_MQTT_URL= pnpm devSource: docs/DEBUGGING.md