OH 3 Alarm Clock

EDIT: The rule below can now be installed from the marketplace.

Ever since OH 1.6 (and before) setting an alarm clock in OH has been troublesome. We used to have to go to great lengths to set it up and expose it on our sitemaps with one Item each for the year, month, day, hour, and minute with rules to trigger when any of them change to construct a DateTime out of them and eventually to set a timer. Search for “Alarm Clock” and you will find many tutorials with different variations on this theme.

Now in OH 3 we have options to make this much simpler and more flexible.

Thus tutorial is focused mainly on the use case where the ability to update an item with the next scheduled alarm on the Android app. It can be expanded relatively easily to support more use cases.

Item

Create a.DateTime Item called AlarmClock. Configure this Item to be populated with the date and time of the next alarm. This can be done any way you choose. Options include:

  • In the Android app open settings and scroll down to “Send device information to server” and enable “Alarm time”, using “AlarmClock” as the name of the Item.

  • Link the Item to an Astro Channel to have the alarm be relative to a sun or moon event.

  • Create a Rule to update the time of the alarm based on some openHAB event.

  • Manually enter the date and time on MainUI. If using this approach, create a rule to advance the date of the alarm time to the current day.

  • Populate the Item based in calendar entries and the iCalendar binding.

Manual Entry

If using manual entry, add the following as a custom widgets under Developer Tools. Then select the widgets as the Default Standalone Widget and Default List Widget in the AlarmClock’ Item’s metadata. See the following for more details:

Then add a rule to advance the alarm clock time to the next day at midnight which will retrigger the creation of the alarm clock timer.

Default Standalone Widget

For use on custom Layout Pages

uid: datetime_standalone
tags: []
props:
  parameters:
    - description: Label for the widget
      label: Label
      name: label
      required: false
      type: TEXT
    - context: item
      description: An item to control
      label: Item
      name: item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Jul 27, 2021, 10:06:53 AM
component: oh-input-card
config:
  outline: true
  clearButton: false
  inputmode: text
  footer: =items[props.item].state
  item: =props.item
  placeholder: mm/dd/yyy, --:-- --
  title: =props.label
  type: datetime-local
  sendButton: true

Default List Widget

For use in the Locations, Equipment, Properties, and inside List Card Widgets.

uid: datetime_list
tags: []
props:
  parameters:
    - description: Label for the wiodget
      label: Label
      name: label
      required: false
      type: TEXT
    - context: item
      description: An item to control
      label: Item
      name: item
      required: false
      type: TEXT
  parameterGroups: []
timestamp: Jul 28, 2021, 9:01:20 AM
config: 
  outline: true
  inputmode: datetime-local
  subtitle: =items[props.item].state
  name: alarmtime
  label: =props.label
  placeholder: mm/dd/yyy, --:-- --
  title: =props.label
  type: text
  sendButton: true

To Today Rule

triggers:
  - id: "1"
    configuration:
      time: 00:01
    type: timer.TimeOfDayTrigger
conditions: []
actions:
  - inputs: {}
    id: "2"
    configuration:
      type: application/javascript
      script: >-
        var ZDT = Java.type("java.time.ZonedDateTime");

        var now = ZDT.now();

        var dt = items["AlarmClock"].getZonedDateTime();

        events.postUpdate("AlarmClock", new DateTimeType(now.withHour(dt.getHour()).withMinute(dt.getMinute()).withSecond(dt.getSecond())));
    type: script.ScriptAction

The above should handle daylight savings but has not been tested. One minute after midnight move the AlarmClock Item’s state to the same time but with today’s date.

Rule Installation

Sometime soon we will have a marketplace for rules. In the mean time you need to copy and paste. Follow the instructions to install the rule found at https://github.com/rkoshak/openhab-rules-tools/tree/main/alarm_clock.

At a high level:

  1. create a new rule
  2. open the code tab
  3. copy the contents of alarmclock.yml on github to that code tab
  4. save
  5. manually run the rule to create the timer; be sure to run it manually every time you modify this rule.
  6. on the Scripts page create a new Script using “alarm_script” as the UID
  7. select any language desired and write the code that should run when the alarm goes off

How it works

The rule in alarmclock.yml handles all the processing of changes to the AlarmClock Item and creating and managing the timer. When the timer goes off at the AlarmClock time, it will run your alarm_script rule.

By separating this into two parts it allows the user to code the stuff to do when the alarm goes off in the script language of their choice. It also allows the user to make modifications to the code that runs when the alarm goes off without needing to remember to manually rerun the rule to reschedule the timer. Finally, it provides a way to upgrade the library code without requiring users to update their custom code to install the updates.

Note, if using text based .rules files, the UID of your rules will be the name of the file followed by a one-up number based on the order of they appear in the file. If using text based rules be sure to update the alarmclock.yml imported rule to use the appropriate rule UID. If using some other language, review MainUI’s list of rules to find the UID for the rule to run and update as appropriate.

Variations

Here are some ideas for expansion and customizations:

  • Instead of using AlarmClock, use one of the Items used in Time of Day so the day starts when the alarm goes off instead of a fixed time or Astro time. Be sure to update the trigger on the rule if a different Item is used.

  • Update the rule to handle more than one AlarmClock Item, such as one per day. To do this add each DateTime Item to a Group and trigger the rule when a member of the Group changes. Iterate through the members of the Group and create a Timer for all the Items that have a DateTime for the future. As an added bonus add the UID for the Script rule to run as Item metadata so each alarm can do something different.

  • Use ephemeris to choose between two or more different alarm scripts based on the type of the day. For example, run one Script rule on weekdays and a different one on weekends and holidays.

8 Likes

This is becoming great. Is there a way to get this date-time-picker into a sitemap?

No.

All right, that’s what I thought. Thank’s anyway!