Step 7 JSON-String in S7 1200 erstellen?

chrisdutz

Level-2
Beiträge
52
Reaktionspunkte
2
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

ich experimentiere gerade ein wenig mit den MQTT Fähigkeiten meiner S7. Soweit habe ich es schon hinbekommen, dass ich einen vorbereiteten text an den MQTT broker schicke, nur will ich nicht immer manuell byte arrays editieren, sondern vielmehr würde ich am liebsten einen UDT oder eine Struct mit werten initialisieren und dann irgendwie in ein byte-array im JSON format serialisieren.

Gibt's da irgendwelche möglichkeiten? Bisher komme ich beim suchen immer wieder auf die REST API der S7, allerdings hilft mir das innerhalb meines Programms leider nicht viel.

Wäre sehr Dankbar für Hinweise.

Viele Grüße,
Chris
 
In der LStream Bibliothek gibts Bausteine zum serialisieren und wieder de-serialisieren für XML und JSON Formate

Ich weiß nicht wie aktuell die Version ist, falls bei dir auch die Funktion "LStream_JsonSerializer" das erste Element im MQTT fehlen sollte, kann ich dir meine vom Support angepasste Quelle geben.

Ansonsten kannst du mal bei meinen erstellten Themen durchstöbern, da ist viel zum Thema MQTT und JSON im TIA Portal.
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hi,
In der tat bin ich kurz nachdem ich meine Frage abgeschickt habe auch auf die LStream lib gestoßen. Es klingt in der Tat, als wäre das ziemlich genau das, was ich suche. Ich werde mal ein wenig damit rumspielen und Rückmeldung geben, ob's damit geklappt hat.

Gruß,
Chris
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Zugegebenermaßen habe ich erstmal mit CONCAT einen JSON string gebaut, weil ich irgendwie nicht so recht durchgestiegen bin, wie man die Datenstrukturen im SCL code manuell baut ... alle beispiele haben nur einen JSON string perparsed und den dann wieder serialisiert und ich konnte nirgends sehen, wie man die Struktur selbst initialisiert.

Um diese Inhalte anzuzeigen, benötigen wir die Zustimmung zum Setzen von Drittanbieter-Cookies.
Für weitere Informationen siehe die Seite Verwendung von Cookies.
 
Hallo, wäre es möglich mal ein Beispiel von dieser Dateninitialisierung zu sehen? Ich versuche schon eine ganze Weile eine JSON Datenstruktur aus meinen SPS Daten zu erstellen, aber ich steige absolut nicht durch, wie man das realisieren kann.
 
Wenn du dich an die Bibliothek von Siemens hältst..

Ein Json Tree besteht aus n Elementen, und das Element hat Attribute welche du dann befüllen musst, dadurch ergibt sich dann ein fertiges Json File, welche dann wieder als Bytestream an den Mqtt Broker geht.

Beispiel:
Code:
#tempIndex := #constUSINT;

REGION Light barriers
    #oTree[#tempIndex].closingElement := 0;
    #oTree[#tempIndex].depth := 0;
    #oTree[#tempIndex].key := 'LightBarriers';
    #oTree[#tempIndex].type := "JSON_TREE_TYPE_0_ELEMENT_OBJECT";
    #oTree[#tempIndex].value := 'NULL';
    #tempIndex := #tempIndex + 1;
    
    #oTree[#tempIndex].closingElement := 0;
    #oTree[#tempIndex].depth := 1;
    #oTree[#tempIndex].key := 'InFrontSeparator';
    #oTree[#tempIndex].type := "JSON_TREE_TYPE_2_TEXT_STRING";
    #oTree[#tempIndex].value := "FC_BOOL_TO_STRING"(#iSensors.InFrontSeparator);
    #tempIndex := #tempIndex + 1;
    
    #oTree[#tempIndex].closingElement := 0;
    #oTree[#tempIndex].depth := 1;
    #oTree[#tempIndex].key := 'InSeperator';
    #oTree[#tempIndex].type := "JSON_TREE_TYPE_2_TEXT_STRING";
    #oTree[#tempIndex].value := "FC_BOOL_TO_STRING"(#iSensors.InSeparator);
    #tempIndex := #tempIndex + 1;
    
    #oTree[#tempIndex].closingElement := 1;
    #oTree[#tempIndex].depth := 1;
    #oTree[#tempIndex].key := 'InTool';
    #oTree[#tempIndex].type := "JSON_TREE_TYPE_2_TEXT_STRING";
    #oTree[#tempIndex].value := "FC_BOOL_TO_STRING"(#iSensors.InTool);
    #tempIndex := #tempIndex + 1;
