Skip to content

Commit

Permalink
Add option to un ignore mechanism to ignore the automatic creation of…
Browse files Browse the repository at this point in the history
… custom entities by device type (#1427)
  • Loading branch information
SukramJ authored Feb 10, 2024
1 parent f27058f commit 263a45d
Show file tree
Hide file tree
Showing 8 changed files with 103 additions and 7 deletions.
4 changes: 4 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
# Version 2024.2.2 (2024-02-10)

- Add option to un ignore mechanism to ignore the automatic creation of custom entities by device type

# Version 2024.2.1 (2024-02-02)

- Accept float as input for int numbers
Expand Down
15 changes: 14 additions & 1 deletion docs/unignore.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,13 @@ FROST_PROTECTION
### parameter with limitation to a device type, channel and paramset type (> 1.55.0):

```
GLOBAL_BUTTON_LOCK:MASTER@HmIP-eTRV-2:0
GLOBAL_BUTTON_LOCK:MASTER@HmIP-eTRV-2:0
LEVEL:VALUES@HmIP-BROLL:3
GLOBAL_BUTTON_LOCK:MASTER@HM-TC-IT-WM-W-EU: (channel is empty!)
```

Wildcards can be used for device_type and channel for parameters from VALUES the paramaset:

```
LEVEL:VALUES@all:3 # (LEVEL on channel 3 for all device types)
LEVEL:VALUES@HmIP-BROLL:all # (LEVEL on all channels for HmIP-BROLL)
Expand All @@ -45,3 +47,14 @@ LEVEL:VALUES@all:all # (LEVEL on all channels for all device types) equivalent
# Known limitations

Parameters from `MASTER` paramset of HM-Classic (BidCos) devices can be changed, but need a manual refresh, by calling the service `homeassistant.update_entity`.

# ignore

There is also an option to ignore the automatic creation of a custom entities for a specific device type:
The line must start with `ignore_` to enable this mechanism.

```
ignore_HmIP-BROLL
```

This is useful, if you want to create your own entities based on HA templates. Ignoring a device_type gives you access to the raw data of this device.
18 changes: 16 additions & 2 deletions hahomematic/caches/visibility.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,13 @@
from hahomematic import central as hmcu, support as hms
from hahomematic.const import CLICK_EVENTS, DEFAULT_ENCODING, Parameter, ParamsetKey
from hahomematic.platforms.custom.definition import get_required_parameters
from hahomematic.support import reduce_args
from hahomematic.support import element_matches_key, reduce_args

_LOGGER: Final = logging.getLogger(__name__)

_FILE_CUSTOM_UN_IGNORE_PARAMETERS: Final = "unignore"
_UN_IGNORE_WILDCARD: Final = "all"
_IGNORE_DEVICE_TYPE: Final = "ignore_"

# Define which additional parameters from MASTER paramset should be created as entity.
# By default these are also on the _HIDDEN_PARAMETERS, which prevents these entities
Expand Down Expand Up @@ -261,7 +262,7 @@ def __init__(
self._custom_un_ignore_complex: Final[
dict[str, dict[int | str | None, dict[str, set[str]]]]
] = {}

self._ignore_custom_device_type: Final[list[str]] = []
self._ignore_parameters_by_device_lower: Final[dict[str, tuple[str, ...]]] = {
parameter: tuple(device_type.lower() for device_type in device_types)
for parameter, device_types in _IGNORE_PARAMETERS_BY_DEVICE.items()
Expand Down Expand Up @@ -312,6 +313,15 @@ def _init(self) -> None:
ParamsetKey.MASTER
].add(parameter)

@lru_cache(maxsize=256)
def device_type_is_ignored(self, device_type: str) -> bool:
"""Check if a device type should be ignored for custom entities."""
return element_matches_key(
search_elements=self._ignore_custom_device_type,
compare_with=device_type.lower(),
do_wildcard_search=True,
)

@lru_cache(maxsize=4096)
def parameter_is_ignored(
self,
Expand Down Expand Up @@ -478,6 +488,10 @@ def _add_line_to_cache(self, line: str) -> None:
if not line.strip():
return None

if line.lower().startswith(_IGNORE_DEVICE_TYPE):
self._ignore_custom_device_type.append(line.lower().replace(_IGNORE_DEVICE_TYPE, ""))
return

if line_details := self._get_unignore_line_details(line=line):
if isinstance(line_details, str):
self._custom_un_ignore_values_parameters.add(line_details)
Expand Down
9 changes: 9 additions & 0 deletions hahomematic/platforms/custom/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ def create_custom_entity_and_append_to_device(
device: hmd.HmDevice,
) -> None:
"""Decides which default platform should be used, and creates the required entities."""

if device.ignore_for_custom_entity:
_LOGGER.debug(
"CREATE_ENTITIES: Ignoring: %s, %s, %s due to device_type_is_ignored",
device.interface_id,
device.device_address,
device.device_type,
)
return
if entity_definition_exists(device.device_type):
_LOGGER.debug(
"CREATE_ENTITIES: Handling custom entity integration: %s, %s, %s",
Expand Down
13 changes: 11 additions & 2 deletions hahomematic/platforms/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,11 +91,15 @@ def __init__(self, central: hmcu.CentralUnit, interface_id: str, device_address:
parameter=Description.SUBTYPE,
)
)
self._ignore_for_custom_entity: Final[
bool
] = central.parameter_visibility.device_type_is_ignored(device_type=self._device_type)
self._manufacturer = self._identify_manufacturer()
self._product_group: Final = self.client.get_product_group(self._device_type)
# marker if device will be created as custom entity
self._has_custom_entity_definition: Final = hmed.entity_definition_exists(
device_type=self._device_type
self._has_custom_entity_definition: Final = (
hmed.entity_definition_exists(device_type=self._device_type)
and not self._ignore_for_custom_entity
)
self._name: Final = get_device_name(
central=central,
Expand Down Expand Up @@ -251,6 +255,11 @@ def interface_id(self) -> str:
"""Return the interface_id of the device."""
return self._interface_id

@config_property
def ignore_for_custom_entity(self) -> bool:
"""Return if device should be ignored for custom entity."""
return self._ignore_for_custom_entity

@property
def has_custom_entity_definition(self) -> bool:
"""Return if custom_entity definition is available for the device."""
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"

[project]
name = "hahomematic"
version = "2024.2.1"
version = "2024.2.2"
license = {text = "MIT License"}
description = "Homematic interface for Home Assistant running on Python 3."
readme = "README.md"
Expand Down
2 changes: 1 addition & 1 deletion requirements_test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
coverage==7.4.1
freezegun==1.4.0
mypy==1.8.0
pip==23.3.2
pip==24.0
pre-commit==3.6.0
pydevccu==0.1.7
pylint-per-file-ignores==1.3.2
Expand Down
47 changes: 47 additions & 0 deletions tests/test_central.py
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,53 @@ async def test_device_unignore_hm2(
assert generic_entity.usage == EntityUsage.ENTITY


@pytest.mark.parametrize(
("lines", "device_type", "address", "expected_result"),
[
(
["ignore_HmIP-BWTH"],
"HmIP-BWTH",
"VCU1769958",
True,
),
(
["ignore_HmIP-2BWTH"],
"HmIP-BWTH",
"VCU1769958",
False,
),
(
["ignore_HmIP-eTRV"],
"HmIP-eTRV-2",
"VCU3609622",
True,
),
],
)
@pytest.mark.asyncio
async def test_ignore_deviec_type(
factory: helper.Factory,
lines: list[str],
device_type: str,
address: str,
expected_result: bool,
) -> None:
"""Test device un ignore."""
central, _ = await factory.get_default_central(
{"VCU1769958": "HmIP-BWTH.json", "VCU3609622": "HmIP-eTRV-2.json"}, un_ignore_list=lines
)

assert (
central.parameter_visibility.device_type_is_ignored(device_type=device_type)
is expected_result
)
if device := central.get_device(address=address):
if expected_result:
assert len(device.custom_entities) == 0
else:
assert len(device.custom_entities) > 0


@pytest.mark.asyncio
async def test_all_parameters(factory: helper.Factory) -> None:
"""Test all_parameters."""
Expand Down

0 comments on commit 263a45d

Please sign in to comment.