TIA Chars aus einzelnen Werten zusammenfügen

BaumimGarten

Level-1
Beiträge
63
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo Leute,

Ich bin gerade dabei ein JSON Telegram aus Zahlenwerten und Zeichen zusammen zusetzen und über MQTT zu verschicken. Bisher habe ich alle meine Werte und Zeichen in einen String umgeformt, um diese dann mit "concat" zusammenzufassen und anschließend in ein Char umgewandelt, um das Telegram für den MQTT Baustein lesbar zu machen.
Jedoch habe ich mittlerweile ein Problem, weil ein String ja nur eine Länge von max. 256 Zeichen hat und meine gesendeten Daten diese Länge überschreiten würde.
JSON Telegram als String sieht ungefähr so aus :
{"ts":166784105,"v01":0.000000E0,"min_v01":0.000000E0,"max_v01":0.000000E0,"v02":0.000000E0,"min_v02":0.000000E0,.......}
Um mein Problem zu lösen habe ich 2 Ansätze, jedoch weiß ich nicht welcher sinniger ist.

Meine Zahlenwerte bestehen aus Real zahlen, da ich ebenfalls Kommerzahlen anzeigen lassen muss. Hier könnte ich allerdings glaub ich einsparen, wenn ich eine Möglichkeit finde die Nachkommazahlen zu verringern, da ich maximal die zweite Stelle brauche. Wenn ich ein Real mit "Real_to_String umwandle, wird dieser immer mit "0.000000E0" angezeigt.

Alternative wäre, wenn ich einen anderen Weg finde meinen JSON nicht als String zusammenzufasse, sondern direkt als Char. Ich übergebe meinem MQTT Client im Endeffekt nur ein Array of Byte, weshalb ich da größeren Spielraum habe, als mit meinem 256 String. Ich könnte zwar mehrere Pakete in ein Array packen allerdings, hab ich das noch nie gemacht, aber es klingt für mich nach einer großen Fummelarbeit, um die Stelle zu finden wo dann das nächste Paket in das Array gesetzt werden muss.

Ich benutze eine S7 1200er mit TIA 16 und programmiere überwiegend in SCL

Vielleicht kann mir ja jemand dabei helfen
MfG Fabian
 
Concat, kann auch WSTRING und WSTRING kann mehr, hier der Text auf der Siemens Hilfe:

Bei der Deklaration eines Operanden vom Datentyp WSTRING können Sie mithilfe von eckigen Klammern seine Länge definieren (z. B. WSTRING[10]). Wenn Sie keine Längenangabe machen, dann wird die Länge des WSTRINGs auf 254 Zeichen eingestellt. Sie können eine Länge von maximal 16382 Zeichen deklarieren (WSTRING[16382]).
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Wenn ich ein Real mit "Real_to_String umwandle, wird dieser immer mit "0.000000E0" angezeigt.
Was ist das für ein "Real_to_String" Baustein. VAL_STRG ?
Um Zeichen zu sparen kannst du eventuell mit ein INT oder DINT arbeiten, und angenommene Fraktionziffern, wie DINT 12345 soll als 123.45 interpretiert werden.
Dann kannst du die VAL_STRG Parameter anpassen dass du ein STRING "123.45" bekommst.
Und mit Strg_TO_Chars kannst du die STRING oder WSTRING in ein CHAR Array (oder BYTE array) umwandeln.
 
Concat, kann auch WSTRING und WSTRING kann mehr, hier der Text auf der Siemens Hilfe:

Bei der Deklaration eines Operanden vom Datentyp WSTRING können Sie mithilfe von eckigen Klammern seine Länge definieren (z. B. WSTRING[10]). Wenn Sie keine Längenangabe machen, dann wird die Länge des WSTRINGs auf 254 Zeichen eingestellt. Sie können eine Länge von maximal 16382 Zeichen deklarieren (WSTRING[16382]).
Also wenn ich eine Zeichenkette von maximal 300 Zeichen brauche, würde ich das dann im Endeffekt wie folgt machen?
Code:
JSON_String[300] := CONCAT_STRING(IN1 := '{"ts":', IN2 := REAL_TO_STRING(IN := Zeitstemepl),
                                  IN3 := ',"v01":', IN4 := REAL_TO_STRING(IN := Wert_v01)
                                  .......
                                  );
Müssen dabei dann auch die einzelnen Elemente die man zusammenfasse will auch WString sein ?

