Realizzare pagine web in Ajax con FB HTTPServer

» Home » Article » Realizzare pagine web in Ajax con FB HTTPServer
  1. Home
  2. Knowledge Base
  3. Controllori SlimLine
  4. Esempi
  5. Realizzare pagine web in Ajax con FB HTTPServer

Scopo del programma

Il programma HTTPServerDemo trattato in questo articolo (Download programma) dimostra come utilizzare il FB HTTPServer per realizzare in modo semplice pagine HTML responsive che permettono di interagire con il programma PLC scambiando dati in formato JSON in tecnica Ajax con il modulo CPU Compact Ethernet da browser.

Il programma è fornito in un file zip che oltre al programma sorgente da aprire con LogicLab contiene la cartella WPages con la pagina Home.htm da trasferire nella cartella Storage dei sistemi Compact o nella cartella C:/WPages dei Cortex M7.

Come si vede dalla foto nella pagina web visualizzata dal browser è ritornato lo stato degli ingressi del modulo ed è possibile comandarne le uscite. Il programma si basa sul FB HTTPServer che permette di gestire fino a 4 connessioni contemporanee. di seguito il listato del programma.

Inizializzazione e gestione server

Nella inizializzazione viene configurato il server HTTP impostando il numero di connessioni contemporanee gestite, la porta in ascolto (Nel nostro esempio è la 2000), la directory in cui si trovano le pagine da visualizate “C/WPages/” e la pagina di default che viene ritornata “Home.htm” quando è richiesto il solo indirizzo IP del dispositivo. Viene impostata anche la dimensione del buffer TCP che determina la dimensione massima dei pacchetti TCP scambiati con il client e la dimensione del buffer HTTP che deve essere dimensionata per contenere oltre all’header di richiesta anche tutti i dati ricevuti dal client (Esempio in caso di richiesta POST).

Viene poi gestito il server che accetta le connessioni dai clients (Web browser) sulla porta 2000. Appena dopo l’esecuzione si resettano le variabili RAck e RNAck che sono da settare nella gestione dei dati ricevuti dal client per inviare la risposta al client. Alla ricezione della richiesta di una pagina la pagina viene automaticamente ritornata se presente nella cartella definita in HPath. Se non è presente viene attivato RRcvd.

   IF (SysFirstLoop) THEN
    HTTPSv.Enable:=TRUE; (* Server enable *)    
    HTTPSv.SpyOn:=TRUE; (* Spy active *)    
    HTTPSv.Port:=2000; (* TCP Port *)
    HTTPSv.AConnections:=2; (* Accepted connections *)    
    HTTPSv.TCPBSize:=1024; (* TCP buffer size *)    
    HTTPSv.HTTPBSize:=512; (* HTTP buffer size *)    
    HTTPSv.HPath:=ADR('C:/WPages/'); (* Home path*)
    HTTPSv.PDefault:=ADR('Home.htm'); (* Default page *)
    HTTPSv.Timeout:=2.0; (* Execution timeout (S) *)
  END_IF;

  (* Eseguo gestione server. *)

  HTTPSv(); (* HTTP server *)
  HTTPSv.RAck:=FALSE; (* Request acknowledge *)
  HTTPSv.RNAck:=FALSE; (* Request not acknowledge *)
  IF NOT(HTTPSv.RRcvd) THEN CaseNr:=1; RETURN; END_IF;

Verifica pagina e ricezione comando output

La parte di programma che gestisce i dati ricevuti dal browser ed invia la risposta è eseguito a stati. Nel case 1 si controlla la pagina richiesta dal browser se è Read.cgi si passa al case 20 dove sarà gestita la risposta.

Se è Command.cgi si passa al case 10, questa pagina è richiesta dal browser in POST che invia anche una stringa JSON del tipo {“DOut”:1}. DOut indica il comando di inversione stato uscita digitale e 1 è l’uscita da invertire. Con il FB JDecode si decodifica la stringa e se trovata variabile DOut in base al valore si inverte lo stato del relativo bit di uscita. Poi si passa al case 20 che ritornerà lo stato degli ingressi e delle uscite al browser per la visualizzazione.

  CASE (CaseNr) OF

    (* ------------------------------------------------------------------ *)
    (* Attesa reset "RRcvd". *)
    0: RETURN;

    (* ------------------------------------------------------------------ *)
    (* Verifica pagina richiesta. *)
    1:
    IF (SysStrFind(HTTPSv.pPage, ADR('Read.cgi'), FIND_DEFAULT) = HTTPSv.pPage) THEN CaseNr:=20; RETURN; END_IF;
    IF (SysStrFind(HTTPSv.pPage, ADR('Command.cgi'), FIND_DEFAULT) = HTTPSv.pPage) THEN CaseNr:=10; RETURN; END_IF;
    HTTPSv.RNAck:=TRUE; (* Request not acknowledge *)
    CaseNr:=0; (* Ritorno dati in lettura *)

    (* ------------------------------------------------------------------ *)
    (* Gestione pagina "Command.cgi" *)
    10:
    JDecode(Object:=HTTPSv.pRxData, Name:=ADR('DOut'), VType:=UDINT_TYPE, VAddress:=ADR(i));
    IF (JDecode.ECode = 0) THEN
      IF (i=0) THEN DOut.Value:=DOut.Value XOR 16#00000001; END_IF;
      IF (i=1) THEN DOut.Value:=DOut.Value XOR 16#00000002; END_IF;
      IF (i=2) THEN DOut.Value:=DOut.Value XOR 16#00000004; END_IF;
      IF (i=3) THEN DOut.Value:=DOut.Value XOR 16#00000008; END_IF;
    END_IF;
    CaseNr:=20; (* Ritorno dati in lettura *)

