1

Téma: [vyřešeno] přepínání relé pomocí sdc-c / mqtt

Dobrý den,

snažím se přepnout relé pomocí sds-c a vůbec se mi nedaří - snažím se o debug, ale nechová se to podle očekávání. - blok mám takto:

 // nejaka zmena ? (jakakoliv nova zprava?)
 if (last1 != sys[2291])  // sys[2291] je casove razitko for index #1
  {
    // ulozit, abychom to mohli pozdeji znovu porovnat
    last1 = sys[2291];

    // pouzij novou hodnotu!!!
    echo('TOPIC #1: "',sys[2211],'" update to: "',sys[2251],'" ');


    echo('sys[231] je ' sys[231]);
    echo('sys[2251] je ' sys[2251]);
                  
rele1 = sys[231];
echo('rele1 je ' rele1);

rele2 = sys[2251];
echo('rele2 je ' rele2);

    ram[10] = sys[2251];
    echo('ram[10] je ' ram[10]);
    echo('promenna rele1 je ' sys[231]);
                 
};

a výstup v sds je tento: ¨

Cekam na dostupnost site
pripojuji k MQTT Broker... ???
pripojeno k brokeru: OK
TOPIC #1: "sds2/rele1" update to: "1" 
sys[231] je 0
sys[2251] je 1
rele1 je 0
rele2 je 0
ram[10] je 0
promenna rele1 je 0

proc když rele2 je definovane jako sys 2251 se stale ukazuje jako nula ? kde mám chybu prosím o radu. Stejne se mi to chová kdyz se snazim misto o echo o zmenu stavu rele - stale tam mam nulu i kdyz je vstup z 2251 na hodnote 1 nebo 2

2

Re: [vyřešeno] přepínání relé pomocí sdc-c / mqtt

Metodou pokus / omyl jsem trošku pokročil - problém je s tím že sice přečtu hodnotu SYS 2251 ale nejsem schopen ji předat - testoval jsem to na proměnných RAM 1 a RAM 2

                       if (sys[2251] == 10) 
                       {
                       sys[231] = 1;  // Nastavení relé na zapnuto
                       echo('rele zapnuto');
                       }
                       if (sys[2251] == 20) 
                       {
                       sys[231] = 0;  // Nastavení relé na vypnuto
                       echo('rele vypnuto');
                       } else 
                       {
                       echo('chyba prevodu');
                       }
                       echo('po provedeni sys[231] je ' sys[231]);
                       echo('po provedeni sys[2251] je ' sys[2251]);

echo('test ' sys[2251]);
#define VSTUP1 sys[2251]
echo('vstup1  je ' VSTUP1);
ram[1] = VSTUP1;
echo('ram[1]  je ' ram[1]);
#define VSTUP2 55
ram[2] = VSTUP2;
echo('ram[2]  je ' ram[2]);

A výstup z programu je tento:

Cekam na dostupnost site
pripojuji k MQTT Broker... ???
pripojeno k brokeru: OK
TOPIC #1: "sds2/rele1" update to: "20" 
sys[231] je 0
sys[2251] je 20
chyba prevodu
po provedeni sys[231] je 0
po provedeni sys[2251] je 20
test 20
vstup1  je 20
ram[1]  je 0
ram[2]  je 55

Dle toho to vypadá že prostě odmítá použít SYS 2251 - pokud mu v RAM2 místo promenne podstrcim pevne cislo tak to funguje - ale já potřebuji abych mohl ten program ovládat externe abych dokázal na základě příchozí SYS 2251 přepsat SYS 231 a tím přepnout relé - je to poslední věc aby mi fungovalo vše co potřebuji, ale nedokáži přijít na to kde je chyba.

3

Re: [vyřešeno] přepínání relé pomocí sdc-c / mqtt

Tady bude asi ten problém

technomagg napsal:

proc když rele2 je definovane jako sys 2251 ...

To co jste tam napsal (rele2=sys[2251]), ale není "definice" nýbrž "předání hodnoty", a to je dost zásadní rozdíl.


Poud chcete ovládat fyzické relé na desce modulu SDS, musíte zapsat správnou hodnotu do správného sys[] indexu.

Jednotlivé sys[] jsou popsány zde: https://wiki.merenienergie.cz/subdom/wiki/index.php?title=SDS-C:_sdsc_sysp

