Passa al contenuto principale

CLIClient, manages a command-line user interface

Questo function block da eseguire in task Back, gestisce l'interfaccia a linea di comando in modalità client. In CStr occorre indicare la stringa di comando da inviare, in PStr la stringa di prompt attesa, e se è attesa anche una stringa di risposta occorre definirla in EAStr. In ABLength occorre definire la dimensione del buffer di ricezione risposta, il buffer viene allocato dal FB con la funzione RMalloc e l'indirizzo di allocazione è ritornato in uscita in ABPtr.

Attivando CSend la stringa di comando (Se definita) viene inviata sullo stream di comunicazione indicato in Fp e viene attesa la ricezione della stringa di prompt (Se definita), alla ricezione del prompt viene controllata anche la ricezione della stringa definita. Se non viene ricevuta ne la stringa di prompt ne la stringa definita nel tempo impostato in PTime viene generato errore.

In caso di errore viene attivata per un loop di programma l'uscita Fault.

Descrizione​

Immagine FB CLIClient

ParametroTipoDescrizione
CSendBOOLSul fronte di attivazione viene inviato al dispositivo il comando definito in CStr. Per inviare un nuovo comando occorre resettarlo e riattivarlo.
SpyOnBOOLSe attivo permette di spiare il funzionamento della FB (Vedi articolo).
FpFILEPFlusso dati stream da utilizzare per la comunicazione.
ABLengthUDINTDimensione buffer memorizzazione risposta.
CStr@STRINGPuntatore alla stringa di definizione comando da inviare. Se eNULL viene eseguita la sola ricezione della risposta.
PStr@STRINGPuntatore alla definizione stringa di prompt attesa. Se eNULL non viene attesa la stringa di prompt.
EAStr@STRINGPuntatore alla definizione stringa di risposta attesa. Se eNULL non viene attesa nessuna stringa.
CWTimeREALTempo di attesa fine ricezione caratteri (S).
PTimeREALTempo di attesa stringa di prompt (S).
EOLBOOLAttivo per un loop se ricevuto prompt (Se PStr<>eNULL) e ricevuta stringa definita (Se EAStr<>eNULL). Se non definiti PStr e EAStr si attiva al termine della trasmissione comando.
FaultBOOLAttivo in caso di errore nella gestione.
RxChrsUDINT) Numero di caratteri di risposta ricevuti.
ABPtr@STRINGPuntatore buffer memorizzazione risposta (Allocato con RMalloc dal FB).

Trigger di spy​

Se SpyOn attivo  è possibile utilizzare la console di spionaggio per verificare il funzionamento della FB. Sono previsti vari livelli di triggers.

Livelli di trigger

TriggerDescrizione
16#00000001Tx: Invio comando definito.
16#00000002Rp: Ricevuto stringa di prompt.
16#00000004Rs: Ricevuto stringa attesa.
16#80000000Rt: Stringa ricevuta su timeout.

Esempi​

Come utilizzare gli esempi.
Il programma si connette alla porta 23 Telnet del sistema (In localhost), esegue l'autenticazione con le credenziali di default (Admin, Admin). Eseguito il login invia il comando RMStats e cattura la risposta ricevuta. Dalla risposta acquisisce il valore di memoria totale e di memoria libera.

LogicLab (Ptp114, ST_CLIClient)
PROGRAM ST_CLIClient
VAR
Start : BOOL; (* Start command *)
CaseNr : USINT; (* Program case *)
CaseAx : USINT; (* Case auxiliary *)
ErrorNr : USINT; (* Error number *)
TimeBf : UDINT; (* Time buffer (mS) *)
RVars : USINT; (* Readed variables *)
MSize : UDINT; (* Memory size *)
MFree : UDINT; (* Memory free *)
TCPClient : SysTCPClient; (* TCP Client *)
CLI : CLIClient; (* Command line interface client *)
END_VAR

// *****************************************************************************
// PROGRAM "ST_CLIClient"
// *****************************************************************************
// Is managed the telnet connection to a SlimLine device, after authentication
// is managed the "RMStats" command. Some parameter values are decoded from the
// received answer.
// -----------------------------------------------------------------------------

// -------------------------------------------------------------------------
// INITIALIZATION
// -------------------------------------------------------------------------
// Program initializations.

IF (SysFirstLoop) THEN

// TCPClient initialization, it connects to localhost.

TCPClient.PeerAdd:=ADR('127.0.0.1'); //Peer address
TCPClient.PeerPort:=23; //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:=128; //Rx buffer size
TCPClient.TxSize:=128; //Tx buffer size

