a nodejs opcua server interfacerobertomana.altervista.org/wp-content/uploads/2019/08/...async http...

5
Gestione Progetto robertomana.it A nodejs OPCUA SERVER Interface pag 1 A nodejs OPCUA SERVER Interface Rev Digitale 1.1 del 01/09/2019 Il codice che segue è stato scritto da Etienne Erossignon sed è disponibile su github all’indirizzo https://github.com/node-opcua/node-opcua http://documentation.unified-automation.com/uasdkdotnet/2.4.2/html/group__NetUaClientSdk.html Richiede le seguenti dipendenze: express node-opcua async http socket.io Scrittura di un client node.js Il client, avviata l’applicazione, mediante il metodo async.series([tasks], callback) esegue in sequenza i seguenti 5 task: 1) Connessione al server var client = new opcua.OPCUAClient(); client.connect(endpointUrl,function (err) { }); 2) Crezione di una sessione di lavoro. Una connessione può gestire più sessioni di lavoro var the_session = client.createSession( function(err) { }); 3) Eventuale Visualizzazione dei nodi esistenti the_session.browse("RootFolder", function(err){ Viusalizza sul Log i nodi di primo livello appesi a RootFolder : Objects, Types, News } 4) Creazione di una Subscription. Una sessione di lavoro può gestire più Subscription. Per la lettura continua delle variabili, OPC UA utilizza una funzionalità molto più efficace rispetto al vecchio polling, la cosiddetta Subscription. Un client OPC UA può definire un insieme di variabili e chiedere al server di essere lui a monitorare queste variabili. In caso di variazione del valore di queste variabili, sarà il server a notificare al client questa variazione tramite apposito messaggio. In questo modo si ottiene una fortissima riduzione nello scambio dei messaggi a vantaggio di una maggiore velocità. Una Subscription deve contenere almeno una variabile detta Monitored Item, ma può raggruppare anche più variabili anche di tipo differente, creando una porzione di informazione detta Notification. Una Notification quindi può contenere più Monitored Items che verranno inviati al client tutti insieme in un unico messaggio. Quando il client imposta una Subscription deve impostare alcuni parametri:

Upload: others

Post on 14-Aug-2020

14 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: A nodejs OPCUA SERVER Interfacerobertomana.altervista.org/wp-content/uploads/2019/08/...async http socket.io Scrittura di un client node.js Il client, avviata l’applicazione, mediante

Gestione Progetto robertomana.it

A nodejs OPCUA SERVER Interface

pag 1

A nodejs OPCUA SERVER Interface

Rev Digitale 1.1 del 01/09/2019

Il codice che segue è stato scritto da Etienne Erossignon sed è disponibile su github all’indirizzo https://github.com/node-opcua/node-opcua http://documentation.unified-automation.com/uasdkdotnet/2.4.2/html/group__NetUaClientSdk.html

Richiede le seguenti dipendenze: express

node-opcua

async

http

socket.io

Scrittura di un client node.js

Il client, avviata l’applicazione, mediante il metodo async.series([tasks], callback) esegue in sequenza i seguenti 5 task: 1) Connessione al server

var client = new opcua.OPCUAClient();

client.connect(endpointUrl,function (err) { });

2) Crezione di una sessione di lavoro. Una connessione può gestire più sessioni di lavoro

var the_session = client.createSession( function(err) { });

3) Eventuale Visualizzazione dei nodi esistenti

the_session.browse("RootFolder", function(err){

Viusalizza sul Log i nodi di primo livello appesi a RootFolder :

Objects, Types, News

}

4) Creazione di una Subscription. Una sessione di lavoro può gestire più Subscription.

Per la lettura continua delle variabili, OPC UA utilizza una funzionalità molto più efficace rispetto al vecchio polling, la cosiddetta Subscription. Un client OPC UA può definire un insieme di variabili e chiedere al server di essere lui a monitorare queste variabili. In caso di variazione del valore di queste variabili, sarà il server a notificare al client questa variazione tramite apposito messaggio. In questo modo si ottiene una fortissima riduzione nello scambio dei messaggi a vantaggio di una maggiore velocità.

