Philips Hue Einblendung

Hallo!

Dieses Thema betrifft die Fähigkeit, ein schrittweises Einschalten einer Hue-Glühbirne zu programmieren, wie in diesem Issue beschrieben.

Ich hatte nicht viel Zeit, um mich damit zu beschäftigen, aber ich habe einen ersten funktionierenden Entwurf.
Ich denke, dass eine Diskussion notwendig ist, bevor ich weitermache und alles erledige, was nötig ist, damit der PR gültig ist.

Die Punkte, die zur Diskussion stehen:

  • Bisher gibt es im Projekt keine „Szenerie“-Funktion, die mit einer Szene verbunden ist. Bisher besteht jede Szene aus einer Reihe von Grundaktionen wie dem Einschalten eines Lichts oder dem Betätigen eines Schalters. Ein Fade-In erfordert die Verkettung mehrerer Grundaktionen, da die Hue-API keine direkte Aktion für ein schrittweises Einschalten bietet. Hier müssen also mehrere einfache Aktionen verkettet werden: das Licht einschalten und dann die Helligkeit in regelmäßigen Abständen ändern. Diese „Szenerie“ erfordert einen komplexeren Satz von Parametern als für Grundaktionen: Es werden sowohl die Dauer des Einschaltens als auch die Zielhelligkeit benötigt. Diese Parameter können nicht in das aktuelle Modell integriert werden, und ich musste schummeln, indem ich die Validierung des Formats der Aktionen einer Szene änderte, um etwas zum Laufen zu bringen. Ich denke also, dass wir etwas Geeigneteres brauchen.
  • Auf der Frontend-Seite musste ich auch für die Komponente LightFadeInParams schummeln, um diese „Aktion“ mit mehreren Parametern zu verwalten. Auch hier muss diskutiert werden, um etwas Saubereres zu machen.
  • Ich habe mit setTimeout gespielt, um das schrittweise Einschalten zu erreichen, aber ich mag diese Lösung nicht so sehr: Es besteht die Gefahr, dass das Einschalten verspätet endet. Wir sollten wahrscheinlich eine bessere angepasste Bibliothek verwenden. Wenn es kein passendes Paket gibt, das bereits in Gladys verwendet wird, werde ich schauen, was infrage kommt. Außerdem scheint die Hue-API, wenn die Einschaltzeit kurz ist, den Zustand des Lichts etwas verspätet im Vergleich zur Rückrufzeit zu ändern. Dies verursacht „Ruckler“ im Prozess des schrittweisen Einschaltens. Ich werde schauen, ob ich vielleicht die Anzahl der API-Aufrufe begrenzen kann.

Es gibt noch viele andere Dinge, die im PR überarbeitet werden müssen, aber ich möchte diese Themen lieber diskutieren, bevor ich weitergehe.

Hallo @christophe, zögere nicht, Bescheid zu sagen, wenn du Tester brauchst

Hallo @christophe und super, wenn du die Entwicklung dieses PRs übernommen hast :slight_smile:

Bist du dir sicher?

Beim schnellen Suchen bin ich auf Folgendes gestoßen:

Sieht das nicht aus wie das, wonach wir suchen?

Das ist kein « Schummeln », so entwickelt man immer! Wenn du mehrere Attribute in einer Aktion benötigst, ist es normal, diese Attribute zur Validierung hinzuzufügen.

Könntest du direkt den Code zeigen, um zu zeigen, inwiefern es « Schummeln » ist? :slight_smile:

Haha tatsächlich habe ich mich nur auf die API auf der Philips-Website konzentriert und war nicht neugierig genug, um zu schauen, was das Node-Modul direkt anbietet. Mein Fehler, ich werde schauen, ob ich es verwenden kann.

Um meinen Punkt zu präzisieren, wo ich die Modellvalidierung geändert habe: Link

Hier habe ich im Frontend geschummelt, bei der Implementierung des Formulars zum Erstellen einer Fade-In-Aktion: Link
Das hängt mit der Validierung des Modells einer Szene zusammen, da ich ein Attribut « parameters » hinzugefügt habe, um alle meine Werte zu verwalten (siehe den vorherigen Link), aktualisiere ich das gesamte Attribut « parameters » jedes Mal, statt nur ein Unterattribut von « parameters » zu aktualisieren. Das ist nicht besonders sauber, aber im Moment sehe ich keine andere Möglichkeit.

@VonOx danke, ich werde dich kontaktieren, wenn es ein bisschen stabiler ist :slight_smile:

Ah tatsächlich, das ist nicht verrückt, warum hast du nicht 2 Variablen gemacht? Es ist nicht nötig, eine übergeordnete Variable „parameters“ zu haben.

Wir machen das in mehreren Szenenaktionen doch so.

Beispiel in deinem Fall:

handleChangeTargetBrightness = e => {
    this.props.updateActionProperty(this.props.columnIndex, this.props.index, 'target_brightness', e.target.value);
};

