Esempio n. 1
0
async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
    """Set up Elexa Guardian from a config entry."""
    hass.data.setdefault(DOMAIN, {})
    hass.data[DOMAIN][entry.entry_id] = {
        DATA_COORDINATOR: {},
        DATA_COORDINATOR_PAIRED_SENSOR: {},
    }

    client = Client(entry.data[CONF_IP_ADDRESS], port=entry.data[CONF_PORT])

    # The valve controller's UDP-based API can't handle concurrent requests very well,
    # so we use a lock to ensure that only one API request is reaching it at a time:
    api_lock = asyncio.Lock()

    # Set up DataUpdateCoordinators for the valve controller:
    init_valve_controller_tasks = []
    for api, api_coro in (
        (API_SENSOR_PAIR_DUMP, client.sensor.pair_dump),
        (API_SYSTEM_DIAGNOSTICS, client.system.diagnostics),
        (API_SYSTEM_ONBOARD_SENSOR_STATUS, client.system.onboard_sensor_status),
        (API_VALVE_STATUS, client.valve.status),
        (API_WIFI_STATUS, client.wifi.status),
    ):
        coordinator = hass.data[DOMAIN][entry.entry_id][DATA_COORDINATOR][
            api
        ] = GuardianDataUpdateCoordinator(
            hass,
            client=client,
            api_name=api,
            api_coro=api_coro,
            api_lock=api_lock,
            valve_controller_uid=entry.data[CONF_UID],
        )
        init_valve_controller_tasks.append(coordinator.async_refresh())

    await asyncio.gather(*init_valve_controller_tasks)
    hass.data[DOMAIN][entry.entry_id][DATA_CLIENT] = client

    # Set up an object to evaluate each batch of paired sensor UIDs and add/remove
    # devices as appropriate:
    paired_sensor_manager = hass.data[DOMAIN][entry.entry_id][
        DATA_PAIRED_SENSOR_MANAGER
    ] = PairedSensorManager(hass, entry, client, api_lock)
    await paired_sensor_manager.async_process_latest_paired_sensor_uids()

    @callback
    def async_process_paired_sensor_uids() -> None:
        """Define a callback for when new paired sensor data is received."""
        hass.async_create_task(
            paired_sensor_manager.async_process_latest_paired_sensor_uids()
        )

    hass.data[DOMAIN][entry.entry_id][DATA_COORDINATOR][
        API_SENSOR_PAIR_DUMP
    ].async_add_listener(async_process_paired_sensor_uids)

    # Set up all of the Guardian entity platforms:
    hass.config_entries.async_setup_platforms(entry, PLATFORMS)

    return True
Esempio n. 2
0
async def main() -> None:
    """Create the aiohttp session and run the example."""
    logging.basicConfig(level=logging.INFO)

    async with Client("172.16.11.208") as guardian:
        try:
            diagnostics_response = await guardian.system.diagnostics()
            _LOGGER.info("diagnostics command response: %s",
                         diagnostics_response)

            onboard_sensor_status = await guardian.system.onboard_sensor_status(
            )
            _LOGGER.info("onboard_sensor_status command response: %s",
                         onboard_sensor_status)

            ping_response = await guardian.system.ping()
            _LOGGER.info("ping command response: %s", ping_response)

            # reboot_response = await guardian.system.reboot()
            # _LOGGER.info("reboot command response: %s", reboot_response)

            # factory_reset_response = await guardian.system.factory_reset()
            # _LOGGER.info("factory_reset command response: %s", factory_reset_response)

            # upgrade_firmware_response = await guardian.system.upgrade_firmware()
            # _LOGGER.info(
            #     "upgrade_firmware command response: %s", upgrade_firmware_response
            # )
        except GuardianError as err:
            _LOGGER.info(err)
Esempio n. 3
0
async def test_command_without_socket_connect():
    """Test that executing a command without an open connection throws an exception."""
    client = Client("192.168.1.100")
    with pytest.raises(SocketError) as err:
        await client.system.ping()

    assert str(err.value) == "You aren't connected to the device yet"
Esempio n. 4
0
async def main() -> None:
    """Create the aiohttp session and run the example."""
    logging.basicConfig(level=logging.INFO)

    async with Client("172.16.11.208") as guardian:
        try:
            wifi_status_response = await guardian.wifi.status()
            _LOGGER.info("wifi_status command response: %s",
                         wifi_status_response)

            # wifi_reset_response = await guardian.wifi.reset()
            # _LOGGER.info("wifi_reset command response: %s", wifi_reset_response)

            # wifi_configure_response = await guardian.wifi.configure(
            #     "<SSID>", "<PASSWORD>"
            # )
            # _LOGGER.info("wifi_configure command response: %s", wifi_configure_response)

            # wifi_enable_ap_response = await guardian.wifi.enable_ap()
            # _LOGGER.info("wifi_enable_ap command response: %s", wifi_enable_ap_response)

            # wifi_disable_ap_response = await guardian.wifi.disable_ap()
            # _LOGGER.info(
            #     "wifi_disable_ap command response: %s", wifi_disable_ap_response
            # )
        except GuardianError as err:
            _LOGGER.info(err)
Esempio n. 5
0
async def test_close_success(mock_datagram_client):
    """Test the valve_close command succeeding."""
    with mock_datagram_client:
        async with Client("192.168.1.100") as client:
            valve_close_response = await client.valve.close()

        assert valve_close_response["command"] == 18
Esempio n. 6
0
async def main() -> None:
    """Create the aiohttp session and run the example."""
    logging.basicConfig(level=logging.INFO)

    async with Client("172.16.11.208") as guardian:
        try:
            pair_dump_response = await guardian.sensor.pair_dump()
            _LOGGER.info("pair_dump_response command response: %s",
                         pair_dump_response)

            for uid in pair_dump_response["data"]["paired_uids"]:
                paired_sensor_status_resp = await guardian.sensor.paired_sensor_status(
                    uid)
                _LOGGER.info(
                    "paired_sensor_status command response (UID: %s): %s",
                    uid,
                    paired_sensor_status_resp,
                )

            # pair_sensor_response = await guardian.sensor.pair_sensor("<UID>")
            # _LOGGER.info("pair_response command response: %s", pair_sensor_response)

            # unpair_sensor_response = await guardian.sensor.unpair_sensor("<UID>")
            # _LOGGER.info("unpair_response command response: %s", unpair_sensor_response)
        except GuardianError as err:
            _LOGGER.info(err)
Esempio n. 7
0
async def test_halt_failure(mock_datagram_client):
    """Test the valve_halt command failing."""
    with mock_datagram_client:
        with pytest.raises(CommandError) as err:
            async with Client("192.168.1.100") as client:
                _ = await client.valve.halt()

        assert str(err.value) == "valve_halt command failed: valve_already_stopped"
Esempio n. 8
0
async def test_publish_state_success(mock_datagram_client):
    """Test the publish_state command succeeding."""
    with mock_datagram_client:
        async with Client("192.168.1.100") as client:
            publish_state_response = await client.iot.publish_state()

        assert publish_state_response["command"] == 65
        assert publish_state_response["status"] == "ok"
Esempio n. 9
0
async def test_open_failure(mock_datagram_client):
    """Test the valve_open command failing."""
    with mock_datagram_client:
        with pytest.raises(CommandError) as err:
            async with Client("192.168.1.100") as client:
                _ = await client.valve.open()

        assert str(err.value) == "valve_open command failed: valve_moving"
Esempio n. 10
0
async def test_upgrade_firmware_success(mock_datagram_client):
    """Test the upgrade_firmware command succeeding."""
    with mock_datagram_client:
        async with Client("192.168.1.100") as client:
            upgrade_firmware_response = await client.system.upgrade_firmware()

        assert upgrade_firmware_response["command"] == 4
        assert upgrade_firmware_response["status"] == "ok"
Esempio n. 11
0
async def test_command_timeout(mock_datagram_client):
    """Test that a timeout during command execution throws an exception."""
    with mock_datagram_client, patch("asyncio.sleep"):
        with pytest.raises(SocketError) as err:
            async with Client("192.168.1.100") as client:
                await client.system.ping()

        assert str(err.value) == "system_ping command timed out"
Esempio n. 12
0
async def test_pair_sensor_success(mock_datagram_client):
    """Test the pair_sensor command succeeding."""
    with mock_datagram_client:
        async with Client("192.168.1.100") as client:
            pair_sensor_response = await client.sensor.pair_sensor("abc123")

        assert pair_sensor_response["command"] == 49
        assert pair_sensor_response["status"] == "ok"
Esempio n. 13
0
async def test_reset_success(mock_datagram_client):
    """Test the wifi_reset command succeeding."""
    with mock_datagram_client:
        async with Client("192.168.1.100") as client:
            wifi_reset_response = await client.wifi.reset()

        assert wifi_reset_response["command"] == 33
        assert wifi_reset_response["status"] == "ok"
Esempio n. 14
0
async def test_factory_reset_success(mock_datagram_client):
    """Test the factory_reset command succeeding."""
    with mock_datagram_client:
        async with Client("192.168.1.100") as client:
            factory_reset_response = await client.system.factory_reset()

        assert factory_reset_response["command"] == 255
        assert factory_reset_response["status"] == "ok"
Esempio n. 15
0
async def test_connect_timeout():
    """Test that a timeout during connection throws an exception."""
    with patch("asyncio_dgram.connect",
               AsyncMock(side_effect=asyncio.TimeoutError)):
        with pytest.raises(SocketError) as err:
            async with Client("192.168.1.100") as client:
                await client.system.ping()

        assert str(err.value) == "Connection to device timed out"
Esempio n. 16
0
async def test_upgrade_firmware_custom_parameters(mock_datagram_client):
    """Test that valid custom parameters work."""
    with mock_datagram_client:
        async with Client("192.168.1.100") as client:
            upgrade_firmware_response = await client.system.upgrade_firmware(
                url="https://firmware.com", port=8080, filename="123.bin")

        assert upgrade_firmware_response["command"] == 4
        assert upgrade_firmware_response["status"] == "ok"
Esempio n. 17
0
async def test_configure_success(mock_datagram_client):
    """Test the wifi_configure command succeeding."""
    with mock_datagram_client:
        async with Client("192.168.1.100") as client:
            wifi_configure_response = await client.wifi.configure(
                "My_Network", "password123")

        assert wifi_configure_response["command"] == 34
        assert wifi_configure_response["status"] == "ok"
Esempio n. 18
0
async def test_raw_command_success(mock_datagram_client):
    """Test a successful raw command."""
    with mock_datagram_client:
        async with Client("192.168.1.100") as client:
            ping_response = await client.execute_raw_command(0)

        assert ping_response["command"] == 0
        assert ping_response["status"] == "ok"
        assert ping_response["data"]["uid"] == "ABCDEF123456"
Esempio n. 19
0
async def test_reset_failure(mock_datagram_client):
    """Test the valve_reset command failing."""
    with mock_datagram_client:
        with pytest.raises(CommandError) as err:
            async with Client("192.168.1.100") as client:
                _ = await client.valve.reset()

        assert (str(err.value) == "valve_reset command failed "
                "(response: {'command': 20, 'status': 'error'})")
Esempio n. 20
0
async def test_ping_success(mock_datagram_client):
    """Test the ping command succeeding."""
    with mock_datagram_client:
        async with Client("192.168.1.100") as client:
            ping_response = await client.system.ping()

        assert ping_response["command"] == 0
        assert ping_response["status"] == "ok"
        assert ping_response["data"] == {"uid": "ABCDEF123456"}
Esempio n. 21
0
async def test_ping_failure(mock_datagram_client):
    """Test a failured ping of the device."""
    with mock_datagram_client:
        with pytest.raises(CommandError) as err:
            async with Client("192.168.1.100") as client:
                _ = await client.system.ping()

        assert str(err.value) == (
            "system_ping command failed (response: {'command': 0, 'status': 'error'})"
        )