Pro ovládání relé č. 2 je potřeba zapsat hodnotu do sys[232].

Současně je potřeba mít přiřazené ovládání relé přes SDSC, a to se dá udělat buď tlačítkem ve webovém rozhraní, nebo (pro relé č. 2) zápisem té správné konkrétní hodnoty do sys[197] (viz odkaz výše).

Takže, pokud vám z MQTT přijde hodnota do sys[], tak ji předáte do relé č. 2 (nebo jinam - úpravou toho indexu) takto:

 // do ovladani rele 2., predame hodnotu z prijate MQTT polozky #1
 sprintf(text[0], sys[2251]); // nejprve prekopirujeme string z sys[2251] do pole text, a to od pozice 0 v poli text[]
 atoi(text[0]); // prevede obsah text (od pozice 0] na cislo, vysledek prevodu da do sys[62]
 sys[232] = sys[62]; // vysledek zapiseme do ovladani rele

Tedy celý vzorový kód:

 // nejaka zmena ? (jakakoliv nova zprava?)
 if (last1 != sys[2291])  // sys[2291] je casove razitko for index #1
 {
    // ulozit, abychom to mohli pozdeji znovu porovnat
    last1 = sys[2291];

    // vypis zmeny do konzole
    echo('TOPIC #1: "',sys[2211],'" update to: "',sys[2251],'" ');

    // aplikuje novou hodnotu - ovladani rele
    sprintf(text[0], sys[2251]); // nejprve prekopirujeme string z sys[2251] do pole text, a to od pozice 0 v poli text[]
    atoi(text[0]); // prevede obsah text (od pozice 0] na cislo, vysledek prevodu da do sys[62]
    sys[232] = sys[62]; // vysledek zapiseme do ovladani rele
 }
Pochlubte se - popište jak využíváte své zařízení SDS zde ! Můžete si bezplatně přidat svou reklamu !

4 Naposledy upravil: technomagg (2024-09-15 21:53:15)

Re: [vyřešeno] přepínání relé pomocí sdc-c / mqtt

Tak nevím - nějak mi to nefunguje - tady je celý můj subscribe blok - už jsem se do toho asi úplně zamotal - ale prostě se příkaz neprovede jak očekávám

  mqtt_subscribe(1, 'sds2/rele1');

 // wait for the successful subscribe
 wS:
 if (sys[2200] < 0) goto mqtt_conn_fail; // disconnected (if any negative number)
 if (sys[2202] == 4) goto wS;            // still working... (done when != 4)
 if (sys[2202] != 8)                     // success ? (only if == 8, otherwise error or failure)
 {
   // FAILED -> not subscribed !
   echo('sub error = ', sys[2202]);
   return;
 };

 // nyní, když jsme přihlášeni, budeme sledovat jakoukoli příchozí aktualizaci (změnu hodnoty):

 var last1;
 last1 = 1;

loop:
sys[196] = 2;

// nejaka zmena ? (jakakoliv nova zprava?)
if (last1 != sys[2291])  // sys[2291] je casove razitko for index #1
 {
    // ulozit, abychom to mohli pozdeji znovu porovnat
    last1 = sys[2291];

    // vypis zmeny do konzole
    echo('TOPIC #1: "',sys[2211],'" update to: "',sys[2251],'" ');

    // aplikuje novou hodnotu - ovladani rele
    sys[231] = sys[2251];  // do ovladani rele 2., predame hodnotu z prijate MQTT polozky #1

echo('promenna sys[2251] "'sys[2251]);
echo('promenna sys[231]"'sys[231]);

//echo('rele zapnuto'last1);

//rele1 = sys[2251];


//echo('stav promenne rele1  'rele1);
//if (sys[2251] == 1){
//    sys[231] = 1;  // Zapni relé
//        echo('rele zapnuto');
//} if (sys[2251] == 2) {
//    sys[231] = 0;  // Vypni relé
//    echo('rele vypnuto');
//} else {
//    echo('chyba prevodu');

//    echo('TOPIC #1: "',sys[2211],'" stav rele je: "',sys[231],'" ');
// }
}
 if (sys[2200] < 0) goto mqtt_conn_fail;    // disconnected ?
 if (sys[2202] == 1) goto loop;               // still working ?
 if (sys[2202] != 2)                        // success ?

 // continue loop
 goto loop;

