コード例 #1
0
ファイル: test_init.py プロジェクト: OpenPeerPower/core
async def test_removed_device(opp, client, multiple_devices, integration):
    """Test that the device registry gets updated when a device gets removed."""
    nodes = multiple_devices

    # Verify how many nodes are available
    assert len(client.driver.controller.nodes) == 2

    # Make sure there are the same number of devices
    dev_reg = dr.async_get(opp)
    device_entries = dr.async_entries_for_config_entry(dev_reg,
                                                       integration.entry_id)
    assert len(device_entries) == 2

    # Check how many entities there are
    ent_reg = er.async_get(opp)
    entity_entries = er.async_entries_for_config_entry(ent_reg,
                                                       integration.entry_id)
    assert len(entity_entries) == 24

    # Remove a node and reload the entry
    old_node = nodes.pop(13)
    await opp.config_entries.async_reload(integration.entry_id)
    await opp.async_block_till_done()

    # Assert that the node and all of it's entities were removed from the device and
    # entity registry
    device_entries = dr.async_entries_for_config_entry(dev_reg,
                                                       integration.entry_id)
    assert len(device_entries) == 1
    entity_entries = er.async_entries_for_config_entry(ent_reg,
                                                       integration.entry_id)
    assert len(entity_entries) == 15
    assert dev_reg.async_get_device({get_device_id(client, old_node)}) is None
コード例 #2
0
async def async_restore_block_attribute_entities(opp, config_entry,
                                                 async_add_entities, wrapper,
                                                 sensors, sensor_class):
    """Restore block attributes entities."""
    entities = []

    ent_reg = await entity_registry.async_get_registry(opp)
    entries = entity_registry.async_entries_for_config_entry(
        ent_reg, config_entry.entry_id)

    domain = sensor_class.__module__.split(".")[-1]

    for entry in entries:
        if entry.domain != domain:
            continue

        attribute = entry.unique_id.split("-")[-1]
        description = BlockAttributeDescription(
            name="",
            icon=entry.original_icon,
            unit=entry.unit_of_measurement,
            device_class=entry.device_class,
        )

        entities.append(
            sensor_class(wrapper, None, attribute, description, entry,
                         sensors))

    if not entities:
        return

    async_add_entities(entities)
コード例 #3
0
ファイル: migration.py プロジェクト: OpenPeerPower/core
async def async_get_migration_data(opp):
    """Return dict with ozw side migration info."""
    data = {}
    nodes_values = opp.data[DOMAIN][NODES_VALUES]
    ozw_config_entries = opp.config_entries.async_entries(DOMAIN)
    config_entry = ozw_config_entries[0]  # ozw only has a single config entry
    ent_reg = await async_get_entity_registry(opp)
    entity_entries = async_entries_for_config_entry(ent_reg,
                                                    config_entry.entry_id)
    unique_entries = {entry.unique_id: entry for entry in entity_entries}
    dev_reg = await async_get_device_registry(opp)

    for node_id, node_values in nodes_values.items():
        for entity_values in node_values:
            unique_id = create_value_id(entity_values.primary)
            if unique_id not in unique_entries:
                continue
            node = entity_values.primary.node
            device_identifier = (
                DOMAIN,
                create_device_id(node, entity_values.primary.instance),
            )
            device_entry = dev_reg.async_get_device({device_identifier}, set())
            data[unique_id] = {
                "node_id": node_id,
                "node_instance": entity_values.primary.instance,
                "device_id": device_entry.id,
                "command_class": entity_values.primary.command_class.value,
                "command_class_label": entity_values.primary.label,
                "value_index": entity_values.primary.index,
                "unique_id": unique_id,
                "entity_entry": unique_entries[unique_id],
            }

    return data
