NEWS
ESP8266 reagiert auf 0 & 1, aber nicht auf true & false
-
Hey zusammen,
ich bin noch ganz neu in dem ganzen Thema. Bin Elektroniker aber leider kein guter Programmierer und habe da ein Problem, welches ich nicht gelöst bekomme.
Also ich habe nun mehrere ESP-01 per MQTT mit ioBroker verbunden. Über die hqwidgets (die runden mit der Glühlampe) konnte ich über vis auch bereits die Ausgänge schalten. Dazu habe ich bei Wert min und max einfach 0 und 1 eingetragen.
Auf den ESP läuft folgender Skript:
`#include <esp8266wifi.h>#include <pubsubclient.h>#include <bounce2.h>#include <eeprom.h>const char* ssid = "..."; const char* password = "..."; const char* mqtt_server = "192.168.178.23"; WiFiClient espClient; PubSubClient client(espClient); long lastMsg = 0; char msg[50]; int value = 0; const char* clientID = "ESP 3"; const char* outTopic = "ESPout3"; const char* inTopic1 = "ESPin3.1"; const char* inTopic2 = "ESPin3.2"; int relay_pin1 = 2; int relay_pin2 = 0; // int button_pin1 = 1; // int button_pin2 = 3; bool relayState1 = LOW; bool relayState2 = LOW; // Instantiate a Bounce object : Bounce debouncer = Bounce(); 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) { // extButton(); for(int i = 0; i<500; i++){ // extButton(); delay(1); } 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(); if ((char)payload[0] == '0') { digitalWrite(relay_pin1, LOW); Serial.println("relay_pin1 -> LOW"); relayState1 = LOW; EEPROM.write(0, relayState1); EEPROM.commit(); } else if ((char)payload[0] == '1') { digitalWrite(relay_pin1, HIGH); Serial.println("relay_pin1 -> HIGH"); relayState1 = HIGH; EEPROM.write(0, relayState1); EEPROM.commit(); } else if ((char)payload[0] == '2') { digitalWrite(relay_pin2, LOW); Serial.println("relay_pin2 -> LOW"); relayState2 = LOW; EEPROM.write(1, relayState2); EEPROM.commit(); } else if ((char)payload[0] == '3') { digitalWrite(relay_pin2, HIGH); Serial.println("relay_pin2 -> HIGH"); relayState2 = HIGH; EEPROM.write(1, relayState2); EEPROM.commit(); } } void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Attempt to connect if (client.connect(clientID)) { Serial.println("connected"); // Once connected, publish an announcement... client.publish(outTopic, "ESP booted"); // client.publish(outTopic2, "ESP booted"); // ... and resubscribe client.subscribe(inTopic1); client.subscribe(inTopic2); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying for(int i = 0; i<5000; i++){ // extButton(); delay(1); } } } } /* void extButton() { debouncer.update(); // Call code if Bounce fell (transition from HIGH to LOW) : if ( debouncer.fell() ) { Serial.println("Debouncer fell"); // Toggle relay state : relayState1 = !relayState1; digitalWrite(relay_pin1,relayState1); EEPROM.write(0, relayState1); // Write state to EEPROM if (relayState1 == 1){ client.publish(outTopic1, "1"); } else if (relayState1 == 0){ client.publish(outTopic1, "0"); } } } */ void setup() { EEPROM.begin(512); // Begin eeprom to store on/off state pinMode(relay_pin1, OUTPUT); // Initialize the relay pin as an output // pinMode(button_pin1, INPUT); // Initialize the relay pin as an output pinMode(relay_pin2, OUTPUT); // Initialize the relay pin as an output // pinMode(button_pin2, INPUT); // Initialize the relay pin as an output relayState1 = EEPROM.read(0); digitalWrite(relay_pin1,relayState1); relayState2 = EEPROM.read(1); digitalWrite(relay_pin2,relayState2); // debouncer.attach(button_pin1); // Use the bounce2 library to debounce the built in button debouncer.interval(50); // Input must be low for 50 ms Serial.begin(115200); setup_wifi(); // Connect to wifi client.setServer(mqtt_server, 1883); client.setCallback(callback); } void loop() { if (!client.connected()) { reconnect(); } client.loop(); // extButton(); }</eeprom.h></bounce2.h></pubsubclient.h></esp8266wifi.h>` So, nun habe ich mal zum Testen auch den yahka-Adapter installiert und per youtube Video hab ich es auch recht schnell geschafft die Objekte in HomeKit am iPhone anzeigen zu lassen. Schalten kann ich die Objekte auch und am ESP blitzt auch immer kurz die blaue LED auf. Laut Skript wechselt der ESP den status des Ausgangs ja, wenn er als Payload eine 1 oder 0 bekommt. Über die HomeKit App und auch bei anderen Vorgängen im ioBroker wird aber immer nur ein true oder false gesendet. Die Befehle kommen auch am ESP an, aber bewirken dann nichts. Muss ich nun eher was am Skript ändern, oder gibt es im ioBroker irgendwo/irgendwie die Möglichkeit dem ESP eine 1 und 0 statt true und false zu schicken? Habe schon die SuFu genutzt, aber es sind noch viele Fachspezifische Begriffe gefallen, die es mir sehr mühsam machen da adhoc durchzublicken. Danke vorab an alle :)[/i]
-
Muss ich nun eher was am Skript ändern, oder gibt es im ioBroker irgendwo/irgendwie die Möglichkeit dem ESP eine 1 und 0 statt true und false zu schicken? `
Ich würde das auf dem ESP ändern. Du musst ja nur zusätzlich zum Payload 0 oder 1 noch true oder false hinzufügen.Ich kenne mich nicht mit der Arduino Programmierung nicht aus aber das dürfte dann entweder so:
if ((char)payload[0] == '0' || 'false')
oder so:
if ((char)payload[0] == '0' || (char)payload[0] == 'false')
aussehen.
-
Ja, das hatte ich vorher auch schonmal versucht, aber führte zu seltsamen Ergebnissen.
Egal in welcher Form ich den zusätzlichen Payload eintrug, wurde entweder gar nichts geschaltet oder immer nur Ein oder immer nur Aus.
Hab auch mal die Anführungszeichen bei true und false weggelassen, aber das half auch nicht.
Befehle kommen zwar immer am ESP an, aber er reagiert noch falsch oder gar nicht.
mit 1 und 0 kann ich weiterhin schalten, aber bei true und false schaltet er entweder immer ein oder gar nicht
6995_bildschirmfoto_2018-04-30_um_10.43.53.png
6995_bildschirmfoto_2018-04-30_um_10.47.26.png -
@Jey Cee:if ((char)payload[0] == '0' || 'false') ```` `
ich weiß nicht genau wie das in C ist, aber if ('false') ist in JS gleichbedeutend mit if (true)
` > ````
if ((char)payload[0] == '0' || (char)payload[0] == 'false')
```` `
Auch das kann nicht funktionieren, da ein einzelnes Zeichen (payload[0]) nicht gleich einem String aus 5 Zeichen ('false') entsprechen kann.Eventuell geht das mit strcmp oder strncmp:
https://stackoverflow.com/a/15580332
http://www.c-howto.de/tutorial/strings- … ergleichn/
also
if ((char)payload[0] == '0' || strcmp(payload, 'false') == 0)
oder
if ((char)payload[0] == '0' || strncmp(payload, 'false', 5) == 0)
-
if ((char)payload[0] == '0' || strcmp(payload, 'false') == 0)
oder
if ((char)payload[0] == '0' || strncmp(payload, 'false', 5) == 0) ```` `
Da gibts ne dicke Fehlermeldung beim Kompilieren
Arduino: 1.8.5 (Mac OS X), Board: "Generic ESP8266 Module, 80 MHz, ck, 26 MHz, 40MHz, QIO, 1M (64K SPIFFS), 5, v2 Lower Memory, Disabled, None, Only Sketch, 115200" /Users/Chris/Desktop/ESP/mqtt_esp8266_master/mqtt_esp8266_master_test/mqtt_esp8266_master_test.ino: In function 'void callback(char*, byte*, unsigned int)': mqtt_esp8266_master_test:67: error: invalid conversion from 'byte* {aka unsigned char*}' to 'const char*' [-fpermissive] if ((char)payload[0] == '0' || strcmp(payload, 'false') == 0) { ^ In file included from /Users/Chris/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/tools/sdk/libc/xtensa-lx106-elf/include/stdlib.h:11:0, from /Users/Chris/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/cores/esp8266/Arduino.h:27, from sketch/mqtt_esp8266_master_test.ino.cpp:1: /Users/Chris/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/tools/sdk/libc/xtensa-lx106-elf/include/string.h:28:13: error: initializing argument 1 of 'int strcmp(const char*, const char*)' [-fpermissive] int _EXFUN(strcmp,(const char *, const char *)); ^ /Users/Chris/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/tools/sdk/libc/xtensa-lx106-elf/include/_ansi.h:65:30: note: in definition of macro '_EXFUN' #define _EXFUN(name, proto) name proto ^ mqtt_esp8266_master_test:67: error: invalid conversion from 'int' to 'const char*' [-fpermissive] if ((char)payload[0] == '0' || strcmp(payload, 'false') == 0) { ^ In file included from /Users/Chris/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/tools/sdk/libc/xtensa-lx106-elf/include/stdlib.h:11:0, from /Users/Chris/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/cores/esp8266/Arduino.h:27, from sketch/mqtt_esp8266_master_test.ino.cpp:1: /Users/Chris/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/tools/sdk/libc/xtensa-lx106-elf/include/string.h:28:13: error: initializing argument 2 of 'int strcmp(const char*, const char*)' [-fpermissive] int _EXFUN(strcmp,(const char *, const char *)); ^ /Users/Chris/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/tools/sdk/libc/xtensa-lx106-elf/include/_ansi.h:65:30: note: in definition of macro '_EXFUN' #define _EXFUN(name, proto) name proto ^ Mehrere Bibliotheken wurden für "PubSubClient.h" gefunden Benutzt: /Users/Chris/Documents/Arduino/libraries/PubSubClient Nicht benutzt: /Users/Chris/Documents/Arduino/libraries/PubSubClient-2.6.09 exit status 1 invalid conversion from 'byte* {aka unsigned char*}' to 'const char*' [-fpermissive] Dieser Bericht wäre detaillierter, wenn die Option "Ausführliche Ausgabe während der Kompilierung" in Datei -> Voreinstellungen aktiviert wäre.
-
Da gibts ne dicke Fehlermeldung beim Kompilieren
invalid conversion from 'byte* {aka unsigned char*}' to 'const char*' [-fpermissive] ```` `
So tief bin ich in C nicht drin, aber eine explizite Umwandlung könnte eventuell funktionieren:
strcmp((char*)payload, 'false')
-
So tief bin ich in C nicht drin, aber eine explizite Umwandlung könnte eventuell funktionieren:
strcmp((char*)payload, 'false') ```` `
Ebenso ohne Erfolg:
Arduino: 1.8.5 (Mac OS X), Board: "Generic ESP8266 Module, 80 MHz, ck, 26 MHz, 40MHz, QIO, 1M (64K SPIFFS), 5, v2 Lower Memory, Disabled, None, Only Sketch, 115200" /Users/Chris/Desktop/ESP/mqtt_esp8266_masterTESTETS/mqtt_esp8266_master_test/MQTT HTTP TEST/MQTT_HTTP_TEST/MQTT_HTTP_TEST.ino: In function 'void callback(char*, byte*, unsigned int)': MQTT_HTTP_TEST:73: error: invalid conversion from 'int' to 'const char*' [-fpermissive] if ((char)payload[0] == '0' || strcmp((char*)payload, 'false')) { ^ In file included from /Users/Chris/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/tools/sdk/libc/xtensa-lx106-elf/include/stdlib.h:11:0, from /Users/Chris/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/cores/esp8266/Arduino.h:27, from sketch/MQTT_HTTP_TEST.ino.cpp:1: /Users/Chris/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/tools/sdk/libc/xtensa-lx106-elf/include/string.h:28:13: error: initializing argument 2 of 'int strcmp(const char*, const char*)' [-fpermissive] int _EXFUN(strcmp,(const char *, const char *)); ^ /Users/Chris/Library/Arduino15/packages/esp8266/hardware/esp8266/2.4.1/tools/sdk/libc/xtensa-lx106-elf/include/_ansi.h:65:30: note: in definition of macro '_EXFUN' #define _EXFUN(name, proto) name proto ^ Mehrere Bibliotheken wurden für "PubSubClient.h" gefunden Benutzt: /Users/Chris/Documents/Arduino/libraries/PubSubClient Nicht benutzt: /Users/Chris/Documents/Arduino/libraries/PubSubClient-2.6.09 exit status 1 invalid conversion from 'int' to 'const char*' [-fpermissive] Dieser Bericht wäre detaillierter, wenn die Option "Ausführliche Ausgabe während der Kompilierung" in Datei -> Voreinstellungen aktiviert wäre.
Gibt es keine Möglichkeit (auch wenn das evtl. gepfuscht ist) im ioBroker quasi ein Objekt anzulegen, welches auf "true" und "false" reagiert und daraufhin eine "0" oder "1" an ein anderes Objekt zu senden?
Das müsste dann wahrscheinlich aber bidirektional laufen…. Ich seh schon die Problematik.... also muss ich mal weiter stöbern und versuchen
-
Gibt es keine Möglichkeit (auch wenn das evtl. gepfuscht ist) im ioBroker quasi ein Objekt anzulegen, welches auf "true" und "false" reagiert und daraufhin eine "0" oder "1" an ein anderes Objekt zu senden? `
Ja, die gibt es mit Hilfe von Javascript. Vorschlag:const nameBool = '...'; // Datenpunktname mit false/true const idBool = 'javascript.' + instance + '.' + nameBool; const idESP = '...'; // Datenpunkt-ID mit "0"/"1" var bool = false; if(getState(idESP).val == '1') bool = true; createState(nameBool, bool, {type: 'boolean'}); on(idBool, function(dp) { if(dp.state.val != bool) { if(dp.state.val) setState(idESP, "1"); else setState(idESP, "0"); } }); on({id: idESP, ack: true}, function(dp) { if(dp.state.val == '1') bool = true; else bool = false; setState(idBool, bool, true); });
-
Das hat auch nicht so recht funktioniert…
Habe jetzt eine Möglichkeit gefunden.
Habe in der callback Funktion noch "String message" hinzugefügt und kann jetzt tatsächlich das Relais_1 entweder über "0 und 1" oder über "true und false" ansteuern. Somit klappt auch das ansteuern über HomeKit bzw. den yahka Adapter. Juhu ^^
Ok, danke schonmal für die Hilfestellung, ohne die ich den passenden Skript nie gefunden hätte
Eine Kleinigkeit wäre da noch, auch wenn ich weiß, dass dies evtl. das falsche Forum für die Frage ist, aber vielleicht könnt ihr mir doch ein paar Hinweise geben
Der Code-Schnipsel sieht nun wie folgt aus:
`void callback(char* topic, byte* payload, unsigned int length) { String message; Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); char c = (char)payload[i]; message += c; } Serial.println(); if ((char)payload[0] == '0' || message == "false") { digitalWrite(relay_pin1, LOW); Serial.println("relay_pin1 -> LOW"); relayState1 = LOW; EEPROM.write(0, relayState1); EEPROM.commit(); } else if ((char)payload[0] == '1' || message == "true") { digitalWrite(relay_pin1, HIGH); Serial.println("relay_pin1 -> HIGH"); relayState1 = LOW; EEPROM.write(0, relayState1); EEPROM.commit(); } else if ((char)payload[0] == '2') { digitalWrite(relay_pin2, LOW); Serial.println("relay_pin2 -> LOW"); relayState2 = LOW; EEPROM.write(1, relayState2); EEPROM.commit(); } else if ((char)payload[0] == '3') { digitalWrite(relay_pin2, HIGH); Serial.println("relay_pin2 -> HIGH"); relayState2 = HIGH; EEPROM.write(1, relayState2); EEPROM.commit(); } }` Wie vielleicht zu erkennen ist, hab ich aber zwei Relais am ESP-01 :D Das hat nun zur Folge, dass ich nicht zweimal den true und false Befehl nutzen kann, da sich sonst beide Relais angesprochen fühlen. Deshalb hatte ich vorab die Payloads auch "0,1" für Relais_1 (GPIO 2) und "2,3" für Relais_2 (GPIO 0) gewählt. Hoffe ihr versteht was ich meine... Zumal ich auch nicht genau weiß, welche Einstellungen ich dann (falls überhaupt möglich) im yahka Adapter wählen müsste für das Objekt... Hier nochmal der ganze Code: `~~[code]~~#include <esp8266wifi.h>#include <pubsubclient.h>#include <bounce2.h>#include <eeprom.h>#include <esp8266webserver.h>const char* ssid = "..."; const char* password = "..."; const char* mqtt_server = "192.168.178.23"; WiFiClient espClient; PubSubClient client(espClient); long lastMsg = 0; char msg[50]; int value = 0; const char* clientID = "ESP 3"; const char* outTopic = "ESPout3"; const char* inTopic1 = "ESPin3.1"; const char* inTopic2 = "ESPin3.2"; #define RelaisPin 2 // Relais int active_low = 1; int relay_pin1 = 2; int relay_pin2 = 0; bool relayState1 = LOW; bool relayState2 = LOW; ESP8266WebServer server(80); // Serverport hier einstellen int val = 0; // Instantiate a Bounce object : Bounce debouncer = Bounce(); 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) { for(int i = 0; i<500; i++){ delay(1); } 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) { String message; Serial.print("Message arrived ["); Serial.print(topic); Serial.print("] "); for (int i = 0; i < length; i++) { Serial.print((char)payload[i]); char c = (char)payload[i]; message += c; } Serial.println(); if ((char)payload[0] == '0' || message == "false") { digitalWrite(relay_pin1, LOW); Serial.println("relay_pin1 -> LOW"); relayState1 = LOW; EEPROM.write(0, relayState1); EEPROM.commit(); } else if ((char)payload[0] == '1' || message == "true") { digitalWrite(relay_pin1, HIGH); Serial.println("relay_pin1 -> HIGH"); relayState1 = LOW; EEPROM.write(0, relayState1); EEPROM.commit(); } else if ((char)payload[0] == '2') { digitalWrite(relay_pin2, LOW); Serial.println("relay_pin2 -> LOW"); relayState2 = LOW; EEPROM.write(1, relayState2); EEPROM.commit(); } else if ((char)payload[0] == '3') { digitalWrite(relay_pin2, HIGH); Serial.println("relay_pin2 -> HIGH"); relayState2 = HIGH; EEPROM.write(1, relayState2); EEPROM.commit(); } } void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Attempt to connect if (client.connect(clientID)) { Serial.println("connected"); // Once connected, publish an announcement... client.publish(outTopic, "ESP booted"); // client.publish(outTopic2, "ESP booted"); // ... and resubscribe client.subscribe(inTopic1); client.subscribe(inTopic2); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying for(int i = 0; i<5000; i++){ // extButton(); delay(1); } } } } void setup() { EEPROM.begin(512); // Begin eeprom to store on/off state pinMode(relay_pin1, OUTPUT); // Initialize the relay pin as an output pinMode(relay_pin2, OUTPUT); // Initialize the relay pin as an output relayState1 = EEPROM.read(0); digitalWrite(relay_pin1,relayState1); relayState2 = EEPROM.read(1); digitalWrite(relay_pin2,relayState2); // debouncer.attach(button_pin1); // Use the bounce2 library to debounce the built in button debouncer.interval(50); // Input must be low for 50 ms Serial.begin(115200); setup_wifi(); // Connect to wifi client.setServer(mqtt_server, 1883); client.setCallback(callback); } void loop() { if (!client.connected()) { reconnect(); } client.loop(); }</esp8266webserver.h></eeprom.h></bounce2.h></pubsubclient.h></esp8266wifi.h>` [/i][/i][/code][/i][/i]
-
Hab jetzt nochmal versucht einen Datenpunkt anzulegen und mit Blockly über den Datenpunkt den Wert von dem anderen Objekt zu ändern, aber das klappt nicht.
Ziel wäre:
Wenn "Relay_ESP_3_2" ist true
dann ändere Wert von "ESPin3.2" auf 3
Aber irgendwie klappt das nicht…
Edit:
Hat sich erledigt. Hatte den Skript in "global" angelegt. Dann hab ich ihn mal bei "common" reingepackt und alles lief sofort
6995_bildschirmfoto_2018-05-01_um_12.22.46.png
6995_bildschirmfoto_2018-05-01_um_12.22.58.png
6995_bildschirmfoto_2018-05-01_um_12.23.08.png