Bump pylamarzocco to 1.4.9 (#140916)

This commit is contained in:
Josef Zweck 2025-03-19 11:25:12 +01:00 committed by GitHub
parent f79aa2f73e
commit 3fd17c802c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 183 additions and 70 deletions

View File

@ -61,6 +61,42 @@ async def async_setup_entry(hass: HomeAssistant, entry: LaMarzoccoConfigEntry) -
client=client,
)
# initialize the firmware update coordinator early to check the firmware version
firmware_device = LaMarzoccoMachine(
model=entry.data[CONF_MODEL],
serial_number=entry.unique_id,
name=entry.data[CONF_NAME],
cloud_client=cloud_client,
)
firmware_coordinator = LaMarzoccoFirmwareUpdateCoordinator(
hass, entry, firmware_device
)
await firmware_coordinator.async_config_entry_first_refresh()
gateway_version = version.parse(
firmware_device.firmware[FirmwareType.GATEWAY].current_version
)
if gateway_version >= version.parse("v5.0.9"):
# remove host from config entry, it is not supported anymore
data = {k: v for k, v in entry.data.items() if k != CONF_HOST}
hass.config_entries.async_update_entry(
entry,
data=data,
)
elif gateway_version < version.parse("v3.4-rc5"):
# incompatible gateway firmware, create an issue
ir.async_create_issue(
hass,
DOMAIN,
"unsupported_gateway_firmware",
is_fixable=False,
severity=ir.IssueSeverity.ERROR,
translation_key="unsupported_gateway_firmware",
translation_placeholders={"gateway_version": str(gateway_version)},
)
# initialize local API
local_client: LaMarzoccoLocalClient | None = None
if (host := entry.data.get(CONF_HOST)) is not None:
@ -117,30 +153,16 @@ async def async_setup_entry(hass: HomeAssistant, entry: LaMarzoccoConfigEntry) -
coordinators = LaMarzoccoRuntimeData(
LaMarzoccoConfigUpdateCoordinator(hass, entry, device, local_client),
LaMarzoccoFirmwareUpdateCoordinator(hass, entry, device),
firmware_coordinator,
LaMarzoccoStatisticsUpdateCoordinator(hass, entry, device),
)
# API does not like concurrent requests, so no asyncio.gather here
await coordinators.config_coordinator.async_config_entry_first_refresh()
await coordinators.firmware_coordinator.async_config_entry_first_refresh()
await coordinators.statistics_coordinator.async_config_entry_first_refresh()
entry.runtime_data = coordinators
gateway_version = device.firmware[FirmwareType.GATEWAY].current_version
if version.parse(gateway_version) < version.parse("v3.4-rc5"):
# incompatible gateway firmware, create an issue
ir.async_create_issue(
hass,
DOMAIN,
"unsupported_gateway_firmware",
is_fixable=False,
severity=ir.IssueSeverity.ERROR,
translation_key="unsupported_gateway_firmware",
translation_placeholders={"gateway_version": gateway_version},
)
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
async def update_listener(

View File

@ -37,5 +37,5 @@
"iot_class": "cloud_polling",
"loggers": ["pylamarzocco"],
"quality_scale": "platinum",
"requirements": ["pylamarzocco==1.4.7"]
"requirements": ["pylamarzocco==1.4.9"]
}

View File

