Skip to content

Commit

Permalink
added CPU and RAM sensors
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexandrErohin committed Dec 11, 2023
1 parent dca4279 commit c4cac38
Show file tree
Hide file tree
Showing 14 changed files with 83 additions and 36 deletions.
22 changes: 13 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ Home Assistant component for TP-Link router administration based on the [TP-Link

See [Supported routers](#supports)

<img src="https://raw.githubusercontent.com/AlexandrErohin/home-assistant-tplink-router/master/docs/media/sensor.png" width="48%"> <img src="https://raw.githubusercontent.com/AlexandrErohin/home-assistant-tplink-router/master/docs/media/switch.png" width="48%">
<img src="https://raw.githubusercontent.com/AlexandrErohin/home-assistant-tplink-router/master/docs/media/sensors.png" width="48%">

## Components
### Switches
Expand All @@ -18,6 +18,8 @@ See [Supported routers](#supports)
- Total amount of main wifi clients
- Total amount of guest wifi clients
- Total amount of all connected clients
- CPU used
- Memory used

### Device Tracker
- Track clients by MAC address across 2.4Ghz, 5Ghz guest and main wifi with connection information
Expand Down Expand Up @@ -45,30 +47,32 @@ Have [HACS](https://hacs.xyz/) installed, this will allow you to update easily.
## Configuration
TP-Link Router is configured via the GUI. See [the HA docs](https://www.home-assistant.io/getting-started/integration/) for more details.

The default data is preset already
The default data is preset already.

If you use `https` connection to your router you may get error `certificate verify failed: EE certificate key too weak`. To fix this - unset `Verify ssl`

<img src="https://raw.githubusercontent.com/AlexandrErohin/home-assistant-tplink-router/master/docs/media/config_flow.png" width="48%">

1. Go to the <b>Settings</b>-><b>Devices & services</b>.
2. Click on `+ ADD INTEGRATION`, search for `TP-Link Router`.
3. Fill IP address and Password.
3. Fill Password.
4. Click `SUBMIT`

## <a id="supports">Supported routers</a>
### Fully tested
- Archer AX10
- Archer C6
- Archer C6U
### Fully tested Hardware Versions
- Archer AX10 v1.0
- Archer C6 v2.0
- Archer C6U v1.0

### Not fully tested
### Not fully tested Hardware Versions
- AD7200 V2
- Archer A6 (V2 and V3)
- Archer A7 V5
- Archer A9 V6
- Archer A10 (V1 and V2)
- Archer A20 (V1, V3)
- Archer AX50 V1
- Archer AX3000 V1 (V2 - should work, but not have been tested)
- Archer AX3000 V1
- Archer AX6000 V1
- Archer C6 V4
- Archer C7 (V4 and V5)
Expand Down
8 changes: 6 additions & 2 deletions custom_components/tplink_router/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
CONF_PASSWORD,
CONF_USERNAME,
CONF_SCAN_INTERVAL,
CONF_VERIFY_SSL,
Platform,
)
from homeassistant.core import HomeAssistant
Expand All @@ -27,10 +28,13 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> b

# Construct the device
host = config_entry.data[CONF_HOST]
if not (host.startswith('http://') or host.startswith('https://')):
host = "http://{}".format(host)
password = config_entry.data[CONF_PASSWORD]
username = config_entry.data[CONF_USERNAME]
device = TplinkRouter(host, password, username, _LOGGER)
info = await device.get_full_info()
verify_ssl = config_entry.data[CONF_VERIFY_SSL] if CONF_VERIFY_SSL in config_entry.data else True
device = TplinkRouter(host, password, username, _LOGGER, verify_ssl)
info = await hass.async_add_executor_job(device.get_full_info)

# Create device coordinator and fetch data
coord = TPLinkRouterCoordinator(hass, device, config_entry.data[CONF_SCAN_INTERVAL], info, _LOGGER)
Expand Down
7 changes: 3 additions & 4 deletions custom_components/tplink_router/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import DOMAIN
from .coordinator import TPLinkRouterCoordinator
from tplinkrouterc6u import TplinkRouter
from homeassistant.helpers.device_registry import DeviceInfo


@dataclass
class TPLinkRouterButtonEntityDescriptionMixin:
method: Callable[[TplinkRouter], Any]
method: Callable[[TPLinkRouterCoordinator], Any]


@dataclass
Expand All @@ -38,7 +37,7 @@ class TPLinkButtonEntityDescription(
name="Reboot",
device_class=ButtonDeviceClass.RESTART,
entity_category=EntityCategory.CONFIG,
method=lambda router: router.reboot(),
method=lambda coordinator: coordinator.reboot(),
),
)

Expand Down Expand Up @@ -74,4 +73,4 @@ def __init__(

async def async_press(self) -> None:
"""Execute the button action."""
await self.entity_description.method(self.coordinator.router)
await self.entity_description.method(self.coordinator)
19 changes: 14 additions & 5 deletions custom_components/tplink_router/config_flow.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,24 @@

import voluptuous as vol
from homeassistant import config_entries
import homeassistant.helpers.config_validation as cv
from .const import DOMAIN
from homeassistant.const import (
CONF_HOST,
CONF_PASSWORD,
CONF_USERNAME,
CONF_SCAN_INTERVAL,
CONF_VERIFY_SSL,
)
from tplinkrouterc6u import TplinkRouter

STEP_USER_DATA_SCHEMA = vol.Schema(
{
vol.Required(CONF_HOST, default='192.168.0.1'): str,
vol.Required(CONF_USERNAME, default='admin'): str,
vol.Required(CONF_PASSWORD): str,
vol.Required(CONF_HOST, default='http://192.168.0.1'): str,
vol.Required(CONF_USERNAME, default='admin'): cv.string,
vol.Required(CONF_PASSWORD): cv.string,
vol.Required(CONF_SCAN_INTERVAL, default=30): int,
vol.Required(CONF_VERIFY_SSL, default=True): cv.boolean,
}
)

Expand All @@ -30,9 +33,15 @@ async def async_step_user(self, user_input=None):
"""Handle the initial step."""
errors = {}
if user_input is not None:
router = TplinkRouter(user_input[CONF_HOST],user_input[CONF_PASSWORD], user_input[CONF_USERNAME], _LOGGER)
router = TplinkRouter(
user_input[CONF_HOST],
user_input[CONF_PASSWORD],
user_input[CONF_USERNAME],
_LOGGER,
user_input[CONF_VERIFY_SSL],
)
try:
await router.test_connect()
await self.hass.async_add_executor_job(router.test_connect)
return self.async_create_entry(title=user_input["host"], data=user_input)
except Exception as error:
_LOGGER.error(error)
Expand Down
10 changes: 8 additions & 2 deletions custom_components/tplink_router/coordinator.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from datetime import timedelta
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
from tplinkrouterc6u import TplinkRouter, Firmware, Status
from tplinkrouterc6u import TplinkRouter, Firmware, Status, Wifi
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, DeviceInfo
from .const import DOMAIN
Expand Down Expand Up @@ -36,6 +36,12 @@ def __init__(
update_interval=timedelta(seconds=update_interval),
)

async def reboot(self) -> None:
await self.hass.async_add_executor_job(self.router.reboot)

async def set_wifi(self, wifi: Wifi, enable: bool) -> None:
await self.hass.async_add_executor_job(self.router.set_wifi, wifi, enable)

async def _async_update_data(self):
"""Asynchronous update of all data."""
self.status = await self.router.get_status()
self.status = await self.hass.async_add_executor_job(self.router.get_status)
8 changes: 5 additions & 3 deletions custom_components/tplink_router/manifest.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
{
"domain": "tplink_router",
"name": "TP-Link Router",
"documentation": "https://github.com/AlexandrErohin/home-assistant-tplink_router",
"requirements": ["tplinkrouterc6u>=0.0.1"],
"version": "0.0.2",
"documentation": "https://github.com/AlexandrErohin/home-assistant-tplink-router",
"issue_tracker": "https://github.com/AlexandrErohin/home-assistant-tplink-router/issues",
"iot_class": "local_polling",
"requirements": ["tplinkrouterc6u>=1.0.0"],
"version": "1.0.0",
"config_flow": true,
"codeowners": ["@AlexandrErohin"]
}
Expand Down
21 changes: 21 additions & 0 deletions custom_components/tplink_router/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@
from collections.abc import Callable
from typing import Any
from homeassistant.components.sensor import (
SensorDeviceClass,
SensorStateClass,
SensorEntity,
SensorEntityDescription,
)
from homeassistant.const import PERCENTAGE, UnitOfInformation
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.device_registry import DeviceInfo
Expand Down Expand Up @@ -55,6 +57,25 @@ class TPLinkRouterSensorEntityDescription(SensorEntityDescription, TPLinkRouterS
state_class=SensorStateClass.TOTAL,
value=lambda status: status.clients_total,
),
TPLinkRouterSensorEntityDescription(
key="cpu_used",
name="CPU used",
icon="mdi:cpu-64-bit",
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=PERCENTAGE,
suggested_display_precision=1,
value=lambda status: (status.cpu_usage * 100) if status.cpu_usage >= 0 else 0,
),
TPLinkRouterSensorEntityDescription(
key="memory_used",
name="Memory used",
icon="mdi:memory",
native_unit_of_measurement=UnitOfInformation.MEGABYTES,
device_class=SensorDeviceClass.DATA_SIZE,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=2,
value=lambda status: status.mem_usage,
),
)


Expand Down
3 changes: 2 additions & 1 deletion custom_components/tplink_router/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"host": "[%key:common::config_flow::data::host%]",
"username": "[%key:common::config_flow::data::username%]",
"password": "[%key:common::config_flow::data::password%]",
"scan_interval": "[%key:common::config_flow::data::scan_interval%]"
"scan_interval": "[%key:common::config_flow::data::scan_interval%]",
"verify_ssl": "[%key:common::config_flow::data::verify_ssl%]"
}
}
}
Expand Down
16 changes: 8 additions & 8 deletions custom_components/tplink_router/switch.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,13 @@
from .const import DOMAIN
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .coordinator import TPLinkRouterCoordinator
from tplinkrouterc6u import TplinkRouter, Wifi, Status
from tplinkrouterc6u import Wifi, Status
from homeassistant.helpers.device_registry import DeviceInfo


