Xiaomi Sauer 2x nacheinander saugen lassen?

Einrichtung der openHAB Umgebung und allgemeine Konfigurationsthemen.

Moderatoren: seppy, udo1toni

Benutzeravatar
Steinspiel
Beiträge: 396
Registriert: 28. Dez 2019 08:49
Answers: 2

Xiaomi Sauer 2x nacheinander saugen lassen?

Beitrag von Steinspiel »

Moin,

Ich will meinen Xiaomi 1S Sauger nacheinander zwei Räume reinigen lassen. Der erste Raum ist kein Problem:

Code: Alles auswählen

rule "test_saugen"

when
        Item Robo_Test_B changed                                        // Testschalter  EIN
    
then
        
        Mi_1S_ActionsCommands.sendCommand("app_segment_clean[16]")      // Raum 16 saugen
                
end
Danach fährt er wieder ins Dock, nur WIE schicke ich ihn dann ein zweites mal los?
Es git ein Item "StatusState", das z.B. mit "Room Clean", "Returning Dock" oder "Charging" Statusmeldungen gibt, nur wie verwende ich die?
Erweitere ich then

Code: Alles auswählen

***
then
        
        Mi_1S_ActionsCommands.sendCommand("app_segment_clean[16]")      // Raum 16 saugen
        if(Mi_1S_StatusState.state == "Charging")   {
        Mi_1S_ActionsCommands.sendCommand("app_segment_clean[17]")      // Raum 17 saugen
        }     
***
passiert nichts wenn er wieder angedockt ist, weil die Rule ja schon abgearbeitet ist bevor der Sauger wieder im Dock steht.

Ich habe es mit einer zweiten Rule versucht

Code: Alles auswählen

***
when
        Item Mi_1S_StatusState changed from "Returning Dock" to "Charging"
***
Also wenn er zurück gekehrt ist und zu laden beginnt, dann wieder los fährt. Funktioniert soweit, ist aber IMO auch doof denn das macht er ja dann immer wenn er in Dock fährt.

Ich habe versucht das dann in if() unter zu bringen,

Code: Alles auswählen

***
then
        
        Mi_1S_ActionsCommands.sendCommand("app_segment_clean[16]")      // Raum 16 saugen
        if(Mi_1S_StatusState changed from "Returning Dock" to "Charging")   {
        Mi_1S_ActionsCommands.sendCommand("app_segment_clean[17]")      // Raum 17 saugen
        }
***		
Aber da hagelt es zig Fehlermeldungen von VSCode, ich denke eine "changed" ist für if() nicht vorgesehen..., oder?

Dann habe ich gedacht einen Timer dazwischen zu bauen, aber das ist ja auch so eine Sache: mal dauert das saugen länger, mal kürzer...

Hat jemand eine Idee, WIE ich den Sauger direkt nach der ersten Reinigung wieder los schicken könnte?

Ach ja, Zonenreinigung mit Koordinaten funktioniert bei mir nicht, ich kann also nicht aus den zwei Räumen einen machen!
bis dann, Steinspiel

Darkwin101
Beiträge: 424
Registriert: 6. Mär 2019 11:19
Answers: 14

Re: Xiaomi Sauer 2x nacheinander saugen lassen?

Beitrag von Darkwin101 »

Du kannst dir doch eine Hilfsvariable zur Hilfe nehmen in etwa so:

Code: Alles auswählen

var int Raumreinigung = 0  // Muss am Anfang der Datei geschrieben werden
rule "test_saugen"

when
        Item Robo_Test_B changed                                        // Testschalter  EIN
    
then
        Mi_1S_ActionsCommands.sendCommand("app_segment_clean[16]")      // Raum 16 saugen
        Raumreinigung = 1        
end
In der zweiten dann:

Code: Alles auswählen

rule"Raum 2 Saugen oder Rücksetzen"
when
        Item Mi_1S_StatusState changed from "Returning Dock" to "Charging"
then
                        if(Raumreinigung == 1){
 			Mi_1S_ActionsCommands.sendCommand("app_segment_clean[17]")      // Raum 17 saugen
 			Raumreinigung = 2}
 			if(Raumreinigung == 2) {
 			Raumreinigung = 0
 			Robo_Test_B.postUpdate(OFF)}
end

Benutzeravatar
Steinspiel
Beiträge: 396
Registriert: 28. Dez 2019 08:49
Answers: 2

