In questo articolo abbiamo visto come sia possibile in modo estremamente semplice implementare applicazioni cloud con i nostri sistemi SlimLine e Netsyst utilizzando il protocollo MQTT tramite il FB MQTTCBeebotte. Ora vediamo come sia altrettanto semplice realizzare un sito web che permette di storicizzare i dati in un database MySQL e di visualizzarli in forma tabellare o grafica attraverso una semplice API in REST a cui è possibile inviare dati tramite il FB RESTClient. Abbiamo inserito nell’armadio del nostro datacenter un sistema Netsyst che ne monitorizza tramite un analizzatore di rete SDM120 i consumi. I dati acquisiti sono visualizzati sul display del prodotto ed inviati via REST ad un server nel cloud.

Il programma utilizzando i FB per la gestione dei contatore Eastron SDM120 esegue in un semplice programma FBD l’acquisizione dei dati di consumo, che, appoggiati a variabili globali sono visualizzati sul display ed inviati via REST al server cloud.

Lo script in linguaggio PHP sul server cloud riceve i dati in POST e li memorizza in un database, una pagina htm di consultazione permette di visualizzare i dati ricevuti su di una dashboard. Per la visualizzazione del grafico viene utilizzata la libreria open source Chart.js che permette di realizzare grafici in HTML5, ecco come si presenta la dashboard.
Programma di esempio
Come utilizzare gli esempi.
Con LogicLab viene fornito il progetto Ptp145 RESTLogger con il programma che gestisce la dashboard visibile nell’esempio. Il progetto è suddiviso in due cartelle la cartella LogicLab contiene il programma del PLC, la cartella RESTLogger contiene i programmi PHP e la pagina HTML di visualizzazione.
LogicLab (Ptp145, ST_RESTDataSend)
PROGRAM ST_RESTDataSend
VAR
DSCmd : BOOL; (* Debug send command *)
UTCDateTime : UDINT; (* UTC Date/Time *)
RESTRequest : STRING[ 128 ]; (* REST request *)
FIFO : FIFOFile_v1; (* FIFO on file *)
TCPClient : SysTCPClient; (* TCP client management *)
HTTPRq : HTTPClient_v5; (* HTTP client *)
REST : RESTClient_v7; (* REST service client *)
END_VAR
// *****************************************************************************
// PROGRAM "ST_RESTDataSend"
// *****************************************************************************
// It sends data to the REST server,
// https://support.elsist.biz/articoli/una-applicazione-rest-in-pratica/
// -----------------------------------------------------------------------------
// To test the program you have to install the RESTLogger PHP program on a LAMP
// or XAMP environment. To test if the RESTServer works properly you can open
// in your browser the bottom link.
// http://localhost/RESTLogger/RESTSvc.php?Post={"MID":1234, "ST":0, "UID":10879070, "MV":"1.0"}
// -----------------------------------------------------------------------------
// -------------------------------------------------------------------------
// PROGRAM INIT
// -------------------------------------------------------------------------
// Executed at first program execution, all variables are initialized.
IF (SysFirstLoop) THEN
// Set FIFO parameters
FIFO.FIFOFilename:=eNULL; //Path and name of FIFO file
FIFO.FIFOSize:=2048; //FIFO file size
FIFO.FIFOIDx:=eNULL; //FIFO indexes
// Set TCPClient parameters.
TCPClient.PeerAdd:=ADR('192.168.1.122'); //Peer address
TCPClient.PeerPort:=80; //Peer port
TCPClient.LocalAdd:=ADR('0.0.0.0'); //Local address
TCPClient.LocalPort:=0; //Local port
TCPClient.FlushTm:=50; //Flush time (mS)
TCPClient.LifeTm:=20; //Life time (S)
TCPClient.RxSize:=512; //Rx buffer size
TCPClient.TxSize:=512; //Tx buffer size
// Set HTTPClient parameters.
HTTPRq.SpyOn:=TRUE; //Activate the spy
HTTPRq.KeepAlive:=FALSE; //HTTP keep-alive
HTTPRq.RMethod:=HTTP_REQUEST#HTTP_POST; //Request method
HTTPRq.HostName:=TCPClient.PeerAdd; // Hostname
HTTPRq.Page:=ADR('/RESTLogger/RESTSvc.php'); //Web page
HTTPRq.Header:=ADR('Content-Type:application/json$r$n'); //HTTP header
HTTPRq.DBSize:=512; //Data buffer size
HTTPRq.Timeout:=T#10s; //Execution timeout
// REST definitions.
REST.SpyOn:=TRUE; //Spy On
REST.BLength:=512; //REST Request/Answer buffers length
REST.Delay:=T#2s; //Delay time
REST.HBitTime:=T#5s; //Heartbeat time
// REST auxiliary object references.
REST.FIFOFile:=ADR(FIFO); //FIFO on file
REST.HTTPClient:=ADR(HTTPRq); //HTTP Client
END_IF;
// -------------------------------------------------------------------------
// REST CLIENT MANAGEMENT
// -------------------------------------------------------------------------
// Here the REST client is managed, it's always enabled.
TCPClient(Connect:=HTTPRq.Connect); //TCPClient management
HTTPRq(File:=TCPClient.File); //HTTP client
REST(Enable:=TRUE); //REST client management
REST.DDelete:=FALSE; //Delete data from FIFO
// -------------------------------------------------------------------------
// ERROR MANAGEMENT
// -------------------------------------------------------------------------
// On error it's possible to count the retries and then decide what to do.
IF (REST.SvcError) THEN
// After 3 retries the message to be sent to the REST server is removed
// from the FIFO register. Before to remove the message it's returned
// to the spy console.
IF (REST.Retries > 3) THEN
FIFO(Out:=TRUE, Dp:=eNULL, Dls:=0); //Read record length
IF NOT(SysRMAlloc(FIFO.Dl+1, ADR(FIFO.Dp))) THEN RETURN; END_IF;
FIFO(Out:=TRUE, Dls:=FIFO.Dl); //Read record data
eTO_JUNK(SysWrSpyData(SPY_ASCII, 0, 16#00000001, ADR('-Delete-'), FIFO.Dp));
eTO_JUNK(SysRMFree(ADR(FIFO.Dp))); //Free malloc memory
REST.DDelete:=TRUE; //Delete data from FIFO
END_IF;
END_IF;
// -------------------------------------------------------------------------
// SEND DATA TO SERVER
// -------------------------------------------------------------------------
// Every minute data are send to the server.
IF (SysGetUTCDateTime(TRUE) <> UTCDateTime) THEN
UTCDateTime:=SysGetUTCDateTime(TRUE); //UTC Date/Time
IF ((MOD(UTCDateTime, 60) = 0) OR (DSCmd)) THEN
DSCmd:=FALSE; //Debug send command
// Eseguo compilazione dati da inviare al server in JSON.
eTO_JUNK(Sysmemset(ADR(RESTRequest), 0, SIZEOF(RESTRequest))); //REST request
eTO_JUNK(JSONEncoder(ADR(RESTRequest), SIZEOF(RESTRequest), ADR('Frequency'), REAL_TYPE, ADR(Frequency), 1));
eTO_JUNK(JSONEncoder(ADR(RESTRequest), SIZEOF(RESTRequest), ADR('Voltage'), REAL_TYPE, ADR(Voltage), 1));
eTO_JUNK(JSONEncoder(ADR(RESTRequest), SIZEOF(RESTRequest), ADR('AcPower'), REAL_TYPE, ADR(AcPower), 1));
eTO_JUNK(JSONEncoder(ADR(RESTRequest), SIZEOF(RESTRequest), ADR('PwFactor'), REAL_TYPE, ADR(PwFactor), 1));
FIFO(In:=TRUE, Dp:=ADR(RESTRequest), Dls:=LEN(RESTRequest)); //Write record on FIFO
END_IF;
END_IF;
// [End of file]]