コード例 #4
0
async def async_unload_entry(opp: core.OpenPeerPower,
                             config_entry: config_entries.ConfigEntry):
    """Unload a config entry."""
    unload_ok = await opp.config_entries.async_unload_platforms(
        config_entry, PLATFORMS)

    opp.data[DOMAIN][config_entry.entry_id][UNDO_UPDATE_LISTENER]()

    # Remove zone2 and zone3 entities if needed
    entity_registry = await er.async_get_registry(opp)
    entries = er.async_entries_for_config_entry(entity_registry,
                                                config_entry.entry_id)
    unique_id = config_entry.unique_id or config_entry.entry_id
    zone2_id = f"{unique_id}-Zone2"
    zone3_id = f"{unique_id}-Zone3"
    for entry in entries:
        if entry.unique_id == zone2_id and not config_entry.options.get(
                CONF_ZONE2):
            entity_registry.async_remove(entry.entity_id)
            _LOGGER.debug("Removing zone2 from DenonAvr")
        if entry.unique_id == zone3_id and not config_entry.options.get(
                CONF_ZONE3):
            entity_registry.async_remove(entry.entity_id)
            _LOGGER.debug("Removing zone3 from DenonAvr")

    if unload_ok:
        opp.data[DOMAIN].pop(config_entry.entry_id)

    return unload_ok
コード例 #5
0
ファイル: switch.py プロジェクト: OpenPeerPower/core
async def async_setup_entry(opp, config_entry, async_add_entities):
    """Set up switches for UniFi component.

    Switches are controlling network access and switch ports with POE.
    """
    controller = opp.data[UNIFI_DOMAIN][config_entry.entry_id]
    controller.entities[DOMAIN] = {
        BLOCK_SWITCH: set(),
        POE_SWITCH: set(),
        DPI_SWITCH: set(),
    }

    if controller.site_role != "admin":
        return

    # Store previously known POE control entities in case their POE are turned off.
    known_poe_clients = []
    entity_registry = await opp.helpers.entity_registry.async_get_registry()
    for entry in async_entries_for_config_entry(entity_registry,
                                                config_entry.entry_id):

        if not entry.unique_id.startswith(POE_SWITCH):
            continue

        mac = entry.unique_id.replace(f"{POE_SWITCH}-", "")
        if mac not in controller.api.clients:
            continue

        known_poe_clients.append(mac)

    for mac in controller.option_block_clients:
        if mac not in controller.api.clients and mac in controller.api.clients_all:
            client = controller.api.clients_all[mac]
            controller.api.clients.process_raw([client.raw])

    @callback
    def items_added(
        clients: set = controller.api.clients,
        devices: set = controller.api.devices,
        dpi_groups: set = controller.api.dpi_groups,
    ) -> None:
        """Update the values of the controller."""
        if controller.option_block_clients:
            add_block_entities(controller, async_add_entities, clients)

        if controller.option_poe_clients:
            add_poe_entities(controller, async_add_entities, clients,
                             known_poe_clients)

        if controller.option_dpi_restrictions:
            add_dpi_entities(controller, async_add_entities, dpi_groups)

    for signal in (controller.signal_update, controller.signal_options_update):
        config_entry.async_on_unload(
            async_dispatcher_connect(opp, signal, items_added))

    items_added()
    known_poe_clients.clear()
コード例 #6
0
async def test_add_new_binary_sensor_ignored(opp, aioclient_mock,
                                             mock_deconz_websocket):
    """Test that adding a new binary sensor is not allowed."""
    sensor = {
        "name": "Presence sensor",
        "type": "ZHAPresence",
        "state": {
            "presence": False
        },
        "config": {
            "on": True,
            "reachable": True
        },
        "uniqueid": "00:00:00:00:00:00:00:00-00",
    }
    event_added_sensor = {
        "t": "event",
        "e": "added",
        "r": "sensors",
        "id": "1",
        "sensor": sensor,
    }

    config_entry = await setup_deconz_integration(
        opp,
        aioclient_mock,
        options={
            CONF_MASTER_GATEWAY: True,
            CONF_ALLOW_NEW_DEVICES: False
        },
    )

    assert len(opp.states.async_all()) == 0

    await mock_deconz_websocket(data=event_added_sensor)
    await opp.async_block_till_done()

    assert len(opp.states.async_all()) == 0
    assert not opp.states.get("binary_sensor.presence_sensor")

    entity_registry = er.async_get(opp)
    assert (len(
        async_entries_for_config_entry(entity_registry,
                                       config_entry.entry_id)) == 0)

    aioclient_mock.clear_requests()
    data = {"groups": {}, "lights": {}, "sensors": {"1": sensor}}
    mock_deconz_request(aioclient_mock, config_entry.data, data)

    await opp.services.async_call(DECONZ_DOMAIN, SERVICE_DEVICE_REFRESH)
    await opp.async_block_till_done()

    assert len(opp.states.async_all()) == 1
    assert opp.states.get("binary_sensor.presence_sensor")