Re: Xiaomi Sauer 2x nacheinander saugen lassen?

Beitrag von Steinspiel »

Moin,
Darkwin101 hat geschrieben: 24. Jul 2020 08:28 Du kannst dir doch eine Hilfsvariable zur Hilfe nehmen in etwa so:
[...]
Das ist doch genau das was ich wollte! Und durch die Variable könne ich noch einen dritten oder vierten Raum hinterher schicken, Danke! ;)

Nur für mich zur Erklärung:

Code: Alles auswählen

var int Raumreinigung = 0  // Muss am Anfang der Datei geschrieben werden
eine Variable als ganze Zahl?

Und noch ne Frage, wieso hast Du in der zweiten Rule die Raumreinigung erst auf "2" und dadurch dann auf "0" gesetzt? Ich habe die "2" weggelassen und nach dem zweiten Aufruf für Raum 17 gleich alles auf "0" gesetzt, hat auch funktioniert!
bis dann, Steinspiel

Darkwin101
Beiträge: 424
Registriert: 6. Mär 2019 11:19
Answers: 14

Re: Xiaomi Sauer 2x nacheinander saugen lassen?

Beitrag von Darkwin101 »

eine Variable als ganze Zahl? ja ganz genau und diese wird initialisiert mit 0
Hat nur den Grund das ich erst warte bis der Sauger wieder im Dock ist also die Raumreinigung abgeschlossen ist.
Kannst natürlich auch bei Start des zweiten Raum sofort zurücksetzen.

Ok sehe meinen Fehler die zweite Abfrage gehört vor die erste damit erreicht wird was ich bezwecken wollte.
Zuletzt geändert von Darkwin101 am 24. Jul 2020 17:00, insgesamt 1-mal geändert.

Benutzeravatar
udo1toni
Beiträge: 15244
Registriert: 11. Apr 2018 18:05
Answers: 242
Wohnort: Darmstadt

Re: Xiaomi Sauer 2x nacheinander saugen lassen?

Beitrag von udo1toni »

Beim Hochzählen geht es, denke ich, darum, dass der Roboter ja in die Ladestation fährt. Das löst die Rule aus.
Eigentlich sollte eine Rule reichen:

Code: Alles auswählen

var int Raumreinigung = 0  // Muss am Anfang der Datei geschrieben werden

rule "Saugen"
when
    Item Robo_Test_B changed to ON or                                      // Testschalter  EIN
    Item Mi_1S_StatusState changed from "Returning Dock" to "Charging"     // Roboter ist zurück in der Station
then
    Raumreinigung ++ // oder Raumreinigung = Raumreinigung + 1             // Raumzähler erhöhen
    var String strRaum = ""                                                // Variable initialisieren
    logInfo("vacuum","Raum {} gewählt",Raumreinigung)
    switch (Raumreinigung) {                                               // Abhängig von Raumzähler
        case 1:                                                            // falls 1
            strRaum = "app_segment_clean[16]"
        case 2:                                                            // falls 2
            strRaum = "app_segment_clean[17]"
        case 3:                                                            // falls 3
            strRaum = "app_segment_clean[18]"
        case 4:                                                            // falls 4
            strRaum = "app_segment_clean[19]"
        default: {                                                         // sonst
            Raumreinigung = 0                                              // Raumzähler auf 0
            if(Robo_Test_B.state != OFF)                                   // Falls Schalter nicht OFF
                Robo_Test_B.postUpdate(OFF)                                // auf OFF
        }
    }
    logInfo("vacuum","Raumzone {} gewählt",strRaum)
    if(strRaum != "")                                                      // Neuer Raum ausgewählt
        Mi_1S_ActionsCommands.sendCommand(strRaum)                         // Raum saugen
end
Wenn Du 27 Räume hast, musst Du nur entsprechend viele case-Anweisungen vorsehen. Im case wird lediglich der String definiert, der abschließnd an den Roboter gesendet werden soll.

Nachteil: Der Roboter spult die Räume stur genau so ab. Man könnte vorn abfragen, ob der Schalter (noch) ON ist, dann kann man zumindest den Saugvorgang am Ende eines Raumes abbrechen.

Die Rule ließe sich aber auch noch erweitern:
  • Startvorgang in dem Raum, der nicht (mehr) gesaugt wurde
  • Liste der zu suagenden Räume wird über Schalter festgelegt
  • ...
