Zum Hauptinhalt springen

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.

ProtokollMessage KeyLänge des Keys
CAN-BusCAN-ID11 oder 29 bit
MVB-BusPort-Nummer12 bit
ProfiBusSlave-Node ID7 bit
ModbusRegister, Coil, Input, Status2 + 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.

fm Producer

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äß

yphys=yrawscale+offsety_{phys} = y_{raw} \cdot \rm{scale} + \rm{offset}

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

ParameternameErforderlichDatentypsinnvoller WertebereichDefaultBeschreibung
fmdJASTRINGFast Message Dispatcher des Sendemoduls
bufferSizeNein1INT1 -1024(default) Puffergröße der angelegten Kanäle
channelPrefixNeinSTRINGKanal Präfix (sinnvoll, wenn mehrere fmproducer Module verwendet werden und die Konfigurationen überlappende Kanalnamen besitzen)
namespaceNeinARRAY [STRING]Kanal Präfix in Form hierarchisch verketteter Namespaces
addressSpecNeinSTRING"ReversedForMsbNumerics"Default Schema der Adressierung
byteOrderNeinSTRING"BigEndian"Default Byte-Order
channelsJAJSON ArrayListe von JSON Objects konfigurierter Kanäle

Konfiguration eines Kanals (JSON Object)

ParameternameErforderlichDatentypsinnvoller WertebereichDefaultBeschreibung
Filter
messageKeyNein2UINTID der empfangenen Botschaft (z.B. CAN-Bus Message ID, MVB Port, ...)
Process Image
addressSpecNeinSTRING(Wert aus globaler Einstellung)Schema der Adressierung, siehe nachfolgende Beschreibung
byteOrderNeinSTRING"BigEndian", "LittleEndian",
"[A-Z]+"
(Wert aus globaler Einstellung)Byte-Order des hinterlegten Wertes, siehe nachfolgende Beschreibung
bitOffsetJAUINTBit-Offset des in der Botschaft hinterlegten Wertes
bitLengthNein3UINTBit-Länge des in der Botschaft hinterlegten Wertes
imageTypeJASTRINGunterstützter Quelldatentyp des hinterlegten Wertes (siehe unten)
stringHintNein4STRINGHinweis zur Bestimmung der String-Länge (siehe unten)
scaleNein5FLOAT1Skalierungsfaktor des produzierten Werts
offsetNein5FLOAT0additiver Offset des produzierten Werts
smartCORE
nameJASTRINGName der Kanals
dataTypeNein6STRINGDatentyp des Kanals
bufferSizeNein1INT1 -1024Puffergröße des angelegten Kanals
physicalDimensionNeinSTRINGphysikalische Größe
physicalUnitNeinSTRINGphysikalische Einheit
noFilterNeinBOOLfalseSchaltet das DataReduction-Filter aus
absoluteToleranceNeinFLOAT0.0Absolute Toleranz für das DataReduction-Filter
cacheSizeNein7INT0Anzahl der Datensamples, die in einem lokalen Cache des Kanals gespeichert werden, bevor diese für andere Module veröffentlicht werden.
Reserviert
debugNeinBOOLfalseSchaltet Debug-Ausgaben für den Kanal frei.
numElementsNeinINT1Lä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.

EnumAliasBeschreibung
ReversedForMsbNumericsMVB8 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.
ReversedForMsb8 Für alle Signale werden Bits in umgekehrter (Motorola) Reihenfolge gezählt.
AscendingFirstBitDBCFür alle Signale werden Bits mit aufsteigender Wertigkeit gezählt.
AscendingLSBitFür alle Signale werden Bits mit aufsteigender Wertigkeit gezählt.
Es wird immer die Position des LSBit adressiert.
AscendingMSBitFü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.

Zählweise für Bits

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.

Dekodierung Zahlenwert Ascending

Und dieses Diagramm ergänzt einen 18-bit Integer Wert in ReversedForMsb-Zählung:

Dekodierung Zahlenwert Reversed

Die Tabelle gibt mögliche Adressierungsvarianten für die oben gezeigten int18-Werte Wert.

addressSpecbyteOrderbitOffsetbitLength
ReversedForMsbNumerics
ReversedForMsb
AscendingFirstBit
AscendingLSBit
LittleEndian1118
AscendingMSBitLittleEndian2818
(ohne Funktion)"CBA"11918
AscendingFirstBit
AscendingMSBit
BigEndian3418
AscendingLSBitBigEndian4918
(ohne Funktion)"ABC"331018
ReversedForMsbNumerics
ReversedForMsb
BigEndian1318

Boolsche Signale

Nicht zuletzt entscheidet bei boolschen Signalen ausschließlich die Zählrichtung über das ausgewählte Bit:

Dekodierung Boolean

addressSpecbyteOrderbitOffsetbitLength
ReversedForMsbBigEndian131
(alle anderen)BigEndian
LittleEndian
101
(ohne Funktion)"A"10111

Unterstützte Anordnung der Bytes 'byteOrder'