Una Subscription deve contenere almeno una variabile detta Monitored Item, ma può raggruppare anche più variabili anche di tipo differente, creando una porzione di informazione detta Notification. Una Notification quindi può contenere più Monitored Items che verranno inviati al client tutti insieme in un unico messaggio.

Quando il client imposta una Subscription deve impostare alcuni parametri:

Page 2: A nodejs OPCUA SERVER Interfacerobertomana.altervista.org/wp-content/uploads/2019/08/...async http socket.io Scrittura di un client node.js Il client, avviata l’applicazione, mediante

Gestione Progetto robertomana.it

A nodejs OPCUA SERVER Interface

pag 2

Il samplingInterval definisce, individualmente per ogni singolo Monitored Item, il tempo di campionamento utilizzato dal server per valutare eventuali variazioni sulla variabile

Il publishingInterval definisce invece l’intervallo di tempo (regolare) entro cui il server, in caso di variazioni, invia al client la Notification completa. In pratica si può chiedere al server di eseguire sulla variabile un campionamento abbastanza rapido. Se in corrispondenza del campionamento il server intercetta una variazione, memorizza il nuovo valore all’interno di una coda. Allo scadere del publishingInterval invia al client l’intera coda relativa anche a variabili multiple (sempre che la coda non sia vuota). In questo modo il client può intercettare (e, ad esempio, memorizzare in un database) anche variazioni molto rapide che diversamente andrebbero perse. Il valore di default è 1000 msec.

queueSize definisce, individualmente per ogni singolo Monitored Item, la dimensione della coda sul server entro la quale memorizzare le variazioni intermedie della variabile stessa. Maggiore è la differenza fra il samplingInterval ed il publishingInterval, maggiore dovrà essere la dimensione della queueSize. Quando i dati vengono inviati al client (publish) la coda viene svuotata. Se la dimensione

della queue size non è sufficiente, in corrispondenza di un nuovo valore il valore più vecchio viene rimosso (discardOldest: true).

keepAliveCount Se allo scadere del publishingInterval la coda è vuota, il server non invia nulla. Il keepAliveCount indica quanti invii possono essere tralasciati, prima che una “empty

notification” venga inviata comunque. Questa “empty notification” server per avvisare il client che il server è sempre attivo anche se non ha dati da segnalare

lifetimeCount Anche il server ha bisogno di sapere se il client è ancora attivo. lifetimeCount indica il numero di publishingInterval con cui il client invia al server una publishRequest per segnalare al server che è ancora attivo. Se il server non riceve questo messaggio rimuove la Subscription e cessa di inviare Notifiche al client. Si consiglia per questo parametro di impostare un valore grande almeno 3 volte il keep alive count.

publishingEnabled Flag che indica se la pubblicazione è abilitata o meno. Il client può decidere in certe fasi di disabilitare temporaneamente la pubblicazione del server.

priority Quando più Subscriptions necessitano di inviare contemporaneamente una notifica al client,

viene servita prima la Subcription con priority maggiore. Il valore di default è 1. Sono ammessi valori tra 1 e 100.

maxNotificationsPerPublish indica il numero massimo di notifiche (subscription) che il server può inviare al client in corrispondenza del messaggio di publishing. È deciso dal client, ma il server può inviarne un numero massimo minore in base al proprio limite stabilito. Se non tutte le notifiche disponibili possono essere inviate in un unico messaggio, verranno inviati più messaggi.

All’interno della funzione 4 di creazione della Subscription vengono eseguite diverse azioni:

a. Creazione della subscription

var the_subscription=new opcua.ClientSubscription(the_session, {params})

params è un object contenente le impostazioni sopra descritte relative al client

b. Richiamo della callback in corrispondenza della terminazione

the_subscription.on("started",function(){

console.log("Subscription Started - Id=",the_subscription.subscriptionId)

});

the_subscription.on ("terminated",function(){

callback();

});

Page 3: A nodejs OPCUA SERVER Interfacerobertomana.altervista.org/wp-content/uploads/2019/08/...async http socket.io Scrittura di un client node.js Il client, avviata l’applicazione, mediante

