Alarm Clock with Sonos & Philips Hue

Hi there!

I’m relatively new to Home Assistant (coming from Domoticz) and I really like HA :heart: So, this is my first post here, and I hope it will help others.

I wanted to create a combined alarm clock with Philips Hue :bulb: and Sonos :speaker: as follows:

  1. I can set an alarm (time and fade in duration) in Home Assistant.
  2. At (alarm_time - fade_in_time) my bedroom’s Hue lights start to fade in until alarm_time.
  3. At alarm_time my Sonos alarm finally goes off. :alarm_clock:

With the ideas (mainly) from these resources, I managed to achieve it and it works great:

This it what it looks like:

And here’s how it’s done…

configuration.yaml

sensor:
  - platform: template
    sensors:
      alarm_clock_time:
        friendly_name: 'Alarm Time'
        icon_template: 'mdi:alarm'
        value_template: '{{ "%0.02d:%0.02d" | format(states.input_slider.alarm_clock_hour.state | int, states.input_slider.alarm_clock_minute.state | int ) }}'
      alarm_clock_fade_in_minutes:
        friendly_name: 'Fade In (Minutes)'
        icon_template: 'mdi:gradient'
        value_template: '{{ states.input_slider.alarm_clock_fade_in_minutes.state | int }}'

input_boolean:
  alarm_clock_status:
    name: Alarm Set
    icon: mdi:alarm-check
    initial: off
input_slider:
  alarm_clock_hour:
    name: Hour
    icon: mdi:timer
    initial: 6
    min: 0
    max: 23
    step: 1
  alarm_clock_minute:
    name: Minute
    icon: mdi:timer
    initial: 30
    min: 0
    max: 55
    step: 5
  alarm_clock_fade_in_minutes:
    name: Fade In (Minutes)
    icon: mdi:gradient
    initial: 15
    min: 0
    max: 30
    step: 5

groups.yaml

alarm_clock:
  name: Alarm Clock
  entities:
    - input_boolean.alarm_clock_status
    - sensor.alarm_clock_time
    - input_slider.alarm_clock_hour
    - input_slider.alarm_clock_minute
    - input_slider.alarm_clock_fade_in_minutes

automations.yaml

- alias: Set Sonos Alarm
  trigger:
    - platform: state
      entity_id: input_boolean.alarm_clock_status
      to: 'on'
  action:
    service: media_player.sonos_update_alarm
    data_template:
      entity_id: media_player.bedroom
      alarm_id: 4
      time: '{{ states.sensor.alarm_clock_time.state }}'
      enabled: true
- alias: Disable Sonos Alarm
  trigger:
    - platform: state
      entity_id: input_boolean.alarm_clock_status
      to: 'off'
  action:
    service: media_player.sonos_update_alarm
    data_template:
      entity_id: media_player.bedroom
      alarm_id: 4
      enabled: false
- alias: Fade in Lights in Bedroom
  trigger:
    platform: time
    seconds: 00
  condition:
    condition: and
    conditions:
      - condition: state
        entity_id: input_boolean.alarm_clock_status
        state: 'on'
      - condition: template
        value_template: '{{ (utcnow().strftime("%s") | int + states.sensor.alarm_clock_fade_in_minutes.state | int * 60) | timestamp_custom("%H:%M") == states.sensor.alarm_clock_time.state }}'
  action:
    service: script.bedroom_light_fade_in

scripts.yaml

bedroom_light_fade_in:
  sequence:
    - service: light.turn_on
      data_template:
        entity_id:
          - light.bedroom_ceiling
          - light.bedroom_door
          - light.bedroom_window
        profile: energize
        transition: '{{ states.sensor.alarm_clock_fade_in_minutes.state | int * 60 }}'
    - delay: '{{ "00:" + "%0.02d" | format(states.sensor.alarm_clock_fade_in_minutes.state | int) + ":15" }}'
    - service: homeassistant.turn_off
      entity_id: input_boolean.alarm_clock_status

Remarks & Tips

  • For the Sonos alarm: HA only sets the alarm’s time and marks it active. I do the rest with the Sonos app - you have way more options there (like source, volume, duration, speaker groups, etc.).
  • To find the Sonos alarm ID:
    1. Using your Sonos app, set an active alarm. Verify it’s a non-recurring one (Frequency: Once).
    2. Open the speaker’s debug API at http://<sonos_ip>:1400/support/review
    3. Navigate to: <speaker_name> > Alarm Data
  • The trigger to start fading in is tricky: You cannot use now() in a trigger to compare the times. So, the trigger is to check the condition/value_template every minute.
  • The additional 15 seconds in the script’s delay (fade_in_time + 15 seconds) prevent the Sonos alarm from being deactivated too early.

I hope this helps! Have fun! :smiley_cat:

12 Likes

First i’d like to say thank you for sharing this piece. I’m trying to implement that in my system, but i’m having a little issue.
1- I cannot locate this option"condition/value_template" in my player. and second can you please tell me how could i change the time format from “condition: template value_template: '{{ (utcnow().strftime("%s")” to local time or eastern time.

