 |
|
Propagazione di situazioni di pericolo
ambientale.
ADP.DLL
(ver 0.1 Build 3)
|
Descrizione generale
La libreria ADP.DLL contiene una classe publica clsADPProtocol che contiene i
metodi e gli eventi per decodificare un comando ricevuto dal protocollo e per crearne uno.
Laltra classe contenuta nella libreria clsParser è privata ed è la classe su
cui clsADPProtocol carira il linguaggio e la sintessi dello stesso. È questa
stessa classe che si incarica di controllare la corretta sintassi dei comandi passati e di
separare i vari token. La classe publica fa da wrapper con questa classe privata, carica
la sintassi nella classe privata e ritorna degli eventi a seconda del tipo di comando che
le viene passato.
La classe clsParser
Descrizione
Questa classe privata permette di aggiungere una lista di comandi referenziati da un ID
numerico per cui è possibile inserire la struttura sintattica del comando e i parametri
che esso deve tornare
Tramite il comando
Add(CmdId As String, Optional CmdSintax)
si aggiunge alla lista il comando con ID = CmdId e,
opzionalmente, la lista sintattica del comando. Se CmdSintax e omesso il
comando sarà accettato nella forma di:
ID DescrComando (p.e. "1001 HELO")
altrimenti dipendera dai possibili valori dati da CmdSintax. I valori
possibili per CmdSintax sono tutti i caratteri ascii che vengono matchati
così come passati e i costrutti che vengono preceduti da uno slash (\). Tali costrutti
sono:
\n
|
Matcha un digit |
\N
|
Matcha un numero |
\w
|
matcha una lettera |
\W
|
matcha una parola |
\S
|
matcha uno o piu spazii |
\A
|
matcha tutto fino alla fine |
\(
|
inizio parametro |
\)
|
fine parametro |
\[
|
Inizio sezione opzionale del comando |
\]
|
fine sezione opzionale del comando |
Le sezioni \(...\) fanno si che la roba che viene matchata al
suo interno vada a finire nelli-esimo parametro del comando che può essere ottenuto
tramite getParam(i). Le sezioni \[...\] sono sezioni opzionali
che se trovate vengono matchate (e tornate nel parametri se contengono il costrutto \(..\)
) altrimenti vengono ignorate
Per esempio il comando
1002 WARN <id>@<ip> [<level>] [<descr>]
viene implementato come
Parser.add(1002,"\(\N\)@\(\N.\N.\N.\N\)\S\[\(\n\)\S\(\A\)\]")
Il controllo viene fatto con il metodo
che torna
|
=>
|
il controllo sintattico è corretto
|
|
=>
|
Troppi pochi parametri passati. Almeno due (ID e descr)
|
|
=>
|
Il comando non è stato trovato
|
|
=>
|
Il comando contiene un errore sintattico
|
Se Check torna 0 allora in getParam(i) si trova
l'i-esimo parametro matchato
Per esempio utilizzando l'esempio precedente si ottiene che
Check("1002 WARN 99999@195.32.69.18 1 Warning di livello 1")
torna 0 e
getParam(1)
|
=>
|
"99999"
|
getParam(2)
|
=>
|
"195.32.69.18"
|
getParam(3)
|
=>
|
"1"
|
getParam(4)
|
=>
|
"Warning di livello 1"
|
Proprietà
Public Property CmdId As String
sola lettura
Torna l'ID del comando passato con il metodo Check
Public Property ParamCount As Long
sola lettura
Wrapper attorno alla variabile interna che conteggia il numero di Parametri trovati.
Conteggio in base 1
Metodi
Public Sub Add(ByVal CmdId As String, [ByVal CmdSintax As String = Vuoto])
Aggiunge alla lista il comando con ID = CmdID e con sintassi CmdSintax.
Public Function Check(ByVal CmdString As String) As Integer
Controlla se CmdString è un comando sintatticamente corretto. Se tale
metodo ha successo (0) in getParam(i) si trova l'i-esimo parametro del
comando
Private Sub ClearParam()
Reinizializza, pulendolo, il vettore interno che contiene la lista dei parametri
ritornati e azzera (-1) la variabile interna che conteggia il numero totale dei parametri
ritornati
Public Function GetParam(ByVal Index As Long) As String
Torna il parametro con indice Index trovato da Check. Se Index
è maggiore del numero massimo di parametri trovati (ricavabile da ParamCount)
torna una stringa nulla.
Private Function MatchText(ByVal StringToMatch As String, ByVal Match As String,_
ByVal Start As Long) As eParameter
Ritorna una struttura eParameter contenente informazioni sulla parte di StringToMatch
che, eventualmente, corrisponde alla struttura sintattica Match a partire dal
carattere corrispondente alla posizione START. La struttura eParameter
è così fatta:
Private Type eParameter |
|
|
Result As Boolean |
Torna se è stata trovata la corrispondenza |
|
ReturnString As String |
Torna la stringa trovata |
|
StartMatch As Long |
Torna la posizione di partenza all'interno della stringa |
|
EndMatch As Long |
Torna la posizione di fine della corrispondenza |
|
EOC As Boolean |
Indica se è stata raggiunta la fine della stringa |
End Type |
|
Private Function ParseCmd() As Boolean
Utilizzando le variabili interne della classe in cui sono state registrate, dal metodo
check, la stringa di comando e la prevista struttura sintattica del comando corrispondente
controlla se la stringa corrisponde alla struttura e inserisce i parametri nel vettore
interno della classe, che potranno essere restituiti dal metodo publico GetParam. Torna TRUE
se la stringa di comando ha la struttura corretta, altrimenti FALSE
Eventi
NESSUN EVENTO PER QUESTA CLASSE
La classe clsADPProtocol
Descrizione
Questa classe publica creabile con eventi (WithEvents), come già detto,
decodifica i messaggi che le vengono passati e genera degli eventi se riconosce o meno
questi messaggi. Inoltre può essere utilizzata per lanciare messaggi secondo le
specifiche del protocollo. E' questa stessa classe che, alla sua inizializzazione, carica
la sintassi nella clsParser e si interfaccia a questa per la scansione della
sintatti dei comandi ricevuti.
Tramite la funzione
si ottiene la stringa formata Id con la descrizione relativa e con
MoreInfo come parametri aggiuntivi ossia, per esempio, con
PrintMsg(1002,"12345@195.32.69.18 1")
si ottiene la stringa
1002 WARN 12345@@195.32.69.18 1
ossia la funzione PrintMsg, a cui viene passato l'ID del comando, si fa
carico di appendere la descrizione del comando e ulteriori parametri.
La funzione
si fà carico di controllare la sintassi del messaggio passatole generando gli eventi
opportuni se riconosce o meno il messaggio ricevuto. Se non riconosce il comando o trova
un errore di sintassi genera un evento
Event ErrorCmd(ByVal Id As Integer, ByVal Descr As String)
contenente l'ID dell'errore ed una eventuale descrizione. La generazione di tale evento
alla ricezione di un messaggio non appartenente al protocollo può essere disabilitata
impostando la proprietà
Questa cosa è utile durante la ricezione di blocchi di messaggi OOP delimitati da uno
SOM fino ad un EOM ( per esempio durante i messaggi di RL o durante il MOTD).
Per gli eventi generati da questa classe si faccia riferimento più avanti in questo
documento.
Metodi
Private Sub AddADPSintax()
Aggiunge l'intera sintassi del protocollo all'istanza interna della classe clsParser
Private Function CheckSyntax(ByVal Message As String) As Boolean
Wrapper interno alla funzione clsParser.check che ne decodifica i messaggi di errore e
genera l'eventale evento di errore
Private Sub ErrorEvent(ByVal Id As Long, [ByVal Descr As String = ""])
Wrapper interno alla generazione dell'evento di errore che controlla che la proprietà RaiseError
è impostata a True prima di generarlo.
Public Function GetCmdString(ByVal Id As Long) As String
Metodo che ritorna la descrizione di un comando dato il suo ID
Public Function PrintMsg(ByVal Id As Long, [ByVal MoreInfo As String]) As String
Metodo che stampa un comando dato il suo ID ed i suoi parametri aggiuntivi
Public Sub ReveiceMsg(ByVal Message As String)
E' il metodo tramite il quale viene passato alla classe il messaggio ricevuto per la
successivi codifica e generazione eventi
Proprietà
Public Property RaiseError As Boolean
Imposta se è attivata la generazione degli eventi di errore. di default è TRUE.
L'impostazione a FALSE ossia la disattivazione dei messaggi di errore può
essere utile nella lettura di messaggio fuori-protocollo come i messaggi del MOTD o della
RL.
Eventi
Public Event ErrorCmd(ByVal Id As Integer, ByVal Descr As String)
Viene generato se viene riportato un qualche errore nel messaggio passato alla classe
per la decodifica. Torna l'ID dell'errore ed una sua eventuale descrizione. Non viene
generato se la proprietà RaiseError è impostata a FALSE
Public Event RcvAlarm(ByVal MsgTime As Long, ByVal MsgIp As String, _
ByVal Level As Integer, ByVal Descr As String)
Viene generato alla ricezione di un messaggio di allarme (ID: 1004). Torna il numero di
secondi da 1/1/1970 in cui è stato generato l'allarme, l'indirizzo ip di chi ha generato
l'allarme, il livello e la descrizione del tipo di allarme
Public Event RcvHelo()
Viene generato alla ricezione del messaggio di HELO (ID:1001)
Public Event RcvQuit()
Viene generato alla ricezione del messaggio di QUIT (ID: 1999)
Public Event RcvReply(ByVal Id As Integer, ByVal Descr As String)
Viene generato alla ricezione di un qualsiasi messaggio di Reply da un server. Torna
l'ID del messaggio di REPLY ed una sua eventuale descrizione altrimenti torna una vbNullString
Public Event RcvUnAlarm(ByVal MsgTime As Long, ByVal MsgIp As String)
Viene generato alla ricezione di un messaggio di fine allarme (ID: 1005). Torna il
numero di secondi dal 1/1/1970 in cui è stato generato il messaggio di UNALARM
è l'indirizzo IP della macchina che l'ha generato.
Public Event RcvUnWarn(ByVal MsgTime As Long, ByVal MsgIp As String)
Viene generato alla ricezione di un messaggio di fine preallarme (ID: 1003). Torna il
numero di secondi dal 1/1/1970 in cui è stato generato il messaggio di UNWARN
è l'indirizzo IP della macchina che l'ha generato.
Public Event RcvWarn(ByVal MsgTime As Long, ByVal MsgIp As String, _
ByVal Level As Integer, ByVal Descr As String)
Viene generato alla ricezione di un messaggio di preallarme (ID: 1002). Torna il numero
di secondi da 1/1/1970 in cui è stato generato preallarme, l'indirizzo ip di chi ha
generato il preallarme, il livello e la descrizione del tipo di preallarme
|
 |
