This Arduino code enables the control of relays using Alexa commands while also providing the capability to configure Wi-Fi access via an Access Point mode. The code utilizes the ESP8266 platform and integrates functions for managing Wi-Fi connections, setting up an Access Point, and communicating with Alexa through the fauxmoESP library.
The Access Point mode is activated when no stored Wi-Fi credentials are available. In this mode, a device named "RelaisKeinNetz" with the password "12345678" can be connected to. Through a simple web interface, Wi-Fi access credentials can be entered and saved. You can Press a Buttom connected to ground and D5 fpr 5 seconds as well.
Once a Wi-Fi connection is established, relays can be controlled using Alexa commands. The code allows the control of up to four relays, with each relay state modifiable via Alexa commands. The names of the relays are defined in the fauxmoESP configuration and can be adjusted accordingly.
#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
#include <EEPROM.h>
#include <DNSServer.h>
#include "fauxmoESP.h"
#define SERIAL_BAUDRATE 115200
#define BUTTON_PIN D5
#define EEPROM_SIZE 512
#define SSID_ADDR 0
#define PASS_ADDR 32
ESP8266WebServer server(80);
DNSServer dnsServer;
const byte DNS_PORT = 53;
unsigned long buttonPressedTime = 0;
const unsigned long longPressTime = 5000; // Duration for long press
bool apModeTriggered = false;
fauxmoESP fauxmo;
// Zustandsvariablen für jedes Relais
bool stateRelay1 = true;
bool stateRelay2 = true;
bool stateRelay3 = true;
bool stateRelay4 = true;
void setup() {
Serial.begin(SERIAL_BAUDRATE);
pinMode(BUTTON_PIN, INPUT_PULLUP);
EEPROM.begin(EEPROM_SIZE);
String ssid = readStringFromEEPROM(SSID_ADDR);
String pass = readStringFromEEPROM(PASS_ADDR);
WiFi.mode(WIFI_STA);
if (ssid.length() > 0) {
Serial.printf("[WIFI] Attempting to connect to %s\n", ssid.c_str());
WiFi.begin(ssid.c_str(), pass.c_str());
while (WiFi.status() != WL_CONNECTED) {
delay(100);
Serial.print(".");
}
Serial.println("\n[WIFI] Connected.");
Serial.printf("[WIFI] IP Address: %s\n", WiFi.localIP().toString().c_str());
startFauxmo();
} else {
Serial.println("[WIFI] No stored credentials, setting up Access Point.");
startAccessPointMode();
}
}
void loop() {
static bool lastButtonState = HIGH; // Start with assumption button is released
bool currentButtonState = digitalRead(BUTTON_PIN);
if (currentButtonState == LOW && lastButtonState == HIGH) {
buttonPressedTime = millis();
Serial.println("[BUTTON] Button press detected, starting timer...");
}
if (currentButtonState == HIGH && lastButtonState == LOW) {
if (millis() - buttonPressedTime > longPressTime && !apModeTriggered) {
Serial.println("[BUTTON] Button pressed long enough, activating AP mode.");
clearEEPROM();
startAccessPointMode();
apModeTriggered = true;
}
buttonPressedTime = 0;
}
lastButtonState = currentButtonState; // Update last button state
if (!apModeTriggered) {
fauxmo.handle();
} else {
dnsServer.processNextRequest();
server.handleClient();
}
}
void startAccessPointMode() {
WiFi.disconnect();
WiFi.mode(WIFI_AP);
WiFi.softAP("RelaisKeinNetz", "12345678");
WiFi.softAPConfig(IPAddress(192, 168, 4, 1), IPAddress(192, 168, 4, 1), IPAddress(255, 255, 255, 0));
server.close(); // Ensure the server is not running before reconfiguring
server.on("/", HTTP_GET, handleRoot);
server.on("/connect", HTTP_POST, handleConnect);
server.begin();
dnsServer.start(DNS_PORT, "*", IPAddress(192, 168, 4, 1)); // Redirect all DNS requests to the AP
Serial.println("[AP MODE] Access Point Mode Started");
Serial.printf("[AP MODE] SSID: RelaisKeinNetz, IP: %s\n", WiFi.softAPIP().toString().c_str());
}
void handleRoot() {
String page = "<html><body><h1>Setup WiFi Connection</h1><form action='/connect' method='POST'>SSID:<input type='text' name='ssid'><br>Password:<input type='password' name='pass'><br><input type='submit' value='Connect'></form></body></html>";
server.send(200, "text/html", page);
Serial.println("[SERVER] Served Root Page.");
}
void handleConnect() {
String ssid = server.arg("ssid");
String pass = server.arg("pass");
if (ssid.length() == 0 || pass.length() == 0) {
Serial.println("[ERROR] SSID or Password not provided.");
server.send(400, "text/html", "<h1>Connection Failed!</h1><p>SSID or password not provided.</p>");
return;
}
WiFi.mode(WIFI_STA);
WiFi.begin(ssid.c_str(), pass.c_str());
Serial.printf("[CONNECT] Trying to connect to %s\n", ssid.c_str());
unsigned long startTime = millis();
while (WiFi.status() != WL_CONNECTED && millis() - startTime < 30000) { // 30-second timeout for WiFi connection
delay(500);
Serial.print(".");
}
if (WiFi.status() != WL_CONNECTED) {
Serial.println("\n[ERROR] Connection Failed! Check your details and try again.");
server.send(500, "text/html", "<h1>Connection Failed!</h1><p>Check your details and try again.</p>");
apModeTriggered = false; // Keep in AP mode to retry
} else {
Serial.println("\n[CONNECT] Connected successfully!");
server.send(200, "text/html", "<h1>Connected successfully!</h1><h2>IP address: " + WiFi.localIP().toString() + "</h2>");
writeStringToEEPROM(SSID_ADDR, ssid);
writeStringToEEPROM(PASS_ADDR, pass);
EEPROM.commit();
WiFi.softAPdisconnect(true);
apModeTriggered = false;
startFauxmo(); // Start Fauxmo service
}
}
void writeStringToEEPROM(int startAddr, const String &data) {
for (int i = 0; i < data.length(); ++i) {
EEPROM.write(startAddr + i, data[i]);
}
EEPROM.write(startAddr + data.length(), '\0'); // Null terminate
EEPROM.commit();
Serial.println("[EEPROM] Credentials saved.");
}
String readStringFromEEPROM(int startAddr) {
String result;
int offset = 0;
char readChar = EEPROM.read(startAddr + offset);
while (readChar != '\0') {
result += readChar;
offset++;
readChar = EEPROM.read(startAddr + offset);
}
return result;
}
void clearEEPROM() {
for (int i = 0; i < EEPROM_SIZE; i++) {
EEPROM.write(i, 0);
}
EEPROM.commit();
Serial.println("[EEPROM] EEPROM Cleared.");
}
void startFauxmo() {
Serial.begin(SERIAL_BAUDRATE);
pinMode(D3, OUTPUT); // Pin für Relais 1
pinMode(D4, OUTPUT); // Pin für Relais 2
pinMode(D1, OUTPUT); // Pin für Relais 3
pinMode(D2, OUTPUT); // Pin für Relais 4
// Initialisiere alle Relais im ausgeschalteten Zustand
digitalWrite(D3, HIGH); // Schalte Relais D3 aus
digitalWrite(D4, HIGH); // Schalte Relais D4 aus
digitalWrite(D1, HIGH); // Schalte Relais D1 aus
digitalWrite(D2, HIGH); // Schalte Relais D2 aus
// Define how the state of the devices should be changed when Alexa sends a command
fauxmo.createServer(true);
fauxmo.setPort(80);
fauxmo.enable(true);
// Füge die Geräte hinzu, die über Alexa gesteuert werden sollen
fauxmo.addDevice("Spiegel");
Serial.println("[DEBUG] Added device Spiegel");
delay(10);
fauxmo.addDevice("Licht an der Tür");
Serial.println("[DEBUG] Added device Licht an der Tür");
delay(10);
fauxmo.addDevice("Licht unter dem Tisch"); // Name für das dritte Relais
Serial.println("[DEBUG] Added device Licht unter dem Tisch");
delay(10);
fauxmo.addDevice("Licht hinterm Bildschirm"); // Name für das vierte Relais
Serial.println("[DEBUG] Added device Licht hinterm Bildschirm");
delay(10);
// Definiere, wie der Zustand der Geräte geändert wird, wenn Alexa einen Befehl sendet
fauxmo.onSetState([](unsigned char device_id, const char * device_name, bool state, unsigned char value) {
Serial.printf("[MAIN] Device #%d (%s) state: %s value: %d\n", device_id, device_name, state ? "ON" : "OFF", value);
// Steuere jedes Relais basierend auf dem Gerätenamen
if (strcmp(device_name, "Spiegel") == 0) {
stateRelay1 = !stateRelay1; // Umschalten des Zustands
digitalWrite(D3, stateRelay1 ? HIGH : LOW);
Serial.println("[DEBUG] Spiegel relay state changed.");
delay(10);
} else if (strcmp(device_name, "Licht an der Tür") == 0) {
stateRelay2 = !stateRelay2; // Umschalten des Zustands
digitalWrite(D4, stateRelay2 ? HIGH : LOW);
Serial.println("[DEBUG] Licht an der Tür relay state changed.");
delay(10);
} else if (strcmp(device_name, "Licht unter dem Tisch") == 0) {
stateRelay3 = !stateRelay3; // Umschalten des Zustands
digitalWrite(D1, stateRelay3 ? HIGH : LOW);
Serial.println("[DEBUG] Licht unter dem Tisch relay state changed.");
delay(10);
} else if (strcmp(device_name, "Licht hinterm Bildschirm") == 0) {
stateRelay4 = !stateRelay4; // Umschalten des Zustands
digitalWrite(D2, stateRelay4 ? HIGH : LOW);
Serial.println("[DEBUG] Licht hinterm Bildschirm relay state changed.");
delay(10);
}
});
Serial.println("[FAUXMO] Fauxmo devices initialized and running.");
}