From d4c94f0cb273617d5396a6285d6fefa91a31fd42 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 27 Sep 2018 13:06:46 +0200 Subject: [PATCH 1/2] Normalize MAC addresses --- homeassistant/helpers/device_registry.py | 17 ++++ tests/helpers/test_device_registry.py | 113 ++++++++++++++++++++--- 2 files changed, 115 insertions(+), 15 deletions(-) diff --git a/homeassistant/helpers/device_registry.py b/homeassistant/helpers/device_registry.py index 478b29c75..0f29ffac2 100644 --- a/homeassistant/helpers/device_registry.py +++ b/homeassistant/helpers/device_registry.py @@ -38,6 +38,17 @@ class DeviceEntry: id = attr.ib(type=str, default=attr.Factory(lambda: uuid.uuid4().hex)) +def format_mac(mac): + """Format the mac address string for entry into dev reg.""" + lower_mac = mac.lower() + if len(lower_mac) == 12: + # no : included + return ':'.join(lower_mac[i:i + 2] for i in range(0, 12, 2)) + + # Either with ':' included or not sure how formatted + return lower_mac + + class DeviceRegistry: """Class to hold a registry of devices.""" @@ -71,6 +82,12 @@ class DeviceRegistry: if connections is None: connections = set() + connections = { + (key, format_mac(value)) if key == CONNECTION_NETWORK_MAC + else (key, value) + for key, value in connections + } + device = self.async_get_device(identifiers, connections) if device is None: diff --git a/tests/helpers/test_device_registry.py b/tests/helpers/test_device_registry.py index a87ad3d48..38e29773b 100644 --- a/tests/helpers/test_device_registry.py +++ b/tests/helpers/test_device_registry.py @@ -15,7 +15,9 @@ async def test_get_or_create_returns_same_entry(registry): """Make sure we do not duplicate entries.""" entry = registry.async_get_or_create( config_entry_id='1234', - connections={('ethernet', '12:34:56:78:90:AB:CD:EF')}, + connections={ + (device_registry.CONNECTION_NETWORK_MAC, '12:34:56:AB:CD:EF') + }, identifiers={('bridgeid', '0123')}, sw_version='sw-version', name='name', @@ -23,12 +25,16 @@ async def test_get_or_create_returns_same_entry(registry): model='model') entry2 = registry.async_get_or_create( config_entry_id='1234', - connections={('ethernet', '11:22:33:44:55:66:77:88')}, + connections={ + (device_registry.CONNECTION_NETWORK_MAC, '11:22:33:66:77:88') + }, identifiers={('bridgeid', '0123')}, manufacturer='manufacturer', model='model') entry3 = registry.async_get_or_create( config_entry_id='1234', - connections={('ethernet', '12:34:56:78:90:AB:CD:EF')} + connections={ + (device_registry.CONNECTION_NETWORK_MAC, '12:34:56:AB:CD:EF') + } ) assert len(registry.devices) == 1 @@ -46,7 +52,9 @@ async def test_requirement_for_identifier_or_connection(registry): """Make sure we do require some descriptor of device.""" entry = registry.async_get_or_create( config_entry_id='1234', - connections={('ethernet', '12:34:56:78:90:AB:CD:EF')}, + connections={ + (device_registry.CONNECTION_NETWORK_MAC, '12:34:56:AB:CD:EF') + }, identifiers=set(), manufacturer='manufacturer', model='model') entry2 = registry.async_get_or_create( @@ -70,17 +78,23 @@ async def test_multiple_config_entries(registry): """Make sure we do not get duplicate entries.""" entry = registry.async_get_or_create( config_entry_id='123', - connections={('ethernet', '12:34:56:78:90:AB:CD:EF')}, + connections={ + (device_registry.CONNECTION_NETWORK_MAC, '12:34:56:AB:CD:EF') + }, identifiers={('bridgeid', '0123')}, manufacturer='manufacturer', model='model') entry2 = registry.async_get_or_create( config_entry_id='456', - connections={('ethernet', '12:34:56:78:90:AB:CD:EF')}, + connections={ + (device_registry.CONNECTION_NETWORK_MAC, '12:34:56:AB:CD:EF') + }, identifiers={('bridgeid', '0123')}, manufacturer='manufacturer', model='model') entry3 = registry.async_get_or_create( config_entry_id='123', - connections={('ethernet', '12:34:56:78:90:AB:CD:EF')}, + connections={ + (device_registry.CONNECTION_NETWORK_MAC, '12:34:56:AB:CD:EF') + }, identifiers={('bridgeid', '0123')}, manufacturer='manufacturer', model='model') @@ -110,7 +124,7 @@ async def test_loading_from_storage(hass, hass_storage): 'identifiers': [ [ 'serial', - '12:34:56:78:90:AB:CD:EF' + '12:34:56:AB:CD:EF' ] ], 'manufacturer': 'manufacturer', @@ -127,7 +141,7 @@ async def test_loading_from_storage(hass, hass_storage): entry = registry.async_get_or_create( config_entry_id='1234', connections={('Zigbee', '01.23.45.67.89')}, - identifiers={('serial', '12:34:56:78:90:AB:CD:EF')}, + identifiers={('serial', '12:34:56:AB:CD:EF')}, manufacturer='manufacturer', model='model') assert entry.id == 'abcdefghijklm' assert isinstance(entry.config_entries, set) @@ -137,17 +151,23 @@ async def test_removing_config_entries(registry): """Make sure we do not get duplicate entries.""" entry = registry.async_get_or_create( config_entry_id='123', - connections={('ethernet', '12:34:56:78:90:AB:CD:EF')}, + connections={ + (device_registry.CONNECTION_NETWORK_MAC, '12:34:56:AB:CD:EF') + }, identifiers={('bridgeid', '0123')}, manufacturer='manufacturer', model='model') entry2 = registry.async_get_or_create( config_entry_id='456', - connections={('ethernet', '12:34:56:78:90:AB:CD:EF')}, + connections={ + (device_registry.CONNECTION_NETWORK_MAC, '12:34:56:AB:CD:EF') + }, identifiers={('bridgeid', '0123')}, manufacturer='manufacturer', model='model') entry3 = registry.async_get_or_create( config_entry_id='123', - connections={('ethernet', '34:56:78:90:AB:CD:EF:12')}, + connections={ + (device_registry.CONNECTION_NETWORK_MAC, '34:56:78:CD:EF:12') + }, identifiers={('bridgeid', '4567')}, manufacturer='manufacturer', model='model') @@ -168,7 +188,9 @@ async def test_specifying_hub_device_create(registry): """Test specifying a hub and updating.""" hub = registry.async_get_or_create( config_entry_id='123', - connections={('ethernet', '12:34:56:78:90:AB:CD:EF')}, + connections={ + (device_registry.CONNECTION_NETWORK_MAC, '12:34:56:AB:CD:EF') + }, identifiers={('hue', '0123')}, manufacturer='manufacturer', model='hub') @@ -195,7 +217,9 @@ async def test_specifying_hub_device_update(registry): hub = registry.async_get_or_create( config_entry_id='123', - connections={('ethernet', '12:34:56:78:90:AB:CD:EF')}, + connections={ + (device_registry.CONNECTION_NETWORK_MAC, '12:34:56:AB:CD:EF') + }, identifiers={('hue', '0123')}, manufacturer='manufacturer', model='hub') @@ -213,7 +237,9 @@ async def test_loading_saving_data(hass, registry): """Test that we load/save data correctly.""" orig_hub = registry.async_get_or_create( config_entry_id='123', - connections={('ethernet', '12:34:56:78:90:AB:CD:EF')}, + connections={ + (device_registry.CONNECTION_NETWORK_MAC, '12:34:56:AB:CD:EF') + }, identifiers={('hue', '0123')}, manufacturer='manufacturer', model='hub') @@ -239,3 +265,60 @@ async def test_loading_saving_data(hass, registry): assert orig_hub == new_hub assert orig_light == new_light + + +async def test_format_mac(registry): + """Make sure we normalize mac addresses.""" + entry = registry.async_get_or_create( + config_entry_id='1234', + connections={ + (device_registry.CONNECTION_NETWORK_MAC, '12:34:56:AB:CD:EF') + }, + ) + entry2 = registry.async_get_or_create( + config_entry_id='1234', + connections={ + (device_registry.CONNECTION_NETWORK_MAC, '123456ABCDEF') + }, + ) + entry3 = registry.async_get_or_create( + config_entry_id='1234', + connections={ + (device_registry.CONNECTION_NETWORK_MAC, '123456abcdef') + }, + ) + entry4 = registry.async_get_or_create( + config_entry_id='1234', + connections={ + (device_registry.CONNECTION_NETWORK_MAC, '12:34:56:ab:cd:ef') + }, + ) + + assert entry.connections == { + (device_registry.CONNECTION_NETWORK_MAC, '12:34:56:ab:cd:ef') + } + + assert entry.id == entry2.id + assert entry2.connections == { + (device_registry.CONNECTION_NETWORK_MAC, '12:34:56:ab:cd:ef') + } + + assert entry.id == entry3.id + assert entry2.connections == { + (device_registry.CONNECTION_NETWORK_MAC, '12:34:56:ab:cd:ef') + } + + assert entry.id == entry4.id + assert entry4.connections == { + (device_registry.CONNECTION_NETWORK_MAC, '12:34:56:ab:cd:ef') + } + + # This should not raise + invalid_mac_entry = registry.async_get_or_create( + config_entry_id='1234', + connections={ + (device_registry.CONNECTION_NETWORK_MAC, 'invalid_mac') + }, + ) + + assert list(invalid_mac_entry.connections)[0][1] == 'invalid_mac' From d9250687709958af2a5b5d1b6fca01f10fa61248 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Thu, 27 Sep 2018 14:13:50 +0200 Subject: [PATCH 2/2] Fix deconz test --- tests/components/deconz/test_init.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/components/deconz/test_init.py b/tests/components/deconz/test_init.py index cfda1232e..0e02db7ed 100644 --- a/tests/components/deconz/test_init.py +++ b/tests/components/deconz/test_init.py @@ -136,6 +136,7 @@ async def test_unload_entry(hass): entry.data = {'host': '1.2.3.4', 'port': 80, 'api_key': '1234567890ABCDEF'} entry.async_unload.return_value = mock_coro(True) deconzmock = Mock() + deconzmock.config.mac = 'mock-mac' deconzmock.async_load_parameters.return_value = mock_coro(True) deconzmock.sensors = {} with patch('pydeconz.DeconzSession', return_value=deconzmock):