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 177 178 179 180 181 182 183 184 185
|
"""Unit test for DPT 3 objects."""
from typing import Any
import pytest
from xknx.dpt import DPTArray, DPTBinary, DPTControlBlinds, DPTControlDimming
from xknx.dpt.dpt_1 import Step, UpDown
from xknx.dpt.dpt_3 import ControlBlinds, ControlDimming
from xknx.exceptions import ConversionError, CouldNotParseTelegram
class TestControlData:
"""Test class for Control data objects."""
@pytest.mark.parametrize(
("data", "dict_value"),
[
(
ControlBlinds(control=UpDown.UP, step_code=0),
{"control": "up", "step_code": 0},
),
(
ControlBlinds(control=UpDown.DOWN, step_code=7),
{"control": "down", "step_code": 7},
),
(
ControlDimming(control=Step.DECREASE, step_code=5),
{"control": "decrease", "step_code": 5},
),
(
ControlDimming(control=Step.INCREASE, step_code=0),
{"control": "increase", "step_code": 0},
),
],
)
def test_dict(self, data: ControlBlinds, dict_value: dict[str, Any]) -> None:
"""Test from_dict and as_dict methods."""
test_dataclass = data.__class__
assert test_dataclass.from_dict(dict_value) == data
assert data.as_dict() == dict_value
@pytest.mark.parametrize(
"data",
[
{"control": 1, "step_code": "invalid"},
{"control": "up", "step_code": "invalid"},
{"control": "increase", "step_code": "invalid"},
{"control": "down", "step_code": None},
{"control": None, "step_code": 1},
{"control": "invalid", "step_code": 0},
{"control": 2, "step_code": 4},
],
)
def test_dict_invalid(self, data: dict[str, Any]) -> None:
"""Test from_dict with invalid data."""
with pytest.raises(ValueError):
ControlBlinds.from_dict(data)
with pytest.raises(ValueError):
ControlDimming.from_dict(data)
@pytest.mark.parametrize(
("dpt", "dpt_data", "control_enum"),
[
(DPTControlDimming, ControlDimming, Step),
(DPTControlBlinds, ControlBlinds, UpDown),
],
)
class TestDPTControlStepCode:
"""Test class for DPT 3 objects."""
def test_to_knx(
self,
dpt: type[DPTControlDimming | DPTControlBlinds],
dpt_data: type[ControlDimming | ControlBlinds],
control_enum: type[Step | UpDown],
) -> None:
"""Test serializing values."""
for rawref in range(16):
control = 1 if rawref >> 3 else 0
raw = dpt.to_knx(
dpt_data(
control=control_enum(control),
step_code=rawref & 0x07,
)
)
assert raw == DPTBinary(rawref)
def test_to_knx_dict(
self,
dpt: type[DPTControlDimming | DPTControlBlinds],
dpt_data: type[ControlDimming | ControlBlinds],
control_enum: type[Step | UpDown],
) -> None:
"""Test serializing values from dict."""
for rawref in range(16):
control = 1 if rawref >> 3 else 0
raw = dpt.to_knx(
{
"control": control_enum(control).name.lower(),
"step_code": rawref & 0x07,
}
)
assert raw == DPTBinary(rawref)
def test_to_knx_wrong_type(
self,
dpt: type[DPTControlDimming | DPTControlBlinds],
dpt_data: type[ControlDimming | ControlBlinds],
control_enum: type[Step | UpDown],
) -> None:
"""Test serializing wrong type."""
with pytest.raises(ConversionError):
dpt.to_knx("")
with pytest.raises(ConversionError):
dpt.to_knx(0)
def test_to_knx_missing_keys(
self,
dpt: type[DPTControlDimming | DPTControlBlinds],
dpt_data: type[ControlDimming | ControlBlinds],
control_enum: type[Step | UpDown],
) -> None:
"""Test serializing map with missing keys."""
with pytest.raises(ConversionError):
dpt.to_knx({"control": 0})
with pytest.raises(ConversionError):
dpt.to_knx({"step_code": 0})
def test_to_knx_wrong_value_types(
self,
dpt: type[DPTControlDimming | DPTControlBlinds],
dpt_data: type[ControlDimming | ControlBlinds],
control_enum: type[Step | UpDown],
) -> None:
"""Test serializing map with keys of invalid type."""
with pytest.raises(ConversionError):
dpt.to_knx({"control": "", "step_code": 0})
with pytest.raises(ConversionError):
dpt.to_knx({"control": 0, "step_code": ""})
def test_to_knx_wrong_values(
self,
dpt: type[DPTControlDimming | DPTControlBlinds],
dpt_data: type[ControlDimming | ControlBlinds],
control_enum: type[Step | UpDown],
) -> None:
"""Test serializing with invalid values."""
with pytest.raises(ConversionError):
dpt.to_knx({"control": -1, "step_code": 0})
with pytest.raises(ConversionError):
dpt.to_knx({"control": 2, "step_code": 0})
with pytest.raises(ConversionError):
dpt.to_knx({"control": 0, "step_code": -1})
with pytest.raises(ConversionError):
dpt.to_knx(dpt_data(control=control_enum(0), step_code=8))
def test_from_knx(
self,
dpt: type[DPTControlDimming | DPTControlBlinds],
dpt_data: type[ControlDimming | ControlBlinds],
control_enum: type[Step | UpDown],
) -> None:
"""Test parsing from KNX."""
for raw in range(16):
control = 1 if raw >> 3 else 0
valueref = dpt_data(
control=control_enum(control),
step_code=raw & 0x07,
)
value = dpt.from_knx(DPTBinary((raw,)))
assert value == valueref
def test_from_knx_wrong_value(
self,
dpt: type[DPTControlDimming | DPTControlBlinds],
dpt_data: type[ControlDimming | ControlBlinds],
control_enum: type[Step | UpDown],
) -> None:
"""Test parsing invalid values from KNX."""
with pytest.raises(CouldNotParseTelegram):
dpt.from_knx(DPTBinary((0x1F,)))
with pytest.raises(CouldNotParseTelegram):
dpt.from_knx(DPTArray((1,)))
|