OH3: historic data

  • Platform information:
    • Hardware: Raspberry Pi 4 Model B Rev 1.1 ; 4GB memory
    • Host: Linux openhabian 5.15.76-v7l+ #1597 SMP Fri Nov 4 12:14:58 GMT 2022 armv7l GNU/Linux
    • Distro: Raspbian GNU/Linux 11 (bullseye)
    • Java: openjdk 11.0.16 2022-07-19
  • OH Version: 3.3.0 (Build)
    • Installation method: openhabian

I have this rule to extract some minima / maxima data values of the day:

val String LOG_PREFIX = "DataCatch."

rule "DC: collect temp, humi, airp, rain"
    when
        // Time cron "5 58 23 * * ? *"
        Time cron "0 0/5 * * * ? *"
    then
        val TEMP_MIN = ar_Temperature.minimumSince(now.with(LocalTime.MIN))
        val TEMP_MAX = ar_Temperature.maximumSince(now.with(LocalTime.MIN))

        val HUMI_MIN = ar_Humidity.minimumSince(now.with(LocalTime.MIN))
        val HUMI_MAX = ar_Humidity.maximumSince(now.with(LocalTime.MIN))

        val AIRP_MIN = House_TriS_Baro1.minimumSince(now.with(LocalTime.MIN))
        val AIRP_MAX = House_TriS_Baro1.maximumSince(now.with(LocalTime.MIN))

        val RAIN_TODAY = ar_RainLast24H.state.toString

        val String COLLECTED_DATA = LocalDateTime.now().toString + "," +
            TEMP_MIN + "," + TEMP_MAX + "," +
            HUMI_MIN + "," + HUMI_MAX + "," +
            AIRP_MIN + "," + AIRP_MAX + "," +
            RAIN_TODAY

        logInfo(LOG_PREFIX + "01.01", "Data collected: {}", COLLECTED_DATA)

        val String CLI_RETURN_CODE = executeCommandLine
        (
            Duration.ofSeconds(3), "/bin/sh", "-c", "echo '" +
            COLLECTED_DATA + "' >> /etc/openhab/html/helga.txt; echo -n $?"
        )

        if (Integer::parseInt(CLI_RETURN_CODE) != 0)
        {
            logInfo(LOG_PREFIX + "01.02", "Return code: {}", CLI_RETURN_CODE)
        }

        logInfo(LOG_PREFIX + "01.03", "Collected environmental data")
end

The output is just horrible and not what I was expecting:

2023-06-18T08:20:00.924985,6/18/23, 3:50 AM: ar_Temperature -> 3.222 °C,org.openhab.core.persistence.extensions.PersistenceExtensions$1@272fb,org.openhab.core.persistence.extensions.PersistenceExtensions$1@1d35787,org.openhab.core.persistence.extensions.PersistenceExtensions$1@afb028,6/18/23, 4:14 AM: House_TriS_Baro1 -> 997.66,6/18/23, 7:12 AM: House_TriS_Baro1 -> 999.55,0.000
2023-06-18T08:25:00.928903,6/18/23, 3:50 AM: ar_Temperature -> 3.222 °C,org.openhab.core.persistence.extensions.PersistenceExtensions$1@1af2647,org.openhab.core.persistence.extensions.PersistenceExtensions$1@88e32a,org.openhab.core.persistence.extensions.PersistenceExtensions$1@15a3806,6/18/23, 4:14 AM: House_TriS_Baro1 -> 997.66,6/18/23, 7:12 AM: House_TriS_Baro1 -> 999.55,0.000
2023-06-18T08:30:00.933399,6/18/23, 3:50 AM: ar_Temperature -> 3.222 °C,org.openhab.core.persistence.extensions.PersistenceExtensions$1@cd3ea7,org.openhab.core.persistence.extensions.PersistenceExtensions$1@f4aee7,org.openhab.core.persistence.extensions.PersistenceExtensions$1@1f68be0,6/18/23, 4:14 AM: House_TriS_Baro1 -> 997.66,6/18/23, 7:12 AM: House_TriS_Baro1 -> 999.55,0.000
2023-06-18T08:35:00.952435,6/18/23, 3:50 AM: ar_Temperature -> 3.222 °C,org.openhab.core.persistence.extensions.PersistenceExtensions$1@14939f9,org.openhab.core.persistence.extensions.PersistenceExtensions$1@fb1dbb,org.openhab.core.persistence.extensions.PersistenceExtensions$1@1886e78,6/18/23, 4:14 AM: House_TriS_Baro1 -> 997.66,6/18/23, 7:12 AM: House_TriS_Baro1 -> 999.55,0.000

On top of that, it returns units and displays the date in UK format (AM/PM instead of ISO)… with 3:50 being wrong anyway.

What I’d like to achieve is:

2023-06-18,08:35,3.222,23.4,34,99,990,1000,0

Any hints appreciated on where my mistakes are.