EnumAliasBeschreibung
BigEndianBig, MSB, Motorola, NetworkDas Byte mit dem höchstwertigen Bit (MSBit) steht in dem übertragenen Datenpaket vorne
LittleEndianLittle, LSB, IntelDas Byte mit dem niederwertigsten Bit (LSBit) steht in dem übertragenen Datenpaket vorne
Folge von A-ZWird 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 202^0 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'

EnumAliasBeschreibung
boolbooleanFeste bitLength von 1 und dataType Bool.
unsignedVorzeichenlose Ganzzahl mit bitLength 2..64.
Kann mit scale und offset zu einer skalierten physikalische Größe verrechnet werden.
signedVorzeichenbehaftete 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.
bcdBinär-Codierte-Dezimalzahlen,
je 4-bits für die Darstellung einer Ziffer 0..9
floatFeste bitLength von 32, IEEE 754
doubleFeste bitLength von 64, IEEE 754
timedate48Feste bitLength von 48,
EN 61375-2-1 §6.4.6.2 (TCN, WTB, MVB)
time64Feste bitLength von 64, RFC 1305
bytearrayWeitere Eigenschaften legen fest, wie sich die Länge des Arrays errechnet
stringWeitere 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'

warnung

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.

EnumAliasBeschreibung
FixedLengthInBitsbitLengthbitLength / 8 definiert die feste Anzahl an Zeichen im String
NullTerminatedDas erste Null-Zeichen (0x00) oder das Ende des Datenbereichs bestimmen das Ende des Strings
FixedLengthnumElements definiert die feste Anzahl an Zeichen im String
U8LengthDer String beginnt mit einem uint8, der die Länge des Strings dynamisch angibt.
U16LengthDer String beginnt mit einem uint16, der die Länge des Strings dynamisch angibt.
U32LengthDer String beginnt mit einem uint32, der die Länge des Strings dynamisch angibt.
EndOfMessageDer Verfügbare Datenbereich wird immer bis zum Ende des Datenpuffers ausgedehnt.

Hinweise zur Bestimmung der Länge eines Datenfeldes 'numElements'

warnung

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.

EnumAliasWertebereichAnwednung
Booleanboolfalse/trueStatus-/Steuersignale
Floatbis 3.4010383.40\cdot10^{38}Messdaten
Doublebis 1.80103081.80\cdot10^{308}
Integer8int827271-2^{7}\dots2^{7}-1
Integer16int162152151-2^{15}\dots2^{15}-1
Integer32int322312311-2^{31}\dots2^{31}-1
Integer64int642632631-2^{63}\dots2^{63}-1Zeitstempel
UnsignedInteger8uint802810\dots2^{8}-1Status-Codes
UnsignedInteger16uint16021610\dots2^{16}-1
UnsignedInteger32uint32023210\dots2^{32}-1
UnsignedInteger64uint64026410\dots2^{64}-1
ByteArray
StringText

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:

warnung

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

InformationWert
AutorenoptiMEAS Measurement and Automation Systems GmbH
seit smartCORE0.103
ModultypFast Message Receiver, Producer
AbhängigkeitenFast Message Sendemodul (z.B. fmudp, canbus, smartmvb, ...)

Footnotes

  1. Die Angabe der bufferSize bestimmt, wieviele Samples im smartCORE-Kanal zur Verwendung für andere Module vorgehalten wird. Sie sollte so gewählt werden, dass ca. 5 .. 10 Sekunden gepuffert werden können. Periodische Datenlücken in den OSF-Daten deuten auf eine zu kleine bufferSIze hin. 2

  2. Ist der "messageKey" nicht konfiguriert, so werden Daten aus allen Messages weiterverarbeitet (dies ist z.B. sinnvoll für CAN RAW und Debugging-Anwendungen).

  3. Ist die "bitLength" nicht konfiguriert, wird diese aus dem imageType oder der Länge der weitergeleiteten Botschaft bestimmt.

  4. Zwingend nur für imageType String

  5. Die Angabe von scale != 1 oder offset != 0 führt mit einem numerischen imageType zur Ausgabe mit dataType float oder double. 2

  6. In der Regel sollte die Angabe des Datentyps weggelassen werden, da er dann optimiert aus dem imageType und der bitLength bestimmt wird. Für manche Kombinationen wird der Datentyp durch das Modul zwingend festgelegt.

  7. Die Angabe einer cacheSize reduziert für sehr schnelle Datenquellen (>100Hz> 100 Hz) die CPU Auslastung, da zunächst neue Datensätze in einem Cache zwischengespeichert werden und erst mit vollständiger Füllung des Caches an andere Module veröffentlicht werden. Die Angabe sollte so gewählt werden, dass eine Veröffentlichung mit einer Rate von 55 bis 20Hz20 Hz erfolgt.

  8. Gilt explizit nur für byteOrder bigEndian. Für byteOrder littleEndian wird das Schema AscendingFirstBit gezählt. 2

  9. byte 1 * 8 + rightShift 3 = 11

  10. byte 4 * 8 + rightShift 1 = 33

  11. byte 1 * 8 + rightShift 2 = 10