import os import argparse from util import DeviceInfo, add_to_group, name_to_id from ruamel.yaml import YAML import knx_conf as knx script_path = os.path.dirname(os.path.realpath(__file__)) yaml = YAML() yaml.preserve_quotes = True sensor_exclude_list = [ 'sensor.fritz_box_7490_bytes_received', 'sensor.fritz_box_7490_bytes_sent', # 'sensor.fritz_box_7490_kbyte_sec_received', # 'sensor.fritz_box_7490_kbyte_sec_sent', 'sensor.fritz_box_7490_packets_received', 'sensor.fritz_box_7490_packets_sec_received', 'sensor.fritz_box_7490_packets_sec_sent', 'sensor.fritz_box_7490_packets_sent', 'sensor.martin_handy_availability_sensor', 'sensor.martin_handy_light_sensor', 'sensor.martin_handy_step_counter_sensor', 'sensor.date_time', 'sensor.date_time_iso', 'sensor.time', 'sensor.time_date', ] def add_knx_devices(devices, groups): imported_csv = knx.import_ets5_csv_file(os.path.join(script_path, 'knx_data/export_project1.csv')) imported_csv.update(knx.import_ets5_csv_file(os.path.join(script_path, 'knx_data/export_project2.csv'))) lights = [ # Dimmers DeviceInfo('Wohnzimmerlampe', 'Wohnzimmer Deckenlampe', 'living_area'), DeviceInfo('EsszimmerlampeWest', 'Esszimmer Deckenlampe West', 'living_area'), DeviceInfo('EsszimmerlampeMitte', 'Esszimmer Deckenlampe Mitte', 'living_area'), DeviceInfo("EsszimmerWandlampe", 'Esszimmer Schrankleuchte', 'living_area'), DeviceInfo("Küchenlampe", "Küche Deckenlampe", 'living_area'), DeviceInfo("AussenleuchteUntenSO", "Aussen Terassenlicht", 'outside'), DeviceInfo("Gang", "Gang Licht", 'hallway'), DeviceInfo("Bad", "Bad Licht", 'bathroom'), DeviceInfo("GangWindfang", "Gang Einganglicht", 'hallway'), DeviceInfo("LichtWaschküche", "Waschküche Licht", 'hallway'), # Normal lights DeviceInfo('AussenleuchteHaustüren', 'Haustür Licht', 'outside'), DeviceInfo('AussenleuchteObenNW', 'Haustür Licht NW', 'first_floor'), DeviceInfo('TreppenhausLicht', "Treppenhaus Licht", 'first_floor'), #DeviceInfo('WCLicht', "WC Licht", 'other'), DeviceInfo('LampeVorratsraum', "Vorratsraum Licht", 'other'), # Bewegungsmelder LEDs DeviceInfo("BewegungsmelderMitte LED", "Bewegungsmelder Mitte LED", 'hallway'), DeviceInfo("BewegungsmelderWest LED", "Bewegungsmelder West LED", 'hallway'), DeviceInfo("BewegungsmelderOst LED", "Bewegungsmelder Ost LED", 'hallway'), # Briefkasten DeviceInfo("KlingelknoepfeLicht", "Klingelknöpfe Licht", 'outside'), DeviceInfo("BriefkastensaeuleBeleuchtung", "Briefkasten Licht", 'outside'), ] shutters = [ DeviceInfo('Wohnzimmer Fenster Rollo', 'Wohnzimmer Fenster Rollo', 'living_area'), DeviceInfo('Terassentür Rollo', 'Wohnzimmer Terrassentür Rollo', 'living_area'), DeviceInfo('Küchenfenster Rollo', 'Küche Fenster Rollo', 'living_area'), DeviceInfo('Esszimmerfenster Rollo', 'Esszimmer Fenster Rollo', 'living_area'), ] switches = [ # Bells DeviceInfo("KlingelOben", "Klingel Oben", 'first_floor'), DeviceInfo("Klingel Innen", "Klingel Innentür", 'other'), DeviceInfo("Klingel Aussen", "Klingel Außentür", 'other'), # Tueroeffner DeviceInfo("Tueroeffner", "Türöffner Gartentür", 'other'), ] scene_button_names = ['ObenLinks', 'ObenRechts', 'MitteLinks', 'MitteRechts', 'UntenLinks', 'UntenRechts'] scene_button_names = [(i, e) for i, e in enumerate(scene_button_names)] switches += [DeviceInfo(f"SzeneEsszimmer{n}", f"Esszimmer Szene {i}") for i, n in scene_button_names] switches += [DeviceInfo(f"SzeneWohnzimmer{n}", f"Wohnzimmer Szene {i}") for i, n in scene_button_names] switches += [DeviceInfo(f"SzeneEingang{n}", f"Eingang Szene {i}") for i, n in scene_button_names[2:]] switches += [DeviceInfo(f"SzeneTerrassentuer{n}", f"Wohnzimmer Terrassentür Szene {i}") for i, n in scene_button_names[2: 4]] switches += [DeviceInfo("AlarmLEDLinksNormal", "alarm_led_links_normal"), DeviceInfo("AlarmLEDLinksUeberlagert", "alarm_led_links_ueberlagert"), DeviceInfo("AlarmLEDRechtsNormal", "alarm_led_rechts_normal"), DeviceInfo("AlarmLEDRechtsUeberlagert", "alarm_led_rechts_ueberlagert"), DeviceInfo("WCLicht Schalten", "wc_licht_taster"), ] power_plugs = [ # Vorratsraum DeviceInfo("VorratsraumSteckdose1", "Vorratsraum Steckdose 1", 'other'), DeviceInfo("VorratsraumSteckdose2", "Vorratsraum Steckdose 2", 'other'), DeviceInfo("VorratsraumSteckdose3", "Gefrierschrank", 'other'), # Waschraum DeviceInfo("Trockner", "Trockner", 'other'), DeviceInfo("Waschmaschine", "Waschmaschine", 'other'), # Küche DeviceInfo("KücheSteckdose1", "Küche Steckdosen rechts"), DeviceInfo("KücheSteckdose2", "Dunstabzug"), DeviceInfo("Spülmaschine", "Spülmaschine", 'living_area'), DeviceInfo("Backofen", "Backofen", 'living_area'), DeviceInfo("HerdP1", "Herd Phase 1", 'living_area'), DeviceInfo("HerdP2", "Herd Phase 2", 'living_area'), DeviceInfo("HerdP3", "Herd Phase 3", 'living_area'), # Rest DeviceInfo("ArbeitszimmerSteckdose", "Arbeitszimmer Steckdose", 'office'), DeviceInfo("WohnzimmerSteckdose1", "Wohnzimmer Steckdose 1", 'living_area'), DeviceInfo("WohnzimmerSteckdose2", "Wohnzimmer Steckdose 2", 'living_area'), # Gartenhaus steckdosen (Pumpen) DeviceInfo("Garten1", "Gartenhaus Steckdose1", 'outside'), DeviceInfo("Garten2", "Gartenhaus Steckdose2", 'outside'), ] motion_sensors = { 'sensor': [ # Brightness {'name': 'Gang Bewegungsmelder West Helligkeit', 'state_address': imported_csv['BewegungsmelderWest Helligkeit'], 'type': 'illuminance'}, {'name': 'Gang Bewegungsmelder Mitte Helligkeit', 'state_address': imported_csv['BewegungsmelderMitte Helligkeit'], 'type': 'illuminance'}, {'name': 'Gang Bewegungsmelder Ost Helligkeit', 'state_address': imported_csv['BewegungsmelderOst Helligkeit'], 'type': 'illuminance'}, # Temperature {'name': 'Esszimmer Temperatur', 'state_address': imported_csv['TemperaturEsszimmer'], 'type': 'temperature'}, {'name': 'Treppenhaus Oben Temperatur', 'state_address': imported_csv['TreppenhausObenTemperatur'], 'type': 'temperature'}, {'name': 'Eingangsbereich Temperatur', 'state_address': imported_csv['TemperaturGang'], 'type': 'temperature'}, {'name': 'Wohnzimmer Gang Temperatur', 'state_address': imported_csv['TemperaturWohnzimmerGangTuer'], 'type': 'temperature'}, {'name': 'Wohnzimmer Terassentür Temperatur', 'state_address': imported_csv['TemperaturWohnzimmerAussenTuer'], 'type': 'temperature'}, ], 'binary_sensor': [ {'name': 'Gang Bewegungsmelder Schlafzimmer', 'state_address': imported_csv['BewegungsmelderWest Motion Links'], 'device_class': 'motion'}, {'name': 'Gang Bewegungsmelder Wohnzimmer', 'state_address': imported_csv['BewegungsmelderWest Motion Rechts'], 'device_class': 'motion'}, {'name': 'Gang Bewegungsmelder Mitte', 'state_address': imported_csv['BewegungsmelderMitte Motion'], 'device_class': 'motion'}, {'name': 'Gang Bewegungsmelder Ost', 'state_address': imported_csv['BewegungsmelderOst Motion'], 'device_class': 'motion'}, {'name': 'KlingelknopfGartensaeule', 'state_address': imported_csv['KlingelknopfGartensaeule'], }, {'name': 'KlingelknopfHaustuerUnten', 'state_address': imported_csv['KlingelknopfHaustuerUnten'], }, {'name': 'KlingelknopfInnentuer', 'state_address': imported_csv['KlingelknopfInnentuer'], }, ] } knx.extent(devices, motion_sensors) knx.extent(devices, knx.create_lights(lights, imported_csv)) knx.extent(devices, knx.create_shutters(shutters, imported_csv)) knx.extent(devices, knx.create_switches(switches, imported_csv)) power_plugs, template_sensors = knx.create_power_plug(power_plugs, imported_csv) knx.extent(devices, power_plugs) for device_type, devices in [('light', lights), ('cover', shutters), ('switch', switches)]: for device in devices: add_to_group(groups, device.groups, device.display_name, device_type) return template_sensors def add_meta_groups(groups): all_devices = set() for group in groups.values(): all_devices.update(group['entities']) first_floor = set(groups['first_floor']['entities']) bedroom = set(groups['bedroom']['entities']) outside = set(groups['outside']['entities']) groups['all_downstairs'] = { 'name': 'Unten Alles', 'entities': [e for e in all_devices - first_floor] } groups['all_downstairs_but_outside'] = { 'name': 'Unten Alles Ausser Draussen', 'entities': [e for e in all_devices - first_floor - outside] } groups['all_downstairs_but_bedroom'] = { 'name': 'Unten Alles Ausser Schlafzimmer', 'entities': [e for e in all_devices - first_floor - bedroom], } groups['all_downstairs_but_bedroom_and_outside'] = { 'name': 'Unten Alles Ausser Schlafzimmer und Draussen', 'entities': [e for e in all_devices - first_floor - bedroom - outside], } def make_sensor_exclude_list(all_devices, name_fragments): exclude_list = [] def handle_sensor(s): name = s['name'] if 'name' in s else s['friendly_name'] if any(t in name for t in name_fragments): exclude_list.append(name_to_id(name, 'sensor')) for sensor_device in all_devices['sensor']: if 'platform' in sensor_device and sensor_device['platform'] == 'time_date': continue elif 'platform' in sensor_device and sensor_device['platform'] == 'template': for nested_sensor_dev in sensor_device['sensors'].values(): handle_sensor(nested_sensor_dev) elif 'platform' in sensor_device and sensor_device['platform'] == 'mqtt_room': pass elif 'name' in sensor_device: handle_sensor(sensor_device) else: raise NotImplementedError(f"Sensor {sensor_device}") return exclude_list def logbook_config(all_devices): sensor_excludes = ['Helligkeit', 'Betriebsstunden', 'Verbrauch', 'Bewegungsmelder'] exclude_list = ['binary_sensor.updater'] exclude_list.extend(sensor_exclude_list) exclude_list.extend(make_sensor_exclude_list(all_devices, sensor_excludes)) return { 'logbook': { 'exclude': { 'entities': exclude_list, 'domains': ['group', 'automation', 'group', 'scene'] } } } def recorder_config(all_devices): recorder_excludes = ['Betriebsstunden', 'Verbrauch mA'] exclude_list = ['sun.sun'] exclude_list.extend(sensor_exclude_list) exclude_list.extend(make_sensor_exclude_list(all_devices, recorder_excludes)) return { 'recorder': { 'db_url': 'mysql://homeassistant:Vc9JpSh0VQqKF1zgwdJG@core-mariadb/homeassistant?charset=utf8', 'purge_keep_days': 60, 'exclude': { 'entities': exclude_list, } } } def create_config(target_directory, development=False): groups_yaml_path = os.path.join(script_path, 'groups.yaml') manual_config_path = os.path.join(script_path, 'manual_config.yaml') group_dict = yaml.load(open(groups_yaml_path, encoding="utf-8")) manual_config_dict = yaml.load(open(manual_config_path, encoding="utf-8")) knx_conf = { #'tunneling': { # 'host': '192.168.178.65', # 'port': 3671 #} } template_sensors = add_knx_devices(knx_conf, group_dict) all_devices = {} all_devices.update(template_sensors) with open(os.path.join(target_directory, 'configuration.yaml'), 'w', encoding="utf-8") as output: output.write("# Dont' edit manually! this is generated!\n\n") for key in ['sensor', 'switch', 'light', 'cover', 'binary_sensor']: if key in manual_config_dict: if key not in all_devices: all_devices[key] = [] all_devices[key].extend(manual_config_dict[key]) del manual_config_dict[key] yaml.dump(manual_config_dict, output) yaml.dump(all_devices, output) yaml.dump(logbook_config(all_devices), output) yaml.dump(recorder_config(all_devices), output) output.write("automation manual: !include_dir_merge_list automations\n") add_meta_groups(group_dict) with open(os.path.join(target_directory, 'knx_conf.yaml'), 'w') as output: output.write("# Dont' edit manually! this is generated!\n\n") yaml.dump(knx_conf, output) with open(os.path.join(target_directory, 'groups.yaml'), 'w') as output: output.write("# Dont' edit manually! this is generated!\n\n") yaml.dump(group_dict, output) with open(os.path.join(target_directory, 'secrets.yaml'), 'w') as output: output.write("# Dont' edit manually! this is generated!\n\n") output.write(open(os.path.join(script_path, 'secrets.yaml'), 'r').read()) output.write("\n\n") additional_file = 'secrets_development.yaml' if development else 'secrets_deploy.yaml' output.write(open(os.path.join(script_path, additional_file), 'r').read()) if __name__ == '__main__': parser = argparse.ArgumentParser() parser.add_argument("-d", "--dev", help="create config file for development", action="store_true") args = parser.parse_args() create_config(target_directory=os.getcwd(), development=args.dev)