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": { "config": {
"title": "Mikrotik Роутер", "title": "Роутер Mikrotik",
"step": { "step": {
"user": { "user": {
"title": "Mikrotik Роутер", "title": "Роутер Mikrotik",
"description": "Настройка интеграции роутера Mikrotik.", "description": "Настройка интеграции роутера Mikrotik.",
"data": { "data": {
"name": "Название интеграции", "name": "Название интеграции",

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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