mirror of
https://github.com/home-assistant/core.git
synced 2025-07-24 21:57:51 +00:00
Alexa - Remove legacy speed support for fan platform (#55174)
* Remove legacy fan speed support * remove fan range controller tests * retrigger tests
This commit is contained in:
parent
a4e4ffef0a
commit
755835ee2e
@ -1483,16 +1483,6 @@ class AlexaRangeController(AlexaCapability):
|
|||||||
if self.entity.state in (STATE_UNAVAILABLE, STATE_UNKNOWN, None):
|
if self.entity.state in (STATE_UNAVAILABLE, STATE_UNKNOWN, None):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
# Fan Speed
|
|
||||||
if self.instance == f"{fan.DOMAIN}.{fan.ATTR_SPEED}":
|
|
||||||
speed_list = self.entity.attributes.get(fan.ATTR_SPEED_LIST)
|
|
||||||
speed = self.entity.attributes.get(fan.ATTR_SPEED)
|
|
||||||
if speed_list is not None and speed is not None:
|
|
||||||
speed_index = next(
|
|
||||||
(i for i, v in enumerate(speed_list) if v == speed), None
|
|
||||||
)
|
|
||||||
return speed_index
|
|
||||||
|
|
||||||
# Cover Position
|
# Cover Position
|
||||||
if self.instance == f"{cover.DOMAIN}.{cover.ATTR_POSITION}":
|
if self.instance == f"{cover.DOMAIN}.{cover.ATTR_POSITION}":
|
||||||
return self.entity.attributes.get(cover.ATTR_CURRENT_POSITION)
|
return self.entity.attributes.get(cover.ATTR_CURRENT_POSITION)
|
||||||
|
@ -535,10 +535,6 @@ class FanCapabilities(AlexaEntity):
|
|||||||
if supported & fan.SUPPORT_SET_SPEED:
|
if supported & fan.SUPPORT_SET_SPEED:
|
||||||
yield AlexaPercentageController(self.entity)
|
yield AlexaPercentageController(self.entity)
|
||||||
yield AlexaPowerLevelController(self.entity)
|
yield AlexaPowerLevelController(self.entity)
|
||||||
# The use of legacy speeds is deprecated in the schema, support will be removed after a quarter (2021.7)
|
|
||||||
yield AlexaRangeController(
|
|
||||||
self.entity, instance=f"{fan.DOMAIN}.{fan.ATTR_SPEED}"
|
|
||||||
)
|
|
||||||
if supported & fan.SUPPORT_OSCILLATE:
|
if supported & fan.SUPPORT_OSCILLATE:
|
||||||
yield AlexaToggleController(
|
yield AlexaToggleController(
|
||||||
self.entity, instance=f"{fan.DOMAIN}.{fan.ATTR_OSCILLATING}"
|
self.entity, instance=f"{fan.DOMAIN}.{fan.ATTR_OSCILLATING}"
|
||||||
|
@ -1091,24 +1091,8 @@ async def async_api_set_range(hass, config, directive, context):
|
|||||||
data = {ATTR_ENTITY_ID: entity.entity_id}
|
data = {ATTR_ENTITY_ID: entity.entity_id}
|
||||||
range_value = directive.payload["rangeValue"]
|
range_value = directive.payload["rangeValue"]
|
||||||
|
|
||||||
# Fan Speed
|
|
||||||
if instance == f"{fan.DOMAIN}.{fan.ATTR_SPEED}":
|
|
||||||
range_value = int(range_value)
|
|
||||||
service = fan.SERVICE_SET_SPEED
|
|
||||||
speed_list = entity.attributes[fan.ATTR_SPEED_LIST]
|
|
||||||
speed = next((v for i, v in enumerate(speed_list) if i == range_value), None)
|
|
||||||
|
|
||||||
if not speed:
|
|
||||||
msg = "Entity does not support value"
|
|
||||||
raise AlexaInvalidValueError(msg)
|
|
||||||
|
|
||||||
if speed == fan.SPEED_OFF:
|
|
||||||
service = fan.SERVICE_TURN_OFF
|
|
||||||
|
|
||||||
data[fan.ATTR_SPEED] = speed
|
|
||||||
|
|
||||||
# Cover Position
|
# Cover Position
|
||||||
elif instance == f"{cover.DOMAIN}.{cover.ATTR_POSITION}":
|
if instance == f"{cover.DOMAIN}.{cover.ATTR_POSITION}":
|
||||||
range_value = int(range_value)
|
range_value = int(range_value)
|
||||||
if range_value == 0:
|
if range_value == 0:
|
||||||
service = cover.SERVICE_CLOSE_COVER
|
service = cover.SERVICE_CLOSE_COVER
|
||||||
@ -1184,29 +1168,8 @@ async def async_api_adjust_range(hass, config, directive, context):
|
|||||||
range_delta_default = bool(directive.payload["rangeValueDeltaDefault"])
|
range_delta_default = bool(directive.payload["rangeValueDeltaDefault"])
|
||||||
response_value = 0
|
response_value = 0
|
||||||
|
|
||||||
# Fan Speed
|
|
||||||
if instance == f"{fan.DOMAIN}.{fan.ATTR_SPEED}":
|
|
||||||
range_delta = int(range_delta)
|
|
||||||
service = fan.SERVICE_SET_SPEED
|
|
||||||
speed_list = entity.attributes[fan.ATTR_SPEED_LIST]
|
|
||||||
current_speed = entity.attributes[fan.ATTR_SPEED]
|
|
||||||
current_speed_index = next(
|
|
||||||
(i for i, v in enumerate(speed_list) if v == current_speed), 0
|
|
||||||
)
|
|
||||||
new_speed_index = min(
|
|
||||||
len(speed_list) - 1, max(0, current_speed_index + range_delta)
|
|
||||||
)
|
|
||||||
speed = next(
|
|
||||||
(v for i, v in enumerate(speed_list) if i == new_speed_index), None
|
|
||||||
)
|
|
||||||
|
|
||||||
if speed == fan.SPEED_OFF:
|
|
||||||
service = fan.SERVICE_TURN_OFF
|
|
||||||
|
|
||||||
data[fan.ATTR_SPEED] = response_value = speed
|
|
||||||
|
|
||||||
# Cover Position
|
# Cover Position
|
||||||
elif instance == f"{cover.DOMAIN}.{cover.ATTR_POSITION}":
|
if instance == f"{cover.DOMAIN}.{cover.ATTR_POSITION}":
|
||||||
range_delta = int(range_delta * 20) if range_delta_default else int(range_delta)
|
range_delta = int(range_delta * 20) if range_delta_default else int(range_delta)
|
||||||
service = SERVICE_SET_COVER_POSITION
|
service = SERVICE_SET_COVER_POSITION
|
||||||
current = entity.attributes.get(cover.ATTR_POSITION)
|
current = entity.attributes.get(cover.ATTR_POSITION)
|
||||||
|
@ -346,16 +346,14 @@ async def test_report_colored_temp_light_state(hass):
|
|||||||
|
|
||||||
|
|
||||||
async def test_report_fan_speed_state(hass):
|
async def test_report_fan_speed_state(hass):
|
||||||
"""Test PercentageController, PowerLevelController, RangeController reports fan speed correctly."""
|
"""Test PercentageController, PowerLevelController reports fan speed correctly."""
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
"fan.off",
|
"fan.off",
|
||||||
"off",
|
"off",
|
||||||
{
|
{
|
||||||
"friendly_name": "Off fan",
|
"friendly_name": "Off fan",
|
||||||
"speed": "off",
|
|
||||||
"supported_features": 1,
|
"supported_features": 1,
|
||||||
"percentage": 0,
|
"percentage": 0,
|
||||||
"speed_list": ["off", "low", "medium", "high"],
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
@ -363,10 +361,8 @@ async def test_report_fan_speed_state(hass):
|
|||||||
"on",
|
"on",
|
||||||
{
|
{
|
||||||
"friendly_name": "Low speed fan",
|
"friendly_name": "Low speed fan",
|
||||||
"speed": "low",
|
|
||||||
"supported_features": 1,
|
"supported_features": 1,
|
||||||
"percentage": 33,
|
"percentage": 33,
|
||||||
"speed_list": ["off", "low", "medium", "high"],
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
@ -374,10 +370,8 @@ async def test_report_fan_speed_state(hass):
|
|||||||
"on",
|
"on",
|
||||||
{
|
{
|
||||||
"friendly_name": "Medium speed fan",
|
"friendly_name": "Medium speed fan",
|
||||||
"speed": "medium",
|
|
||||||
"supported_features": 1,
|
"supported_features": 1,
|
||||||
"percentage": 66,
|
"percentage": 66,
|
||||||
"speed_list": ["off", "low", "medium", "high"],
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
hass.states.async_set(
|
hass.states.async_set(
|
||||||
@ -385,32 +379,26 @@ async def test_report_fan_speed_state(hass):
|
|||||||
"on",
|
"on",
|
||||||
{
|
{
|
||||||
"friendly_name": "High speed fan",
|
"friendly_name": "High speed fan",
|
||||||
"speed": "high",
|
|
||||||
"supported_features": 1,
|
"supported_features": 1,
|
||||||
"percentage": 100,
|
"percentage": 100,
|
||||||
"speed_list": ["off", "low", "medium", "high"],
|
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
properties = await reported_properties(hass, "fan.off")
|
properties = await reported_properties(hass, "fan.off")
|
||||||
properties.assert_equal("Alexa.PercentageController", "percentage", 0)
|
properties.assert_equal("Alexa.PercentageController", "percentage", 0)
|
||||||
properties.assert_equal("Alexa.PowerLevelController", "powerLevel", 0)
|
properties.assert_equal("Alexa.PowerLevelController", "powerLevel", 0)
|
||||||
properties.assert_equal("Alexa.RangeController", "rangeValue", 0)
|
|
||||||
|
|
||||||
properties = await reported_properties(hass, "fan.low_speed")
|
properties = await reported_properties(hass, "fan.low_speed")
|
||||||
properties.assert_equal("Alexa.PercentageController", "percentage", 33)
|
properties.assert_equal("Alexa.PercentageController", "percentage", 33)
|
||||||
properties.assert_equal("Alexa.PowerLevelController", "powerLevel", 33)
|
properties.assert_equal("Alexa.PowerLevelController", "powerLevel", 33)
|
||||||
properties.assert_equal("Alexa.RangeController", "rangeValue", 1)
|
|
||||||
|
|
||||||
properties = await reported_properties(hass, "fan.medium_speed")
|
properties = await reported_properties(hass, "fan.medium_speed")
|
||||||
properties.assert_equal("Alexa.PercentageController", "percentage", 66)
|
properties.assert_equal("Alexa.PercentageController", "percentage", 66)
|
||||||
properties.assert_equal("Alexa.PowerLevelController", "powerLevel", 66)
|
properties.assert_equal("Alexa.PowerLevelController", "powerLevel", 66)
|
||||||
properties.assert_equal("Alexa.RangeController", "rangeValue", 2)
|
|
||||||
|
|
||||||
properties = await reported_properties(hass, "fan.high_speed")
|
properties = await reported_properties(hass, "fan.high_speed")
|
||||||
properties.assert_equal("Alexa.PercentageController", "percentage", 100)
|
properties.assert_equal("Alexa.PercentageController", "percentage", 100)
|
||||||
properties.assert_equal("Alexa.PowerLevelController", "powerLevel", 100)
|
properties.assert_equal("Alexa.PowerLevelController", "powerLevel", 100)
|
||||||
properties.assert_equal("Alexa.RangeController", "rangeValue", 3)
|
|
||||||
|
|
||||||
|
|
||||||
async def test_report_fan_preset_mode(hass):
|
async def test_report_fan_preset_mode(hass):
|
||||||
|
@ -385,8 +385,6 @@ async def test_variable_fan(hass):
|
|||||||
{
|
{
|
||||||
"friendly_name": "Test fan 2",
|
"friendly_name": "Test fan 2",
|
||||||
"supported_features": 1,
|
"supported_features": 1,
|
||||||
"speed_list": ["low", "medium", "high"],
|
|
||||||
"speed": "high",
|
|
||||||
"percentage": 100,
|
"percentage": 100,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
@ -401,28 +399,18 @@ async def test_variable_fan(hass):
|
|||||||
"Alexa.PercentageController",
|
"Alexa.PercentageController",
|
||||||
"Alexa.PowerController",
|
"Alexa.PowerController",
|
||||||
"Alexa.PowerLevelController",
|
"Alexa.PowerLevelController",
|
||||||
"Alexa.RangeController",
|
|
||||||
"Alexa.EndpointHealth",
|
"Alexa.EndpointHealth",
|
||||||
"Alexa",
|
"Alexa",
|
||||||
)
|
)
|
||||||
|
|
||||||
range_capability = get_capability(capabilities, "Alexa.RangeController")
|
capability = get_capability(capabilities, "Alexa.PercentageController")
|
||||||
assert range_capability is not None
|
assert capability is not None
|
||||||
assert range_capability["instance"] == "fan.speed"
|
|
||||||
|
|
||||||
properties = range_capability["properties"]
|
capability = get_capability(capabilities, "Alexa.PowerController")
|
||||||
assert properties["nonControllable"] is False
|
assert capability is not None
|
||||||
assert {"name": "rangeValue"} in properties["supported"]
|
|
||||||
|
|
||||||
capability_resources = range_capability["capabilityResources"]
|
capability = get_capability(capabilities, "Alexa.PowerLevelController")
|
||||||
assert capability_resources is not None
|
assert capability is not None
|
||||||
assert {
|
|
||||||
"@type": "asset",
|
|
||||||
"value": {"assetId": "Alexa.Setting.FanSpeed"},
|
|
||||||
} in capability_resources["friendlyNames"]
|
|
||||||
|
|
||||||
configuration = range_capability["configuration"]
|
|
||||||
assert configuration is not None
|
|
||||||
|
|
||||||
call, _ = await assert_request_calls_service(
|
call, _ = await assert_request_calls_service(
|
||||||
"Alexa.PercentageController",
|
"Alexa.PercentageController",
|
||||||
@ -671,181 +659,6 @@ async def test_direction_fan(hass):
|
|||||||
assert call.data
|
assert call.data
|
||||||
|
|
||||||
|
|
||||||
async def test_fan_range(hass):
|
|
||||||
"""Test fan speed with rangeController."""
|
|
||||||
device = (
|
|
||||||
"fan.test_5",
|
|
||||||
"off",
|
|
||||||
{
|
|
||||||
"friendly_name": "Test fan 5",
|
|
||||||
"supported_features": 1,
|
|
||||||
"speed_list": ["off", "low", "medium", "high", "turbo", 5, "warp_speed"],
|
|
||||||
"speed": "medium",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
appliance = await discovery_test(device, hass)
|
|
||||||
|
|
||||||
assert appliance["endpointId"] == "fan#test_5"
|
|
||||||
assert appliance["displayCategories"][0] == "FAN"
|
|
||||||
assert appliance["friendlyName"] == "Test fan 5"
|
|
||||||
|
|
||||||
capabilities = assert_endpoint_capabilities(
|
|
||||||
appliance,
|
|
||||||
"Alexa.PercentageController",
|
|
||||||
"Alexa.PowerController",
|
|
||||||
"Alexa.PowerLevelController",
|
|
||||||
"Alexa.RangeController",
|
|
||||||
"Alexa.EndpointHealth",
|
|
||||||
"Alexa",
|
|
||||||
)
|
|
||||||
|
|
||||||
range_capability = get_capability(capabilities, "Alexa.RangeController")
|
|
||||||
assert range_capability is not None
|
|
||||||
assert range_capability["instance"] == "fan.speed"
|
|
||||||
|
|
||||||
capability_resources = range_capability["capabilityResources"]
|
|
||||||
assert capability_resources is not None
|
|
||||||
assert {
|
|
||||||
"@type": "asset",
|
|
||||||
"value": {"assetId": "Alexa.Setting.FanSpeed"},
|
|
||||||
} in capability_resources["friendlyNames"]
|
|
||||||
|
|
||||||
configuration = range_capability["configuration"]
|
|
||||||
assert configuration is not None
|
|
||||||
|
|
||||||
supported_range = configuration["supportedRange"]
|
|
||||||
assert supported_range["minimumValue"] == 0
|
|
||||||
assert supported_range["maximumValue"] == 6
|
|
||||||
assert supported_range["precision"] == 1
|
|
||||||
|
|
||||||
presets = configuration["presets"]
|
|
||||||
assert {
|
|
||||||
"rangeValue": 0,
|
|
||||||
"presetResources": {
|
|
||||||
"friendlyNames": [
|
|
||||||
{"@type": "text", "value": {"text": "off", "locale": "en-US"}}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
} in presets
|
|
||||||
|
|
||||||
assert {
|
|
||||||
"rangeValue": 1,
|
|
||||||
"presetResources": {
|
|
||||||
"friendlyNames": [
|
|
||||||
{"@type": "text", "value": {"text": "low", "locale": "en-US"}},
|
|
||||||
{"@type": "asset", "value": {"assetId": "Alexa.Value.Minimum"}},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
} in presets
|
|
||||||
|
|
||||||
assert {
|
|
||||||
"rangeValue": 2,
|
|
||||||
"presetResources": {
|
|
||||||
"friendlyNames": [
|
|
||||||
{"@type": "text", "value": {"text": "medium", "locale": "en-US"}}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
} in presets
|
|
||||||
|
|
||||||
assert {"rangeValue": 5} not in presets
|
|
||||||
|
|
||||||
assert {
|
|
||||||
"rangeValue": 6,
|
|
||||||
"presetResources": {
|
|
||||||
"friendlyNames": [
|
|
||||||
{"@type": "text", "value": {"text": "warp speed", "locale": "en-US"}},
|
|
||||||
{"@type": "asset", "value": {"assetId": "Alexa.Value.Maximum"}},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
} in presets
|
|
||||||
|
|
||||||
call, _ = await assert_request_calls_service(
|
|
||||||
"Alexa.RangeController",
|
|
||||||
"SetRangeValue",
|
|
||||||
"fan#test_5",
|
|
||||||
"fan.set_speed",
|
|
||||||
hass,
|
|
||||||
payload={"rangeValue": 1},
|
|
||||||
instance="fan.speed",
|
|
||||||
)
|
|
||||||
assert call.data["speed"] == "low"
|
|
||||||
|
|
||||||
call, _ = await assert_request_calls_service(
|
|
||||||
"Alexa.RangeController",
|
|
||||||
"SetRangeValue",
|
|
||||||
"fan#test_5",
|
|
||||||
"fan.set_speed",
|
|
||||||
hass,
|
|
||||||
payload={"rangeValue": 5},
|
|
||||||
instance="fan.speed",
|
|
||||||
)
|
|
||||||
assert call.data["speed"] == 5
|
|
||||||
|
|
||||||
call, _ = await assert_request_calls_service(
|
|
||||||
"Alexa.RangeController",
|
|
||||||
"SetRangeValue",
|
|
||||||
"fan#test_5",
|
|
||||||
"fan.set_speed",
|
|
||||||
hass,
|
|
||||||
payload={"rangeValue": 6},
|
|
||||||
instance="fan.speed",
|
|
||||||
)
|
|
||||||
assert call.data["speed"] == "warp_speed"
|
|
||||||
|
|
||||||
await assert_range_changes(
|
|
||||||
hass,
|
|
||||||
[
|
|
||||||
("low", -1, False),
|
|
||||||
("high", 1, False),
|
|
||||||
("medium", 0, False),
|
|
||||||
("warp_speed", 99, False),
|
|
||||||
],
|
|
||||||
"Alexa.RangeController",
|
|
||||||
"AdjustRangeValue",
|
|
||||||
"fan#test_5",
|
|
||||||
"fan.set_speed",
|
|
||||||
"speed",
|
|
||||||
instance="fan.speed",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def test_fan_range_off(hass):
|
|
||||||
"""Test fan range controller 0 turns_off fan."""
|
|
||||||
device = (
|
|
||||||
"fan.test_6",
|
|
||||||
"off",
|
|
||||||
{
|
|
||||||
"friendly_name": "Test fan 6",
|
|
||||||
"supported_features": 1,
|
|
||||||
"speed_list": ["off", "low", "medium", "high"],
|
|
||||||
"speed": "high",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
await discovery_test(device, hass)
|
|
||||||
|
|
||||||
call, _ = await assert_request_calls_service(
|
|
||||||
"Alexa.RangeController",
|
|
||||||
"SetRangeValue",
|
|
||||||
"fan#test_6",
|
|
||||||
"fan.turn_off",
|
|
||||||
hass,
|
|
||||||
payload={"rangeValue": 0},
|
|
||||||
instance="fan.speed",
|
|
||||||
)
|
|
||||||
assert call.data["speed"] == "off"
|
|
||||||
|
|
||||||
await assert_range_changes(
|
|
||||||
hass,
|
|
||||||
[("off", -3, False), ("off", -99, False)],
|
|
||||||
"Alexa.RangeController",
|
|
||||||
"AdjustRangeValue",
|
|
||||||
"fan#test_6",
|
|
||||||
"fan.turn_off",
|
|
||||||
"speed",
|
|
||||||
instance="fan.speed",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
async def test_preset_mode_fan(hass, caplog):
|
async def test_preset_mode_fan(hass, caplog):
|
||||||
"""Test fan discovery.
|
"""Test fan discovery.
|
||||||
|
|
||||||
|
@ -51,8 +51,6 @@ async def test_report_state_instance(hass, aioclient_mock):
|
|||||||
{
|
{
|
||||||
"friendly_name": "Test fan",
|
"friendly_name": "Test fan",
|
||||||
"supported_features": 15,
|
"supported_features": 15,
|
||||||
"speed": None,
|
|
||||||
"speed_list": ["off", "low", "high"],
|
|
||||||
"oscillating": False,
|
"oscillating": False,
|
||||||
"preset_mode": None,
|
"preset_mode": None,
|
||||||
"preset_modes": ["auto", "smart"],
|
"preset_modes": ["auto", "smart"],
|
||||||
@ -68,8 +66,6 @@ async def test_report_state_instance(hass, aioclient_mock):
|
|||||||
{
|
{
|
||||||
"friendly_name": "Test fan",
|
"friendly_name": "Test fan",
|
||||||
"supported_features": 15,
|
"supported_features": 15,
|
||||||
"speed": "high",
|
|
||||||
"speed_list": ["off", "low", "high"],
|
|
||||||
"oscillating": True,
|
"oscillating": True,
|
||||||
"preset_mode": "smart",
|
"preset_mode": "smart",
|
||||||
"preset_modes": ["auto", "smart"],
|
"preset_modes": ["auto", "smart"],
|
||||||
@ -109,12 +105,7 @@ async def test_report_state_instance(hass, aioclient_mock):
|
|||||||
assert report["value"] == 90
|
assert report["value"] == 90
|
||||||
assert report["namespace"] == "Alexa.PowerLevelController"
|
assert report["namespace"] == "Alexa.PowerLevelController"
|
||||||
checks += 1
|
checks += 1
|
||||||
if report["name"] == "rangeValue":
|
assert checks == 4
|
||||||
assert report["value"] == 2
|
|
||||||
assert report["instance"] == "fan.speed"
|
|
||||||
assert report["namespace"] == "Alexa.RangeController"
|
|
||||||
checks += 1
|
|
||||||
assert checks == 5
|
|
||||||
|
|
||||||
assert call_json["event"]["endpoint"]["endpointId"] == "fan#test_fan"
|
assert call_json["event"]["endpoint"]["endpointId"] == "fan#test_fan"
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user