Calculating rain duration

My KNX weatherstation reports ON for rain and OFF for no rain. To do some nice charts I also store this into mySQL leveraging OpenHAB persistance. This all works fine. OpenHAB stores every 15 min either ON or OFF and i get charts showing this.

Now, I want to calculate the amount of time it’s been raining the last 24hrs and the last 48hrs. Has anyone of you a great idea how to best calculate this?

Nice puzzle.

One approach could be to use a counter how long it has been raining since midnight and use a rule to increment the counter with the time between ON and OFF events.

But that doesn’t make use of your persistence.

The wiki https://github.com/openhab/openhab/wiki/Persistence includes a new extension:

<item>.sumSince(AbstractInstant) - Retrieves the sum of the previous states since a certain point in time. (OpenHab 1.8)

If you store the ON signals as 1 and OFF as 0 (zero) then you could use this in a rule to compute the number of switches and multiply that by 15 minutes.

Just my 2 cents.

I believe ON is represented in the DB as a 1 and OFF as a 0. If I’m correct, you should be able to do:

val dayRainTotalMinutes = RainSwitch.sumSince(now.minusDays(1))) * 15
val twoDayRainTotalMinutes = RainSwitch.sumSince(now.minusDays(2))) * 15

This assumes you are truly only storing the value every 15 minutes and not also storing every change or every update as well. It gets much trickier if you are.

Note: this approach can suffer from some sampling biases as well because it if rains for one minute at the time of your sample, stops, then rains for another minute around the time of your next sample you will get 30 minutes of rain instead of the actual two minutes of rain.

playing around doing some try and error…
One question, you would do this as a rule or script? I currently have a rule, but it does not work:

`var number dayRainTotalMinutes
var number twoDayRainTotalMinutes

val dayRainTotalMinutes = Regensensor.sumSince(now.minusDays(1))) * 15
val twoDayRainTotalMinutes = Regensensor.sumSince(now.minusDays(2))) * 15`

I did say I think that is how it works. Perhaps it didn’t save them as 1 and 0.

What happens in your rule? "Doesn’t work doesn’t tell me enough. Are errors printed in the log, is the number calculated wrong, etc?

Since I’m using the pretty much same weather station as @FCZ_1896 I just checked the values in mysql DB: the persisted values are ON and OFF not 1 and 0. Seems to be that it needs another rule that creates numbers out of the strings.

Could not work on this for a while and restarted today…

The command is sent as ON or OFF and it is stored like this in the database. Trying to address this by a rule now. However, i get an error for the following rule which is likely to have a wrong element in it. Do you have an idea whats wrong?

when Item Sensor received command then if (receivedCommand == ON) { Sensor_0_1.postUpdate("1") } else if (receivedCommand == OFF) { Sensor_0_1.postUpdate("0") } end

Error msg that i get:

Refreshing model ‘rain-on-off.rules’
2016-06-12 11:50:46.440 [ERROR] [.o.m.c.i.folder.FolderObserver] - An unexpected exception has occured
java.lang.NullPointerException: null
at org.eclipse.emf.ecore.util.EcoreUtil.getAdapter(EcoreUtil.java:148) ~[na:na]
at org.eclipse.xtext.xbase.jvmmodel.JvmModelAssociator.getOrInstall(JvmModelAssociator.java:90) ~[na:na]
at org.eclipse.xtext.xbase.jvmmodel.JvmModelAssociator.sourceToTargetMap(JvmModelAssociator.java:165) ~[na:na]
at org.eclipse.xtext.xbase.jvmmodel.JvmModelAssociator.cleanAssociationState(JvmModelAssociator.java:253) ~[na:na]
at org.eclipse.xtext.xbase.jvmmodel.JvmModelAssociator.discardDerivedState(JvmModelAssociator.java:241) ~[na:na]
at org.eclipse.xtext.resource.DerivedStateAwareResource.discardDerivedState(DerivedStateAwareResource.java:111) ~[na:na]
at org.eclipse.xtext.resource.DerivedStateAwareResource.updateInternalState(DerivedStateAwareResource.java:59) ~[na:na]
at org.eclipse.xtext.resource.XtextResource.doLoad(XtextResource.java:160) ~[na:na]
at org.eclipse.xtext.linking.lazy.LazyLinkingResource.doLoad(LazyLinkingResource.java:75) ~[na:na]
at org.eclipse.emf.ecore.resource.impl.ResourceImpl.load(ResourceImpl.java:1505) ~[na:na]
at org.openhab.model.core.internal.ModelRepositoryImpl.addOrRefreshModel(ModelRepositoryImpl.java:99) ~[na:na]
at org.openhab.model.core.internal.folder.FolderObserver.checkFolder(FolderObserver.java:142) ~[na:na]
at org.openhab.model.core.internal.folder.FolderObserver.run(FolderObserver.java:99) ~[na:na]

Maybe this item name is not correct?
Sensor

I guess it should be renamed to
Sensor_0_1

Sensor is Switch? There is a difference between “ON” and ON and when it can’t automatically convert between things like this is will throw a NullPointer exception.

Great! I changed the code a bit, but it seems the " caused the issue. Thanks for helping. The below code works:

rule “rain-on-off”
when
Item Regensensor received command
then
if (receivedCommand == “ON”) {
sendCommand(Regensensor_0_1, 1)
}
else if (receivedCommand == “OFF”) {
sendCommand(Regensensor_0_1, 0)
}
end

Driving forward with the “project” now and want to try your above provided code. Just 1 question. Do you put this into a rule or as a script?

