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) | ||
| stringEncoding5 | Nein4 | STRING | IANA-Name, z.B. "UTF-8", "windows-1252" | 6 | Zeichenkodierung des Strings im Datenpaket (siehe unten) |
| timeFix5 | Nein7 | STRING | "RFC4330", "RFC5905" | "RFC4330" | Behandlung des Überlaufs von time64 im Jahr 2036 (siehe unten) |
| scale | Nein8 | FLOAT | 1 | Skalierungsfaktor des produzierten Werts | |
| offset | Nein8 | FLOAT | 0 | additiver Offset des produzierten Werts | |
| smartCORE | |||||
| name | JA | STRING | Name der Kanals | ||
| dataType | Nein9 | 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 | Nein10 | 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 EN61375 mit Bezug auf ByteOrder, Datentypen, Alignment und Bit-Zählung. - Der bitOffset ist byteOffset * 8 + rightShift - Nicht konforme Konfigurationen werden abgelehnt. |
| ReversedForMsb | Rev Reversed | 11 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)12 Die Norm definiert keine Datentypen, die nicht die Länge einer glatten 2-er Potenz haben. Ein Zahlenwert mit einer anderen bitLength wird verarbeitet, aber beim Start mit einer Warnung im Logfile gemeldet. Ausgenommen sind imageTypes, deren Länge der Typ selbst festlegt (z.B. timedate48).
-
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 .
-
Ein Wert unter 8 bit beginnt und endet im selben Byte. Das gilt auch für eine bitLength, die keine 2-er Potenz ist: Ein 3-bit-Wert mit überschreitet die Byte-Grenze und wird abgelehnt.
Ein Wert unter 8 bit, der die Byte-Grenze überschreitet, wird abgelehnt. Eine bitLength, die keine 2-er Potenz ist, wird gemeldet.
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" | 1113 | 18 |
| ReversedForMsb | BigEndian | 13 | 18 |
| AscendingFirstBit AscendingMSBit | BigEndian | 34 | 18 |
| AscendingLSBit | BigEndian | 49 | 18 |
| (ohne Funktion) | "ABC" | 3314 | 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" | 1015 | 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 | 16 Feste bitLength von 32, IEEE 754 | |
| double | 16 Feste bitLength von 64, IEEE 754 | |
| timedate48 | Feste bitLength von 48, EN 61375-2-1 §6.4.6.2 (TCN, WTB, MVB), siehe Zeitstempel | |
| time64 | Feste bitLength von 64, RFC 1305, siehe Zeitstempel | |
| 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) |
Zeitstempel 'timedate48' und 'time64'
time64 wird ab 1900 gezählt, wie RFC 1305 es festlegt; zuvor lag der Wert 70 Jahre daneben. Ein Zeitstempel 0 wird als 0 weitergegeben.
Beide imageTypes werden in Nanosekunden seit 01.01.1970 (UTC) als dataType int64 produziert. Die Umrechnung erfolgt ganzzahlig, der Sekundenbruchteil wird auf die nächste Nanosekunde gerundet.
| imageType | Aufbau | Bezugszeitpunkt | gültig bis |
|---|---|---|---|
| timedate48 | 32 bit Sekunden (vorzeichenlos) + 16 bit Bruchteil in s | 01.01.1970 | 07.02.2106 |
| time64 | 32 bit Sekunden (vorzeichenlos) + 32 bit Bruchteil in s | 01.01.1900 | siehe timeFix |
Ein Zeitstempel, dessen Bits alle 0 sind, wird als 0 weitergegeben und kennzeichnet damit einen fehlenden Zeitstempel.
Überlauf von time64 im Jahr 2036 'timeFix'
Der Sekundenzähler von time64 läuft am 07.02.2036 um 06:28:16 UTC über. Welche Epoche ein empfangener Wert meint, legt timeFix fest:
| timeFix | Verfahren |
|---|---|
| RFC4330 (Default) | RFC 4330 §3: Ist das höchstwertige Bit der Sekunden gesetzt, liegt die Zeit zwischen 1968 und 2036, sonst zwischen 2036 und 2104. Feste Zuordnung ohne Bezug zur Systemzeit. |
| RFC5905 | RFC 5905 §6: Es gilt die Epoche, die dem Empfangszeitstempel am nächsten liegt. Setzt eine korrekte Systemzeit voraus. |
Weicht ein Zeitstempel um mehr als 30 Jahre vom Empfangszeitstempel ab, wird dies einmalig je Kanal mit beiden Zeitpunkten im Logfile gemeldet. Typische Ursache ist eine Gegenstelle, die Sekunden seit 1970 statt seit 1900 sendet.
Hinweise zur Bestimmung der Länge eines Strings 'stringHint' und 'numElements'
- Jeder String endet am ersten Null-Zeichen, unabhängig vom stringHint.
- bitOffset und bitLength von string und bytearray müssen Vielfache von 8 sein, addressSpec und byteOrder sind dafür ohne Funktion.
- Ohne addressSpec (Default EN61375_MVB) werden Strings als ISO-8859-1 gelesen.
"stringEncoding": "UTF-8"stellt das bisherige Verhalten her.
Strings und Datenfelder (imageType string und bytearray) liegen immer byteweise im Datenpaket:
-
bitOffset und bitLength müssen Vielfache von 8 sein. Andernfalls wird der Kanal beim Start mit einer Meldung im Logfile gesperrt.
-
bitOffset ist die Byte-Position × 8. addressSpec und byteOrder sind ohne Funktion; byteOrder bestimmt nur die Byte-Reihenfolge eines Längenfelds (siehe unten).
Der für den String reservierte Bereich im Datenpuffer ergibt sich aus
-
der bitLength,
-
numElements × bitLength, wenn numElements angegeben ist. bitLength ist dann die Breite eines Zeichens (Default 8 bit, bei U8WLength bis U32WLength und S7WLength 16 bit), oder
-
ohne beide Angaben dem Rest der Botschaft ab bitOffset.
Unabhängig vom stringHint endet jeder String am ersten Null-Zeichen (U+0000) nach der Dekodierung. Was danach im reservierten Bereich steht, wird verworfen. Werden alle Bytes benötigt, ist imageType bytearray zu verwenden.
| Enum | Alias | Beschreibung |
|---|---|---|
| FixedLengthInBits | bitLength | (Default) Der String füllt den reservierten Bereich. |
| NullTerminated | Gleichwertig mit FixedLengthInBits, aus Kompatibilitätsgründen erhalten | |
| FixedLength | numElements definiert die Anzahl an Zeichen im String. | |
| U8Length | Ein uint8 vor dem Text gibt dessen Länge in Bytes an. | |
| U16Length | Ein uint16 vor dem Text gibt dessen Länge in Bytes an. | |
| U32Length | Ein uint32 vor dem Text gibt dessen Länge in Bytes an. | |
| U8WLength5 | Ein uint8 vor dem Text gibt dessen Länge in Worten (2 Bytes, z.B. UTF-16) an. | |
| U16WLength5 | Ein uint16 vor dem Text gibt dessen Länge in Worten an. | |
| U32WLength5 | Ein uint32 vor dem Text gibt dessen Länge in Worten an. | |
| S7Length5 | SIMATIC STRING, siehe unten | |
| S7WLength5 | SIMATIC WSTRING, siehe unten | |
| EndOfMessage | Der String reicht immer bis zum Ende der Botschaft. |
Strings mit Längenfeld
Bei U8Length bis U32WLength steht ab bitOffset ein Längenfeld vor dem Text. Die reservierte Breite aus bitLength bzw. numElements gilt für den Text, das Längenfeld kommt hinzu. Ein Längenfeld aus 2 oder 4 Bytes wird bei byteOrder LittleEndian little endian gelesen, sonst big endian.
Gibt das Längenfeld mehr an, als der reservierte Bereich oder die Botschaft enthält, wird der Text gekürzt und dies einmalig je Kanal im Logfile gemeldet. Fehlt das Längenfeld in der Botschaft, wird kein Wert produziert.
Beispiel U16Length, byteOrder BigEndian, bitOffset 0:
00 02 41 42 43 → "AB"
SIMATIC-Strings 'S7Length' und 'S7WLength'
SIMATIC-Steuerungen legen Strings mit einem Kopf aus deklarierter Maximallänge und aktueller Länge ab. Beide zählen Zeichen. Gelesen werden nur die Zeichen der aktuellen Länge, was dahinter im reservierten Bereich steht, ist ohne Bedeutung.
| stringHint | SIMATIC-Datentyp | Kopf | Zeichen | Default stringEncoding | Maximallänge |
|---|---|---|---|---|---|
| S7Length | STRING[n] | 1 Byte Maximallänge, 1 Byte aktuelle Länge | 1 Byte | windows-1252 | 254 |
| S7WLength | WSTRING[n] | 2 Bytes Maximallänge, 2 Bytes aktuelle Länge, big endian | 2 Bytes | UTF-16BE | 16382 |
numElements entspricht der Deklaration n und ist optional; ohne Angabe gilt der Rest der Botschaft. Der Kopf von S7WLength ist unabhängig von byteOrder immer big endian.
Ist die aktuelle Länge größer als die Maximallänge, wird auf die Maximallänge gekürzt. Dies sowie eine Maximallänge über der Grenze oder abweichend von numElements wird einmalig je Kanal im Logfile gemeldet, der Wert wird trotzdem gelesen.
Beispiel STRING[10] := 'abcdef' mit numElements 10:
0A 06 61 62 63 64 65 66 xx xx xx xx → "abcdef"
Zeichenkodierung 'stringEncoding'
Intern verarbeitet smartCORE alle Strings als Unicode. stringEncoding gibt an, in welcher Kodierung die Bytes im Datenpaket stehen. Ohne Angabe gilt für S7Length "windows-1252", für S7WLength "UTF-16BE", für addressSpec EN61375_MVB "ISO-8859-1" (Latin-1), sonst "UTF-8".
Zulässig sind die Namen und Aliase aus dem IANA-Register "Character Sets". Groß- und Kleinschreibung spielt keine Rolle. Die Aliase mit Präfix cs (z.B. csUTF8) werden nicht unterstützt. Ein unbekannter Name wird beim Start im Logfile gemeldet und der Kanal gesperrt.
Häufig verwendete Kodierungen und die Bytes einiger Zeichen:
| stringEncoding | ä | Ä | ß | € | ° | µ | ² |
|---|---|---|---|---|---|---|---|
| UTF-8 | C3 A4 | C3 84 | C3 9F | E2 82 AC | C2 B0 | C2 B5 | C2 B2 |
| ISO-8859-1 (Latin-1) | E4 | C4 | DF | – | B0 | B5 | B2 |
| ISO-8859-15 (Latin-9) | E4 | C4 | DF | A4 | B0 | B5 | B2 |
| windows-1252 | E4 | C4 | DF | 80 | B0 | B5 | B2 |
| IBM437 (cp437) | 84 | 8E | E1 | – | F8 | E6 | FD |
| UTF-16BE (MVB UNICODE16) | 00 E4 | 00 C4 | 00 DF | 20 AC | 00 B0 | 00 B5 | 00 B2 |
| US-ASCII | – | – | – | – | – | – | – |
US-ASCII kennt nur die Bytes 00 bis 7F. Ein Zeichen, das in der Kodierung nicht vorhanden ist, oder eine ungültige Bytefolge erscheint im Kanal als Ersatzzeichen „�“ (U+FFFD).
Jede Botschaft wird für sich dekodiert. Eine Bytefolge, die am Ende des Datenbereichs abgeschnitten ist, wird nicht mit der nächsten Botschaft zusammengesetzt, sondern ebenfalls als „� “ ausgegeben.
Typische Fehlerbilder bei falscher Einstellung:
| Anzeige im Kanal | Ursache |
|---|---|
ä statt ä | Die Daten sind UTF-8, eingestellt ist ISO-8859-1 oder windows-1252. |
� statt ä | Die Daten sind ISO-8859-1 oder windows-1252, eingestellt ist UTF-8. |
„ statt ä | Die Daten sind IBM437, eingestellt ist windows-1252. |
Hinweise zur Bestimmung der Länge eines Datenfeldes 'numElements'
Auch für Datenfelder gilt die Byte-Ausrichtung von bitOffset und bitLength (siehe oben).
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.
Ein numerischer imageType kann keinen dataType String, ByteArray oder GpsLocation füllen; ein solcher Kanal wird beim Start mit einer Meldung abgeschaltet, die beide Typen nennt.5
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, ...) |