예제 #1
0
async def test_site_cannot_update(opp, requests_mock, legacy_patchable_time):
    """Test we handle cannot connect error."""

    # all metoffice test data encapsulated in here
    mock_json = json.loads(load_fixture("metoffice.json"))
    all_sites = json.dumps(mock_json["all_sites"])
    wavertree_hourly = json.dumps(mock_json["wavertree_hourly"])

    requests_mock.get("/public/data/val/wxfcs/all/json/sitelist/", text=all_sites)
    requests_mock.get(
        "/public/data/val/wxfcs/all/json/354107?res=3hourly", text=wavertree_hourly
    )

    entry = MockConfigEntry(
        domain=DOMAIN,
        data=METOFFICE_CONFIG_WAVERTREE,
    )
    entry.add_to_opp(opp)
    await opp.config_entries.async_setup(entry.entry_id)
    await opp.async_block_till_done()

    entity = opp.states.get("weather.met_office_wavertree")
    assert entity

    requests_mock.get("/public/data/val/wxfcs/all/json/354107?res=3hourly", text="")

    future_time = utcnow() + timedelta(minutes=20)
    async_fire_time_changed(opp, future_time)
    await opp.async_block_till_done()

    entity = opp.states.get("weather.met_office_wavertree")
    assert entity.state == STATE_UNAVAILABLE
예제 #2
0
async def help_test_entity_available(opp: core.OpenPeerPower, domain: str,
                                     device: dict[str, Any], entity_id: str):
    """Run common test to verify available property."""
    await setup_platform(opp, domain, device)

    assert opp.states.get(entity_id).state != STATE_UNAVAILABLE

    with patch_bond_device_state(side_effect=AsyncIOTimeoutError()):
        async_fire_time_changed(opp, utcnow() + timedelta(seconds=30))
        await opp.async_block_till_done()
    assert opp.states.get(entity_id).state == STATE_UNAVAILABLE

    with patch_bond_device_state(return_value={}):
        async_fire_time_changed(opp, utcnow() + timedelta(seconds=30))
        await opp.async_block_till_done()
    assert opp.states.get(entity_id).state != STATE_UNAVAILABLE
예제 #3
0
async def test_bpup_goes_offline_and_recovers_same_entity(opp: core.OpenPeerPower):
    """Test that push updates fail and we fallback to polling and then bpup recovers.

    The BPUP recovery is triggered by an update for the entity and
    we do not fallback to polling because state is in sync.
    """
    bpup_subs = BPUPSubscriptions()
    with patch(
        "openpeerpower.components.bond.BPUPSubscriptions",
        return_value=bpup_subs,
    ):
        await setup_platform(
            opp, FAN_DOMAIN, ceiling_fan("name-1"), bond_device_id="test-device-id"
        )

    bpup_subs.notify(
        {
            "s": 200,
            "t": "bond/test-device-id/update",
            "b": {"power": 1, "speed": 3, "direction": 0},
        }
    )
    await opp.async_block_till_done()
    assert opp.states.get("fan.name_1").attributes[fan.ATTR_PERCENTAGE] == 100

    bpup_subs.notify(
        {
            "s": 200,
            "t": "bond/test-device-id/update",
            "b": {"power": 1, "speed": 1, "direction": 0},
        }
    )
    await opp.async_block_till_done()
    assert opp.states.get("fan.name_1").attributes[fan.ATTR_PERCENTAGE] == 33

    bpup_subs.last_message_time = 0
    with patch_bond_device_state(side_effect=asyncio.TimeoutError):
        async_fire_time_changed(opp, utcnow() + timedelta(seconds=230))
        await opp.async_block_till_done()

    assert opp.states.get("fan.name_1").state == STATE_UNAVAILABLE

    # Ensure we do not poll to get the state
    # since bpup has recovered and we know we
    # are back in sync
    with patch_bond_device_state(side_effect=Exception):
        bpup_subs.notify(
            {
                "s": 200,
                "t": "bond/test-device-id/update",
                "b": {"power": 1, "speed": 2, "direction": 0},
            }
        )
        await opp.async_block_till_done()

    state = opp.states.get("fan.name_1")
    assert state.state == STATE_ON
    assert state.attributes[fan.ATTR_PERCENTAGE] == 66
예제 #4
0
async def test_parse_brightness(opp: core.OpenPeerPower):
    """Tests that reported brightness level (0..100) converted to OPP brightness (0...255)."""
    await setup_platform(opp, LIGHT_DOMAIN, dimmable_ceiling_fan("name-1"))

    with patch_bond_device_state(return_value={"light": 1, "brightness": 50}):
        async_fire_time_changed(opp, utcnow() + timedelta(seconds=30))
        await opp.async_block_till_done()

    assert opp.states.get("light.name_1").attributes[ATTR_BRIGHTNESS] == 128
