ich versuche schon seit Tagen einen Pushbutton zu Basteln.
Als Basis dient dieser Code:
Grundsätzlich funktioniert das ganze. Doch leider schickt er bei einem Tastendruck BEIDE Befehle an den MQTT Broker. Also er schickt ON und dann direkt OFF.
Nun dachte ich mir:
Ich speichere den letzten Wert (ON oder OFF) in eine Variable in den ESP. Diese sollte ja solange leben bleiben bis die Batterie leer ist.
oder
Ich rufe den MQTT Topic mit dem aktuelen Status ab (ON oder OFF) und lasse den entsprechend Befehle per IF-Schleife den gegengesetzt Befehl senden, bei ON sende OFF usw.
Ich habe mich an beiden sachen bereits versucht. Variante 1 war mir zu kompliziert und kann nicht mal sagen ob das überhaupt geht.
Variante 2 hat da mehr gefruchtet. Ich konnte das Topic abfragen, und das ergebnis in eine Variable geschrieben. Tja.. Doch in den Rules unten bei case konnte ich das nicht umsetzten, weil er den Callback vom MQTT wohl NACH den Rules ausgeführt hat und somit hat er immer ein ON gesendet...
Jetzt bin ich mit meinem Latain am Ende.
Ich merke an: Ich bin FiSi und lernwillig und habe mich mit Arduino und der Sprache dazu erst seit ein paar tagen beschäftig, doch nun bin ich am Ende und habe aus Frust alles verworfen und meinen Code gelöscht -.-
Dann habe ich es mit ESPEasy versucht, damit funktioniert es, doch da bekomme ich den ESP aus dem DeepSleep nicht mehr raus. Und das liegt an dem ESP-01. Aber das gehört hier nicht hin.
Hat jemand einen heißen Tipp für mich? Hab ich einen Denkfehler?
Oder kann mir jemand sogar den Code etwas umbasteln, dass Variante 1 oder 2 ausgeführt wird?
Danke!!
case 1: // Give out the message "ON"
client.publish(outTopicMsg, "ON");
Serial.println("Send: ON");
state = 2;
break;
case 2: // Give out the message "OFF"
client.publish(outTopicMsg, "OFF");
Serial.println("Send: OFF");
state = 3;
break;
Das ist ein Auszug aus der switch.
Was denkst Du, passiert, wenn case 1 zutrifft?
Ja, Es wird 'ON' gesendet und der status auf 3 2 umgestellt.
Was denkst Du passiert, wenn wir in 0,2344323 Sekunden hier wieder vorbei kommen?
Ich denke, daß dann der Status OFF gesendet wird.
Die gleiche Zeit später gibt's die Spannung und noch etwas später geht's ins Bett.
Wo hier Rules sind oder wie MQTT im Allgemeinen abläuft - keine Ahnung, aber der Switch Block MUSS den Kram direkt nacheinander so ausgeben - steht ja so da.
Einzig das delay(100) begrenzt die Ausgabe zeitlich etwas.
MfG
Edit
Der Status wird im case auf Zwei, nicht Drei (wie ich Es schrieb) gesetzt.
Dadurch laufen die einzelnen Status auch nacheinander ab, sobald Diese 'losgelöst' wurden.
Sorry. Entweder habe ich gerade Hirnfrost oder ich raff es einfach nicht.
Da fällt mir ein... Kann ich bei der MQTT Abfrage nicht den switch-state auf 2 bzw. 1 setzen?!
Das ganze müsste dann im loop passieren... mhh. Ich muss da nochmal drüber nachdenken.
Hier nochmal mein Code mit MQTT Abfrage/subscribe.
Nun komme ich nicht weiter.
Damit der Ablauf im switch korrekt funktioniert, muss ich ja irgendwie den Variable state dauerhaft speichern. Dann kann ich ja mit einer if schleife die cases abarbeiten.
Also: Wie kann man eine Variable dauerhaft speichern?
Dann würde ich eine variable erstelllen z.B. mqtt_state und die dann abfragen, aber die muss dauerhaft abgespeichert werden. Bis eben die Batterie oder Stromversorgung weg ist. Muss den DeepSleep überstehen.
Hier der Code:
/*
AndyW Dash Button V1
23.02.2018
by Andy Wolff
*/
//**********************************************************************
// INCLUDE
//**********************************************************************
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266mDNS.h>
#include <ESP8266HTTPUpdateServer.h>
//**********************************************************************
// DEFINE
//**********************************************************************
#define LED 2 // GPIO2 - Onboard LED
#define SETUP_BUTTON 12 // Button for Webupdate
//**********************************************************************
// PARAMETER
//**********************************************************************
// Wifi
const char* host = "dashbutton-sz-light";
const char* ssid = "Headquarter";
const char* password = "XXXXXX";
// MQTT
const char* mqtt_server = "10.80.1.24";
const char* mqtt_clientId = "dashbutton-sz-light";
const char* outTopicMsg = "dashbutton-sz/light/state";
const char* outTopicVCC = "dashbutton-sz/light/vcc";
const char* outTopicCon = "dashbutton-sz/light/connect";
// Hardware
boolean mSetupButton = LOW; // flag Setup Button
int ledState = HIGH; // ledState used to set the LED
unsigned long previousMillis = 0; // will store last time LED was updated
const long interval = 500; // interval at which to blink (milliseconds)
long sendtime = 0; // sendtime
char msg[50]; // message for mqtt publish
int state = 0; // for Statemachine
//**********************************************************************
// SETUP
//**********************************************************************
ADC_MODE (ADC_VCC); // VCC Read
ESP8266WebServer httpServer(80);
ESP8266HTTPUpdateServer httpUpdater;
WiFiClient espClient;
PubSubClient client(espClient);
void setup(){
pinMode(SETUP_BUTTON, INPUT_PULLUP); // Webupdate Button
pinMode(LED, OUTPUT); // Onboard LED on ESP-08S as Output
sendtime = millis();
Serial.begin(115200);
// Setup Wifi
setup_wifi();
// Setup MQTT
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
// Setup httpUpdater
MDNS.begin(host);
httpUpdater.setup(&httpServer);
httpServer.begin();
MDNS.addService("http", "tcp", 80);
}
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void callback(char* topic, byte* payload, unsigned int length) {
Serial.print("Message arrived [");
Serial.print(topic);
Serial.print("] ");
for (int i=0;i<length;i++) {
Serial.print((char)payload[i]);
}
Serial.println();
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.println("Attempting MQTT connection...");
// Client ID connected
if (client.connect(mqtt_clientId)) {
Serial.print(mqtt_clientId);
Serial.println(" connected");
// Once connected, publish an announcement...
client.publish(outTopicCon, "connected");
// ... and resubscribe
client.subscribe(outTopicMsg);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
//**********************************************************************
// LOOP
//**********************************************************************
void loop(){
// HTTPServer Handle Client
httpServer.handleClient();
// MQTT Client
if (!client.connected()) {
reconnect();
}
client.loop();
// LED blink when ESP is in Upload Mode
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
// if the LED is off turn it on and vice-versa:
if ((ledState == LOW) && (mSetupButton = HIGH)){
ledState = HIGH;
} else {
ledState = LOW;
}
// set the LED with the ledState of the variable:
digitalWrite(LED, ledState);
}
// Read the VCC from Battery
float vcc = ESP.getVcc() / 1000.0;
vcc = vcc - 0.12; // correction value from VCC
// StateMachine for send the telegram to MQTT
switch (state) {
case 0: // SETUP
if (digitalRead(SETUP_BUTTON) == LOW) {
mSetupButton = HIGH;
Serial.println("Webupdate started ...");
Serial.printf("Open http://%s.local/update in your browser\n", host);
} else {
state = 1;
Serial.println("No Webupdate...");
}
if (mSetupButton == HIGH){
state = 0;
Serial.println("Starting Webupdate...");
}
break;
case 1: // Give out the message "ON"
client.publish(outTopicMsg, "1");
Serial.println("Send: ON");
state = 2;
break;
case 2: // Give out the message "OFF"
client.publish(outTopicMsg, "0");
Serial.println("Send: OFF");
state = 3;
break;
case 3: // Give out the message of the State from VCC
dtostrf(vcc, sizeof(vcc), 2, msg);
client.publish(outTopicVCC, msg);
Serial.print("VCC: ");
Serial.print(msg);
Serial.println("V");
state = 4;
break;
case 4: // Give out the Sendtime on Serial and go to Deepsleep
sendtime = millis() - sendtime;
Serial.print("Sendtime: ");
Serial.print(sendtime);
Serial.println("ms");
Serial.print("Good Night ...");
ESP.deepSleep(0, WAKE_RFCAL);
break;
}
delay(200); // delay in between reads for stability
}
Das habe ich mir schon gedacht, das hatte mich schon sehr verwirrt.
Da frage ich mich wieso, dass so viele nutzen und keiner sich irgendwie dazu äußert.
Hat jemand noch eine Idee?
Ich versuche mich heute abend mal an den RTC Memory vom ESP und bastel was eigenes zusammen.
Etwas fortschritt. RTC war nicht der richtige weg. Machte kein Sinn.
Ich habe nun folgendes zusammengebaut:
//**********************************************************************
// INCLUDE
//**********************************************************************
#include <ESP8266WiFi.h>
#include <PubSubClient.h>
#include <WiFiClient.h>
//**********************************************************************
// DEFINE
//**********************************************************************
#define LED 2 // GPIO2 - Onboard LED
//**********************************************************************
// PARAMETER
//**********************************************************************
// Wifi
const char* host = "dashbutton-sz-light";
const char* ssid = "Headquarter";
const char* password = "XXXXXXXXX";
// MQTT
const char* mqtt_server = "10.80.1.24";
const char* mqtt_clientId = "dashbutton-sz-light";
const char* outTopicMsg = "dashbutton-sz/light/state";
const char* outTopicVCC = "dashbutton-sz/light/vcc";
const char* outTopicCon = "dashbutton-sz/light/connect";
// Hardware
int ledState = HIGH; // ledState used to set the LED
unsigned long previousMillis = 0; // will store last time LED was updated
const long interval = 500; // interval at which to blink (milliseconds)
long sendtime = 0; // sendtime
char msg[50]; // message for mqtt publish
//int mqtt_state = 3;
//**********************************************************************
// SETUP
//**********************************************************************
ADC_MODE (ADC_VCC); // VCC Read
WiFiClient espClient;
PubSubClient client(espClient);
void setup(){
pinMode(LED, OUTPUT); // Onboard LED on ESP-08S as Output
sendtime = millis();
Serial.begin(115200);
// Setup Wifi
setup_wifi();
// Setup MQTT
client.setServer(mqtt_server, 1883);
client.setCallback(callback);
}
void setup_wifi() {
delay(10);
// We start by connecting to a WiFi network
Serial.println();
Serial.print("Connecting to ");
Serial.println(ssid);
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
}
void reconnect() {
// Loop until we're reconnected
while (!client.connected()) {
Serial.println("Attempting MQTT connection...");
// Client ID connected
if (client.connect(mqtt_clientId)) {
Serial.print(mqtt_clientId);
Serial.println(" connected");
// Once connected, publish an announcement...
client.publish(outTopicCon, "connected");
// ... and resubscribe
client.subscribe(outTopicMsg);
} else {
Serial.print("failed, rc=");
Serial.print(client.state());
Serial.println(" try again in 5 seconds");
// Wait 5 seconds before retrying
delay(5000);
}
}
}
void callback(char* topic, byte* payload, unsigned int length) {
String s = String((char*)payload);
int mqtt_state = s.toInt();
Serial.print("Actual State is: ");
Serial.println(mqtt_state);
// Read the VCC from Battery
float vcc = ESP.getVcc() / 1000.0;
vcc = vcc - 0.12; // correction value from VCC
dtostrf(vcc, sizeof(vcc), 2, msg);
Serial.print("VCC: ");
Serial.print(msg);
Serial.println("V");
Serial.print("Publishing VCC State to the MQTT Broker now.");
client.publish(outTopicVCC, msg);
//Set State and publish
Serial.print("Setting State and publishing it to the MQTT Broker now. ");
if (mqtt_state == 0) {
Serial.print("State is OFF. Turning ON. ");
mqtt_state = 1;
Serial.print("State is now: ");
Serial.println(mqtt_state);
sendtime = millis() - sendtime;
Serial.print("Sendtime: ");
Serial.print(sendtime);
Serial.println("ms");
Serial.print("Finished. Going to sleep now.");
//ESP.deepSleep(0, WAKE_RFCAL);
} else if (mqtt_state == 1) {
Serial.print("State is ON. Turning OFF. ");
mqtt_state = 0;
Serial.print("State is now:");
Serial.println(mqtt_state);
sendtime = millis() - sendtime;
Serial.print("Sendtime: ");
Serial.print(sendtime);
Serial.println("ms");
Serial.print("Finished. Going to sleep now.");
//ESP.deepSleep(0, WAKE_RFCAL);
} else {
Serial.print("ERROR: No vaild Value found. ");
Serial.print("Finished with ERRORS. Going to sleep now.");
//ESP.deepSleep(0, WAKE_RFCAL);
}
}
//**********************************************************************
// LOOP
//**********************************************************************
void loop(){
// MQTT Client
if (!client.connected()) {
reconnect();
}
client.loop();
delay(500);
}
Zwei Probleme:
Die Callback Funktion wird nur ausgelöst. Wenn eine MQTT Nachricht in das Topic eingeht.
Wie kann ich die Funktion im loop aufrufen, dass er einfach das Topic ausliest. Es hat ja irgendein Wert, was mein Broker gespeichert hat.
Der Wert in mqtt_state wird am anfang korrekt gespeichert. Dieser hat z.B. den Wert 0. Den schicke aktuell Manuell raus. Wenn ich nun die 1 an das Topic sende, dann kommt eine 13 raus. Wenn ich dann wieder eine 0 sende kommt eine 3. Wenn ich aber 00 oder 01 sende, dann passt es... Hier mal die Serial Console:
Na danke...
Zwei Foren = Verschiedene Leute = Verschiedene Anworten und Lösungen.
Und die Antwort im anderen Forum war ja klar und deutlich und habe neue Fragen bzw. um neue Hilfe gebeten.
Verstehe gerade ein Problem nicht.
Und DerkleinePunk hat schnell geantwortet und ich weiß nicht ob er in dem anderen Forum geantwortet. Ich bin auf jede Hilfe angewiesen und freue mich. Aber sowas muss nicht sein.
Zumindest könntest Du den potentiellen Helfern reinen Wein einschenken, daß Sie eventuell gar nicht mehr beachtet werden, da Du ja bereits seit einer Woche schon woanders Hilfe bekommen hast (Das wäre was für 'Nebenan') oder, daß Du ein weiteres Forum gefunden hast, wo Du Deine Frage gestellt hast (Das wäre hier).
In BEIDEN Threads gehören Links zum jeweils Anderen - so kann sich die Helfer-Schar, Der Das nicht zu blöd ist, anschauen, was bereits versucht wurde.
Und ganz ganz toll ist's auch in zwölf Jahren, wenn irgend ein Neuer über Dein Thread stolpert und eben auch den Anderen findet, wo's vll die Lösung gibt.
Stichwort: Diese gehört dann ebenfalls in BEIDEN erwähnt oder zumindest, daß 'Nebenan' wohl die Lösung erarbeitet wurde - mit Link.
Und wenn Du meinst, daß Das nicht nötig ist, hast Du echt ein Problem!