Skip to content

Commit

Permalink
add method to delete a single device to central (#133)
Browse files Browse the repository at this point in the history
* Move core methods to central

- move delete_devices from RPCFunctions to central
- move new_devices from RPCFunctions to central

* Update setup.py

* add method to delete a single device to central
  • Loading branch information
SukramJ authored Jan 4, 2022
1 parent 0e343d9 commit f909bc6
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 70 deletions.
3 changes: 3 additions & 0 deletions changelog.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
Version 0.13.2 (2022-01-04)
- Fix cover state
- Move delete_devices from RPCFunctions to central
- Move new_devices from RPCFunctions to central
- Add method to delete a single device to central

Version 0.13.1 (2022-01-04)
- Use generic climate profiles list
Expand Down
82 changes: 82 additions & 0 deletions hahomematic/central_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
FILE_DEVICES,
FILE_NAMES,
FILE_PARAMSETS,
HH_EVENT_DELETE_DEVICES,
HM_VIRTUAL_REMOTE_HM,
HM_VIRTUAL_REMOTE_HMIP,
LOCALHOST,
Expand Down Expand Up @@ -209,6 +210,87 @@ def create_devices(self) -> None:
_LOGGER.exception("CentralUnit.init: Failed to create entities")
raise Exception("entity-creation-error") from err

async def delete_device(self, interface_id: str, device_address: str) -> None:
"""Delete devices from central_unit."""
_LOGGER.debug(
"CentralUnit.delete_device: interface_id = %s, device_address = %s",
interface_id,
device_address,
)
addresses: list[str] = []
if hm_device := self.hm_devices.get(device_address):
addresses.append(device_address)
addresses.extend(hm_device.channels)

await self.delete_devices(interface_id=interface_id, addresses=addresses)
args: list[Any] = [HH_EVENT_DELETE_DEVICES, addresses]
if self.callback_system_event is not None and callable(self.callback_system_event):
self.callback_system_event(HH_EVENT_DELETE_DEVICES, *args) # pylint: disable=not-callable

async def delete_devices(self, interface_id: str, addresses: list[str]) -> None:
"""Delete devices from central_unit."""
_LOGGER.debug(
"CentralUnit.delete_devices: interface_id = %s, addresses = %s",
interface_id,
str(addresses),
)

await self.raw_devices.cleanup(
interface_id=interface_id, deleted_addresses=addresses
)

for address in addresses:
try:
if ":" in address:
self.paramsets.remove(
interface_id=interface_id, channel_address=address
)
self.names.remove(address=address)
if hm_device := self.hm_devices.get(address):
hm_device.remove_event_subscriptions()
hm_device.remove_from_collections()
del self.hm_devices[address]
except KeyError:
_LOGGER.exception("Failed to delete: %s", address)
await self.paramsets.save()
await self.names.save()

async def add_new_devices(
self, interface_id: str, dev_descriptions: list[dict[str, Any]]
) -> None:
"""Async implementation"""
_LOGGER.debug(
"CentralUnit.add_new_devices: interface_id = %s, dev_descriptions = %s",
interface_id,
len(dev_descriptions),
)

if interface_id not in self.clients:
_LOGGER.error(
"RPCFunctions.newDevices: Missing client for interface_id %s.",
interface_id,
)
return None

# We need this list to avoid adding duplicates.
known_addresses = [
dev_desc[ATTR_HM_ADDRESS]
for dev_desc in self.raw_devices.get_device_descriptions(interface_id)
]
client = self.clients[interface_id]
for dev_desc in dev_descriptions:
try:
if dev_desc[ATTR_HM_ADDRESS] not in known_addresses:
self.raw_devices.add_device_description(interface_id, dev_desc)
await client.fetch_paramsets(dev_desc)
except Exception:
_LOGGER.exception("RPCFunctions.newDevices: Exception")
await self.raw_devices.save()
await self.paramsets.save()
await client.fetch_names()
await self.names.save()
create_devices(self)

async def stop(self) -> None:
"""
then shut down our XML-RPC server.
Expand Down
5 changes: 5 additions & 0 deletions hahomematic/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,11 @@ def device_address(self) -> str:
"""Return the address."""
return self._device_address

@property
def channels(self) -> list[str]:
"""Return the channels."""
return self._channels

def add_hm_entity(self, hm_entity: BaseEntity) -> None:
"""Add a hm entity to a device."""
if isinstance(hm_entity, GenericEntity):
Expand Down
2 changes: 1 addition & 1 deletion hahomematic/devices/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -490,7 +490,7 @@ def _current_profile_name(self) -> str | None:
def _profiles(self) -> dict[str, int]:
"""Return the profile groups."""
profiles: dict[str, int] = {}
for i in range(self._e_active_profile.min, self._e_active_profile.max+1):
for i in range(self._e_active_profile.min, self._e_active_profile.max + 1):
profiles[f"Profile {i}"] = i

return profiles
Expand Down
76 changes: 8 additions & 68 deletions hahomematic/xml_rpc_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@

import hahomematic.central_unit as hm_central
from hahomematic.const import (
ATTR_HM_ADDRESS,
HH_EVENT_DELETE_DEVICES,
HH_EVENT_ERROR,
HH_EVENT_LIST_DEVICES,
Expand All @@ -25,7 +24,6 @@
PORT_ANY,
)
from hahomematic.decorators import callback_event, callback_system_event
from hahomematic.device import create_devices

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -110,45 +108,13 @@ def newDevices(
We react on that and add those devices as well.
"""

async def _async_new_devices(central_unit: hm_central.CentralUnit) -> None:
"""Async implementation"""
_LOGGER.debug(
"RPCFunctions.newDevices: interface_id = %s, dev_descriptions = %s",
interface_id,
len(dev_descriptions),
)

if interface_id not in central_unit.clients:
_LOGGER.error(
"RPCFunctions.newDevices: Missing client for interface_id %s.",
interface_id,
)
return None

# We need this list to avoid adding duplicates.
known_addresses = [
dd[ATTR_HM_ADDRESS]
for dd in central_unit.raw_devices.get_device_descriptions(interface_id)
]
client = central_unit.clients[interface_id]
for dd in dev_descriptions:
try:
if dd[ATTR_HM_ADDRESS] not in known_addresses:
central_unit.raw_devices.add_device_description(
interface_id, dd
)
await client.fetch_paramsets(dd)
except Exception:
_LOGGER.exception("RPCFunctions.newDevices: Exception")
await central_unit.raw_devices.save()
await central_unit.paramsets.save()
await client.fetch_names()
await central_unit.names.save()
create_devices(central_unit)

central: hm_central.CentralUnit | None
if central := self._xml_rpc_server.get_central(interface_id):
central.run_coroutine(_async_new_devices(central))
central.run_coroutine(
central.add_new_devices(
interface_id=interface_id, dev_descriptions=dev_descriptions
)
)

@callback_system_event(HH_EVENT_DELETE_DEVICES)
def deleteDevices(self, interface_id: str, addresses: list[str]) -> None:
Expand All @@ -157,37 +123,11 @@ def deleteDevices(self, interface_id: str, addresses: list[str]) -> None:
We react on that and remove those devices as well.
"""

async def _async_delete_devices(central_unit: hm_central.CentralUnit) -> None:
"""async implementation."""
_LOGGER.debug(
"RPCFunctions.deleteDevices: interface_id = %s, addresses = %s",
interface_id,
str(addresses),
)

await central_unit.raw_devices.cleanup(
interface_id=interface_id, deleted_addresses=addresses
)

for address in addresses:
try:
if ":" in address:
central_unit.paramsets.remove(
interface_id=interface_id, channel_address=address
)
central_unit.names.remove(address=address)
if hm_device := central_unit.hm_devices.get(address):
hm_device.remove_event_subscriptions()
hm_device.remove_from_collections()
del central_unit.hm_devices[address]
except KeyError:
_LOGGER.exception("Failed to delete: %s", address)
await central_unit.paramsets.save()
await central_unit.names.save()

central: hm_central.CentralUnit | None
if central := self._xml_rpc_server.get_central(interface_id):
central.run_coroutine(_async_delete_devices(central))
central.run_coroutine(
central.delete_devices(interface_id=interface_id, addresses=addresses)
)

@callback_system_event(HH_EVENT_UPDATE_DEVICE)
# pylint: disable=no-self-use
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ def readme():
},
PACKAGE_NAME = "hahomematic"
HERE = os.path.abspath(os.path.dirname(__file__))
VERSION = "0.13.1"
VERSION = "0.13.2"

PACKAGES = find_packages(exclude=["tests", "tests.*", "dist", "build"])

Expand Down

0 comments on commit f909bc6

Please sign in to comment.