OK, changing this section to:

        val TEMP_MIN = (ar_Temperature.minimumSince(now.with(LocalTime.MIN)).state as Number).toString
        val TEMP_MAX = (ar_Temperature.maximumSince(now.with(LocalTime.MIN)).state as Number).toString

        val HUMI_MIN = (ar_Humidity.minimumSince(now.with(LocalTime.MIN)).state as Number).toString
        val HUMI_MAX = (ar_Humidity.maximumSince(now.with(LocalTime.MIN)).state as Number).toString

        val AIRP_MIN = (House_TriS_Baro1.minimumSince(now.with(LocalTime.MIN)).state as Number).toString
        val AIRP_MAX = (House_TriS_Baro1.maximumSince(now.with(LocalTime.MIN)).state as Number).toString

… with the help of this historicState Date format error (OH3.1) - #3 by kriznik results in:

2023-06-18T09:35:00.534736,3.222 °C,18.778 °C,76,99.0,997.66,999.58,0.000

Now it’s about getting rid of units and format the date nicer.

Any hints appreciated.

Well, I eventually figured it out…

This is the new rule (quite cumbersome)…

rule "DC: collect temp, humi, air pressure, rain"
    when
        Time cron "5 58 23 * * ? *"
        //Time cron "0 0/5 * * * ? *"
    then
        //val TEMP_MIN = (ar_Temperature.minimumSince(now.with(LocalTime.MIN)).state as QuantityType<Temperature>).toString
        val TEMP_MIN = ((ar_Temperature.minimumSince(now.with(LocalTime.MIN)).state as Number).floatValue).toString
        val TEMP_MAX = ((ar_Temperature.maximumSince(now.with(LocalTime.MIN)).state as Number).floatValue).toString

        val HUMI_MIN = (ar_Humidity.minimumSince(now.with(LocalTime.MIN)).state as Number).toString
        val HUMI_MAX = (ar_Humidity.maximumSince(now.with(LocalTime.MIN)).state as Number).toString

        val AIRP_MIN = (House_TriS_Baro1.minimumSince(now.with(LocalTime.MIN)).state as Number).toString
        val AIRP_MAX = (House_TriS_Baro1.maximumSince(now.with(LocalTime.MIN)).state as Number).toString

        val RAIN_TODAY = ar_RainLast24H.state.toString

        var year   = (now.getYear).toString
        var month  = (now.getMonthValue).toString
        var day    = (now.getDayOfMonth).toString
        var hour   = (now.getHour).toString
        var minute = (now.getMinute).toString

        //val String COLLECTED_DATA = LocalDateTime.now().toString + "," +
        val String COLLECTED_DATA =
            day  + "/" + month  + "/" + year + "," +
            hour + ":" + minute + "," +
            TEMP_MIN + "," + TEMP_MAX + "," +
            HUMI_MIN + "," + HUMI_MAX + "," +
            AIRP_MIN + "," + AIRP_MAX + "," +
            RAIN_TODAY

        logInfo(LOG_PREFIX + "01.01", "Data collected: {}", COLLECTED_DATA)

        val String CLI_RETURN_CODE = executeCommandLine
        (
            Duration.ofSeconds(3), "/bin/sh", "-c", "echo '" +
            COLLECTED_DATA + "' >> /etc/openhab/html/helga.txt; echo -n $?"
        )

        if (Integer::parseInt(CLI_RETURN_CODE) != 0)
        {
            logInfo(LOG_PREFIX + "01.02", "Return code: {}", CLI_RETURN_CODE)
        }

        logInfo(LOG_PREFIX + "01.03", "Collected environmental data")
end

Resulting in:

18/6/2023,22:25,3.222,25.889,46.0,99,993.28,999.58,0.000

If you are throwing away the units anyway, why keep them at all? Change the Item to be just a Number instead of a Number:Temperature and there will be no units.

1 Like

I pondered about this when units became available… as I saw no practical value, but only complications for having to deal with a number that has a UoM.
UoM, at least for me, has caused nothing but grief.
Thank you for this comment.

It should be much less so in OH 4 as we now have full control over units. Now:

  • you are not forced to use a Number:X Item even if the Channel demands it
  • conversely, you can use a Number:X Item even if the Channel demands just a Number
  • you can explicitly define the unit independently from the unit delivered by the Channel and from how it’s shown in the UI, conversions will happen automatically (e.g. if the Item delivers Wh and you want kWh, define the unit metadata and it will convert to kWh for you).

I believe all the rules languages have decent support for working with units now. I particularly like JS Scripting’s approach as the Item has four methods to get the state of the Item:

Method What you get
.state The state converted to a String
.numericState The state as a plain old number or null if that isn’t possible (e.g. it’s NULL or it’s a String Item or something.
.quantityState The state as a Quantity which preserves the units.
.rawState The original Java State Object, should only rarely need to be used in cases where you are trying to do something not supported by the helper library already

So in rules, even if you decide to use Units everywhere you don’t have to worry about them unless you want to (I like to because it makes the code more self documenting).

In short, you now have full and independent choice on when and where to use units.

1 Like

This topic was automatically closed 41 days after the last reply. New replies are no longer allowed.