mirror of
https://github.com/home-assistant/core.git
synced 2025-04-24 01:08:12 +00:00
Add name and default name to device info of APCUPSD sensors (#94415)
This commit is contained in:
parent
2c42a319a2
commit
36ad24ce01
@ -11,6 +11,7 @@ from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT, Platform
|
||||
from homeassistant.core import HomeAssistant
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.util import Throttle
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -79,16 +80,6 @@ class APCUPSdData:
|
||||
return self.status[model_key]
|
||||
return None
|
||||
|
||||
@property
|
||||
def sw_version(self) -> str | None:
|
||||
"""Return the software version of the APCUPSd, if available."""
|
||||
return self.status.get("VERSION")
|
||||
|
||||
@property
|
||||
def hw_version(self) -> str | None:
|
||||
"""Return the firmware version of the UPS, if available."""
|
||||
return self.status.get("FIRMWARE")
|
||||
|
||||
@property
|
||||
def serial_no(self) -> str | None:
|
||||
"""Return the unique serial number of the UPS, if available."""
|
||||
@ -99,6 +90,21 @@ class APCUPSdData:
|
||||
"""Return the STATFLAG indicating the status of the UPS, if available."""
|
||||
return self.status.get("STATFLAG")
|
||||
|
||||
@property
|
||||
def device_info(self) -> DeviceInfo | None:
|
||||
"""Return the DeviceInfo of this APC UPS for the sensors, if serial number is available."""
|
||||
if self.serial_no is None:
|
||||
return None
|
||||
|
||||
return DeviceInfo(
|
||||
identifiers={(DOMAIN, self.serial_no)},
|
||||
model=self.model,
|
||||
manufacturer="APC",
|
||||
name=self.name if self.name is not None else "APC UPS",
|
||||
hw_version=self.status.get("FIRMWARE"),
|
||||
sw_version=self.status.get("VERSION"),
|
||||
)
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||
def update(self, **kwargs: Any) -> None:
|
||||
"""Fetch the latest status from APCUPSd.
|
||||
|
@ -9,7 +9,6 @@ from homeassistant.components.binary_sensor import (
|
||||
)
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import DOMAIN, VALUE_ONLINE, APCUPSdData
|
||||
@ -53,13 +52,8 @@ class OnlineStatus(BinarySensorEntity):
|
||||
# Set up unique id and device info if serial number is available.
|
||||
if (serial_no := data_service.serial_no) is not None:
|
||||
self._attr_unique_id = f"{serial_no}_{description.key}"
|
||||
self._attr_device_info = DeviceInfo(
|
||||
identifiers={(DOMAIN, serial_no)},
|
||||
model=data_service.model,
|
||||
manufacturer="APC",
|
||||
hw_version=data_service.hw_version,
|
||||
sw_version=data_service.sw_version,
|
||||
)
|
||||
self._attr_device_info = data_service.device_info
|
||||
|
||||
self.entity_description = description
|
||||
self._data_service = data_service
|
||||
|
||||
|
@ -21,7 +21,6 @@ from homeassistant.const import (
|
||||
UnitOfTime,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity import DeviceInfo
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
|
||||
from . import DOMAIN, APCUPSdData
|
||||
@ -496,13 +495,7 @@ class APCUPSdSensor(SensorEntity):
|
||||
# Set up unique id and device info if serial number is available.
|
||||
if (serial_no := data_service.serial_no) is not None:
|
||||
self._attr_unique_id = f"{serial_no}_{description.key}"
|
||||
self._attr_device_info = DeviceInfo(
|
||||
identifiers={(DOMAIN, serial_no)},
|
||||
model=data_service.model,
|
||||
manufacturer="APC",
|
||||
hw_version=data_service.hw_version,
|
||||
sw_version=data_service.sw_version,
|
||||
)
|
||||
self._attr_device_info = data_service.device_info
|
||||
|
||||
self.entity_description = description
|
||||
self._data_service = data_service
|
||||
|
@ -20,6 +20,7 @@ MOCK_STATUS: Final = OrderedDict(
|
||||
("CABLE", "USB Cable"),
|
||||
("DRIVER", "USB UPS Driver"),
|
||||
("UPSMODE", "Stand Alone"),
|
||||
("UPSNAME", "MyUPS"),
|
||||
("MODEL", "Back-UPS ES 600"),
|
||||
("STATUS", "ONLINE"),
|
||||
("LINEV", "124.0 Volts"),
|
||||
|
@ -124,7 +124,7 @@ async def test_flow_works(hass: HomeAssistant) -> None:
|
||||
)
|
||||
await hass.async_block_till_done()
|
||||
assert result["type"] == FlowResultType.CREATE_ENTRY
|
||||
assert result["title"] == MOCK_STATUS["MODEL"]
|
||||
assert result["title"] == MOCK_STATUS["UPSNAME"]
|
||||
assert result["data"] == CONF_DATA
|
||||
|
||||
mock_setup.assert_called_once()
|
||||
|
@ -8,6 +8,7 @@ from homeassistant.components.apcupsd import DOMAIN
|
||||
from homeassistant.config_entries import SOURCE_USER, ConfigEntryState
|
||||
from homeassistant.const import STATE_UNAVAILABLE
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers import device_registry as dr
|
||||
|
||||
from . import CONF_DATA, MOCK_MINIMAL_STATUS, MOCK_STATUS, async_init_integration
|
||||
|
||||
@ -28,6 +29,53 @@ async def test_async_setup_entry(hass: HomeAssistant, status: OrderedDict) -> No
|
||||
assert state.state == "on"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"status",
|
||||
(
|
||||
# We should not create device entries if SERIALNO is not reported.
|
||||
MOCK_MINIMAL_STATUS,
|
||||
# We should set the device name to be the friendly UPSNAME field if available.
|
||||
MOCK_MINIMAL_STATUS | {"SERIALNO": "XXXX", "UPSNAME": "MyUPS"},
|
||||
# Otherwise, we should fall back to default device name --- "APC UPS".
|
||||
MOCK_MINIMAL_STATUS | {"SERIALNO": "XXXX"},
|
||||
# We should create all fields of the device entry if they are available.
|
||||
MOCK_STATUS,
|
||||
),
|
||||
)
|
||||
async def test_device_entry(hass: HomeAssistant, status: OrderedDict) -> None:
|
||||
"""Test successful setup of device entries."""
|
||||
await async_init_integration(hass, status=status)
|
||||
|
||||
# Verify device info is properly set up.
|
||||
device_entries = dr.async_get(hass)
|
||||
|
||||
if "SERIALNO" not in status:
|
||||
assert len(device_entries.devices) == 0
|
||||
return
|
||||
|
||||
assert len(device_entries.devices) == 1
|
||||
entry = device_entries.async_get_device({(DOMAIN, status["SERIALNO"])})
|
||||
assert entry is not None
|
||||
# Specify the mapping between field name and the expected fields in device entry.
|
||||
fields = {
|
||||
"UPSNAME": entry.name,
|
||||
"MODEL": entry.model,
|
||||
"VERSION": entry.sw_version,
|
||||
"FIRMWARE": entry.hw_version,
|
||||
}
|
||||
|
||||
for field, entry_value in fields.items():
|
||||
if field in status:
|
||||
assert entry_value == status[field]
|
||||
elif field == "UPSNAME":
|
||||
# Even if UPSNAME is not available, we must fall back to default "APC UPS".
|
||||
assert entry_value == "APC UPS"
|
||||
else:
|
||||
assert entry_value is None
|
||||
|
||||
assert entry.manufacturer == "APC"
|
||||
|
||||
|
||||
async def test_multiple_integrations(hass: HomeAssistant) -> None:
|
||||
"""Test successful setup for multiple entries."""
|
||||
# Load two integrations from two mock hosts.
|
||||
|
Loading…
x
Reference in New Issue
Block a user