@dataclass
class TPLinkRouterSwitchEntityDescriptionMixin:
method: Callable[[TplinkRouter, bool], Any]
method: Callable[[TPLinkRouterCoordinator, bool], Any]
property: str


Expand All @@ -32,31 +32,31 @@ class TPLinkRouterSwitchEntityDescription(SwitchEntityDescription, TPLinkRouterS
icon="mdi:wifi",
entity_category=EntityCategory.CONFIG,
property='guest_2g_enable',
method=lambda router, value: router.set_wifi(Wifi.WIFI_GUEST_2G, value),
method=lambda coordinator, value: coordinator.set_wifi(Wifi.WIFI_GUEST_2G, value),
),
TPLinkRouterSwitchEntityDescription(
key="wifi_guest_5g",
name="Guest WIFI 5G",
icon="mdi:wifi",
entity_category=EntityCategory.CONFIG,
property='guest_5g_enable',
method=lambda router, value: router.set_wifi(Wifi.WIFI_GUEST_5G, value),
method=lambda coordinator, value: coordinator.set_wifi(Wifi.WIFI_GUEST_5G, value),
),
TPLinkRouterSwitchEntityDescription(
key="wifi_24g",
name="WIFI 2.4G",
icon="mdi:wifi",
entity_category=EntityCategory.CONFIG,
property='wifi_2g_enable',
method=lambda router, value: router.set_wifi(Wifi.WIFI_2G, value),
method=lambda coordinator, value: coordinator.set_wifi(Wifi.WIFI_2G, value),
),
TPLinkRouterSwitchEntityDescription(
key="wifi_5g",
name="WIFI 5G",
icon="mdi:wifi",
entity_category=EntityCategory.CONFIG,
property='wifi_5g_enable',
method=lambda router, value: router.set_wifi(Wifi.WIFI_5G, value),
method=lambda coordinator, value: coordinator.set_wifi(Wifi.WIFI_5G, value),
),
)

Expand Down Expand Up @@ -99,12 +99,12 @@ def is_on(self) -> bool:

async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the entity on."""
await self.entity_description.method(self.coordinator.router, True)
await self.entity_description.method(self.coordinator, True)
setattr(self.coordinator.status, self.entity_description.property, True)
self.async_write_ha_state()

async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the entity off."""
await self.entity_description.method(self.coordinator.router, False)
await self.entity_description.method(self.coordinator, False)
setattr(self.coordinator.status, self.entity_description.property, False)
self.async_write_ha_state()
5 changes: 3 additions & 2 deletions custom_components/tplink_router/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@
"user": {
"description": "Integration config",
"data": {
"host": "IP address",
"host": "Host",
"username": "Login",
"password": "Password",
"scan_interval": "Scan interval for updates in seconds"
"scan_interval": "Scan interval for updates in seconds",
"verify_ssl": "Verify ssl for https connection"
}
}
}
Expand Down
Binary file modified docs/media/config_flow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed docs/media/sensor.png
Binary file not shown.
Binary file added docs/media/sensors.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed docs/media/switch.png
Binary file not shown.

0 comments on commit c4cac38

Please sign in to comment.