@ -144,9 +144,12 @@ KEY_ENTITIES: tuple[LaMarzoccoKeyNumberEntityDescription, ...] = (
set_value_fn=lambda machine, value, key: machine.set_prebrew_time(
prebrew_off_time=value, key=key
),
native_value_fn=lambda config, key: config.prebrew_configuration[key].off_time,
native_value_fn=lambda config, key: config.prebrew_configuration[key][
0
].off_time,
available_fn=lambda device: len(device.config.prebrew_configuration) > 0
and device.config.prebrew_mode == PrebrewMode.PREBREW,
and device.config.prebrew_mode
in (PrebrewMode.PREBREW, PrebrewMode.PREBREW_ENABLED),
supported_fn=lambda coordinator: coordinator.device.model
!= MachineModel.GS3_MP,
),
@ -162,9 +165,12 @@ KEY_ENTITIES: tuple[LaMarzoccoKeyNumberEntityDescription, ...] = (
set_value_fn=lambda machine, value, key: machine.set_prebrew_time(
prebrew_on_time=value, key=key
),
native_value_fn=lambda config, key: config.prebrew_configuration[key].off_time,
native_value_fn=lambda config, key: config.prebrew_configuration[key][
0
].off_time,
available_fn=lambda device: len(device.config.prebrew_configuration) > 0
and device.config.prebrew_mode == PrebrewMode.PREBREW,
and device.config.prebrew_mode
in (PrebrewMode.PREBREW, PrebrewMode.PREBREW_ENABLED),
supported_fn=lambda coordinator: coordinator.device.model
!= MachineModel.GS3_MP,
),
@ -180,8 +186,8 @@ KEY_ENTITIES: tuple[LaMarzoccoKeyNumberEntityDescription, ...] = (
set_value_fn=lambda machine, value, key: machine.set_preinfusion_time(
preinfusion_time=value, key=key
),
native_value_fn=lambda config, key: config.prebrew_configuration[
key
native_value_fn=lambda config, key: config.prebrew_configuration[key][
1
].preinfusion_time,
available_fn=lambda device: len(device.config.prebrew_configuration) > 0
and device.config.prebrew_mode == PrebrewMode.PREINFUSION,

View File

@ -38,6 +38,7 @@ STEAM_LEVEL_LM_TO_HA = {value: key for key, value in STEAM_LEVEL_HA_TO_LM.items(
PREBREW_MODE_HA_TO_LM = {
"disabled": PrebrewMode.DISABLED,
"prebrew": PrebrewMode.PREBREW,
"prebrew_enabled": PrebrewMode.PREBREW_ENABLED,
"preinfusion": PrebrewMode.PREINFUSION,
}

View File

@ -148,6 +148,7 @@
"state": {
"disabled": "Disabled",
"prebrew": "Prebrew",
"prebrew_enabled": "Prebrew",
"preinfusion": "Preinfusion"
}
},

2
requirements_all.txt generated
View File

@ -2081,7 +2081,7 @@ pykwb==0.0.8
pylacrosse==0.4
# homeassistant.components.lamarzocco
pylamarzocco==1.4.7
pylamarzocco==1.4.9
# homeassistant.components.lastfm
pylast==5.1.0

View File

@ -1692,7 +1692,7 @@ pykrakenapi==0.1.8
pykulersky==0.5.2
# homeassistant.components.lamarzocco
pylamarzocco==1.4.7
pylamarzocco==1.4.9
# homeassistant.components.lastfm
pylast==5.1.0

View File

@ -101,28 +101,60 @@
"mode": "TypeB",
"Group1": [
{
"mode": "TypeA",
"groupNumber": "Group1",
"doseType": "DoseA",
"preWetTime": 0.5,
"preWetHoldTime": 1
},
{
"mode": "TypeB",
"groupNumber": "Group1",
"doseType": "DoseA",
"preWetTime": 0,
"preWetHoldTime": 4
},
{
"mode": "TypeA",
"groupNumber": "Group1",
"doseType": "DoseB",
"preWetTime": 0.5,
"preWetHoldTime": 1
},
{
"mode": "TypeB",
"groupNumber": "Group1",
"doseType": "DoseC",
"preWetTime": 3.2999999523162842,
"preWetHoldTime": 3.2999999523162842
"doseType": "DoseB",
"preWetTime": 0,
"preWetHoldTime": 4
},
{
"mode": "TypeA",
"groupNumber": "Group1",
"doseType": "DoseC",
"preWetTime": 3.3,
"preWetHoldTime": 3.3
},
{
"mode": "TypeB",
"groupNumber": "Group1",
"doseType": "DoseC",
"preWetTime": 0,
"preWetHoldTime": 4
},
{
"mode": "TypeA",
"groupNumber": "Group1",
"doseType": "DoseD",
"preWetTime": 2,
"preWetHoldTime": 2
},
{
"mode": "TypeB",
"groupNumber": "Group1",
"doseType": "DoseD",
"preWetTime": 0,
"preWetHoldTime": 4
}
]
},

View File

@ -82,10 +82,18 @@
"mode": "TypeB",
"Group1": [
{
"mode": "TypeA",
"groupNumber": "Group1",
"doseType": "DoseA",
"doseType": "Continuous",
"preWetTime": 2,
"preWetHoldTime": 3
},
{
"mode": "TypeB",
"groupNumber": "Group1",
"doseType": "Continuous",
"preWetTime": 0,
"preWetHoldTime": 3
}
]
},

View File

@ -27,22 +27,46 @@
}),
'plumbed_in': True,
'prebrew_configuration': dict({
'1': dict({
'off_time': 1,
'on_time': 0.5,
}),
'2': dict({
'off_time': 1,
'on_time': 0.5,
}),
'3': dict({
'off_time': 3.299999952316284,
'on_time': 3.299999952316284,
}),
'4': dict({
'off_time': 2,
'on_time': 2,
}),
'1': list([
dict({
'off_time': 1,
'on_time': 0.5,
}),
dict({
'off_time': 4,
'on_time': 0,
}),
]),
'2': list([
dict({
'off_time': 1,
'on_time': 0.5,
}),
dict({
'off_time': 4,
'on_time': 0,
}),
]),
'3': list([
dict({
'off_time': 3.3,
'on_time': 3.3,
}),
dict({
'off_time': 4,
'on_time': 0,
}),
]),
'4': list([
dict({
'off_time': 2,
'on_time': 2,
}),
dict({
'off_time': 4,
'on_time': 0,
}),
]),
}),
'prebrew_mode': 'TypeB',
'scale': None,

