Hi everyone,
I want to control Homematic IP shutter slats using groups in rules. I’m a beginner with rules (and not a programmer) but already tried different options.
Beneath you see my first approach which worked fine, but unfortunately is “evil” (see for example Why have my Rules stopped running? Why Thread::sleep is a bad idea or Implement delay in x.members.forEach, exec binding+rcswitch) and therefore skipped. Please don’t copy&paste.
Still, it worked for me and I will post it here for you to get an idea what I’m aiming for and where I’m coming from:
rule "Control slat positions"
when
Item Lamellen received update
then
logInfo( "rollershutter.rules", "Rule 'Control slats positions' triggered" )
if(Lamellen.state == 0) {
Wintergarten_Jalousie_Tuer_Level2.sendCommand(0)
Wintergarten_Jalousie_Tuer_Stop.sendCommand(ON)
Thread::sleep(3500)
Wintergarten_Jalousie_links_Level2.sendCommand(0)
Wintergarten_Jalousie_links_Stop.sendCommand(ON)
Thread::sleep(3500)
Wintergarten_Jalousie_rechts_Level2.sendCommand(0)
Wintergarten_Jalousie_rechts_Stop.sendCommand(ON)
}
else if (Lamellen.state == 25) {
Wintergarten_Jalousie_Tuer_Level2.sendCommand(25)
Wintergarten_Jalousie_Tuer_Stop.sendCommand(ON)
Thread::sleep(3500)
Wintergarten_Jalousie_links_Level2.sendCommand(25)
Wintergarten_Jalousie_links_Stop.sendCommand(ON)
Thread::sleep(3500)
Wintergarten_Jalousie_rechts_Level2.sendCommand(25)
Wintergarten_Jalousie_rechts_Stop.sendCommand(ON)
}
else if (Lamellen.state == 50) {
Wintergarten_Jalousie_Tuer_Level2.sendCommand(50)
Wintergarten_Jalousie_Tuer_Stop.sendCommand(ON)
Thread::sleep(3500)
Wintergarten_Jalousie_links_Level2.sendCommand(50)
Wintergarten_Jalousie_links_Stop.sendCommand(ON)
Thread::sleep(3500)
Wintergarten_Jalousie_rechts_Level2.sendCommand(50)
Wintergarten_Jalousie_rechts_Stop.sendCommand(ON)
}
else if (Lamellen.state == 75) {
Wintergarten_Jalousie_Tuer_Level2.sendCommand(75)
Wintergarten_Jalousie_Tuer_Stop.sendCommand(ON)
Thread::sleep(3500)
Wintergarten_Jalousie_links_Level2.sendCommand(75)
Wintergarten_Jalousie_links_Stop.sendCommand(ON)
Thread::sleep(3500)
Wintergarten_Jalousie_rechts_Level2.sendCommand(75)
Wintergarten_Jalousie_rechts_Stop.sendCommand(ON)
}
else if (Lamellen.state == 100) {
Wintergarten_Jalousie_Tuer_Level2.sendCommand(99)
Wintergarten_Jalousie_Tuer_Stop.sendCommand(ON)
Thread::sleep(3500)
Wintergarten_Jalousie_links_Level2.sendCommand(99)
Wintergarten_Jalousie_links_Stop.sendCommand(ON)
Thread::sleep(3500)
Wintergarten_Jalousie_rechts_Level2.sendCommand(99)
Wintergarten_Jalousie_rechts_Stop.sendCommand(ON)
}
end
The relevant part of my sitemap looks like this:
Frame label="Gruppensteuerung" {
Switch item= gRollos label="Rollladen [%d %%]"
Switch item= gJalousien label="Jalousien [%d %%]"
Switch item= Lamellen label="Lamellen" mappings=[0="0%", 25="25%",50="50%", 75="75%", 100="100%"]
}
I want to be able to change the 5 slats (=“Lamellen”) conditions 0%, 25%, 50%, 75% and 100%. And I want them to change short after each other, that’s why there is a delay of 3.5 seconds which I personally liked most. As you can see, there are 3 shutters in total.
I’m sending 2 commands for each shutter, since - for whatever reason - the first command itself doesn’t work (known problem, see Rollershutter with Homematic IP (HmIP) HmIPW-DRBL4), Homematic Raffstore/blinds control) or here (external link, german only), the 2nd command is needed.
Looks and feels ugly, but I couldn’t find any better option:
Wintergarten_Jalousie_Tuer_Level2.sendCommand(25)
Wintergarten_Jalousie_Tuer_Stop.sendCommand(ON)
My second approach from this morning looked like this:
rule "Control slat positions"
when
Item Lamellen received update
then
if(Lamellen.state == 0) {
tSlats?.cancel
iStep = 0
tSlats = createTimer(now.plusSeconds(0.5), [
iStep ++ // short for "iStep = iStep + 1"
switch iStep {
case 1: {
Wintergarten_Jalousie_Tuer_Level2.sendCommand(0)
Wintergarten_Jalousie_Tuer_Stop.sendCommand(ON)
tSlats.reschedule(now.plusSeconds(3))
}
case 2: {
Wintergarten_Jalousie_links_Level2.sendCommand(0)
Wintergarten_Jalousie_links_Stop.sendCommand(ON)
tSlats.reschedule(now.plusSeconds(3))
}
case 3: {
Wintergarten_Jalousie_rechts_Level2.sendCommand(0)
Wintergarten_Jalousie_rechts_Stop.sendCommand(ON)
tSlats.reschedule(now.plusSeconds(3))
}
}
])
}
else if(Lamellen.state == 25) {
tSlats?.cancel
iStep = 0
tSlats = createTimer(now.plusSeconds(0.5), [
iStep ++
switch iStep {
case 1: {
Wintergarten_Jalousie_Tuer_Level2.sendCommand(25)
Wintergarten_Jalousie_Tuer_Stop.sendCommand(ON)
tSlats.reschedule(now.plusSeconds(3))
}
case 2: {
Wintergarten_Jalousie_links_Level2.sendCommand(25)
Wintergarten_Jalousie_links_Stop.sendCommand(ON)
tSlats.reschedule(now.plusSeconds(3))
}
case 3: {
Wintergarten_Jalousie_rechts_Level2.sendCommand(25)
Wintergarten_Jalousie_rechts_Stop.sendCommand(ON)
tSlats.reschedule(now.plusSeconds(3))
}
}
])
}
else if(Lamellen.state == 50) {
tSlats?.cancel
iStep = 0
tSlats = createTimer(now.plusSeconds(0.5), [
iStep ++
switch iStep {
case 1: {
Wintergarten_Jalousie_Tuer_Level2.sendCommand(50)
Wintergarten_Jalousie_Tuer_Stop.sendCommand(ON)
tSlats.reschedule(now.plusSeconds(3))
}
case 2: {
Wintergarten_Jalousie_links_Level2.sendCommand(50)
Wintergarten_Jalousie_links_Stop.sendCommand(ON)
tSlats.reschedule(now.plusSeconds(3))
}
case 3: {
Wintergarten_Jalousie_rechts_Level2.sendCommand(50)
Wintergarten_Jalousie_rechts_Stop.sendCommand(ON)
tSlats.reschedule(now.plusSeconds(3))
}
}
])
}
else if(Lamellen.state == 100) {
tSlats?.cancel
iStep = 0
tSlats = createTimer(now.plusSeconds(0.5), [
iStep ++
switch iStep {
case 1: {
Wintergarten_Jalousie_Tuer_Level2.sendCommand(99)
Wintergarten_Jalousie_Tuer_Stop.sendCommand(ON)
tSlats.reschedule(now.plusSeconds(3))
}
case 2: {
Wintergarten_Jalousie_links_Level2.sendCommand(99)
Wintergarten_Jalousie_links_Stop.sendCommand(ON)
tSlats.reschedule(now.plusSeconds(3))
}
case 3: {
Wintergarten_Jalousie_rechts_Level2.sendCommand(99)
Wintergarten_Jalousie_rechts_Stop.sendCommand(ON)
tSlats.reschedule(now.plusSeconds(3))
}
}
])
}
end
I got the state machine idea from [SOLVED] Switch multiple timer in succession and it basically worked for me + it avoids sleep + it looks a bit nicer than v1, but I was aiming for something more clever with less code.
This is where I came across the Rollershutter group & rule thread, but I couldn’t geht that version to run (c&p version):
rule "Rollläden schließen 1h nach Sonnenuntergang"
when
Channel "astro:sun:home:set#event" triggered START
then if (zeit_rolladen.state == ON) {
var Timer rolladen_nacht = null
rolladen_nacht = createTimer(now.plusMinutes(60), [|
val openShutters = rollershutter.members.filter[ rs | rs.state != 100 ].forEach[ rs, i | createTimer(now.plusMillis(500*i), [ | rs.sendCommand(100) ])
sendTelegram("marco" , "Rollläden werden automatisch geschlossen") ])
}
end
And this is where I struggled alot and couldn’t get it adapted although it’s already a shutter example and quite near to my use case.
At this point, may I ask for some assistance? Could this be a better solution for me than the state machine approach?
Thanks,
Linus
PS: This is my first own topic and first “serious” post. It’s probably a bit too long at all and I’m not sure if these long code quotes are okay, but I guess you will let me know.
PPS: Sorry for that deleted topic before. I accidentally and very early hit the “Create topic” button and didn’t want to let the topic be unfinished for such a long time (until I finished this post).