1

Téma: UDP Broadcast/Multicast

Zdravím,
mám krátce doma 2 SDS, z nichž jedno bude měřit energie (elměr, plynoměr, vodoměr) a teplotu venku, druhé na půdě hlavně teploty, vlhkost, tlak, vítr...
Napsal jsem si jednoduchý prográmek, který se přes UDP dotazuje pravidelně každou vteřinu na hodnoty a bylo by fajn využít UDP broadcast nebo multicast (nemusel bych posílat individuální pakety a nebyl by problém při nepřipojeném SDS s chybějící "Route-To-Host"), ale SDS nějak na broadcast a multicast (s adresou 224.0.0.1) nereagují, nevíte někdo, co s tím?

Zkoušel jsem opačně posílat broadcast pakety z obou SDS, což by pro mne bylo výhodnější, fungovalo to, ale při zátěži (např. současný HTTP přístup a chod programu v SDS) se někdy komunikace SDS zasekne (a chci ta data každou vteřinu).

2

Re: UDP Broadcast/Multicast

SDS reaguje jen na ARP broadcast, jinak vše ostatní co není s odpovídající IP adresou se zahodí.

Jak by mělo reagovat ? Osobně mě moc nenapadá jak, právě to že nereaguje by mělo být správné ... nicméně se o tom samozřejmě tady můžeme pobavit a v některé z následujících beta verzí se to může přidat (už teď je nových požadavků dost... ale co).

Odeslání UDP z SDS-C programu by mělo fungovat, ale je potřeba hlídat sys[95].

Každopádně doporučím aktualizovat firmware, protože se tam propustnost řešila (v rámci vydání za poslední dva měsíce). Dneska byla vydána oficiální verze pro MICRO, takže bych to zkusil s tímto.

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

3

Re: UDP Broadcast/Multicast

Nepřesně jsem se vyjádřil. Ten UDP broadcast je samozřejmě ve stejném tvaru jako normální UDP paket, tzn. QUERY, WRITE, RDSYS, RDRAM, WRSYS nebo WRRAM, jen cílová adresa je broadcast a ne unicast. Takže by se mi líbilo, kdyby všechny SDS, které paket obdrží odpověděly na zdrojovou adresu (takže odpověď se neliší od odpovědi na normální unicast dotaz), já bych si potom SDS rozlišoval podle sysLocation (což dělám i teď)...

To odesílání UDP ze SDS funguje, jenže se mi po nějaké době stalo (podle mne to souvisí s tím, když se zároveň přes prohlížeč připojuji na HTTP server v SDS), že se SDS nějak zaseklo a odesílalo stále dokola stejné UDP pakety. Je ale pravda, že to bylo z betaFW, možná to už funguje dobře...

4

Re: UDP Broadcast/Multicast

Takže to UDP (dotaz) by poslal PC, vyplnit SVOU adresu IP jako odesílatel, ale cíl by byl IP broadcast.
Všechny SDS by to chytili, a poslali odpověď na tu konkrétní IP kterou PC uvede jako odesílatel.
Jo to bude ono, protože jsem předpokládal že IP odesílatele bude taky nějaká univerzální hodnota - pokud by tam však byla platná adresa stroje, tak by to šlo udělat. V některé z dalších beta verzí...

SDS po odeslání UDP paketu (z SDS-C programu) ty data, co byly odeslány ven, "nemá" (je to ve sdíleném paměťovém prostoru, který se nuluje), takže se nemůže na této úrovni opakovat (tj. opakovat stejný paket), tam se muselo stát něco jiného - a to by mne zajímalo co se stalo. Hmm byl bych rád za test s nejnovějším firmware, který je dostupný pro SDS MICRO. Pak uvidíme co dál.

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

5 Naposledy upravil: jirsoft (2012-12-29 01:44:57)

Re: UDP Broadcast/Multicast

Takže to vypadá, že s novým FW už ten UDP broadcast nepadá. Co ale komplikuje práci, je složitost vytváření UDP paketu. Když využívám funkci sprintf(), musím ručně dohledat, kam až sahají data pomocí extra funkce txt_konec()(např. takhle):

