Reliable four-input digital pressure node for the Nightshift system.
Device ID: pressure-01 | Board: ESP32-S3-DevKitC-1 (detected unit:
32 MB octal flash, 16 MB octal PSRAM) | Firmware: 0.1.0
| ESP32-S3 GPIO | Meaning | Electrical Trigger Level |
|---|---|---|
| GPIO4 | Cushion left | Low = triggered |
| GPIO5 | Cushion right | Low = triggered |
| GPIO6 | Footrest left | Low = triggered |
| GPIO7 | Footrest right | Low = triggered |
Logical groups:
cushion = GPIO4 OR GPIO5footrest = GPIO6 OR GPIO7presence = cushion OR footrest
All four pins are sampled from one GPIO input register approximately every
10 ms and use internal pull-ups. The hardware inputs are active-low, and the
sampling layer normalizes them before debounce and publication. All serial and
MQTT logical values therefore retain the contract 1/true = triggered and
0/false = not triggered.
| Parameter | Value |
|---|---|
| SSID | stillwork |
| Security | WPA2-PSK |
| Band | 2.4 GHz |
| Addressing | DHCP (192.168.51.10–100) |
| Gateway | 192.168.51.1 |
| Parameter | Value |
|---|---|
| Broker | 192.168.51.1:1884 |
| Username | pressure-01 |
| Client ID | pressure-01-<6-hex eFuse-MAC suffix> |
| Keepalive | 30 seconds |
nightshift/v1/sensor/pressure/pressure-01/availability (QoS 1, retained)
nightshift/v1/sensor/pressure/pressure-01/state (QoS 1, retained)
nightshift/v1/sensor/pressure/pressure-01/telemetry (QoS 0, not retained)
{
"schema": "nightshift.sensor-availability.v1",
"device_id": "pressure-01",
"online": true,
"boot_id": "7f92ab31",
"version": "0.1.0",
"started_at_ms": 0,
"time_base": "monotonic_boot_ms"
}{
"schema": "nightshift.sensor-availability.v1",
"device_id": "pressure-01",
"online": false
}{
"schema": "nightshift.pressure-state.v1",
"device_id": "pressure-01",
"boot_id": "7f92ab31",
"seq": 123,
"sampled_at_ms": 123,
"time_base": "monotonic_boot_ms",
"gpio": { "4": true, "5": false, "6": true, "7": true },
"cushion": true,
"footrest": true,
"presence": true
}{
"schema": "nightshift.pressure-telemetry.v1",
"device_id": "pressure-01",
"boot_id": "7f92ab31",
"uptime_ms": 90000,
"wifi_rssi_dbm": -51,
"mqtt_reconnect_count": 1,
"publish_count": 35,
"reported_at_ms": 90000,
"time_base": "monotonic_boot_ms"
}The AP may have no internet route, so all *_at_ms fields use unsigned
milliseconds since this boot and explicitly declare monotonic_boot_ms.
Core reporting never waits for NTP. See docs/protocol.md
and the machine-readable examples in protocol/examples.
- PlatformIO CLI or PlatformIO IDE
- ESP32-S3 connected via USB on COM9
Copy-Item include/secrets.h.example include/secrets.h
# Edit the ignored include/secrets.h locally.pio run -e esp32-s3-devkitc-1pio run -e esp32-s3-devkitc-1 --target uploadpio device monitor -b 115200 -p COM9When a host C++ compiler is installed:
pio test -e nativeThe production-linked suite can also run on COM9:
pio test -e esp32-s3-tests -f test_core --upload-port COM9 --test-port COM9Target tests temporarily replace the application; flash the normal environment again afterward. The exact commands used for acceptance are recorded in docs/acceptance-test.md.
| Parameter | Value |
|---|---|
| GPIO sample interval | 10 ms |
| Press debounce | 30 ms |
| Release debounce | 100 ms |
| State publish (on change) | Immediate |
| State refresh (periodic) | 3 seconds |
| Telemetry interval | 30 seconds |
| MQTT keepalive | 30 seconds |
application.cpp coordinator; sampling stays independent of networking
gpio_sampler.cpp coherent GPIO register read
debounce.cpp testable asymmetric debounce and group aggregation
wifi_manager.cpp DHCP Wi-Fi lifecycle with bounded backoff and jitter
mqtt_manager.cpp asynchronous ESP-MQTT, LWT, QoS, bounded outbox
payload.cpp normalized JSON serialization
publish_scheduler.cpp change/reconnect/periodic publish policy
test/test_core/ production-linked Unity tests (host or ESP32 target)
| Symptom | Check |
|---|---|
| No serial output | Verify COM9 at 115200 baud and close other serial monitors |
| Flash fails | Close COM9 users and retry automatic reset first; use BOOT only if esptool logs cannot enter download mode |
| Wi-Fi won't connect | Verify SSID/password in secrets.h; check AP is on 2.4GHz ch6 |
| MQTT connect fails | Verify broker on 192.168.51.1:1884; check username/password |
| All logical GPIOs read high | Check wiring; sensors should pull GPIO low when triggered |
| Reconnect loop | Read bounded retry lines in serial; the device should not reboot |
More detail is in docs/troubleshooting.md.
# On the Orange Pi or any machine with network access:
mosquitto_sub -h 192.168.51.1 -p 1884 -u pressure-01 -P <password> -t "nightshift/v1/sensor/pressure/#" -vAlternatively set NIGHTSHIFT_MQTT_PASSWORD locally and run
python scripts/observe_mqtt.py. Neither credentials nor local evidence logs
are tracked.