예제 #5
0
async def test_update_reports_closed_cover(opp: core.OpenPeerPower):
    """Tests that update command sets correct state when Bond API reports cover is closed."""
    await setup_platform(opp, COVER_DOMAIN, shades("name-1"))

    with patch_bond_device_state(return_value={"open": 0}):
        async_fire_time_changed(opp, utcnow() + timedelta(seconds=30))
        await opp.async_block_till_done()

    assert opp.states.get("cover.name_1").state == "closed"
예제 #6
0
async def test_update_reports_switch_is_off(opp: core.OpenPeerPower):
    """Tests that update command sets correct state when Bond API reports the device is off."""
    await setup_platform(opp, SWITCH_DOMAIN, generic_device("name-1"))

    with patch_bond_device_state(return_value={"power": 0}):
        async_fire_time_changed(opp, utcnow() + timedelta(seconds=30))
        await opp.async_block_till_done()

    assert opp.states.get("switch.name_1").state == "off"
예제 #7
0
async def _goto_future(opp, future=None):
    """Move to future."""
    if not future:
        future = utcnow() + datetime.timedelta(minutes=10)
    with patch("openpeerpower.util.utcnow", return_value=future):
        async_fire_time_changed(opp, future)
        await opp.async_block_till_done()
        async_fire_time_changed(opp, future)
        await opp.async_block_till_done()
예제 #8
0
async def test_update_reports_down_light_is_off(opp: core.OpenPeerPower):
    """Tests that update command sets correct state when Bond API reports the down light is off."""
    await setup_platform(opp, LIGHT_DOMAIN, down_light_ceiling_fan("name-1"))

    with patch_bond_device_state(return_value={"down_light": 0, "light": 0}):
        async_fire_time_changed(opp, utcnow() + timedelta(seconds=30))
        await opp.async_block_till_done()

    assert opp.states.get("light.name_1_down_light").state == "off"
예제 #9
0
async def test_update_reports_fan_off(opp: core.OpenPeerPower):
    """Tests that update command sets correct state when Bond API reports fan power is off."""
    await setup_platform(opp, FAN_DOMAIN, ceiling_fan("name-1"))

    with patch_bond_device_state(return_value={"power": 0, "speed": 1}):
        async_fire_time_changed(opp, utcnow() + timedelta(seconds=30))
        await opp.async_block_till_done()

    assert opp.states.get("fan.name_1").state == "off"
예제 #10
0
async def test_connection_state_changes(harmony_client, mock_hc, opp,
                                        mock_write_config):
    """Ensure connection changes are reflected in the switch states."""
    entry = MockConfigEntry(domain=DOMAIN,
                            data={
                                CONF_HOST: "192.0.2.0",
                                CONF_NAME: HUB_NAME
                            })

    entry.add_to_opp(opp)
    await opp.config_entries.async_setup(entry.entry_id)
    await opp.async_block_till_done()

    # mocks start with current activity == Watch TV
    assert opp.states.is_state(ENTITY_WATCH_TV, STATE_ON)
    assert opp.states.is_state(ENTITY_PLAY_MUSIC, STATE_OFF)

    harmony_client.mock_disconnection()
    await opp.async_block_till_done()

    # Entities do not immediately show as unavailable
    assert opp.states.is_state(ENTITY_WATCH_TV, STATE_ON)
    assert opp.states.is_state(ENTITY_PLAY_MUSIC, STATE_OFF)

    future_time = utcnow() + timedelta(seconds=10)
    async_fire_time_changed(opp, future_time)
    await opp.async_block_till_done()
    assert opp.states.is_state(ENTITY_WATCH_TV, STATE_UNAVAILABLE)
    assert opp.states.is_state(ENTITY_PLAY_MUSIC, STATE_UNAVAILABLE)

    harmony_client.mock_reconnection()
    await opp.async_block_till_done()

    assert opp.states.is_state(ENTITY_WATCH_TV, STATE_ON)
    assert opp.states.is_state(ENTITY_PLAY_MUSIC, STATE_OFF)

    harmony_client.mock_disconnection()
    harmony_client.mock_reconnection()
    future_time = utcnow() + timedelta(seconds=10)
    async_fire_time_changed(opp, future_time)

    await opp.async_block_till_done()
    assert opp.states.is_state(ENTITY_WATCH_TV, STATE_ON)
    assert opp.states.is_state(ENTITY_PLAY_MUSIC, STATE_OFF)