Invio stringa JSON di risposta al browser

In questo case si prepara la stringa JSON di risposta che riporta in un array il colore degli ingressi e delle uscite (L’elemento attivo è in rosso), la stringa che sarà inviata al browser è del tipo: {“Inputs”:[“red”, “#303030”, “#303030”, “#303030”, “#303030”, “#303030″],”Outputs”:[“red”, “#303030”, “red”, “#303030”]}.

Sono acquisiti gli ingressi digitali e iterando sui 6 valori viene valorizzato un array di puntatori a stringhe con la definizione del colore da inviare. Il FB JEncode provvede poi a generare la stringa JSON nel buffer puntato da pTxData.

Sono poi gestite le uscite digitali ed iterando sui 4 valori viene valorizzato un array di puntatori a stringhe con la definizione del colore da inviare. Il FB JEncode provvede poi a generare la stringa JSON nel buffer puntato da pTxData.

In TxDSize viene trasferita la lunghezza della risposta, ed attivando RAck la risposta viene inviata al browser.

    (* ------------------------------------------------------------------ *)
    (* Gestione ingressi digitali. *)
    20:
    i:=Sysmemset(HTTPSv.pTxData, 0, HTTPSv.HTTPBSize); (* Inizializzo buffer *)
    DInp(Address:=255, Mode:=DI_8_LL); (* Digital inputs acquisistion *)

    i:=DInp.Value; (* Auxiliary variable *)
    FOR j:=0 TO 5 DO
      IF TO_BOOL(i AND 16#00000001) THEN LEDStatus[j]:=ADR('red'); ELSE LEDStatus[j]:=ADR('#303030'); END_IF;
      i:=i/2; (* Auxiliary variable *)
    END_FOR;

    JEncode(Object:=HTTPSv.pTxData, OSize:=HTTPSv.HTTPBSize, Name:=ADR('Inputs'), VType:=STRING_TYPE, VAddress:=ADR(LEDStatus), Count:=6);

    (* Gestione uscite digitali. *)
    
    DOut(Address:=255, Mode:=DO_8_LL, Mask:=16#0000000F); (* Digital inputs acquisistion *)

    i:=DOut.Value; (* Auxiliary variable *)
    FOR j:=0 TO 3 DO
      IF TO_BOOL(i AND 16#00000001) THEN LEDStatus[j]:=ADR('red'); ELSE LEDStatus[j]:=ADR('#303030'); END_IF;
      i:=i/2; (* Auxiliary variable *)
    END_FOR;

    JEncode(Object:=HTTPSv.pTxData, OSize:=HTTPSv.HTTPBSize, Name:=ADR('Outputs'), VType:=STRING_TYPE, VAddress:=ADR(LEDStatus), Count:=4);

    (* Eseguo invio dati al client. *)

    HTTPSv.TxDSize:=Sysstrlen(HTTPSv.pTxData); (* Answer data length *)
    HTTPSv.RAck:=TRUE; (* Request acknowledge *)
    CaseNr:=0; (* Ritorno dati in lettura *)
  END_CASE;

Pagina web

Per la visualizzazione nel browser è fornita la pagina Home.htm, questa è una pagina responsive realizzata con la libreria Skeleton. Non mi dilungo sulla gestione dei css per il responsive mentre è importante soffrmarci sulle funzioni javascript di aggiornamento pagina.

PRefresh: Eseguita al caricamento pagina ed ogni secondo invia una richiesta Ajax in GET della pagina Read.cgi che come visto nel programma farà saltare al case 20 dove viene preparata ed inviata la stringa JSON di risposta.

WCommand: Eseguita sulla pressione degli oggetti di visualizzazione uscite digitali, invia una richiesta Ajax in POST della pagina Command.cgi con l’indicazione dell’uscita comandata, che come visto nel programma farà saltare al case 10 dove viene gestita l’uscita e poi al case 20 dove viene preparata ed inviata la stringa JSON di risposta.

PUpdate: Richiamata dalle due funzioni precedenti riceve in PContent la stringa JSON ricevuta dal programma e provvede ad aggiornare il colore di background degli oggetti. Viene anche eseguita l’uscta sulla console del brower dei dati ricevuti per poterli visualizzare attivando la console del browser (Chrome o Firefox).

function PRefresh()
{
  GETAjax('Read.cgi', function(PContent){PUpdate(PContent);});
}

function WCommand(Do)
{
  POSTAjax('Command.cgi', '{"DOut":'+Do+'}', function(PContent){PUpdate(PContent);});
}

function PUpdate(PContent)
{
  console.warn(PContent);
  var Obj = JSON.parse(PContent);

  // Eseguo gestione LED I/O digitali.

  for (i=0; i<6; i++) document.getElementById("Di0"+i).style.backgroundColor = Obj.Inputs[i];
  for (i=0; i<4; i++) document.getElementById("Do0"+i).style.backgroundColor = Obj.Outputs[i];
}

Conclusioni

La disponibilità del FB HTTPServer permette di aggiungere uno o più server web nel proprio programma PLC permettendo di gestire scambio dati in JSON con il browser e/o di gestire servizi web come ad esempio richieste REST.

Ti è stato utile questo articolo ?