Add MyPlace support to Advantage Air (#91108)

Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
Brett Adams 2023-04-17 08:27:37 +10:00 committed by GitHub
parent 4420201fe6
commit 5001a50876
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 390 additions and 51 deletions

View File

@ -75,6 +75,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
"coordinator": coordinator,
"aircon": error_handle_factory(api.aircon.async_set),
"lights": error_handle_factory(api.lights.async_set),
"things": error_handle_factory(api.things.async_set),
}
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)

View File

@ -16,7 +16,7 @@ from .const import (
ADVANTAGE_AIR_STATE_OPEN,
DOMAIN as ADVANTAGE_AIR_DOMAIN,
)
from .entity import AdvantageAirZoneEntity
from .entity import AdvantageAirThingEntity, AdvantageAirZoneEntity
PARALLEL_UPDATES = 0
@ -37,6 +37,16 @@ async def async_setup_entry(
# Only add zone vent controls when zone in vent control mode.
if zone["type"] == 0:
entities.append(AdvantageAirZoneVent(instance, ac_key, zone_key))
if things := instance["coordinator"].data.get("myThings"):
for thing in things["things"].values():
if thing["channelDipState"] in [1, 2]: # 1 = "Blind", 2 = "Blind 2"
entities.append(
AdvantageAirThingCover(instance, thing, CoverDeviceClass.BLIND)
)
elif thing["channelDipState"] == 3: # 3 = "Garage door"
entities.append(
AdvantageAirThingCover(instance, thing, CoverDeviceClass.GARAGE)
)
async_add_entities(entities)
@ -113,3 +123,32 @@ class AdvantageAirZoneVent(AdvantageAirZoneEntity, CoverEntity):
}
}
)
class AdvantageAirThingCover(AdvantageAirThingEntity, CoverEntity):
"""Representation of Advantage Air Cover controlled by MyPlace."""
_attr_supported_features = CoverEntityFeature.OPEN | CoverEntityFeature.CLOSE
def __init__(
self,
instance: dict[str, Any],
thing: dict[str, Any],
device_class: CoverDeviceClass,
) -> None:
"""Initialize an Advantage Air Things Cover."""
super().__init__(instance, thing)
self._attr_device_class = device_class
@property
def is_closed(self) -> bool:
"""Return if cover is fully closed."""
return self._data["value"] == 0
async def async_open_cover(self, **kwargs: Any) -> None:
"""Fully open zone vent."""
return await self.async_turn_on()
async def async_close_cover(self, **kwargs: Any) -> None:
"""Fully close zone vent."""
return await self.async_turn_off()

View File

@ -1,5 +1,4 @@
"""Advantage Air parent entity class."""
from typing import Any
from homeassistant.helpers.entity import DeviceInfo
@ -54,3 +53,40 @@ class AdvantageAirZoneEntity(AdvantageAirAcEntity):
@property
def _zone(self) -> dict[str, Any]:
return self.coordinator.data["aircons"][self.ac_key]["zones"][self.zone_key]
class AdvantageAirThingEntity(AdvantageAirEntity):
"""Parent class for Advantage Air Things Entities."""
def __init__(self, instance: dict[str, Any], thing: dict[str, Any]) -> None:
"""Initialize common aspects of an Advantage Air Things entity."""
super().__init__(instance)
self.set = instance["things"]
self._id = thing["id"]
self._attr_unique_id += f"-{self._id}"
self._attr_device_info = DeviceInfo(
via_device=(DOMAIN, self.coordinator.data["system"]["rid"]),
identifiers={(DOMAIN, self._attr_unique_id)},
manufacturer="Advantage Air",
model="MyPlace",
name=thing["name"],
)
@property
def _data(self) -> dict:
"""Return the thing data."""
return self.coordinator.data["myThings"]["things"][self._id]
@property
def is_on(self):
"""Return if the thing is considered on."""
return self._data["value"] > 0
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the thing on."""
await self.set({self._id: {"id": self._id, "value": 100}})
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the thing off."""
await self.set({self._id: {"id": self._id, "value": 0}})

View File

