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
|
"""Implementation of Basic KNX 1-Byte signed integer values."""
from __future__ import annotations
from xknx.exceptions import ConversionError
from .dpt import DPTNumeric
from .payload import DPTArray, DPTBinary
class DPTSignedRelativeValue(DPTNumeric):
"""
Abstraction for KNX 1 Byte "1-octet Signed Relative Value".
DPT 6.***
"""
dpt_main_number = 6
dpt_sub_number: int | None = None
value_type = "1byte_signed"
payload_length = 1
value_min = -128
value_max = 127
resolution = 1
@classmethod
def from_knx(cls, payload: DPTArray | DPTBinary) -> int:
"""Parse/deserialize from KNX/IP raw data."""
raw = cls.validate_payload(payload)
if raw[0] > cls.value_max:
return raw[0] - 0x100
return raw[0]
@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("Value out of range")
if knx_value < 0:
knx_value += 0x100
return DPTArray(knx_value & 0xFF)
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 DPTPercentV8(DPTSignedRelativeValue):
"""
Abstraction for KNX DPT_Percent_V8.
DPT 6.001
"""
dpt_main_number = 6
dpt_sub_number = 1
value_type = "percentV8"
unit = "%"
class DPTValue1Count(DPTSignedRelativeValue):
"""
Abstraction for KNX DPT_Value_1_Count.
DPT 6.010
"""
dpt_main_number = 6
dpt_sub_number = 10
value_type = "counter_pulses"
unit = "counter pulses"
|