Esempio n. 22
0
async def test_upgrade_firmware_invalid_url(mock_datagram_client):
    """Test that an invalid firmware URL throws an exception."""
    with mock_datagram_client:
        with pytest.raises(GuardianError) as err:
            async with Client("192.168.1.100") as client:
                _ = await client.system.upgrade_firmware(url="not_real_url")

        assert str(err.value) == (
            "Invalid parameters provided: Invalid URL for dictionary value @ "
            "data['url']")
async def test_onboard_sensor_status_failure(mock_datagram_client):
    """Test the onboard_sensor_status command failing."""
    with mock_datagram_client:
        with pytest.raises(CommandError) as err:
            async with Client("192.168.1.100") as client:
                _ = await client.system.onboard_sensor_status()

        assert str(
            err.value) == ("system_onboard_sensor_status command failed "
                           "(response: {'command': 80, 'status': 'error'})")
async def test_paired_sensor_status_failure_not_paired(mock_datagram_client):
    """Test the paired_sensor_status command failing because it isn't paired."""
    with mock_datagram_client:
        with pytest.raises(CommandError) as err:
            async with Client("192.168.1.100") as client:
                _ = await client.sensor.paired_sensor_status("ABCDE1234567")

        assert (str(
            err.value
        ) == "sensor_paired_sensor_status command failed: sensor_not_paired")
Esempio n. 25
0
async def test_configure_failure(mock_datagram_client):
    """Test the wifi_configure command failing."""
    with mock_datagram_client:
        with pytest.raises(CommandError) as err:
            async with Client("192.168.1.100") as client:
                _ = await client.wifi.configure("My_Network", "password123")

        assert str(
            err.value) == ("wifi_configure command failed "
                           "(response: {'command': 34, 'status': 'error'})")
async def test_paired_sensor_status_invalid_uid(mock_datagram_client):
    """Test that an invalid UID throws an exception."""
    with mock_datagram_client:
        with pytest.raises(CommandError) as err:
            async with Client("192.168.1.100") as client:
                _ = await client.sensor.paired_sensor_status("$@&*!@--")

        assert str(err.value) == (
            "Invalid parameters provided: String is not alphanumeric for dictionary "
            "value @ data['uid']")
Esempio n. 27
0
async def test_reboot_failure(mock_datagram_client):
    """Test the reboot command failing."""
    with mock_datagram_client:
        with pytest.raises(CommandError) as err:
            async with Client("192.168.1.100") as client:
                _ = await client.system.reboot()

        assert str(err.value) == (
            "system_reboot command failed (response: {'command': 2, 'status': 'error'})"
        )
Esempio n. 28
0
async def test_publish_state_failure(mock_datagram_client):
    """Test the publish_state command failing."""
    with mock_datagram_client:
        with pytest.raises(CommandError) as err:
            async with Client("192.168.1.100") as client:
                _ = await client.iot.publish_state()
            client.disconnect()

    assert str(err.value) == ("iot_publish_state command failed "
                              "(response: {'command': 65, 'status': 'error'})")
Esempio n. 29
0
async def test_reboot_success(mock_datagram_client):
    """Test the reboot command succeeding."""
    with mock_datagram_client:
        async with Client("192.168.1.100") as client:
            # Patch asyncio.sleep so that this test doesn't take 3-ish seconds:
            with patch("asyncio.sleep", AsyncMock()):
                reboot_response = await client.system.reboot()

        assert reboot_response["command"] == 2
        assert reboot_response["status"] == "ok"
Esempio n. 30
0
async def test_status_failure(mock_datagram_client):
    """Test the wifi_status command failing."""
    with mock_datagram_client:
        with pytest.raises(CommandError) as err:
            async with Client("192.168.1.100") as client:
                _ = await client.wifi.status()

        assert str(err.value) == (
            "wifi_status command failed (response: {'command': 32, 'status': 'error'})"
        )