Skip to content

Commit

Permalink
Merge pull request #296 from tomaae/coordinator
Browse files Browse the repository at this point in the history
Coordinator
  • Loading branch information
tomaae authored Aug 31, 2023
2 parents 4d957ae + c872823 commit 380884d
Show file tree
Hide file tree
Showing 21 changed files with 1,559 additions and 1,558 deletions.
71 changes: 29 additions & 42 deletions custom_components/mikrotik_router/__init__.py
Original file line number Diff line number Diff line change
@@ -1,80 +1,67 @@
"""Mikrotik Router integration."""
from __future__ import annotations

import voluptuous as vol

import homeassistant.helpers.config_validation as cv
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers import device_registry
from homeassistant.config_entries import ConfigEntry
from homeassistant.exceptions import ConfigEntryNotReady

from .const import (
PLATFORMS,
DOMAIN,
RUN_SCRIPT_COMMAND,
)
from .mikrotik_controller import MikrotikControllerData
from .coordinator import MikrotikData, MikrotikCoordinator, MikrotikTrackerCoordinator

SCRIPT_SCHEMA = vol.Schema(
{vol.Required("router"): cv.string, vol.Required("script"): cv.string}
)


# ---------------------------
# async_setup
# ---------------------------
async def async_setup(hass, _config):
"""Set up configured Mikrotik Controller."""
hass.data[DOMAIN] = {}
return True


# ---------------------------
# update_listener
# ---------------------------
async def update_listener(hass, config_entry) -> None:
"""Handle options update."""
await hass.config_entries.async_reload(config_entry.entry_id)


# ---------------------------
# async_setup_entry
# ---------------------------
async def async_setup_entry(hass, config_entry) -> bool:
"""Set up Mikrotik Router as config entry."""
controller = MikrotikControllerData(hass, config_entry)
await controller.async_hwinfo_update()
if not controller.connected():
raise ConfigEntryNotReady("Cannot connect to host")

await controller.async_update()

if not controller.data:
raise ConfigEntryNotReady()

await controller.async_init()
hass.data[DOMAIN][config_entry.entry_id] = controller
async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
"""Set up a config entry."""
coordinator = MikrotikCoordinator(hass, config_entry)
await coordinator.async_config_entry_first_refresh()
coordinatorTracker = MikrotikTrackerCoordinator(hass, config_entry, coordinator)
await coordinatorTracker.async_config_entry_first_refresh()
hass.data.setdefault(DOMAIN, {})[config_entry.entry_id] = MikrotikData(
data_coordinator=coordinator,
tracker_coordinator=coordinatorTracker,
)

await hass.config_entries.async_forward_entry_setups(config_entry, PLATFORMS)
config_entry.async_on_unload(config_entry.add_update_listener(update_listener))

config_entry.async_on_unload(config_entry.add_update_listener(async_reload_entry))

hass.services.async_register(
DOMAIN, RUN_SCRIPT_COMMAND, controller.run_script, schema=SCRIPT_SCHEMA
DOMAIN, RUN_SCRIPT_COMMAND, coordinator.run_script, schema=SCRIPT_SCHEMA
)

return True


# ---------------------------
# async_reload_entry
# ---------------------------
async def async_reload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> None:
"""Reload the config entry when it changed."""
await hass.config_entries.async_reload(config_entry.entry_id)


# ---------------------------
# async_unload_entry
# ---------------------------
async def async_unload_entry(hass, config_entry) -> bool:
async def async_unload_entry(hass: HomeAssistant, config_entry: ConfigEntry) -> bool:
"""Unload a config entry."""
unload_ok = await hass.config_entries.async_unload_platforms(

if unload_ok := await hass.config_entries.async_unload_platforms(
config_entry, PLATFORMS
)
if unload_ok:
controller = hass.data[DOMAIN][config_entry.entry_id]
await controller.async_reset()
):
hass.services.async_remove(DOMAIN, RUN_SCRIPT_COMMAND)
hass.data[DOMAIN].pop(config_entry.entry_id)

