Add additonal number entities to La Marzocco (#108258)

pull/110463/head
Josef Zweck 2024-02-13 09:47:39 +01:00 committed by GitHub
parent 545a34a849
commit ee25f6b960
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 1004 additions and 4 deletions

View File

@ -25,9 +25,21 @@
"coffee_temp": {
"default": "mdi:thermometer-water"
},
"dose": {
"default": "mdi:weight-kilogram"
},
"steam_temp": {
"default": "mdi:thermometer-water"
},
"prebrew_off": {
"default": "mdi:water-off"
},
"prebrew_on": {
"default": "mdi:water"
},
"preinfusion_off": {
"default": "mdi:water"
},
"tea_water_duration": {
"default": "mdi:timer-sand"
}

View File

@ -5,7 +5,7 @@ from dataclasses import dataclass
from typing import Any
from lmcloud import LMCloud as LaMarzoccoClient
from lmcloud.const import LaMarzoccoModel
from lmcloud.const import KEYS_PER_MODEL, LaMarzoccoModel
from homeassistant.components.number import (
NumberDeviceClass,
@ -16,6 +16,7 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
PRECISION_TENTHS,
PRECISION_WHOLE,
EntityCategory,
UnitOfTemperature,
UnitOfTime,
)
@ -40,6 +41,19 @@ class LaMarzoccoNumberEntityDescription(
]
@dataclass(frozen=True, kw_only=True)
class LaMarzoccoKeyNumberEntityDescription(
LaMarzoccoEntityDescription,
NumberEntityDescription,
):
"""Description of an La Marzocco number entity with keys."""
native_value_fn: Callable[[LaMarzoccoClient, int], float | int]
set_value_fn: Callable[
[LaMarzoccoClient, float | int, int], Coroutine[Any, Any, bool]
]
ENTITIES: tuple[LaMarzoccoNumberEntityDescription, ...] = (
LaMarzoccoNumberEntityDescription(
key="coffee_temp",
@ -89,6 +103,103 @@ ENTITIES: tuple[LaMarzoccoNumberEntityDescription, ...] = (
)
async def _set_prebrew_on(
lm: LaMarzoccoClient,
value: float,
key: int,
) -> bool:
return await lm.configure_prebrew(
on_time=int(value * 1000),
off_time=int(lm.current_status[f"prebrewing_toff_k{key}"] * 1000),
key=key,
)
async def _set_prebrew_off(
lm: LaMarzoccoClient,
value: float,
key: int,
) -> bool:
return await lm.configure_prebrew(
on_time=int(lm.current_status[f"prebrewing_ton_k{key}"] * 1000),
off_time=int(value * 1000),
key=key,
)
async def _set_preinfusion(
lm: LaMarzoccoClient,
value: float,
key: int,
) -> bool:
return await lm.configure_prebrew(
off_time=int(value * 1000),
key=key,
)
KEY_ENTITIES: tuple[LaMarzoccoKeyNumberEntityDescription, ...] = (
LaMarzoccoKeyNumberEntityDescription(
key="prebrew_off",
translation_key="prebrew_off",
device_class=NumberDeviceClass.DURATION,
native_unit_of_measurement=UnitOfTime.SECONDS,
native_step=PRECISION_TENTHS,
native_min_value=1,
native_max_value=10,
entity_category=EntityCategory.CONFIG,
set_value_fn=_set_prebrew_off,
native_value_fn=lambda lm, key: lm.current_status[f"prebrewing_ton_k{key}"],
available_fn=lambda lm: lm.current_status["enable_prebrewing"],
supported_fn=lambda coordinator: coordinator.lm.model_name
!= LaMarzoccoModel.GS3_MP,
),
LaMarzoccoKeyNumberEntityDescription(
key="prebrew_on",
translation_key="prebrew_on",
device_class=NumberDeviceClass.DURATION,
native_unit_of_measurement=UnitOfTime.SECONDS,
native_step=PRECISION_TENTHS,
native_min_value=2,
native_max_value=10,
entity_category=EntityCategory.CONFIG,
set_value_fn=_set_prebrew_on,
native_value_fn=lambda lm, key: lm.current_status[f"prebrewing_toff_k{key}"],
available_fn=lambda lm: lm.current_status["enable_prebrewing"],
supported_fn=lambda coordinator: coordinator.lm.model_name
!= LaMarzoccoModel.GS3_MP,
),
LaMarzoccoKeyNumberEntityDescription(
key="preinfusion_off",
translation_key="preinfusion_off",
device_class=NumberDeviceClass.DURATION,
native_unit_of_measurement=UnitOfTime.SECONDS,
native_step=PRECISION_TENTHS,
native_min_value=2,
native_max_value=29,
entity_category=EntityCategory.CONFIG,
set_value_fn=_set_preinfusion,
native_value_fn=lambda lm, key: lm.current_status[f"preinfusion_k{key}"],
available_fn=lambda lm: lm.current_status["enable_preinfusion"],
supported_fn=lambda coordinator: coordinator.lm.model_name
!= LaMarzoccoModel.GS3_MP,
),
LaMarzoccoKeyNumberEntityDescription(
key="dose",
translation_key="dose",
native_unit_of_measurement="ticks",
native_step=PRECISION_WHOLE,
native_min_value=0,
native_max_value=999,
entity_category=EntityCategory.CONFIG,
set_value_fn=lambda lm, ticks, key: lm.set_dose(key=key, value=int(ticks)),
native_value_fn=lambda lm, key: lm.current_status[f"dose_k{key}"],
supported_fn=lambda coordinator: coordinator.lm.model_name
== LaMarzoccoModel.GS3_AV,
),
)
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
@ -103,6 +214,17 @@ async def async_setup_entry(
if description.supported_fn(coordinator)
)
entities: list[LaMarzoccoKeyNumberEntity] = []
for description in KEY_ENTITIES:
if description.supported_fn(coordinator):
num_keys = KEYS_PER_MODEL[coordinator.lm.model_name]
for key in range(min(num_keys, 1), num_keys + 1):
entities.append(
LaMarzoccoKeyNumberEntity(coordinator, description, key)
)
async_add_entities(entities)
class LaMarzoccoNumberEntity(LaMarzoccoEntity, NumberEntity):
"""La Marzocco number entity."""
@ -118,3 +240,42 @@ class LaMarzoccoNumberEntity(LaMarzoccoEntity, NumberEntity):
"""Set the value."""
await self.entity_description.set_value_fn(self.coordinator, value)
self.async_write_ha_state()
class LaMarzoccoKeyNumberEntity(LaMarzoccoEntity, NumberEntity):
"""Number representing espresso machine with key support."""
entity_description: LaMarzoccoKeyNumberEntityDescription
def __init__(
self,
coordinator: LaMarzoccoUpdateCoordinator,
description: LaMarzoccoKeyNumberEntityDescription,
pyhsical_key: int,
) -> None:
"""Initialize the entity."""
super().__init__(coordinator, description)
# Physical Key on the machine the entity represents.
if pyhsical_key == 0:
pyhsical_key = 1
else:
self._attr_translation_key = f"{description.translation_key}_key"
self._attr_translation_placeholders = {"key": str(pyhsical_key)}
self._attr_unique_id = f"{super()._attr_unique_id}_key{pyhsical_key}"
self._attr_entity_registry_enabled_default = False
self.pyhsical_key = pyhsical_key
@property
def native_value(self) -> float:
"""Return the current value."""
return self.entity_description.native_value_fn(
self.coordinator.lm, self.pyhsical_key
)
async def async_set_native_value(self, value: float) -> None:
"""Set the value."""
await self.entity_description.set_value_fn(
self.coordinator.lm, value, self.pyhsical_key
)
self.async_write_ha_state()

View File

@ -60,6 +60,27 @@
"coffee_temp": {
"name": "Coffee target temperature"
},
"dose_key": {
"name": "Dose Key {key}"
},
"prebrew_on": {
"name": "Prebrew on time"
},
"prebrew_on_key": {
"name": "Prebrew on time Key {key}"
},
"prebrew_off": {
"name": "Prebrew off time"
},
"prebrew_off_key": {
"name": "Prebrew off time Key {key}"
},
"preinfusion_off": {
"name": "Preinfusion time"
},
"preinfusion_off_key": {
"name": "Preinfusion time Key {key}"
},
"steam_temp": {
"name": "Steam target temperature"
},

View File

@ -269,3 +269,611 @@
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
})
# ---
# name: test_pre_brew_infusion_key_numbers[dose-6-set_dose-kwargs3-GS3 AV][GS01234_dose_key_1-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'GS01234 Dose Key 1',
'max': 999,
'min': 0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1,
'unit_of_measurement': 'ticks',
}),
'context': <ANY>,
'entity_id': 'number.gs01234_dose_key_1',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '1023',
})
# ---
# name: test_pre_brew_infusion_key_numbers[dose-6-set_dose-kwargs3-GS3 AV][GS01234_dose_key_2-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'GS01234 Dose Key 2',
'max': 999,
'min': 0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1,
'unit_of_measurement': 'ticks',
}),
'context': <ANY>,
'entity_id': 'number.gs01234_dose_key_2',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '1023',
})
# ---
# name: test_pre_brew_infusion_key_numbers[dose-6-set_dose-kwargs3-GS3 AV][GS01234_dose_key_3-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'GS01234 Dose Key 3',
'max': 999,
'min': 0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1,
'unit_of_measurement': 'ticks',
}),
'context': <ANY>,
'entity_id': 'number.gs01234_dose_key_3',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '1023',
})
# ---
# name: test_pre_brew_infusion_key_numbers[dose-6-set_dose-kwargs3-GS3 AV][GS01234_dose_key_4-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'GS01234 Dose Key 4',
'max': 999,
'min': 0,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 1,
'unit_of_measurement': 'ticks',
}),
'context': <ANY>,
'entity_id': 'number.gs01234_dose_key_4',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '1023',
})
# ---
# name: test_pre_brew_infusion_key_numbers[prebrew_off_time-6-configure_prebrew-kwargs0-GS3 AV][GS01234_prebrew_off_time_key_1-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'GS01234 Prebrew off time Key 1',
'max': 10,
'min': 1,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
}),
'context': <ANY>,
'entity_id': 'number.gs01234_prebrew_off_time_key_1',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '3',
})
# ---
# name: test_pre_brew_infusion_key_numbers[prebrew_off_time-6-configure_prebrew-kwargs0-GS3 AV][GS01234_prebrew_off_time_key_2-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'GS01234 Prebrew off time Key 2',
'max': 10,
'min': 1,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
}),
'context': <ANY>,
'entity_id': 'number.gs01234_prebrew_off_time_key_2',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '3',
})
# ---
# name: test_pre_brew_infusion_key_numbers[prebrew_off_time-6-configure_prebrew-kwargs0-GS3 AV][GS01234_prebrew_off_time_key_3-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'GS01234 Prebrew off time Key 3',
'max': 10,
'min': 1,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
}),
'context': <ANY>,
'entity_id': 'number.gs01234_prebrew_off_time_key_3',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '3',
})
# ---
# name: test_pre_brew_infusion_key_numbers[prebrew_off_time-6-configure_prebrew-kwargs0-GS3 AV][GS01234_prebrew_off_time_key_4-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'GS01234 Prebrew off time Key 4',
'max': 10,
'min': 1,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
}),
'context': <ANY>,
'entity_id': 'number.gs01234_prebrew_off_time_key_4',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '3',
})
# ---
# name: test_pre_brew_infusion_key_numbers[prebrew_on_time-6-configure_prebrew-kwargs1-GS3 AV][GS01234_prebrew_on_time_key_1-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'GS01234 Prebrew on time Key 1',
'max': 10,
'min': 2,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
}),
'context': <ANY>,
'entity_id': 'number.gs01234_prebrew_on_time_key_1',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '5',
})
# ---
# name: test_pre_brew_infusion_key_numbers[prebrew_on_time-6-configure_prebrew-kwargs1-GS3 AV][GS01234_prebrew_on_time_key_2-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'GS01234 Prebrew on time Key 2',
'max': 10,
'min': 2,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
}),
'context': <ANY>,
'entity_id': 'number.gs01234_prebrew_on_time_key_2',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '5',
})
# ---
# name: test_pre_brew_infusion_key_numbers[prebrew_on_time-6-configure_prebrew-kwargs1-GS3 AV][GS01234_prebrew_on_time_key_3-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'GS01234 Prebrew on time Key 3',
'max': 10,
'min': 2,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
}),
'context': <ANY>,
'entity_id': 'number.gs01234_prebrew_on_time_key_3',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '5',
})
# ---
# name: test_pre_brew_infusion_key_numbers[prebrew_on_time-6-configure_prebrew-kwargs1-GS3 AV][GS01234_prebrew_on_time_key_4-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'GS01234 Prebrew on time Key 4',
'max': 10,
'min': 2,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
}),
'context': <ANY>,
'entity_id': 'number.gs01234_prebrew_on_time_key_4',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '5',
})
# ---
# name: test_pre_brew_infusion_key_numbers[preinfusion_time-7-configure_prebrew-kwargs2-GS3 AV][GS01234_preinfusion_time_key_1-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'GS01234 Preinfusion time Key 1',
'max': 29,
'min': 2,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
}),
'context': <ANY>,
'entity_id': 'number.gs01234_preinfusion_time_key_1',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---
# name: test_pre_brew_infusion_key_numbers[preinfusion_time-7-configure_prebrew-kwargs2-GS3 AV][GS01234_preinfusion_time_key_2-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'GS01234 Preinfusion time Key 2',
'max': 29,
'min': 2,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
}),
'context': <ANY>,
'entity_id': 'number.gs01234_preinfusion_time_key_2',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---
# name: test_pre_brew_infusion_key_numbers[preinfusion_time-7-configure_prebrew-kwargs2-GS3 AV][GS01234_preinfusion_time_key_3-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'GS01234 Preinfusion time Key 3',
'max': 29,
'min': 2,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
}),
'context': <ANY>,
'entity_id': 'number.gs01234_preinfusion_time_key_3',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---
# name: test_pre_brew_infusion_key_numbers[preinfusion_time-7-configure_prebrew-kwargs2-GS3 AV][GS01234_preinfusion_time_key_4-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'GS01234 Preinfusion time Key 4',
'max': 29,
'min': 2,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
}),
'context': <ANY>,
'entity_id': 'number.gs01234_preinfusion_time_key_4',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---
# name: test_pre_brew_infusion_numbers[prebrew_off_time-6-kwargs0-Linea Mini]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'LM01234 Prebrew off time',
'max': 10,
'min': 1,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
}),
'context': <ANY>,
'entity_id': 'number.lm01234_prebrew_off_time',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '3',
})
# ---
# name: test_pre_brew_infusion_numbers[prebrew_off_time-6-kwargs0-Linea Mini].1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'max': 10,
'min': 1,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'number',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'number.lm01234_prebrew_off_time',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'name': None,
'options': dict({
}),
'original_device_class': <NumberDeviceClass.DURATION: 'duration'>,
'original_icon': None,
'original_name': 'Prebrew off time',
'platform': 'lamarzocco',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'prebrew_off',
'unique_id': 'LM01234_prebrew_off',
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
})
# ---
# name: test_pre_brew_infusion_numbers[prebrew_off_time-6-kwargs0-Micra]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'MR01234 Prebrew off time',
'max': 10,
'min': 1,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
}),
'context': <ANY>,
'entity_id': 'number.mr01234_prebrew_off_time',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '3',
})
# ---
# name: test_pre_brew_infusion_numbers[prebrew_off_time-6-kwargs0-Micra].1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'max': 10,
'min': 1,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'number',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'number.mr01234_prebrew_off_time',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'name': None,
'options': dict({
}),
'original_device_class': <NumberDeviceClass.DURATION: 'duration'>,
'original_icon': None,
'original_name': 'Prebrew off time',
'platform': 'lamarzocco',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'prebrew_off',
'unique_id': 'MR01234_prebrew_off',
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
})
# ---
# name: test_pre_brew_infusion_numbers[prebrew_on_time-6-kwargs1-Linea Mini]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'LM01234 Prebrew on time',
'max': 10,
'min': 2,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
}),
'context': <ANY>,
'entity_id': 'number.lm01234_prebrew_on_time',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '5',
})
# ---
# name: test_pre_brew_infusion_numbers[prebrew_on_time-6-kwargs1-Linea Mini].1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'max': 10,
'min': 2,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'number',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'number.lm01234_prebrew_on_time',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'name': None,
'options': dict({
}),
'original_device_class': <NumberDeviceClass.DURATION: 'duration'>,
'original_icon': None,
'original_name': 'Prebrew on time',
'platform': 'lamarzocco',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'prebrew_on',
'unique_id': 'LM01234_prebrew_on',
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
})
# ---
# name: test_pre_brew_infusion_numbers[prebrew_on_time-6-kwargs1-Micra]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'MR01234 Prebrew on time',
'max': 10,
'min': 2,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
}),
'context': <ANY>,
'entity_id': 'number.mr01234_prebrew_on_time',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': '5',
})
# ---
# name: test_pre_brew_infusion_numbers[prebrew_on_time-6-kwargs1-Micra].1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'max': 10,
'min': 2,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'number',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'number.mr01234_prebrew_on_time',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'name': None,
'options': dict({
}),
'original_device_class': <NumberDeviceClass.DURATION: 'duration'>,
'original_icon': None,
'original_name': 'Prebrew on time',
'platform': 'lamarzocco',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'prebrew_on',
'unique_id': 'MR01234_prebrew_on',
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
})
# ---
# name: test_pre_brew_infusion_numbers[preinfusion_time-7-kwargs2-Linea Mini]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'LM01234 Preinfusion time',
'max': 29,
'min': 2,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
}),
'context': <ANY>,
'entity_id': 'number.lm01234_preinfusion_time',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---
# name: test_pre_brew_infusion_numbers[preinfusion_time-7-kwargs2-Linea Mini].1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'max': 29,
'min': 2,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'number',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'number.lm01234_preinfusion_time',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'name': None,
'options': dict({
}),
'original_device_class': <NumberDeviceClass.DURATION: 'duration'>,
'original_icon': None,
'original_name': 'Preinfusion time',
'platform': 'lamarzocco',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'preinfusion_off',
'unique_id': 'LM01234_preinfusion_off',
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
})
# ---
# name: test_pre_brew_infusion_numbers[preinfusion_time-7-kwargs2-Micra]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
'friendly_name': 'MR01234 Preinfusion time',
'max': 29,
'min': 2,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
}),
'context': <ANY>,
'entity_id': 'number.mr01234_preinfusion_time',
'last_changed': <ANY>,
'last_updated': <ANY>,
'state': 'unavailable',
})
# ---
# name: test_pre_brew_infusion_numbers[preinfusion_time-7-kwargs2-Micra].1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': dict({
'max': 29,
'min': 2,
'mode': <NumberMode.AUTO: 'auto'>,
'step': 0.1,
}),
'config_entry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'number',
'entity_category': <EntityCategory.CONFIG: 'config'>,
'entity_id': 'number.mr01234_preinfusion_time',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'name': None,
'options': dict({
}),
'original_device_class': <NumberDeviceClass.DURATION: 'duration'>,
'original_icon': None,
'original_name': 'Preinfusion time',
'platform': 'lamarzocco',
'previous_unique_id': None,
'supported_features': 0,
'translation_key': 'preinfusion_off',
'unique_id': 'MR01234_preinfusion_off',
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
})
# ---

