From a05a34239d3898876afe7c347b15a065a492a77e Mon Sep 17 00:00:00 2001
From: tdfountain <174762217+tdfountain@users.noreply.github.com>
Date: Sun, 3 Nov 2024 15:27:27 -0800
Subject: [PATCH] Show NUT device serial number if provided in Device Info
 (#124168)

---
 homeassistant/components/nut/__init__.py |  5 ++++-
 homeassistant/components/nut/sensor.py   |  2 ++
 tests/components/nut/test_init.py        | 26 +++++++++++++++++++++++-
 3 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/homeassistant/components/nut/__init__.py b/homeassistant/components/nut/__init__.py
index c9b2bcc13b2..6bbe19e8f3c 100644
--- a/homeassistant/components/nut/__init__.py
+++ b/homeassistant/components/nut/__init__.py
@@ -131,6 +131,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: NutConfigEntry) -> bool:
         manufacturer=data.device_info.manufacturer,
         model=data.device_info.model,
         sw_version=data.device_info.firmware,
+        serial_number=data.device_info.serial,
     )
 
     await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
@@ -209,6 +210,7 @@ class NUTDeviceInfo:
     manufacturer: str | None = None
     model: str | None = None
     firmware: str | None = None
+    serial: str | None = None
 
 
 class PyNUTData:
@@ -268,7 +270,8 @@ class PyNUTData:
         manufacturer = _manufacturer_from_status(self._status)
         model = _model_from_status(self._status)
         firmware = _firmware_from_status(self._status)
-        return NUTDeviceInfo(manufacturer, model, firmware)
+        serial = _serial_from_status(self._status)
+        return NUTDeviceInfo(manufacturer, model, firmware, serial)
 
     async def _async_get_status(self) -> dict[str, str]:
         """Get the ups status from NUT."""
diff --git a/homeassistant/components/nut/sensor.py b/homeassistant/components/nut/sensor.py
index 7f211d5452b..bb702873052 100644
--- a/homeassistant/components/nut/sensor.py
+++ b/homeassistant/components/nut/sensor.py
@@ -15,6 +15,7 @@ from homeassistant.components.sensor import (
 from homeassistant.const import (
     ATTR_MANUFACTURER,
     ATTR_MODEL,
+    ATTR_SERIAL_NUMBER,
     ATTR_SW_VERSION,
     PERCENTAGE,
     STATE_UNKNOWN,
@@ -42,6 +43,7 @@ NUT_DEV_INFO_TO_DEV_INFO: dict[str, str] = {
     "manufacturer": ATTR_MANUFACTURER,
     "model": ATTR_MODEL,
     "firmware": ATTR_SW_VERSION,
+    "serial": ATTR_SERIAL_NUMBER,
 }
 
 _LOGGER = logging.getLogger(__name__)
diff --git a/tests/components/nut/test_init.py b/tests/components/nut/test_init.py
index 61a5187407b..cd56c209a36 100644
--- a/tests/components/nut/test_init.py
+++ b/tests/components/nut/test_init.py
@@ -8,8 +8,9 @@ from homeassistant.components.nut.const import DOMAIN
 from homeassistant.config_entries import ConfigEntryState
 from homeassistant.const import CONF_HOST, CONF_PORT, STATE_UNAVAILABLE
 from homeassistant.core import HomeAssistant
+from homeassistant.helpers import device_registry as dr
 
-from .util import _get_mock_nutclient
+from .util import _get_mock_nutclient, async_init_integration
 
 from tests.common import MockConfigEntry
 
@@ -96,3 +97,26 @@ async def test_auth_fails(hass: HomeAssistant) -> None:
     flows = hass.config_entries.flow.async_progress()
     assert len(flows) == 1
     assert flows[0]["context"]["source"] == "reauth"
+
+
+async def test_serial_number(hass: HomeAssistant) -> None:
+    """Test for serial number set on device."""
+    mock_serial_number = "A00000000000"
+    await async_init_integration(
+        hass,
+        username="someuser",
+        password="somepassword",
+        list_vars={"ups.serial": mock_serial_number},
+        list_ups={"ups1": "UPS 1"},
+        list_commands_return_value=[],
+    )
+
+    device_registry = dr.async_get(hass)
+    assert device_registry is not None
+
+    device_entry = device_registry.async_get_device(
+        identifiers={(DOMAIN, mock_serial_number)}
+    )
+
+    assert device_entry is not None
+    assert device_entry.serial_number == mock_serial_number