Passa al contenuto principale

Remote Plugin

warning

Per motivi tecnici il codice sorgente completo di questi esempi non può essere visualizzato qui.
Visitare il nostro repository GitHub per ulteriori esempi e il codice sorgente completo.

L'"optiMEAS Remote Plugin Module" è uno strumento altamente flessibile per il collegamento di applicazioni esterne al sistema smartCORE, basato su moderni protocolli di comunicazione e tecnologie. La comunicazione sottostante avviene tramite il protocollo UDP (User Datagram Protocol), noto per la sua bassa latenza e la sua efficienza, in particolare nelle applicazioni in tempo reale. Il modulo utilizza il formato MsgPack per la serializzazione e la deserializzazione efficienti dei dati, consentendo una trasmissione dei dati compatta e rapida. L'interfaccia per la comunicazione con il sistema smartCORE avviene tramite IPC (comunicazione interprocesso), e la configurazione dei canali producer e consumer può essere adattata individualmente. Ciò consente l'integrazione e il controllo di software esterno in tempo reale e supporta l'estensione flessibile dei sistemi esistenti. La documentazione mette a disposizione esempi dettagliati per facilitare lo sviluppo di plug-in propri, in modo da poter implementare in modo semplice ed efficiente requisiti specifici. Grazie all'impiego di queste tecnologie, il modulo offre una soluzione robusta e scalabile per la comunicazione tra smartCORE e processi esterni, ideale per applicazioni in ambienti industriali impegnativi.

Note sullo sviluppo di script:

  • Se si lavora su Windows, assicurarsi che gli script contengano solo \n e non \r\n

Tutorial​

Sviluppo su PC esterno
Semplice plug-in per la scrittura di dati
Plug-in per la lettura e la scrittura di dati
[Avanzato] Installazione di nuove librerie Python (ad es. NumPy)

Configurazione JSON​

Configurazione dei parametri di rete​

Parola chiaveSpiegazione
portPorta UDP su cui il plug-in è in ascolto (default: 61616)
localhostLimitazione alla comunicazione "solo localhost" (default: true)

Configurazione del controllo dei processi​

NomeSpiegazione
enableStabilisce se il processo deve essere avviato e monitorato (default: false)
logOutputRiporta l'output (stdout e stderr) del processo nel file di log di smartCORE (default: true)
watchdogTimeoutTempo massimo tra 2 messaggi IPC prima del RESTART del processo
disableKillAllProcessesDisattiva la terminazione di tutti i processi all'avvio o in caso di problemi (default: false)
commandNome (con percorso opzionale) del processo
argumentsArgomenti della riga di comando per il processo

Configurazione dei Producer Channel ( producerChannels )​

Parola chiaveSpiegazione
nameNome del canale
dataTypeTipo di dati del canale
physicalUnitUnità del canale

Configurazione dei Consumer Channel ( consumerChannels )​

Parola chiaveSpiegazione
nameNome del canale che deve essere letto

Configurazione di esempio​

{
"module": "remote",
"factory": "remote",
"config": {
"port": 61616,
"localhost": true,
"process":
{
"enable": true,
"logOutput": false,
"watchdogTimeout": 60,
"disableKillAllProcesses": false,
"command": "i2c-sen5x-cpp",
"arguments": "--device-path=/dev/i2c-1 --interval=1"
},
"producerChannels": [
{
"name": "sen5x_pm1p0",
"dataType": "float",
"physicalUnit": "ug/m^3"
},
{
"name": "sen5x_pm2p5",
"dataType": "float",
"physicalUnit": "ug/m^3"
}
],
"consumerChannels": [
{
"name": "scd40_co2"
}
]
}
}

API/Protocollo​

Il protocollo è costituito da un header in gran parte statico, in cui viene specificato un codice di comando, e (se necessario) da un payload JSON.

Metadati dell'header​

