diff --git a/homeassistant/components/tplink_omada/__init__.py b/homeassistant/components/tplink_omada/__init__.py
index 709ad52012590d74fd35b69cf063817149b55158..824ea8df423916f0616c25d20071b5348e655330 100644
--- a/homeassistant/components/tplink_omada/__init__.py
+++ b/homeassistant/components/tplink_omada/__init__.py
@@ -44,7 +44,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
             f"Unexpected error connecting to Omada controller: {ex}"
         ) from ex
 
-    site_client = await client.get_site_client(OmadaSite(None, entry.data[CONF_SITE]))
+    site_client = await client.get_site_client(OmadaSite("", entry.data[CONF_SITE]))
     controller = OmadaSiteController(hass, site_client)
     hass.data[DOMAIN][entry.entry_id] = controller
 
diff --git a/homeassistant/components/tplink_omada/controller.py b/homeassistant/components/tplink_omada/controller.py
index b42cb37ff76fcb4d1bde224d2a121ba252c2eea1..508a8b914da958e4d501176533da0045aef02e18 100644
--- a/homeassistant/components/tplink_omada/controller.py
+++ b/homeassistant/components/tplink_omada/controller.py
@@ -1,7 +1,5 @@
 """Controller for sharing Omada API coordinators between platforms."""
 
-from functools import partial
-
 from tplink_omada_client.devices import OmadaSwitch, OmadaSwitchPortDetails
 from tplink_omada_client.omadasiteclient import OmadaSiteClient
 
@@ -9,13 +7,28 @@ from homeassistant.core import HomeAssistant
 
 from .coordinator import OmadaCoordinator
 
+POLL_SWITCH_PORT = 300
+
+
+class OmadaSwitchPortCoordinator(OmadaCoordinator[OmadaSwitchPortDetails]):
+    """Coordinator for getting details about ports on a switch."""
+
+    def __init__(
+        self,
+        hass: HomeAssistant,
+        omada_client: OmadaSiteClient,
+        network_switch: OmadaSwitch,
+    ) -> None:
+        """Initialize my coordinator."""
+        super().__init__(
+            hass, omada_client, f"{network_switch.name} Ports", POLL_SWITCH_PORT
+        )
+        self._network_switch = network_switch
 
-async def _poll_switch_state(
-    client: OmadaSiteClient, network_switch: OmadaSwitch
-) -> dict[str, OmadaSwitchPortDetails]:
-    """Poll a switch's current state."""
-    ports = await client.get_switch_ports(network_switch)
-    return {p.port_id: p for p in ports}
+    async def poll_update(self) -> dict[str, OmadaSwitchPortDetails]:
+        """Poll a switch's current state."""
+        ports = await self.omada_client.get_switch_ports(self._network_switch)
+        return {p.port_id: p for p in ports}
 
 
 class OmadaSiteController:
@@ -26,9 +39,7 @@ class OmadaSiteController:
         self._hass = hass
         self._omada_client = omada_client
 
-        self._switch_port_coordinators: dict[
-            str, OmadaCoordinator[OmadaSwitchPortDetails]
-        ] = {}
+        self._switch_port_coordinators: dict[str, OmadaSwitchPortCoordinator] = {}
 
     @property
     def omada_client(self) -> OmadaSiteClient:
@@ -37,16 +48,11 @@ class OmadaSiteController:
 
     def get_switch_port_coordinator(
         self, switch: OmadaSwitch
-    ) -> OmadaCoordinator[OmadaSwitchPortDetails]:
+    ) -> OmadaSwitchPortCoordinator:
         """Get coordinator for network port information of a given switch."""
         if switch.mac not in self._switch_port_coordinators:
