FULL-C: sharing

Tato stránka popisuje programovací jazyk FULL-C, který je dostupný na vybraných zařízeních SDS. 
Některá zařízení používají SDS-C, pro který máme návody jinde na této WiKi.

Sdílené proměnné

Často nestačí mít "jenom" program spuštěný v zařízení SDS, ale je také potřeba ho na dálku řídit (nebo jenom čas od času mu "změnit nastavení" bez nutnosti nahrávat upravený program znovu). Současně je potřeba program i sledovat.

Nejčastěji se používá webová stránka, která je nahraná spolu s FULL-C programem v zařízení SDS, a která periodicky získává hodnoty sdílených proměnných z programu, a vhodně je zobrazuje. Současně je možné (na té samé stránce) poskytnout uživateli možnost hodnoty i měnit.

Podporované typy sdílených proměnných:

typ položky               rozsah           celková velikost typu     
-----------------------+----------------+-------------------------
  signed   long        |  -2^31..+2^31  |  4 BYTES                
  unsigned long        |      0..+2^32  |  4 BYTES                
  IP address           |  uchar[4]      |  4 BYTES                
  float                |  IEEE-754      |  4 BYTES                
  string (text)        |   char[n]      |  1..n BYTES             
  binary array         |  uchar[n]      |  1..n BYTES             


Informace:

POZOR - proměnné o velikosti 64-bit nelze v této verzi firmware sdílet (ale jinak je lze běžně v programu používat). Podporovány jsou POUZE proměnné maximálně 32-bit široké (viz tabulka výše).

Vy, jako tvůrce celého programu, a systému, si sami vyberete, jaké údaje potřebujete mezi (např.) webovou stránkou a SDS, přenášet. Podle toho si deklarujete proměnné v programu, např. pro přenos jednoho čísla si zavedete proměnnou S00, a tak dále. Poté, pomocí webového API volání, můžete obsah této proměnné číst (v reálném čase), nebo do ní kdykoliv zapisovat (a zápis se, tím pádem, okamžitě projeví v programu, protože obsah proměnné se ihned přepíše na novou hodnotu, kterou jste tam z venku poslali).


Identifikace sdílených proměnných ve FULL-C programu

Ve vašem programu musíte deklarovat specifické proměnné, které budou přístupné "z venku". Toto "omezení" na seznam určitých proměnných (viz dále), je zde z bezpečnostních důvodů, protože tak má autor programu plnou kontrolu nad tím, které proměnné bude možnost měnit a které ne. Z venku tedy lze přistupovat jen na proměnné se schváleným název (ze seznamu), a už nikoliv na jakékoliv jiné proměnné vašeho programu.

Názvy sdílených proměnných jsou právě tím klíčem, který určuje, zda-li je proměnné "sdílená" (přístupná), nebo ne.

SDÍLENÁ PROMĚNNÁ: název je složen vždy z jednoho znaku a dvou čísel.

Příklad:

signed long   S00;
signed int    S00;
unsigned long U00;
unsigned int  U00;
float         F00;
char          T00[32];

Samozřejmě číselná hodnota je od "00" do "99" (decimální hodnota).

unsigned long U23;
char          T11[8];


Vnější přístup - změna hodnot (ZÁPIS)

Pro zápis do deklarovaných sdílených proměnných, se přistupuje přes webové rozhraní zařízení SDS:

192.168.1.250/sv?S00=-123&U02=1000&T00=hello

Uvedený příklad způsobí toto: že současně budou nastaveny: proměnná S00 na -123, proměnná U02 na 1000 a proměnné T00 na "hello" (zbytek pole nastaven na 0x00).

Jak lze vidět, lze současně měnit jednu nebo více proměnných.

Skladba volání:

192.168.1.250 / sv            ? U01       = 1        & S02       = 2 

IP_nebo_DNS   / název_příkazu ? proměnná1 = hodnota1 & proměnná2 = hodnota2 . . .

Jednotlivé páry (proměnná+hodnota) jsou od sebe odděleny znakem '&', přičemž tento znak se nedává za poslední pár (pouze mezi páry).


Vnější přístup - zabezpečení zápisu

Zápis lze omezit - pokud provedete nastavení, pouze přihlášení uživatelé budou moct zapisovat do sdílených proměnných.

Záleží na nastavení hodnoty indexu 150: použijte sds_set_u32(150, hodnota); kde hodnota je nula pro neomezený přístup (zápis a čtení i bez přihlášení), nebo jakékoliv nenulové číslo (potom je zápis omezen pouze pro přihlášené uživatele).


Příklad programu - jak využívat sdílené proměnné

FULL-C program není automaticky informován o tom, že došlo ke změně sdílené proměnné.

Musí si tedy změny a) buď detekovat sám, nebo b) využít jednu z proměnných jako indikátoru změny.

// this is an example, on how to use a shared-variables in SDS
// use this web call to modify the U00 contents >>> 192.168.1.250/sv?U00=1234

 unsigned long U00;

 void main(void)
 {
   unsigned long old_U00;

   // start - set initial default values
   U00 = 0;
   old_U00 = U00;

   // main loop  - show any changes coming from "outside"
   for (;;)
   {
     // waiting for an "outside" change (external write to U00)
     while (U00 == old_U00)
     {
       ;  // no change detected yet, so wait...
     }
     // change has been detected, so store the new value for future comparison
     old_U00 = U00;
     // and output the new value to "echo.html", so we can verify it works
     printf("new value of U00 is %u \n", U00);
   }
 }

Tento vzorový program je dostatečně zřejmý, a ukazuje variantu kdy se čeká na změnu proměnné.


Samozřejmě lze to i jinak, pokud si jednu ze sdílených proměnných vyhradíme jako indikátor změny, a nastavíme ji vždy současné se změnou jiné proměnné.

// toto je ukazka sdilenych promennych (U00 - indikator zmeny) (S23 - aktualni promenna)
// >>> 192.168.1.250/sv?U00=1&S23=-1234

 unsigned long U00;
 signed long S23;

 void main(void)
 {

   // start - nastav vychozi hodnoty
   U00 = 0;
   S23 = 0;

   // nekonecna smycka - zobrazit zmeny prichazejici "z venku"
   for (;;)
   {
     // cekam na zmenu "z venku"
     while (U00 != 1)
     {
       ;  // nedoslo ke zmene, cekam
     }
     // vynuluju flag at muzu znovu reagovat pri pristi zmene
     U00 = 0;

     // a napisu novou do echo.html
     printf("nova hodnota S23 je %d \n", S23);
   }
 }

Jak je vidět, vyhrazena byla proměnná U00, která když se nastaví "z venku" do 1, tak je to (v tomto příkladu) indikace že S23 má novou hodnotu.

Pozor - oba příklady způsobí zablokování vykonávání programu na "while" smyčce. Jedná se samozřejmě o příklady, přičemž ve skutečném programu to bude potřeba udělat jinak; tak aby k zablokování činnosti zbytku programu nedošlo. Jde to samozřejmě snadno, viz další příklad.


// toto je ukazka sdilenych promennych
// >>> 192.168.1.250/sv?U00=1234

 unsigned long U00;

 void main(void)
 {
   unsigned long old_U00;

   // start - nastav vychozi hodnoty
   U00 = 0;
   old_U00 = U00;

   // nekonecna smycka - program
   for (;;)
   {

     //... delam neco jiheho ...

     // otestujina zmenu "z venku"
     if (U00 != old_U00)
     {
       // doslo ke zmene, ulozim si hodnotu
       old_U00 = U00;
       // a napisu novou do echo.html
       printf("nova hodnota U00 je %u \n", U00);
     }

     //... delej neco dalsiho ...

   }
 }


Vnější přístup - čtení jednotlivých proměnných

Skladba volání:

192.168.1.250 / getsv         ? s00          = U00       & s01          = F12       . . .

IP_nebo_DNS   / název_příkazu ? poziceDotazu = proměnná1 & poziceDotazu = proměnná2 . . .  (omezení: rozsah poziceDotazu je s00 až s15)

Zde pozor - způsob sestavení dotazu může být matoucí (dotazy zapsány jako parametry do sXX prvků), ale nenechte se zmást !

Do SDS je potřeba zaslat seznam proměnných, a to se dá prostřednictvím URL dotazu provést právě takto - že se jednotlivé proměnné zapíší postupně jako dotazy, přičemž je možné poslat jeden až 16 dotazů v rámci jednoho příkazu "getsv".

Příklad:

192.168.1.250/getsv?s00=U12&s01=S00&s02=F32

Odpověď bude následující (stejný formát jako share.txt popsaný dole) - vlastní hodnoty jsou smyšlené:

  et|1521594414|ut|123|U12|12345|S00|texttext|F32|1234|

Příklad:

192.168.1.250/getsv?s00=S12

Odpověď bude následující (stejný formát jako share.txt popsaný dole) - vlastní hodnoty jsou smyšlené:

  et|1521594654|ut|321|S12|textxyz|

Poznámka:

1) Pokud nejsou deklarovány jakékoliv sdílené proměnné, je odpověď následující (číselné hodnoty jsou smyšlené, podstatné pro tento příklad nejsou):

 et|1421594413|ut|123|NOSV|0|

2) Pokud pošlete getsv dotaz na takové názvy proměnných, které ale nejsou ve FULL-C programu deklarovány, pak obdržíte toto:

 et|1421594413|ut|456|NOTHING|0|

3) Pokud by odpověď měla překročit velikost TCP Payload-MSS, bude oříznuta - protože v současném FW se odpověď musí vlézt do jednoho jediného paketu. Tímto omezením netrpí ostatní metody získávání sdílených proměnných, ale jen a pouze getsv - ovšem toto by neměl být problém.


Vnější přístup - hromadné čtení sdílených proměnných

Sdílené proměnné lze i číst, stačí poslat správný dotaz do zařízení SDS, a odpovědí je buď XML soubor nebo textová delimitovaná odpověď - obojí s očekávaným obsahem.

