Skip to content

Commit

Permalink
Add reload facility
Browse files Browse the repository at this point in the history
  • Loading branch information
gluap committed Dec 31, 2023
1 parent 2f23f61 commit 1506611
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 7 deletions.
68 changes: 61 additions & 7 deletions custom_components/duofern/__init__.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import asyncio
import logging
import os
import re
from typing import Any

# from homeassistant.const import 'serial_port', 'config_file', 'code'
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.core import HomeAssistant, ServiceCall, callback
from homeassistant.config_entries import ConfigEntry
import homeassistant.helpers.config_validation as cv
import voluptuous as vol
Expand All @@ -25,7 +26,14 @@
_LOGGER = logging.getLogger(__name__)

from .const import DOMAIN, DUOFERN_COMPONENTS
from .domain_data import _getData
from custom_components.duofern.domain_data import getDuofernStick, isDeviceSetUp, saveDeviceAsSetUp, unsetupDevice

from homeassistant.helpers.device_registry import DeviceEntry

SERVICES = ['start_pairing', 'start_unpairing', 'clean_config', 'dump_device_state', 'ask_for_update',
'set_update_interval']

# Validation of the user's configuration
CONFIG_SCHEMA = vol.Schema({DOMAIN: vol.Schema({
vol.Optional('serial_port',
Expand All @@ -38,12 +46,12 @@


async def async_remove_config_entry_device(
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: DeviceEntry
hass: HomeAssistant, config_entry: ConfigEntry, device_entry: DeviceEntry
) -> bool:
"""Remove a config entry from a device."""
stick = getDuofernStick(hass)
try:
del(stick.duofern_parser.modules["by_code"][device_entry.name])
del (stick.duofern_parser.modules["by_code"][device_entry.name])
stick.config['devices'] = [dev for dev in stick.config['devices'] if dev['id'] != device_entry.name]
except:
logging.warning(device_entry)
Expand All @@ -52,6 +60,50 @@ async def async_remove_config_entry_device(
return True


async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
"""Unload deCONZ config entry."""

stick = getDuofernStick(hass)
stick.stop()
try:
stick.serial_connection.close()
except:
_LOGGER.exception("closing serial connection failed")

await asyncio.sleep(0.5)



for duofernDevice in stick.config['devices']:
_LOGGER.info(f"unsetting up device {duofernDevice}")
duofernId: str = duofernDevice['id']
if not isDeviceSetUp(hass, duofernId):
continue
_LOGGER.info(f"unsetting up device {duofernDevice}")
unsetupDevice(hass, duofernId)

for component in DUOFERN_COMPONENTS:
hass.async_create_task(
hass.config_entries.async_forward_entry_unload(config_entry, component)
)


newstick = DuofernStickThreaded(serial_port=stick.port, system_code=stick.system_code,
config_file_json=stick.config_file,
ephemeral=False)
newstick.start()
hass.data[DOMAIN]['stick'] = newstick
del stick

return True


@callback
def async_unload_services(hass: HomeAssistant) -> None:
for service in SERVICES:
hass.services.async_remove(DOMAIN, service)


def setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Setup the duofern stick for communicating with the duofern devices via entities"""
configEntries = hass.config_entries.async_entries(DOMAIN)
Expand Down Expand Up @@ -122,7 +174,7 @@ def start_unpairing(call: ServiceCall) -> None:
_LOGGER.warning("start pairing")
getDuofernStick(hass).unpair(call.data.get('timeout', 60))

#def sync_devices(call: ServiceCall) -> None:
# def sync_devices(call: ServiceCall) -> None:
# stick.sync_devices()

def dump_device_state(call: ServiceCall) -> None:
Expand Down Expand Up @@ -152,8 +204,9 @@ def get_device_id(hass_entity_id):
_LOGGER.info("Asking specific devices for update")
device_ids = [get_device_id(i) for i in hass_device_id]
except Exception:
_LOGGER.exception(f"Exception while getting device id {call}, {call.data}, i know {hass.data[DOMAIN]['deviceByHassId']}, fyi deviceByID is {hass.data[DOMAIN]['devices']}")
for id,dev in hass.data[DOMAIN]['deviceByHassId'].items():
_LOGGER.exception(
f"Exception while getting device id {call}, {call.data}, i know {hass.data[DOMAIN]['deviceByHassId']}, fyi deviceByID is {hass.data[DOMAIN]['devices']}")
for id, dev in hass.data[DOMAIN]['deviceByHassId'].items():
_LOGGER.warning(f"{id}, {dev.__dict__}")
raise
if device_ids is None:
Expand All @@ -165,7 +218,8 @@ def get_device_id(hass_entity_id):
for device_id in device_ids:
if device_id is not None:
if device_id not in hass.data[DOMAIN]['stick'].duofern_parser.modules['by_code']:
_LOGGER.warning(f"{device_id} is not a valid duofern device, I only know {hass.data[DOMAIN]['stick'].duofern_parser.modules['by_code'].keys()}. Gonna handle the other devices in {device_ids} though.")
_LOGGER.warning(
f"{device_id} is not a valid duofern device, I only know {hass.data[DOMAIN]['stick'].duofern_parser.modules['by_code'].keys()}. Gonna handle the other devices in {device_ids} though.")
continue
_LOGGER.info(f"asking {device_id} for update")
getDuofernStick(hass).command(device_id, 'getStatus')
Expand Down
15 changes: 15 additions & 0 deletions custom_components/duofern/domain_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from custom_components.duofern.const import DOMAIN


class DuofernDomainData(TypedDict):
stick: DuofernStickThreaded
devices: dict[str, Entity]
Expand All @@ -15,19 +16,33 @@ class DuofernDomainData(TypedDict):
def getDuofernStick(hass: HomeAssistant) -> DuofernStickThreaded:
return _getData(hass)['stick']


def isDeviceSetUp(hass: HomeAssistant, duofernId: str, subIdWithinHassDevice: str = "") -> bool:
return (duofernId + subIdWithinHassDevice) in _getData(hass)['devices']


def saveDeviceAsSetUp(hass: HomeAssistant, device: Entity, duofernId: str, subIdWithinHassDevice: str = "") -> None:
_getData(hass)['devices'][duofernId + subIdWithinHassDevice] = device
_getData(hass)['deviceByHassId'][device.unique_id] = device


def unsetupDevice(hass: HomeAssistant, duofernId: str) -> None:
device_ids = [d for d in _getData(hass)['devices'] if d.startswith(duofernId)]
unique_ids = [_getData(hass)['devices'][d].unique_id for d in device_ids]
for did in device_ids:
if did in _getData(hass)['devices']:
del _getData(hass)['devices'][did]
for uid in unique_ids:
del _getData(hass)['deviceByHassId'][uid]


def setupDomainData(hass: HomeAssistant, stick: DuofernStickThreaded) -> None:
hass.data[DOMAIN] = DuofernDomainData({
'stick': stick,
'devices': {},
'deviceByHassId': {}
})


def _getData(hass: HomeAssistant) -> DuofernDomainData:
return cast(DuofernDomainData, hass.data[DOMAIN])

0 comments on commit 1506611

Please sign in to comment.