Ich selbst habe keinen Saugroboter, das würde bei unserem Chaos auch nie funktionieren (Der Roboter muss ja leere Fläche zum Reinigen haben...), aber die Programmierung macht bestimmt Spaß ;)
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Benutzeravatar
Steinspiel
Beiträge: 396
Registriert: 28. Dez 2019 08:49
Answers: 2

Re: Xiaomi Sauer 2x nacheinander saugen lassen?

Beitrag von Steinspiel »

Moin,
Die Zählweise lass ich so wie sie mir @Darkwin101 vorgeschlagen hat. Ist für mich im Moment alles noch sehr gut nach voll ziehbar... ;-)
udo1toni hat geschrieben: 24. Jul 2020 17:00 [...]
[*]Liste der zu suagenden Räume wird über Schalter festgelegt
Da bin ich gerade dabei: In einer Siemap gibt es Schalter "Vorauswahl Stube", "Vorauswahl Bad" usw. in der Rule wird dann geprüft ob sie AN oder AUS sind. Ist in der ersten Rule der Schalter auf auf AUS (also am Anfang meiner "Kette") wird der Raumzähler trotzdem um einen nach oben gesetzt, damit es weiter geht:

Code: Alles auswählen

***
	if(Robo_vor_wahl_16_Arbeitszimmer.state == OFF)      {
	Raumreinigung = 1
	}
***	
Bis dahin fand ich meine Idee schon mal gar nicht schlecht... ;-) Nur wie aktivier ich die zweite Rule der "Kette" ? Normalerweise ist das ein

Code: Alles auswählen

***
when
        Item Mi_1S_StatusState changed from "Returning Dock" to "Charging"
***		
wenn der Sauger von der ersten Runde des ersten Rule zurück ins Doch gefahren ist. Nun habe ein ODER drangehängt womit VSCode gar nicht einverstanden ist! :-(

Code: Alles auswählen

***
when
        Item Mi_1S_StatusState changed from "Returning Dock" to "Charging" or
        Item Robo_vor_wahl_16_Arbeitszimmer.state == OFF
***		
Hast Du eine Idee wie ich die jeweils folgende Rule aktiviert bekomme wenn die vorhergehende in der Sitemap ausgeschaltet ist? (es sind insgesamt vier Rules / Räume)
bis dann, Steinspiel

Benutzeravatar
Steinspiel
Beiträge: 396
Registriert: 28. Dez 2019 08:49
Answers: 2

Re: Xiaomi Sauer 2x nacheinander saugen lassen?

Beitrag von Steinspiel »

Ich glaub ich habe es: am Ende der ersten Rule gibt es noch einen (virtuellen) Abbruchschalter der ON geschaltet wird, in der zweiten Rule wird der dann mit ODER bei when geprüft! :-)

Code: Alles auswählen

***
                        if(Robo_vor_wahl_16_Arbeitszimmer.state == OFF)      {                                                                  // wenn Vorauswahl AUS dann
                        Raumreinigung = 1                                                                                                       // trotzdem Raumreinigung hoch setzten
                        Robo_vor_wahl_abbruch.sendCommand (ON)
                        }    
end

rule"sauger_vormittagsreinigung_flur"
when
        Item Mi_1S_StatusState changed from "Returning Dock" to "Charging" or
        Item Robo_vor_wahl_abbruch changed from OFF to ON
***
bis dann, Steinspiel

Benutzeravatar
udo1toni
Beiträge: 15244
Registriert: 11. Apr 2018 18:05
Answers: 242
Wohnort: Darmstadt

Re: Xiaomi Sauer 2x nacheinander saugen lassen?

Beitrag von udo1toni »

Na ja, da brauchst Du aber, so scheint mir, eine Menge Rules (eben für jeden Raum eine plus noch eine letzte)

Du kannst alle Schalter, die die Raumreinigung aktivieren, in einer Gruppe zusammenfassen. Dann kannst Du in einer Rule diese Liste von Items filtern, und zwar nach eingeschalteten Schaltern. Diese Liste wiederum kannst Du sortieren (z.B. alphabetisch) und je Durchlauf das n-te Element der Liste verwenden. Etwa so:

Code: Alles auswählen

import java.util.HashMap

