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