diff --git a/homeassistant/components/eddystone_temperature/__init__.py b/homeassistant/components/eddystone_temperature/__init__.py deleted file mode 100644 index af37eb629b5..00000000000 --- a/homeassistant/components/eddystone_temperature/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -"""The eddystone_temperature component.""" - -DOMAIN = "eddystone_temperature" -CONF_BEACONS = "beacons" -CONF_INSTANCE = "instance" -CONF_NAMESPACE = "namespace" diff --git a/homeassistant/components/eddystone_temperature/manifest.json b/homeassistant/components/eddystone_temperature/manifest.json deleted file mode 100644 index 18e67f55667..00000000000 --- a/homeassistant/components/eddystone_temperature/manifest.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "domain": "eddystone_temperature", - "name": "Eddystone", - "codeowners": [], - "documentation": "https://www.home-assistant.io/integrations/eddystone_temperature", - "iot_class": "local_polling", - "loggers": ["beacontools"], - "quality_scale": "legacy", - "requirements": ["beacontools[scan]==2.1.0"] -} diff --git a/homeassistant/components/eddystone_temperature/sensor.py b/homeassistant/components/eddystone_temperature/sensor.py deleted file mode 100644 index 7b8e726cf45..00000000000 --- a/homeassistant/components/eddystone_temperature/sensor.py +++ /dev/null @@ -1,211 +0,0 @@ -"""Read temperature information from Eddystone beacons. - -Your beacons must be configured to transmit UID (for identification) and TLM -(for temperature) frames. -""" - -from __future__ import annotations - -import logging - -from beacontools import BeaconScanner, EddystoneFilter, EddystoneTLMFrame -import voluptuous as vol - -from homeassistant.components.sensor import ( - PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA, - SensorDeviceClass, - SensorEntity, -) -from homeassistant.const import ( - CONF_NAME, - EVENT_HOMEASSISTANT_START, - EVENT_HOMEASSISTANT_STOP, - STATE_UNKNOWN, - UnitOfTemperature, -) -from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, Event, HomeAssistant -from homeassistant.helpers import config_validation as cv -from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.issue_registry import IssueSeverity, create_issue -from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType - -from . import CONF_BEACONS, CONF_INSTANCE, CONF_NAMESPACE, DOMAIN - -_LOGGER = logging.getLogger(__name__) - -CONF_BT_DEVICE_ID = "bt_device_id" - - -BEACON_SCHEMA = vol.Schema( - { - vol.Required(CONF_NAMESPACE): cv.string, - vol.Required(CONF_INSTANCE): cv.string, - vol.Optional(CONF_NAME): cv.string, - } -) - -PLATFORM_SCHEMA = SENSOR_PLATFORM_SCHEMA.extend( - { - vol.Optional(CONF_BT_DEVICE_ID, default=0): cv.positive_int, - vol.Required(CONF_BEACONS): vol.Schema({cv.string: BEACON_SCHEMA}), - } -) - - -def setup_platform( - hass: HomeAssistant, - config: ConfigType, - add_entities: AddEntitiesCallback, - discovery_info: DiscoveryInfoType | None = None, -) -> None: - """Validate configuration, create devices and start monitoring thread.""" - create_issue( - hass, - HOMEASSISTANT_DOMAIN, - f"deprecated_system_packages_yaml_integration_{DOMAIN}", - breaks_in_ha_version="2025.12.0", - is_fixable=False, - issue_domain=DOMAIN, - severity=IssueSeverity.WARNING, - translation_key="deprecated_system_packages_yaml_integration", - translation_placeholders={ - "domain": DOMAIN, - "integration_title": "Eddystone", - }, - ) - - bt_device_id: int = config[CONF_BT_DEVICE_ID] - - beacons: dict[str, dict[str, str]] = config[CONF_BEACONS] - devices: list[EddystoneTemp] = [] - - for dev_name, properties in beacons.items(): - namespace = get_from_conf(properties, CONF_NAMESPACE, 20) - instance = get_from_conf(properties, CONF_INSTANCE, 12) - name = properties.get(CONF_NAME, dev_name) - - if instance is None or namespace is None: - _LOGGER.error("Skipping %s", dev_name) - continue - - devices.append(EddystoneTemp(name, namespace, instance)) - - if devices: - mon = Monitor(hass, devices, bt_device_id) - - def monitor_stop(event: Event) -> None: - """Stop the monitor thread.""" - _LOGGER.debug("Stopping scanner for Eddystone beacons") - mon.stop() - - def monitor_start(event: Event) -> None: - """Start the monitor thread.""" - _LOGGER.debug("Starting scanner for Eddystone beacons") - mon.start() - - add_entities(devices) - mon.start() - hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, monitor_stop) - hass.bus.listen_once(EVENT_HOMEASSISTANT_START, monitor_start) - else: - _LOGGER.warning("No devices were added") - - -def get_from_conf(config: dict[str, str], config_key: str, length: int) -> str | None: - """Retrieve value from config and validate length.""" - string = config[config_key] - if len(string) != length: - _LOGGER.error( - ( - "Error in configuration parameter %s: Must be exactly %d " - "bytes. Device will not be added" - ), - config_key, - length / 2, - ) - return None - return string - - -class EddystoneTemp(SensorEntity): - """Representation of a temperature sensor.""" - - _attr_device_class = SensorDeviceClass.TEMPERATURE - _attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS - _attr_should_poll = False - - def __init__(self, name: str, namespace: str, instance: str) -> None: - """Initialize a sensor.""" - self._attr_name = name - self.namespace = namespace - self.instance = instance - self.bt_addr = None - self.temperature = STATE_UNKNOWN - - @property - def native_value(self): - """Return the state of the device.""" - return self.temperature - - -class Monitor: - """Continuously scan for BLE advertisements.""" - - def __init__( - self, hass: HomeAssistant, devices: list[EddystoneTemp], bt_device_id: int - ) -> None: - """Construct interface object.""" - self.hass = hass - - # List of beacons to monitor - self.devices = devices - # Number of the bt device (hciX) - self.bt_device_id = bt_device_id - - def callback(bt_addr, _, packet, additional_info): - """Handle new packets.""" - self.process_packet( - additional_info["namespace"], - additional_info["instance"], - packet.temperature, - ) - - device_filters = [EddystoneFilter(d.namespace, d.instance) for d in devices] - - self.scanner = BeaconScanner( - callback, bt_device_id, device_filters, EddystoneTLMFrame - ) - self.scanning = False - - def start(self) -> None: - """Continuously scan for BLE advertisements.""" - if not self.scanning: - self.scanner.start() - self.scanning = True - else: - _LOGGER.debug("start() called, but scanner is already running") - - def process_packet(self, namespace, instance, temperature) -> None: - """Assign temperature to device.""" - _LOGGER.debug( - "Received temperature for <%s,%s>: %d", namespace, instance, temperature - ) - - for dev in self.devices: - if ( - dev.namespace == namespace - and dev.instance == instance - and dev.temperature != temperature - ): - dev.temperature = temperature - dev.schedule_update_ha_state() - - def stop(self) -> None: - """Signal runner to stop and join thread.""" - if self.scanning: - _LOGGER.debug("Stopping") - self.scanner.stop() - _LOGGER.debug("Stopped") - self.scanning = False - else: - _LOGGER.debug("stop() called but scanner was not running") diff --git a/homeassistant/generated/integrations.json b/homeassistant/generated/integrations.json index 87739075005..f84941ef62f 100644 --- a/homeassistant/generated/integrations.json +++ b/homeassistant/generated/integrations.json @@ -1585,12 +1585,6 @@ "config_flow": true, "iot_class": "local_push" }, - "eddystone_temperature": { - "name": "Eddystone", - "integration_type": "hub", - "config_flow": false, - "iot_class": "local_polling" - }, "edimax": { "name": "Edimax", "integration_type": "hub", diff --git a/requirements_all.txt b/requirements_all.txt index bd132a1fa4f..5e4f5549953 100644 --- a/requirements_all.txt +++ b/requirements_all.txt @@ -619,9 +619,6 @@ base36==0.1.1 # homeassistant.components.linux_battery batinfo==0.4.2 -# homeassistant.components.eddystone_temperature -# beacontools[scan]==2.1.0 - # homeassistant.components.scrape beautifulsoup4==4.13.3 diff --git a/requirements_test_all.txt b/requirements_test_all.txt index 4f352ecf384..2667d2d2c41 100644 --- a/requirements_test_all.txt +++ b/requirements_test_all.txt @@ -559,9 +559,6 @@ babel==2.15.0 # homeassistant.components.homekit base36==0.1.1 -# homeassistant.components.eddystone_temperature -# beacontools[scan]==2.1.0 - # homeassistant.components.scrape beautifulsoup4==4.13.3 diff --git a/script/gen_requirements_all.py b/script/gen_requirements_all.py index 0371818c271..ea88997d237 100755 --- a/script/gen_requirements_all.py +++ b/script/gen_requirements_all.py @@ -23,7 +23,6 @@ EXCLUDED_REQUIREMENTS_ALL = { "atenpdu", # depends on pysnmp which is not maintained at this time "avea", # depends on bluepy "avion", - "beacontools", "beewi-smartclim", # depends on bluepy "bluepy", "decora", diff --git a/tests/components/eddystone_temperature/__init__.py b/tests/components/eddystone_temperature/__init__.py deleted file mode 100644 index af67530c946..00000000000 --- a/tests/components/eddystone_temperature/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Tests for eddystone temperature.""" diff --git a/tests/components/eddystone_temperature/test_sensor.py b/tests/components/eddystone_temperature/test_sensor.py deleted file mode 100644 index 056681fdb90..00000000000 --- a/tests/components/eddystone_temperature/test_sensor.py +++ /dev/null @@ -1,45 +0,0 @@ -"""Tests for eddystone temperature.""" - -from unittest.mock import Mock, patch - -from homeassistant.components.eddystone_temperature import ( - CONF_BEACONS, - CONF_INSTANCE, - CONF_NAMESPACE, - DOMAIN, -) -from homeassistant.components.sensor import DOMAIN as PLATFORM_DOMAIN -from homeassistant.const import CONF_PLATFORM -from homeassistant.core import DOMAIN as HOMEASSISTANT_DOMAIN, HomeAssistant -from homeassistant.helpers import issue_registry as ir -from homeassistant.setup import async_setup_component - - -@patch.dict("sys.modules", beacontools=Mock()) -async def test_repair_issue_is_created( - hass: HomeAssistant, - issue_registry: ir.IssueRegistry, -) -> None: - """Test repair issue is created.""" - assert await async_setup_component( - hass, - PLATFORM_DOMAIN, - { - PLATFORM_DOMAIN: [ - { - CONF_PLATFORM: DOMAIN, - CONF_BEACONS: { - "living_room": { - CONF_NAMESPACE: "112233445566778899AA", - CONF_INSTANCE: "000000000001", - } - }, - } - ], - }, - ) - await hass.async_block_till_done() - assert ( - HOMEASSISTANT_DOMAIN, - f"deprecated_system_packages_yaml_integration_{DOMAIN}", - ) in issue_registry.issues