Ogni nodo di un server OPC UA ha un NodeId: un indice di namespace e un identificatore, scritti come ns=2;s=LineA.Temperature. L’identificatore è di uno di quattro tipi: numerico (i=), stringa (s=), GUID (g=) o byte opachi (b=). Un client, come un sistema SCADA o un Gateway, si collega a un endpoint del server e usa i NodeId per leggere, scrivere o sottoscrivere.
Un’integrazione OPC UA che oggi legge il valore giusto può leggere quello sbagliato dopo un aggiornamento del server, se l’identità conservata non è quella stabile. Un server OPC UA espone uno spazio degli indirizzi: un insieme di nodi che descrivono le apparecchiature, i loro valori e le loro relazioni. Un’integrazione affidabile identifica ogni valore con il suo NodeId e il suo namespace, e conserva insieme al valore lo stato e i timestamp. Questa guida spiega tali identificativi e come validare un punto prima di aggiungerne cento.
Questa guida fa parte della serie su OPC UA e MQTT. Tratta il consueto scambio client-server basato su sessione, non OPC UA PubSub.
Client OPC UA e server
La panoramica della OPC Foundation (parte 1) distingue i due ruoli. Il server possiede lo spazio degli indirizzi e offre servizi su di esso. Il client si collega e usa quei servizi. Un’applicazione può svolgere entrambi i ruoli: un Gateway può leggere come client il server di un PLC e offrire un proprio server a un sistema SCADA. Sono due interfacce, ciascuna con le proprie specifiche e prove. Un caso comune è un componente software che espone un server UA davanti a un vecchio server OPC DA; la guida alla migrazione da OPC DA lo descrive.
Verifica separatamente ogni servizio necessario al progetto: Browse, Read, Write, sottoscrizioni (monitored items), chiamate ai metodi e accesso ai dati storici. La lettura riuscita di un solo valore scalare dimostra soltanto che quella lettura funziona per quel nodo e quell’utente.
URL degli endpoint e sicurezza
L’URL di un endpoint, per esempio opc.tcp://plc-line-a.example:4840/UA/Process, identifica una connessione, non un valore. opc.tcp è il protocollo binario su TCP. La porta 4840 è quella che IANA registra per OPC UA su TCP, ma molti server ascoltano su un’altra porta, quindi copia l’URL indicato dal server. Ogni endpoint pubblica nel proprio EndpointDescription:
- una security policy, cioè l’insieme degli algoritmi;
- una modalità di sicurezza dei messaggi: None, Sign oppure SignAndEncrypt;
- i tipi di credenziali utente ammessi: accesso anonimo, nome utente e password oppure certificato.
Seguono due decisioni di attendibilità distinte. Il client e il server devono considerare attendibili i rispettivi certificati applicativi. Il server deve poi autorizzare l’utente. Considerare attendibile un certificato non autorizza l’utente; neppure una connessione TCP riuscita dimostra uno dei due aspetti. Registra l’endpoint, la policy e la modalità di sicurezza, l’identità dell’utente e dove ciascun certificato è considerato attendibile.
NodeId e namespace
Un NodeId identifica un nodo. La parte 3 della specifica (OPC 10000-3, 8.2) gli assegna tre elementi: un indice di namespace (un UInt16), un tipo di identificatore e l’identificatore. La parte 6 (OPC 10000-6, 5.1.12) definisce la forma testuale ns=<indice>;<tipo>=<identificatore>. I tipi di identificatore sono quattro:
| Tipo di identificatore | Prefisso | Esempio | Regole |
|---|---|---|---|
| Numerico | i= | ns=3;i=1001 | Un intero senza segno. I nodi definiti dalla OPC Foundation sono numerici: i=2258 è l’ora corrente del server |
| Stringa | s= | ns=2;s=LineA.Temperature | Fino a 4.096 caratteri, senza caratteri di controllo |
| GUID | g= | ns=4;g=09087e75-8e5e-499b-954f-f2a9603db28a | 32 cifre esadecimali nella forma 8-4-4-4-12 |
| Opaco | b= | ns=5;b=M/RbKBsRVkePCePcx24oRA== | Byte scritti in Base64, fino a 4.096 byte, in un formato definito dal server |
Il namespace 0 è il namespace OPC UA, http://opcfoundation.org/UA/, e i suoi NodeId si scrivono senza ns=, come i=2258. L’indice 1 è riservato al namespace locale del server (OPC 10000-5, 6.3.1). I namespace del modello informativo di un dispositivo o dei tag di un PLC partono dall’indice 2 o superiore. La parte 6 consente anche l’URI al posto dell’indice, come in nsu=urn:example:process-model;s=LineA.Temperature, ma client e strumenti meno recenti non accettano questa forma.
L’indice del namespace è una posizione nel NamespaceArray del server e ogni posizione contiene un URI di namespace. L’URI è il nome stabile. L’indice può cambiare quando cambiano configurazione o firmware del server. La parte 5 vieta a un server di modificare o eliminare voci mentre un client ha una sessione aperta e raccomanda di aggiungere soltanto voci nuove, ma ammette che una modifica possa essere inevitabile, quindi un client dovrebbe verificare gli indici quando avvia una sessione:
Registra l’URI del namespace con ogni NodeId nell’elenco dei punti. Dopo ogni modifica al server, controlla il NamespaceArray prima di fidarti dei vecchi indici.
Neppure il nome visualizzato e il percorso di navigazione sono NodeId. Usali per trovare il nodo, poi registra il suo NodeId.
Valore, stato e timestamp
Una lettura restituisce un DataValue, definito nella parte 4. Conservane tutti gli elementi:
| Campo | Significato |
|---|---|
| Value | Il valore, del tipo di dato del nodo: scalare, array o struttura |
| StatusCode | Good, Uncertain o Bad, con una motivazione |
| SourceTimestamp | Quando il valore è stato misurato o è cambiato alla sorgente, se il server lo sa |
| ServerTimestamp | Quando il server ha saputo per l’ultima volta che il valore era attuale |
Regole di utilizzo:
- Controlla prima lo stato. Un valore Bad non è una misura. Concorda una regola per Uncertain.
- Tieni distinti i due timestamp. Un valore stabile può mantenere un vecchio timestamp della sorgente mentre il server lo conferma più volte. «Nessuna variazione da un’ora» non equivale a «nessuna comunicazione da un’ora».
- Controlla il tipo di dato. Registra il tipo dichiarato e indica se si tratta di un array. Un contatore UInt64 è valido in OPC UA, ma può perdere precisione in software che memorizza i numeri come float a 64 bit.
- Sappi quale timestamp conserva il sistema di raccolta. Alcuni conservano quello della sorgente o del server; altri usano l’ora della propria lettura. La guida ai timestamp spiega la differenza.
Valida un punto, poi estendi
Per il primo punto, annota l’endpoint, le impostazioni di sicurezza, l’utente, l’URI del namespace, il NodeId, il tipo di dato, l’unità, l’eventuale fattore di scala e l’intervallo di lettura. Poi:
- Confronta il valore, mentre cambia, con un riferimento indipendente.
- Registra il codice di stato e i timestamp sul server, nel sistema di raccolta e alla destinazione finale.
- Ferma la sorgente o la connessione con l’approvazione del responsabile. I dati devono mostrare una lacuna o uno stato Bad o Uncertain, non un vecchio valore con un timestamp nuovo.
- Riavvia il sistema di raccolta e verifica che torni a leggere lo stesso nodo.
- Leggi un nodo inesistente e uno a cui l’utente non ha accesso. Entrambe le letture devono fallire in modo chiaro, non restituire il valore di un altro nodo.
Prova le scritture separatamente, con l’approvazione del responsabile dell’apparecchiatura e una verifica indipendente del risultato fisico.
OPC UA con Edge
Edge sul Gateway ZGW-20 è un client OPC UA. Si collega a un endpoint con la security policy e la modalità offerte dal server (None, Sign o SignAndEncrypt), come utente anonimo, con un nome utente o con un certificato. Legge ogni nodo variabile secondo una pianificazione, da una volta al secondo a una volta al giorno, e applica eventuali moltiplicatori e offset. Edge indirizza ogni nodo con la stringa completa del NodeId, fino a 512 caratteri, incluso l’indice del namespace. Copia il NodeId dallo spazio degli indirizzi del server, perché un nome di navigazione da solo non è un indirizzo, e controlla l’indice dopo ogni modifica al server. Ogni valore riceve un timestamp quando Edge lo legge.
Domande frequenti
Che cos’è un NodeId in OPC UA?
È l’identificatore di un nodo nello spazio degli indirizzi di un server. Contiene l’indice di un namespace e un identificatore, che può essere un numero, una stringa, un GUID o una sequenza di byte. Per esempio, ns=2;s=LineA.Temperature identifica la stringa LineA.Temperature nel namespace 2.
Che cos’è un namespace OPC UA?
È un insieme di identificatori di nodi denominato da un URI. Il server elenca i namespace nel proprio NamespaceArray e un NodeId fa riferimento a un namespace mediante la sua posizione in quell’array. L’URI è stabile; la posizione, cioè l’indice, può cambiare con la configurazione del server.
Qual è la differenza tra client e server OPC UA?
Il server possiede lo spazio degli indirizzi e offre servizi su di esso. Il client si collega e usa questi servizi per esplorare, leggere, scrivere o sottoscriversi. Un’applicazione può svolgere entrambi i ruoli: per esempio, un Gateway che legge come client il server di un PLC e offre un proprio server a un sistema SCADA.
Che cosa significa un codice di stato OPC UA?
Ogni valore restituito da un server ha un codice di stato: Good, Uncertain o Bad, con una motivazione. Un valore Bad non deve essere usato come misura. Per i valori Uncertain serve una regola concordata per il progetto.
Che cosa significa ns=2;s= in un NodeId OPC UA?
ns=2 è l’indice del namespace, la posizione 2 nel NamespaceArray del server. s= indica che l’identificatore che segue è una stringa. Gli altri tipi di identificatore sono i= per un numero, g= per un GUID e b= per byte opachi in Base64. Un NodeId nel namespace 0, come i=2258, si scrive senza ns=.
L’indice del namespace di un NodeId può cambiare?
Sì. OPC 10000-5 vieta a un server di modificare o eliminare le voci della tabella dei namespace mentre un client ha una sessione aperta e raccomanda ai server di aggiungere soltanto nuove voci. Ammette però che una modifica possa essere inevitabile, quindi un client dovrebbe verificare gli indici quando avvia una sessione. L’URI del namespace non cambia.