MQTT Button mit UI
Beschreibung:
Dieser Code implementiert einen Button-Sensor auf einem ESP8266 (D1 Mini), der den Zustand eines Tasters über MQTT an einen Server sendet. Der Gerätename kann über eine einfache Weboberfläche konfiguriert werden, und der Name bleibt auch nach einem Neustart erhalten, da er im EEPROM gespeichert wird. Die IP-Adresse des Geräts wird ebenfalls regelmäßig an den MQTT-Server gesendet.
Der Button-Sensor schaltet zwischen „true“ und „false“ um, je nachdem, ob der Taster gedrückt wird oder nicht. Der Gerätename kann angepasst werden, was automatisch die MQTT-Pfade aktualisiert.
Hardware-Verkabelung:
- Button: Der Taster wird an GPIO 4 (D2) des D1 Mini angeschlossen. Der interne Pull-Up-Widerstand wird aktiviert, sodass kein externer Widerstand notwendig ist.
- D1 Mini: Das Modul benötigt WLAN-Zugang, um mit dem konfigurierten Netzwerk zu kommunizieren und Daten an den MQTT-Server zu senden.
Anschlussübersicht:
- Button: Einer der Kontakte des Tasters wird mit GPIO 4 (Pin D2) verbunden, der andere Kontakt geht an GND.
- ESP8266 (D1 Mini): Das Modul muss über USB mit Strom versorgt werden und über WLAN Zugang zum konfigurierten Netzwerk haben.
Die Weboberfläche ermöglicht es, den Gerätenamen direkt über den Browser zu ändern. Dies vereinfacht das Ändern von Einstellungen, ohne dass der Code jedes Mal neu geflasht werden muss.
#include
#include
#include
#include
// WiFi Zugangsdaten
const char* ssid = "WLAN SSID"; // hier Dein WLAN Name eintragen
const char* password = "WLAN Passwort"; // hier Dein WLAN Passwort eintragen
// MQTT Zugangsdaten
const char* mqtt_server = "192.168.x.xx"; // hier die IP des MQTT-Servers eintragen
const int mqtt_port = 1885; // hier den Port des MQTT-Servers eintragen
const char* mqtt_user = "MQTT-User"; // hier den Benutzer vom MQTT-Servers eintragen
const char* mqtt_password = "MQTT-Passwort"; // hier das Passwort vom MQTT-Servers eintragen
// EEPROM Konfiguration
#define EEPROM_SIZE 64
#define DEVICE_NAME_ADDRESS 0
char device_name[32];
// MQTT Topic Basis
String mqtt_topic;
String mqtt_info_topic;
WiFiClient espClient;
PubSubClient client(espClient);
ESP8266WebServer server(80);
const int buttonPin = 4; // Pin an dem der Button angeschlossen ist
bool lastButtonState = false;
void setup() {
Serial.begin(115200);
// EEPROM initialisieren
EEPROM.begin(EEPROM_SIZE);
loadDeviceName();
// MQTT Topic initialisieren
mqtt_topic = String(device_name) + "/Button";
mqtt_info_topic = String(device_name) + "/Info/ip";
// Button Pin konfigurieren
pinMode(buttonPin, INPUT_PULLUP);
// WLAN Verbindung herstellen
setup_wifi();
// MQTT Client konfigurieren
client.setServer(mqtt_server, mqtt_port);
reconnect();
// Webserver Endpunkte konfigurieren
server.on("/", HTTP_GET, []() {
String html = "Device Name Config
";
html += "";
server.send(200, "text/html", html);
});
server.on("/setname", HTTP_POST, []() {
if (server.hasArg("name")) {
String newName = server.arg("name");
newName.toCharArray(device_name, sizeof(device_name));
saveDeviceName();
mqtt_topic = String(device_name) + "/Button";
mqtt_info_topic = String(device_name) + "/Info/ip";
server.send(200, "text/html", "Device Name updated to: " + String(device_name) + "
Go Back");
// Nach Aktualisierung den neuen Gerätenamen veröffentlichen
publishDeviceInfo();
} else {
server.send(400, "text/html", "Bad Request
");
}
});
server.begin();
// IP-Adresse an MQTT senden
publishDeviceInfo();
}
void setup_wifi() {
delay(10);
Serial.println();
Serial.print("Verbinde mit WLAN: ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WLAN verbunden");
Serial.print("IP Adresse: ");
Serial.println(WiFi.localIP());
}
void reconnect() {
// Versuche Verbindung zum MQTT Server aufzubauen
while (!client.connected()) {
Serial.print("Verbinde mit MQTT Server: ");
Serial.println(mqtt_server);
if (client.connect(device_name, mqtt_user, mqtt_password)) {
Serial.println("MQTT verbunden");
} else {
Serial.print("Fehler, rc=");
Serial.print(client.state());
Serial.println(", neuer Versuch in 5 Sekunden");
delay(5000);
}
}
}
void loop() {
if (!client.connected()) {
reconnect();
}
client.loop();
server.handleClient();
bool buttonState = digitalRead(buttonPin) == LOW;
if (buttonState != lastButtonState) {
// Button Status hat sich geändert
lastButtonState = buttonState;
// Button Status an MQTT senden
if (buttonState) {
client.publish(mqtt_topic.c_str(), "true");
Serial.println("Button gedrückt: true");
} else {
client.publish(mqtt_topic.c_str(), "false");
Serial.println("Button losgelassen: false");
}
}
}
void loadDeviceName() {
for (int i = 0; i < sizeof(device_name); ++i) {
device_name[i] = EEPROM.read(DEVICE_NAME_ADDRESS + i);
}
if (device_name[0] == 0xFF || device_name[0] == '\0') {
// Standardname setzen, falls noch keiner gespeichert ist
strcpy(device_name, "buttonsensor"); // hier den Name des Buttons eintragen, dieser kann danach über das Web-UI geändert werden
}
}
void saveDeviceName() {
for (int i = 0; i < sizeof(device_name); ++i) {
EEPROM.write(DEVICE_NAME_ADDRESS + i, device_name[i]);
}
EEPROM.commit();
}
void publishDeviceInfo() {
String ip_address = WiFi.localIP().toString();
client.publish(mqtt_info_topic.c_str(), ip_address.c_str());
Serial.print("IP Adresse veröffentlicht: ");
Serial.println(ip_address);
}