Seite 1 von 1

Aqara Motion Sensor schaltet immer

Verfasst: 16. Nov 2020 12:44
von superpedro
Hallo,

ich versuche gerade seit Tagen meinen Aqara Motion Sensor erfolgreich ins System zu integrieren.
Habe das Ganze über Raspbee II gelöst.

Jetzt möchte ich, dass der Sensor eine Lampe nur dann schaltet, wenn es im Raum dunkel ist und nach 3 Minuten wieder aus. Ich habe dafür eine Rule geschrieben, die via Lichtsensor den Lux-Wert ermittelt und dann bei Bewegung schaltet. Damit dies funzt muss aus dem state des Sensors, der reine Zahlenanteil extrahiert werden (muss das so sein?), um Ihn dann mit einen Schwellenwert vergleichen zu können.
Ich habe dies durch die Übergabe des reinen Zahlenwertes in eine Variable gelöst. Leider zeigt zum einen der Lichtsensor manchmal komische Lux-Werte an, aber leider schaltet der Sensor gerade immer das Licht an denn, im Visual Studio kommt die Errormeldung:

Code: Alles auswählen

Cannot reference the field 'Bewegung_Whz_Illuminance' before it is defined
Fragen:
Wie habt Ihr das hell/ dunkel Problem zuverlässig gelöst? Gibt es irgendeine zusätzliche Variable um das Dunkel zu überprüfen? Wie zuverlässig ist der DaylightPhilips Lightlevel Wert??

Gibt es eine Lösung für diesen Fehler?

Hier meine Rule:

Code: Alles auswählen

var Timer tNachtlicht = null
var int Schwellwert = 5
var Number Flur_Lux = Bewegung_Whz_Illuminance.state as Number

rule "Bewegungsmelder"
when
  Item Bewegung_WhzLUMI_Presence changed from OFF to ON
then
  if(Flur_Lux < Schwellwert) {
  // Sollte der Timer bereits gesetzt sein, wird er verworfen
  if (tNachtlicht!== null) {
    tNachtlicht.cancel
    tNachtlicht = null
  }
  
  logDebug("Nachtlicht", "Schalte jetzt das Nachtlicht.")
  sendCommand(LED_Wohnzimmer002, "ON")
    tNachtlicht = createTimer(now.plusSeconds(180)) [|
      sendCommand(LED_Wohnzimmer002, "OFF")
    ]
  }
  
end

Re: Aqara Motion Sensor schaltet immer

Verfasst: 16. Nov 2020 13:56
von udo1toni
Also, ich bin ja immer ein Korinthen... ;)

Visual Studio... ist eine Programmierumgebung für .NET in den verschiedenen Geschmacksrichtungen. Du nutzt Visual Studio Code (oder kurz VS Code).

Der nächste Punkt. Du definierst eine globale Variable Flur_Lux und versuchst bei der Definition, ihr den Status von Bewegung_Whz_Illuminance zuzuweisen. Wie kommst Du auf die Idee, dass anschließend ein reiner Zahlenwert vorliegt? Und noch schlimmer: Wie kommst Du auf die Idee, dass eine globale Variable automatisch den Wert dynamisch ändert?

Die Variable kann global definiert sein (ist aber hier gar nicht nötig), der Wert muss aber zwingend beim Ausführen der Rule gesetzt werden.
Das sieht dann so aus:

Code: Alles auswählen

var Timer tNachtlicht = null
var Integer iSchwellwert = 5

rule "Bewegungsmelder"
when
    Item Bewegung_WhzLUMI_Presence changed from OFF to ON
then
    val Integer iFlur_Lux = if(Bewegung_Whz_Illuminance.state instanceof Number) (Bewegung_Whz_Illuminance.state as Number).intValue else 0
    if(iFlur_Lux < iSchwellwert) {
        tNachtlicht?.cancel                                       // Timer verwerfen, falls vorhanden
        logDebug("Nachtlicht", "Schalte jetzt das Nachtlicht.")
        LED_Wohnzimmer002.sendCommand(ON)                         // Switch Item einschalten
        tNachtlicht = createTimer(now.plusSeconds(180), [|
            LED_Wohnzimmer002.sendCommand(OFF)                    // Switch Item ausschalten
        ])
    }
end
Der Wert aus Bewegung_Whz_Illuminance wird in der Konstanten iFlur_Lux gespeichert, falls es sich um einen gültigen wert handelt. Ansonsten wird 0 als Wert angenommen. Der ternäre Operator spart Platz...
Verzichtet man auf diese Einschränkung, kann es zu einer NullPointerException kommen.
Beim Speichern wird explizit der intValue verwendet (man könnte hier z.B. auch floatValue verwenden), weil wir mit einem Integer vergleichen wollen. Nur durch die Verwendung von intValue (oder floatValue...) wird eine eventuell vorhandene Einheit entfernt!.
Entsprechend nehmen wir auch gleich eine Integer Konstante (nicht int, das ist zwar auch Integer, aber ein primitive)
Im Aufruf tNachtlicht?.cancel bewirkt das Fragezeichen das gleiche Verhalten, falls tNachtlicht nicht null ist, wird der Timer gecancelt.
Die Schreibweise des Timers ist im Detail abweichend, das Lambda steht nicht hinter der Funktion, sondern ist der zweite Parameter der Funktion (also schließende Klammer erst nach der schließenden eckigen Klammer und ein Komma vor dem Lambda)
Damit wird beim Lesen des Codes besser klar, dass das Lambda eben genau das ist: ein übergebener Parameter.
sendCommand als Action ist nicht unproblematisch, weil beide Parameter als String übergeben werden müssen (wobei openHAB oft, aber eben nicht immer automatisch nach String wandelt). Besser ist es, die Methode sendCommand zu nutzen. Sofern es sich um ein Switch Item handelt, sollte man dann auch den OnOffType als Parameter verwenden und nicht einen String.