File: remote_value_sensor.py

package info (click to toggle)
python-xknx 3.6.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 4,012 kB
  • sloc: python: 39,710; javascript: 8,556; makefile: 27; sh: 12
file content (96 lines) | stat: -rw-r--r-- 2,948 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
"""
Module for managing a remote value typically used within a sensor.

The module maps a given value_type to a DPT class and uses this class
for serialization and deserialization of the KNX value.
"""

from __future__ import annotations

from typing import TYPE_CHECKING, TypeVar

from xknx.dpt import DPTBase, DPTNumeric, DPTString
from xknx.exceptions import ConversionError
from xknx.typing import DPTParsable

from .remote_value import GroupAddressesType, RemoteValue, RVCallbackType

if TYPE_CHECKING:
    from xknx.xknx import XKNX

ValueT = TypeVar("ValueT")


class _RemoteValueGeneric(RemoteValue[ValueT]):
    """Abstraction for generic DPT types."""

    dpt_base_class: type[DPTBase]
    _default_dpt_class: type[DPTBase] | None = None
    dpt_class: type[DPTBase]

    def __init__(
        self,
        xknx: XKNX,
        group_address: GroupAddressesType = None,
        group_address_state: GroupAddressesType = None,
        sync_state: bool | int | float | str = True,
        value_type: DPTParsable | type[DPTBase] | None = None,
        device_name: str | None = None,
        feature_name: str = "Value",
        after_update_cb: RVCallbackType[ValueT] | None = None,
    ) -> None:
        """Initialize RemoteValueSensor class."""
        try:
            if value_type is None:
                if self._default_dpt_class is None:
                    raise ValueError
                self.dpt_class = self._default_dpt_class
            else:
                self.dpt_class = self.dpt_base_class.get_dpt(value_type)
        except ValueError:
            raise ConversionError(
                f"invalid value type for base class {self.dpt_base_class.dpt_name()}",
                value_type=value_type,
                device_name=device_name,
            ) from None
        super().__init__(
            xknx,
            group_address,
            group_address_state,
            sync_state=sync_state,
            device_name=device_name,
            feature_name=feature_name,
            after_update_cb=after_update_cb,
        )

    @property
    def unit_of_measurement(self) -> str | None:
        """Return the unit of measurement."""
        return self.dpt_class.unit

    @property
    def ha_device_class(self) -> str | None:
        """Return a string representing the home assistant device class."""
        return getattr(self.dpt_class, "ha_device_class", None)


class RemoteValueSensor(_RemoteValueGeneric[int | float | str]):
    """Abstraction for sensor DPT types."""

    dpt_base_class = DPTBase
    dpt_class: type[DPTBase]


class RemoteValueNumeric(_RemoteValueGeneric[int | float]):
    """Abstraction for numeric DPT types."""

    dpt_base_class = DPTNumeric
    dpt_class: type[DPTNumeric]


class RemoteValueString(_RemoteValueGeneric[str]):
    """Abstraction for string DPT types."""

    dpt_base_class = DPTString
    dpt_class: type[DPTString]
    _default_dpt_class = DPTString