var number dayRainTotalMinutes
var number twoDayRainTotalMinutes

val dayRainTotalMinutes = Regensensor.sumSince(now.minusDays(1))) * 15
val twoDayRainTotalMinutes = Regensensor.sumSince(now.minusDays(2))) * 15

I only use Rules. I’m not sure how or whether it will work in a script.

Still working on this “project” :wink:

I created the following rules file:

rule “calc rain”

when
Item Regensensor received command

then

if (receivedCommand == “ON”) {
var number dayRainTotalMinutes
var number twoDayRainTotalMinutes

val dayRainTotalMinutes = Regensensor_01.sumSince(now.minusDays(1))) * 15
val twoDayRainTotalMinutes = Regensensor_01.sumSince(now.minusDays(2))) * 15
sendCommand(Regensensor_dayRainTotalMinutes, dayRainTotalMinutes)
sendCommand(Regensensor_twoDayRainTotalMinutes, twoDayRainTotalMinutes)

}

else if (receivedCommand == “OFF”) {
var number dayRainTotalMinutes
var number twoDayRainTotalMinutes

val dayRainTotalMinutes = Regensensor_01.sumSince(now.minusDays(1))) * 15
val twoDayRainTotalMinutes = Regensensor_01.sumSince(now.minusDays(2))) * 15
sendCommand(Regensensor_dayRainTotalMinutes, dayRainTotalMinutes)
sendCommand(Regensensor_twoDayRainTotalMinutes, twoDayRainTotalMinutes)

}

end

I see, openhab has created all items successfully in the database, the item “Regensensor” receives values and all are successfully stored in the db, but there is no values stored for the others. I guess there is something wrong with my rules. Do you have any idea?

Btw. the Items i have in the items file are:
Number Regensensor_01 “Statistik Regen” (gSQL, All)
Number Regensensor_dayRainTotalMinutes “Rain in the last 24h [%s]” (gSQL, All)
Number Regensensor_twoDayRainTotalMinutes “Rain in the last 2 days [%s]” (gSQL, All)
Switch Regensensor “Regen [MAP(Regensensor.map):%s]” (gSQL, All) { knx=“<(60)x/y/z”}

A quick scan doesn’t show any errors. You may try using the .sendCommand method on the Items instead of the sendCommand action (e.g. Regensensor_dayRainTotalMinutes.sendCommand(dayRainTotalMinutes)). Sometimes the actions don’t work that well. But I would expect to see errors in the logs if this were the problem.

Try logging the results of your sumSince calls and make sure you are getting something that makes sense.

Beyond that I have no suggestions.

I changed this as of your advice. Whilst it is not writing anything into the database, i now get at least an error message in openhab log. Played around with the var’s but could not fix it. Do you have any idea after reading the below error message?

Error message:
2016-06-26 22:30:00.261 [WARN ] [o.p.j.i.JdbcPersistenceService] - JDBC::store: ignore Item 'Regensensor_dayRainTotalMinutes' because it is UnDefType 2016-06-26 22:30:00.327 [WARN ] [o.p.j.i.JdbcPersistenceService] - JDBC::store: ignore Item 'Regensensor_twoDayRainTotalMinutes' because it is UnDefType

Rules:

import org.openhab.core.library.types.*
import org.openhab.core.persistence.*
import org.openhab.model.script.actions.*

rule “calc rain”

when
Item Regensensor received command
then
if (receivedCommand == ON) {
var number dayRainTotalMinutes
var number twoDayRainTotalMinutes

val dayRainTotalMinutes=Regensensor_01.sumSince(now.minusDays(1))) * 15
val twoDayRainTotalMinutes=Regensensor_01.sumSince(now.minusDays(2))) * 15
Regensensor_dayRainTotalMinutes.sendCommand(dayRainTotalMinutes)
Regensensor_twoDayRainTotalMinutes.sendCommand(twoDayRainTotalMinutes)

}

else if (receivedCommand == OFF) {
var Number dayRainTotalMinutes = NumberItem.state as DecimalType
var number twoDayRainTotalMinutes

val dayRainTotalMinutes=Regensensor_01.sumSince(now.minusDays(1))) * 15
val twoDayRainTotalMinutes=Regensensor_01.sumSince(now.minusDays(2))) * 15
Regensensor_dayRainTotalMinutes.sendCommand(dayRainTotalMinutes)
Regensensor_twoDayRainTotalMinutes.sendCommand(twoDayRainTotalMinutes)

}

end

The error indicates that the persistence service is trying to persist all the Items but Regensensor_day_RainTotalMinutes and Regensensor_twoDayRainTotalMinutes do not yet have a value (i.e. Undefined, UnDefType). Persistence will not save undefined.

NOTE: Warnings are not necessarily errors. They are just a heads up that something may not quite be what it should be but the program is able to execute despite the weirdness.

I made this work now and it is fantastic to evaluate if i have to water the garden!

@rlkoshak thans a lot for your great support here! Same to JonnyX

For knowledge sharing, here’s the configuration that works:

when
Time cron “0 15 * * * ?”
then
val dayRainTotalMinutes=Regensensor_01.sumSince(now.minusDays(1)) * 15
val twoDayRainTotalMinutes=Regensensor_01.sumSince(now.minusDays(2)) * 15
Regensensor_dayRainTotalMinutes.sendCommand(dayRainTotalMinutes)
Regensensor_twoDayRainTotalMinutes.sendCommand(twoDayRainTotalMinutes)
end