コード例 #7
0
    def _resolve_config_entry(self, config_entry_id) -> None:
        """Resolve a config entry.

        Will only be called if config entry is an entry point.
        """
        for device_entry in device_registry.async_entries_for_config_entry(
                self._device_reg, config_entry_id):
            self._add_or_resolve("device", device_entry.id)

        for entity_entry in entity_registry.async_entries_for_config_entry(
                self._entity_reg, config_entry_id):
            self._add_or_resolve("entity", entity_entry.entity_id)
コード例 #8
0
async def async_setup_entry(opp: OpenPeerPower, config_entry: ConfigEntry) -> bool:
    """Load the saved entities."""
    if config_entry.unique_id is not None:
        opp.config_entries.async_update_entry(config_entry, unique_id=None)

        ent_reg = async_get(opp)
        for entity in async_entries_for_config_entry(ent_reg, config_entry.entry_id):
            ent_reg.async_update_entity(
                entity.entity_id, new_unique_id=config_entry.entry_id
            )

    opp.config_entries.async_setup_platforms(config_entry, PLATFORMS)
    return True
コード例 #9
0
async def async_setup_entry(opp: OpenPeerPower, config_entry: ConfigEntry):
    """Set up Google Maps Travel Time from a config entry."""
    if config_entry.unique_id is not None:
        opp.config_entries.async_update_entry(config_entry, unique_id=None)

        ent_reg = async_get(opp)
        for entity in async_entries_for_config_entry(ent_reg, config_entry.entry_id):
            ent_reg.async_update_entity(
                entity.entity_id, new_unique_id=config_entry.entry_id
            )

    opp.config_entries.async_setup_platforms(config_entry, PLATFORMS)
    return True
コード例 #10
0
ファイル: binary_sensor.py プロジェクト: OpenPeerPower/core
async def async_setup_entry(opp, config_entry, async_add_entities):
    """Set up mobile app binary sensor from a config entry."""
    entities = []

    webhook_id = config_entry.data[CONF_WEBHOOK_ID]

    entity_registry = await er.async_get_registry(opp)
    entries = er.async_entries_for_config_entry(entity_registry,
                                                config_entry.entry_id)
    for entry in entries:
        if entry.domain != ENTITY_TYPE or entry.disabled_by:
            continue
        config = {
            ATTR_SENSOR_ATTRIBUTES: {},
            ATTR_SENSOR_DEVICE_CLASS: entry.device_class,
            ATTR_SENSOR_ICON: entry.original_icon,
            ATTR_SENSOR_NAME: entry.original_name,
            ATTR_SENSOR_STATE: None,
            ATTR_SENSOR_TYPE: entry.domain,
            ATTR_SENSOR_UNIQUE_ID: entry.unique_id,
        }
        entities.append(
            MobileAppBinarySensor(config, entry.device_id, config_entry))

    async_add_entities(entities)

    @callback
    def handle_sensor_registration(data):
        if data[CONF_WEBHOOK_ID] != webhook_id:
            return

        data[CONF_UNIQUE_ID] = unique_id(data[CONF_WEBHOOK_ID],
                                         data[ATTR_SENSOR_UNIQUE_ID])
        data[
            CONF_NAME] = f"{config_entry.data[ATTR_DEVICE_NAME]} {data[ATTR_SENSOR_NAME]}"

        device = opp.data[DOMAIN][DATA_DEVICES][data[CONF_WEBHOOK_ID]]

        async_add_entities([MobileAppBinarySensor(data, device, config_entry)])

    async_dispatcher_connect(
        opp,
        f"{DOMAIN}_{ENTITY_TYPE}_register",
        handle_sensor_registration,
    )
