Home Assistant Unofficial Reference 2024.12.1
sensor.py
Go to the documentation of this file.
1 """Support for the Brother service."""
2 
3 from __future__ import annotations
4 
5 from collections.abc import Callable
6 from dataclasses import dataclass
7 from datetime import datetime
8 import logging
9 
10 from brother import BrotherSensors
11 
13  DOMAIN as PLATFORM,
14  SensorDeviceClass,
15  SensorEntity,
16  SensorEntityDescription,
17  SensorStateClass,
18 )
19 from homeassistant.const import PERCENTAGE, EntityCategory
20 from homeassistant.core import HomeAssistant, callback
21 from homeassistant.helpers import entity_registry as er
22 from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, DeviceInfo
23 from homeassistant.helpers.entity_platform import AddEntitiesCallback
24 from homeassistant.helpers.typing import StateType
25 from homeassistant.helpers.update_coordinator import CoordinatorEntity
26 
27 from . import BrotherConfigEntry, BrotherDataUpdateCoordinator
28 from .const import DOMAIN
29 
30 ATTR_COUNTER = "counter"
31 ATTR_REMAINING_PAGES = "remaining_pages"
32 
33 _LOGGER = logging.getLogger(__name__)
34 
35 
36 @dataclass(frozen=True, kw_only=True)
38  """A class that describes sensor entities."""
39 
40  value: Callable[[BrotherSensors], StateType | datetime]
41 
42 
43 SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
45  key="status",
46  translation_key="status",
47  entity_category=EntityCategory.DIAGNOSTIC,
48  value=lambda data: data.status,
49  ),
51  key="page_counter",
52  translation_key="page_counter",
53  state_class=SensorStateClass.MEASUREMENT,
54  entity_category=EntityCategory.DIAGNOSTIC,
55  value=lambda data: data.page_counter,
56  ),
58  key="bw_counter",
59  translation_key="bw_pages",
60  state_class=SensorStateClass.MEASUREMENT,
61  entity_category=EntityCategory.DIAGNOSTIC,
62  value=lambda data: data.bw_counter,
63  ),
65  key="color_counter",
66  translation_key="color_pages",
67  state_class=SensorStateClass.MEASUREMENT,
68  entity_category=EntityCategory.DIAGNOSTIC,
69  value=lambda data: data.color_counter,
70  ),
72  key="duplex_unit_pages_counter",
73  translation_key="duplex_unit_page_counter",
74  state_class=SensorStateClass.MEASUREMENT,
75  entity_category=EntityCategory.DIAGNOSTIC,
76  value=lambda data: data.duplex_unit_pages_counter,
77  ),
79  key="drum_remaining_life",
80  translation_key="drum_remaining_life",
81  native_unit_of_measurement=PERCENTAGE,
82  state_class=SensorStateClass.MEASUREMENT,
83  entity_category=EntityCategory.DIAGNOSTIC,
84  value=lambda data: data.drum_remaining_life,
85  ),
87  key="drum_remaining_pages",
88  translation_key="drum_remaining_pages",
89  state_class=SensorStateClass.MEASUREMENT,
90  entity_category=EntityCategory.DIAGNOSTIC,
91  value=lambda data: data.drum_remaining_pages,
92  ),
94  key="drum_counter",
95  translation_key="drum_page_counter",
96  state_class=SensorStateClass.MEASUREMENT,
97  entity_category=EntityCategory.DIAGNOSTIC,
98  value=lambda data: data.drum_counter,
99  ),
101  key="black_drum_remaining_life",
102  translation_key="black_drum_remaining_life",
103  native_unit_of_measurement=PERCENTAGE,
104  state_class=SensorStateClass.MEASUREMENT,
105  entity_category=EntityCategory.DIAGNOSTIC,
106  value=lambda data: data.black_drum_remaining_life,
107  ),
109  key="black_drum_remaining_pages",
110  translation_key="black_drum_remaining_pages",
111  state_class=SensorStateClass.MEASUREMENT,
112  entity_category=EntityCategory.DIAGNOSTIC,
113  value=lambda data: data.black_drum_remaining_pages,
114  ),
116  key="black_drum_counter",
117  translation_key="black_drum_page_counter",
118  state_class=SensorStateClass.MEASUREMENT,
119  entity_category=EntityCategory.DIAGNOSTIC,
120  value=lambda data: data.black_drum_counter,
121  ),
123  key="cyan_drum_remaining_life",
124  translation_key="cyan_drum_remaining_life",
125  native_unit_of_measurement=PERCENTAGE,
126  state_class=SensorStateClass.MEASUREMENT,
127  entity_category=EntityCategory.DIAGNOSTIC,
128  value=lambda data: data.cyan_drum_remaining_life,
129  ),
131  key="cyan_drum_remaining_pages",
132  translation_key="cyan_drum_remaining_pages",
133  state_class=SensorStateClass.MEASUREMENT,
134  entity_category=EntityCategory.DIAGNOSTIC,
135  value=lambda data: data.cyan_drum_remaining_pages,
136  ),
138  key="cyan_drum_counter",
139  translation_key="cyan_drum_page_counter",
140  state_class=SensorStateClass.MEASUREMENT,
141  entity_category=EntityCategory.DIAGNOSTIC,
142  value=lambda data: data.cyan_drum_counter,
143  ),
145  key="magenta_drum_remaining_life",
146  translation_key="magenta_drum_remaining_life",
147  native_unit_of_measurement=PERCENTAGE,
148  state_class=SensorStateClass.MEASUREMENT,
149  entity_category=EntityCategory.DIAGNOSTIC,
150  value=lambda data: data.magenta_drum_remaining_life,
151  ),
153  key="magenta_drum_remaining_pages",
154  translation_key="magenta_drum_remaining_pages",
155  state_class=SensorStateClass.MEASUREMENT,
156  entity_category=EntityCategory.DIAGNOSTIC,
157  value=lambda data: data.magenta_drum_remaining_pages,
158  ),
160  key="magenta_drum_counter",
161  translation_key="magenta_drum_page_counter",
162  state_class=SensorStateClass.MEASUREMENT,
163  entity_category=EntityCategory.DIAGNOSTIC,
164  value=lambda data: data.magenta_drum_counter,
165  ),
167  key="yellow_drum_remaining_life",
168  translation_key="yellow_drum_remaining_life",
169  native_unit_of_measurement=PERCENTAGE,
170  state_class=SensorStateClass.MEASUREMENT,
171  entity_category=EntityCategory.DIAGNOSTIC,
172  value=lambda data: data.yellow_drum_remaining_life,
173  ),
175  key="yellow_drum_remaining_pages",
176  translation_key="yellow_drum_remaining_pages",
177  state_class=SensorStateClass.MEASUREMENT,
178  entity_category=EntityCategory.DIAGNOSTIC,
179  value=lambda data: data.yellow_drum_remaining_pages,
180  ),
182  key="yellow_drum_counter",
183  translation_key="yellow_drum_page_counter",
184  state_class=SensorStateClass.MEASUREMENT,
185  entity_category=EntityCategory.DIAGNOSTIC,
186  value=lambda data: data.yellow_drum_counter,
187  ),
189  key="belt_unit_remaining_life",
190  translation_key="belt_unit_remaining_life",
191  native_unit_of_measurement=PERCENTAGE,
192  state_class=SensorStateClass.MEASUREMENT,
193  entity_category=EntityCategory.DIAGNOSTIC,
194  value=lambda data: data.belt_unit_remaining_life,
195  ),
197  key="fuser_remaining_life",
198  translation_key="fuser_remaining_life",
199  native_unit_of_measurement=PERCENTAGE,
200  state_class=SensorStateClass.MEASUREMENT,
201  entity_category=EntityCategory.DIAGNOSTIC,
202  value=lambda data: data.fuser_remaining_life,
203  ),
205  key="laser_remaining_life",
206  translation_key="laser_remaining_life",
207  native_unit_of_measurement=PERCENTAGE,
208  state_class=SensorStateClass.MEASUREMENT,
209  entity_category=EntityCategory.DIAGNOSTIC,
210  value=lambda data: data.laser_remaining_life,
211  ),
213  key="pf_kit_1_remaining_life",
214  translation_key="pf_kit_1_remaining_life",
215  native_unit_of_measurement=PERCENTAGE,
216  state_class=SensorStateClass.MEASUREMENT,
217  entity_category=EntityCategory.DIAGNOSTIC,
218  value=lambda data: data.pf_kit_1_remaining_life,
219  ),
221  key="pf_kit_mp_remaining_life",
222  translation_key="pf_kit_mp_remaining_life",
223  native_unit_of_measurement=PERCENTAGE,
224  state_class=SensorStateClass.MEASUREMENT,
225  entity_category=EntityCategory.DIAGNOSTIC,
226  value=lambda data: data.pf_kit_mp_remaining_life,
227  ),
229  key="black_toner_remaining",
230  translation_key="black_toner_remaining",
231  native_unit_of_measurement=PERCENTAGE,
232  state_class=SensorStateClass.MEASUREMENT,
233  entity_category=EntityCategory.DIAGNOSTIC,
234  value=lambda data: data.black_toner_remaining,
235  ),
237  key="cyan_toner_remaining",
238  translation_key="cyan_toner_remaining",
239  native_unit_of_measurement=PERCENTAGE,
240  state_class=SensorStateClass.MEASUREMENT,
241  entity_category=EntityCategory.DIAGNOSTIC,
242  value=lambda data: data.cyan_toner_remaining,
243  ),
245  key="magenta_toner_remaining",
246  translation_key="magenta_toner_remaining",
247  native_unit_of_measurement=PERCENTAGE,
248  state_class=SensorStateClass.MEASUREMENT,
249  entity_category=EntityCategory.DIAGNOSTIC,
250  value=lambda data: data.magenta_toner_remaining,
251  ),
253  key="yellow_toner_remaining",
254  translation_key="yellow_toner_remaining",
255  native_unit_of_measurement=PERCENTAGE,
256  state_class=SensorStateClass.MEASUREMENT,
257  entity_category=EntityCategory.DIAGNOSTIC,
258  value=lambda data: data.yellow_toner_remaining,
259  ),
261  key="black_ink_remaining",
262  translation_key="black_ink_remaining",
263  native_unit_of_measurement=PERCENTAGE,
264  state_class=SensorStateClass.MEASUREMENT,
265  entity_category=EntityCategory.DIAGNOSTIC,
266  value=lambda data: data.black_ink_remaining,
267  ),
269  key="cyan_ink_remaining",
270  translation_key="cyan_ink_remaining",
271  native_unit_of_measurement=PERCENTAGE,
272  state_class=SensorStateClass.MEASUREMENT,
273  entity_category=EntityCategory.DIAGNOSTIC,
274  value=lambda data: data.cyan_ink_remaining,
275  ),
277  key="magenta_ink_remaining",
278  translation_key="magenta_ink_remaining",
279  native_unit_of_measurement=PERCENTAGE,
280  state_class=SensorStateClass.MEASUREMENT,
281  entity_category=EntityCategory.DIAGNOSTIC,
282  value=lambda data: data.magenta_ink_remaining,
283  ),
285  key="yellow_ink_remaining",
286  translation_key="yellow_ink_remaining",
287  native_unit_of_measurement=PERCENTAGE,
288  state_class=SensorStateClass.MEASUREMENT,
289  entity_category=EntityCategory.DIAGNOSTIC,
290  value=lambda data: data.yellow_ink_remaining,
291  ),
293  key="uptime",
294  translation_key="last_restart",
295  entity_registry_enabled_default=False,
296  device_class=SensorDeviceClass.TIMESTAMP,
297  entity_category=EntityCategory.DIAGNOSTIC,
298  value=lambda data: data.uptime,
299  ),
300 )
301 
302 
304  hass: HomeAssistant,
305  entry: BrotherConfigEntry,
306  async_add_entities: AddEntitiesCallback,
307 ) -> None:
308  """Add Brother entities from a config_entry."""
309  coordinator = entry.runtime_data
310  # Due to the change of the attribute name of one sensor, it is necessary to migrate
311  # the unique_id to the new one.
312  entity_registry = er.async_get(hass)
313  old_unique_id = f"{coordinator.brother.serial.lower()}_b/w_counter"
314  if entity_id := entity_registry.async_get_entity_id(
315  PLATFORM, DOMAIN, old_unique_id
316  ):
317  new_unique_id = f"{coordinator.brother.serial.lower()}_bw_counter"
318  _LOGGER.debug(
319  "Migrating entity %s from old unique ID '%s' to new unique ID '%s'",
320  entity_id,
321  old_unique_id,
322  new_unique_id,
323  )
324  entity_registry.async_update_entity(entity_id, new_unique_id=new_unique_id)
325 
327  BrotherPrinterSensor(coordinator, description)
328  for description in SENSOR_TYPES
329  if description.value(coordinator.data) is not None
330  )
331 
332 
334  CoordinatorEntity[BrotherDataUpdateCoordinator], SensorEntity
335 ):
336  """Define an Brother Printer sensor."""
337 
338  _attr_has_entity_name = True
339  entity_description: BrotherSensorEntityDescription
340 
341  def __init__(
342  self,
343  coordinator: BrotherDataUpdateCoordinator,
344  description: BrotherSensorEntityDescription,
345  ) -> None:
346  """Initialize."""
347  super().__init__(coordinator)
348  self._attr_device_info_attr_device_info = DeviceInfo(
349  configuration_url=f"http://{coordinator.brother.host}/",
350  identifiers={(DOMAIN, coordinator.brother.serial)},
351  connections={(CONNECTION_NETWORK_MAC, coordinator.brother.mac)},
352  serial_number=coordinator.brother.serial,
353  manufacturer="Brother",
354  model=coordinator.brother.model,
355  name=coordinator.brother.model,
356  sw_version=coordinator.brother.firmware,
357  )
358  self._attr_native_value_attr_native_value = description.value(coordinator.data)
359  self._attr_unique_id_attr_unique_id = f"{coordinator.brother.serial.lower()}_{description.key}"
360  self.entity_descriptionentity_description = description
361 
362  @callback
363  def _handle_coordinator_update(self) -> None:
364  """Handle updated data from the coordinator."""
365  self._attr_native_value_attr_native_value = self.entity_descriptionentity_description.value(self.coordinator.data)
366  self.async_write_ha_stateasync_write_ha_state()
None __init__(self, BrotherDataUpdateCoordinator coordinator, BrotherSensorEntityDescription description)
Definition: sensor.py:345
None async_setup_entry(HomeAssistant hass, BrotherConfigEntry entry, AddEntitiesCallback async_add_entities)
Definition: sensor.py:307