END_REGION

REGION Pressure switches
    #oTree[#tempIndex].closingElement := 0;
    #oTree[#tempIndex].depth := 0;
    #oTree[#tempIndex].key := 'PressureSwitches';
    #oTree[#tempIndex].type := "JSON_TREE_TYPE_0_ELEMENT_OBJECT";
    #oTree[#tempIndex].value := 'NULL';
    #tempIndex := #tempIndex + 1;
    
    #oTree[#tempIndex].closingElement := 0;
    #oTree[#tempIndex].depth := 1;
    #oTree[#tempIndex].key := 'ChannelA';
    #oTree[#tempIndex].type := "JSON_TREE_TYPE_2_TEXT_STRING";
    #oTree[#tempIndex].value := "FC_BOOL_TO_STRING"(#iSensors.ChannelA);
    #tempIndex := #tempIndex + 1;
    
    #oTree[#tempIndex].closingElement := 0;
    #oTree[#tempIndex].depth := 1;
    #oTree[#tempIndex].key := 'ChannelB';
    #oTree[#tempIndex].type := "JSON_TREE_TYPE_2_TEXT_STRING";
    #oTree[#tempIndex].value := "FC_BOOL_TO_STRING"(#iSensors.ChannelB);
    #tempIndex := #tempIndex + 1;
    
    #oTree[#tempIndex].closingElement := 1;
    #oTree[#tempIndex].depth := 1;
    #oTree[#tempIndex].key := 'Value';
    #oTree[#tempIndex].type := "JSON_TREE_TYPE_3_NUMBER";
    #oTree[#tempIndex].value := "FC_REAL_TO_STRING"(#iSensors.PressureValue);
END_REGION

Sieht dann so aus:
JSON:
{
    "LightBarriers": {
        "InFrontSeparator": "FALSE",
        "InSeperator": "TRUE",
        "InTool": "FALSE"
    },
    "PressureSwitches": {
        "ChannelA": "TRUE",
        "ChannelB": "TRUE",
        "Value": 4.751
    }
}
 
Zuletzt bearbeitet:
Zuviel Werbung?
-> Hier kostenlos registrieren
Ja, die hatte ich mir angeschaut, aber leider war es mir, mit der von Siemens vorhandenen Dokumentation, nicht möglich das umzusetzen.
Ich habe nicht so richtig verstehen können, wie ich das am besten umsetze.
 
Zugegebenermaßen habe ich den einfachen weg genommen und habe mit CONCAT einfach einen String zusammen gebaut. Die LStream lib, habe ich nur Beispiele gefunden, wie man ein JSON Dokument lädt und das dann wieder Schreibt allerdings keine Doku darüber, wie man die Datenstrukturen manuell bauen würde. Ich konnte ich nicht rein debuggen, weil ich nur eine S7-1200 hatte ... nun habe ich eine S7-1500 ... daher werde ich mir das mal genauer anschauen und schauen wie man die Datenstrukturen initialisieren muss.

Bis es soweit ist, ist hier mein code, den ich benutzt habe:

