Yet another Alarmclock (nonblocking)

Hey there,

I just wanted to show you my take on an alarmclock where the brightness/volume increase is done with python_scripts.

image

It is inspired by:

alarmclock.py

"""
Inspired by:
https://community.home-assistant.io/t/light-fade-in/35509

Call from script:
{
  "light_entity_id": "group.noshow_lights_alarmclock_wakeup",
  "media_entity_id": "media_player.my_room",
  "transition_time": 5
}


automation:
- alias: alarmclock_wakeup
  trigger:
    platform: template
    value_template: "{{ states('sensor.time') == states('sensor.alarmclock_start_time') }}"
  condition:
    condition: and
    conditions:
      - condition: state                                                        # make sure I'm at home
        entity_id: input_boolean.presence_tillmann
        state: 'on'
      - condition: state                                                        # make sure all lights are switched off
        entity_id: group.all_lights
        state: 'off'
      - condition: state                                                        # make sure the laptop is switched off
        entity_id: input_boolean.presence_device_tillmann_workstation
        state: 'off'
      - condition: or                                                           # check for workingday/weekend option
        conditions:
          - condition: state
            entity_id: input_boolean.alarmclock_status_weekends
            state: 'on'
          - condition: state
            entity_id: binary_sensor.workday_sensor
            state: 'on'
  action:
    - service: input_boolean.turn_off
      entity_id: input_boolean.alarmclock_cancel
    - service: python_script.alarmclock
        data:
          light_entity_id: group.noshow_lights_alarmclock_wakeup                # lights to fade in
          media_entity_id: media_player.my_room                                 # media players to fade in
          transition_time: 20                                                   # minutes to go from start to end brightness/volume
          stepsize: 10                                                          # amount of seconds per step
          brightness_start: 1                                                   # starting brightness of lights entity
          brightness_end: 255                                                   # end brightness of lights entity
          volume_start: 0.01                                                    # start volume of media entity
          volume_end: 0.5                                                       # end volume of media entity
          stream_url: http://wdr-1live-live.cast.addradio.de/wdr/1live/live/mp3/128/stream.mp3  # url for the stream to play

"""

light_entity_id = data.get('light_entity_id')
media_entity_id = data.get('media_entity_id')
transition_time = int(float(data.get('transition_time', 30)))*60
stepsize_seconds = int(float(data.get('stepsize', 5)))
brightness_start = int(float(data.get('brightness_start', 1)))
brightness_end = int(float(data.get('brightness_end', 255)))
volume_start = float(data.get('volume_start', 0.01))
volume_end = float(data.get('volume_end', 0.5))
stream_url = data.get('stream_url', 'http://wdr-1live-live.cast.addradio.de/wdr/1live/live/mp3/128/stream.mp3')

if (light_entity_id is not None and media_entity_id is not None) and (stepsize_seconds <= transition_time):
    """ Get the states of the light and media entities """
    light = hass.states.get(light_entity_id)
    media = hass.states.get(media_entity_id)

    """ Calculate number of steps """
    steps = int(transition_time/stepsize_seconds)
    stepsize_brightness = (brightness_end-brightness_start) / steps
    stepsize_volume = (volume_end - volume_start) / steps

    """ Initialize the media device and the light """
    light_data = {"entity_id": light_entity_id, "brightness": brightness_start}
    media_data = {"entity_id": media_entity_id, "volume_level": volume_start}
    hass.services.call('light', 'turn_on', light_data)
    hass.services.call('media_player', 'volume_set', media_data)
    media_data = {"entity_id": media_entity_id}
    hass.services.call('media_player', 'turn_on', media_data)
    media_data = {"entity_id": media_entity_id, "media_content_id": stream_url, "media_content_type": "audio/mp4"}
    hass.services.call('media_player', 'play_media', media_data)

    """ In case we only have one step, directly set the final volume / brightness """
    if steps == 1:
        light_data = {"entity_id": light_entity_id, "brightness": brightness_end}
        media_data = {"entity_id": media_entity_id, "volume_level": volume_end}
        hass.services.call('light', 'turn_on', light_data)
        hass.services.call('media_player', 'volume_set', media_data)
    else:
        """ Start the iteration process """
        new_brightness = brightness_start
        new_volume = volume_start

        lasttime = time.time() + stepsize_seconds
        endtime  = time.time() + transition_time
        while True:
            now = time.time()
            if (now - endtime >= 0) or (hass.states.get("input_boolean.alarmclock_cancel").state == "on"):
                break
            elif now - lasttime >= stepsize_seconds:
                lasttime = time.time()
                current_brightness = light.attributes.get('brightness', 0)
                current_volume = media.attributes.get('volume_level', 0)

                light_data = {"entity_id": light_entity_id, "brightness": new_brightness}
                media_data = {"entity_id": media_entity_id, "volume_level": new_volume}
                hass.services.call('light', 'turn_on', light_data)
                hass.services.call('media_player', 'volume_set', media_data)
                new_brightness = new_brightness + int(stepsize_brightness)
                new_volume = new_volume + stepsize_volume

    """ Ensure we reached the end values (in case we didn't cancel) """
    if (hass.states.get("input_boolean.alarmclock_cancel").state == "off"):
        light_data = {"entity_id": light_entity_id, "brightness": brightness_end}
        media_data = {"entity_id": media_entity_id, "volume_level": volume_end}
        hass.services.call('light', 'turn_on', light_data)
        hass.services.call('media_player', 'volume_set', media_data)

To run this script, you’ll need

  1. dimmable light
  2. media_player
  3. a input_boolean.alarmclock_cancel item (to cancel the alarm while running)
5 Likes