Offset e tipo di datiNomeDescrizione
[0] uint32_tmagicTokenRiconoscimento del protocollo (fisso 0x45554C42)
[4] uint8_tversionVersione del protocollo (attualmente sempre 1; aperta a estensioni)
[5] uint8_tpayloadTypeSupporto e distinzione di diversi tipi di payload (qui attualmente sempre 2)
[6] uint16_treservedRiservato per estensioni future (la dimensione dell'header deve essere divisibile per 4)
[8] uint64_tsenderPidID di processo del processo mittente
[16] uint64_tsenderTime_msSEIstante in millisecondi in cui il pacchetto è stato inviato (a scopo diagnostico)
[24] uint16_tgroupIdentificativo del servizio a cui era diretta la chiamata RPC o da cui proviene la risposta (qui fisso 1000)
[26] uint16_tcommandNumero della chiamata RPC (vedere la tabella seguente)

Comandi​

N. comandoDenominazioneSpiegazione
0LifeSignRequestInterrogazione dello stato di smartCORE
1LifeSignResponseRisposta a LifeSignRequest
100WriteSamplesByNameInvio di singoli campioni con nome del canale
101ReadSamplesByNameRequestInterrogazione di singoli canali tramite nome del canale
102ReadSamplesByNameResponseRisposta a ReadSamplesByNameRequest (valori misurati)
200ChannelListRequestInterrogazione dell'elenco dei canali (associazione nome del canale => indice)
201ChannelListResponseRisposta a ChannelListRequest (elenco dei canali)
202WriteSamplesRequestInvio di campioni (opzionalmente con timestamp) tramite indice
203WriteSamplesResponseRisposta opzionale a WriteSamplesRequest se è stato passato un token di conferma
204ReadSamplesBeginAttivazione dell'invio ciclico dei valori misurati da parte di smartCORE
205ReadSamplesContentValori misurati dell'invio ciclico
206ReadSamplesEndDisattivazione dell'invio ciclico
300AlarmMessageRequestScrittura di un allarme nella centrale allarmi di smartCORE
301AlarmMessageResponseConferma di AlarmMessageRequest

Struttura del payload (contenuto JSON)​

Comandi byName​

Scrittura di valori in smartCORE​

RPC: WriteSamplesByName (Client => smartCORE)

ParametroDescrizione
cArray dei canali
nNome del canale
vValore misurato
tTimestamp (opzionale)
{
"c": [
{
"n": "sen5x_pm1p0",
"v": 1.0099999904632568,
"t": 1720074467000000
},
{
"n": "sen5x_pm2p5",
"v": 2.009999990463257,
"t": 1720074467000000
}
]
}
Lettura di valori da smartCORE (polling)​

RPC: ReadSamplesByNameRequest (Client => smartCORE)

ParametroDescrizione
cArray dei nomi dei canali
{
"c": [
"sen5x_pm1p0",
"sen5x_pm2p5"
]
}

RPC: ReadSamplesByNameResponse (smartCORE => Client)

ParametroDescrizione
cArray dei canali
nNome del canale
vValore misurato
tTimestamp
{
"c": [
{
"n": "sen5x_pm1p0",
"v": 1.0099999904632568,
"t": 1720074467000000
},
{
"n": "sen5x_pm2p5",
"v": 2.009999990463257,
"t": 1720074467000000
}
]
}

Comandi byIndex​

Interrogazione dell'elenco dei canali​

RPC: ChannelListRequest (Client => smartCORE)

Qui è possibile inviare una richiesta vuota per interrogare i nomi di tutti i canali. In alternativa è possibile richiedere anche solo i nomi di canali selezionati:

ParametroDescrizione
cArray dei nomi dei canali
fRichiesta di campi speciali, ad es. "d" (tipo di dati) [opzionale]
{
"f": [
"d"
],
"c": [
"sen5x_pm1p0",
"sen5x_pm2p5"
]
}

RPC: ChannelListResponse (smartCORE => Client)

ParametroDescrizione
cArray dei canali
nNome del canale
iIndice del canale
wScrivibile (canale producer) [assente se false]
dTipo di dati (opzionale; se richiesto)
{
"c": [
{
"n": "sen5x_pm1p0",
"i": 0,
"w": true,
"d": "float"
},
{
"n": "sen5x_pm2p5",
"i": 1,
"d": "int32"
}
]
}
Scrittura di valori in smartCORE​

RPC: WriteSamplesRequest (Client => smartCORE)

Qui sono possibili tre payload:

  • singoli campioni per canale
  • più campioni con timestamp per canale
  • campioni equidistanti per canale
ParametroDescrizione
aToken per ricevere un pacchetto di acknowledge (opzionale)
cArray dei canali
iIndice del canale
vValore misurato
tTimestamp (opzionale)
sDifferenza di tempo per campioni equidistanti

Payload variante 1: singoli campioni per canale

{
"a": "xyz",
"t": 1720074467000000,
"c": [
{
"i": 0,
"v": 1.0099999904632568,
"t": 1720074467000000
},
{
"i": 1,
"v": 2.009999990463257,
}
]
}

Payload variante 2: più campioni con timestamp per canale

{
"a": "xyz",
"c": [
{
"i": 0,
"v": [
1,
2,
3
],
"t": [
1720074467000000,
1720074467000100,
1720074467000200
]
},
{
"i": 1,
"v": [
1,
2,
3
],
"t": 1720074467000000,
"s": 200
}
]
}

Payload variante 3: campioni equidistanti per canale

{
"a": "xyz",
"t": 1720074467000000,
"s": 200,
"c": [
{
"i": 0,
"v": [
1,
2,
3
],
"t": 1720074467000000,
"s": 200
},
{
"i": 1,
"v": [
1,
2,
3
]
}
]
}

RPC: WriteSamplesResponse (smartCORE => Client)

Se nel pacchetto di richiesta è stato indicato un token, smartCORE invia un pacchetto con il token come conferma.

ParametroDescrizione
aToken dal pacchetto di richiesta
{
"a": "xyz"
}
Lettura continua di valori da smartCORE​

RPC: ReadSamplesBegin (Client => smartCORE)

ParametroDescrizione
tTempo in millisecondi tra due pacchetti (intervallo di invio)
nNumero di campioni desiderato (numero di intervalli di consumo identici per intervallo di invio)
eEquidistante (senza trasmissione dei timestamp)
cElenco degli indici dei canali
{
"t": 100,
"n": 10,
"e": true,
"c": [
2,
5
]
}

RPC: ReadSamplesContent (smartCORE => Client)

ParametroDescrizione
xindice progressivo del pacchetto dall'inizio (ad es. per rilevare la perdita di dati)
cArray dei canali
iIndice del canale
vValore misurato
tTimestamp

Note:

  • Se sono disponibili meno campioni del numero desiderato, vengono trasmessi solo i campioni disponibili.
  • Se non è disponibile alcun campione aggiornato, viene inviato solo l'"Last Value".

Payload variante 1: con timestamp ( e = "false")

{
"x": 123,
"c": [
{
"i": 2,
"v": [
1.0099999904632568,
5.009999990463257,
6.009999990463257
],
"t": [
1720074467000000,
1720074467000100,
1720074467000200
]
},
{
"i": 5,
"v": [
1.0099999904632568,
5.009999990463257,
6.009999990463257
],
"t": [
1720074467000000,
1720074467000100,
1720074467000200
]
}
]
}

Payload variante 2: senza timestamp ( e = "true")

{
"x": 123,
"t": 1720074467000000,
"s": 100,
"c": [
{
"i": 2,
"v": [
1.0099999904632568,
5.0099999904632568,
6.0099999904632568
]
},
{
"i": 5,
"v": [
1.0099999904632568,
5.0099999904632568,
6.0099999904632568
]
}
]
}

RPC: ReadSamplesEnd (Client => smartCORE)

Richiesta vuota per disattivare la trasmissione.