The cool part: this doesn't need an Amazon developer account, an MQTT broker, or any cloud service. The ESP8266 pretends to be a Belkin Wemo smart switch, which Alexa discovers natively over your LAN.
Parts
- Wemos D1 Mini (ESP8266)
- 5V relay module (the kind with an opto-isolator + transistor — not bare coil)
- USB power supply or 5V wall adapter
- A USB-powered lamp (for safety — start with low-voltage loads before touching mains)
WARNING: if you're switching mains AC, only do it inside a properly earthed metal box with a fuse. Don't switch mains on a bare breadboard. This tutorial sticks with low-voltage USB.
Wiring
- Relay VCC → D1 Mini 5V
- Relay GND → D1 Mini GND
- Relay IN → D1 Mini D1
- Lamp's 5V positive line passes through the relay's normally-open contacts.
Library: install 'fauxmoESP' from Library Manager (Xose Pérez's library — it implements the Wemo discovery protocol).
Sketch outline
#include <ESP8266WiFi.h>
#include <fauxmoESP.h>
fauxmoESP fauxmo;
void setup() {
WiFi.begin("YourSSID", "YourPassword");
while (WiFi.status() != WL_CONNECTED) delay(100);
fauxmo.createServer(true);
fauxmo.setPort(80);
fauxmo.enable(true);
fauxmo.addDevice("desk lamp");
fauxmo.onSetState([](unsigned char id, const char* name, bool state, unsigned char value) {
digitalWrite(D1, state ? HIGH : LOW);
});
}
void loop() { fauxmo.handle(); }Pairing with Alexa
1. Open the Alexa app on your phone.
2. Devices → + → Add Device → Other → Discover devices.
3. Wait ~30 seconds. 'Desk lamp' shows up.
4. Try 'Alexa, turn on the desk lamp.'
Why this works: when Alexa discovers devices it broadcasts a UPnP M-SEARCH on UDP port 1900. fauxmoESP listens and responds with a fake Wemo device descriptor. From Alexa's perspective, your D1 Mini is indistinguishable from a real Belkin switch.
Caveats: if your router has client isolation enabled (common on guest networks), the discovery won't work — Alexa and the ESP8266 must be on the same subnet. Also: when the ESP8266 reboots, Alexa sometimes misses the next state change; a 5-second WiFi reconnect retry fixes it.