Examples as Arduino sketches: one folder per device type, each its own endpointId, Wi-Fi with a timeout

Light, DimmableLight, ColorTemperatureLight, ColorLight, TemperatureSensor, ContactSensor, Blind,
Thermostat, Lock, Scene, Doorbell and MultiDevice on the 2.0 API: addCapability(row, instance), one
onDirective() handler, the report helpers, ChangeReports from loop(), a deferred answer for the lock.
Wi-Fi is waited for 30 s, then the sketch says what to check and carries on.

examples/README.md has what each sketch does, its limits and the measured sizes for d1_mini: Light
takes 30,616 bytes of static RAM and 332,565 of flash; all 17 sketches build with 0 warnings.
test/test_examples compares the discovery object of every new sketch: 147 host tests (were 135).
The sketches were compiled, not run on a board.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
David 2026-09-28 21:41:51 +00:00
parent 7369883479
commit 69b4d59896
15 changed files with 2061 additions and 1 deletions

114
examples/README.md Normal file
View file

@ -0,0 +1,114 @@
# Examples
One folder per kind of device. Every sketch is complete: Wi-Fi, the MQTT session, one device (MultiDevice: two) with
its own endpoint id and name, and one handler for its directives.
| Sketch | Device | Interfaces | Endpoint id |
|---|---|---|---|
| [Light](Light/Light.ino) | a lamp, on and off | PowerController | `esp-light` |
| [DimmableLight](DimmableLight/DimmableLight.ino) | a lamp with PWM brightness | PowerController, BrightnessController | `esp-dimmable-light` |
| [ColorTemperatureLight](ColorTemperatureLight/ColorTemperatureLight.ino) | a lamp with a warm and a cold channel, 2200 K to 7000 K | PowerController, BrightnessController, ColorTemperatureController | `esp-white-light` |
| [ColorLight](ColorLight/ColorLight.ino) | an RGB lamp | PowerController, BrightnessController, ColorController | `esp-color-light` |
| [TemperatureSensor](TemperatureSensor/TemperatureSensor.ino) | a thermometer; a ChangeReport after a change of more than 0.5 degrees, at most one a minute | TemperatureSensor | `esp-temperature` |
| [ContactSensor](ContactSensor/ContactSensor.ino) | a door contact on a GPIO; a ChangeReport on every change | ContactSensor | `esp-contact` |
| [Blind](Blind/Blind.ino) | a blind with a position of 0 to 100 and the words open, close, raise, lower | RangeController `Blind.Lift` with semantics | `esp-blind` |
| [Thermostat](Thermostat/Thermostat.ino) | HEAT, COOL, AUTO and OFF, one setpoint or two, the errors of the thermostat | ThermostatController, TemperatureSensor | `esp-thermostat` |
| [Lock](Lock/Lock.ino) | a bolt that takes 3 s: DeferredResponse, then the answer from `loop()` | LockController | `esp-lock` |
| [Scene](Scene/Scene.ino) | a scene that switches two outputs | SceneController | `esp-scene` |
| [Doorbell](Doorbell/Doorbell.ino) | a button on a GPIO; DoorbellPress on every press | DoorbellEventSource | `esp-doorbell` |
| [MultiDevice](MultiDevice/MultiDevice.ino) | two lamps, two endpoints, one handler | PowerController | `esp-multi-left`, `esp-multi-right` |
Every device announces EndpointHealth as well and reports `connectivity` with its state.
The sketches in [`legacy/`](legacy/) are the examples of 1.x, unchanged. They use `registerEvent()` and the
`Add...Prop()` names and are kept to show that a 1.x sketch compiles against 2.0. New sketches start from the ones
above.
## Before flashing
Fill in the five constants at the top of the sketch: the Wi-Fi network and the MQTT user name, password and root
topic of your Alex2MQTT account.
```cpp
const char *WIFI_SSID = "";
const char *WIFI_PASSWORD = "";
const char *ALEXA_USERNAME = "";
const char *ALEXA_PASSWORD = "";
const char *ALEXA_ROOT_TOPIC = "";
```
Two boards with the same endpoint id on one account are one device to Alexa. Change the id and the name in
`getDevice()` when you flash a sketch a second time.
Each sketch names the pins it uses by GPIO number, with the label of the Wemos D1 mini in a comment. The serial
output is at 74880 baud.
## Wi-Fi
`connectWiFi()` waits for the network for 30 s at the most. Without a connection it prints the status and the two
constants to check, and the sketch carries on: the ESP8266 keeps trying to join, and `alexa.loop()` opens the MQTT
session once Wi-Fi is up.
## Building
Arduino IDE: a sketch is a folder with an `.ino` of the same name, which is how the IDE opens it.
PlatformIO: copy the `.ino` into `src/` of a project that has the library in `lib_deps`, or make the folder of the
sketch the source directory of the project (`src_dir`, or the environment variable of the same meaning). In a
project with a `d1_mini` environment and the library:
```
PLATFORMIO_SRC_DIR=/path/to/Alex2ESP/examples/Light pio run -e d1_mini
```
This is how the sizes below were built. The sketches define every function before it is used and include `Arduino.h`, so they are also valid as a `.cpp`
file.
## Size
Static RAM and flash as PlatformIO reports them for `d1_mini` (espressif8266 4.2.1, Arduino core 3.1.2,
AsyncMqttClient 0.9.0, ArduinoJson 7.4.3), built from this folder as committed, with empty credentials and the default
log level. A D1 mini has 81,920 bytes of RAM; what is not static is the heap.
| Sketch | Static RAM (bytes) | Flash (bytes) |
|---|---:|---:|
| Light | 30,616 | 332,565 |
| DimmableLight | 30,692 | 336,765 |
| ColorTemperatureLight | 30,808 | 337,489 |
| ColorLight | 30,748 | 338,657 |
| TemperatureSensor | 30,572 | 333,213 |
| ContactSensor | 30,584 | 332,861 |
| Blind | 30,860 | 336,525 |
| Thermostat | 31,044 | 337,517 |
| Lock | 30,648 | 333,441 |
| Scene | 30,640 | 333,277 |
| Doorbell | 30,584 | 333,013 |
| MultiDevice | 30,672 | 332,725 |
| legacy/basicLight | 30,520 | 333,989 |
| legacy/lightWithBrightness | 30,648 | 337,929 |
| legacy/lightWithColorTemp | 30,828 | 338,653 |
| legacy/tempSensor | 30,412 | 332,781 |
| legacy/blindControl | 30,568 | 335,261 |
## What has been tried
The sketches of this folder were compiled with PlatformIO, with 0 warnings. They have not been built with the
Arduino IDE and have not run on a board yet. What each announces
in discovery is checked by the host tests in `test/test_examples`.
With this library on a Wemos D1 mini, a real Alexa account and other sketches (2026-09-28), Alexa discovered and
drove PowerController, BrightnessController, ColorTemperatureController and one instance each of ToggleController,
RangeController and ModeController. Not tried with Alexa from this library: ColorController, ThermostatController,
LockController and the deferred answer, SceneController, the ChangeReports and DoorbellPress. Voice commands have
not been tried.
## Limits
- Scene: the discovery object does not carry `supportsDeactivation`. The sketch answers `Deactivate`, but Alexa
may never send it.
- Doorbell, ContactSensor: an event or a change while there is no session with the broker is not sent later.
- Lock: the answer after the DeferredResponse is sent once. If the session is lost while the bolt moves, Alexa gets
the state with its next ReportState.
- Blind, Scene, Thermostat, the lamps: the state is kept in RAM and starts from the values in the sketch after a
reset.