Zum Hauptinhalt springen

Remote Plugin

warnung

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üsselwortErläuterung
portUDP Port auf dem das Plugin hört (Default: 61616)
localhostBeschränkung auf "localhost only" Kommunikation (Default: true)

Konfiguration der Prozess Steuerung

NameErläuterung
enableLegt fest ob der Prozess gestartet und überwacht werden soll (Default: false)
logOutputAusgabe (stdout & stderr) des Prozesses ins smartCORE Logfile übernehmen (Default: true)
watchdogTimeoutMaximale Zeit zwischen 2x IPC Messages bis zum RESTART des Prozesses
disableKillAllProcessesAlle Prozesse töten beim Start oder bei Problemen deaktivieren (Default: false)
commandName (mit optionalem Pfad) des Prozesses
argumentsKommandozeilenargumente für den Prozesses

Konfiguration der Producer Channels ( producerChannels )

SchlüsselwortErläuterung
nameName des Kanals
dataTypeDatentyp des Kanals
physicalUnitEinheit des Kanals

Konfiguration des Consumer Channels ( consumerChannels )

SchlüsselwortErläuterung
nameName 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 Metadaten

Offset und DatentypNameBeschreibung
[0] uint32_tmagicTokenErkennung des Protokolls (fest 0x45554C42)
[4] uint8_tversionProtokoll Version (aktuell immer 1; offen für Erweiterungen)
[5] uint8_tpayloadTypeUnterstützung und Unterscheidung verschiedener Payload Arten (hier aktuell immer 2)
[6] uint16_treservedReserviert für spätere Erweiterungen (Header Größe soll durch 4 teilbar sein)
[8] uint64_tsenderPidProzess ID des versendenden Prozess
[16] uint64_tsenderTime_msSEZeitpunkt in Millisekunden wann das Paket versendet wurde (für Diagnosezwecke)
[24] uint16_tgroupKennung an welchen Dienst der RPC Call ging bzw. von dem die Antwort kommt (hier fest 1000)
[26] uint16_tcommandNummer des RPC-Calls (siehe folgende Tabelle)

Commands

Command-NrBezeichnungErläuterung
0LifeSignRequestsmartCORE Status Abfrage
1LifeSignResponseAntwort auf LifeSignRequest
100WriteSamplesByNameEinzelne Samples mit Kanalname senden
101ReadSamplesByNameRequestAbfrage einzelner Kanäle über Kanalnamen
102ReadSamplesByNameResponseAntwort auf ReadSamplesByNameRequest (Messwerte)
200ChannelListRequestAbfrage der Kanalliste (Zuordnung Kanalname => Index)
201ChannelListResponseAntwort auf ChannelListRequest (Kanalliste)
202WriteSamplesRequestSamples (optional mit Zeitstempel) über Index senden
203WriteSamplesResponseOptionale Antwort auf WriteSamplesRequest falls ein Token zur Bestätigung übergeben wurde
204ReadSamplesBeginEinschalten des zyklischen Senden von Messwerten durch den smartCORE
205ReadSamplesContentMesswerte des zyklischen Senden
206ReadSamplesEndAbschalten des zyklischen Senden
300AlarmMessageRequestSchreiben eines Alarm in die smartCORE Alarmzentrale
301AlarmMessageResponseBestätigung auf AlarmMessageRequest

Payload-struktur (JSON Content)

byName Commands

Werte in smartCORE schreiben

RPC: WriteSamplesByName (Client => smartCORE)

ParameterBeschreibung
cArray der Kanäle
nKanal Name
vMesswert
tZeit 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)

ParameterBeschreibung
cArray der Kanal Namen
{
"c": [
"sen5x_pm1p0",
"sen5x_pm2p5"
]
}

RPC: ReadSamplesByNameResponse (smartCORE => Client)

ParameterBeschreibung
cArray der Kanäle
nKanal Name
vMesswert
tZeit 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:

ParameterBeschreibung
cArray der Kanal Namen
fAnfrage spezieller Felder wie z.B. "d" (Datentyp) [optional]
{
"f": [
"d"
],
"c": [
"sen5x_pm1p0",
"sen5x_pm2p5"
]
}

RPC: ChannelListResponse (smartCORE => Client)

ParameterBeschreibung
cArray der Kanäle
nKanal Name
iIndex des Kanal
wSchreibbar (Producer Kanal) [bei false nicht vorhanden]
dDatentyp (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
ParameterBeschreibung
aToken um Acknowledge Paket zu erhalten (optional)
cArray der Kanäle
iKanal Index
vMesswert
tZeit Stempel (optional)
sDifferent 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.

ParameterBeschreibung
aToken aus dem Request Paket
{
"a": "xyz"
}
Kontinuierliche Werte aus smartCORE lesen

RPC: ReadSamplesBegin (Client => smartCORE)

ParameterBeschreibung
tZeit im Millisekunden zwischen zwei Paketen (Versandintervall)
nGewünschte Anzahl Samples (Anzahl von identischen Konsumptionsintervallen pro Versandintervall)
eÄquidistant (ohne Übertragung der Zeit Stempel)
cListe der Kanal Indizes
{
"t": 100,
"n": 10,
"e": true,
"c": [
2,
5
]
}

RPC: ReadSamplesContent (smartCORE => Client)

ParameterBeschreibung
xfortlaufender Paket Index seit Begin (z.B. um Datenverlust zu ermitteln)
cArray der Kanäle
iKanal Index
vMesswert
tZeit 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.