Remote Plugin
Aus technischen Gründen kann der vollständige Quellcode dieser Beispiele nicht hier angezeigt werden.
Bitte besuchen Sie unser Github Repository für weitere Beispiele und vollständigen Quellcode.
Das "optiMEAS Remote Plugin Module" ist ein hochflexibles Werkzeug zur Anbindung externer Anwendungen an das smartCORE-System, basierend auf modernen Kommunikationsprotokollen und Technologien. Die zugrunde liegende Kommunikation erfolgt über das UDP-Protokoll (User Datagram Protocol), das für seine niedrige Latenz und Effizienz bekannt ist, insbesondere in Echtzeitanwendungen. Das Modul nutzt das MsgPack-Format zur effizienten Serialisierung und Deserialisierung von Daten, wodurch eine kompakte und schnelle Datenübertragung ermöglicht wird. Die Schnittstelle zur Kommunikation mit dem smartCORE-System erfolgt über IPC (Interprozesskommunikation), wobei die Konfiguration von Erzeuger- und Verbraucherkanälen individuell angepasst werden kann. Dies ermöglicht die Integration und Steuerung externer Software in Echtzeit und unterstützt die flexible Erweiterung bestehender Systeme. Die Dokumentation stellt detaillierte Beispiele bereit, um die Entwicklung eigener Plugins zu erleichtern, wodurch spezifische Anforderungen einfach und effizient umgesetzt werden können. Durch den Einsatz dieser Technologien bietet das Modul eine robuste und skalierbare Lösung für die Kommunikation zwischen smartCORE und externen Prozessen, ideal für Anwendungen in anspruchsvollen industriellen Umgebungen.
Hinweise zur Skript-Entwicklung:
- Wenn sie auf Windows arbeiten stellen sie sicher, dass Skripts nur
\n
enthalten, nicht\r\n
Tutorials
Entwicklung auf externem PC
Einfaches Daten-schreibe Plugin
Daten-lese und -schreibe Plugin
[Fortgeschritten] Installation von neuen Python Bibliotheken (z.B. NumPy)
JSON Konfiguration
Konfiguration der Netzwerk Parameter
Schlüsselwort | Erläuterung |
---|---|
port | UDP Port auf dem das Plugin hört (Default: 61616) |
localhost | Beschränkung auf "localhost only" Kommunikation (Default: true) |
Konfiguration der Prozess Steuerung
Name | Erläuterung |
---|---|
enable | Legt fest ob der Prozess gestartet und überwacht werden soll (Default: false) |
logOutput | Ausgabe (stdout & stderr) des Prozesses ins smartCORE Logfile übernehmen (Default: true) |
watchdogTimeout | Maximale Zeit zwischen 2x IPC Messages bis zum RESTART des Prozesses |
disableKillAllProcesses | Alle Prozesse töten beim Start oder bei Problemen deaktivieren (Default: false) |
command | Name (mit optionalem Pfad) des Prozesses |
arguments | Kommandozeilenargumente für den Prozesses |
Konfiguration der Producer Channels ( producerChannels )
Schlüsselwort | Erläuterung |
---|---|
name | Name des Kanals |
dataType | Datentyp des Kanals |
physicalUnit | Einheit des Kanals |
Konfiguration des Consumer Channels ( consumerChannels )
Schlüsselwort | Erläuterung |
---|---|
name | Name des Kanals, der eingelesen werden soll |
Beispielkonfiguration
{
"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": "µg/m³"
},
{
"name": "sen5x_pm2p5",
"dataType": "float",
"physicalUnit": "µg/m³"
}
],
"consumerChannels": [
{
"name": "scd40_co2"
}
]
}
}
API/Protokoll
Das Protokoll besteht aus einem größtenteils statischen Header, in dem ein Kommando-Code spezifiziert wird, und (falls nötig) einem JSON Payload.
Header
Header Metadaten
Offset und Datentyp | Name | Beschreibung |
---|---|---|
[0] uint32_t | magicToken | Erkennung des Protokolls (fest 0x45554C42) |
[4] uint8_t | version | Protokoll Version (aktuell immer 1; offen für Erweiterungen) |
[5] uint8_t | payloadType | Unterstützung und Unterscheidung verschiedener Payload Arten (hier aktuell immer 2) |
[6] uint16_t | reserved | Reserviert für spätere Erweiterungen (Header Größe soll durch 4 teilbar sein) |
[8] uint64_t | senderPid | Prozess ID des versendenden Prozess |
[16] uint64_t | senderTime_msSE | Zeitpunkt in Millisekunden wann das Paket versendet wurde (für Diagnosezwecke) |
[24] uint16_t | group | Kennung an welchen Dienst der RPC Call ging bzw. von dem die Antwort kommt (hier fest 1000) |
[26] uint16_t | command | Nummer des RPC-Calls (siehe folgende Tabelle) |
Commands
Command-Nr | Bezeichnung | Erläuterung |
---|---|---|
0 | LifeSignRequest | smartCORE Status Abfrage |
1 | LifeSignResponse | Antwort auf LifeSignRequest |
100 | WriteSamplesByName | Einzelne Samples mit Kanalname senden |
101 | ReadSamplesByNameRequest | Abfrage einzelner Kanäle über Kanalnamen |
102 | ReadSamplesByNameResponse | Antwort auf ReadSamplesByNameRequest (Messwerte) |
200 | ChannelListRequest | Abfrage der Kanalliste (Zuordnung Kanalname => Index) |
201 | ChannelListResponse | Antwort auf ChannelListRequest (Kanalliste) |
202 | WriteSamplesRequest | Samples (optional mit Zeitstempel) über Index senden |
203 | WriteSamplesResponse | Optionale Antwort auf WriteSamplesRequest falls ein Token zur Bestätigung übergeben wurde |
204 | ReadSamplesBegin | Einschalten des zyklischen Senden von Messwerten durch den smartCORE |
205 | ReadSamplesContent | Messwerte des zyklischen Senden |
206 | ReadSamplesEnd | Abschalten des zyklischen Senden |
300 | AlarmMessageRequest | Schreiben eines Alarm in die smartCORE Alarmzentrale |
301 | AlarmMessageResponse | Bestätigung auf AlarmMessageRequest |
Payload-struktur (JSON Content)
byName Commands
Werte in smartCORE schreiben
RPC: WriteSamplesByName (Client => smartCORE)
Parameter | Beschreibung |
---|---|
c | Array der Kanäle |
n | Kanal Name |
v | Messwert |
t | Zeit Stempel (optional) |
{
"c": [
{
"n": "sen5x_pm1p0",
"v": 1.0099999904632568,
"t": 1720074467000000
},
{
"n": "sen5x_pm2p5",
"v": 2.009999990463257,
"t": 1720074467000000
}
]
}
Werte aus smartCORE lesen (Polling)
RPC: ReadSamplesByNameRequest (Client => smartCORE)
Parameter | Beschreibung |
---|---|
c | Array der Kanal Namen |
{
"c": [
"sen5x_pm1p0",
"sen5x_pm2p5"
]
}
RPC: ReadSamplesByNameResponse (smartCORE => Client)
Parameter | Beschreibung |
---|---|
c | Array der Kanäle |
n | Kanal Name |
v | Messwert |
t | Zeit Stempel |
{
"c": [
{
"n": "sen5x_pm1p0",
"v": 1.0099999904632568,
"t": 1720074467000000
},
{
"n": "sen5x_pm2p5",
"v": 2.009999990463257,
"t": 1720074467000000
}
]
}
byIndex Commands
Kanalliste abfragen
RPC: ChannelListRequest (Client => smartCORE)
Hier kann ein leerer Request gesendet werden um die Namen aller Kanäle anzufragen. Alternativ können auch nur ausgewählte Kanalnamen angefragt werden:
Parameter | Beschreibung |
---|---|
c | Array der Kanal Namen |
f | Anfrage spezieller Felder wie z.B. "d" (Datentyp) [optional] |
{
"f": [
"d"
],
"c": [
"sen5x_pm1p0",
"sen5x_pm2p5"
]
}
RPC: ChannelListResponse (smartCORE => Client)
Parameter | Beschreibung |
---|---|
c | Array der Kanäle |
n | Kanal Name |
i | Index des Kanal |
w | Schreibbar (Producer Kanal) [bei false nicht vorhanden] |
d | Datentyp (optional; wenn angefragt) |
{
"c": [
{
"n": "sen5x_pm1p0",
"i": 0,
"w": true,
"d": "float"
},
{
"n": "sen5x_pm2p5",
"i": 1,
"d": "int32"
}
]
}
Werte in smartCORE schreiben
RPC: WriteSamplesRequest (Client => smartCORE)
Hier gibt es drei mögliche Payloads:
- einzelne Samples pro Kanal
- Mehreres Samples mit Zeit Stempel pro Kanal
- Äquidistante Samples pro Kanal
Parameter | Beschreibung |
---|---|
a | Token um Acknowledge Paket zu erhalten (optional) |
c | Array der Kanäle |
i | Kanal Index |
v | Messwert |
t | Zeit Stempel (optional) |
s | Different Zeit bei äquidistanten Samples |
Payload Variante 1: einzelne Samples pro Kanal
{
"a": "xyz",
"t": 1720074467000000,
"c": [
{
"i": 0,
"v": 1.0099999904632568,
"t": 1720074467000000
},
{
"i": 1,
"v": 2.009999990463257,
}
]
}
Payload Variante 2: Mehreres Samples mit Zeit Stempel pro Kanal
{
"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: Äquidistante Samples pro Kanal
{
"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)
Wenn im Request Paket ein Token angegeben wurde, sendet der smartCORE eine Paket mit dem Token zur Bestätigung.
Parameter | Beschreibung |
---|---|
a | Token aus dem Request Paket |
{
"a": "xyz"
}
Kontinuierliche Werte aus smartCORE lesen
RPC: ReadSamplesBegin (Client => smartCORE)
Parameter | Beschreibung |
---|---|
t | Zeit im Millisekunden zwischen zwei Paketen (Versandintervall) |
n | Gewünschte Anzahl Samples (Anzahl von identischen Konsumptionsintervallen pro Versandintervall) |
e | Äquidistant (ohne Übertragung der Zeit Stempel) |
c | Liste der Kanal Indizes |
{
"t": 100,
"n": 10,
"e": true,
"c": [
2,
5
]
}
RPC: ReadSamplesContent (smartCORE => Client)
Parameter | Beschreibung |
---|---|
x | fortlaufender Paket Index seit Begin (z.B. um Datenverlust zu ermitteln) |
c | Array der Kanäle |
i | Kanal Index |
v | Messwert |
t | Zeit Stempel |
Hinweise:
- Stehen weniger als die genwünschten Anzahl Samples zur Verfügung, werden nur die zur Verfügung stehenden Samples übertragen.
- Steht kein aktuelles Sample zur Verfügung, wird nur der "Last Value" gesendet.
Payload Variante 1: mit Zeit Stempel ( 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: ohne Zeit Stempel ( 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)
Leerer Request zum Abschalten der Übertragung.