Gestione Progetto robertomana.it

A nodejs OPCUA SERVER Interface

pag 3

Come s può vedere la funzione di callback viene richiamata soltanto in corrispondenza dell’evento “terminated” della Subscription, cioè nel momento in cui qualcuno termina esplicitamente la Subscription. Non richiamando la funzione di callback, async.series rimane bloccata e non esegue mai la callback finale.

c. Eventuale impostazione esplicita della termianzione

La terminazione della Subscription può essere eseguita in corrispondenza di un certo pulsante dell’interfaccia grafica oppure dopo un certo tempo (es 60 sec).

setTimeout(function(){

the_subscription.terminate();

},60000);

d. Creazione dei monitored items

Questo è il passo centrale di tutto il codice; quello in cui, tramite il metodo monitor, viene definita la variabile da monitorare e, al contempo, viene avviata la monitorizzazione:

var monitoredItem = the_subscription.monitor(

{

nodeId: opcua.resolveNodeId("ns=4;s=tappe"),

attributeId: opcua.AttributeIds.Value

},

{

// Server parameters

samplingInterval: 100,

queueSize: 10,

discardOldest: true

},

opcua.read_service.TimestampsToReturn.Both

);

Il metodo .monitor dell’oggetto Subscription si aspetta 3 parametri:

Il primo parametro è un object contenente due informazioni: il nodeID del nodo da monitorare (espresso come stringa) e che cosa si vuole monitorare di quel nodo, tipicamente il suo value (attribute Id=13). tappe in pratica è il nome della variabile da monitorare.

Il secondo parametro è un oggetto contenete i Server Parameters relativi a questa singola variabile. Per ogni variabile si possono impostare i suoi Server Parameters

Il terzo parametro opcua.read_service.TimestampsToReturn.Both fa sì che il server ritorni anche i due TimeStamps (sourceTimeStamp e serverTimeStamp) relativi a data e ora della lettura. Il valore di default è none, che andrebbe benissimo, per cui questa riga potrebbe tranquillamente essere eliminata. Per maggiori dettagli si rimanda al seguente link https://readthedocs.web.cern.ch/display/ICKB/OPC-UA+time-stamps+on+WinnCC+OA

e. Lettura dei valori

monitoredItem.on("changed",function(dataValue){

tappe = dataValue.value.value;

console.log("VALORE = ", tappe);

});

Evento richiamato in corrispondenza di ogni variazione della variabile. Il valore letto viene salvato nella variabile globale tappe.

Page 4: A nodejs OPCUA SERVER Interfacerobertomana.altervista.org/wp-content/uploads/2019/08/...async http socket.io Scrittura di un client node.js Il client, avviata l’applicazione, mediante

Gestione Progetto robertomana.it

A nodejs OPCUA SERVER Interface

pag 4

5) Chiusura della sessione di lavoro. La 5° funzione di async.series (che si avvia soltanto nel momento in cui viene terminata la Subscription) si limita a chiudere la sessione di lavoro:

the_session.close(function(err) { });

Schermata di funzionamento :

Page 5: A nodejs OPCUA SERVER Interfacerobertomana.altervista.org/wp-content/uploads/2019/08/...async http socket.io Scrittura di un client node.js Il client, avviata l’applicazione, mediante

Gestione Progetto robertomana.it

A nodejs OPCUA SERVER Interface

pag 5

Scrittura di una variabile da nodejs verso l’OPC UA SERVER

Il seguente codice è decisamente auto esplicativo:

app.get('/set', function (req, res) {

var vet = new Array(32);

for (var i=0; i<32; i++)

vet[i]=false;

vet[8]=true; // M1.0

vet[24]=true; // M3.0

var dataToWrite = {

dataType: "Boolean",

value: vet

};

the_session.writeSingleNode("ns=4;s=uscite", dataToWrite,

function(err, statusCode, diagnosticInfo) {

if (!err) {

console.log(" write ok" );

res.send('OK');

//console.log(diagnosticInfo);

//console.log(statusCode);

}

else {

console.log("Errore :" + err );

res.send('NOK');

}

});

});