View File

@ -1,9 +1,8 @@
"""Tests for the La Marzocco number entities."""
from unittest.mock import MagicMock
from lmcloud.const import LaMarzoccoModel
from lmcloud.const import KEYS_PER_MODEL, LaMarzoccoModel
import pytest
from syrupy import SnapshotAssertion
@ -12,7 +11,7 @@ from homeassistant.components.number import (
DOMAIN as NUMBER_DOMAIN,
SERVICE_SET_VALUE,
)
from homeassistant.const import ATTR_ENTITY_ID
from homeassistant.const import ATTR_ENTITY_ID, STATE_UNAVAILABLE
from homeassistant.core import HomeAssistant
from homeassistant.helpers import device_registry as dr, entity_registry as er
@ -126,3 +125,202 @@ async def test_gs3_exclusive_none(
for entity in ENTITIES:
state = hass.states.get(f"number.{serial_number}_{entity}")
assert state is None
@pytest.mark.parametrize(
"device_fixture", [LaMarzoccoModel.LINEA_MICRA, LaMarzoccoModel.LINEA_MINI]
)
@pytest.mark.parametrize(
("entity_name", "value", "kwargs"),
[
("prebrew_off_time", 6, {"on_time": 3000, "off_time": 6000, "key": 1}),
("prebrew_on_time", 6, {"on_time": 6000, "off_time": 5000, "key": 1}),
("preinfusion_time", 7, {"off_time": 7000, "key": 1}),
],
)
async def test_pre_brew_infusion_numbers(
hass: HomeAssistant,
mock_lamarzocco: MagicMock,
entity_registry: er.EntityRegistry,
device_registry: dr.DeviceRegistry,
snapshot: SnapshotAssertion,
entity_name: str,
value: float,
kwargs: dict[str, float],
) -> None:
"""Test the La Marzocco prebrew/-infusion sensors."""
mock_lamarzocco.current_status["enable_preinfusion"] = True
serial_number = mock_lamarzocco.serial_number
state = hass.states.get(f"number.{serial_number}_{entity_name}")
assert state
assert state == snapshot
entry = entity_registry.async_get(state.entity_id)
assert entry
assert entry.device_id
assert entry == snapshot
device = device_registry.async_get(entry.device_id)
assert device
# service call
await hass.services.async_call(
NUMBER_DOMAIN,
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: f"number.{serial_number}_{entity_name}",
ATTR_VALUE: value,
},
blocking=True,
)
assert len(mock_lamarzocco.configure_prebrew.mock_calls) == 1
mock_lamarzocco.configure_prebrew.assert_called_once_with(**kwargs)
@pytest.mark.parametrize("device_fixture", [LaMarzoccoModel.GS3_AV])
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
@pytest.mark.parametrize(
("entity_name", "value", "function_name", "kwargs"),
[
(
"prebrew_off_time",
6,
"configure_prebrew",
{"on_time": 3000, "off_time": 6000},
),
(
"prebrew_on_time",
6,
"configure_prebrew",
{"on_time": 6000, "off_time": 5000},
),
("preinfusion_time", 7, "configure_prebrew", {"off_time": 7000}),
("dose", 6, "set_dose", {"value": 6}),
],
)
async def test_pre_brew_infusion_key_numbers(
hass: HomeAssistant,
mock_lamarzocco: MagicMock,
snapshot: SnapshotAssertion,
entity_name: str,
value: float,
function_name: str,
kwargs: dict[str, float],
) -> None:
"""Test the La Marzocco number sensors for GS3AV model."""
mock_lamarzocco.current_status["enable_preinfusion"] = True
serial_number = mock_lamarzocco.serial_number
func = getattr(mock_lamarzocco, function_name)
state = hass.states.get(f"number.{serial_number}_{entity_name}")
assert state is None
for key in range(1, KEYS_PER_MODEL[mock_lamarzocco.model_name] + 1):
state = hass.states.get(f"number.{serial_number}_{entity_name}_key_{key}")
assert state
assert state == snapshot(name=f"{serial_number}_{entity_name}_key_{key}-state")
# service call
await hass.services.async_call(
NUMBER_DOMAIN,
SERVICE_SET_VALUE,
{
ATTR_ENTITY_ID: f"number.{serial_number}_{entity_name}_key_{key}",
ATTR_VALUE: value,
},
blocking=True,
)
kwargs["key"] = key
assert len(func.mock_calls) == key
func.assert_called_with(**kwargs)
@pytest.mark.parametrize("device_fixture", [LaMarzoccoModel.GS3_AV])
async def test_disabled_entites(
hass: HomeAssistant,
mock_lamarzocco: MagicMock,
) -> None:
"""Test the La Marzocco prebrew/-infusion sensors for GS3AV model."""
ENTITIES = (
"prebrew_off_time",
"prebrew_on_time",
"preinfusion_time",
"set_dose",
)
serial_number = mock_lamarzocco.serial_number
for entity_name in ENTITIES:
for key in range(1, KEYS_PER_MODEL[mock_lamarzocco.model_name] + 1):
state = hass.states.get(f"number.{serial_number}_{entity_name}_key_{key}")
assert state is None
@pytest.mark.parametrize(
"device_fixture",
[LaMarzoccoModel.GS3_MP, LaMarzoccoModel.LINEA_MICRA, LaMarzoccoModel.LINEA_MINI],
)
async def test_not_existing_key_entites(
hass: HomeAssistant,
mock_lamarzocco: MagicMock,
) -> None:
"""Assert not existing key entities."""
serial_number = mock_lamarzocco.serial_number
for entity in (
"prebrew_off_time",
"prebrew_on_time",
"preinfusion_time",
"set_dose",
):
for key in range(1, KEYS_PER_MODEL[LaMarzoccoModel.GS3_AV] + 1):
state = hass.states.get(f"number.{serial_number}_{entity}_key_{key}")
assert state is None
@pytest.mark.parametrize(
"device_fixture",
[LaMarzoccoModel.GS3_MP],
)
async def test_not_existing_entites(
hass: HomeAssistant,
mock_lamarzocco: MagicMock,
) -> None:
"""Assert not existing entities."""
serial_number = mock_lamarzocco.serial_number
for entity in (
"prebrew_off_time",
"prebrew_on_time",
"preinfusion_time",
"set_dose",
):
state = hass.states.get(f"number.{serial_number}_{entity}")
assert state is None
@pytest.mark.parametrize("device_fixture", [LaMarzoccoModel.LINEA_MICRA])
async def test_not_settable_entites(
hass: HomeAssistant,
mock_lamarzocco: MagicMock,
) -> None:
"""Assert not settable causes error."""
serial_number = mock_lamarzocco.serial_number
state = hass.states.get(f"number.{serial_number}_preinfusion_time")
assert state
assert state.state == STATE_UNAVAILABLE