Alexa to handle brightness and catch exceptions (#65322)
parent
70da08499a
commit
bf138c4ffb
|
@ -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."""
|
||||
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
|
|
@ -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}
|
||||
|
||||
|
|
|
@ -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"])
|
||||
|
||||
|
||||
|
|
|
@ -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):
|
||||
|
|
Loading…
Reference in New Issue