PM8 code optimization

This commit is contained in:
Andrey Khrolenok 2020-03-21 19:02:28 +03:00
parent f0b4c5e723
commit 7ccaf0d9c3
No known key found for this signature in database
GPG key ID: 9D4D4A25BDFFA655
10 changed files with 557 additions and 536 deletions

View file

@ -1,9 +1,9 @@
{
"config": {
"title": "Mikrotik Роутер",
"title": "Роутер Mikrotik",
"step": {
"user": {
"title": "Mikrotik Роутер",
"title": "Роутер Mikrotik",
"description": "Настройка интеграции роутера Mikrotik.",
"data": {
"name": "Название интеграции",

View file

@ -1,103 +1,108 @@
"""Mikrotik Router integration."""
import logging
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.const import (
CONF_NAME,
CONF_HOST,
CONF_PORT,
CONF_UNIT_OF_MEASUREMENT,
CONF_USERNAME,
CONF_PASSWORD,
CONF_SSL,
)
from .mikrotik_controller import MikrotikControllerData
from .const import (
DOMAIN,
DATA_CLIENT,
DEFAULT_TRAFFIC_TYPE,
)
_LOGGER = logging.getLogger(__name__)
# ---------------------------
# async_setup
# ---------------------------
async def async_setup(hass, _config):
"""Set up configured Mikrotik Controller."""
hass.data[DOMAIN] = {}
hass.data[DOMAIN][DATA_CLIENT] = {}
return True
# ---------------------------
# async_setup_entry
# ---------------------------
async def async_setup_entry(hass, config_entry):
"""Set up Mikrotik Router as config entry."""
name = config_entry.data[CONF_NAME]
host = config_entry.data[CONF_HOST]
port = config_entry.data[CONF_PORT]
username = config_entry.data[CONF_USERNAME]
password = config_entry.data[CONF_PASSWORD]
use_ssl = config_entry.data[CONF_SSL]
if CONF_UNIT_OF_MEASUREMENT in config_entry.data:
traffic_type = config_entry.data[CONF_UNIT_OF_MEASUREMENT]
else:
traffic_type = DEFAULT_TRAFFIC_TYPE
mikrotik_controller = MikrotikControllerData(
hass, config_entry, name, host, port, username, password, use_ssl, traffic_type
)
await mikrotik_controller.hwinfo_update()
await mikrotik_controller.async_update()
if not mikrotik_controller.data:
raise ConfigEntryNotReady()
hass.data[DOMAIN][DATA_CLIENT][config_entry.entry_id] = mikrotik_controller
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(config_entry, "sensor")
)
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(config_entry, "binary_sensor")
)
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(config_entry, "device_tracker")
)
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(config_entry, "switch")
)
device_registry = await hass.helpers.device_registry.async_get_registry()
device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
manufacturer=mikrotik_controller.data["resource"]["platform"],
model=mikrotik_controller.data["routerboard"]["model"],
name=mikrotik_controller.data["routerboard"]["model"],
sw_version=mikrotik_controller.data["resource"]["version"],
)
return True
# ---------------------------
# async_unload_entry
# ---------------------------
async def async_unload_entry(hass, config_entry):
"""Unload a config entry."""
mikrotik_controller = hass.data[DOMAIN][DATA_CLIENT][config_entry.entry_id]
await hass.config_entries.async_forward_entry_unload(config_entry, "sensor")
await hass.config_entries.async_forward_entry_unload(config_entry, "binary_sensor")
await hass.config_entries.async_forward_entry_unload(config_entry, "device_tracker")
await hass.config_entries.async_forward_entry_unload(config_entry, "switch")
await mikrotik_controller.async_reset()
hass.data[DOMAIN][DATA_CLIENT].pop(config_entry.entry_id)
return True
"""Mikrotik Router integration."""
import logging
from homeassistant.const import (
CONF_NAME,
CONF_HOST,
CONF_PORT,
CONF_UNIT_OF_MEASUREMENT,
CONF_USERNAME,
CONF_PASSWORD,
CONF_SSL,
)
from homeassistant.exceptions import ConfigEntryNotReady
from .const import (
DOMAIN,
DATA_CLIENT,
DEFAULT_TRAFFIC_TYPE,
)
from .mikrotik_controller import MikrotikControllerData
_LOGGER = logging.getLogger(__name__)
# ---------------------------
# async_setup
# ---------------------------
async def async_setup(hass, _config):
"""Set up configured Mikrotik Controller."""
hass.data[DOMAIN] = {}
hass.data[DOMAIN][DATA_CLIENT] = {}
return True
# ---------------------------
# async_setup_entry
# ---------------------------
async def async_setup_entry(hass, config_entry):
"""Set up Mikrotik Router as config entry."""
name = config_entry.data[CONF_NAME]
host = config_entry.data[CONF_HOST]
port = config_entry.data[CONF_PORT]
username = config_entry.data[CONF_USERNAME]
password = config_entry.data[CONF_PASSWORD]
use_ssl = config_entry.data[CONF_SSL]
if CONF_UNIT_OF_MEASUREMENT in config_entry.data:
traffic_type = config_entry.data[CONF_UNIT_OF_MEASUREMENT]
else:
traffic_type = DEFAULT_TRAFFIC_TYPE
mikrotik_controller = MikrotikControllerData(
hass, config_entry, name, host, port, username, password, use_ssl,
traffic_type
)
await mikrotik_controller.hwinfo_update()
await mikrotik_controller.async_update()
if not mikrotik_controller.data:
raise ConfigEntryNotReady()
hass.data[DOMAIN][DATA_CLIENT][config_entry.entry_id] = mikrotik_controller
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(config_entry, "sensor")
)
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(config_entry,
"binary_sensor")
)
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(config_entry,
"device_tracker")
)
hass.async_create_task(
hass.config_entries.async_forward_entry_setup(config_entry, "switch")
)
device_registry = await hass.helpers.device_registry.async_get_registry()
device_registry.async_get_or_create(
config_entry_id=config_entry.entry_id,
manufacturer=mikrotik_controller.data["resource"]["platform"],
model=mikrotik_controller.data["routerboard"]["model"],
name=mikrotik_controller.data["routerboard"]["model"],
sw_version=mikrotik_controller.data["resource"]["version"],
)
return True
# ---------------------------
# async_unload_entry
# ---------------------------
async def async_unload_entry(hass, config_entry):
"""Unload a config entry."""
mikrotik_controller = hass.data[DOMAIN][DATA_CLIENT][config_entry.entry_id]
await hass.config_entries.async_forward_entry_unload(config_entry, "sensor")
await hass.config_entries.async_forward_entry_unload(config_entry,
"binary_sensor")
await hass.config_entries.async_forward_entry_unload(config_entry,
"device_tracker")
await hass.config_entries.async_forward_entry_unload(config_entry, "switch")
await mikrotik_controller.async_reset()
hass.data[DOMAIN][DATA_CLIENT].pop(config_entry.entry_id)
return True

