From 73de8a2c6309219ec032f60d1f7fdb43acdccc38 Mon Sep 17 00:00:00 2001 From: basbruss <68892092+basbruss@users.noreply.github.com> Date: Thu, 4 Apr 2024 16:00:08 +0200 Subject: [PATCH 01/14] =?UTF-8?q?=F0=9F=94=A7=20Add=20manual=20override=20?= =?UTF-8?q?switch=20for=20adaptive=20control.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adaptive_cover/coordinator.py | 29 ++++++++++++------- custom_components/adaptive_cover/switch.py | 12 ++++++-- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/custom_components/adaptive_cover/coordinator.py b/custom_components/adaptive_cover/coordinator.py index 2be0ae8..7c1651f 100644 --- a/custom_components/adaptive_cover/coordinator.py +++ b/custom_components/adaptive_cover/coordinator.py @@ -166,20 +166,27 @@ async def _async_update_data(self) -> AdaptiveCoverData: self.config_entry.options.get(CONF_FOV_LEFT), self.config_entry.options.get(CONF_FOV_RIGHT), ], - # "manual control": self.find_manual_control, - # "states_data": self.state_change_data, + "manual control": self.find_manual_control, + "states_data": self.state_change_data, }, ) - # @property - # def find_manual_control(self): - # """.""" - # if self.state_change_data: - # if self.state_change_data.entity_id.startswith("cover."): - # return ( - # self.state_change_data.new_state.attributes["current_position"] - # != self.state - # ) + @property + def find_manual_control(self): + """Find position change other than calculated state.""" + if self.state_change_data: + if self.state_change_data.entity_id.startswith("cover."): + if self._cover_type == 'cover_tilt': + return ( + self.state_change_data.new_state.attributes["current_tilt_position"] + != self.state + ) + else: + return ( + self.state_change_data.new_state.attributes["current_position"] + != self.state + ) + async def async_handle_call_service(self): """Handle call service.""" for entity in self.entities: diff --git a/custom_components/adaptive_cover/switch.py b/custom_components/adaptive_cover/switch.py index 5d624a4..4893556 100644 --- a/custom_components/adaptive_cover/switch.py +++ b/custom_components/adaptive_cover/switch.py @@ -32,10 +32,18 @@ async def async_setup_entry( config_entry.entry_id ] + manual_switch = AdaptiveCoverSwitch( + config_entry, + config_entry.entry_id, + "Manual Override", + True, + "manual_toggle", + coordinator, + ) control_switch = AdaptiveCoverSwitch( config_entry, config_entry.entry_id, - "Toggle Control", + "Adaptive Control", True, "control_toggle", coordinator, @@ -63,7 +71,7 @@ async def async_setup_entry( switches = [] if len(config_entry.options.get(CONF_ENTITIES)) >= 1: - switches.append(control_switch) + switches=[control_switch, manual_switch] if climate_mode: switches.append(climate_switch) From 0016d7e3a9136b22af24e9288a711ddcc3055bb8 Mon Sep 17 00:00:00 2001 From: basbruss <68892092+basbruss@users.noreply.github.com> Date: Wed, 10 Apr 2024 18:17:44 +0200 Subject: [PATCH 02/14] =?UTF-8?q?=E2=9C=A8=20Add=20AdaptiveCoverManager=20?= =?UTF-8?q?class=20for=20tracking=20position=20changes.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adaptive_cover/coordinator.py | 114 +++++++++++++----- 1 file changed, 87 insertions(+), 27 deletions(-) diff --git a/custom_components/adaptive_cover/coordinator.py b/custom_components/adaptive_cover/coordinator.py index 7c1651f..f419ec0 100644 --- a/custom_components/adaptive_cover/coordinator.py +++ b/custom_components/adaptive_cover/coordinator.py @@ -3,6 +3,7 @@ from __future__ import annotations import datetime as dt +import logging from dataclasses import dataclass from homeassistant.components.cover import DOMAIN as COVER_DOMAIN @@ -65,6 +66,8 @@ get_time, ) +_LOGGER = logging.getLogger(__name__) + @dataclass class StateChangedData: @@ -98,8 +101,10 @@ def __init__(self, hass: HomeAssistant) -> None: # noqa: D107 self._inverse_state = self.config_entry.options.get(CONF_INVERSE_STATE, False) self._temp_toggle = False self._control_toggle = True + self._manual_duration = {"hours": 0, "minutes": 2, "seconds": 0} self.state_change_data: StateChangedData | None = None + self.manager = AdaptiveCoverManager(self._manual_duration) async def async_check_entity_state_change( self, entity: str, old_state: State | None, new_state: State | None @@ -117,6 +122,8 @@ async def _async_update_data(self) -> AdaptiveCoverData: cover_data = self.get_blind_data() + self.manager.add_covers(self.entities) + control_method = "intermediate" self.climate_state = None @@ -145,8 +152,17 @@ async def _async_update_data(self) -> AdaptiveCoverData: self.default_state = round(NormalCoverState(cover_data).get_state()) + entity_id = False + if self.state_change_data is not None: + event = self.state_change_data + entity_id = event.entity_id + self.manager.state_change(event, self.state, self._cover_type) + self.manager.reset_if_needed() + if self.control_toggle: - await self.async_handle_call_service() + for cover in self.entities: + if not self.manager.is_cover_manual(cover): + await self.async_handle_call_service(cover) return AdaptiveCoverData( climate_mode_toggle=self.switch_mode, @@ -166,36 +182,23 @@ async def _async_update_data(self) -> AdaptiveCoverData: self.config_entry.options.get(CONF_FOV_LEFT), self.config_entry.options.get(CONF_FOV_RIGHT), ], - "manual control": self.find_manual_control, - "states_data": self.state_change_data, + # "manual control": self.find_manual_control, + "function": "", + "manual_control": self.manager.manual_control, + "manual_control_time": self.manager.manual_control_time, + "states_data": entity_id, + "data": self.state_change_data, }, ) - @property - def find_manual_control(self): - """Find position change other than calculated state.""" - if self.state_change_data: - if self.state_change_data.entity_id.startswith("cover."): - if self._cover_type == 'cover_tilt': - return ( - self.state_change_data.new_state.attributes["current_tilt_position"] - != self.state - ) - else: - return ( - self.state_change_data.new_state.attributes["current_position"] - != self.state - ) - - async def async_handle_call_service(self): + async def async_handle_call_service(self, entity): """Handle call service.""" - for entity in self.entities: - if ( - self.check_position(entity) - and self.check_time_delta(entity) - and self.after_start_time - ): - await self.async_set_position(entity) + if ( + self.check_position(entity) + and self.check_time_delta(entity) + and self.after_start_time + ): + await self.async_set_position(entity) async def async_set_position(self, entity): """Call service to set cover position.""" @@ -346,3 +349,60 @@ def control_toggle(self): @control_toggle.setter def control_toggle(self, value): self._control_toggle = value + + +class AdaptiveCoverManager: + """Track position changes.""" + + def __init__(self, reset_duration: dict[str:int]) -> None: + """Initialize the AdaptiveCoverManager.""" + self.covers: set[str] = set() + + self.manual_control: dict[str, bool] = {} + self.manual_control_time: dict[str, dt.datetime] = {} + self.reset_duration = reset_duration + + def add_covers(self, entity): + """Update set with entities.""" + self.covers.update(entity) + + def state_change(self, states_data, our_state, blind_type): + event = states_data + entity_id = event.entity_id + if entity_id not in self.covers: + return + + new_state = event.new_state + + if blind_type == "cover_tilt": + new_position = new_state.attributes.get("current_tilt_position") + else: + new_position = new_state.attributes.get("current_position") + + if new_position != our_state: + if self.manual_control.get("entity_id") is not True: + self.mark_manual_control(entity_id) + + # if self.manual_control_time.get(entity_id): + # return + + last_updated = new_state.last_updated + self.set_last_updated(entity_id, last_updated) + + def mark_manual_control(self, cover: str) -> None: + self.manual_control[cover] = True + + def set_last_updated(self, entity_id, last_updated): + self.manual_control_time[entity_id] = last_updated + + def reset_if_needed(self): + """Reset manual control state of the covers.""" + current_time = dt.datetime.now(dt.UTC) + # Iterate over a copy of the dictionary + for entity_id, last_updated in list(self.manual_control_time.items()): + if current_time - last_updated > dt.timedelta(**self.reset_duration): + self.manual_control[entity_id] = False + self.manual_control_time.pop(entity_id, None) + + def is_cover_manual(self, entity_id): + return self.manual_control.get(entity_id, False) From eef925b6a3e5a0553501408b94b84a45ef5b99dd Mon Sep 17 00:00:00 2001 From: basbruss <68892092+basbruss@users.noreply.github.com> Date: Wed, 10 Apr 2024 20:15:31 +0200 Subject: [PATCH 03/14] =?UTF-8?q?=F0=9F=94=A7=20Update=20switch=20names=20?= =?UTF-8?q?in=20async=5Fsetup=5Fentry=20for=20clarity=20and=20consistency.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- custom_components/adaptive_cover/switch.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/custom_components/adaptive_cover/switch.py b/custom_components/adaptive_cover/switch.py index 4893556..7fa0f6e 100644 --- a/custom_components/adaptive_cover/switch.py +++ b/custom_components/adaptive_cover/switch.py @@ -43,7 +43,7 @@ async def async_setup_entry( control_switch = AdaptiveCoverSwitch( config_entry, config_entry.entry_id, - "Adaptive Control", + "Toggle Control", True, "control_toggle", coordinator, @@ -71,7 +71,7 @@ async def async_setup_entry( switches = [] if len(config_entry.options.get(CONF_ENTITIES)) >= 1: - switches=[control_switch, manual_switch] + switches = [control_switch, manual_switch] if climate_mode: switches.append(climate_switch) From 8d32a46c9e995aff6115820b698458fdb688f103 Mon Sep 17 00:00:00 2001 From: basbruss <68892092+basbruss@users.noreply.github.com> Date: Thu, 11 Apr 2024 11:34:02 +0200 Subject: [PATCH 04/14] =?UTF-8?q?=F0=9F=94=84=20Refactor=20the=20manual=20?= =?UTF-8?q?override=20functionality=20in=20coordinator=20file.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adaptive_cover/config_flow.py | 9 +++ custom_components/adaptive_cover/const.py | 3 + .../adaptive_cover/coordinator.py | 64 +++++++++++-------- 3 files changed, 50 insertions(+), 26 deletions(-) diff --git a/custom_components/adaptive_cover/config_flow.py b/custom_components/adaptive_cover/config_flow.py index 8d055ab..22ccfe3 100644 --- a/custom_components/adaptive_cover/config_flow.py +++ b/custom_components/adaptive_cover/config_flow.py @@ -36,6 +36,7 @@ CONF_SENSOR_TYPE, CONF_START_ENTITY, CONF_START_TIME, + CONF_SUNRISE_OFFSET, CONF_SUNSET_OFFSET, CONF_SUNSET_POS, CONF_TEMP_ENTITY, @@ -268,6 +269,10 @@ vol.Optional(CONF_START_ENTITY): selector.EntitySelector( selector.EntitySelectorConfig(domain=["sensor", "input_datetime"]) ), + vol.Required( + CONF_MANUAL_OVERRIDE_DURATION, default={"minutes": 15} + ): selector.DurationSelector(), + vol.Required(CONF_MANUAL_OVERRIDE_RESET, default=False): bool, } ) @@ -400,6 +405,10 @@ async def async_step_update(self, user_input: dict[str, Any] | None = None): CONF_DELTA_TIME: self.config.get(CONF_DELTA_TIME), CONF_START_TIME: self.config.get(CONF_START_TIME), CONF_START_ENTITY: self.config.get(CONF_START_ENTITY), + CONF_MANUAL_OVERRIDE_DURATION: self.config.get( + CONF_MANUAL_OVERRIDE_DURATION + ), + CONF_MANUAL_OVERRIDE_RESET: self.config.get(CONF_MANUAL_OVERRIDE_RESET), }, ) diff --git a/custom_components/adaptive_cover/const.py b/custom_components/adaptive_cover/const.py index a1f0f5a..fbf66db 100644 --- a/custom_components/adaptive_cover/const.py +++ b/custom_components/adaptive_cover/const.py @@ -39,10 +39,13 @@ CONF_MAX_POSITION = "max_position" CONF_OUTSIDETEMP_ENTITY = "outside_temp" + CONF_DELTA_POSITION = "delta_position" CONF_DELTA_TIME = "delta_time" CONF_START_TIME = "start_time" CONF_START_ENTITY = "start_entity" +CONF_MANUAL_OVERRIDE_DURATION = "manual_override_duration" +CONF_MANUAL_OVERRIDE_RESET = "manual_override_reset" STRATEGY_MODE_BASIC = "basic" STRATEGY_MODE_CLIMATE = "climate" diff --git a/custom_components/adaptive_cover/coordinator.py b/custom_components/adaptive_cover/coordinator.py index f419ec0..1f6e580 100644 --- a/custom_components/adaptive_cover/coordinator.py +++ b/custom_components/adaptive_cover/coordinator.py @@ -101,10 +101,12 @@ def __init__(self, hass: HomeAssistant) -> None: # noqa: D107 self._inverse_state = self.config_entry.options.get(CONF_INVERSE_STATE, False) self._temp_toggle = False self._control_toggle = True - self._manual_duration = {"hours": 0, "minutes": 2, "seconds": 0} + self.manual_duration = self.config_entry.options.get( + CONF_MANUAL_OVERRIDE_DURATION, {"minutes": 15} + ) self.state_change_data: StateChangedData | None = None - self.manager = AdaptiveCoverManager(self._manual_duration) + self.manager = AdaptiveCoverManager(self.manual_duration) async def async_check_entity_state_change( self, entity: str, old_state: State | None, new_state: State | None @@ -119,6 +121,12 @@ async def _async_update_data(self) -> AdaptiveCoverData: self.time_threshold = self.config_entry.options.get(CONF_DELTA_TIME, 2) self.start_time = self.config_entry.options.get(CONF_START_TIME) self.start_time_entity = self.config_entry.options.get(CONF_START_ENTITY) + self.manual_reset = self.config_entry.options.get( + CONF_MANUAL_OVERRIDE_RESET, False + ) + self.manual_duration = self.config_entry.options.get( + CONF_MANUAL_OVERRIDE_DURATION, {"minutes": 15} + ) cover_data = self.get_blind_data() @@ -152,17 +160,13 @@ async def _async_update_data(self) -> AdaptiveCoverData: self.default_state = round(NormalCoverState(cover_data).get_state()) - entity_id = False - if self.state_change_data is not None: - event = self.state_change_data - entity_id = event.entity_id - self.manager.state_change(event, self.state, self._cover_type) - self.manager.reset_if_needed() + self.manager.state_change( + self.state_change_data, self.state, self._cover_type, self.manual_reset + ) if self.control_toggle: for cover in self.entities: - if not self.manager.is_cover_manual(cover): - await self.async_handle_call_service(cover) + await self.async_handle_call_service(cover) return AdaptiveCoverData( climate_mode_toggle=self.switch_mode, @@ -183,11 +187,10 @@ async def _async_update_data(self) -> AdaptiveCoverData: self.config_entry.options.get(CONF_FOV_RIGHT), ], # "manual control": self.find_manual_control, - "function": "", "manual_control": self.manager.manual_control, "manual_control_time": self.manager.manual_control_time, - "states_data": entity_id, - "data": self.state_change_data, + "bool": self.manager.is_cover_manual(self.entities[0]), + "reset_duration": self.manager.reset_duration, }, ) @@ -366,8 +369,10 @@ def add_covers(self, entity): """Update set with entities.""" self.covers.update(entity) - def state_change(self, states_data, our_state, blind_type): + def state_change(self, states_data, our_state, blind_type, allow_reset): event = states_data + if event is None: + return entity_id = event.entity_id if entity_id not in self.covers: return @@ -380,26 +385,33 @@ def state_change(self, states_data, our_state, blind_type): new_position = new_state.attributes.get("current_position") if new_position != our_state: - if self.manual_control.get("entity_id") is not True: - self.mark_manual_control(entity_id) - - # if self.manual_control_time.get(entity_id): - # return - - last_updated = new_state.last_updated - self.set_last_updated(entity_id, last_updated) + self.mark_manual_control(entity_id) + self.set_last_updated(entity_id, new_state, allow_reset) + + def set_last_updated(self, entity_id, new_state, allow_reset): + if entity_id not in self.manual_control_time or allow_reset: + last_updated = new_state.last_updated + self.manual_control_time[entity_id] = last_updated + _LOGGER.debug( + "Updating last updated to %s for %s. Allow reset:%s", + last_updated, + entity_id, + allow_reset, + ) + if not allow_reset: + _LOGGER.debug( + "Already time specified, reset is not allowed by user setting:%s", + allow_reset, + ) def mark_manual_control(self, cover: str) -> None: self.manual_control[cover] = True - def set_last_updated(self, entity_id, last_updated): - self.manual_control_time[entity_id] = last_updated - def reset_if_needed(self): """Reset manual control state of the covers.""" current_time = dt.datetime.now(dt.UTC) # Iterate over a copy of the dictionary - for entity_id, last_updated in list(self.manual_control_time.items()): + for entity_id, last_updated in self.manual_control_time.items(): if current_time - last_updated > dt.timedelta(**self.reset_duration): self.manual_control[entity_id] = False self.manual_control_time.pop(entity_id, None) From 3276559fcaccaae8c8c026aac98a23ffb5817f44 Mon Sep 17 00:00:00 2001 From: basbruss <68892092+basbruss@users.noreply.github.com> Date: Thu, 11 Apr 2024 12:58:41 +0200 Subject: [PATCH 05/14] =?UTF-8?q?=F0=9F=8E=A8=20Add=20button=20platform=20?= =?UTF-8?q?and=20reset=20button=20for=20Adaptive=20Cover=20integration.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- custom_components/adaptive_cover/__init__.py | 2 +- custom_components/adaptive_cover/button.py | 84 +++++++++++++++++++ custom_components/adaptive_cover/const.py | 1 + .../adaptive_cover/coordinator.py | 48 +++++++---- 4 files changed, 120 insertions(+), 15 deletions(-) create mode 100644 custom_components/adaptive_cover/button.py diff --git a/custom_components/adaptive_cover/__init__.py b/custom_components/adaptive_cover/__init__.py index f2ae58b..e8135e0 100644 --- a/custom_components/adaptive_cover/__init__.py +++ b/custom_components/adaptive_cover/__init__.py @@ -18,7 +18,7 @@ ) from .coordinator import AdaptiveDataUpdateCoordinator -PLATFORMS = [Platform.SENSOR, Platform.SWITCH, Platform.BINARY_SENSOR] +PLATFORMS = [Platform.SENSOR, Platform.SWITCH, Platform.BINARY_SENSOR, Platform.BUTTON] CONF_SUN = ["sun.sun"] diff --git a/custom_components/adaptive_cover/button.py b/custom_components/adaptive_cover/button.py new file mode 100644 index 0000000..82781fc --- /dev/null +++ b/custom_components/adaptive_cover/button.py @@ -0,0 +1,84 @@ +"""Button platform for the Adaptive Cover integration.""" + +from __future__ import annotations + +from homeassistant.components.button import ButtonEntity +from homeassistant.config_entries import ConfigEntry +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity import DeviceInfo +from homeassistant.helpers.entity_platform import AddEntitiesCallback +from homeassistant.helpers.update_coordinator import CoordinatorEntity + +from .const import _LOGGER, CONF_ENTITIES, CONF_SENSOR_TYPE, DOMAIN +from .coordinator import AdaptiveDataUpdateCoordinator + + +async def async_setup_entry( + hass: HomeAssistant, + config_entry: ConfigEntry, + async_add_entities: AddEntitiesCallback, +) -> None: + """Set up the button platform.""" + coordinator: AdaptiveDataUpdateCoordinator = hass.data[DOMAIN][ + config_entry.entry_id + ] + + reset_manual = AdaptiveCoverButton( + config_entry, config_entry.entry_id, "Reset Manual Override", coordinator + ) + + buttons = [] + + entities = config_entry.options.get(CONF_ENTITIES, []) + if len(entities) >= 1: + buttons = [reset_manual] + + async_add_entities(buttons) + + +class AdaptiveCoverButton( + CoordinatorEntity[AdaptiveDataUpdateCoordinator], ButtonEntity +): + """Representation of a adaptive cover button.""" + + _attr_has_entity_name = True + _attr_should_poll = False + + def __init__( + self, + config_entry, + unique_id: str, + button_name: str, + coordinator: AdaptiveDataUpdateCoordinator, + ) -> None: + """Initialize the button.""" + super().__init__(coordinator=coordinator) + self.type = { + "cover_blind": "Vertical", + "cover_awning": "Horizontal", + "cover_tilt": "Tilt", + } + self._name = config_entry.data["name"] + self._device_name = self.type[config_entry.data[CONF_SENSOR_TYPE]] + self._attr_unique_id = f"{unique_id}_{button_name}" + self._device_id = unique_id + self._button_name = button_name + self._entities = config_entry.options.get(CONF_ENTITIES, []) + self._attr_device_info = DeviceInfo( + identifiers={(DOMAIN, self._device_id)}, + name=self._device_name, + ) + + @property + def name(self): + """Name of the entity.""" + return f"{self._button_name} {self._name}" + + async def async_press(self) -> None: + """Handle the button press.""" + for entity in self._entities: + _LOGGER.debug("resetting manual override for: %s", entity) + await self.coordinator.async_set_position(entity) + self.coordinator.manager.reset(entity) + + await self.coordinator.async_refresh() diff --git a/custom_components/adaptive_cover/const.py b/custom_components/adaptive_cover/const.py index fbf66db..863a0ab 100644 --- a/custom_components/adaptive_cover/const.py +++ b/custom_components/adaptive_cover/const.py @@ -4,6 +4,7 @@ DOMAIN = "adaptive_cover" LOGGER = logging.getLogger(__package__) +_LOGGER = logging.getLogger(__name__) ATTR_POSITION = "position" ATTR_TILT_POSITION = "tilt_position" diff --git a/custom_components/adaptive_cover/coordinator.py b/custom_components/adaptive_cover/coordinator.py index 1f6e580..93a8ef4 100644 --- a/custom_components/adaptive_cover/coordinator.py +++ b/custom_components/adaptive_cover/coordinator.py @@ -104,7 +104,7 @@ def __init__(self, hass: HomeAssistant) -> None: # noqa: D107 self.manual_duration = self.config_entry.options.get( CONF_MANUAL_OVERRIDE_DURATION, {"minutes": 15} ) - + self.state_change = False self.state_change_data: StateChangedData | None = None self.manager = AdaptiveCoverManager(self.manual_duration) @@ -113,6 +113,7 @@ async def async_check_entity_state_change( ) -> None: """Fetch and process state change event.""" self.state_change_data = StateChangedData(entity, old_state, new_state) + self.state_change = True await self.async_refresh() async def _async_update_data(self) -> AdaptiveCoverData: @@ -160,13 +161,17 @@ async def _async_update_data(self) -> AdaptiveCoverData: self.default_state = round(NormalCoverState(cover_data).get_state()) - self.manager.state_change( - self.state_change_data, self.state, self._cover_type, self.manual_reset - ) + if self.state_change: + self.manager.state_change( + self.state_change_data, self.state, self._cover_type, self.manual_reset + ) + self.state_change = False # reset state change + await self.manager.reset_if_needed() if self.control_toggle: for cover in self.entities: - await self.async_handle_call_service(cover) + if self.manager.is_cover_manual(cover): + await self.async_handle_call_service(cover) return AdaptiveCoverData( climate_mode_toggle=self.switch_mode, @@ -189,8 +194,7 @@ async def _async_update_data(self) -> AdaptiveCoverData: # "manual control": self.find_manual_control, "manual_control": self.manager.manual_control, "manual_control_time": self.manager.manual_control_time, - "bool": self.manager.is_cover_manual(self.entities[0]), - "reset_duration": self.manager.reset_duration, + "track_state_change": self.state_change, }, ) @@ -216,6 +220,7 @@ async def async_set_position(self, entity): service_data[ATTR_POSITION] = self.state await self.hass.services.async_call(COVER_DOMAIN, service, service_data) + _LOGGER.debug("Run %s with data %s", service, service_data) def get_blind_data(self): """Assign correct class for type of blind.""" @@ -363,7 +368,7 @@ def __init__(self, reset_duration: dict[str:int]) -> None: self.manual_control: dict[str, bool] = {} self.manual_control_time: dict[str, dt.datetime] = {} - self.reset_duration = reset_duration + self.reset_duration = dt.timedelta(**reset_duration) def add_covers(self, entity): """Update set with entities.""" @@ -385,6 +390,12 @@ def state_change(self, states_data, our_state, blind_type, allow_reset): new_position = new_state.attributes.get("current_position") if new_position != our_state: + _LOGGER.debug( + "Set manual control for %s, for at least %s seconds, reset_allowed: %s", + entity_id, + self.reset_duration.total_seconds(), + allow_reset, + ) self.mark_manual_control(entity_id) self.set_last_updated(entity_id, new_state, allow_reset) @@ -400,21 +411,30 @@ def set_last_updated(self, entity_id, new_state, allow_reset): ) if not allow_reset: _LOGGER.debug( - "Already time specified, reset is not allowed by user setting:%s", + "Already time specified for %s, reset is not allowed by user setting:%s", + entity_id, allow_reset, ) def mark_manual_control(self, cover: str) -> None: self.manual_control[cover] = True - def reset_if_needed(self): + async def reset_if_needed(self): """Reset manual control state of the covers.""" current_time = dt.datetime.now(dt.UTC) # Iterate over a copy of the dictionary - for entity_id, last_updated in self.manual_control_time.items(): - if current_time - last_updated > dt.timedelta(**self.reset_duration): - self.manual_control[entity_id] = False - self.manual_control_time.pop(entity_id, None) + manual_control_time_copy = dict(self.manual_control_time) + for entity_id, last_updated in manual_control_time_copy.items(): + if current_time - last_updated > self.reset_duration: + _LOGGER.debug( + "Resetting manual override for %s, because duration has elasped", + entity_id, + ) + self.reset(entity_id) + + def reset(self, entity_id): + self.manual_control[entity_id] = False + self.manual_control_time.pop(entity_id, None) def is_cover_manual(self, entity_id): return self.manual_control.get(entity_id, False) From 7ec4b7565cb796460a7114fc3d9792c2d23c8233 Mon Sep 17 00:00:00 2001 From: basbruss <68892092+basbruss@users.noreply.github.com> Date: Thu, 11 Apr 2024 13:07:14 +0200 Subject: [PATCH 06/14] =?UTF-8?q?=E2=9C=A8=20Fix=20issue=20with=20not=20re?= =?UTF-8?q?setting=20manual=20override=20if=20cover=20is=20already=20auto-?= =?UTF-8?q?controlled.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- custom_components/adaptive_cover/button.py | 13 +++++++++---- custom_components/adaptive_cover/coordinator.py | 2 +- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/custom_components/adaptive_cover/button.py b/custom_components/adaptive_cover/button.py index 82781fc..23ce648 100644 --- a/custom_components/adaptive_cover/button.py +++ b/custom_components/adaptive_cover/button.py @@ -77,8 +77,13 @@ def name(self): async def async_press(self) -> None: """Handle the button press.""" for entity in self._entities: - _LOGGER.debug("resetting manual override for: %s", entity) - await self.coordinator.async_set_position(entity) - self.coordinator.manager.reset(entity) - + if self.coordinator.manager.is_cover_manual(entity): + _LOGGER.debug("Resetting manual override for: %s", entity) + await self.coordinator.async_set_position(entity) + self.coordinator.manager.reset(entity) + else: + _LOGGER.debug( + "Resetting manual override for %s is not needed since it is already auto-cotrolled", + entity, + ) await self.coordinator.async_refresh() diff --git a/custom_components/adaptive_cover/coordinator.py b/custom_components/adaptive_cover/coordinator.py index 93a8ef4..99661d6 100644 --- a/custom_components/adaptive_cover/coordinator.py +++ b/custom_components/adaptive_cover/coordinator.py @@ -170,7 +170,7 @@ async def _async_update_data(self) -> AdaptiveCoverData: if self.control_toggle: for cover in self.entities: - if self.manager.is_cover_manual(cover): + if not self.manager.is_cover_manual(cover): await self.async_handle_call_service(cover) return AdaptiveCoverData( From 5afb2f88117f54167a9d1a527329ecc72ae1f568 Mon Sep 17 00:00:00 2001 From: basbruss <68892092+basbruss@users.noreply.github.com> Date: Thu, 11 Apr 2024 13:15:20 +0200 Subject: [PATCH 07/14] =?UTF-8?q?=F0=9F=9A=80=20Add=20async=5Fconfig=5Fent?= =?UTF-8?q?ry=5Ffirst=5Frefresh=20method=20to=20call=20custom=20position?= =?UTF-8?q?=20update=20on=20first=20refresh.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- custom_components/adaptive_cover/coordinator.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/custom_components/adaptive_cover/coordinator.py b/custom_components/adaptive_cover/coordinator.py index 99661d6..394bfff 100644 --- a/custom_components/adaptive_cover/coordinator.py +++ b/custom_components/adaptive_cover/coordinator.py @@ -108,6 +108,13 @@ def __init__(self, hass: HomeAssistant) -> None: # noqa: D107 self.state_change_data: StateChangedData | None = None self.manager = AdaptiveCoverManager(self.manual_duration) + async def async_config_entry_first_refresh(self): + """Call the first update from config_entry.""" + await super().async_config_entry_first_refresh() + # Call your custom method here + for cover in self.entities: + await self.async_set_position(cover) + async def async_check_entity_state_change( self, entity: str, old_state: State | None, new_state: State | None ) -> None: From 159b29d0642993d0dba48888b460b2e757117fbc Mon Sep 17 00:00:00 2001 From: basbruss <68892092+basbruss@users.noreply.github.com> Date: Thu, 11 Apr 2024 13:17:23 +0200 Subject: [PATCH 08/14] =?UTF-8?q?=F0=9F=94=A7=20Update=20coordinator=20to?= =?UTF-8?q?=20only=20set=20position=20if=20control=20toggle=20is=20enabled?= =?UTF-8?q?.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- custom_components/adaptive_cover/coordinator.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/custom_components/adaptive_cover/coordinator.py b/custom_components/adaptive_cover/coordinator.py index 394bfff..436b8db 100644 --- a/custom_components/adaptive_cover/coordinator.py +++ b/custom_components/adaptive_cover/coordinator.py @@ -112,8 +112,9 @@ async def async_config_entry_first_refresh(self): """Call the first update from config_entry.""" await super().async_config_entry_first_refresh() # Call your custom method here - for cover in self.entities: - await self.async_set_position(cover) + if self._control_toggle: + for cover in self.entities: + await self.async_set_position(cover) async def async_check_entity_state_change( self, entity: str, old_state: State | None, new_state: State | None From 6eb6e34724ef8af8549acf227e499fdb75753939 Mon Sep 17 00:00:00 2001 From: basbruss <68892092+basbruss@users.noreply.github.com> Date: Thu, 11 Apr 2024 13:41:07 +0200 Subject: [PATCH 09/14] =?UTF-8?q?=E2=9C=A8=20Add=20manual=20override=20bin?= =?UTF-8?q?ary=20sensor,=20including=20manual=20controlled=20attribute.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adaptive_cover/binary_sensor.py | 26 ++++++++++++++++--- .../adaptive_cover/coordinator.py | 12 ++++++++- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/custom_components/adaptive_cover/binary_sensor.py b/custom_components/adaptive_cover/binary_sensor.py index 177590e..cf2d642 100644 --- a/custom_components/adaptive_cover/binary_sensor.py +++ b/custom_components/adaptive_cover/binary_sensor.py @@ -2,6 +2,9 @@ from __future__ import annotations +from collections.abc import Mapping +from typing import Any + from homeassistant.components.binary_sensor import ( BinarySensorDeviceClass, BinarySensorEntity, @@ -31,10 +34,20 @@ async def async_setup_entry( config_entry.entry_id, "Sun Infront", False, + "sun_motion", BinarySensorDeviceClass.MOTION, coordinator, ) - async_add_entities([binary_sensor]) + manual_override = AdaptiveCoverBinarySensor( + config_entry, + config_entry.entry_id, + "Manual Override Active", + False, + "manual_override", + BinarySensorDeviceClass.RUNNING, + coordinator, + ) + async_add_entities([binary_sensor, manual_override]) class AdaptiveCoverBinarySensor( @@ -44,7 +57,6 @@ class AdaptiveCoverBinarySensor( _attr_has_entity_name = True _attr_should_poll = False - _attr_translation_key = "sun_motion" def __init__( self, @@ -52,6 +64,7 @@ def __init__( unique_id: str, binary_name: str, state: bool, + key: str, device_class: BinarySensorDeviceClass, coordinator: AdaptiveDataUpdateCoordinator, ) -> None: @@ -62,6 +75,8 @@ def __init__( "cover_awning": "Horizontal", "cover_tilt": "Tilt", } + self._key = key + self._attr_translation_key = key self._name = config_entry.data["name"] self._device_name = self.type[config_entry.data[CONF_SENSOR_TYPE]] self._binary_name = binary_name @@ -82,4 +97,9 @@ def name(self): @property def is_on(self) -> bool: """Return true if the binary sensor is on.""" - return self.coordinator.data.states["binary"] + return self.coordinator.data.states[self._key] + + @property + def extra_state_attributes(self) -> Mapping[str, Any] | None: # noqa: D102 + if self._key == "manual_override": + return {"manual_controlled": self.coordinator.data.states["manual_list"]} diff --git a/custom_components/adaptive_cover/coordinator.py b/custom_components/adaptive_cover/coordinator.py index 436b8db..889c54f 100644 --- a/custom_components/adaptive_cover/coordinator.py +++ b/custom_components/adaptive_cover/coordinator.py @@ -188,7 +188,9 @@ async def _async_update_data(self) -> AdaptiveCoverData: "start": NormalCoverState(cover_data).cover.solar_times()[0], "end": NormalCoverState(cover_data).cover.solar_times()[1], "control": control_method, - "binary": NormalCoverState(cover_data).cover.valid, + "sun_motion": NormalCoverState(cover_data).cover.valid, + "manual_override": self.manager.binary_cover_manual, + "manual_list": self.manager.manual_controlled, }, attributes={ "default": self.config_entry.options.get(CONF_DEFAULT_HEIGHT), @@ -446,3 +448,11 @@ def reset(self, entity_id): def is_cover_manual(self, entity_id): return self.manual_control.get(entity_id, False) + + @property + def binary_cover_manual(self): + return any(value for value in self.manual_control.values()) + + @property + def manual_controlled(self): + return [k for k, v in self.manual_control.items() if v] From f8cf5f01123d45b4ece0739782491692ce2f4244 Mon Sep 17 00:00:00 2001 From: basbruss <68892092+basbruss@users.noreply.github.com> Date: Thu, 11 Apr 2024 14:45:17 +0200 Subject: [PATCH 10/14] =?UTF-8?q?=F0=9F=8E=A8=20Update=20icons.json=20with?= =?UTF-8?q?=20new=20icon=20values=20and=20shorten=20entity=20names.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../adaptive_cover/binary_sensor.py | 2 +- custom_components/adaptive_cover/button.py | 1 + custom_components/adaptive_cover/icons.json | 60 ++++++++++--------- 3 files changed, 35 insertions(+), 28 deletions(-) diff --git a/custom_components/adaptive_cover/binary_sensor.py b/custom_components/adaptive_cover/binary_sensor.py index cf2d642..8b57939 100644 --- a/custom_components/adaptive_cover/binary_sensor.py +++ b/custom_components/adaptive_cover/binary_sensor.py @@ -41,7 +41,7 @@ async def async_setup_entry( manual_override = AdaptiveCoverBinarySensor( config_entry, config_entry.entry_id, - "Manual Override Active", + "Manual Override", False, "manual_override", BinarySensorDeviceClass.RUNNING, diff --git a/custom_components/adaptive_cover/button.py b/custom_components/adaptive_cover/button.py index 23ce648..6df6752 100644 --- a/custom_components/adaptive_cover/button.py +++ b/custom_components/adaptive_cover/button.py @@ -43,6 +43,7 @@ class AdaptiveCoverButton( _attr_has_entity_name = True _attr_should_poll = False + _attr_icon = "mdi:cog-refresh-outline" def __init__( self, diff --git a/custom_components/adaptive_cover/icons.json b/custom_components/adaptive_cover/icons.json index 06741cd..973f0ce 100644 --- a/custom_components/adaptive_cover/icons.json +++ b/custom_components/adaptive_cover/icons.json @@ -1,35 +1,41 @@ { - "entity": { - "binary_sensor": { - "sun_motion": { - "default": "mdi:weather-sunny", - "state":{ - "off": "mdi:weather-sunny-off" - } + "entity": { + "binary_sensor": { + "sun_motion": { + "default": "mdi:weather-sunny", + "state": { + "off": "mdi:weather-sunny-off" } }, - "sensor": { - "control": { - "default": "mdi:white-balance-sunny", - "state":{ - "winter": "mdi:snowflake", - "summer": "mdi:heat-wave" - } + "manual_override": { + "default": "mdi:cog-outline", + "state": { + "off": "mdi:cog-sync-outline" } - }, - "switch":{ - "control_toggle":{ - "default":"mdi:toggle-switch-outline", - "state":{ - "off":"mdi:toggle-switch-off-outline" - } - }, - "temp_toggle":{ - "default":"mdi:thermometer" - }, - "switch_mode":{ - "default":"mdi:home-thermometer-outline" + } + }, + "sensor": { + "control": { + "default": "mdi:white-balance-sunny", + "state": { + "winter": "mdi:snowflake", + "summer": "mdi:heat-wave" + } + } + }, + "switch": { + "control_toggle": { + "default": "mdi:toggle-switch-outline", + "state": { + "off": "mdi:toggle-switch-off-outline" } + }, + "temp_toggle": { + "default": "mdi:thermometer" + }, + "switch_mode": { + "default": "mdi:home-thermometer-outline" } } } +} From 147c5d9848da20fdbf26ae40e496efa93f821d4d Mon Sep 17 00:00:00 2001 From: basbruss <68892092+basbruss@users.noreply.github.com> Date: Thu, 11 Apr 2024 15:00:56 +0200 Subject: [PATCH 11/14] =?UTF-8?q?=E2=9C=A8=20Refactor=20coordinator=20meth?= =?UTF-8?q?ods=20for=20better=20organization=20and=20clarity.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- custom_components/adaptive_cover/coordinator.py | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/custom_components/adaptive_cover/coordinator.py b/custom_components/adaptive_cover/coordinator.py index 889c54f..2bb1ac0 100644 --- a/custom_components/adaptive_cover/coordinator.py +++ b/custom_components/adaptive_cover/coordinator.py @@ -111,7 +111,6 @@ def __init__(self, hass: HomeAssistant) -> None: # noqa: D107 async def async_config_entry_first_refresh(self): """Call the first update from config_entry.""" await super().async_config_entry_first_refresh() - # Call your custom method here if self._control_toggle: for cover in self.entities: await self.async_set_position(cover) @@ -201,10 +200,6 @@ async def _async_update_data(self) -> AdaptiveCoverData: self.config_entry.options.get(CONF_FOV_LEFT), self.config_entry.options.get(CONF_FOV_RIGHT), ], - # "manual control": self.find_manual_control, - "manual_control": self.manager.manual_control, - "manual_control_time": self.manager.manual_control_time, - "track_state_change": self.state_change, }, ) @@ -385,6 +380,7 @@ def add_covers(self, entity): self.covers.update(entity) def state_change(self, states_data, our_state, blind_type, allow_reset): + """Process state change event.""" event = states_data if event is None: return @@ -410,6 +406,7 @@ def state_change(self, states_data, our_state, blind_type, allow_reset): self.set_last_updated(entity_id, new_state, allow_reset) def set_last_updated(self, entity_id, new_state, allow_reset): + """Set last updated time for manual control.""" if entity_id not in self.manual_control_time or allow_reset: last_updated = new_state.last_updated self.manual_control_time[entity_id] = last_updated @@ -419,7 +416,7 @@ def set_last_updated(self, entity_id, new_state, allow_reset): entity_id, allow_reset, ) - if not allow_reset: + elif not allow_reset: _LOGGER.debug( "Already time specified for %s, reset is not allowed by user setting:%s", entity_id, @@ -427,12 +424,12 @@ def set_last_updated(self, entity_id, new_state, allow_reset): ) def mark_manual_control(self, cover: str) -> None: + """Mark cover as under manual control.""" self.manual_control[cover] = True async def reset_if_needed(self): """Reset manual control state of the covers.""" current_time = dt.datetime.now(dt.UTC) - # Iterate over a copy of the dictionary manual_control_time_copy = dict(self.manual_control_time) for entity_id, last_updated in manual_control_time_copy.items(): if current_time - last_updated > self.reset_duration: @@ -443,16 +440,20 @@ async def reset_if_needed(self): self.reset(entity_id) def reset(self, entity_id): + """Reset manual control for a cover.""" self.manual_control[entity_id] = False self.manual_control_time.pop(entity_id, None) def is_cover_manual(self, entity_id): + """Check if a cover is under manual control.""" return self.manual_control.get(entity_id, False) @property def binary_cover_manual(self): + """Check if any cover is under manual control.""" return any(value for value in self.manual_control.values()) @property def manual_controlled(self): + """Get the list of covers under manual control.""" return [k for k, v in self.manual_control.items() if v] From 6a159b4f0f3835ea8f90a9be53c16be2590cbedf Mon Sep 17 00:00:00 2001 From: basbruss <68892092+basbruss@users.noreply.github.com> Date: Thu, 11 Apr 2024 15:32:05 +0200 Subject: [PATCH 12/14] Update nl.json --- .../adaptive_cover/translations/nl.json | 118 ++++++++++-------- 1 file changed, 65 insertions(+), 53 deletions(-) diff --git a/custom_components/adaptive_cover/translations/nl.json b/custom_components/adaptive_cover/translations/nl.json index 2b717dc..f277780 100644 --- a/custom_components/adaptive_cover/translations/nl.json +++ b/custom_components/adaptive_cover/translations/nl.json @@ -11,18 +11,22 @@ }, "automation": { "data": { - "delta_position": "Minimale positieaanpassing", - "delta_time": "Minimale interval tussen positieveranderingen", - "start_time": "Starttijd", - "start_entity": "Entiteit die starttijd aangeeft" + "delta_position": "Minimale positieaanpassing", + "delta_time": "Minimale interval tussen positieveranderingen", + "start_time": "Starttijd", + "start_entity": "Entiteit die starttijd aangeeft", + "manual_override_duration": "Duur van handmatige overschrijving", + "manual_override_reset": "Reset handmatige overschrijvingsduur" }, "data_description": { - "delta_position": "Minimale verandering in positie vereist voordat de positie van de bekleding wordt aangepast", - "delta_time": "Minimale tijdsinterval tussen positieveranderingen; minimum is 2 minuten", - "start_time": "Starttijd voor elke dag; voor deze tijd blijft de bekleding stationair", - "start_entity": "Entiteit die de status van de starttijd vertegenwoordigt, die de hierboven ingestelde statische starttijd overschrijft. Handig voor het automatiseren van de starttijd met een entiteit" + "delta_position": "Minimale verandering in positie vereist voordat de positie van de bekleding wordt aangepast", + "delta_time": "Minimale tijdsinterval tussen positieveranderingen; minimum is 2 minuten", + "start_time": "Starttijd voor elke dag; voor deze tijd blijft de bekleding stationair", + "start_entity": "Entiteit die de status van de starttijd vertegenwoordigt, die de hierboven ingestelde statische starttijd overschrijft. Handig voor het automatiseren van de starttijd met een entiteit", + "manual_override_duration": "De duur van handmatige bediening voordat wordt teruggekeerd naar automatische bediening", + "manual_override_reset": "Optie om de duur van handmatige overschrijving na elke handmatige aanpassing te resetten; als dit is uitgeschakeld, geldt de duur alleen voor de eerste handmatige aanpassing" } - }, + }, "vertical": { "data": { "set_azimuth": "Raam Azimuth", @@ -49,13 +53,14 @@ "group": "Selecteer entiteiten om te besturen via integratie", "sunset_position": "Positie om naar over te schakelen na zonsondergang", "sunset_offset": "Verschil (±) vanaf zonsondergang in minuten", + "sunrise_offset": "Verschil (±) vanaf zonsopkomst in minuten", "climate_mode": "Configureer variabelen voor klimaatmodus" }, "description": "Voeg configuratie variabelen toe", "title": "Verticaal scherm" }, - "climate":{ - "data":{ + "climate": { + "data": { "temp_entity": "Binnen temperatuur entiteit", "presence_entity": "Aanwezigheid entiteit (optioneel)", "weather_entity": "Weer entiteit (optioneel)", @@ -63,7 +68,7 @@ "temp_low": "Minimale comfort temperatuur", "temp_high": "Maximale comfort temperatuur" }, - "data_description":{ + "data_description": { "presence_entity": "Entiteit die de aanwezigheidsstatus van de ruimte of het huis vertegenwoordigt", "weather_entity": "Controleert weersomstandigheden, en buitentemperatuur", "outside_temp": "Overschrijft de buitentemperatuur van de weerentiteit als beide zijn ingesteld", @@ -73,11 +78,11 @@ "description": "Voeg additionele klimaat configuratie variabelen toe. Weer and Aanwezigheid entiteiten zijn optioneel", "title": "Klimaat instellingen" }, - "weather":{ - "data":{ + "weather": { + "data": { "weather_state": "Weer Condities" }, - "data_description":{ + "data_description": { "weather_state": "Kies de weersomstandigheden die automatische raambediening mogelijk maken." }, "title": "Weer Condities" @@ -99,7 +104,6 @@ "sunset_position": "Zonsondergang Posistie", "sunset_offset": "Afwijking Zonsondergang", "climate_mode": "Klimaat Modus" - }, "data_description": { "set_azimuth": "Stel Azimuth in", @@ -115,6 +119,7 @@ "group": "Selecteer entiteiten om te besturen via integratie", "sunset_position": "Positie om naar over te schakelen na zonsondergang", "sunset_offset": "Verschil (±) vanaf zonsondergang in minuten", + "sunrise_offset": "Verschil (±) vanaf zonsopkomst in minuten", "climate_mode": "Configureer variabelen voor klimaatmodus" }, "description": "Voeg configuratie variabelen toe", @@ -123,12 +128,12 @@ "tilt": { "data": { "set_azimuth": "Raam Azimuth", - "slat_depth": "Lameldiepte", - "slat_distance": "Lamelafstand", - "default_percentage": "Standaard positie", - "max_position": "Maximale positie", - "fov_left": "Links gezichtsveld", - "fov_right": "Rechts gezichtsveld", + "slat_depth": "Lameldiepte", + "slat_distance": "Lamelafstand", + "default_percentage": "Standaard positie", + "max_position": "Maximale positie", + "fov_left": "Links gezichtsveld", + "fov_right": "Rechts gezichtsveld", "group": "Cover Entities", "inverse_state": "Draai de status om (nodig voor sommige covers die omgekeerde percentages hanteren)", "sunset_position": "Zonsondergang Posistie", @@ -147,36 +152,41 @@ "group": "Selecteer entiteiten om te besturen via integratie", "sunset_position": "Positie om naar over te schakelen na zonsondergang", "sunset_offset": "Verschil (±) vanaf zonsondergang in minuten", + "sunrise_offset": "Verschil (±) vanaf zonsopkomst in minuten", "climate_mode": "Configureer variabelen voor klimaatmodus", "tilt_mode": "Kies het type beweging" }, "description": "Voeg configuratie variabelen toe", "title": "Kantelbare Cover" - } } - }, + } + }, "options": { "step": { - "init":{ - "menu_options":{ + "init": { + "menu_options": { "automation": "Wijzig Automatiseringsinstellingen", "blind": "Pas parameters van de zonwering aan" } }, "automation": { "data": { - "delta_position": "Minimale positieaanpassing", - "delta_time": "Minimale interval tussen positieveranderingen", - "start_time": "Starttijd", - "start_entity": "Entiteit die starttijd aangeeft" + "delta_position": "Minimale positieaanpassing", + "delta_time": "Minimale interval tussen positieveranderingen", + "start_time": "Starttijd", + "start_entity": "Entiteit die starttijd aangeeft", + "manual_override_duration": "Duur van handmatige overschrijving", + "manual_override_reset": "Reset handmatige overschrijvingsduur" }, "data_description": { - "delta_position": "Minimale verandering in positie vereist voordat de positie van de bekleding wordt aangepast", - "delta_time": "Minimale tijdsinterval tussen positieveranderingen; minimum is 2 minuten", - "start_time": "Starttijd voor elke dag; voor deze tijd blijft de bekleding stationair", - "start_entity": "Entiteit die de status van de starttijd vertegenwoordigt, die de hierboven ingestelde statische starttijd overschrijft. Handig voor het automatiseren van de starttijd met een entiteit" + "delta_position": "Minimale verandering in positie vereist voordat de positie van de bekleding wordt aangepast", + "delta_time": "Minimale tijdsinterval tussen positieveranderingen; minimum is 2 minuten", + "start_time": "Starttijd voor elke dag; voor deze tijd blijft de bekleding stationair", + "start_entity": "Entiteit die de status van de starttijd vertegenwoordigt, die de hierboven ingestelde statische starttijd overschrijft. Handig voor het automatiseren van de starttijd met een entiteit", + "manual_override_duration": "De duur van handmatige bediening voordat wordt teruggekeerd naar automatische bediening", + "manual_override_reset": "Optie om de duur van handmatige overschrijving na elke handmatige aanpassing te resetten; als dit is uitgeschakeld, geldt de duur alleen voor de eerste handmatige aanpassing" } - }, + }, "vertical": { "data": { "set_azimuth": "Raam Azimuth", @@ -203,13 +213,14 @@ "group": "Selecteer entiteiten om te besturen via integratie", "sunset_position": "Positie om naar over te schakelen na zonsondergang", "sunset_offset": "Verschil (±) vanaf zonsondergang in minuten", + "sunrise_offset": "Verschil (±) vanaf zonsopkomst in minuten", "climate_mode": "Configureer variabelen voor klimaatmodus" }, "description": "Voeg configuratie variabelen toe", "title": "Verticaal scherm" }, - "climate":{ - "data":{ + "climate": { + "data": { "temp_entity": "Binnen temperatuur entiteit", "presence_entity": "Aanwezigheid entiteit (optioneel)", "weather_entity": "Weer entiteit (optioneel)", @@ -217,7 +228,7 @@ "temp_low": "Minimale comfort temperatuur", "temp_high": "Maximale comfort temperatuur" }, - "data_description":{ + "data_description": { "presence_entity": "Entiteit die de aanwezigheidsstatus van de ruimte of het huis vertegenwoordigt", "weather_entity": "Controleert weersomstandigheden, en buitentemperatuur", "outside_temp": "Overschrijft de buitentemperatuur van de weerentiteit als beide zijn ingesteld", @@ -227,11 +238,11 @@ "description": "Voeg additionele klimaat configuratie variabelen toe. Weer and Aanwezigheid entiteiten zijn optioneel", "title": "Klimaat instellingen" }, - "weather":{ - "data":{ + "weather": { + "data": { "weather_state": "Weer Condities" }, - "data_description":{ + "data_description": { "weather_state": "Kies de weersomstandigheden die automatische raambediening mogelijk maken." }, "title": "Weer Condities" @@ -253,7 +264,6 @@ "sunset_position": "Zonsondergang Posistie", "sunset_offset": "Afwijking Zonsondergang", "climate_mode": "Klimaat Modus" - }, "data_description": { "set_azimuth": "Stel Azimuth in", @@ -269,6 +279,7 @@ "group": "Selecteer entiteiten om te besturen via integratie", "sunset_position": "Positie om naar over te schakelen na zonsondergang", "sunset_offset": "Verschil (±) vanaf zonsondergang in minuten", + "sunrise_offset": "Verschil (±) vanaf zonsopkomst in minuten", "climate_mode": "Configureer variabelen voor klimaatmodus" }, "description": "Voeg configuratie variabelen toe", @@ -277,12 +288,12 @@ "tilt": { "data": { "set_azimuth": "Raam Azimuth", - "slat_depth": "Lameldiepte", - "slat_distance": "Lamelafstand", - "default_percentage": "Standaard positie", - "max_position": "Maximale positie", - "fov_left": "Links gezichtsveld", - "fov_right": "Rechts gezichtsveld", + "slat_depth": "Lameldiepte", + "slat_distance": "Lamelafstand", + "default_percentage": "Standaard positie", + "max_position": "Maximale positie", + "fov_left": "Links gezichtsveld", + "fov_right": "Rechts gezichtsveld", "group": "Cover Entities", "inverse_state": "Draai de status om (nodig voor sommige covers die omgekeerde percentages hanteren)", "sunset_position": "Zonsondergang Posistie", @@ -301,17 +312,18 @@ "group": "Selecteer entiteiten om te besturen via integratie", "sunset_position": "Positie om naar over te schakelen na zonsondergang", "sunset_offset": "Verschil (±) vanaf zonsondergang in minuten", + "sunrise_offset": "Verschil (±) vanaf zonsopkomst in minuten", "climate_mode": "Configureer variabelen voor klimaatmodus", "tilt_mode": "Kies het type beweging" }, "description": "Voeg configuratie variabelen toe", "title": "Kantelbare Cover" - } - } -}, + } + } + }, "selector": { - "mode":{ - "options":{ + "mode": { + "options": { "cover_blind": "Verticaal scherm", "cover_awning": "Horizontaal scherm", "cover_tilt": "Kantelbaar scherm" From 07cfbd88da982d7f79c0d165439b87bf1aafa6f8 Mon Sep 17 00:00:00 2001 From: basbruss <68892092+basbruss@users.noreply.github.com> Date: Thu, 11 Apr 2024 15:33:17 +0200 Subject: [PATCH 13/14] update translations --- custom_components/adaptive_cover/strings.json | 642 ++++++++--------- .../adaptive_cover/translations/en.json | 654 +++++++++--------- 2 files changed, 671 insertions(+), 625 deletions(-) diff --git a/custom_components/adaptive_cover/strings.json b/custom_components/adaptive_cover/strings.json index 02d115d..ea05059 100644 --- a/custom_components/adaptive_cover/strings.json +++ b/custom_components/adaptive_cover/strings.json @@ -1,315 +1,341 @@ { "title": "Adaptive Cover", "config": { - "step": { - "user": { - "data": { - "name": "Name", - "blueprint": "Add blueprint to HomeAssistant", - "mode": "Type of blind" - } - }, - "automation": { - "data": { - "delta_position": "Minimum position adjustment", - "delta_time": "Minimum interval between position changes", - "start_time": "Starting time", - "start_entity": "Entity indicating starting time" - }, - "data_description": { - "delta_position": "Minimum change in position required before adjusting the cover's position", - "delta_time": "Minimum time interval between position changes; minimum is 2 minutes", - "start_time": "Starting time for each day; before this time, the cover will remain stationary", - "start_entity": "Entity representing starting time state, overriding the fixed start time set above. Useful for automating the start time with an entity" - } - }, - "vertical": { - "data": { - "set_azimuth": "Window Azimuth", - "window_height": "Window Height", - "distance_shaded_area": "Shaded area", - "default_percentage": "Default Position", - "max_position": "Maximum Position", - "fov_left": "Field of view left", - "fov_right": "Field of view right", - "group": "Cover Entities", - "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", - "sunset_position": "Sunset Position", - "sunset_offset": "Sunset Offset", - "climate_mode": "Climate Mode" - }, - "data_description": { - "set_azimuth": "Adjust Azimuth", - "window_height": "Specify window height in meters", - "distance_shaded_area": "Distance from cover to shaded area in meters", - "default_percentage": "Default cover position as a percentage", - "max_position": "Maximum adjustable cover position as a percentage", - "fov_left": "Field of view angle to the left of the window center", - "fov_right": "Field of view angle to the right of the window center", - "group": "Select entities to control via integration", - "sunset_position": "Position to switch to after sunset", - "sunset_offset": "Offset (±) from sunset time in minutes", - "climate_mode": "Configure variables for climate mode" - }, - "description": "Add configuration variables to the sensor", - "title": "Vertical cover" - }, - "climate": { - "data": { - "temp_entity": "Inside temperature entity", - "presence_entity": "Presence entity (optional)", - "weather_entity": "Weather entity (optional)", - "outside_temp": "Outside temperature sensor (optional)", - "temp_low": "Low temperature threshold", - "temp_high": "High temperature threshold" - }, - "data_description": { - "presence_entity": "Entity representing room or home presence status", - "weather_entity": "Monitors weather conditions, and outside temperature", - "outside_temp": "Overrides outside temperature from weather entity if both are set", - "temp_low": "Minimum comfortable temperature", - "temp_high": "Maximum comfortable temperature" - }, - "description": "Add additional climate configuration variables.", - "title": "Climate settings" - }, - "weather": { - "data": {"weather_state": "Weather Conditions"}, - "data_description": { - "weather_state": "Choose the weather conditions that enable automatic window control." - }, - "title": "Weather Conditions" - }, - "horizontal": { - "data": { - "set_azimuth": "Window Azimuth", - "height_awning": "Awning Height", - "length_awning": "Awning Span Length", - "window_height": "Window Height", - "angle": "Awning Angle", - "distance_shaded_area": "Shaded area", - "default_percentage": "Default Position", - "max_position": "Maximum Position", - "fov_left": "Field of view left", - "fov_right": "Field of view right", - "group": "Cover Entities", - "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", - "sunset_position": "Sunset Position", - "sunset_offset": "Sunset Offset", - "climate_mode": "Climate Mode" - }, - "data_description": { - "set_azimuth": "Specify the Azimuth", - "height_awning": "Adjust the height of the awning from the ground", - "window_height": "Specify the height of the window(s) in meters", - "length_awning": "Total span length in meters", - "angle": "Angle of the attached awning measured perpendicular from the wall to the ground", - "distance_shaded_area": "Distance from cover to shaded area in meters", - "default_percentage": "Default cover position as a percentage", - "max_position": "Maximum adjustable cover position as a percentage", - "fov_left": "Field of view degrees to the left of the window center", - "fov_right": "Field of view degrees to the right of the window center", - "group": "Select entities to control via integration", - "sunset_position": "Position to switch to after sunset", - "sunset_offset": "Offset (±) from sunset time in minutes", - "climate_mode": "Configure variables for climate mode" - }, - "description": "Add configuration variables to the sensor", - "title": "Horizontal cover" - }, - "tilt": { - "data": { - "set_azimuth": "Window Azimuth", - "slat_depth": "Slat Depth", - "slat_distance": "Slat Spacing", - "default_percentage": "Default Position", - "max_position": "Maximum Position", - "fov_left": "Field of view left", - "fov_right": "Field of view right", - "group": "Cover Entities", - "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", - "sunset_position": "Sunset Position", - "sunset_offset": "Sunset Offset", - "climate_mode": "Climate Mode", - "tilt_mode": "Type of movement" - }, - "data_description": { - "set_azimuth": "Specify the Azimuth", - "slat_depth": "Depth of each individual slat in centimeters", - "slat_distance": "Vertical distance between two slats in centimeters", - "default_percentage": "Default cover position as a percentage", - "max_position": "Maximum adjustable cover position as a percentage", - "fov_left": "Degrees to consider from the left side of the window center", - "fov_right": "Degrees to consider from the right side of the window center", - "group": "Select entities to control via integration", - "sunset_position": "Position to transition to after sunset", - "sunset_offset": "Offset (±) from sunset time in minutes", - "climate_mode": "Configure variables for climate mode", - "tilt_mode": "Choose the type of movement" - }, - "description": "Add configuration variables to the sensor", - "title": "Tilted cover" - } + "step": { + "user": { + "data": { + "name": "Name", + "blueprint": "Add blueprint to HomeAssistant", + "mode": "Type of blind" + } + }, + "automation": { + "data": { + "delta_position": "Minimum position adjustment", + "delta_time": "Minimum interval between position changes", + "start_time": "Starting time", + "start_entity": "Entity indicating starting time", + "manual_override_duration": "Duration of manual override", + "manual_override_reset": "Reset Manual override duration" + }, + "data_description": { + "delta_position": "Minimum change in position required before adjusting the cover's position", + "delta_time": "Minimum time interval between position changes; minimum is 2 minutes", + "start_time": "Starting time for each day; before this time, the cover will remain stationary", + "start_entity": "Entity representing starting time state, overriding the fixed start time set above. Useful for automating the start time with an entity", + "manual_override_duration": "The duration of manual control before resetting to automatic control", + "manual_override_reset": "Option to reset the manual override duration after each manual adjustment; if disabled, the duration only applies to the first manual adjustment" + } + }, + "vertical": { + "data": { + "set_azimuth": "Window Azimuth", + "window_height": "Window Height", + "distance_shaded_area": "Shaded area", + "default_percentage": "Default Position", + "max_position": "Maximum Position", + "fov_left": "Field of view left", + "fov_right": "Field of view right", + "group": "Cover Entities", + "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", + "sunset_position": "Sunset Position", + "sunset_offset": "Sunset Offset", + "sunrise_offset": "Sunrise Offset", + "climate_mode": "Climate Mode" + }, + "data_description": { + "set_azimuth": "Adjust Azimuth", + "window_height": "Specify window height in meters", + "distance_shaded_area": "Distance from cover to shaded area in meters", + "default_percentage": "Default cover position as a percentage", + "max_position": "Maximum adjustable cover position as a percentage", + "fov_left": "Field of view angle to the left of the window center", + "fov_right": "Field of view angle to the right of the window center", + "group": "Select entities to control via integration", + "sunset_position": "Position to switch to after sunset", + "sunset_offset": "Offset (±) from sunset time in minutes", + "sunrise_offset": "Offset (±) from sunrise time in minutes", + "climate_mode": "Configure variables for climate mode" + }, + "description": "Add configuration variables to the sensor", + "title": "Vertical cover" + }, + "climate": { + "data": { + "temp_entity": "Inside temperature entity", + "presence_entity": "Presence entity (optional)", + "weather_entity": "Weather entity (optional)", + "outside_temp": "Outside temperature sensor (optional)", + "temp_low": "Low temperature threshold", + "temp_high": "High temperature threshold" + }, + "data_description": { + "presence_entity": "Entity representing room or home presence status", + "weather_entity": "Monitors weather conditions, and outside temperature", + "outside_temp": "Overrides outside temperature from weather entity if both are set", + "temp_low": "Minimum comfortable temperature", + "temp_high": "Maximum comfortable temperature" + }, + "description": "Add additional climate configuration variables.", + "title": "Climate settings" + }, + "weather": { + "data": { "weather_state": "Weather Conditions" }, + "data_description": { + "weather_state": "Choose the weather conditions that enable automatic window control." + }, + "title": "Weather Conditions" + }, + "horizontal": { + "data": { + "set_azimuth": "Window Azimuth", + "height_awning": "Awning Height", + "length_awning": "Awning Span Length", + "window_height": "Window Height", + "angle": "Awning Angle", + "distance_shaded_area": "Shaded area", + "default_percentage": "Default Position", + "max_position": "Maximum Position", + "fov_left": "Field of view left", + "fov_right": "Field of view right", + "group": "Cover Entities", + "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", + "sunset_position": "Sunset Position", + "sunset_offset": "Sunset Offset", + "sunrise_offset": "Sunrise Offset", + "climate_mode": "Climate Mode" + }, + "data_description": { + "set_azimuth": "Specify the Azimuth", + "height_awning": "Adjust the height of the awning from the ground", + "window_height": "Specify the height of the window(s) in meters", + "length_awning": "Total span length in meters", + "angle": "Angle of the attached awning measured perpendicular from the wall to the ground", + "distance_shaded_area": "Distance from cover to shaded area in meters", + "default_percentage": "Default cover position as a percentage", + "max_position": "Maximum adjustable cover position as a percentage", + "fov_left": "Field of view degrees to the left of the window center", + "fov_right": "Field of view degrees to the right of the window center", + "group": "Select entities to control via integration", + "sunset_position": "Position to switch to after sunset", + "sunset_offset": "Offset (±) from sunset time in minutes", + "sunrise_offset": "Offset (±) from sunrise time in minutes", + "climate_mode": "Configure variables for climate mode" + }, + "description": "Add configuration variables to the sensor", + "title": "Horizontal cover" + }, + "tilt": { + "data": { + "set_azimuth": "Window Azimuth", + "slat_depth": "Slat Depth", + "slat_distance": "Slat Spacing", + "default_percentage": "Default Position", + "max_position": "Maximum Position", + "fov_left": "Field of view left", + "fov_right": "Field of view right", + "group": "Cover Entities", + "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", + "sunset_position": "Sunset Position", + "sunset_offset": "Sunset Offset", + "sunrise_offset": "Sunrise Offset", + "climate_mode": "Climate Mode", + "tilt_mode": "Type of movement" + }, + "data_description": { + "set_azimuth": "Specify the Azimuth", + "slat_depth": "Depth of each individual slat in centimeters", + "slat_distance": "Vertical distance between two slats in centimeters", + "default_percentage": "Default cover position as a percentage", + "max_position": "Maximum adjustable cover position as a percentage", + "fov_left": "Degrees to consider from the left side of the window center", + "fov_right": "Degrees to consider from the right side of the window center", + "group": "Select entities to control via integration", + "sunset_position": "Position to transition to after sunset", + "sunset_offset": "Offset (±) from sunset time in minutes", + "sunrise_offset": "Offset (±) from sunrise time in minutes", + "climate_mode": "Configure variables for climate mode", + "tilt_mode": "Choose the type of movement" + }, + "description": "Add configuration variables to the sensor", + "title": "Tilted cover" + } + } + }, + "options": { + "step": { + "init": { + "menu_options": { + "automation": "Modify Automation Configuration", + "blind": "Fine-tune Blind Settings" + } + }, + "automation": { + "data": { + "delta_position": "Minimum position adjustment", + "delta_time": "Minimum interval between position changes", + "start_time": "Starting time", + "start_entity": "Entity indicating starting time", + "manual_override_duration": "Duration of manual override", + "manual_override_reset": "Reset Manual override duration" + }, + "data_description": { + "delta_position": "Minimum change in position required before adjusting the cover's position", + "delta_time": "Minimum time interval between position changes; minimum is 2 minutes", + "start_time": "Starting time for each day; before this time, the cover will remain stationary", + "start_entity": "Entity representing starting time state, overriding the fixed start time set above. Useful for automating the start time with an entity", + "manual_override_duration": "The duration of manual control before resetting to automatic control", + "manual_override_reset": "Option to reset the manual override duration after each manual adjustment; if disabled, the duration only applies to the first manual adjustment" + } + }, + "vertical": { + "data": { + "set_azimuth": "Window Azimuth", + "window_height": "Window Height", + "distance_shaded_area": "Shaded area", + "default_percentage": "Default Position", + "max_position": "Maximum Position", + "fov_left": "Field of view left", + "fov_right": "Field of view right", + "group": "Cover Entities", + "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", + "sunset_position": "Sunset Position", + "sunset_offset": "Sunset Offset", + "sunrise_offset": "Sunrise Offset", + "climate_mode": "Climate Mode" + }, + "data_description": { + "set_azimuth": "Adjust Azimuth", + "window_height": "Specify window height in meters", + "distance_shaded_area": "Distance from cover to shaded area in meters", + "default_percentage": "Default cover position as a percentage", + "max_position": "Maximum adjustable cover position as a percentage", + "fov_left": "Field of view angle to the left of the window center", + "fov_right": "Field of view angle to the right of the window center", + "group": "Select entities to control via integration", + "sunset_position": "Position to switch to after sunset", + "sunset_offset": "Offset (±) from sunset time in minutes", + "sunrise_offset": "Offset (±) from sunrise time in minutes", + "climate_mode": "Configure variables for climate mode" + }, + "description": "Add configuration variables to the sensor", + "title": "Vertical cover" + }, + "climate": { + "data": { + "temp_entity": "Inside temperature entity", + "presence_entity": "Presence entity (optional)", + "weather_entity": "Weather entity (optional)", + "outside_temp": "Outside temperature sensor (optional)", + "temp_low": "Low temperature threshold", + "temp_high": "High temperature threshold" + }, + "data_description": { + "presence_entity": "Entity representing room or home presence status", + "weather_entity": "Monitors weather conditions, and outside temperature", + "outside_temp": "Overrides outside temperature from weather entity if both are set", + "temp_low": "Minimum comfortable temperature", + "temp_high": "Maximum comfortable temperature" + }, + "description": "Add additional climate configuration variables.", + "title": "Climate settings" + }, + "weather": { + "data": { "weather_state": "Weather Conditions" }, + "data_description": { + "weather_state": "Choose the weather conditions that enable automatic window control." + }, + "title": "Weather Conditions" + }, + "horizontal": { + "data": { + "set_azimuth": "Window Azimuth", + "height_awning": "Awning Height", + "length_awning": "Awning Span Length", + "window_height": "Window Height", + "angle": "Awning Angle", + "distance_shaded_area": "Shaded area", + "default_percentage": "Default Position", + "max_position": "Maximum Position", + "fov_left": "Field of view left", + "fov_right": "Field of view right", + "group": "Cover Entities", + "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", + "sunset_position": "Sunset Position", + "sunset_offset": "Sunset Offset", + "sunrise_offset": "Sunrise Offset", + "climate_mode": "Climate Mode" + }, + "data_description": { + "set_azimuth": "Specify the Azimuth", + "height_awning": "Adjust the height of the awning from the ground", + "window_height": "Specify the height of the window(s) in meters", + "length_awning": "Total span length in meters", + "angle": "Angle of the attached awning measured perpendicular from the wall to the ground", + "distance_shaded_area": "Distance from cover to shaded area in meters", + "default_percentage": "Default cover position as a percentage", + "max_position": "Maximum adjustable cover position as a percentage", + "fov_left": "Field of view degrees to the left of the window center", + "fov_right": "Field of view degrees to the right of the window center", + "group": "Select entities to control via integration", + "sunset_position": "Position to switch to after sunset", + "sunset_offset": "Offset (±) from sunset time in minutes", + "sunrise_offset": "Offset (±) from sunrise time in minutes", + "climate_mode": "Configure variables for climate mode" + }, + "description": "Add configuration variables to the sensor", + "title": "Horizontal cover" + }, + "tilt": { + "data": { + "set_azimuth": "Window Azimuth", + "slat_depth": "Slat Depth", + "slat_distance": "Slat Spacing", + "default_percentage": "Default Position", + "max_position": "Maximum Position", + "fov_left": "Field of view left", + "fov_right": "Field of view right", + "group": "Cover Entities", + "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", + "sunset_position": "Sunset Position", + "sunset_offset": "Sunset Offset", + "sunrise_offset": "Sunrise Offset", + "climate_mode": "Climate Mode", + "tilt_mode": "Type of movement" + }, + "data_description": { + "set_azimuth": "Specify the Azimuth", + "slat_depth": "Depth of each individual slat in centimeters", + "slat_distance": "Vertical distance between two slats in centimeters", + "default_percentage": "Default cover position as a percentage", + "max_position": "Maximum adjustable cover position as a percentage", + "fov_left": "Degrees to consider from the left side of the window center", + "fov_right": "Degrees to consider from the right side of the window center", + "group": "Select entities to control via integration", + "sunset_position": "Position to transition to after sunset", + "sunset_offset": "Offset (±) from sunset time in minutes", + "sunrise_offset": "Offset (±) from sunrise time in minutes", + "climate_mode": "Configure variables for climate mode", + "tilt_mode": "Choose the type of movement" + }, + "description": "Add configuration variables to the sensor", + "title": "Tilted cover" + } + } + }, + "selector": { + "mode": { + "options": { + "cover_blind": "Vertical blind", + "cover_awning": "Horizontal blind", + "cover_tilt": "Tilted blind" } }, + "tilt_mode": { "options": { - "step": { - "automation": { - "data": { - "delta_position": "Minimum position adjustment", - "delta_time": "Minimum interval between position changes", - "start_time": "Starting time", - "start_entity": "Entity indicating starting time" - }, - "data_description": { - "delta_position": "Minimum change in position required before adjusting the cover's position", - "delta_time": "Minimum time interval between position changes; minimum is 2 minutes", - "start_time": "Starting time for each day; before this time, the cover will remain stationary", - "start_entity": "Entity representing starting time state, overriding the fixed start time set above. Useful for automating the start time with an entity" - } - }, - "vertical": { - "data": { - "set_azimuth": "Window Azimuth", - "window_height": "Window Height", - "distance_shaded_area": "Shaded area", - "default_percentage": "Default Position", - "max_position": "Maximum Position", - "fov_left": "Field of view left", - "fov_right": "Field of view right", - "group": "Cover Entities", - "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", - "sunset_position": "Sunset Position", - "sunset_offset": "Sunset Offset", - "climate_mode": "Climate Mode" - }, - "data_description": { - "set_azimuth": "Adjust Azimuth", - "window_height": "Specify window height in meters", - "distance_shaded_area": "Distance from cover to shaded area in meters", - "default_percentage": "Default cover position as a percentage", - "max_position": "Maximum adjustable cover position as a percentage", - "fov_left": "Field of view angle to the left of the window center", - "fov_right": "Field of view angle to the right of the window center", - "group": "Select entities to control via integration", - "sunset_position": "Position to switch to after sunset", - "sunset_offset": "Offset (±) from sunset time in minutes", - "climate_mode": "Configure variables for climate mode" - }, - "description": "Add configuration variables to the sensor", - "title": "Vertical cover" - }, - "climate": { - "data": { - "temp_entity": "Inside temperature entity", - "presence_entity": "Presence entity (optional)", - "weather_entity": "Weather entity (optional)", - "outside_temp": "Outside temperature sensor (optional)", - "temp_low": "Low temperature threshold", - "temp_high": "High temperature threshold" - }, - "data_description": { - "presence_entity": "Entity representing room or home presence status", - "weather_entity": "Monitors weather conditions, and outside temperature", - "outside_temp": "Overrides outside temperature from weather entity if both are set", - "temp_low": "Minimum comfortable temperature", - "temp_high": "Maximum comfortable temperature" - }, - "description": "Add additional climate configuration variables.", - "title": "Climate settings" - }, - "weather": { - "data": {"weather_state": "Weather Conditions"}, - "data_description": { - "weather_state": "Choose the weather conditions that enable automatic window control." - }, - "title": "Weather Conditions" - }, - "horizontal": { - "data": { - "set_azimuth": "Window Azimuth", - "height_awning": "Awning Height", - "length_awning": "Awning Span Length", - "window_height": "Window Height", - "angle": "Awning Angle", - "distance_shaded_area": "Shaded area", - "default_percentage": "Default Position", - "max_position": "Maximum Position", - "fov_left": "Field of view left", - "fov_right": "Field of view right", - "group": "Cover Entities", - "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", - "sunset_position": "Sunset Position", - "sunset_offset": "Sunset Offset", - "climate_mode": "Climate Mode" - }, - "data_description": { - "set_azimuth": "Specify the Azimuth", - "height_awning": "Adjust the height of the awning from the ground", - "window_height": "Specify the height of the window(s) in meters", - "length_awning": "Total span length in meters", - "angle": "Angle of the attached awning measured perpendicular from the wall to the ground", - "distance_shaded_area": "Distance from cover to shaded area in meters", - "default_percentage": "Default cover position as a percentage", - "max_position": "Maximum adjustable cover position as a percentage", - "fov_left": "Field of view degrees to the left of the window center", - "fov_right": "Field of view degrees to the right of the window center", - "group": "Select entities to control via integration", - "sunset_position": "Position to switch to after sunset", - "sunset_offset": "Offset (±) from sunset time in minutes", - "climate_mode": "Configure variables for climate mode" - }, - "description": "Add configuration variables to the sensor", - "title": "Horizontal cover" - }, - "tilt": { - "data": { - "set_azimuth": "Window Azimuth", - "slat_depth": "Slat Depth", - "slat_distance": "Slat Spacing", - "default_percentage": "Default Position", - "max_position": "Maximum Position", - "fov_left": "Field of view left", - "fov_right": "Field of view right", - "group": "Cover Entities", - "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", - "sunset_position": "Sunset Position", - "sunset_offset": "Sunset Offset", - "climate_mode": "Climate Mode", - "tilt_mode": "Type of movement" - }, - "data_description": { - "set_azimuth": "Specify the Azimuth", - "slat_depth": "Depth of each individual slat in centimeters", - "slat_distance": "Vertical distance between two slats in centimeters", - "default_percentage": "Default cover position as a percentage", - "max_position": "Maximum adjustable cover position as a percentage", - "fov_left": "Degrees to consider from the left side of the window center", - "fov_right": "Degrees to consider from the right side of the window center", - "group": "Select entities to control via integration", - "sunset_position": "Position to transition to after sunset", - "sunset_offset": "Offset (±) from sunset time in minutes", - "climate_mode": "Configure variables for climate mode", - "tilt_mode": "Choose the type of movement" - }, - "description": "Add configuration variables to the sensor", - "title": "Tilted cover" - } - } - }, - "selector": { - "mode": { - "options": { - "cover_blind": "Vertical blind", - "cover_awning": "Horizontal blind", - "cover_tilt": "Tilted blind" - } - }, - "tilt_mode": { - "options": { - "mode1": "single direction (0% = closed / 100% = open)", - "mode2": "bi-directional (0% = closed / 50% = open / 100% = closed)" - } - } - } + "mode1": "single direction (0% = closed / 100% = open)", + "mode2": "bi-directional (0% = closed / 50% = open / 100% = closed)" } + } + } +} diff --git a/custom_components/adaptive_cover/translations/en.json b/custom_components/adaptive_cover/translations/en.json index e2ed439..ea05059 100644 --- a/custom_components/adaptive_cover/translations/en.json +++ b/custom_components/adaptive_cover/translations/en.json @@ -1,321 +1,341 @@ { - "title": "Adaptive Cover", - "config": { - "step": { - "user": { - "data": { - "name": "Name", - "blueprint": "Add blueprint to HomeAssistant", - "mode": "Type of blind" - } - }, - "automation": { - "data": { - "delta_position": "Minimum position adjustment", - "delta_time": "Minimum interval between position changes", - "start_time": "Starting time", - "start_entity": "Entity indicating starting time" - }, - "data_description": { - "delta_position": "Minimum change in position required before adjusting the cover's position", - "delta_time": "Minimum time interval between position changes; minimum is 2 minutes", - "start_time": "Starting time for each day; before this time, the cover will remain stationary", - "start_entity": "Entity representing starting time state, overriding the fixed start time set above. Useful for automating the start time with an entity" - } - }, - "vertical": { - "data": { - "set_azimuth": "Window Azimuth", - "window_height": "Window Height", - "distance_shaded_area": "Shaded area", - "default_percentage": "Default Position", - "max_position": "Maximum Position", - "fov_left": "Field of view left", - "fov_right": "Field of view right", - "group": "Cover Entities", - "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", - "sunset_position": "Sunset Position", - "sunset_offset": "Sunset Offset", - "climate_mode": "Climate Mode" - }, - "data_description": { - "set_azimuth": "Adjust Azimuth", - "window_height": "Specify window height in meters", - "distance_shaded_area": "Distance from cover to shaded area in meters", - "default_percentage": "Default cover position as a percentage", - "max_position": "Maximum adjustable cover position as a percentage", - "fov_left": "Field of view angle to the left of the window center", - "fov_right": "Field of view angle to the right of the window center", - "group": "Select entities to control via integration", - "sunset_position": "Position to switch to after sunset", - "sunset_offset": "Offset (±) from sunset time in minutes", - "climate_mode": "Configure variables for climate mode" - }, - "description": "Add configuration variables to the sensor", - "title": "Vertical cover" - }, - "climate": { - "data": { - "temp_entity": "Inside temperature entity", - "presence_entity": "Presence entity (optional)", - "weather_entity": "Weather entity (optional)", - "outside_temp": "Outside temperature sensor (optional)", - "temp_low": "Low temperature threshold", - "temp_high": "High temperature threshold" - }, - "data_description": { - "presence_entity": "Entity representing room or home presence status", - "weather_entity": "Monitors weather conditions, and outside temperature", - "outside_temp": "Overrides outside temperature from weather entity if both are set", - "temp_low": "Minimum comfortable temperature", - "temp_high": "Maximum comfortable temperature" - }, - "description": "Add additional climate configuration variables.", - "title": "Climate settings" - }, - "weather": { - "data": {"weather_state": "Weather Conditions"}, - "data_description": { - "weather_state": "Choose the weather conditions that enable automatic window control." - }, - "title": "Weather Conditions" - }, - "horizontal": { - "data": { - "set_azimuth": "Window Azimuth", - "height_awning": "Awning Height", - "length_awning": "Awning Span Length", - "window_height": "Window Height", - "angle": "Awning Angle", - "distance_shaded_area": "Shaded area", - "default_percentage": "Default Position", - "max_position": "Maximum Position", - "fov_left": "Field of view left", - "fov_right": "Field of view right", - "group": "Cover Entities", - "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", - "sunset_position": "Sunset Position", - "sunset_offset": "Sunset Offset", - "climate_mode": "Climate Mode" - }, - "data_description": { - "set_azimuth": "Specify the Azimuth", - "height_awning": "Adjust the height of the awning from the ground", - "window_height": "Specify the height of the window(s) in meters", - "length_awning": "Total span length in meters", - "angle": "Angle of the attached awning measured perpendicular from the wall to the ground", - "distance_shaded_area": "Distance from cover to shaded area in meters", - "default_percentage": "Default cover position as a percentage", - "max_position": "Maximum adjustable cover position as a percentage", - "fov_left": "Field of view degrees to the left of the window center", - "fov_right": "Field of view degrees to the right of the window center", - "group": "Select entities to control via integration", - "sunset_position": "Position to switch to after sunset", - "sunset_offset": "Offset (±) from sunset time in minutes", - "climate_mode": "Configure variables for climate mode" - }, - "description": "Add configuration variables to the sensor", - "title": "Horizontal cover" - }, - "tilt": { - "data": { - "set_azimuth": "Window Azimuth", - "slat_depth": "Slat Depth", - "slat_distance": "Slat Spacing", - "default_percentage": "Default Position", - "max_position": "Maximum Position", - "fov_left": "Field of view left", - "fov_right": "Field of view right", - "group": "Cover Entities", - "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", - "sunset_position": "Sunset Position", - "sunset_offset": "Sunset Offset", - "climate_mode": "Climate Mode", - "tilt_mode": "Type of movement" - }, - "data_description": { - "set_azimuth": "Specify the Azimuth", - "slat_depth": "Depth of each individual slat in centimeters", - "slat_distance": "Vertical distance between two slats in centimeters", - "default_percentage": "Default cover position as a percentage", - "max_position": "Maximum adjustable cover position as a percentage", - "fov_left": "Degrees to consider from the left side of the window center", - "fov_right": "Degrees to consider from the right side of the window center", - "group": "Select entities to control via integration", - "sunset_position": "Position to transition to after sunset", - "sunset_offset": "Offset (±) from sunset time in minutes", - "climate_mode": "Configure variables for climate mode", - "tilt_mode": "Choose the type of movement" - }, - "description": "Add configuration variables to the sensor", - "title": "Tilted cover" - } + "title": "Adaptive Cover", + "config": { + "step": { + "user": { + "data": { + "name": "Name", + "blueprint": "Add blueprint to HomeAssistant", + "mode": "Type of blind" } }, - "options": { - "step": { - "init":{ - "menu_options":{ - "automation": "Modify Automation Configuration", - "blind": "Fine-tune Blind Settings" - } - }, - "automation": { - "data": { - "delta_position": "Minimum position adjustment", - "delta_time": "Minimum interval between position changes", - "start_time": "Starting time", - "start_entity": "Entity indicating starting time" - }, - "data_description": { - "delta_position": "Minimum change in position required before adjusting the cover's position", - "delta_time": "Minimum time interval between position changes; minimum is 2 minutes", - "start_time": "Starting time for each day; before this time, the cover will remain stationary", - "start_entity": "Entity representing starting time state, overriding the fixed start time set above. Useful for automating the start time with an entity" - } - }, - "vertical": { - "data": { - "set_azimuth": "Window Azimuth", - "window_height": "Window Height", - "distance_shaded_area": "Shaded area", - "default_percentage": "Default Position", - "max_position": "Maximum Position", - "fov_left": "Field of view left", - "fov_right": "Field of view right", - "group": "Cover Entities", - "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", - "sunset_position": "Sunset Position", - "sunset_offset": "Sunset Offset", - "climate_mode": "Climate Mode" - }, - "data_description": { - "set_azimuth": "Adjust Azimuth", - "window_height": "Specify window height in meters", - "distance_shaded_area": "Distance from cover to shaded area in meters", - "default_percentage": "Default cover position as a percentage", - "max_position": "Maximum adjustable cover position as a percentage", - "fov_left": "Field of view angle to the left of the window center", - "fov_right": "Field of view angle to the right of the window center", - "group": "Select entities to control via integration", - "sunset_position": "Position to switch to after sunset", - "sunset_offset": "Offset (±) from sunset time in minutes", - "climate_mode": "Configure variables for climate mode" - }, - "description": "Add configuration variables to the sensor", - "title": "Vertical cover" - }, - "climate": { - "data": { - "temp_entity": "Inside temperature entity", - "presence_entity": "Presence entity (optional)", - "weather_entity": "Weather entity (optional)", - "outside_temp": "Outside temperature sensor (optional)", - "temp_low": "Low temperature threshold", - "temp_high": "High temperature threshold" - }, - "data_description": { - "presence_entity": "Entity representing room or home presence status", - "weather_entity": "Monitors weather conditions, and outside temperature", - "outside_temp": "Overrides outside temperature from weather entity if both are set", - "temp_low": "Minimum comfortable temperature", - "temp_high": "Maximum comfortable temperature" - }, - "description": "Add additional climate configuration variables.", - "title": "Climate settings" - }, - "weather": { - "data": {"weather_state": "Weather Conditions"}, - "data_description": { - "weather_state": "Choose the weather conditions that enable automatic window control." - }, - "title": "Weather Conditions" - }, - "horizontal": { - "data": { - "set_azimuth": "Window Azimuth", - "height_awning": "Awning Height", - "length_awning": "Awning Span Length", - "window_height": "Window Height", - "angle": "Awning Angle", - "distance_shaded_area": "Shaded area", - "default_percentage": "Default Position", - "max_position": "Maximum Position", - "fov_left": "Field of view left", - "fov_right": "Field of view right", - "group": "Cover Entities", - "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", - "sunset_position": "Sunset Position", - "sunset_offset": "Sunset Offset", - "climate_mode": "Climate Mode" - }, - "data_description": { - "set_azimuth": "Specify the Azimuth", - "height_awning": "Adjust the height of the awning from the ground", - "window_height": "Specify the height of the window(s) in meters", - "length_awning": "Total span length in meters", - "angle": "Angle of the attached awning measured perpendicular from the wall to the ground", - "distance_shaded_area": "Distance from cover to shaded area in meters", - "default_percentage": "Default cover position as a percentage", - "max_position": "Maximum adjustable cover position as a percentage", - "fov_left": "Field of view degrees to the left of the window center", - "fov_right": "Field of view degrees to the right of the window center", - "group": "Select entities to control via integration", - "sunset_position": "Position to switch to after sunset", - "sunset_offset": "Offset (±) from sunset time in minutes", - "climate_mode": "Configure variables for climate mode" - }, - "description": "Add configuration variables to the sensor", - "title": "Horizontal cover" - }, - "tilt": { - "data": { - "set_azimuth": "Window Azimuth", - "slat_depth": "Slat Depth", - "slat_distance": "Slat Spacing", - "default_percentage": "Default Position", - "max_position": "Maximum Position", - "fov_left": "Field of view left", - "fov_right": "Field of view right", - "group": "Cover Entities", - "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", - "sunset_position": "Sunset Position", - "sunset_offset": "Sunset Offset", - "climate_mode": "Climate Mode", - "tilt_mode": "Type of movement" - }, - "data_description": { - "set_azimuth": "Specify the Azimuth", - "slat_depth": "Depth of each individual slat in centimeters", - "slat_distance": "Vertical distance between two slats in centimeters", - "default_percentage": "Default cover position as a percentage", - "max_position": "Maximum adjustable cover position as a percentage", - "fov_left": "Degrees to consider from the left side of the window center", - "fov_right": "Degrees to consider from the right side of the window center", - "group": "Select entities to control via integration", - "sunset_position": "Position to transition to after sunset", - "sunset_offset": "Offset (±) from sunset time in minutes", - "climate_mode": "Configure variables for climate mode", - "tilt_mode": "Choose the type of movement" - }, - "description": "Add configuration variables to the sensor", - "title": "Tilted cover" - } - } - }, - "selector": { - "mode": { - "options": { - "cover_blind": "Vertical blind", - "cover_awning": "Horizontal blind", - "cover_tilt": "Tilted blind" - } - }, - "tilt_mode": { - "options": { - "mode1": "single direction (0% = closed / 100% = open)", - "mode2": "bi-directional (0% = closed / 50% = open / 100% = closed)" - } - } - } + "automation": { + "data": { + "delta_position": "Minimum position adjustment", + "delta_time": "Minimum interval between position changes", + "start_time": "Starting time", + "start_entity": "Entity indicating starting time", + "manual_override_duration": "Duration of manual override", + "manual_override_reset": "Reset Manual override duration" + }, + "data_description": { + "delta_position": "Minimum change in position required before adjusting the cover's position", + "delta_time": "Minimum time interval between position changes; minimum is 2 minutes", + "start_time": "Starting time for each day; before this time, the cover will remain stationary", + "start_entity": "Entity representing starting time state, overriding the fixed start time set above. Useful for automating the start time with an entity", + "manual_override_duration": "The duration of manual control before resetting to automatic control", + "manual_override_reset": "Option to reset the manual override duration after each manual adjustment; if disabled, the duration only applies to the first manual adjustment" } + }, + "vertical": { + "data": { + "set_azimuth": "Window Azimuth", + "window_height": "Window Height", + "distance_shaded_area": "Shaded area", + "default_percentage": "Default Position", + "max_position": "Maximum Position", + "fov_left": "Field of view left", + "fov_right": "Field of view right", + "group": "Cover Entities", + "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", + "sunset_position": "Sunset Position", + "sunset_offset": "Sunset Offset", + "sunrise_offset": "Sunrise Offset", + "climate_mode": "Climate Mode" + }, + "data_description": { + "set_azimuth": "Adjust Azimuth", + "window_height": "Specify window height in meters", + "distance_shaded_area": "Distance from cover to shaded area in meters", + "default_percentage": "Default cover position as a percentage", + "max_position": "Maximum adjustable cover position as a percentage", + "fov_left": "Field of view angle to the left of the window center", + "fov_right": "Field of view angle to the right of the window center", + "group": "Select entities to control via integration", + "sunset_position": "Position to switch to after sunset", + "sunset_offset": "Offset (±) from sunset time in minutes", + "sunrise_offset": "Offset (±) from sunrise time in minutes", + "climate_mode": "Configure variables for climate mode" + }, + "description": "Add configuration variables to the sensor", + "title": "Vertical cover" + }, + "climate": { + "data": { + "temp_entity": "Inside temperature entity", + "presence_entity": "Presence entity (optional)", + "weather_entity": "Weather entity (optional)", + "outside_temp": "Outside temperature sensor (optional)", + "temp_low": "Low temperature threshold", + "temp_high": "High temperature threshold" + }, + "data_description": { + "presence_entity": "Entity representing room or home presence status", + "weather_entity": "Monitors weather conditions, and outside temperature", + "outside_temp": "Overrides outside temperature from weather entity if both are set", + "temp_low": "Minimum comfortable temperature", + "temp_high": "Maximum comfortable temperature" + }, + "description": "Add additional climate configuration variables.", + "title": "Climate settings" + }, + "weather": { + "data": { "weather_state": "Weather Conditions" }, + "data_description": { + "weather_state": "Choose the weather conditions that enable automatic window control." + }, + "title": "Weather Conditions" + }, + "horizontal": { + "data": { + "set_azimuth": "Window Azimuth", + "height_awning": "Awning Height", + "length_awning": "Awning Span Length", + "window_height": "Window Height", + "angle": "Awning Angle", + "distance_shaded_area": "Shaded area", + "default_percentage": "Default Position", + "max_position": "Maximum Position", + "fov_left": "Field of view left", + "fov_right": "Field of view right", + "group": "Cover Entities", + "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", + "sunset_position": "Sunset Position", + "sunset_offset": "Sunset Offset", + "sunrise_offset": "Sunrise Offset", + "climate_mode": "Climate Mode" + }, + "data_description": { + "set_azimuth": "Specify the Azimuth", + "height_awning": "Adjust the height of the awning from the ground", + "window_height": "Specify the height of the window(s) in meters", + "length_awning": "Total span length in meters", + "angle": "Angle of the attached awning measured perpendicular from the wall to the ground", + "distance_shaded_area": "Distance from cover to shaded area in meters", + "default_percentage": "Default cover position as a percentage", + "max_position": "Maximum adjustable cover position as a percentage", + "fov_left": "Field of view degrees to the left of the window center", + "fov_right": "Field of view degrees to the right of the window center", + "group": "Select entities to control via integration", + "sunset_position": "Position to switch to after sunset", + "sunset_offset": "Offset (±) from sunset time in minutes", + "sunrise_offset": "Offset (±) from sunrise time in minutes", + "climate_mode": "Configure variables for climate mode" + }, + "description": "Add configuration variables to the sensor", + "title": "Horizontal cover" + }, + "tilt": { + "data": { + "set_azimuth": "Window Azimuth", + "slat_depth": "Slat Depth", + "slat_distance": "Slat Spacing", + "default_percentage": "Default Position", + "max_position": "Maximum Position", + "fov_left": "Field of view left", + "fov_right": "Field of view right", + "group": "Cover Entities", + "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", + "sunset_position": "Sunset Position", + "sunset_offset": "Sunset Offset", + "sunrise_offset": "Sunrise Offset", + "climate_mode": "Climate Mode", + "tilt_mode": "Type of movement" + }, + "data_description": { + "set_azimuth": "Specify the Azimuth", + "slat_depth": "Depth of each individual slat in centimeters", + "slat_distance": "Vertical distance between two slats in centimeters", + "default_percentage": "Default cover position as a percentage", + "max_position": "Maximum adjustable cover position as a percentage", + "fov_left": "Degrees to consider from the left side of the window center", + "fov_right": "Degrees to consider from the right side of the window center", + "group": "Select entities to control via integration", + "sunset_position": "Position to transition to after sunset", + "sunset_offset": "Offset (±) from sunset time in minutes", + "sunrise_offset": "Offset (±) from sunrise time in minutes", + "climate_mode": "Configure variables for climate mode", + "tilt_mode": "Choose the type of movement" + }, + "description": "Add configuration variables to the sensor", + "title": "Tilted cover" + } + } + }, + "options": { + "step": { + "init": { + "menu_options": { + "automation": "Modify Automation Configuration", + "blind": "Fine-tune Blind Settings" + } + }, + "automation": { + "data": { + "delta_position": "Minimum position adjustment", + "delta_time": "Minimum interval between position changes", + "start_time": "Starting time", + "start_entity": "Entity indicating starting time", + "manual_override_duration": "Duration of manual override", + "manual_override_reset": "Reset Manual override duration" + }, + "data_description": { + "delta_position": "Minimum change in position required before adjusting the cover's position", + "delta_time": "Minimum time interval between position changes; minimum is 2 minutes", + "start_time": "Starting time for each day; before this time, the cover will remain stationary", + "start_entity": "Entity representing starting time state, overriding the fixed start time set above. Useful for automating the start time with an entity", + "manual_override_duration": "The duration of manual control before resetting to automatic control", + "manual_override_reset": "Option to reset the manual override duration after each manual adjustment; if disabled, the duration only applies to the first manual adjustment" + } + }, + "vertical": { + "data": { + "set_azimuth": "Window Azimuth", + "window_height": "Window Height", + "distance_shaded_area": "Shaded area", + "default_percentage": "Default Position", + "max_position": "Maximum Position", + "fov_left": "Field of view left", + "fov_right": "Field of view right", + "group": "Cover Entities", + "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", + "sunset_position": "Sunset Position", + "sunset_offset": "Sunset Offset", + "sunrise_offset": "Sunrise Offset", + "climate_mode": "Climate Mode" + }, + "data_description": { + "set_azimuth": "Adjust Azimuth", + "window_height": "Specify window height in meters", + "distance_shaded_area": "Distance from cover to shaded area in meters", + "default_percentage": "Default cover position as a percentage", + "max_position": "Maximum adjustable cover position as a percentage", + "fov_left": "Field of view angle to the left of the window center", + "fov_right": "Field of view angle to the right of the window center", + "group": "Select entities to control via integration", + "sunset_position": "Position to switch to after sunset", + "sunset_offset": "Offset (±) from sunset time in minutes", + "sunrise_offset": "Offset (±) from sunrise time in minutes", + "climate_mode": "Configure variables for climate mode" + }, + "description": "Add configuration variables to the sensor", + "title": "Vertical cover" + }, + "climate": { + "data": { + "temp_entity": "Inside temperature entity", + "presence_entity": "Presence entity (optional)", + "weather_entity": "Weather entity (optional)", + "outside_temp": "Outside temperature sensor (optional)", + "temp_low": "Low temperature threshold", + "temp_high": "High temperature threshold" + }, + "data_description": { + "presence_entity": "Entity representing room or home presence status", + "weather_entity": "Monitors weather conditions, and outside temperature", + "outside_temp": "Overrides outside temperature from weather entity if both are set", + "temp_low": "Minimum comfortable temperature", + "temp_high": "Maximum comfortable temperature" + }, + "description": "Add additional climate configuration variables.", + "title": "Climate settings" + }, + "weather": { + "data": { "weather_state": "Weather Conditions" }, + "data_description": { + "weather_state": "Choose the weather conditions that enable automatic window control." + }, + "title": "Weather Conditions" + }, + "horizontal": { + "data": { + "set_azimuth": "Window Azimuth", + "height_awning": "Awning Height", + "length_awning": "Awning Span Length", + "window_height": "Window Height", + "angle": "Awning Angle", + "distance_shaded_area": "Shaded area", + "default_percentage": "Default Position", + "max_position": "Maximum Position", + "fov_left": "Field of view left", + "fov_right": "Field of view right", + "group": "Cover Entities", + "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", + "sunset_position": "Sunset Position", + "sunset_offset": "Sunset Offset", + "sunrise_offset": "Sunrise Offset", + "climate_mode": "Climate Mode" + }, + "data_description": { + "set_azimuth": "Specify the Azimuth", + "height_awning": "Adjust the height of the awning from the ground", + "window_height": "Specify the height of the window(s) in meters", + "length_awning": "Total span length in meters", + "angle": "Angle of the attached awning measured perpendicular from the wall to the ground", + "distance_shaded_area": "Distance from cover to shaded area in meters", + "default_percentage": "Default cover position as a percentage", + "max_position": "Maximum adjustable cover position as a percentage", + "fov_left": "Field of view degrees to the left of the window center", + "fov_right": "Field of view degrees to the right of the window center", + "group": "Select entities to control via integration", + "sunset_position": "Position to switch to after sunset", + "sunset_offset": "Offset (±) from sunset time in minutes", + "sunrise_offset": "Offset (±) from sunrise time in minutes", + "climate_mode": "Configure variables for climate mode" + }, + "description": "Add configuration variables to the sensor", + "title": "Horizontal cover" + }, + "tilt": { + "data": { + "set_azimuth": "Window Azimuth", + "slat_depth": "Slat Depth", + "slat_distance": "Slat Spacing", + "default_percentage": "Default Position", + "max_position": "Maximum Position", + "fov_left": "Field of view left", + "fov_right": "Field of view right", + "group": "Cover Entities", + "inverse_state": "Inverse the state (needed for some covers that don't follow HA guidelines)", + "sunset_position": "Sunset Position", + "sunset_offset": "Sunset Offset", + "sunrise_offset": "Sunrise Offset", + "climate_mode": "Climate Mode", + "tilt_mode": "Type of movement" + }, + "data_description": { + "set_azimuth": "Specify the Azimuth", + "slat_depth": "Depth of each individual slat in centimeters", + "slat_distance": "Vertical distance between two slats in centimeters", + "default_percentage": "Default cover position as a percentage", + "max_position": "Maximum adjustable cover position as a percentage", + "fov_left": "Degrees to consider from the left side of the window center", + "fov_right": "Degrees to consider from the right side of the window center", + "group": "Select entities to control via integration", + "sunset_position": "Position to transition to after sunset", + "sunset_offset": "Offset (±) from sunset time in minutes", + "sunrise_offset": "Offset (±) from sunrise time in minutes", + "climate_mode": "Configure variables for climate mode", + "tilt_mode": "Choose the type of movement" + }, + "description": "Add configuration variables to the sensor", + "title": "Tilted cover" + } + } + }, + "selector": { + "mode": { + "options": { + "cover_blind": "Vertical blind", + "cover_awning": "Horizontal blind", + "cover_tilt": "Tilted blind" + } + }, + "tilt_mode": { + "options": { + "mode1": "single direction (0% = closed / 100% = open)", + "mode2": "bi-directional (0% = closed / 50% = open / 100% = closed)" + } + } + } +} From e5761da064c027d22798adacb09817b9edc1f97b Mon Sep 17 00:00:00 2001 From: basbruss <68892092+basbruss@users.noreply.github.com> Date: Thu, 11 Apr 2024 15:36:07 +0200 Subject: [PATCH 14/14] Update coordinator.py --- custom_components/adaptive_cover/coordinator.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/custom_components/adaptive_cover/coordinator.py b/custom_components/adaptive_cover/coordinator.py index 2bb1ac0..1256387 100644 --- a/custom_components/adaptive_cover/coordinator.py +++ b/custom_components/adaptive_cover/coordinator.py @@ -41,6 +41,8 @@ CONF_HEIGHT_WIN, CONF_INVERSE_STATE, CONF_LENGTH_AWNING, + CONF_MANUAL_OVERRIDE_DURATION, + CONF_MANUAL_OVERRIDE_RESET, CONF_MAX_POSITION, CONF_OUTSIDETEMP_ENTITY, CONF_PRESENCE_ENTITY,