Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add QNAP QSW firmware update support #92869

Merged
merged 3 commits into from
May 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 13 additions & 1 deletion homeassistant/components/qnap_qsw/update.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
"""Support for the QNAP QSW update."""
from __future__ import annotations

from typing import Final
from typing import Any, Final

from aioqsw.const import (
QSD_DESCRIPTION,
Expand All @@ -16,6 +16,7 @@
UpdateDeviceClass,
UpdateEntity,
UpdateEntityDescription,
UpdateEntityFeature,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import EntityCategory
Expand Down Expand Up @@ -51,6 +52,7 @@ async def async_setup_entry(
class QswUpdate(QswFirmwareEntity, UpdateEntity):
"""Define a QNAP QSW update."""

_attr_supported_features = UpdateEntityFeature.INSTALL
entity_description: UpdateEntityDescription

def __init__(
Expand Down Expand Up @@ -87,3 +89,13 @@ def _async_update_attrs(self) -> None:
self._attr_release_summary = self.get_device_value(
QSD_FIRMWARE_CHECK, QSD_DESCRIPTION
)

async def async_install(
self, version: str | None, backup: bool, **kwargs: Any
) -> None:
"""Install an update."""
await self.coordinator.async_refresh()
await self.coordinator.qsw.live_update()

self._attr_installed_version = self.latest_version
self.async_write_ha_state()
71 changes: 65 additions & 6 deletions tests/components/qnap_qsw/test_update.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,32 @@
"""The sensor tests for the QNAP QSW platform."""

from aioqsw.const import API_RESULT, API_VERSION
from unittest.mock import patch

from homeassistant.const import STATE_OFF
from aioqsw.const import API_ERROR_CODE, API_ERROR_MESSAGE, API_RESULT, API_VERSION

from homeassistant.components.update import (
ATTR_BACKUP,
ATTR_IN_PROGRESS,
ATTR_INSTALLED_VERSION,
ATTR_LATEST_VERSION,
DOMAIN as UPDATE_DOMAIN,
SERVICE_INSTALL,
)
from homeassistant.const import ATTR_ENTITY_ID, STATE_OFF, STATE_ON
from homeassistant.core import HomeAssistant

from .util import FIRMWARE_INFO_MOCK, FIRMWARE_UPDATE_CHECK_MOCK, async_init_integration
from .util import (
FIRMWARE_INFO_MOCK,
FIRMWARE_UPDATE_CHECK_MOCK,
USERS_VERIFICATION_MOCK,
async_init_integration,
)

FIRMWARE_UPDATE_LIVE_MOCK = {
API_ERROR_CODE: 200,
API_ERROR_MESSAGE: "OK",
API_RESULT: "None",
}


async def test_qnap_qsw_update(hass: HomeAssistant) -> None:
Expand All @@ -15,12 +36,50 @@ async def test_qnap_qsw_update(hass: HomeAssistant) -> None:

update = hass.states.get("update.qsw_m408_4c_firmware_update")
assert update is not None
assert update.state == STATE_OFF
assert update.state == STATE_ON
assert (
update.attributes.get("installed_version")
update.attributes[ATTR_INSTALLED_VERSION]
== FIRMWARE_INFO_MOCK[API_RESULT][API_VERSION]
)
assert (
update.attributes.get("latest_version")
update.attributes[ATTR_LATEST_VERSION]
== FIRMWARE_UPDATE_CHECK_MOCK[API_RESULT][API_VERSION]
)
assert update.attributes[ATTR_IN_PROGRESS] is False

with patch(
"homeassistant.components.qnap_qsw.QnapQswApi.get_firmware_update_check",
return_value=FIRMWARE_UPDATE_CHECK_MOCK,
) as mock_firmware_update_check, patch(
"homeassistant.components.qnap_qsw.QnapQswApi.get_users_verification",
return_value=USERS_VERIFICATION_MOCK,
) as mock_users_verification, patch(
"homeassistant.components.qnap_qsw.QnapQswApi.post_firmware_update_live",
return_value=FIRMWARE_UPDATE_LIVE_MOCK,
) as mock_firmware_update_live:
await hass.services.async_call(
UPDATE_DOMAIN,
SERVICE_INSTALL,
{
ATTR_BACKUP: False,
ATTR_ENTITY_ID: "update.qsw_m408_4c_firmware_update",
},
blocking=True,
)

mock_firmware_update_check.assert_called_once()
mock_firmware_update_live.assert_called_once()
mock_users_verification.assert_called()

update = hass.states.get("update.qsw_m408_4c_firmware_update")
assert update is not None
assert update.state == STATE_OFF
assert (
update.attributes[ATTR_INSTALLED_VERSION]
== FIRMWARE_UPDATE_CHECK_MOCK[API_RESULT][API_VERSION]
)
assert (
update.attributes[ATTR_LATEST_VERSION]
== FIRMWARE_UPDATE_CHECK_MOCK[API_RESULT][API_VERSION]
)
assert update.attributes[ATTR_IN_PROGRESS] is False
16 changes: 8 additions & 8 deletions tests/components/qnap_qsw/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,17 +109,17 @@
API_ERROR_CODE: 200,
API_ERROR_MESSAGE: "OK",
API_RESULT: {
API_VERSION: "1.2.0",
API_NUMBER: "29649",
API_BUILD_NUMBER: "20220128",
API_DATE: "Fri, 28 Jan 2022 01:17:39 +0800",
API_VERSION: "1.3.0",
API_NUMBER: "527638",
API_BUILD_NUMBER: "20221123",
API_DATE: "Wed, 07, Dec 2022 16:30:00 +0800",
API_DESCRIPTION: "",
API_DOWNLOAD_URL: [
"https://download.qnap.com/Storage/Networking/QSW408FW/QSW-M408AC3-FW.v1.2.0_S20220128_29649.img",
"https://eu1.qnap.com/Storage/Networking/QSW408FW/QSW-M408AC3-FW.v1.2.0_S20220128_29649.img",
"https://us1.qnap.com/Storage/Networking/QSW408FW/QSW-M408AC3-FW.v1.2.0_S20220128_29649.img",
"https://download.qnap.com/Storage/Networking/QSW408FW/QSW-M408AC3-FW.v1.3.0_S20221123_527638.img",
"https://eu1.qnap.com/Storage/Networking/QSW408FW/QSW-M408AC3-FW.v1.3.0_S20221123_527638.img",
"https://us1.qnap.com/Storage/Networking/QSW408FW/QSW-M408AC3-FW.v1.3.0_S20221123_527638.img",
],
API_NEWER: False,
API_NEWER: True,
},
}

Expand Down