Sonderzeichen erzeugt PHP-unserialize() Error

Bin mir nicht sicher, ob an den im folgenden auftretenden Fehlern IPS oder unterschiedliche Version von PHP schuld sind (die Buchstaben und Ziffern in der Beschreibung hab ich zur Referenzierung eingefügt):

(A) Auf einem Raspi mit ‚IP-Symcon 4.00, 17.02.2016, 7a945af31e30‘ wird
(1) durch ein Skript (das 1wire-Resultate scannt)
(2) eine Variable mit dem CustomProfile ‚~Temperature‘ verändert
(3) die dann über ein Ereignis ein
(4) anderes Skript aufruft .

In dem Skript(4) wird ein Array erstellt, u.a. mit folgenden Befehlen:

// Daten schnell holen, später bewerten
$Vobj = $_IPS['VARIABLE'];    // Objekt-Nr. der Variablen
$IVar = IPS_GetVariable($Vobj);         // Info zur VARIABLE
$vSta = @GetValueFormatted($Vobj);      // verbaler Status Ergibt z.B.: 22,3 °C
$bSta = @GetValueBoolean($Vobj);        // Binär-Wert der Variablen: TRUE/FALSE
$aSta = $_IPS['VALUE'];                           // Analoger Wert der Variablen: 22.3
$oSta = $_IPS['OLDVALUE'];                        // Wert der auslösenden Variable vor Auslösezeitpunkt
$tSta = $IVar ['VariableValue'] ['ValueType'];    // Variablentyp (0: Boolean, 1: Integer, 2: Float, 3: String)
$IDNa = McIPS . $Vobj;                 // zum Key wird der ID-Name = "IPS" + ID-Nummer 5stellig


....

        $DvPar['lWert'] = $DvPar['aWert'];
        $DvPar['lStat'] = $DvPar['Statu'];
        $DvPar['aWert'] = $aSta;
        $DvPar['Statu'] = $vSta;             // neuer Gerätezustand

Das Array hat dann auf dem Quell-Raspi(A) folgendes Format (einige Felder nicht dargestellt, wichtig sind [Statu] und [lStat]):


    [IPS42843] => Array
        (
            [ObjID] => 42843
            [OriPC] => RaspiB5
...
            [aWert] => 22
            [lWert] => 22.0625
            [Statu] => 22.0 °C
            [lStat] => 22.1 °C
            [MinTa] => 20.6875
            [MaxTa] => 22.0625
            [MinWo] => 20.6875
            [MaxWo] => 25.8125
            [MinMo] => 20.6875
            [MaxMo] => 25.8125
        )


(5) in einem weiteren Schritt wird das Array serialized :

$ParPac = serialize ($ParPac);