Expand Down
36 changes: 21 additions & 15 deletions custom_components/mikrotik_router/apiparser.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
"""API parser for JSON APIs"""
from pytz import utc
from logging import getLogger
"""API parser for JSON APIs."""
from datetime import datetime
from logging import getLogger

from pytz import utc
from voluptuous import Optional

from homeassistant.components.diagnostics import async_redact_data

from .const import TO_REDACT

_LOGGER = getLogger(__name__)
Expand All @@ -13,15 +16,15 @@
# utc_from_timestamp
# ---------------------------
def utc_from_timestamp(timestamp: float) -> datetime:
"""Return a UTC time from a timestamp"""
"""Return a UTC time from a timestamp."""
return utc.localize(datetime.utcfromtimestamp(timestamp))


# ---------------------------
# from_entry
# ---------------------------
def from_entry(entry, param, default="") -> str:
"""Validate and return str value an API dict"""
"""Validate and return str value an API dict."""
if "/" in param:
for tmp_param in param.split("/"):
if isinstance(entry, dict) and tmp_param in entry:
Expand Down Expand Up @@ -50,7 +53,7 @@ def from_entry(entry, param, default="") -> str:
# from_entry_bool
# ---------------------------
def from_entry_bool(entry, param, default=False, reverse=False) -> bool:
"""Validate and return a bool value from an API dict"""
"""Validate and return a bool value from an API dict."""
if "/" in param:
for tmp_param in param.split("/"):
if isinstance(entry, dict) and tmp_param in entry:
Expand Down Expand Up @@ -91,8 +94,11 @@ def parse_api(
only=None,
skip=None,
) -> dict:
"""Get data from API"""
"""Get data from API."""
debug = _LOGGER.getEffectiveLevel() == 10
if type(source) == dict:
tmp = source
source = [tmp]

