Aller au contenu principal

Remote Plugin

attention

Pour des raisons techniques, le code source complet de ces exemples ne peut pas être affiché ici.
Veuillez consulter notre dépôt Github pour d'autres exemples et le code source complet.

Le « optiMEAS Remote Plugin Module » est un outil très flexible pour connecter des applications externes au système smartCORE, basé sur des protocoles de communication et des technologies modernes. La communication sous-jacente s'effectue via le protocole UDP (User Datagram Protocol), connu pour sa faible latence et son efficacité, en particulier dans les applications temps réel. Le module utilise le format MsgPack pour la sérialisation et la désérialisation efficaces des données, ce qui permet une transmission de données compacte et rapide. L'interface de communication avec le système smartCORE passe par l'IPC (communication inter-processus), la configuration des canaux producteurs et consommateurs pouvant être adaptée individuellement. Cela permet l'intégration et la commande de logiciels externes en temps réel et soutient l'extension flexible de systèmes existants. La documentation fournit des exemples détaillés pour faciliter le développement de vos propres plug-ins, de sorte que des exigences spécifiques peuvent être mises en œuvre simplement et efficacement. Grâce à ces technologies, le module offre une solution robuste et évolutive pour la communication entre smartCORE et des processus externes, idéale pour les applications dans des environnements industriels exigeants.

Remarques sur le développement de scripts :

  • Si vous travaillez sous Windows, assurez-vous que les scripts ne contiennent que \n, et non \r\n

Tutoriels​

Développement sur un PC externe
Plug-in simple d'écriture de données
Plug-in de lecture et d'écriture de données
[Avancé] Installation de nouvelles bibliothèques Python (par ex. NumPy)

Configuration JSON​

Configuration des paramètres réseau​

Mot-cléExplication
portPort UDP sur lequel le plug-in écoute (par défaut : 61616)
localhostRestriction à la communication « localhost only » (par défaut : true)

Configuration de la commande de processus​

NomExplication
enableDétermine si le processus doit être démarré et surveillé (par défaut : false)
logOutputReprendre la sortie (stdout & stderr) du processus dans le fichier journal smartCORE (par défaut : true)
watchdogTimeoutTemps maximal entre 2 messages IPC avant le RESTART du processus
disableKillAllProcessesDésactive l'arrêt forcé de tous les processus au démarrage ou en cas de problème (par défaut : false)
commandNom (avec chemin facultatif) du processus
argumentsArguments de ligne de commande du processus

Configuration des Producer Channels ( producerChannels )​

Mot-cléExplication
nameNom du canal
dataTypeType de données du canal
physicalUnitUnité du canal

Configuration des Consumer Channels ( consumerChannels )​

Mot-cléExplication
nameNom du canal à lire

Exemple de configuration​

