mirror of https://github.com/home-assistant/core
Add MyPlace support to Advantage Air (#91108)
Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
parent
4420201fe6
commit
5001a50876
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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}})
|
||||
|
|
|
@ -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),
|
||||
}
|
||||
}
|
||||
)
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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):
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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"
|
||||
|
|
Loading…
Reference in New Issue