Code:
// If we're currently not doing anything and we detected a new token, initialize the
// structures and send am mqtt message.
IF NOT("LMQTT".publish) AND NOT("LMQTT".messageSent) AND ("Data"."White Detected" OR "Data"."Red Detected" OR "Data"."Blue Detected") THEN
    // Get the local time, convert that to a unix timestamp and serialize that to a string.
    #retReadTime := RD_SYS_T(#curTime);
    #longCurTime := "LGF_DTLToUnixTime"(timeDTL := #curTime, error => #dtConvError, status => #dtConvStatus);
    #strCurTime := "LGF_IntToString"(#longCurTime);
    
    // Set the right color of token in the message.
    IF "Data"."White Detected" THEN
        #strColor := 'green';
    ELSIF "Data"."Red Detected" THEN
        #strColor := 'red';
    ELSIF "Data"."Blue Detected" THEN
        #strColor := 'blue';
    END_IF;
    
    // Assemble the message string.
    #messageString := CONCAT(IN1 := '{"device": "root.factory.sortinglane", "timestamp": "', IN2 := #strCurTime, IN3 := '", "measurements": ["color"], "values":["', IN4 := #strColor, IN5 :='"]}');
    
    // Serialize the string into an byte array and tell the MQTT client to send it.
    FOR #i := 0 TO LEN(#messageString) DO
        "LMQTT".publishMsgPayload[#i - 1] := CHAR_TO_BYTE(STRING_TO_CHAR(MID(IN := #messageString, L := 1, P := #i)));
    END_FOR;
    "LMQTT".publichMsgLen := LEN(#messageString);
    "LMQTT".publish := TRUE;
    
    "LMQTT".messageSent := TRUE;
END_IF;

// As soon as the MQTT Client is finshed sending the message, clear the buffer.
IF "LMQTT".done THEN
    "LMQTT".publish := FALSE;
    "LMQTT".done := FALSE;
    // Reset the array.
    FOR #i := 0 TO 999 DO
        "LMQTT".publishMsgPayload[#i] := 0;
    END_FOR;
    "LMQTT".numMessagesSent := "LMQTT".numMessagesSent + 1;
END_IF;
 
Warum willst du denn dein Json File händisch bauen, wenn dir Siemens Funktionen gibt, mit denen nur die Elemente befüllen musst und den Rest dann die Funktionen übernehmen?

Json Elemente befüllen > serialisieren > publish ausführen
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Ich vermute ja, dass man ein Array anlegen muss mit einem element für jedes JSON element (also wirklich jedes element und nicht nur die root-elemente) ... dass dann jedes element eine ID bekommt und man irgendwie in jedem element die ID von seinem parent angeben kann (anders kann ich mir das nicht vorstellen). Die Wurzel ist dann die menge aller elemente im array ohne parent-id. Aber leider sind da so viele attribute, dass ich das nicht einmal probieren wollte, ohne mit dem Debugger mir das mal anzusehen.
 
Ist der von Siemens angedachte weg, dass man ein Dummy-JSON baut und dann in der Function einzelne werte überschreibt? Oder wie bekomme ich das hin, dass ich dynamisch prozess werte mitgeben kann? Eigentlich liebäugle ich auch damit eine Lib zu bauen, bei der man sozusagen im Structured Text sagen kann "LogValue('value-name', value)" und am ende dann sagen kann (z.B. am Ende eines produktionszyklus) "SendValues" und dann schickt der alle telemetriedaten, die der Automatisierungingenieur in seinem ST während eines Produktionszyklusses gesammelt hat. Das wäre mit einem Statischen JSON template eher schwer.
 
Hab dir mal ein Beispiel oben angehangen von mir. Jede Zeile Text im Json ist quasi ein Element, über depth und closingElement werden eben die Klammern passend gesetzt. Ein Array musst du anlegen, irgendwo musst die Daten ja speichern, welche du publishen möchtest. Die Payload für MQTT ist ja auch ein Array of Byte.

Was meinst du mit dynamisch? Dass sich der Aufbau deiner Json File ändert? Das denke ich geht nicht, da ja die Größe deines Json Trees bestimmt, wie groß der Bereich der Payload sein muss.

Zudem halte ich persönlich nichts davon, wenn so etwas nicht vorher definiert ist, dann landen die Werte immer irgendwo anders und es wird ein Sandkasten daraus. Telegramme gehören definiert und sich daran gehalten (Thema Standardisierung)
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hehe ... glaube hier prallen halt zwei welten aufeinander ... IT und OT ... und ich stimme dir zu ... aber auch sehe ich durchaus potential in dynamischen Telegrammen, die bei "hinzufügen eines zusätzlichen parameters" nicht gleich weider anpassungen in 10 stellen erfordern.

Klar braucht man ein Array, da in ST hierarchiche strukturen nicht möglich sind (Also dass ich für ein Element eine variable anzahl von kind-elementen allokieren könnte. Daher macht das schon sinn das so zu machen. Hätte da halt einfach einen Puffer aus einer sinnvollen menge an möglichen elementen angelegt und solange man die nicht überschreitet, gibt's keine Probleme.

Werde mir auf jeden Fall mal dein beispiel ansehen .... vielen Dank dafür.

... Habe es mir angesehen ...

Sehe ich das richtig, dass eigentlich nur depth und closingElement wichtig sind? Also wenn "closingElement = true" ist, wird eine klammer zu gemacht und wenn "depth == 0 && closingElement == true", dann ist das dokument fertig?
 
Vielen Dank! Beide Beispiele helfen mir sehr weiter!

Wenn du dich an die Bibliothek von Siemens hältst..

Ein Json Tree besteht aus n Elementen, und das Element hat Attribute welche du dann befüllen musst, dadurch ergibt sich dann ein fertiges Json File, welche dann wieder als Bytestream an den Mqtt Broker geht.

Beispiel:
Code:
#tempIndex := #constUSINT;

REGION Light barriers
    #oTree[#tempIndex].closingElement := 0;
    #oTree[#tempIndex].depth := 0;
    #oTree[#tempIndex].key := 'LightBarriers';
    #oTree[#tempIndex].type := "JSON_TREE_TYPE_0_ELEMENT_OBJECT";
    #oTree[#tempIndex].value := 'NULL';
    #tempIndex := #tempIndex + 1;
   
    #oTree[#tempIndex].closingElement := 0;
    #oTree[#tempIndex].depth := 1;
    #oTree[#tempIndex].key := 'InFrontSeparator';
    #oTree[#tempIndex].type := "JSON_TREE_TYPE_2_TEXT_STRING";
    #oTree[#tempIndex].value := "FC_BOOL_TO_STRING"(#iSensors.InFrontSeparator);
    #tempIndex := #tempIndex + 1;
   
    #oTree[#tempIndex].closingElement := 0;
    #oTree[#tempIndex].depth := 1;
    #oTree[#tempIndex].key := 'InSeperator';
    #oTree[#tempIndex].type := "JSON_TREE_TYPE_2_TEXT_STRING";
    #oTree[#tempIndex].value := "FC_BOOL_TO_STRING"(#iSensors.InSeparator);
    #tempIndex := #tempIndex + 1;
   
    #oTree[#tempIndex].closingElement := 1;
    #oTree[#tempIndex].depth := 1;
    #oTree[#tempIndex].key := 'InTool';
    #oTree[#tempIndex].type := "JSON_TREE_TYPE_2_TEXT_STRING";
    #oTree[#tempIndex].value := "FC_BOOL_TO_STRING"(#iSensors.InTool);
    #tempIndex := #tempIndex + 1;
END_REGION

REGION Pressure switches
    #oTree[#tempIndex].closingElement := 0;
    #oTree[#tempIndex].depth := 0;
    #oTree[#tempIndex].key := 'PressureSwitches';
    #oTree[#tempIndex].type := "JSON_TREE_TYPE_0_ELEMENT_OBJECT";
    #oTree[#tempIndex].value := 'NULL';
    #tempIndex := #tempIndex + 1;
   
    #oTree[#tempIndex].closingElement := 0;
    #oTree[#tempIndex].depth := 1;
    #oTree[#tempIndex].key := 'ChannelA';
    #oTree[#tempIndex].type := "JSON_TREE_TYPE_2_TEXT_STRING";
    #oTree[#tempIndex].value := "FC_BOOL_TO_STRING"(#iSensors.ChannelA);
    #tempIndex := #tempIndex + 1;
   
    #oTree[#tempIndex].closingElement := 0;
    #oTree[#tempIndex].depth := 1;
    #oTree[#tempIndex].key := 'ChannelB';
    #oTree[#tempIndex].type := "JSON_TREE_TYPE_2_TEXT_STRING";
    #oTree[#tempIndex].value := "FC_BOOL_TO_STRING"(#iSensors.ChannelB);
    #tempIndex := #tempIndex + 1;
   
    #oTree[#tempIndex].closingElement := 1;
    #oTree[#tempIndex].depth := 1;
    #oTree[#tempIndex].key := 'Value';
    #oTree[#tempIndex].type := "JSON_TREE_TYPE_3_NUMBER";
    #oTree[#tempIndex].value := "FC_REAL_TO_STRING"(#iSensors.PressureValue);
END_REGION

Sieht dann so aus:
JSON:
{
    "LightBarriers": {
        "InFrontSeparator": "FALSE",
        "InSeperator": "TRUE",
        "InTool": "FALSE"
    },
    "PressureSwitches": {
        "ChannelA": "TRUE",
        "ChannelB": "TRUE",
        "Value": 4.751
    }
}
Dieses Beispiel hat auf jeden Fall, was die LStream Bibliothek angeht, absolut Licht ins Dunkle gebracht. Vielen Dank dafür!
Das Problem habe ich mit Siemens Dokumentation leider öfter, dass ich quasi erst ein Beispiel sehen muss, oder eine Kleinigkeit fehlt, um wirklich zu verstehen, wie es gemeint ist.
Nach Deinem Beispiel erschließt sich mir jetzt auch die Doku der LStream Bibliothek komplett.

Zugegebenermaßen habe ich den einfachen weg genommen und habe mit CONCAT einfach einen String zusammen gebaut. Die LStream lib, habe ich nur Beispiele gefunden, wie man ein JSON Dokument lädt und das dann wieder Schreibt allerdings keine Doku darüber, wie man die Datenstrukturen manuell bauen würde. Ich konnte ich nicht rein debuggen, weil ich nur eine S7-1200 hatte ... nun habe ich eine S7-1500 ... daher werde ich mir das mal genauer anschauen und schauen wie man die Datenstrukturen initialisieren muss.

Bis es soweit ist, ist hier mein code, den ich benutzt habe:

Code:
// If we're currently not doing anything and we detected a new token, initialize the
// structures and send am mqtt message.
IF NOT("LMQTT".publish) AND NOT("LMQTT".messageSent) AND ("Data"."White Detected" OR "Data"."Red Detected" OR "Data"."Blue Detected") THEN
    // Get the local time, convert that to a unix timestamp and serialize that to a string.
    #retReadTime := RD_SYS_T(#curTime);
    #longCurTime := "LGF_DTLToUnixTime"(timeDTL := #curTime, error => #dtConvError, status => #dtConvStatus);
    #strCurTime := "LGF_IntToString"(#longCurTime);
   
    // Set the right color of token in the message.
    IF "Data"."White Detected" THEN
        #strColor := 'green';
    ELSIF "Data"."Red Detected" THEN
        #strColor := 'red';
    ELSIF "Data"."Blue Detected" THEN
        #strColor := 'blue';
    END_IF;
   
    // Assemble the message string.
    #messageString := CONCAT(IN1 := '{"device": "root.factory.sortinglane", "timestamp": "', IN2 := #strCurTime, IN3 := '", "measurements": ["color"], "values":["', IN4 := #strColor, IN5 :='"]}');
   
    // Serialize the string into an byte array and tell the MQTT client to send it.
    FOR #i := 0 TO LEN(#messageString) DO
        "LMQTT".publishMsgPayload[#i - 1] := CHAR_TO_BYTE(STRING_TO_CHAR(MID(IN := #messageString, L := 1, P := #i)));
    END_FOR;
    "LMQTT".publichMsgLen := LEN(#messageString);
    "LMQTT".publish := TRUE;
   
    "LMQTT".messageSent := TRUE;
END_IF;

// As soon as the MQTT Client is finshed sending the message, clear the buffer.
IF "LMQTT".done THEN
    "LMQTT".publish := FALSE;
    "LMQTT".done := FALSE;
    // Reset the array.
    FOR #i := 0 TO 999 DO
        "LMQTT".publishMsgPayload[#i] := 0;
    END_FOR;
    "LMQTT".numMessagesSent := "LMQTT".numMessagesSent + 1;
END_IF;
So einen ähnlichen Ansatz hatte ich davor auch, dieser hat aber nicht so richtig funktioniert bei mir.
Mit dem Beispiel würde es auf jeden fall auch funktionieren und vermutlich für ein erstes kleines Programm reichen.

Eigentlich hatte ich auch gehofft, dass man über verschiedene DB's 'iterieren' kann oder ganze DB's zu einem JSON String wandeln kann.
Also Variablenname als Key und dann den Wert dahinter.
Dieser Ansatz ist aber denke ich zu sehr aus der Softwareentwickler/Hochsprachen Sicht gedacht und hat wenig mit der Automatisiererwelt zu tun.

Mein Problem ist jetzt auf jeden Fall gelöst und ich kann endlich weiter machen! Nochmals vielen Dank!
 
Hehe ... glaube hier prallen halt zwei welten aufeinander ... IT und OT ... und ich stimme dir zu ... aber auch sehe ich durchaus potential in dynamischen Telegrammen, die bei "hinzufügen eines zusätzlichen parameters" nicht gleich weider anpassungen in 10 stellen erfordern.

Klar braucht man ein Array, da in ST hierarchiche strukturen nicht möglich sind (Also dass ich für ein Element eine variable anzahl von kind-elementen allokieren könnte. Daher macht das schon sinn das so zu machen. Hätte da halt einfach einen Puffer aus einer sinnvollen menge an möglichen elementen angelegt und solange man die nicht überschreitet, gibt's keine Probleme.

Werde mir auf jeden Fall mal dein beispiel ansehen .... vielen Dank dafür.

... Habe es mir angesehen ...

Sehe ich das richtig, dass eigentlich nur depth und closingElement wichtig sind? Also wenn "closingElement = true" ist, wird eine klammer zu gemacht und wenn "depth == 0 && closingElement == true", dann ist das dokument fertig?
Ne, ich glaube das Ende des Dokuments setzt die Funktion zum Serialisieren selbst (wenn eben kein befülltes Element mehr kommt)

Mein Tree und meine Payload sind aktuell so groß, damit ich die größte Nachricht die ich hab übermitteln kann.

Da kannst du natürlich auch für dich noch Puffer vorhalten, dennnoch sollte abgestimmt und definiert werden welche Datenpunkte benötigt werden und wie die Nachrichten aufgebaut sein sollen, daran kann man sich dann orientieren.

Vielen Dank! Beide Beispiele helfen mir sehr weiter!


Dieses Beispiel hat auf jeden Fall, was die LStream Bibliothek angeht, absolut Licht ins Dunkle gebracht. Vielen Dank dafür!
Das Problem habe ich mit Siemens Dokumentation leider öfter, dass ich quasi erst ein Beispiel sehen muss, oder eine Kleinigkeit fehlt, um wirklich zu verstehen, wie es gemeint ist.
Nach Deinem Beispiel erschließt sich mir jetzt auch die Doku der LStream Bibliothek komplett.


So einen ähnlichen Ansatz hatte ich davor auch, dieser hat aber nicht so richtig funktioniert bei mir.
Mit dem Beispiel würde es auf jeden fall auch funktionieren und vermutlich für ein erstes kleines Programm reichen.

Eigentlich hatte ich auch gehofft, dass man über verschiedene DB's 'iterieren' kann oder ganze DB's zu einem JSON String wandeln kann.
Also Variablenname als Key und dann den Wert dahinter.
Dieser Ansatz ist aber denke ich zu sehr aus der Softwareentwickler/Hochsprachen Sicht gedacht und hat wenig mit der Automatisiererwelt zu tun.

Mein Problem ist jetzt auf jeden Fall gelöst und ich kann endlich weiter machen! Nochmals vielen Dank!
Ich hab selbst viel herumprobiert und auch optimiert, da ich auch nur eine 1200er in dem Projekt hab.. das ganze Thema geht schon an den Speicher der CPU, da ist man mit einer 1500 besser aufgestellt.

Auch hab ich mir FCs erstellt die ich Aufrufe, mit denen ich dann die Daten in der Zeile in der ich mein Element befülle direkt wandeln kann ohne die Formatierung zu sprengen.

Ich versende zB meine Daten event-basiert. d.h. nur wenn ich eine Wertänderung feststelle, wird eine Nachricht abgeschickt. Meine Topics handele ich in via CASE Anweisungen.

Code:
-------- Daten am IN meiner Publish Funktion temporär laden:
// Information
#tempDataInformation := #iInformation;

-------- Beispiel aus der Case Anweisung:
    16: // Wait for mqtt ready
        #ioInterface.InOut.MqttTopic := #constWSTRING;
        IF #tempReady AND #statDataCleared THEN
            #ioPublishControl.StepNumber := 17;
        END_IF;
        //===============================================================================
    17: // Publish data information
        IF #tempDataInformation <> #statDataInformationOld THEN
            #ioInterface.InOut.MqttTopic := "MQTT_TOPIC_PUBLISH_INFORMATION";
            IF #ioPublishPrepare.Prepared.Information THEN
                #ioPublishControl.StepName := 'Publish message information';
                #statJsonSerializer.execute := 1;
                IF #tempSerialized AND #tempReady THEN
                    #ioInterface.In.Publish := 1;
                END_IF;
                
                IF #ioInterface.Out.Done THEN
                    #statDataInformationOld := #tempDataInformation;
                    #tempDataInformation := #ioPublishPrepare.InformationEmpty;
                    #ioInterface.In.Publish := 0;
                    #statJsonSerializer.execute := 0;
                    #ioPublishControl.StepNumber := 18;
                END_IF;
            END_IF;
        ELSE
            #ioPublishControl.StepNumber :=18;
        END_IF;
        //===============================================================================
    18: // Wait for mqtt ready
        #ioPublishControl.StepName := 'Wait for mqtt ready';
        #ioInterface.InOut.MqttTopic := #constWSTRING;
        IF #tempReady AND #statDataCleared THEN
            #ioPublishControl.StepNumber := 19;
        END_IF;

Daten bereite ich jeweils in einem passenden FC auf:
Screenshot 2024-01-11 130241.png
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hehe ... das ist genau der Grund, warum ich mich mit diesem Thema beschäftige.

Normalerweise arbeite ich in Apache PLC4X ja daran treiber zu bauen, um daten lesend (oder via subscription bei einigen) aus der SPS zu bekommen. Leider sehe ich allerdings, immer wieder, wie die armen SPSen komplett überlastet werden, weil sie von mehreren seiten alle paar millisekunden nach daten gefragt werden, weil diese so "zyklussynchron wie möglich" gelesen werden sollen. Musste ein wenig lachen als ich diesen Ausdruck das erste mal gehört habe.

Daher versuche ich mal das mit dem MQTT und dem aktiven senden, weil dann stimme ich dir zu, geht ein wenig speicher dafür drauf, allerdings hat die CPU der SPS fast nichts mehr zu tun (außer ihrem normalen job).
 
Wenn es nah am Zyklus sein soll, dann ist es am besten Telegramme event-basiert aus der SPS an den Broker zu senden. Da die Steuerungen von Siemens auch nicht die schnellsten sind, wirst du immer etwas Zeit dazwischen haben, eventuell bekommt man auch die MQTT Kommunikation in einen gesonderten OB gelegt, sodass er etwas freier vom eigentlichen Programm arbeiten kann. Da würde ich mal auf den Siemens Support zugehen eventuell
 
Das war interessant gewesen, diesen Thread zu lesen. Dazu hätte ich jetzt mal eine Frage - eigentlich vorrangig an @DCDCDC weil ich aus älteren Diskussionen weiß, dass er sich gerade mit diesem Thema ziemlich auseinandergesetzt hat ...

JSON kommt ja eigentlich aus der Hochsprachenwelt und dient zum Serialisieren und Deserialisieren von beliebigen Klassen-Objekten. In dieser Welt übergebe ich der Methode ein komplettes Objekt und erhalte dann den JSON-String als Antwort ... oder umgekehrt - ich habe eine JSON-String und der befüllt die Elemente einer Klasse, die er befüllen kann.
Nun die Frage :
In diesem Thread bastelt ihr euch ja im Grund den JSON-String selbst zusammen. Gibt es da keine Analogie zu dem von mir beschriebenen ?
Also im Klartext : Ich baue mir (z.B. in einem DB) ein Datenobjekt zusammen und übergebe dies dem Serialisierer und der erstellt mir daraus einen passenden JSON-String ?
Und dann auch gleich die zweite Frage :
Was ist wenn ihr einen JSON-String erhalten würdet ? Muss der dann quasi selbst zerpflückt werden ?
 
Zurück
Oben