From 2f7c05ef4d34a1143ff0ef87454c36f414e42cfb Mon Sep 17 00:00:00 2001 From: Elad Bar Date: Wed, 20 Apr 2022 09:41:11 +0300 Subject: [PATCH] Fixed support for store debug file, --- CHANGELOG.md | 4 + README.md | 94 +++++++++---------- .../edgeos/clients/web_socket.py | 10 +- .../edgeos/managers/data_manager.py | 14 ++- .../edgeos/managers/entity_manager.py | 11 ++- .../edgeos/managers/storage_manager.py | 6 ++ requirements.txt | 2 +- 7 files changed, 80 insertions(+), 61 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b001051..f4a5b2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,9 @@ # Changelog +## 1.1.9 + +- Fixed support for store debug file, will store the file under `.storage/edgeos.debug.json` + ## 1.1.8 - Removed entity / device delete upon restarting HA diff --git a/README.md b/README.md index a969748..6927577 100644 --- a/README.md +++ b/README.md @@ -18,24 +18,24 @@ Look for "Integration with EdgeOS (Ubiquiti)" and install To add integration use Configuration -> Integrations -> Add `EdgeOS` Integration supports **multiple** EdgeOS devices -Fields name | Type | Required | Default | Description ---- | --- | --- | --- | --- | -Name | Textbox | + | - | Represents the integration name -Host | Textbox | + | - | Hostname or IP address to access EdgeOS device -Username | Textbox | + | - | Username of user with `Operator` level access or higher, better to create a dedicated user for that integration for faster issues identification -Password | Textbox | + | - | -Unit | Drop-down | + | Bytes | Unit for sensors, available options are: Bytes, KiloBytes, MegaBytes +| Fields name | Type | Required | Default | Description | +|-------------|-----------|----------|---------|--------------------------------------------------------------------------------------------------------------------------------------------------| +| Name | Textbox | + | - | Represents the integration name | +| Host | Textbox | + | - | Hostname or IP address to access EdgeOS device | +| Username | Textbox | + | - | Username of user with `Operator` level access or higher, better to create a dedicated user for that integration for faster issues identification | +| Password | Textbox | + | - | | +| Unit | Drop-down | + | Bytes | Unit for sensors, available options are: Bytes, KiloBytes, MegaBytes | ###### EdgeOS Device validation errors -Errors | ---- | -Cannot reach device (404) | -Invalid credentials (403) | -General authentication error (when failed to get valid response from device) | -Could not retrieve device data from EdgeOS Router | -Export (traffic-analysis) configuration is disabled, please enable | -Deep Packet Inspection (traffic-analysis) configuration is disabled, please enable | -Unsupported firmware version| +| Errors | +|------------------------------------------------------------------------------------| +| Cannot reach device (404) | +| Invalid credentials (403) | +| General authentication error (when failed to get valid response from device) | +| Could not retrieve device data from EdgeOS Router | +| Export (traffic-analysis) configuration is disabled, please enable | +| Deep Packet Inspection (traffic-analysis) configuration is disabled, please enable | +| Unsupported firmware version | ###### Encryption key got corrupted If a persistent notification popped up with the following message: @@ -49,22 +49,22 @@ Please remove the integration and re-add it to make it work again. #### Options *Configuration -> Integrations -> {Integration} -> Options*
-Fields name | Type | Required | Default | Description ---- | --- | --- | --- | --- | -Host | Textbox | + | - | Hostname or IP address to access EdgeOS device -Username | Textbox | + | - | Username of user with `Operator` level access or higher, better to create a dedicated user for that integration for faster issues identification -Password | Textbox | + | - | -Clear credentials | Check-box | + | Unchecked | Will reset username and password (Not being stored under options) -Unit | Drop-down | + | Bytes | Unit for sensors, available options are: Bytes, KiloBytes, MegaBytes -Consider away interval | Textbox | + | 180 | Consider away interval in seconds -Monitored devices | Drop-down | + | NONE | Devices to monitor using binary_sensor and sensor -Monitored interfaces | Drop-down | + | NONE | Interfaces to monitor using binary_sensor and sensor, -Track | Drop-down | + | NONE | Devices to track using device_trac -Update API Interval | Textbox | + | 60 | Number of seconds to update new devices and router settings -Update Entities Interval | Textbox | + | 1 | Number of seconds to update entities -Save debug file | Check-box | + | Unchecked | Will store debug file, more details below (Not being stored under options) -Log level | Drop-down | + | Default | Changes component's log level (more details below) -Log incoming messages | Check-box | + | Unchecked | Whether to log as DEBUG incoming web-socket messages or not +| Fields name | Type | Required | Default | Description | +|--------------------------|-----------|----------|-----------|--------------------------------------------------------------------------------------------------------------------------------------------------| +| Host | Textbox | + | - | Hostname or IP address to access EdgeOS device | +| Username | Textbox | + | - | Username of user with `Operator` level access or higher, better to create a dedicated user for that integration for faster issues identification | +| Password | Textbox | + | - | | +| Clear credentials | Check-box | + | Unchecked | Will reset username and password (Not being stored under options) | +| Unit | Drop-down | + | Bytes | Unit for sensors, available options are: Bytes, KiloBytes, MegaBytes | +| Consider away interval | Textbox | + | 180 | Consider away interval in seconds | +| Monitored devices | Drop-down | + | NONE | Devices to monitor using binary_sensor and sensor | +| Monitored interfaces | Drop-down | + | NONE | Interfaces to monitor using binary_sensor and sensor, | +| Track | Drop-down | + | NONE | Devices to track using device_trac | +| Update API Interval | Textbox | + | 60 | Number of seconds to update new devices and router settings | +| Update Entities Interval | Textbox | + | 1 | Number of seconds to update entities | +| Save debug file | Check-box | + | Unchecked | Will store debug file, more details below (Not being stored under options) | +| Log level | Drop-down | + | Default | Changes component's log level (more details below) | +| Log incoming messages | Check-box | + | Unchecked | Whether to log as DEBUG incoming web-socket messages or not | ###### Log Level's drop-down New feature to set the log level for the component without need to set log_level in `customization:` and restart or call manually `logger.set_level` and loose it after restart. @@ -74,7 +74,7 @@ Upon startup or integration's option update, based on the value chosen, the comp In case `Default` option is chosen, flow will skip calling the service, after changing from any other option to `Default`, it will not take place automatically, only after restart ###### Save debug file -Will store debug data from the component to HA CONFIG path named `edgeos_data.log` +Will store debug data from the component to `.storage/edgeos.debug.json` #### Debugging To set the log level of the component to DEBUG, please set it from the options of the component if installed, otherwise, set it within configuration YAML of HA: @@ -87,26 +87,26 @@ logger: ## Components #### Default -Name | Type | State | Attributes | ---- | --- | --- | --- | -{Integration Name} System Status | Binary Sensor | Connected or not | CPU
Memory
Up-time
API Last Update
WS Last Update -{Integration Name} System Uptime | Sensor | Time since restart in seconds | CPU
Memory
Is Alive
API Last Update
WS Last Update -{Integration Name} Unknown Devices | Sensor | Number of unknown devices | Unknown Devices description +| Name | Type | State | Attributes | +|------------------------------------|---------------|-------------------------------|----------------------------------------------------------------------------| +| {Integration Name} System Status | Binary Sensor | Connected or not | CPU
Memory
Up-time
API Last Update
WS Last Update | +| {Integration Name} System Uptime | Sensor | Time since restart in seconds | CPU
Memory
Is Alive
API Last Update
WS Last Update | +| {Integration Name} Unknown Devices | Sensor | Number of unknown devices | Unknown Devices description | #### Monitored Devices -Name | Type | State | Attributes | ---- | --- | --- | --- | -{Integration Name} Device {Device Name} | Binary Sensor | Connected or not | IP
MAC
Name
{Unit}Bytes (Sent)
{Unit}Bytes/ps (Sent)
{Unit}Bytes (Received)
{Unit}Bytes/ps (Received)
Last Activity
Last Changed +| Name | Type | State | Attributes | +|-----------------------------------------|---------------|------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| {Integration Name} Device {Device Name} | Binary Sensor | Connected or not | IP
MAC
Name
{Unit}Bytes (Sent)
{Unit}Bytes/ps (Sent)
{Unit}Bytes (Received)
{Unit}Bytes/ps (Received)
Last Activity
Last Changed | #### Monitored Interfaces -Name | Type | State | Attributes | ---- | --- | --- | --- | -{Integration Name} Interface {Interface Name} | Binary Sensor | Connected or not | Name
Duplex
Link Speed (Mbps)
address
Packets (Received)
Packets (Sent)
Errors (Received)
Errors (Sent)
Dropped packets (Received)
Dropped packets (Sent)
{Unit}Bytes (Received)
{Unit}Bytes (Sent)
{Unit}Bytes/ps (Received)
{Unit}Bytes/ps (Sent)
Multicast
Last Changed +| Name | Type | State | Attributes | +|-----------------------------------------------|---------------|------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| {Integration Name} Interface {Interface Name} | Binary Sensor | Connected or not | Name
Duplex
Link Speed (Mbps)
address
Packets (Received)
Packets (Sent)
Errors (Received)
Errors (Sent)
Dropped packets (Received)
Dropped packets (Sent)
{Unit}Bytes (Received)
{Unit}Bytes (Sent)
{Unit}Bytes/ps (Received)
{Unit}Bytes/ps (Sent)
Multicast
Last Changed | #### Tracked Devices -Name | Type | State | Attributes | ---- | --- | --- | --- | -{Integration Name} {Device Name} | Device Tracker | Home or Away | Host
IP
MAC
Name
Last Activity
Connected +| Name | Type | State | Attributes | +|----------------------------------|----------------|--------------|------------------------------------------------------------------------| +| {Integration Name} {Device Name} | Device Tracker | Home or Away | Host
IP
MAC
Name
Last Activity
Connected | ### Setting up the integration diff --git a/custom_components/edgeos/clients/web_socket.py b/custom_components/edgeos/clients/web_socket.py index 3d1c5ee..6168759 100644 --- a/custom_components/edgeos/clients/web_socket.py +++ b/custom_components/edgeos/clients/web_socket.py @@ -106,7 +106,7 @@ def last_update(self): return result - def parse_message(self, message): + async def parse_message(self, message): parsed = False try: @@ -120,7 +120,7 @@ def parse_message(self, message): if len(message) > 0: payload_json = json.loads(message) - self._edgeos_callback(payload_json) + await self._edgeos_callback(payload_json) parsed = True else: _LOGGER.debug("Parse message skipped (Empty)") @@ -151,7 +151,7 @@ async def listen(self): _LOGGER.info("Subscribed to WS payloads") async for msg in self._ws: - continue_to_next = self.handle_next_message(msg) + continue_to_next = await self.handle_next_message(msg) if ( not continue_to_next @@ -162,7 +162,7 @@ async def listen(self): _LOGGER.info(f"Stop listening") - def handle_next_message(self, msg): + async def handle_next_message(self, msg): _LOGGER.debug(f"Starting to handle next message") result = False @@ -185,7 +185,7 @@ def handle_next_message(self, msg): if msg.data == "close": result = False else: - self.parse_message(msg.data) + await self.parse_message(msg.data) result = True diff --git a/custom_components/edgeos/managers/data_manager.py b/custom_components/edgeos/managers/data_manager.py index 153afd2..0d4f986 100644 --- a/custom_components/edgeos/managers/data_manager.py +++ b/custom_components/edgeos/managers/data_manager.py @@ -15,6 +15,7 @@ from ..models.exceptions import IncompatibleVersion, SessionTerminatedException from .configuration_manager import ConfigManager from .version_check import VersionManager +from .storage_manager import StorageManager _LOGGER = logging.getLogger(__name__) @@ -55,6 +56,8 @@ def __init__(self, hass, config_manager: ConfigManager, update_home_assistant): self._is_active = True + self._storage_manager = StorageManager(hass) + @property def version(self): return self.version_manager.version @@ -210,7 +213,7 @@ async def refresh(self): if unknown_devices_data is not None: self.load_unknown_devices(unknown_devices_data) - self.update() + await self.update() except Exception as ex: exc_type, exc_obj, tb = sys.exc_info() @@ -220,7 +223,7 @@ async def refresh(self): f"Failed to load devices data, Error: {ex}, Line: {line_number}" ) - def update(self): + async def update(self): try: devices = self.get_devices() interfaces = self.get_interfaces() @@ -244,6 +247,9 @@ def update(self): ATTR_WEB_SOCKET_LAST_UPDATE: web_socket_last_update, } + if self.config_data.store_debug_files: + await self._storage_manager.async_save_debug_to_store(self.system_data) + self._update_home_assistant() except Exception as ex: exc_type, exc_obj, tb = sys.exc_info() @@ -251,7 +257,7 @@ def update(self): _LOGGER.error(f"Failed to refresh data, Error: {ex}, Line: {line_number}") - def ws_handler(self, payload=None): + async def ws_handler(self, payload=None): try: if payload is not None: for key in payload: @@ -265,7 +271,7 @@ def ws_handler(self, payload=None): else: handler(data) - self.update() + await self.update() except Exception as ex: exc_type, exc_obj, tb = sys.exc_info() line_number = tb.tb_lineno diff --git a/custom_components/edgeos/managers/entity_manager.py b/custom_components/edgeos/managers/entity_manager.py index 54be1c3..ae802e0 100644 --- a/custom_components/edgeos/managers/entity_manager.py +++ b/custom_components/edgeos/managers/entity_manager.py @@ -53,10 +53,13 @@ def system_data(self): return self.data_manager.system_data def set_domain_component(self, domain, async_add_entities, component): - self.domain_component_manager[domain] = { - "async_add_entities": async_add_entities, - "component": component, - } + if domain in self.domain_component_manager: + _LOGGER.warning(f'Domain {domain} already set up') + else: + self.domain_component_manager[domain] = { + "async_add_entities": async_add_entities, + "component": component, + } def is_device_name_in_use(self, device_name): result = False diff --git a/custom_components/edgeos/managers/storage_manager.py b/custom_components/edgeos/managers/storage_manager.py index 28ac51f..014049c 100644 --- a/custom_components/edgeos/managers/storage_manager.py +++ b/custom_components/edgeos/managers/storage_manager.py @@ -37,3 +37,9 @@ async def async_save_to_store(self, data: StorageData): store = Store(self._hass, STORAGE_VERSION, self.file_name, encoder=JSONEncoder) await store.async_save(data.to_dict()) + + async def async_save_debug_to_store(self, data): + """Generate dynamic data to store and save it to the filesystem.""" + store = Store(self._hass, STORAGE_VERSION, f"{DOMAIN}.debug.json", encoder=JSONEncoder) + + await store.async_save(data) diff --git a/requirements.txt b/requirements.txt index cfc8a89..0a88087 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,5 @@ pre-commit -homeassistant==2021.12.0b6 +homeassistant voluptuous aiohttp cryptography