|
 |
sono molto interessato a questo tuo articolo e vorrei avere, se è possibile, maggiori informazioni: il PLC è dell'AllenBradley?
E' possibile avere qualche informazione sugli schemi SFC o sulla programmazione del protocollo in ladder?
Grazie
IL PLC era un Siemens, non ricordo che modello però.
La programmazione non l'ho fatta io, mi sono interessato alla parte di comunicazione via seriale quindi non posso esserti d'aiuto non sapendo neanche cosa sia il protocollo in ladder.
Sorry.
intendevo la programmazione del plc in ladder (normalmente aperto, normalmente chiuso.... non so se ho reso l'idea)
sulla chat IRC non ci sei. Se non è un peso, potresti mandarmi maggiori informazioni via email sulla parte di comunicazione seriale su cui hai lavorato, oppure c'è un altro modo per contattarti?
Tutta la parte di comunicazione è qui
Dato che ti intendi di protocolli di comunicazione sapresti dirmi dove posso trovare informazioni rigurdanti le specifiche di del protocollo executive.
Se fossero dettagliate come la ta descrizione sarei molto contento.
Questo articolo è meraviglioso. Consente facilmente l'ingresso nel mondo della comunicazione PLC-PC fornendo un possibile spunto per iniziare a scrivere client proprietari lato pc.
Ma come descrivere connessioni e parametri fra porte logiche, timer, etc, e il loro stato (es: nc/na)?