mirror of
https://github.com/home-assistant/core.git
synced 2026-01-20 06:26:56 +01:00
Compare commits
5 Commits
simplify_e
...
use-new-ap
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
362769d64d | ||
|
|
48852bab7a | ||
|
|
7d370f4513 | ||
|
|
9d97791faf | ||
|
|
4fe8982b68 |
@@ -52,7 +52,7 @@ class AdGuardHomeEntity(Entity):
|
||||
def device_info(self) -> DeviceInfo:
|
||||
"""Return device information about this AdGuard Home instance."""
|
||||
if self._entry.source == SOURCE_HASSIO:
|
||||
config_url = "homeassistant://hassio/ingress/a0d7b954_adguard"
|
||||
config_url = "homeassistant://app/a0d7b954_adguard"
|
||||
elif self.adguard.tls:
|
||||
config_url = f"https://{self.adguard.host}:{self.adguard.port}"
|
||||
else:
|
||||
|
||||
@@ -10,7 +10,7 @@ LOGGER = logging.getLogger(__package__)
|
||||
|
||||
DOMAIN = "deconz"
|
||||
|
||||
HASSIO_CONFIGURATION_URL = "homeassistant://hassio/ingress/core_deconz"
|
||||
HASSIO_CONFIGURATION_URL = "homeassistant://app/core_deconz"
|
||||
|
||||
CONF_BRIDGE_ID = "bridgeid"
|
||||
CONF_GROUP_ID_BASE = "group_id_base"
|
||||
|
||||
@@ -1034,7 +1034,7 @@ def _async_setup_device_registry(
|
||||
and dashboard.data
|
||||
and dashboard.data.get(device_info.name)
|
||||
):
|
||||
configuration_url = f"homeassistant://hassio/ingress/{dashboard.addon_slug}"
|
||||
configuration_url = f"homeassistant://app/{dashboard.addon_slug}"
|
||||
|
||||
manufacturer = "espressif"
|
||||
if device_info.manufacturer:
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"title": "Lawn mower",
|
||||
"triggers": {
|
||||
"docked": {
|
||||
"description": "Triggers after one or more lawn mowers return to dock.",
|
||||
"description": "Triggers after one or more lawn mowers have returned to dock.",
|
||||
"fields": {
|
||||
"behavior": {
|
||||
"description": "[%key:component::lawn_mower::common::trigger_behavior_description%]",
|
||||
|
||||
@@ -50,7 +50,7 @@ class MealieConfigFlow(ConfigFlow, domain=DOMAIN):
|
||||
"""Check connection to the Mealie API."""
|
||||
assert self.host is not None
|
||||
|
||||
if "/hassio/ingress/" in self.host:
|
||||
if "/app/" in self.host:
|
||||
return {"base": "ingress_url"}, None
|
||||
|
||||
client = MealieClient(
|
||||
|
||||
@@ -373,7 +373,7 @@ class NumberDeviceClass(StrEnum):
|
||||
SULPHUR_DIOXIDE = "sulphur_dioxide"
|
||||
"""Amount of SO2.
|
||||
|
||||
Unit of measurement: `μg/m³`
|
||||
Unit of measurement: `ppb` (parts per billion), `μg/m³`
|
||||
"""
|
||||
|
||||
TEMPERATURE = "temperature"
|
||||
@@ -545,7 +545,10 @@ DEVICE_CLASS_UNITS: dict[NumberDeviceClass, set[type[StrEnum] | str | None]] = {
|
||||
},
|
||||
NumberDeviceClass.SOUND_PRESSURE: set(UnitOfSoundPressure),
|
||||
NumberDeviceClass.SPEED: {*UnitOfSpeed, *UnitOfVolumetricFlux},
|
||||
NumberDeviceClass.SULPHUR_DIOXIDE: {CONCENTRATION_MICROGRAMS_PER_CUBIC_METER},
|
||||
NumberDeviceClass.SULPHUR_DIOXIDE: {
|
||||
CONCENTRATION_PARTS_PER_BILLION,
|
||||
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
},
|
||||
NumberDeviceClass.TEMPERATURE: set(UnitOfTemperature),
|
||||
NumberDeviceClass.TEMPERATURE_DELTA: set(UnitOfTemperature),
|
||||
NumberDeviceClass.VOLATILE_ORGANIC_COMPOUNDS: {
|
||||
|
||||
@@ -158,7 +158,7 @@ MODEL_NAMES = [ # https://ollama.com/library
|
||||
"yi",
|
||||
"zephyr",
|
||||
]
|
||||
DEFAULT_MODEL = "qwen3:4b"
|
||||
DEFAULT_MODEL = "qwen3:4b-instruct"
|
||||
|
||||
DEFAULT_CONVERSATION_NAME = "Ollama Conversation"
|
||||
DEFAULT_AI_TASK_NAME = "Ollama AI Task"
|
||||
|
||||
@@ -64,6 +64,7 @@ from homeassistant.util.unit_conversion import (
|
||||
ReactiveEnergyConverter,
|
||||
ReactivePowerConverter,
|
||||
SpeedConverter,
|
||||
SulphurDioxideConcentrationConverter,
|
||||
TemperatureConverter,
|
||||
TemperatureDeltaConverter,
|
||||
UnitlessRatioConverter,
|
||||
@@ -225,6 +226,7 @@ _PRIMARY_UNIT_CONVERTERS: list[type[BaseUnitConverter]] = [
|
||||
_SECONDARY_UNIT_CONVERTERS: list[type[BaseUnitConverter]] = [
|
||||
CarbonMonoxideConcentrationConverter,
|
||||
TemperatureDeltaConverter,
|
||||
SulphurDioxideConcentrationConverter,
|
||||
]
|
||||
|
||||
STATISTIC_UNIT_TO_UNIT_CONVERTER: dict[str | None, type[BaseUnitConverter]] = {
|
||||
|
||||
@@ -38,6 +38,7 @@ from homeassistant.util.unit_conversion import (
|
||||
ReactiveEnergyConverter,
|
||||
ReactivePowerConverter,
|
||||
SpeedConverter,
|
||||
SulphurDioxideConcentrationConverter,
|
||||
TemperatureConverter,
|
||||
TemperatureDeltaConverter,
|
||||
UnitlessRatioConverter,
|
||||
@@ -94,6 +95,9 @@ UNIT_SCHEMA = vol.Schema(
|
||||
vol.Optional("reactive_energy"): vol.In(ReactiveEnergyConverter.VALID_UNITS),
|
||||
vol.Optional("reactive_power"): vol.In(ReactivePowerConverter.VALID_UNITS),
|
||||
vol.Optional("speed"): vol.In(SpeedConverter.VALID_UNITS),
|
||||
vol.Optional("sulphur_dioxide"): vol.In(
|
||||
SulphurDioxideConcentrationConverter.VALID_UNITS
|
||||
),
|
||||
vol.Optional("temperature"): vol.In(TemperatureConverter.VALID_UNITS),
|
||||
vol.Optional("temperature_delta"): vol.In(
|
||||
TemperatureDeltaConverter.VALID_UNITS
|
||||
|
||||
@@ -68,6 +68,7 @@ from homeassistant.util.unit_conversion import (
|
||||
ReactiveEnergyConverter,
|
||||
ReactivePowerConverter,
|
||||
SpeedConverter,
|
||||
SulphurDioxideConcentrationConverter,
|
||||
TemperatureConverter,
|
||||
TemperatureDeltaConverter,
|
||||
UnitlessRatioConverter,
|
||||
@@ -409,7 +410,7 @@ class SensorDeviceClass(StrEnum):
|
||||
SULPHUR_DIOXIDE = "sulphur_dioxide"
|
||||
"""Amount of SO2.
|
||||
|
||||
Unit of measurement: `μg/m³`
|
||||
Unit of measurement: `ppb` (parts per billion), `μg/m³`
|
||||
"""
|
||||
|
||||
TEMPERATURE = "temperature"
|
||||
@@ -569,6 +570,7 @@ UNIT_CONVERTERS: dict[SensorDeviceClass | str | None, type[BaseUnitConverter]] =
|
||||
SensorDeviceClass.PRESSURE: PressureConverter,
|
||||
SensorDeviceClass.REACTIVE_ENERGY: ReactiveEnergyConverter,
|
||||
SensorDeviceClass.REACTIVE_POWER: ReactivePowerConverter,
|
||||
SensorDeviceClass.SULPHUR_DIOXIDE: SulphurDioxideConcentrationConverter,
|
||||
SensorDeviceClass.SPEED: SpeedConverter,
|
||||
SensorDeviceClass.TEMPERATURE: TemperatureConverter,
|
||||
SensorDeviceClass.TEMPERATURE_DELTA: TemperatureDeltaConverter,
|
||||
@@ -657,7 +659,10 @@ DEVICE_CLASS_UNITS: dict[SensorDeviceClass, set[type[StrEnum] | str | None]] = {
|
||||
},
|
||||
SensorDeviceClass.SOUND_PRESSURE: set(UnitOfSoundPressure),
|
||||
SensorDeviceClass.SPEED: {*UnitOfSpeed, *UnitOfVolumetricFlux},
|
||||
SensorDeviceClass.SULPHUR_DIOXIDE: {CONCENTRATION_MICROGRAMS_PER_CUBIC_METER},
|
||||
SensorDeviceClass.SULPHUR_DIOXIDE: {
|
||||
CONCENTRATION_PARTS_PER_BILLION,
|
||||
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
},
|
||||
SensorDeviceClass.TEMPERATURE: set(UnitOfTemperature),
|
||||
SensorDeviceClass.TEMPERATURE_DELTA: set(UnitOfTemperature),
|
||||
SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS: {
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["waterfurnace"],
|
||||
"quality_scale": "legacy",
|
||||
"requirements": ["waterfurnace==1.2.0"]
|
||||
"requirements": ["waterfurnace==1.4.0"]
|
||||
}
|
||||
|
||||
@@ -103,6 +103,7 @@ _AMBIENT_IDEAL_GAS_MOLAR_VOLUME = ( # m3⋅mol⁻¹
|
||||
)
|
||||
# Molar masses in g⋅mol⁻¹
|
||||
_CARBON_MONOXIDE_MOLAR_MASS = 28.01
|
||||
_SULPHUR_DIOXIDE_MOLAR_MASS = 64.066
|
||||
|
||||
|
||||
class BaseUnitConverter:
|
||||
@@ -208,6 +209,22 @@ class CarbonMonoxideConcentrationConverter(BaseUnitConverter):
|
||||
}
|
||||
|
||||
|
||||
class SulphurDioxideConcentrationConverter(BaseUnitConverter):
|
||||
"""Convert sulphur dioxide ratio to mass per volume."""
|
||||
|
||||
UNIT_CLASS = "sulphur_dioxide"
|
||||
_UNIT_CONVERSION: dict[str | None, float] = {
|
||||
CONCENTRATION_PARTS_PER_BILLION: 1e9,
|
||||
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER: (
|
||||
_SULPHUR_DIOXIDE_MOLAR_MASS / _AMBIENT_IDEAL_GAS_MOLAR_VOLUME * 1e6
|
||||
),
|
||||
}
|
||||
VALID_UNITS = {
|
||||
CONCENTRATION_PARTS_PER_BILLION,
|
||||
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
}
|
||||
|
||||
|
||||
class DataRateConverter(BaseUnitConverter):
|
||||
"""Utility to convert data rate values."""
|
||||
|
||||
|
||||
2
requirements_all.txt
generated
2
requirements_all.txt
generated
@@ -3170,7 +3170,7 @@ wallbox==0.9.0
|
||||
watchdog==6.0.0
|
||||
|
||||
# homeassistant.components.waterfurnace
|
||||
waterfurnace==1.2.0
|
||||
waterfurnace==1.4.0
|
||||
|
||||
# homeassistant.components.watergate
|
||||
watergate-local-api==2025.1.0
|
||||
|
||||
@@ -100,13 +100,6 @@ async def target_entities(
|
||||
suggested_object_id=f"device_{domain}",
|
||||
device_id=device.id,
|
||||
)
|
||||
entity_reg.async_get_or_create(
|
||||
domain=domain,
|
||||
platform="test",
|
||||
unique_id=f"{domain}_device2",
|
||||
suggested_object_id=f"device2_{domain}",
|
||||
device_id=device.id,
|
||||
)
|
||||
entity_reg.async_get_or_create(
|
||||
domain=domain,
|
||||
platform="test",
|
||||
@@ -137,11 +130,9 @@ async def target_entities(
|
||||
return {
|
||||
"included": [
|
||||
f"{domain}.standalone_{domain}",
|
||||
f"{domain}.standalone2_{domain}",
|
||||
f"{domain}.label_{domain}",
|
||||
f"{domain}.area_{domain}",
|
||||
f"{domain}.device_{domain}",
|
||||
f"{domain}.device2_{domain}",
|
||||
],
|
||||
"excluded": [
|
||||
f"{domain}.standalone_{domain}_excluded",
|
||||
@@ -159,22 +150,17 @@ def parametrize_target_entities(domain: str) -> list[tuple[dict, str, int]]:
|
||||
"""
|
||||
return [
|
||||
(
|
||||
{
|
||||
CONF_ENTITY_ID: [
|
||||
f"{domain}.standalone_{domain}",
|
||||
f"{domain}.standalone2_{domain}",
|
||||
]
|
||||
},
|
||||
{CONF_ENTITY_ID: f"{domain}.standalone_{domain}"},
|
||||
f"{domain}.standalone_{domain}",
|
||||
2,
|
||||
1,
|
||||
),
|
||||
({ATTR_LABEL_ID: "test_label"}, f"{domain}.label_{domain}", 3),
|
||||
({ATTR_AREA_ID: "test_area"}, f"{domain}.area_{domain}", 3),
|
||||
({ATTR_FLOOR_ID: "test_floor"}, f"{domain}.area_{domain}", 3),
|
||||
({ATTR_LABEL_ID: "test_label"}, f"{domain}.device_{domain}", 3),
|
||||
({ATTR_AREA_ID: "test_area"}, f"{domain}.device_{domain}", 3),
|
||||
({ATTR_FLOOR_ID: "test_floor"}, f"{domain}.device_{domain}", 3),
|
||||
({ATTR_DEVICE_ID: "test_device"}, f"{domain}.device_{domain}", 2),
|
||||
({ATTR_LABEL_ID: "test_label"}, f"{domain}.label_{domain}", 2),
|
||||
({ATTR_AREA_ID: "test_area"}, f"{domain}.area_{domain}", 2),
|
||||
({ATTR_FLOOR_ID: "test_floor"}, f"{domain}.area_{domain}", 2),
|
||||
({ATTR_LABEL_ID: "test_label"}, f"{domain}.device_{domain}", 2),
|
||||
({ATTR_AREA_ID: "test_area"}, f"{domain}.device_{domain}", 2),
|
||||
({ATTR_FLOOR_ID: "test_floor"}, f"{domain}.device_{domain}", 2),
|
||||
({ATTR_DEVICE_ID: "test_device"}, f"{domain}.device_{domain}", 1),
|
||||
]
|
||||
|
||||
|
||||
@@ -198,19 +184,18 @@ class ConditionStateDescription(TypedDict):
|
||||
|
||||
included: _StateDescription # State for entities meant to be targeted
|
||||
excluded: _StateDescription # State for entities not meant to be targeted
|
||||
state_valid: bool # False if the state of the included entities is missing (None), unavailable or unknown
|
||||
|
||||
condition_true: bool # If the condition is expected to evaluate to true
|
||||
condition_true_first_entity: bool # If the condition is expected to evaluate to true for the first targeted entity
|
||||
|
||||
|
||||
def _parametrize_condition_states(
|
||||
def parametrize_condition_states(
|
||||
*,
|
||||
condition: str,
|
||||
condition_options: dict[str, Any] | None = None,
|
||||
target_states: list[str | None | tuple[str | None, dict]],
|
||||
other_states: list[str | None | tuple[str | None, dict]],
|
||||
additional_attributes: dict | None,
|
||||
condition_true_if_invalid: bool,
|
||||
additional_attributes: dict | None = None,
|
||||
) -> list[tuple[str, dict[str, Any], list[ConditionStateDescription]]]:
|
||||
"""Parametrize states and expected condition evaluations.
|
||||
|
||||
@@ -227,7 +212,7 @@ def _parametrize_condition_states(
|
||||
def state_with_attributes(
|
||||
state: str | None | tuple[str | None, dict],
|
||||
condition_true: bool,
|
||||
condition_true_first_entity: bool,
|
||||
state_valid: bool,
|
||||
) -> ConditionStateDescription:
|
||||
"""Return ConditionStateDescription dict."""
|
||||
if isinstance(state, str) or state is None:
|
||||
@@ -241,7 +226,7 @@ def _parametrize_condition_states(
|
||||
"attributes": {},
|
||||
},
|
||||
"condition_true": condition_true,
|
||||
"condition_true_first_entity": condition_true_first_entity,
|
||||
"state_valid": state_valid,
|
||||
}
|
||||
return {
|
||||
"included": {
|
||||
@@ -253,7 +238,7 @@ def _parametrize_condition_states(
|
||||
"attributes": state[1],
|
||||
},
|
||||
"condition_true": condition_true,
|
||||
"condition_true_first_entity": condition_true_first_entity,
|
||||
"state_valid": state_valid,
|
||||
}
|
||||
|
||||
return [
|
||||
@@ -262,19 +247,11 @@ def _parametrize_condition_states(
|
||||
condition_options,
|
||||
list(
|
||||
itertools.chain(
|
||||
(state_with_attributes(None, condition_true_if_invalid, True),),
|
||||
(state_with_attributes(None, False, False),),
|
||||
(state_with_attributes(STATE_UNAVAILABLE, False, False),),
|
||||
(state_with_attributes(STATE_UNKNOWN, False, False),),
|
||||
(
|
||||
state_with_attributes(
|
||||
STATE_UNAVAILABLE, condition_true_if_invalid, True
|
||||
),
|
||||
),
|
||||
(
|
||||
state_with_attributes(
|
||||
STATE_UNKNOWN, condition_true_if_invalid, True
|
||||
),
|
||||
),
|
||||
(
|
||||
state_with_attributes(other_state, False, False)
|
||||
state_with_attributes(other_state, False, True)
|
||||
for other_state in other_states
|
||||
),
|
||||
),
|
||||
@@ -286,8 +263,8 @@ def _parametrize_condition_states(
|
||||
condition,
|
||||
condition_options,
|
||||
[
|
||||
state_with_attributes(other_states[0], False, False),
|
||||
state_with_attributes(target_state, True, False),
|
||||
state_with_attributes(other_states[0], False, True),
|
||||
state_with_attributes(target_state, True, True),
|
||||
],
|
||||
)
|
||||
for target_state in target_states
|
||||
@@ -295,60 +272,6 @@ def _parametrize_condition_states(
|
||||
]
|
||||
|
||||
|
||||
def parametrize_condition_states_any(
|
||||
*,
|
||||
condition: str,
|
||||
condition_options: dict[str, Any] | None = None,
|
||||
target_states: list[str | None | tuple[str | None, dict]],
|
||||
other_states: list[str | None | tuple[str | None, dict]],
|
||||
additional_attributes: dict | None = None,
|
||||
) -> list[tuple[str, dict[str, Any], list[ConditionStateDescription]]]:
|
||||
"""Parametrize states and expected condition evaluations.
|
||||
|
||||
The target_states and other_states iterables are either iterables of
|
||||
states or iterables of (state, attributes) tuples.
|
||||
|
||||
Returns a list of tuples with (condition, condition options, list of states),
|
||||
where states is a list of ConditionStateDescription dicts.
|
||||
"""
|
||||
|
||||
return _parametrize_condition_states(
|
||||
condition=condition,
|
||||
condition_options=condition_options,
|
||||
target_states=target_states,
|
||||
other_states=other_states,
|
||||
additional_attributes=additional_attributes,
|
||||
condition_true_if_invalid=False,
|
||||
)
|
||||
|
||||
|
||||
def parametrize_condition_states_all(
|
||||
*,
|
||||
condition: str,
|
||||
condition_options: dict[str, Any] | None = None,
|
||||
target_states: list[str | None | tuple[str | None, dict]],
|
||||
other_states: list[str | None | tuple[str | None, dict]],
|
||||
additional_attributes: dict | None = None,
|
||||
) -> list[tuple[str, dict[str, Any], list[ConditionStateDescription]]]:
|
||||
"""Parametrize states and expected condition evaluations.
|
||||
|
||||
The target_states and other_states iterables are either iterables of
|
||||
states or iterables of (state, attributes) tuples.
|
||||
|
||||
Returns a list of tuples with (condition, condition options, list of states),
|
||||
where states is a list of ConditionStateDescription dicts.
|
||||
"""
|
||||
|
||||
return _parametrize_condition_states(
|
||||
condition=condition,
|
||||
condition_options=condition_options,
|
||||
target_states=target_states,
|
||||
other_states=other_states,
|
||||
additional_attributes=additional_attributes,
|
||||
condition_true_if_invalid=True,
|
||||
)
|
||||
|
||||
|
||||
def parametrize_trigger_states(
|
||||
*,
|
||||
trigger: str,
|
||||
|
||||
@@ -16,8 +16,7 @@ from tests.components import (
|
||||
assert_condition_gated_by_labs_flag,
|
||||
create_target_condition,
|
||||
other_states,
|
||||
parametrize_condition_states_all,
|
||||
parametrize_condition_states_any,
|
||||
parametrize_condition_states,
|
||||
parametrize_target_entities,
|
||||
set_or_remove_state,
|
||||
target_entities,
|
||||
@@ -62,7 +61,7 @@ async def test_alarm_control_panel_conditions_gated_by_labs_flag(
|
||||
@pytest.mark.parametrize(
|
||||
("condition", "condition_options", "states"),
|
||||
[
|
||||
*parametrize_condition_states_any(
|
||||
*parametrize_condition_states(
|
||||
condition="alarm_control_panel.is_armed",
|
||||
target_states=[
|
||||
AlarmControlPanelState.ARMED_AWAY,
|
||||
@@ -79,7 +78,7 @@ async def test_alarm_control_panel_conditions_gated_by_labs_flag(
|
||||
AlarmControlPanelState.TRIGGERED,
|
||||
],
|
||||
),
|
||||
*parametrize_condition_states_any(
|
||||
*parametrize_condition_states(
|
||||
condition="alarm_control_panel.is_armed_away",
|
||||
target_states=[AlarmControlPanelState.ARMED_AWAY],
|
||||
other_states=other_states(AlarmControlPanelState.ARMED_AWAY),
|
||||
@@ -87,7 +86,7 @@ async def test_alarm_control_panel_conditions_gated_by_labs_flag(
|
||||
ATTR_SUPPORTED_FEATURES: AlarmControlPanelEntityFeature.ARM_AWAY
|
||||
},
|
||||
),
|
||||
*parametrize_condition_states_any(
|
||||
*parametrize_condition_states(
|
||||
condition="alarm_control_panel.is_armed_home",
|
||||
target_states=[AlarmControlPanelState.ARMED_HOME],
|
||||
other_states=other_states(AlarmControlPanelState.ARMED_HOME),
|
||||
@@ -95,7 +94,7 @@ async def test_alarm_control_panel_conditions_gated_by_labs_flag(
|
||||
ATTR_SUPPORTED_FEATURES: AlarmControlPanelEntityFeature.ARM_HOME
|
||||
},
|
||||
),
|
||||
*parametrize_condition_states_any(
|
||||
*parametrize_condition_states(
|
||||
condition="alarm_control_panel.is_armed_night",
|
||||
target_states=[AlarmControlPanelState.ARMED_NIGHT],
|
||||
other_states=other_states(AlarmControlPanelState.ARMED_NIGHT),
|
||||
@@ -103,7 +102,7 @@ async def test_alarm_control_panel_conditions_gated_by_labs_flag(
|
||||
ATTR_SUPPORTED_FEATURES: AlarmControlPanelEntityFeature.ARM_NIGHT
|
||||
},
|
||||
),
|
||||
*parametrize_condition_states_any(
|
||||
*parametrize_condition_states(
|
||||
condition="alarm_control_panel.is_armed_vacation",
|
||||
target_states=[AlarmControlPanelState.ARMED_VACATION],
|
||||
other_states=other_states(AlarmControlPanelState.ARMED_VACATION),
|
||||
@@ -111,12 +110,12 @@ async def test_alarm_control_panel_conditions_gated_by_labs_flag(
|
||||
ATTR_SUPPORTED_FEATURES: AlarmControlPanelEntityFeature.ARM_VACATION
|
||||
},
|
||||
),
|
||||
*parametrize_condition_states_any(
|
||||
*parametrize_condition_states(
|
||||
condition="alarm_control_panel.is_disarmed",
|
||||
target_states=[AlarmControlPanelState.DISARMED],
|
||||
other_states=other_states(AlarmControlPanelState.DISARMED),
|
||||
),
|
||||
*parametrize_condition_states_any(
|
||||
*parametrize_condition_states(
|
||||
condition="alarm_control_panel.is_triggered",
|
||||
target_states=[AlarmControlPanelState.TRIGGERED],
|
||||
other_states=other_states(AlarmControlPanelState.TRIGGERED),
|
||||
@@ -169,7 +168,7 @@ async def test_alarm_control_panel_state_condition_behavior_any(
|
||||
@pytest.mark.parametrize(
|
||||
("condition", "condition_options", "states"),
|
||||
[
|
||||
*parametrize_condition_states_all(
|
||||
*parametrize_condition_states(
|
||||
condition="alarm_control_panel.is_armed",
|
||||
target_states=[
|
||||
AlarmControlPanelState.ARMED_AWAY,
|
||||
@@ -186,7 +185,7 @@ async def test_alarm_control_panel_state_condition_behavior_any(
|
||||
AlarmControlPanelState.TRIGGERED,
|
||||
],
|
||||
),
|
||||
*parametrize_condition_states_all(
|
||||
*parametrize_condition_states(
|
||||
condition="alarm_control_panel.is_armed_away",
|
||||
target_states=[AlarmControlPanelState.ARMED_AWAY],
|
||||
other_states=other_states(AlarmControlPanelState.ARMED_AWAY),
|
||||
@@ -194,7 +193,7 @@ async def test_alarm_control_panel_state_condition_behavior_any(
|
||||
ATTR_SUPPORTED_FEATURES: AlarmControlPanelEntityFeature.ARM_AWAY
|
||||
},
|
||||
),
|
||||
*parametrize_condition_states_all(
|
||||
*parametrize_condition_states(
|
||||
condition="alarm_control_panel.is_armed_home",
|
||||
target_states=[AlarmControlPanelState.ARMED_HOME],
|
||||
other_states=other_states(AlarmControlPanelState.ARMED_HOME),
|
||||
@@ -202,7 +201,7 @@ async def test_alarm_control_panel_state_condition_behavior_any(
|
||||
ATTR_SUPPORTED_FEATURES: AlarmControlPanelEntityFeature.ARM_HOME
|
||||
},
|
||||
),
|
||||
*parametrize_condition_states_all(
|
||||
*parametrize_condition_states(
|
||||
condition="alarm_control_panel.is_armed_night",
|
||||
target_states=[AlarmControlPanelState.ARMED_NIGHT],
|
||||
other_states=other_states(AlarmControlPanelState.ARMED_NIGHT),
|
||||
@@ -210,7 +209,7 @@ async def test_alarm_control_panel_state_condition_behavior_any(
|
||||
ATTR_SUPPORTED_FEATURES: AlarmControlPanelEntityFeature.ARM_NIGHT
|
||||
},
|
||||
),
|
||||
*parametrize_condition_states_all(
|
||||
*parametrize_condition_states(
|
||||
condition="alarm_control_panel.is_armed_vacation",
|
||||
target_states=[AlarmControlPanelState.ARMED_VACATION],
|
||||
other_states=other_states(AlarmControlPanelState.ARMED_VACATION),
|
||||
@@ -218,12 +217,12 @@ async def test_alarm_control_panel_state_condition_behavior_any(
|
||||
ATTR_SUPPORTED_FEATURES: AlarmControlPanelEntityFeature.ARM_VACATION
|
||||
},
|
||||
),
|
||||
*parametrize_condition_states_all(
|
||||
*parametrize_condition_states(
|
||||
condition="alarm_control_panel.is_disarmed",
|
||||
target_states=[AlarmControlPanelState.DISARMED],
|
||||
other_states=other_states(AlarmControlPanelState.DISARMED),
|
||||
),
|
||||
*parametrize_condition_states_all(
|
||||
*parametrize_condition_states(
|
||||
condition="alarm_control_panel.is_triggered",
|
||||
target_states=[AlarmControlPanelState.TRIGGERED],
|
||||
other_states=other_states(AlarmControlPanelState.TRIGGERED),
|
||||
@@ -260,10 +259,17 @@ async def test_alarm_control_panel_state_condition_behavior_all(
|
||||
|
||||
set_or_remove_state(hass, entity_id, included_state)
|
||||
await hass.async_block_till_done()
|
||||
assert condition(hass) == state["condition_true_first_entity"]
|
||||
# The condition passes if all entities are either in a target state or invalid
|
||||
assert condition(hass) == (
|
||||
(not state["state_valid"])
|
||||
or (state["condition_true"] and entities_in_target == 1)
|
||||
)
|
||||
|
||||
for other_entity_id in other_entity_ids:
|
||||
set_or_remove_state(hass, other_entity_id, included_state)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert condition(hass) == state["condition_true"]
|
||||
# The condition passes if all entities are either in a target state or invalid
|
||||
assert condition(hass) == (
|
||||
(not state["state_valid"]) or state["condition_true"]
|
||||
)
|
||||
|
||||
@@ -12,8 +12,7 @@ from tests.components import (
|
||||
assert_condition_gated_by_labs_flag,
|
||||
create_target_condition,
|
||||
other_states,
|
||||
parametrize_condition_states_all,
|
||||
parametrize_condition_states_any,
|
||||
parametrize_condition_states,
|
||||
parametrize_target_entities,
|
||||
set_or_remove_state,
|
||||
target_entities,
|
||||
@@ -55,22 +54,22 @@ async def test_assist_satellite_conditions_gated_by_labs_flag(
|
||||
@pytest.mark.parametrize(
|
||||
("condition", "condition_options", "states"),
|
||||
[
|
||||
*parametrize_condition_states_any(
|
||||
*parametrize_condition_states(
|
||||
condition="assist_satellite.is_idle",
|
||||
target_states=[AssistSatelliteState.IDLE],
|
||||
other_states=other_states(AssistSatelliteState.IDLE),
|
||||
),
|
||||
*parametrize_condition_states_any(
|
||||
*parametrize_condition_states(
|
||||
condition="assist_satellite.is_listening",
|
||||
target_states=[AssistSatelliteState.LISTENING],
|
||||
other_states=other_states(AssistSatelliteState.LISTENING),
|
||||
),
|
||||
*parametrize_condition_states_any(
|
||||
*parametrize_condition_states(
|
||||
condition="assist_satellite.is_processing",
|
||||
target_states=[AssistSatelliteState.PROCESSING],
|
||||
other_states=other_states(AssistSatelliteState.PROCESSING),
|
||||
),
|
||||
*parametrize_condition_states_any(
|
||||
*parametrize_condition_states(
|
||||
condition="assist_satellite.is_responding",
|
||||
target_states=[AssistSatelliteState.RESPONDING],
|
||||
other_states=other_states(AssistSatelliteState.RESPONDING),
|
||||
@@ -123,22 +122,22 @@ async def test_assist_satellite_state_condition_behavior_any(
|
||||
@pytest.mark.parametrize(
|
||||
("condition", "condition_options", "states"),
|
||||
[
|
||||
*parametrize_condition_states_all(
|
||||
*parametrize_condition_states(
|
||||
condition="assist_satellite.is_idle",
|
||||
target_states=[AssistSatelliteState.IDLE],
|
||||
other_states=other_states(AssistSatelliteState.IDLE),
|
||||
),
|
||||
*parametrize_condition_states_all(
|
||||
*parametrize_condition_states(
|
||||
condition="assist_satellite.is_listening",
|
||||
target_states=[AssistSatelliteState.LISTENING],
|
||||
other_states=other_states(AssistSatelliteState.LISTENING),
|
||||
),
|
||||
*parametrize_condition_states_all(
|
||||
*parametrize_condition_states(
|
||||
condition="assist_satellite.is_processing",
|
||||
target_states=[AssistSatelliteState.PROCESSING],
|
||||
other_states=other_states(AssistSatelliteState.PROCESSING),
|
||||
),
|
||||
*parametrize_condition_states_all(
|
||||
*parametrize_condition_states(
|
||||
condition="assist_satellite.is_responding",
|
||||
target_states=[AssistSatelliteState.RESPONDING],
|
||||
other_states=other_states(AssistSatelliteState.RESPONDING),
|
||||
@@ -175,10 +174,17 @@ async def test_assist_satellite_state_condition_behavior_all(
|
||||
|
||||
set_or_remove_state(hass, entity_id, included_state)
|
||||
await hass.async_block_till_done()
|
||||
assert condition(hass) == state["condition_true_first_entity"]
|
||||
# The condition passes if all entities are either in a target state or invalid
|
||||
assert condition(hass) == (
|
||||
(not state["state_valid"])
|
||||
or (state["condition_true"] and entities_in_target == 1)
|
||||
)
|
||||
|
||||
for other_entity_id in other_entity_ids:
|
||||
set_or_remove_state(hass, other_entity_id, included_state)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert condition(hass) == state["condition_true"]
|
||||
# The condition passes if all entities are either in a target state or invalid
|
||||
assert condition(hass) == (
|
||||
(not state["state_valid"]) or state["condition_true"]
|
||||
)
|
||||
|
||||
@@ -11,8 +11,7 @@ from tests.components import (
|
||||
ConditionStateDescription,
|
||||
assert_condition_gated_by_labs_flag,
|
||||
create_target_condition,
|
||||
parametrize_condition_states_all,
|
||||
parametrize_condition_states_any,
|
||||
parametrize_condition_states,
|
||||
parametrize_target_entities,
|
||||
set_or_remove_state,
|
||||
target_entities,
|
||||
@@ -58,12 +57,12 @@ async def test_fan_conditions_gated_by_labs_flag(
|
||||
@pytest.mark.parametrize(
|
||||
("condition", "condition_options", "states"),
|
||||
[
|
||||
*parametrize_condition_states_any(
|
||||
*parametrize_condition_states(
|
||||
condition="fan.is_on",
|
||||
target_states=[STATE_ON],
|
||||
other_states=[STATE_OFF],
|
||||
),
|
||||
*parametrize_condition_states_any(
|
||||
*parametrize_condition_states(
|
||||
condition="fan.is_off",
|
||||
target_states=[STATE_OFF],
|
||||
other_states=[STATE_ON],
|
||||
@@ -124,12 +123,12 @@ async def test_fan_state_condition_behavior_any(
|
||||
@pytest.mark.parametrize(
|
||||
("condition", "condition_options", "states"),
|
||||
[
|
||||
*parametrize_condition_states_all(
|
||||
*parametrize_condition_states(
|
||||
condition="fan.is_on",
|
||||
target_states=[STATE_ON],
|
||||
other_states=[STATE_OFF],
|
||||
),
|
||||
*parametrize_condition_states_all(
|
||||
*parametrize_condition_states(
|
||||
condition="fan.is_off",
|
||||
target_states=[STATE_OFF],
|
||||
other_states=[STATE_ON],
|
||||
@@ -170,10 +169,17 @@ async def test_fan_state_condition_behavior_all(
|
||||
|
||||
set_or_remove_state(hass, entity_id, included_state)
|
||||
await hass.async_block_till_done()
|
||||
assert condition(hass) == state["condition_true_first_entity"]
|
||||
# The condition passes if all entities are either in a target state or invalid
|
||||
assert condition(hass) == (
|
||||
(not state["state_valid"])
|
||||
or (state["condition_true"] and entities_in_target == 1)
|
||||
)
|
||||
|
||||
for other_entity_id in other_entity_ids:
|
||||
set_or_remove_state(hass, other_entity_id, included_state)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert condition(hass) == state["condition_true"]
|
||||
# The condition passes if all entities are either in a target state or invalid
|
||||
assert condition(hass) == (
|
||||
(not state["state_valid"]) or state["condition_true"]
|
||||
)
|
||||
|
||||
@@ -11,8 +11,7 @@ from tests.components import (
|
||||
ConditionStateDescription,
|
||||
assert_condition_gated_by_labs_flag,
|
||||
create_target_condition,
|
||||
parametrize_condition_states_all,
|
||||
parametrize_condition_states_any,
|
||||
parametrize_condition_states,
|
||||
parametrize_target_entities,
|
||||
set_or_remove_state,
|
||||
target_entities,
|
||||
@@ -58,12 +57,12 @@ async def test_light_conditions_gated_by_labs_flag(
|
||||
@pytest.mark.parametrize(
|
||||
("condition", "condition_options", "states"),
|
||||
[
|
||||
*parametrize_condition_states_any(
|
||||
*parametrize_condition_states(
|
||||
condition="light.is_on",
|
||||
target_states=[STATE_ON],
|
||||
other_states=[STATE_OFF],
|
||||
),
|
||||
*parametrize_condition_states_any(
|
||||
*parametrize_condition_states(
|
||||
condition="light.is_off",
|
||||
target_states=[STATE_OFF],
|
||||
other_states=[STATE_ON],
|
||||
@@ -124,12 +123,12 @@ async def test_light_state_condition_behavior_any(
|
||||
@pytest.mark.parametrize(
|
||||
("condition", "condition_options", "states"),
|
||||
[
|
||||
*parametrize_condition_states_all(
|
||||
*parametrize_condition_states(
|
||||
condition="light.is_on",
|
||||
target_states=[STATE_ON],
|
||||
other_states=[STATE_OFF],
|
||||
),
|
||||
*parametrize_condition_states_all(
|
||||
*parametrize_condition_states(
|
||||
condition="light.is_off",
|
||||
target_states=[STATE_OFF],
|
||||
other_states=[STATE_ON],
|
||||
@@ -170,10 +169,17 @@ async def test_light_state_condition_behavior_all(
|
||||
|
||||
set_or_remove_state(hass, entity_id, included_state)
|
||||
await hass.async_block_till_done()
|
||||
assert condition(hass) == state["condition_true_first_entity"]
|
||||
# The condition passes if all entities are either in a target state or invalid
|
||||
assert condition(hass) == (
|
||||
(not state["state_valid"])
|
||||
or (state["condition_true"] and entities_in_target == 1)
|
||||
)
|
||||
|
||||
for other_entity_id in other_entity_ids:
|
||||
set_or_remove_state(hass, other_entity_id, included_state)
|
||||
await hass.async_block_till_done()
|
||||
|
||||
assert condition(hass) == state["condition_true"]
|
||||
# The condition passes if all entities are either in a target state or invalid
|
||||
assert condition(hass) == (
|
||||
(not state["state_valid"]) or state["condition_true"]
|
||||
)
|
||||
|
||||
@@ -103,7 +103,7 @@ async def test_ingress_host(
|
||||
result = await hass.config_entries.flow.async_configure(
|
||||
result["flow_id"],
|
||||
{
|
||||
CONF_HOST: "http://homeassistant/hassio/ingress/db21ed7f_mealie",
|
||||
CONF_HOST: "http://homeassistant/app/db21ed7f_mealie",
|
||||
CONF_API_TOKEN: "token",
|
||||
},
|
||||
)
|
||||
|
||||
@@ -3118,7 +3118,6 @@ def test_device_class_converters_are_complete() -> None:
|
||||
SensorDeviceClass.PM4,
|
||||
SensorDeviceClass.SIGNAL_STRENGTH,
|
||||
SensorDeviceClass.SOUND_PRESSURE,
|
||||
SensorDeviceClass.SULPHUR_DIOXIDE,
|
||||
SensorDeviceClass.TIMESTAMP,
|
||||
SensorDeviceClass.WIND_DIRECTION,
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ from homeassistant.util.unit_conversion import (
|
||||
ReactiveEnergyConverter,
|
||||
ReactivePowerConverter,
|
||||
SpeedConverter,
|
||||
SulphurDioxideConcentrationConverter,
|
||||
TemperatureConverter,
|
||||
TemperatureDeltaConverter,
|
||||
UnitlessRatioConverter,
|
||||
@@ -102,6 +103,7 @@ _ALL_CONVERTERS: dict[type[BaseUnitConverter], list[str | None]] = {
|
||||
EnergyDistanceConverter,
|
||||
VolumeConverter,
|
||||
VolumeFlowRateConverter,
|
||||
SulphurDioxideConcentrationConverter,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -175,6 +177,11 @@ _GET_UNIT_RATIO: dict[type[BaseUnitConverter], tuple[str | None, str | None, flo
|
||||
UnitOfSpeed.MILES_PER_HOUR,
|
||||
1.609343,
|
||||
),
|
||||
SulphurDioxideConcentrationConverter: (
|
||||
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
CONCENTRATION_PARTS_PER_BILLION,
|
||||
2.6633,
|
||||
),
|
||||
TemperatureConverter: (
|
||||
UnitOfTemperature.CELSIUS,
|
||||
UnitOfTemperature.FAHRENHEIT,
|
||||
@@ -846,6 +853,20 @@ _CONVERTED_VALUE: dict[
|
||||
# float(round(((20.7 m/s / 0.836) ** 2) ** (1 / 3))) = 8.0Bft
|
||||
(20.7, UnitOfSpeed.METERS_PER_SECOND, 8.0, UnitOfSpeed.BEAUFORT),
|
||||
],
|
||||
SulphurDioxideConcentrationConverter: [
|
||||
(
|
||||
1,
|
||||
CONCENTRATION_PARTS_PER_BILLION,
|
||||
2.6633,
|
||||
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
),
|
||||
(
|
||||
120,
|
||||
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
45.056879,
|
||||
CONCENTRATION_PARTS_PER_BILLION,
|
||||
),
|
||||
],
|
||||
TemperatureConverter: [
|
||||
(100, UnitOfTemperature.CELSIUS, 212, UnitOfTemperature.FAHRENHEIT),
|
||||
(100, UnitOfTemperature.CELSIUS, 373.15, UnitOfTemperature.KELVIN),
|
||||
|
||||
Reference in New Issue
Block a user