Well, in fact, the function should have nothing to do with hardware or version.
→ make things for your hardware
→ make appropriate channels which you want to control (i.e. for a dimmable light bulb make a dimmer channel)
→ connect the channel to control with an appropriate Item (i.e. a Dimmer Item here)
→ build a rule to control the Dimmer Item
In question of OH2 vs. OH3, it depends on how the rule is built. In general, if the light should fade over time, the common way is to send a bunch of commands over time, so you will need a timer for that job.
Simple solution in DSL:
// global var has to be on top of file
var Timer tMorningFade = null
rule "fade at morning"
when
Time cron "0 0 6 * * MON-FRI" // Monday to Friday at 06:00:00 a.m.
then
tMorningFade?.cancel // get rid of old timer, if there is any
tMorningFade = createTimer(now.plusSeconds(1), [| // start fadeing at 06:00:01 a.m.
var iBright = (myBulb.state as Number).intValue // get current brightness
iBright = iBright + 1 // add 1
myBulb.sendCommand(iBright) // send new brightness
if(iBright < 100) // if not at 100 %
tMorningFade.reschedule(now.plusSeconds(5)) // next step in 5 Seconds
])
end
That code will work from OH1 up to OH4 - and I’m pretty sure it will even in OH5…
Where should this code be stored? I pasted the code both under rules as a new Rules DSL script and under scripts under new rule as Rules DSL. In both cases the script fails with the following error in log:
2023-07-16 08:52:33.443 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID '9a8d38e42a' failed: // global var has to be on top of file
var Timer tMorningFade = null
rule "fade at morning"
when
Time cron "0 0 6 * * MON-FRI" // Monday to Friday at 06:00:00 a.m.
then
tMorningFade?.cancel // get rid of old timer, if there is any
tMorningFade = createTimer(now.plusSeconds(1), [| // start fadeing at 06:00:01 a.m.
var iBright = (myBulb.state as Number).intValue // get current brightness
iBright = iBright + 1 // add 1
myBulb.sendCommand(iBright) // send new brightness
if(iBright < 100) // if not at 100 %
tMorningFade.reschedule(now.plusSeconds(5)) // next step in 5 Seconds
])
end
1. The method or field rule is undefined; line 4, column 70, length 4
2. The method or field when is undefined; line 5, column 93, length 4
3. The method or field cron is undefined; line 6, column 107, length 4
4. The method or field then is undefined; line 7, column 169, length 4
5. The method or field myBulb is undefined; line 10, column 353, length 6
6. The method or field myBulb is undefined; line 12, column 485, length 6
7. The method or field end is undefined; line 16, column 720, length 3
8. Cannot refer to the non-final variable tMorningFade inside a lambda expression; line 14, column 643, length 12
9. This expression is not allowed in this context, since it doesn't cause any side effects.; line 4, column 75, length 17
10. This expression is not allowed in this context, since it doesn't cause any side effects.; line 6, column 102, length 4
11. This expression is not allowed in this context, since it doesn't cause any side effects.; line 6, column 112, length 19
This is a pure DSL (DomainSpecificLanguage) rule. You have to create a text file, its name ending with .rules. The file has to be created in $OPENHAB_CONF/rules/, so e.g. (openHABian Image for Raspberry Pi) /etc/openhab/rules/my.rules
myBulb is an Item (the light to be faded) Obviously, you’ll have to change the Item name in the rule to match your Dimmer Item.
Thanks, got it to run when I stored it in the right position.
However, my bulb starts with 100% brightness at 06:00.
The bulb is a Tuya wifi bult that apparently does not use the warm light leds and color leds at the same time.
All of those waits give me a little bit of concern. I’m not sure it’s that big of a deal unless there is even a slight chance that this rule could get triggered more than once in the nearly 75 minutes that this rule will currently take to exit you might be facing some problems. For example, if somehow this rule were triggered 20 times in the morning, this rule would be running all day over and over again.
Luckily it’s not that hard to prevent that. You can either add an if statement to only run the above if the light and/or current time ist right (e.g. if the light is already brightness 99 and green >= 167 there’s nothing to do, or if it’s more than an hour past the usual time to run) or, even better, add a condition (i.e. “but only if”) to do these checks and prevent the actions from running if the conditions are not right.
Thanks for the heads up! I already ended up in a never ending loop while testing the script and had to restart OH. The code is not of good quality yet. I will add safety measures as per your advice.
Shortly, the script is supposed to during the first 30 minutes make my bedside lamp run through a sunrise palette of colours and then in 15 minutes run up the warm white light from 1% to 100%. The lamp will stay on for half an hour and then shut it self off. I trigger it with cron from the UI. It has now run once. I will now go the bed and see and report what happens tomorrow morning.
If you are really looking to improve the code, you should look into using timers instead of waits. The big difference is that the timer gets scheduled to run in the future instead of blocking execution of the rule for a given amount of time.
But the code can become a little more complex as a result because now it doesn’t just execute from the top to the bottom.
Is there a way to provide H, S and B values directly with Blockly? The starting sequence is too bright, and it woul be great to fade up Brightness along with the sunrise palette.
I don’t have this sort of light bulb, but maybe this DSL rule will work as intended:
// global var has to be on top of file
var Timer tMorningFade = null
var Integer iGreen = 0
var Integer iBright = 0
rule "fade at morning"
when
Time cron "0 0 6 * * MON-FRI" // Monday to Friday at 06:00:00 a.m.
then
tMorningFade?.cancel // get rid of old timer, if there is any
iGreen = 0 // set start values
iBright = 0
tMorningFade = createTimer(now.plusSeconds(1), [| // start fadeing at 06:00:01 a.m.
var iTime = 10778 // don't know if it's worth the millis
if(iGreen < 168 && iBright == 0) { // color fade
iGreen ++ // add 1
val hsb = new HSBType(new Color(255, 0, iGreen)) // create hsb value
timonYopoytaValonVarit.sendCommand(hsb) // send color
} else if(iBright < 100) { // brightnes fade
iBright ++ // add 1
timonYopoytaValo.sendCommand(iBright) // send brightnes
iTime = 9000 // set different time
}
if(iBright == 100) { // end of fading
iBright = 101 // to get to the else-part next time
iTime = 1800000 // set off time
} else if(iBright == 101) { // time to
timonYopoytaValo.sendCommand(0) // switch off the light
return; // nothing left to do
}
tMorningFade.reschedule(now.plus(iTime,ChronoUnit.MILLIS)) // next step in iTime Miiliseconds
])
end
Not sure about Color(red, blue, green), this is according to auto text in VSCode, but maybe it should be Color(red, green, blue) instead.
In RGB the higher the number the higher the brightness. So use lower RGB values and the light will be dimmer. For example, 50% brightness white will be 128,128,128 RGB value.
Or construct a String of the HSB value and send that string as a command. H,S,B.
Or just send an integer between 0 and 100 as a command and OH will treat that as a command to change just the brightness.
But note that as soon as you command the light again using your hard coded RGB values in the block above, it will override that previously set brightness with what ever brightness is embedded in the RGB values.
Setting the brightness alone switches the mode of the lamp to White light. I would like to create a hsb string, but how do I do that? There is no concatenation block in blockly?