Legacy‐Gerätedefinitionen für Adapter Version 2.0.1 oder neuer anpassen. - ioBroker/ioBroker.zigbee GitHub Wiki
So reparieren Sie die Gerätedefinition, um die alten Gerätezustände von vor V2.0.1 beizubehalten
Kontext
Mit der Änderung von Adapterversion 1.10.x auf 2.0.x hat der Adapter alle adapterspezifischen Gerätedefinitionen in den Status „alt“ gesetzt, da sich die von den Zigbee-Herdsman-Konvertern gesendeten Nutzdaten beim Update von den Zigbee-Herdsman-Konvertern 20.x auf 21.x stark geändert haben. Obwohl es theoretisch möglich ist die adapterspezifischen Gerätedefinitionen mit den neuen Nutzdaten zum Laufen zu bringen haben wir (die Entwickler des Adapters) uns entschieden diesen Weg nicht zu gehen da dies ein veraltetes System zementiert das ständige Überwachung sowie Zugriff auf die jeweiligen Geräte erfordert. Dies ist für die aktuellen Adapterentwickler nicht machbar. Jeder, der ein betroffenes Gerät hat, ist herzlich eingeladen diese Arbeit durchzuführen und die alte Definition zu aktualisieren. Dieses Dokument erläutert die dazu erforderlichen Schritte. Es versucht auch, die Verbindung zwischen Gerätenachrichtennutzdaten und -zustand zu erklären. Bitte beachten Sie, dass diese Erklärung nur die gängigsten Mittel hierfür abdeckt. Es gibt zusätzliche Überlegungen die möglicherweise eine eingehende Diskussion mit einem Adapterentwickler erfordern. In diesem Fall sollte ein Github Issue, in dem um Unterstützung bei der Aktualisierung eines Geräts gebeten wird, die erforderlichen Informationen liefern.
Struktur
Jede Kommunikation zwischen dem Zigbee-Adapter und dem Gerät durchläuft 2 Übersetzungsebenen. Ebene 1 ist die Übersetzung zwischen dem ioBroker-Status und der Nachrichtennutzlast. Dies wird durch die Statusdefinition gehandhabt. Bei älteren Geräten wird dies explizit in der Datei lib/states.js
definiert. Bei normalen Geräten wird die Statusdefinition automatisch mit Informationen generiert, die über die Exposes-Funktionalität aus den Zigbee-Herdsman-Converters gezogen werden.
Ebene 2 wird vom Konverter aus der Zigbee-Herdsman-Converters-Bibliothek gehandhabt, der die Konvertierung zwischen Nutzlast und Zigbee-Nachrichtendaten übernimmt.
Die Gerätedefinition im Zigbee-Adapter definiert die Zustände, die ein Gerät haben wird. Bei älteren Geräten ist dies explizit in der Datei lib/devices.js
definiert. Bei normalen Geräten wird dies über die Exposes-Funktionalität aus den Zigbee-Herdsman-Converters bezogen.
Beispielcode
devices.js:
const legacy_devices = [
.
.
.
{
models: ['QBKG12LM'],
icon: 'img/ctrl_ln2.png',
states: [
states.left_button, states.right_button, states.left_state, states.right_state,
states.operation_mode_left, states.operation_mode_right,
states.left_click_single, states.right_click_single, states.both_click_single,
states.left_click_double, states.right_click_double, states.both_click_double,
],
},
.
.
.
]
states.js:
const states = {
.
.
.
left_state: {
id: 'left_state',
prop: 'state_left',
name: 'Left switch state',
icon: undefined,
role: 'switch',
write: true,
read: true,
type: 'boolean',
getter: payload => (payload.state_left === 'ON'),
setter: (value) => (value) ? 'ON' : 'OFF',
setattr: 'state',
epname: 'left',
},
right_state: {
id: 'right_state',
prop: 'state_right',
name: 'Right switch state',
icon: undefined,
role: 'switch',
write: true,
read: true,
type: 'boolean',
getter: payload => (payload.state_right === 'ON'),
setter: (value) => (value) ? 'ON' : 'OFF',
setattr: 'state',
epname: 'right',
},
left_click_single: {
id: 'left_click',
prop: 'click',
name: 'Left click event',
icon: undefined,
role: 'button',
write: false,
read: true,
type: 'boolean',
isEvent: true,
getter: payload => (payload.click === 'left_single') ? true : undefined,
},
left_click_double: {
id: 'left_click_double',
prop: 'click',
name: 'Left click double event',
icon: undefined,
role: 'button',
write: false,
read: true,
type: 'boolean',
isEvent: true,
getter: payload => (payload.click === 'left_double') ? true : undefined,
},
.
.
.
}
Beachten Sie, dass das Codebeispiel von einem funktionierenden Gerät stammt, aber unvollständig ist.
Verknüpfung zwischen Gerät und Gerätedefinition:
Jedes Zigbee-Gerät enthält eine „Modell“-Bezeichnung auf dem Infobildschirm (siehe Bild)
Diese Zeichenfolge wird verwendet um die Gerätedefinition aus dem Array der Legacy-Geräte zu identifizieren.
Dinge die angepasst werden müssen um einen Status einer Nachrichtenstruktur zuzuordnen
Um dies erfolgreich zu tun muss man verstehen wie die Verbindung zwischen der Nutzlast und dem Status hergestellt wird. Es gibt verschiedene Methoden dafür - 3 davon werden in der Folge beschrieben. Von diesen sind nur zwei Teil der obigen Beispiele:
- durch
id
. Wird als Basis-Fallback verwendet, wenn keine der beiden anderen Methoden ausgelöst wird: Wenn das Nutzlastobjekt die Eigenschaft enthält, die der Eigenschaftid
entspricht, wird der Wert für diese Eigenschaft der Nutzlast als Wert für den Status festgelegt. Im Falle von Statusänderungen enthält die generierte Nutzlast das jeweilige Eigenschafts-/Wertpaar.
Beispielcode und Nutzlastpaar:
example_state: {
id: 'p1',
write: true,
read: true,
type: 'boolean',
},
Der Wert für den Status .p1
wird auf 'randomstringvalue'
gesetzt, wenn die Nutzlast { p1:‘randomstringvalue‘ }
empfangen wird. Beachten Sie, dass dies eine Warnung vom JSController generiert, da es nicht richtig ist einem booleschen Status einen Zeichenfolgenwert zuzuweisen.
Eine Statusänderung des Status .p1 durch den Benutzer auf true
generiert die Nutzlast {p1:true}
und sendet sie an den Konverter. Hinweis: In den meisten Fällen ist wird in der Nutzlast eine Zeichenkette oder eine Zahl als Wert erwartet, kein boolscher Wert.
– durch prop
. Wird als Fallback verwendet, wenn kein Getter/Setter verfügbar ist: Wenn das Nutzlastobjekt die Eigenschaft enthält, die der Eigenschaft prop
entspricht, wird der Wert für diese Eigenschaft der Nutzlast als Wert für den Status festgelegt. Im Falle von Statusänderungen enthält die generierte Nutzlast das entsprechende Eigenschafts-/Wertpaar.
Beispielcode und Nutzlastpaar:
example_state: {
id: 'p1',
prop: 'example'
write: true,
read: true,
type: 'boolean',
},
Der Wert für den Status .p1
wird auf 99 gesetzt, wenn die Nutzlast {example:99}
empfangen wird. Beachten Sie, dass dies eine Warnung vom JSController generiert, da es nicht richtig ist, einem booleschen Status einen Zahlenwert zuzuweisen.
Eine Statusänderung des Status .p1
durch den Benutzer auf true
generiert die Nutzlast {example:true}
und sendet sie an den Konverter.
- durch
Getter/Setter
. Wenn der Getter einen nicht undefinierten Wert zurückgibt, wird davon ausgegangen, dass die Nutzlast verarbeitet wurde, und der Status wird aktualisiert. Bei Statusänderungen wird der Setter (falls verfügbar) mit dem Parametervalue
aufgerufen. Beispielcode und Nutzlastpaar:
example_state: {
id: 'p1',
prop: 'example'
write: true,
read: true,
type: 'boolean',
getter: payload => (payload.state_right === 'ON'),
setter: (value) => (value) ? 'ON' : 'OFF',
},
Der Wert für den Status .p1 wird auf true
gesetzt, wenn die Nutzlast { state_right:'ON' }
empfangen wird, (auf false
für jede Nutzlast, die die Eigenschaft state_right
mit einem Wert ungleich 'ON'
enthält.
Eine Statusänderung des Status .p1 durch den Benutzer auf true
generiert die Nutzlast { example:'ON' }
und sendet sie an den Konverter.
Eine State-Definition muss nicht unbedingt getter und setter definieren. Sofern nur eine der beiden Funktionen definiert ist wird der andere Fall durch die vorhandenen Fallback-Methoden abgedeckt.
Weitere Überlegungen
Es gibt eine Reihe weiterer wichtiger Eigenschaften der Statusdefinition:
- write: wenn der Status vom Benutzer beschreibbar ist
- read: wenn der Status vom Benutzer lesbar ist
- max: ein Maximalwert für numerische Status
- min: ein Minimalwert für numerische Status
- type: der Typ des Status
- role: die Rolle für den Status, wie sie in der iobroker-Statusanzeige sichtbar ist.
- isEvent: nur gültig für boolesche Stati. Wenn dies auf
true
gesetzt ist wird der Status 200 ms nachdem er durch eine empfangene Nutzlast auftrue
gesetzt wurde auffalse
zurückgesetzt - isOption: Dieser Status generiert keine eigene Konverternutzlast. Stattdessen wird sie eingeschlossen, wenn andere Nutzlastnachrichten gesendet werden.
Diese Liste ist keineswegs vollständig. Die Datei states.js enthält eine große Anzahl von Zuständen die als Beispiele für die Handhabung bestimmter Fälle verwendet werden können.
Warnung
Es ist wichtig zu beachten, dass Änderungen an Zuständen, die von mehreren Geräten verwendet werden, alle dieser Geräte betreffen. Daher sollten nur gerätespezifische Zustände auf diese Weise aktualisiert werden. Wenn ein globaler Zustand verwendet wird, sollte er in einen gerätespezifischen Zustand kopiert und dann an die neue Nachrichtenstruktur angepasst werden.
Schlussbemerkungen
Eine Möglichkeit zum Generieren einer externen Gerätedefinition, die in sich geschlossen ist und nur die „geänderten“ Zustände definiert, während auf die allgemeinen Zustände zugegriffen wird, ist in Entwicklung. Sobald diese verfügbar ist, wird dieses Dokument aktualisiert, um diese Änderung widerzuspiegeln. Es gibt jedoch derzeit keine ETA für diese Funktion.
Sobald Änderungen erfolgreich vorgenommen wurden erwarten wir dass ein Pull Request aus einem geforkten Adapter-Repository an den Hauptzweig dieses Adapters gesendet wird. Dadurch können wir Änderungen einfach überprüfen, akzeptieren oder ablehnen. Beachten Sie, dass automatische Tests Teil der Pull Request-Funktionalität sind und wir erwarten, dass jeder PR die meisten - wenn nicht alle - dieser Tests fehlerfrei besteht. Jede verbleibende Fehler/Warnmeldung muss in einem Kommentar zum PR begründet werden.