A framework for building secure, modular MQTT clients on PoE RP2040 devices. Devices are fully configurable via YAML, integrate with Home Assistant out of the box via MQTT Discovery, and operate reliably offline-first over encrypted MQTTS.
| Component | Part |
|---|---|
| MCU | Raspberry Pi RP2040 |
| Board | Silicognition RP2040-Shim |
| Ethernet | Silicognition FeatherWing PoE (W5500) |
| Connectivity | Ethernet over PoE — no Wi-Fi dependency |
- Offline-first — devices buffer state and reconnect with backoff; the control loop never blocks on network I/O
- MQTTS (TLS) — all broker communication is encrypted; plaintext MQTT is forbidden
- Home Assistant Discovery — every module publishes HA-compatible discovery payloads automatically on startup and reconnect
- YAML-configurable — GPIO assignments, MQTT topics, and module composition are defined in per-device YAML config files; nothing is hardcoded in firmware
- GPIO-aware — pin assignments are validated against the target board's pinout at config load time
- Modular architecture — capabilities (sensors, relays, status LEDs, etc.) are composed as independent, testable modules
- Framework: Arduino (via PlatformIO)
- Language: C++14
- Build: PlatformIO Core
devices/ # Per-device YAML configuration files
scripts/
gen_config.py # YAML → generated_config.h (PlatformIO pre-script)
gen_certs.py # PEM CA cert → trust_anchors.h (BearSSL)
include/
IGPIODriver.h # GPIO hardware abstraction interface
IModule.h # Capability module interface
IBundle.h # Use-case bundle interface
vanlab-iot.h # Framework entry point (include this in sketches)
src/
main.cpp # Arduino entry point (setup/loop)
core/
Orchestrator.h/.cpp # Top-level device coordinator
config/
ConfigTypes.h # All config structs (DeviceConfig, BundleConfig, …)
ConfigLoader.h/.cpp # Runtime JSON loader (LittleFS)
generated_config.h # Auto-generated by gen_config.py (not committed)
hal/
RP2040GPIODriver.h # Concrete IGPIODriver for RP2040 (Arduino core)
mqtt/
MQTTClientWrapper.h/.cpp # MQTTS FSM with offline buffer + backoff
StateBuffer.h/.cpp # Ring buffer for offline state messages
HADiscoveryPayload.h/.cpp # HA MQTT Discovery payload builder
bundles/
base/
BundleEventBus.h/.cpp # Typed queued event bus (offline coordination)
BundleRegistry.h/.cpp # Bundle + standalone module orchestrator
light/
LightBundle.h/.cpp # Dimmable light use-case (dimmer + switch)
modules/
dimmer/ # DimmerModule — PWM output (bundle-owned)
physical_switch/ # PhysicalSwitchModule — debounced digital input
status_led/ # StatusLEDModule — standalone blink indicator
neopixel/ # NeoPixelModule — HA-controllable RGB NeoPixel
tests/
mocks/
MockGPIODriver.h # IGPIODriver test double (records all calls)
MockEventBus.h # BundleEventBus test double (records events)
test_mock_gpio/ # MockGPIODriver verification
test_state_buffer/ # StateBuffer push/pop/overflow
test_mqtt_fsm/ # FSM state + offline buffer behaviour
test_event_bus/ # BundleEventBus dispatch + MockEventBus
test_ha_discovery/ # HADiscoveryPayload builder + validation
test_config_loader/ # ConfigLoader JSON parsing
test_status_led/ # StatusLEDModule blink behaviour
test_light_bundle/ # LightBundle switch→toggle end-to-end
test_neopixel_module/ # NeoPixelModule status indicator behaviour
test_neopixel_light/ # NeoPixelLightModule HA RGB light behaviour
platformio.ini # PlatformIO environments: rp2040_shim, feather_rp2040, native
-
Install PlatformIO
-
Copy the appropriate device config template to
devices/<your-device>.ymland configure GPIO pins and MQTT settings -
Provision a TLS certificate for the device and reference it in the device config
-
Run the native test suite (no hardware required):
pio test --environment native -
Build and flash — choose the environment matching your hardware:
Environment Board rp2040_shimSilicognition RP2040-Shim feather_rp2040Adafruit RP2040 Feather NeoPixel operating mode (status indicator vs HA RGB light) is selected by the
typefield in the device YAML config — no separate environment needed.pio run --target upload --environment feather_rp2040
-
Monitor serial output (PlatformIO auto-detects the port; 115200 baud):
pio device monitor
Each device is described by a YAML file in devices/. Example:
device:
id: workshop-sensor-01
board: silicognition-rp2040-shim
mqtt:
broker: mqtts://homeassistant.local:8883
credentials_file: secrets/broker.yml
modules:
- type: temperature
gpio: 4
topic: workshop/temperature
- type: relay
gpio: 16
topic: workshop/relay/1Project principles and governance are defined in .specify/memory/constitution.md.