rule "Light on for 3 minutes on motion detected" do
changed Stairway_Motion, to: ON
between "20:00".."05:00"
run { Salt_Lamp.on for: 3.minutes }
end
This won’t set multiple timers when triggered again before the previous timer ended
rule "Light on for 3 minutes on motion detected" do
changed Stairway_Motion, to: ON
between "20:00".."05:00"
run { Salt_Lamp.on for: 3.minutes }
end
This won’t set multiple timers when triggered again before the previous timer ended
Sure, but that wasn’t one of the requirements!
Thanks for the :for
bit!
The other languages will however allow you to abstract stuff into separate methods that you can just call.
As an example I have a normal_schedule?
method that returns true unless we are on vacation, the kids are sick, nobody is home, it’s a public or a school holiday and so on. Makes it super easy to write very terse rules.
All valid points although I must admit I’m not sold on the idea of rule templates. It is (to me) much simpler to just write the things I want especially since the jruby rules can be made so terse.
And having code that writes rules is very nice:
[
{ text: "Monday", cron: "0 25 15 ? * Mon *" },
{ text: "Friday", cron: "0 0 15 ? * Fri *" },
{ text: "late", cron: "0 15 16 ? * Tue,Wed,Thu *" },
].each do |e|
rule "Boys, #{e[:text]} fetch from school" do
cron e[:cron]
only_if { normal_schedule? }
run { announce FETCH.sample }
end
end
I fully understand that there might be cases where blockly makes sense, but I guess the question I should have asked is if anyone with a development background still uses that.
Yes, I do use and love blockly.
We’re going slightly off-topic now, for which I apologize, but I’d be super curious to hear what your use-cases are for that and if you are also using any of the other rule engines. If so, which tasks you prefer to handle in blockly and which through the various DSLs.
By blindly starting a new timer without cancelling the previous timers, you can get in the situation where the light turns off “randomly” because the previous timer(s) that are still active just fired, even though your latest timer still has a few more minutes to go.
The simple Salt_Lamp.on for: 3.minutes
takes care of that. (sorry there shouldn’t be a comma between .on and for)
Only some leftovers from old rules DSL cause I did not find time to move them to blockly. No other rules language in use here.
So you don’t use libraries? Because that would be kind of the same argument against that. All a rule template is is code you can use that you didn’t have to write.
Rule templates can be written in any language (mine are all Rules DSL, ECMAScript 5.1 and ECMAScript 2021). Same for UI rules for that matter. You can even use jRuby or a combo of languages in the same rule.
Blockly lets you create libraries too. There’s a section for them under Developer Tools. But you’ll need to know ECMAScript 5.1 to do so because that what your blocks will compile to.
And just in case it’s not clear, you can call and use personal libraries of classes and functions from UI created rules too.
I’ve coded professionally since graduating college in 1999 (less so now that I’m pushed into more managerial roles, but use C, C++, Java, and most recently Python) and I use and like Blockly for some things. But most of my UI rules are written in ECMAScript 2021 because it has the best support for writing script actions and conditions in the UI.
Often when there’s something really simple and straight forward that I don’t know off the top of my head how to do in JS Scripting and I’m too lazy to look it up. Or if I want to have a rule that I want my nine-year-old son to play with and modify I’ll code it up in Blockly.
I mostly use ECMAScript 2021 (i.e. JS Scripting). I would have used jRuby but the developers were slow to provide support for UI rules (I still think there isn’t the concept of cache
to share variables between rules) and you still have to get the helper library through gems instead of coming with the add-on and the docs are maintained somewhere else instead of incorporated into the official docs. But sometimes something will be easier in Rules DSL or Blockly and I’ll do that in those cases. I’ve still some ECMAScript 5.1 hanging around but I’ve not had time to upgrade them.
Out of respect for the original poster, who has not indicated that their problem is solved, this discussion should probably continue in a new thread.
Getting back to the @aworldofchaos’s original question, here’s an updated rule in jruby that takes into account the sunset / sunrise time. I use Xiaomi Aqara PIR motion sensors, and it has a built in light sensor too. The second example takes it into account as well.
rule "Light on for 3 minutes on motion detected" do
changed Stairway_Motion, to: ON
between "4pm".."7am" # restrict to a time range
only_if { things["astro:sun:home"].getElevation(nil).to_f < 5 } # only from a bit before sunset, until a bit after sunrise
run { Salt_Lamp.on for: 3.minutes }
end
This assumes you have configured the Astro binding and have a Thing called astro:sun:home
configured with your latitude/longitude.
If you’ve set up your Semantic model so that Motion Sensors and Lights belong in their corresponding Rooms, then you can make one rule handle all of them.
Furthermore if you have Lux sensors in (some of) the rooms, you can incorporate that into the rule. Rooms that have no lux sensors will simply not take lux into consideration.
LUX_THRESHOLD = 300 | "lx" # adjust accordingly
rule "Light on for 3 minutes on motion detected" do
changed gSensors_for_Motion_Activated_Lights.members, to: ON # add any motion sensors you'd like into this group
between "4pm".."7am" # restrict to a time range
only_if { dusk_to_dawn? } # only from a bit before sunset, until a bit after sunrise
run do |event|
lux = avg_lux(event.item.location)
next unless lux.nil? || lux < LUX_THRESHOLD
event.item
.location
.equipments(Semantics::Lightbulb) # select all the Lightbulbs in the room
.members
.points(Semantics::Control, Semantics::Power)
.ensure
.on for: 3.minutes
end
end
def dusk_to_dawn?
things["astro:sun:home"].getElevation(nil).to_f < 5
end
# Returns the average lux in the room (if there are multiple lux sensors in the same room)
# returns nil if there are no lux sensors in the room
def avg_lux(location)
lux_sensors = location.equipments.members.points(Semantics::Measurement, Semantics::Light)
return lux_sensors.sum(&:state) / lux_sensors.count unless lux_sensors.empty?
end
From here on, you just need to add the motion sensors that you want to trigger lights in the same Location into the gSensors_for_Motion_Activated_Lights
. This is a separate group, in case you don’t want all your motion sensors to trigger lights in the room.
You can customise it further, say you want 3 minutes for room A and 30 minutes for room B, and 1 hour for room C, etc.
You can make the lux threshold configurable for each room, if you like.
Easy to do but I don’t want to make this post too long.
Rich and Hans-Jörg, I cannot thank you enough for the detailed responses!
I come for the software and stay for the community!
I guess you did not really mean me.
Yeah. I did in fact mean Rich and Jim ;-), but I still very much appreciate all the work you have put into OH, so thank you for that!
Sorry, work, xmas, holiday and back to work had put this on the at the back of the list for a couple of months.
I just wanted to extend a very very big thank you to everyone that has posted on this thread over the last few months. I have learnt a lot about the different rule engines and pros and cons of each.
Personally I’ve really come to like jruby and blocky from reading about them since this discussion. I’m comfortable with wiring, soldering, linux cli, gadgets but coding/scripting/programming my brain cannot compute!
I installed jruby from the gui but found that it had not created the correct directories so I had to create them and chown them to the correct owner. To work this out took a little time.
$OPENHAB_CONF/automation/jsr223/ruby/personal
require "openhab"
rule "Light on for 3 minutes on motion detected" do
changed Stairway_Motion, to: ON
between "20:00".."05:00"
run { Salt_Lamp.on }
delay 3.minutes
run { Salt_Lamp.off }
end
Thats what code ended up working for me.
Once again, hats off the openhab community, thank you so much.
May I suggest a little improvement:
require "openhab"
rule "Light on for 3 minutes on motion detected" do
changed Stairway_Motion, to: ON
between "20:00".."05:00"
run { Salt_Lamp.on for: 3.minutes }
end
Thank you.
How would I add another sensor in?
I have added one to the top of the stairs now…
rule "Light on for 3 minutes on motion detected" do
changed Stairway_Motion_Top, Stairway_Motion_Bottom to: ON
etc.....
You just missed one comma before to
changed Stairway_Motion_Top, Stairway_Motion_Bottom, to: ON
Thank you!