I’m currently running OH2.5 snapshot #1601.
In using the buienradar binding, I use a rule for setting some item values to circumvent the absence of an update timestamp channel. I’m grouping the rain forecasts in quarters and in hours, hence the group totals change several times as the forecast data are released from the buienradar binding to OH.
I use a timer to wait at least 5 seconds after an update of the group item representing the total amount of rainfall. Due to the several changes, I have to reset the timer in the rule several times as well.
I am somehow surprised that I run into “object already existing” exceptions when rescheduling the timer:
==> /var/log/openhab2/openhab.log <==
2019-06-15 09:21:05.961 [WARN ] [el.script.internal.actions.TimerImpl] - An error occurred while rescheduling the job 'DEFAULT.2019-06-15T09:21:10.915+02:00: Proxy for org.eclipse.xtext.xbase.lib.Procedures$Procedure0: [ | {
val ruleTitle
logDebug(<XFeatureCallImplCustom>,<XStringLiteralImpl>)
org.eclipse.xtext.xbase.impl.XIfExpressionImpl@78fc9c
<null>.buienRadarTimer = <XNullLiteralImplCustom>
} ]': Unable to store Job : 'DEFAULT.2019-06-15T09:21:10.915+02:00: Proxy for org.eclipse.xtext.xbase.lib.Procedures$Procedure0: [ | {
val ruleTitle
logDebug(<XFeatureCallImplCustom>,<XStringLiteralImpl>)
org.eclipse.xtext.xbase.impl.XIfExpressionImpl@78fc9c
<null>.buienRadarTimer = <XNullLiteralImplCustom>
} ]', because one already exists with this identification.
Here’s the buienradar.rules file:
var Timer buienRadarTimer = null
rule "It will rain"
when
Item gBuienRadarForecastRain changed
then
val String ruleTitle = "It will rain"
// Wait until all group state updates have been propagated
if (buienRadarTimer !== null && !buienRadarTimer.hasTerminated) {
// Reschedule the timer if it already exists
logDebug(ruleTitle, "Rescheduling the timer")
buienRadarTimer.reschedule(now.plusSeconds(5))
} else {
logDebug(ruleTitle, "Creating the timer")
buienRadarTimer = createTimer(now.plusSeconds(5), [ |
val String ruleTitle = "It will rain (inside timer)"
logDebug(ruleTitle, "Timer has terminated - code execution started")
if (gBuienRadarForecastRain.state instanceof DecimalType) {
val Number rain = gBuienRadarForecastRain.state as Number
if (rain > 0) {
logDebug(ruleTitle, "It will rain: {} mm expected in the coming 120 minutes", rain)
val int earliest_time = gBuienRadarForecastRain.allMembers.filter[ i | i.state as Number > 0 ].map[ i |
Integer::parseInt( i.name.substring(i.name.length() - 7).substring(0, 3) )
].reduce[ min, v |
if (v < min)
v
else
min
] // Lambda return type is: Number
postUpdate(Wx_buienradar_rain_time, earliest_time)
}
logDebug(ruleTitle, "Timer has terminated - code execution terminated")
} else {
// gBuienRadarForecastRain.state is not set
logWarn(ruleTitle, "gBuienRadarForecastRain.state is not a numeric value: '{}'", gBuienRadarForecastRain.state)
}
buienRadarTimer = null
])
}
end
So I suppose this is due to the timer granularity (hence the name collision exceptions) and to the burst of item updates triggering the rule (hence the higher chances of occurring).
Is there something I could to to avoid the exceptions (unless asking for the update timestamp to be made available from the binding)?
FWIW I linked this post to the following feature request on GitHub: