text: """The Fjäråskupan integration."""
  from __future__ import annotations
  
  from collections.abc import Callable
  from dataclasses import dataclass
  from datetime import timedelta
  import logging
  
  from bleak import BleakScanner
  from bleak.backends.device import BLEDevice
  from bleak.backends.scanner import AdvertisementData
  from fjaraskupan import Device, State, device_filter
  
  from homeassistant.config_entries import ConfigEntry
  from homeassistant.core import HomeAssistant, callback
  from homeassistant.helpers.dispatcher import (
      async_dispatcher_connect,
      async_dispatcher_send,
  )
  from homeassistant.helpers.entity import DeviceInfo, Entity
  from homeassistant.helpers.entity_platform import AddEntitiesCallback
  from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
  
  from .const import DISPATCH_DETECTION, DOMAIN
  
  PLATFORMS = ["binary_sensor", "fan", "light", "sensor"]
  
  _LOGGER = logging.getLogger(__name__)
  
  
  @dataclass
  class DeviceState:
      """Store state of a device."""
  
      device: Device
      coordinator: DataUpdateCoordinator[State]
      device_info: DeviceInfo
  
  
  @dataclass
  class EntryState:
      """Store state of config entry."""
  
      scanner: BleakScanner
      devices: dict[str, DeviceState]
  
  
  async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
      """Set up Fjäråskupan from a config entry."""
  
      scanner = BleakScanner()
  
      state = EntryState(scanner, {})
      hass.data.setdefault(DOMAIN, {})
      hass.data[DOMAIN][entry.entry_id] = state
  
      async def detection_callback(
          ble_device: BLEDevice, advertisement_data: AdvertisementData
      ) -> None:
          if not device_filter(ble_device, advertisement_data):
              return
  
          _LOGGER.debug(
              "Detection: %s %s - %s", ble_device.name, ble_device, advertisement_data
          )
  
          if data := state.devices.get(ble_device.address):
              data.device.detection_callback(ble_device, advertisement_data)
              data.coordinator.async_set_updated_data(data.device.state)
          else:
  
              device = Device(ble_device)
              device.detection_callback(ble_device, advertisement_data)
  
              async def async_update_data():
                  """Handle an explicit update request."""
                  await device.update()
                  return device.state
  
              coordinator: DataUpdateCoordinator[State] = DataUpdateCoordinator(
                  hass,
                  logger=_LOGGER,
                  name="Fjaraskupan Updater",
                  update_interval=timedelta(seconds=120),
                  update_method=async_update_data,
              )
              coordinator.async_set_updated_data(device.state)
  
              device_info: DeviceInfo = {
                  "identifiers": {(DOMAIN, ble_device.address)},
                  "manufacturer": "Fjäråskupan",
                  "name": "Fjäråskupan",
              }
              device_state = DeviceState(device, coordinator, device_info)
              state.devices[ble_device.address] = device_state
              async_dispatcher_send(
                  hass, f"{DISPATCH_DETECTION}.{entry.entry_id}", device_state
              )
  
      scanner.register_detection_callback(detection_callback)
      await scanner.start()
  
      hass.config_entries.async_setup_platforms(entry, PLATFORMS)
      return True
  
  
  @callback
  def async_setup_entry_platform(
      hass: HomeAssistant,
      entry: ConfigEntry,
      async_add_entities: AddEntitiesCallback,
      constructor: Callable[[DeviceState], list[Entity]],
  ) -> None:
      """Set up a platform with added entities."""
  
      entry_state: EntryState = hass.data[DOMAIN][entry.entry_id]
      async_add_entities(
          entity
          for device_state in entry_state.devices.values()
          for entity in constructor(device_state)
      )
  
      @callback
      def _detection(device_state: DeviceState) -> None:
          async_add_entities(constructor(device_state))
  
      entry.async_on_unload(
          async_dispatcher_connect(
              hass, f"{DISPATCH_DETECTION}.{entry.entry_id}", _detection
          )
      )
  
  
  async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
      """Unload a config entry."""
      unload_ok = await hass.config_entries.async_unload_platforms(entry, PLATFORMS)
      if unload_ok:
          entry_state: EntryState = hass.data[DOMAIN].pop(entry.entry_id)
          await entry_state.scanner.stop()
  
      return unload_ok
  