Was ist das für ein "Real_to_String" Baustein. VAL_STRG ?
Um Zeichen zu sparen kannst du eventuell mit ein INT oder DINT arbeiten, und angenommene Fraktionziffern, wie DINT 12345 soll als 123.45 interpretiert werden.
Dann kannst du die VAL_STRG Parameter anpassen dass du ein STRING "123.45" bekommst.
Und mit Strg_TO_Chars kannst du die STRING oder WSTRING in ein CHAR Array (oder BYTE array) umwandeln.

Wenn ich das wüsste XD
Ich gehe von VAL_STRG aus, ist halt schwierig zu sagen weil ich ja in SCL arbeite und einfach nur Keyword "REAL_TO_.." eingebe.
Aber das klingt auch gut hatte mich zwar von gescheut, weil das dann doch Schreibarbeit ist, die ich vermeiden wollte aber sieht halt deutlich besser aus.

Vielen dank für eure Antworten

ZUSATZ: Okay hab es schon gesehen dass ich die WString Länge im Datentypen eintragen muss
 
Müsste so aussehen:
Code:
#JSON_String := CONCAT_WSTRING(IN1 := WSTRING#'{"ts":', IN2 := REAL_TO_WSTRING(IN := #Zeitstemepl),
                               IN3 := WSTRING#',"v01":', IN4 := REAL_TO_WSTRING(IN := #Wert_v01)
);

Ich weiß aber nicht ob dein Kommunikationspartner mit dem WString klar kommt.
Beim WString ist ein Zeichen 16Bit groß und Unicode (UCS2).
Kann sein das der nur mit UTF8 (oder ASCII) klar kommt.
 
Und mit Strg_TO_Chars kannst du die STRING oder WSTRING in ein CHAR Array (oder BYTE array) umwandeln.
Eine Frage hätte ich noch. Logischerweise gibt TIA mir ein Fehler aus wenn ich ein WString in ein Array of Char oder Bytes umwandeln will.
Deswegen will ich nochmal nachdem ich den WString in WChar umgewandelt habe aus dem WChar ein Char machen.
Muss ich dafür jedes Element des Arrays anfassen? (also dann logischerweise über ne Funktion)
Oder kann ich da einfach das ganze Wchar Array nehmen und in das Char Array convertieren?
 
Die Biblitoteksbaustein Strg_TO_Chars kann ein STRING oder WSTRING in ein Array of CHARs in einen Ruck machen.
edit: Ist falsch. Von STRING nach CHAR Array oder von WSTRING nach WCHAR Array. Siehe unten.
Die Baustein kannst du auch in SCL aufrufen.

Ich glaube nicht dass du ein WCHAR Array brauchst.
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
1666865122450.png

Laut der Beschreibung des Bausteines bin ich ganz bei dir aber irgendwie gibt er mir doch ein Fehler aus

NACHTRAG: Erst wenn ich aus dem Char einen WChar mache funktioniert es.
 
Zuletzt bearbeitet:
Laut Siemens Hilfe geht es nicht direkt von WSTRING zu Array of CHAR.
Code:
Mit der Anweisung "Strg_TO_Chars" kopieren Sie eine Zeichenkette vom Datentyp STRING in ein Array of CHAR oder Array of BYTE
bzw. eine Zeichenkette vom Datentyp WSTRING in ein Array of WCHAR oder Array of WORD. 
Für den Kopiervorgang sind ausschließlich ASCII-Zeichen gültig.

Musst du in dem fall in einer Schleife machen:
Code:
FOR #tmpCount := 1 TO LEN(#JSON_String) DO
    #sendewachr[#tmpCount]:= WCHAR_TO_CHAR(#JSON_String[#tmpCount]);
END_FOR;
 
Laut Siemens Hilfe geht es nicht direkt von WSTRING zu Array of CHAR.
Das ist korrekt. Ich lese jetzt
With the "Strg_TO_Chars" instruction, you copy a character string of the data type STRING to an Array of CHAR or Array of BYTE or a character string of the data type WSTRING to an Array of WCHAR or Array of WORD.

Wenn die ARRAY an MQTT grösser als 255 CHARs einhalten soll, dann muss man etwas speziell programmieren.
Für MQTT verwendet man wohl ein Biblioteksbaustein; kann diese Baustein Arrays grösser als 255 CHARs akseptieren ?
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Jedoch habe ich mittlerweile ein Problem, weil ein String ja nur eine Länge von max. 256 Zeichen hat und meine gesendeten Daten diese Länge überschreiten würde.
Na ja, sagen wir mal bei SCL maximal 254 Zeichen.
Das Stichwort "Telegramm" lässt mich aber aufhorchen.
Was ist mit dem Empfänger des Telegramms? Welche maximale TelegrammLänge kann er denn verarbeiten?