View File

@ -419,7 +419,7 @@
'state': '121',
})
# ---
# name: test_pre_brew_infusion_key_numbers[prebrew_off_time-6-Enabled-set_prebrew_time-kwargs0-GS3 AV][GS012345_prebrew_off_time_key_1-state]
# name: test_pre_brew_infusion_key_numbers[prebrew_off_time-6-TypeA-set_prebrew_time-kwargs0-GS3 AV][GS012345_prebrew_off_time_key_1-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
@ -438,7 +438,7 @@
'state': '1',
})
# ---
# name: test_pre_brew_infusion_key_numbers[prebrew_off_time-6-Enabled-set_prebrew_time-kwargs0-GS3 AV][GS012345_prebrew_off_time_key_2-state]
# name: test_pre_brew_infusion_key_numbers[prebrew_off_time-6-TypeA-set_prebrew_time-kwargs0-GS3 AV][GS012345_prebrew_off_time_key_2-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
@ -457,7 +457,7 @@
'state': '1',
})
# ---
# name: test_pre_brew_infusion_key_numbers[prebrew_off_time-6-Enabled-set_prebrew_time-kwargs0-GS3 AV][GS012345_prebrew_off_time_key_3-state]
# name: test_pre_brew_infusion_key_numbers[prebrew_off_time-6-TypeA-set_prebrew_time-kwargs0-GS3 AV][GS012345_prebrew_off_time_key_3-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
@ -473,10 +473,10 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '3.29999995231628',
'state': '3.3',
})
# ---
# name: test_pre_brew_infusion_key_numbers[prebrew_off_time-6-Enabled-set_prebrew_time-kwargs0-GS3 AV][GS012345_prebrew_off_time_key_4-state]
# name: test_pre_brew_infusion_key_numbers[prebrew_off_time-6-TypeA-set_prebrew_time-kwargs0-GS3 AV][GS012345_prebrew_off_time_key_4-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
@ -495,7 +495,7 @@
'state': '2',
})
# ---
# name: test_pre_brew_infusion_key_numbers[prebrew_on_time-6-Enabled-set_prebrew_time-kwargs1-GS3 AV][GS012345_prebrew_on_time_key_1-state]
# name: test_pre_brew_infusion_key_numbers[prebrew_on_time-6-TypeA-set_prebrew_time-kwargs1-GS3 AV][GS012345_prebrew_on_time_key_1-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
@ -514,7 +514,7 @@
'state': '1',
})
# ---
# name: test_pre_brew_infusion_key_numbers[prebrew_on_time-6-Enabled-set_prebrew_time-kwargs1-GS3 AV][GS012345_prebrew_on_time_key_2-state]
# name: test_pre_brew_infusion_key_numbers[prebrew_on_time-6-TypeA-set_prebrew_time-kwargs1-GS3 AV][GS012345_prebrew_on_time_key_2-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
@ -533,7 +533,7 @@
'state': '1',
})
# ---
# name: test_pre_brew_infusion_key_numbers[prebrew_on_time-6-Enabled-set_prebrew_time-kwargs1-GS3 AV][GS012345_prebrew_on_time_key_3-state]
# name: test_pre_brew_infusion_key_numbers[prebrew_on_time-6-TypeA-set_prebrew_time-kwargs1-GS3 AV][GS012345_prebrew_on_time_key_3-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
@ -549,10 +549,10 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '3.29999995231628',
'state': '3.3',
})
# ---
# name: test_pre_brew_infusion_key_numbers[prebrew_on_time-6-Enabled-set_prebrew_time-kwargs1-GS3 AV][GS012345_prebrew_on_time_key_4-state]
# name: test_pre_brew_infusion_key_numbers[prebrew_on_time-6-TypeA-set_prebrew_time-kwargs1-GS3 AV][GS012345_prebrew_on_time_key_4-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
@ -587,7 +587,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '1',
'state': '4',
})
# ---
# name: test_pre_brew_infusion_key_numbers[preinfusion_time-7-TypeB-set_preinfusion_time-kwargs2-GS3 AV][GS012345_preinfusion_time_key_2-state]
@ -606,7 +606,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '1',
'state': '4',
})
# ---
# name: test_pre_brew_infusion_key_numbers[preinfusion_time-7-TypeB-set_preinfusion_time-kwargs2-GS3 AV][GS012345_preinfusion_time_key_3-state]
@ -625,7 +625,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '3.29999995231628',
'state': '4',
})
# ---
# name: test_pre_brew_infusion_key_numbers[preinfusion_time-7-TypeB-set_preinfusion_time-kwargs2-GS3 AV][GS012345_preinfusion_time_key_4-state]
@ -644,10 +644,10 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '2',
'state': '4',
})
# ---
# name: test_pre_brew_infusion_numbers[prebrew_off_time-set_prebrew_time-Enabled-6-kwargs0-Linea Mini]
# name: test_pre_brew_infusion_numbers[prebrew_off_time-set_prebrew_time-TypeA-6-kwargs0-Linea Mini]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
@ -666,7 +666,7 @@
'state': '3',
})
# ---
# name: test_pre_brew_infusion_numbers[prebrew_off_time-set_prebrew_time-Enabled-6-kwargs0-Linea Mini].1
# name: test_pre_brew_infusion_numbers[prebrew_off_time-set_prebrew_time-TypeA-6-kwargs0-Linea Mini].1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -705,7 +705,7 @@
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
})
# ---
# name: test_pre_brew_infusion_numbers[prebrew_off_time-set_prebrew_time-Enabled-6-kwargs0-Micra]
# name: test_pre_brew_infusion_numbers[prebrew_off_time-set_prebrew_time-TypeA-6-kwargs0-Micra]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
@ -724,7 +724,7 @@
'state': '1',
})
# ---
# name: test_pre_brew_infusion_numbers[prebrew_off_time-set_prebrew_time-Enabled-6-kwargs0-Micra].1
# name: test_pre_brew_infusion_numbers[prebrew_off_time-set_prebrew_time-TypeA-6-kwargs0-Micra].1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -763,7 +763,7 @@
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
})
# ---
# name: test_pre_brew_infusion_numbers[prebrew_on_time-set_prebrew_time-Enabled-6-kwargs1-Linea Mini]
# name: test_pre_brew_infusion_numbers[prebrew_on_time-set_prebrew_time-TypeA-6-kwargs1-Linea Mini]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
@ -782,7 +782,7 @@
'state': '3',
})
# ---
# name: test_pre_brew_infusion_numbers[prebrew_on_time-set_prebrew_time-Enabled-6-kwargs1-Linea Mini].1
# name: test_pre_brew_infusion_numbers[prebrew_on_time-set_prebrew_time-TypeA-6-kwargs1-Linea Mini].1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -821,7 +821,7 @@
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
})
# ---
# name: test_pre_brew_infusion_numbers[prebrew_on_time-set_prebrew_time-Enabled-6-kwargs1-Micra]
# name: test_pre_brew_infusion_numbers[prebrew_on_time-set_prebrew_time-TypeA-6-kwargs1-Micra]
StateSnapshot({
'attributes': ReadOnlyDict({
'device_class': 'duration',
@ -840,7 +840,7 @@
'state': '1',
})
# ---
# name: test_pre_brew_infusion_numbers[prebrew_on_time-set_prebrew_time-Enabled-6-kwargs1-Micra].1
# name: test_pre_brew_infusion_numbers[prebrew_on_time-set_prebrew_time-TypeA-6-kwargs1-Micra].1
EntityRegistryEntrySnapshot({
'aliases': set({
}),
@ -953,7 +953,7 @@
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': '1',
'state': '4',
})
# ---
# name: test_pre_brew_infusion_numbers[preinfusion_time-set_preinfusion_time-TypeB-7-kwargs2-Micra].1

View File

@ -170,12 +170,18 @@ async def test_bluetooth_is_set_from_discovery(
"homeassistant.components.lamarzocco.async_discovered_service_info",
return_value=[service_info],
) as discovery,
patch("homeassistant.components.lamarzocco.LaMarzoccoMachine") as init_device,
patch(
"homeassistant.components.lamarzocco.LaMarzoccoMachine"
) as mock_machine_class,
):
mock_machine = MagicMock()
mock_machine.get_firmware = AsyncMock()
mock_machine.firmware = mock_lamarzocco.firmware
mock_machine_class.return_value = mock_machine
await async_init_integration(hass, mock_config_entry)
discovery.assert_called_once()
init_device.assert_called_once()
_, kwargs = init_device.call_args
assert mock_machine_class.call_count == 2
_, kwargs = mock_machine_class.call_args
assert kwargs["bluetooth_client"] is not None
assert mock_config_entry.data[CONF_NAME] == service_info.name
assert mock_config_entry.data[CONF_MAC] == service_info.address
@ -223,6 +229,19 @@ async def test_gateway_version_issue(
assert (issue is not None) == issue_exists
async def test_conf_host_removed_for_new_gateway(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_lamarzocco: MagicMock,
) -> None:
"""Make sure we get the issue for certain gateway firmware versions."""
mock_lamarzocco.firmware[FirmwareType.GATEWAY].current_version = "v5.0.9"
await async_init_integration(hass, mock_config_entry)
assert CONF_HOST not in mock_config_entry.data
async def test_device(
hass: HomeAssistant,
mock_lamarzocco: MagicMock,