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": "ReversedForMsbNumerics",
"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": "AscendingMSBit",
"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 | "ReversedForMsbNumerics" | 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 |
| bitOffset | JA | UINT | Bit-Offset des in der Botschaft hinterlegten Wertes | ||
| bitLength | Nein3 | UINT | Bit-Länge des in der Botschaft hinterlegten Wertes | ||
| imageType | JA | STRING | unterstützter Quelldatentyp des hinterlegten Wertes (siehe unten) | ||
| 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 |
Unterstützte Adressspezifikationen 'addressSpec'
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 ReversedForMsbNumerics auch die Default-Einstellung.
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 |
|---|---|---|
| ReversedForMsbNumerics | MVB | 8 Für boolsche Signale werden die Bits mit aufsteigender Wertigkeit gezählt. Für alle anderen Signale werden Bits in umgekehrter (Motorola) Reihenfolge gezählt. |
| ReversedForMsb | 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 | Für alle Signale werden Bits mit aufsteigender Wertigkeit gezählt. Es wird immer die Position des LSBit adressiert. | |
| AscendingMSBit | Für alle Signale werden Bits mit aufsteigender Wertigkeit gezählt. Es wird immer die Position des MSBit adressiert. |
Zählung der Bit-Position
Die wichtigste Unterscheidung 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 CAN- oder Profibus-Konfigurationen.
Mit den Einstellungen ReversedForMsb* werden die Bits in der byteOrder BigEndian (Motorola, MSB, Network) strikt von links nach rechts durchgezählt. Um die Verwirrung zu komplettieren, zählen TCN, WTB oder MVB (EN 61375-2-1 §6.4.4.3) jedoch bit-Felder wieder mit aufsteigender Wertigkeit, damit gilt die umgekehrte Zählweise nur für numerische Werte (ReversedForMsbNumerics), nicht aber für einzelne Bits.
Die Grafik zeigt die unterschiedliche Zählweise für exemplarisch 3 Bytes.
Festlegung des Anker-Bits
In den Ascending*-Einstellungen wird außerdem noch 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 Wert.
| addressSpec | byteOrder | bitOffset | bitLength |
|---|---|---|---|
| ReversedForMsbNumerics ReversedForMsb AscendingFirstBit AscendingLSBit | LittleEndian | 11 | 18 |
| AscendingMSBit | LittleEndian | 28 | 18 |
| (ohne Funktion) | "CBA" | 119 | 18 |
| AscendingFirstBit AscendingMSBit | BigEndian | 34 | 18 |
| AscendingLSBit | BigEndian | 49 | 18 |
| (ohne Funktion) | "ABC" | 3310 | 18 |
| ReversedForMsbNumerics ReversedForMsb | BigEndian | 13 | 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" | 1011 | 1 |
Unterstützte 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);
Unterstützte 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. | |
| 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 | Feste bitLength von 32, IEEE 754 | |
| double | 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!
Unterstützte 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 die Datenquelle schon einen Fließ- oder Festkommawert liefert oder scale != 1.0, offset != 0.0 oder eine physicalUnit spezifiziert ist. Sofern die bitLength <= 24 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 ausgewählt.
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 dataType Integer 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 Datenreduktioonsfilter 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 Measurement and Automation Systems GmbH |
| seit smartCORE | 0.103 |
| Modultyp | Fast Message Receiver, Producer |
| Abhängigkeiten | Fast Message Sendemodul (z.B. fmudp, canbus, smartmvb, ...) |