diff --git a/homeassistant/components/octoprint/__init__.py b/homeassistant/components/octoprint/__init__.py index eee1ccd2814..706f54ac708 100644 --- a/homeassistant/components/octoprint/__init__.py +++ b/homeassistant/components/octoprint/__init__.py @@ -1,9 +1,11 @@ """Support for monitoring OctoPrint 3D printers.""" from datetime import timedelta import logging +from typing import cast from pyoctoprintapi import ApiError, OctoprintClient, PrinterOffline import voluptuous as vol +from yarl import URL from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry from homeassistant.const import ( @@ -20,6 +22,7 @@ from homeassistant.const import ( from homeassistant.core import HomeAssistant from homeassistant.helpers.aiohttp_client import async_get_clientsession import homeassistant.helpers.config_validation as cv +from homeassistant.helpers.entity import DeviceInfo from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from homeassistant.util import slugify as util_slugify 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]) - coordinator = OctoprintDataUpdateCoordinator(hass, client, entry.entry_id, 30) + coordinator = OctoprintDataUpdateCoordinator(hass, client, entry, 30) await coordinator.async_config_entry_first_refresh() @@ -184,20 +187,23 @@ async def async_unload_entry(hass: HomeAssistant, entry: ConfigEntry): class OctoprintDataUpdateCoordinator(DataUpdateCoordinator): """Class to manage fetching Octoprint data.""" + config_entry: ConfigEntry + def __init__( self, hass: HomeAssistant, octoprint: OctoprintClient, - config_entry_id: str, + config_entry: ConfigEntry, interval: int, ) -> None: """Initialize.""" super().__init__( hass, _LOGGER, - name=f"octoprint-{config_entry_id}", + name=f"octoprint-{config_entry.entry_id}", update_interval=timedelta(seconds=interval), ) + self.config_entry = config_entry self._octoprint = octoprint self._printer_offline = False self.data = {"printer": None, "job": None, "last_read_time": None} @@ -225,3 +231,21 @@ class OctoprintDataUpdateCoordinator(DataUpdateCoordinator): self._printer_offline = False 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), + ) diff --git a/homeassistant/components/octoprint/binary_sensor.py b/homeassistant/components/octoprint/binary_sensor.py index 221fc453e07..e1db7a95136 100644 --- a/homeassistant/components/octoprint/binary_sensor.py +++ b/homeassistant/components/octoprint/binary_sensor.py @@ -2,7 +2,6 @@ from __future__ import annotations from abc import abstractmethod -import logging from pyoctoprintapi import OctoprintPrinterInfo @@ -10,14 +9,10 @@ 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 homeassistant.helpers.update_coordinator import ( - CoordinatorEntity, - DataUpdateCoordinator, -) +from homeassistant.helpers.update_coordinator import CoordinatorEntity -from .const import DOMAIN as COMPONENT_DOMAIN - -_LOGGER = logging.getLogger(__name__) +from . import OctoprintDataUpdateCoordinator +from .const import DOMAIN async def async_setup_entry( @@ -26,7 +21,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up the available OctoPrint binary sensors.""" - coordinator: DataUpdateCoordinator = hass.data[COMPONENT_DOMAIN][ + coordinator: OctoprintDataUpdateCoordinator = hass.data[DOMAIN][ config_entry.entry_id ]["coordinator"] device_id = config_entry.unique_id @@ -44,9 +39,11 @@ async def async_setup_entry( class OctoPrintBinarySensorBase(CoordinatorEntity, BinarySensorEntity): """Representation an OctoPrint binary sensor.""" + coordinator: OctoprintDataUpdateCoordinator + def __init__( self, - coordinator: DataUpdateCoordinator, + coordinator: OctoprintDataUpdateCoordinator, sensor_type: str, device_id: str, ) -> None: @@ -59,11 +56,7 @@ class OctoPrintBinarySensorBase(CoordinatorEntity, BinarySensorEntity): @property def device_info(self): """Device info.""" - return { - "identifiers": {(COMPONENT_DOMAIN, self._device_id)}, - "manufacturer": "OctoPrint", - "name": "OctoPrint", - } + return self.coordinator.device_info @property def is_on(self): @@ -86,7 +79,9 @@ class OctoPrintBinarySensorBase(CoordinatorEntity, BinarySensorEntity): class OctoPrintPrintingBinarySensor(OctoPrintBinarySensorBase): """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.""" super().__init__(coordinator, "Printing", device_id) @@ -97,7 +92,9 @@ class OctoPrintPrintingBinarySensor(OctoPrintBinarySensorBase): class OctoPrintPrintingErrorBinarySensor(OctoPrintBinarySensorBase): """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.""" super().__init__(coordinator, "Printing Error", device_id) diff --git a/homeassistant/components/octoprint/sensor.py b/homeassistant/components/octoprint/sensor.py index 8682f246aa3..70151d86022 100644 --- a/homeassistant/components/octoprint/sensor.py +++ b/homeassistant/components/octoprint/sensor.py @@ -16,12 +16,10 @@ from homeassistant.const import ( ) from homeassistant.core import HomeAssistant from homeassistant.helpers.entity_platform import AddEntitiesCallback -from homeassistant.helpers.update_coordinator import ( - CoordinatorEntity, - DataUpdateCoordinator, -) +from homeassistant.helpers.update_coordinator import CoordinatorEntity -from . import DOMAIN as COMPONENT_DOMAIN +from . import OctoprintDataUpdateCoordinator +from .const import DOMAIN _LOGGER = logging.getLogger(__name__) @@ -32,7 +30,7 @@ async def async_setup_entry( async_add_entities: AddEntitiesCallback, ) -> None: """Set up the available OctoPrint binary sensors.""" - coordinator: DataUpdateCoordinator = hass.data[COMPONENT_DOMAIN][ + coordinator: OctoprintDataUpdateCoordinator = hass.data[DOMAIN][ config_entry.entry_id ]["coordinator"] device_id = config_entry.unique_id @@ -67,9 +65,11 @@ async def async_setup_entry( class OctoPrintSensorBase(CoordinatorEntity, SensorEntity): """Representation of an OctoPrint sensor.""" + coordinator: OctoprintDataUpdateCoordinator + def __init__( self, - coordinator: DataUpdateCoordinator, + coordinator: OctoprintDataUpdateCoordinator, sensor_type: str, device_id: str, ) -> None: @@ -82,11 +82,7 @@ class OctoPrintSensorBase(CoordinatorEntity, SensorEntity): @property def device_info(self): """Device info.""" - return { - "identifiers": {(COMPONENT_DOMAIN, self._device_id)}, - "manufacturer": "OctoPrint", - "name": "OctoPrint", - } + return self.coordinator.device_info class OctoPrintStatusSensor(OctoPrintSensorBase): @@ -94,7 +90,9 @@ class OctoPrintStatusSensor(OctoPrintSensorBase): _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.""" super().__init__(coordinator, "Current State", device_id) @@ -119,7 +117,9 @@ class OctoPrintJobPercentageSensor(OctoPrintSensorBase): _attr_native_unit_of_measurement = PERCENTAGE _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.""" super().__init__(coordinator, "Job Percentage", device_id) @@ -141,7 +141,9 @@ class OctoPrintEstimatedFinishTimeSensor(OctoPrintSensorBase): _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.""" super().__init__(coordinator, "Estimated Finish Time", device_id) @@ -162,7 +164,9 @@ class OctoPrintStartTimeSensor(OctoPrintSensorBase): _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.""" super().__init__(coordinator, "Start Time", device_id) @@ -188,7 +192,7 @@ class OctoPrintTemperatureSensor(OctoPrintSensorBase): def __init__( self, - coordinator: DataUpdateCoordinator, + coordinator: OctoprintDataUpdateCoordinator, tool: str, temp_type: str, device_id: str,