// Command line interface initialization.

CLI.SpyOn:=TRUE; //Spy On
CLI.CWTime:=0.1; //Character wait time (S)
CLI.PTime:=10.0; //Prompt time (S)
CLI.ABLength:=2048; //Answer buffer length

// Variables initialization.

TimeBf:=SysTimeGetMs(); //Time buffer (mS)
END_IF;

// -------------------------------------------------------------------------
// FBs EXECUTION
// -------------------------------------------------------------------------
// Manage the TCP client.

TCPClient(); //TCPClient
CLI.Fp:=TCPClient.File; //File pointer
CLI(); //Command interface

// Fault management.

IF ((CLI.Fault) OR (ErrorNr <> 0)) THEN CaseNr:=0; END_IF;

// -------------------------------------------------------------------------
// TIMEOUT CONTROL
// -------------------------------------------------------------------------
// The sequences execution timeout is checked.

IF ((CaseNr = 0) OR (CaseNr <> CaseAx)) THEN TimeBf:=SysTimeGetMs(); END_IF;
IF ((SysTimeGetMs()-TimeBf) > TO_UDINT(T#10s)) THEN ErrorNr:=10; RETURN; END_IF;
CaseAx:=CaseNr; //Case auxiliary

// -------------------------------------------------------------------------
// PROGRAM CASES
// -------------------------------------------------------------------------
// Program cases management.

CASE (CaseNr) OF

// ---------------------------------------------------------------------
// CONNECTION TO THE SERVER
// ---------------------------------------------------------------------
// To start sequence the "Start" command must be set by debug.

0:
CLI.CSend:=FALSE; //Command send
TCPClient.Connect:=FALSE; //Connect command
IF NOT(Start) THEN RETURN; END_IF;
Start:=FALSE; //Start command

// Connect to the server.

RVars:=0; //Readed variables
ErrorNr:=0; //Error number
TCPClient.Connect:=TRUE; //Connect command
CaseNr:=CaseNr+1; //Program case

// ---------------------------------------------------------------------
// Check if client connect and wait for "Login:" string.

1:
IF NOT(TCPClient.Connected) THEN RETURN; END_IF;
CLI.CStr:=NULL; CLI.PStr:=NULL; CLI.EAStr:=ADR('Login:'); CLI.CSend:=TRUE;
IF NOT(CLI.EOL) THEN RETURN; END_IF;
CLI.CSend:=FALSE; //Command send
CaseNr:=CaseNr+1; //Program case

// ---------------------------------------------------------------------
// Send login username and wait for "Password:" string.

2:
CLI.CStr:=ADR('Admin$r'); CLI.PStr:=NULL; CLI.EAStr:=ADR('Password:'); CLI.CSend:=TRUE;
IF NOT(CLI.EOL) THEN RETURN; END_IF;
CLI.CSend:=FALSE; //Command send
CaseNr:=CaseNr+1; //Program case

// ---------------------------------------------------------------------
// Send password and wait for "[Admin]>" string as a prompt.

3:
CLI.CStr:=ADR('Admin$r'); CLI.PStr:=ADR('[Admin]>'); CLI.EAStr:=NULL; CLI.CSend:=TRUE;
IF NOT(CLI.EOL) THEN RETURN; END_IF;
CLI.CSend:=FALSE; //Command send
CaseNr:=10; //Program case

// ---------------------------------------------------------------------
// SEND COMMAND
// ---------------------------------------------------------------------
// Send the RMalloc statistics request command, every answer row ends
// with <CR><LF> so they are wait.

10:
CLI.CStr:=ADR('RMStats$r'); CLI.PStr:=ADR('[Admin]>'); CLI.EAStr:=NULL; CLI.CSend:=TRUE;
IF NOT(CLI.EOL) THEN RETURN; END_IF;
CLI.CSend:=FALSE; //Command send

// Reads the needed information in every answer row.

IF (SysVsscanf(SysStrFind(CLI.ABPtr, ADR('Memory size.........'), FIND_GET_END), ADR('%d'), UDINT_TYPE, ADR(MSize))) THEN RVars:=RVars+1; END_IF;
IF (SysVsscanf(SysStrFind(CLI.ABPtr, ADR('Act free memory.....'), FIND_GET_END), ADR('%d'), UDINT_TYPE, ADR(MFree))) THEN RVars:=RVars+1; END_IF;

// All the needed 2 variables has been received.

IF (RVars <> 2) THEN ErrorNr:=50; RETURN; END_IF;
CaseNr:=0; //Program case
END_CASE;

// [End of file]