- Beiträge
- 3.607
- Reaktionspunkte
- 1.045
-> Hier kostenlos registrieren
Hallo zusammen,
Umgebung:
CPU 1217C DC/DC/DC 6ES7 217-1AG40-0XB0 V4.6
TIA Portal V18 Update 2
Ich muss Daten für MQTT Nachrichten aufbereiten, diese werden als UTF-8 kodiertes Byte Array an den Baustein übergeben, der bastelt dann aus dem Topic und der Payload das Telegramm. Soweit so gut.
Aktuell geht es nur darum, die Positionen der Achsen unseres Portals zu übermitteln.
Diese liegen als Real Datentyp vor (kommen über die Schnittstelle als DInt, daraus bastele ich dann die Gleitpunktzahl)
Verwende ich jetzt für die aktuelle Position die Funktion REAL_TO_WSTRING, sieht das ganze so aus:


Ich habe mir aus dem MQTT Baustein den Schnipsel rausgesucht welcher WString in eine UTF-8 kodiertes Byte Array umwandelt kopiert und jetzt für den Fall seperat angewendet. Das passt auch soweit, also der WString stimmt mit dem Inhalt der Nachricht überein:


Zudem werden noch eine ganze Reihe an nicht darstellbaren Zeichen angezeigt, wie man sieht.
Mein Array der Nachricht sieht so aus:

Ich hab das Array mal 100 Byte groß gewählt, weil ich noch nicht weiß, wie lange unsere Payload wird.
Woher kommen die nicht darstellbaren Zeichen, wenn da eine klare 0 drin steht? Hatte in dem Umfang noch nichts mit dem UTF-8 Format zu tun, bzw. schon lange nicht mehr mit Telegrammen gearbeitet welche reine Byte Arrays als Payload haben.
Gibt es eine einfachere Methode als für jeden Datentyp von Werten die ich publishen möchte eine Funktion zu erstellen in der ich erstmal alles in ein Array von WChar umwandele und mir dann meinen WString wieder zusammenbastele?
z.B. möchte ich von der Position nur die drei Stellen vor dem Komma und die ersten drei Nachkommastellen übermitteln, so wie sie auch zB im HMI dargstellt werden.
Das Komma verschiebt sich ja auch abhängig davon ob die Position einstellig, zweistellig oder dreistellig ist, d.h. ich könnte nicht einfach stumpf die Chars zusammensetzen sondern müsste erstmal die Position im Array suchen, an der mein Kommata sitzt?
Hier noch der gesamte Code welcher die Konvertierung in WString und dann ins Byte Array macht.
Der Code wird bewusst zyklisch ausgeführt, da immer die aktuelle Position übermittelt werden soll.
Edit: Hab gerade gesehen, beim schreiben, dass das erste Byte der Nachricht leer war und hab deswegen #statPayloadPos := 1; zu #statPayloadPos := 0; abgeändert.
Danke soweit und einen schönen Freitag, hoffe das war ausführlich genug!
Umgebung:
CPU 1217C DC/DC/DC 6ES7 217-1AG40-0XB0 V4.6
TIA Portal V18 Update 2
Ich muss Daten für MQTT Nachrichten aufbereiten, diese werden als UTF-8 kodiertes Byte Array an den Baustein übergeben, der bastelt dann aus dem Topic und der Payload das Telegramm. Soweit so gut.
Aktuell geht es nur darum, die Positionen der Achsen unseres Portals zu übermitteln.
Diese liegen als Real Datentyp vor (kommen über die Schnittstelle als DInt, daraus bastele ich dann die Gleitpunktzahl)
Verwende ich jetzt für die aktuelle Position die Funktion REAL_TO_WSTRING, sieht das ganze so aus:


Ich habe mir aus dem MQTT Baustein den Schnipsel rausgesucht welcher WString in eine UTF-8 kodiertes Byte Array umwandelt kopiert und jetzt für den Fall seperat angewendet. Das passt auch soweit, also der WString stimmt mit dem Inhalt der Nachricht überein:


Zudem werden noch eine ganze Reihe an nicht darstellbaren Zeichen angezeigt, wie man sieht.
Mein Array der Nachricht sieht so aus:

