Ankündigung

Einklappen
Keine Ankündigung bisher.

Hausgeräte Abfrage in einer Rule nutzen

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    [Codebeispiel] Hausgeräte Abfrage in einer Rule nutzen

    Hallo,
    ich frage meine Miele Hausgeräte über der Http-Binding ab und möchte die Ergebnisse in einer Rule nutzten. Hierzu frage ich das Gateway ab welches mir ein .XSL File zur Verfügung stellt. Mein Item hierzu ist zb. bei meinem Trockner:
    Code:
    String statustrockner "Status [%s]" (Trockner) { http="<[http://192.168.11.230/homebus/device?language=de&type=TD_T4898&id=TD_T4898.-1609532774:60000:XSLT(trocknerstatus.xsl)]" }
    Um nun die passenden Ausgaben zu bekommen hier noch die trocknerstatus.xsl :

    Code:
    <?xml version="1.0" encoding="utf-8" ?>
    <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
        <xsl:output indent="yes" method="xml" encoding="UTF-8" omit-xml-declaration="yes"/>
        <xsl:template match="/device/information">
            <xsl:value-of select="key[position() = 2]/@value"/>
        </xsl:template>
    </xsl:stylesheet>
    Als Ausgabe bekomme ich nun jede Statusänderung wobei ich dann in einer Rule eine Aktion auslösen möchte wenn der Trockner fertig ist. Meine Rule:

    Code:
    import org.openhab.core.library.types.*
    
    import org.openhab.model.script.actions.*
    var Timer timer
    var condition = transform("MAP", "miele.map", "Fehler!")
        rule "Miele Trockner"
    
        when
                Item statustrockner changed to Ende
        then
            if(statustrockner.state.toString==Ende) {
                logInfo("Miele","statustockner: {}",statustrocner.state)
                logInfo("Miele","Esszimer_Color: {}",Esszimmer_Color.state)
                sendCommand(Esszimmer_Color,100) //100 => 100%-Helligkeit
                sendCommand(Esszimmer_Color, HSBType::RED)
                timer = createTimer(now.plusMinutes(10)) [|
                    {
                    Esszimmer_Color.sendCommand("74,78,56")
                    postUpdate(timer1,OFF)
                    //pushover ("Trockner ist fertig")
                    }
                ]
            } else {
                if(timer!=null) {
                    timer.cancel
                    timer = null
                }
            }
        end


    Leider läuft es nicht, ich beomme im Log folgende Meldung:

    Code:
    2017-11-26 09:47:14.113 [ERROR] [.script.engine.ScriptExecutionThread] - Rule 'Miele Trockner': An error occurred during the script execution: The name 'Ende' cannot be resolved to an item or type.
    Hätte jemand eine Idee was ich falsch mache ?

    Gruß
    Frank



    #2
    Man kann im when-Teil einer Rule im Zusammenhang mit changed oder received nur bekannte States verwenden. Bekannt in dem Sinne, dass openHAB dafür einen Typ definiert hat. Es gibt z.B. OnOffType, das wären dann die Status ON, OFF und NULL.

    Man kann aber nicht auf eine beliebige Zeichenkette triggern (also z.B. "Ende") - abgesehen davon, dass Dein Trigger ja ein Status wäre und keine Zeichenkette.
    Es gibt dazu einen Issue in github mit dem Wunsch, diese Fähigkeit auszubauen. Bis dahin muss der Kopf der Rule so aussehen:
    Code:
    rule "Miele Trockner"      
    when        
        Item statustrockner changed
    then    
        if(statustrockner.state.toString=="Ende") {
    Weiterhin, falls Du openHAB2 einsetzt, sind beide imports zum einen ungültig (openHAB2 unterstützt keine .* im import), zum anderen aber auch unnötig, weil beide Klassen ohnehin per default vorhanden sind und deshalb nicht mehr importiert werden müssen.

    Ich mache immer Werbung, die Methoden statt der Actions einzusetzen. Interessanterweise nutzt Du ja beide Varianten in einer Rule.
    Diese Variante sendCommand(Esszimmer_Color, HSBType::RED) ist schlecht, diese Variante Esszimmer_Color.sendCommand("74,78,56") ist gut.
    Bis auf Helligkeitswert und Farbe sollten sich die beiden ja erstmal nicht unterscheiden, aber die Action sendCommand(Item as String, Value as String) verlangt immer für beide Parameter einen String. Dass dies oft klappt, obwohl man gar keinen String übergeben hat, liegt daran, dass openHAB stillschweigend die Methode .toString anwendet, falls ein Objekt übergeben wird (alle Objekte kennen die Methode .toString, da sie vererbt wurde). Man könnte hier aber auch ein Primitive übergeben, und wenn das dann nicht vom Typ String ist, geht der Aufruf schief. Die Methode kennt für jeden sinnvollen Parametertyp unterschiedliche Wege und nimmt Umrechnungen selbst vor, weshalb der Aufruf auch mit einem Primitive vom Typ integer oder float funktionieren wird. Genaueres kannst Du der offiziellen Doku entnehmen.
    Warum gibt es überhaupt die Action? Es kann sein, dass man den Namen eines Items per Formel erzeugt, dann klappt die direkte Übergabe als Objekt nicht.

    Kommentar


      #3
      Vielen Dank für deine Hilfe, dass schaut schon deutlich besser aus. Um allerdings Erfolg melden zu können brauche ich noch etwas weil die Maschinen alle laufen müssen. Ich möchte den Homebus ungern simulieren.

      Was mir jedoch schon aufgefallen ist , dass bei "Item statustrockner changed" habe ich zwei Auslöser. Also das Programm läuft folgendermaßen ab:

      Fertig to Aufheizen, ......................, Kaltluft to Fertig.

      Kommentar


        #4
        letztlich ist es ja egal, wieviele verschieden Status es gibt. Je mehr Du davon auswerten möchtest, desto mehr Bedingungen musst Du halt einbauen:
        Code:
        rule "Miele trockner"
        when
            Item statustrockner changed
        then
            if(statustrockner.state.toString=="Ende") {
                //Mach was
            }
            else if(statustrockner.state.toString=="Kaltluft") {
                //Mach was anderes
            }
            else if(statustrockner.state.toString=="Aufheizen") {
                //Mach noch was anderes
            }
        end
        Wenn es genug verschiedene Meldungen gibt, die Aktionen auslösen sollen, lohnt sich dann switch - case:
        Code:
        rule "Miele trockner"
        when
            Item statustrockner changed
        then
            switch statustrockner.state.toString {
                case "Ende": { //Wenn Ende
                    //Mach was
                }
                case "Kaltluft": { //Wenn Kaltluft
                    //Mach was anderes
                }
                case "Aufheizen": { //Wenn Aufheizen
                    //Mach noch was anderes
                }
                case default: { //alles andere
                    //Daran wurde nicht gedacht...
                }
            }
        end
        switch case kann nur mit diskreten Werten umgehen, man kann also nicht (bei numerischem input) Wertebereiche abdecken. Ansonsten ist der Code oft besser lesbar.

        Wenn man in der Rule berücksichtigen will, von welchem Wert der aktuelle Wert gewechselt wurde, geht das mit previousState (bitte nicht verwechseln mit dem Attribut .previousState, dafür benötigt man einen persistence Service - für die Variable braucht man den nicht).
        Die Variable previousState ist automatisch mit dem vorangegangenen Status des Items gefüllt, welches einen Change getriggert hat. Wenn also die Rule getriggert wird, ist im Fall, dass der Trockner "Fertig" meldet, der Inhalt von previousState "Kaltluft". Allerdings sollte das keine Rolle spielen, die Rule triggert ja nur, wenn sich der Status geändert hat, und dann wird durch die if-Abfrage der passende Code nur ausgeführt, wenn der aktuelle Status das Ende des Trocknungsvorgangs meldet. Es sollte natürlich nicht vorkommen, dass das Gerät aus einem anderen Zustand nach "Fertig" springt, ohne dass Wäsche getrocknet wurde, aber das ließe sich ja leicht mit previousState abfangen.

        Kommentar

        Lädt...
        X