UDP Read JSON

Hallo,

ich habe einen Drucker der per UDP / JSON-Request aktuelle Stati zurückliefert.

Doku:

Interessieren würde mich, wie ich z.B. einen {„read“:„global_counter“} absetze und das Ergebnis zu Symcon zurück bekomme.
(Leider konnte mir der Hersteller da nicht weiter helfen und ich selbst habe da keinen Plan…)

Einen UDP-Socket zum Drucker habe ich erstellt, aber wie sende ich da?
In der Symcon-Doku fand ich nur „boolean USCK_SendText (integer $InstanzID, string $Text)“ aber damit bekomme ich ja keine Werte zurück geliefert…

Oder gibt es hier im Forum was, an dem ich mich orientieren könnte?

Öffne mal den Debug des Sockets (rechts oben der Käfer) in der offenen Instanzkonfiguration.
Dann setze per Script deinen USCK_SendText ab und schaue ob eine Antwort kommt.

Falls ja, ein Script „Drucker auswerten“ anlegen sowie eine Instanz „Register Variable“ anlegen. Die Variable erhält als Gateway den UDP Client Socket und als Ziel das Script. Weitere Infos in der IPS Doku zu Register Variable.

Hallo Jürgen,

Die Verbindung ist eine TCP/IP. Deswegen lege mal einen Clientsocket in Symcon an. Standard Port bei Auslieferung des Druckers ist 34568. Dann den o.g. JSON String senden und der m610 Antwortet darauf.

Danke für die schnellen Antworten.
Die Firewall-Config zwischen Symcon und dem Drucker dauerte etwas…
(Auf UDP kam ich wegen dem JSON Commander mit welchem ich teste.)

So weit bin ich:
$Text=„read:global_counter“;
CSCK_SendText (48840, $Text);

08.12.2020, 16:07:41 | TRANSMIT | 72 65 61 64 3A 67 6C 6F 62 61 6C 5F 63 6F 75 6E 74 65 72

Nun frage ich mich:

  1. [li]Eigentlich müsste ich den Text wohl als „{„read“:„global_counter“}“ schicken. [/li]Aber wie bekomme ich das mit den Sonderzeichen in eine Variable?
    Ein Escape-Versuch mit „{„read:global_counter“}“ liefert zumindest keinen PHP-Fehler, aber natürlich einen anderen Transmit:
    08.12.2020, 17:46:47 | TRANSMIT | 5C 7B 22 72 65 61 64 3A 67 6C 6F 62 61 6C 5F 63 6F 75 6E 74 65 72 22 5C 7D
    [li]Auf den Transmit „read:global_counter“ kam irgend wie keine Antwort, da ist ja nur der Transmit… [/li]Mit welchem Befehl schickt man denn den Read?
    Wie bekomme ich die Antwort in ein Array?
    CSCK_SendText liefert ja nur true oder false zurück.
    „string ReceiveData (string $JSONString)“ habe ich da gefunden, könnte das klappen? Wie in php einbauen?

Erstmal muss im Debug eine Antwort sichtbar sein. Dann kann man sich darum kümmern den Auszuwerten.
Dafür gibt es die RegisterVariable. Einfach mal dazu in die Doku gucken.

Zum Thema Sonderzeichen in Variable. Das einfachste ist ’ statt " zu verwenden. Also etwa so
$text = ‚{„blub“}‘;

Ggf. musst du auch noch ein
oder \r nachsenden. Dsa ginge dann etwa so:
$text = ‚{„blub“}‘ . "
";

beachte hier die unterschiedlichen Anführungszeichen, wodurch in den " aus dem
tatsächlich der passende Ascii Code wird.

Hi,

Ja das sollte funktionieren:

$text = '{"read":"global_counter"}';

Ich bin morgen in der Firma, da müsste noch so ein Drucker rumliegen. Den nehm ich mal mit, dann kann ich das testen.

So hatte ich das mal für Siemens TIA per TCP auf Port 34568 gemacht:
TIA4.png

Attain

Hurra, es klappt.
Danke für eure Tips !!!

Damit es Anfänger wie ich evtl. später mal leichter haben, hier mein Versuch einer „Anfänger-Doku“.

Q: Warum gab es vom Drucker keine Antwort?
A: Die Firewall hatte die noch blockiert.

Q: Welchen String sende ich jetzt?
A: $Text = ‚{„read“:„global_counter“}‘;
CSCK_SendText (48840<-Client-Socket-ID, $Text);

Q: Wie werden die Werte ausgelesen?
A: Der Register-Variablen Tip hat mir geholfen. Die Doku von Symcon dazu ist für mich als Anfänger nicht sonderlich hilfreich, ich hatte das aber schon mal geschafft und nun konnte von meinem alten Script abschauen…

Meine Schritte (für Anfänger):

  1. Client Socket anlegen:
    Rechte Maustaste -> Objekt hinzufügen -> INSTANZ auswählen, nach „Client“ suchen und einen Client-Socket anlegen.
    Diesen dann mit IP und Port konfigurieren und aktivieren.

  2. Script für das Absenden der Anfrage anlegen.

$Text = '{"read":"global_counter"}';
CSCK_SendText (48840<-- ID des ClientSocket aus (1.), $Text);
  1. Script für das verarbeiten des Ergebnisses anlegen und folgenden Code rein kopieren:
    Beispiel-Code:

