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

View file

@ -0,0 +1,127 @@
// TemperatureSensor: a thermometer that Alexa reads, and that tells Alexa when the temperature changed
// (Alexa.TemperatureSensor).
//
// The sensor is a TMP36 on A0 of a Wemos D1 mini, whose A0 takes 0 to 3.2 V; for another sensor replace
// readTemperature(). The temperature is read every 2 s. A ChangeReport is sent when it differs by more than
// 0.5 degrees from what Alexa was told last, and at most once a minute.
#include <Arduino.h>
#include <ESP8266WiFi.h>
#include <Alex2ESP.h>
// Wi-Fi and the credentials of your Alex2MQTT account
const char *WIFI_SSID = "";
const char *WIFI_PASSWORD = "";
const char *ALEXA_USERNAME = "";
const char *ALEXA_PASSWORD = "";
const char *ALEXA_ROOT_TOPIC = "";
const unsigned long READ_EVERY_MS = 2000;
const unsigned long REPORT_EVERY_MS = 60000;
const float REPORT_DIFFERENCE = 0.5f; // degrees Celsius
Alex2ESP alexa;
AlexaDevice *sensor;
float temperature = 0; // degrees Celsius, as read last
float reported = 0; // what the last ChangeReport said
bool everReported = false;
unsigned long lastRead = 0;
unsigned long lastReport = 0;
// Joins the Wi-Fi network and returns after 30 s at the latest. Without a connection the sketch carries on: the
// ESP8266 keeps trying, and alexa.loop() opens the MQTT session once Wi-Fi is up.
void connectWiFi()
{
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASSWORD);
Serial.printf("\n[WIFI] Connecting to \"%s\"\n", WIFI_SSID);
unsigned long started = millis();
while (WiFi.status() != WL_CONNECTED && millis() - started < 30000)
{
delay(100);
}
if (WiFi.status() == WL_CONNECTED)
{
Serial.printf("[WIFI] Connected, IP address %s\n", WiFi.localIP().toString().c_str());
}
else
{
Serial.printf("[WIFI] No connection after 30 s (status %d): check WIFI_SSID and WIFI_PASSWORD. Still trying.\n",
WiFi.status());
}
}
// TMP36: 0.5 V at 0 degrees Celsius, 10 mV per degree
float readTemperature()
{
float volts = analogRead(A0) * 3.2f / 1023;
return (volts - 0.5f) * 100;
}
void onDirective(AlexaDirective &directive)
{
if (directive.isReportState())
{
directive.stateReport()
.addHealthProp(EndpointHealth::OK)
.addTemperatureSensorProp(temperature, TemperatureSensorScale::CELSIUS, millis() - lastRead)
.send();
return;
}
directive.error(AlexaErrorType::INVALID_DIRECTIVE, "A thermometer takes no directives").send();
}
void reportChange()
{
bool due = !everReported || millis() - lastReport >= REPORT_EVERY_MS;
if (!due || fabs(temperature - reported) <= REPORT_DIFFERENCE || alexa.getState() != Alex2ESPState::CONNECTED)
{
return;
}
bool sent = sensor->changeReport(AlexaCause::PERIODIC_POLL)
.addTemperatureSensorProp(temperature)
.context()
.addHealthProp(EndpointHealth::OK)
.send();
if (sent)
{
reported = temperature;
everReported = true;
lastReport = millis();
}
}
void setup()
{
Serial.begin(74880);
temperature = readTemperature();
connectWiFi();
// MQTT user name, MQTT password, root topic
alexa.begin(ALEXA_USERNAME, ALEXA_PASSWORD, ALEXA_ROOT_TOPIC);
// The name Alexa shows, and the id of the endpoint: every device of an account has its own
sensor = alexa.getDevice("Room Temperature", "esp-temperature");
sensor->setDisplayCategory(DisplayCategory::TEMPERATURE_SENSOR);
sensor->addCapability(AlexaInterfaces::TemperatureSensor)->setProactivelyReported(true);
sensor->addCapability(AlexaInterfaces::EndpointHealth);
sensor->onDirective(onDirective);
}
void loop()
{
alexa.loop();
if (millis() - lastRead >= READ_EVERY_MS)
{
lastRead = millis();
temperature = readTemperature();
reportChange();
}
}