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 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
|
"""Implementation of Basic KNX DPT_1_Ucount Values."""
from __future__ import annotations
from xknx.exceptions import ConversionError
from .dpt import DPTNumeric
from .payload import DPTArray, DPTBinary
class DPTValue1ByteUnsigned(DPTNumeric):
"""
Abstraction for KNX 1 Octet.
DPT 5.***
"""
dpt_main_number = 5
dpt_sub_number: int | None = None
value_type = "1byte_unsigned"
payload_length = 1
value_min = 0
value_max = 255
resolution = 1
@classmethod
def from_knx(cls, payload: DPTArray | DPTBinary) -> int:
"""Parse/deserialize from KNX/IP raw data."""
value = cls.validate_payload(payload)[0]
if not cls._test_boundaries(value):
raise ConversionError(
f"Could not parse {cls.dpt_name()}", value=value, payload=payload
)
return value
@classmethod
def to_knx(cls, value: int | float) -> DPTArray:
"""Serialize to KNX/IP raw data."""
try:
knx_value = int(value)
if not cls._test_boundaries(knx_value):
raise ValueError(f"Value out of range {cls.value_min}..{cls.value_max}")
return DPTArray(knx_value)
except ValueError as err:
raise ConversionError(
f"Could not serialize {cls.dpt_name()}", value=value
) from err
@classmethod
def _test_boundaries(cls, value: int) -> bool:
"""Test if value is within defined range for this object."""
return cls.value_min <= value <= cls.value_max
class DPTScaling(DPTNumeric):
"""
Abstraction for KNX 1 Octet Percent.
DPT 5.001
"""
dpt_main_number = 5
dpt_sub_number = 1
value_type = "percent"
unit = "%"
payload_length = 1
value_min = 0
value_max = 100
resolution = 1
@classmethod
def from_knx(cls, payload: DPTArray | DPTBinary) -> int:
"""Parse/deserialize from KNX/IP raw data."""
knx_value = cls.validate_payload(payload)[0]
delta = cls.value_max - cls.value_min
value = round((knx_value / 255) * delta) + cls.value_min
if not cls._test_boundaries(value):
raise ConversionError(
f"Could not parse {cls.dpt_name()}", value=value, payload=payload
)
return value
@classmethod
def to_knx(cls, value: float) -> DPTArray:
"""Serialize to KNX/IP raw data."""
try:
percent_value = float(value)
if not cls._test_boundaries(percent_value):
raise ValueError("Value out of range")
delta = cls.value_max - cls.value_min
knx_value = round((percent_value - cls.value_min) / delta * 255)
return DPTArray(knx_value)
except ValueError as err:
raise ConversionError(
f"Could not serialize {cls.dpt_name()}", value=value
) from err
@classmethod
def _test_boundaries(cls, value: float) -> bool:
"""Test if value is within defined range for this object."""
return cls.value_min <= value <= cls.value_max
class DPTAngle(DPTScaling):
"""
Abstraction for KNX 1 Octet Angle.
DPT 5.003
"""
dpt_main_number = 5
dpt_sub_number = 3
value_type = "angle"
unit = "°"
value_min = 0
value_max = 360
resolution = 1
class DPTPercentU8(DPTValue1ByteUnsigned):
"""
Abstraction for KNX 1 Octet Percent.
DPT 5.004
"""
dpt_main_number = 5
dpt_sub_number = 4
value_type = "percentU8"
unit = "%"
resolution = 1
class DPTDecimalFactor(DPTValue1ByteUnsigned):
"""
Abstraction for KNX 1 Octet Percent.
DPT 5.005
"""
dpt_main_number = 5
dpt_sub_number = 5
value_type = "decimal_factor"
class DPTTariff(DPTValue1ByteUnsigned):
"""
Abstraction for KNX 1 Octet tariff information.
DPT 5.006
"""
dpt_main_number = 5
dpt_sub_number = 6
value_type = "tariff"
value_max = 254
class DPTValue1Ucount(DPTValue1ByteUnsigned):
"""
Abstraction for KNX 1 Octet counter pulses.
DPT 5.010
"""
dpt_main_number = 5
dpt_sub_number = 10
value_type = "pulse"
unit = "counter pulses"
|