import re import os from ruamel.yaml import YAML yaml = YAML() # -------------------------------------- put the config here ----------------------------------------------------------- def get_config(): return { 'bedroom': { 'ir_host': 'bedroompi', '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_orange', 'key_green': '[scene] schlafzimmer_rot', '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', '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', } } } # ---------------------------------------------------------------------------------------------------------------------- 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'] media_player = ir_description['media_player'] group = ir_description['group'] 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': action = service('media_player.play_media', media_player, media_content_id=value, media_content_type='music') elif function == 'radio': 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': 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/Pause', 'trigger': [ir_trigger(ir_host, 'key_play'), ir_trigger(ir_host, 'key_pause')], 'action': service('media_player.media_play_pause', 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 = automation_from_config(data) rules += default_light_controls(data['group'], data['ir_host']) rules += default_music_controls(data['media_player'], data['ir_host']) rules += default_shutter_controls(data['group'], 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)