I have done the coding and tested it. I think it works right now. I include my solution here in case somebody would like to do the same in the future.
My scenario is some sort pump which I want to monitor how much it runs. I think this is a good way of monitoring an automated process to make sure it is working correctly. I used this scenario to monitor my well pump for sprinklers. I just look at the run time in the morning to make sure it has done irrigation overnight.
These are my items. Pump is the switch to turn it on and off manually. PumpTime holds the run time in seconds. PumpTimeD1 shows the seconds yesterday:
Number Chart_Period "Period" (System)
Switch Pump "Pump swi tch" <switch> (Pump)
Number PumpTime "Pump uptime [> %.1f seconds]" <clock> (PumpTime)
Number PumpTimeD1 "Pump uptime yesterday [%.1f seconds]" <clock>
I added these to rrd4j.persist. Pump is added to display on/off state in a graph and PumpTime is there so I can retrieve stats for previous day.
Pump : strategy = everyMinute, everyChange
PumpTime : strategy = everyChange, restoreOnStartup
Next are the rules that I put in a separate rules file. I has a few local variables and five methods:
“Initialize counters”: runs on startup to initialize some of the variables
“Pump Switched On”: runs when the pump turns on and saved the current timestamp in millis
“Pump Live Update”: this is scheduled for every 5 seconds to update the runtime when the pump is running. Here you can add some code to handle what should happen if the pump runs for a very long time. For example if this pump is topping up a cistern and the top float switch fails you probably want to turn off the pump after a certain time to prevent overfill. In a production scenario it is probably sufficient to have this running every minute. I left it every 5 seconds for testing.
“Pump Switched Off”: updates the runtime after the switch is turned off.
“Pump daily stats”: this runs at midnight to reset the stats to zero and save yesterday’s runtime in the D1 variable. This is my first major rule, some of the imports might not be required.
import org.joda.time.*
import org.openhab.core.library.types.*
import org.openhab.core.persistence.*
import org.openhab.model.script.actions.*
var Number PumpRunStart // Timestamp when the switch was turned on
var Number PumpRunTime // Total runtime in seconds
var Number PumpPrevTime // Runtime until the last swtiching on
// Initialize the counters at startup
rule “Initialize counters”
when
System started
then
PumpRunTime = 0
PumpPrevTime = 0
PumpRunStart = now.millis
end
// Rule when the switch is turned on. This stores the current time
// and current runtime for calculation
rule “Pump Switched On”
when
Item Pump received command ON
then
PumpRunStart = now.millis
PumpPrevTime = PumpRunTime
end
// Every 5 second job to update the runtime when the switch is on
rule “Pump Live Update”
when
Time cron “0/5 * * * * ?”
then
if(Pump.state==ON) {
PumpPrevTime = PumpRunTime + (now.millis - PumpRunStart) / 1000
PumpTime.postUpdate( PumpPrevTime )
// add some code here to handle overrun (e.g. pump cannot run for more than 2 hours a day
}
end
// Update the runtime based on the time between off and on changes
rule “Pump Switched Off”
when
Item Pump received command OFF
then
PumpRunTime = PumpRunTime + (now.millis - PumpRunStart) / 1000
PumpTime.postUpdate( PumpRunTime )
end
// Rule for calculating the daily stats
rule “Pump daily stats”
when
Time is midnight
then
// update stats if the pump is still running
if(Pump.state==ON) {
PumpRunTime = PumpRunTime + (now.millis - PumpRunStart) / 1000
PumpTime.postUpdate( PumpRunTime )
}
// getting yesterday's stats from persistence
var Number min
min = PumpTime.maximumSince(now.minusHours(11),"rrd4j").state as DecimalType
PumpTimeD1.postUpdate(min)
//resetting counters on midnight
PumpRunStart = now.millis
PumpRunTime = 0
PumpPrevTime = 0
PumpTime.postUpdate(0)
end
This is how it looks like on the sitemap:
Text label="Runtime calculation" icon="energy" {
Switch item=Pump
Text item=PumpTime
Switch item=Chart_Period mappings=[0="1h", 1="4h", 2="8h", 3="12h", 4="24h"]
Chart item=Pump period=h refresh=60000 visibility=[Chart_Period==0, Chart_Period=="Uninitialized"]
Chart item=Pump period=4h refresh=60000 visibility=[Chart_Period==1]
Chart item=Pump period=8h refresh=60000 visibility=[Chart_Period==2]
Chart item=Pump period=12h refresh=60000 visibility=[Chart_Period==3]
Chart item=Pump period=D refresh=60000 visibility=[Chart_Period==4]
Text item=PumpTimeD1
}
And this is how it looks like:
I have taken the screenshot before midnight, so the D-1 stats is null right now. I added the graph to visually represent when the pump was on and off. It might be useful to identify if there is some issue in the control logic and it keeps turning on and off too many times.
I hope you find this useful. Cheers.