My rulesdsl is rusty, and coding in it is just a pain compared to JRuby which is my preference for rule scripting.
Here’s how I would do it in JRuby:
@state_changes = []
REPORT_PERIOD = "8am".."4pm"
SMTP = "mail:smtp:samplesmtp"
EMAIL = "my_email@gmail.com"
rule "Keep track of door states" do
changed GF_Entry_Door, from: CLOSED, to: OPEN
changed GF_Entry_Door, from: OPEN, to: CLOSED
between REPORT_PERIOD
run do |event|
if event.open?
@state_changes << { opened: ZonedDateTime.now }
things[SMTP].send_html_mail(EMAIL, "OH Alert - Main door event", "Entry door was opened")
logger.info "eMail of main door status change was sent"
else
@state_changes.last[:closed] = ZonedDateTime.now
end
end
end
rule "Report door state changes" do
every 2.hours
between REPORT_PERIOD
run do
changes = @state_changes.slice!(0..) # move the array into `changes` and empty it
changes = changes.map do |change|
opened, closed = change.values_at(:opened, :closed)
if closed
duration = closed - opened
closed = closed.to_time.strftime("%H:%M:%S")
else
duration = ZonedDateTime.now - opened
closed = "still open"
end
opened = opened.to_time.strftime("%H:%M:%S")
"<li>#{opened} - #{closed} (#{duration.to_minutes} minutes)</li>"
end
msg = <<~HTML
<h1>Main door log</h1>
<ul>
#{changes.join}
#{changes.empty? ? "<li>No changes. Current door state: #{GF_Entry_Door.state}</li>" : ""}
</ul>
HTML
things[SMTP].send_html_mail(EMAIL, "OH Alert - Main door log", msg)
end
end
Untested, so there may be bugs, but I hope you get the general idea of how to implement it.
The variable @state_changes
will reset (empty) when you save/reload the script, so once it’s working, don’t touch it
Another way of doing it is using persistence.