// wenn das Skript von einer RegisterVariable-Instanz aus aufgerufen worden ist
if ($_IPS['SENDER'] == "RegisterVariable") {
    $data = $_IPS['VALUE'];
    // Ausgabe in den Symcon-Meldungen zum debuggen
    // print_r("Socket Script wurde aufgerufen
");
    // print_r($data);
 
    // wenn das Trennzeichen "," in $data gefunden worden ist
    if (strpos($data, ',')) {
        // $data in durch "," separierte Datensätze zerlegen
        $datasets = explode(',', $data);
 
        // alle Datensätze ausgeben
        for ($i = 0; $i < count($datasets) - 1; $i++) {
            echo "empfangener Datensatz: ".$datasets[$i]."
";
        }
        // Stand in die Variable wegschreiben. 
        // Ich brauche nur den 1. Wert des Array.
        SetValueInteger(59640,$datasets[1]);

    }
}

  1. Register-Variable anlegen:
    Rechte Maustaste -> Objekt hinzufügen -> INSTANZ auswählen, nach „Register“ suchen und so eine Instanz und nicht eine „Variable“ anlegen…

  2. In die Instanz-Config der unter (4.) erzeugten „Register-Variablen“ rein gehen und zunächst mit „Gateway ändern“ den unter (1.) angelegten Client-Socket zuordnen. Dann noch das Script aus (3.) zuordnen und abspeichern.

  3. Script aus (2.) starten, dadurch wird der Abruf der Daten an den Drucker geschickt und die Antwort wird vom Script aus (3.) verarbeitet.

Kannst du uns mal die Antwort(en) des Druckers zeigen? Ich vermute ein json_decode hätte dir auch helfen können.

Mit


........
if ($_IPS['SENDER'] == "RegisterVariable") {
    $data = $_IPS['VALUE'];
    $instanz = $_IPS['INSTANCE'];

    // Ausgabe in den Symcon-Meldungen zum debuggen
    print_r("Socket Script W41 wurde aufgerufen
");
    print_r($data);
    print_r($instanz);
    print_r($_IPS['SENDER']);
    print_r($_IPS['CLIENTIP']);
.........

kommt bei den Meldungen

10.12.2020, 22:58:42 | Register Variable    | Socket Script W41 wurde aufgerufen
{
    "globalcounter": [
        2363554,
        2363464,
        2363374,
        2363329,
        0,
        0
    ]
}
28099

10.12.2020, 23:08:50 | TRANSMIT | 7B 22 72 65 61 64 22 3A 22 67 6C 6F 62 61 6C 5F 63 6F 75 6E 74 65 72 22 7D
10.12.2020, 23:08:50 | RECEIVED | 7B 0A 20 20 20 20 22 67 6C 6F 62 61 6C 63 6F 75 6E 74 65 72 22 3A 20 5B 0A 20 20 20 20 20 20 20 20 32 34 38 31 30 39 38 2C 0A 20 20 20 20 20 20 20 20 32 34 38 30 39 33 33 2C 0A 20 20 20 20 20 20 20 20 32 34 38 30 38 32 33 2C 0A 20 20 20 20 20 20 20 20 32 32 38 37 38 30 38 2C 0A 20 20 20 20 20 20 20 20 30 2C 0A 20 20 20 20 20 20 20 20 30 0A 20 20 20 20 5D 0A 7D 0A

$_IPS[‚SENDER‘] und $_IPS[‚CLIENTIP‘] bleiben leider leer.
Insgesamt frage ich die Stände von 8 Druckern mit je 4 von 6 bestückten Druckköpfen ab.
(Deshalb 42363xx und 20 in der Antwort.)

Das ganze jeweils nach Schicht-Ende, dann müssen die Jungs nicht immer Zahlen für ihre bisher von Hand gemachte Statistik sammeln. Morgends um 6 wird dann noch die Tagessumme der Linie berechnet.

$_IPS[‚INSTANCE‘] liefert wenigstens was (hier die 28099).
Damit mache ich dann beim auswerten die Zuordnung zu den Variablen.

     switch($instanz) {  

                case'51732': // UMA
                switch($jetzt){
                    case "06":
                        $neu=$datasets[1] - GetValueInteger(18891);
                        $tagessumme = $neu;
                        SetValueInteger(22008,$neu);
                        SetValueInteger(18891,$datasets[1]);
                        break;
                    case "14":
                        SetValueInteger(44182,$datasets[1]);
                        break;
                    case "22":
                        SetValueInteger(59640,$datasets[1]);
                        break;
                }


                case'22085': // UMB
                switch($jetzt){
                    case "06":
                        $neu=$datasets[1] - GetValueInteger(30780);
                        $tagessumme = $tagessumme + $neu;
                        SetValueInteger(55134,$neu);
       .........
.........

Wobei das „Sammel-Script“ mit dem Case noch nichts taugt.
Das „Switchen“ durch die Instanz-Nummern scheint nicht immer sauber zu klappen, das läuft wild durcheinander.

Auch das aufaddieren der Tagessumme klappt so natürlich nicht, da das Script ja nicht „von oben“ durchläuft, sondern auch mal in der Mitte startet, wenn ein Ergebnis von dem Drucker zuerst zurück kommt.
$neu wird dabei auch oft im Speicher verwürfelt und die Zahlen passen dann nicht.

Also wie man elegant die Rückmeldungen mehrerer Socket in einem Script erledigt habe ich noch nicht so richtig herausgefunden…