From b47861d9738915240f39bf579c31e92c51f08979 Mon Sep 17 00:00:00 2001
From: "J. Nick Koston" <nick@koston.org>
Date: Sun, 14 Jan 2024 09:44:42 -1000
Subject: [PATCH] Update shelly bluetooth scanner to version 2.0 (#107917)

---
 .../components/shelly/bluetooth/__init__.py   | 16 ++-----
 .../components/shelly/bluetooth/scanner.py    | 48 -------------------
 homeassistant/components/shelly/manifest.json |  2 +-
 requirements_all.txt                          |  2 +-
 requirements_test_all.txt                     |  2 +-
 .../shelly/bluetooth/test_scanner.py          | 46 +++++++++++++++++-
 6 files changed, 50 insertions(+), 66 deletions(-)
 delete mode 100644 homeassistant/components/shelly/bluetooth/scanner.py

diff --git a/homeassistant/components/shelly/bluetooth/__init__.py b/homeassistant/components/shelly/bluetooth/__init__.py
index 2f9019ba5e6..5432ceb3a12 100644
--- a/homeassistant/components/shelly/bluetooth/__init__.py
+++ b/homeassistant/components/shelly/bluetooth/__init__.py
@@ -3,7 +3,7 @@ from __future__ import annotations
 
 from typing import TYPE_CHECKING
 
-from aioshelly.ble import async_start_scanner
+from aioshelly.ble import async_start_scanner, create_scanner
 from aioshelly.ble.const import (
     BLE_SCAN_RESULT_EVENT,
     BLE_SCAN_RESULT_VERSION,
@@ -12,15 +12,11 @@ from aioshelly.ble.const import (
     DEFAULT_WINDOW_MS,
 )
 
-from homeassistant.components.bluetooth import (
-    HaBluetoothConnector,
-    async_register_scanner,
-)
+from homeassistant.components.bluetooth import async_register_scanner
 from homeassistant.core import CALLBACK_TYPE, HomeAssistant, callback as hass_callback
 from homeassistant.helpers.device_registry import format_mac
 
 from ..const import BLEScannerMode
-from .scanner import ShellyBLEScanner
 
 if TYPE_CHECKING:
     from ..coordinator import ShellyRpcCoordinator
@@ -35,13 +31,7 @@ async def async_connect_scanner(
     device = coordinator.device
     entry = coordinator.entry
     source = format_mac(coordinator.mac).upper()
-    connector = HaBluetoothConnector(
-        # no active connections to shelly yet
-        client=None,  # type: ignore[arg-type]
-        source=source,
-        can_connect=lambda: False,
-    )
-    scanner = ShellyBLEScanner(source, entry.title, connector, False)
+    scanner = create_scanner(source, entry.title)
     unload_callbacks = [
         async_register_scanner(hass, scanner),
         scanner.async_setup(),
diff --git a/homeassistant/components/shelly/bluetooth/scanner.py b/homeassistant/components/shelly/bluetooth/scanner.py
deleted file mode 100644
index 7c0dc3c792a..00000000000
--- a/homeassistant/components/shelly/bluetooth/scanner.py
+++ /dev/null
@@ -1,48 +0,0 @@
-"""Bluetooth scanner for shelly."""
-from __future__ import annotations
-
-from typing import Any
-
-from aioshelly.ble import parse_ble_scan_result_event
-from aioshelly.ble.const import BLE_SCAN_RESULT_EVENT, BLE_SCAN_RESULT_VERSION
-
-from homeassistant.components.bluetooth import MONOTONIC_TIME, BaseHaRemoteScanner
-from homeassistant.core import callback
-
-from ..const import LOGGER
-
-
-class ShellyBLEScanner(BaseHaRemoteScanner):
-    """Scanner for shelly."""
-
-    @callback
-    def async_on_event(self, event: dict[str, Any]) -> None:
-        """Process an event from the shelly and ignore if its not a ble.scan_result."""
-        if event.get("event") != BLE_SCAN_RESULT_EVENT:
-            return
-
-        data = event["data"]
-
-        if data[0] != BLE_SCAN_RESULT_VERSION:
-            LOGGER.warning("Unsupported BLE scan result version: %s", data[0])
-            return
-
-        try:
-            address, rssi, parsed = parse_ble_scan_result_event(data)
-        except Exception as err:  # pylint: disable=broad-except
-            # Broad exception catch because we have no
-            # control over the data that is coming in.
-            LOGGER.error("Failed to parse BLE event: %s", err, exc_info=True)
-            return
-
-        self._async_on_advertisement(
-            address,
-            rssi,
-            parsed.local_name,
-            parsed.service_uuids,
-            parsed.service_data,
-            parsed.manufacturer_data,
-            parsed.tx_power,
-            {},
-            MONOTONIC_TIME(),
-        )
diff --git a/homeassistant/components/shelly/manifest.json b/homeassistant/components/shelly/manifest.json
index 82833bf34af..94e2e9d70f0 100644
--- a/homeassistant/components/shelly/manifest.json
+++ b/homeassistant/components/shelly/manifest.json
@@ -9,7 +9,7 @@
   "iot_class": "local_push",
   "loggers": ["aioshelly"],
   "quality_scale": "platinum",
-  "requirements": ["aioshelly==7.1.0"],
+  "requirements": ["aioshelly==8.0.0"],
   "zeroconf": [
     {
       "type": "_http._tcp.local.",
diff --git a/requirements_all.txt b/requirements_all.txt
index c402377c4de..d59389e7aa8 100644
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -359,7 +359,7 @@ aioruuvigateway==0.1.0
 aiosenz==1.0.0
 
 # homeassistant.components.shelly
-aioshelly==7.1.0
+aioshelly==8.0.0
 
 # homeassistant.components.skybell
 aioskybell==22.7.0
diff --git a/requirements_test_all.txt b/requirements_test_all.txt
index 8ba2348dacd..bc8483c42e9 100644
--- a/requirements_test_all.txt
+++ b/requirements_test_all.txt
@@ -332,7 +332,7 @@ aioruuvigateway==0.1.0
 aiosenz==1.0.0
 
 # homeassistant.components.shelly
-aioshelly==7.1.0
+aioshelly==8.0.0
 
 # homeassistant.components.skybell
 aioskybell==22.7.0
diff --git a/tests/components/shelly/bluetooth/test_scanner.py b/tests/components/shelly/bluetooth/test_scanner.py
index 9fe5f77f00c..d9ec0064606 100644
--- a/tests/components/shelly/bluetooth/test_scanner.py
+++ b/tests/components/shelly/bluetooth/test_scanner.py
@@ -11,8 +11,8 @@ from homeassistant.core import HomeAssistant
 from .. import init_integration, inject_rpc_device_event
 
 
-async def test_scanner(hass: HomeAssistant, mock_rpc_device, monkeypatch) -> None:
-    """Test injecting data into the scanner."""
+async def test_scanner_v1(hass: HomeAssistant, mock_rpc_device, monkeypatch) -> None:
+    """Test injecting data into the scanner v1."""
     await init_integration(
         hass, 2, options={CONF_BLE_SCANNER_MODE: BLEScannerMode.ACTIVE}
     )
@@ -49,6 +49,48 @@ async def test_scanner(hass: HomeAssistant, mock_rpc_device, monkeypatch) -> Non
     assert ble_device is None
 
 
+async def test_scanner_v2(hass: HomeAssistant, mock_rpc_device, monkeypatch) -> None:
+    """Test injecting data into the scanner v2."""
+    await init_integration(
+        hass, 2, options={CONF_BLE_SCANNER_MODE: BLEScannerMode.ACTIVE}
+    )
+    assert mock_rpc_device.initialized is True
+    inject_rpc_device_event(
+        monkeypatch,
+        mock_rpc_device,
+        {
+            "events": [
+                {
+                    "component": "script:1",
+                    "data": [
+                        2,
+                        [
+                            [
+                                "aa:bb:cc:dd:ee:ff",
+                                -62,
+                                "AgEGCf9ZANH7O3TIkA==",
+                                "EQcbxdWlAgC4n+YRTSIADaLLBhYADUgQYQ==",
+                            ]
+                        ],
+                    ],
+                    "event": BLE_SCAN_RESULT_EVENT,
+                    "id": 1,
+                    "ts": 1668522399.2,
+                }
+            ],
+            "ts": 1668522399.2,
+        },
+    )
+    ble_device = bluetooth.async_ble_device_from_address(
+        hass, "AA:BB:CC:DD:EE:FF", connectable=False
+    )
+    assert ble_device is not None
+    ble_device = bluetooth.async_ble_device_from_address(
+        hass, "AA:BB:CC:DD:EE:FF", connectable=True
+    )
+    assert ble_device is None
+
+
 async def test_scanner_ignores_non_ble_events(
     hass: HomeAssistant, mock_rpc_device, monkeypatch
 ) -> None:
-- 
GitLab