mirror of
https://github.com/home-assistant/core.git
synced 2025-04-25 01:38:02 +00:00
Add new QNAP QSW uptime timestamp sensor (#122589)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
parent
ebd1baa42c
commit
4306b0caba
@ -2,7 +2,9 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from collections.abc import Callable
|
||||
from dataclasses import dataclass, replace
|
||||
from datetime import datetime
|
||||
from typing import Final
|
||||
|
||||
from aioqsw.const import (
|
||||
@ -26,8 +28,11 @@ from aioqsw.const import (
|
||||
QSD_TX_OCTETS,
|
||||
QSD_TX_SPEED,
|
||||
QSD_UPTIME_SECONDS,
|
||||
QSD_UPTIME_TIMESTAMP,
|
||||
)
|
||||
|
||||
from homeassistant.components.automation import automations_with_entity
|
||||
from homeassistant.components.script import scripts_with_entity
|
||||
from homeassistant.components.sensor import (
|
||||
SensorDeviceClass,
|
||||
SensorEntity,
|
||||
@ -43,8 +48,10 @@ from homeassistant.const import (
|
||||
UnitOfTime,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.helpers import entity_registry as er, issue_registry as ir
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import UNDEFINED
|
||||
from homeassistant.helpers.typing import UNDEFINED, StateType
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
from .const import ATTR_MAX, DOMAIN, QSW_COORD_DATA, RPM
|
||||
from .coordinator import QswDataCoordinator
|
||||
@ -58,6 +65,17 @@ class QswSensorEntityDescription(SensorEntityDescription, QswEntityDescription):
|
||||
attributes: dict[str, list[str]] | None = None
|
||||
qsw_type: QswEntityType | None = None
|
||||
sep_key: str = "_"
|
||||
value_fn: Callable[[str], datetime | StateType] = lambda value: value
|
||||
|
||||
|
||||
DEPRECATED_UPTIME_SECONDS = QswSensorEntityDescription(
|
||||
translation_key="uptime",
|
||||
key=QSD_SYSTEM_TIME,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
native_unit_of_measurement=UnitOfTime.SECONDS,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
subkey=QSD_UPTIME_SECONDS,
|
||||
)
|
||||
|
||||
|
||||
SENSOR_TYPES: Final[tuple[QswSensorEntityDescription, ...]] = (
|
||||
@ -140,12 +158,12 @@ SENSOR_TYPES: Final[tuple[QswSensorEntityDescription, ...]] = (
|
||||
subkey=QSD_TX_SPEED,
|
||||
),
|
||||
QswSensorEntityDescription(
|
||||
translation_key="uptime",
|
||||
translation_key="uptime_timestamp",
|
||||
key=QSD_SYSTEM_TIME,
|
||||
device_class=SensorDeviceClass.TIMESTAMP,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
native_unit_of_measurement=UnitOfTime.SECONDS,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
subkey=QSD_UPTIME_SECONDS,
|
||||
subkey=QSD_UPTIME_TIMESTAMP,
|
||||
value_fn=dt_util.parse_datetime,
|
||||
),
|
||||
)
|
||||
|
||||
@ -337,6 +355,46 @@ async def async_setup_entry(
|
||||
)
|
||||
entities.append(QswSensor(coordinator, _desc, entry, port_id))
|
||||
|
||||
# Can be removed in HA 2025.5.0
|
||||
entity_reg = er.async_get(hass)
|
||||
reg_entities = er.async_entries_for_config_entry(entity_reg, entry.entry_id)
|
||||
for entity in reg_entities:
|
||||
if entity.domain == "sensor" and entity.unique_id.endswith(
|
||||
("_uptime", "_uptime_seconds")
|
||||
):
|
||||
entity_id = entity.entity_id
|
||||
|
||||
if entity.disabled:
|
||||
entity_reg.async_remove(entity_id)
|
||||
continue
|
||||
|
||||
if (
|
||||
DEPRECATED_UPTIME_SECONDS.key in coordinator.data
|
||||
and DEPRECATED_UPTIME_SECONDS.subkey
|
||||
in coordinator.data[DEPRECATED_UPTIME_SECONDS.key]
|
||||
):
|
||||
entities.append(
|
||||
QswSensor(coordinator, DEPRECATED_UPTIME_SECONDS, entry)
|
||||
)
|
||||
|
||||
entity_automations = automations_with_entity(hass, entity_id)
|
||||
entity_scripts = scripts_with_entity(hass, entity_id)
|
||||
|
||||
for item in entity_automations + entity_scripts:
|
||||
ir.async_create_issue(
|
||||
hass,
|
||||
DOMAIN,
|
||||
f"uptime_seconds_deprecated_{entity_id}_{item}",
|
||||
breaks_in_ha_version="2025.5.0",
|
||||
is_fixable=False,
|
||||
severity=ir.IssueSeverity.WARNING,
|
||||
translation_key="uptime_seconds_deprecated",
|
||||
translation_placeholders={
|
||||
"entity": entity_id,
|
||||
"info": item,
|
||||
},
|
||||
)
|
||||
|
||||
async_add_entities(entities)
|
||||
|
||||
|
||||
@ -374,5 +432,5 @@ class QswSensor(QswSensorEntity, SensorEntity):
|
||||
self.entity_description.subkey,
|
||||
self.entity_description.qsw_type,
|
||||
)
|
||||
self._attr_native_value = value
|
||||
self._attr_native_value = self.entity_description.value_fn(value)
|
||||
super()._async_update_attrs()
|
||||
|
@ -52,7 +52,16 @@
|
||||
},
|
||||
"uptime": {
|
||||
"name": "Uptime"
|
||||
},
|
||||
"uptime_timestamp": {
|
||||
"name": "Uptime timestamp"
|
||||
}
|
||||
}
|
||||
},
|
||||
"issues": {
|
||||
"uptime_seconds_deprecated": {
|
||||
"title": "QNAP QSW uptime seconds sensor deprecated",
|
||||
"description": "The QNAP QSW uptime seconds sensor entity is deprecated and will be removed in HA 2025.2.0.\nHome Assistant detected that entity `{entity}` is being used in `{info}`\n\nYou should remove the uptime seconds entity from `{info}` then click submit to fix this issue."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,19 +1,27 @@
|
||||
"""The sensor tests for the QNAP QSW platform."""
|
||||
|
||||
from unittest.mock import patch
|
||||
|
||||
from freezegun.api import FrozenDateTimeFactory
|
||||
import pytest
|
||||
|
||||
from homeassistant.components.qnap_qsw.const import ATTR_MAX
|
||||
from homeassistant.components.qnap_qsw.const import ATTR_MAX, DOMAIN
|
||||
from homeassistant.const import Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import entity_registry as er, issue_registry as ir
|
||||
|
||||
from .util import async_init_integration
|
||||
from .util import async_init_integration, init_config_entry
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_qnap_qsw_create_sensors(
|
||||
hass: HomeAssistant,
|
||||
freezer: FrozenDateTimeFactory,
|
||||
) -> None:
|
||||
"""Test creation of sensors."""
|
||||
|
||||
await hass.config.async_set_time_zone("UTC")
|
||||
freezer.move_to("2024-07-25 12:00:00+00:00")
|
||||
await async_init_integration(hass)
|
||||
|
||||
state = hass.states.get("sensor.qsw_m408_4c_fan_1_speed")
|
||||
@ -45,8 +53,8 @@ async def test_qnap_qsw_create_sensors(
|
||||
state = hass.states.get("sensor.qsw_m408_4c_tx_speed")
|
||||
assert state.state == "0"
|
||||
|
||||
state = hass.states.get("sensor.qsw_m408_4c_uptime")
|
||||
assert state.state == "91"
|
||||
state = hass.states.get("sensor.qsw_m408_4c_uptime_timestamp")
|
||||
assert state.state == "2024-07-25T11:58:29+00:00"
|
||||
|
||||
# LACP Ports
|
||||
state = hass.states.get("sensor.qsw_m408_4c_lacp_port_1_link_speed")
|
||||
@ -373,3 +381,60 @@ async def test_qnap_qsw_create_sensors(
|
||||
|
||||
state = hass.states.get("sensor.qsw_m408_4c_port_12_tx_speed")
|
||||
assert state.state == "0"
|
||||
|
||||
|
||||
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
|
||||
async def test_deprecated_uptime_seconds(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
issue_registry: ir.IssueRegistry,
|
||||
) -> None:
|
||||
"""Test deprecation warning of the Uptime seconds sensor entity."""
|
||||
original_id = "sensor.qsw_m408_4c_uptime"
|
||||
domain = Platform.SENSOR
|
||||
|
||||
config_entry = init_config_entry(hass)
|
||||
|
||||
entity = entity_registry.async_get_or_create(
|
||||
domain=domain,
|
||||
platform=DOMAIN,
|
||||
unique_id=original_id,
|
||||
config_entry=config_entry,
|
||||
suggested_object_id=original_id,
|
||||
disabled_by=None,
|
||||
)
|
||||
|
||||
assert entity_registry.async_get_entity_id(domain, DOMAIN, original_id)
|
||||
|
||||
with patch(
|
||||
"homeassistant.components.qnap_qsw.sensor.automations_with_entity",
|
||||
return_value=["item"],
|
||||
):
|
||||
await async_init_integration(hass, config_entry=config_entry)
|
||||
assert issue_registry.async_get_issue(
|
||||
DOMAIN, f"uptime_seconds_deprecated_{entity.entity_id}_item"
|
||||
)
|
||||
|
||||
|
||||
async def test_cleanup_deprecated_uptime_seconds(
|
||||
hass: HomeAssistant,
|
||||
entity_registry: er.EntityRegistry,
|
||||
) -> None:
|
||||
"""Test cleanup of the Uptime seconds sensor entity."""
|
||||
original_id = "sensor.qsw_m408_4c_uptime_seconds"
|
||||
domain = Platform.SENSOR
|
||||
|
||||
config_entry = init_config_entry(hass)
|
||||
|
||||
entity_registry.async_get_or_create(
|
||||
domain=domain,
|
||||
platform=DOMAIN,
|
||||
unique_id=original_id,
|
||||
config_entry=config_entry,
|
||||
suggested_object_id=original_id,
|
||||
disabled_by=er.RegistryEntryDisabler.USER,
|
||||
)
|
||||
|
||||
assert entity_registry.async_get_entity_id(domain, DOMAIN, original_id)
|
||||
|
||||
await async_init_integration(hass, config_entry=config_entry)
|
||||
|
@ -491,11 +491,10 @@ USERS_VERIFICATION_MOCK = {
|
||||
}
|
||||
|
||||
|
||||
async def async_init_integration(
|
||||
def init_config_entry(
|
||||
hass: HomeAssistant,
|
||||
) -> None:
|
||||
"""Set up the QNAP QSW integration in Home Assistant."""
|
||||
|
||||
) -> MockConfigEntry:
|
||||
"""Set up the QNAP QSW entry in Home Assistant."""
|
||||
config_entry = MockConfigEntry(
|
||||
data=CONFIG,
|
||||
domain=DOMAIN,
|
||||
@ -503,6 +502,18 @@ async def async_init_integration(
|
||||
)
|
||||
config_entry.add_to_hass(hass)
|
||||
|
||||
return config_entry
|
||||
|
||||
|
||||
async def async_init_integration(
|
||||
hass: HomeAssistant,
|
||||
config_entry: MockConfigEntry | None = None,
|
||||
) -> None:
|
||||
"""Set up the QNAP QSW integration in Home Assistant."""
|
||||
|
||||
if config_entry is None:
|
||||
config_entry = init_config_entry(hass)
|
||||
|
||||
with (
|
||||
patch(
|
||||
"homeassistant.components.qnap_qsw.QnapQswApi.get_firmware_condition",
|
||||
|
Loading…
x
Reference in New Issue
Block a user