-            self._switch_port_coordinators[switch.mac] = OmadaCoordinator[
-                OmadaSwitchPortDetails
-            ](
-                self._hass,
-                self._omada_client,
-                f"{switch.name} Ports",
-                partial(_poll_switch_state, network_switch=switch),
+            self._switch_port_coordinators[switch.mac] = OmadaSwitchPortCoordinator(
+                self._hass, self._omada_client, switch
             )
 
         return self._switch_port_coordinators[switch.mac]
diff --git a/homeassistant/components/tplink_omada/coordinator.py b/homeassistant/components/tplink_omada/coordinator.py
index d73461dc786b54a7e155cf50aa59442a8631b33d..3ff73501bdc04554d40423a876fe2b015273fa64 100644
--- a/homeassistant/components/tplink_omada/coordinator.py
+++ b/homeassistant/components/tplink_omada/coordinator.py
@@ -1,5 +1,4 @@
 """Generic Omada API coordinator."""
-from collections.abc import Awaitable, Callable
 from datetime import timedelta
 import logging
 from typing import Generic, TypeVar
@@ -24,7 +23,6 @@ class OmadaCoordinator(DataUpdateCoordinator[dict[str, T]], Generic[T]):
         hass: HomeAssistant,
         omada_client: OmadaSiteClient,
         name: str,
-        update_func: Callable[[OmadaSiteClient], Awaitable[dict[str, T]]],
         poll_delay: int = 300,
     ) -> None:
         """Initialize my coordinator."""
@@ -35,12 +33,15 @@ class OmadaCoordinator(DataUpdateCoordinator[dict[str, T]], Generic[T]):
             update_interval=timedelta(seconds=poll_delay),
         )
         self.omada_client = omada_client
-        self._update_func = update_func
 
     async def _async_update_data(self) -> dict[str, T]:
         """Fetch data from API endpoint."""
         try:
             async with async_timeout.timeout(10):
-                return await self._update_func(self.omada_client)
+                return await self.poll_update()
         except OmadaClientException as err:
             raise UpdateFailed(f"Error communicating with API: {err}") from err
+
+    async def poll_update(self) -> dict[str, T]:
+        """Poll the current data from the controller."""
+        raise NotImplementedError("Update method not implemented")
diff --git a/homeassistant/components/tplink_omada/manifest.json b/homeassistant/components/tplink_omada/manifest.json
index a0fb58b3f6c66cc8fac7080cac5ceeb3da4850f1..9d7234077645d6615c1f8fd77e0af736db90af30 100644
--- a/homeassistant/components/tplink_omada/manifest.json
+++ b/homeassistant/components/tplink_omada/manifest.json
@@ -6,5 +6,5 @@
   "documentation": "https://www.home-assistant.io/integrations/tplink_omada",
   "integration_type": "hub",
   "iot_class": "local_polling",
-  "requirements": ["tplink-omada-client==1.1.3"]
+  "requirements": ["tplink-omada-client==1.1.4"]
 }
diff --git a/homeassistant/components/tplink_omada/switch.py b/homeassistant/components/tplink_omada/switch.py
index e85b1c181fcd6c7e13aac3dbeff43f1141338072..830f75b6a936ca7da1821e4ed77f32e23b67e9c2 100644
--- a/homeassistant/components/tplink_omada/switch.py
+++ b/homeassistant/components/tplink_omada/switch.py
@@ -14,8 +14,7 @@ from homeassistant.core import HomeAssistant, callback
 from homeassistant.helpers.entity_platform import AddEntitiesCallback
 
 from .const import DOMAIN
-from .controller import OmadaSiteController
-from .coordinator import OmadaCoordinator
+from .controller import OmadaSiteController, OmadaSwitchPortCoordinator
 from .entity import OmadaDeviceEntity
 
 POE_SWITCH_ICON = "mdi:ethernet"