Hi @mistrovly You’re welcome, I’m glad I could help others.

  1. condition/value_template has nothing to do with your player. It’s just a “numeric state condition” (https://home-assistant.io/docs/scripts/conditions/#numeric-state-condition) and because I check the values with a template, the key value: becomes value_template:. My remark “condition/value_template” is not a real check/condition, it’s just a reference to my construct at:
condition:
    condition: and
    conditions:
      - condition: state
        entity_id: input_boolean.alarm_clock_status
        state: 'on'
      - condition: template
        value_template: '{{ ... }}'
  1. My system does not run on UTC either, it runs on CEST. My check if it’s time to start fading in the lights works as follows:
    1. I take a UTC timestamp (“now in seconds since …”),
    2. then I add the fade in time in seconds -> this gives me a new timestamp in seconds,
    3. this new timestamp is then converted to local time (with timestamp_custom("%H:%M")) and
    4. finally, this is the (local) time I can compare to my (local) alarm time.
      So, this calculation (taking a UTC timestamp, do some calulations and print out the local value) should be absolutely independent of your timezone.
      If you just want a local timestamp, take now(), see: https://home-assistant.io/docs/configuration/templating/#home-assistant-template-extensions.

Hi, thanks for the howto. I have a problem with finding the Alarm Data. At http://<sonos_ip>:1400/support/review I can only see:
Zone Player Info
Zone Players
Media Servers
DNS Cache
Ethernet Ports
Ethernet Ports Statistics
Accounts
/VERSION
/etc/resolv.conf
/proc/ath_rincon/status
/proc/ath_rincon/phyerr
/proc/ath_rincon/nf
/proc/ath_rincon/station
/sbin/ifconfig
/usr/bin/uptime
/usr/sbin/brctl showstp br0

Hi Max

You’re right, the “Alarm Data” section seems to have vanished with the last update(s). At the moment, I see no other possibility to find the alarm ID but “trying it out”. Try ID = 1 and check if the alarm is updated, if not, try the next ID, etc.

Dave

Alright, I will try that, thank you for the fast reply :slight_smile:
Edit: It works now, but I have another problem. This line doesn’t work:
value_template: '{{ states.sensor.time.state == states.sensor.alarm_clock_time_long.state - ":15" }}'
I want to substract 15 minutes, so that my light starts 15 minutes before the music. Also I have a problem with the transition setting. I want to increase the intensity of the light over 15 minutes. So I would put in 90000, becuase it says it is in ms. I also did not find an option for choosing the colour for Xiaomi Yeelight.

I had the same issue, that i could not find the Alarm_id.
Wrote a mini-script based on soco

#!/usr/bin/env python
import soco
import soco.alarms

for zone in soco.discover():
  print zone.player_name   
device = soco.discovery.any_soco()
print device

alarm = soco.alarms.Alarm(device)
print soco.alarms.get_alarms()

I tried the iterative process, but after I tried alarm_id: 9, i gave up.
found that my alarm_id was set to 61 :wink:

1 Like

just a stupid/naive question, everyone is still using input slider while i believe that this changed to input_number with 0.55. or did i miss read something somewhere?

you are right… just change it and functionality is the same.

Hey Guys, i am brand new to homeassisant and the forums and i was wondering if someone could help me with a modified version of my alarmclock. It does what it is supposed to do but, it seems very roundabout.

configuration.yml

sensor:
  - platform: template
    sensors:
      alarm_time:
        friendly_name: 'Time'
        value_template: '{{ "%0.02d:%0.02d" | format(states("input_number.alarmhour") | int, states("input_number.alarmminutes") | int) }}'
  - platform: template
    sensors:
      alarm_time_before_hours:
        friendly_name: 'Time before hours'
        value_template: '{{ 
        ((((states("input_number.alarmhour") | int)*60 + (states("input_number.alarmminutes") | int) - (states("input_number.alarmoffset"))| int)/60)| int)     
        }}'
  - platform: template
    sensors:
      alarm_time_before_minutes:
        friendly_name: 'Time before minutes'
        value_template: '{{ 
         (((((((((states("input_number.alarmhour") | int)*60 + (states("input_number.alarmminutes") | int) - (states("input_number.alarmoffset")) | int)/60)) - 
         ((((states("input_number.alarmhour") | int)*60 + (states("input_number.alarmminutes") | int) - (states("input_number.alarmoffset")) | int)/60)| int))*100) | int)*60/100) | round)        
        }}'
input_number:
  alarmhour:
    name: Hours
    icon: mdi:timer
    initial: 6
    min: 0
    max: 23
    step: 1
  alarmminutes:
    name: Minutes
    icon: mdi:timer
    initial: 30
    min: 0
    max: 59
    step: 5
  alarmoffset:
    name: Offset
    icon: mdi:blur-linear
    initial: 15
    min: 0
    max: 60
    step: 15

input_boolean:
  alarmweekday:
    name: Weekdays Only 
    initial: on
    icon: mdi:calendar
  alarmweekon:
    name: Active     
    initial: on