예제 #11
0
async def test_polling_fails_and_recovers(opp: core.OpenPeerPower):
    """Test that polling fails and we recover."""
    await setup_platform(
        opp, FAN_DOMAIN, ceiling_fan("name-1"), bond_device_id="test-device-id"
    )

    with patch_bond_device_state(side_effect=asyncio.TimeoutError):
        async_fire_time_changed(opp, utcnow() + timedelta(seconds=230))
        await opp.async_block_till_done()

    assert opp.states.get("fan.name_1").state == STATE_UNAVAILABLE

    with patch_bond_device_state(return_value={"power": 1, "speed": 1}):
        async_fire_time_changed(opp, utcnow() + timedelta(seconds=230))
        await opp.async_block_till_done()

    state = opp.states.get("fan.name_1")
    assert state.state == STATE_ON
    assert state.attributes[fan.ATTR_PERCENTAGE] == 33
예제 #12
0
async def test_update_reports_direction_reverse(opp: core.OpenPeerPower):
    """Tests that update command sets correct direction when Bond API reports fan direction is reverse."""
    await setup_platform(opp, FAN_DOMAIN, ceiling_fan("name-1"))

    with patch_bond_device_state(
            return_value={"direction": Direction.REVERSE}):
        async_fire_time_changed(opp, utcnow() + timedelta(seconds=30))
        await opp.async_block_till_done()

    assert opp.states.get(
        "fan.name_1").attributes[ATTR_DIRECTION] == DIRECTION_REVERSE
예제 #13
0
async def test_polling_stops_at_the_stop_event(opp: core.OpenPeerPower):
    """Test that polling stops at the stop event."""
    await setup_platform(
        opp, FAN_DOMAIN, ceiling_fan("name-1"), bond_device_id="test-device-id"
    )

    with patch_bond_device_state(side_effect=asyncio.TimeoutError):
        async_fire_time_changed(opp, utcnow() + timedelta(seconds=230))
        await opp.async_block_till_done()

    assert opp.states.get("fan.name_1").state == STATE_UNAVAILABLE

    opp.bus.async_fire(EVENT_OPENPEERPOWER_STOP)
    opp.state = CoreState.stopping
    await opp.async_block_till_done()

    with patch_bond_device_state(return_value={"power": 1, "speed": 1}):
        async_fire_time_changed(opp, utcnow() + timedelta(seconds=230))
        await opp.async_block_till_done()

    assert opp.states.get("fan.name_1").state == STATE_UNAVAILABLE
예제 #14
0
async def test_clients_update_failed(opp):
    """Test failed update."""
    await init_integration(opp)

    future = utcnow() + timedelta(minutes=60)
    with patch(
        "openpeerpower.components.ruckus_unleashed.RuckusUnleashedDataUpdateCoordinator._fetch_clients",
        side_effect=ConnectionError,
    ):
        async_fire_time_changed(opp, future)
        await opp.async_block_till_done()

        await opp.helpers.entity_component.async_update_entity(TEST_CLIENT_ENTITY_ID)
        test_client = opp.states.get(TEST_CLIENT_ENTITY_ID)
        assert test_client.state == STATE_UNAVAILABLE
예제 #15
0
async def test_client_disconnected(opp):
    """Test client disconnected."""
    await init_integration(opp)

    future = utcnow() + timedelta(minutes=60)
    with patch(
        "openpeerpower.components.ruckus_unleashed.RuckusUnleashedDataUpdateCoordinator._fetch_clients",
        return_value={},
    ):
        async_fire_time_changed(opp, future)
        await opp.async_block_till_done()

        await opp.helpers.entity_component.async_update_entity(TEST_CLIENT_ENTITY_ID)
        test_client = opp.states.get(TEST_CLIENT_ENTITY_ID)
        assert test_client.state == STATE_NOT_HOME
예제 #16
0
    async def async_update(self):
        """Get the latest data and update the states."""
        # Remove outdated samples
        if self._sample_duration > 0:
            cutoff = utcnow().timestamp() - self._sample_duration
            while self.samples and self.samples[0][0] < cutoff:
                self.samples.popleft()

        if len(self.samples) < 2:
            return

        # Calculate gradient of linear trend
        await self.opp.async_add_executor_job(self._calculate_gradient)

        # Update state
        self._state = (abs(self._gradient) > abs(self._min_gradient)
                       and math.copysign(self._gradient,
                                         self._min_gradient) == self._gradient)

        if self._invert:
            self._state = not self._state
