XAN77 Postat Februarie 21 Partajează Postat Februarie 21 Vă salut, Am o nouă mică dilemă. M-am apucat să reconfigurez jucăriile din casă ce trimit date la un broker mqtt, în general esp01/nodemcu cu senzori, punând pe toate firmware Tasmota, întrucât mi s-a părut mie interesant că pentru modificări ulterioare nu necesită reprogramare ci doar configurare, plus că se poate integra în Homeassistant sau alte aplicații. Pe de altă parte am și module ce au cod făcut în ArduinoIDE pe care nu pot pune Tasmota pentru că au display cu afișare ”complexă”, afișează date din mai multe topicuri mqtt, succesiv și în diverse stiluri, ceea ce nu am găsit cum pot face cu Tasmota. Acestea sunt de regulă ceasurile din camere, ce au display matriceal 8x32 puncte cu MAX7219. M-am lovit astfel de problema necesității de a extrage valorile trimise de senzori din mesajele ce le trimite Tasmota, care sunt mai stufoase decât trimiteam eu cu cod diy. Mesajele respectă stilul JSON, adică reprezintă obiecte (din câte am înțeles). Cel din camera mică unde am un esp01 cu un singur senzor 18b20 trimite mesajul: {"Time":"2024-02-21T19:03:02","DS18B20":{"Id":"0417315443FF","Temperature":24.4},"TempUnit":"C"} Și ăsta e unul simplu, alte mesaje sunt mai stufoase dacă sunt mai mulți senzori, dacă au și umiditate etc. Momentan extrag temperatura folosind poziția caracterelor din șir, în exemplul de mai sus primu caracter e la poziia 75. Dar e penibilă soluția pentru că dacă am mai multe temperaturi în mesaj, poziția acestora se poate schimba dacă unu din ele capătă valori din mai multe sau mai puține caractere. Momentan e ok că nu o să am în cameră sub 10 sau peste 99 grade, dar nu e elegant. Aș vrea să folosesc JSON și să extrag exact obiectele, adică valoarea "Temperature" pentru senzorul "DS18B20", indiferent câte caractere are, dacă are - în față sau nu etc. Dar nu am reușit să înțeleg perfect cum se lucrează cu JSON și nu am reușit să scriu cod pentru a face asta. Dacă are cineva un exemplu sau, și mai bine, timp ca să editeze codul meu de mai jos, dau o bere virtuală Am încercat să chelesc un cod de alte bălării, să fie cât mai simplu. nodemcu cu display cu 4 matrici chinezesc, ce dă subscribe la topicul ce l-am luat cu copy din consola Tasmota, extrag din șir valorile temperaturii și o afișez cu scroll, defilare de la dreapta la stânga cu funcția display_message. Scuze de postarea lungă. Nu am grabă în a rezolva speța. E util însă pe viitor să pot folosi JSON. #include <ESP8266WiFi.h> #include <PubSubClient.h> #include <SPI.h> #include <Adafruit_GFX.h> #include <Max72xxPanel.h> const char* ssid = "..."; const char* password = "..."; const char* mqtt_server = "..."; WiFiClient espClient; PubSubClient client(espClient); long lastMsg = 0; char msg[50]; int value = 0; int ore, minute, secunde; int wait = 70; // In milliseconds int spacer = 1; int width = 5 + spacer; // The font width is 5 pixels int m; int ti, ti_c, ti_cr; // folosite la afisarea temp si umid pe displayul local LED int hi; int pinCS = D4; int numberOfHorizontalDisplays = 6; int numberOfVerticalDisplays = 1; char tasmota_message[150]; char temp_value[6]; Max72xxPanel matrix = Max72xxPanel(pinCS, numberOfHorizontalDisplays, numberOfVerticalDisplays); //ruleaza un text de la dreapta la stanga void display_message(String message){ for ( int i = 0 ; i < width * message.length() + matrix.width() - spacer; i++ ) { //matrix.fillScreen(LOW); int letter = i / width; int x = (matrix.width() - 1) - i % width; int y = (matrix.height() - 8) / 2; // center the text vertically while ( x + width - spacer >= 0 && letter >= 0 ) { if ( letter < message.length() ) { matrix.drawChar(x, y, message[letter], HIGH, LOW, 1); // HIGH LOW means foreground ON, background off, reverse to invert the image } letter--; x -= width; } matrix.write(); // Send bitmap to display delay(wait/2); client.loop(); } } 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); display_message("..wait for wifi.."); } randomSeed(micros()); Serial.println(""); Serial.println("WiFi connected"); Serial.println("IP address: "); Serial.println(WiFi.localIP()); } void callback(String 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]); } if (topic == "tele/%cameramica%/SENSOR") { for (int i = 0; i < length; i++) { tasmota_message[i] = payload[i]; } } temp_value[0] = tasmota_message[75]; temp_value[1] = tasmota_message[76]; temp_value[2] = tasmota_message[77]; temp_value[3] = tasmota_message[78]; temp_value[4] = tasmota_message[93]; } void reconnect() { // Loop until we're reconnected while (!client.connected()) { Serial.print("Attempting MQTT connection..."); // Create a random client ID String clientId = "camera-mica"; clientId += String(random(0xffff), HEX); // Attempt to connect if (client.connect(clientId.c_str() , "x_dadu", "Pecineaga1" )) { Serial.println("subscribed and connected"); client.subscribe("tele/%cameramica%/SENSOR"); } else { Serial.print("failed, rc="); Serial.print(client.state()); Serial.println(" try again in 5 seconds"); // Wait 5 seconds before retrying delay(5000); } } } void verificari(){ client.loop(); } //face delay din bucati de 100ms, intre care face alte verificari void diy_wait_ms (int timp){ client.loop(); timp=timp/100; for (int i=0; i<timp; i++) { // splituisc un delay de 500ms in 5 de 100 delay(100); verificari(); // ca sa fac niste verificari mai des } } void setup() { Serial.begin(115200); matrix.setIntensity(1); // Use a value between 0 and 15 for brightness matrix.setRotation(0, 1); // The first display is position upside down matrix.setRotation(1, 1); // The first display is position upside down matrix.setRotation(2, 1); // The first display is position upside down matrix.setRotation(3, 1); // The first display is position upside down matrix.fillScreen(LOW); matrix.write(); setup_wifi(); client.setServer(mqtt_server, 1883); client.setCallback(callback); } void loop() { if (!client.connected()) { reconnect(); } client.loop(); matrix.fillScreen(LOW); matrix.write(); display_message(temp_value); diy_wait_ms(1000); client.loop(); } Link spre comentariu
XAN77 Postat Februarie 21 Autor Partajează Postat Februarie 21 Am încercat dar nu mam descurcat. Am băgat versiunea 7, apoi un 5.13.5 parca, cum văzusem un toturial pe randomnerdtutorial. Dar nu mia ieșit. Link spre comentariu
Bandi Szasz Postat Februarie 21 Partajează Postat Februarie 21 (editat) E foarte sinmplu cu ArduinoJson, intrii aici pe assistant dai copy paste la Json-ul tau sa iti da codul gata facut https://arduinojson.org/v7/assistant/#/step1 // Stream& input; JsonDocument doc; DeserializationError error = deserializeJson(doc, input); if (error) { Serial.print("deserializeJson() failed: "); Serial.println(error.c_str()); return; } const char* Time = doc["Time"]; // "2024-02-21T19:03:02" const char* DS18B20_Id = doc["DS18B20"]["Id"]; // "0417315443FF" float DS18B20_Temperature = doc["DS18B20"]["Temperature"]; // 24.4 const char* TempUnit = doc["TempUnit"]; // "C" Editat Februarie 21 de Bandi Szasz Link spre comentariu
Bandi Szasz Postat Februarie 21 Partajează Postat Februarie 21 (editat) Daca e generat de site-ul omului care a dezvoltat biblioteca ArduinoJson eu zic ca merge. Editat Februarie 21 de validae Library = Bibliotecă Link spre comentariu
XAN77 Postat Februarie 22 Autor Partajează Postat Februarie 22 Vă salut și vă mulțumesc. Da merge codul generat pe siteul respectiv. Am bâjbâit un pic până am pus componentele codului unde trebuie, unele declarări de variabile sau constante la început în afara funcțiilor ca să fie globale să le pot accesa în loop(). În setup() nu am mai pus nimic, majoritatea liniilor de cod le am în funcția callback. Am modificat acum unu din ceasurile mele și afișez una din temperaturile a 3 senzori în paralel, extrăgând doar obiectul respectiv, în cazul meu cu: JsonObject ds18b20 = doc["DS18B20-1"]; Link spre comentariu
Postări Recomandate
Creează un cont sau autentifică-te pentru a adăuga comentariu
Trebuie să fi un membru pentru a putea lăsa un comentariu.
Creează un cont
Înregistrează-te pentru un nou cont în comunitatea nostră. Este simplu!
Înregistrează un nou contAutentificare
Ai deja un cont? Autentifică-te aici.
Autentifică-te acum