Skip to content

Commit

Permalink
[TASK] add current_humidity
Browse files Browse the repository at this point in the history
  • Loading branch information
KartoffelToby committed Nov 5, 2024
1 parent 89174c2 commit 4d25edd
Show file tree
Hide file tree
Showing 3 changed files with 263 additions and 1 deletion.
3 changes: 2 additions & 1 deletion custom_components/better_thermostat/climate.py
Original file line number Diff line number Diff line change
Expand Up @@ -579,7 +579,8 @@ async def startup(self):
continue

if self.humidity_entity_id is not None:
if self.hass.states.get(self.humidity_entity_id).state in (
humidity_state = self.hass.states.get(self.humidity_entity_id)
if humidity_state is None or humidity_state.state in (
STATE_UNAVAILABLE,
STATE_UNKNOWN,
None,
Expand Down
123 changes: 123 additions & 0 deletions custom_components/better_thermostat/device_action.py
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 custom_components/better_thermostat/device_condition.py
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 {}

0 comments on commit 4d25edd

Please sign in to comment.