Just making a quick run through the rule and pointing out what sticks out to me.
Remove the import for actions.*. This is not needed for OH 2.x
Locks are very dangerous, do your really need the Lock?
org.joda.time.DateTime is already imported for you, just use var DateTime whenStarted = null
Avoid the use of primitives (e.g longValue) unless absolutely required.
Use a Timer instead of a 45 second sleep. If the Rule takes more than half a second to run, you need to be using Timers.
The error is almost certainly that MainHeater_Runtime_MSec is NULL. NULL indicates an Item is uninitialized. NULL is not a Number and cannot be cast to a Number.
Here is one reason why Locks are dangerous. Because you have a type error in āCheck Main Heater and Increment Runtimesā, the finally clause never executes and your Lock never gets unlocked.
Try this:
Not tested but VSCode is happy with it so far:
var DateTime whenStarted = null
var Timer MainHeater_timer = null
rule "Main Heater Started"
when
Item MainHeater received command ON
then
if (MainHeater_timer === null) { /// Check equivalent to lock
MainHeater_timer = createTimer(now.plusSeconds(45), [ |
if (MainHeater.state == ON) {
whenStarted = now // Start Clock
MainHeater_Failed.postUpdate(OFF)
MainHeater_Cooling.postUpdate(OFF)
createTimer(now.plusSeconds(15), [ |
//sendMail("myemail@gmail.com", "MainHeater", "Main Heater Started, load at " + Buy_Total_Watts.state + " watts")
])
} else {
whenStarted = null
MainHeater_Failed.postUpdate(ON)
MainHeater_Override.postUpdate(OFF)
//sendMail("myemail@gmail.com", "Main Heater", "Main Heater Failed to Start!!")
}
MainHeater_timer = null
])
}
end
rule "Main Heater Stopped"
when
Item MainHeater received command OFF
then
whenStarted = null //Stops clock
MainHeater_Cooling.postUpdate(ON)
createTimer(now.plusSeconds(90), [ |
MainHeater_Cooling.postUpdate(OFF)
])
end
rule "Check Main Heater and Increment Runtimes"
when
Time cron "0 0/1 * * * ?"
then
// Check if MainHeater failed
if (MainHeater_Failed.state == ON) {
//sendMail("myemail@gmail.com", "Main Heater", "Main Heater Failed!!")
}
// Increment Runtimes
if (MainHeater.state == ON && whenStarted !== null) {
val Number nowMSec = now.millis
val Number wsMSec = whenStarted.millis
whenStarted = now
val Number timeSinceLastUpdate = nowMSec - wsMSec
val Number oldVal = if (MainHeater_RuntimeMSec.state == UNDEF || GeneratorRuntimeMSec.state == NULL) 0 else GeneratorRuntimeMSec.state as Number
val Number totalMSec = oldVal + timeSinceLastUpdate // calculate total runtime
MainHeater_Runtime_MSec.postUpdate(totalMSec) // post the full runtime
val Number hours = totalMSec / 3600000 // (1000 / 60 / 60)
MainHeater_Runtime_Hours.postUpdate(hours)
// Calculate runtime for today
val Number todayOldVal = if(Today_MainHeater_Runtime_MSec.state == UNDEF || Today_MainHeater_Runtime_MSec.state == NULL) 0 else (Today_MainHeater_Runtime_MSec.state as Number).longValue
val Number todayTotalMSec = todayOldVal + timeSinceLastUpdate // calculate total runtime
Today_MainHeater_Runtime_MSec.postUpdate(todayTotalMSec) // post the full runtime
val Number todayHours = todayTotalMSec/1000.0/60.0/60.0
Today_MainHeater_Runtime_Hours.postUpdate(todayHours)
}
end
rule "Today Main Heater Runtime Reset"
when
Time cron "50 59 23 * * ?"
then
Today_MainHeater_Runtime_MSec.postUpdate(0)
end
Thatās a thing of beauty. I will get over and put it in today. We have a cold day here so it will get a chance to start recording.
On the variables in the rule, anything that has a post update I can add as an item and then to the sitemap? Do I even need to create an item for them or your doing that in the rule? They can be persisted as well? Would that be done in the rule or in the item? Once we get this running I will want to create another rule that will calculate the actual propane usage thatās one reason for the ask as well as just wanting to keep this charted.
The two variables, whenstarted and MainHeater_timer, no item needed. You will need to create the other items such as MainHeater_Failed, MainHeater_Cooling, MainHeater_Override. Looking at the rule these items will be a Switch type (ON/OFF).
Switch MainHeater_Failed "Main Heater Failed"
Other items such as MainHeater_Runtime_Hours and Today_MainHeater_Runtime_Hours will need to be a Number item.
Number MainHeater_Runtime_Hours "Main Heater Run Hours [%d]"
After creating the item you can add all of these to your sitemap.
Switch MainHeater_Failed "Main Heater Failed"
Switch MainHeater_Cooling "Main Heater Cooling"
Switch MainHeater_Override " Main Heater Override"
Number MainHeater_Runtime_Hours "Main Heater Runtime Hours [%.1f Hours]" <heater>
Number Today_MainHeater_Runtime_Hours "Main Heater Runtime Hours [%.1f Hours]" <heater>
Number MainHeater_Runtime_MSec "Main Heater Runtime [%.1f MSec]" <heater>
Number Today_MainHeater_Runtime_MSec "Today Main Heater Runtime_MSec [%.1f MSec]" <heater>
I persisted each of those.
I added this to my sitemap:
Text item=MainHeater_Runtime_Hours
Text item=Today_MainHeater_Runtime_Hours
i get this as an error:
[ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'Check Main Heater and Increment Runtimes': The name 'MainHeater_RuntimeMSec' cannot be resolved to an item or type; line 55, column 33, length 22
also, at what point would i expect data to start showing up?
The item name and the name in the rule is not the same. Easy fix is to change the name in the items file to MainHeater_RuntimeMSec, as this is used several time in the rule. Notice the difference of _ in the item MainHeater_Runtime_MSec vs the item in the rule?
My post above was a quick scan of items to create, must have missed those. Not a big deal, just add them in your items file and check that you have no errors in the logs.
Ok, I changed the MainHeater_RuntimeMSec to MainHeater_Runtime_MSec across the board. I added the Generator item even though I dont think i need it.
i get this in the log!
2018-11-15 14:31:00.075 [vent.ItemStateChangedEvent] - MainHeater_Runtime_MSec changed from 35650 to 60004
2018-11-15 14:31:00.100 [vent.ItemStateChangedEvent] - MainHeater_Runtime_Hours changed from 0.00990278 to 0.01666778
2018-11-15 14:31:00.133 [vent.ItemStateChangedEvent] - Today_MainHeater_Runtime_MSec changed from 35650 to 95654
2018-11-15 14:31:00.152 [vent.ItemStateChangedEvent] - Today_MainHeater_Runtime_Hours changed from 0.00990278 to 0.02657056
added the runtime hours and today hours into the sitemap. thats now showing as zero as i just did the short test but it smells like success to me!
Looks good, glad to see working. Time will tell, if anything a slight tweak may be needed to suit a particular need but nothing major. @vzorglub knows his rules.
Agreed! @vzorglub pretty much rocks. How do you do that when you cant test it? Lotās of practice. I brag on the Openhab community all the time to my friends. Best community out there. Oh, itās an awesome app tooā¦
In any case, this is awesome. I was able to create another rule that takes the daily total and calculates the gallons that are being used based on the run time. Thatās what I wanted to get to. Now I need to see how that works over a couple of days. I may need to make some modifications so I can track that over time effectively.
Iāll do a follow up post with the final final so others can follow along. Again, thanks for all the help. I am sure this will be useful for others.
Thanks, I donāt deserve that praise. I am just standing on the shoulder of giants.
Please tick the solution post.
@boilermanc
If you want to PM me so we can go through the rule line by line. Think of it as a personalised tutorial.
And Iāll help you put together the tutorial post.
Seems elaborate.
Online flowmeter would give a direct digital pulse or pulses per revolution.
Count the pulses to give the quantity of gas used in any period
Assuming a constant flow rate i.e. a constant heat output then calculate total period from the number of pulses