A TOTO JE VÝSTUP Z LOGU PROGRAMU: (napřed jsem posílal hodnotu 255 a pak jsem poslal hodnotu 1 - ani jedno se nepropsalo - zůstala tam pořád nula na sys[231] - co dělám špatně ? Když napíšu do programu sys[231] = 1 nebo sys[231] = 255 tak se to normálně provede - ale v okamžiku kdy to porovnávám s proměnnou 2251 tak se žádné porovnání neprovede a vždy je výsledek zápisu nula - nemůže to být nějaký bug? Přijde mi že to neumí porovnat hodnotu 2251 - jak kdyby to nebylo číslo i když echo číslo zobrazuje - ale já tam neposílám string ale number - toto jsem kontroloval a zkoušel i přenastavit.

ekam na dostupnost site
pripojuji k MQTT Broker... ???
pripojeno k brokeru: OK
TOPIC #1: "sds2/rele1" update to: "255" 
promenna sys[2251] "255
promenna sys[231]"0
TOPIC #1: "sds2/rele1" update to: "1" 
promenna sys[2251] "1
promenna sys[231]"0

5

Re: [vyřešeno] přepínání relé pomocí sdc-c / mqtt

Tak někde je problém:

pokud udělám toto:

if (sys[2251] == 255){
ram[1] = 20;
echo('ram[1] je: "'ram[1]]);
} else {
    echo('chyba prevodu');
echo('stav promenne ram[1]  'ram[1]);
echo('stav promenne sys[2251]  'sys[2251]);

je odpověď tato:

Cekam na dostupnost site
pripojuji k MQTT Broker... ???
pripojeno k brokeru: OK
TOPIC #1: "sds2/rele1" update to: "255" 
promenna sys[2251] 255
promenna sys[231] 0
chyba prevodu
stav promenne ram[1]  0
stav promenne sys[2251]  255

ALE pokud udělám toto:

rele1 = 10;
if (rele1 == 10){
ram[1] = 20;
echo('ram[1] je: "'ram[1]]);
} else {
    echo('chyba prevodu');
echo('stav promenne ram[1]  'ram[1]);
echo('stav promenne sys[2251]  'sys[2251]);

JE ODPOVĚĎ SPRÁVNÁ - VIZ:

Cekam na dostupnost site
pripojuji k MQTT Broker... ???
pripojeno k brokeru: OK
TOPIC #1: "sds2/rele1" update to: "255" 
promenna sys[2251] 255
promenna sys[231] 0
ram[1] je: "20

Z toho mi přijde že SDS neumí s tou proměnnou sys[2251] správně a korektně pracovat - nevím proč to tak je - ale i když přijde odpověď správně - tak ji neumí v podmínkách nijak zpracovat. Správně mi to v druhém případě kdy jsem nepracoval s sys[2251] ale s var rele1 provedlo blok kodu - ale když jsem se snažil pracovat s sys[2251] tak bylo jedno co je obsahem sys[2251] vždy byl výsledek chybný jak kdyby to pro něj nebylo číslo.

6

Re: [vyřešeno] přepínání relé pomocí sdc-c / mqtt

technomagg napsal:

... - ale když jsem se snažil pracovat s sys[2251] tak bylo jedno co je obsahem sys[2251] vždy byl výsledek chybný jak kdyby to pro něj nebylo číslo.

Ano, není to číslo:

sys[2250] 09 s R   poslední přijatý Value z Brokeru (broker publish)

Všimněte si toho "09 s R" což znamená:
- 09: dostupné od verze SDS-C č. 09
- s: proměnná je TEXT (STRING)
- R: pouze pro čtení

To znamená, že z MQTT brokeru nedostáváte číslo, ale TEXT (to je princip MQTT, vše přenáší jako text, resp. binární blob).
Tento text je potřeba nejprve převést na číslo.

Takže toto SPRÁVNĚ NEFUNGUJE, protože nelze přiřadit do číselné proměnné (integer) text (string):

 sys[231] = sys[2250];  // nelze

Řešení je takové: nejprve převést text na číslo, a pak s výsledkem převodu až dále pracovat. Samozřejmě přes MQTT může přijít i cokoliv jiného, ne jen čisté číslo (ale někdo tam může poslat i písmena, a MQTT to samozřejmé a správně předá dále, ale je na přijemci, aby si to pak ohlídal).

  sprintf(text[0], sys[2251]); // nejprve prekopirujeme string z sys[2251] do pole text, a to od pozice 0 v poli text[]
  atoi(text[0]); // prevede obsah text (od pozice 0] na cislo, vysledek prevodu da do sys[62]
  sys[232] = sys[62]; // vysledek zapiseme do ovladani rele

Popis funkce sprintf() a funkce atoi() je na wiki. Funkci sprintf() je potřeba použít, protože atoi() pracuje jen s poli text[] nebo share[].

Práce s texty v SDS-C není jednoduchá. Proto, pokud v tomto směru potřebujete často pracovat, doporučím přejít na FULL-C, tedy použít odpovídající HW (SDS-BIG).

Pochlubte se - popište jak využíváte své zařízení SDS zde ! Můžete si bezplatně přidat svou reklamu !

7

Re: [vyřešeno] přepínání relé pomocí sdc-c / mqtt

pokud by jste potřeboval nějakou kooperaci - případně třeba i dálkový přístup k běžícímu prostředí - můžeme se nějak domluvit - nemám problém Vám přes teamviewer pustit na chvíli k SDS desce včetně MQQT brokeru a nodeRed - můžete to ověřit na nainstalovaném prostředí se vším všudy.

8

Re: [vyřešeno] přepínání relé pomocí sdc-c / mqtt

SUPER - TAK VŠE POTVRZUJI JAKO FUNKCNI -
abych také něčím přispěl - rád Vám nabídnu k volnému použití můj vzorový program na vyčítání dat pomocí MQQT brokeru (klidně ho umístěte i na wiki do manuálu k mqqt - mám vyzkoušenou komunikaci pomocí brokeru mqqt v home assistant, zpracování hodnot v node red a jejich zpětné poskytnutí do homeassistant - nyní mi již funguje i odeslání příkazu k přepnutí relé. Možná by ten program šel ještě nějak učesat - ale upřímně - zase tolik se v programování nevyznám - pro mne je obrovský úspěch že jsem to rozhýbal s vydatnou pomocí od chatgpt a s pomocí od Vás kde jste mne navedli kde dělám sice drobnou, ale naprosto zásadní chybu.

main
{

// výpočet výkonu dle pulsů - vypnuto, místo toho odesílám dobu mezi pulsy a počítám v NodeRED

//var elektromer1_vykon;
//var elektromer2_vykon;
//var elektromer3_vykon;

  // elektromer1_vykon = 3600000 / sys[592];
  // ram[4] = elektromer1_vykon;

  // elektromer2_vykon = 3600000 / sys[593];
  // ram[5] = elektromer2_vykon;

  // elektromer3_vykon = 4500000 / sys[594];
  // ram[6] = elektromer3_vykon;






// network communication shall be started only after the SDS is connected to network (ethernet is up)
 echo('waiting for network availability');

waiting_ethernet:
wait(50);
 if (sys[24] == 0) goto waiting_ethernet; // 0 = no ethernet
 if (sys[27] == 0) goto waiting_ethernet; // 0 = no IP address

 // OK, now we have an ethernet connection up and running

 // EXAMPLE START:


 // connect on start
 echo('connecting to MQTT Broker... ???');

// Zadání IP adresy, jména a hesla MQQT serveru - je treba vyplnit jak máte vy - pokud odesílate data z více desek
// je třeba jedinečné client-id - pokud je stejné pro dva clienty komunikace se zasekne
 //           ip   ip   ip ip   port  client-id          username   password    keepalive(sec)
 mqtt_connect(192, 168, 1, 30, 1883, 'SDS-HL_Elektromer', 'mqtt', 'heslo_mqqt', 120);
 wait(150);
 // wait for a complete connection
 label waiting_for_mqqt_conn:
 wait(150);
 // error - failed ?
 if (sys[2200] <= 0) goto mqtt_conn_fail; // error ? (any negative number is error code)

 // done - connected ?
 if (sys[2200] != 4) goto waiting_for_mqqt_conn; // success ? (yes only if == 4)

 // test the CONNACK result - see "3.2.2.3 Connect Return code" - we expect "0" as OK

 if (sys[2201] != 0) goto mqtt_conn_fail; // is broker's result code OK ? (OK only if == 0)

 // connected (CONNACK result is 0x00)

 echo('connected to broker: OK');

                 mqtt_publish('sds2/elektromer1', sys[493]);
                w4:
                if (sys[2200] < 0) goto mqtt_conn_fail;    // disconnected ?
                if (sys[2202] == 1) goto w4;               // still working ?
                if (sys[2202] != 2)                        // success ?
                { echo('publish error elektromer1= ', sys[2202]); };

                 mqtt_publish('sds2/elektromer1_vykon', sys[592]);
                 w5:
                 if (sys[2200] < 0) goto mqtt_conn_fail;    // disconnected ?
                 if (sys[2202] == 1) goto w5;               // still working ?
                 if (sys[2202] != 2)                        // success ?
                 { echo('publish error elektromer1_vykon = ', sys[2202]); };

                 mqtt_publish('sds2/elektromer2', sys[494]);
                 w6:
                 if (sys[2200] < 0) goto mqtt_conn_fail;    // disconnected ?
                 if (sys[2202] == 1) goto w6;               // still working ?
                 if (sys[2202] != 2)                        // success ?
                 { echo('publish error elektromer2 = ', sys[2202]); };

                 mqtt_publish('sds2/elektromer2_vykon', sys[593]);
                 w7:
                 if (sys[2200] < 0) goto mqtt_conn_fail;    // disconnected ?
                 if (sys[2202] == 1) goto w7;               // still working ?
                 if (sys[2202] != 2)                        // success ?
                 { echo('publish error elektromer2_vykon = ', sys[2202]); };

                 mqtt_publish('sds2/elektromer3', sys[495]);
                 w8:
                 if (sys[2200] < 0) goto mqtt_conn_fail;    // disconnected ?
                 if (sys[2202] == 1) goto w8;               // still working ?
                 if (sys[2202] != 2)                        // success ?
                 { echo('publish error elektromer3 = ', sys[2202]); };

                 mqtt_publish('sds2/elektromer3_vykon', sys[594]);
                 w9:
                 if (sys[2200] < 0) goto mqtt_conn_fail;    // disconnected ?
                 if (sys[2202] == 1) goto w9;               // still working ?
                 if (sys[2202] != 2)                        // success ?
                 { echo('publish error elektromer3_vykon = ', sys[2202]); };

                 mqtt_subscribe(1, 'sds2/rele1');
                 wS:
                 if (sys[2200] < 0) goto mqtt_conn_fail; // disconnected (if any negative number)
                 if (sys[2202] == 4) goto wS;            // still working... (done when != 4)
                 if (sys[2202] != 8)                     // success ? (only if == 8, otherwise error or failure)
                       {
                       // FAILED -> not subscribed !
                       echo('sub error = ', sys[2202]);
                       return;
                       };


                 var last1;
                          last1 = 1;
                          loop:
                          if (last1 != sys[2291])  // sys[2291] je casove razitko for index #1
                          {
                          last1 = sys[2291];
                          }
                          echo('MQQT cesta Topic #1: "', sys[2211], '" hodnota sys[2251] aktualizovana na: "', sys[2251], '" ');

                                           wait(50);
                                           sprintf(text[0], sys[2251]); // nejprve prekopirujeme string z sys[2251] do pole text, a to od pozice 0 v poli text[]
                                           atoi(text[0]); // prevede obsah text (od pozice 0] na cislo, vysledek prevodu da do sys[62]
                                           sys[231] = sys[62]; // vysledek zapiseme do ovladani rele
                                           echo('promenna sys[2251] ' sys[2251]);
                                           echo('promenna sys[62] ' sys[62]);
                                           echo('promenna sys[231] ' sys[231]);
                                          

                          // Unsubscribe from topic
                          mqtt_unsubscribe_index(1);
                          wU:
                          if (sys[2200] < 0) goto error; // disconnected
                          if (sys[2202] < 0) goto error; // error (if any negative number)
                          if (sys[2202] != 16) goto wU;  // waiting until done (done when result == 32)

                       echo('unsubscribed');






                 // go
            mqtt_disconnect();

            // we shall wait until the connection is properly closed
        wait_for_disconnect:
        if (sys[2200] <= 0) goto error;                // error ?
        if (sys[2200] == 8) goto wait_for_disconnect;  // success, or still working ?

        // done !
 echo('DISCONNECTED from broker');

 wait(250);

 // EXIT the example - we are DONE
 return;


 // error handling
 label mqtt_conn_fail:
 echo('unable to connect... error=', sys[2200],' connack=', sys[2201]);

 // error handling
 label error:
 echo('error');
}