automation.yaml

- action:
  - data:
      message: wake up
    service: notify.zchat
  alias: Wake me up
  id: '1507981123211'
  trigger:
    - platform: time
      minutes: '/1'
      seconds: 0
  condition:
  - condition: state
    entity_id: input_boolean.alarmweekon
    state: 'on'
  - condition: state
    entity_id: input_boolean.alarmweekday
    state: 'on'
  - condition: time
    weekday:
      - mon
      - tue
      - wed
      - thu
      - fri
  - condition: template
    value_template: ' {{ now().strftime("%H:%M") == states.sensor.alarm_time.state
      }}'
- action:
  - data:
      message: Transition Lights
    service: notify.zchat
  alias: Transition Lights
  id: '1507981123212'
  trigger:
    - platform: time
      minutes: '/1'
      seconds: 0
  condition:
  - condition: state
    entity_id: input_boolean.alarmweekon
    state: 'on'
  - condition: state
    entity_id: input_boolean.alarmweekday
    state: 'on'
  - condition: time
    weekday:
      - mon
      - tue
      - wed
      - thu
      - fri
  - condition: template
    value_template: ' {{ now().strftime("%H:%M") == (states.sensor.alarm_time_before.state)
      }}'

which leads to

image

What this does, at the moment, is sending two messages to a chat. First when the Transition timer is hit (at the moment set to 0 minutes prior) and second when the alarm goes off.

and to

image

or two messages with an offset. but i was to lazy to wait…

To my question, i have a bunch of stupid math in the beginning in order to get a point in time before the actual time, is there a nicer way to do that ?

1 Like

please check the Automation Docs.
They are supposed to start with a trigger, then a condition (if needed) and then… the action.
You seem to start with the action?

Hey Poolcactus, thanks for the info. However, when you create a new automation using the automation creator this is how the file is created. So i am not sure maybe that’s because I am using something above 0.55. I also have to say that these automation work without a problem. I was just wondering if there is a better way to add minutes to time than what I have done

Sorry, I’m not familiar with the automation creator.
However, looking at what I think you are trying to achieve. (having the lights go on before the alarm with a specific offset?)

it might be easier to calculate that time with strptime()
which you can substract from the now.strftime

did a quick check in python:

1 #!/usr/bin/env python
2
3 from datetime import datetime
4
5 print datetime.now()
6
7 alarmtime = datetime.now().strftime("%H:%M")
8 offset = datetime.strptime("00:20", "%H:%M")
9 earlyalarm = datetime.now() - offset
10
11 print alarmtime
12 print offset
13 print earlyalarm

gives:

pi@raspi:~ $ ./timetest.py
2017-10-24 21:15:44.725232 
21:15
1900-01-01 00:20:00
43030 days, 20:55:44.757239

you may get the idea, hope it is useful

Hey,

thank you so much for your contribution! This is really cool and it worked with just minor adjustments, I would like to let everyone know:

  1. As described in the comments, I changed the input_slider to input_number. Maybe you could update the orignal post, so that people do not need to go through all comments? :slight_smile:
  2. For me “now()” instead of “utcnow()” worked. I could easily test the right code with the template developer tool
  3. I had to hide the “sensor.alarm_clock_fade_in_minutes” within the “customize”-section.
  4. I have added an automation with trigger on any of the input_numbers (Hour, Minute, Fade-in) in order to turn off the alarm (bool). It forces me to turn the alarm on again after doing changes to Hour, Minute or Fade-in. Otherwise the sonos app would not notice changes to the alarm time…

Anyhow. Your code is really cool! Thanks again!

Nazze

Hey Nazze
Thank you for your reply/feedback. I wanted to change the original post after input_slider became input_number a while ago, but it seems that posts cannot be edited anymore when they have reached a certain age.

How can I execute the script to find out the id of my alarm when running HA on Hassio? Does it have to be a non-recurring alarm for this to work?

Sure, you could use some “trial and error” method to find your alarm ID. Start with 1, set the alarm and verify in the Sonos app if it was activated. If not, increment the ID and test again.

I suggest taking a non-recurring alarm as the alarm in HA goes to off after it fired. If you use a recurring alarm in Sonos, your “alarm system” gets out of sync: Sonos will continue to ring the alarm while the alarm system in HA is deactivated after the first alarm.

If I dont want to increment 1 and keep going, is there a script that I can run within Hass.io to get the number instead?

Sorry, I thought you are just looking for the alarm ID in sonos for the setup. I don’t know what you are trying to achieve by dynamically getting the IDs from your Sonos alarms and I don’t know a way how to look them up.

Maybe you could write a script to poll the Sonos Web-API to get the alarm IDs.

Hello
You can read out the Sonos Alarm ID with Intels software tools for uPnP : https://software.intel.com/en-us/articles/intel-software-for-upnp-technology-download-tools

Start the “Device Spy” app and open a sonos IP address, look for “ListAlarms” , rightclick and chose Invoke action !

/Michael