var zbyva, delka, casUDP, casHTTP, IP1, IP2, IP3, IP4;

spinaci_hodiny {
    var cas,on,off,dd,den;
    if (sys[10]!=0)                    //spínáme jen v první vteřinu minuty
        goto nespiname;
        
    cas = sys[8] * 100 + sys[9];    //připravíme čas HHMM
    den = ((sys[4] / 86400) + 3) % 7;    //den v týdnu, 0=pondělí
    
    //RE1
    on = sys[140] / 10000;            //rozebereme sys[140] HHMMHHMM (on/off)
    off = sys[140] % 10000;
    dd = on / 10000;                //program pro den v týdnu ... 0-6=konkrétní den, 7=pracovní, 8=víkend, 9=každý den
    on = on % 10000;
    if (dd<7 && dd!=den)
        goto test2;
    if (dd==7 && den>4)
        goto test2;
    if (dd==8 && den<5)
        goto test2;
    //porovnáváme časy, pokud on=off (nebo 0), nic neděláme
    if (cas==on && sys[231]==0 && on!=off) { 
        sys[231]=1;
        echo('PRG1: RE1 zapnuto v ',sys[8],':',sys[9]);
    }
    if (cas==off && sys[231]!=0 && on!=off) { 
        sys[231]=0;
        echo('PRG1: RE1 vypnuto v ',sys[8],':',sys[9]);
    }

test2:
    on = sys[141] / 10000;            //rozebereme sys[141] HHMMHHMM (on/off)
    off = sys[141] % 10000;
    dd = on / 10000;                //program pro den v týdnu ... 0-6=konkrétní den, 7=pracovní, 8=víkend, 9=každý den
    on = on % 10000;
    if (dd<7 && dd!=den)
        goto test3;
    if (dd==7 && den>4)
        goto test3;
    if (dd==8 && den<5)
        goto test3;
    
    //porovnáváme časy, pokud on=off (nebo 0), nic neděláme
    if (cas==on && sys[231]==0 && on!=off) { 
        sys[231]=1;
        echo('PRG2: RE1 zapnuto v ',sys[8],':',sys[9]);
    }
    if (cas==off && sys[231]!=0 && on!=off) { 
        sys[231]=0;
        echo('PRG2: RE1 vypnuto v ',sys[8],':',sys[9]);
    }

test3:
    on = sys[142] / 10000;            //rozebereme sys[142] HHMMHHMM (on/off)
    off = sys[142] % 10000;
    dd = on / 10000;                //program pro den v týdnu ... 0-6=konkrétní den, 7=pracovní, 8=víkend, 9=každý den
    on = on % 10000;
    if (dd<7 && dd!=den)
        goto test4;
    if (dd==7 && den>4)
        goto test4;
    if (dd==8 && den<5)
        goto test4;

    //porovnáváme časy, pokud on=off (nebo 0), nic neděláme
    if (cas==on && sys[231]==0 && on!=off) { 
        sys[231]=1;
        echo('PRG3: RE1 zapnuto v ',sys[8],':',sys[9]);
    }
    if (cas==off && sys[231]!=0 && on!=off) { 
        sys[231]=0;
        echo('PRG3: RE1 vypnuto v ',sys[8],':',sys[9]);
    }

test4:
    on = sys[143] / 10000;            //rozebereme sys[143] HHMMHHMM (on/off)
    off = sys[143] % 10000;
    dd = on / 10000;                //program pro den v týdnu ... 0-6=konkrétní den, 7=pracovní, 8=víkend, 9=každý den
    on = on % 10000;
    if (dd<7 && dd!=den)
        goto test5;
    if (dd==7 && den>4)
        goto test5;
    if (dd==8 && den<5)
        goto test5;
    
    //porovnáváme časy, pokud on=off (nebo 0), nic neděláme
    if (cas==on && sys[231]==0 && on!=off) { 
        sys[231]=1;
        echo('PRG4: RE1 zapnuto v ',sys[8],':',sys[9]);
    }
    if (cas==off && sys[231]!=0 && on!=off) { 
        sys[231]=0;
        echo('PRG4: RE1 vypnuto v ',sys[8],':',sys[9]);
    }

test5:
    //RE2
    on = sys[144] / 10000;            //rozebereme sys[144] HHMMHHMM (on/off)
    off = sys[144] % 10000;
    dd = on / 10000;                //program pro den v týdnu ... 0-6=konkrétní den, 7=pracovní, 8=víkend, 9=každý den
    on = on % 10000;
    if (dd<7 && dd!=den)
        goto test6;
    if (dd==7 && den>4)
        goto test6;
    if (dd==8 && den<5)
        goto test6;

    //porovnáváme časy, pokud on=off (nebo 0), nic neděláme
    if (cas==on && sys[232]==0 && on!=off) { 
        sys[232]=1;
        echo('PRG5: RE2 zapnuto v ',sys[8],':',sys[9]);
    }
    if (cas==off && sys[232]!=0 && on!=off) { 
        sys[232]=0;
        echo('PRG5: RE2 vypnuto v ',sys[8],':',sys[9]);
    }

test6:
    on = sys[145] / 10000;            //rozebereme sys[145] HHMMHHMM (on/off)
    off = sys[145] % 10000;
    dd = on / 10000;                //program pro den v týdnu ... 0-6=konkrétní den, 7=pracovní, 8=víkend, 9=každý den
    on = on % 10000;
    if (dd<7 && dd!=den)
        goto test7;
    if (dd==7 && den>4)
        goto test7;
    if (dd==8 && den<5)
        goto test7;
    
    //porovnáváme časy, pokud on=off (nebo 0), nic neděláme
    if (cas==on && sys[232]==0 && on!=off) { 
        sys[232]=1;
        echo('PRG6: RE2 zapnuto v ',sys[8],':',sys[9]);
    }
    if (cas==off && sys[232]!=0 && on!=off) { 
        sys[232]=0;
        echo('PRG6: RE2 vypnuto v ',sys[8],':',sys[9]);
    }

test7:
    on = sys[146] / 10000;            //rozebereme sys[146] HHMMHHMM (on/off)
    off = sys[146] % 10000;
    dd = on / 10000;                //program pro den v týdnu ... 0-6=konkrétní den, 7=pracovní, 8=víkend, 9=každý den
    on = on % 10000;
    if (dd<7 && dd!=den)
        goto test8;
    if (dd==7 && den>4)
        goto test8;
    if (dd==8 && den<5)
        goto test8;

    //porovnáváme časy, pokud on=off (nebo 0), nic neděláme
    if (cas==on && sys[232]==0 && on!=off) { 
        sys[232]=1;
        echo('PRG7: RE2 zapnuto v ',sys[8],':',sys[9]);
    }
    if (cas==off && sys[232]!=0 && on!=off) { 
        sys[232]=0;
        echo('PRG7: RE2 vypnuto v ',sys[8],':',sys[9]);
    }

test8:
    on = sys[147] / 10000;            //rozebereme sys[147] HHMMHHMM (on/off)
    off = sys[147] % 10000;
    dd = on / 10000;                //program pro den v týdnu ... 0-6=konkrétní den, 7=pracovní, 8=víkend, 9=každý den
    on = on % 10000;
    if (dd<7 && dd!=den)
        goto nespiname;
    if (dd==7 && den>4)
        goto nespiname;
    if (dd==8 && den<5)
        goto nespiname;
    
    //porovnáváme časy, pokud on=off (nebo 0), nic neděláme
    if (cas==on && sys[232]==0 && on!=off) { 
        sys[232]=1;
        echo('PRG8: RE2 zapnuto v ',sys[8],':',sys[9]);
    }
    if (cas==off && sys[232]!=0 && on!=off) { 
        sys[232]=0;
        echo('PRG8: RE2 vypnuto v ',sys[8],':',sys[9]);
    }

nespiname:
}
dns {
    dns_resolv('verca.jirsoft.eu');         //adresa HTTP serveru, kam posíláme data

    //počkáme na převod
label cekam_na_dns:
    if (sys[65] == 0) goto cekam_na_dns;

    //máme výsledek
    if (sys[65] != 512) goto preskocit;

    //převod OK...
    IP1 = sys[66];                            //tady bude IP adresa
    IP2 = sys[67];
    IP3 = sys[68];
    IP4 = sys[69];

label preskocit:
}

