core/homeassistant/components/brother/sensor.py

424 lines
15 KiB
Python

"""Support for the Brother service."""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from datetime import datetime
import logging
from brother import BrotherSensors
from homeassistant.components.sensor import (
DOMAIN as PLATFORM,
SensorDeviceClass,
SensorEntity,
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_HOST, PERCENTAGE
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity import DeviceInfo, EntityCategory
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import StateType
from homeassistant.helpers.update_coordinator import CoordinatorEntity
from . import BrotherDataUpdateCoordinator
from .const import DATA_CONFIG_ENTRY, DOMAIN
ATTR_COUNTER = "counter"
ATTR_REMAINING_PAGES = "remaining_pages"
UNIT_PAGES = "p"
_LOGGER = logging.getLogger(__name__)
@dataclass
class BrotherSensorRequiredKeysMixin:
"""Class for Brother entity required keys."""
value: Callable[[BrotherSensors], StateType | datetime]
@dataclass
class BrotherSensorEntityDescription(
SensorEntityDescription, BrotherSensorRequiredKeysMixin
):
"""A class that describes sensor entities."""
SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
BrotherSensorEntityDescription(
key="status",
icon="mdi:printer",
name="Status",
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.status,
),
BrotherSensorEntityDescription(
key="page_counter",
icon="mdi:file-document-outline",
name="Page counter",
native_unit_of_measurement=UNIT_PAGES,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.page_counter,
),
BrotherSensorEntityDescription(
key="bw_counter",
icon="mdi:file-document-outline",
name="B/W counter",
native_unit_of_measurement=UNIT_PAGES,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.bw_counter,
),
BrotherSensorEntityDescription(
key="color_counter",
icon="mdi:file-document-outline",
name="Color counter",
native_unit_of_measurement=UNIT_PAGES,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.color_counter,
),
BrotherSensorEntityDescription(
key="duplex_unit_pages_counter",
icon="mdi:file-document-outline",
name="Duplex unit pages counter",
native_unit_of_measurement=UNIT_PAGES,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.duplex_unit_pages_counter,
),
BrotherSensorEntityDescription(
key="drum_remaining_life",
icon="mdi:chart-donut",
name="Drum remaining life",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.drum_remaining_life,
),
BrotherSensorEntityDescription(
key="drum_remaining_pages",
icon="mdi:chart-donut",
name="Drum remaining pages",
native_unit_of_measurement=UNIT_PAGES,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.drum_remaining_pages,
),
BrotherSensorEntityDescription(
key="drum_counter",
icon="mdi:chart-donut",
name="Drum counter",
native_unit_of_measurement=UNIT_PAGES,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.drum_counter,
),
BrotherSensorEntityDescription(
key="black_drum_remaining_life",
icon="mdi:chart-donut",
name="Black drum remaining life",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.black_drum_remaining_life,
),
BrotherSensorEntityDescription(
key="black_drum_remaining_pages",
icon="mdi:chart-donut",
name="Black drum remaining pages",
native_unit_of_measurement=UNIT_PAGES,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.black_drum_remaining_pages,
),
BrotherSensorEntityDescription(
key="black_drum_counter",
icon="mdi:chart-donut",
name="Black drum counter",
native_unit_of_measurement=UNIT_PAGES,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.black_drum_counter,
),
BrotherSensorEntityDescription(
key="cyan_drum_remaining_life",
icon="mdi:chart-donut",
name="Cyan drum remaining life",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.cyan_drum_remaining_life,
),
BrotherSensorEntityDescription(
key="cyan_drum_remaining_pages",
icon="mdi:chart-donut",
name="Cyan drum remaining pages",
native_unit_of_measurement=UNIT_PAGES,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.cyan_drum_remaining_pages,
),
BrotherSensorEntityDescription(
key="cyan_drum_counter",
icon="mdi:chart-donut",
name="Cyan drum counter",
native_unit_of_measurement=UNIT_PAGES,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.cyan_drum_counter,
),
BrotherSensorEntityDescription(
key="magenta_drum_remaining_life",
icon="mdi:chart-donut",
name="Magenta drum remaining life",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.magenta_drum_remaining_life,
),
BrotherSensorEntityDescription(
key="magenta_drum_remaining_pages",
icon="mdi:chart-donut",
name="Magenta drum remaining pages",
native_unit_of_measurement=UNIT_PAGES,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.magenta_drum_remaining_pages,
),
BrotherSensorEntityDescription(
key="magenta_drum_counter",
icon="mdi:chart-donut",
name="Magenta drum counter",
native_unit_of_measurement=UNIT_PAGES,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.magenta_drum_counter,
),
BrotherSensorEntityDescription(
key="yellow_drum_remaining_life",
icon="mdi:chart-donut",
name="Yellow drum remaining life",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.yellow_drum_remaining_life,
),
BrotherSensorEntityDescription(
key="yellow_drum_remaining_pages",
icon="mdi:chart-donut",
name="Yellow drum remaining pages",
native_unit_of_measurement=UNIT_PAGES,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.yellow_drum_remaining_pages,
),
BrotherSensorEntityDescription(
key="yellow_drum_counter",
icon="mdi:chart-donut",
name="Yellow drum counter",
native_unit_of_measurement=UNIT_PAGES,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.yellow_drum_counter,
),
BrotherSensorEntityDescription(
key="belt_unit_remaining_life",
icon="mdi:current-ac",
name="Belt unit remaining life",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.belt_unit_remaining_life,
),
BrotherSensorEntityDescription(
key="fuser_remaining_life",
icon="mdi:water-outline",
name="Fuser remaining life",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.fuser_remaining_life,
),
BrotherSensorEntityDescription(
key="laser_remaining_life",
icon="mdi:spotlight-beam",
name="Laser remaining life",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.laser_remaining_life,
),
BrotherSensorEntityDescription(
key="pf_kit_1_remaining_life",
icon="mdi:printer-3d",
name="PF Kit 1 remaining life",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.pf_kit_1_remaining_life,
),
BrotherSensorEntityDescription(
key="pf_kit_mp_remaining_life",
icon="mdi:printer-3d",
name="PF Kit MP remaining life",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.pf_kit_mp_remaining_life,
),
BrotherSensorEntityDescription(
key="black_toner_remaining",
icon="mdi:printer-3d-nozzle",
name="Black toner remaining",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.black_toner_remaining,
),
BrotherSensorEntityDescription(
key="cyan_toner_remaining",
icon="mdi:printer-3d-nozzle",
name="Cyan toner remaining",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.cyan_toner_remaining,
),
BrotherSensorEntityDescription(
key="magenta_toner_remaining",
icon="mdi:printer-3d-nozzle",
name="Magenta toner remaining",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.magenta_toner_remaining,
),
BrotherSensorEntityDescription(
key="yellow_toner_remaining",
icon="mdi:printer-3d-nozzle",
name="Yellow toner remaining",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.yellow_toner_remaining,
),
BrotherSensorEntityDescription(
key="black_ink_remaining",
icon="mdi:printer-3d-nozzle",
name="Black ink remaining",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.black_ink_remaining,
),
BrotherSensorEntityDescription(
key="cyan_ink_remaining",
icon="mdi:printer-3d-nozzle",
name="Cyan ink remaining",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.cyan_ink_remaining,
),
BrotherSensorEntityDescription(
key="magenta_ink_remaining",
icon="mdi:printer-3d-nozzle",
name="Magenta ink remaining",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.magenta_ink_remaining,
),
BrotherSensorEntityDescription(
key="yellow_ink_remaining",
icon="mdi:printer-3d-nozzle",
name="Yellow ink remaining",
native_unit_of_measurement=PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.yellow_ink_remaining,
),
BrotherSensorEntityDescription(
key="uptime",
name="Uptime",
entity_registry_enabled_default=False,
device_class=SensorDeviceClass.TIMESTAMP,
entity_category=EntityCategory.DIAGNOSTIC,
value=lambda data: data.uptime,
),
)
async def async_setup_entry(
hass: HomeAssistant, entry: ConfigEntry, async_add_entities: AddEntitiesCallback
) -> None:
"""Add Brother entities from a config_entry."""
coordinator = hass.data[DOMAIN][DATA_CONFIG_ENTRY][entry.entry_id]
# Due to the change of the attribute name of one sensor, it is necessary to migrate
# the unique_id to the new one.
entity_registry = er.async_get(hass)
old_unique_id = f"{coordinator.data.serial.lower()}_b/w_counter"
if entity_id := entity_registry.async_get_entity_id(
PLATFORM, DOMAIN, old_unique_id
):
new_unique_id = f"{coordinator.data.serial.lower()}_bw_counter"
_LOGGER.debug(
"Migrating entity %s from old unique ID '%s' to new unique ID '%s'",
entity_id,
old_unique_id,
new_unique_id,
)
entity_registry.async_update_entity(entity_id, new_unique_id=new_unique_id)
sensors = []
device_info = DeviceInfo(
configuration_url=f"http://{entry.data[CONF_HOST]}/",
identifiers={(DOMAIN, coordinator.data.serial)},
manufacturer="Brother",
model=coordinator.data.model,
name=coordinator.data.model,
sw_version=coordinator.data.firmware,
)
for description in SENSOR_TYPES:
if description.value(coordinator.data) is not None:
sensors.append(BrotherPrinterSensor(coordinator, description, device_info))
async_add_entities(sensors, False)
class BrotherPrinterSensor(
CoordinatorEntity[BrotherDataUpdateCoordinator], SensorEntity
):
"""Define an Brother Printer sensor."""
_attr_has_entity_name = True
entity_description: BrotherSensorEntityDescription
def __init__(
self,
coordinator: BrotherDataUpdateCoordinator,
description: BrotherSensorEntityDescription,
device_info: DeviceInfo,
) -> None:
"""Initialize."""
super().__init__(coordinator)
self._attr_device_info = device_info
self._attr_native_value = description.value(coordinator.data)
self._attr_unique_id = f"{coordinator.data.serial.lower()}_{description.key}"
self.entity_description = description
@callback
def _handle_coordinator_update(self) -> None:
"""Handle updated data from the coordinator."""
self._attr_native_value = self.entity_description.value(self.coordinator.data)
self.async_write_ha_state()