Skip to content

Commit

Permalink
added sending sms and router data fetching switch
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexandrErohin committed Nov 19, 2024
1 parent 590246d commit 348cb54
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 4 deletions.
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ See [Supported routers](#supports)

### Switches
- Router Reboot
- Router data fetching - you may disable router data fetching before accessing the router, so it wont logging your out.
If you forget to enable it back - it would be automatically enable after 20 minutes
- 2.4Ghz host wifi Enable/Disable
- 5Ghz host wifi Enable/Disable
- 6Ghz host wifi Enable/Disable
Expand All @@ -42,6 +44,9 @@ To find your device - Go to `Developer tools` and search for your MAC address -

It will also fire Home Assistant event when a device connects to router

### Services
- Send SMS message - Available only for MR LTE routers

### Notification
To receive notifications of appearing a new device in your network, or becoming device online\offline add following lines to your `configuration.yaml` file:
```yaml
Expand All @@ -66,6 +71,20 @@ All available fields in `trigger.event.data`:
- packets_sent
- packets_received

### Send SMS only for MR LTE routers
To send SMS add following lines to your automation in yaml:
```yaml
...
action:
- service: tplink_router.send_sms
data:
number: ""pass phone number here"
text: "pass text here"
device: "pass tplink router device id here"
```

Device id is required because user may have several routers that could send SMS - so you need to select the needed router

## Installation

### HACS (recommended)
Expand Down Expand Up @@ -159,6 +178,7 @@ To do that:
- Archer C5400X V1
- Archer GX90 v1.0
- Archer MR200 (v5, v5.3)
- Archer MR550 v1
- Archer MR600 (v1, v2, v3)
- Archer VR600 v3
- Archer VR900v
Expand All @@ -180,6 +200,7 @@ To do that:
- TL-MR105
- TL-MR6400 (v5, v5.3)
- TL-MR6500v
- TL-XDR3010 V2
- TL-WA3001 v1.0

### Not fully tested Hardware Versions
Expand Down
31 changes: 30 additions & 1 deletion custom_components/tplink_router/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,13 @@
CONF_VERIFY_SSL,
Platform,
)
from homeassistant.core import HomeAssistant
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.config_entries import ConfigEntry
from .const import DOMAIN
import logging
from tplinkrouterc6u import TPLinkMRClient
from .coordinator import TPLinkRouterCoordinator
from homeassistant.helpers import device_registry
from .sensor import SENSOR_TYPES
from .button import BUTTON_TYPES
from .switch import SWITCH_TYPES
Expand Down Expand Up @@ -56,6 +58,8 @@ def callback():
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
entry.async_on_unload(entry.add_update_listener(async_reload_entry))

register_services(hass, coordinator)

return True


Expand All @@ -69,3 +73,28 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:

async def async_reload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> None:
await hass.config_entries.async_reload(config_entry.entry_id)

def register_services(hass: HomeAssistant, coord: TPLinkRouterCoordinator) -> None:

if not issubclass(coord.router.__class__, TPLinkMRClient):
return

dr = device_registry.async_get(hass)

async def send_sms_service(service: ServiceCall) -> None:
device_entry = dr.async_get(service.data.get("device"))
if device_entry is None:
_LOGGER.error('TplinkRouter Integration Exception - device was not found')
return
coordinator = hass.data[DOMAIN][list(device_entry.config_entries)[0]]

if not issubclass(coordinator.router.__class__, TPLinkMRClient):
_LOGGER.error('TplinkRouter Integration Exception - This device cannot send SMS')
return

def callback():
coord.router.send_sms(service.data.get("number"), service.data.get("text"))
await hass.async_add_executor_job(TPLinkRouterCoordinator.request, coord.router, callback)

if not hass.services.has_service(DOMAIN, 'send_sms'):
hass.services.async_register(DOMAIN, 'send_sms', send_sms_service)
7 changes: 6 additions & 1 deletion custom_components/tplink_router/coordinator.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from __future__ import annotations
from datetime import timedelta
from datetime import timedelta, datetime
from logging import Logger
from collections.abc import Callable
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator
Expand Down Expand Up @@ -37,6 +37,8 @@ def __init__(
hw_version=firmware.hardware_version,
)

self.scan_stopped_at: datetime|None = None

super().__init__(
hass,
logger,
Expand Down Expand Up @@ -69,5 +71,8 @@ def callback():

async def _async_update_data(self):
"""Asynchronous update of all data."""
if self.scan_stopped_at is not None and self.scan_stopped_at > (datetime.now() - timedelta(minutes=20)):
return
self.scan_stopped_at = None
self.status = await self.hass.async_add_executor_job(TPLinkRouterCoordinator.request, self.router,
self.router.get_status)
4 changes: 2 additions & 2 deletions custom_components/tplink_router/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@
"documentation": "https://github.com/AlexandrErohin/home-assistant-tplink-router",
"iot_class": "local_polling",
"issue_tracker": "https://github.com/AlexandrErohin/home-assistant-tplink-router/issues",
"requirements": ["tplinkrouterc6u==5.1.0"],
"version": "2.1.0"
"requirements": ["tplinkrouterc6u==5.3.0"],
"version": "2.2.0"
}
14 changes: 14 additions & 0 deletions custom_components/tplink_router/services.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
send_sms:
fields:
number:
required: true
selector:
text:
text:
required: true
selector:
text:
device:
required: true
selector:
device:
20 changes: 20 additions & 0 deletions custom_components/tplink_router/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,25 @@
}
}
}
},
"services": {
"send_sms": {
"name": "Send SMS",
"description": "Send SMS",
"fields": {
"number": {
"name": "Phone",
"description": "Phone number"
},
"text": {
"name": "Message",
"description": "Text"
},
"device": {
"name": "Router",
"description": "Select the TP-Link router to send sms"
}
}
}
}
}
37 changes: 37 additions & 0 deletions custom_components/tplink_router/switch.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from datetime import datetime
from typing import Any
from homeassistant.components.switch import SwitchEntity, SwitchEntityDescription
from homeassistant.config_entries import ConfigEntry
Expand Down Expand Up @@ -111,6 +112,9 @@ async def async_setup_entry(

for description in SWITCH_TYPES:
switches.append(TPLinkRouterSwitchEntity(coordinator, description))

switches.append(TPLinkRouterScanEntity(coordinator))

async_add_entities(switches, False)


Expand Down Expand Up @@ -151,3 +155,36 @@ async def async_turn_off(self, **kwargs: Any) -> None:
await self.entity_description.method(self.coordinator, False)
setattr(self.coordinator.status, self.entity_description.property, False)
self.async_write_ha_state()


class TPLinkRouterScanEntity(
CoordinatorEntity[TPLinkRouterCoordinator], SwitchEntity
):
entity_description: SwitchEntityDescription

def __init__(self, coordinator: TPLinkRouterCoordinator) -> None:
super().__init__(coordinator)

self._attr_device_info = coordinator.device_info
self.entity_description = SwitchEntityDescription(
key="scanning",
name="Router data fetching",
icon="mdi:connection",
entity_category=EntityCategory.CONFIG,
)
self._attr_unique_id = f"{coordinator.unique_id}_{DOMAIN}_{self.entity_description.key}"

@property
def is_on(self) -> bool:
"""Return true if switch is on."""
return self.coordinator.scan_stopped_at is None

async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn the entity on."""
self.coordinator.scan_stopped_at = None
self.async_write_ha_state()

async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn the entity off."""
self.coordinator.scan_stopped_at = datetime.now()
self.async_write_ha_state()
20 changes: 20 additions & 0 deletions custom_components/tplink_router/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,25 @@
}
}
}
},
"services": {
"send_sms": {
"name": "Send SMS",
"description": "Send SMS",
"fields": {
"number": {
"name": "Phone",
"description": "Phone number"
},
"text": {
"name": "Message",
"description": "Text"
},
"device": {
"name": "Router",
"description": "Select the TP-Link router to send sms"
}
}
}
}
}

0 comments on commit 348cb54

Please sign in to comment.