Add configuration_url to OctoPrint (#58753)

* Add configuration_url to Octoprint

* fix device_info() return

Co-authored-by: Michael <35783820+mib1185@users.noreply.github.com>
This commit is contained in:
Franck Nijhof 2021-10-31 08:00:31 +01:00 committed by GitHub
parent 8da010cacd
commit 26b951194c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 37 deletions

View File

@ -1,9 +1,11 @@
"""Support for monitoring OctoPrint 3D printers.""" """Support for monitoring OctoPrint 3D printers."""
from datetime import timedelta from datetime import timedelta
import logging import logging
from typing import cast
from pyoctoprintapi import ApiError, OctoprintClient, PrinterOffline from pyoctoprintapi import ApiError, OctoprintClient, PrinterOffline
import voluptuous as vol import voluptuous as vol
from yarl import URL
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
from homeassistant.const import ( from homeassistant.const import (
@ -20,6 +22,7 @@ from homeassistant.const import (
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.aiohttp_client import async_get_clientsession from homeassistant.helpers.aiohttp_client import async_get_clientsession
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.entity import DeviceInfo
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from homeassistant.util import slugify as util_slugify from homeassistant.util import slugify as util_slugify
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
@ -160,7 +163,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
client.set_api_key(entry.data[CONF_API_KEY]) client.set_api_key(entry.data[CONF_API_KEY])
coordinator = OctoprintDataUpdateCoordinator(hass, client, entry.entry_id, 30) coordinator = OctoprintDataUpdateCoordinator(hass, client, entry, 30)
await coordinator.async_config_entry_first_refresh() await coordinator.async_config_entry_first_refresh()
@ -184,20 +187,23 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry):
class OctoprintDataUpdateCoordinator(DataUpdateCoordinator): class OctoprintDataUpdateCoordinator(DataUpdateCoordinator):
"""Class to manage fetching Octoprint data.""" """Class to manage fetching Octoprint data."""
config_entry: ConfigEntry
def __init__( def __init__(
self, self,
hass: HomeAssistant, hass: HomeAssistant,
octoprint: OctoprintClient, octoprint: OctoprintClient,
config_entry_id: str, config_entry: ConfigEntry,
interval: int, interval: int,
) -> None: ) -> None:
"""Initialize.""" """Initialize."""
super().__init__( super().__init__(
hass, hass,
_LOGGER, _LOGGER,
name=f"octoprint-{config_entry_id}", name=f"octoprint-{config_entry.entry_id}",
update_interval=timedelta(seconds=interval), update_interval=timedelta(seconds=interval),
) )
self.config_entry = config_entry
self._octoprint = octoprint self._octoprint = octoprint
self._printer_offline = False self._printer_offline = False
self.data = {"printer": None, "job": None, "last_read_time": None} self.data = {"printer": None, "job": None, "last_read_time": None}
@ -225,3 +231,21 @@ class OctoprintDataUpdateCoordinator(DataUpdateCoordinator):
self._printer_offline = False self._printer_offline = False
return {"job": job, "printer": printer, "last_read_time": dt_util.utcnow()} return {"job": job, "printer": printer, "last_read_time": dt_util.utcnow()}
@property
def device_info(self) -> DeviceInfo:
"""Device info."""
unique_id = cast(str, self.config_entry.unique_id)
configuration_url = URL.build(
scheme=self.config_entry.data[CONF_SSL] and "https" or "http",
host=self.config_entry.data[CONF_HOST],
port=self.config_entry.data[CONF_PORT],
path=self.config_entry.data[CONF_PATH],
)
return DeviceInfo(
identifiers={(DOMAIN, unique_id)},
manufacturer="OctoPrint",
name="OctoPrint",
configuration_url=str(configuration_url),
)

View File

@ -2,7 +2,6 @@
from __future__ import annotations from __future__ import annotations
from abc import abstractmethod from abc import abstractmethod
import logging
from pyoctoprintapi import OctoprintPrinterInfo from pyoctoprintapi import OctoprintPrinterInfo
@ -10,14 +9,10 @@ from homeassistant.components.binary_sensor import BinarySensorEntity
from homeassistant.config_entries import ConfigEntry from homeassistant.config_entries import ConfigEntry
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import ( from homeassistant.helpers.update_coordinator import CoordinatorEntity
CoordinatorEntity,
DataUpdateCoordinator,
)
from .const import DOMAIN as COMPONENT_DOMAIN from . import OctoprintDataUpdateCoordinator
from .const import DOMAIN
_LOGGER = logging.getLogger(__name__)
async def async_setup_entry( async def async_setup_entry(
@ -26,7 +21,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up the available OctoPrint binary sensors.""" """Set up the available OctoPrint binary sensors."""
coordinator: DataUpdateCoordinator = hass.data[COMPONENT_DOMAIN][ coordinator: OctoprintDataUpdateCoordinator = hass.data[DOMAIN][
config_entry.entry_id config_entry.entry_id
]["coordinator"] ]["coordinator"]
device_id = config_entry.unique_id device_id = config_entry.unique_id
@ -44,9 +39,11 @@ async def async_setup_entry(
class OctoPrintBinarySensorBase(CoordinatorEntity, BinarySensorEntity): class OctoPrintBinarySensorBase(CoordinatorEntity, BinarySensorEntity):
"""Representation an OctoPrint binary sensor.""" """Representation an OctoPrint binary sensor."""
coordinator: OctoprintDataUpdateCoordinator
def __init__( def __init__(
self, self,
coordinator: DataUpdateCoordinator, coordinator: OctoprintDataUpdateCoordinator,
sensor_type: str, sensor_type: str,
device_id: str, device_id: str,
) -> None: ) -> None:
@ -59,11 +56,7 @@ class OctoPrintBinarySensorBase(CoordinatorEntity, BinarySensorEntity):
@property @property
def device_info(self): def device_info(self):
"""Device info.""" """Device info."""
return { return self.coordinator.device_info
"identifiers": {(COMPONENT_DOMAIN, self._device_id)},
"manufacturer": "OctoPrint",
"name": "OctoPrint",
}
@property @property
def is_on(self): def is_on(self):
@ -86,7 +79,9 @@ class OctoPrintBinarySensorBase(CoordinatorEntity, BinarySensorEntity):
class OctoPrintPrintingBinarySensor(OctoPrintBinarySensorBase): class OctoPrintPrintingBinarySensor(OctoPrintBinarySensorBase):
"""Representation an OctoPrint binary sensor.""" """Representation an OctoPrint binary sensor."""
def __init__(self, coordinator: DataUpdateCoordinator, device_id: str) -> None: def __init__(
self, coordinator: OctoprintDataUpdateCoordinator, device_id: str
) -> None:
"""Initialize a new OctoPrint sensor.""" """Initialize a new OctoPrint sensor."""
super().__init__(coordinator, "Printing", device_id) super().__init__(coordinator, "Printing", device_id)
@ -97,7 +92,9 @@ class OctoPrintPrintingBinarySensor(OctoPrintBinarySensorBase):
class OctoPrintPrintingErrorBinarySensor(OctoPrintBinarySensorBase): class OctoPrintPrintingErrorBinarySensor(OctoPrintBinarySensorBase):
"""Representation an OctoPrint binary sensor.""" """Representation an OctoPrint binary sensor."""
def __init__(self, coordinator: DataUpdateCoordinator, device_id: str) -> None: def __init__(
self, coordinator: OctoprintDataUpdateCoordinator, device_id: str
) -> None:
"""Initialize a new OctoPrint sensor.""" """Initialize a new OctoPrint sensor."""
super().__init__(coordinator, "Printing Error", device_id) super().__init__(coordinator, "Printing Error", device_id)

View File

@ -16,12 +16,10 @@ from homeassistant.const import (
) )
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.update_coordinator import ( from homeassistant.helpers.update_coordinator import CoordinatorEntity
CoordinatorEntity,
DataUpdateCoordinator,
)
from . import DOMAIN as COMPONENT_DOMAIN from . import OctoprintDataUpdateCoordinator
from .const import DOMAIN
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -32,7 +30,7 @@ async def async_setup_entry(
async_add_entities: AddEntitiesCallback, async_add_entities: AddEntitiesCallback,
) -> None: ) -> None:
"""Set up the available OctoPrint binary sensors.""" """Set up the available OctoPrint binary sensors."""
coordinator: DataUpdateCoordinator = hass.data[COMPONENT_DOMAIN][ coordinator: OctoprintDataUpdateCoordinator = hass.data[DOMAIN][
config_entry.entry_id config_entry.entry_id
]["coordinator"] ]["coordinator"]
device_id = config_entry.unique_id device_id = config_entry.unique_id
@ -67,9 +65,11 @@ async def async_setup_entry(
class OctoPrintSensorBase(CoordinatorEntity, SensorEntity): class OctoPrintSensorBase(CoordinatorEntity, SensorEntity):
"""Representation of an OctoPrint sensor.""" """Representation of an OctoPrint sensor."""
coordinator: OctoprintDataUpdateCoordinator
def __init__( def __init__(
self, self,
coordinator: DataUpdateCoordinator, coordinator: OctoprintDataUpdateCoordinator,
sensor_type: str, sensor_type: str,
device_id: str, device_id: str,
) -> None: ) -> None:
@ -82,11 +82,7 @@ class OctoPrintSensorBase(CoordinatorEntity, SensorEntity):
@property @property
def device_info(self): def device_info(self):
"""Device info.""" """Device info."""
return { return self.coordinator.device_info
"identifiers": {(COMPONENT_DOMAIN, self._device_id)},
"manufacturer": "OctoPrint",
"name": "OctoPrint",
}
class OctoPrintStatusSensor(OctoPrintSensorBase): class OctoPrintStatusSensor(OctoPrintSensorBase):
@ -94,7 +90,9 @@ class OctoPrintStatusSensor(OctoPrintSensorBase):
_attr_icon = "mdi:printer-3d" _attr_icon = "mdi:printer-3d"
def __init__(self, coordinator: DataUpdateCoordinator, device_id: str) -> None: def __init__(
self, coordinator: OctoprintDataUpdateCoordinator, device_id: str
) -> None:
"""Initialize a new OctoPrint sensor.""" """Initialize a new OctoPrint sensor."""
super().__init__(coordinator, "Current State", device_id) super().__init__(coordinator, "Current State", device_id)
@ -119,7 +117,9 @@ class OctoPrintJobPercentageSensor(OctoPrintSensorBase):
_attr_native_unit_of_measurement = PERCENTAGE _attr_native_unit_of_measurement = PERCENTAGE
_attr_icon = "mdi:file-percent" _attr_icon = "mdi:file-percent"
def __init__(self, coordinator: DataUpdateCoordinator, device_id: str) -> None: def __init__(
self, coordinator: OctoprintDataUpdateCoordinator, device_id: str
) -> None:
"""Initialize a new OctoPrint sensor.""" """Initialize a new OctoPrint sensor."""
super().__init__(coordinator, "Job Percentage", device_id) super().__init__(coordinator, "Job Percentage", device_id)
@ -141,7 +141,9 @@ class OctoPrintEstimatedFinishTimeSensor(OctoPrintSensorBase):
_attr_device_class = DEVICE_CLASS_TIMESTAMP _attr_device_class = DEVICE_CLASS_TIMESTAMP
def __init__(self, coordinator: DataUpdateCoordinator, device_id: str) -> None: def __init__(
self, coordinator: OctoprintDataUpdateCoordinator, device_id: str
) -> None:
"""Initialize a new OctoPrint sensor.""" """Initialize a new OctoPrint sensor."""
super().__init__(coordinator, "Estimated Finish Time", device_id) super().__init__(coordinator, "Estimated Finish Time", device_id)
@ -162,7 +164,9 @@ class OctoPrintStartTimeSensor(OctoPrintSensorBase):
_attr_device_class = DEVICE_CLASS_TIMESTAMP _attr_device_class = DEVICE_CLASS_TIMESTAMP
def __init__(self, coordinator: DataUpdateCoordinator, device_id: str) -> None: def __init__(
self, coordinator: OctoprintDataUpdateCoordinator, device_id: str
) -> None:
"""Initialize a new OctoPrint sensor.""" """Initialize a new OctoPrint sensor."""
super().__init__(coordinator, "Start Time", device_id) super().__init__(coordinator, "Start Time", device_id)
@ -188,7 +192,7 @@ class OctoPrintTemperatureSensor(OctoPrintSensorBase):
def __init__( def __init__(
self, self,
coordinator: DataUpdateCoordinator, coordinator: OctoprintDataUpdateCoordinator,
tool: str, tool: str,
temp_type: str, temp_type: str,
device_id: str, device_id: str,