Meine Zahlenwerte bestehen aus Real zahlen, da ich ebenfalls Kommerzahlen anzeigen lassen muss. Hier könnte ich allerdings glaub ich einsparen, wenn ich eine Möglichkeit finde die Nachkommazahlen zu verringern, da ich maximal die zweite Stelle brauche. Wenn ich ein Real mit "Real_to_String umwandle, wird dieser immer mit "0.000000E0" angezeigt.
Die Anzahl der NachkommaStellen auf 'n' zu begrenzen, ist "im Prinzip" einfach:
Code:
TempString := DINT_TO_STRING(REAL_TO_DINT(RealZahl * 10.0 ** n)) ;
String := CONCAT(IN1:=LEFT(TempString, LEN(TempString)-n), IN2:=KommaZeichen, IN3:=RIGHT(TempString, n)) ;
Aber es lauern FallStricke.

Das Stichwort "Telegramm" lässt mich schon wieder aufhorchen.
Welches Zeichen erwartet der Empfänger als "DezimalKommaZeichen"? ',' oder '.' oder akzeptiert er beide?
Welche ZahlenDarstellung erwartet der Empfänger?
Akzeptiert er z.B. die GanzZahl '12345', wenn er eine REAL-Zahl erwartet? Oder muss sich die Zahl durch das KommaZeichen als GleitKommaZahl zu erkennen geben (also z.B. '12345.')?
Kommt er mit den Schreibweisen '0' oder '0.' oder '.0' oder '0.0' oder '.' für eine Null gleichermaßen klar?
Wo erwartet er das Vorzeichen (vor der Zahl oder dahinter oder funktionieren beide Varianten)?
Muss eine positive Zahl das Vorzeichen enthalten?
Darf eine positive Zahl das Vorzeichen enthalten?
Erwartet er grundsätzlich/ausschliesslich die ExponenzialSchreibweise?
Kann er die ExponenzialSchreibweise überhaupt verarbeiten? Wenn ja, wie muss/darf diese konkret aussehen?
U.s.w. ...