udp {
opakovat_odesilani:
    send_udp(255,255,255,255, 13131, 0, delka);

    // pockáme až se to dokoncí (odešle se paket)
cekej_na_provedeni:

    // ješte pracuje ?
    if (sys[95] == 1)
        goto cekej_na_provedeni;

    // ted: co se skutecne provedlo ?

    if (sys[95] == 2) {
        // byl odeslán UDP paket, takže jsme hotovi
        //echo('UDP send OK');
        return;
    }

    if (sys[95] == 3) {
        // místo UDP paketu byl odeslán ARP dotaz
        // takže chvíli pockáme, at nezahltíme sít opakování ARP dotazu
        // (obvykle to chvíli trvá, než prijde ARP odpoved,
        // takže pockáme napr. 250msec - toto si upravte dle potreby)
        //echo('UDP-ARP sent');
        wait(250);

        // tím, že se místo našeho požadovaného UDP paketu
        // odeslal ARP paket, byl náš puvodní UDP paket zahozen:
        // takže ho musíme nechat poslat znovu (dokola dokud se to nepovede)
        // pozn. tady by bylo dobré dát pocítadlo a pokud se to nepovede
        // vícekrát, tak ohlásit selhání a skoncit, jinak se program odsud nikdy nedostane
        goto opakovat_odesilani;
    }

    if (sys[95] == 4) {
        // funkce send_udp() byla zavolána dríve než bylo dokonceno
        // provádení predchozího požadovaného požadavku

        // obsluhu této situaci si musíte vyrešit dle svého úkolu

        // typické rešení by bylo pockat (chvíli, 250 msec napríklad)
        // a pak provést: goto opakovat_odesilani;

        // my v tomto príkladu opustíme tuto funkci (tj. naše selhání)
        echo('UDP: prilis rychle odesilani');
        return;
    }

    if (sys[95] == 5) {
        // funkce zavolána s neplatným parametrem (nebo více parametry)

        // tento príklad nic takového nereší,
        // takže jdeme z této funkce pryc.
        echo('UDP: neplatny parametr');
        return;
    }

    // pokud se dostaneme sem, tak je v sys[95] neznámá hodnota
    echo('UDP: neznámá hodnota v sys[95]',sys[95]);
}

