NEWS
ESP Signal auf iobroker publishen ???
-
Hi Leutz
Ich bin gerade dabei den Heizöltankfüllstandsmelder nachzu bauen. Anleitungen gibt es ja genug und über Tasmota funktioniert das auch super.
Da ich aber direkt am Sensor noch ein OLED anschließen möchte, bin ichh von Tasmota weg und hab versucht eine Software zu schreiben. Also Arduino aufgemacht, alle Bibliotheken und Boards installiert und meinen Ultraschallsensor HR-SC04 eingebunden. Funktioniert auch gut. Ist allerdings auch nicht wirklich schwer. Das Display SH1306 habe ich auch am laufen. Ein bischen gerechnet und ein paar if-Abfragen rein um die Daten richtig zu positionieren und gut ist. Klappt auch.
Jetzt bin ich dabei die Daten zum iobroker zu schicken. Das Skript mqtt ESP8266 habe ich integriert und es funktioniert auch. Allerdings schickt das Skript nur einen Text "Hallo Welt" mit aufsteigender Nummer zum iobroker und sendet einen Befehl zu meinem ESP8266 um ein Relais bzw. eine LED anzuschalten.Jetzt meine Verständnissfrage:
Wie bekomme ich meine errechnete int-Zahl anstatt des Textes geschickt? Ich habe viel gelesen und habe es so verstanden, dass ich das Format von Char in int ändern muss. Ich habe aber noch nicht verstanden, wie es genau geht. Je mehr ich lese, desto weniger verstehe ich.In Zukunft möchte ich noch ein paar Sensoren (Temp) an den ESP hängen. Aber eins nach dem anderen. Kann mir/uns bitte einmal des MQTT-Skript so erklären, dass ich/wir es auch verstehen?
Warum wird bei der ersten verbindung ein "Halle Welt" geschickt und anschließend ein "Hallo Welt" mit einer laufenden Nummer? Dient der erste Sendebefehl zur initialisierung? Wie kann ich mehrere Strings, chars oder int versenden?LG aus dem Sauerland
Jörg
/* Basic ESP8266 MQTT example This sketch demonstrates the capabilities of the pubsub library in combination with the ESP8266 board/library. It connects to an MQTT server then: - publishes "hello world" to the topic "outTopic" every two seconds - subscribes to the topic "inTopic", printing out any messages it receives. NB - it assumes the received payloads are strings not binary - If the first character of the topic "inTopic" is an 1, switch ON the ESP Led, else switch it off It will reconnect to the server if the connection is lost using a blocking reconnect function. See the 'mqtt_reconnect_nonblocking' example for how to achieve the same result without blocking the main loop. To install the ESP8266 board, (using Arduino 1.6.4+): - Add the following 3rd party board manager under "File -> Preferences -> Additional Boards Manager URLs": http://arduino.esp8266.com/stable/package_esp8266com_index.json - Open the "Tools -> Board -> Board Manager" and click install for the ESP8266" - Select your ESP8266 in "Tools -> Board" */ #include <ESP8266WiFi.h> #include <PubSubClient.h> // Update these with values suitable for your network. const char* ssid = "ConnectionPoint_1"; const char* password = "081269cIIIb"; const char* mqtt_server = "192.168.178.100"; WiFiClient espClient; PubSubClient client(espClient); unsigned long lastMsg = 0; #define MSG_BUFFER_SIZE (50) char msg[MSG_BUFFER_SIZE]; int value = 0; void setup_wifi() { delay(10); // We start by connecting to a WiFi network Serial.println(); Serial.print("Connecting to "); Serial.println(ssid); WiFi.mode(WIFI_STA); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); } randomSeed(micros()); 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(); // Switch on the LED if an 1 was received as first character if ((char)payload[0] == '1') { digitalWrite(BUILTIN_LED, LOW); // Turn the LED on (Note that LOW is the voltage level // but actually the LED is on; this is because // it is active low on the ESP-01) } else { digitalWrite(BUILTIN_LED, HIGH); // Turn the LED off by making the voltage HIGH } } void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Create a random client ID String clientId = "ESP8266Client-"; clientId += String(random(0xffff), HEX); // Attempt to connect if (client.connect(clientId.c_str())) { Serial.println("connected"); // Once connected, publish an announcement... client.publish("outTopic", "hello world"); // ... and resubscribe client.subscribe("inTopic"); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } void setup() { pinMode(BUILTIN_LED, OUTPUT); // Initialize the BUILTIN_LED pin as an output Serial.begin(115200); setup_wifi(); client.setServer(mqtt_server, 1886); client.setCallback(callback); } void loop() { if (!client.connected()) { reconnect(); } client.loop(); unsigned long now = millis(); if (now - lastMsg > 2000) { lastMsg = now; ++value; snprintf (msg, MSG_BUFFER_SIZE, "hello world #%ld", value); Serial.print("Publish message: "); Serial.println(msg); client.publish("outTopic", msg); } }
-
Hi Leutz
Ich mache wohl mal den Anfang mit dem, was ich so verstanden habe, was auch funktioniert, was aber evtl. auch falsch verstanden ist.
-
Die Kommentare oben brauche ich nicht erklären.
-
Als nächstes werden die beiden benötigten Bibliotheken eingebunden. Soweit auch klar.
-
Das eigene SSID und das Kennwort eintragen, damit sich der ESP auch im eigenen Netz befindent. Auch klar.
-
Die IP des iobroker sollte auch klar sein. Bei mir ist es ein Raspberry mit einer festen IP. Klappt auch
-
Im nächsten Schritt wird der WIFI-Client mit dem Namen "espClient" gestartet. "WiFiClient espClient;"
-
Dem PubSub wird mitgeteilt, dass er genau auf diesen Client schauen soll. "PubSubClient client(espClient);"
-
Jetzt wird eine Variable "lastMsg" als unsigned long erstellt und die Null zugewiesen. Also kann diese Variable positive Ganzzahlen erhalten.
-
Anschließend wird eine Variable "MSG_BUFFER_SIZE" definiert, Wofür steht die 50 in der runden Klammer?
Ist das eine definierte Größe? Ich habe gelesen, dass dadurch ein Bufferüberlauf verhindert werden soll. Allerdings habe ich eine MSG mit über 50 Zeichen erstellt. Diese wird auch komplett zum iobroker geschickt. Oder ist das eine max. Anzahl von MSG welche ich hier erstellen bzw. verschicken kann/darf?gelöst: Die 50 gibt die Länge an. D.H. es können max. 49 Zeichen gesendet werden. Das 50'ste Zeichen ist die abschließende Null und wird nicht mit gesendet. -
die Intergerzahl Value ist auch klar und wird zum raufzählen der laufenden Nummer benötigt.
-
im Void setup WIFI wird in den Monitor geschrieben, was gemacht wird, anschließend wir das WIFI gestartet und so lange gewartet bis es connectetd ist. Solange der Aufbau dauert, wird alle 500ms ein Punkt in den Monitor geschrieben.
-
wofür steht das " randomSeed(micros());"? Es wird eine Zufallszahl aus micros gebildet? Warum random? Micros ist doch die Anzahl der Microsekunden, seit das Board gestartet wurde.
Jetzt wird es spannend: Void callback
- callback steht für Daten Empfangen. Heist lesen vom iobroker zum ESP.
- Hier werden drei Variablen gebildet. Einmal das Format char*, einmal byte* und einmal integer mit der Variablen "lenght"
- Wenn ich das richtig verstanden habe, schaut sich das Skript an, wie lang die Daten sind und schreibt so lange einzelne Daten in den Char payload bis eine Null als Abschluss gefunden wird. Was aber bedutet das [i]? Das sollte doch die Anzahl der Variablen sein. Heist das z.B. bei einem Datenstrig "test" (der Wert des String ist das Wort test) gibt es payload[0] bis [3]? und im char wird es zusammengeführt? genau so ist das. Kann man sehr schön im Monitor testen, wenn man nach jedem Wert einen Zeilenubruch einfügt. (als Hilfe)
- das nächste ist wieder klar. Wenn eine "1" vom iobroker gesendet wird, wird das Relais/LED gesetzt. Null heist zwar "EIN" und eins bedeutet "AUS", ist aber bei Tasmota genauso und funktioniert auch.
- void reconnect verstehe ich so, dass nur Daten gesendet werden, wenn ein Verbindung besteht. Ist ja auch logisch. Ansonsten wird so lange gewartet, bis eine Verbindung besteht.
- der gebildete String clientID wird gebildet und bekommt eine zufällige HEX-Zahl nangehängt. Die sehe ich auch im iobroker unter Instanzen
- steht die Verbindung, gibt es den ersten Datensatz mit "Hallo Welt". Den sehe ich aber im iobroker nicht. Oder er ist so schnell, dass er sofort überschrieben wird. Wofür macht man das? Variable im void loop umbenannt. Jetzt sieht man diesen Eintrag und im Anschluss wird die umbenannte Variable gesendet.
- Ich habe gelesen, dass dieser auch weggelassen werden kann. Muss ich mal ausprobieren.
- Besteht keine Verbindung, versucht der ESP alle 5 Sekunden ein reconnect. Auch klar.
- Bei einem Abbruch steht in meinem Monitor als State eine -2. Weiss jemand, was das bedeutet? Ist das der Abbruchgrund? Stört ja nicht, ist aber iterresant zu wissen.
Im Setup wird der Pinout deklariert, die Baudrate hinterlegt (für den Monitor) und der Port für meinen iobroker gebildet.
- Was bedeutet " client.setCallback(callback);" Wird hier nur gesagt, dass es einen Client Callback gibt um Daten abzurufen?
Die loop verstehe ich wieder. Naja, fast jedenfalls.
- alle 2 Sekunden wird ein Wert geschrieben. Das ist über millis gemacht um das Programm an der Stelle nicht duch delay anzuhalten.
- value wird jeweils um eins erhöht. Haben wir ja weiter oben als unsigned interger gebildet.
- was bedeutet das "#%ld"? Da finde ich nichts zu. Im Monitor sehe ich, dass zum "Hallo Welt" die value (#1, #2, #3, ...) angehangen wird. Ist das ein Befehl zur Darstellung?
- als letztes wird der Befehl "client.publish("outTopic", msg);" ausgegeben. Das ist der Name (outTopic) den ich auch im iobroker sehe. Wenn ich hier einen anderen Namen (z.B. Abstand) eingebe, wird er vermutlich im iobroker auch geädert. Richtig? In diese Variable wird der Wert geschrieben, welcher sich gerade in msg befindet. genau so ist es.
- client.loop(); gefunden: In der Schleife loop() sollten noch client.loop(); stehen. Damit wird regelmäßg nachgefragt, ob eine Botschaft angekommen ist (und gegebenenfalls die callback() Routine aufgerufen).
Um eine int-Zahl zu schicken, muss ich doch meine int-Zahl in einen char umwandeln. Wie mache ich das? Und ist es hier die richtige Stelle? Ich hätte es direkt hinter den snprintf-Befehl gesetzt. Oder macht man das mit int-Werten noch ganz anders?
LG aus dem Sauerland
Jörg
-
-
Schon ein paar Tage her....
@c3b said in ESP Signal auf iobroker publishen ???:
Hi Leutz
Ich bin gerade dabei den Heizöltankfüllstandsmelder nachzu bauen. Anleitungen gibt es ja genug und über Tasmota funktioniert das auch super.
Da ich aber direkt am Sensor noch ein OLED anschließen möchte, bin ichh von Tasmota wegkenne ich und hatte für eine 7-Segmentanzeige gleichen Trigger.
und hab versucht eine Software zu schreiben.
hab dafür ESPEasy verwendet was auch alles bzgl. MQTT an Board hat.
VG