316 lines
13 KiB
Python
316 lines
13 KiB
Python
import re
|
|
import os
|
|
from ruamel.yaml import YAML
|
|
|
|
yaml = YAML()
|
|
|
|
# -------------------------------------- put the config here -----------------------------------------------------------
|
|
|
|
def get_config():
|
|
return {
|
|
'bedroom': {
|
|
'ir_host': 'bedroompi.fritz.box',
|
|
'media_player': 'media_player.bedroompi',
|
|
'group': 'group.bedroom',
|
|
|
|
'mapping': {
|
|
'btn_1': '[playlist] Good Morning',
|
|
'btn_2': '[playlist] Good Night Long',
|
|
'btn_3': '[playlist] Good Night',
|
|
|
|
'btn_4': '[playlist] Bar Classics',
|
|
'btn_5': '[playlist] Sentimental Moods',
|
|
'btn_6': '[playlist] Pop',
|
|
|
|
'btn_7': '[radio] B 5 aktuell',
|
|
'btn_8': '[radio] BR-Klassik',
|
|
'btn_9': '[playlist] http://opml.radiotime.com/Tune.ashx?id=s25028&formats=aac,ogg,mp3', # Klassik Radio
|
|
|
|
'key_numeric_star': '[radio] Antenne Bayern',
|
|
'btn_0': '[radio] Bayern 3',
|
|
'key_numeric_pound': '[radio] Bayern 2',
|
|
|
|
'key_red': '[scene] schlafzimmer_stillen',
|
|
'key_green': '[scene] schlafzimmer_orange',
|
|
'key_yellow': '[scene] schlafzimmer_ganz_hell',
|
|
'key_blue': '[scene] schlafzimmer_blau',
|
|
|
|
'key_tv': [service('script.turn_on', 'script.timed_sleep',
|
|
variables={'media_content_id': 'spotify:playlist:37i9dQZF1DXbcPC6Vvqudd', # Regen
|
|
'light_off_secs': 15 * 60,
|
|
'music_off_secs': 45 * 60,
|
|
'shuffle': 1,
|
|
})],
|
|
'key_video': [service('script.turn_on', 'script.timed_sleep',
|
|
variables={'media_content_id': 'Good Night',
|
|
'light_off_secs': 15 * 60,
|
|
'music_off_secs': 45 * 60,
|
|
'shuffle': 0,
|
|
})],
|
|
'key_music': [service('script.turn_on', 'script.timed_sleep',
|
|
variables={'media_content_id': 'spotify:playlist:37i9dQZF1DXbcPC6Vvqudd', # Regen
|
|
'light_off_secs': 5 * 60,
|
|
'music_off_secs': 20 * 60,
|
|
'shuffle': 1,
|
|
})],
|
|
'key_pictures': [service('script.turn_on', 'script.timed_sleep',
|
|
variables={'media_content_id': 'Good Night',
|
|
'light_off_secs': 5 * 60,
|
|
'music_off_secs': 20 * 60,
|
|
'shuffle': 0,
|
|
})],
|
|
|
|
'key_power': [ # Music & Lights off
|
|
service('media_player.media_pause', 'media_player.bedroompi'),
|
|
service('light.turn_off', 'group.bedroom'),
|
|
],
|
|
'key_ok': [ # Grosser Rollo zu, kleiner halb zu
|
|
service('cover.close_cover', 'cover.schlafzimmer_rollo_gross'),
|
|
service('cover_half.set_half', 'cover.schlafzimmer_rollo_klein'),
|
|
],
|
|
'key_mute': [service('light.turn_off', 'group.all_downstairs_but_bedroom_and_outside')],
|
|
'key_channel': [service('light.turn_off', 'group.all_downstairs_but_bedroom')],
|
|
}
|
|
},
|
|
'living_area': {
|
|
'ir_host': 'kitchenpi.fritz.box',
|
|
'media_player': 'media_player.kitchenpi',
|
|
'group': 'group.living_area',
|
|
|
|
'mapping': {
|
|
'btn_4': '[playlist] Bar Classics',
|
|
'btn_5': '[playlist] Sentimental Moods',
|
|
'btn_6': '[playlist] Pop',
|
|
|
|
'btn_7': '[radio] B 5 aktuell',
|
|
'btn_8': '[radio] BR-Klassik',
|
|
'btn_9': '[playlist] http://opml.radiotime.com/Tune.ashx?id=s25028&formats=aac,ogg,mp3', # Klassik Radio
|
|
|
|
'key_numeric_star': '[radio] Antenne Bayern',
|
|
'btn_0': '[radio] Bayern 3',
|
|
'key_numeric_pound': '[radio] Bayern 2',
|
|
|
|
'key_red': '[scene] wohnbereich_orange',
|
|
'key_green': '[scene] wohnbereich_grun',
|
|
'key_yellow': '[scene] wohnbereich_hell',
|
|
'key_blue': '[scene] wohnbereich_blau_grun',
|
|
}
|
|
},
|
|
'first_floor_dining_room': {
|
|
'ir_host': 'esszimmerradio.fritz.box',
|
|
'media_player': 'media_player.esszimmer',
|
|
'mapping': {
|
|
'btn_1': '[radio] Bayern 1',
|
|
'btn_2': '[radio] Bayern 2',
|
|
'btn_3': '[radio] BR Heimat',
|
|
'btn_4': '[radio] Bayern+',
|
|
'btn_5': '[radio] B 5 Aktuell',
|
|
'btn_6': '[radio] BR-Klassik',
|
|
'btn_7': '[playlist] Gesammelte Weihnachtslieder',
|
|
'btn_8': '[playlist] Harmonic Brass Christmas',
|
|
'btn_9': '[playlist] German Brass Christmas',
|
|
'key_numeric_star': '[playlist] Weihnachten mit den Wiener Sängerknaben',
|
|
'btn_0': '[playlist] Weihnachten mit den Wiener Sängerknaben',
|
|
'key_numeric_pound': '[playlist] SammlungGeorg',
|
|
}
|
|
},
|
|
'first_floor_living_room': {
|
|
'ir_host': 'musikserverWohnzimmerOben.fritz.box',
|
|
'media_player': 'media_player.wohnzimmer',
|
|
'mapping': {
|
|
'btn_1': '[radio] Bayern 1',
|
|
'btn_2': '[radio] Bayern 2',
|
|
'btn_3': '[radio] BR Heimat',
|
|
'btn_4': '[radio] Bayern+',
|
|
'btn_5': '[radio] B 5 Aktuell',
|
|
'btn_6': '[radio] BR-Klassik',
|
|
'btn_7': '[playlist] Gesammelte Weihnachtslieder',
|
|
'btn_8': '[playlist] Harmonic Brass Christmas',
|
|
'btn_9': '[playlist] German Brass Christmas',
|
|
'key_numeric_star': '[playlist] Weihnachten mit den Wiener Sängerknaben',
|
|
'btn_0': '[playlist] Weihnachten mit den Wiener Sängerknaben',
|
|
'key_numeric_pound': '[playlist] SammlungGeorg',
|
|
}
|
|
},
|
|
}
|
|
|
|
|
|
# ----------------------------------------------------------------------------------------------------------------------
|
|
|
|
|
|
description_regex = re.compile(r'\[\s*(.*)\s*\](.*)')
|
|
|
|
|
|
def split_description(d):
|
|
res = description_regex.match(d)
|
|
return res.group(1).strip(), res.group(2).strip()
|
|
|
|
|
|
def automation_from_config(ir_description):
|
|
ir_host = ir_description['ir_host']
|
|
|
|
result = []
|
|
for key, description in ir_description['mapping'].items():
|
|
automation = {'alias': f'IR {ir_host} {key}',
|
|
'trigger': ir_trigger(ir_host, key)}
|
|
if isinstance(description, list):
|
|
action = description
|
|
elif isinstance(description, str):
|
|
function, value = split_description(description)
|
|
if function == 'playlist':
|
|
media_player = ir_description['media_player']
|
|
action = service('media_player.play_media', media_player,
|
|
media_content_id=value, media_content_type='music')
|
|
elif function == 'radio':
|
|
media_player = ir_description['media_player']
|
|
action = service('media_player.play_media', media_player,
|
|
media_content_id=value, media_content_type='channel')
|
|
elif function == 'scene':
|
|
action = service('scene.turn_on', 'scene.' + value)
|
|
elif function == 'timed_light_off':
|
|
group = ir_description['group']
|
|
action = service('light.turn_off', group, transition=str(60 * int(value)))
|
|
else:
|
|
raise ValueError("Invalid prefix " + function)
|
|
else:
|
|
raise ValueError("Invalid type for entry " + key)
|
|
|
|
automation['action'] = action
|
|
result.append(automation)
|
|
return result
|
|
|
|
|
|
def ir_trigger(ir_host, button_name):
|
|
return {
|
|
'platform': 'event',
|
|
'event_type': 'ir_command_received',
|
|
'event_data': {
|
|
'button_name': button_name,
|
|
'repeat_counter': 0,
|
|
'host': ir_host,
|
|
}
|
|
}
|
|
|
|
|
|
def service(service_name, entity_id, **kwargs):
|
|
kwargs['entity_id'] = entity_id
|
|
return {
|
|
'service': service_name,
|
|
'data': kwargs
|
|
}
|
|
|
|
|
|
def default_shutter_controls(device_group, ir_host):
|
|
"""Default rules for Hauppauge IR for Shutter control with up, down, left, right buttons"""
|
|
return [
|
|
{
|
|
'alias': f'IR {ir_host} Rollo auf',
|
|
'trigger': ir_trigger(ir_host, 'key_up'),
|
|
'action': service('cover.open_cover', device_group),
|
|
},
|
|
{
|
|
'alias': f'IR {ir_host} Rollo zu',
|
|
'trigger': ir_trigger(ir_host, 'key_down'),
|
|
'action': service('cover.close_cover', device_group),
|
|
},
|
|
{
|
|
'alias': f'IR {ir_host} Rollo halb',
|
|
'trigger': [ir_trigger(ir_host, 'key_left'), ir_trigger(ir_host, 'key_right')],
|
|
'action': service('cover_half.set_half', device_group),
|
|
},
|
|
]
|
|
|
|
|
|
def default_light_controls(device_group, ir_host):
|
|
"""Default light rules for Hauppauge IR for light dimming with channel up/down and light off with stop button"""
|
|
return [
|
|
{
|
|
'alias': f'IR {ir_host} Licht heller',
|
|
'trigger': ir_trigger(ir_host, 'key_channelup'),
|
|
'action': service('dimmer.dim', device_group, offset=30),
|
|
},
|
|
{
|
|
'alias': f'IR {ir_host} Licht dunkler',
|
|
'trigger': ir_trigger(ir_host, 'key_channeldown'),
|
|
'action': service('dimmer.dim', device_group, offset=-30),
|
|
},
|
|
{
|
|
'alias': f'IR {ir_host} Licht viel heller',
|
|
'trigger': ir_trigger(ir_host, 'key_menu'),
|
|
'action': service('dimmer.dim', device_group, offset=130),
|
|
},
|
|
{
|
|
'alias': f'IR {ir_host} Licht viel dunkler',
|
|
'trigger': ir_trigger(ir_host, 'key_stop'),
|
|
'action': service('dimmer.dim', device_group, offset=-130),
|
|
},
|
|
{
|
|
'alias': f'IR {ir_host} Licht aus',
|
|
'trigger': ir_trigger(ir_host, 'key_goto'),
|
|
'action': service('light.turn_off', device_group),
|
|
},
|
|
]
|
|
|
|
|
|
def default_music_controls(device_group, ir_host):
|
|
"""Default music control (play, pause, next) for Hauppauge IR"""
|
|
return [
|
|
{
|
|
'alias': f'IR {ir_host} Musik Play',
|
|
'trigger': ir_trigger(ir_host, 'key_play'),
|
|
'action': service('media_player.media_play_pause', device_group),
|
|
},
|
|
{
|
|
'alias': f'IR {ir_host} Musik Pause',
|
|
'trigger': ir_trigger(ir_host, 'key_pause'),
|
|
'action': service('media_player.turn_off', device_group),
|
|
},
|
|
{
|
|
'alias': f'IR {ir_host} Musik Next',
|
|
'trigger': [ir_trigger(ir_host, 'key_forward'), ir_trigger(ir_host, 'key_fastforward')],
|
|
'action': service('media_player.media_next_track', device_group),
|
|
},
|
|
{
|
|
'alias': f'IR {ir_host} Musik Prev',
|
|
'trigger': [ir_trigger(ir_host, 'key_previous'), ir_trigger(ir_host, 'key_rewind')],
|
|
'action': service('media_player.media_next_track', device_group),
|
|
},
|
|
{
|
|
'alias': f'IR {ir_host} Vol Up',
|
|
'trigger': ir_trigger(ir_host, 'key_volumeup'),
|
|
'action': service('media_player.volume_up', device_group),
|
|
},
|
|
{
|
|
'alias': f'IR {ir_host} Vol Down',
|
|
'trigger': ir_trigger(ir_host, 'key_volumedown'),
|
|
'action': service('media_player.volume_down', device_group),
|
|
},
|
|
{
|
|
'alias': f'IR {ir_host} Shuffle On',
|
|
'trigger': ir_trigger(ir_host, 'key_menu'),
|
|
'action': service('media_player.shuffle_set', device_group, shuffle=True),
|
|
},
|
|
{
|
|
'alias': f'IR {ir_host} Shuffle Off',
|
|
'trigger': ir_trigger(ir_host, 'key_exit'),
|
|
'action': service('media_player.shuffle_set', device_group, shuffle=False),
|
|
},
|
|
]
|
|
|
|
|
|
def create_rules(folder):
|
|
for name, data in get_config().items():
|
|
rules = []
|
|
rules += automation_from_config(data)
|
|
|
|
if 'group' in data:
|
|
rules += default_shutter_controls(data['group'], data['ir_host'])
|
|
rules += default_light_controls(data['group'], data['ir_host'])
|
|
if 'media_player' in data:
|
|
rules += default_music_controls(data['media_player'], data['ir_host'])
|
|
|
|
file_name = os.path.join(folder, "ir_" + name + '.yaml')
|
|
with open(file_name, 'w') as f:
|
|
f.write("# Dont' edit manually! this is generated!\n\n")
|
|
yaml.dump(rules, f)
|