FULL-C: http client functions

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.

Síťové funkce: komunikace s webovým serverem

Zařízení SDS umožňuje odeslat HTTP-GET a HTTP-POST dotaz na zvolený HTTP server. FULL-C program určuje cílový server (IP adresu a Host název), a současně určuje obsah (Body) v dotazu.

Za tímto účelem jsou k dispozici tyto dvě funkce:

         void http_get(unsigned int IP0, unsigned int IP1, unsigned int IP2, unsigned int IP3, unsigned int Port, char *HostName, char *GETtext, void *ReceiveDataBuffer, unsigned int MaximalReceiveDataLength);
 unsigned int http_get_status(unsigned int *httpResponseValue, unsigned int *receivedDataSize);

Dále je možné poslat HTTP-POST požadavek, prakticky stejným způsobem:

         void http_post(unsigned int IP0, unsigned int IP1, unsigned int IP2, unsigned int IP3, unsigned int Port,                         
                        char *HostName, char *GETtext, void *ReceiveDataBuffer, unsigned int MaximalReceiveDataLength, char *POSTtext);

Před odesláním HTTP-GET nebo HTTP-POST, lze provést uživatelskou konfiguraci HTTP hlavičky.

         int http_header_set_content_type(char * value);
         int http_header_set_user_row(unsigned int reserved, char * text);

Probíhající get/post požadavek lze z FULL-C programu (předčasně) ukončit:

         void http_close(void);


Princip

SDS po zavolání funkce http_get() se SDS spojí s webovým serverem na zadané IP adrese a předá tomuto serveru GET požadavek. Odpověď je pak v SDS zpracována a předána FULL-C programu.

Pro kontrolu průběhu a úspěchu či chyby, je k dispozici funkce http_get_status().

Funkce http_get() se typicky kombinuje s funkcí dns_resolv(), kdy jako uživatel pouze znáte HostName, a potřebujete nejprve získat aktuální hodnotu IP adresu serveru, před zavoláním http_get().


Upozornění

Všechny funkce (http_get / http_post) pro svou práci potřebují určité volné místo v pracovní paměti (heap). Pokud toto místo není k dispozici, funkce nejsou provedeny (ohlášena chyba 1034). Je na vás zajistit, aby tam to místo bylo.

Potřebná velikost paměti odpovídá celému datovému obsahu (http hlavička + get/post texty), který se odesílá do serveru. Paměť si funkce alokuje sama, interně. Po dokončení odesílání je tato paměť automaticky uvolněna.


Příklad #1: HTTP GET

V tomto příkladu komunikuje SDS s webovým serverem na adrese 192.168.1.110 na TCP portu 80, a pokud se vše povede, tak vypíše do konzole i přijatou odpověď (o délce MaximalReceiveDataLength bajtů).

void main(void)
{
 unsigned int status;
 unsigned int MaximalReceiveDataLength;
 unsigned char * ReceiveDataBuffer;
 unsigned int httpResponseValue;
 unsigned int receivedDataSize;

 // todo: check if internet is available 

 printf("START \n");
 
 // how much received data do we maximally want ? (this example: we want
 0 up to 128 chars)
 MaximalReceiveDataLength = 128;
 
 // get a buffer (on local heap) to store the received response
 ReceiveDataBuffer = (unsigned char *)malloc(MaximalReceiveDataLength);

 // did we got the memory ?
 if (ReceiveDataBuffer == 0)
 {
   printf(" out of memory ");
   return;
 }
 
 // go
 printf("calling http_get...\n");
 http_get(192,168,1,110, 80, "www.hostname.cz", "/index.htm", (void *)ReceiveDataBuffer, MaximalReceiveDataLength);
 
 // wait for the result
 status = http_get_status(&httpResponseValue, &receivedDataSize);
 while (status == 1023)
 {
   status = http_get_status(&httpResponseValue, &receivedDataSize);
 }
 
 // process the result
 if (status == 1024)
 {
    // all is great
    printf("DONE OK.  HTTP RESPSTAT = %u    receivedDataSize = %u\n", httpResponseValue, receivedDataSize);
    
    // now we can process the data (body text) of the server's response
    if (receivedDataSize > 0)
    {
      // for thix example, just simply print the text to console
      printf("%s", (char *)ReceiveDataBuffer);
    }
 } else
 {
    // status != 1024
    printf("FAILED. error code = %u \n", status);
 }
 
 // finally -> DO NOT FORGET to release the memory back to heap
 free(ReceiveDataBuffer); ReceiveDataBuffer = 0;
 
}

Příklad #2: HTTP GET

V tomto příkladu komunikuje SDS s webovým serverem na adrese 192.168.1.110 na TCP portu 80, a ignoruje datový obsah odpovědi serveru.

void main(void)
{
 unsigned int status;
 unsigned int httpResponseValue;

 // todo: check if internet is available 

 printf("START \n");
 
 // go
 printf("calling http_get...\n");
 http_get(192,168,1,110, 80, "www.hostname.cz", "/index.htm", (void *)0, 0);
 
 // wait for the result
 status = http_get_status(&httpResponseValue, 0);
 while (status == 1023)
 {
   status = http_get_status(&httpResponseValue, 0);
 }
 
 // process the result
 if (status == 1024)
 {
    // all great
    printf("DONE OK.  HTTP RESPSTAT = %u \n", httpResponseValue);

 } else
 {
    // status != 1024
    printf("FAILED. error code = %u \n", status);
 }
 
}