if not source:
if not key and not key_search:
Expand Down Expand Up @@ -138,7 +144,7 @@ def parse_api(
# get_uid
# ---------------------------
def get_uid(entry, key, key_secondary, key_search, keymap) -> Optional(str):
"""Get UID for data list"""
"""Get UID for data list."""
uid = None
if not key_search:
key_primary_found = key in entry
Expand Down Expand Up @@ -167,7 +173,7 @@ def get_uid(entry, key, key_secondary, key_search, keymap) -> Optional(str):
# generate_keymap
# ---------------------------
def generate_keymap(data, key_search) -> Optional(dict):
"""Generate keymap"""
"""Generate keymap."""
return (
{data[uid][key_search]: uid for uid in data if key_search in data[uid]}
if key_search
Expand All @@ -179,7 +185,7 @@ def generate_keymap(data, key_search) -> Optional(dict):
# matches_only
# ---------------------------
def matches_only(entry, only) -> bool:
"""Return True if all variables are matched"""
"""Return True if all variables are matched."""
ret = False
for val in only:
if val["key"] in entry and entry[val["key"]] == val["value"]:
Expand All @@ -195,7 +201,7 @@ def matches_only(entry, only) -> bool:
# can_skip
# ---------------------------
def can_skip(entry, skip) -> bool:
"""Return True if at least one variable matches"""
"""Return True if at least one variable matches."""
ret = False
for val in skip:
if val["name"] in entry and entry[val["name"]] == val["value"]:
Expand All @@ -213,7 +219,7 @@ def can_skip(entry, skip) -> bool:
# fill_defaults
# ---------------------------
def fill_defaults(data, vals) -> dict:
"""Fill defaults if source is not present"""
"""Fill defaults if source is not present."""
for val in vals:
_name = val["name"]
_type = val["type"] if "type" in val else "str"
Expand Down Expand Up @@ -242,7 +248,7 @@ def fill_defaults(data, vals) -> dict:
# fill_vals
# ---------------------------
def fill_vals(data, entry, uid, vals) -> dict:
"""Fill all data"""
"""Fill all data."""
for val in vals:
_name = val["name"]
_type = val["type"] if "type" in val else "str"
Expand Down Expand Up @@ -292,7 +298,7 @@ def fill_vals(data, entry, uid, vals) -> dict:
# fill_ensure_vals
# ---------------------------
def fill_ensure_vals(data, uid, ensure_vals) -> dict:
"""Add required keys which are not available in data"""
"""Add required keys which are not available in data."""
for val in ensure_vals:
if uid:
if val["name"] not in data[uid]:
Expand All @@ -310,7 +316,7 @@ def fill_ensure_vals(data, uid, ensure_vals) -> dict:
# fill_vals_proc
# ---------------------------
def fill_vals_proc(data, uid, vals_proc) -> dict:
"""Add custom keys"""
"""Add custom keys."""
_data = data[uid] if uid else data
for val_sub in vals_proc:
_name = None
Expand Down
63 changes: 32 additions & 31 deletions custom_components/mikrotik_router/binary_sensor.py
Original file line number Diff line number Diff line change
@@ -1,48 +1,49 @@
"""Support for the Mikrotik Router binary sensor service."""
from __future__ import annotations

import logging
from typing import Any
from logging import getLogger
from collections.abc import Mapping
from homeassistant.components.binary_sensor import (
BinarySensorEntity,
)
from .helper import format_attribute
from .const import (
CONF_SENSOR_PPP,
DEFAULT_SENSOR_PPP,
CONF_SENSOR_PORT_TRACKER,
DEFAULT_SENSOR_PORT_TRACKER,
)
from .model import model_async_setup_entry, MikrotikEntity
from typing import Any

from homeassistant.components.binary_sensor import BinarySensorEntity
from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from .binary_sensor_types import (
SENSOR_TYPES,
SENSOR_SERVICES,
DEVICE_ATTRIBUTES_IFACE_ETHER,
DEVICE_ATTRIBUTES_IFACE_SFP,
DEVICE_ATTRIBUTES_IFACE_WIRELESS,
)
from .const import (
CONF_SENSOR_PPP,
DEFAULT_SENSOR_PPP,
CONF_SENSOR_PORT_TRACKER,
DEFAULT_SENSOR_PORT_TRACKER,
)
from .entity import MikrotikEntity, async_add_entities
from .helper import format_attribute

_LOGGER = logging.getLogger(__name__)
_LOGGER = getLogger(__name__)


# ---------------------------
# async_setup_entry
# ---------------------------
async def async_setup_entry(hass, config_entry, async_add_entities):
async def async_setup_entry(
hass: HomeAssistant,
config_entry: ConfigEntry,
_async_add_entities: AddEntitiesCallback,
) -> None:
"""Set up entry for component"""
dispatcher = {
"MikrotikBinarySensor": MikrotikBinarySensor,
"MikrotikPPPSecretBinarySensor": MikrotikPPPSecretBinarySensor,
"MikrotikPortBinarySensor": MikrotikPortBinarySensor,
}
await model_async_setup_entry(
hass,
config_entry,
async_add_entities,
SENSOR_SERVICES,
SENSOR_TYPES,
dispatcher,
)
await async_add_entities(hass, config_entry, dispatcher)


# ---------------------------
Expand Down Expand Up @@ -86,10 +87,10 @@ def is_on(self) -> bool:
else False
)

@property
def available(self) -> bool:
"""Return if controller is available."""
return self._ctrl.connected() if self.option_sensor_ppp else False
# @property
# def available(self) -> bool:
# """Return if controller is available."""
# return self._ctrl.connected() if self.option_sensor_ppp else False


# ---------------------------
Expand All @@ -105,10 +106,10 @@ def option_sensor_port_tracker(self) -> bool:
CONF_SENSOR_PORT_TRACKER, DEFAULT_SENSOR_PORT_TRACKER
)

@property
def available(self) -> bool:
"""Return if controller is available."""
return self._ctrl.connected() if self.option_sensor_port_tracker else False
# @property
# def available(self) -> bool:
# """Return if controller is available."""
# return self._ctrl.connected() if self.option_sensor_port_tracker else False

@property
def icon(self) -> str:
Expand Down
Loading

0 comments on commit 380884d

Please sign in to comment.