From 002165c9a827241e13b00e3fa757a62b3c7ec313 Mon Sep 17 00:00:00 2001 From: gvigroux Date: Sat, 11 Jan 2025 19:02:17 +0100 Subject: [PATCH] v0.7.4 --- custom_components/freebox_home/__init__.py | 1 + .../freebox_home/alarm_control_panel.py | 74 ++++++++++++------- custom_components/freebox_home/config_flow.py | 7 +- custom_components/freebox_home/manifest.json | 2 +- custom_components/freebox_home/router.py | 28 ++++++- 5 files changed, 78 insertions(+), 34 deletions(-) diff --git a/custom_components/freebox_home/__init__.py b/custom_components/freebox_home/__init__.py index 095ab9d..f82966e 100644 --- a/custom_components/freebox_home/__init__.py +++ b/custom_components/freebox_home/__init__.py @@ -71,5 +71,6 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry): if unload_ok: router = hass.data[DOMAIN].pop(entry.unique_id) await router.close() + await router.remove_config(hass, entry.data[CONF_HOST]) return unload_ok diff --git a/custom_components/freebox_home/alarm_control_panel.py b/custom_components/freebox_home/alarm_control_panel.py index 6e9dd04..7e12a3b 100644 --- a/custom_components/freebox_home/alarm_control_panel.py +++ b/custom_components/freebox_home/alarm_control_panel.py @@ -55,14 +55,15 @@ def __init__(self, hass, router: FreeboxRouter, node: Dict[str, any]) -> None: self._command_timeout3 = self.get_command_id(node['type']['endpoints'], "slot", "timeout3") # Durée de la sirène self._command_state = self.get_command_id(node['type']['endpoints'], "signal", "state" ) - self.set_state("idle") + #self.set_state("idle") + self._freebox_alarm_state = "idle" self._unsub_watcher = None self._supported_features = AlarmControlPanelEntityFeature.ARM_AWAY self.update_parameters(node) - @property - def state(self) -> str: - return self._state + #@property + #def state(self) -> str: + # return self._state @property def supported_features(self) -> int: @@ -90,19 +91,18 @@ async def async_alarm_arm_night(self, code=None) -> None: time.sleep(1) self._unsub_watcher = async_track_time_interval(self.hass, self.sync_update_during_arming, timedelta(seconds=1)) - async def sync_update_during_arming(self, now: Optional[datetime] = None) -> None: - self.set_state(await self.get_home_endpoint_value( self._command_state)) + #self.set_state(await self.get_home_endpoint_value( self._command_state)) + self._freebox_alarm_state = await self.get_home_endpoint_value( self._command_state) self.async_write_ha_state() async def async_update(self): """Get the state & name and update it.""" - state = await self.get_home_endpoint_value( self._command_state) - if( state == "idle" and self._unsub_watcher != None): + self._freebox_alarm_state = await self.get_home_endpoint_value( self._command_state) + if( self._freebox_alarm_state == "idle" and self._unsub_watcher != None): self._unsub_watcher() self.update_parameters(self._router.nodes[self._id]) - def update_parameters(self, node): #Update name self._name = node["label"].strip() @@ -120,7 +120,6 @@ def update_parameters(self, node): else: self._supported_features = AlarmControlPanelEntityFeature.ARM_AWAY - # Parse all endpoints values for endpoint in filter(lambda x:(x["ep_type"] == "signal"), node['show_endpoints']): if( endpoint["name"] == "pin" ): @@ -138,21 +137,42 @@ def update_parameters(self, node): elif( endpoint["name"] == "battery" ): self._battery = endpoint["value"] - def set_state(self, state): - if( state == "alarm1_arming"): - self._state = AlarmControlPanelState.ARMING - elif( state == "alarm2_arming"): - self._state = SAlarmControlPanelState.ARMING - elif( state == "alarm1_armed"): - self._state = AlarmControlPanelState.ARMED_AWAY - elif( state == "alarm2_armed"): - self._state = AlarmControlPanelState.ARMED_NIGHT - elif( state == "alarm1_alert_timer"): - self._state = AlarmControlPanelState.TRIGGERED - elif( state == "alarm2_alert_timer"): - self._state = AlarmControlPanelState.TRIGGERED - elif( state == "alert"): - self._state = AlarmControlPanelState.TRIGGERED - else: - self._state = AlarmControlPanelState.DISARMED +# def set_state(self, state): +# if( state == "alarm1_arming"): +# self._state = AlarmControlPanelState.ARMING +# elif( state == "alarm2_arming"): +# self._state = SAlarmControlPanelState.ARMING +# elif( state == "alarm1_armed"): +# self._state = AlarmControlPanelState.ARMED_AWAY +# elif( state == "alarm2_armed"): +# self._state = AlarmControlPanelState.ARMED_NIGHT +# elif( state == "alarm1_alert_timer"): +# self._state = AlarmControlPanelState.TRIGGERED +# elif( state == "alarm2_alert_timer"): +# self._state = AlarmControlPanelState.TRIGGERED +# elif( state == "alert"): +# self._state = AlarmControlPanelState.TRIGGERED +# else: +# self._state = AlarmControlPanelState.DISARMED + + + @property + def alarm_state(self) -> AlarmControlPanelState | None: + """Return the state of the alarm.""" + + if( self._freebox_alarm_state == "alarm1_arming"): + return AlarmControlPanelState.ARMING + elif( self._freebox_alarm_state == "alarm2_arming"): + return SAlarmControlPanelState.ARMING + elif( self._freebox_alarm_state == "alarm1_armed"): + return AlarmControlPanelState.ARMED_AWAY + elif( self._freebox_alarm_state == "alarm2_armed"): + return AlarmControlPanelState.ARMED_NIGHT + elif( self._freebox_alarm_state == "alarm1_alert_timer"): + return AlarmControlPanelState.TRIGGERED + elif( self._freebox_alarm_state == "alarm2_alert_timer"): + returnAlarmControlPanelState.TRIGGERED + elif( self._freebox_alarm_state == "alert"): + return AlarmControlPanelState.TRIGGERED + return AlarmControlPanelState.DISARMED diff --git a/custom_components/freebox_home/config_flow.py b/custom_components/freebox_home/config_flow.py index d3e60e0..bc4b19a 100644 --- a/custom_components/freebox_home/config_flow.py +++ b/custom_components/freebox_home/config_flow.py @@ -9,7 +9,7 @@ from homeassistant.data_entry_flow import AbortFlow from .const import DOMAIN -from .router import get_api +from .router import get_api, remove_config _LOGGER = logging.getLogger(__name__) @@ -90,7 +90,10 @@ async def async_step_link(self, user_input=None): ''' except AuthorizationError as error: - _LOGGER.error(error) + # Config file may be wrong, I will delete IT. + _LOGGER.error("AuthorizationError: %s", error) + await remove_config(self.hass, self._host) + _LOGGER.error("The current configuration file is invalid. It has been deleted. Please retry") errors["base"] = "register_failed" except HttpRequestError: diff --git a/custom_components/freebox_home/manifest.json b/custom_components/freebox_home/manifest.json index 049d823..8cb18f5 100644 --- a/custom_components/freebox_home/manifest.json +++ b/custom_components/freebox_home/manifest.json @@ -9,5 +9,5 @@ "after_dependencies": ["zeroconf"], "zeroconf": ["_fbx-api._tcp.local."], "codeowners": ["gvigroux"], - "version": "0.7.3" + "version": "0.7.4" } \ No newline at end of file diff --git a/custom_components/freebox_home/router.py b/custom_components/freebox_home/router.py index 0a5987a..f47dd4b 100644 --- a/custom_components/freebox_home/router.py +++ b/custom_components/freebox_home/router.py @@ -1,6 +1,7 @@ """Represent the Freebox router and its devices and sensors.""" from datetime import datetime, timedelta import logging +import os from pathlib import Path from typing import Any, Dict, Optional @@ -79,11 +80,30 @@ async def close(self) -> None: self._api = None +#async def get_api(hass, host: str) -> Freepybox: +# """Get the Freebox API.""" +# #freebox_path = Path(hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY).path) +# freebox_path = Path(Store(hass, STORAGE_VERSION, STORAGE_KEY).path) +# freebox_path.mkdir(exist_ok=True) +# +# token_file = Path(f"{freebox_path}/{slugify(host)}.conf") +# return Freepybox(APP_DESC, token_file, API_VERSION) + + async def get_api(hass, host: str) -> Freepybox: """Get the Freebox API.""" - #freebox_path = Path(hass.helpers.storage.Store(STORAGE_VERSION, STORAGE_KEY).path) - freebox_path = Path(Store(hass, STORAGE_VERSION, STORAGE_KEY).path) - freebox_path.mkdir(exist_ok=True) + freebox_path = Store(hass, STORAGE_VERSION, STORAGE_KEY).path + + if not os.path.exists(freebox_path): + await hass.async_add_executor_job(os.makedirs, freebox_path) + + token_file = Path(f"{freebox_path}/{slugify(host)}.conf") + + return Freepybox(APP_DESC, token_file, api_version="latest") + +async def remove_config(hass, host: str): + freebox_path = Store(hass, STORAGE_VERSION, STORAGE_KEY).path token_file = Path(f"{freebox_path}/{slugify(host)}.conf") - return Freepybox(APP_DESC, token_file, API_VERSION) + os.remove(token_file) +