Vai al contenuto

Limite dimensione messaggi in ricezione e trasmissione con HTTPClient

Home Forum Programmazione IEC 61131 (LogicLab) Limite dimensione messaggi in ricezione e trasmissione con HTTPClient

Stai visualizzando 3 post - dal 1 a 3 (di 3 totali)
  • Autore
    Post
  • #82611
    Anonimo
    Inattivo

    Ho realizzato un sistema con i Vs PLC SlimLine per gestire impianti di climatizzazione. I PLC posti sugli impianti comunicano utilizzando il FB HTTPClient con una applicazione server nel cloud.

    Guardando gli esempi del FB HTTPClient ho capito come trasferire in un file i dati ricevuti dal server e quindi gestire ricezione di stringhe dati anche molto lunghe.

    Purtroppo non ho capito come inviare stringhe dati al server con il metodo POST utilizzando la proprietà Request del FB HTTPClient. Ho verificato che la lunghezza massima trasferibile è di 512 bytes.

    #82615
    Sergio Bertana
    Amministratore del forum

    Iniziamo con il dire che non c’è limite sulla dimensione dei dati che si possono inviare e/o ricevere in una comunicazione HTTP con il FB HTTPClient. Visto che per i dati in ricezione ti è chiaro come procedere e penso che il programma ST_HTTPClient_ToFile ne sia un esauriente esempio, vediamo come procedere per i dati da inviare al server.

    Premesso che si si hanno molti dati da inviare è preferibile utilizzare una richiesta POST in cui i dati vengono inviati nel body senza limiti di lunghezza. Nelle richieste in GET i dati vengono passati nell’URL, che ha una lunghezza definita per ogni server, solitamente mi limito ai 256 caratteri. Ora vediamo il valore 512 a cui penso ti riferissi, negli esempi del FB HTTPClient vedi questo valore ripetuto più volte.

    TCPClient.RxSize:=512; //Rx buffer size
    TCPClient.TxSize:=512; //Tx buffer size
    HTTPRq.DBSize:=512; //Data buffer size

    Nel TCPClient, è definita la dimensione dei buffers Rx e Tx, un pacchetto TCP tipico trasporta fino a 1460 byte di dati, quindi si potrebbero definire questi buffer pari a questa dimensione. Solitamente utilizzo la dimensione 512 per non allocare troppa memoria RAM, il protocollo TCP negozia la quantità dei dati da trasferire in ogni pacchetto dimensionandola alla dimensione buffer. Quindi i dati da ricevere/trasmettere su protocollo TCP saranno frazionati in tanti pacchetti pari alla dimensione definita.

    Nel HTTPClient è definita la dimensione del buffer di appoggio per trasmissione/ricezione dati verso stream di comunicazione (TCPClient) l’indirizzo è trasferito in DBAddress. Il FB compone i dati da inviare in questo buffer e poi li invia allo stream definito in File. I dati ricevuti dallo stream sono trasferiti nel buffer e la dimensione dei dati ricevuti è trasferita in DBChars in modo da permettere al programma utente di leggerli.

    I dati da inviare al server vanno scritti in un buffer di memoria il cui indirizzo và definito in Request, attivando Send il FB provvederà ad inviare la richiesta inviando la stringa presente nel buffer. Siccome i sistemi SlimLine non hanno molta memoria RAM ipotizzando di dover inviare 4kBytes di dati conviene utilizzare la funzione SysRMAlloc per allocare il buffer, memoria che sarà disallocata al termine dell’invio. L’invio verrà sudiviso in pacchetti di dimensione pari al valore più piccolo tra quelli definiti in DBSize e TxSize.

    #82629
    Sergio Bertana
    Amministratore del forum

    La spiegazione magari è più chiara con un programma di esempio. Partendo dal programma ST_HTTPClient ho estratto la parte di comunicazione evidenziando come sia possibile tramite la funzione SysRMAlloc allocare un buffer da 4KBytes per i dati da inviare al server in POST ed un altro buffer da 4KBytes per contenere i dati ricevuti dal server.

    La variabile Page da stringa è stata modificata in puntatore a stringa in modo da poter esserre utilizzata per definire l’indirizzo del buffer di ricezione dati di pagina dal server.

    • CaseNr=0: Se i buffers sono allocati vengono disallocati e si inizializza il tempo di attesa.
    • CaseNr=1: Si attende l’invio dei dati, e si allocano i due buffers di memoria.  Siccome potrebbe non esserci memoria disponibile occoe attendere che si liberi memoria per l’allocazione dei buffers. Quando i due buffers sono allocati è possibile compilare la stringa da inviare al server. I buffers allocati sono sempre azzerati.
    • CaseNr=2: Si controlla la ricezione di caratteri dal server e i caratteri ricevuti sono trasferiti nel buffer di pagina. Al termine della ricezione si ritorna al Case 0.

    Ecco l’estratto del programma da sostituire nel programma ST_HTTPClient di questo articolo.

    VAR
        Page : @STRING; (* Page string *)
    END_VAR
    
        // -------------------------------------------------------------------------
        // PROGRAM SEQUENCIES
        // -------------------------------------------------------------------------
        // Program sequencies.
    
        CASE (CaseNr) OF
    
            // ---------------------------------------------------------------------
            // Initialize the time to manage acquisition delay.
    
            0:
            HTTPRq.Send:=FALSE; //Send request
            IF (HTTPRq.Request <> eNULL) THEN eTO_JUNK(SysRMFree(ADR(HTTPRq.Request))); END_IF;
            IF (Page <> eNULL) THEN eTO_JUNK(SysRMFree(ADR(Page))); END_IF;
            TimeBf:=SysTimeGetMs(); //Time buffer (mS)
            CaseNr:=CaseNr+1; //Program case
    
            // ---------------------------------------------------------------------
            // Wait delay time then initialize buffers and enable client.
    
            1:
            IF ((SysTimeGetMs()-TimeBf) < TO_UDINT(T#5s)) THEN RETURN; END_IF;
            
            IF (HTTPRq.Request = eNULL) THEN IF NOT(SysRMAlloc(4096, ADR(HTTPRq.Request))) THEN RETURN; END_IF; END_IF;
            IF (Page = eNULL) THEN IF NOT(SysRMAlloc(4096, ADR(Page))) THEN RETURN; END_IF; END_IF;
    
               eTO_JUNK(SysVsnprintf(HTTPRq.Request, 4096, ADR('%s'), STRING_TYPE, ADR('Some text')));
               eTO_JUNK(SysCVsnprintf(HTTPRq.Request, 4096, ADR('%s'), STRING_TYPE, ADR('More text')));
               // ... More SysCVsnprintf to add data
               eTO_JUNK(SysCVsnprintf(HTTPRq.Request, 4096, ADR('%s'), STRING_TYPE, ADR('More text')));
            HTTPRq.Send:=TRUE; //Send request
            CaseNr:=CaseNr+1; //Program case
    
            // ---------------------------------------------------------------------
            // Header/Page data are received from server by chunked. When a chunk
            // has been received DBChars returns its length.
    
            2:
            IF ((HTTPRq.DBChars <> 0) AND HTTPRq.HPSelector) THEN
                IF ((Sysstrlen(Page)+HTTPRq.DBChars) < 4096) THEN
                    eTO_JUNK(Sysmemmove(eTO_POINTER(Page)+Sysstrlen(Page), HTTPRq.DBAddress, HTTPRq.DBChars));
                END_IF;
            END_IF;
    
            // The received page content could be used.
    
            IF (HTTPRq.Done) THEN CaseNr:=0; END_IF;
        END_CASE;
    
    // [End of file]
Stai visualizzando 3 post - dal 1 a 3 (di 3 totali)
  • Devi essere connesso per rispondere a questo topic.