Skip to content

Instantly share code, notes, and snippets.

@aschamberger
Last active July 20, 2024 06:32
Show Gist options
  • Save aschamberger/ee3934d3d6fe87fae99da495c0065992 to your computer and use it in GitHub Desktop.
Save aschamberger/ee3934d3d6fe87fae99da495c0065992 to your computer and use it in GitHub Desktop.
HA Automation Blueprint: Control Logitech Squeezebox media player entities from KNX switching and relative dimming (DPT 3.007) telegrams.
blueprint:
name: KNX - Squeezebox control
description: Control Logitech Squeezebox media player entities from KNX switching and relative
dimming (DPT 3.007) telegrams.
homeassistant:
# `knx.telegram` trigger and `enabled` templates require Home Assistant 2024.6.0
min_version: "2024.6.0"
domain: automation
input:
media_player:
name: Squeezebox media player
description: The Squeezebox instance that shall be controled.
selector:
entity:
domain: media_player
dimm_helper:
name: Helper for relative dimming
description: Relative dimming 'toggle helper' to handle stop command
selector:
entity:
domain: input_boolean
default: {}
switch_address:
name: Switch group address
description: >
Group address for switching the player on and off (DPT 1.001).
Example: '8/3/20'
default: null
state_address:
name: State group address
description: >
Group address for player state (DPT 1.001).
Example: '8/3/21''
default: null
dimm_address:
name: Volume relative dimming address
description: >
Group address for dimming the volume (DPT 3.007).
Example: '8/3/22'
default: null
volume_state_address:
name: Volume state group address
description: >
Group address for player volume (DPT 5.001).
Example: '8/3/23'
default: null
favorite_address:
name: favorite group address
description: >
Group address for iterating the favorite list (DPT 1.007). Value: only 1.
Example: '8/3/24'
default: null
mute_address:
name: Mute group address
description: >
Group address for muting the player (DPT 1.001).
Example: '8/3/25'
default: null
mute_state_address:
name: Mute state group address
description: >
Group address for muting state of the player (DPT 1.001).
Example: '8/3/26'
default: null
dimm_time:
name: Dimm time
description: Time dimming from 0 to 100% shall take.
selector:
number:
min: 1
max: 20
step: 0.1
unit_of_measurement: seconds
mode: slider
default: 4
dimm_steps:
name: Dimm steps
description: Steps used to dimm from 0 to 100%.
selector:
number:
min: 1
max: 100
step: 1
unit_of_measurement: steps
mode: slider
default: 40
source_url: https://gist.github.com/aschamberger/ee3934d3d6fe87fae99da495c0065992
mode: parallel
max_exceeded: silent
variables:
media_player_entity_id: !input media_player
_dimm_time: !input dimm_time
_dimm_steps: !input dimm_steps
dimm_time: '{{ _dimm_time|float }}'
dimm_steps: '{{ _dimm_steps|int }}'
dimm_step: '{{ (1 / dimm_steps) }}'
dimm_delay: '{{ dimm_time * 1000 / dimm_steps }}'
trigger_variables:
_dimm_helper: !input dimm_helper
_switch_address: !input switch_address
_state_address: !input state_address
_dimm_address: !input dimm_address
_volume_state_address: !input volume_state_address
_favorite_address: !input favorite_address
_mute_address: !input mute_address
_mute_state_address: !input mute_state_address
trigger:
- platform: homeassistant
event: start
id: initialize
- platform: event
event_type: automation_reloaded
id: initialize
# when KNX integration was reloaded
- platform: event
event_type: service_registered
event_data:
domain: knx
service: event_register
id: initialize
- platform: knx.telegram
destination: !input switch_address
group_value_read: false
group_value_response: false
id: switch
enabled: "{{ _switch_address != None }}"
- platform: knx.telegram
destination: !input dimm_address
group_value_read: false
group_value_response: false
id: dimm
enabled: "{{ not not _dimm_helper and _dimm_address != None }}"
- platform: knx.telegram
destination: !input favorite_address
group_value_read: false
group_value_response: false
id: favorite
enabled: "{{ _favorite_address != None }}"
- platform: knx.telegram
destination: !input mute_address
group_value_read: false
group_value_response: false
id: mute
enabled: "{{ _mute_address != None }}"
- platform: state
entity_id: !input media_player
to:
id: expose_state
enabled: "{{ _state_address != None }}"
- platform: knx.telegram
destination: !input state_address
group_value_write: false
group_value_response: false
id: expose_state_read
enabled: "{{ _state_address != None }}"
- platform: state
entity_id: !input media_player
attribute: volume_level
id: expose_volume
enabled: "{{ _volume_state_address != None }}"
- platform: knx.telegram
destination: !input volume_state_address
group_value_write: false
group_value_response: false
id: expose_volume_read
enabled: "{{ _volume_state_address != None }}"
action:
- choose:
# TURN ON
- conditions:
condition: and
conditions:
- condition: trigger
id: switch
- '{{ trigger.payload == 1 }}'
sequence:
- service: media_player.media_play
entity_id: !input media_player
# TURN OFF
- conditions:
condition: and
conditions:
- condition: trigger
id: switch
- '{{ trigger.payload == 0 }}'
sequence:
- service: media_player.turn_off
entity_id: !input media_player
# VOLUME STOP
- conditions:
condition: and
conditions:
- condition: trigger
id: dimm
- '{{ trigger.payload == 0 or trigger.payload == 8 }}'
sequence:
- service: input_boolean.turn_on
data: {}
target:
entity_id: !input dimm_helper
# VOLUME UP
- conditions:
condition: and
conditions:
- condition: trigger
id: dimm
- '{{ 9 <= trigger.payload <= 15 }}'
sequence:
- service: input_boolean.turn_off
data: {}
target:
entity_id: !input dimm_helper
- repeat:
while:
- condition: state
entity_id: !input dimm_helper
state: "off"
- "{{ repeat.index <= dimm_steps }}"
sequence:
- service: media_player.volume_set
entity_id: !input media_player
data:
volume_level: '{% if state_attr(media_player_entity_id, "volume_level") == None %}{{ dimm_step }}{% else %}{{ ([0.01, state_attr(media_player_entity_id, "volume_level") + dimm_step, 1]|sort)[1] }}{% endif %}'
- delay:
milliseconds: '{{ dimm_delay }}'
- service: input_boolean.turn_off
data: {}
target:
entity_id: !input dimm_helper
# VOLUME DOWN
- conditions:
condition: and
conditions:
- condition: trigger
id: dimm
- '{{ 1 <= trigger.payload <= 7 }}'
sequence:
- service: input_boolean.turn_off
data: {}
target:
entity_id: !input dimm_helper
- repeat:
while:
- condition: state
entity_id: !input dimm_helper
state: "off"
- "{{ repeat.index <= dimm_steps }}"
sequence:
- service: media_player.volume_set
entity_id: !input media_player
data:
volume_level: '{% if state_attr(media_player_entity_id, "volume_level") == None %}{{ dimm_step }}{% else %}{{ ([0.01, state_attr(media_player_entity_id, "volume_level") - dimm_step, 1]|sort)[1] }}{% endif %}'
- delay:
milliseconds: '{{ dimm_delay }}'
- service: input_boolean.turn_off
data: {}
target:
entity_id: !input dimm_helper
# FAVORITE
- conditions:
condition: and
conditions:
- condition: trigger
id: favorite
- '{{ trigger.payload == 1 }}'
sequence:
# 1: get currently played item
- service: squeezebox.call_query
entity_id: !input media_player
data:
command: path
parameters:
- '?'
# 2a: search if current item is a favorite
- service: squeezebox.call_query
entity_id: !input media_player
data:
command: favorites
parameters:
- exists
- "{{ state_attr(media_player_entity_id, 'query_result')['_path'] }}"
# 2b: store result
- variables:
current_item: "{% if state_attr(media_player_entity_id, 'query_result')['exists'] == 1 %}{{ state_attr(media_player_entity_id, 'query_result')['index'] }}{% else %}-1{% endif %}"
# 3: get all favorites
- service: squeezebox.call_query
entity_id: !input media_player
data:
command: favorites
parameters:
- items
- '0'
- 'item_id:'
# 4: play next item from favorites
- service: squeezebox.call_query
entity_id: !input media_player
data:
command: favorites
parameters:
- playlist
- play
- >
{%- set ns = namespace(ids=[]) -%}
{%- for fav in state_attr(media_player_entity_id, 'query_result')['loop_loop'] if fav.isaudio == 1 -%}
{%- set ns.ids = ns.ids + [fav.id.split('.')[1]] -%}
{%- endfor -%}
{%- if current_item == -1 -%}
item_id:{{ ns.ids[0] }}
{%- else -%}
{%- if ns.ids.index(current_item|string)+1 == ns.ids|length -%}
item_id:{{ ns.ids[0] }}
{%- else -%}
item_id:{{ ns.ids[ns.ids.index(current_item|string)+1] }}
{%- endif -%}
{%- endif -%}
# MUTE
- conditions:
condition: and
conditions:
- condition: trigger
id: mute
- '{{ trigger.payload == 1 }}'
sequence:
- service: media_player.volume_mute
entity_id: !input media_player
data:
is_volume_muted: true
# UNMUTE
- conditions:
condition: and
conditions:
- condition: trigger
id: mute
- '{{ trigger.payload == 0 }}'
sequence:
- service: media_player.volume_mute
entity_id: !input media_player
data:
is_volume_muted: false
# EXPOSE STATE
- conditions:
condition: or
conditions:
- condition: trigger
id: expose_state
- condition: trigger
id: expose_state_read
sequence:
- service: knx.send
data:
address: !input state_address
payload: "{% if states(media_player_entity_id) == 'off' %}0{% else %}1{% endif %}"
response: "{{ trigger.id == 'expose_state_read' }}"
# EXPOSE VOLUME
- conditions:
condition: or
conditions:
- condition: trigger
id: expose_volume
- condition: trigger
id: expose_volume_read
sequence:
- service: knx.send
data:
address: !input volume_state_address
payload: "{% if state_attr(media_player_entity_id, 'volume_level') == None %}0{% else %}{{ state_attr(media_player_entity_id, 'volume_level')*100 }}{% endif %}"
response: "{{ trigger.id == 'expose_volume_read' }}"
type: percent
# INITIALIZE
- conditions:
condition: trigger
id: initialize
sequence:
- sequence:
- condition: template
value_template: "{{ True }}"
enabled: "{{ _mute_state_address != None }}"
- service: knx.exposure_register
data:
address: !input mute_state_address
entity_id: !input media_player
attribute: is_volume_muted
type: binary
default: 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment