Map heatercooler rotation speed as 3 level fan speed in homekit controller (#98291)

Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
Marco Garzola
2023-08-21 10:10:24 -05:00
committed by GitHub
co-authored by J. Nick Koston
parent 207e3f90a6
commit b8086f3c21
4 changed files with 370 additions and 0 deletions
@@ -0,0 +1,161 @@
[
{
"aid": 1,
"services": [
{
"iid": 1,
"type": "0000003E-0000-1000-8000-0026BB765291",
"characteristics": [
{
"type": "00000014-0000-1000-8000-0026BB765291",
"iid": 2,
"perms": ["pw"],
"format": "bool",
"description": "Identify"
},
{
"type": "00000052-0000-1000-8000-0026BB765291",
"iid": 3,
"perms": ["pr", "ev"],
"format": "string",
"value": "1.0.0",
"description": "Firmware Revision",
"maxLen": 64
},
{
"type": "00000053-0000-1000-8000-0026BB765291",
"iid": 4,
"perms": ["pr"],
"format": "string",
"value": "1.0.0",
"description": "Hardware Revision",
"maxLen": 64
},
{
"type": "00000020-0000-1000-8000-0026BB765291",
"iid": 5,
"perms": ["pr"],
"format": "string",
"value": "Garzola Marco",
"description": "Manufacturer",
"maxLen": 64
},
{
"type": "00000021-0000-1000-8000-0026BB765291",
"iid": 6,
"perms": ["pr"],
"format": "string",
"value": "Daikin-fwec3a-esp32-homekit-bridge",
"description": "Model",
"maxLen": 64
},
{
"type": "00000023-0000-1000-8000-0026BB765291",
"iid": 7,
"perms": ["pr"],
"format": "string",
"value": "Air Conditioner",
"description": "Name",
"maxLen": 64
},
{
"type": "00000030-0000-1000-8000-0026BB765291",
"iid": 8,
"perms": ["pr"],
"format": "string",
"value": "00000001",
"description": "Serial Number",
"maxLen": 64
}
]
},
{
"iid": 9,
"type": "000000BC-0000-1000-8000-0026BB765291",
"characteristics": [
{
"type": "000000B0-0000-1000-8000-0026BB765291",
"iid": 10,
"perms": ["pr", "pw", "ev"],
"format": "uint8",
"value": 1,
"description": "Active"
},
{
"type": "00000011-0000-1000-8000-0026BB765291",
"iid": 11,
"perms": ["pr", "ev"],
"format": "float",
"value": 27.9,
"description": "Current Temperature",
"unit": "celsius",
"minValue": 0,
"maxValue": 99,
"minStep": 0.5
},
{
"type": "000000B1-0000-1000-8000-0026BB765291",
"iid": 12,
"perms": ["pr", "ev"],
"format": "uint8",
"value": 3,
"description": "Current Heater Cooler State"
},
{
"type": "000000B2-0000-1000-8000-0026BB765291",
"iid": 13,
"perms": ["pr", "pw", "ev"],
"format": "uint8",
"value": 2,
"description": "Target Heater Cooler State"
},
{
"type": "0000000D-0000-1000-8000-0026BB765291",
"iid": 14,
"perms": ["pr", "pw", "ev"],
"format": "float",
"value": 24.5,
"description": "Cooling Threshold Temperature",
"unit": "celsius",
"minValue": 18,
"maxValue": 32,
"minStep": 0.5
},
{
"type": "00000012-0000-1000-8000-0026BB765291",
"iid": 15,
"perms": ["pr", "pw", "ev"],
"format": "float",
"value": 24.5,
"description": "Heating Threshold Temperature",
"unit": "celsius",
"minValue": 13,
"maxValue": 27,
"minStep": 0.5
},
{
"type": "00000029-0000-1000-8000-0026BB765291",
"iid": 16,
"perms": ["pr", "pw", "ev"],
"format": "float",
"value": 100,
"description": "Rotation Speed",
"unit": "percentage",
"minValue": 0,
"maxValue": 100,
"minStep": 1
},
{
"type": "00000023-0000-1000-8000-0026BB765291",
"iid": 17,
"perms": ["pr"],
"format": "string",
"value": "SlaveID 1",
"description": "Name",
"maxLen": 64
}
]
}
]
}
]
@@ -0,0 +1,51 @@
"""Tests for handling accessories on a Homespan esp32 daikin bridge."""
from homeassistant.components.climate import ClimateEntityFeature
from homeassistant.core import HomeAssistant
from ..common import (
HUB_TEST_ACCESSORY_ID,
DeviceTestInfo,
EntityTestInfo,
assert_devices_and_entities_created,
setup_accessories_from_file,
setup_test_accessories,
)
async def test_homespan_daikin_bridge_setup(hass: HomeAssistant) -> None:
"""Test that aHomespan esp32 daikin bridge can be correctly setup in HA via HomeKit."""
accessories = await setup_accessories_from_file(hass, "homespan_daikin_bridge.json")
await setup_test_accessories(hass, accessories)
await assert_devices_and_entities_created(
hass,
DeviceTestInfo(
unique_id=HUB_TEST_ACCESSORY_ID,
name="Air Conditioner",
model="Daikin-fwec3a-esp32-homekit-bridge",
manufacturer="Garzola Marco",
sw_version="1.0.0",
hw_version="1.0.0",
serial_number="00000001",
devices=[],
entities=[
EntityTestInfo(
entity_id="climate.air_conditioner_slaveid_1",
friendly_name="Air Conditioner SlaveID 1",
unique_id="00:00:00:00:00:00_1_9",
supported_features=(
ClimateEntityFeature.TARGET_TEMPERATURE
| ClimateEntityFeature.FAN_MODE
),
capabilities={
"hvac_modes": ["heat_cool", "heat", "cool", "off"],
"min_temp": 18,
"max_temp": 32,
"target_temp_step": 0.5,
"fan_modes": ["off", "low", "medium", "high"],
},
state="cool",
),
],
),
)
@@ -691,6 +691,9 @@ def create_heater_cooler_service(accessory):
char = service.add_char(CharacteristicsTypes.SWING_MODE)
char.value = 0
char = service.add_char(CharacteristicsTypes.ROTATION_SPEED)
char.value = 100
# Test heater-cooler devices
def create_heater_cooler_service_min_max(accessory):
@@ -867,6 +870,103 @@ async def test_heater_cooler_change_thermostat_temperature(
)
async def test_heater_cooler_change_fan_speed(hass: HomeAssistant, utcnow) -> None:
"""Test that we can change the target fan speed."""
helper = await setup_test_component(hass, create_heater_cooler_service)
await hass.services.async_call(
DOMAIN,
SERVICE_SET_HVAC_MODE,
{"entity_id": "climate.testdevice", "hvac_mode": HVACMode.COOL},
blocking=True,
)
await hass.services.async_call(
DOMAIN,
SERVICE_SET_FAN_MODE,
{"entity_id": "climate.testdevice", "fan_mode": "low"},
blocking=True,
)
helper.async_assert_service_values(
ServicesTypes.HEATER_COOLER,
{
CharacteristicsTypes.ROTATION_SPEED: 33,
},
)
await hass.services.async_call(
DOMAIN,
SERVICE_SET_FAN_MODE,
{"entity_id": "climate.testdevice", "fan_mode": "medium"},
blocking=True,
)
helper.async_assert_service_values(
ServicesTypes.HEATER_COOLER,
{
CharacteristicsTypes.ROTATION_SPEED: 66,
},
)
await hass.services.async_call(
DOMAIN,
SERVICE_SET_FAN_MODE,
{"entity_id": "climate.testdevice", "fan_mode": "high"},
blocking=True,
)
helper.async_assert_service_values(
ServicesTypes.HEATER_COOLER,
{
CharacteristicsTypes.ROTATION_SPEED: 100,
},
)
async def test_heater_cooler_read_fan_speed(hass: HomeAssistant, utcnow) -> None:
"""Test that we can read the state of a HomeKit thermostat accessory."""
helper = await setup_test_component(hass, create_heater_cooler_service)
# Simulate that fan speed is off
await helper.async_update(
ServicesTypes.HEATER_COOLER,
{
CharacteristicsTypes.ROTATION_SPEED: 0,
},
)
state = await helper.poll_and_get_state()
assert state.attributes["fan_mode"] == "off"
# Simulate that fan speed is low
await helper.async_update(
ServicesTypes.HEATER_COOLER,
{
CharacteristicsTypes.ROTATION_SPEED: 33,
},
)
state = await helper.poll_and_get_state()
assert state.attributes["fan_mode"] == "low"
# Simulate that fan speed is medium
await helper.async_update(
ServicesTypes.HEATER_COOLER,
{
CharacteristicsTypes.ROTATION_SPEED: 66,
},
)
state = await helper.poll_and_get_state()
assert state.attributes["fan_mode"] == "medium"
# Simulate that fan speed is high
await helper.async_update(
ServicesTypes.HEATER_COOLER,
{
CharacteristicsTypes.ROTATION_SPEED: 100,
},
)
state = await helper.poll_and_get_state()
assert state.attributes["fan_mode"] == "high"
async def test_heater_cooler_read_thermostat_state(hass: HomeAssistant, utcnow) -> None:
"""Test that we can read the state of a HomeKit thermostat accessory."""
helper = await setup_test_component(hass, create_heater_cooler_service)