Help with OH 4 Android alarm clock rule

Hi, can you please help me fixing the following rule?

I finally upgraded from 2.x to 4.0 and am nearly done updating my rules. My alarm clock rule I can’t get to work again. The goal is to send to alarm clock time from my Android phone and trigger a rule at the given time.

I’m trying the following two options:

1) Updating my old rule:
The following rule I used for years now without a flaw.

Item:
Number AlarmClock_user1

Rule:

var Timer timerAlarm = null

rule "Alarm Clock"
when
  Item AlarmClock_user1 changed
then
  if (AlarmClock_user1.state == UNDEF || AlarmClock_user1.state == NULL) {
    if (timerAlarm !== null) {
      timerAlarm.cancel
      timerAlarm = null
    }
    logInfo("alarm", "All alarms are cancelled")
  } else {
    alarm_clock_time = new DateTime((AlarmClock_user1.state as Number).longValue)
    logInfo("alarm", "Scheduling alarm clock for " + alarm_clock_time.toString)

    if (timerAlarm !== null) {
      logInfo("alarm", "Rescheduling alarm clock.")
      timerAlarm.reschedule(alarm_clock_time)
    } else {
      logInfo("alarm", "New alarm clock is set.")
      timerAlarm = createTimer(alarm_clock_time,
        [ alarm_clock_timer_id |
          logInfo("alarm", "Trigger timerAlarm!")
          // do something
        ]
      )
    }
  }
end

Unfortunately sending the the update to the item AlarmClock_user1 in the app leads to:

2023-07-27 13:35:31.907 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'AlarmClock_user1' received command 1690520100000
2023-07-27 13:35:31.907 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'AlarmClock_user1' changed from UNDEF to 1690520100000
2023-07-27 13:35:31.908 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID 'alarm_clock-1' failed: An error occurred during the script execution: Cannot invoke "org.eclipse.xtext.common.types.JvmType.eIsProxy()" because "type" is null in alarm_clock

What is the “new” syntax for creating a timer or needed time format?

2) Using the example from the docs:

Items:
DateTime AlarmClock_Default "Alarm Clock [%s]" <time>

Rule:

rule "Alarm Clock Default"
when
    Time is AlarmClock_Default
then
    logInfo("alarm", "Triggered default alarm clock rule.")
end

The problem is that the rule does not trigger to the correct time - I think due a timezone problem. Updating the items shows:

2023-07-27 13:44:23.421 [INFO ] [openhab.event.ItemCommandEvent      ] - Item 'AlarmClock_Default' received command 2023-07-28T05:00:00.000+0000
2023-07-27 13:44:23.421 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'AlarmClock_Default' changed from UNDEF to 2023-07-28T05:00:00.000+0000

The alarm should trigger at local time 07:00, not 05:00. I think therefore, at 07:00 nothing happens.

The OH instance runs in a docker container with environment variable:

EXTRA_JAVA_OPTS: "-Duser.timezone=Europe/Berlin"

The timestamp the log shows are correct. The GUI settings do show Europe/Berlin as set timezone.

How do I achieve that the alarm triggers at the correct local time?

Thanks for the help!

05:00 GMT is 07:00 Berlin time. They are the exact same moment in time. That’s what the +0000 part of the timestamp is all about, the timezone offset.

The Android system keeps the alarm clock times in GMT and therefore the Android app delivers the time in GMT.

You can test it easily by setting an alarm for a couple of minutes from now and you should see the rule triggered at the correct time.

Thanks for your explanation. Unfortunately your suggested test doesn’t work or I’m afraid I don’t unterstand.

E.g.

  • My local time is now: 17:30
  • I set the alarm on my Android to 17:35
  • Item 'AlarmClock_Default' changed from UNDEF to 2023-07-27T15:35:00.000+0000
  • At 17:35 local time: My Android rings and AlarmClock_Default changes to UNDEF or the next set alarm. But the rule (logInfo from above) is not executed.

I also tried:

  • My local time is now: 17:30
  • I set the alarm on my Android to 19:35
  • Item 'AlarmClock_Default' changed from UNDEF to 2023-07-27T17:35:00.000+0000
  • At 17:35 local time: Nothing happens.

Exactly 17:35:00.000? or a little after? It might be the Android app is unsetting the alarm too soon or the time is off between the phone and the OH server. Even one second off could cause problems.

This seems to be the reason. I made some more tests:

[...]
# alarm set for 20:46
2023-07-27 20:46:00.007 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'AlarmClock_Default' changed from 2023-07-27T18:46:00.000+0000 to UNDEF
2023-07-27 20:46:00.259 [INFO ] [org.openhab.core.model.script.alarm ] - Triggered default alarm clock rule.
# => SUCCESS
[...]
# alarm set for 20:48
2023-07-27 20:47:59.336 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'AlarmClock_Default' changed from 2023-07-27T18:48:00.000+0000 to UNDEF
# => no rule trigger
[...]
# alarm set for 20:53
2023-07-27 20:52:59.347 [INFO ] [openhab.event.ItemStateChangedEvent ] - Item 'AlarmClock_Default' changed from 2023-07-27T18:53:00.000+0000 to UNDEF
# =>  no rule trigger