Ich hab das Array mal 100 Byte groß gewählt, weil ich noch nicht weiß, wie lange unsere Payload wird.
Woher kommen die nicht darstellbaren Zeichen, wenn da eine klare 0 drin steht? Hatte in dem Umfang noch nichts mit dem UTF-8 Format zu tun, bzw. schon lange nicht mehr mit Telegrammen gearbeitet welche reine Byte Arrays als Payload haben.
Gibt es eine einfachere Methode als für jeden Datentyp von Werten die ich publishen möchte eine Funktion zu erstellen in der ich erstmal alles in ein Array von WChar umwandele und mir dann meinen WString wieder zusammenbastele?
z.B. möchte ich von der Position nur die drei Stellen vor dem Komma und die ersten drei Nachkommastellen übermitteln, so wie sie auch zB im HMI dargstellt werden.
Das Komma verschiebt sich ja auch abhängig davon ob die Position einstellig, zweistellig oder dreistellig ist, d.h. ich könnte nicht einfach stumpf die Chars zusammensetzen sondern müsste erstmal die Position im Array suchen, an der mein Kommata sitzt?
Hier noch der gesamte Code welcher die Konvertierung in WString und dann ins Byte Array macht.
Code:
// Delete old data
#statPayloadWString := #WSTRING_EMPTY;
#statPayloadPublishMessage := #tempPayloadPublishMessageEmpty;
#statPayloadPos := 0;
// Get current data
#statPayloadWString := REAL_TO_WSTRING(IN := "DB_Axis".X.PositionData.ActualPosition);
#statTopicWString := WSTRING#'Stationsbezeichnung\AxisX\ActualPosition';
// Convert payload to byte array
FOR #tempConvertLoop := #FIRST_CHARACTER TO LEN(#statPayloadWString) DO
"LMQTT_ConvertToUtf8"(character := #statPayloadWString[#tempConvertLoop],
convertedUtf8 => #statConvertedChar,
bytesUsed => #tempConvertBytesUsed,
error => #tempConvertError,
status => #tempConvertStatus);
CASE #tempConvertBytesUsed OF
#UTF8_1_BYTE:
#statPayloadPublishMessage[#statPayloadPos] := #statConvertedChar.%B0;
#statPayloadPos += 1;
#UTF8_2_BYTE:
#statPayloadPublishMessage[#statPayloadPos] := #statConvertedChar.%B0;
#statPayloadPos += 1;
#statPayloadPublishMessage[#statPayloadPos] := #statConvertedChar.%B1;
#statPayloadPos += 1;
#UTF8_3_BYTE:
#statPayloadPublishMessage[#statPayloadPos] := #statConvertedChar.%B0;
#statPayloadPos += 1;
#statPayloadPublishMessage[#statPayloadPos] := #statConvertedChar.%B1;
#statPayloadPos += 1;
#statPayloadPublishMessage[#statPayloadPos] := #statConvertedChar.%B2;
#statPayloadPos += 1;
END_CASE;
END_FOR;
IF #tempConvertLoop >= LEN(#statPayloadWString) THEN
"DB_Mqtt".Payload.PublishMessage := #statPayloadPublishMessage;
"DB_Mqtt".Interface.InOut.MqttTopic := #statTopicWString;
END_IF;
IF ("DB_Mqtt".Payload.PublishMessage = #statPayloadPublishMessage) AND ("DB_Mqtt".Interface.InOut.MqttTopic = #statTopicWString) AND
(NOT "DB_Mqtt".Interface.Out.Done) THEN
"DB_Mqtt".Interface.In.Publish := 1;
END_IF;
Der Code wird bewusst zyklisch ausgeführt, da immer die aktuelle Position übermittelt werden soll.
Edit: Hab gerade gesehen, beim schreiben, dass das erste Byte der Nachricht leer war und hab deswegen #statPayloadPos := 1; zu #statPayloadPos := 0; abgeändert.
Danke soweit und einen schönen Freitag, hoffe das war ausführlich genug!

Zuletzt bearbeitet: