-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
256 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# Contribution guidelines | ||
|
||
Contributing to this project should be as easy and transparent as possible, whether it's: | ||
|
||
- Reporting a bug | ||
- Discussing the current state of the code | ||
- Submitting a fix | ||
- Proposing new features | ||
|
||
## Github is used for everything | ||
|
||
Github is used to host code, to track issues and feature requests, as well as accept pull requests. | ||
|
||
Pull requests are the best way to propose changes to the codebase. | ||
|
||
1. Fork the repo and create your branch from `master`. | ||
2. If you've changed something, update the documentation. | ||
3. Make sure your code lints (using black). | ||
4. Issue that pull request! | ||
|
||
## Any contributions you make will be under the MIT Software License | ||
|
||
In short, when you submit code changes, your submissions are understood to be under the same [MIT License](http://choosealicense.com/licenses/mit/) that covers the project. Feel free to contact the maintainers if that's a concern. | ||
|
||
## Report bugs using Github's [issues](../../issues) | ||
|
||
GitHub issues are used to track public bugs. | ||
Report a bug by [opening a new issue](../../issues/new/choose); it's that easy! | ||
|
||
## Write bug reports with detail, background, and sample code | ||
|
||
**Great Bug Reports** tend to have: | ||
|
||
- A quick summary and/or background | ||
- Steps to reproduce | ||
- Be specific! | ||
- Give sample code if you can. | ||
- What you expected would happen | ||
- What actually happens | ||
- Notes (possibly including why you think this might be happening, or stuff you tried that didn't work) | ||
|
||
People *love* thorough bug reports. I'm not even kidding. | ||
|
||
## Use a Consistent Coding Style | ||
|
||
Use [black](https://github.com/ambv/black) to make sure the code follows the style. | ||
|
||
## License | ||
|
||
By contributing, you agree that your contributions will be licensed under its Apache 2.0 License. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,44 @@ | ||
# linksys_velop | ||
The linksys_velop platform allows for presence detection by listing devices connected to your Linksys Velop router. | ||
|
||
It was tested with a Linksys Velop WHW03v1 Firmware version 1.1.11.197735 | ||
|
||
## Installation | ||
|
||
1. Using the tool of choice open the directory (folder) for your HA configuration (where you find `configuration.yaml`). | ||
2. If you do not have a `custom_components` directory (folder) there, you need to create it. | ||
3. In the `custom_components` directory (folder) create a new folder called `linksys_velop`. | ||
4. Download _all_ the files from the `custom_components/linksys_velop/` directory (folder) in this repository. | ||
5. Place the files you downloaded in the new directory (folder) you created. | ||
6. Restart Home Assistant. | ||
7. Move on to the configuration. | ||
|
||
Using your HA configuration directory (folder) as a starting point you should now also have this: | ||
|
||
```text | ||
custom_components/linksys_velop/__init__.py | ||
custom_components/linksys_velop/device_tracker.py | ||
custom_components/linksys_velop/manifest.json | ||
``` | ||
|
||
## Example configuration.yaml | ||
|
||
```yaml | ||
device_tracker: | ||
- platform: linksys_velop | ||
host: 192.168.1.1 | ||
username: admin | ||
password: YOUR_PASSWORD | ||
``` | ||
### Configuration options | ||
Key | Type | Required | Description | ||
-- | -- | -- | -- | ||
`host` | `string` | `True` | The hostname or IP address of your access point, e.g., 192.168.1.1. | ||
`username` | `string` | `False` | Defaults to `admin`. You should not have to customize it as Velops deveult to `admin` on login and only allow you to specify password. | ||
`password` | `string` | `True` | The password for your given local admin account. | ||
|
||
## Contributions are welcome! | ||
|
||
If you want to contribute to this please read the [Contribution guidelines](CONTRIBUTING.md) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
"""The linksys_velop component.""" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
"""Support for Linksys Velop routers.""" | ||
import logging | ||
|
||
import requests | ||
import voluptuous as vol | ||
|
||
import homeassistant.helpers.config_validation as cv | ||
from homeassistant.components.device_tracker import ( | ||
DOMAIN, | ||
PLATFORM_SCHEMA, | ||
DeviceScanner, | ||
) | ||
|
||
from homeassistant.const import CONF_HOST, CONF_PASSWORD, CONF_USERNAME | ||
from base64 import b64encode as b64 | ||
|
||
DEFAULT_TIMEOUT = 10 | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend( | ||
{ | ||
vol.Required(CONF_HOST): cv.string, | ||
vol.Required(CONF_PASSWORD): cv.string, | ||
vol.Optional(CONF_USERNAME, default="admin"): cv.string, | ||
} | ||
) | ||
|
||
|
||
def get_scanner(hass, config): | ||
"""Validate the configuration and return a Linksys AP scanner.""" | ||
try: | ||
return LinksysSmartWifiDeviceScanner(config[DOMAIN]) | ||
except ConnectionError: | ||
return None | ||
|
||
|
||
class LinksysSmartWifiDeviceScanner(DeviceScanner): | ||
"""This class queries a Linksys Access Point.""" | ||
|
||
def __init__(self, config): | ||
"""Initialize the scanner.""" | ||
self.host = config[CONF_HOST] | ||
self.username = config[CONF_USERNAME] | ||
self.password = config[CONF_PASSWORD] | ||
self.last_results = {} | ||
|
||
# Check if the access point is accessible | ||
response = self._make_request() | ||
if not response.status_code == 200: | ||
raise ConnectionError("Cannot connect to Linksys Access Point") | ||
|
||
def scan_devices(self): | ||
"""Scan for new devices and return a list with device IDs (MACs).""" | ||
self._update_info() | ||
|
||
return self.last_results.keys() | ||
|
||
def get_device_name(self, device): | ||
"""Return the name (if known) of the device.""" | ||
return self.last_results.get(device) | ||
|
||
def _update_info(self): | ||
"""Check for connected devices.""" | ||
_LOGGER.info("Checking Linksys Smart Wifi") | ||
|
||
self.last_results = {} | ||
response = self._make_request() | ||
if response.status_code != 200: | ||
_LOGGER.error( | ||
"Got HTTP status code %d when getting device list", response.status_code | ||
) | ||
return False | ||
try: | ||
data = response.json() | ||
result = data["responses"][0] | ||
devices = result["output"]["devices"] | ||
for device in devices: | ||
macs = device["knownMACAddresses"] | ||
if not macs: | ||
_LOGGER.warning("Skipping device without known MAC address") | ||
continue | ||
mac = macs[-1] | ||
connections = device["connections"] | ||
if not connections: | ||
_LOGGER.debug("Device %s is not connected", mac) | ||
continue | ||
|
||
name = None | ||
for prop in device["properties"]: | ||
if prop["name"] == "userDeviceName": | ||
name = prop["value"] | ||
if not name: | ||
name = device.get("friendlyName", device["deviceID"]) | ||
|
||
_LOGGER.debug("Device %s is connected", mac) | ||
self.last_results[mac] = name | ||
except (KeyError, IndexError): | ||
_LOGGER.exception("Router returned unexpected response") | ||
return False | ||
return True | ||
|
||
def _make_request(self): | ||
# Weirdly enough, this doesn't seem to require authentication | ||
data = [ | ||
{ | ||
"request": {"sinceRevision": 0}, | ||
"action": "http://linksys.com/jnap/devicelist/GetDevices", | ||
} | ||
] | ||
|
||
token = b64(bytes(self.username + ":" + self.password, "utf8")).decode("ascii"); | ||
|
||
headers = { | ||
"X-JNAP-Action": "http://linksys.com/jnap/core/Transaction", | ||
"X-JNAP-Authorization": "Basic " + token | ||
} | ||
|
||
|
||
return requests.post( | ||
f"http://{self.host}/JNAP/", | ||
timeout=DEFAULT_TIMEOUT, | ||
headers=headers, | ||
json=data, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
{ | ||
"domain": "linksys_velop", | ||
"name": "Linksys Velop", | ||
"documentation": "https://www.home-assistant.io/components/linksys_velop", | ||
"requirements": [], | ||
"dependencies": [], | ||
"codeowners": ["@adamnaj"], | ||
"homeassistant": "0.100.0" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
{ | ||
"name": "linksys_velop" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# linksys_velop | ||
The linksys_velop platform allows for presence detection by listing devices connected to your Linksys Velop router. | ||
|
||
It was tested with a Linksys Velop WHW03v1 Firmware version 1.1.11.197735 | ||
|
||
## Example configuration.yaml | ||
|
||
```yaml | ||
device_tracker: | ||
- platform: linksys_velop | ||
host: 192.168.1.1 | ||
password: YOUR_PASSWORD | ||
``` | ||
### Configuration options | ||
Key | Type | Required | Description | ||
-- | -- | -- | -- | ||
`host` | `string` | `True` | The hostname or IP address of your access point, e.g., 192.168.1.1. | ||
`username` | `string` | `False` | Defaults to `admin`. You should not have to customize it as Velops deveult to `admin` on login and only allow you to specify password. | ||
`password` | `string` | `True` | The password for your given local admin account. | ||
|
||
## Contributions are welcome! | ||
|
||
If you want to contribute to this please read the [Contribution guidelines](CONTRIBUTING.md) |