コード例 #11
0
    async def async_cleanup_registry_entries(service) -> None:
        """Remove extra entities that are no longer part of the integration."""
        entity_registry = await er.async_get_registry(opp)
        config_ids = []
        current_unique_ids = []

        for config_entry_id in opp.data[DOMAIN]:
            entries_for_this_config = er.async_entries_for_config_entry(
                entity_registry, config_entry_id)
            config_ids.extend([(entity.unique_id, entity.entity_id)
                               for entity in entries_for_this_config])

            opp_isy_data = opp.data[DOMAIN][config_entry_id]
            uuid = opp_isy_data[ISY994_ISY].configuration["uuid"]

            for platform in PLATFORMS:
                for node in opp_isy_data[ISY994_NODES][platform]:
                    if hasattr(node, "address"):
                        current_unique_ids.append(f"{uuid}_{node.address}")

            for platform in PROGRAM_PLATFORMS:
                for _, node, _ in opp_isy_data[ISY994_PROGRAMS][platform]:
                    if hasattr(node, "address"):
                        current_unique_ids.append(f"{uuid}_{node.address}")

            for node in opp_isy_data[ISY994_VARIABLES]:
                if hasattr(node, "address"):
                    current_unique_ids.append(f"{uuid}_{node.address}")

        extra_entities = [
            entity_id for unique_id, entity_id in config_ids
            if unique_id not in current_unique_ids
        ]

        for entity_id in extra_entities:
            if entity_registry.async_is_registered(entity_id):
                entity_registry.async_remove(entity_id)

        _LOGGER.debug(
            "Cleaning up ISY994 Entities and devices: Config Entries: %s, Current Entries: %s, "
            "Extra Entries Removed: %s",
            len(config_ids),
            len(current_unique_ids),
            len(extra_entities),
        )
コード例 #12
0
ファイル: __init__.py プロジェクト: OpenPeerPower/core
async def async_get_ozw_migration_data(opp):
    """Return dict with info for migration to ozw integration."""
    data_to_migrate = {}

    zwave_config_entries = opp.config_entries.async_entries(DOMAIN)
    if not zwave_config_entries:
        _LOGGER.error("Config entry not set up")
        return data_to_migrate

    if opp.data.get(DATA_ZWAVE_CONFIG_YAML_PRESENT):
        _LOGGER.warning(
            "Remove %s from configuration.yaml "
            "to avoid setting up this integration on restart "
            "after completing migration to ozw",
            DOMAIN,
        )

    config_entry = zwave_config_entries[
        0]  # zwave only has a single config entry
    ent_reg = await async_get_entity_registry(opp)
    entity_entries = async_entries_for_config_entry(ent_reg,
                                                    config_entry.entry_id)
    unique_entries = {entry.unique_id: entry for entry in entity_entries}
    dev_reg = await async_get_device_registry(opp)

    for entity_values in opp.data[DATA_ENTITY_VALUES]:
        node = entity_values.primary.node
        unique_id = compute_value_unique_id(node, entity_values.primary)
        if unique_id not in unique_entries:
            continue
        device_identifier, _ = node_device_id_and_name(
            node, entity_values.primary.instance)
        device_entry = dev_reg.async_get_device({device_identifier}, set())
        data_to_migrate[unique_id] = {
            "node_id": node.node_id,
            "node_instance": entity_values.primary.instance,
            "device_id": device_entry.id,
            "command_class": entity_values.primary.command_class,
            "command_class_label": entity_values.primary.label,
            "value_index": entity_values.primary.index,
            "unique_id": unique_id,
            "entity_entry": unique_entries[unique_id],
        }

    return data_to_migrate
コード例 #13
0
ファイル: __init__.py プロジェクト: OpenPeerPower/core
async def async_remove_obsolete_entities(opp: OpenPeerPower,
                                         entry: ConfigEntry,
                                         hap: HomematicipHAP):
    """Remove obsolete entities from entity registry."""

    if hap.home.currentAPVersion < "2.2.12":
        return

    entity_registry = await er.async_get_registry(opp)
    er_entries = async_entries_for_config_entry(entity_registry,
                                                entry.entry_id)
    for er_entry in er_entries:
        if er_entry.unique_id.startswith("HomematicipAccesspointStatus"):
            entity_registry.async_remove(er_entry.entity_id)
            continue

        for hapid in hap.home.accessPointUpdateStates:
            if er_entry.unique_id == f"HomematicipBatterySensor_{hapid}":
                entity_registry.async_remove(er_entry.entity_id)
