Warum überhaupt der Umweg über die globale Variable?
Geht es evtl. darum, dass Sonos_Delta_Move gar keinen gültigen Wert anzeigt? Das liegt dann daran, dass das Item keinen gültigen Initialwert hat. Damit löst auch die Rule nicht aus, denn das Setpoint Widget kann nur korrekt arbeiten, wenn das Item schon einen gültigen Wert enthält. Du musst also (einmalig) dafür sorgen, dass eine Zahl im Item gespeichert ist. Anschließend kannst Du das Item über die Persistence und die Strategy
everyChange,restoreOnStartup beim Systemstart mit dem zuletzt eingestellten Wert versorgen.
Für den Initialwert gibt es verschiedene Möglichkeiten, die "geradeaus Variante" wäre, über den API Explorer das Item zu setzen. alternativ auch über die Karaf Konsole, ein Widget, welches gezielt einen fixen Wert sendet oder eine Rule, welche mit
system started triggert, oder, oder, oder...
Ein paar weitere Dinge: In der ersten Rule testest Du (vorbildlich), ob das Item einen gültigen Zahlenwert enthält. In der zweiten Rule unterlässt Du das, dort kann es aber genauso passieren, dass eines der Items keine gültige Zahl liefert.
Wie gesagt gehe ich davon aus, dass die erste Rule mutmaßlich entfallen kann.
Das momentane Verhalten (wenn alles korrekt funktionieren würde) wäre, dass die Lautstärke von Sonos_Mov um den Wert von Sonos_Delta_Move niedriger als Sonos_Kue gesetzt wird, allerdings ausschließlich, wenn Sonos_Grp_Vol geändert wurde. Wenn man z.B. Sonos_Delta_Move anpasst, passiert nichts, genauso wenn man Sonos_Kue anpasst (es sei denn, dieses ist Member von Sonos_Grp_Move und das Group Item hat eine Funktion AVG hinterlegt, so dass jede Änderung eines Members auch zwingend eine Änderung des Group Items nach sie zieht).
Mutmaßlich wäre also so etwas zielführender:
Code: Alles auswählen
rule "Sonos group volume kitchen"
when
// Item Sonos_Delta_Move changed or
// Item Sonos_Kue_Volume changed or
Item Sonos_Grp_Vol changed
then
val volumeDelta = if(Sonos_Delta_Move.state instanceof Number) {Sonos_Delta_Move.state as Number).intValue else 0
val volKue = if(Sonos_Kue_Volume.state instanceof Number) (Sonos_Kue_Volume.state as Number).intValue else -1
val volMove = if(Sonos_Mov_Volume.state instanceof Number) (Sonos_Mov_Volume.state as Number).intValue else -1
if(volKue < 0) {
logWarn("groupVol","Sonos_Kue_Volume liefert keinen gültigen Zahlenwert! Abbruch.")
return;
}
var newVolMove = volKue - volumeDelta
if (newVolMove < 0) newVolMove = 0
if (newVolMove != volMove) Sonos_Mov_Volume.sendCommand(newVolMove)
end
Die beiden zusätzlichen Trigger sind für den Fall, dass die Änderung jeweils direkt Auswirkungen auf Sonos_Mov haben soll, dann müsstest Du jeweils die Kommentarzeichen entfernen.
In den ersten drei Zeilen werden die Items ausgelesen. Liegt kein gültiger Wert vor, so wird die Zahl am Ende als Wert gesetzt.
Im Fall von volKue muss ein gültiger Wert ausgelesen worden sein, weshalb man mit einer Prüfung auf < 0 nun eine Warnmeldung ausgeben kann und die Rule abbricht, ohne etwas zu tun.
Anschließend kann die neue Soll Lautstärke berechnet werden und bei Abweichung diese gesendet werden.
Die geschweiften Klammern markieren mehrere Befehle als einen Block. Muss nur ein einzelner Befehl ausgeführt werden, so kann man darauf verzichten.
Die Methode
Sonos_Mov_Volume.sendCommand(newVolMove) sollte immer der Action
sendCommand(Sonos_Mov_Volume,newVolMove) vorgezogen werden.
Es ist hier nicht notwendig, den Datentyp der Variablen und Konstanten explizit vorzugeben, da dieser sich aus dem zugewiesenen Wert ergibt.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet