Hi
I am trying to set up a dimming function - so that the “TP-LINK KASA KL130” lights dim to “OFF” slowly when the OFF switch is clicked.
Item file is:
Color lamp1_Color { channel=“tplinksmarthome:kl130:7FFE13:color” }
Switch substitute_switch_for_lamp1 //presumably I need to create this?
Sitemap file is:
Switch item=lamp1_Color label= “On / Off” icon=“Light” //normal fully off or fully on switch - presumably I will delete this once dimmer function is set up…
Switch substitute_switch_for_lamp1 //presumably I need to create this new switch to avoid conflicts with normal ON,OFF functionality
Rules file is:
val HSBType myColorNow = [how to query h,s,b values]
val h = [parse myColorNow]
val s = [parse myColorNow]
val b = [parse myColorNow]
val step=10
rule "dimming rule"
when
Item substitute_switch_for_lamp1 received command OFF
then
while (b >= 0)
{
lamp1_Color.sendCommand(h,s,b)
Thread::sleep(500)
if(b>step)
{
b=b-step
}
else
{
b=0
}
}
end
I believe I need help with:
the items and sitemap - have I correctly thought about the need for a user defined item to avoid conflicts with the KL130 pre-defined ON/OFF functions
the Rules - I have no idea how to query the current H,S,B values of the light - even though they show up in the logs so should be readily available…
I do not have eclipse smarthome installed - do I need it for what I am trying to do? Would prefer to avoid…
Appreciate it.
I now have the following code which appears to work. Hope it may be of some use to others.
Nonetheless I am puzzled by the syntax:
rule "dimming rule"
when
Item substitute_switch_for_lamp1 received command OFF
then
var HSBType myColorNow = lamp1_Color.state as HSBType
var myColorNowAsArray=myColorNow.toString.split(",")
var h = myColorNowAsArray.get(0)
var s = myColorNowAsArray.get(1)
var b = myColorNowAsArray.get(2)
var step=1
//var hD = Float::parseFloat(h)
//var sP = Float::parseFloat(s)
var bP = Float::parseFloat(b)
while (bP >= 0)
{
var newColorType = h+","+s+","+bP
lamp1_Color.sendCommand(new HSBType(newColorType))
Thread::sleep(100)
bP=bP-step
}
end
Specifically I don’t understand why I had to parse the “b” variable into a float, yet “h” and “s” seem to be just fine staying as they are (presumably Strings?).
Any guidance appreciated.
If the code could be improved, please make suggestions.
OK, great job Mark. I’m pretty sure the color state is returned as a string. Not sure why it has to be parsed as a float.
Your rule looks good and the only thing people will bark at you for using thread sleep which is generally not a good idea but your sleep is so short I don’t believe it will hurt. 100 ms is safe
no Mark, that would be my first choice to replace the sleeps
I was going to suggest the expire binding. The resolution isn’t perfect (time wise) for short duration periods. some times my 3 second expire timer seems closer to 4 seconds but you can adjust it
Well, it’s no trouble at all but a necessary step for math to parse string to float (or int).
Even when doing math in good old Basic you have to use val(string).
In question of Thread::sleep(): As your rule does a single Thread::sleep(100), there is absolutely no reason to change this.
But think about another rule, let’s say we have 10 lights, every light shall dim up from 0 to 100 in 200 seconds, and it shall be light by light.
If doing it with a Thread::sleep(), we will end up with something like
for each light {
while(brightnss < 100) {
brightness += 1
light.sendCommand(brightness)
Thread::sleep(2000)
}
}
(just symbolic code, won’t work!)
Now that is: The rule is started, then iterates through the lights and does a dim up in 1% steps. But that is 10 times 100 times 2 sec runtime for this rule (plus execution time for sendCommand…). Thread::sleep() will exactly do that: let the thread sleep. The rule will block one thread completely for 2000 Seconds!
(this code won’t work either )
When using a timer, the rule will simply schedule the timer, the timer will step through the lights and the brightness for each lamp, but will reschedule itself. The commands will need some time for the job, the timer will also use a thread, but instead of sleeping, the timer is rescheduled and no thread is blocked, instead the timer code will be executed 2000 times.