txt_konec {
jeste:
    if (text[delka]!=0) {
        delka += 1;
        goto jeste;
    }
    text[delka]=44;
    delka += 1;
}

napln_udp_data {
    var pom,b2,b3,b4,zn;
    
    text[0] = 1;                //na začátek dáme číslo SDS (zde 1)
    
    text[1] = sys[5];            //pak časovou značku
    text[2] = sys[6];
    text[3] = sys[7] % 100;
    text[4] = sys[8];
    text[5] = sys[9];
    text[6] = sys[10];
    delka = 7;
    text[delka] = 44;
    delka += 1;

    //přepočet, počítadlo, mezi pulsy a od posledního pulsu pro vstup 1 (elměr)
    sprintf(text[delka],sys[559],',',sys[592],',',sys[625],',',sys[493]);
    txt_konec();
    //přepočet, počítadlo, mezi pulsy a od posledního pulsu pro vstup 2 (plynoměr)
    sprintf(text[delka],sys[560],',',sys[593],',',sys[626],',',sys[494]);
    txt_konec();
    //přepočet, počítadlo, mezi pulsy a od posledního pulsu pro vstup 3 (vodoměr)
    sprintf(text[delka],sys[561],',',sys[594],',',sys[627],',',sys[495]);
    txt_konec();
    
    //venkovní vlhkost, tlak
    sprintf(text[delka],sys[431],',',sys[432]);
    txt_konec();
    
    //teplota slpupek, rozvaděč
    sprintf(text[delka],sys[310],',',sys[311]);
    txt_konec();    

    //spínací hodiny
    sprintf(text[delka],sys[140],',',sys[141],',',sys[142],',',sys[143],',',sys[144],',',sys[145],',',sys[146],',',sys[147]);
    txt_konec();    
    
    if (sys[231]!=0) {            //RE1
        text[delka] = 49;
    }
    else {
        text[delka] = 48;
    }
    delka += 1;
    text[delka] = 44;
    delka += 1;
    
    if (sys[232]!=0) {            //RE2
        text[delka] = 49;
    }
    else {
        text[delka] = 48;
    }
    
    delka += 1;
    text[delka] = 0;

}

