From 52442c50f1b8d654449809b7f02d5bb0dd47cc69 Mon Sep 17 00:00:00 2001 From: Martin Bauer Date: Fri, 7 Aug 2026 10:09:42 +0200 Subject: [PATCH] updates --- .HA_VERSION | 2 +- .gitignore | 1 + automations.yaml | 414 ++++++++++-------- config_creation/main.py | 54 ++- config_creation/manual_config.yaml | 42 +- custom_components/cover_half/__init__.py | 2 + .../squeezebox_telnet/media_player.py | 39 +- influx.yaml | 21 + make_config.sh | 4 +- pyscript/ios_actions.py | 61 ++- pyscript/knx_buttons.py | 36 +- pyscript/modules/ir_helpers.py | 10 +- scenes.yaml | 383 ++++++++++++++++ scenes/wohnbereich.yaml | 4 +- scripts.yaml | 6 +- 15 files changed, 827 insertions(+), 252 deletions(-) create mode 100644 influx.yaml diff --git a/.HA_VERSION b/.HA_VERSION index 9174360..2398eb2 100644 --- a/.HA_VERSION +++ b/.HA_VERSION @@ -1 +1 @@ -2024.5.0 \ No newline at end of file +2026.7.2 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 1dbcfc6..f2bf6bc 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,4 @@ node_modules /themes /node-red /.storage/hacs/*.hacs +/.cache \ No newline at end of file diff --git a/automations.yaml b/automations.yaml index d1e008f..6065bf7 100644 --- a/automations.yaml +++ b/automations.yaml @@ -44,21 +44,22 @@ - id: '1589377976830' alias: Alarm Martin Handy description: '' - trigger: + triggers: - entity_id: binary_sensor.gang_bewegungsmelder_schlafzimmer, binary_sensor.gang_bewegungsmelder_ost, binary_sensor.gang_bewegungsmelder_mitte from: 'off' - platform: state to: 'on' - condition: [] - action: - - service: notify.mobile_app_iphone_von_martin + trigger: state + conditions: [] + actions: + - action: notify.mobile_app_iphone16_von_martin data: message: Bewegung im Gang + title: Alarm - data: message: Bewegung im Gang title: Alarm - service: notify.mobile_app_martins_ipad + action: notify.mobile_app_martins_ipad - delay: hours: 0 minutes: 2 @@ -68,94 +69,79 @@ - id: '1598594894559' alias: KlingelknopfGartensäuleAufMobileGeräte description: Push Notification auf Martin Handy, Rebecca Handy und iPad - trigger: + triggers: - entity_id: - binary_sensor.klingelknopfgartensaeule from: 'off' - platform: state to: 'on' - condition: [] - action: - - service: notify.mobile_app_iphone_von_martin + trigger: state + conditions: [] + actions: + - action: notify.mobile_app_iphone_von_rebecca metadata: {} data: message: Jemand hat an der Briefkastensäule geklingelt title: "\U0001F514\U0001F4EA Klingel" - - service: notify.mobile_app_rebeccahandysamsung + - action: notify.mobile_app_martin_ipadprom4 metadata: {} data: message: Jemand hat an der Briefkastensäule geklingelt title: "\U0001F514\U0001F4EA Klingel" - - service: notify.mobile_app_martins_ipad + - action: notify.mobile_app_martin_iphonepro16 metadata: {} data: - title: "\U0001F514\U0001F4EA Klingel" message: Jemand hat an der Briefkastensäule geklingelt + title: "\U0001F514\U0001F4EA Klingel" mode: single - id: '1606655282153' - alias: Weihnachtslichter an morgens um 6 + alias: Weihnachtslichter an morgens um 7 description: '' - trigger: - - platform: time - at: 06:00 - condition: [] - action: - - service: switch.turn_on - data: {} - entity_id: - - switch.tasmota02 - - switch.tasmota04 - - switch.tasmota05 - - switch.tasmota06 + triggers: + - at: 07:00:00 + trigger: time + conditions: [] + actions: + - data: {} + entity_id: switch.weihnachtslichter_unten + action: switch.turn_on mode: single - id: '1607412098745' alias: Weihnachtslichter aus morgens description: '' - trigger: - - platform: sun - event: sunrise - offset: 00:15:00 - condition: [] - action: - - service: switch.turn_off - data: {} - entity_id: - - switch.tasmota02 - - switch.tasmota04 - - switch.tasmota05 - - switch.tasmota06 + triggers: + - event: sunrise + offset: 00:20:00 + trigger: sun + conditions: [] + actions: + - data: {} + entity_id: switch.weihnachtslichter_unten + action: switch.turn_off mode: single - id: '1607412144113' alias: Weihnachtslichter An Abends description: '' - trigger: - - platform: sun - event: sunset - condition: [] - action: - - service: switch.turn_on - data: {} - entity_id: - - switch.tasmota02 - - switch.tasmota04 - - switch.tasmota05 - - switch.tasmota06 + triggers: + - event: sunset + trigger: sun + offset: -00:20:00 + conditions: [] + actions: + - data: {} + entity_id: switch.weihnachtslichter_unten + action: switch.turn_on mode: single - id: '1607412210097' alias: Weihnachtslichter Aus Abends description: '' - trigger: - - platform: time - at: '22:30' - condition: [] - action: - - service: switch.turn_off - data: {} - entity_id: - - switch.tasmota02 - - switch.tasmota04 - - switch.tasmota05 - - switch.tasmota06 + triggers: + - at: '22:45:00' + trigger: time + conditions: [] + actions: + - data: {} + entity_id: switch.weihnachtslichter_unten + action: switch.turn_off mode: single - id: '1612028092169' alias: Bewegungsmelder Schlafzimmer Nacht @@ -194,23 +180,27 @@ entity_id: light.bett_martin, light.bett_rebecca mode: single - id: '1632393568599' - alias: Herd vorgeheizt -> iPad + alias: Herd vorgeheizt -> iPhoneMartin description: '' - trigger: - - platform: numeric_state - entity_id: sensor.backofen_verbrauch + triggers: + - entity_id: sensor.backofen_verbrauch below: '20' for: hours: 0 minutes: 0 seconds: 5 milliseconds: 0 - condition: [] - action: - - service: notify.mobile_app_martins_ipad + trigger: numeric_state + conditions: [] + actions: + - action: notify.mobile_app_martin_iphonepro16 + metadata: {} data: - title: Herd vorgeheizt - message: herd ist heiss :) + message: Herd ist heiss + - action: notify.mobile_app_martin_ipadprom4 + metadata: {} + data: + message: Herd ist heiss mode: single - id: '1633435293611' alias: Gang Bogen Nachtlicht @@ -263,7 +253,7 @@ description: '' trigger: - platform: time - at: 02:00:00 + at: 04:00:00 condition: [] action: - service: cover.close_cover @@ -276,123 +266,104 @@ - id: '1669014477577' alias: Weihnachtslichter oben 01 morgens an um 7 description: '' - trigger: - - platform: time - at: 07:00:00 - condition: [] - action: - - service: switch.turn_on - data: {} + triggers: + - at: 07:00:00 + trigger: time + conditions: [] + actions: + - data: {} + action: switch.turn_on target: - entity_id: switch.tasmota06 + entity_id: switch.tasmota01 mode: single - id: '1669014568292' alias: Weihnachtslichter oben 02 morgens aus um 9 description: '' - trigger: - - platform: time - at: 09:00:00 - condition: [] - action: - - service: switch.turn_off - data: {} + triggers: + - at: 09:00:00 + trigger: time + conditions: [] + actions: + - data: {} + action: switch.turn_off target: - entity_id: switch.tasmota06 + entity_id: switch.tasmota01 mode: single - id: '1669014612655' alias: Weihnachtslichter oben 03 abends an 16:30 description: '' - trigger: - - platform: time - at: '16:30:00' - condition: [] - action: - - service: switch.turn_on - data: {} + triggers: + - at: '16:30:00' + trigger: time + conditions: [] + actions: + - data: {} + action: switch.turn_on target: - entity_id: switch.tasmota06 + entity_id: switch.tasmota01 mode: single - id: '1669014682496' alias: Weihnachtslichter oben 04 abends aus 22:00 description: '' - trigger: - - platform: time - at: '22:00:00' - condition: [] - action: - - service: switch.turn_off - data: {} + triggers: + - at: '22:00:00' + trigger: time + conditions: [] + actions: + - data: {} + action: switch.turn_off target: - entity_id: switch.tasmota06 + entity_id: switch.tasmota01 mode: single - id: '1693231134539' - alias: Pool Pumpe ein um 9 und 17 Uhr + alias: 'Pool Pumpe ein: 5:00, 20:30' description: '' - trigger: - - platform: time - at: 09:00:00 - - platform: time - at: '17:00:00' - condition: [] - action: - - service: switch.turn_on - data: {} + triggers: + - at: 05:00:00 + trigger: time + - at: '20:30:00' + trigger: time + conditions: [] + actions: + - data: {} target: entity_id: switch.poolpumpe_speed1 + action: switch.turn_on - delay: hours: 0 minutes: 0 seconds: 2 milliseconds: 0 - - service: switch.turn_off - data: {} + - data: {} target: entity_id: switch.poolpumpe_speed1 + action: switch.turn_off mode: single - id: '1693231202553' - alias: Pool Pumpe aus um 10:15 und 18:15 + alias: Pool Pumpe aus 8:00, 22:30, 1:00 description: '' - trigger: - - platform: time - at: '10:15:00' - - platform: time - at: '18:15:00' - condition: [] - action: - - service: switch.turn_on - data: {} + triggers: + - at: 08:00:00 + trigger: time + - at: '22:30:00' + trigger: time + - trigger: time + at: 01:00:00 + conditions: [] + actions: + - data: {} target: entity_id: switch.poolpumpe_speed_off + action: switch.turn_on - delay: hours: 0 minutes: 0 - seconds: 2 + seconds: 5 milliseconds: 0 - - service: switch.turn_off - data: {} + - data: {} target: entity_id: switch.poolpumpe_speed_off - mode: single -- id: '1693845791544' - alias: Sprinkler alle 2 stunden - description: Sprinkler an für 3 minuten um 10,12,14,16,18,20 Uhr - trigger: - - platform: time - at: - - '10:00:00' - - '11:00:00' - - '12:00:00' - - '13:00:00' - - '14:00:00' - - '15:00:00' - - '16:00:00' - - '18:00:00' - - '20:00:00' - condition: [] - action: - - service: script.sprinkler_an_5_minuten - data: - minutes: 3 + action: switch.turn_off mode: single - id: '1693849132880' alias: Eingangslichter Beet an wenn Haustur licht an @@ -557,7 +528,7 @@ description: '' trigger: - platform: time - at: '22:00:00' + at: 00:30:00 condition: [] action: - service: switch.turn_off @@ -638,25 +609,25 @@ - id: '1709737843307' alias: KlingelknopfHaustuerUntenAufMobileGeräte description: Push Notification auf Martin Handy, Rebecca Handy und iPad - trigger: + triggers: - entity_id: - binary_sensor.klingelknopfhaustuerunten from: 'off' - platform: state to: 'on' - condition: [] - action: - - service: notify.mobile_app_iphone_von_martin + trigger: state + conditions: [] + actions: + - action: notify.mobile_app_iphone_von_rebecca metadata: {} data: message: Jemand hat an der Haustür unten geklingelt title: "\U0001F514 \U0001F6AA Klingel" - - service: notify.mobile_app_rebeccahandysamsung + - action: notify.mobile_app_martin_ipadprom4 metadata: {} data: message: Jemand hat an der Haustür unten geklingelt title: "\U0001F514 \U0001F6AA Klingel" - - service: notify.mobile_app_martins_ipad + - action: notify.mobile_app_martin_iphonepro16 metadata: {} data: title: "\U0001F514 \U0001F6AA Klingel" @@ -665,22 +636,123 @@ - id: '1709738037256' alias: KlingelknopfInnentürAufMobileGeräte description: Push Notification auf Martin Handy und iPad - trigger: + triggers: - entity_id: - binary_sensor.klingelknopfinnentuer from: 'off' - platform: state to: 'on' + trigger: state + conditions: [] + actions: + - action: notify.mobile_app_iphone_von_rebecca + metadata: {} + data: + message: Jemand hat an der Innentür geklingelt + title: Klingel Innen + - action: notify.mobile_app_martin_iphonepro16 + metadata: {} + data: + message: Jemand hat an der Innentür geklingelt + title: Klingel Innen + mode: single +- id: '1715632353191' + alias: Kinderzimmer Rollo zu um 4 nachts + description: '' + trigger: + - platform: time + at: 04:00:00 condition: [] action: - - service: notify.mobile_app_iphone_von_martin + - service: cover.close_cover metadata: {} - data: - message: Jemand hat an der Innentür geklingelt - title: "\U0001F56D Klingel Innen" - - service: notify.mobile_app_martins_ipad - metadata: {} - data: - title: "\U0001F56D Klingel Innen" - message: Jemand hat an der Innentür geklingelt + data: {} + target: + entity_id: cover.kinderzimmer_rollo + mode: single +- id: '1718390440758' + alias: Sprinkler Beet West aus 4min + description: '' + use_blueprint: + path: homeassistant/auto_off.yaml + input: + the_device: switch.ventil_beet_west + duration_until_off: + hours: 0 + minutes: 3 + seconds: 0 +- id: '1718390486813' + alias: Beete Eingang & Hochbeet Tropfschlauch nach 15min + description: '' + use_blueprint: + path: homeassistant/auto_off.yaml + input: + the_device: switch.ventil_giessanlage_vorne + duration_until_off: + hours: 0 + minutes: 15 + seconds: 0 +- id: '1721931988033' + alias: Sprinkler Beet Süd aus 4min + description: '' + use_blueprint: + path: homeassistant/auto_off.yaml + input: + duration_until_off: + hours: 0 + minutes: 3 + seconds: 0 + the_device: switch.ventil_beet_sued +- id: '1786086669295' + alias: Giessanlage um 21:30 + description: '' + triggers: + - trigger: time + at: '21:30:00' + conditions: [] + actions: + - action: switch.turn_on + metadata: {} + target: + entity_id: switch.ventil_sprinkler_sud + data: {} + - delay: + hours: 0 + minutes: 7 + seconds: 0 + milliseconds: 0 + - action: switch.turn_off + metadata: {} + target: + entity_id: switch.ventil_sprinkler_sud + data: {} + - action: switch.turn_on + metadata: {} + target: + entity_id: switch.ventil_giessanlage_vorne + data: {} + - delay: + hours: 0 + minutes: 15 + seconds: 0 + milliseconds: 0 + - action: switch.turn_off + metadata: {} + target: + entity_id: switch.ventil_giessanlage_vorne + data: {} + - action: switch.turn_on + metadata: {} + target: + entity_id: switch.ventil_beet_sued + data: {} + - delay: + hours: 0 + minutes: 5 + seconds: 0 + milliseconds: 0 + - action: switch.turn_off + metadata: {} + target: + entity_id: switch.ventil_beet_sued + data: {} mode: single diff --git a/config_creation/main.py b/config_creation/main.py index 3b68ed2..7cc2b66 100644 --- a/config_creation/main.py +++ b/config_creation/main.py @@ -263,6 +263,40 @@ def recorder_config(all_devices): } +def merge_configs(base_config, override_config): + """ + Merge two configuration dictionaries by combining list-type entries. + + For keys that exist in both configs and have list values in override_config, + the lists are concatenated. If base_config has a dict value for that key, + it's first converted to a single-element list before extending. + + Keys with list values are moved from override_config to base_config. + Non-list entries in override_config remain unchanged. + + Args: + base_config: The base configuration dict to merge into (modified in place) + override_config: The override configuration dict (list entries are removed) + + Returns: + tuple: (base_config, override_config) after merging + """ + keys_to_merge = [] + for key in override_config: + if isinstance(override_config[key], list): + keys_to_merge.append(key) + for key in keys_to_merge: + override_value = override_config[key] + if key not in base_config: + base_config[key] = [] + # Handle case where base_config[key] is a dict (convert to list first) + if isinstance(base_config[key], dict): + base_config[key] = [base_config[key]] + base_config[key].extend(override_value) + del override_config[key] + return base_config, override_config + + 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') @@ -282,12 +316,20 @@ def create_config(target_directory, development=False): 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] + # Merge list-type configurations from manual_config into all_devices + keys_to_merge = [] + for key in manual_config_dict: + if isinstance(manual_config_dict[key], list): + keys_to_merge.append(key) + for key in keys_to_merge: + manual_value = manual_config_dict[key] + if key not in all_devices: + all_devices[key] = [] + # Handle case where all_devices[key] is a dict (convert to list first) + if isinstance(all_devices[key], dict): + all_devices[key] = [all_devices[key]] + all_devices[key].extend(manual_value) + del manual_config_dict[key] yaml.dump(manual_config_dict, output) yaml.dump(all_devices, output) yaml.dump(logbook_config(all_devices), output) diff --git a/config_creation/manual_config.yaml b/config_creation/manual_config.yaml index 045ac45..bfd0c9b 100644 --- a/config_creation/manual_config.yaml +++ b/config_creation/manual_config.yaml @@ -9,7 +9,7 @@ person: sun: system_health: #logbook: - + input_boolean: input_datetime: input_number: @@ -178,7 +178,7 @@ ios: color: "#ffffff" show_in_carplay: false show_in_watch: true - - name: schlafzimmer_bett_bringen + - name: schlafzimmer_bett_bringen background_color: "#6D4C41" label: text: "Schlafzimmer Bett bringen" @@ -366,7 +366,7 @@ homekit: - light.wohnzimmer_deckenlampe - light.kuche_deckenlampe - light.esszimmer_deckenlampe_west - - light.esszimmer_deckenlampe_mitte + - light.esszimmer_deckenlampe_mitte - cover.wohnzimmer_fenster_rollo - cover.wohnzimmer_terrassentur_rollo - cover.kuche_fenster_rollo @@ -430,6 +430,10 @@ homekit: - cover.kinderzimmer_rollo - light.music_mouse_regal_licht - light.kinderzimmer_fluter + # -- Arbeitszimmer Oben + - light.arbeitszimmer_oben_fluter + - cover.arbeitszimmer_oben_rollo_ost + - cover.arbeitszimmer_oben_rollo_west #google_assistant: # project_id: homeassistant-d3afc @@ -521,7 +525,7 @@ sysdweb: services: - lircd - squeezelite - - shairport-sync + - shairport-sync - dht22_sensing - host: bedroompi.fritz.box port: 10080 @@ -530,7 +534,7 @@ sysdweb: services: - lircd - squeezelite - - shairport-sync + - shairport-sync - dht22_sensing #- host: esszimmerradio.fritz.box # port: 10080 @@ -539,7 +543,7 @@ sysdweb: # services: # - lircd # - squeezelite -# - shairport-sync +# - shairport-sync # - sispmctl - host: musikserverwohnzimmeroben.fritz.box port: 10080 @@ -548,9 +552,9 @@ sysdweb: services: - irserver - squeezelite - - shairport-sync + - shairport-sync #- dht22_sensing - - logitechmediaserver + - logitechmediaserver lirc_network: - host: kitchenpi.fritz.box @@ -566,7 +570,7 @@ lirc_network: binary_sensor: - platform: lirc_network # sensor to show for each host if it is currently connected - - platform: sysdweb + - platform: sysdweb - platform: ffmpeg_noise input: rtsp://camera:1238djie!d24yu@babycamera:554/stream2 extra_arguments: -filter:a highpass=f=300,lowpass=f=2500,volume=volume=2 @@ -578,12 +582,12 @@ media_player: - platform: squeezebox_telnet host: server.fritz.box - platform: squeezebox_telnet - host: musikserverWohnzimmerOben.fritz.box + host: musikserverWohnzimmerOben.fritz.box template: - sensor: - - default_entity_id: motion_combined - friendly_name: Bewegung + - unique_id: motion_combined + name: Bewegung state: > {%- set pirs = {'Gang Mitte': states.binary_sensor.gang_bewegungsmelder_mitte, 'Eingang': states.binary_sensor.gang_bewegungsmelder_ost, @@ -594,8 +598,8 @@ template: {{ pir_name }} {% endif %} {% endfor %} - - default_entity_id: oxilife_ph_filtered - friendly_name: Oxilify pH Filtered + - unique_id: oxilife_ph_filtered + name: Oxilify pH Filtered unit_of_measurement: "{{ states.sensor.oxilife_ph.attributes.unit_of_measurement }}" state: > {% if 200 <= states('sensor.gartenhaus_steckdose2_verbrauch') | float %} @@ -603,8 +607,8 @@ template: {% else %} unknown {% endif %} - - default_entity_id: oxilife_redox_level_filtered - friendly_name: Oxilify Redox Filtered + - unique_id: oxilife_redox_level_filtered + name: Oxilify Redox Filtered unit_of_measurement: "{{ states.sensor.oxilife_redox_level.attributes.unit_of_measurement }}" state: > {% if 200 <= states('sensor.gartenhaus_steckdose2_verbrauch') | float %} @@ -612,8 +616,8 @@ template: {% else %} unknown {% endif %} - - default_entity_id: pool_temperatur_filtered - friendly_name: Oxilify Temperature Filtered + - unique_id: pool_temperatur_filtered + name: Oxilify Temperature Filtered unit_of_measurement: "{{ states.sensor.pool_temperatur.attributes.unit_of_measurement }}" state: > {% if 200 <= states('sensor.gartenhaus_steckdose2_verbrauch') | float %} @@ -760,5 +764,3 @@ light: entities: - light.arbeitszimmer_oben_fluter_hinten - light.arbeitszimmer_oben_fluter_vorne - - diff --git a/custom_components/cover_half/__init__.py b/custom_components/cover_half/__init__.py index 97bc362..797eae5 100644 --- a/custom_components/cover_half/__init__.py +++ b/custom_components/cover_half/__init__.py @@ -35,6 +35,8 @@ async def async_setup(hass, config): async def async_set_half_service(service): entity_ids = await async_extract_entity_ids(hass, service, expand_group=True) for entity_id in entity_ids: + if not entity_id.startswith(f"{COVER_DOMAIN}."): + continue data = { ATTR_ENTITY_ID: entity_id, ATTR_POSITION: hass.states.get(entity_id).attributes.get(ATTR_HALF_POSITION, 20) diff --git a/custom_components/squeezebox_telnet/media_player.py b/custom_components/squeezebox_telnet/media_player.py index 957f32b..ed2f6c3 100644 --- a/custom_components/squeezebox_telnet/media_player.py +++ b/custom_components/squeezebox_telnet/media_player.py @@ -9,14 +9,8 @@ from ..reconnecting_client import ReconnectingClient from .radio import find_local_radio_url_by_name, fill_station_cache_async from homeassistant.components.media_player import ( - MediaPlayerEntity, PLATFORM_SCHEMA) -from homeassistant.components.media_player.const import ( - ATTR_MEDIA_ENQUEUE, DOMAIN, MEDIA_TYPE_MUSIC, - SUPPORT_CLEAR_PLAYLIST, SUPPORT_NEXT_TRACK, SUPPORT_PAUSE, - SUPPORT_PLAY, SUPPORT_PLAY_MEDIA, SUPPORT_PREVIOUS_TRACK, SUPPORT_SEEK, - SUPPORT_SHUFFLE_SET, SUPPORT_REPEAT_SET, SUPPORT_TURN_OFF, SUPPORT_TURN_ON, - SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_SET, REPEAT_MODE_ALL, REPEAT_MODE_OFF, - REPEAT_MODE_ONE,) + MediaPlayerEntity, PLATFORM_SCHEMA, MediaType, RepeatMode, ATTR_MEDIA_ENQUEUE) +from homeassistant.components.media_player.const import DOMAIN from homeassistant.const import ( ATTR_COMMAND, CONF_HOST, CONF_PASSWORD, CONF_PORT, CONF_USERNAME, ATTR_ENTITY_ID, STATE_IDLE, STATE_OFF, STATE_PAUSED, STATE_PLAYING) @@ -28,10 +22,6 @@ _LOGGER = logging.getLogger(__name__) DEFAULT_PORT = 9090 -SUPPORT_SQUEEZEBOX = SUPPORT_PAUSE | SUPPORT_VOLUME_SET | \ - SUPPORT_VOLUME_MUTE | SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK | \ - SUPPORT_SEEK | SUPPORT_TURN_ON | SUPPORT_TURN_OFF | SUPPORT_PLAY_MEDIA | \ - SUPPORT_PLAY | SUPPORT_SHUFFLE_SET | SUPPORT_CLEAR_PLAYLIST | SUPPORT_REPEAT_SET PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ vol.Required(CONF_HOST): cv.string, @@ -255,6 +245,23 @@ class LogitechMediaServer(ReconnectingClient): class SqueezeBoxDevice(MediaPlayerEntity): """Representation of a SqueezeBox device.""" + _attr_supported_features = ( + MediaPlayerEntityFeature.PAUSE + | MediaPlayerEntityFeature.VOLUME_SET + | MediaPlayerEntityFeature.VOLUME_MUTE + | MediaPlayerEntityFeature.PREVIOUS_TRACK + | MediaPlayerEntityFeature.NEXT_TRACK + | MediaPlayerEntityFeature.SEEK + | MediaPlayerEntityFeature.TURN_ON + | MediaPlayerEntityFeature.TURN_OFF + | MediaPlayerEntityFeature.PLAY_MEDIA + | MediaPlayerEntityFeature.PLAY + | MediaPlayerEntityFeature.REPEAT_SET + | MediaPlayerEntityFeature.SHUFFLE_SET + | MediaPlayerEntityFeature.CLEAR_PLAYLIST + | MediaPlayerEntityFeature.STOP + ) + def __init__(self, lms, playerid, name, **attributes): """Initialize the SqueezeBox device.""" super(SqueezeBoxDevice, self).__init__() @@ -362,7 +369,7 @@ class SqueezeBoxDevice(MediaPlayerEntity): @property def media_content_type(self): """Content type of current playing media.""" - return MEDIA_TYPE_MUSIC + return MediaType.MUSIC @property def media_duration(self): @@ -446,11 +453,11 @@ class SqueezeBoxDevice(MediaPlayerEntity): def repeat(self): repeat_status = self._status.get('playlist repeat', 0) if repeat_status == 1: - return REPEAT_MODE_ONE + return RepeatMode.ONE elif repeat_status == 2: - return REPEAT_MODE_ALL + return RepeatMode.ALL else: - return REPEAT_MODE_OFF + return RepeatMode.OFF def set_repeat(self, repeat: str) -> None: """Set repeat mode.""" diff --git a/influx.yaml b/influx.yaml new file mode 100644 index 0000000..ed50dc8 --- /dev/null +++ b/influx.yaml @@ -0,0 +1,21 @@ +default_measurement: state +tags_attributes: + - unit_of_measurement +exclude: + entities: + - sensor.zone_presets # valetudo zones + - homematic.raspberrymatic + - sun.sun + entity_globs: + - sensor.*_sim_* # sim card info from mobile app + - sensor.*geokodierter* + - sensor.*geocoded* + - sensor.fritz_box* +ignore_attributes: + - BSSID + - Battery Level + - Carrier ID + - Carrier Name + - Cellular Technology + - Free internal storage + - last_knx_update diff --git a/make_config.sh b/make_config.sh index 014f0cc..ae5c99a 100755 --- a/make_config.sh +++ b/make_config.sh @@ -1,4 +1,6 @@ #!/bin/bash -python3 config_creation/main.py +apk add py3-slugify py3-ruamel + +python config_creation/main.py diff --git a/pyscript/ios_actions.py b/pyscript/ios_actions.py index e71a099..d819355 100644 --- a/pyscript/ios_actions.py +++ b/pyscript/ios_actions.py @@ -35,7 +35,7 @@ def kz_regal_scenes(): entity = "light.music_mouse_regal_licht" def fade_out_f(rgb_color, seconds): - return multiple_f(cover_f("close_cover", "cover_kinderzimmer_rollo"), + return multiple_f(cover_f("close_cover", "cover.kinderzimmer_rollo"), light_f("turn_on", entity, brightness=250, rgb_color=rgb_color, effect="side_0.5"), light_f("turn_on", entity, brightness= 10, rgb_color=rgb_color, effect="side_0.5_inc4", transition=int(0.8 * seconds)), light_f("turn_on", entity, brightness= 10, rgb_color=rgb_color, effect="side_0.2_inc8", transition=int(0.2 * seconds))), @@ -46,7 +46,7 @@ def kz_regal_scenes(): fade_out_f([255, 98, 231], 10 * 60), light_f("turn_off", entity) ] - else: + else: scenes = [ light_f("turn_on", entity, brightness=250, rgb_color=[255, 182, 41], effect="static"), light_f("turn_on", entity, brightness=250, rgb_color=[255, 98, 231], effect="static"), @@ -154,8 +154,10 @@ def on_ios_action_fired(actionName, **kwargs): if actionName == "az_oben_licht": scene_helper(az_oben_licht_scenes) elif actionName == "kz_regal": + log.info("KZ Regal action fired") scene_helper(kz_regal_scenes) elif actionName == "az_unten_licht": + log.info("AZ unten Licht action fired") scene_helper(az_unten_licht_scenes) elif actionName == "wz_deckenlampe": scene_helper(wz_deckenlampe) @@ -205,17 +207,52 @@ def on_ios_shortcut_event(room, action, device, **kwargs): elif action == "hass_cover_half": cover_half.set_half(entity_id="cover.arbeitszimmer_rollo") + if room in ("küche", "esszimmer", "sofa", "wohnzimmer"): + if action == "hass_light_off": + light_f('turn_off', "group.living_area")() + elif action == "hass_light_orange": + scene_f("wohnbereich_orange")() + elif action == "hass_light_blue": + scene_f("wohnbereich_blau_grun")() + elif action == "hass_light_bright": + scene_f("wohnbereich_hell")() + elif action == "hass_light_darken": + dimmer.dim(entity_id="group.living_area", offset=-80) + elif action == "hass_light_brighten": + dimmer.dim(entity_id="group.living_area", offset=80) + elif action == "hass_light_off": + light.turn_off(entity_id="group.living_area") + elif action == "hass_cover_open": + cover.open_cover(entity_id="group.living_area") + elif action == "hass_cover_close": + cover.close_cover(entity_id="group.living_area") + elif action == "hass_cover_half": + cover_half.set_half(entity_id="group.living_area") + elif action == "hass_sun_blinds": + cover_half.set_half(entitiy_id="cover.wohnzimmer_fenster_rollo") + + if room == "kinderzimmer": + if action == "hass_cover_open": + cover.open_cover(area_id="kinderzimmer") + elif action == "hass_cover_close": + cover.close_cover(area_id="kinderzimmer") + if room == "buero_oben": - entity = "scene.arbeitszimmer_orange" if action == "hass_light": scene_helper(az_oben_licht_scenes) - elif action == "hass_light_orange": - light_f("turn_on", entity, color_temp=470, brightness=100)() - elif action == "hass_light_blue": - light_f("turn_on", entity, color_temp=180, brightness=230)() - elif action == "hass_light_darken": - dimmer.dim(entity_id=entity, offset=-30) - elif action == "hass_light_brighten": - dimmer.dim(entity_id=entity, offset=30) elif action == "hass_light_off": - light.turn_off(entity_id=entity) \ No newline at end of file + light.turn_off(entity_id="light.arbeitszimmer_oben_fluter") + elif action == "hass_light_orange": + scene_f("arbeitszimmer_oben_orange")() + elif action == "hass_light_blue": + scene_f("arbeitszimmer_oben_blau")() + elif action == "hass_light_darken": + dimmer.dim(entity_id="light.arbeitszimmer_oben_fluter", offset=-80) + elif action == "hass_light_brighten": + dimmer.dim(entity_id="light.arbeitszimmer_oben_fluter", offset=80) + elif action == "hass_light_off": + light.turn_off(entity_id="light.arbeitszimmer_oben_fluter") + elif action == "hass_cover_open": + cover.open_cover(area_id="arbeitszimmeroben") + elif action == "hass_cover_close": + cover.close_cover(area_id="arbeitszimmeroben") diff --git a/pyscript/knx_buttons.py b/pyscript/knx_buttons.py index e3ba6ca..d340187 100644 --- a/pyscript/knx_buttons.py +++ b/pyscript/knx_buttons.py @@ -71,15 +71,17 @@ def esszimmer_gangtuer(entity_id=None, event_type=None): covers = ['group.living_area'] if key == "arrow_down": - if long_click: - vacuum("Esszimmer") - else: - cover_half.set_half(entity_id=covers) + cover_half.set_half(entity_id=covers) + #if long_click: + # vacuum("Esszimmer") + #else: + # cover_half.set_half(entity_id=covers) elif key == "arrow_up": - if long_click: - vacuum("Küche") - else: - cover.open_cover(entity_id=covers) + cover.open_cover(entity_id=covers) + #if long_click: + # vacuum("Küche") + #else: + # cover.open_cover(entity_id=covers) elif key == "bulb_orange": if long_click: scene.kuche_essbereich_orange.turn_on() @@ -114,15 +116,17 @@ def wohnzimmer_gangtur(entity_id=None, event_type=None): covers = ['group.living_area'] if key == "arrow_down": - if long_click: - vacuum("Wohnzimmer") - else: - cover_half.set_half(entity_id=covers) + cover_half.set_half(entity_id=covers) + #if long_click: + # vacuum("Wohnzimmer") + #else: + # cover_half.set_half(entity_id=covers) elif key == "arrow_up": - if long_click: - vacuum("Wohnzimmer") - else: - cover.open_cover(entity_id=covers) + cover.open_cover(entity_id=covers) + #if long_click: + # vacuum("Wohnzimmer") + #else: + # cover.open_cover(entity_id=covers) elif key == "bulb_orange": if long_click: scene.wohnzimmer_orange.turn_on() diff --git a/pyscript/modules/ir_helpers.py b/pyscript/modules/ir_helpers.py index b324682..ee4025a 100644 --- a/pyscript/modules/ir_helpers.py +++ b/pyscript/modules/ir_helpers.py @@ -61,6 +61,8 @@ def cover_half_f(entity_id): def light_f(name, entity_id, **kwargs): + if 'color_temp' in kwargs: + kwargs['color_temp_kelvin'] = round(1_000_000 / kwargs.pop('color_temp')) async def f(): await hass.services.async_call('light', name, {'entity_id': entity_id, **kwargs}) return f @@ -133,7 +135,7 @@ class CyclicCounter: -TIMEOUT_REPEAT_PRESS = 5 # time to switch states when pressed shortly in sequence, in seconds +TIMEOUT_REPEAT_PRESS = 3 # time to switch states when pressed shortly in sequence, in seconds # --------------------------------- Helper functions ---------------------------------------------------- @@ -144,7 +146,7 @@ def scene_helper(scene_function): Otherwise light is toggled""" unique_name_for_globals = id(scene_function) is_on_func, scenes = scene_function() - last_called, call_idx = light_scene_helper_dict.get(unique_name_for_globals, (datetime.now(), -1)) + last_called, call_idx = light_scene_helper_dict.get(unique_name_for_globals, (datetime.now(), -1)) now = datetime.now() time_since_last_call = now - last_called recently_called = (time_since_last_call < timedelta(seconds=TIMEOUT_REPEAT_PRESS)) @@ -161,8 +163,8 @@ def scene_helper(scene_function): elif not light_already_on: scenes[0]() call_idx = 0 - else: + else: idx = call_idx % len(scenes) scenes[idx]() - light_scene_helper_dict[unique_name_for_globals] = (now, call_idx) \ No newline at end of file + light_scene_helper_dict[unique_name_for_globals] = (now, call_idx) diff --git a/scenes.yaml b/scenes.yaml index b6e3a09..8b67a30 100644 --- a/scenes.yaml +++ b/scenes.yaml @@ -922,3 +922,386 @@ entity_only: true light.gartenhaus_wandlicht: entity_only: true +- id: '1736186099938' + name: Kinderzimmer Regal Dunkel + entities: + light.music_mouse_regal_licht: + effect_list: + - static + - circular + - wipeup + - twocolor + - twocolorrandom + - side_0.2 + - side_0.5 + - side_0.2_inc4 + - side_0.2_inc8 + - side_0.5_inc4 + - top_0.2 + - top_0.5 + - top_0.2_inc4 + - top_0.5_inc4 + supported_color_modes: + - rgbw + effect: side_0.2_inc8 + color_mode: rgbw + brightness: 84 + hs_color: + - 19.66 + - 92.157 + rgb_color: + - 255 + - 97 + - 20 + xy_color: + - 0.643 + - 0.342 + rgbw_color: + - 255 + - 97 + - 20 + - 0 + friendly_name: Music Mouse Regal Licht + supported_features: 44 + state: 'on' + light.kinderzimmer_deckenlampe: + supported_color_modes: + - brightness + color_mode: + brightness: + id: JEQ0199674 + interface: rf + level: 0 + working: 'No' + friendly_name: kinderzimmer_deckenlampe + supported_features: 32 + state: 'off' + light.kinderzimmer_fluter: + min_color_temp_kelvin: 2000 + max_color_temp_kelvin: 6535 + min_mireds: 153 + max_mireds: 500 + effect_list: + - None + - candle + - fire + - prism + - sparkle + - opal + - glisten + - unknown + - unknown + - unknown + - unknown + - sunrise + - sunset + supported_color_modes: + - color_temp + - xy + effect: + color_mode: + brightness: + color_temp_kelvin: + color_temp: + hs_color: + rgb_color: + xy_color: + mode: normal + dynamics: none + icon: hue:beyond + friendly_name: Kinderzimmer Fluter + supported_features: 44 + state: 'off' + icon: mdi:bookshelf + metadata: + light.music_mouse_regal_licht: + entity_only: true + light.kinderzimmer_deckenlampe: + entity_only: true + light.kinderzimmer_fluter: + entity_only: true +- id: '1750279587277' + name: Gartenstimmung + entities: + light.suedseite6: + supported_color_modes: + - rgb + color_mode: rgb + brightness: 255 + hs_color: + - 321.094 + - 50.196 + rgb_color: + - 255 + - 127 + - 210 + xy_color: + - 0.42 + - 0.239 + friendly_name: Garten Rs485 Controller2 suedseite6 + supported_features: 40 + state: 'on' + light.suedseite1: + supported_color_modes: + - rgb + color_mode: rgb + brightness: 214 + hs_color: + - 53.913 + - 54.118 + rgb_color: + - 255 + - 241 + - 117 + xy_color: + - 0.425 + - 0.452 + friendly_name: Garten Rs485 Controller2 suedseite1 + supported_features: 40 + state: 'on' + light.suedseite2: + supported_color_modes: + - rgb + color_mode: rgb + brightness: 214 + hs_color: + - 53.913 + - 54.118 + rgb_color: + - 255 + - 241 + - 117 + xy_color: + - 0.425 + - 0.452 + friendly_name: Garten Rs485 Controller2 suedseite2 + supported_features: 40 + state: 'on' + light.suedseite3: + supported_color_modes: + - rgb + color_mode: rgb + brightness: 214 + hs_color: + - 64.099 + - 63.137 + rgb_color: + - 244 + - 255 + - 94 + xy_color: + - 0.41 + - 0.493 + friendly_name: Garten Rs485 Controller2 suedseite3 + supported_features: 40 + state: 'on' + light.suedseite4: + supported_color_modes: + - rgb + color_mode: rgb + brightness: 214 + hs_color: + - 67.187 + - 75.294 + rgb_color: + - 232 + - 255 + - 63 + xy_color: + - 0.406 + - 0.523 + friendly_name: Garten Rs485 Controller2 suedseite4 + supported_features: 40 + state: 'on' + light.suedseite5: + supported_color_modes: + - rgb + color_mode: rgb + brightness: 214 + hs_color: + - 54.824 + - 100 + rgb_color: + - 255 + - 233 + - 0 + xy_color: + - 0.471 + - 0.494 + friendly_name: Garten Rs485 Controller2 suedseite5 + supported_features: 40 + state: 'on' + metadata: + light.suedseite6: + entity_only: true + light.suedseite1: + entity_only: true + light.suedseite2: + entity_only: true + light.suedseite3: + entity_only: true + light.suedseite4: + entity_only: true + light.suedseite5: + entity_only: true +- id: '1773408613570' + name: arbeitszimmer_oben_orange + entities: + light.arbeitszimmer_oben_fluter_vorne: + min_color_temp_kelvin: 2000 + max_color_temp_kelvin: 6535 + effect_list: + - 'off' + - candle + - fire + - prism + - sparkle + - opal + - glisten + - underwater + - cosmos + - sunbeam + - enchant + - sunrise + - sunset + supported_color_modes: + - color_temp + - xy + effect: 'off' + color_mode: color_temp + brightness: 36 + color_temp_kelvin: 2386 + hs_color: + - 29.192 + - 76.816 + rgb_color: + - 255 + - 154 + - 59 + xy_color: + - 0.559 + - 0.389 + mode: normal + dynamics: none + icon: hue:beyond-up + friendly_name: Fluter vorne + supported_features: 44 + state: 'on' + light.arbeitszimmer_oben_fluter_hinten: + min_color_temp_kelvin: 2000 + max_color_temp_kelvin: 6535 + effect_list: + - 'off' + - candle + - fire + - prism + - sparkle + - opal + - glisten + - underwater + - cosmos + - sunbeam + - enchant + - sunrise + - sunset + supported_color_modes: + - color_temp + - xy + effect: + color_mode: + brightness: + color_temp_kelvin: + hs_color: + rgb_color: + xy_color: + mode: normal + dynamics: none + icon: hue:beyond-down + friendly_name: Fluter Hinten + supported_features: 44 + state: 'off' + metadata: {} +- id: '1773408671408' + name: arbeitszimmer_oben_blau + entities: + light.arbeitszimmer_oben_fluter_vorne: + min_color_temp_kelvin: 2000 + max_color_temp_kelvin: 6535 + effect_list: + - 'off' + - candle + - fire + - prism + - sparkle + - opal + - glisten + - underwater + - cosmos + - sunbeam + - enchant + - sunrise + - sunset + supported_color_modes: + - color_temp + - xy + effect: 'off' + color_mode: color_temp + brightness: 255 + color_temp_kelvin: 6172 + hs_color: + - 33.105 + - 5.284 + rgb_color: + - 255 + - 249 + - 242 + xy_color: + - 0.334 + - 0.336 + mode: normal + dynamics: none + icon: hue:beyond-up + friendly_name: Fluter vorne + supported_features: 44 + state: 'on' + light.arbeitszimmer_oben_fluter_hinten: + min_color_temp_kelvin: 2000 + max_color_temp_kelvin: 6535 + effect_list: + - 'off' + - candle + - fire + - prism + - sparkle + - opal + - glisten + - underwater + - cosmos + - sunbeam + - enchant + - sunrise + - sunset + supported_color_modes: + - color_temp + - xy + effect: 'off' + color_mode: color_temp + brightness: 255 + color_temp_kelvin: 5649 + hs_color: + - 28.456 + - 11.075 + rgb_color: + - 255 + - 240 + - 227 + xy_color: + - 0.349 + - 0.341 + mode: normal + dynamics: none + icon: hue:beyond-down + friendly_name: Fluter Hinten + supported_features: 44 + state: 'on' + metadata: {} diff --git a/scenes/wohnbereich.yaml b/scenes/wohnbereich.yaml index a6eb049..4bd89a4 100644 --- a/scenes/wohnbereich.yaml +++ b/scenes/wohnbereich.yaml @@ -28,12 +28,12 @@ - 0.396 light.kuche_vorne: state: true - color_temp: 477 + color_temp_kelvin: 2386 brightness: 114 light.wohnzimmer_kugel: state: true brightness: 229 - color_temp: 492 + color_temp_kelvin: 2400 light.wohnzimmer_stehlampe: state: true brightness: 191 diff --git a/scripts.yaml b/scripts.yaml index fd2114f..a8b3c79 100644 --- a/scripts.yaml +++ b/scripts.yaml @@ -218,12 +218,12 @@ pool_pumpe_schalten: roomtracker_learn_aktueller_raum: alias: 'RoomTracker Learn: Aktueller Raum' sequence: - - service: mqtt.publish - metadata: {} + - metadata: {} data: qos: '0' topic: my_btmonitor/known_room - payload_template: '{{real_room}}' + payload: '{{real_room}}' + action: mqtt.publish mode: single icon: mdi:desk fields: