Add set_myzone service to Advantage Air (#46934)
* Add set_myzone service requested on forums * Add MyZone binary sensor for climate zones * Fixed Black on binary_sensor.py * Add the new entity * Fix spelling * Test myZone value * MyZone Binary Sensor test * Fixed new binary sensor tests * Fix removed dependancy * Correct fixture * Update homeassistant/components/advantage_air/binary_sensor.py Co-authored-by: Philip Allgaier <philip.allgaier@gmx.de> * Updated services.yaml to use target Co-authored-by: Philip Allgaier <philip.allgaier@gmx.de>pull/49371/head
parent
b2c33c1373
commit
afd79a675c
|
@ -24,6 +24,9 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||
# Only add motion sensor when motion is enabled
|
||||
if zone["motionConfig"] >= 2:
|
||||
entities.append(AdvantageAirZoneMotion(instance, ac_key, zone_key))
|
||||
# Only add MyZone if it is available
|
||||
if zone["type"] != 0:
|
||||
entities.append(AdvantageAirZoneMyZone(instance, ac_key, zone_key))
|
||||
async_add_entities(entities)
|
||||
|
||||
|
||||
|
@ -73,3 +76,27 @@ class AdvantageAirZoneMotion(AdvantageAirEntity, BinarySensorEntity):
|
|||
def is_on(self):
|
||||
"""Return if motion is detect."""
|
||||
return self._zone["motion"]
|
||||
|
||||
|
||||
class AdvantageAirZoneMyZone(AdvantageAirEntity, BinarySensorEntity):
|
||||
"""Advantage Air Zone MyZone."""
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name."""
|
||||
return f'{self._zone["name"]} MyZone'
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
"""Return a unique id."""
|
||||
return f'{self.coordinator.data["system"]["rid"]}-{self.ac_key}-{self.zone_key}-myzone'
|
||||
|
||||
@property
|
||||
def is_on(self):
|
||||
"""Return if this zone is the myZone."""
|
||||
return self._zone["number"] == self._ac["myZone"]
|
||||
|
||||
@property
|
||||
def entity_registry_enabled_default(self):
|
||||
"""Return false to disable this entity by default."""
|
||||
return False
|
||||
|
|
|
@ -15,6 +15,7 @@ from homeassistant.components.climate.const import (
|
|||
SUPPORT_TARGET_TEMPERATURE,
|
||||
)
|
||||
from homeassistant.const import ATTR_TEMPERATURE, PRECISION_WHOLE, TEMP_CELSIUS
|
||||
from homeassistant.helpers import entity_platform
|
||||
|
||||
from .const import (
|
||||
ADVANTAGE_AIR_STATE_CLOSE,
|
||||
|
@ -49,6 +50,7 @@ AC_HVAC_MODES = [
|
|||
HVAC_MODE_FAN_ONLY,
|
||||
HVAC_MODE_DRY,
|
||||
]
|
||||
ADVANTAGE_AIR_SERVICE_SET_MYZONE = "set_myzone"
|
||||
ZONE_HVAC_MODES = [HVAC_MODE_OFF, HVAC_MODE_FAN_ONLY]
|
||||
|
||||
PARALLEL_UPDATES = 0
|
||||
|
@ -68,6 +70,13 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
|
|||
entities.append(AdvantageAirZone(instance, ac_key, zone_key))
|
||||
async_add_entities(entities)
|
||||
|
||||
platform = entity_platform.current_platform.get()
|
||||
platform.async_register_entity_service(
|
||||
ADVANTAGE_AIR_SERVICE_SET_MYZONE,
|
||||
{},
|
||||
"set_myzone",
|
||||
)
|
||||
|
||||
|
||||
class AdvantageAirClimateEntity(AdvantageAirEntity, ClimateEntity):
|
||||
"""AdvantageAir Climate class."""
|
||||
|
@ -233,3 +242,9 @@ class AdvantageAirZone(AdvantageAirClimateEntity):
|
|||
await self.async_change(
|
||||
{self.ac_key: {"zones": {self.zone_key: {"setTemp": temp}}}}
|
||||
)
|
||||
|
||||
async def set_myzone(self, **kwargs):
|
||||
"""Set this zone as the 'MyZone'."""
|
||||
await self.async_change(
|
||||
{self.ac_key: {"info": {"myZone": self._zone["number"]}}}
|
||||
)
|
||||
|
|
|
@ -1,9 +1,18 @@
|
|||
set_time_to:
|
||||
name: Set Time To
|
||||
description: Control timers to turn the system on or off after a set number of minutes
|
||||
target:
|
||||
entity:
|
||||
integration: advantage_air
|
||||
domain: sensor
|
||||
fields:
|
||||
entity_id:
|
||||
description: Time To sensor entity
|
||||
example: "sensor.ac_time_to_on"
|
||||
minutes:
|
||||
description: Minutes until action
|
||||
example: "60"
|
||||
set_myzone:
|
||||
name: Set MyZone
|
||||
description: Change which zone is set as the reference for temperature control
|
||||
target:
|
||||
entity:
|
||||
integration: advantage_air
|
||||
domain: climate
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
"""Test the Advantage Air Binary Sensor Platform."""
|
||||
from datetime import timedelta
|
||||
|
||||
from homeassistant.config_entries import RELOAD_AFTER_UPDATE_DELAY
|
||||
from homeassistant.const import STATE_OFF, STATE_ON
|
||||
from homeassistant.helpers import entity_registry as er
|
||||
from homeassistant.util import dt
|
||||
|
||||
from tests.common import async_fire_time_changed
|
||||
from tests.components.advantage_air import (
|
||||
TEST_SET_RESPONSE,
|
||||
TEST_SET_URL,
|
||||
|
@ -68,3 +72,47 @@ async def test_binary_sensor_async_setup_entry(hass, aioclient_mock):
|
|||
entry = registry.async_get(entity_id)
|
||||
assert entry
|
||||
assert entry.unique_id == "uniqueid-ac1-z02-motion"
|
||||
|
||||
# Test First MyZone Sensor (disabled by default)
|
||||
entity_id = "binary_sensor.zone_open_with_sensor_myzone"
|
||||
|
||||
assert not hass.states.get(entity_id)
|
||||
|
||||
registry.async_update_entity(entity_id=entity_id, disabled_by=None)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
async_fire_time_changed(
|
||||
hass,
|
||||
dt.utcnow() + timedelta(seconds=RELOAD_AFTER_UPDATE_DELAY + 1),
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
assert state.state == STATE_ON
|
||||
|
||||
entry = registry.async_get(entity_id)
|
||||
assert entry
|
||||
assert entry.unique_id == "uniqueid-ac1-z01-myzone"
|
||||
|
||||
# Test Second Motion Sensor (disabled by default)
|
||||
entity_id = "binary_sensor.zone_closed_with_sensor_myzone"
|
||||
|
||||
assert not hass.states.get(entity_id)
|
||||
|
||||
registry.async_update_entity(entity_id=entity_id, disabled_by=None)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
async_fire_time_changed(
|
||||
hass,
|
||||
dt.utcnow() + timedelta(seconds=RELOAD_AFTER_UPDATE_DELAY + 1),
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
state = hass.states.get(entity_id)
|
||||
assert state
|
||||
assert state.state == STATE_OFF
|
||||
|
||||
entry = registry.async_get(entity_id)
|
||||
assert entry
|
||||
assert entry.unique_id == "uniqueid-ac1-z02-myzone"
|
||||
|
|
|
@ -3,12 +3,14 @@
|
|||
from json import loads
|
||||
|
||||
from homeassistant.components.advantage_air.climate import (
|
||||
ADVANTAGE_AIR_SERVICE_SET_MYZONE,
|
||||
HASS_FAN_MODES,
|
||||
HASS_HVAC_MODES,
|
||||
)
|
||||
from homeassistant.components.advantage_air.const import (
|
||||
ADVANTAGE_AIR_STATE_OFF,
|
||||
ADVANTAGE_AIR_STATE_ON,
|
||||
DOMAIN as ADVANTAGE_AIR_DOMAIN,
|
||||
)
|
||||
from homeassistant.components.climate.const import (
|
||||
ATTR_FAN_MODE,
|
||||
|
@ -170,6 +172,21 @@ async def test_climate_async_setup_entry(hass, aioclient_mock):
|
|||
assert aioclient_mock.mock_calls[-1][0] == "GET"
|
||||
assert aioclient_mock.mock_calls[-1][1].path == "/getSystemData"
|
||||
|
||||
# Test set_myair service
|
||||
await hass.services.async_call(
|
||||
ADVANTAGE_AIR_DOMAIN,
|
||||
ADVANTAGE_AIR_SERVICE_SET_MYZONE,
|
||||
{ATTR_ENTITY_ID: [entity_id]},
|
||||
blocking=True,
|
||||
)
|
||||
assert len(aioclient_mock.mock_calls) == 17
|
||||
assert aioclient_mock.mock_calls[-2][0] == "GET"
|
||||
assert aioclient_mock.mock_calls[-2][1].path == "/setAircon"
|
||||
data = loads(aioclient_mock.mock_calls[-2][1].query["json"])
|
||||
assert data["ac1"]["info"]["myZone"] == 1
|
||||
assert aioclient_mock.mock_calls[-1][0] == "GET"
|
||||
assert aioclient_mock.mock_calls[-1][1].path == "/getSystemData"
|
||||
|
||||
|
||||
async def test_climate_async_failed_update(hass, aioclient_mock):
|
||||
"""Test climate change failure."""
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
"filterCleanStatus": 0,
|
||||
"freshAirStatus": "off",
|
||||
"mode": "vent",
|
||||
"myZone": 0,
|
||||
"myZone": 1,
|
||||
"name": "AC One",
|
||||
"setTemp": 24,
|
||||
"state": "on"
|
||||
|
@ -38,7 +38,7 @@
|
|||
"motion": 0,
|
||||
"motionConfig": 2,
|
||||
"name": "Zone closed with Sensor",
|
||||
"number": 1,
|
||||
"number": 2,
|
||||
"rssi": 10,
|
||||
"setTemp": 24,
|
||||
"state": "close",
|
||||
|
@ -53,7 +53,7 @@
|
|||
"motion": 1,
|
||||
"motionConfig": 1,
|
||||
"name": "Zone 3",
|
||||
"number": 1,
|
||||
"number": 3,
|
||||
"rssi": 25,
|
||||
"setTemp": 24,
|
||||
"state": "close",
|
||||
|
@ -68,7 +68,7 @@
|
|||
"motion": 1,
|
||||
"motionConfig": 1,
|
||||
"name": "Zone 4",
|
||||
"number": 1,
|
||||
"number": 4,
|
||||
"rssi": 75,
|
||||
"setTemp": 24,
|
||||
"state": "close",
|
||||
|
@ -80,7 +80,7 @@
|
|||
"maxDamper": 100,
|
||||
"measuredTemp": 25,
|
||||
"minDamper": 0,
|
||||
"motion": 1,
|
||||
"motion": 5,
|
||||
"motionConfig": 1,
|
||||
"name": "Zone 5",
|
||||
"number": 1,
|
||||
|
@ -130,7 +130,7 @@
|
|||
"motion": 0,
|
||||
"motionConfig": 0,
|
||||
"name": "Zone closed without sensor",
|
||||
"number": 1,
|
||||
"number": 2,
|
||||
"rssi": 0,
|
||||
"setTemp": 24,
|
||||
"state": "close",
|
||||
|
|
Loading…
Reference in New Issue