core/tests/components/netatmo/test_climate.py

1094 lines
36 KiB
Python

"""The tests for the Netatmo climate platform."""
from datetime import timedelta
from unittest.mock import AsyncMock, patch
import pytest
from syrupy import SnapshotAssertion
from voluptuous.error import MultipleInvalid
from homeassistant.components.climate import (
ATTR_HVAC_MODE,
ATTR_PRESET_MODE,
DOMAIN as CLIMATE_DOMAIN,
PRESET_AWAY,
PRESET_BOOST,
SERVICE_SET_HVAC_MODE,
SERVICE_SET_PRESET_MODE,
SERVICE_SET_TEMPERATURE,
SERVICE_TURN_OFF,
SERVICE_TURN_ON,
HVACMode,
)
from homeassistant.components.netatmo.climate import PRESET_FROST_GUARD, PRESET_SCHEDULE
from homeassistant.components.netatmo.const import (
ATTR_END_DATETIME,
ATTR_SCHEDULE_NAME,
ATTR_TARGET_TEMPERATURE,
ATTR_TIME_PERIOD,
DOMAIN as NETATMO_DOMAIN,
SERVICE_CLEAR_TEMPERATURE_SETTING,
SERVICE_SET_PRESET_MODE_WITH_END_DATETIME,
SERVICE_SET_SCHEDULE,
SERVICE_SET_TEMPERATURE_WITH_END_DATETIME,
SERVICE_SET_TEMPERATURE_WITH_TIME_PERIOD,
)
from homeassistant.const import (
ATTR_ENTITY_ID,
ATTR_TEMPERATURE,
CONF_WEBHOOK_ID,
Platform,
)
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ServiceValidationError
import homeassistant.helpers.entity_registry as er
from homeassistant.util import dt as dt_util
from .common import selected_platforms, simulate_webhook, snapshot_platform_entities
from tests.common import MockConfigEntry
async def test_entity(
hass: HomeAssistant,
config_entry: MockConfigEntry,
netatmo_auth: AsyncMock,
snapshot: SnapshotAssertion,
entity_registry: er.EntityRegistry,
) -> None:
"""Test entities."""
await snapshot_platform_entities(
hass,
config_entry,
Platform.CLIMATE,
entity_registry,
snapshot,
)
async def test_webhook_event_handling_thermostats(
hass: HomeAssistant, config_entry: MockConfigEntry, netatmo_auth: AsyncMock
) -> None:
"""Test service and webhook event handling with thermostats."""
with selected_platforms([Platform.CLIMATE]):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
webhook_id = config_entry.data[CONF_WEBHOOK_ID]
climate_entity_livingroom = "climate.livingroom"
assert hass.states.get(climate_entity_livingroom).state == "auto"
assert (
hass.states.get(climate_entity_livingroom).attributes["preset_mode"] == "away"
)
assert hass.states.get(climate_entity_livingroom).attributes["temperature"] == 12
# Test service setting the temperature
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_TEMPERATURE,
{ATTR_ENTITY_ID: climate_entity_livingroom, ATTR_TEMPERATURE: 21},
blocking=True,
)
await hass.async_block_till_done()
# Fake webhook thermostat manual set point
response = {
"room_id": "2746182631",
"home": {
"id": "91763b24c43d3e344f424e8b",
"name": "MYHOME",
"country": "DE",
"rooms": [
{
"id": "2746182631",
"name": "Livingroom",
"type": "livingroom",
"therm_setpoint_mode": "manual",
"therm_setpoint_temperature": 21,
"therm_setpoint_end_time": 1612734552,
}
],
"modules": [
{"id": "12:34:56:00:01:ae", "name": "Livingroom", "type": "NATherm1"}
],
},
"mode": "manual",
"event_type": "set_point",
"temperature": 21,
"push_type": "display_change",
}
await simulate_webhook(hass, webhook_id, response)
assert hass.states.get(climate_entity_livingroom).state == "heat"
assert (
hass.states.get(climate_entity_livingroom).attributes["preset_mode"] == "away"
)
assert hass.states.get(climate_entity_livingroom).attributes["temperature"] == 21
# Test service setting the HVAC mode to "heat"
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_HVAC_MODE,
{ATTR_ENTITY_ID: climate_entity_livingroom, ATTR_HVAC_MODE: HVACMode.HEAT},
blocking=True,
)
await hass.async_block_till_done()
# Fake webhook thermostat mode change to "Max"
response = {
"room_id": "2746182631",
"home": {
"id": "91763b24c43d3e344f424e8b",
"name": "MYHOME",
"country": "DE",
"rooms": [
{
"id": "2746182631",
"name": "Livingroom",
"type": "livingroom",
"therm_setpoint_mode": "max",
"therm_setpoint_end_time": 1612749189,
}
],
"modules": [
{"id": "12:34:56:00:01:ae", "name": "Livingroom", "type": "NATherm1"}
],
},
"mode": "max",
"event_type": "set_point",
"push_type": "display_change",
}
await simulate_webhook(hass, webhook_id, response)
assert hass.states.get(climate_entity_livingroom).state == "heat"
assert hass.states.get(climate_entity_livingroom).attributes["temperature"] == 30
# Test service setting the HVAC mode to "off"
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_HVAC_MODE,
{ATTR_ENTITY_ID: climate_entity_livingroom, ATTR_HVAC_MODE: HVACMode.OFF},
blocking=True,
)
await hass.async_block_till_done()
# Fake webhook turn thermostat off
response = {
"home": {
"id": "91763b24c43d3e344f424e8b",
"name": "MYHOME",
"country": "DE",
"rooms": [
{
"id": "2746182631",
"name": "Livingroom",
"type": "livingroom",
"therm_setpoint_mode": "off",
}
],
"modules": [
{"id": "12:34:56:00:01:ae", "name": "Livingroom", "type": "NATherm1"}
],
},
"mode": "off",
"event_type": "set_point",
"push_type": "display_change",
}
await simulate_webhook(hass, webhook_id, response)
assert hass.states.get(climate_entity_livingroom).state == "off"
# Test service setting the HVAC mode to "auto"
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_HVAC_MODE,
{ATTR_ENTITY_ID: climate_entity_livingroom, ATTR_HVAC_MODE: HVACMode.AUTO},
blocking=True,
)
await hass.async_block_till_done()
# Fake webhook thermostat mode cancel set point
response = {
"room_id": "2746182631",
"home": {
"id": "91763b24c43d3e344f424e8b",
"name": "MYHOME",
"country": "DE",
"rooms": [
{
"id": "2746182631",
"name": "Livingroom",
"type": "livingroom",
"therm_setpoint_mode": "home",
}
],
"modules": [
{"id": "12:34:56:00:01:ae", "name": "Livingroom", "type": "NATherm1"}
],
},
"mode": "home",
"event_type": "cancel_set_point",
"push_type": "display_change",
}
await simulate_webhook(hass, webhook_id, response)
assert hass.states.get(climate_entity_livingroom).state == "auto"
assert (
hass.states.get(climate_entity_livingroom).attributes["preset_mode"] == "away"
)
async def test_service_preset_mode_frost_guard_thermostat(
hass: HomeAssistant, config_entry: MockConfigEntry, netatmo_auth: AsyncMock
) -> None:
"""Test service with frost guard preset for thermostats."""
with selected_platforms([Platform.CLIMATE]):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
webhook_id = config_entry.data[CONF_WEBHOOK_ID]
climate_entity_livingroom = "climate.livingroom"
assert hass.states.get(climate_entity_livingroom).state == "auto"
assert (
hass.states.get(climate_entity_livingroom).attributes["preset_mode"] == "away"
)
# Test service setting the preset mode to "frost guard"
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_PRESET_MODE,
{
ATTR_ENTITY_ID: climate_entity_livingroom,
ATTR_PRESET_MODE: PRESET_FROST_GUARD,
},
blocking=True,
)
await hass.async_block_till_done()
# Fake webhook thermostat mode change to "Frost Guard"
response = {
"event_type": "therm_mode",
"home": {"id": "91763b24c43d3e344f424e8b", "therm_mode": "hg"},
"mode": "hg",
"previous_mode": "schedule",
"push_type": "home_event_changed",
}
await simulate_webhook(hass, webhook_id, response)
assert hass.states.get(climate_entity_livingroom).state == "auto"
assert (
hass.states.get(climate_entity_livingroom).attributes["preset_mode"]
== "frost_guard"
)
# Test service setting the preset mode to "frost guard"
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_PRESET_MODE,
{
ATTR_ENTITY_ID: climate_entity_livingroom,
ATTR_PRESET_MODE: PRESET_SCHEDULE,
},
blocking=True,
)
await hass.async_block_till_done()
# Test webhook thermostat mode change to "Schedule"
response = {
"event_type": "therm_mode",
"home": {"id": "91763b24c43d3e344f424e8b", "therm_mode": "schedule"},
"mode": "schedule",
"previous_mode": "hg",
"push_type": "home_event_changed",
}
await simulate_webhook(hass, webhook_id, response)
assert hass.states.get(climate_entity_livingroom).state == "auto"
assert (
hass.states.get(climate_entity_livingroom).attributes["preset_mode"] == "away"
)
async def test_service_preset_modes_thermostat(
hass: HomeAssistant, config_entry: MockConfigEntry, netatmo_auth: AsyncMock
) -> None:
"""Test service with preset modes for thermostats."""
with selected_platforms([Platform.CLIMATE]):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
webhook_id = config_entry.data[CONF_WEBHOOK_ID]
climate_entity_livingroom = "climate.livingroom"
assert hass.states.get(climate_entity_livingroom).state == "auto"
assert (
hass.states.get(climate_entity_livingroom).attributes["preset_mode"] == "away"
)
# Test service setting the preset mode to "away"
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_PRESET_MODE,
{ATTR_ENTITY_ID: climate_entity_livingroom, ATTR_PRESET_MODE: PRESET_AWAY},
blocking=True,
)
await hass.async_block_till_done()
# Fake webhook thermostat mode change to "Away"
response = {
"event_type": "therm_mode",
"home": {"id": "91763b24c43d3e344f424e8b", "therm_mode": "away"},
"mode": "away",
"previous_mode": "schedule",
"push_type": "home_event_changed",
}
await simulate_webhook(hass, webhook_id, response)
assert hass.states.get(climate_entity_livingroom).state == "auto"
assert (
hass.states.get(climate_entity_livingroom).attributes["preset_mode"] == "away"
)
# Test service setting the preset mode to "boost"
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_PRESET_MODE,
{ATTR_ENTITY_ID: climate_entity_livingroom, ATTR_PRESET_MODE: PRESET_BOOST},
blocking=True,
)
await hass.async_block_till_done()
# Test webhook thermostat mode change to "Max"
response = {
"room_id": "2746182631",
"home": {
"id": "91763b24c43d3e344f424e8b",
"name": "MYHOME",
"country": "DE",
"rooms": [
{
"id": "2746182631",
"name": "Livingroom",
"type": "livingroom",
"therm_setpoint_mode": "max",
"therm_setpoint_end_time": 1612749189,
}
],
"modules": [
{"id": "12:34:56:00:01:ae", "name": "Livingroom", "type": "NATherm1"}
],
},
"mode": "max",
"event_type": "set_point",
"push_type": "display_change",
}
await simulate_webhook(hass, webhook_id, response)
assert hass.states.get(climate_entity_livingroom).state == "heat"
assert hass.states.get(climate_entity_livingroom).attributes["temperature"] == 30
async def test_service_set_temperature_with_end_datetime(
hass: HomeAssistant, config_entry: MockConfigEntry, netatmo_auth: AsyncMock
) -> None:
"""Test service setting temperature with an end datetime."""
with selected_platforms([Platform.CLIMATE]):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
webhook_id = config_entry.data[CONF_WEBHOOK_ID]
climate_entity_livingroom = "climate.livingroom"
assert hass.states.get(climate_entity_livingroom).state == "auto"
# Test service setting the temperature without an end datetime
await hass.services.async_call(
NETATMO_DOMAIN,
SERVICE_SET_TEMPERATURE_WITH_END_DATETIME,
{
ATTR_ENTITY_ID: climate_entity_livingroom,
ATTR_TARGET_TEMPERATURE: 25,
ATTR_END_DATETIME: "2023-11-17 12:23:00",
},
blocking=True,
)
await hass.async_block_till_done()
# Test webhook room mode change to "manual"
response = {
"room_id": "2746182631",
"home": {
"id": "91763b24c43d3e344f424e8b",
"name": "MYHOME",
"country": "DE",
"rooms": [
{
"id": "2746182631",
"name": "Livingroom",
"type": "livingroom",
"therm_setpoint_mode": "manual",
"therm_setpoint_temperature": 25,
"therm_setpoint_end_time": 1612749189,
}
],
"modules": [
{"id": "12:34:56:00:01:ae", "name": "Livingroom", "type": "NATherm1"}
],
},
"mode": "manual",
"event_type": "set_point",
"push_type": "display_change",
}
await simulate_webhook(hass, webhook_id, response)
assert hass.states.get(climate_entity_livingroom).state == "heat"
assert hass.states.get(climate_entity_livingroom).attributes["temperature"] == 25
async def test_service_set_temperature_with_time_period(
hass: HomeAssistant, config_entry: MockConfigEntry, netatmo_auth: AsyncMock
) -> None:
"""Test service setting temperature with an end datetime."""
with selected_platforms([Platform.CLIMATE]):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
webhook_id = config_entry.data[CONF_WEBHOOK_ID]
climate_entity_livingroom = "climate.livingroom"
assert hass.states.get(climate_entity_livingroom).state == "auto"
# Test service setting the temperature without an end datetime
await hass.services.async_call(
NETATMO_DOMAIN,
SERVICE_SET_TEMPERATURE_WITH_TIME_PERIOD,
{
ATTR_ENTITY_ID: climate_entity_livingroom,
ATTR_TARGET_TEMPERATURE: 25,
ATTR_TIME_PERIOD: "02:24:00",
},
blocking=True,
)
await hass.async_block_till_done()
# Test webhook room mode change to "manual"
response = {
"room_id": "2746182631",
"home": {
"id": "91763b24c43d3e344f424e8b",
"name": "MYHOME",
"country": "DE",
"rooms": [
{
"id": "2746182631",
"name": "Livingroom",
"type": "livingroom",
"therm_setpoint_mode": "manual",
"therm_setpoint_temperature": 25,
"therm_setpoint_end_time": 1612749189,
}
],
"modules": [
{"id": "12:34:56:00:01:ae", "name": "Livingroom", "type": "NATherm1"}
],
},
"mode": "manual",
"event_type": "set_point",
"push_type": "display_change",
}
await simulate_webhook(hass, webhook_id, response)
assert hass.states.get(climate_entity_livingroom).state == "heat"
assert hass.states.get(climate_entity_livingroom).attributes["temperature"] == 25
async def test_service_clear_temperature_setting(
hass: HomeAssistant, config_entry: MockConfigEntry, netatmo_auth: AsyncMock
) -> None:
"""Test service clearing temperature setting."""
with selected_platforms([Platform.CLIMATE]):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
webhook_id = config_entry.data[CONF_WEBHOOK_ID]
climate_entity_livingroom = "climate.livingroom"
assert hass.states.get(climate_entity_livingroom).state == "auto"
# Simulate a room thermostat change to manual boost
response = {
"room_id": "2746182631",
"home": {
"id": "91763b24c43d3e344f424e8b",
"name": "MYHOME",
"country": "DE",
"rooms": [
{
"id": "2746182631",
"name": "Livingroom",
"type": "livingroom",
"therm_setpoint_mode": "manual",
"therm_setpoint_temperature": 25,
"therm_setpoint_end_time": 1612749189,
}
],
"modules": [
{"id": "12:34:56:00:01:ae", "name": "Livingroom", "type": "NATherm1"}
],
},
"mode": "manual",
"event_type": "set_point",
"push_type": "display_change",
}
await simulate_webhook(hass, webhook_id, response)
assert hass.states.get(climate_entity_livingroom).state == "heat"
assert hass.states.get(climate_entity_livingroom).attributes["temperature"] == 25
# Test service setting the temperature without an end datetime
await hass.services.async_call(
NETATMO_DOMAIN,
SERVICE_CLEAR_TEMPERATURE_SETTING,
{ATTR_ENTITY_ID: climate_entity_livingroom},
blocking=True,
)
await hass.async_block_till_done()
# Test webhook room mode change to "home"
response = {
"room_id": "2746182631",
"home": {
"id": "91763b24c43d3e344f424e8b",
"name": "MYHOME",
"country": "DE",
"rooms": [
{
"id": "2746182631",
"name": "Livingroom",
"type": "livingroom",
"therm_setpoint_mode": "home",
}
],
"modules": [
{"id": "12:34:56:00:01:ae", "name": "Livingroom", "type": "NATherm1"}
],
},
"mode": "home",
"event_type": "cancel_set_point",
"push_type": "display_change",
}
await simulate_webhook(hass, webhook_id, response)
assert hass.states.get(climate_entity_livingroom).state == "auto"
async def test_webhook_event_handling_no_data(
hass: HomeAssistant, config_entry: MockConfigEntry, netatmo_auth: AsyncMock
) -> None:
"""Test service and webhook event handling with erroneous data."""
with selected_platforms([Platform.CLIMATE]):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
# Test webhook without home entry
webhook_id = config_entry.data[CONF_WEBHOOK_ID]
response = {
"push_type": "home_event_changed",
}
await simulate_webhook(hass, webhook_id, response)
# Test webhook with different home id
response = {
"home_id": "3d3e344f491763b24c424e8b",
"room_id": "2746182631",
"home": {
"id": "3d3e344f491763b24c424e8b",
"name": "MYHOME",
"country": "DE",
"rooms": [],
"modules": [],
},
"mode": "home",
"event_type": "cancel_set_point",
"push_type": "display_change",
}
await simulate_webhook(hass, webhook_id, response)
# Test webhook without room entries
response = {
"room_id": "2746182631",
"home": {
"id": "91763b24c43d3e344f424e8b",
"name": "MYHOME",
"country": "DE",
"rooms": [],
"modules": [],
},
"mode": "home",
"event_type": "cancel_set_point",
"push_type": "display_change",
}
await simulate_webhook(hass, webhook_id, response)
async def test_service_schedule_thermostats(
hass: HomeAssistant, config_entry, caplog: pytest.LogCaptureFixture, netatmo_auth
) -> None:
"""Test service for selecting Netatmo schedule with thermostats."""
with selected_platforms([Platform.CLIMATE]):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
webhook_id = config_entry.data[CONF_WEBHOOK_ID]
climate_entity_livingroom = "climate.livingroom"
# Test setting a valid schedule
with patch("pyatmo.home.Home.async_switch_schedule") as mock_switch_schedule:
await hass.services.async_call(
"netatmo",
SERVICE_SET_SCHEDULE,
{ATTR_ENTITY_ID: climate_entity_livingroom, ATTR_SCHEDULE_NAME: "Winter"},
blocking=True,
)
await hass.async_block_till_done()
mock_switch_schedule.assert_called_once_with(
schedule_id="b1b54a2f45795764f59d50d8"
)
# Fake backend response for valve being turned on
response = {
"event_type": "schedule",
"schedule_id": "b1b54a2f45795764f59d50d8",
"previous_schedule_id": "59d32176d183948b05ab4dce",
"push_type": "home_event_changed",
}
await simulate_webhook(hass, webhook_id, response)
assert (
hass.states.get(climate_entity_livingroom).attributes["selected_schedule"]
== "Winter"
)
# Test setting an invalid schedule
with patch("pyatmo.home.Home.async_switch_schedule") as mock_switch_home_schedule:
await hass.services.async_call(
"netatmo",
SERVICE_SET_SCHEDULE,
{ATTR_ENTITY_ID: climate_entity_livingroom, ATTR_SCHEDULE_NAME: "summer"},
blocking=True,
)
await hass.async_block_till_done()
mock_switch_home_schedule.assert_not_called()
assert "summer is not a valid schedule" in caplog.text
async def test_service_preset_mode_with_end_time_thermostats(
hass: HomeAssistant, config_entry, caplog: pytest.LogCaptureFixture, netatmo_auth
) -> None:
"""Test service for set preset mode with end datetime for Netatmo thermostats."""
with selected_platforms([Platform.CLIMATE]):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
webhook_id = config_entry.data[CONF_WEBHOOK_ID]
climate_entity_livingroom = "climate.livingroom"
# Test setting a valid preset mode (that allow an end datetime in Netatmo == THERM_MODES) and a valid end datetime
await hass.services.async_call(
"netatmo",
SERVICE_SET_PRESET_MODE_WITH_END_DATETIME,
{
ATTR_ENTITY_ID: climate_entity_livingroom,
ATTR_PRESET_MODE: PRESET_AWAY,
ATTR_END_DATETIME: (dt_util.now() + timedelta(days=10)).strftime(
"%Y-%m-%d %H:%M:%S"
),
},
blocking=True,
)
await hass.async_block_till_done()
# Fake webhook thermostat mode change to "Away"
response = {
"event_type": "therm_mode",
"home": {"id": "91763b24c43d3e344f424e8b", "therm_mode": "away"},
"mode": "away",
"previous_mode": "schedule",
"push_type": "home_event_changed",
}
await simulate_webhook(hass, webhook_id, response)
assert hass.states.get(climate_entity_livingroom).state == "auto"
assert (
hass.states.get(climate_entity_livingroom).attributes["preset_mode"] == "away"
)
# Test setting an invalid preset mode (not in THERM_MODES) and a valid end datetime
with pytest.raises(MultipleInvalid):
await hass.services.async_call(
"netatmo",
SERVICE_SET_PRESET_MODE_WITH_END_DATETIME,
{
ATTR_ENTITY_ID: climate_entity_livingroom,
ATTR_PRESET_MODE: PRESET_BOOST,
ATTR_END_DATETIME: (dt_util.now() + timedelta(days=10)).strftime(
"%Y-%m-%d %H:%M:%S"
),
},
blocking=True,
)
# Test setting a valid preset mode (that allow an end datetime in Netatmo == THERM_MODES) without an end datetime
with pytest.raises(MultipleInvalid):
await hass.services.async_call(
"netatmo",
SERVICE_SET_PRESET_MODE_WITH_END_DATETIME,
{
ATTR_ENTITY_ID: climate_entity_livingroom,
ATTR_PRESET_MODE: PRESET_AWAY,
},
blocking=True,
)
async def test_service_preset_mode_already_boost_valves(
hass: HomeAssistant, config_entry: MockConfigEntry, netatmo_auth: AsyncMock
) -> None:
"""Test service with boost preset for valves when already in boost mode."""
with selected_platforms([Platform.CLIMATE]):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
webhook_id = config_entry.data[CONF_WEBHOOK_ID]
climate_entity_entrada = "climate.entrada"
assert hass.states.get(climate_entity_entrada).state == "auto"
assert (
hass.states.get(climate_entity_entrada).attributes["preset_mode"]
== "frost_guard"
)
assert hass.states.get(climate_entity_entrada).attributes["temperature"] == 7
# Test webhook valve mode change to "Max"
response = {
"room_id": "2833524037",
"home": {
"id": "91763b24c43d3e344f424e8b",
"name": "MYHOME",
"country": "DE",
"rooms": [
{
"id": "2833524037",
"name": "Entrada",
"type": "lobby",
"therm_setpoint_mode": "max",
"therm_setpoint_end_time": 1612749189,
}
],
"modules": [{"id": "12:34:56:00:01:ae", "name": "Entrada", "type": "NRV"}],
},
"mode": "max",
"event_type": "set_point",
"push_type": "display_change",
}
await simulate_webhook(hass, webhook_id, response)
# Test service setting the preset mode to "boost"
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_PRESET_MODE,
{ATTR_ENTITY_ID: climate_entity_entrada, ATTR_PRESET_MODE: PRESET_BOOST},
blocking=True,
)
await hass.async_block_till_done()
# Test webhook valve mode change to "Max"
response = {
"room_id": "2833524037",
"home": {
"id": "91763b24c43d3e344f424e8b",
"name": "MYHOME",
"country": "DE",
"rooms": [
{
"id": "2833524037",
"name": "Entrada",
"type": "lobby",
"therm_setpoint_mode": "max",
"therm_setpoint_end_time": 1612749189,
}
],
"modules": [{"id": "12:34:56:00:01:ae", "name": "Entrada", "type": "NRV"}],
},
"mode": "max",
"event_type": "set_point",
"push_type": "display_change",
}
await simulate_webhook(hass, webhook_id, response)
assert hass.states.get(climate_entity_entrada).state == "heat"
assert hass.states.get(climate_entity_entrada).attributes["temperature"] == 30
async def test_service_preset_mode_boost_valves(
hass: HomeAssistant, config_entry: MockConfigEntry, netatmo_auth: AsyncMock
) -> None:
"""Test service with boost preset for valves."""
with selected_platforms([Platform.CLIMATE]):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
webhook_id = config_entry.data[CONF_WEBHOOK_ID]
climate_entity_entrada = "climate.entrada"
# Test service setting the preset mode to "boost"
assert hass.states.get(climate_entity_entrada).state == "auto"
assert hass.states.get(climate_entity_entrada).attributes["temperature"] == 7
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_PRESET_MODE,
{ATTR_ENTITY_ID: climate_entity_entrada, ATTR_PRESET_MODE: PRESET_BOOST},
blocking=True,
)
await hass.async_block_till_done()
# Fake backend response
response = {
"room_id": "2833524037",
"home": {
"id": "91763b24c43d3e344f424e8b",
"name": "MYHOME",
"country": "DE",
"rooms": [
{
"id": "2833524037",
"name": "Entrada",
"type": "lobby",
"therm_setpoint_mode": "max",
"therm_setpoint_end_time": 1612749189,
}
],
"modules": [{"id": "12:34:56:00:01:ae", "name": "Entrada", "type": "NRV"}],
},
"mode": "max",
"event_type": "set_point",
"push_type": "display_change",
}
await simulate_webhook(hass, webhook_id, response)
assert hass.states.get(climate_entity_entrada).state == "heat"
assert hass.states.get(climate_entity_entrada).attributes["temperature"] == 30
async def test_service_preset_mode_invalid(
hass: HomeAssistant, config_entry, caplog: pytest.LogCaptureFixture, netatmo_auth
) -> None:
"""Test service with invalid preset."""
with selected_platforms([Platform.CLIMATE]):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
with pytest.raises(ServiceValidationError):
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_SET_PRESET_MODE,
{ATTR_ENTITY_ID: "climate.cocina", ATTR_PRESET_MODE: "invalid"},
blocking=True,
)
async def test_valves_service_turn_off(
hass: HomeAssistant, config_entry: MockConfigEntry, netatmo_auth: AsyncMock
) -> None:
"""Test service turn off for valves."""
with selected_platforms([Platform.CLIMATE]):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
webhook_id = config_entry.data[CONF_WEBHOOK_ID]
climate_entity_entrada = "climate.entrada"
assert hass.states.get(climate_entity_entrada).attributes["hvac_modes"] == [
"auto",
"heat",
]
# Test turning valve off
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_TURN_OFF,
{ATTR_ENTITY_ID: climate_entity_entrada},
blocking=True,
)
await hass.async_block_till_done()
# Fake backend response for valve being turned off
response = {
"room_id": "2833524037",
"home": {
"id": "91763b24c43d3e344f424e8b",
"name": "MYHOME",
"country": "DE",
"rooms": [
{
"id": "2833524037",
"name": "Entrada",
"type": "lobby",
"therm_setpoint_mode": "off",
}
],
"modules": [{"id": "12:34:56:00:01:ae", "name": "Entrada", "type": "NRV"}],
},
"mode": "off",
"event_type": "set_point",
"push_type": "display_change",
}
await simulate_webhook(hass, webhook_id, response)
assert hass.states.get(climate_entity_entrada).state == "off"
async def test_valves_service_turn_on(
hass: HomeAssistant, config_entry: MockConfigEntry, netatmo_auth: AsyncMock
) -> None:
"""Test service turn on for valves."""
with selected_platforms([Platform.CLIMATE]):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
webhook_id = config_entry.data[CONF_WEBHOOK_ID]
climate_entity_entrada = "climate.entrada"
# Test turning valve on
await hass.services.async_call(
CLIMATE_DOMAIN,
SERVICE_TURN_ON,
{ATTR_ENTITY_ID: climate_entity_entrada},
blocking=True,
)
await hass.async_block_till_done()
# Fake backend response for valve being turned on
response = {
"room_id": "2833524037",
"home": {
"id": "91763b24c43d3e344f424e8b",
"name": "MYHOME",
"country": "DE",
"rooms": [
{
"id": "2833524037",
"name": "Entrada",
"type": "lobby",
"therm_setpoint_mode": "home",
}
],
"modules": [{"id": "12:34:56:00:01:ae", "name": "Entrada", "type": "NRV"}],
},
"mode": "home",
"event_type": "cancel_set_point",
"push_type": "display_change",
}
await simulate_webhook(hass, webhook_id, response)
assert hass.states.get(climate_entity_entrada).state == "auto"
async def test_webhook_home_id_mismatch(
hass: HomeAssistant, config_entry: MockConfigEntry, netatmo_auth: AsyncMock
) -> None:
"""Test service turn on for valves."""
with selected_platforms([Platform.CLIMATE]):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
webhook_id = config_entry.data[CONF_WEBHOOK_ID]
climate_entity_entrada = "climate.entrada"
assert hass.states.get(climate_entity_entrada).state == "auto"
# Fake backend response for valve being turned on
response = {
"room_id": "2833524037",
"home": {
"id": "123",
"name": "MYHOME",
"country": "DE",
"rooms": [
{
"id": "2833524037",
"name": "Entrada",
"type": "lobby",
"therm_setpoint_mode": "home",
}
],
"modules": [{"id": "12:34:56:00:01:ae", "name": "Entrada", "type": "NRV"}],
},
"mode": "home",
"event_type": "cancel_set_point",
"push_type": "display_change",
}
await simulate_webhook(hass, webhook_id, response)
assert hass.states.get(climate_entity_entrada).state == "auto"
async def test_webhook_set_point(
hass: HomeAssistant, config_entry: MockConfigEntry, netatmo_auth: AsyncMock
) -> None:
"""Test service turn on for valves."""
with selected_platforms([Platform.CLIMATE]):
assert await hass.config_entries.async_setup(config_entry.entry_id)
await hass.async_block_till_done()
webhook_id = config_entry.data[CONF_WEBHOOK_ID]
climate_entity_entrada = "climate.entrada"
# Fake backend response for valve being turned on
response = {
"room_id": "2746182631",
"home": {
"id": "91763b24c43d3e344f424e8b",
"name": "MYHOME",
"country": "DE",
"rooms": [
{
"id": "2833524037",
"name": "Entrada",
"type": "lobby",
"therm_setpoint_mode": "home",
"therm_setpoint_temperature": 30,
}
],
"modules": [{"id": "12:34:56:00:01:ae", "name": "Entrada", "type": "NRV"}],
},
"mode": "home",
"event_type": "set_point",
"temperature": 21,
"push_type": "display_change",
}
await simulate_webhook(hass, webhook_id, response)
assert hass.states.get(climate_entity_entrada).state == "heat"