-
-
Notifications
You must be signed in to change notification settings - Fork 135
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
89174c2
commit 4d25edd
Showing
3 changed files
with
263 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
"""Provides device actions for Better Thermostat.""" | ||
|
||
from __future__ import annotations | ||
|
||
import voluptuous as vol | ||
|
||
from homeassistant.const import ( | ||
ATTR_ENTITY_ID, | ||
CONF_DEVICE_ID, | ||
CONF_DOMAIN, | ||
CONF_ENTITY_ID, | ||
CONF_TYPE, | ||
) | ||
from homeassistant.core import Context, HomeAssistant | ||
from homeassistant.helpers import entity_registry | ||
import homeassistant.helpers.config_validation as cv | ||
from homeassistant.helpers.typing import ConfigType, TemplateVarsType | ||
|
||
from . import DOMAIN | ||
from homeassistant.components.climate import ( | ||
ATTR_HVAC_MODE, | ||
ATTR_TARGET_TEMP_HIGH, | ||
ATTR_TARGET_TEMP_LOW, | ||
ATTR_TEMPERATURE, | ||
DOMAIN as CLIMATE_DOMAIN, | ||
HVACMode, | ||
SERVICE_SET_HVAC_MODE, | ||
SERVICE_SET_TEMPERATURE, | ||
) | ||
|
||
ACTION_TYPES = {"set_hvac_mode", "set_temperature"} | ||
|
||
_ACTION_SCHEMA = cv.DEVICE_ACTION_BASE_SCHEMA.extend( | ||
{ | ||
vol.Required(CONF_TYPE): vol.In(ACTION_TYPES), | ||
vol.Required(CONF_ENTITY_ID): cv.entity_domain(CLIMATE_DOMAIN), | ||
} | ||
) | ||
|
||
|
||
async def async_get_actions( | ||
hass: HomeAssistant, device_id: str | ||
) -> list[dict[str, str]]: | ||
"""List device actions for Better Thermostat devices.""" | ||
registry = entity_registry.async_get(hass) | ||
actions = [] | ||
|
||
# Get all the integrations entities for this device | ||
for entry in entity_registry.async_entries_for_device(registry, device_id): | ||
if entry.domain != DOMAIN: | ||
continue | ||
|
||
base_action = { | ||
CONF_DEVICE_ID: device_id, | ||
CONF_DOMAIN: DOMAIN, | ||
CONF_ENTITY_ID: entry.entity_id, | ||
} | ||
|
||
actions.extend( | ||
[ | ||
{**base_action, CONF_TYPE: "set_hvac_mode"}, | ||
{**base_action, CONF_TYPE: "set_temperature"}, | ||
] | ||
) | ||
|
||
return actions | ||
|
||
|
||
async def async_call_action_from_config( | ||
hass: HomeAssistant, | ||
config: ConfigType, | ||
variables: TemplateVarsType, | ||
context: Context | None, | ||
) -> None: | ||
"""Execute a device action.""" | ||
service_data = {ATTR_ENTITY_ID: config[CONF_ENTITY_ID]} | ||
|
||
if config[CONF_TYPE] == "set_hvac_mode": | ||
service = SERVICE_SET_HVAC_MODE | ||
service_data[ATTR_HVAC_MODE] = config[ATTR_HVAC_MODE] | ||
else: # config[CONF_TYPE] == "set_temperature" | ||
service = SERVICE_SET_TEMPERATURE | ||
if ATTR_TARGET_TEMP_HIGH in config: | ||
service_data[ATTR_TARGET_TEMP_HIGH] = config[ATTR_TARGET_TEMP_HIGH] | ||
if ATTR_TARGET_TEMP_LOW in config: | ||
service_data[ATTR_TARGET_TEMP_LOW] = config[ATTR_TARGET_TEMP_LOW] | ||
if ATTR_TEMPERATURE in config: | ||
service_data[ATTR_TEMPERATURE] = config[ATTR_TEMPERATURE] | ||
|
||
await hass.services.async_call( | ||
CLIMATE_DOMAIN, service, service_data, blocking=True, context=context | ||
) | ||
|
||
|
||
async def async_get_action_capabilities( | ||
hass: HomeAssistant, config: ConfigType | ||
) -> dict[str, vol.Schema]: | ||
"""List action capabilities.""" | ||
action_type = config[CONF_TYPE] | ||
|
||
if action_type == "set_hvac_mode": | ||
return { | ||
"extra_fields": vol.Schema( | ||
{ | ||
vol.Required(ATTR_HVAC_MODE): vol.In( | ||
[HVACMode.HEAT, HVACMode.OFF, HVACMode.HEAT_COOL] | ||
) | ||
} | ||
) | ||
} | ||
|
||
if action_type == "set_temperature": | ||
return { | ||
"extra_fields": vol.Schema( | ||
{ | ||
vol.Optional(ATTR_TEMPERATURE): vol.Coerce(float), | ||
vol.Optional(ATTR_TARGET_TEMP_HIGH): vol.Coerce(float), | ||
vol.Optional(ATTR_TARGET_TEMP_LOW): vol.Coerce(float), | ||
} | ||
) | ||
} | ||
|
||
return {} |
138 changes: 138 additions & 0 deletions
138
custom_components/better_thermostat/device_condition.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
"""Provide device conditions for Better Thermostat.""" | ||
|
||
from __future__ import annotations | ||
|
||
import voluptuous as vol | ||
|
||
from homeassistant.const import ( | ||
CONF_CONDITION, | ||
CONF_DEVICE_ID, | ||
CONF_DOMAIN, | ||
CONF_ENTITY_ID, | ||
CONF_TYPE, | ||
) | ||
from homeassistant.core import HomeAssistant, callback | ||
from homeassistant.helpers import condition, config_validation as cv, entity_registry | ||
from homeassistant.helpers.typing import ConfigType | ||
|
||
from . import DOMAIN | ||
from homeassistant.components.climate.const import ( | ||
ATTR_HVAC_ACTION, | ||
ATTR_HVAC_MODE, | ||
HVACAction, | ||
HVACMode, | ||
) | ||
|
||
CONDITION_TYPES = {"is_hvac_mode", "is_hvac_action"} | ||
|
||
HVAC_MODE_CONDITION = vol.Schema( | ||
{ | ||
vol.Required(CONF_ENTITY_ID): cv.entity_id, | ||
vol.Required(CONF_TYPE): "is_hvac_mode", | ||
vol.Required(ATTR_HVAC_MODE): vol.In( | ||
[HVACMode.OFF, HVACMode.HEAT, HVACMode.HEAT_COOL] | ||
), | ||
} | ||
) | ||
|
||
HVAC_ACTION_CONDITION = vol.Schema( | ||
{ | ||
vol.Required(CONF_ENTITY_ID): cv.entity_id, | ||
vol.Required(CONF_TYPE): "is_hvac_action", | ||
vol.Required(ATTR_HVAC_ACTION): vol.In( | ||
[HVACAction.OFF, HVACAction.HEATING, HVACAction.IDLE] | ||
), | ||
} | ||
) | ||
|
||
CONDITION_SCHEMA = vol.Any(HVAC_MODE_CONDITION, HVAC_ACTION_CONDITION) | ||
|
||
|
||
async def async_get_conditions( | ||
hass: HomeAssistant, device_id: str | ||
) -> list[dict[str, str]]: | ||
"""List device conditions for Better Thermostat devices.""" | ||
registry = entity_registry.async_get(hass) | ||
conditions = [] | ||
|
||
# Get all the integrations entities for this device | ||
for entry in entity_registry.async_entries_for_device(registry, device_id): | ||
if entry.domain != DOMAIN: | ||
continue | ||
|
||
base_condition = { | ||
CONF_CONDITION: "device", | ||
CONF_DEVICE_ID: device_id, | ||
CONF_DOMAIN: DOMAIN, | ||
CONF_ENTITY_ID: entry.entity_id, | ||
} | ||
|
||
conditions.extend( | ||
[{**base_condition, CONF_TYPE: cond} for cond in CONDITION_TYPES] | ||
) | ||
|
||
return conditions | ||
|
||
|
||
@callback | ||
def async_condition_from_config( | ||
hass: HomeAssistant, config: ConfigType | ||
) -> condition.ConditionCheckerType: | ||
"""Create a function to test a device condition.""" | ||
if config[CONF_TYPE] == "is_hvac_mode": | ||
hvac_mode = config[ATTR_HVAC_MODE] | ||
|
||
def test_is_hvac_mode(hass: HomeAssistant, variables: dict) -> bool: | ||
"""Test if an HVAC mode condition is met.""" | ||
state = hass.states.get(config[CONF_ENTITY_ID]) | ||
return ( | ||
state is not None and state.attributes.get(ATTR_HVAC_MODE) == hvac_mode | ||
) | ||
|
||
return test_is_hvac_mode | ||
|
||
if config[CONF_TYPE] == "is_hvac_action": | ||
hvac_action = config[ATTR_HVAC_ACTION] | ||
|
||
def test_is_hvac_action(hass: HomeAssistant, variables: dict) -> bool: | ||
"""Test if an HVAC action condition is met.""" | ||
state = hass.states.get(config[CONF_ENTITY_ID]) | ||
return ( | ||
state is not None | ||
and state.attributes.get(ATTR_HVAC_ACTION) == hvac_action | ||
) | ||
|
||
return test_is_hvac_action | ||
|
||
return lambda *_: False | ||
|
||
|
||
async def async_get_condition_capabilities( | ||
hass: HomeAssistant, config: ConfigType | ||
) -> dict[str, vol.Schema]: | ||
"""List condition capabilities.""" | ||
condition_type = config[CONF_TYPE] | ||
|
||
if condition_type == "is_hvac_mode": | ||
return { | ||
"extra_fields": vol.Schema( | ||
{ | ||
vol.Required(ATTR_HVAC_MODE): vol.In( | ||
[HVACMode.OFF, HVACMode.HEAT, HVACMode.HEAT_COOL] | ||
) | ||
} | ||
) | ||
} | ||
|
||
if condition_type == "is_hvac_action": | ||
return { | ||
"extra_fields": vol.Schema( | ||
{ | ||
vol.Required(ATTR_HVAC_ACTION): vol.In( | ||
[HVACAction.OFF, HVACAction.HEATING, HVACAction.IDLE] | ||
) | ||
} | ||
) | ||
} | ||
|
||
return {} |