"""Bluetti Bluetooth Integration""" from __future__ import annotations import re import logging from homeassistant.components import bluetooth from homeassistant.config_entries import ConfigEntry from homeassistant.const import CONF_ADDRESS, CONF_TYPE, CONF_NAME, Platform from homeassistant.core import HomeAssistant from homeassistant.helpers.entity import DeviceInfo from homeassistant.exceptions import ConfigEntryNotReady from bluetti_mqtt.bluetooth import build_device as orig_build_device from .const import ( CONF_MAX_RETRIES, CONF_PERSISTENT_CONN, CONF_POLLING_INTERVAL, CONF_POLLING_TIMEOUT, CONF_USE_CONTROLS, DATA_COORDINATOR, DATA_POLLING_RUNNING, DEVICE_NAME_RE, DOMAIN, MANUFACTURER, ) from .coordinator import PollingCoordinator from .devices.ep600 import EP600 from .devices.ep700 import EP700 PLATFORMS: [Platform] = [Platform.BINARY_SENSOR, Platform.SENSOR] _LOGGER = logging.getLogger(__name__) async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: """Set up Bluetti Powerstation from a config entry.""" address = entry.data.get(CONF_ADDRESS) device_name = entry.data.get(CONF_NAME) use_controls = entry.data.get(CONF_USE_CONTROLS) polling_interval = entry.data.get(CONF_POLLING_INTERVAL, 20) persistent_conn = entry.data.get(CONF_PERSISTENT_CONN, False) polling_timeout = entry.data.get(CONF_POLLING_TIMEOUT, 45) max_retries = entry.data.get(CONF_MAX_RETRIES, 5) if address is None: return False if not bluetooth.async_address_present(hass, address): raise ConfigEntryNotReady("Bluetti device not present") # Create data structure hass.data.setdefault(DOMAIN, {}) hass.data[DOMAIN].setdefault(entry.entry_id, {}) hass.data[DOMAIN][entry.entry_id].setdefault(DATA_POLLING_RUNNING, False) # Create coordinator for polling coordinator = PollingCoordinator(hass, address, device_name, polling_interval, persistent_conn, polling_timeout, max_retries) await coordinator.async_config_entry_first_refresh() hass.data[DOMAIN][entry.entry_id].setdefault(DATA_COORDINATOR, coordinator) platforms: list = PLATFORMS if use_controls is True: _LOGGER.warning("You are using controls with this integration at your own risk!") platforms.append(Platform.SWITCH) # Setup platforms await hass.config_entries.async_forward_entry_setups(entry, platforms) return True def device_info(entry: ConfigEntry) -> DeviceInfo: """Device info.""" return DeviceInfo( identifiers={(DOMAIN, entry.data.get(CONF_ADDRESS))}, name=entry.title, manufacturer=MANUFACTURER, model=entry.data.get(CONF_TYPE), ) def get_unique_id(name: str, sensor_type: str | None = None): """Generate an unique id.""" res = re.sub("[^A-Za-z0-9]+", "_", name).lower() if sensor_type is not None: return f"{sensor_type}.{res}" return res def get_type_by_bt_name(bt_name: str): """Get the device type.""" dev_type = "Unknown" if bt_name.startswith("AC200M"): dev_type = "AC200M" elif bt_name.startswith("AC300"): dev_type = "AC300" elif bt_name.startswith("AC500"): dev_type = "AC500" elif bt_name.startswith("AC60"): dev_type = "AC60" elif bt_name.startswith("EB3A"): dev_type = "EB3A" elif bt_name.startswith("EP500"): dev_type = "EP500" elif bt_name.startswith("EP600"): dev_type = "EP600" elif bt_name.startswith("EP700"): dev_type = "EP700" return dev_type def build_device(address: str, name: str): match = DEVICE_NAME_RE.match(name) if match[1] == 'EP700': return EP700(address, match[2]) elif match[1] == 'EP600': return EP600(address, match[2]) else: return orig_build_device(address, name)