Countdown Timer from Joda.time to Java.time (Openhab 3.x)

Hi community,

I was switching over from OH 2.5.10 to 3.0.0 with success in general. The paper UI and text based Things/items/etc. were automatically adapted and the basic function is running. On few points I need to adapt, before I will spend time in getting familiar with new OH3 features.
I have a problem in one rule and fear I’m not able to solve it by myself, because I’m no professional programmer. In OH2 the rule was working smooth, without any problems, even if someone of this community named it “ugly code”, but for me it was working.

The target application: If AmazonEcho is getting a timer, it sends a DateTime information to an item. This information is the target date and time on which the timer is counted to 0. I puzzled for OH2 a functional code after researching step by step and using some code examples and now I need to translate that from joda.time base to java.time base.

I was thinking, if it is possible to import a joda.time base for that rule?
If this is not possible, may somebody can translate that with ease?

Here is the item, which is triggered with the target date time information, if a timer is started via Amazon Alexa:

DateTime EchoWohnzimmer_NaechsterTimer "EchoWohnzimmer_NaechsterTimer" {channel="amazonechocontrol:echo:Sabrina_Amazon:G090RF0474830SUC:nextTimer"}

This item is the trigger for the following rule, which will calculate the difference between the target time of the item and the current time, to show a countdown in a string item “EchoTimer”:

var Timer echotimer //Variable für den Echo-Timer im Wohnzimmer

rule "Echo-Timer"
when
    Item EchoWohnzimmer_NaechsterTimer changed
then

    if (EchoWohnzimmer_NaechsterTimer.state == UNDEF) {
    EchoTimer.sendCommand("Kein aktiver Timer")
    }

        else {
        
            // Timer Date and time 2019-10-20T21:58:35.870-0600
            val timerString = EchoWohnzimmer_NaechsterTimer.state.format("%1$tY-%1$tm-%1$tdT%1$tH:%1$tM:%1$tS")

                echotimer = createTimer(now, [ |
        
                // parse String to Date Time
                var DateTime timestring = parse(timerString)
                // find out time left in minutes
                val timeleft = (((timestring.millis + 60000) - now.millis) / 60000)

                    // finish sequence if the time left is 0
                    if(timeleft == 0) {
                    EchoTimer.sendCommand("Timer abgelaufen")
                    Thread::sleep(2000)
                    EchoTimer.sendCommand("Kein aktiver Timer")
                    }
                        else {
                        // update the timer Item with time remaining 
                        EchoTimer.sendCommand("noch " + timeleft + " Min.")
                        // reschedule the timer for 1 minute
                        echotimer.reschedule(now.plusMillis(60000))
                        }
           
                
                ] )
        }
end

Thank’s for any help to get this functional in OH 3!

No, Joda is completely gone in OH 3.

You’ve formatted the String into an ISO8601 format which is redundant because a DateTimeType’s toString outputs in that format already.

Furthermore, you don’t even need the String to parse in the first place. You can get the ZonedDateTime straight from the Item’s state.

var timestring = EchoWohnzimmer_NaechsterTimer.getZonedDateTime

Note, this is a horribly named variable. It’s not an never was a timestring.

You don’t really need milliseconds so you can use ZonedDateTime’s toEpochSecond.

val timeleft = ((timestring.toEpochSecond + 60) - now.toEpochSecond) / 60

It’s a good thing you are moving to OH 3 because that sleep was a really bad idea in OH 2.

So with the simplifications possible with using ZonedDateTime which replaced Joda the code would be something like

then
    // You should check for NULL too
    if (EchoWohnzimmer_NaechsterTimer.state == UNDEF || EchoWohnzimmer_NaechsterTimer.state == NULL) {
        EchoTimer.sendCommand("Kein aktiver Timer")
    }
    else {
        echotimer = createTimer(now, [ |
            val timeleft = (EchoWohnzimmer_NaechsterTimer.state.toEpochSecond + 60 - now.toEpochSecond) / 60
            ...
        ])
    }

Hi rlkoshak,

Thank’s for that valuable input. As I said, this is a code puzzle result and some names I copied and pasted. With your advices and hints I will try to clean up this code as good as possible.

What do you exactly mean with:

It’s a good thing you are moving to OH 3 because that sleep was a really bad idea in OH 2

Yesterday, I was able to bring it to life in OH3 with many trial&error processes. The code yesterday was:

var Timer echotimer //Variable für den Echo-Timer im Wohnzimmer

rule "Echo-Timer Show5"

when

    Item EchoWohnzimmer_NaechsterTimer changed

then

    if (EchoWohnzimmer_NaechsterTimer.state == UNDEF) {

    EchoTimer.sendCommand("Kein aktiver Timer")

    }

        else {  echotimer = createTimer(now, [ |

        

                // parse String to Date Time

                var timestring = (EchoWohnzimmer_NaechsterTimer.state as DateTimeType).getZonedDateTime()

                //Then get the epoch on GMT

                var EpochTime = timestring.toInstant().toEpochMilli();

                //Get now time to epoch

                var nowTimeEpoche = Instant.now().toEpochMilli();

                

                // find out time left in minutes

                val timeleft = (((EpochTime + 60000) - nowTimeEpoche) / 60000)

                    // finish sequence if the time left is 0

                    if(timeleft == 0) {

                    EchoTimer.sendCommand("Timer abgelaufen")

                    Thread::sleep(2000)

                    EchoTimer.sendCommand("Kein aktiver Timer")

                    }

                        else {

                        // update the timer Item with time remaining 

                        EchoTimer.postUpdate("noch " + timeleft + " Min.")

                        // reschedule the timer for 1 minute

                        echotimer.reschedule(ZonedDateTime.now.plusSeconds(60))

                        }

                           

                ] )

        }

end

For daily use I switched back to OH 2.5.11 yesterday, because it was not running very smooth. Especially the HabPanel has problems with German ä,ö,ü,ß. What is the best way to restore an OH2 backup to a new clean OH3 installation? My things are all created in the paper UI of OH2 and the items are a mix of paper UI and text files.

Thank you very much for your time!

In OH 2.5 long running rules run risk of using up all the execution threads making it so none of your rules can run. That’s not a pregnant in oh 3 any more. Why have my Rules stopped running? Why Thread::sleep is a bad idea

I’m rebuilding from scratch so I don’t know the best way to migrate.