var int Raumreinigung = 0  // Muss am Anfang der Datei geschrieben werden
val HashMap<String,String> Raeume = newHashMap("Raum1" -> "app_segment_clean[16]",
                                               "Raum2" -> "app_segment_clean[17]",
                                               "Raum3" -> "app_segment_clean[18]",
                                               "Raum4" -> "app_segment_clean[19]")

rule "Saugen"
when
    Item Robo_Test_B changed to ON or                                      // Testschalter  EIN
    Item Mi_1S_StatusState changed from "Returning Dock" to "Charging"     // Roboter ist zurück in der Station
then
    Raumreinigung ++ // oder Raumreinigung = Raumreinigung + 1             // Raumzähler erhöhen
    if(Raumreinigung > gRooms.members.filter[i|i.state == ON].size) {      // Letzter Raum schon gesaugt
        logInfo("vacuum","Fertig mit Saugen!")
        Raumreinigung = 0                                                  // Raumzähler auf 0
        if(Robo_Test_B.state != OFF)                                       // Falls Schalter nicht OFF
            Robo_Test_B.postUpdate(OFF)                                    // auf OFF
            return;
    }
    val vacRoom = gRooms.members.filter[i|i.state == ON].sortBy[name].get(Raumreinigung-1)
    logInfo("vacuum","{}. Raum ({}) gewählt",Raumreinigung,vacRoom.name)
    val String strRaum = Raeume.get(vacRoom.name)                           // Variable initialisieren
    logInfo("vacuum","Raumzone {} gewählt",strRaum)
    Mi_1S_ActionsCommands.sendCommand(strRaum)                             // Raum saugen
end
Lustigerweise ist der Code kürzer geworden... ;)
Die Schalter zum aktivieren oder deaktivieren sind in der Gruppe gRooms zusammengefasst und heißen Raum1, Raum2, Raum3 und Raum4. Oben definiere ich eine Hashmap, anhand der man vom Itemnamen auf die Zone schließen kann (das ist also einfach eine Wertzuweisung)
In der Rule wird (wie gehabt) einfach der Zähler hochgezählt. Anschließend prüft die Rule, ob der Zähler oberhalb der Anzahl zu reinigender Räume liegt, dann wurde bereits der letzte Raum gesaugt und Schalter sowie Raumzähler werden zurückgesetzt.
Ist die Anzahl zu reinigender Räume jedoch größer oder gleich dem Raumreinigungsindex, bestimmt die Rule den Namen des Items, der jetzt dran ist. (der Listenindex ist 0-basiert, weshalb wir hier 1 abziehen müssen)
Anschließend wird die Zonenbezeichnung aus der Hashmap entnommen und der Saugvorgang gestartet.

Man könnte das Ganze auch ohne Hashmap realisieren, müsste dann aber den Index der Zone im Namen hinterlegen und in der Rule extrahieren. Damit wäre dann die Reihenfolge vorgegeben.

Natürlich gilt hier (wie bei den meisten vergleichbaren Ansätzen), dass während des Saugvorgangs keine weiteren Saugaktivierungsschalter betätigt werden dürfen, da sonst die Sortierung durcheinander geraten könnte.

Man könnte die Liste der aktiven Items auch nach lastUpdate sortieren (das ist unabhängig von einer Persistence!), dann könnte man die Saugreihenfolge über die Aktivierungsreihenfolge festlegen.
Eine weitere Option wäre auch, den Raumreinigungsindex komplett weg zu lassen (kommt mir grade so...):

Code: Alles auswählen

import java.util.HashMap

val HashMap<String,String> Raeume = newHashMap("Raum1" -> "app_segment_clean[16]",
                                               "Raum2" -> "app_segment_clean[17]",
                                               "Raum3" -> "app_segment_clean[18]",
                                               "Raum4" -> "app_segment_clean[19]")

rule "Saugen"
when
    Item Robo_Test_B changed to ON or                                      // Testschalter  EIN
    Item Mi_1S_StatusState changed from "Returning Dock" to "Charging"     // Roboter ist zurück in der Station