It’s not very reliable. Any ideas how to solve this? Fixing my option 1 above could work around this.

Double check your clock on your phone and your server. I suspect it’s unreliable because your phone is half a second or more ahead of your server leaving not enough time for the rule to trigger before the Android app sets the Item to UNDEF.

How long do you let the alarm go? IIRC it doesn’t set the Item to UNDEF until the alarm is dismissed. If you let it run for a few seconds does it work? That would confirm the clock is the issue.

I wasn’t able to reliably get Sleep as Android alarms working with the Android app on Android 13 so I switched over to using Sleep as Android’s MQTT capabilities. That has the added benefit of not waking up the house when I’m not home (e.g. on travel).

The item is set immediately to UNDEF or to the next set alarm. It’s is irrelevant how long I let the alarm run on the phone.

Do you have a hint how to fix my initial rule instead?

The problems seems to be the line:
alarm_clock_time = new DateTime((AlarmClock_user1.state as Number).longValue)

This value should be the parameter for the methods createTimer(alarm_clock_time, …) and reschedule (alarm_clock_time).

In OH 3/4 it causes:
Script execution of rule with UID 'alarm_clock-2' failed: An error occurred during the script execution: Cannot invoke "org.eclipse.xtext.common.types.JvmType.eIsProxy()" because "type" is null in alarm_clock

The original rule isn’t going to work any better. If the Item gets set to UNDEF before the timer goes off, as is the case, the timer will be cancelled and never go off same as the triggering of the rule is being cancelled.

  if (AlarmClock_user1.state == UNDEF || AlarmClock_user1.state == NULL) {
    if (timerAlarm !== null) {
      timerAlarm.cancel
      timerAlarm = null
    }
    logInfo("alarm", "All alarms are cancelled")
  }

I don’t know how this ever would have worked. A DateTimeType, which is the state carried by a DateTime Item, is not and never was a Number.

I’m not sure why you are using a DateTime here anyway. Nothing in OH accepts a DateTime. You need a ZonedDateTime or LocalDateTime to schedule a timer.

But you don’t need to create a DateTime. DateTimeType has geZonedDateTime() method.

alarm_clock_time = (AlarmClock_user1.state as DateTimeType).zonedDateTime

But at this point I’ve not used Rules DSL for years. My ability to support these is quickly diminishing. :person_shrugging:

OK, that’s probably why the original code actually worked. I missed at first that you are coming from 2.x. IIRC it’s OK as written for OH 2 but there were a bunch of breaking changes around date times in OH 3.0.

When making such a huge jump between versions, you need to look at the breaking changes in the release announcements for all the releases between your version and the current version: 3.0, 3.1, 3.2, 3.3, 3.4 and 4.0 because OH 4.0 includes all of those breaking changes. In this particular case, the removal of Joda DateTime and the Joda library in favor of the built in java.time classes is the breaking change on this line which was introduced in OH 3.0.

1 Like

but you can accomplish the same by using your presence items (assuming you have them).
For example, I have rules to mute home amp (music, tv…) when our phones have incoming and outgoing calls, and unmute when the call is completed.
Also alarm clock rules.
But both of those rules happen only if that phone is currently in the house, As I dont want my music go to mute because my wife received a call while she is on another continent. same for android alarms, the rule specifies presence has to be ON.

Of course. There are lots of ways to achieve things and certain approaches will be better under certain circumstances.

But the way I have it now I need do nothing. No extra Items (assuming I didn’t track presence). No rule. Rule Conditions or if statement to check presence.

When I’m not home, the alarm Item simply remains NULL and the MORNING stuff doesn’t happen because there is no alarm event in the first place.

I solved the problem in the meantime by this dirty trick… I know it’s not the best solution but for me the simplest one.

var zoned_date = (AlarmClock_user1.state as DateTimeType).zonedDateTime.minusSeconds(10)

Complete rule:

rule "Alarm Clock user1 test"
when
  Item AlarmClock_user1 changed
then
    if (AlarmClock_user1.state == UNDEF || AlarmClock_user1.state == NULL) {
      if(alarm_clock_timer_user1 !== null) {
        alarm_clock_timer_user1.cancel
        alarm_clock_timer_user1 = null
        logInfo("alarm", "Cancel all user1 wake up timer")
      }
    } else {
      var zoned_date = (AlarmClock_user1.state as DateTimeType).zonedDateTime.minusSeconds(10)
      if(alarm_clock_timer_user1 !== null && !alarm_clock_timer_user1.hasTerminated) {
        logInfo("alarm", "Rescheduling user1 wake up timer")
        alarm_clock_timer_user1.reschedule(zoned_date)
      } else {
        logInfo("alarm", "Create new user1 wake up timer for: " + zoned_date)
        alarm_clock_timer_user1 = createTimer(zoned_date, [ alarm_clock_timer_user1_id |
          logInfo("alarm", "Trigger user1 wake up timer")
          alarm_clock_timer_user1 = null
        ])
      }
    }
end

Thanks a lot @rlkoshak for your help!

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