und per $rpc = new JSONRPC („http://user:password@‚IP‘:‚Port‘/api/“); und $rpc → IPS_RunScriptEx (xxxxx, array(…)) an
(B) einen anderen Raspi und
© einen Windows7-PC mit IPS3.40 (der für mich aktuellen stabilen Version)
gesendet.

  1. Fehler (nur ein Manko):
    auf dem Windows7-PC © wird das Array nach unserialize so dargestellt (Augenmerk auf [Statu] und [lStat]):
OW700000067B77E928 = Array
(
    [ObjID] => 42843
    [OriPC] => RaspiB5
...
    [aWert] => 22.0625
    [lWert] => 22
    [Statu] => 22.1 °C
    [lStat] => 22.0 °C
    [MinTa] => 20.6875
    [MaxTa] => 22.0625
    [MinWo] => 20.6875
    [MaxWo] => 25.8125
    [MinMo] => 20.6875
    [MaxMo] => 25.8125
)

  1. Fehler (PHP-Skript wird nicht komplett ausgeführt):
    Auf dem anderen Raspi(B) tritt beim Statement
                        $DvPar = unserialize ($_IPS['ParPac']);

permanent folgender Fehler auf:

<br />
<b>Notice</b>:  unserialize(): Error at offset 415 of 581 bytes in <b>/var/lib/symcon/scripts/JSON_RX.ips.php</b> on line <b>349</b><br />

Das gleiche Array wird ja unter IPS3.40 und Windows (fast) fehlerfrei unserialized.

Fehlereingrenzung::
Vor dem serialized auf dem Raspi(A) werden [Statu] und [lStat] auf einen Leerstring reduziert.

$ParPac['Statu'] = '';
$ParPac['lStat'] = '';

Darauf tritt beim Raspi(B) kein Fehler mehr auf!!
Aber meine „°C“ sind weg, die ja Bestandteil des Meßwertes sind!

Ich kann natürlich ein Workaround für die Übermittlung von Sonderzeichen schreiben aber ein Fehler im System IPS/PHP scheint es mir trotzdem zu sein.

Viele Grüsse
Harald

Versuche es doch mal mit utf_encode und utf_decode. Das Array kannst Du dann direkt ohne serialize dem json_encode übergeben.

Tommi

Alles was über die JSON-RPC API geht, wird nach UTF-8 kodiert. Wenn du das nicht willst, würde ich deinen Output vorher z.B. mit base64_encode kodieren, damit dieses Problem bei der Übertragung gar nicht erst auftritt.

paresy

Danke für die raschen Tipps!!

Hab jetzt ein Workaround gemacht in der nur mir bekannten Komplexität:cool::

Beim Sender:

...
            $ParPac['Base64'] = Array (// Umgehung weil alles was über die JSON-RPC API geht nach UTF-8 kodiert wird
                'Statu' => base64_encode ($ParPac['Statu']),
                'lStat' => base64_encode ($ParPac['lStat']),
            );
            unset ($ParPac['Statu']);
            unset ($ParPac['lStat']);
            $ParPac = serialize ($ParPac);
...

Beim Empfänger:

...
                        $DvPar = unserialize ($_IPS['ParPac']);
                        if (isset ($DvPar['Base64'])) {     // dieses Array wurde MIME base64 kodiert
                            foreach ($DvPar['Base64'] as $IDNa => $ParPacDvPar) {
                                $DvPar [$IDNa] = base64_decode ($ParPacDvPar);
                            }
                            unset ($DvPar['Base64']);
                        }
...

Das Ergebnis:
in der Quelle:

...
    [aWert] => 22.0625
    [lWert] => 22.125
    [Statu] => 22.1 °C
    [lStat] => 22.1 °C
    [MinTa] => 21.5625
    [MaxTa] => 22.4375
    [MinWo] => 20.6875
...

in der Senke:

...
    [MaxWo] => 25.8125
    [MinMo] => 20.6875
    [MaxMo] => 25.8125
    [Statu] => 22.1 °C
    [lStat] => 22.1 °C
)

Aber das kommt auf dem Windows-System mit IPS 3.4 raus:

...
    [MinMo] => 20.6875
    [MaxMo] => 25.8125
    [Statu] => 22.1 °C
    [lStat] => 22.1 °C
)

Da stellt sich mir halt immer noch die Frage, was denn bei IPS 4.0 anders gemacht wird als bei 3.4 und wie ich die Fehldarstellung für alle möglichen Fälle korrigieren kann.

Und wie es zu einem unserialize() Error kommen kann, wenn serialize- und unserialize-Routine auf derselben 8nicht der gleichen) Plattform ablaufen. Da muß doch die JSON RPC-Routine was falsch machen (es darf doch nicht sein, daß die Payload so verändert wird, dass sie unbrauchbar wird).

Viele Grüße
Harald

Beim Versuch von der 3.4 auf die 4.0 zu wechseln (win7) tritt ein vergleichbarer Fehler auf:
Ein unter 3.4 serialisiertes array bricht in der Version 4.0 beim deserialsieren (unserialize) mit FALSE ab und es wird eine E_NOTIC zurück gegeben.