then
    if(gRooms.members.filter[i|i.state == ON].size == 0) {                 // Letzter Raum schon gesaugt
        logInfo("vacuum","Fertig mit Saugen!")
        if(Robo_Test_B.state != OFF)                                       // Falls Schalter nicht OFF
            Robo_Test_B.postUpdate(OFF)                                    // auf OFF
            return;
    }
    val vacRoom = gRooms.members.filter[i|i.state == ON].sortBy[name].head // 1. Element der Liste
    logInfo("vacuum","{}. Raum ({}) gewählt",Raumreinigung,vacRoom.name)
    val String strRaum = Raeume.get(vacRoom.name)                           // Variable initialisieren
    logInfo("vacuum","Raumzone {} gewählt",strRaum)
    Mi_1S_ActionsCommands.sendCommand(strRaum)                             // Raum saugen
    vacRoom.postUpdate(OFF)
end
Bei dieser Variante wird der zu saugende Raum nach dem Losschicken des Roboters auf OFF gesetzt. Man könnte das auch in einer separaten Rule machen, die auf changed to "returning Dock" triggert, dann wäre der Schalter während des Saugvorgangs noch aktiv und ginge erst nach dem Saugvorgang auf OFF.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Benutzeravatar
Steinspiel
Beiträge: 396
Registriert: 28. Dez 2019 08:49
Answers: 2

Re: Xiaomi Sauer 2x nacheinander saugen lassen?

Beitrag von Steinspiel »

udo1toni hat geschrieben: 25. Jul 2020 12:54 [...]
Eine weitere Option wäre auch, den Raumreinigungsindex komplett weg zu lassen (kommt mir grade so...):
[...]
Moin,

Ich muss ja sagen, das ist schon ne ganz andere Nummer im Vergleich zu dem Rulemonster was ich mir da heute früh gebastelt habe... !
Ich habe mich für Variante 2 entschieden, wenn es recht ist, allerdings läuft sie noch nicht (wie Variante 1 auch).

Also, ich habe in einer *.items eine Gruppe angelegt:

Code: Alles auswählen

Group:Switch:OR(ON,OFF)     gRooms      "Gruppe fuer Sitemap Sauger Udo"    
Switch Raum1                "Raum1"     (gRooms)    // Schalter fuer Sitemap Sauger Udo
Switch Raum2                "Raum2"     (gRooms)    // auch
Switch Raum3                "Raum3"     (gRooms)    // auch
Switch Raum4                "Raum4"     (gRooms)    // auch
Dann in einer Sitemap diese Schalter eingefügt
Bild

Schalter und Gruppe funktionieren: Schalte ich in der Sitemap einen auf "ON" wird mir das beim Mouseover in der Rule in VSCode angezeigt, genau wie auch die Gruppenmitglieder.

In der Rule selbst moniert VSCode zum einen das "Map" bei/in/vor der HashMap. Da ich gar nichts darüber weiß habe ich gesucht und Beispiele gefunden die genau so geschrieben werden, habe also nichts korrigiert. ;-)
https://community.openhab.org/t/struct ... /47253/16

Auch wird der Umlaut "ä" dort bemängelt, allerdings nicht der in der Variablen

Code: Alles auswählen

val String strRaum = Räume.get(vacRoom.name)                           // Variable initialisieren
Bild

Ändere ich einen oder beide Umlaute in "ae" gibt es noch mehr Fehlermeldungen...

Ich denke vieleicht ist einer dieser angezeigten Fehler der Grund das die Rule noch nicht funktioniert. Schalte ich "Robo_Test_B" in der Sitemap auf ON (was dann in der Rule auch angezeigt wird) ist das einzige was im Log dazu zu sehen ist das:

Code: Alles auswählen

2020-07-25 19:29:10.965 [ome.event.ItemCommandEvent] - Item 'Robo_Test_B' received command ON
2020-07-25 19:29:10.974 [vent.ItemStateChangedEvent] - Robo_Test_B changed from OFF to ON
Es kommt also gar nicht erst zum "logInfo" im "then" Bereich der Rule.

Weißt Du was ich ändern muss?
bis dann, Steinspiel

Benutzeravatar
udo1toni
Beiträge: 15244
Registriert: 11. Apr 2018 18:05
Answers: 242
Wohnort: Darmstadt

Re: Xiaomi Sauer 2x nacheinander saugen lassen?

Beitrag von udo1toni »

Oh ja, peinlich, Umlaute sind nicht erlaubt...

weiterhin habe ich zum einen einen import vergessen, zum anderen muss es HashMap heißen, nicht Map...

Ich hab das oben mal korrigiert.
openHAB4.3.3 stable in einem Debian-Container (bookworm) (Proxmox 8.3.5, LXC), mit openHABian eingerichtet

Antworten