예제 #17
0
async def test_form_duplicate_error(opp):
    """Test we handle duplicate error."""
    result = await opp.config_entries.flow.async_init(
        DOMAIN, context={"source": config_entries.SOURCE_USER})

    with patch(
            "openpeerpower.components.ruckus_unleashed.Ruckus.connect",
            return_value=None,
    ), patch(
            "openpeerpower.components.ruckus_unleashed.Ruckus.mesh_name",
            return_value=DEFAULT_TITLE,
    ), patch(
            "openpeerpower.components.ruckus_unleashed.Ruckus.system_info",
            return_value=DEFAULT_SYSTEM_INFO,
    ):
        await opp.config_entries.flow.async_configure(
            result["flow_id"],
            CONFIG,
        )

        future = utcnow() + timedelta(minutes=60)
        async_fire_time_changed(opp, future)
        await opp.async_block_till_done()

        result = await opp.config_entries.flow.async_init(
            DOMAIN, context={"source": config_entries.SOURCE_USER})
        assert result["type"] == "form"
        assert result["errors"] == {}

        result2 = await opp.config_entries.flow.async_configure(
            result["flow_id"],
            CONFIG,
        )

    assert result2["type"] == "abort"
    assert result2["reason"] == "already_configured"
예제 #18
0
async def test_connect_retry(opp, mock_panel):
    """Test that we create a Konnected Panel and save the data."""
    device_config = config_flow.CONFIG_ENTRY_SCHEMA({
        "host":
        "1.2.3.4",
        "port":
        1234,
        "id":
        "112233445566",
        "model":
        "Konnected Pro",
        "access_token":
        "11223344556677889900",
        "default_options":
        config_flow.OPTIONS_SCHEMA({
            "io": {
                "1": "Binary Sensor",
                "2": "Binary Sensor",
                "3": "Binary Sensor",
                "4": "Digital Sensor",
                "5": "Digital Sensor",
                "6": "Switchable Output",
                "out": "Switchable Output",
            },
            "binary_sensors": [
                {
                    "zone": "1",
                    "type": "door"
                },
                {
                    "zone": "2",
                    "type": "window",
                    "name": "winder",
                    "inverse": True,
                },
                {
                    "zone": "3",
                    "type": "door"
                },
            ],
            "sensors": [
                {
                    "zone": "4",
                    "type": "dht"
                },
                {
                    "zone": "5",
                    "type": "ds18b20",
                    "name": "temper"
                },
            ],
            "switches": [
                {
                    "zone": "out",
                    "name": "switcher",
                    "activation": "low",
                    "momentary": 50,
                    "pause": 100,
                    "repeat": 4,
                },
                {
                    "zone": "6"
                },
            ],
        }),
    })

    entry = MockConfigEntry(
        domain="konnected",
        title="Konnected Alarm Panel",
        data=device_config,
        options={},
    )
    entry.add_to_opp(opp)

    # fail first 2 attempts, and succeed the third
    mock_panel.get_status.side_effect = [
        mock_panel.ClientError,
        mock_panel.ClientError,
        {
            "hwVersion": "2.3.0",
            "swVersion": "2.3.1",
            "heap": 10000,
            "uptime": 12222,
            "ip": "192.168.1.90",
            "port": 9123,
            "sensors": [],
            "actuators": [],
            "dht_sensors": [],
            "ds18b20_sensors": [],
            "mac": "11:22:33:44:55:66",
            "model": "Konnected Pro",
            "settings": {},
        },
    ]

    # setup the integration and inspect panel behavior
    assert (await async_setup_component(
        opp,
        panel.DOMAIN,
        {
            panel.DOMAIN: {
                panel.CONF_ACCESS_TOKEN: "arandomstringvalue",
                panel.CONF_API_HOST: "http://192.168.1.1:8123",
            }
        },
    ) is True)

    # confirm switch is unavailable after initial attempt
    await opp.async_block_till_done()
    assert opp.states.get(
        "switch.konnected_445566_actuator_6").state == "unavailable"

    # confirm switch is unavailable after second attempt
    async_fire_time_changed(opp, utcnow() + timedelta(seconds=11))
    await opp.async_block_till_done()
    await opp.helpers.entity_component.async_update_entity(
        "switch.konnected_445566_actuator_6")
    assert opp.states.get(
        "switch.konnected_445566_actuator_6").state == "unavailable"

    # confirm switch is available after third attempt
    async_fire_time_changed(opp, utcnow() + timedelta(seconds=21))
    await opp.async_block_till_done()
    await opp.helpers.entity_component.async_update_entity(
        "switch.konnected_445566_actuator_6")
    assert opp.states.get("switch.konnected_445566_actuator_6").state == "off"