View file

@ -1,13 +1,14 @@
"""Support for the Mikrotik Router binary sensor service."""
import logging
from homeassistant.core import callback
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.const import (
CONF_NAME,
ATTR_ATTRIBUTION,
)
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from .const import (
DOMAIN,

View file

@ -1,183 +1,185 @@
"""Config flow to configure Mikrotik Router."""
import logging
import voluptuous as vol
from homeassistant.core import callback
from homeassistant.config_entries import (
CONN_CLASS_LOCAL_POLL,
ConfigFlow,
OptionsFlow,
)
from homeassistant.const import (
CONF_NAME,
CONF_HOST,
CONF_PORT,
CONF_UNIT_OF_MEASUREMENT,
CONF_USERNAME,
CONF_PASSWORD,
CONF_SSL,
)
from .const import (
DOMAIN,
CONF_TRACK_ARP,
DEFAULT_TRACK_ARP,
CONF_SCAN_INTERVAL,
DEFAULT_SCAN_INTERVAL,
DEFAULT_TRAFFIC_TYPE,
TRAFFIC_TYPES,
)
from .mikrotikapi import MikrotikAPI
_LOGGER = logging.getLogger(__name__)
# ---------------------------
# configured_instances
# ---------------------------
@callback
def configured_instances(hass):
"""Return a set of configured instances."""
return set(
entry.data[CONF_NAME] for entry in hass.config_entries.async_entries(DOMAIN)
)
# ---------------------------
# MikrotikControllerConfigFlow
# ---------------------------
class MikrotikControllerConfigFlow(ConfigFlow, domain=DOMAIN):
"""MikrotikControllerConfigFlow class"""
VERSION = 1
CONNECTION_CLASS = CONN_CLASS_LOCAL_POLL
def __init__(self):
"""Initialize MikrotikControllerConfigFlow."""
@staticmethod
@callback
def async_get_options_flow(config_entry):
"""Get the options flow for this handler."""
return MikrotikControllerOptionsFlowHandler(config_entry)
async def async_step_import(self, user_input=None):
"""Occurs when a previously entry setup fails and is re-initiated."""
return await self.async_step_user(user_input)
async def async_step_user(self, user_input=None):
"""Handle a flow initialized by the user."""
errors = {}
if user_input is not None:
# Check if instance with this name already exists
if user_input[CONF_NAME] in configured_instances(self.hass):
errors["base"] = "name_exists"
# Test connection
api = MikrotikAPI(
host=user_input["host"],
username=user_input["username"],
password=user_input["password"],
port=user_input["port"],
use_ssl=user_input["ssl"],
)
if not api.connect():
errors[CONF_HOST] = api.error
# Save instance
if not errors:
return self.async_create_entry(
title=user_input[CONF_NAME], data=user_input
)
return self._show_config_form(
host=user_input["host"],
username=user_input["username"],
password=user_input["password"],
port=user_input["port"],
name=user_input["name"],
use_ssl=user_input["ssl"],
errors=errors,
)
return self._show_config_form(errors=errors)
# ---------------------------
# _show_config_form
# ---------------------------
def _show_config_form(
self,
host="10.0.0.1",
username="admin",
password="admin",
port=0,
name="Mikrotik",
use_ssl=False,
errors=None,
):
"""Show the configuration form to edit data."""
return self.async_show_form(
step_id="user",
data_schema=vol.Schema(
{
vol.Required(CONF_HOST, default=host): str,
vol.Required(CONF_USERNAME, default=username): str,
vol.Required(CONF_PASSWORD, default=password): str,
vol.Optional(
CONF_UNIT_OF_MEASUREMENT, default=DEFAULT_TRAFFIC_TYPE
): vol.In(TRAFFIC_TYPES),
vol.Optional(CONF_PORT, default=port): int,
vol.Optional(CONF_NAME, default=name): str,
vol.Optional(CONF_SSL, default=use_ssl): bool,
}
),
errors=errors,
)
# ---------------------------
# MikrotikControllerOptionsFlowHandler
# ---------------------------
class MikrotikControllerOptionsFlowHandler(OptionsFlow):
"""Handle options."""
def __init__(self, config_entry):
"""Initialize options flow."""
self.config_entry = config_entry
self.options = dict(config_entry.options)
async def async_step_init(self, user_input=None):
"""Manage the options."""
return await self.async_step_device_tracker(user_input)
async def async_step_device_tracker(self, user_input=None):
"""Manage the device tracker options."""
if user_input is not None:
self.options.update(user_input)
return self.async_create_entry(title="", data=self.options)
return self.async_show_form(
step_id="device_tracker",
data_schema=vol.Schema(
{
vol.Optional(
CONF_TRACK_ARP,
default=self.config_entry.options.get(
CONF_TRACK_ARP, DEFAULT_TRACK_ARP
),
): bool,
vol.Optional(
CONF_SCAN_INTERVAL,
default=self.config_entry.options.get(
CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL
),
): int,
vol.Optional(
CONF_UNIT_OF_MEASUREMENT,
default=self.config_entry.options.get(
CONF_UNIT_OF_MEASUREMENT, DEFAULT_TRAFFIC_TYPE
),
): vol.In(TRAFFIC_TYPES),
}
),
)
"""Config flow to configure Mikrotik Router."""
import logging
import voluptuous as vol
from homeassistant.config_entries import (
CONN_CLASS_LOCAL_POLL,
ConfigFlow,
OptionsFlow,
)
from homeassistant.const import (
CONF_NAME,
CONF_HOST,
CONF_PORT,
CONF_UNIT_OF_MEASUREMENT,
CONF_USERNAME,
CONF_PASSWORD,
CONF_SSL,
)
from homeassistant.core import callback
from .const import (
DOMAIN,
CONF_TRACK_ARP,
DEFAULT_TRACK_ARP,
CONF_SCAN_INTERVAL,
DEFAULT_SCAN_INTERVAL,
DEFAULT_TRAFFIC_TYPE,
TRAFFIC_TYPES,
)
from .mikrotikapi import MikrotikAPI
_LOGGER = logging.getLogger(__name__)
# ---------------------------
# configured_instances
# ---------------------------
@callback
def configured_instances(hass):
"""Return a set of configured instances."""
return set(
entry.data[CONF_NAME] for entry in
hass.config_entries.async_entries(DOMAIN)
)
# ---------------------------
# MikrotikControllerConfigFlow
# ---------------------------
class MikrotikControllerConfigFlow(ConfigFlow, domain=DOMAIN):
"""MikrotikControllerConfigFlow class"""
VERSION = 1
CONNECTION_CLASS = CONN_CLASS_LOCAL_POLL
def __init__(self):
"""Initialize MikrotikControllerConfigFlow."""
@staticmethod
@callback
def async_get_options_flow(config_entry):
"""Get the options flow for this handler."""
return MikrotikControllerOptionsFlowHandler(config_entry)
async def async_step_import(self, user_input=None):
"""Occurs when a previously entry setup fails and is re-initiated."""
return await self.async_step_user(user_input)
async def async_step_user(self, user_input=None):
"""Handle a flow initialized by the user."""
errors = {}
if user_input is not None:
# Check if instance with this name already exists
if user_input[CONF_NAME] in configured_instances(self.hass):
errors["base"] = "name_exists"
# Test connection
api = MikrotikAPI(
host=user_input["host"],
username=user_input["username"],
password=user_input["password"],
port=user_input["port"],
use_ssl=user_input["ssl"],
)
if not api.connect():
errors[CONF_HOST] = api.error
# Save instance
if not errors:
return self.async_create_entry(
title=user_input[CONF_NAME], data=user_input
)
return self._show_config_form(
host=user_input["host"],
username=user_input["username"],
password=user_input["password"],
port=user_input["port"],
name=user_input["name"],
use_ssl=user_input["ssl"],
errors=errors,
)
return self._show_config_form(errors=errors)
# ---------------------------
# _show_config_form
# ---------------------------
def _show_config_form(
self,
host="10.0.0.1",
username="admin",
password="admin",
port=0,
name="Mikrotik",
use_ssl=False,
errors=None,
):
"""Show the configuration form to edit data."""
return self.async_show_form(
step_id="user",
data_schema=vol.Schema(
{
vol.Required(CONF_HOST, default=host): str,
vol.Required(CONF_USERNAME, default=username): str,
vol.Required(CONF_PASSWORD, default=password): str,
vol.Optional(
CONF_UNIT_OF_MEASUREMENT, default=DEFAULT_TRAFFIC_TYPE
): vol.In(TRAFFIC_TYPES),
vol.Optional(CONF_PORT, default=port): int,
vol.Optional(CONF_NAME, default=name): str,
vol.Optional(CONF_SSL, default=use_ssl): bool,
}
),
errors=errors,
)
# ---------------------------
# MikrotikControllerOptionsFlowHandler
# ---------------------------
class MikrotikControllerOptionsFlowHandler(OptionsFlow):
"""Handle options."""
def __init__(self, config_entry):
"""Initialize options flow."""
self.config_entry = config_entry
self.options = dict(config_entry.options)
async def async_step_init(self, user_input=None):
"""Manage the options."""
return await self.async_step_device_tracker(user_input)
async def async_step_device_tracker(self, user_input=None):
"""Manage the device tracker options."""
if user_input is not None:
self.options.update(user_input)
return self.async_create_entry(title="", data=self.options)
return self.async_show_form(
step_id="device_tracker",
data_schema=vol.Schema(
{
vol.Optional(
CONF_TRACK_ARP,
default=self.config_entry.options.get(
CONF_TRACK_ARP, DEFAULT_TRACK_ARP
),
): bool,
vol.Optional(
CONF_SCAN_INTERVAL,
default=self.config_entry.options.get(
CONF_SCAN_INTERVAL, DEFAULT_SCAN_INTERVAL
),
): int,
vol.Optional(
CONF_UNIT_OF_MEASUREMENT,
default=self.config_entry.options.get(
CONF_UNIT_OF_MEASUREMENT, DEFAULT_TRAFFIC_TYPE
),
): vol.In(TRAFFIC_TYPES),
}
),
)

View file

@ -1,191 +1,194 @@
"""Support for the Mikrotik Router device tracker."""
import logging
from homeassistant.core import callback
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.components.device_tracker.config_entry import ScannerEntity
from homeassistant.components.device_tracker.const import SOURCE_TYPE_ROUTER
from homeassistant.const import (
CONF_NAME,
ATTR_ATTRIBUTION,
)
from .const import (
DOMAIN,
DATA_CLIENT,
ATTRIBUTION,
)
_LOGGER = logging.getLogger(__name__)
DEVICE_ATTRIBUTES = [
"running",
"enabled",
"comment",
"client-ip-address",
"client-mac-address",
"port-mac-address",
"last-link-down-time",
"last-link-up-time",
"link-downs",
"actual-mtu",
"type",
"name",
"default-name",
]
# ---------------------------
# format_attribute
# ---------------------------
def format_attribute(attr):
res = attr.replace("-", " ")
res = res.capitalize()
res = res.replace(" ip ", " IP ")
res = res.replace(" mac ", " MAC ")
res = res.replace(" mtu", " MTU")
return res
# ---------------------------
# async_setup_entry
# ---------------------------
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up device tracker for Mikrotik Router component."""
inst = config_entry.data[CONF_NAME]
mikrotik_controller = hass.data[DOMAIN][DATA_CLIENT][config_entry.entry_id]
tracked = {}
@callback
def update_controller():
"""Update the values of the controller."""
update_items(inst, mikrotik_controller, async_add_entities, tracked)
mikrotik_controller.listeners.append(
async_dispatcher_connect(
hass, mikrotik_controller.signal_update, update_controller
)
)
update_controller()
# ---------------------------
# update_items
# ---------------------------
@callback
def update_items(inst, mikrotik_controller, async_add_entities, tracked):
"""Update tracked device state from the controller."""
new_tracked = []
for uid in mikrotik_controller.data["interface"]:
if mikrotik_controller.data["interface"][uid]["type"] == "ether":
item_id = (
f"{inst}-{mikrotik_controller.data['interface'][uid]['default-name']}"
)
if item_id in tracked:
if tracked[item_id].enabled:
tracked[item_id].async_schedule_update_ha_state()
continue
tracked[item_id] = MikrotikControllerPortDeviceTracker(
inst, uid, mikrotik_controller
)
new_tracked.append(tracked[item_id])
if new_tracked:
async_add_entities(new_tracked)
# ---------------------------
# MikrotikControllerPortDeviceTracker
# ---------------------------
class MikrotikControllerPortDeviceTracker(ScannerEntity):
"""Representation of a network port."""
def __init__(self, inst, uid, mikrotik_controller):
"""Set up tracked port."""
self._inst = inst
self._ctrl = mikrotik_controller
self._data = mikrotik_controller.data["interface"][uid]
self._attrs = {
ATTR_ATTRIBUTION: ATTRIBUTION,
}
@property
def entity_registry_enabled_default(self):
"""Return if the entity should be enabled when first added to the entity registry."""
return True
async def async_added_to_hass(self):
"""Port entity created."""
_LOGGER.debug(
"New port tracker %s (%s %s)",
self._inst,
self._data["default-name"],
self._data["port-mac-address"],
)
async def async_update(self):
"""Synchronize state with controller."""
@property
def is_connected(self):
"""Return true if the port is connected to the network."""
return self._data["running"]
@property
def source_type(self):
"""Return the source type of the port."""
return SOURCE_TYPE_ROUTER
@property
def name(self):
"""Return the name of the port."""
return f"{self._inst} {self._data['default-name']}"
@property
def unique_id(self):
"""Return a unique identifier for this port."""
return f"{self._inst.lower()}-{self._data['port-mac-address']}"
@property
def available(self) -> bool:
"""Return if controller is available."""
return self._ctrl.connected()
@property
def icon(self):
"""Return the icon."""
if self._data["running"]:
icon = "mdi:lan-connect"
else:
icon = "mdi:lan-pending"
if not self._data["enabled"]:
icon = "mdi:lan-disconnect"
return icon
@property
def device_info(self):
"""Return a port description for device registry."""
info = {
"connections": {(CONNECTION_NETWORK_MAC, self._data["port-mac-address"])},
"manufacturer": self._ctrl.data["resource"]["platform"],
"model": self._ctrl.data["resource"]["board-name"],
"name": self._data["default-name"],
}
return info
@property
def device_state_attributes(self):
"""Return the port state attributes."""
attributes = self._attrs
for variable in DEVICE_ATTRIBUTES:
if variable in self._data:
attributes[format_attribute(variable)] = self._data[variable]
return attributes
"""Support for the Mikrotik Router device tracker."""
import logging
from homeassistant.components.device_tracker.config_entry import ScannerEntity
from homeassistant.components.device_tracker.const import SOURCE_TYPE_ROUTER
from homeassistant.const import (
CONF_NAME,
ATTR_ATTRIBUTION,
)
from homeassistant.core import callback
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from .const import (
DOMAIN,
DATA_CLIENT,
ATTRIBUTION,
)
_LOGGER = logging.getLogger(__name__)
DEVICE_ATTRIBUTES = [
"running",
"enabled",
"comment",
"client-ip-address",
"client-mac-address",
"port-mac-address",
"last-link-down-time",
"last-link-up-time",
"link-downs",
"actual-mtu",
"type",
"name",
"default-name",
]
# ---------------------------
# format_attribute
# ---------------------------
def format_attribute(attr):
res = attr.replace("-", " ")
res = res.capitalize()
res = res.replace(" ip ", " IP ")
res = res.replace(" mac ", " MAC ")
res = res.replace(" mtu", " MTU")
return res
# ---------------------------
# async_setup_entry
# ---------------------------
async def async_setup_entry(hass, config_entry, async_add_entities):
"""Set up device tracker for Mikrotik Router component."""
inst = config_entry.data[CONF_NAME]
mikrotik_controller = hass.data[DOMAIN][DATA_CLIENT][config_entry.entry_id]
tracked = {}
@callback
def update_controller():
"""Update the values of the controller."""
update_items(inst, mikrotik_controller, async_add_entities, tracked)
mikrotik_controller.listeners.append(
async_dispatcher_connect(
hass, mikrotik_controller.signal_update, update_controller
)
)
update_controller()
# ---------------------------
# update_items
# ---------------------------
@callback
def update_items(inst, mikrotik_controller, async_add_entities, tracked):
"""Update tracked device state from the controller."""
new_tracked = []
for uid in mikrotik_controller.data["interface"]:
if mikrotik_controller.data["interface"][uid]["type"] == "ether":
item_id = (
f"{inst}-{mikrotik_controller.data['interface'][uid]['default-name']}"
)
if item_id in tracked:
if tracked[item_id].enabled:
tracked[item_id].async_schedule_update_ha_state()
continue
tracked[item_id] = MikrotikControllerPortDeviceTracker(
inst, uid, mikrotik_controller
)
new_tracked.append(tracked[item_id])
if new_tracked:
async_add_entities(new_tracked)
# ---------------------------
# MikrotikControllerPortDeviceTracker
# ---------------------------
class MikrotikControllerPortDeviceTracker(ScannerEntity):
"""Representation of a network port."""
def __init__(self, inst, uid, mikrotik_controller):
"""Set up tracked port."""
self._inst = inst
self._ctrl = mikrotik_controller
self._data = mikrotik_controller.data["interface"][uid]
self._attrs = {
ATTR_ATTRIBUTION: ATTRIBUTION,
}
@property
def entity_registry_enabled_default(self):
"""Return if the entity should be enabled when first added to the entity registry."""
return True
async def async_added_to_hass(self):
"""Port entity created."""
_LOGGER.debug(
"New port tracker %s (%s %s)",
self._inst,
self._data["default-name"],
self._data["port-mac-address"],
)
async def async_update(self):
"""Synchronize state with controller."""
@property
def is_connected(self):
"""Return true if the port is connected to the network."""
return self._data["running"]
@property
def source_type(self):
"""Return the source type of the port."""
return SOURCE_TYPE_ROUTER
@property
def name(self):
"""Return the name of the port."""
return f"{self._inst} {self._data['default-name']}"
@property
def unique_id(self):
"""Return a unique identifier for this port."""
return f"{self._inst.lower()}-{self._data['port-mac-address']}"
@property
def available(self) -> bool:
"""Return if controller is available."""
return self._ctrl.connected()
@property
def icon(self):
"""Return the icon."""
if self._data["running"]:
icon = "mdi:lan-connect"
else:
icon = "mdi:lan-pending"
if not self._data["enabled"]:
icon = "mdi:lan-disconnect"
return icon
@property
def device_info(self):
"""Return a port description for device registry."""
info = {
"connections": {
(CONNECTION_NETWORK_MAC, self._data["port-mac-address"])},
"manufacturer": self._ctrl.data["resource"]["platform"],
"model": self._ctrl.data["resource"]["board-name"],
"name": self._data["default-name"],
}
return info
@property
def device_state_attributes(self):
"""Return the port state attributes."""
attributes = self._attrs
for variable in DEVICE_ATTRIBUTES:
if variable in self._data:
attributes[format_attribute(variable)] = self._data[variable]
return attributes

View file

@ -265,7 +265,8 @@ def fill_vals_proc(data, uid, vals_proc) -> dict:
if _action == "combine":
if "key" in val:
tmp = _data[val["key"]] if val["key"] in _data else "unknown"
tmp = _data[val["key"]]\
if val["key"] in _data else "unknown"
if not _value:
_value = tmp
else:

View file

@ -1,8 +1,8 @@
"""Mikrotik Controller for Mikrotik Router."""
from datetime import timedelta
import asyncio
import logging
from datetime import timedelta
from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_send
@ -17,10 +17,9 @@ from .const import (
DEFAULT_SCAN_INTERVAL,
DEFAULT_TRAFFIC_TYPE,
)
from .mikrotikapi import MikrotikAPI
from .helper import from_entry, parse_api
from .exceptions import ApiEntryNotFound
from .helper import from_entry, parse_api
from .mikrotikapi import MikrotikAPI
_LOGGER = logging.getLogger(__name__)
@ -277,8 +276,10 @@ class MikrotikControllerData:
traffic_div = 1
for uid in self.data["interface"]:
self.data["interface"][uid]["rx-bits-per-second-attr"] = traffic_type
self.data["interface"][uid]["tx-bits-per-second-attr"] = traffic_type
self.data["interface"][uid][
"rx-bits-per-second-attr"] = traffic_type
self.data["interface"][uid][
"tx-bits-per-second-attr"] = traffic_type
self.data["interface"][uid]["rx-bits-per-second"] = round(
self.data["interface"][uid]["rx-bits-per-second"] * traffic_div
)
@ -402,7 +403,8 @@ class MikrotikControllerData:
self.data["arp"][uid]["mac-address"] = "multiple"
self.data["arp"][uid]["address"] = "multiple"
else:
self.data["arp"][uid]["mac-address"] = from_entry(entry, "mac-address")
self.data["arp"][uid]["mac-address"] = from_entry(entry,
"mac-address")
self.data["arp"][uid]["address"] = (
mac2ip[self.data["arp"][uid]["mac-address"]]
if self.data["arp"][uid]["mac-address"] in mac2ip
@ -541,8 +543,8 @@ class MikrotikControllerData:
if "status" in self.data["fw-update"]:
self.data["fw-update"]["available"] = (
True
if self.data["fw-update"]["status"] == "New version is available"
True if self.data["fw-update"][
"status"] == "New version is available"
else False
)
else:

View file

@ -1,22 +1,23 @@
"""Mikrotik API for Mikrotik Router."""
import ssl
import importlib
import logging
import os
import ssl
import sys
import time
from threading import Lock
from voluptuous import Optional
from .exceptions import ApiEntryNotFound
from .const import (
DEFAULT_LOGIN_METHOD,
DEFAULT_ENCODING,
)
from .exceptions import ApiEntryNotFound
import os
import sys
import importlib
MODULE_PATH = os.path.join(os.path.dirname(__file__), "librouteros_custom", "__init__.py")
MODULE_PATH = os.path.join(os.path.dirname(__file__), "librouteros_custom",
"__init__.py")
MODULE_NAME = "librouteros_custom"
spec = importlib.util.spec_from_file_location(MODULE_NAME, MODULE_PATH)
librouteros_custom = importlib.util.module_from_spec(spec)
@ -112,7 +113,8 @@ class MikrotikAPI:
) as api_error:
if not self.connection_error_reported:
_LOGGER.error(
"Mikrotik %s error while connecting: %s", self._host, api_error
"Mikrotik %s error while connecting: %s", self._host,
api_error
)
self.connection_error_reported = True
@ -123,7 +125,8 @@ class MikrotikAPI:
except:
if not self.connection_error_reported:
_LOGGER.error(
"Mikrotik %s error while connecting: %s", self._host, "Unknown"
"Mikrotik %s error while connecting: %s", self._host,
"Unknown"
)
self.connection_error_reported = True
@ -196,7 +199,8 @@ class MikrotikAPI:
ValueError,
) as api_error:
if not self.connection_error_reported:
_LOGGER.error("Mikrotik %s error while path %s", self._host, api_error)
_LOGGER.error("Mikrotik %s error while path %s", self._host,
api_error)
self.connection_error_reported = True
self.disconnect()
@ -204,7 +208,8 @@ class MikrotikAPI:
return None
except:
if not self.connection_error_reported:
_LOGGER.error("Mikrotik %s error while path %s", self._host, "unknown")
_LOGGER.error("Mikrotik %s error while path %s", self._host,
"unknown")
self.connection_error_reported = True
self.disconnect()
@ -215,7 +220,8 @@ class MikrotikAPI:
tuple(response)
except librouteros_custom.exceptions.ConnectionClosed as api_error:
if not self.connection_error_reported:
_LOGGER.error("Mikrotik %s error while path %s", self._host, api_error)
_LOGGER.error("Mikrotik %s error while path %s", self._host,
api_error)
self.connection_error_reported = True
self.disconnect()
@ -223,7 +229,8 @@ class MikrotikAPI:
return None
except:
if not self.connection_error_reported:
_LOGGER.error("Mikrotik %s error while path %s", self._host, "unknown")
_LOGGER.error("Mikrotik %s error while path %s", self._host,
"unknown")
self.connection_error_reported = True
self.disconnect()
@ -283,7 +290,8 @@ class MikrotikAPI:
) as api_error:
if not self.connection_error_reported:
_LOGGER.error(
"Mikrotik %s error while update %s", self._host, api_error
"Mikrotik %s error while update %s", self._host,
api_error
)
self.connection_error_reported = True
@ -293,7 +301,8 @@ class MikrotikAPI:
except:
if not self.connection_error_reported:
_LOGGER.error(
"Mikrotik %s error while update %s", self._host, "unknown"
"Mikrotik %s error while update %s", self._host,
"unknown"
)
self.connection_error_reported = True
@ -357,7 +366,8 @@ class MikrotikAPI:
) as api_error:
if not self.connection_error_reported:
_LOGGER.error(
"Mikrotik %s error while run_script %s", self._host, api_error
"Mikrotik %s error while run_script %s", self._host,
api_error
)
self.connection_error_reported = True
@ -367,7 +377,8 @@ class MikrotikAPI:
except:
if not self.connection_error_reported:
_LOGGER.error(
"Mikrotik %s error while run_script %s", self._host, "unknown"
"Mikrotik %s error while run_script %s", self._host,
"unknown"
)
self.connection_error_reported = True
@ -426,7 +437,8 @@ class MikrotikAPI:
) as api_error:
if not self.connection_error_reported:
_LOGGER.error(
"Mikrotik %s error while get_traffic %s", self._host, api_error
"Mikrotik %s error while get_traffic %s", self._host,
api_error
)
self.connection_error_reported = True
@ -436,7 +448,8 @@ class MikrotikAPI:
except:
if not self.connection_error_reported:
_LOGGER.error(
"Mikrotik %s error while get_traffic %s", self._host, "unknown"
"Mikrotik %s error while get_traffic %s", self._host,
"unknown"
)
self.connection_error_reported = True
@ -449,7 +462,8 @@ class MikrotikAPI:
except librouteros_custom.exceptions.ConnectionClosed as api_error:
if not self.connection_error_reported:
_LOGGER.error(
"Mikrotik %s error while get_traffic %s", self._host, api_error
"Mikrotik %s error while get_traffic %s", self._host,
api_error
)
self.connection_error_reported = True
@ -459,7 +473,8 @@ class MikrotikAPI:
except:
if not self.connection_error_reported:
_LOGGER.error(
"Mikrotik %s error while get_traffic %s", self._host, "unknown"
"Mikrotik %s error while get_traffic %s", self._host,
"unknown"
)
self.connection_error_reported = True

View file

@ -1,21 +1,14 @@
"""Support for the Mikrotik Router sensor service."""
import logging
from homeassistant.const import (CONF_NAME, ATTR_ATTRIBUTION, ATTR_DEVICE_CLASS)
from homeassistant.core import callback
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity import Entity
from homeassistant.const import (
CONF_NAME,
ATTR_ATTRIBUTION,
ATTR_DEVICE_CLASS,
)
from .const import (
DOMAIN,
DATA_CLIENT,
ATTRIBUTION,
)
from .const import (DOMAIN, DATA_CLIENT, ATTRIBUTION)
_LOGGER = logging.getLogger(__name__)
@ -116,13 +109,15 @@ def update_items(inst, mikrotik_controller, async_add_entities, sensors):
continue
sensors[item_id] = MikrotikControllerSensor(
mikrotik_controller=mikrotik_controller, inst=inst, sensor=sensor
mikrotik_controller=mikrotik_controller, inst=inst,
sensor=sensor
)
new_sensors.append(sensors[item_id])
if "traffic_" in sensor:
for uid in mikrotik_controller.data["interface"]:
if mikrotik_controller.data["interface"][uid]["type"] == "ether":
if mikrotik_controller.data["interface"][uid][
"type"] == "ether":
item_id = f"{inst}-{sensor}-{mikrotik_controller.data['interface'][uid]['default-name']}"
if item_id in sensors:
if sensors[item_id].enabled:
@ -248,7 +243,8 @@ class MikrotikControllerTrafficSensor(MikrotikControllerSensor):
"""Initialize."""
super().__init__(mikrotik_controller, inst, sensor)
self._uid = uid
self._data = mikrotik_controller.data[SENSOR_TYPES[sensor][ATTR_PATH]][uid]
self._data = mikrotik_controller.data[SENSOR_TYPES[sensor][ATTR_PATH]][
uid]
@property
def name(self):
@ -264,7 +260,8 @@ class MikrotikControllerTrafficSensor(MikrotikControllerSensor):
def device_info(self):
"""Return a port description for device registry."""
info = {
"connections": {(CONNECTION_NETWORK_MAC, self._data["port-mac-address"])},
"connections": {
(CONNECTION_NETWORK_MAC, self._data["port-mac-address"])},
"manufacturer": self._ctrl.data["resource"]["platform"],
"model": self._ctrl.data["resource"]["board-name"],
"name": self._data["default-name"],

View file

@ -2,20 +2,13 @@
import logging
from homeassistant.components.switch import SwitchDevice
from homeassistant.const import (CONF_NAME, ATTR_ATTRIBUTION)
from homeassistant.core import callback
from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.restore_state import RestoreEntity
from homeassistant.const import (
CONF_NAME,
ATTR_ATTRIBUTION,
)
from .const import (
DOMAIN,
DATA_CLIENT,
ATTRIBUTION,
)
from .const import (DOMAIN, DATA_CLIENT, ATTRIBUTION)
_LOGGER = logging.getLogger(__name__)
@ -192,7 +185,8 @@ class MikrotikControllerPortSwitch(MikrotikControllerSwitch):
def device_info(self):
"""Return a port description for device registry."""
info = {
"connections": {(CONNECTION_NETWORK_MAC, self._data["port-mac-address"])},
"connections": {
(CONNECTION_NETWORK_MAC, self._data["port-mac-address"])},
"manufacturer": self._ctrl.data["resource"]["platform"],
"model": self._ctrl.data["resource"]["board-name"],
"name": self._data["default-name"],
@ -362,7 +356,8 @@ class MikrotikControllerScriptSwitch(MikrotikControllerSwitch):
async def async_added_to_hass(self):
"""Script switch entity created."""
_LOGGER.debug("New script switch %s (%s)", self._inst, self._data["name"])
_LOGGER.debug("New script switch %s (%s)", self._inst,
self._data["name"])
@property
def name(self) -> str: