Alexa to handle brightness and catch exceptions (#65322)

pull/65339/head
Paulus Schoutsen 2022-01-31 15:01:46 -08:00 committed by GitHub
parent 70da08499a
commit bf138c4ffb
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 50 additions and 26 deletions

View File

@ -1,6 +1,8 @@
"""Alexa related errors."""
from __future__ import annotations
from typing import Literal
from homeassistant.exceptions import HomeAssistantError
from .const import API_TEMP_UNITS
@ -58,6 +60,30 @@ class AlexaInvalidValueError(AlexaError):
error_type = "INVALID_VALUE"
class AlexaInteralError(AlexaError):
"""Class to represent internal errors."""
namespace = "Alexa"
error_type = "INTERNAL_ERROR"
class AlexaNotSupportedInCurrentMode(AlexaError):
"""The device is not in the correct mode to support this command."""
namespace = "Alexa"
error_type = "NOT_SUPPORTED_IN_CURRENT_MODE"
def __init__(
self,
endpoint_id: str,
current_mode: Literal["COLOR", "ASLEEP", "NOT_PROVISIONED", "OTHER"],
) -> None:
"""Initialize invalid endpoint error."""
msg = f"Not supported while in {current_mode} mode"
AlexaError.__init__(self, msg, {"currentDeviceMode": current_mode})
self.endpoint_id = endpoint_id
class AlexaUnsupportedThermostatModeError(AlexaError):
"""Class to represent UnsupportedThermostatMode errors."""

View File

@ -212,20 +212,14 @@ async def async_api_adjust_brightness(hass, config, directive, context):
entity = directive.entity
brightness_delta = int(directive.payload["brightnessDelta"])
# read current state
try:
current = math.floor(
int(entity.attributes.get(light.ATTR_BRIGHTNESS)) / 255 * 100
)
except ZeroDivisionError:
current = 0
# set brightness
brightness = max(0, brightness_delta + current)
await hass.services.async_call(
entity.domain,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: entity.entity_id, light.ATTR_BRIGHTNESS_PCT: brightness},
{
ATTR_ENTITY_ID: entity.entity_id,
light.ATTR_BRIGHTNESS_STEP_PCT: brightness_delta,
},
blocking=False,
context=context,
)

View File

@ -48,8 +48,18 @@ async def async_handle_message(hass, config, request, context=None, enabled=True
response = directive.error()
except AlexaError as err:
response = directive.error(
error_type=err.error_type, error_message=err.error_message
error_type=err.error_type,
error_message=err.error_message,
payload=err.payload,
)
except Exception: # pylint: disable=broad-except
_LOGGER.exception(
"Uncaught exception processing Alexa %s/%s request (%s)",
directive.namespace,
directive.name,
directive.entity_id or "-",
)
response = directive.error(error_message="Unknown error")
request_info = {"namespace": directive.namespace, "name": directive.name}

View File

@ -194,7 +194,7 @@ async def assert_scene_controller_works(
assert re.search(pattern, response["event"]["payload"]["timestamp"])
async def reported_properties(hass, endpoint):
async def reported_properties(hass, endpoint, return_full_response=False):
"""Use ReportState to get properties and return them.
The result is a ReportedProperties instance, which has methods to make
@ -203,6 +203,8 @@ async def reported_properties(hass, endpoint):
request = get_new_request("Alexa", "ReportState", endpoint)
msg = await smart_home.async_handle_message(hass, get_default_config(), request)
await hass.async_block_till_done()
if return_full_response:
return msg
return ReportedProperties(msg["context"]["properties"])

View File

@ -4,7 +4,6 @@ from unittest.mock import patch
import pytest
from homeassistant.components.alexa import smart_home
from homeassistant.components.alexa.errors import UnsupportedProperty
from homeassistant.components.climate import const as climate
from homeassistant.components.lock import STATE_JAMMED, STATE_LOCKING, STATE_UNLOCKING
from homeassistant.components.media_player.const import (
@ -39,8 +38,8 @@ from . import (
from tests.common import async_mock_service
@pytest.mark.parametrize("result,adjust", [(25, "-5"), (35, "5"), (0, "-80")])
async def test_api_adjust_brightness(hass, result, adjust):
@pytest.mark.parametrize("adjust", ["-5", "5", "-80"])
async def test_api_adjust_brightness(hass, adjust):
"""Test api adjust brightness process."""
request = get_new_request(
"Alexa.BrightnessController", "AdjustBrightness", "light#test"
@ -64,7 +63,7 @@ async def test_api_adjust_brightness(hass, result, adjust):
assert len(call_light) == 1
assert call_light[0].data["entity_id"] == "light.test"
assert call_light[0].data["brightness_pct"] == result
assert call_light[0].data["brightness_step_pct"] == int(adjust)
assert msg["header"]["name"] == "Response"
@ -677,16 +676,9 @@ async def test_report_climate_state(hass):
ATTR_UNIT_OF_MEASUREMENT: TEMP_CELSIUS,
},
)
with pytest.raises(UnsupportedProperty):
properties = await reported_properties(hass, "climate.unsupported")
properties.assert_not_has_property(
"Alexa.ThermostatController", "thermostatMode"
)
properties.assert_equal(
"Alexa.TemperatureSensor",
"temperature",
{"value": 34.0, "scale": "CELSIUS"},
)
msg = await reported_properties(hass, "climate.unsupported", True)
assert msg["event"]["header"]["name"] == "ErrorResponse"
assert msg["event"]["payload"]["type"] == "INTERNAL_ERROR"
async def test_temperature_sensor_sensor(hass):