Unabhängig von der ZahlenDarstellung wittere ich weiteres SparPotenzial.
Müssen die Bezeichner der Zahlen bzw. die SpaltenÜberschriften der Tabelle (z.B. "ts": ...,"v01": ...,"min_v01": ...,"max_v01": ...,"v02": ...,"min_v02": ...) in derselben Zeile geliefert werden wie die dazugehörigen Zahlen?
Oder könnte man diese vorab in einer eigenen Zeile übergeben, wie es z.B. bei csv-Dateien möglich ist?
Sind die "TrennZeichen" ':' zwischen den Bezeichnern und den Zahlen entbehrlich? Eigentlich sollte die Abgrenzung durch die GänseBeinchen (") schon ausreichen, sofern als Werte nur Zahlen und keine Texte ausgegeben werden.

Ehe ich eine Verdopplung der Anzahl Byte (= TelegrammLänge) durch die Verwendung von WSTRING an Stelle von STRING überhaupt in Erwägung ziehen würde, würde ich zunächst versuchen, die obigen Fragen zu klären und zu prüfen, wie gross das SparPotenzial überhaupt sein kann und ob die Einsparungen auch in Zeilen, in denen sich die "HärteFälle" häufen, überhaupt ausreichen würden.

Die Verwendung von WSTRING produziert m.E. mehr Probleme, als sie löst. Selbst wenn man sie nicht im Telegramm, sondern nur "sender-intern" verwendet, um irgendwelche vermeintlichen SparPotenziale zu erzielen.

Ich übergebe ... im Endeffekt nur ein Array of Byte, weshalb ich da größeren Spielraum habe, als mit meinem 256 String.
Hmmm, wie sieht es mit der Obergenze der TelegrammLänge aus? Beim Sender? Beim Empfänger?
Wenn auch eine dieser beiden bei 254 Zeichen oder 255 Byte liegen sollte, wo und wie soll sich durch diese Massnahme ein "grösserer SpielRaum" ergeben?
Kann denn der Empfänger diese grössere TelegrammLänge überhaupt verarbeiten?
Falls nicht, ist der Emfänger evtl. in der Lage, zwei aufeinanderfolgende Telegramme (<255 Byte) zu einer Einheit von (>254 Bxte) zusammenzufassen (wenn das erste "TeilTelegramm" nicht mit einem LF endet) und diese Einheit als 1 "Telegramm" zu interpretieren und auszuwerten?
 
Wenn die ARRAY an MQTT grösser als 255 CHARs einhalten soll, dann muss man etwas speziell programmieren.
Für MQTT verwendet man wohl ein Biblioteksbaustein; kann diese Baustein Arrays grösser als 255 CHARs akseptieren ?
-Prinzipiell sehe ich nicht was da gegen spricht, da es standardmäßig von der Bibliothek mit einem Array of Byte [0...999] erstellt wird, jedoch getestet habe ich das nur kurz am Rand, dass der MQTT Client ein größeres Telegramm als 254 Zeichen schicken kann und der Mosquitto Broker das auch auslesen kann.

@Heinileini
Das Übertragen funktioniert alles schon, nur die längeren Telegramme bzw. JSON Objekte leider noch nicht wegen den bekannten Begrenzungen des Datentyps.
Im Broker selber kommen die Telegramme so an:

[ATTACH type="full"]64561[/ATTACH]

Dahinter ist noch ein OPC UA Server geschaltet, der es für weitere Zwecke in Double umwandelt. Und nein ich kann die MQTT Verbindung nicht weg lassen und direkt über OPC UA gehen. Der OPC UA Server ist momentan nur dazwischen geschalten, weil die Webvisus etc. noch nicht 100% auf MQTT ausgelegt sind, jedoch in Zukunft alles über MQTT laufen soll.

Unabhängig von der ZahlenDarstellung wittere ich weiteres SparPotenzial.
Müssen die Bezeichner der Zahlen bzw. die SpaltenÜberschriften der Tabelle (z.B. "ts": ...,"v01": ...,"min_v01": ...,"max_v01": ...,"v02": ...,"min_v02": ...) in derselben Zeile geliefert werden wie die dazugehörigen Zahlen?
Du meinst, dass man mehrere kleinere Telegramme schickt?
Wäre zu mindestens eine Übergangslösung, jedoch glaube ich schon, dass ich nicht ganz darauf verzichten kann größere Objekte zu schicken. Durch das JSON Format sind allerdings die "" und : vorgeschrieben, damit der OPC UA bzw. der Rest das erkennt. So weit wie ich das verstanden habe, ist es dem Broker egal was er bekommt, nur das Format im Broker sollte dann auch für die weiterführenden Programme stimmen, das ist aber alles noch in Progress.

MfG Fabian
 

Anhänge

  • 1666938757687.png
    1666938757687.png
    35,3 KB · Aufrufe: 10
Zuletzt bearbeitet:
-Prinzipiell sehe ich nicht was da gegen spricht, da es standardmäßig von der Bibliothek mit einem Array of Byte [0...999] erstellt wird, jedoch getestet habe ich das nur kurz am Rand, dass der MQTT Client ein größeres Telegramm als 254 Zeichen schicken kann und der Mosquitto Broker das auch auslesen kann.
Umso besser, wenn die maximale Länge des Telegramms nicht ebenfalls bzw. zusätzlich ein Nadelöhr bildet.
Die TeilStrings, die erst in der Summe ihrer belegten Bereiche die Länge des Telegramms ergeben, sind ja nicht annähernd 254 Zeichen lang.
Also lassen sie sich problemlos erzeugen, um dann in ein Array of BYTE oder CHAR eingebracht zu werden.
Du meinst, dass man mehrere kleinere Telegramme schickt?
Ja, das hätte ich in Erwägung gezogen, wenn auch die maximale TelegrammLänge so sehr eingeschränkt wäre, dass sie ein "Hindernis" dargestellt hätte.
Wäre zu mindestens eine Übergangslösung, jedoch glaube ich schon, dass ich nicht ganz darauf verzichten kann größere Objekte zu schicken.
Es wäre eine NotLösung gewesen, wenn eine Begrenzung der TelegrammLänge ein Aufspalten in mehrere Telegramme erfordert hätte.
Durch das JSON Format sind allerdings die "" und : vorgeschrieben, damit der OPC UA bzw. der Rest das erkennt. So weit wie ich das verstanden habe, ist es dem Broker egal was er bekommt, nur das Format im Broker sollte dann auch für die weiterführenden Programme stimmen, das ist aber alles noch in Progress.
Die TelegrammLänge scheint zum Glück nicht das Problem zu sein, das hier geknackt werden müsste.
Das JSON Format brauchen wir also gar nicht erst auf weiteres SparPotenzial zu untersuchen.
Ich hab dein Beispiel noch nicht 100% verstanden. Die Rechnung an sich versteh ich, aber muss es nicht noch ein Schritt geben, in dem der String in "LEFT" und "RIGHT" aufgesplittet werden muss?
In meinem Beispiel geht es nur darum, eine REAL-Zahl in eine DINT-Zahl zu wandeln, um die "überflüssigen" NachkommaStellen abzuschneiden zu können.
Die wenigen NachkommaStellen, die erhalten werden sollen, werden vorher durch Multiplikation mit einer ZehnerPotenz (10 für 1 NachkommaStelle, 100 für 2 NachkommaStellen, u.s.w.) "gerettet". Nach der Umwandlung der DINT-Zahl in einen String, wird noch das KommaZeichen an der entsprechenden Stelle eingefügt. Nicht mehr und nicht weniger.
Damit wollte ich nur einen Weg andeuten, der aber auch schnell an seine Grenzen kommt und ungeahnt viel DetailArbeit erfordert.
Der durch die Umwandlung von DINT in STRING erzeugte String, könnte z.B. zu kurz sein, um an einer vorgegebenen Stelle ein KommaZeichen einzufügen (Beispiel: um '0.00' zu erzeugen, müsste die Zahl '0' zunächst um 2 weitere Nullen auf '000' aufgepeppelt werden).
Das SparPotenzial ist abhängig von der darzustellenden Zahl und auch das muss natürlich noch berücksichtigt werden. Die Exponenzial-Darstellung kann auch mal die kürzere/bessere sein.
Die begrenzte Anzahl der relevanten Stellen beim DatenTyp REAL sollte natürlich auch im Auge behalten werden, wenn man sich den Kopf über SparPotenzial zerbricht. Z.B. könnten die zwei NachkommaStellen, die man eigentlich erhalten möchte, in dem SonderFall, dass die relevanten Stellen schon im Bereich der VorkommaStellen "aufgebraucht" sind, auch ganz entfallen. Für die Übertragung der ZahlenWerte im Telegramm sind die NachkommaStellen nicht wichtig. Wohl aber, wenn man die Zahlen vor dem Senden bereits "augenfreundlich" zur Darstellung am Bildschirm oder im Ausdruck aufbereiten möchte (z.B. ausgerichtet nach der Position des Kommas).
bzw. wäre das nicht eine absolute Platzverschwendung? da man ja quasi pro Zahlenwert 3 Strings hat ergo 3*256 Byte = 768 Byte?
oder werden nur die tatsächlichen Zeichen gewertet, also nur die Zeichen umgewandelt in Byte?
Die String-Befehle "wissen", in welcher Länge die "Behälter" tatsächlich belegt sind. Die Länge der "Behälter" gibt der Programmierer (lang genug) vor. In welcher Länge sie dann tatsächlich belegt werden, hängt aber von den Zahlen ab und auch von den Regeln, die man sich für die Umwandlung ausdenkt.
Deine Bedenken wegen "3*256 Byte = 768 Byte" sind unbegründet. Selbst die Längen der "Behälter" für die ZwischenErgebnisse sind bezogen auf das komplette Telegramm irrelevant, da die Länge der einzelnen "Behälter", die zum Telegramm zusammengestückelt werden, sich nicht auf die Länge des "Behälters" des Telegramms auswirken. Sie werden nur temporär belegt.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Vielen dank, dass du dir die ganze Arbeit mit machst :)
Deine Bedenken wegen "3*256 Byte = 768 Byte" sind unbegründet.
Das ist auf jeden fall schon mal ein guter Hinweis!
Ich hatte jetzt schon mal meine Teilstring nochmal wie du schon vorgeschlagen hattest, in meine gewünschte Form, umgewandelt. Gleichzeitig kam gerade nochmal ein Arbeitskollege zu mir und hat mir den JSON Serialisier Baustein aus der LStream Bibliothek ( https://support.industry.siemens.co...ek-für-daten-streams-(lstream)?dti=0&lc=de-DE ) von Siemens ans Herz gelegt.
Jedoch hab ich bis jetzt es noch nicht geschafft den zum Laufen zu bringen. ich bin immer die gleiche Fehlermeldung dass meine JSON-Tiefe in der Baumstruktur nicht angegeben wurde.
Ich bin noch nicht dahinter gekommen was das genau heißt, werde es aber nochmal probieren einzelne Telegramme seriell zu schicken, damit zu mindestens etwas funktioniert.
 
Gleichzeitig kam gerade nochmal ein Arbeitskollege zu mir und hat mir den JSON Serialisier Baustein aus der LStream Bibliothek ( https://support.industry.siemens.com/cs/document/109781165/bibliothek-für-daten-streams-(lstream)?dti=0&lc=de-DE ) von Siemens ans Herz gelegt.
Jedoch hab ich bis jetzt es noch nicht geschafft den zum Laufen zu bringen. ich bin immer die gleiche Fehlermeldung dass meine JSON-Tiefe in der Baumstruktur nicht angegeben wurde.
Ich kenne den Baustein leider nicht und kann Dir hierbei nicht weiterhelfen ...
 
Zurück
Oben