diff --git a/custom_components/mikrotik_router/binary_sensor_types.py b/custom_components/mikrotik_router/binary_sensor_types.py index c1b5226..6f16fad 100644 --- a/custom_components/mikrotik_router/binary_sensor_types.py +++ b/custom_components/mikrotik_router/binary_sensor_types.py @@ -111,20 +111,6 @@ class MikrotikBinarySensorEntityDescription(BinarySensorEntityDescription): SENSOR_TYPES = { - "system_fwupdate": MikrotikBinarySensorEntityDescription( - key="system_fwupdate", - name="Firmware update", - icon_enabled="", - icon_disabled="", - device_class=BinarySensorDeviceClass.UPDATE, - entity_category=EntityCategory.DIAGNOSTIC, - ha_group="System", - data_path="fw-update", - data_name="", - data_uid="", - data_reference="", - data_attributes_list=DEVICE_ATTRIBUTES_FWUPDATE, - ), "system_ups": MikrotikBinarySensorEntityDescription( key="system_ups", name="UPS", diff --git a/custom_components/mikrotik_router/const.py b/custom_components/mikrotik_router/const.py index 54367c7..7ae0301 100644 --- a/custom_components/mikrotik_router/const.py +++ b/custom_components/mikrotik_router/const.py @@ -7,6 +7,7 @@ PLATFORMS = [ Platform.DEVICE_TRACKER, Platform.SWITCH, Platform.BUTTON, + Platform.UPDATE, ] DOMAIN = "mikrotik_router" diff --git a/custom_components/mikrotik_router/update.py b/custom_components/mikrotik_router/update.py new file mode 100644 index 0000000..9c08418 --- /dev/null +++ b/custom_components/mikrotik_router/update.py @@ -0,0 +1,108 @@ +"""Support for the Mikrotik Router update service.""" + +import logging +from typing import Any +from requests import get as requests_get +from homeassistant.components.update import ( + UpdateEntity, + UpdateDeviceClass, + UpdateEntityFeature, +) +from .model import model_async_setup_entry, MikrotikEntity +from .update_types import ( + SENSOR_TYPES, + SENSOR_SERVICES, +) + +_LOGGER = logging.getLogger(__name__) +DEVICE_UPDATE = "device_update" + + +# --------------------------- +# async_setup_entry +# --------------------------- +async def async_setup_entry(hass, config_entry, async_add_entities): + """Set up entry for component""" + dispatcher = { + "MikrotikUpdate": MikrotikUpdate, + } + await model_async_setup_entry( + hass, + config_entry, + async_add_entities, + SENSOR_SERVICES, + SENSOR_TYPES, + dispatcher, + ) + + +# --------------------------- +# MikrotikUpdate +# --------------------------- +class MikrotikUpdate(MikrotikEntity, UpdateEntity): + """Define an Mikrotik Controller Update entity.""" + + TYPE = DEVICE_UPDATE + _attr_device_class = UpdateDeviceClass.FIRMWARE + + def __init__( + self, + inst, + uid: "", + mikrotik_controller, + entity_description, + ): + """Set up device update entity.""" + super().__init__(inst, uid, mikrotik_controller, entity_description) + + self._attr_supported_features = UpdateEntityFeature.INSTALL + self._attr_supported_features |= UpdateEntityFeature.BACKUP + self._attr_supported_features |= UpdateEntityFeature.RELEASE_NOTES + + @property + def is_on(self) -> bool: + """Return true if device is on.""" + return self._data[self.entity_description.data_attribute] + + @property + def installed_version(self) -> str: + """Version installed and in use.""" + return self._data["installed-version"] + + @property + def latest_version(self) -> str: + """Latest version available for install.""" + return self._data["latest-version"] + + async def options_updated(self) -> None: + """No action needed.""" + + async def async_install(self, version: str, backup: bool, **kwargs: Any) -> None: + """Install an update.""" + if backup: + self._ctrl.execute("/system/backup", "save", None, None) + + self._ctrl.execute("/system/package/update", "install", None, None) + + # await self.controller.api.devices.upgrade(self.device.mac) + + async def async_release_notes(self) -> str: + """Return the release notes.""" + try: + response = await self._ctrl.hass.async_add_executor_job( + requests_get, + f"https://mikrotik.com/download/changelogs?ax=loadLog&val={self._data['latest-version']}", + ) + + if response.status_code == 200: + return response.text.replace(chr(10), "
") + + except: + _LOGGER.warning("Mikrotik %s failed to download release notes", self._host) + + return "Failed to download release notes" + + @property + def release_url(self) -> str: + """URL to the full release notes of the latest version available.""" + return "https://mikrotik.com/download/changelogs" diff --git a/custom_components/mikrotik_router/update_types.py b/custom_components/mikrotik_router/update_types.py new file mode 100644 index 0000000..e7f6a95 --- /dev/null +++ b/custom_components/mikrotik_router/update_types.py @@ -0,0 +1,36 @@ +"""Definitions for Mikrotik Router update entities.""" +from dataclasses import dataclass, field +from typing import List +from homeassistant.components.update import UpdateEntityDescription + + +@dataclass +class MikrotikUpdateEntityDescription(UpdateEntityDescription): + """Class describing mikrotik entities.""" + + ha_group: str = "" + ha_connection: str = "" + ha_connection_value: str = "" + data_path: str = "" + data_attribute: str = "available" + data_name: str = "" + data_name_comment: bool = False + data_uid: str = "" + data_reference: str = "" + data_attributes_list: List = field(default_factory=lambda: []) + func: str = "MikrotikUpdate" + + +SENSOR_TYPES = { + "system_fwupdate": MikrotikUpdateEntityDescription( + key="system_fwupdate", + name="Firmware update", + ha_group="System", + data_path="fw-update", + data_name="", + data_uid="", + data_reference="", + ), +} + +SENSOR_SERVICES = {}