Skip to content

Commit cc8a1b3

Browse files
committed
Create coordinator
1 parent 8b88717 commit cc8a1b3

File tree

9 files changed

+130
-44
lines changed

9 files changed

+130
-44
lines changed

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,9 @@ Telekom Speedport Integration for Home Assistant based on [speedport-api](https:
99
| ⚠️ **Work in progress...** ⚠️ |
1010
|------------------------------|
1111

12-
Currently, this integration can be used to track devices in network.
13-
12+
- Track presence of connected devices
13+
- Turn on/off wifi (guest/office/normal)
14+
- Reconnect, reboot, wps on
1415

1516
## Installation
1617
#### Installing via HACS

custom_components/speedport/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
2020
host=entry.data["host"], password=entry.data["password"], session=session
2121
).create()
2222
hass.data[DOMAIN][entry.entry_id] = speedport
23+
hass.data[DOMAIN]["coordinators"] = {}
2324

2425
for platform in PLATFORMS:
2526
hass.async_create_task(

custom_components/speedport/button.py

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
from homeassistant.core import HomeAssistant
66
from homeassistant.helpers.entity import EntityCategory
77
from homeassistant.helpers.entity_platform import AddEntitiesCallback
8+
from homeassistant.helpers.typing import HomeAssistantType
89
from speedport import Speedport
910

1011
from .const import DOMAIN
12+
from .device import SpeedportEntity
1113

1214

1315
async def async_setup_entry(
@@ -18,53 +20,56 @@ async def async_setup_entry(
1820
coordinator = hass.data[DOMAIN][entry.entry_id]
1921
async_add_entities(
2022
[
21-
SpeedportReconnectButton(coordinator),
22-
SpeedportRebootButton(coordinator),
23-
SpeedportWPSButton(coordinator),
23+
SpeedportReconnectButton(hass, coordinator),
24+
SpeedportRebootButton(hass, coordinator),
25+
SpeedportWPSButton(hass, coordinator),
2426
]
2527
)
2628

2729

28-
class SpeedportReconnectButton(ButtonEntity):
30+
class SpeedportReconnectButton(ButtonEntity, SpeedportEntity):
2931
_attr_device_class = ButtonDeviceClass.RESTART
3032
_attr_entity_category = EntityCategory.CONFIG
31-
_attr_name = "Reconnect"
3233

33-
def __init__(self, coordinator) -> None:
34+
def __init__(self, hass: HomeAssistantType, speedport: Speedport) -> None:
3435
"""Initialize the button entity."""
35-
self.coordinator = coordinator
36+
super().__init__(hass, speedport)
37+
self._attr_name = "Reconnect"
38+
self._speedport = speedport
3639
self._attr_unique_id = "speedport_reconnect"
3740

3841
async def async_press(self) -> None:
3942
"""Send out a restart command."""
40-
await self.coordinator.reconnect()
43+
await self._speedport.reconnect()
4144

4245

43-
class SpeedportRebootButton(ButtonEntity):
46+
class SpeedportRebootButton(ButtonEntity, SpeedportEntity):
4447
_attr_device_class = ButtonDeviceClass.RESTART
4548
_attr_entity_category = EntityCategory.CONFIG
46-
_attr_name = "Reboot"
4749

48-
def __init__(self, coordinator) -> None:
50+
def __init__(self, hass: HomeAssistantType, speedport: Speedport) -> None:
4951
"""Initialize the button entity."""
50-
self.coordinator = coordinator
52+
super().__init__(hass, speedport)
53+
self._attr_name = "Reboot"
54+
self._speedport = speedport
5155
self._attr_unique_id = "speedport_reboot"
5256

5357
async def async_press(self) -> None:
5458
"""Send out a restart command."""
55-
await self.coordinator.reboot()
59+
await self._speedport.reboot()
5660

5761

58-
class SpeedportWPSButton(ButtonEntity):
62+
class SpeedportWPSButton(ButtonEntity, SpeedportEntity):
5963
_attr_device_class = ButtonDeviceClass.IDENTIFY
6064
_attr_entity_category = EntityCategory.CONFIG
61-
_attr_name = "WPS on"
6265

63-
def __init__(self, coordinator) -> None:
66+
def __init__(self, hass: HomeAssistantType, speedport: Speedport) -> None:
6467
"""Initialize the button entity."""
65-
self.coordinator: Speedport = coordinator
68+
super().__init__(hass, speedport)
69+
self._attr_name = "WPS on"
70+
self._speedport: Speedport = speedport
6671
self._attr_unique_id = "speedport_wps"
6772

6873
async def async_press(self) -> None:
6974
"""Send out a restart command."""
70-
await self.coordinator.wps_on()
75+
await self._speedport.wps_on()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
"""Constants for the Speedport integration."""
22

33
DOMAIN = "speedport"
4+
UPDATE_INTERVAL = 5
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import logging
2+
from datetime import timedelta
3+
4+
from homeassistant.core import callback
5+
from homeassistant.helpers.device_registry import DeviceInfo
6+
from homeassistant.helpers.typing import HomeAssistantType
7+
from homeassistant.helpers.update_coordinator import (
8+
DataUpdateCoordinator,
9+
CoordinatorEntity,
10+
)
11+
from speedport import Speedport
12+
13+
from .const import DOMAIN, UPDATE_INTERVAL
14+
15+
_LOGGER = logging.getLogger(__name__)
16+
17+
18+
class SpeedportCoordinator(DataUpdateCoordinator[None]):
19+
def __init__(self, hass: HomeAssistantType, device: Speedport):
20+
"""Initialize my coordinator."""
21+
22+
super().__init__(
23+
hass,
24+
_LOGGER,
25+
name=device.device_name,
26+
update_interval=timedelta(seconds=UPDATE_INTERVAL),
27+
)
28+
self._device = device
29+
30+
async def _async_update_data(self) -> None:
31+
return await self._device.update_status()
32+
33+
34+
class SpeedportEntity(CoordinatorEntity[SpeedportCoordinator]):
35+
_attr_has_entity_name = True
36+
37+
def __init__(self, hass: HomeAssistantType, speedport: Speedport) -> None:
38+
coordinator = get_coordinator(hass, speedport)
39+
super().__init__(coordinator)
40+
41+
self._coordinator = coordinator
42+
self._speedport: Speedport = speedport
43+
44+
@property
45+
def device_info(self) -> DeviceInfo:
46+
return DeviceInfo(
47+
identifiers={(DOMAIN, self._speedport.serial_number)},
48+
manufacturer="Telekom",
49+
name="Speedport",
50+
model=self._speedport.device_name,
51+
sw_version=self._speedport.firmware_version,
52+
configuration_url=self._speedport.api.url,
53+
)
54+
55+
@callback
56+
def _handle_coordinator_update(self) -> None:
57+
self.async_write_ha_state()
58+
59+
60+
def get_coordinator(
61+
hass: HomeAssistantType, speedport: Speedport
62+
) -> SpeedportCoordinator:
63+
coordinators = hass.data[DOMAIN]["coordinators"]
64+
if speedport.serial_number in coordinators:
65+
coordinator: SpeedportCoordinator = hass.data[DOMAIN]["coordinators"][
66+
speedport.serial_number
67+
]
68+
else:
69+
coordinator = SpeedportCoordinator(hass, speedport)
70+
hass.data[DOMAIN]["coordinators"][speedport.serial_number] = coordinator
71+
return coordinator

custom_components/speedport/manifest.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
"iot_class": "local_polling",
1313
"issue_tracker": "https://github.com/Andre0512/speedport/issues",
1414
"requirements": [
15-
"speedport-api==0.5.0"
15+
"speedport-api==0.5.1"
1616
],
17-
"version": "0.2.0"
17+
"version": "0.2.1"
1818
}

custom_components/speedport/switch.py

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@
33
import logging
44
from typing import Any
55

6-
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
6+
from homeassistant.components.switch import SwitchEntity
77
from homeassistant.config_entries import ConfigEntry
88
from homeassistant.core import HomeAssistant
99
from homeassistant.helpers.entity_platform import AddEntitiesCallback
10+
from homeassistant.helpers.typing import HomeAssistantType
1011
from speedport import Speedport
1112

1213
from .const import DOMAIN
14+
from .device import SpeedportEntity
1315

1416
_LOGGER = logging.getLogger(__name__)
1517

@@ -23,23 +25,25 @@ async def async_setup_entry(
2325
await speedport.update_status()
2426
async_add_entities(
2527
[
26-
SpeedportWifiSwitch(speedport),
27-
SpeedportGuestWifiSwitch(speedport),
28-
SpeedportOfficeWifiSwitch(speedport),
28+
SpeedportWifiSwitch(hass, speedport),
29+
SpeedportGuestWifiSwitch(hass, speedport),
30+
SpeedportOfficeWifiSwitch(hass, speedport),
2931
]
3032
)
3133

3234

33-
class SpeedportWifiSwitch(SwitchEntity):
35+
class SpeedportWifiSwitch(SwitchEntity, SpeedportEntity):
3436
_attr_is_on: bool | None = False
3537

36-
def __init__(self, speedport: Speedport) -> None:
38+
def __init__(self, hass: HomeAssistantType, speedport: Speedport) -> None:
39+
super().__init__(hass, speedport)
3740
self._speedport: Speedport = speedport
3841
self._attr_icon = "mdi:wifi"
39-
self._attr_name = speedport.wlan_ssid
42+
self._attr_name = f"WLAN {speedport.wlan_ssid}"
4043
self._attr_unique_id = "wifi"
4144

42-
async def is_on(self) -> bool | None:
45+
@property
46+
def is_on(self) -> bool | None:
4347
return self._speedport.wlan_active
4448

4549
async def async_turn_on(self, **kwargs: Any) -> None:
@@ -51,16 +55,18 @@ async def async_turn_off(self, **kwargs: Any) -> None:
5155
await self._speedport.wifi_off()
5256

5357

54-
class SpeedportGuestWifiSwitch(SwitchEntity):
58+
class SpeedportGuestWifiSwitch(SwitchEntity, SpeedportEntity):
5559
_attr_is_on: bool | None = False
5660

57-
def __init__(self, speedport: Speedport) -> None:
61+
def __init__(self, hass: HomeAssistantType, speedport: Speedport) -> None:
62+
super().__init__(hass, speedport)
5863
self._speedport: Speedport = speedport
5964
self._attr_icon = "mdi:wifi"
60-
self._attr_name = speedport.wlan_guest_ssid
65+
self._attr_name = f"WLAN {speedport.wlan_guest_ssid}"
6166
self._attr_unique_id = "wifi_guest"
6267

63-
async def is_on(self) -> bool | None:
68+
@property
69+
def is_on(self) -> bool | None:
6470
return self._speedport.wlan_guest_active
6571

6672
async def async_turn_on(self, **kwargs: Any) -> None:
@@ -72,16 +78,18 @@ async def async_turn_off(self, **kwargs: Any) -> None:
7278
await self._speedport.wifi_guest_off()
7379

7480

75-
class SpeedportOfficeWifiSwitch(SwitchEntity):
81+
class SpeedportOfficeWifiSwitch(SwitchEntity, SpeedportEntity):
7682
_attr_is_on: bool | None = False
7783

78-
def __init__(self, speedport: Speedport) -> None:
84+
def __init__(self, hass: HomeAssistantType, speedport: Speedport) -> None:
85+
super().__init__(hass, speedport)
7986
self._speedport: Speedport = speedport
8087
self._attr_icon = "mdi:wifi"
81-
self._attr_name = speedport.wlan_office_ssid
88+
self._attr_name = f"WLAN {speedport.wlan_office_ssid}"
8289
self._attr_unique_id = "wifi_office"
8390

84-
async def is_on(self) -> bool | None:
91+
@property
92+
def is_on(self) -> bool | None:
8593
return self._speedport.wlan_office_ssid
8694

8795
async def async_turn_on(self, **kwargs: Any) -> None:

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
speedport-api==0.5.0
1+
speedport-api==0.5.1
22
homeassistant~=2023.10

requirements_dev.txt

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
homeassistant~=2023.10.0
2-
black~=23.7.0
3-
flake8~=6.0.0
4-
mypy~=1.4.1
5-
pylint~=2.17.4
1+
black~=23.9
2+
flake8~=6.1
3+
mypy~=1.6
4+
pylint~=3.0

0 commit comments

Comments
 (0)