{
"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/Protocole​

Le protocole se compose d'un en-tête en grande partie statique, dans lequel un code de commande est spécifié, et (si nécessaire) d'une charge utile JSON.

En-tête​

Métadonnées de l'en-tête​

Offset et type de donnéesNomDescription
[0] uint32_tmagicTokenIdentification du protocole (fixe 0x45554C42)
[4] uint8_tversionVersion du protocole (actuellement toujours 1 ; ouvert aux extensions)
[5] uint8_tpayloadTypePrise en charge et distinction de différents types de charge utile (ici actuellement toujours 2)
[6] uint16_treservedRéservé à de futures extensions (la taille de l'en-tête doit être divisible par 4)
[8] uint64_tsenderPidID du processus émetteur
[16] uint64_tsenderTime_msSEInstant, en millisecondes, où le paquet a été envoyé (à des fins de diagnostic)
[24] uint16_tgroupIdentifiant du service auquel l'appel RPC était destiné ou dont provient la réponse (ici fixe 1000)
[26] uint16_tcommandNuméro de l'appel RPC (voir le tableau suivant)

Commandes​

N° de commandeDésignationExplication
0LifeSignRequestInterrogation de l'état de smartCORE
1LifeSignResponseRéponse à LifeSignRequest
100WriteSamplesByNameEnvoi d'échantillons individuels avec le nom du canal
101ReadSamplesByNameRequestInterrogation de canaux individuels via les noms de canaux
102ReadSamplesByNameResponseRéponse à ReadSamplesByNameRequest (valeurs mesurées)
200ChannelListRequestInterrogation de la liste des canaux (correspondance nom de canal => index)
201ChannelListResponseRéponse à ChannelListRequest (liste des canaux)
202WriteSamplesRequestEnvoi d'échantillons (avec horodatage facultatif) via l'index
203WriteSamplesResponseRéponse facultative à WriteSamplesRequest si un jeton de confirmation a été transmis
204ReadSamplesBeginActivation de l'envoi cyclique de valeurs mesurées par smartCORE
205ReadSamplesContentValeurs mesurées de l'envoi cyclique
206ReadSamplesEndDésactivation de l'envoi cyclique
300AlarmMessageRequestÉcriture d'une alarme dans la centrale d'alarmes smartCORE
301AlarmMessageResponseConfirmation de AlarmMessageRequest

Structure de la charge utile (contenu JSON)​

Commandes byName​

Écriture de valeurs dans smartCORE​

RPC : WriteSamplesByName (client => smartCORE)

ParamètreDescription
cTableau des canaux
nNom du canal
vValeur mesurée
tHorodatage (facultatif)
{
"c": [
{
"n": "sen5x_pm1p0",
"v": 1.0099999904632568,
"t": 1720074467000000
},
{
"n": "sen5x_pm2p5",
"v": 2.009999990463257,
"t": 1720074467000000
}
]
}
Lecture de valeurs depuis smartCORE (polling)​

RPC : ReadSamplesByNameRequest (client => smartCORE)

ParamètreDescription
cTableau des noms de canaux
{
"c": [
"sen5x_pm1p0",
"sen5x_pm2p5"
]
}

RPC : ReadSamplesByNameResponse (smartCORE => client)

ParamètreDescription
cTableau des canaux
nNom du canal
vValeur mesurée
tHorodatage
{
"c": [
{
"n": "sen5x_pm1p0",
"v": 1.0099999904632568,
"t": 1720074467000000
},
{
"n": "sen5x_pm2p5",
"v": 2.009999990463257,
"t": 1720074467000000
}
]
}

Commandes byIndex​

Interrogation de la liste des canaux​

RPC : ChannelListRequest (client => smartCORE)

Une requête vide peut ici être envoyée pour demander les noms de tous les canaux. Il est également possible de ne demander que des noms de canaux sélectionnés :

ParamètreDescription
cTableau des noms de canaux
fDemande de champs spéciaux, par ex. "d" (type de données) [facultatif]
{
"f": [
"d"
],
"c": [
"sen5x_pm1p0",
"sen5x_pm2p5"
]
}

RPC : ChannelListResponse (smartCORE => client)

ParamètreDescription
cTableau des canaux
nNom du canal
iIndex du canal
wInscriptible (canal producteur) [absent si false]
dType de données (facultatif ; si demandé)
{
"c": [
{
"n": "sen5x_pm1p0",
"i": 0,
"w": true,
"d": "float"
},
{
"n": "sen5x_pm2p5",
"i": 1,
"d": "int32"
}
]
}
Écriture de valeurs dans smartCORE​

RPC : WriteSamplesRequest (client => smartCORE)

Trois charges utiles sont ici possibles :

  • échantillons individuels par canal
  • plusieurs échantillons avec horodatage par canal
  • échantillons équidistants par canal
ParamètreDescription
aJeton pour recevoir un paquet d'acquittement (facultatif)
cTableau des canaux
iIndex du canal
vValeur mesurée
tHorodatage (facultatif)
sDifférence de temps pour les échantillons équidistants

Variante de charge utile 1 : échantillons individuels par canal

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

Variante de charge utile 2 : plusieurs échantillons avec horodatage par canal

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

Variante de charge utile 3 : échantillons équidistants par canal

{
"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)

Si un jeton a été indiqué dans le paquet de requête, smartCORE envoie un paquet contenant le jeton à titre de confirmation.

ParamètreDescription
aJeton du paquet de requête
{
"a": "xyz"
}
Lecture continue de valeurs depuis smartCORE​

RPC : ReadSamplesBegin (client => smartCORE)

ParamètreDescription
tTemps en millisecondes entre deux paquets (intervalle d'envoi)
nNombre d'échantillons souhaité (nombre d'intervalles de consommation identiques par intervalle d'envoi)
eÉquidistant (sans transmission des horodatages)
cListe des index de canaux
{
"t": 100,
"n": 10,
"e": true,
"c": [
2,
5
]
}

RPC : ReadSamplesContent (smartCORE => client)

ParamètreDescription
xIndex de paquet continu depuis le début (par ex. pour détecter une perte de données)
cTableau des canaux
iIndex du canal
vValeur mesurée
tHorodatage

Remarques :

  • Si moins d'échantillons que le nombre souhaité sont disponibles, seuls les échantillons disponibles sont transmis.
  • Si aucun échantillon actuel n'est disponible, seule la « Last Value » est envoyée.

Variante de charge utile 1 : avec horodatage ( 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
]
}
]
}

Variante de charge utile 2 : sans horodatage ( 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)

Requête vide pour désactiver la transmission.