napln_http_data {
}

http {
}

init
{
    echoclear(0);            //smazání konzole
    echo('SDS-program spusten...');

    IP1 = 0;                //smažeme IP adresu pro případ neúspěchu DNS
    IP2 = 0;
    IP3 = 0;
    IP4 = 0;
    dns();                    //DNS převod pro HTTP server
    
    sys[231] = 0;            //vypnout RE1
    sys[232] = 0;            //vypnout RE2
    
    sys[63] = 128;            //vypnuto rychlostni omezení
    
    casUDP = -1;
    casHTTP = -1;
}

main
{
    spinaci_hodiny();                    //nemáme zapnout/vypnout relé?

    if (casUDP!=sys[4]) {
        casUDP = sys[4];                //tahle vteřina už byla
        napln_udp_data();                //připrav data pro UDP,
        udp();                            //odešli UDP broadcast
    }
     
    zbyva = sys[4] % 30;                //kolik sec zbývá do HTTP?
    if (zbyva==0 && casHTTP!=sys[4]) {
        casHTTP = sys[4];                //tahle vteřina už byla
        napln_http_data();                //připrav data pro HTTP,
        http();                            //odešli HTTP paket
    }
}

(V programu je již připraveno místo na posílání HTTP GET na můj server, jednotlivé údaje odděluji čárkami). Hodilo by se, aby buď sprintf() vracelo jako návratovou hodnotu pozici té NUL na konci, případně mít ještě další "výstupní" funkci, která by uměla zapsat na pozici v text těch 32 bitů s hodnotou.

6 Naposledy upravil: nesvara (2012-12-30 19:20:56)

Re: UDP Broadcast/Multicast

Jaká čidla budete používat na měření tlaku a rychlosti větru?
Děkuji

7

Re: UDP Broadcast/Multicast

Vítr vyřeším tímhle. Předpokládám, že rychlost budou pulsy, takže chci přidat převodník F/U a připojit na AD vstup, směr nejspíš bude nějak absolutně kódován, ale skoro bych tipnul na nějaký odpor úměrný pozici (16 pozic), takže po připojení jako dělič lze opět připojit na AD převodník.

Snímač tlaku ještě hledám, zatím jsem našel spoustu modulů s výstupy I2C (z HK kolem $10), jakmile to má přímo P/U, stojí kolem 1000 Kč, což je (pro mne) zbytečně drahé

8

Re: UDP Broadcast/Multicast

Díky za odpověď. Chci dodělat měření rychlosti větru na moji stránku www.nesvara.cz . Mám ještě volný napěťový vstup. Pokusím se najít Vámi zmíněný převodník F/U popř. pokud najdu nějaký další senzor větru, který bude generovat napětí ozvu se. Zatím jsem nic nenašel.

9

Re: UDP Broadcast/Multicast

Tak jsem koukal na ty převodníky f/U, šel by použít třeba LM2907 za nějakých 30 Kč. Při vhodném nastavení konstant (externí R a C) bude podle mne přesnost docela dobrá a není třeba hlídat pulsy...

10

Re: UDP Broadcast/Multicast

To doplnění sprintf() se udělá, to je velmi dobrá poznámka.

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