mirror of
https://github.com/home-assistant/core.git
synced 2025-07-27 15:17:35 +00:00
Add Alexa's EndpointHealth reporting (#19784)
* add Health reports * add health report for all devices * update tests * Update homeassistant/components/alexa/smart_home.py Co-Authored-By: abmantis <abmantis@users.noreply.github.com> * lint * add tests
This commit is contained in:
parent
de76b59d0b
commit
6c29315088
@ -27,8 +27,9 @@ from homeassistant.const import (
|
|||||||
CONF_NAME, SERVICE_LOCK, SERVICE_MEDIA_NEXT_TRACK, SERVICE_MEDIA_PAUSE,
|
CONF_NAME, SERVICE_LOCK, SERVICE_MEDIA_NEXT_TRACK, SERVICE_MEDIA_PAUSE,
|
||||||
SERVICE_MEDIA_PLAY, SERVICE_MEDIA_PREVIOUS_TRACK, SERVICE_MEDIA_STOP,
|
SERVICE_MEDIA_PLAY, SERVICE_MEDIA_PREVIOUS_TRACK, SERVICE_MEDIA_STOP,
|
||||||
SERVICE_SET_COVER_POSITION, SERVICE_TURN_OFF, SERVICE_TURN_ON,
|
SERVICE_SET_COVER_POSITION, SERVICE_TURN_OFF, SERVICE_TURN_ON,
|
||||||
SERVICE_UNLOCK, SERVICE_VOLUME_SET, STATE_LOCKED, STATE_ON, STATE_UNLOCKED,
|
SERVICE_UNLOCK, SERVICE_VOLUME_SET, STATE_LOCKED, STATE_ON,
|
||||||
TEMP_CELSIUS, TEMP_FAHRENHEIT, MATCH_ALL)
|
STATE_UNAVAILABLE, STATE_UNLOCKED, TEMP_CELSIUS, TEMP_FAHRENHEIT,
|
||||||
|
MATCH_ALL)
|
||||||
import homeassistant.core as ha
|
import homeassistant.core as ha
|
||||||
import homeassistant.util.color as color_util
|
import homeassistant.util.color as color_util
|
||||||
from homeassistant.util.decorator import Registry
|
from homeassistant.util.decorator import Registry
|
||||||
@ -393,6 +394,37 @@ class _AlexaInterface:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class _AlexaEndpointHealth(_AlexaInterface):
|
||||||
|
"""Implements Alexa.EndpointHealth.
|
||||||
|
|
||||||
|
https://developer.amazon.com/docs/smarthome/state-reporting-for-a-smart-home-skill.html#report-state-when-alexa-requests-it
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, hass, entity):
|
||||||
|
super().__init__(entity)
|
||||||
|
self.hass = hass
|
||||||
|
|
||||||
|
def name(self):
|
||||||
|
return 'Alexa.EndpointHealth'
|
||||||
|
|
||||||
|
def properties_supported(self):
|
||||||
|
return [{'name': 'connectivity'}]
|
||||||
|
|
||||||
|
def properties_proactively_reported(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def properties_retrievable(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
def get_property(self, name):
|
||||||
|
if name != 'connectivity':
|
||||||
|
raise _UnsupportedProperty(name)
|
||||||
|
|
||||||
|
if self.entity.state == STATE_UNAVAILABLE:
|
||||||
|
return {'value': 'UNREACHABLE'}
|
||||||
|
return {'value': 'OK'}
|
||||||
|
|
||||||
|
|
||||||
class _AlexaPowerController(_AlexaInterface):
|
class _AlexaPowerController(_AlexaInterface):
|
||||||
"""Implements Alexa.PowerController.
|
"""Implements Alexa.PowerController.
|
||||||
|
|
||||||
@ -769,7 +801,8 @@ class _GenericCapabilities(_AlexaEntity):
|
|||||||
return [_DisplayCategory.OTHER]
|
return [_DisplayCategory.OTHER]
|
||||||
|
|
||||||
def interfaces(self):
|
def interfaces(self):
|
||||||
return [_AlexaPowerController(self.entity)]
|
return [_AlexaPowerController(self.entity),
|
||||||
|
_AlexaEndpointHealth(self.hass, self.entity)]
|
||||||
|
|
||||||
|
|
||||||
@ENTITY_ADAPTERS.register(switch.DOMAIN)
|
@ENTITY_ADAPTERS.register(switch.DOMAIN)
|
||||||
@ -778,7 +811,8 @@ class _SwitchCapabilities(_AlexaEntity):
|
|||||||
return [_DisplayCategory.SWITCH]
|
return [_DisplayCategory.SWITCH]
|
||||||
|
|
||||||
def interfaces(self):
|
def interfaces(self):
|
||||||
return [_AlexaPowerController(self.entity)]
|
return [_AlexaPowerController(self.entity),
|
||||||
|
_AlexaEndpointHealth(self.hass, self.entity)]
|
||||||
|
|
||||||
|
|
||||||
@ENTITY_ADAPTERS.register(climate.DOMAIN)
|
@ENTITY_ADAPTERS.register(climate.DOMAIN)
|
||||||
@ -792,6 +826,7 @@ class _ClimateCapabilities(_AlexaEntity):
|
|||||||
yield _AlexaPowerController(self.entity)
|
yield _AlexaPowerController(self.entity)
|
||||||
yield _AlexaThermostatController(self.hass, self.entity)
|
yield _AlexaThermostatController(self.hass, self.entity)
|
||||||
yield _AlexaTemperatureSensor(self.hass, self.entity)
|
yield _AlexaTemperatureSensor(self.hass, self.entity)
|
||||||
|
yield _AlexaEndpointHealth(self.hass, self.entity)
|
||||||
|
|
||||||
|
|
||||||
@ENTITY_ADAPTERS.register(cover.DOMAIN)
|
@ENTITY_ADAPTERS.register(cover.DOMAIN)
|
||||||
@ -804,6 +839,7 @@ class _CoverCapabilities(_AlexaEntity):
|
|||||||
supported = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
|
supported = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
|
||||||
if supported & cover.SUPPORT_SET_POSITION:
|
if supported & cover.SUPPORT_SET_POSITION:
|
||||||
yield _AlexaPercentageController(self.entity)
|
yield _AlexaPercentageController(self.entity)
|
||||||
|
yield _AlexaEndpointHealth(self.hass, self.entity)
|
||||||
|
|
||||||
|
|
||||||
@ENTITY_ADAPTERS.register(light.DOMAIN)
|
@ENTITY_ADAPTERS.register(light.DOMAIN)
|
||||||
@ -821,6 +857,7 @@ class _LightCapabilities(_AlexaEntity):
|
|||||||
yield _AlexaColorController(self.entity)
|
yield _AlexaColorController(self.entity)
|
||||||
if supported & light.SUPPORT_COLOR_TEMP:
|
if supported & light.SUPPORT_COLOR_TEMP:
|
||||||
yield _AlexaColorTemperatureController(self.entity)
|
yield _AlexaColorTemperatureController(self.entity)
|
||||||
|
yield _AlexaEndpointHealth(self.hass, self.entity)
|
||||||
|
|
||||||
|
|
||||||
@ENTITY_ADAPTERS.register(fan.DOMAIN)
|
@ENTITY_ADAPTERS.register(fan.DOMAIN)
|
||||||
@ -833,6 +870,7 @@ class _FanCapabilities(_AlexaEntity):
|
|||||||
supported = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
|
supported = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
|
||||||
if supported & fan.SUPPORT_SET_SPEED:
|
if supported & fan.SUPPORT_SET_SPEED:
|
||||||
yield _AlexaPercentageController(self.entity)
|
yield _AlexaPercentageController(self.entity)
|
||||||
|
yield _AlexaEndpointHealth(self.hass, self.entity)
|
||||||
|
|
||||||
|
|
||||||
@ENTITY_ADAPTERS.register(lock.DOMAIN)
|
@ENTITY_ADAPTERS.register(lock.DOMAIN)
|
||||||
@ -841,7 +879,8 @@ class _LockCapabilities(_AlexaEntity):
|
|||||||
return [_DisplayCategory.SMARTLOCK]
|
return [_DisplayCategory.SMARTLOCK]
|
||||||
|
|
||||||
def interfaces(self):
|
def interfaces(self):
|
||||||
return [_AlexaLockController(self.entity)]
|
return [_AlexaLockController(self.entity),
|
||||||
|
_AlexaEndpointHealth(self.hass, self.entity)]
|
||||||
|
|
||||||
|
|
||||||
@ENTITY_ADAPTERS.register(media_player.DOMAIN)
|
@ENTITY_ADAPTERS.register(media_player.DOMAIN)
|
||||||
@ -851,6 +890,7 @@ class _MediaPlayerCapabilities(_AlexaEntity):
|
|||||||
|
|
||||||
def interfaces(self):
|
def interfaces(self):
|
||||||
yield _AlexaPowerController(self.entity)
|
yield _AlexaPowerController(self.entity)
|
||||||
|
yield _AlexaEndpointHealth(self.hass, self.entity)
|
||||||
|
|
||||||
supported = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
|
supported = self.entity.attributes.get(ATTR_SUPPORTED_FEATURES, 0)
|
||||||
if supported & media_player.SUPPORT_VOLUME_SET:
|
if supported & media_player.SUPPORT_VOLUME_SET:
|
||||||
@ -913,6 +953,7 @@ class _SensorCapabilities(_AlexaEntity):
|
|||||||
TEMP_CELSIUS,
|
TEMP_CELSIUS,
|
||||||
):
|
):
|
||||||
yield _AlexaTemperatureSensor(self.hass, self.entity)
|
yield _AlexaTemperatureSensor(self.hass, self.entity)
|
||||||
|
yield _AlexaEndpointHealth(self.hass, self.entity)
|
||||||
|
|
||||||
|
|
||||||
@ENTITY_ADAPTERS.register(binary_sensor.DOMAIN)
|
@ENTITY_ADAPTERS.register(binary_sensor.DOMAIN)
|
||||||
@ -934,6 +975,8 @@ class _BinarySensorCapabilities(_AlexaEntity):
|
|||||||
elif sensor_type is self.TYPE_MOTION:
|
elif sensor_type is self.TYPE_MOTION:
|
||||||
yield _AlexaMotionSensor(self.hass, self.entity)
|
yield _AlexaMotionSensor(self.hass, self.entity)
|
||||||
|
|
||||||
|
yield _AlexaEndpointHealth(self.hass, self.entity)
|
||||||
|
|
||||||
def get_type(self):
|
def get_type(self):
|
||||||
"""Return the type of binary sensor."""
|
"""Return the type of binary sensor."""
|
||||||
attrs = self.entity.attributes
|
attrs = self.entity.attributes
|
||||||
|
@ -153,6 +153,15 @@ async def discovery_test(device, hass, expected_endpoints=1):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_capability(capabilities, capability_name):
|
||||||
|
"""Search a set of capabilities for a specific one."""
|
||||||
|
for capability in capabilities:
|
||||||
|
if capability['interface'] == capability_name:
|
||||||
|
return capability
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def assert_endpoint_capabilities(endpoint, *interfaces):
|
def assert_endpoint_capabilities(endpoint, *interfaces):
|
||||||
"""Assert the endpoint supports the given interfaces.
|
"""Assert the endpoint supports the given interfaces.
|
||||||
|
|
||||||
@ -176,7 +185,11 @@ async def test_switch(hass, events):
|
|||||||
assert appliance['endpointId'] == 'switch#test'
|
assert appliance['endpointId'] == 'switch#test'
|
||||||
assert appliance['displayCategories'][0] == "SWITCH"
|
assert appliance['displayCategories'][0] == "SWITCH"
|
||||||
assert appliance['friendlyName'] == "Test switch"
|
assert appliance['friendlyName'] == "Test switch"
|
||||||
assert_endpoint_capabilities(appliance, 'Alexa.PowerController')
|
assert_endpoint_capabilities(
|
||||||
|
appliance,
|
||||||
|
'Alexa.PowerController',
|
||||||
|
'Alexa.EndpointHealth',
|
||||||
|
)
|
||||||
|
|
||||||
await assert_power_controller_works(
|
await assert_power_controller_works(
|
||||||
'switch#test',
|
'switch#test',
|
||||||
@ -196,7 +209,11 @@ async def test_light(hass):
|
|||||||
assert appliance['endpointId'] == 'light#test_1'
|
assert appliance['endpointId'] == 'light#test_1'
|
||||||
assert appliance['displayCategories'][0] == "LIGHT"
|
assert appliance['displayCategories'][0] == "LIGHT"
|
||||||
assert appliance['friendlyName'] == "Test light 1"
|
assert appliance['friendlyName'] == "Test light 1"
|
||||||
assert_endpoint_capabilities(appliance, 'Alexa.PowerController')
|
assert_endpoint_capabilities(
|
||||||
|
appliance,
|
||||||
|
'Alexa.PowerController',
|
||||||
|
'Alexa.EndpointHealth',
|
||||||
|
)
|
||||||
|
|
||||||
await assert_power_controller_works(
|
await assert_power_controller_works(
|
||||||
'light#test_1',
|
'light#test_1',
|
||||||
@ -222,6 +239,7 @@ async def test_dimmable_light(hass):
|
|||||||
appliance,
|
appliance,
|
||||||
'Alexa.BrightnessController',
|
'Alexa.BrightnessController',
|
||||||
'Alexa.PowerController',
|
'Alexa.PowerController',
|
||||||
|
'Alexa.EndpointHealth',
|
||||||
)
|
)
|
||||||
|
|
||||||
properties = await reported_properties(hass, 'light#test_2')
|
properties = await reported_properties(hass, 'light#test_2')
|
||||||
@ -260,6 +278,7 @@ async def test_color_light(hass):
|
|||||||
'Alexa.PowerController',
|
'Alexa.PowerController',
|
||||||
'Alexa.ColorController',
|
'Alexa.ColorController',
|
||||||
'Alexa.ColorTemperatureController',
|
'Alexa.ColorTemperatureController',
|
||||||
|
'Alexa.EndpointHealth',
|
||||||
)
|
)
|
||||||
|
|
||||||
# IncreaseColorTemperature and DecreaseColorTemperature have their own
|
# IncreaseColorTemperature and DecreaseColorTemperature have their own
|
||||||
@ -277,7 +296,8 @@ async def test_script(hass):
|
|||||||
|
|
||||||
(capability,) = assert_endpoint_capabilities(
|
(capability,) = assert_endpoint_capabilities(
|
||||||
appliance,
|
appliance,
|
||||||
'Alexa.SceneController')
|
'Alexa.SceneController',
|
||||||
|
)
|
||||||
assert not capability['supportsDeactivation']
|
assert not capability['supportsDeactivation']
|
||||||
|
|
||||||
await assert_scene_controller_works(
|
await assert_scene_controller_works(
|
||||||
@ -299,7 +319,8 @@ async def test_cancelable_script(hass):
|
|||||||
assert appliance['endpointId'] == 'script#test_2'
|
assert appliance['endpointId'] == 'script#test_2'
|
||||||
(capability,) = assert_endpoint_capabilities(
|
(capability,) = assert_endpoint_capabilities(
|
||||||
appliance,
|
appliance,
|
||||||
'Alexa.SceneController')
|
'Alexa.SceneController',
|
||||||
|
)
|
||||||
assert capability['supportsDeactivation']
|
assert capability['supportsDeactivation']
|
||||||
|
|
||||||
await assert_scene_controller_works(
|
await assert_scene_controller_works(
|
||||||
@ -321,7 +342,11 @@ async def test_input_boolean(hass):
|
|||||||
assert appliance['endpointId'] == 'input_boolean#test'
|
assert appliance['endpointId'] == 'input_boolean#test'
|
||||||
assert appliance['displayCategories'][0] == "OTHER"
|
assert appliance['displayCategories'][0] == "OTHER"
|
||||||
assert appliance['friendlyName'] == "Test input boolean"
|
assert appliance['friendlyName'] == "Test input boolean"
|
||||||
assert_endpoint_capabilities(appliance, 'Alexa.PowerController')
|
assert_endpoint_capabilities(
|
||||||
|
appliance,
|
||||||
|
'Alexa.PowerController',
|
||||||
|
'Alexa.EndpointHealth',
|
||||||
|
)
|
||||||
|
|
||||||
await assert_power_controller_works(
|
await assert_power_controller_works(
|
||||||
'input_boolean#test',
|
'input_boolean#test',
|
||||||
@ -341,7 +366,8 @@ async def test_scene(hass):
|
|||||||
|
|
||||||
(capability,) = assert_endpoint_capabilities(
|
(capability,) = assert_endpoint_capabilities(
|
||||||
appliance,
|
appliance,
|
||||||
'Alexa.SceneController')
|
'Alexa.SceneController'
|
||||||
|
)
|
||||||
assert not capability['supportsDeactivation']
|
assert not capability['supportsDeactivation']
|
||||||
|
|
||||||
await assert_scene_controller_works(
|
await assert_scene_controller_works(
|
||||||
@ -359,7 +385,11 @@ async def test_fan(hass):
|
|||||||
assert appliance['endpointId'] == 'fan#test_1'
|
assert appliance['endpointId'] == 'fan#test_1'
|
||||||
assert appliance['displayCategories'][0] == "OTHER"
|
assert appliance['displayCategories'][0] == "OTHER"
|
||||||
assert appliance['friendlyName'] == "Test fan 1"
|
assert appliance['friendlyName'] == "Test fan 1"
|
||||||
assert_endpoint_capabilities(appliance, 'Alexa.PowerController')
|
assert_endpoint_capabilities(
|
||||||
|
appliance,
|
||||||
|
'Alexa.PowerController',
|
||||||
|
'Alexa.EndpointHealth',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_variable_fan(hass):
|
async def test_variable_fan(hass):
|
||||||
@ -386,6 +416,7 @@ async def test_variable_fan(hass):
|
|||||||
appliance,
|
appliance,
|
||||||
'Alexa.PercentageController',
|
'Alexa.PercentageController',
|
||||||
'Alexa.PowerController',
|
'Alexa.PowerController',
|
||||||
|
'Alexa.EndpointHealth',
|
||||||
)
|
)
|
||||||
|
|
||||||
call, _ = await assert_request_calls_service(
|
call, _ = await assert_request_calls_service(
|
||||||
@ -412,7 +443,11 @@ async def test_lock(hass):
|
|||||||
assert appliance['endpointId'] == 'lock#test'
|
assert appliance['endpointId'] == 'lock#test'
|
||||||
assert appliance['displayCategories'][0] == "SMARTLOCK"
|
assert appliance['displayCategories'][0] == "SMARTLOCK"
|
||||||
assert appliance['friendlyName'] == "Test lock"
|
assert appliance['friendlyName'] == "Test lock"
|
||||||
assert_endpoint_capabilities(appliance, 'Alexa.LockController')
|
assert_endpoint_capabilities(
|
||||||
|
appliance,
|
||||||
|
'Alexa.LockController',
|
||||||
|
'Alexa.EndpointHealth',
|
||||||
|
)
|
||||||
|
|
||||||
_, msg = await assert_request_calls_service(
|
_, msg = await assert_request_calls_service(
|
||||||
'Alexa.LockController', 'Lock', 'lock#test',
|
'Alexa.LockController', 'Lock', 'lock#test',
|
||||||
@ -449,6 +484,7 @@ async def test_media_player(hass):
|
|||||||
'Alexa.Speaker',
|
'Alexa.Speaker',
|
||||||
'Alexa.StepSpeaker',
|
'Alexa.StepSpeaker',
|
||||||
'Alexa.PlaybackController',
|
'Alexa.PlaybackController',
|
||||||
|
'Alexa.EndpointHealth',
|
||||||
)
|
)
|
||||||
|
|
||||||
await assert_power_controller_works(
|
await assert_power_controller_works(
|
||||||
@ -546,7 +582,11 @@ async def test_alert(hass):
|
|||||||
assert appliance['endpointId'] == 'alert#test'
|
assert appliance['endpointId'] == 'alert#test'
|
||||||
assert appliance['displayCategories'][0] == "OTHER"
|
assert appliance['displayCategories'][0] == "OTHER"
|
||||||
assert appliance['friendlyName'] == "Test alert"
|
assert appliance['friendlyName'] == "Test alert"
|
||||||
assert_endpoint_capabilities(appliance, 'Alexa.PowerController')
|
assert_endpoint_capabilities(
|
||||||
|
appliance,
|
||||||
|
'Alexa.PowerController',
|
||||||
|
'Alexa.EndpointHealth',
|
||||||
|
)
|
||||||
|
|
||||||
await assert_power_controller_works(
|
await assert_power_controller_works(
|
||||||
'alert#test',
|
'alert#test',
|
||||||
@ -563,7 +603,11 @@ async def test_automation(hass):
|
|||||||
assert appliance['endpointId'] == 'automation#test'
|
assert appliance['endpointId'] == 'automation#test'
|
||||||
assert appliance['displayCategories'][0] == "OTHER"
|
assert appliance['displayCategories'][0] == "OTHER"
|
||||||
assert appliance['friendlyName'] == "Test automation"
|
assert appliance['friendlyName'] == "Test automation"
|
||||||
assert_endpoint_capabilities(appliance, 'Alexa.PowerController')
|
assert_endpoint_capabilities(
|
||||||
|
appliance,
|
||||||
|
'Alexa.PowerController',
|
||||||
|
'Alexa.EndpointHealth',
|
||||||
|
)
|
||||||
|
|
||||||
await assert_power_controller_works(
|
await assert_power_controller_works(
|
||||||
'automation#test',
|
'automation#test',
|
||||||
@ -580,7 +624,11 @@ async def test_group(hass):
|
|||||||
assert appliance['endpointId'] == 'group#test'
|
assert appliance['endpointId'] == 'group#test'
|
||||||
assert appliance['displayCategories'][0] == "OTHER"
|
assert appliance['displayCategories'][0] == "OTHER"
|
||||||
assert appliance['friendlyName'] == "Test group"
|
assert appliance['friendlyName'] == "Test group"
|
||||||
assert_endpoint_capabilities(appliance, 'Alexa.PowerController')
|
assert_endpoint_capabilities(
|
||||||
|
appliance,
|
||||||
|
'Alexa.PowerController',
|
||||||
|
'Alexa.EndpointHealth',
|
||||||
|
)
|
||||||
|
|
||||||
await assert_power_controller_works(
|
await assert_power_controller_works(
|
||||||
'group#test',
|
'group#test',
|
||||||
@ -609,6 +657,7 @@ async def test_cover(hass):
|
|||||||
appliance,
|
appliance,
|
||||||
'Alexa.PercentageController',
|
'Alexa.PercentageController',
|
||||||
'Alexa.PowerController',
|
'Alexa.PowerController',
|
||||||
|
'Alexa.EndpointHealth',
|
||||||
)
|
)
|
||||||
|
|
||||||
await assert_power_controller_works(
|
await assert_power_controller_works(
|
||||||
@ -675,11 +724,16 @@ async def test_temp_sensor(hass):
|
|||||||
assert appliance['displayCategories'][0] == 'TEMPERATURE_SENSOR'
|
assert appliance['displayCategories'][0] == 'TEMPERATURE_SENSOR'
|
||||||
assert appliance['friendlyName'] == 'Test Temp Sensor'
|
assert appliance['friendlyName'] == 'Test Temp Sensor'
|
||||||
|
|
||||||
(capability,) = assert_endpoint_capabilities(
|
capabilities = assert_endpoint_capabilities(
|
||||||
appliance,
|
appliance,
|
||||||
|
'Alexa.TemperatureSensor',
|
||||||
|
'Alexa.EndpointHealth',
|
||||||
|
)
|
||||||
|
|
||||||
|
temp_sensor_capability = get_capability(capabilities,
|
||||||
'Alexa.TemperatureSensor')
|
'Alexa.TemperatureSensor')
|
||||||
assert capability['interface'] == 'Alexa.TemperatureSensor'
|
assert temp_sensor_capability is not None
|
||||||
properties = capability['properties']
|
properties = temp_sensor_capability['properties']
|
||||||
assert properties['retrievable'] is True
|
assert properties['retrievable'] is True
|
||||||
assert {'name': 'temperature'} in properties['supported']
|
assert {'name': 'temperature'} in properties['supported']
|
||||||
|
|
||||||
@ -704,11 +758,16 @@ async def test_contact_sensor(hass):
|
|||||||
assert appliance['displayCategories'][0] == 'CONTACT_SENSOR'
|
assert appliance['displayCategories'][0] == 'CONTACT_SENSOR'
|
||||||
assert appliance['friendlyName'] == 'Test Contact Sensor'
|
assert appliance['friendlyName'] == 'Test Contact Sensor'
|
||||||
|
|
||||||
(capability,) = assert_endpoint_capabilities(
|
capabilities = assert_endpoint_capabilities(
|
||||||
appliance,
|
appliance,
|
||||||
|
'Alexa.ContactSensor',
|
||||||
|
'Alexa.EndpointHealth',
|
||||||
|
)
|
||||||
|
|
||||||
|
contact_sensor_capability = get_capability(capabilities,
|
||||||
'Alexa.ContactSensor')
|
'Alexa.ContactSensor')
|
||||||
assert capability['interface'] == 'Alexa.ContactSensor'
|
assert contact_sensor_capability is not None
|
||||||
properties = capability['properties']
|
properties = contact_sensor_capability['properties']
|
||||||
assert properties['retrievable'] is True
|
assert properties['retrievable'] is True
|
||||||
assert {'name': 'detectionState'} in properties['supported']
|
assert {'name': 'detectionState'} in properties['supported']
|
||||||
|
|
||||||
@ -717,6 +776,9 @@ async def test_contact_sensor(hass):
|
|||||||
properties.assert_equal('Alexa.ContactSensor', 'detectionState',
|
properties.assert_equal('Alexa.ContactSensor', 'detectionState',
|
||||||
'DETECTED')
|
'DETECTED')
|
||||||
|
|
||||||
|
properties.assert_equal('Alexa.EndpointHealth', 'connectivity',
|
||||||
|
{'value': 'OK'})
|
||||||
|
|
||||||
|
|
||||||
async def test_motion_sensor(hass):
|
async def test_motion_sensor(hass):
|
||||||
"""Test motion sensor discovery."""
|
"""Test motion sensor discovery."""
|
||||||
@ -734,11 +796,16 @@ async def test_motion_sensor(hass):
|
|||||||
assert appliance['displayCategories'][0] == 'MOTION_SENSOR'
|
assert appliance['displayCategories'][0] == 'MOTION_SENSOR'
|
||||||
assert appliance['friendlyName'] == 'Test Motion Sensor'
|
assert appliance['friendlyName'] == 'Test Motion Sensor'
|
||||||
|
|
||||||
(capability,) = assert_endpoint_capabilities(
|
capabilities = assert_endpoint_capabilities(
|
||||||
appliance,
|
appliance,
|
||||||
|
'Alexa.MotionSensor',
|
||||||
|
'Alexa.EndpointHealth',
|
||||||
|
)
|
||||||
|
|
||||||
|
motion_sensor_capability = get_capability(capabilities,
|
||||||
'Alexa.MotionSensor')
|
'Alexa.MotionSensor')
|
||||||
assert capability['interface'] == 'Alexa.MotionSensor'
|
assert motion_sensor_capability is not None
|
||||||
properties = capability['properties']
|
properties = motion_sensor_capability['properties']
|
||||||
assert properties['retrievable'] is True
|
assert properties['retrievable'] is True
|
||||||
assert {'name': 'detectionState'} in properties['supported']
|
assert {'name': 'detectionState'} in properties['supported']
|
||||||
|
|
||||||
@ -787,6 +854,7 @@ async def test_thermostat(hass):
|
|||||||
appliance,
|
appliance,
|
||||||
'Alexa.ThermostatController',
|
'Alexa.ThermostatController',
|
||||||
'Alexa.TemperatureSensor',
|
'Alexa.TemperatureSensor',
|
||||||
|
'Alexa.EndpointHealth',
|
||||||
)
|
)
|
||||||
|
|
||||||
properties = await reported_properties(
|
properties = await reported_properties(
|
||||||
@ -1486,9 +1554,11 @@ async def test_entity_config(hass):
|
|||||||
assert appliance['displayCategories'][0] == "SWITCH"
|
assert appliance['displayCategories'][0] == "SWITCH"
|
||||||
assert appliance['friendlyName'] == "Config name"
|
assert appliance['friendlyName'] == "Config name"
|
||||||
assert appliance['description'] == "Config description"
|
assert appliance['description'] == "Config description"
|
||||||
assert len(appliance['capabilities']) == 1
|
assert_endpoint_capabilities(
|
||||||
assert appliance['capabilities'][-1]['interface'] == \
|
appliance,
|
||||||
'Alexa.PowerController'
|
'Alexa.PowerController',
|
||||||
|
'Alexa.EndpointHealth',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
async def test_unsupported_domain(hass):
|
async def test_unsupported_domain(hass):
|
||||||
@ -1651,6 +1721,38 @@ async def test_disabled(hass):
|
|||||||
assert msg['payload']['type'] == 'BRIDGE_UNREACHABLE'
|
assert msg['payload']['type'] == 'BRIDGE_UNREACHABLE'
|
||||||
|
|
||||||
|
|
||||||
|
async def test_endpoint_good_health(hass):
|
||||||
|
"""Test endpoint health reporting."""
|
||||||
|
device = (
|
||||||
|
'binary_sensor.test_contact',
|
||||||
|
'on',
|
||||||
|
{
|
||||||
|
'friendly_name': "Test Contact Sensor",
|
||||||
|
'device_class': 'door',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
await discovery_test(device, hass)
|
||||||
|
properties = await reported_properties(hass, 'binary_sensor#test_contact')
|
||||||
|
properties.assert_equal('Alexa.EndpointHealth', 'connectivity',
|
||||||
|
{'value': 'OK'})
|
||||||
|
|
||||||
|
|
||||||
|
async def test_endpoint_bad_health(hass):
|
||||||
|
"""Test endpoint health reporting."""
|
||||||
|
device = (
|
||||||
|
'binary_sensor.test_contact',
|
||||||
|
'unavailable',
|
||||||
|
{
|
||||||
|
'friendly_name': "Test Contact Sensor",
|
||||||
|
'device_class': 'door',
|
||||||
|
}
|
||||||
|
)
|
||||||
|
await discovery_test(device, hass)
|
||||||
|
properties = await reported_properties(hass, 'binary_sensor#test_contact')
|
||||||
|
properties.assert_equal('Alexa.EndpointHealth', 'connectivity',
|
||||||
|
{'value': 'UNREACHABLE'})
|
||||||
|
|
||||||
|
|
||||||
async def test_report_state(hass, aioclient_mock):
|
async def test_report_state(hass, aioclient_mock):
|
||||||
"""Test proactive state reports."""
|
"""Test proactive state reports."""
|
||||||
aioclient_mock.post(TEST_URL, json={'data': 'is irrelevant'})
|
aioclient_mock.post(TEST_URL, json={'data': 'is irrelevant'})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user