geändertes Verhalten der Konfigurationsformular in IPS 5?

Hallo,

ich verwende in einigen Konfigurator-Module (z.B. NetatmoWeather) dynamische Konfigurationsformulare. Dabei wird eine Auswahlliste mit Daten, die ich vorher geholt habe, gefüllt, aus dieser Liste soll ein Eintrag ausgewählt werden, der dann bei eine Aufruf einer entsprechende Aktion verarbeitet werden soll.


    public function GetConfigurationForm()
    {
        $SendData = ['DataID' => '{DC5A0AD3-88A5-CAED-3CA9-44C20CC20610}'];
        $data = $this->SendDataToParent(json_encode($SendData));

        $this->SendDebug(__FUNCTION__, "data=$data", 0);

        $options = [];
        if ($data != '') {
            $netatmo = json_decode($data, true);
            $devices = $netatmo['body']['devices'];
            foreach ($devices as $device) {
                $station_name = $device['station_name'];
                $options[] = ['label' => $station_name, 'value' => $station_name];
            }
        }

        $formActions = [];
        $formActions[] = ['type' => 'Select', 'name' => 'station_name', 'caption' => 'Station-Name', 'options' => $options];
        $formActions[] = ['type' => 'Button', 'label' => 'Import of station', 'onClick' => 'NetatmoWeatherConfig_Doit($id, $station_name);'];
        $formStatus = [];
        $formStatus[] = ['code' => '101', 'icon' => 'inactive', 'caption' => 'Instance getting created'];
        $formStatus[] = ['code' => '102', 'icon' => 'active', 'caption' => 'Instance is active'];
        $formStatus[] = ['code' => '104', 'icon' => 'inactive', 'caption' => 'Instance is inactive'];

        $formStatus[] = ['code' => '201', 'icon' => 'error', 'caption' => 'Instance is inactive (no data)'];
        $formStatus[] = ['code' => '202', 'icon' => 'error', 'caption' => 'Instance is inactive (station missing)'];
        $formStatus[] = ['code' => '203', 'icon' => 'error', 'caption' => 'Instance is inactive (no station)'];

        return json_encode(['actions' => $formActions, 'status' => $formStatus]);
    }

    public function Doit(string $station_name)
    {
....

Wenn kein Eintrags ausgewählt wurde, griff in IPS 4.4 eine Prüffunktion in Doit(), die erkannte, das kein Eintrag gewählt wurde und entsprechend reagierte.

In IPS 5 gibt es nun eine Fehlermeldung:


Error: Error: Uncaught TypeError: Argument 1 passed to NetatmoWeatherConfig:oit() must be of the type string, null given, called in /var/lib/symcon/scripts/__generated.inc.php on line 991 and defined in /var/lib/symcon/modules/NetatmoWeather/NetatmoWeatherConfig/module.php:93
Stack trace:
#0 /var/lib/symcon/scripts/__generated.inc.php(991): NetatmoWeatherConfig->Doit(NULL)
#1 /-(4): NetatmoWeatherConfig_Doit(4711, NULL)
#2 {main}
thrown
Error in Script /var/lib/symcon/modules/NetatmoWeather/NetatmoWeatherConfig/module.php on Line 93
134 in IPSLibrary/app/core/IPSLogger/IPSLogger.inc.php (call IPSLogger_Out)
33 in IPSLibrary/app/core/IPSLogger/IPSLogger_PhpErrorHandler.inc.php (call IPSLogger_Err)
121 in IPSLibrary/app/core/IPSLogger/IPSLogger_PhpErrorHandler.inc.php (call IPSLogger_PhpErrorHandler)
in IPSLogger_PhpFatalErrorHandler

Das ist vermutlich der neuen PHP-Version und dem strikteren Typ-Checking geschuldet.

Hat jemand eine Idee, wie ich verhindern kann, das die Übergaben von NULL an Doit() ein Problem wird?

danke
demel

Dies kommt dadurch, dass PHP 7 strikter ist was skalare Type Hints angeht. Du kannst das Problem lösen, indem du ein ? vor den Datentyp setzt, wodurch null zusätzlich zum skalaren Typ erlaubt wird (Damit ist dein Modul aber definitiv erst ab IP-Symcon 5.0 kompatibel)

Ich habe mal ein Beispiel erstellt: empty dropdown with allowed null operator · symcon/SymconTest@05db490 · GitHub

paresy

Hallo,

um es vorerst mit beiden Versionen zum laufen zu bekommen, könnte er doch allerdings auch Abfragen welche IPS Version benutzt wird und darauf reagieren, also ein Mal mit ? und ein Mal ohne ?.

Klar ist das nicht schön, aber so könnte man doch für den Übergang wenigstens beides nutzen?!
Oder liege ich da falsch?

Grüße,
Kai

Ich denke nicht, da das ? ein Syntax Error liefern müsste.

Grad mal ausprobiert: PHP Sandbox, test PHP online, PHP tester

paresy

Ah, gar nicht drüber nachgedacht.

Grüße,
Kai

Gesendet von iPhone mit Tapatalk

Hmm, das ist schon dumm, es wird sicherlich länger dauern, bis nur noch IPS 5 an Start ist.

In der PHP-Sandbox funktioniert das hier


<?php

if (@constant('PHP_VERSION_ID') >= 7) {
    define('INT_WITH_NULL', '?int');
    define('FLOAT_WITH_NULL', '?float');
    define('STRING_WITH_NULL', '?string');
} else {
    define('INT_WITH_NULL', 'int');
    define('FLOAT_WITH_NULL', 'float');
    define('STRING_WITH_NULL', 'string');
}

function asd(STRING_WITH_NULL $a) {
    //
}

mit beiden PHP-Versionen, nicht aber in IPS.

Dann habe ich noch folgendes versucht:

ein Wrapper für die eigentliche Funktion Doit() in zwei Varianten (also eine für PHP 5 und eine für PHP 7) erstellt und als Dateien …/libs/wrapper_php5.php und …/libs/wrapper_php7.php abgelegt.
Diese Datei wollte ich dann in Abhängigkeit von PHP_VERSION_ID mit include / require_once verwenden.

Keine Chance (muss aber sagen, das ich auch nicht ganz so tief in php drin stecke, das ich jeden Trick kenne).

Die Module in zwei Varianten/git-repositories anzubieten ist auch nicht das gelbe vom Ei, die Pflege wird damit nicht einfacher.

Das muss ja eigentlich ein Problem beim jedem Modul sein, das mit Select-Listen in einem Konfigurator arbeitet? Da man ja auch kein Listen-Element von options als Default angeben kann, kommt man da nicht drum herum.

Das ist kein kritisches Problem (für mich), weil es ja nur unter bestimmten Umständen passiert, sieht dann zwar unschön aus und man wundert sich, aber mehr nicht.

demel

Doch genau so.
Den aktuellen Zweig als neuen Zweig z.b. IPS4 archivieren und in master die Änderungen für IPS 5 einbauen.
Und darauf hinweisen, dass es keine Bugfix mehr für IPS 4 gibt.
Oder willst du für immer und ewig jede Version unterstützen?

Das Problem tritt nicht auf, wenn man in IPS 5 gleich das Element Configurator dafür nutzt.
Oder anstatt eine Public Methode in dem Modul, alles durch die Console erledigen lässt. (Die Public Methode verwirrt ja auch nur User… Was soll DoIt sein :wink: )
Siehe hier:
IPSSqueezeBox/module.php at ae9c2bcc0eb272f23d2471d3841f2c863759b891 · Nall-chan/IPSSqueezeBox · GitHub
Wobei ich dies jetzt auch auf das Element Configurator umstellen werden.
Michael

Hi demel,

ich schau mal, ob ich was schickes austüfteln kann, womit beides geht. Mich wundert, dass die Lösung mit den zwei Dateien nicht klappt. Denn das hätte gehen müssen.

paresy

Auf Dauer sicherlich nicht, da hast Du recht, allerdings so von jetzt auf gleich …

Mit dem Zweig hätte ich auch noch ein kleine mentales Problem: ein Anwender hat ja den ‚master‘ normalerweise aktiv.
Wenn er nun mit IPS 4.4 ein Modul-Update macht, bekommt er ja automatisch dann die ‚master‘-Änderungen. Geht also schief. Ok, dann müsste man ihm sagen, stell auf „IPS 4“ um mach nochmal ein Update (um das falsche Update wieder zu heilen) … naja, könnte ich mit leben.

Muss mich mal einlesen, wie man das mit den Zweigen in Github macht.

jaaa … das mit dem ‚public Doit()‘ fand ich auch immer etwas doof.
Das durch die Konsole machen zu lassen (wie bei Deinem Beispiel) … da finde ich den Code etwas unleserlich (wegen der „<<<EOF“-Bereiche).
Mit dem Element Configurator habe ich mich noch nicht beschäftigt, werde ich mal machen.

danke
demel

wie gesagt, ich will nicht ausschliessen, das ich da ein Fehler gemacht habe. Ich komme eher aus dem C-Bereich und habe bestimmt was falsch gemacht.

Ist aber nicht dringend. Mit der Idee vor NallChan, mittelfristig die IPS4-Varianten zu archivieren und da nur noch kritische Bugfixes zu machen könnte ich anfreunden.

Also kein Stress
demel

Da sage ich inzwischen… Pech gehabt.
Wer einfach nur immer auf Update klickt (egal ob IPS oder Module), ohne vorher das Changelog zu lesen… Der hat Fehler verdient :wink:
Michael

Wenn man die compatilibty Flags setzt, dann wird auch vor dem Update geprüft. Leider erst mit Version 5.0 sauber… Das Feature war unter der 4.4 etwas Buggy :frowning:

paresy