Fast Message Producer Modul "fmproducer"
Beschreibung
Fast alle Datenquellen in der Prozesstechnik übertragen die Daten in gepackten Datenfeldern von Bytes. Der Inhalt und eventuell auch die Länge dieser Pakete sind über einen messageKey (oder auch "ID") indentifizierbar. Beispiele sind in der folgenden Tabelle angegeben.
| Protokoll | Message Key | Länge des Keys |
|---|---|---|
| CAN-Bus | CAN-ID | 11 oder 29 bit |
| MVB-Bus | Port-Nummer | 12 bit |
| ProfiBus | Slave-Node ID | 7 bit |
| Modbus | Register, Coil, Input, Status | 2 + 16-bit |
Verschiedene smartCORE Plugins (z.B. fmudp, canbus, smartmvb) realisieren die Anbindung der Hardware über dedizierte Schnittstellen, Empfangen oder Versenden Datenpakete und speisen mit den empfangenen Paketen den sogenannten Fast Message Dispatcher (FMD). Dieser stellt eine effiziente Technologie im smartCORE bereit, um aus beliebigen Datenquellen nach immer wiederkehrendem Schema Messdaten und Statusinformationen herauszulesen und in einzelne smartCORE Kanäle zu produzieren (daher der Name "fm Producer").
Die Schnittstellen-Module erzeugen mindestens eine Instanz eines FMDs unter ihrem eigenen Namen. Dieser wird im fmProducer über die Eigenschaft fmd angebunden.
In den empfangenen Paketen sind neben der MessageID und einem Zeitstempel die Daten in einem Datenfeld aus Bytes enthalten. Für einen Kanal sind darin die Daten ab einem bestimmten bitOffset mit einer festgelegten bitLength zu finden. Dabei spielt noch die Anordnung der Bytes byteOrder im Puffer, sowie (leider) die addressSpec(ification) ein Rolle, mit der festgelegt wird, wie die Bits im Puffer gezählt werden.
Nachdem die Rohdaten-Bytes in die richtige Reihenfolge, der Wert korrekt verschoben und maskiert wurde, erfolgt die Interpretation über den imageType. Hat die Zahl ein Vorzeichen oder nicht? Ist die Zahl als BCD (Binary Coded Decimal) oder als Polarer-Wert (Fix-Komma) zu lesen? Ganzzahlig, Fließkomma oder sogar Text?
Nach einer optionalen Skalierung auf eine physikalische Messgröße (scale, offset, physicalUnit) gemäß
erfolgt die Produktion des Datenwertes in den smartCORE Kanal mit dem ebenfalls vom Schnittstellen-Modul übermittelten (Empfangs-)Zeitstempel.
Verwendete Schnittstellen & Protokolle
- Fast Message Dispatching
JSON-Konfiguration
Im folgenden Abschnitt soll die gesamte JSON-Konfiguration des Moduls beschrieben und die einzelnen Parameter erläutert werden.
Beispielkonfiguration (minimal)
{
"module":"FmProducer",
"factory":"fmproducer",
"config":{
"fmd":"FastMessageDispatcher",
"channels":[
{
"name":"Channel",
"messageKey":42,
"bitOffset":0,
"bitLength":32,
"imageType":"float"
},
[...]
]
}
}
Beispielkonfiguration (maximal)
{
"module":"FmProducerSmartMVB",
"factory":"fmproducer",
"config":{
"fmd":"smartmvb0",
"bufferSize":1024,
"namespace":["directory","subDirectory"],
"channelPrefix":"SmartMVB",
"addressSpec": "EN61375_MVB",
"byteOrder": "bigEndian",
"channels":[
{
"name":"SmartMVBmessageData",
"bufferSize":1024,
"scale":3.14,
"offset":2.72,
"physicalDimension":"Length",
"physicalUnit":"m",
"messageKey":10012,
"bitOffset":0,
"bitLength":20,
"imageType":"unsigned",
"addressSpec": "AscendingFirstBit",
"byteOrder": "littleEndian",
"absoluteTolerance":0.5
},
[...]
]
}
}
Globale Modulparameter
| Parametername | Erforderlich | Datentyp | sinnvoller Wertebereich | Default | Beschreibung |
|---|---|---|---|---|---|
| fmd | JA | STRING | Fast Message Dispatcher des Sendemoduls | ||
| bufferSize | Nein1 | INT | 1 - | 1024 | (default) Puffergröße der angelegten Kanäle |
| channelPrefix | Nein | STRING | Kanal Präfix (sinnvoll, wenn mehrere fmproducer Module verwendet werden und die Konfigurationen überlappende Kanalnamen besitzen) | ||
| namespace | Nein | ARRAY [STRING] | Kanal Präfix in Form hierarchisch verketteter Namespaces | ||
| addressSpec | Nein | STRING | "EN61375_MVB" | Default Schema der Adressierung | |
| byteOrder | Nein | STRING | "BigEndian" | Default Byte-Order | |
| channels | JA | JSON Array | Liste von JSON Objects konfigurierter Kanäle |
Konfiguration eines Kanals (JSON Object)
| Parametername | Erforderlich | Datentyp | sinnvoller Wertebereich | Default | Beschreibung |
|---|---|---|---|---|---|
| Filter | |||||
| messageKey | Nein2 | UINT | ID der empfangenen Botschaft (z.B. CAN-Bus Message ID, MVB Port, ...) | ||
| Process Image | |||||
| addressSpec | Nein | STRING | (Wert aus globaler Einstellung) | Schema der Adressierung, siehe nachfolgende Beschreibung | |
| byteOrder | Nein | STRING | "BigEndian", "LittleEndian", "[A-Z]+" | (Wert aus globaler Einstellung) | Byte-Order des hinterlegten Wertes, siehe nachfolgende Beschreibung |
| imageType | JA | STRING | unterstützter Quelldatentyp des hinterlegten Wertes (siehe unten) | ||
| bitOffset | JA | UINT | Bit-Offset des in der Botschaft hinterlegten Wertes | ||
| bitLength | Nein3 | UINT | Bit-Länge des in der Botschaft hinterlegten Wertes | ||
| stringHint | Nein4 | STRING | Hinweis zur Bestimmung der String-Länge (siehe unten) | ||
| scale | Nein5 | FLOAT | 1 | Skalierungsfaktor des produzierten Werts | |
| offset | Nein5 | FLOAT | 0 | additiver Offset des produzierten Werts | |
| smartCORE | |||||
| name | JA | STRING | Name der Kanals | ||
| dataType | Nein6 | STRING | Datentyp des Kanals | ||
| bufferSize | Nein1 | INT | 1 - | 1024 | Puffergröße des angelegten Kanals |
| physicalDimension | Nein | STRING | physikalische Größe | ||
| physicalUnit | Nein | STRING | physikalische Einheit | ||
| noFilter | Nein | BOOL | false | Schaltet das DataReduction-Filter aus | |
| absoluteTolerance | Nein | FLOAT | 0.0 | Absolute Toleranz für das DataReduction-Filter | |
| cacheSize | Nein7 | INT | 0 | Anzahl der Datensamples, die in einem lokalen Cache des Kanals gespeichert werden, bevor diese für andere Module veröffentlicht werden. | |
| Reserviert | |||||
| debug | Nein | BOOL | false | Schaltet Debug-Ausgaben für den Kanal frei. | |
| numElements | Nein | INT | 1 | Länge eines Datenfelds in Vielfachen des Grundelements |
Adressspezifikationen 'addressSpec'
Warum muss ein Adressierungs-Schema festgelegt werden?
Der fmproducer zerlegt das von einem externen Gerät empfangene Datenpaket. Und die Spezifikation dieses Gerätes und der verwendeten Schnittstelle legen fest, wie einzelne Datenkanäle in dem Datenstrom zu lokalisieren sind. Hierbei gibt es leider viele Variationen, weil trotz Standardisierung in bestimmten Bereichen immer noch genügend proprietäre Implementierungen existieren.
Die Adress-Spezifikation addressSpec legt fest, in welcher Zählweise das MSBit oder das LSBit im bitOffset angegeben sind. Aus historischen Gründen (fmProducer wurde zuerst für den MVB entwickelt) ist die Einstellung EN61375_MVB auch die Default-Einstellung.
Einstellbare Werte
Sofern nicht anders angegeben, wird jeweils die Position des ersten Bits (Msb/Lsb je nach byteOrder) adressiert. Die Angabe der addressSpec ist ohne Funktion, wenn als byteOrder ein freies Mapping gewählt wird.
| Enum | Alias | Beschreibung |
|---|---|---|
| EN61375_MVB | MVB EN61375 RevNum ReversedNum ReversedForMsbNumerics | Folgt strikt der EN61275 mit Bezug auf ByteOrder, Datentypen, Alignment und Bit-Zählung. - Der bitOffset ist byteOffset * 8 + rightShift - Nicht konforme Konfigurationen werden abgelehnt. |
| ReversedForMsb | Rev Reversed | 8 Für alle Signale werden Bits in umgekehrter (Motorola) Reihenfolge gezählt. |
| AscendingFirstBit | DBC | Für alle Signale werden Bits mit aufsteigender Wertigkeit gezählt. |
| AscendingLSBit | positionLsb | Für alle Signale werden Bits mit aufsteigender Wertigkeit gezählt. Es wird immer die Position des LSBit adressiert. |
| AscendingMSBit | positionMsb | Für alle Signale werden Bits mit aufsteigender Wertigkeit gezählt. Es wird immer die Position des MSBit adressiert. |
Festlegung der Image-Position für EN61375_MVB
In der Norm EN 61375-2-1 gibt es ab §6.4.2 verschiedene Hinweise, wie Daten auf dem MVB übertragen werden müssen. Dabei sind bestimmte Fälle von vornherein ausgeschlossen. Kanäle mit einer nicht konformen Konfiguration werden im fmproducer ab smartCORE 2.10.1 als Fehler im Logfile ausgegeben und für die Verarbeitung gesperrt.
-
(Annahme und Grauzone)9 Die Norm definiert keine Datentypen, die nicht die Länge einer glatten 2-er Potenz haben.
-
Damit verweist bitOffset nicht konsistent auf das MSBit oder LSBit einer Variablen, sondern entweder auf das erste (ganze) Byte oder das LSbit in einem Byte für
-
Die Darstellung ist immer BigEndian. Damit werden LittleEndian Anordnungen ausgeschlossen.
-
Die Image-Position muss immer an einem Vielfachen ihrer Größe im Datenpuffer ausgerichtet sein. Für Datentypen mit 1, 2 oder 4 bit Länge können diese also ausschließlich innerhalb eines Bytes liegen. Alle anderen mit Länge 8, 16, 32, 64 bit müssen zwingend an einem Byte augerichtet sein. Ein Verschieben des Images ist nicht zulässig! => ab .
Falls eine Dekodierung mit diesem Schema EN61375_MVB nicht möglich ist, kann für einen einzelnen Kanal immer noch eines der anderen Schemata gewählt werden und dann auch eine Verschiebung und Neuausrichtung der Bits und Bytes probiert werden.
Zählung der Bit-Position
Die wichtigste Unterscheidung für alle anderen Schemata ist zunächst, in welcher Reihenfolge die Bits gezählt werden.
Mit den Ascending*-Einstellungen zählen die Bits gemäß der aufsteigenden Wertigkeit. Dies ist typisch für CANbus- oder Profibus-Konfigurationen und entspricht auch Implementierungen in Programmiersprachen.
Mit der Einstellung ReversedForMsb werden die Bits in der byteOrder BigEndian (Motorola, MSB, Network) strikt von links nach rechts durchgezählt. Dies enspricht der Zählweise auf physikalischer Ebene in seriellen Datenübetragungsprotokollen, wie z.B. CANbus, SPI oder auch MVB.
Die Grafik zeigt die unterschiedliche Zählweise für exemplarisch 3 Bytes.
Festlegung des Anker-Bits für die Image-Position
In den Ascending*-Einstellungen wird unterschieden, welches Bit des Datenwertes mit bitOffset adressiert wird. Üblicherweise ist es das erste Bit (AscendingFirstBit), also bei byteOrder bigEndian das MSBit und bei littleEndian das LSBit. Es gibt aber auch Ausnahmen, bei denen unabhängig von der byteOrder immer das MSBit oder das LSBit adressiert ist.
Im folgenden Diagramm werden aus einen Datentelegramm mit Ascending*- Zählung zwei 18-bit Integer-Werte extrahiert, die einmal mit byteOrder littleEndian und einmal bigEndian übertragen werden.
Und dieses Diagramm ergänzt einen 18-bit Integer Wert in ReversedForMsb-Zählung:
Die Tabelle gibt mögliche Adressierungsvarianten für die oben gezeigten int18-Werte.
| addressSpec | byteOrder | bitOffset | bitLength |
|---|---|---|---|
| ReversedForMsb AscendingFirstBit AscendingLSBit | LittleEndian | 11 | 18 |
| AscendingMSBit | LittleEndian | 28 | 18 |
| (ohne Funktion) | "CBA" | 1110 | 18 |
| ReversedForMsb | BigEndian | 13 | 18 |
| AscendingFirstBit AscendingMSBit | BigEndian | 34 | 18 |
| AscendingLSBit | BigEndian | 49 | 18 |
| (ohne Funktion) | "ABC" | 3311 | 18 |
Boolsche Signale
Nicht zuletzt entscheidet bei boolschen Signalen ausschließlich die Zählrichtung über das ausgewählte Bit:
| addressSpec | byteOrder | bitOffset | bitLength |
|---|---|---|---|
| ReversedForMsb | BigEndian | 13 | 1 |
| (alle anderen) | BigEndian LittleEndian | 10 | 1 |
| (ohne Funktion) | "A" | 1012 | 1 |
Anordnung der Bytes 'byteOrder'
| Enum | Alias | Beschreibung |
|---|---|---|
| BigEndian | Big, MSB, Motorola, Network | Das Byte mit dem höchstwertigen Bit (MSBit) steht in dem übertragenen Datenpaket vorne |
| LittleEndian | Little, LSB, Intel | Das Byte mit dem niederwertigsten Bit (LSBit) steht in dem übertragenen Datenpaket vorne |
| Folge von A-Z | Wird ein Mapping-String verwendet, können die Bytes aus einer beliebig gemischten Anordnung in die korrekte Reihenfolge gebracht werden. addressSpec ist damit ohne Funktion. |
Verwendung eines Mapping-Strings
Die Bytes im Empfangspuffer werden ab bitOffset / 8 beginnend mit 'A' aufsteigend indiziert. Die Reihenfolge der Bytes in absteigender Wertigkeit wird durch den String festgelegt. bitOffset MODULO 8 bestimmt, um wieviele Bits der extrahierte Wert nach rechts verschoben werden muss, damit das niederwertigste Bit (LSBit) an Position steht.
Mit diesem freien Mapping können in der Regel alle Telegramme interpretiert werden, die einen langen Weg von einer Messklemme, durch Buskoppler, Steuerungen, Gateways, etc. genommen und dabei verschiedene Neuordnungen und Interpretationen der Bytereihenfolge erlebt haben. Jedes System bietet eigene Einstellmöglichkeiten und die werden auch reichlich genutzt. Es könnte so einfach sein...
Beispiel:
bytes: 0_______ 1_______ 2_______ 3_______ 4_______ 5_______ 6_______
bits: 76543210 76543210 76543210 76543210 76543210 76543210 76543210
bitOffset: --------------------->|
Indizierung: A B C D E ...
Extraktion für "CDBA"
value = ((((byte[4] << 8) // alias 'C' (bitOffset / 8) + 2
| byte[5] << 8) // alias 'D' (bitOffset / 8) + 3
| byte[3] << 8) // alias 'B' (bitOffset / 8) + 1
| byte[2]) // alias 'A' (bitOffset / 8) + 0
>> (bitOffset % 8);
Quelldatentypen 'imageType'
| Enum | Alias | Beschreibung |
|---|---|---|
| bool | boolean | Feste bitLength von 1 und dataType Bool. |
| unsigned | Vorzeichenlose Ganzzahl mit bitLength 2..64. Kann mit scale und offset zu einer skalierten physikalische Größe verrechnet werden. | |
| antivalent, antivalent2 | => unsigned mit bitLength = 2, meist im MVB Kontext für gesicherte Boolsche Werte verwendet: 0: ERROR 1: FALSE 2: TRUE 3: UNDEFINED | |
| signed | Vorzeichenbehaftete Ganzzahl mit bitLength 2..64, das höchstwertige Bit ist das Vorzeichen-Bit. Kann mit scale und offset zu einer skalierten physikalische Größe verrechnet werden. | |
| bcd | Binär-Codierte-Dezimalzahlen, je 4-bits für die Darstellung einer Ziffer 0..9 | |
| float | 13 Feste bitLength von 32, IEEE 754 | |
| double | 13 Feste bitLength von 64, IEEE 754 | |
| timedate48 | Feste bitLength von 48, EN 61375-2-1 §6.4.6.2 (TCN, WTB, MVB) | |
| time64 | Feste bitLength von 64, RFC 1305 | |
| bytearray | Weitere Eigenschaften legen fest, wie sich die Länge des Arrays errechnet | |
| string | Weitere Eigenschaften legen fest, wie sich die Länge des Strings errechnet | |
UniPolar<M>.<N> | Vorzeichenlose Fix-Kommazahl mit <M> Ganzzahl-Bits und einer festen bitLength von <N> Bits.Kann mit scale und offset zu einer skalierten physikalische Größe verrechnet werden. EN 61375-2-1 §6.4.3.7 (TCN, WTB, MVB) | |
BiPolar<M>.<N> | Vorzeichenbehaftete Fix-Kommazahl mit <M> Ganzzahl-Bits (inklusive Vorzeichen) und einer festen bitLength von <N> Bits.Kann mit scale und offset zu einer skalierten physikalische Größe verrechnet werden. EN 61375-2-1 §6.4.3.8 (TCN, WTB, MVB) |
Hinweise zur Bestimmung der Länge eines Strings 'stringHint' und 'numElements'
imageType: String
Die Funktion zum Dekodieren von Strings ist noch nicht verifiziert. Verwendung nur nach Rücksprache!
Der für den String reservierte Bereich im Datenpuffer ergibt sich aus
-
der bitLength in ganzzahligen Vielfachen von 8 oder
-
der Angabe von numElements als Anzahl der Zeichen.
| Enum | Alias | Beschreibung |
|---|---|---|
| FixedLengthInBits | bitLength | bitLength / 8 definiert die feste Anzahl an Zeichen im String |
| NullTerminated | Das erste Null-Zeichen (0x00) oder das Ende des Datenbereichs bestimmen das Ende des Strings | |
| FixedLength | numElements definiert die feste Anzahl an Zeichen im String | |
| U8Length | Der String beginnt mit einem uint8, der die Länge des Strings dynamisch angibt. | |
| U16Length | Der String beginnt mit einem uint16, der die Länge des Strings dynamisch angibt. | |
| U32Length | Der String beginnt mit einem uint32, der die Länge des Strings dynamisch angibt. | |
| EndOfMessage | Der Verfügbare Datenbereich wird immer bis zum Ende des Datenpuffers ausgedehnt. |
Hinweise zur Bestimmung der Länge eines Datenfeldes 'numElements'
imageType: ByteArray
Die Funktion zum Dekodieren von Datenfeldern ist noch nicht verifiziert. Verwendung nur nach Rücksprache!
Kanaldatentypen (Zieldatentypen) 'dataType'
Der dataType wird immer automatisch aus dem imageType bestimmt, wenn er nicht spezifiziert wird. Dabei wird ein Zielformat eingestellt, mit dem ein Informationsverlust bei kleinstmöglichem Speicherbedarf vermieden wird.
| Enum | Alias | Wertebereich | Anwednung |
|---|---|---|---|
| Boolean | bool | false/true | Status-/Steuersignale |
| Float | bis | Messdaten | |
| Double | bis | ||
| Integer8 | int8 | ||
| Integer16 | int16 | ||
| Integer32 | int32 | ||
| Integer64 | int64 | Zeitstempel | |
| UnsignedInteger8 | uint8 | Status-Codes | |
| UnsignedInteger16 | uint16 | ||
| UnsignedInteger32 | uint32 | ||
| UnsignedInteger64 | uint64 | ||
| ByteArray | |||
| String | Text |
Erzwungene Datentypen:
Ist die bitLength == 1 oder der imageType == bool, so ist auch der dataType automatisch immer bool.
Für imageType == string oder bytearray ist auch der dataType immer string oder bytearray.
Die imageTypes time64 oder timedate48 erzwingen mit int64 den dataType, um die Zeitstempel korrekt und vollständig in Nano-Sekunden seit 01.01.1970 konvertieren zu können.
Eine Angabe von numElements > 1 erzwingt den dataType ByteArray, sofern nicht ein imageType String eingestellt ist.
Automatische Datentypen:
Dabei haben Fließkommaformate float und double Vorrang, sofern eines der folgenden Kriterien erfüllt ist:
- die Datenquelle liefert über den imagetype (float, double, unipolar, bipolar) schon einen Fließ- oder Festkommawert,
- oder ,
- eine physicalUnit ist spezifiziert.
Sofern die ist, genügt ein float für die verlustfreie Umsetzung.
Integer-Formate werden ebenfalls über die bitLength und das Vorhandensein eines Vorzeichens (signed) im imageType für den kleinstmöglichen Datenbereich ausgewählt:
- (Unsigned)Integer8 für
- (Unsigned)Integer16 für
- (Unsigned)Integer32 für
- (Unsigned)Integer64 für
Das optionale Vorzeichen wird aus dem höchstwertigen Bit des Images auf die Breite des dataType aufgefüllt.
Manuelle Datentypen und Konvertierung:
Die manuelle Auswahl des dataType kann zu einem Verlust der Genauigkeit, der Auflösung oder einer signifikanten Einschränkung des verfügbaren Wertebereichs führen und ist deshalb in der Regel zu vermeiden!
Wenn die Datenquelle nach zuvor genannten Regeln eine Fließkommazahl liefert, wird für die Konvertierung in einen Integer dataType gerundet: ab .50 auf den nächst größeren Integer Wert.
In jedem Fall werden die Wertebereiche der gewählten Integer-Typen berücksichtigt. Liegt der Wert aus dem Image außerhalb des verfügbaren Bereichs, wird das entsprechend Minimum oder Maximum, das darstellbar ist, ersetzt und eine Meldung im Log-File ausgegeben.
Datenreduktions-Filter
Für jeden Kanal wird ein Datenreduktions-Filter konfiguriert. Dieses sorgt in der Grundeinstellung dafür, dass neue Datensätze nur dann in den Kanal geschrieben werden, wenn sich der Dateninhalt ändert (OnChange). Der Empfangszeitstempel der Daten wird hingegen mit jedem verarbeiteten Datensatz weiter aktualisiert, sodass eine Verarbeitung der (konstanten) Daten in anderen Plugins bis zum jüngsten Zeitpunkt ermöglicht wird.
Mit der Option absoluteTolerance wird ein Toleranzband um den zuletzt geschriebenen Wert gelegt. Ein neuer Datensatz wird erst dann veröffentlicht, wenn die Differenz zum zuletzt geschriebenen Wert um mehr als dieses Toleranzband abweicht. Diese Einstellung ist für stark verrauschte Signale hilfreich, um die Datenmenge signifikant zu reduzieren.
Wird die Option noFilter auf true gesetzt, wird kein Datenreduktionsfilter erstellt. Diese Einstellung ist sinnvoll für schnelle Daten, die nicht reduziert werden dürfen, weil z.B. für Schwingungssignale eine Betrachtung im Frequenzbereich folgt.
Modul-Informationen
| Information | Wert |
|---|---|
| Autoren | optiMEAS GmbH |
| seit smartCORE | 0.103 |
| Modultyp | Fast Message Receiver, Producer |
| Abhängigkeiten | Fast Message Sendemodul (z.B. fmudp, canbus, smartmvb, rawplayback, ...) |