So, I think this solution have issues. If you change the sleep mode before the alarm goes off on the same day, this will make HA believe the alarm if for tomorrow.
I’m not an expert in IOS Shortcut, so correct me if I’m wrong! Also, when an alarm is skipped for the day, I believe we should get the next alarm day! And if the alarm is not set for everyday (week-end off), this is also a problem with the current implementation.
My suggestion consist to send all the data to HA and use a script to parse, understand, and generate the right alarm time and other variables!
I started this HA Template and I will probably write down a script + share a shortcut once it’s tested but I would like some feedbacks!
{# INPUTS from IOS #}
{# This block is not used yet but I beleive we should pass them #}
{% set allowsSnooze = true %}
{% set repeats = true %}
{# This is what I currently use which come from IOS #}
{% set isEnabled = true %}
{% set hours = 6 %}
{% set minutes = 30 %}
{% set repeatDays = "Wednesday\nMonday\nTuesday\nThursday\nFriday" %}
{% set IosNow = "2024-03-18T20:07:14-05:30" %}
{# Let's calculate the TZ diff #}
{# Extract TZ for IOS #}
{% set iosTZ = (IosNow | as_datetime).strftime('%z') | int %}
{% set iosMinutesTZ = iosTZ - ((iosTZ / 100) | int) * 40 %}
{# Extract TZ for HA #}
{% set haTZ = now().strftime('%z') | int %}
{% set haMinutesTZ = haTZ - ((haTZ / 100) | int) * 40 %}
{# Calculate the offset in minutes for IOS to HA #}
{% set diffTZ = iosMinutesTZ - haMinutesTZ %}
{# Let's set some vairable #}
{% set alarmTimeStr = hours|string + ':' + minutes|string %}
{% set repeatDaysArray = repeatDays.split('\n')%}
{% set ns = namespace(
alarmDay = today_at(alarmTimeStr) + timedelta(minutes = diffTZ),
skippedOnce = false,
foundDay = false,
skippedAlarm = false,
) %}
{# Does the alarm could be for today? #}
{% if (ns.alarmDay < now()) %}
{% set ns.alarmDay = ns.alarmDay + timedelta(days = 1) %}
{%endif%}
{# Let's found which day this alarm is #}
{% for _ in range(0, 8) %}
{% if (not ns.foundDay) %}
{% if (ns.alarmDay.strftime('%A') not in repeatDaysArray)%}
{# This day is not in the list, let go to the next day #}
{% set ns.alarmDay = ns.alarmDay + timedelta(days = 1) %}
{% elif (not isEnabled and not ns.skippedOnce) %}
{# This day is in the list, but we need to skip it #}
{% set ns.skippedOnce = true %}
{% set ns.skippedAlarm = ns.alarmDay %}
{% set ns.alarmDay = ns.alarmDay + timedelta(days = 1) %}
{% else %}
{# This is the right day! #}
{% set ns.foundDay = true %}
{%endif%}
{%endif%}
{% endfor %}
{# If we didn't found a day, let's just set alarmDay to false #}
{% if (not ns.foundDay) %}
{% set ns.alarmDay = false %}
{%endif%}
{# Results! #}
foundDay: {{ns.foundDay}}
alarmDay day of the week: {{ns.alarmDay and ns.alarmDay.strftime('%A')}}
alarmDay: {{ns.alarmDay}}
skippedAlarm: {{ns.skippedAlarm}}
skippedOnce: {{ns.skippedOnce}}
Questions for all:
- Does my concerns on bugs are valid?
- Does my template seems to work for you? (you could play with the variable in the header!)
- Does my inputs match your from IOS? (specifically if HA and IOS are not in the same timezone)
Potential downside:
- When you have different schedule for different days, this is only sending the current schedule. This means that even if I have one schedule for the week and one for the weekend, and we’re Thursday, and we skip the next alarm, HA will compute the next alarm to be Monday! This could be compensate by running the shortcut every day to make sure when the new schedule is active, HA will receive the proper update.
- I’m not sure if HA and IOS are not in the same timezone, how this will react!(I updated my script with TZ adjustment)