Übrigens, ich sehe, dass du neben deinem updateActionProperty auch ein setState machst, das ist nicht ideal, weil du die beiden Zustände synchronisieren musst. Du könntest direkt die Eigenschaft props.action verwenden, die vom übergeordneten Element injiziert wird!

Wenn ich drei Variablen verwende, muss ich das actionSchema des Modells scene ändern und drei Attribute target_brightness, duration_value und duration_unit hinzufügen. Diese Attribute werden nur für diesen Aktionstyp verwendet. Daher die Idee, ein einziges Attribut parameters vom Typ object zu verwenden, um das Schema generisch und wiederverwendbar zu machen, wenn auch sehr permissiv.

das ist genau der Sinn davon! :smiley:

das ist genau das, was wir vermeiden wollen! In Gladys 4 machen wir alles so streng wie möglich. Wenn das Schema zu flexibel ist, landen wir mit allem Möglichen in der DB, wir werden Nutzer mit mysteriösen Problemen haben, und es wird sehr schwer zu debuggen und zu korrigieren sein.

Dabei bin ich mit dir einer Meinung, dass dieses Schema, das alle Aktionen auf die gleiche Weise validiert, seltsam und nicht streng genug ist.

Ich dachte nicht, dass das mit Joi am Anfang möglich wäre, aber tatsächlich kann man mit .when() (https://joi.dev/api/?v=17.3.0#anywhencondition-options) bedingte Schemas erstellen.

Ich würde gerne darauf migrieren, damit wir jeden Aktionstyp einzeln validieren können.

Deshalb wollte ich darüber sprechen, ich mag die Idee von Optionen, die meistens null sein werden, nicht und ich denke auch, dass parameters zu permissiv ist.
Ich werde mir die bedingten Schemata ansehen.

Hallo,
Ich habe den PR mit Folgendem aktualisiert:

  • Direkte Nutzung der Hue-API-Funktion, um die Fade-in-Dauer zu spezifizieren
  • Nutzung von bedingten Schemata für die Szenenparameter.

Bei Letzterem habe ich das Feld parameters beibehalten, um die alten Felder text, value und unit zu umfassen. Ich habe eine Migration entsprechend erstellt.

Mir bleibt noch etwas Arbeit, um das Ganze vollständiger und getestet zu machen. Ganz zu schweigen von den Voraussetzungen, damit der PR gültig ist :slight_smile:

Toll! Kann es kaum erwarten, das zu sehen :slightly_smiling_face:

Hallo,
Nach einer viermonatigen Winterpause habe ich etwas Zeit in die PR investiert.
Ich denke, sie ist bereit für eine Überprüfung, ich habe ein Image für meinen Rasp 4 erstellt und es läuft gut.

@VonOx, falls du es testen möchtest.
Danke @pierre-gilles und @AlexTrovato für die erste Durchsicht, ich habe die Rückmeldungen berücksichtigt.

Hallo Christophe!

Schon mal danke für dein PR und all die Arbeit, die du reingesteckt hast, das ist cool :slight_smile:

Ich habe eine Review zu deinem PR geschrieben.

Dein PR macht einige größere Änderungen an der API an vielen Stellen, die nicht mit Philips Hue zusammenhängen, und ich denke, es wäre sinnvoll, darüber vorher zu diskutieren, und falls diese Änderungen wirklich notwendig sind (ich bin mir nicht sicher), denke ich, dass sie eher in einem separaten PR ihren Platz hätten.

Wir versuchen, im Allgemeinen eher kleine PRs zu machen, und wenn es größere API-Änderungen (wie hier in deinem PR) mit Migrations gibt, ist das etwas, worüber wir normalerweise vorher diskutieren.

Ich denke, es ist super wichtig, eine stabile und nicht-brechende API im Laufe der Zeit zu haben, da Nutzer davon abhängen und potenziell Skripte oder externe Integrationen schreiben, die davon abhängen, also sollte man solche Änderungen nicht auf die leichte Schulter nehmen.

Hallo,

Ich habe weiter oben in diesem Gespräch bereits erklärt, warum ich diese Änderungen vornehmen muss.
Ich benötige drei Parameter, um meine Aktion zu konfigurieren: die Zielintensität, die Zeiteinheit und den Wert für die Dauer der Aktion.
Ich denke, dass das Aktionsobjekt nicht geeignet war:

  • Die einzigen möglichen Werte waren text, value und unit, die keine Informationen über die tatsächliche Natur des Inhalts der Variable liefern.
  • Diese Werte befinden sich auf derselben Ebene wie type und devices, es gibt keine Unterscheidung zwischen den Parametern, die die Natur einer Aktion definieren, und denen, die es einer Aktion eines bestimmten Typs ermöglichen, zu funktionieren.

Allerdings hatte ich nicht bedacht, dass die API auch von anderen Verbrauchern als der Gladys-Frontend verwendet werden kann. Ich denke, ich sollte tatsächlich auf die Änderungen der API-Schnittstelle zurückkommen, aber ich schlage vor, die Migration des Datenmodells aus den oben genannten Gründen beizubehalten.

Die Einführung eines Konzepts für ein Szenario ermöglicht die Definition von Aktionen, die komplexer sind als nur das Aktivieren einer Funktion. Ich habe es nicht fadeIn genannt, weil das Szenario-Konzept für jeden Gerätetyp verwendet werden könnte, fadeIn hingegen ist spezifisch für Lampen. Danach habe ich es Szenario genannt, aber es ist mir egal, einen anderen Begriff zu verwenden :smiley:

Das Aktionsobjekt ist beliebig erweiterbar: Du kannst alles reinpacken, was du möchtest :slight_smile:

Wenn du 3 freie Attribute hinzufügen möchtest, nur zu!

Wir hatten darüber gesprochen, spezifische Checks für jede Aktion hinzuzufügen (statt einen globalen Check durchzuführen), aber keinen verschachtelten Objekten im Aktionsobjekt zu erstellen.

Für mich würde die Lesbarkeit erhalten bleiben, wenn wir ein „flaches“ Aktionsobjekt beibehalten, ohne zusätzliche Ebenen zu erstellen.

Wir haben bereits eine Szenario-Funktionalität in Gladys, daher ist es verwirrend, da es hier keinen Bezug dazu gibt.

Wenn du etwas ultra-generisches machen möchtest, warum nicht in diesem Fall über setValue gehen?

Eine der Schwierigkeiten, die ich beim Einstieg in das Konzept von Szenen und Aktionen hatte, ist genau dieser Mangel an Hierarchie bei den Aktionsobjekten. Ich finde, dass ein flaches Objekt die Verständlichkeit der Rolle jeder Eigenschaft erschwert.

Meine Vorstellung von setValue ist der Übergang einer Funktion von einem Zustand in einen anderen für ein bestimmtes Gerät. Der Aufruf löst die Zustandsänderung aus und gibt direkt zurück. Dadurch kann eine API-Anfrage in einer angemessenen Zeit beantwortet werden.
Hier gehört die Aktion zu einer Szene, die aus mehreren Aktionsgruppen bestehen kann, die sequenziell ausgeführt werden müssen.
Stellen Sie sich eine Szene vor, in der ich möchte, dass meine Lampe um 7:20 Uhr für 10 Minuten zu leuchten beginnt und dann mein Radio eingeschaltet wird. Mit einem setValue, das direkt zurückgibt, würde mein Radio um 7:20 Uhr eingeschaltet werden. Ich muss also warten, bis der Zustand meiner Lampe der gewünschte Endzustand ist, um meine Aktion zu beenden und die nächste auszulösen.
Zusätzlich rufe ich in meinem « Szenario » zwei unterschiedliche Funktionen des Objekts Licht auf: binary und brightness. Der setValue sollte sich auf eine einzige Funktion beschränken.

Ich bin nicht einverstanden, für mich ist jede Aktion ein Objekt, das alle seine Eigenschaften hat.

Eine Reihe von Beispielen:

Aktion « 10 Sekunden warten »:

type: "wait"
unit: "seconds"
value: 12

Aktion « Szene « Heizung » starten »:

type: "scene.start"
scene: "chauffage"

Bedingung « Überprüfen, ob die Uhrzeit zwischen 12:00 und 14:00 liegt »:

type: "condition.check-time"
after: "12:00"
before: "14:00"

Ich denke, dass, falls jemand in Zukunft ein kleines Tool programmiert, um Szenen in YAML zu erstellen und sie in Gladys zu importieren, das lesbarer sein wird.

Danach, gut, das ist Geschmackssache, ich denke, es ist auch gut, etwas Leichtes zu behalten, ohne zu viele Objekte zu instanziieren, und nicht zu verschachtelt ^^

In der API ja, aber in einer Szene kannst du einen setValue machen, der wartet, bis das Gerät geantwortet hat, alles ist möglich :slight_smile:

Ich dachte, du nutzt die API von Philips Hue, die das in einem Befehl erledigt?

Nimm meine Anmerkungen nicht übel, ich finde es super, wenn man die getroffenen Entscheidungen an verschiedenen Stellen hinterfragt :smiley:

Aber ich verteidige auch die gewählten Datenformate, die wurden nicht leichtfertig gewählt, und ich denke, es ist wichtig, in dem Maße wie möglich rückwärtskompatibel zu bleiben (außer wenn es wirklich mega blockierend ist und man vorankommen will).

Ich denke, es ist ein gutes Signal an die Community, dass die API « stabil » ist und sich nicht bei jeder Gladys-Minor-Version alle paar Tage ändert :slight_smile:

Okay, dann entferne ich die Parameter.

Ich muss die Lampe einschalten und die Helligkeit zu Beginn der Aktion auf das Minimum zurücksetzen, bevor ich den Befehl für die schrittweise Helligkeitsänderung verwende. Ich ändere also mehrere Zustände auf verschiedenen Features eines Geräts.

Ok, ich sehe

Danach ist es ein „technisches Detail“ der Philips Hue-Implementierung, oder? Das ist nicht spezifisch für Gladys?

Gut, ich werde in deinem PR sehen, was du gemacht hast :slight_smile:

Super! Danke für die Änderung :folded_hands: