diff --git a/plugwise_usb/constants.py b/plugwise_usb/constants.py index 47aab62e4..df8442103 100644 --- a/plugwise_usb/constants.py +++ b/plugwise_usb/constants.py @@ -58,26 +58,26 @@ "038500": "Stick", "070085": "Stick", "120002": "Stick Legrand", - "120041": "Circle+ Legrand type E", - "120000": "Circle+ Legrand type F", - "090000": "Circle+ type B", - "090007": "Circle+ type B", - "090088": "Circle+ type E", - "070073": "Circle+ type F", - "090048": "Circle+ type G", + "120041": "Circle + Legrand type E", + "120000": "Circle + Legrand type F", + "090000": "Circle + type B", + "090007": "Circle + type B", + "090088": "Circle + type E", + "070073": "Circle + type F", + "090048": "Circle + type G", + "090188": "Stealth +", "120049": "Stealth M+", - "090188": "Stealth+", + "120029": "Stealth Legrand", + "100025": "Circle", "120040": "Circle Legrand type E", "120001": "Circle Legrand type F", "090079": "Circle type B", "090087": "Circle type E", "070140": "Circle type F", "090093": "Circle type G", - "100025": "Circle", - "120048": "Stealth M", - "120029": "Stealth Legrand", "090011": "Stealth", "001200": "Stealth", + "120048": "Stealth M", "080007": "Scan", "110028": "Scan Legrand", "070030": "Sense", diff --git a/plugwise_usb/helpers/util.py b/plugwise_usb/helpers/util.py index c8529d65c..8e85878fc 100644 --- a/plugwise_usb/helpers/util.py +++ b/plugwise_usb/helpers/util.py @@ -21,18 +21,21 @@ def validate_mac(mac: str) -> bool: return True -def version_to_model(version: str | None) -> str: +def version_to_model(version: str | None) -> tuple[str|None, str]: """Translate hardware_version to device type.""" if version is None: - return "Unknown" + return (None, "Unknown") + local_version = version model = HW_MODELS.get(version) if model is None: - model = HW_MODELS.get(version[4:10]) + local_version = version[4:10] + model = HW_MODELS.get(local_version) if model is None: # Try again with reversed order - model = HW_MODELS.get(version[-2:] + version[-4:-2] + version[-6:-4]) + local_version = version[-2:] + version[-4:-2] + version[-6:-4] + model = HW_MODELS.get(local_version) - return model if model is not None else "Unknown" + return (local_version, model) if model is not None else (None, "Unknown") # octals (and hex) type as int according to diff --git a/plugwise_usb/nodes/node.py b/plugwise_usb/nodes/node.py index 75ec5dd64..1f937b99c 100644 --- a/plugwise_usb/nodes/node.py +++ b/plugwise_usb/nodes/node.py @@ -499,20 +499,26 @@ async def update_node_details( complete = False else: if self._node_info.version != hardware: - self._node_info.version = hardware # Generate modelname based on hardware version - model_info = version_to_model(hardware).split(" ") + hardware, model_info = version_to_model(hardware) + model_info = model_info.split(" ") self._node_info.model = model_info[0] + # Handle + devices + if len(model_info) > 1 and "+" in model_info[1]: + self._node_info.model = model_info[0] + " " + model_info[1] + model_info[0] = self._node_info.model + model_info.pop(1) + + self._node_info.version = hardware if self._node_info.model == "Unknown": _LOGGER.warning( "Failed to detect hardware model for %s based on '%s'", self.mac, hardware, ) + self._node_info.model_type = None if len(model_info) > 1: self._node_info.model_type = " ".join(model_info[1:]) - else: - self._node_info.model_type = "" if self._node_info.model is not None: self._node_info.name = f"{model_info[0]} {self._node_info.mac[-5:]}" self._set_cache(CACHE_HARDWARE, hardware) diff --git a/tests/stick_test_data.py b/tests/stick_test_data.py index ac32b151a..be98c323c 100644 --- a/tests/stick_test_data.py +++ b/tests/stick_test_data.py @@ -47,7 +47,7 @@ + b"00044280" # log address 20 + b"01" # relay + b"01" # hz - + b"000000730007" # hw_ver + + b"000000730007" # hw_ver + b"4E0843A9" # fw_ver + b"01", # node_type (Circle+) ), @@ -445,7 +445,7 @@ + b"000442C0" # log address 44000 + b"01" # relay + b"01" # hz - + b"000000070140" # hw_ver + + b"000007014000" # hw_ver + b"4E0844C2" # fw_ver + b"02", # node_type (Circle) ), @@ -458,7 +458,7 @@ + b"00044300" # log address + b"01" # relay + b"01" # hz - + b"000000090011" # hw_ver + + b"000009001100" # hw_ver + b"4EB28FD5" # fw_ver + b"09", # node_type (Stealth - Legrand) ), @@ -495,7 +495,7 @@ + b"00044340" # log address + b"01" # relay + b"01" # hz - + b"000000070073" # hw_ver + + b"000007007300" # hw_ver + b"4DCCDB7B" # fw_ver + b"02", # node_type (Circle) ), @@ -508,7 +508,7 @@ + b"000443C0" # log address + b"01" # relay + b"01" # hz - + b"000000070073" # hw_ver + + b"000007007300" # hw_ver + b"4E0844C2" # fw_ver + b"02", # node_type (Circle) ), @@ -654,7 +654,7 @@ + b"00000000" # log address + b"00" # relay + b"01" # hz - + b"000000070008" # hw_ver + + b"000008000700" # hw_ver + b"4E084590" # fw_ver + b"06", # node_type (Scan) ), diff --git a/tests/test_usb.py b/tests/test_usb.py index 17002b9d1..bfd4ec430 100644 --- a/tests/test_usb.py +++ b/tests/test_usb.py @@ -586,9 +586,9 @@ async def test_stick_node_discovered_subscription( assert stick.nodes["5555555555555555"].node_info.firmware == dt( 2011, 6, 27, 8, 55, 44, tzinfo=UTC ) - assert stick.nodes["5555555555555555"].node_info.version == "000000070008" + assert stick.nodes["5555555555555555"].node_info.version == "080007" assert stick.nodes["5555555555555555"].node_info.model == "Scan" - assert stick.nodes["5555555555555555"].node_info.model_type == "" + assert stick.nodes["5555555555555555"].node_info.model_type == None assert stick.nodes["5555555555555555"].available assert stick.nodes["5555555555555555"].node_info.is_battery_powered assert sorted(stick.nodes["5555555555555555"].features) == sorted( @@ -1466,7 +1466,7 @@ async def test_creating_request_messages(self) -> None: @pytest.mark.asyncio async def test_stick_network_down(self, monkeypatch: pytest.MonkeyPatch) -> None: - """Testing timeout circle+ discovery.""" + """Testing timeout Circle + discovery.""" mock_serial = MockSerial( { b"\x05\x05\x03\x03000AB43C\r\n": ( @@ -2393,14 +2393,14 @@ async def test_node_discovery_and_load( assert len(stick.nodes) == 6 assert stick.nodes["0098765432101234"].is_loaded - assert stick.nodes["0098765432101234"].name == "Circle+ 01234" + assert stick.nodes["0098765432101234"].name == "Circle + 01234" assert stick.nodes["0098765432101234"].node_info.firmware == dt( 2011, 6, 27, 8, 47, 37, tzinfo=UTC ) - assert stick.nodes["0098765432101234"].node_info.version == "000000730007" - assert stick.nodes["0098765432101234"].node_info.model == "Circle+" + assert stick.nodes["0098765432101234"].node_info.version == "070073" + assert stick.nodes["0098765432101234"].node_info.model == "Circle +" assert stick.nodes["0098765432101234"].node_info.model_type == "type F" - assert stick.nodes["0098765432101234"].node_info.name == "Circle+ 01234" + assert stick.nodes["0098765432101234"].node_info.name == "Circle + 01234" assert stick.nodes["0098765432101234"].available assert not stick.nodes["0098765432101234"].node_info.is_battery_powered assert not stick.nodes["0098765432101234"].is_battery_powered @@ -2472,8 +2472,8 @@ async def test_node_discovery_and_load( assert state[pw_api.NodeFeature.INFO].firmware == dt( 2011, 6, 27, 8, 47, 37, tzinfo=UTC ) - assert state[pw_api.NodeFeature.INFO].name == "Circle+ 01234" - assert state[pw_api.NodeFeature.INFO].model == "Circle+" + assert state[pw_api.NodeFeature.INFO].name == "Circle + 01234" + assert state[pw_api.NodeFeature.INFO].model == "Circle +" assert state[pw_api.NodeFeature.INFO].model_type == "type F" assert state[pw_api.NodeFeature.INFO].node_type == pw_api.NodeType.CIRCLE_PLUS assert ( @@ -2482,7 +2482,7 @@ async def test_node_discovery_and_load( ) == get_state_timestamp ) - assert state[pw_api.NodeFeature.INFO].version == "000000730007" + assert state[pw_api.NodeFeature.INFO].version == "070073" assert state[pw_api.NodeFeature.RELAY].state @@ -2495,7 +2495,7 @@ async def test_node_discovery_and_load( assert state[pw_api.NodeFeature.INFO].mac == "1111111111111111" assert state[pw_api.NodeFeature.INFO].zigbee_address == 0 assert not state[pw_api.NodeFeature.INFO].is_battery_powered - assert state[pw_api.NodeFeature.INFO].version == "000000070140" + assert state[pw_api.NodeFeature.INFO].version == "070140" assert state[pw_api.NodeFeature.INFO].node_type == pw_api.NodeType.CIRCLE assert ( state[pw_api.NodeFeature.INFO].timestamp.replace( @@ -2529,9 +2529,9 @@ async def test_node_discovery_and_load( assert stick.nodes["5555555555555555"].node_info.firmware == dt( 2011, 6, 27, 8, 55, 44, tzinfo=UTC ) - assert stick.nodes["5555555555555555"].node_info.version == "000000070008" + assert stick.nodes["5555555555555555"].node_info.version == "080007" assert stick.nodes["5555555555555555"].node_info.model == "Scan" - assert stick.nodes["5555555555555555"].node_info.model_type == "" + assert stick.nodes["5555555555555555"].node_info.model_type == None assert stick.nodes["5555555555555555"].available assert stick.nodes["5555555555555555"].node_info.is_battery_powered assert sorted(stick.nodes["5555555555555555"].features) == sorted( @@ -2594,9 +2594,9 @@ async def test_node_discovery_and_load( assert stick.nodes["8888888888888888"].node_info.firmware == dt( 2011, 6, 27, 9, 4, 10, tzinfo=UTC ) - assert stick.nodes["8888888888888888"].node_info.version == "000007005100" + assert stick.nodes["8888888888888888"].node_info.version == "070051" assert stick.nodes["8888888888888888"].node_info.model == "Switch" - assert stick.nodes["8888888888888888"].node_info.model_type == "" + assert stick.nodes["8888888888888888"].node_info.model_type == None assert stick.nodes["8888888888888888"].available assert stick.nodes["8888888888888888"].node_info.is_battery_powered assert sorted(stick.nodes["8888888888888888"].features) == sorted(