From 60a25d88d1e097f3097275886ca48d49801a6143 Mon Sep 17 00:00:00 2001 From: Jordan H Date: Sun, 3 Sep 2023 22:50:52 +0000 Subject: [PATCH] family_safety --- config/configuration.yaml | 2 +- .../const.py | 5 +- .../ha-familysafety/manifest.json | 12 +++ .../translations/en.json | 0 .../integration_blueprint/__init__.py | 55 ------------ .../integration_blueprint/api.py | 90 ------------------- .../integration_blueprint/binary_sensor.py | 50 ----------- .../integration_blueprint/config_flow.py | 80 ----------------- .../integration_blueprint/coordinator.py | 49 ---------- .../integration_blueprint/entity.py | 25 ------ .../integration_blueprint/manifest.json | 12 --- .../integration_blueprint/sensor.py | 46 ---------- .../integration_blueprint/switch.py | 56 ------------ hacs.json | 4 +- 14 files changed, 17 insertions(+), 469 deletions(-) rename custom_components/{integration_blueprint => ha-familysafety}/const.py (51%) create mode 100644 custom_components/ha-familysafety/manifest.json rename custom_components/{integration_blueprint => ha-familysafety}/translations/en.json (100%) delete mode 100644 custom_components/integration_blueprint/__init__.py delete mode 100644 custom_components/integration_blueprint/api.py delete mode 100644 custom_components/integration_blueprint/binary_sensor.py delete mode 100644 custom_components/integration_blueprint/config_flow.py delete mode 100644 custom_components/integration_blueprint/coordinator.py delete mode 100644 custom_components/integration_blueprint/entity.py delete mode 100644 custom_components/integration_blueprint/manifest.json delete mode 100644 custom_components/integration_blueprint/sensor.py delete mode 100644 custom_components/integration_blueprint/switch.py diff --git a/config/configuration.yaml b/config/configuration.yaml index 8c0d4e4..7cb0a0c 100644 --- a/config/configuration.yaml +++ b/config/configuration.yaml @@ -5,4 +5,4 @@ default_config: logger: default: info logs: - custom_components.integration_blueprint: debug + custom_components.family_safety: debug diff --git a/custom_components/integration_blueprint/const.py b/custom_components/ha-familysafety/const.py similarity index 51% rename from custom_components/integration_blueprint/const.py rename to custom_components/ha-familysafety/const.py index 66c28f3..413cefa 100644 --- a/custom_components/integration_blueprint/const.py +++ b/custom_components/ha-familysafety/const.py @@ -3,7 +3,6 @@ LOGGER: Logger = getLogger(__package__) -NAME = "Integration blueprint" -DOMAIN = "integration_blueprint" +NAME = "Microsoft Family Safety" +DOMAIN = "family_safety" VERSION = "0.0.0" -ATTRIBUTION = "Data provided by http://jsonplaceholder.typicode.com/" diff --git a/custom_components/ha-familysafety/manifest.json b/custom_components/ha-familysafety/manifest.json new file mode 100644 index 0000000..788c450 --- /dev/null +++ b/custom_components/ha-familysafety/manifest.json @@ -0,0 +1,12 @@ +{ + "domain": "family_safety", + "name": "Microsoft Family Safety", + "codeowners": [ + "@pantherale0" + ], + "config_flow": true, + "documentation": "https://github.com/pantherale0/ha-familysafety", + "iot_class": "cloud_polling", + "issue_tracker": "https://github.com/pantherale0/ha-familysafety/issues", + "version": "0.0.0" +} \ No newline at end of file diff --git a/custom_components/integration_blueprint/translations/en.json b/custom_components/ha-familysafety/translations/en.json similarity index 100% rename from custom_components/integration_blueprint/translations/en.json rename to custom_components/ha-familysafety/translations/en.json diff --git a/custom_components/integration_blueprint/__init__.py b/custom_components/integration_blueprint/__init__.py deleted file mode 100644 index a9adfdc..0000000 --- a/custom_components/integration_blueprint/__init__.py +++ /dev/null @@ -1,55 +0,0 @@ -"""Custom integration to integrate integration_blueprint with Home Assistant. - -For more details about this integration, please refer to -https://github.com/ludeeus/integration_blueprint -""" -from __future__ import annotations - -from homeassistant.config_entries import ConfigEntry -from homeassistant.const import CONF_PASSWORD, CONF_USERNAME, Platform -from homeassistant.core import HomeAssistant -from homeassistant.helpers.aiohttp_client import async_get_clientsession - -from .api import IntegrationBlueprintApiClient -from .const import DOMAIN -from .coordinator import BlueprintDataUpdateCoordinator - -PLATFORMS: list[Platform] = [ - Platform.SENSOR, - Platform.BINARY_SENSOR, - Platform.SWITCH, -] - - -# https://developers.home-assistant.io/docs/config_entries_index/#setting-up-an-entry -async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: - """Set up this integration using UI.""" - hass.data.setdefault(DOMAIN, {}) - hass.data[DOMAIN][entry.entry_id] = coordinator = BlueprintDataUpdateCoordinator( - hass=hass, - client=IntegrationBlueprintApiClient( - username=entry.data[CONF_USERNAME], - password=entry.data[CONF_PASSWORD], - session=async_get_clientsession(hass), - ), - ) - # https://developers.home-assistant.io/docs/integration_fetching_data#coordinated-single-api-poll-for-data-for-all-entities - await coordinator.async_config_entry_first_refresh() - - await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS) - entry.async_on_unload(entry.add_update_listener(async_reload_entry)) - - return True - - -async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: - """Handle removal of an entry.""" - if unloaded := await hass.config_entries.async_unload_platforms(entry, PLATFORMS): - hass.data[DOMAIN].pop(entry.entry_id) - return unloaded - - -async def async_reload_entry(hass: HomeAssistant, entry: ConfigEntry) -> None: - """Reload config entry.""" - await async_unload_entry(hass, entry) - await async_setup_entry(hass, entry) diff --git a/custom_components/integration_blueprint/api.py b/custom_components/integration_blueprint/api.py deleted file mode 100644 index a738040..0000000 --- a/custom_components/integration_blueprint/api.py +++ /dev/null @@ -1,90 +0,0 @@ -"""Sample API Client.""" -from __future__ import annotations - -import asyncio -import socket - -import aiohttp -import async_timeout - - -class IntegrationBlueprintApiClientError(Exception): - """Exception to indicate a general API error.""" - - -class IntegrationBlueprintApiClientCommunicationError( - IntegrationBlueprintApiClientError -): - """Exception to indicate a communication error.""" - - -class IntegrationBlueprintApiClientAuthenticationError( - IntegrationBlueprintApiClientError -): - """Exception to indicate an authentication error.""" - - -class IntegrationBlueprintApiClient: - """Sample API Client.""" - - def __init__( - self, - username: str, - password: str, - session: aiohttp.ClientSession, - ) -> None: - """Sample API Client.""" - self._username = username - self._password = password - self._session = session - - async def async_get_data(self) -> any: - """Get data from the API.""" - return await self._api_wrapper( - method="get", url="https://jsonplaceholder.typicode.com/posts/1" - ) - - async def async_set_title(self, value: str) -> any: - """Get data from the API.""" - return await self._api_wrapper( - method="patch", - url="https://jsonplaceholder.typicode.com/posts/1", - data={"title": value}, - headers={"Content-type": "application/json; charset=UTF-8"}, - ) - - async def _api_wrapper( - self, - method: str, - url: str, - data: dict | None = None, - headers: dict | None = None, - ) -> any: - """Get information from the API.""" - try: - async with async_timeout.timeout(10): - response = await self._session.request( - method=method, - url=url, - headers=headers, - json=data, - ) - if response.status in (401, 403): - raise IntegrationBlueprintApiClientAuthenticationError( - "Invalid credentials", - ) - response.raise_for_status() - return await response.json() - - except asyncio.TimeoutError as exception: - raise IntegrationBlueprintApiClientCommunicationError( - "Timeout error fetching information", - ) from exception - except (aiohttp.ClientError, socket.gaierror) as exception: - raise IntegrationBlueprintApiClientCommunicationError( - "Error fetching information", - ) from exception - except Exception as exception: # pylint: disable=broad-except - raise IntegrationBlueprintApiClientError( - "Something really wrong happened!" - ) from exception diff --git a/custom_components/integration_blueprint/binary_sensor.py b/custom_components/integration_blueprint/binary_sensor.py deleted file mode 100644 index fff5b21..0000000 --- a/custom_components/integration_blueprint/binary_sensor.py +++ /dev/null @@ -1,50 +0,0 @@ -"""Binary sensor platform for integration_blueprint.""" -from __future__ import annotations - -from homeassistant.components.binary_sensor import ( - BinarySensorDeviceClass, - BinarySensorEntity, - BinarySensorEntityDescription, -) - -from .const import DOMAIN -from .coordinator import BlueprintDataUpdateCoordinator -from .entity import IntegrationBlueprintEntity - -ENTITY_DESCRIPTIONS = ( - BinarySensorEntityDescription( - key="integration_blueprint", - name="Integration Blueprint Binary Sensor", - device_class=BinarySensorDeviceClass.CONNECTIVITY, - ), -) - - -async def async_setup_entry(hass, entry, async_add_devices): - """Set up the binary_sensor platform.""" - coordinator = hass.data[DOMAIN][entry.entry_id] - async_add_devices( - IntegrationBlueprintBinarySensor( - coordinator=coordinator, - entity_description=entity_description, - ) - for entity_description in ENTITY_DESCRIPTIONS - ) - - -class IntegrationBlueprintBinarySensor(IntegrationBlueprintEntity, BinarySensorEntity): - """integration_blueprint binary_sensor class.""" - - def __init__( - self, - coordinator: BlueprintDataUpdateCoordinator, - entity_description: BinarySensorEntityDescription, - ) -> None: - """Initialize the binary_sensor class.""" - super().__init__(coordinator) - self.entity_description = entity_description - - @property - def is_on(self) -> bool: - """Return true if the binary_sensor is on.""" - return self.coordinator.data.get("title", "") == "foo" diff --git a/custom_components/integration_blueprint/config_flow.py b/custom_components/integration_blueprint/config_flow.py deleted file mode 100644 index a474163..0000000 --- a/custom_components/integration_blueprint/config_flow.py +++ /dev/null @@ -1,80 +0,0 @@ -"""Adds config flow for Blueprint.""" -from __future__ import annotations - -import voluptuous as vol -from homeassistant import config_entries -from homeassistant.const import CONF_PASSWORD, CONF_USERNAME -from homeassistant.helpers import selector -from homeassistant.helpers.aiohttp_client import async_create_clientsession - -from .api import ( - IntegrationBlueprintApiClient, - IntegrationBlueprintApiClientAuthenticationError, - IntegrationBlueprintApiClientCommunicationError, - IntegrationBlueprintApiClientError, -) -from .const import DOMAIN, LOGGER - - -class BlueprintFlowHandler(config_entries.ConfigFlow, domain=DOMAIN): - """Config flow for Blueprint.""" - - VERSION = 1 - - async def async_step_user( - self, - user_input: dict | None = None, - ) -> config_entries.FlowResult: - """Handle a flow initialized by the user.""" - _errors = {} - if user_input is not None: - try: - await self._test_credentials( - username=user_input[CONF_USERNAME], - password=user_input[CONF_PASSWORD], - ) - except IntegrationBlueprintApiClientAuthenticationError as exception: - LOGGER.warning(exception) - _errors["base"] = "auth" - except IntegrationBlueprintApiClientCommunicationError as exception: - LOGGER.error(exception) - _errors["base"] = "connection" - except IntegrationBlueprintApiClientError as exception: - LOGGER.exception(exception) - _errors["base"] = "unknown" - else: - return self.async_create_entry( - title=user_input[CONF_USERNAME], - data=user_input, - ) - - return self.async_show_form( - step_id="user", - data_schema=vol.Schema( - { - vol.Required( - CONF_USERNAME, - default=(user_input or {}).get(CONF_USERNAME), - ): selector.TextSelector( - selector.TextSelectorConfig( - type=selector.TextSelectorType.TEXT - ), - ), - vol.Required(CONF_PASSWORD): selector.TextSelector( - selector.TextSelectorConfig( - type=selector.TextSelectorType.PASSWORD - ), - ), - } - ), - errors=_errors, - ) - - async def _test_credentials(self, username: str, password: str) -> None: - """Validate credentials.""" - client = IntegrationBlueprintApiClient( - username=username, - password=password, - session=async_create_clientsession(self.hass), - ) - await client.async_get_data() diff --git a/custom_components/integration_blueprint/coordinator.py b/custom_components/integration_blueprint/coordinator.py deleted file mode 100644 index d427a1a..0000000 --- a/custom_components/integration_blueprint/coordinator.py +++ /dev/null @@ -1,49 +0,0 @@ -"""DataUpdateCoordinator for integration_blueprint.""" -from __future__ import annotations - -from datetime import timedelta - -from homeassistant.config_entries import ConfigEntry -from homeassistant.core import HomeAssistant -from homeassistant.helpers.update_coordinator import ( - DataUpdateCoordinator, - UpdateFailed, -) -from homeassistant.exceptions import ConfigEntryAuthFailed - -from .api import ( - IntegrationBlueprintApiClient, - IntegrationBlueprintApiClientAuthenticationError, - IntegrationBlueprintApiClientError, -) -from .const import DOMAIN, LOGGER - - -# https://developers.home-assistant.io/docs/integration_fetching_data#coordinated-single-api-poll-for-data-for-all-entities -class BlueprintDataUpdateCoordinator(DataUpdateCoordinator): - """Class to manage fetching data from the API.""" - - config_entry: ConfigEntry - - def __init__( - self, - hass: HomeAssistant, - client: IntegrationBlueprintApiClient, - ) -> None: - """Initialize.""" - self.client = client - super().__init__( - hass=hass, - logger=LOGGER, - name=DOMAIN, - update_interval=timedelta(minutes=5), - ) - - async def _async_update_data(self): - """Update data via library.""" - try: - return await self.client.async_get_data() - except IntegrationBlueprintApiClientAuthenticationError as exception: - raise ConfigEntryAuthFailed(exception) from exception - except IntegrationBlueprintApiClientError as exception: - raise UpdateFailed(exception) from exception diff --git a/custom_components/integration_blueprint/entity.py b/custom_components/integration_blueprint/entity.py deleted file mode 100644 index 4325227..0000000 --- a/custom_components/integration_blueprint/entity.py +++ /dev/null @@ -1,25 +0,0 @@ -"""BlueprintEntity class.""" -from __future__ import annotations - -from homeassistant.helpers.entity import DeviceInfo -from homeassistant.helpers.update_coordinator import CoordinatorEntity - -from .const import ATTRIBUTION, DOMAIN, NAME, VERSION -from .coordinator import BlueprintDataUpdateCoordinator - - -class IntegrationBlueprintEntity(CoordinatorEntity): - """BlueprintEntity class.""" - - _attr_attribution = ATTRIBUTION - - def __init__(self, coordinator: BlueprintDataUpdateCoordinator) -> None: - """Initialize.""" - super().__init__(coordinator) - self._attr_unique_id = coordinator.config_entry.entry_id - self._attr_device_info = DeviceInfo( - identifiers={(DOMAIN, self.unique_id)}, - name=NAME, - model=VERSION, - manufacturer=NAME, - ) diff --git a/custom_components/integration_blueprint/manifest.json b/custom_components/integration_blueprint/manifest.json deleted file mode 100644 index 817cd7b..0000000 --- a/custom_components/integration_blueprint/manifest.json +++ /dev/null @@ -1,12 +0,0 @@ -{ - "domain": "integration_blueprint", - "name": "Integration blueprint", - "codeowners": [ - "@ludeeus" - ], - "config_flow": true, - "documentation": "https://github.com/ludeeus/integration_blueprint", - "iot_class": "cloud_polling", - "issue_tracker": "https://github.com/ludeeus/integration_blueprint/issues", - "version": "0.0.0" -} \ No newline at end of file diff --git a/custom_components/integration_blueprint/sensor.py b/custom_components/integration_blueprint/sensor.py deleted file mode 100644 index 06201fe..0000000 --- a/custom_components/integration_blueprint/sensor.py +++ /dev/null @@ -1,46 +0,0 @@ -"""Sensor platform for integration_blueprint.""" -from __future__ import annotations - -from homeassistant.components.sensor import SensorEntity, SensorEntityDescription - -from .const import DOMAIN -from .coordinator import BlueprintDataUpdateCoordinator -from .entity import IntegrationBlueprintEntity - -ENTITY_DESCRIPTIONS = ( - SensorEntityDescription( - key="integration_blueprint", - name="Integration Sensor", - icon="mdi:format-quote-close", - ), -) - - -async def async_setup_entry(hass, entry, async_add_devices): - """Set up the sensor platform.""" - coordinator = hass.data[DOMAIN][entry.entry_id] - async_add_devices( - IntegrationBlueprintSensor( - coordinator=coordinator, - entity_description=entity_description, - ) - for entity_description in ENTITY_DESCRIPTIONS - ) - - -class IntegrationBlueprintSensor(IntegrationBlueprintEntity, SensorEntity): - """integration_blueprint Sensor class.""" - - def __init__( - self, - coordinator: BlueprintDataUpdateCoordinator, - entity_description: SensorEntityDescription, - ) -> None: - """Initialize the sensor class.""" - super().__init__(coordinator) - self.entity_description = entity_description - - @property - def native_value(self) -> str: - """Return the native value of the sensor.""" - return self.coordinator.data.get("body") diff --git a/custom_components/integration_blueprint/switch.py b/custom_components/integration_blueprint/switch.py deleted file mode 100644 index 33340a2..0000000 --- a/custom_components/integration_blueprint/switch.py +++ /dev/null @@ -1,56 +0,0 @@ -"""Switch platform for integration_blueprint.""" -from __future__ import annotations - -from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription - -from .const import DOMAIN -from .coordinator import BlueprintDataUpdateCoordinator -from .entity import IntegrationBlueprintEntity - -ENTITY_DESCRIPTIONS = ( - SwitchEntityDescription( - key="integration_blueprint", - name="Integration Switch", - icon="mdi:format-quote-close", - ), -) - - -async def async_setup_entry(hass, entry, async_add_devices): - """Set up the sensor platform.""" - coordinator = hass.data[DOMAIN][entry.entry_id] - async_add_devices( - IntegrationBlueprintSwitch( - coordinator=coordinator, - entity_description=entity_description, - ) - for entity_description in ENTITY_DESCRIPTIONS - ) - - -class IntegrationBlueprintSwitch(IntegrationBlueprintEntity, SwitchEntity): - """integration_blueprint switch class.""" - - def __init__( - self, - coordinator: BlueprintDataUpdateCoordinator, - entity_description: SwitchEntityDescription, - ) -> None: - """Initialize the switch class.""" - super().__init__(coordinator) - self.entity_description = entity_description - - @property - def is_on(self) -> bool: - """Return true if the switch is on.""" - return self.coordinator.data.get("title", "") == "foo" - - async def async_turn_on(self, **_: any) -> None: - """Turn on the switch.""" - await self.coordinator.api.async_set_title("bar") - await self.coordinator.async_request_refresh() - - async def async_turn_off(self, **_: any) -> None: - """Turn off the switch.""" - await self.coordinator.api.async_set_title("foo") - await self.coordinator.async_request_refresh() diff --git a/hacs.json b/hacs.json index 65f7335..c1149fd 100644 --- a/hacs.json +++ b/hacs.json @@ -1,6 +1,6 @@ { - "name": "Integration blueprint", - "filename": "integration_blueprint.zip", + "name": "Microsoft Family Safety", + "filename": "family_safety.zip", "hide_default_branch": true, "homeassistant": "2023.3.0", "render_readme": true,