Remote Plugin
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 |
|---|---|
| port | Port UDP sur lequel le plug-in écoute (par défaut : 61616) |
| localhost | Restriction à la communication « localhost only » (par défaut : true) |
Configuration de la commande de processus
| Nom | Explication |
|---|---|
| enable | Détermine si le processus doit être démarré et surveillé (par défaut : false) |
| logOutput | Reprendre la sortie (stdout & stderr) du processus dans le fichier journal smartCORE (par défaut : true) |
| watchdogTimeout | Temps maximal entre 2 messages IPC avant le RESTART du processus |
| disableKillAllProcesses | Désactive l'arrêt forcé de tous les processus au démarrage ou en cas de problème (par défaut : false) |
| command | Nom (avec chemin facultatif) du processus |
| arguments | Arguments de ligne de commande du processus |
Configuration des Producer Channels ( producerChannels )
| Mot-clé | Explication |
|---|---|
| name | Nom du canal |
| dataType | Type de données du canal |
| physicalUnit | Unité du canal |
Configuration des Consumer Channels ( consumerChannels )
| Mot-clé | Explication |
|---|---|
| name | Nom 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ées | Nom | Description |
|---|---|---|
| [0] uint32_t | magicToken | Identification du protocole (fixe 0x45554C42) |
| [4] uint8_t | version | Version du protocole (actuellement toujours 1 ; ouvert aux extensions) |
| [5] uint8_t | payloadType | Prise en charge et distinction de différents types de charge utile (ici actuellement toujours 2) |
| [6] uint16_t | reserved | Réservé à de futures extensions (la taille de l'en-tête doit être divisible par 4) |
| [8] uint64_t | senderPid | ID du processus émetteur |
| [16] uint64_t | senderTime_msSE | Instant, en millisecondes, où le paquet a été envoyé (à des fins de diagnostic) |
| [24] uint16_t | group | Identifiant du service auquel l'appel RPC était destiné ou dont provient la réponse (ici fixe 1000) |
| [26] uint16_t | command | Numéro de l'appel RPC (voir le tableau suivant) |
Commandes
| N° de commande | Désignation | Explication |
|---|---|---|
| 0 | LifeSignRequest | Interrogation de l'état de smartCORE |
| 1 | LifeSignResponse | Réponse à LifeSignRequest |
| 100 | WriteSamplesByName | Envoi d'échantillons individuels avec le nom du canal |
| 101 | ReadSamplesByNameRequest | Interrogation de canaux individuels via les noms de canaux |
| 102 | ReadSamplesByNameResponse | Réponse à ReadSamplesByNameRequest (valeurs mesurées) |
| 200 | ChannelListRequest | Interrogation de la liste des canaux (correspondance nom de canal => index) |
| 201 | ChannelListResponse | Réponse à ChannelListRequest (liste des canaux) |
| 202 | WriteSamplesRequest | Envoi d'échantillons (avec horodatage facultatif) via l'index |
| 203 | WriteSamplesResponse | Réponse facultative à WriteSamplesRequest si un jeton de confirmation a été transmis |
| 204 | ReadSamplesBegin | Activation de l'envoi cyclique de valeurs mesurées par smartCORE |
| 205 | ReadSamplesContent | Valeurs mesurées de l'envoi cyclique |
| 206 | ReadSamplesEnd | Désactivation de l'envoi cyclique |
| 300 | AlarmMessageRequest | Écriture d'une alarme dans la centrale d'alarmes smartCORE |
| 301 | AlarmMessageResponse | Confirmation de AlarmMessageRequest |
Structure de la charge utile (contenu JSON)
Commandes byName
Écriture de valeurs dans smartCORE
RPC : WriteSamplesByName (client => smartCORE)
| Paramètre | Description |
|---|---|
| c | Tableau des canaux |
| n | Nom du canal |
| v | Valeur mesurée |
| t | Horodatage (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ètre | Description |
|---|---|
| c | Tableau des noms de canaux |
{
"c": [
"sen5x_pm1p0",
"sen5x_pm2p5"
]
}
RPC : ReadSamplesByNameResponse (smartCORE => client)
| Paramètre | Description |
|---|---|
| c | Tableau des canaux |
| n | Nom du canal |
| v | Valeur mesurée |
| t | Horodatage |
{
"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ètre | Description |
|---|---|
| c | Tableau des noms de canaux |
| f | Demande de champs spéciaux, par ex. "d" (type de données) [facultatif] |
{
"f": [
"d"
],
"c": [
"sen5x_pm1p0",
"sen5x_pm2p5"
]
}
RPC : ChannelListResponse (smartCORE => client)
| Paramètre | Description |
|---|---|
| c | Tableau des canaux |
| n | Nom du canal |
| i | Index du canal |
| w | Inscriptible (canal producteur) [absent si false] |
| d | Type 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ètre | Description |
|---|---|
| a | Jeton pour recevoir un paquet d'acquittement (facultatif) |
| c | Tableau des canaux |
| i | Index du canal |
| v | Valeur mesurée |
| t | Horodatage (facultatif) |
| s | Diffé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ètre | Description |
|---|---|
| a | Jeton du paquet de requête |
{
"a": "xyz"
}
Lecture continue de valeurs depuis smartCORE
RPC : ReadSamplesBegin (client => smartCORE)
| Paramètre | Description |
|---|---|
| t | Temps en millisecondes entre deux paquets (intervalle d'envoi) |
| n | Nombre d'échantillons souhaité (nombre d'intervalles de consommation identiques par intervalle d'envoi) |
| e | Équidistant (sans transmission des horodatages) |
| c | Liste des index de canaux |
{
"t": 100,
"n": 10,
"e": true,
"c": [
2,
5
]
}
RPC : ReadSamplesContent (smartCORE => client)
| Paramètre | Description |
|---|---|
| x | Index de paquet continu depuis le début (par ex. pour détecter une perte de données) |
| c | Tableau des canaux |
| i | Index du canal |
| v | Valeur mesurée |
| t | Horodatage |
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.