コード例 #14
0
ファイル: controller.py プロジェクト: OpenPeerPower/core
    async def async_setup(self):
        """Set up a UniFi controller."""
        try:
            self.api = await get_controller(
                self.opp,
                host=self.config_entry.data[CONF_HOST],
                username=self.config_entry.data[CONF_USERNAME],
                password=self.config_entry.data[CONF_PASSWORD],
                port=self.config_entry.data[CONF_PORT],
                site=self.config_entry.data[CONF_SITE_ID],
                verify_ssl=self.config_entry.data[CONF_VERIFY_SSL],
                async_callback=self.async_unifi_signalling_callback,
            )
            await self.api.initialize()

            sites = await self.api.sites()
            description = await self.api.site_description()

        except CannotConnect as err:
            raise ConfigEntryNotReady from err

        except AuthenticationRequired as err:
            raise ConfigEntryAuthFailed from err

        for site in sites.values():
            if self.site == site["name"]:
                self.site_id = site["_id"]
                self._site_name = site["desc"]
                break

        self._site_role = description[0]["site_role"]

        # Restore clients that are not a part of active clients list.
        entity_registry = await self.opp.helpers.entity_registry.async_get_registry(
        )
        for entry in async_entries_for_config_entry(
                entity_registry, self.config_entry.entry_id):
            if entry.domain == TRACKER_DOMAIN:
                mac = entry.unique_id.split("-", 1)[0]
            elif entry.domain == SWITCH_DOMAIN and (
                    entry.unique_id.startswith(BLOCK_SWITCH)
                    or entry.unique_id.startswith(POE_SWITCH)):
                mac = entry.unique_id.split("-", 1)[1]
            else:
                continue

            if mac in self.api.clients or mac not in self.api.clients_all:
                continue

            client = self.api.clients_all[mac]
            self.api.clients.process_raw([client.raw])
            LOGGER.debug(
                "Restore disconnected client %s (%s)",
                entry.entity_id,
                client.mac,
            )

        wireless_clients = self.opp.data[UNIFI_WIRELESS_CLIENTS]
        self.wireless_clients = wireless_clients.get_data(self.config_entry)
        self.update_wireless_clients()

        self.opp.config_entries.async_setup_platforms(self.config_entry,
                                                      PLATFORMS)

        self.api.start_websocket()

        self.config_entry.add_update_listener(self.async_config_entry_updated)

        self._cancel_heartbeat_check = async_track_time_interval(
            self.opp, self._async_check_for_stale, CHECK_HEARTBEAT_INTERVAL)

        return True
コード例 #15
0
async def test_remove_orphaned_entries_service(opp, aioclient_mock):
    """Test service works and also don't remove more than expected."""
    data = {
        "lights": {
            "1": {
                "name": "Light 1 name",
                "state": {
                    "reachable": True
                },
                "type": "Light",
                "uniqueid": "00:00:00:00:00:00:00:01-00",
            }
        },
        "sensors": {
            "1": {
                "name": "Switch 1",
                "type": "ZHASwitch",
                "state": {
                    "buttonevent": 1000,
                    "gesture": 1
                },
                "config": {
                    "battery": 100
                },
                "uniqueid": "00:00:00:00:00:00:00:03-00",
            },
        },
    }
    with patch.dict(DECONZ_WEB_REQUEST, data):
        config_entry = await setup_deconz_integration(opp, aioclient_mock)

    device_registry = dr.async_get(opp)
    device = device_registry.async_get_or_create(
        config_entry_id=config_entry.entry_id,
        connections={(dr.CONNECTION_NETWORK_MAC, "123")},
    )

    assert (len([
        entry for entry in device_registry.devices.values()
        if config_entry.entry_id in entry.config_entries
    ]) == 5  # Host, gateway, light, switch and orphan
            )

    entity_registry = er.async_get(opp)
    entity_registry.async_get_or_create(
        SENSOR_DOMAIN,
        DECONZ_DOMAIN,
        "12345",
        suggested_object_id="Orphaned sensor",
        config_entry=config_entry,
        device_id=device.id,
    )

    assert (len(
        async_entries_for_config_entry(entity_registry, config_entry.entry_id))
            == 3  # Light, switch battery and orphan
            )

    await opp.services.async_call(
        DECONZ_DOMAIN,
        SERVICE_REMOVE_ORPHANED_ENTRIES,
        service_data={CONF_BRIDGE_ID: BRIDGEID},
    )
    await opp.async_block_till_done()

    assert (len([
        entry for entry in device_registry.devices.values()
        if config_entry.entry_id in entry.config_entries
    ]) == 4  # Host, gateway, light and switch
            )

    assert (len(
        async_entries_for_config_entry(entity_registry, config_entry.entry_id))
            == 2  # Light and switch battery
            )