Příklad #3: HTTP POST

V tomto příkladu komunikuje SDS s webovým serverem na adrese 192.168.1.110 na TCP portu 80, a ignoruje datový obsah odpovědi serveru.

void main(void)
{
 unsigned int status;
 unsigned int httpResponseValue;

 // todo: check if internet is available 

 printf("START \n");
 
 // go
 printf("calling http_post...\n");
 http_post(192,168,1,110, 80, "www.hostname.cz", "/process.php", (void *)0, 0, "post text going to server");
 
 // wait for the result
 status = http_get_status(&httpResponseValue, 0);
 while (status == 1023)
 {
   status = http_get_status(&httpResponseValue, 0);
 }
 
 // process the result
 if (status == 1024)
 {
    // all great
    printf("DONE OK.  HTTP RESPSTAT = %u \n", httpResponseValue);

 } else
 {
    // status != 1024
    printf("FAILED. error code = %u \n", status);
 }
 
}


Nastavení uživatelského obsahu HTTP hlavičky

POZOR: toto je dostupné teprve ve firmware od 03/2023 !

Změna Content-Type

Ve výchozím stavu, vkládá SDS do HTTP hlavičky (kterou SDS posílá na server), mimo jiné tento řádek:

Content-Type: text/plain

Obsah Content-Type je možné změnit pomocí funkce http_header_set_content_type().

Zadejte čistě text parametru, příklad (bez uvozovek): "application/json" - tedy čistě to co je až za dvoutečkou, a bez ukončovacích znaků !

Tento příklad se realizuje takto:

 ret = http_header_set_content_type("application/json");

Pozor na maximální omezení délky tohoto textu.

Přidání dalšího uživatelského řádku do hlavičky

Pomocí funkce http_header_set_user_row() lze přidat jeden celý vlastní řádek.

Například:

X-THINGSPEAKAPIKEY: XXXXXXXXXXXXXXX

se do hlavičky přidá pomocí volání funkce:

 ret = http_header_set_user_row(0, "X-THINGSPEAKAPIKEY: XXXXXXXXXXXXXXX");

Tato funkce očekává celkový text plného řádku, ale pozor - bez ukončovacích znaků atd. - viz příklad výše.

Pozor na maximální délku textu, který lze do hlavičky vložit.

Návratové hodnoty pro obě tyto funkce

Tyto dvě specifické funkce vracejí výsledek přímo v rámci své návratové hodnoty (na rozdíl od ostatních, které průběžné předávají hodnotu přes http_get_status() funkci).

Návratové hodnoty:

 0 = změna provedena
-1 = chybné parametry, neprovedeno
-2 = nelze změnit, protože HTTP-GET nebo HTTP-POST právě probíhá 
-4 = jiná chyba, neprovedeno


http_close()

Tuto funkci obvykle vůbec není potřeba použít.

Použití je jen ve speciálních případech, kdy už nechcete dále čekat na dokončení komunikace se http serverem.

Nelze totiž začít další http_get/post, dokud plně neskončil právě eventuálně probíhající.

V běžném provozu není tato funkce potřeba, neboť server ukončuje spojení ihned po přenesení odpovědi do SDS. Nicméně, pokud máte server který je nakonfigurován že vždy spojení neuzavře (forced persistent connection), pak je tato funkce řešením tohoto problému (váš program, po obdržení celé odpovědi, zavolá tuto funkci a tím slušně ukončí tcp spojení na server).


Stavové hodnoty / chyby

Program musí použít volání funkce http_get_status() pro zjištění okamžitého stavu. Tuto funkci lze použít pro GET i POST.

 http_get_status()          význam
-------------------------+-----------------------------------------------------------------------
 0                       |  klid, žádná akce nebyla zahájena
 1023                    |  právě probíhá požadovaná činnost, čekejte
 1024                    |  úspěsně provedeno (HTTP GET dotaz odeslán na server, a byla obdržena odpověď)
 1025                    |  nelze se připojit k serveru (činnost neprovedena)
 1026                    |  timeout (nepovedlo se provést činnost v určeném čase, limit je 45 vteřin)
 1027                    |  server předčasně ukončil spojení (nemáme odpověď, dotaz se zřejmě také nepovedlo předat)
 1028                    |  byly přijaty neplatné data v odpovědi ze serveru (neznáme odpověď)
 1029                    |  pokoušíte se poslat další dotaz, zatímco ten předchozí ještě nebyl dokončen (takže ten nový je ignorován a není proveden)
 1030                    |  zařízení SDS nemá platnou IP adresu (připojení k serveru neprovedeno, činnost neprovedena)
 1031                    |  zařízení SDS nemá funkční Ethernet (vytáhnutý kabel, vypnutý switch) (cinnost neprovedena)
 1032                    |  funkce byla zavolána s neplatnými parametry (činnost neprovedena)
 1033                    |  timeout
 1034                    |  nedostatek paměti (heap) pro provedení funkce