@@ -68,7 +67,7 @@ class OmadaNetworkSwitchPortPoEControl(
 
     def __init__(
         self,
-        coordinator: OmadaCoordinator[OmadaSwitchPortDetails],
+        coordinator: OmadaSwitchPortCoordinator,
         device: OmadaSwitch,
         port_id: str,
     ) -> None:
diff --git a/homeassistant/components/tplink_omada/update.py b/homeassistant/components/tplink_omada/update.py
index 5581f61d824a49c44e0ba34e298e45258552511f..685ad9c57614f6a20f69c0bf74025029cacc07e0 100644
--- a/homeassistant/components/tplink_omada/update.py
+++ b/homeassistant/components/tplink_omada/update.py
@@ -1,24 +1,26 @@
-"""Support for TPLink Omada device toggle options."""
+"""Support for TPLink Omada device firmware updates."""
 from __future__ import annotations
 
-import logging
+from datetime import timedelta
 from typing import Any, NamedTuple
 
 from tplink_omada_client.devices import OmadaFirmwareUpdate, OmadaListDevice
+from tplink_omada_client.exceptions import OmadaClientException, RequestFailed
 from tplink_omada_client.omadasiteclient import OmadaSiteClient
 
 from homeassistant.components.update import UpdateEntity, UpdateEntityFeature
 from homeassistant.config_entries import ConfigEntry
 from homeassistant.core import HomeAssistant, callback
+from homeassistant.exceptions import HomeAssistantError
 from homeassistant.helpers.entity_platform import AddEntitiesCallback
-from homeassistant.helpers.event import async_call_later
 
 from .const import DOMAIN
 from .controller import OmadaSiteController
 from .coordinator import OmadaCoordinator
 from .entity import OmadaDeviceEntity
 
-_LOGGER = logging.getLogger(__name__)
+POLL_DELAY_IDLE = 6 * 60 * 60
+POLL_DELAY_UPGRADE = 60
 
 
 class FirmwareUpdateStatus(NamedTuple):
@@ -28,24 +30,39 @@ class FirmwareUpdateStatus(NamedTuple):
     firmware: OmadaFirmwareUpdate | None
 
 
-async def _get_firmware_updates(client: OmadaSiteClient) -> list[FirmwareUpdateStatus]:
-    devices = await client.get_devices()
-    return [
-        FirmwareUpdateStatus(
-            device=d,
-            firmware=None
-            if not d.need_upgrade
-            else await client.get_firmware_details(d),
+class OmadaFirmwareUpdateCoodinator(OmadaCoordinator[FirmwareUpdateStatus]):
+    """Coordinator for getting details about ports on a switch."""
+
+    def __init__(self, hass: HomeAssistant, omada_client: OmadaSiteClient) -> None:
+        """Initialize my coordinator."""
+        super().__init__(hass, omada_client, "Firmware Updates", POLL_DELAY_IDLE)
+
+    async def _get_firmware_updates(self) -> list[FirmwareUpdateStatus]:
+        devices = await self.omada_client.get_devices()
+
+        updates = [
+            FirmwareUpdateStatus(
+                device=d,
+                firmware=None
+                if not d.need_upgrade
+                else await self.omada_client.get_firmware_details(d),
+            )
+            for d in devices
+        ]
+
+        # During a firmware upgrade, poll more frequently
+        self.update_interval = timedelta(
+            seconds=(
+                POLL_DELAY_UPGRADE
+                if any(u.device.fw_download for u in updates)
+                else POLL_DELAY_IDLE
+            )
         )
-        for d in devices
-    ]
+        return updates
 
-
-async def _poll_firmware_updates(
-    client: OmadaSiteClient,
-) -> dict[str, FirmwareUpdateStatus]:
-    """Poll the state of Omada Devices firmware update availability."""
-    return {d.device.mac: d for d in await _get_firmware_updates(client)}
+    async def poll_update(self) -> dict[str, FirmwareUpdateStatus]:
+        """Poll the state of Omada Devices firmware update availability."""
+        return {d.device.mac: d for d in await self._get_firmware_updates()}
 
 
 async def async_setup_entry(
@@ -59,19 +76,9 @@ async def async_setup_entry(
 
     devices = await omada_client.get_devices()
 
-    coordinator = OmadaCoordinator[FirmwareUpdateStatus](
-        hass,
-        omada_client,
-        "Firmware Updates",
-        _poll_firmware_updates,
-        poll_delay=6 * 60 * 60,
-    )
-
-    entities: list = []
-    for device in devices:
-        entities.append(OmadaDeviceUpdate(coordinator, device))
+    coordinator = OmadaFirmwareUpdateCoodinator(hass, omada_client)
 
-    async_add_entities(entities)
+    async_add_entities(OmadaDeviceUpdate(coordinator, device) for device in devices)
     await coordinator.async_request_refresh()
 
 
@@ -86,64 +93,57 @@ class OmadaDeviceUpdate(
         | UpdateEntityFeature.PROGRESS
         | UpdateEntityFeature.RELEASE_NOTES
     )
-    _firmware_update: OmadaFirmwareUpdate = None
+    _attr_has_entity_name = True
+    _attr_name = "Firmware update"
 
     def __init__(
         self,
-        coordinator: OmadaCoordinator[FirmwareUpdateStatus],
+        coordinator: OmadaFirmwareUpdateCoodinator,
         device: OmadaListDevice,
     ) -> None:
         """Initialize the update entity."""
         super().__init__(coordinator, device)
 
         self._mac = device.mac
-        self._device = device
         self._omada_client = coordinator.omada_client
 
         self._attr_unique_id = f"{device.mac}_firmware"
-        self._attr_has_entity_name = True
-        self._attr_name = "Firmware Update"
-        self._refresh_state()
-
-    def _refresh_state(self) -> None:
-        if self._firmware_update and self._device.need_upgrade:
-            self._attr_installed_version = self._firmware_update.current_version
-            self._attr_latest_version = self._firmware_update.latest_version
-        else:
-            self._attr_installed_version = self._device.firmware_version
-            self._attr_latest_version = self._device.firmware_version
-        self._attr_in_progress = self._device.fw_download
-
-        if self._attr_in_progress:
-            # While firmware update is in progress, poll more frequently
-            async_call_later(self.hass, 60, self._request_refresh)
-
-    async def _request_refresh(self, _now: Any) -> None:
-        await self.coordinator.async_request_refresh()
 
     def release_notes(self) -> str | None:
         """Get the release notes for the latest update."""
-        if self._firmware_update:
-            return str(self._firmware_update.release_notes)
-        return ""
+        status = self.coordinator.data[self._mac]
+        if status.firmware:
+            return status.firmware.release_notes
+        return None
 
     async def async_install(
         self, version: str | None, backup: bool, **kwargs: Any
     ) -> None:
         """Install a firmware update."""
-        if self._firmware_update and (
-            version is None or self._firmware_update.latest_version == version
-        ):
-            await self._omada_client.start_firmware_upgrade(self._device)
+        try:
+            await self._omada_client.start_firmware_upgrade(
+                self.coordinator.data[self._mac].device
+            )
+        except RequestFailed as ex:
+            raise HomeAssistantError("Firmware update request rejected") from ex
+        except OmadaClientException as ex:
+            raise HomeAssistantError(
+                "Unable to send Firmware update request. Check the controller is online."
+            ) from ex
+        finally:
             await self.coordinator.async_request_refresh()
-        else:
-            _LOGGER.error("Firmware upgrade is not available for %s", self._device.name)
 
     @callback
     def _handle_coordinator_update(self) -> None:
         """Handle updated data from the coordinator."""
         status = self.coordinator.data[self._mac]
-        self._device = status.device
-        self._firmware_update = status.firmware
-        self._refresh_state()
+
+        if status.firmware and status.device.need_upgrade:
+            self._attr_installed_version = status.firmware.current_version
+            self._attr_latest_version = status.firmware.latest_version
+        else:
+            self._attr_installed_version = status.device.firmware_version
+            self._attr_latest_version = status.device.firmware_version
+        self._attr_in_progress = status.device.fw_download
+
         self.async_write_ha_state()
diff --git a/requirements_all.txt b/requirements_all.txt
index 45d6c88ae8f8555b40c3916324e13c11327bac1a..1560012227f8b1ac687976da3e4cefec14666d38 100644
--- a/requirements_all.txt
+++ b/requirements_all.txt
@@ -2521,7 +2521,7 @@ total_connect_client==2023.2
 tp-connected==0.0.4
 
 # homeassistant.components.tplink_omada
-tplink-omada-client==1.1.3
+tplink-omada-client==1.1.4
 
 # homeassistant.components.transmission
 transmission-rpc==3.4.0
diff --git a/requirements_test_all.txt b/requirements_test_all.txt
index 2da989a58a3c471b54ff75ddccd8ef5d00ad2958..e1235f47340c14e348f56e4c9375bbdd600739bf 100644
--- a/requirements_test_all.txt
+++ b/requirements_test_all.txt
@@ -1788,7 +1788,7 @@ toonapi==0.2.1
 total_connect_client==2023.2
 
 # homeassistant.components.tplink_omada
-tplink-omada-client==1.1.3
+tplink-omada-client==1.1.4
 
 # homeassistant.components.transmission
 transmission-rpc==3.4.0