Základem je použití shared.txt souboru = tento soubor obsahuje výpis VŠECH sdílených proměnných, které jsou v programu zavedeny.

Výpis ve shared.txt není omezen, a vypíší se všechny existující sdílené proměnné (nedojde k uříznutí či vynechání).

Ovšem pozor na jediné existující omezení - pokud by však některá Txx[] proměnná měla délkou svého obsahu přesáhnout délku TCP Payload-MSS, bude tento Txx[] vynechán a místo tohoto bude na jeho místě v odpovědi poskytnut text "XXX|0|". Prakticky řečeno, toto se nestane dokud v Txx[] bude text kratší než zhruba 1400 znaků (skutečná velikost záleží právě na hodnotě MSS, což je věc dynamická, kterou nelze jen tak určit - závisí na síti ve které je SDS provozováno).

Příklad obsahu TXT souboru pro program, který definuje proměnné T00 a U24:

 et|1421594413|ut|528|T00|text|U24|1895647|

Stavba textu v odpovědi je následující - zde je pro názornost položku za položkou vysvětlen příklad uvedený o řádek výše:

 položka (zleva doprava)   obsah
-------------------------+---------------------------------------
 et                      | (speciální) název následující položky (bude to EpochTime hodnota)
 znak '|' (svislítko)    | oddělovač položek (pozor ať jej nepoužijete vy v hodnotách Txx)
 1421594413              | LOCAL-TIME v okamžiku generování odpovědi (lze použít pro vyloučení starých hodnot v cache prohlížeče)
 znak '|' (svislítko)    | oddělovač položek
 ut                      | (speciální) název následující položky (bude to UpTime hodnota)
 znak '|' (svislítko)    | oddělovač položek (pozor ať jej nepoužijete vy v hodnotách Txx)
 528                     | UpTime v okamžiku generování odpovědi (lze použít pro vyloučení starých hodnot v cache prohlížeče)
 znak '|' (svislítko)    | oddělovač položek
 T00                     | název proměnné, která bude mít následně vypsán svůj obsah
 znak '|' (svislítko)    | oddělovač položek
 text                    | aktuální obsah T00
 znak '|' (svislítko)    | oddělovač položek
 U24                     | název proměnné, která bude mít následně vypsán svůj obsah
 znak '|' (svislítko)    | oddělovač položek
 1895647                 | aktuální obsah U24
 znak '|' (svislítko)    | oddělovač položek (je umístěn i na konci)

Pozor na používání znaku svislítka v proměnných Txx, takový znak v obsahu Txx samozřejmě znemožní zpracování této odpovědi.

Hodnota LOCAL-TIME určuje lokální čas (tj. NTP UTC ale se všemi úpravami, jako je aplikace DST offsetu atd.).

Hodnota UpTime určuje čas od zapnutí zařízení (kdy to bylo nastaveno na nulu) v milisekundách.

Využívejte těchto hodnot pro kontrolu správnosti odpovědi (např. UpTime musí neustále růst, pokud to tak nebude, tak je někde chyba - restart SDS, přeházené pořadí odpovědí, starší odpověď, atd.).


Pokud obdržíte následující specifickou odpověď (NOSV):

 et|1421594413|ut|528|NOSV|0|

pak to znamená, že a) buď není v zařízení nahraný FULL-C program nebo b) nahraný program nepoužívá sdílené proměnné.


Druhou možností je použití shared.xml souboru = tento soubor obsahuje výpis VŠECH sdílených proměnných, které jsou v programu zavedeny.

Příklad obsahu XML souboru pro program, který definuje právě proměnné T00 a U24:


 <?xml version="1.0" encoding="UTF-8"?>
 <FULL-C>

  <et>1421594413</et>
  <ut>528</ut>

  <sv>
  <T00>text</T00>
  <U24>1895647</U24>
  </sv>

 </FULL-C> 

Výpis v XML není omezen na celkovou délku, či počet všech sdílených proměnných; nicméně pro Txx[] platí stejné omezení na jednotlivou délku tak jak to bylo popsáno výše (u shared.txt).


Zobrazovaní sdílených proměnných na živé webové stránce

Standardní způsob je použít JavaScript a pomocí AJAX volaní, periodicky číst hodnoty sdílených proměnných z SDS, a zobrazovat je (nebo jinak zpracovávat) na vaší vlastní webové stránce. Nebo si je také můžete číst a jen např. ukládat do své databáze, a tak dále. Není zde jakékoliv omezení.


Vnější přístup - protokol S-UDP

Ke všem sdíleným proměnným lze zabezpečeným a rychlým způsobem přistupovat i prostřednictvím S-UDP protokolu. Rychlost je dána použitím UDP protokolu pro přenos dat, zabezpečení je provedeno symetrickou šifrou.

Více informací viz SUDP Protokol.


Vnější přístup - protokol SNMP

Ke všem sdíleným proměnným lze přistupovat i prostřednictvím SNMP protokolu. Viz seznam OID respektive MIB tabulka pro dané zařízení.