@ -12,7 +12,7 @@ from .const import (
ADVANTAGE_AIR_STATE_ON,
DOMAIN as ADVANTAGE_AIR_DOMAIN,
)
from .entity import AdvantageAirEntity
from .entity import AdvantageAirEntity, AdvantageAirThingEntity
async def async_setup_entry(
@ -31,6 +31,12 @@ async def async_setup_entry(
entities.append(AdvantageAirLight(instance, light))
else:
entities.append(AdvantageAirLightDimmable(instance, light))
if things := instance["coordinator"].data.get("myThings"):
for thing in things["things"].values():
if thing["channelDipState"] == 4: # 4 = "Light (on/off)""
entities.append(AdvantageAirThingLight(instance, thing))
elif thing["channelDipState"] == 5: # 5 = "Light (Dimmable)""
entities.append(AdvantageAirThingLightDimmable(instance, thing))
async_add_entities(entities)
@ -42,7 +48,7 @@ class AdvantageAirLight(AdvantageAirEntity, LightEntity):
def __init__(self, instance: dict[str, Any], light: dict[str, Any]) -> None:
"""Initialize an Advantage Air Light."""
super().__init__(instance)
self.lights = instance["lights"]
self.set = instance["lights"]
self._id: str = light["id"]
self._attr_unique_id += f"-{self._id}"
self._attr_device_info = DeviceInfo(
@ -54,24 +60,22 @@ class AdvantageAirLight(AdvantageAirEntity, LightEntity):
)
@property
def _light(self) -> dict[str, Any]:
def _data(self) -> dict[str, Any]:
"""Return the light object."""
return self.coordinator.data["myLights"]["lights"][self._id]
@property
def is_on(self) -> bool:
"""Return if the light is on."""
return self._light["state"] == ADVANTAGE_AIR_STATE_ON
return self._data["state"] == ADVANTAGE_AIR_STATE_ON
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the light on."""
await self.lights({self._id: {"id": self._id, "state": ADVANTAGE_AIR_STATE_ON}})
await self.set({self._id: {"id": self._id, "state": ADVANTAGE_AIR_STATE_ON}})
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the light off."""
await self.lights(
{self._id: {"id": self._id, "state": ADVANTAGE_AIR_STATE_OFF}}
)
await self.set({self._id: {"id": self._id, "state": ADVANTAGE_AIR_STATE_OFF}})
class AdvantageAirLightDimmable(AdvantageAirLight):
@ -82,7 +86,7 @@ class AdvantageAirLightDimmable(AdvantageAirLight):
@property
def brightness(self) -> int:
"""Return the brightness of this light between 0..255."""
return round(self._light["value"] * 255 / 100)
return round(self._data["value"] * 255 / 100)
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the light on and optionally set the brightness."""
@ -91,4 +95,32 @@ class AdvantageAirLightDimmable(AdvantageAirLight):
}
if ATTR_BRIGHTNESS in kwargs:
data[self._id]["value"] = round(kwargs[ATTR_BRIGHTNESS] * 100 / 255)
await self.lights(data)
await self.set(data)
class AdvantageAirThingLight(AdvantageAirThingEntity, LightEntity):
"""Representation of Advantage Air Light controlled by myThings."""
_attr_supported_color_modes = {ColorMode.ONOFF}
class AdvantageAirThingLightDimmable(AdvantageAirThingEntity, LightEntity):
"""Representation of Advantage Air Dimmable Light controlled by myThings."""
_attr_supported_color_modes = {ColorMode.ONOFF, ColorMode.BRIGHTNESS}
@property
def brightness(self) -> int:
"""Return the brightness of this light between 0..255."""
return round(self._data["value"] * 255 / 100)
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the light on by setting the brightness."""
await self.set(
{
self._id: {
"id": self._id,
"value": round(kwargs.get(ATTR_BRIGHTNESS, 255) * 100 / 255),
}
}
)

View File

@ -42,11 +42,14 @@ class AdvantageAirMyZone(AdvantageAirAcEntity, SelectEntity):
self._number_to_name = {0: ADVANTAGE_AIR_INACTIVE}
self._name_to_number = {ADVANTAGE_AIR_INACTIVE: 0}
for zone in instance["coordinator"].data["aircons"][ac_key]["zones"].values():
if zone["type"] > 0:
self._name_to_number[zone["name"]] = zone["number"]
self._number_to_name[zone["number"]] = zone["name"]
self._attr_options.append(zone["name"])
if "aircons" in instance["coordinator"].data:
for zone in (
instance["coordinator"].data["aircons"][ac_key]["zones"].values()
):
if zone["type"] > 0:
self._name_to_number[zone["name"]] = zone["number"]
self._number_to_name[zone["number"]] = zone["name"]
self._attr_options.append(zone["name"])
@property
def current_option(self) -> str:

View File

@ -1,7 +1,7 @@
"""Switch platform for Advantage Air integration."""
from typing import Any
from homeassistant.components.switch import SwitchEntity
from homeassistant.components.switch import SwitchDeviceClass, SwitchEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback
@ -11,7 +11,7 @@ from .const import (
ADVANTAGE_AIR_STATE_ON,
DOMAIN as ADVANTAGE_AIR_DOMAIN,
)
from .entity import AdvantageAirAcEntity
from .entity import AdvantageAirAcEntity, AdvantageAirThingEntity
async def async_setup_entry(
@ -28,6 +28,10 @@ async def async_setup_entry(
for ac_key, ac_device in aircons.items():
if ac_device["info"]["freshAirStatus"] != "none":
entities.append(AdvantageAirFreshAir(instance, ac_key))
if things := instance["coordinator"].data.get("myThings"):
for thing in things["things"].values():
if thing["channelDipState"] == 8: # 8 = Other relay
entities.append(AdvantageAirRelay(instance, thing))
async_add_entities(entities)
@ -36,6 +40,7 @@ class AdvantageAirFreshAir(AdvantageAirAcEntity, SwitchEntity):
_attr_icon = "mdi:air-filter"
_attr_name = "Fresh air"
_attr_device_class = SwitchDeviceClass.SWITCH
def __init__(self, instance: dict[str, Any], ac_key: str) -> None:
"""Initialize an Advantage Air fresh air control."""
@ -58,3 +63,9 @@ class AdvantageAirFreshAir(AdvantageAirAcEntity, SwitchEntity):
await self.aircon(
{self.ac_key: {"info": {"freshAirStatus": ADVANTAGE_AIR_STATE_OFF}}}
)
class AdvantageAirRelay(AdvantageAirThingEntity, SwitchEntity):
"""Representation of Advantage Air Thing."""
_attr_device_class = SwitchDeviceClass.SWITCH

View File

@ -20,6 +20,9 @@ TEST_SET_URL = f"http://{USER_INPUT[CONF_IP_ADDRESS]}:{USER_INPUT[CONF_PORT]}/se
TEST_SET_LIGHT_URL = (
f"http://{USER_INPUT[CONF_IP_ADDRESS]}:{USER_INPUT[CONF_PORT]}/setLights"
)
TEST_SET_THING_URL = (
f"http://{USER_INPUT[CONF_IP_ADDRESS]}:{USER_INPUT[CONF_PORT]}/setThings"
)
async def add_mock_config(hass):

View File

@ -220,11 +220,64 @@
}
}
},
"myThings": {
"things": {
"200": {
"buttonType": "upDown",
"channelDipState": 1,
"id": "200",
"name": "Blind 1",
"value": 100
},
"201": {
"buttonType": "upDown",
"channelDipState": 2,
"id": "201",
"name": "Blind 2",
"value": 0
},
"202": {
"buttonType": "openClose",
"channelDipState": 3,
"id": "202",
"name": "Garage",
"value": 100
},
"203": {
"buttonType": "onOff",
"channelDipState": 4,
"id": "203",
"name": "Thing Light",
"value": 100
},
"204": {
"buttonType": "upDown",
"channelDipState": 5,
"id": "204",
"name": "Thing Light Dimmable",
"value": 100
},
"205": {
"buttonType": "onOff",
"channelDipState": 8,
"id": "205",
"name": "Relay",
"value": 100
},
"206": {
"buttonType": "onOff",
"channelDipState": 9,
"id": "206",
"name": "Fan",
"value": 100
}
}
},
"system": {
"hasAircons": true,
"hasLights": true,
"hasSensors": false,
"hasThings": false,
"hasThings": true,
"hasThingsBOG": false,
"hasThingsLight": false,
"needsUpdate": false,

View File

@ -19,6 +19,7 @@ from homeassistant.helpers import entity_registry as er
from . import (
TEST_SET_RESPONSE,
TEST_SET_THING_URL,
TEST_SET_URL,
TEST_SYSTEM_DATA,
TEST_SYSTEM_URL,
@ -28,7 +29,7 @@ from . import (
from tests.test_util.aiohttp import AiohttpClientMocker
async def test_cover_async_setup_entry(
async def test_ac_cover(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
) -> None:
"""Test cover platform."""
@ -46,8 +47,6 @@ async def test_cover_async_setup_entry(
registry = er.async_get(hass)
assert len(aioclient_mock.mock_calls) == 1
# Test Cover Zone Entity
entity_id = "cover.myauto_zone_y"
state = hass.states.get(entity_id)
@ -66,7 +65,6 @@ async def test_cover_async_setup_entry(
{ATTR_ENTITY_ID: [entity_id]},
blocking=True,
)
assert len(aioclient_mock.mock_calls) == 3
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"])
@ -80,7 +78,6 @@ async def test_cover_async_setup_entry(
{ATTR_ENTITY_ID: [entity_id]},
blocking=True,
)
assert len(aioclient_mock.mock_calls) == 5
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"])
@ -95,7 +92,6 @@ async def test_cover_async_setup_entry(
{ATTR_ENTITY_ID: [entity_id], ATTR_POSITION: 50},
blocking=True,
)
assert len(aioclient_mock.mock_calls) == 7
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"])
@ -109,7 +105,6 @@ async def test_cover_async_setup_entry(
{ATTR_ENTITY_ID: [entity_id], ATTR_POSITION: 0},
blocking=True,
)
assert len(aioclient_mock.mock_calls) == 9
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"])
@ -129,7 +124,6 @@ async def test_cover_async_setup_entry(
},
blocking=True,
)
assert len(aioclient_mock.mock_calls) == 11
data = loads(aioclient_mock.mock_calls[-2][1].query["json"])
assert data["ac3"]["zones"]["z01"]["state"] == ADVANTAGE_AIR_STATE_CLOSE
assert data["ac3"]["zones"]["z02"]["state"] == ADVANTAGE_AIR_STATE_CLOSE
@ -144,7 +138,65 @@ async def test_cover_async_setup_entry(
},
blocking=True,
)
assert len(aioclient_mock.mock_calls) == 13
data = loads(aioclient_mock.mock_calls[-2][1].query["json"])
assert data["ac3"]["zones"]["z01"]["state"] == ADVANTAGE_AIR_STATE_OPEN
assert data["ac3"]["zones"]["z02"]["state"] == ADVANTAGE_AIR_STATE_OPEN
async def test_things_cover(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
) -> None:
"""Test cover platform."""
aioclient_mock.get(
TEST_SYSTEM_URL,
text=TEST_SYSTEM_DATA,
)
aioclient_mock.get(
TEST_SET_THING_URL,
text=TEST_SET_RESPONSE,
)
await add_mock_config(hass)
registry = er.async_get(hass)
# Test Blind 1 Entity
entity_id = "cover.blind_1"
thing_id = "200"
state = hass.states.get(entity_id)
assert state
assert state.state == STATE_OPEN
assert state.attributes.get("device_class") == CoverDeviceClass.BLIND
entry = registry.async_get(entity_id)
assert entry
assert entry.unique_id == "uniqueid-200"
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_CLOSE_COVER,
{ATTR_ENTITY_ID: [entity_id]},
blocking=True,
)
assert aioclient_mock.mock_calls[-2][0] == "GET"
assert aioclient_mock.mock_calls[-2][1].path == "/setThings"
data = loads(aioclient_mock.mock_calls[-2][1].query["json"]).get(thing_id)
assert data["id"] == thing_id
assert data["value"] == 0
assert aioclient_mock.mock_calls[-1][0] == "GET"
assert aioclient_mock.mock_calls[-1][1].path == "/getSystemData"
await hass.services.async_call(
COVER_DOMAIN,
SERVICE_OPEN_COVER,
{ATTR_ENTITY_ID: [entity_id]},
blocking=True,
)
assert aioclient_mock.mock_calls[-2][0] == "GET"
assert aioclient_mock.mock_calls[-2][1].path == "/setThings"
data = loads(aioclient_mock.mock_calls[-2][1].query["json"]).get(thing_id)
assert data["id"] == thing_id
assert data["value"] == 100
assert aioclient_mock.mock_calls[-1][0] == "GET"
assert aioclient_mock.mock_calls[-1][1].path == "/getSystemData"

View File

@ -11,13 +11,14 @@ from homeassistant.components.light import (
SERVICE_TURN_OFF,
SERVICE_TURN_ON,
)
from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF
from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from . import (
TEST_SET_LIGHT_URL,
TEST_SET_RESPONSE,
TEST_SET_THING_URL,
TEST_SYSTEM_DATA,
TEST_SYSTEM_URL,
add_mock_config,
@ -26,9 +27,7 @@ from . import (
from tests.test_util.aiohttp import AiohttpClientMocker
async def test_light_async_setup_entry(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
) -> None:
async def test_light(hass: HomeAssistant, aioclient_mock: AiohttpClientMocker) -> None:
"""Test light setup."""
aioclient_mock.get(
@ -44,17 +43,16 @@ async def test_light_async_setup_entry(
registry = er.async_get(hass)
assert len(aioclient_mock.mock_calls) == 1
# Test Light Entity
entity_id = "light.light_a"
light_id = "100"
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-100"
assert entry.unique_id == f"uniqueid-{light_id}"
await hass.services.async_call(
LIGHT_DOMAIN,
@ -62,11 +60,10 @@ async def test_light_async_setup_entry(
{ATTR_ENTITY_ID: [entity_id]},
blocking=True,
)
assert len(aioclient_mock.mock_calls) == 3
assert aioclient_mock.mock_calls[-2][0] == "GET"
assert aioclient_mock.mock_calls[-2][1].path == "/setLights"
data = loads(aioclient_mock.mock_calls[-2][1].query["json"]).get("100")
assert data["id"] == "100"
data = loads(aioclient_mock.mock_calls[-2][1].query["json"]).get(light_id)
assert data["id"] == light_id
assert data["state"] == ADVANTAGE_AIR_STATE_ON
assert aioclient_mock.mock_calls[-1][0] == "GET"
assert aioclient_mock.mock_calls[-1][1].path == "/getSystemData"
@ -77,21 +74,21 @@ async def test_light_async_setup_entry(
{ATTR_ENTITY_ID: [entity_id]},
blocking=True,
)
assert len(aioclient_mock.mock_calls) == 5
assert aioclient_mock.mock_calls[-2][0] == "GET"
assert aioclient_mock.mock_calls[-2][1].path == "/setLights"
data = loads(aioclient_mock.mock_calls[-2][1].query["json"]).get("100")
assert data["id"] == "100"
data = loads(aioclient_mock.mock_calls[-2][1].query["json"]).get(light_id)
assert data["id"] == light_id
assert data["state"] == ADVANTAGE_AIR_STATE_OFF
assert aioclient_mock.mock_calls[-1][0] == "GET"
assert aioclient_mock.mock_calls[-1][1].path == "/getSystemData"
# Test Dimmable Light Entity
entity_id = "light.light_b"
light_id = "101"
entry = registry.async_get(entity_id)
assert entry
assert entry.unique_id == "uniqueid-101"
assert entry.unique_id == f"uniqueid-{light_id}"
await hass.services.async_call(
LIGHT_DOMAIN,
@ -99,12 +96,69 @@ async def test_light_async_setup_entry(
{ATTR_ENTITY_ID: [entity_id], ATTR_BRIGHTNESS: 128},
blocking=True,
)
assert len(aioclient_mock.mock_calls) == 7
assert aioclient_mock.mock_calls[-2][0] == "GET"
assert aioclient_mock.mock_calls[-2][1].path == "/setLights"
data = loads(aioclient_mock.mock_calls[-2][1].query["json"]).get("101")
assert data["id"] == "101"
data = loads(aioclient_mock.mock_calls[-2][1].query["json"]).get(light_id)
assert data["id"] == light_id
assert data["value"] == 50
assert data["state"] == ADVANTAGE_AIR_STATE_ON
assert aioclient_mock.mock_calls[-1][0] == "GET"
assert aioclient_mock.mock_calls[-1][1].path == "/getSystemData"
async def test_things_light(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
) -> None:
"""Test things lights."""
aioclient_mock.get(
TEST_SYSTEM_URL,
text=TEST_SYSTEM_DATA,
)
aioclient_mock.get(
TEST_SET_THING_URL,
text=TEST_SET_RESPONSE,
)
await add_mock_config(hass)
registry = er.async_get(hass)
# Test Switch Entity
entity_id = "light.thing_light_dimmable"
light_id = "204"
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-204"
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: [entity_id]},
blocking=True,
)
assert aioclient_mock.mock_calls[-2][0] == "GET"
assert aioclient_mock.mock_calls[-2][1].path == "/setThings"
data = loads(aioclient_mock.mock_calls[-2][1].query["json"]).get(light_id)
assert data["id"] == light_id
assert data["value"] == 0
assert aioclient_mock.mock_calls[-1][0] == "GET"
assert aioclient_mock.mock_calls[-1][1].path == "/getSystemData"
await hass.services.async_call(
LIGHT_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: [entity_id], ATTR_BRIGHTNESS: 128},
blocking=True,
)
assert aioclient_mock.mock_calls[-2][0] == "GET"
assert aioclient_mock.mock_calls[-2][1].path == "/setThings"
data = loads(aioclient_mock.mock_calls[-2][1].query["json"]).get(light_id)
assert data["id"] == light_id
assert data["value"] == 50
assert aioclient_mock.mock_calls[-1][0] == "GET"
assert aioclient_mock.mock_calls[-1][1].path == "/getSystemData"

View File

@ -10,12 +10,13 @@ from homeassistant.components.switch import (
SERVICE_TURN_OFF,
SERVICE_TURN_ON,
)
from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF
from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from . import (
TEST_SET_RESPONSE,
TEST_SET_THING_URL,
TEST_SET_URL,
TEST_SYSTEM_DATA,
TEST_SYSTEM_URL,
@ -43,8 +44,6 @@ async def test_cover_async_setup_entry(
registry = er.async_get(hass)
assert len(aioclient_mock.mock_calls) == 1
# Test Switch Entity
entity_id = "switch.myzone_fresh_air"
state = hass.states.get(entity_id)
@ -61,7 +60,6 @@ async def test_cover_async_setup_entry(
{ATTR_ENTITY_ID: [entity_id]},
blocking=True,
)
assert len(aioclient_mock.mock_calls) == 3
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"])
@ -75,10 +73,67 @@ async def test_cover_async_setup_entry(
{ATTR_ENTITY_ID: [entity_id]},
blocking=True,
)
assert len(aioclient_mock.mock_calls) == 5
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"]["freshAirStatus"] == ADVANTAGE_AIR_STATE_OFF
assert aioclient_mock.mock_calls[-1][0] == "GET"
assert aioclient_mock.mock_calls[-1][1].path == "/getSystemData"
async def test_things_switch(
hass: HomeAssistant, aioclient_mock: AiohttpClientMocker
) -> None:
"""Test things switches."""
aioclient_mock.get(
TEST_SYSTEM_URL,
text=TEST_SYSTEM_DATA,
)
aioclient_mock.get(
TEST_SET_THING_URL,
text=TEST_SET_RESPONSE,
)
await add_mock_config(hass)
registry = er.async_get(hass)
# Test Switch Entity
entity_id = "switch.relay"
thing_id = "205"
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-205"
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: [entity_id]},
blocking=True,
)
assert aioclient_mock.mock_calls[-2][0] == "GET"
assert aioclient_mock.mock_calls[-2][1].path == "/setThings"
data = loads(aioclient_mock.mock_calls[-2][1].query["json"]).get(thing_id)
assert data["id"] == thing_id
assert data["value"] == 0
assert aioclient_mock.mock_calls[-1][0] == "GET"
assert aioclient_mock.mock_calls[-1][1].path == "/getSystemData"
await hass.services.async_call(
SWITCH_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: [entity_id]},
blocking=True,
)
assert aioclient_mock.mock_calls[-2][0] == "GET"
assert aioclient_mock.mock_calls[-2][1].path == "/setThings"
data = loads(aioclient_mock.mock_calls[-2][1].query["json"]).get(thing_id)
assert data["id"] == thing_id
assert data["value"] == 100
assert aioclient_mock.mock_calls[-1][0] == "GET"
assert aioclient_mock.mock_calls[-1][1].path == "/getSystemData"