Refactor Fully Kiosk and add logging details (#83028)
* - Refactor fully_kiosk/services.py with a less repetitive structure. - Log exception details in config_flow.py. * Log config_flow.py connection exception details * Appropriate logging level including stack trace. Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * Finish setting appropriate logging level when recording stack trace. * Log unknown exception with stack trace Co-authored-by: Martin Hjelmare <marhje52@gmail.com> * test_config_flow.py now passes. * All pytests passing. Co-authored-by: Martin Hjelmare <marhje52@gmail.com>pull/83463/head
parent
b665a060f7
commit
fa98685b1e
|
@ -41,10 +41,15 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||||
try:
|
try:
|
||||||
async with timeout(15):
|
async with timeout(15):
|
||||||
device_info = await fully.getDeviceInfo()
|
device_info = await fully.getDeviceInfo()
|
||||||
except (ClientConnectorError, FullyKioskError, asyncio.TimeoutError):
|
except (
|
||||||
|
ClientConnectorError,
|
||||||
|
FullyKioskError,
|
||||||
|
asyncio.TimeoutError,
|
||||||
|
) as error:
|
||||||
|
LOGGER.debug(error.args, exc_info=True)
|
||||||
errors["base"] = "cannot_connect"
|
errors["base"] = "cannot_connect"
|
||||||
except Exception: # pylint: disable=broad-except
|
except Exception as error: # pylint: disable=broad-except
|
||||||
LOGGER.exception("Unexpected exception")
|
LOGGER.exception("Unexpected exception: %s", error)
|
||||||
errors["base"] = "unknown"
|
errors["base"] = "unknown"
|
||||||
else:
|
else:
|
||||||
await self.async_set_unique_id(device_info["deviceID"])
|
await self.async_set_unique_id(device_info["deviceID"])
|
||||||
|
|
|
@ -1,6 +1,10 @@
|
||||||
"""Services for the Fully Kiosk Browser integration."""
|
"""Services for the Fully Kiosk Browser integration."""
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Callable
|
||||||
|
from typing import Any
|
||||||
|
|
||||||
|
from fullykiosk import FullyKiosk
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.const import ATTR_DEVICE_ID
|
from homeassistant.const import ATTR_DEVICE_ID
|
||||||
|
@ -12,6 +16,7 @@ from .const import (
|
||||||
ATTR_APPLICATION,
|
ATTR_APPLICATION,
|
||||||
ATTR_URL,
|
ATTR_URL,
|
||||||
DOMAIN,
|
DOMAIN,
|
||||||
|
LOGGER,
|
||||||
SERVICE_LOAD_URL,
|
SERVICE_LOAD_URL,
|
||||||
SERVICE_START_APPLICATION,
|
SERVICE_START_APPLICATION,
|
||||||
)
|
)
|
||||||
|
@ -20,54 +25,59 @@ from .const import (
|
||||||
async def async_setup_services(hass: HomeAssistant) -> None:
|
async def async_setup_services(hass: HomeAssistant) -> None:
|
||||||
"""Set up the services for the Fully Kiosk Browser integration."""
|
"""Set up the services for the Fully Kiosk Browser integration."""
|
||||||
|
|
||||||
async def async_load_url(call: ServiceCall) -> None:
|
async def execute_service(
|
||||||
"""Load a URL on the Fully Kiosk Browser."""
|
call: ServiceCall,
|
||||||
|
fully_method: Callable,
|
||||||
|
*args: list[str],
|
||||||
|
**kwargs: dict[str, Any],
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Execute a Fully service call.
|
||||||
|
|
||||||
|
:param call: {ServiceCall} HA service call.
|
||||||
|
:param fully_method: {Callable} A method of the FullyKiosk class.
|
||||||
|
:param args: Arguments for fully_method.
|
||||||
|
:param kwargs: Key-word arguments for fully_method.
|
||||||
|
:return: None
|
||||||
|
"""
|
||||||
|
LOGGER.debug(
|
||||||
|
"Calling Fully service %s with args: %s, %s", ServiceCall, args, kwargs
|
||||||
|
)
|
||||||
registry = dr.async_get(hass)
|
registry = dr.async_get(hass)
|
||||||
for target in call.data[ATTR_DEVICE_ID]:
|
for target in call.data[ATTR_DEVICE_ID]:
|
||||||
|
|
||||||
device = registry.async_get(target)
|
device = registry.async_get(target)
|
||||||
if device:
|
if device:
|
||||||
coordinator = hass.data[DOMAIN][list(device.config_entries)[0]]
|
coordinator = hass.data[DOMAIN][list(device.config_entries)[0]]
|
||||||
await coordinator.fully.loadUrl(call.data[ATTR_URL])
|
# fully_method(coordinator.fully, *args, **kwargs) would make
|
||||||
|
# test_services.py fail.
|
||||||
|
await getattr(coordinator.fully, fully_method.__name__)(*args, **kwargs)
|
||||||
|
|
||||||
|
async def async_load_url(call: ServiceCall) -> None:
|
||||||
|
"""Load a URL on the Fully Kiosk Browser."""
|
||||||
|
await execute_service(call, FullyKiosk.loadUrl, call.data[ATTR_URL])
|
||||||
|
|
||||||
async def async_start_app(call: ServiceCall) -> None:
|
async def async_start_app(call: ServiceCall) -> None:
|
||||||
"""Start an app on the device."""
|
"""Start an app on the device."""
|
||||||
registry = dr.async_get(hass)
|
await execute_service(
|
||||||
for target in call.data[ATTR_DEVICE_ID]:
|
call, FullyKiosk.startApplication, call.data[ATTR_APPLICATION]
|
||||||
|
)
|
||||||
|
|
||||||
device = registry.async_get(target)
|
# Register all the above services
|
||||||
if device:
|
service_mapping = [
|
||||||
coordinator = hass.data[DOMAIN][list(device.config_entries)[0]]
|
(async_load_url, SERVICE_LOAD_URL, ATTR_URL),
|
||||||
await coordinator.fully.startApplication(call.data[ATTR_APPLICATION])
|
(async_start_app, SERVICE_START_APPLICATION, ATTR_APPLICATION),
|
||||||
|
]
|
||||||
hass.services.async_register(
|
for service_handler, service_name, attrib in service_mapping:
|
||||||
DOMAIN,
|
hass.services.async_register(
|
||||||
SERVICE_LOAD_URL,
|
DOMAIN,
|
||||||
async_load_url,
|
service_name,
|
||||||
schema=vol.Schema(
|
service_handler,
|
||||||
vol.All(
|
schema=vol.Schema(
|
||||||
{
|
vol.All(
|
||||||
vol.Required(ATTR_DEVICE_ID): cv.ensure_list,
|
{
|
||||||
vol.Required(
|
vol.Required(ATTR_DEVICE_ID): cv.ensure_list,
|
||||||
ATTR_URL,
|
vol.Required(attrib): cv.string,
|
||||||
): cv.string,
|
}
|
||||||
},
|
)
|
||||||
)
|
),
|
||||||
),
|
)
|
||||||
)
|
|
||||||
|
|
||||||
hass.services.async_register(
|
|
||||||
DOMAIN,
|
|
||||||
SERVICE_START_APPLICATION,
|
|
||||||
async_start_app,
|
|
||||||
schema=vol.Schema(
|
|
||||||
vol.All(
|
|
||||||
{
|
|
||||||
vol.Required(ATTR_DEVICE_ID): cv.ensure_list,
|
|
||||||
vol.Required(
|
|
||||||
ATTR_APPLICATION,
|
|
||||||
): cv.string,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
),
|
|
||||||
)
|
|
||||||
|
|
Loading…
Reference in New Issue