From f45151cfd0d21429479b31854ef246e6276ff30d Mon Sep 17 00:00:00 2001 From: Maciej Bieniek Date: Sat, 26 Sep 2026 15:00:35 +0200 Subject: [PATCH] Add a binary sensor platform to the Brother integration (#183084) --- homeassistant/components/brother/__init__.py | 2 +- .../components/brother/binary_sensor.py | 163 ++ homeassistant/components/brother/entity.py | 5 + homeassistant/components/brother/sensor.py | 13 +- homeassistant/components/brother/strings.json | 47 + tests/components/brother/conftest.py | 27 +- .../brother/snapshots/test_binary_sensor.ambr | 1327 +++++++++++++++++ .../brother/snapshots/test_diagnostics.ambr | 5 +- .../components/brother/test_binary_sensor.py | 149 ++ 9 files changed, 1723 insertions(+), 15 deletions(-) create mode 100644 homeassistant/components/brother/binary_sensor.py create mode 100644 tests/components/brother/snapshots/test_binary_sensor.ambr create mode 100644 tests/components/brother/test_binary_sensor.py diff --git a/homeassistant/components/brother/__init__.py b/homeassistant/components/brother/__init__.py index e4ea48efee04..24037c4b1c4f 100644 --- a/homeassistant/components/brother/__init__.py +++ b/homeassistant/components/brother/__init__.py @@ -20,7 +20,7 @@ from .coordinator import BrotherConfigEntry, BrotherDataUpdateCoordinator _LOGGER = logging.getLogger(__name__) -PLATFORMS = [Platform.SENSOR] +PLATFORMS = [Platform.BINARY_SENSOR, Platform.SENSOR] async def async_setup_entry(hass: HomeAssistant, entry: BrotherConfigEntry) -> bool: diff --git a/homeassistant/components/brother/binary_sensor.py b/homeassistant/components/brother/binary_sensor.py new file mode 100644 index 000000000000..b21d0aac34e4 --- /dev/null +++ b/homeassistant/components/brother/binary_sensor.py @@ -0,0 +1,163 @@ +"""Support for the Brother binary sensors.""" + +from typing import TYPE_CHECKING, override + +from homeassistant.components.binary_sensor import ( + BinarySensorDeviceClass, + BinarySensorEntity, + BinarySensorEntityDescription, +) +from homeassistant.const import CONF_TYPE, EntityCategory +from homeassistant.core import HomeAssistant +from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback + +from .const import PRINTER_TYPE_INK, PRINTER_TYPE_LASER +from .coordinator import BrotherConfigEntry +from .entity import BrotherPrinterEntity + +# Coordinator is used to centralize the data updates +PARALLEL_UPDATES = 0 + +BINARY_SENSOR_TYPES: tuple[BinarySensorEntityDescription, ...] = ( + BinarySensorEntityDescription( + key="door_open", + translation_key="door_open", + device_class=BinarySensorDeviceClass.PROBLEM, + entity_category=EntityCategory.DIAGNOSTIC, + ), + BinarySensorEntityDescription( + key="input_tray_empty", + translation_key="input_tray_empty", + device_class=BinarySensorDeviceClass.PROBLEM, + entity_category=EntityCategory.DIAGNOSTIC, + entity_registry_enabled_default=False, + ), + BinarySensorEntityDescription( + key="input_tray_missing", + translation_key="input_tray_missing", + device_class=BinarySensorDeviceClass.PROBLEM, + entity_category=EntityCategory.DIAGNOSTIC, + entity_registry_enabled_default=False, + ), + BinarySensorEntityDescription( + key="jammed", + translation_key="jammed", + device_class=BinarySensorDeviceClass.PROBLEM, + entity_category=EntityCategory.DIAGNOSTIC, + ), + BinarySensorEntityDescription( + key="low_paper", + translation_key="low_paper", + device_class=BinarySensorDeviceClass.PROBLEM, + entity_category=EntityCategory.DIAGNOSTIC, + entity_registry_enabled_default=False, + ), + BinarySensorEntityDescription( + key="no_paper", + translation_key="no_paper", + device_class=BinarySensorDeviceClass.PROBLEM, + entity_category=EntityCategory.DIAGNOSTIC, + ), + BinarySensorEntityDescription( + key="output_full", + translation_key="output_full", + device_class=BinarySensorDeviceClass.PROBLEM, + entity_category=EntityCategory.DIAGNOSTIC, + entity_registry_enabled_default=False, + ), + BinarySensorEntityDescription( + key="output_near_full", + translation_key="output_near_full", + device_class=BinarySensorDeviceClass.PROBLEM, + entity_category=EntityCategory.DIAGNOSTIC, + entity_registry_enabled_default=False, + ), + BinarySensorEntityDescription( + key="output_tray_missing", + translation_key="output_tray_missing", + device_class=BinarySensorDeviceClass.PROBLEM, + entity_category=EntityCategory.DIAGNOSTIC, + entity_registry_enabled_default=False, + ), + BinarySensorEntityDescription( + key="overdue_prevent_maint", + translation_key="overdue_prevent_maint", + device_class=BinarySensorDeviceClass.PROBLEM, + entity_category=EntityCategory.DIAGNOSTIC, + entity_registry_enabled_default=False, + ), + BinarySensorEntityDescription( + key="service_requested", + translation_key="service_requested", + device_class=BinarySensorDeviceClass.PROBLEM, + entity_category=EntityCategory.DIAGNOSTIC, + entity_registry_enabled_default=False, + ), +) + +SUPPLY_BINARY_SENSOR_TYPES: dict[str, tuple[BinarySensorEntityDescription, ...]] = { + PRINTER_TYPE_LASER: ( + BinarySensorEntityDescription( + key="low_toner", + translation_key="low_toner", + device_class=BinarySensorDeviceClass.PROBLEM, + entity_category=EntityCategory.DIAGNOSTIC, + ), + BinarySensorEntityDescription( + key="no_toner", + translation_key="no_toner", + device_class=BinarySensorDeviceClass.PROBLEM, + entity_category=EntityCategory.DIAGNOSTIC, + ), + ), + PRINTER_TYPE_INK: ( + BinarySensorEntityDescription( + key="low_toner", + translation_key="low_ink", + device_class=BinarySensorDeviceClass.PROBLEM, + entity_category=EntityCategory.DIAGNOSTIC, + ), + BinarySensorEntityDescription( + key="no_toner", + translation_key="no_ink", + device_class=BinarySensorDeviceClass.PROBLEM, + entity_category=EntityCategory.DIAGNOSTIC, + ), + ), +} + + +async def async_setup_entry( + hass: HomeAssistant, + entry: BrotherConfigEntry, + async_add_entities: AddConfigEntryEntitiesCallback, +) -> None: + """Add Brother entities from a config_entry.""" + coordinator = entry.runtime_data + + # printer_errors is None only if the printer does not support the OID that returns + # errors, in that case, we do not create binary sensors + if coordinator.data.printer_errors is None: + return + + descriptions = ( + BINARY_SENSOR_TYPES + SUPPLY_BINARY_SENSOR_TYPES[entry.data[CONF_TYPE]] + ) + + async_add_entities( + BrotherPrinterBinarySensor(coordinator, description) + for description in descriptions + ) + + +class BrotherPrinterBinarySensor(BrotherPrinterEntity, BinarySensorEntity): + """Define a Brother Printer binary sensor.""" + + @property + @override + def is_on(self) -> bool: + """Return true if the printer reports this error.""" + if TYPE_CHECKING: + assert self.coordinator.data.printer_errors is not None + + return self.entity_description.key in self.coordinator.data.printer_errors diff --git a/homeassistant/components/brother/entity.py b/homeassistant/components/brother/entity.py index 0b8ddc988a1d..3b36ad8fcec0 100644 --- a/homeassistant/components/brother/entity.py +++ b/homeassistant/components/brother/entity.py @@ -1,6 +1,7 @@ """Define the Brother entity.""" from homeassistant.helpers.device_registry import CONNECTION_NETWORK_MAC, DeviceInfo +from homeassistant.helpers.entity import EntityDescription from homeassistant.helpers.update_coordinator import CoordinatorEntity from .const import DOMAIN @@ -15,9 +16,13 @@ class BrotherPrinterEntity(CoordinatorEntity[BrotherDataUpdateCoordinator]): def __init__( self, coordinator: BrotherDataUpdateCoordinator, + description: EntityDescription, ) -> None: """Initialize.""" super().__init__(coordinator) + + self._attr_unique_id = f"{coordinator.brother.serial.lower()}_{description.key}" + self.entity_description = description self._attr_device_info = DeviceInfo( configuration_url=f"http://{coordinator.brother.host}/", identifiers={(DOMAIN, coordinator.brother.serial)}, diff --git a/homeassistant/components/brother/sensor.py b/homeassistant/components/brother/sensor.py index dd8c2d2dd75f..94d0c75c8628 100644 --- a/homeassistant/components/brother/sensor.py +++ b/homeassistant/components/brother/sensor.py @@ -22,7 +22,7 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback from homeassistant.helpers.typing import StateType from .const import DOMAIN -from .coordinator import BrotherConfigEntry, BrotherDataUpdateCoordinator +from .coordinator import BrotherConfigEntry from .entity import BrotherPrinterEntity # Coordinator is used to centralize the data updates @@ -354,17 +354,6 @@ class BrotherPrinterSensor(BrotherPrinterEntity, SensorEntity): entity_description: BrotherSensorEntityDescription - def __init__( - self, - coordinator: BrotherDataUpdateCoordinator, - description: BrotherSensorEntityDescription, - ) -> None: - """Initialize.""" - super().__init__(coordinator) - - self._attr_unique_id = f"{coordinator.brother.serial.lower()}_{description.key}" - self.entity_description = description - @property @override def native_value(self) -> StateType | datetime: diff --git a/homeassistant/components/brother/strings.json b/homeassistant/components/brother/strings.json index 9fad21a72309..f048a96968f6 100644 --- a/homeassistant/components/brother/strings.json +++ b/homeassistant/components/brother/strings.json @@ -83,6 +83,53 @@ } }, "entity": { + "binary_sensor": { + "door_open": { + "name": "Door open" + }, + "input_tray_empty": { + "name": "Input tray empty" + }, + "input_tray_missing": { + "name": "Input tray missing" + }, + "jammed": { + "name": "Paper jam" + }, + "low_ink": { + "name": "Low ink" + }, + "low_paper": { + "name": "Low paper" + }, + "low_toner": { + "name": "Low toner" + }, + "no_ink": { + "name": "No ink" + }, + "no_paper": { + "name": "No paper" + }, + "no_toner": { + "name": "No toner" + }, + "output_full": { + "name": "Output tray full" + }, + "output_near_full": { + "name": "Output tray near full" + }, + "output_tray_missing": { + "name": "Output tray missing" + }, + "overdue_prevent_maint": { + "name": "Preventive maintenance overdue" + }, + "service_requested": { + "name": "Service requested" + } + }, "sensor": { "belt_unit_remaining_life": { "name": "Belt unit remaining lifetime" diff --git a/tests/components/brother/conftest.py b/tests/components/brother/conftest.py index 34032462de7e..8ea8ba553570 100644 --- a/tests/components/brother/conftest.py +++ b/tests/components/brother/conftest.py @@ -68,8 +68,8 @@ BROTHER_DATA = BrotherSensors( pf_kit_1_remaining_pages=48741, pf_kit_mp_remaining_life=None, pf_kit_mp_remaining_pages=None, - printer_errors=None, printer_status="idle", + printer_errors=["door_open", "low_toner"], status="waiting", uptime=datetime(2024, 3, 3, 15, 4, 24, tzinfo=UTC), yellow_counter=None, @@ -117,6 +117,15 @@ def mock_brother_client(mock_brother: AsyncMock) -> AsyncMock: return client +@pytest.fixture +def mock_ink_brother_client(mock_brother_client: AsyncMock) -> AsyncMock: + """Mock Brother client for an inkjet printer.""" + mock_brother_client.serial = "9876543210" + mock_brother_client.model = "DCP-J562DW" + + return mock_brother_client + + @pytest.fixture def mock_config_entry() -> MockConfigEntry: """Mock a config entry.""" @@ -131,3 +140,19 @@ def mock_config_entry() -> MockConfigEntry: }, minor_version=2, ) + + +@pytest.fixture +def mock_ink_config_entry() -> MockConfigEntry: + """Mock a config entry for an inkjet printer.""" + return MockConfigEntry( + domain=DOMAIN, + title="DCP-J562DW 9876543210", + unique_id="9876543210", + data={ + CONF_HOST: "localhost", + CONF_TYPE: "ink", + SECTION_ADVANCED_SETTINGS: {CONF_PORT: 161, CONF_COMMUNITY: "public"}, + }, + minor_version=2, + ) diff --git a/tests/components/brother/snapshots/test_binary_sensor.ambr b/tests/components/brother/snapshots/test_binary_sensor.ambr new file mode 100644 index 000000000000..582458684b93 --- /dev/null +++ b/tests/components/brother/snapshots/test_binary_sensor.ambr @@ -0,0 +1,1327 @@ +# serializer version: 1 +# name: test_binary_sensors[binary_sensor.hl_l2340dw_door_open-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.hl_l2340dw_door_open', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Door open', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Door open', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'door_open', + 'unique_id': '0123456789_door_open', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_door_open-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'HL-L2340DW Door open', + }), + 'context': , + 'entity_id': 'binary_sensor.hl_l2340dw_door_open', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_input_tray_empty-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.hl_l2340dw_input_tray_empty', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Input tray empty', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Input tray empty', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'input_tray_empty', + 'unique_id': '0123456789_input_tray_empty', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_input_tray_empty-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'HL-L2340DW Input tray empty', + }), + 'context': , + 'entity_id': 'binary_sensor.hl_l2340dw_input_tray_empty', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_input_tray_missing-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.hl_l2340dw_input_tray_missing', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Input tray missing', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Input tray missing', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'input_tray_missing', + 'unique_id': '0123456789_input_tray_missing', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_input_tray_missing-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'HL-L2340DW Input tray missing', + }), + 'context': , + 'entity_id': 'binary_sensor.hl_l2340dw_input_tray_missing', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_low_paper-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.hl_l2340dw_low_paper', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Low paper', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Low paper', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'low_paper', + 'unique_id': '0123456789_low_paper', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_low_paper-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'HL-L2340DW Low paper', + }), + 'context': , + 'entity_id': 'binary_sensor.hl_l2340dw_low_paper', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_low_toner-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.hl_l2340dw_low_toner', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Low toner', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Low toner', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'low_toner', + 'unique_id': '0123456789_low_toner', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_low_toner-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'HL-L2340DW Low toner', + }), + 'context': , + 'entity_id': 'binary_sensor.hl_l2340dw_low_toner', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_no_paper-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.hl_l2340dw_no_paper', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'No paper', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'No paper', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'no_paper', + 'unique_id': '0123456789_no_paper', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_no_paper-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'HL-L2340DW No paper', + }), + 'context': , + 'entity_id': 'binary_sensor.hl_l2340dw_no_paper', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_no_toner-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.hl_l2340dw_no_toner', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'No toner', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'No toner', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'no_toner', + 'unique_id': '0123456789_no_toner', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_no_toner-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'HL-L2340DW No toner', + }), + 'context': , + 'entity_id': 'binary_sensor.hl_l2340dw_no_toner', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_output_tray_full-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.hl_l2340dw_output_tray_full', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Output tray full', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Output tray full', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'output_full', + 'unique_id': '0123456789_output_full', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_output_tray_full-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'HL-L2340DW Output tray full', + }), + 'context': , + 'entity_id': 'binary_sensor.hl_l2340dw_output_tray_full', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_output_tray_missing-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.hl_l2340dw_output_tray_missing', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Output tray missing', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Output tray missing', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'output_tray_missing', + 'unique_id': '0123456789_output_tray_missing', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_output_tray_missing-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'HL-L2340DW Output tray missing', + }), + 'context': , + 'entity_id': 'binary_sensor.hl_l2340dw_output_tray_missing', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_output_tray_near_full-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.hl_l2340dw_output_tray_near_full', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Output tray near full', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Output tray near full', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'output_near_full', + 'unique_id': '0123456789_output_near_full', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_output_tray_near_full-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'HL-L2340DW Output tray near full', + }), + 'context': , + 'entity_id': 'binary_sensor.hl_l2340dw_output_tray_near_full', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_paper_jam-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.hl_l2340dw_paper_jam', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Paper jam', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Paper jam', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'jammed', + 'unique_id': '0123456789_jammed', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_paper_jam-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'HL-L2340DW Paper jam', + }), + 'context': , + 'entity_id': 'binary_sensor.hl_l2340dw_paper_jam', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_preventive_maintenance_overdue-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.hl_l2340dw_preventive_maintenance_overdue', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Preventive maintenance overdue', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Preventive maintenance overdue', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'overdue_prevent_maint', + 'unique_id': '0123456789_overdue_prevent_maint', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_preventive_maintenance_overdue-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'HL-L2340DW Preventive maintenance overdue', + }), + 'context': , + 'entity_id': 'binary_sensor.hl_l2340dw_preventive_maintenance_overdue', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_service_requested-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.hl_l2340dw_service_requested', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Service requested', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Service requested', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'service_requested', + 'unique_id': '0123456789_service_requested', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors[binary_sensor.hl_l2340dw_service_requested-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'HL-L2340DW Service requested', + }), + 'context': , + 'entity_id': 'binary_sensor.hl_l2340dw_service_requested', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_door_open-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.dcp_j562dw_door_open', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Door open', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Door open', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'door_open', + 'unique_id': '9876543210_door_open', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_door_open-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'DCP-J562DW Door open', + }), + 'context': , + 'entity_id': 'binary_sensor.dcp_j562dw_door_open', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_input_tray_empty-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.dcp_j562dw_input_tray_empty', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Input tray empty', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Input tray empty', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'input_tray_empty', + 'unique_id': '9876543210_input_tray_empty', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_input_tray_empty-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'DCP-J562DW Input tray empty', + }), + 'context': , + 'entity_id': 'binary_sensor.dcp_j562dw_input_tray_empty', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_input_tray_missing-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.dcp_j562dw_input_tray_missing', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Input tray missing', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Input tray missing', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'input_tray_missing', + 'unique_id': '9876543210_input_tray_missing', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_input_tray_missing-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'DCP-J562DW Input tray missing', + }), + 'context': , + 'entity_id': 'binary_sensor.dcp_j562dw_input_tray_missing', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_low_ink-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.dcp_j562dw_low_ink', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Low ink', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Low ink', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'low_ink', + 'unique_id': '9876543210_low_toner', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_low_ink-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'DCP-J562DW Low ink', + }), + 'context': , + 'entity_id': 'binary_sensor.dcp_j562dw_low_ink', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'on', + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_low_paper-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.dcp_j562dw_low_paper', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Low paper', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Low paper', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'low_paper', + 'unique_id': '9876543210_low_paper', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_low_paper-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'DCP-J562DW Low paper', + }), + 'context': , + 'entity_id': 'binary_sensor.dcp_j562dw_low_paper', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_no_ink-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.dcp_j562dw_no_ink', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'No ink', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'No ink', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'no_ink', + 'unique_id': '9876543210_no_toner', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_no_ink-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'DCP-J562DW No ink', + }), + 'context': , + 'entity_id': 'binary_sensor.dcp_j562dw_no_ink', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_no_paper-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.dcp_j562dw_no_paper', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'No paper', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'No paper', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'no_paper', + 'unique_id': '9876543210_no_paper', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_no_paper-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'DCP-J562DW No paper', + }), + 'context': , + 'entity_id': 'binary_sensor.dcp_j562dw_no_paper', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_output_tray_full-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.dcp_j562dw_output_tray_full', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Output tray full', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Output tray full', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'output_full', + 'unique_id': '9876543210_output_full', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_output_tray_full-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'DCP-J562DW Output tray full', + }), + 'context': , + 'entity_id': 'binary_sensor.dcp_j562dw_output_tray_full', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_output_tray_missing-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.dcp_j562dw_output_tray_missing', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Output tray missing', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Output tray missing', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'output_tray_missing', + 'unique_id': '9876543210_output_tray_missing', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_output_tray_missing-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'DCP-J562DW Output tray missing', + }), + 'context': , + 'entity_id': 'binary_sensor.dcp_j562dw_output_tray_missing', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_output_tray_near_full-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.dcp_j562dw_output_tray_near_full', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Output tray near full', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Output tray near full', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'output_near_full', + 'unique_id': '9876543210_output_near_full', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_output_tray_near_full-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'DCP-J562DW Output tray near full', + }), + 'context': , + 'entity_id': 'binary_sensor.dcp_j562dw_output_tray_near_full', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_paper_jam-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.dcp_j562dw_paper_jam', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Paper jam', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Paper jam', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'jammed', + 'unique_id': '9876543210_jammed', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_paper_jam-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'DCP-J562DW Paper jam', + }), + 'context': , + 'entity_id': 'binary_sensor.dcp_j562dw_paper_jam', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_preventive_maintenance_overdue-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.dcp_j562dw_preventive_maintenance_overdue', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Preventive maintenance overdue', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Preventive maintenance overdue', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'overdue_prevent_maint', + 'unique_id': '9876543210_overdue_prevent_maint', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_preventive_maintenance_overdue-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'DCP-J562DW Preventive maintenance overdue', + }), + 'context': , + 'entity_id': 'binary_sensor.dcp_j562dw_preventive_maintenance_overdue', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_service_requested-entry] + EntityRegistryEntrySnapshot({ + 'aliases': list([ + None, + ]), + 'area_id': None, + 'capabilities': None, + 'config_entry_id': , + 'config_subentry_id': , + 'device_class': None, + 'device_id': , + 'disabled_by': None, + 'domain': 'binary_sensor', + 'entity_category': , + 'entity_id': 'binary_sensor.dcp_j562dw_service_requested', + 'has_entity_name': True, + 'hidden_by': None, + 'icon': None, + 'id': , + 'labels': set({ + }), + 'name': None, + 'object_id_base': 'Service requested', + 'options': dict({ + }), + 'original_device_class': , + 'original_icon': None, + 'original_name': 'Service requested', + 'platform': 'brother', + 'previous_unique_id': None, + 'suggested_object_id': None, + 'supported_features': 0, + 'translation_key': 'service_requested', + 'unique_id': '9876543210_service_requested', + 'unit_of_measurement': None, + }) +# --- +# name: test_binary_sensors_ink[binary_sensor.dcp_j562dw_service_requested-state] + StateSnapshot({ + 'attributes': ReadOnlyDict({ + : 'problem', + : 'DCP-J562DW Service requested', + }), + 'context': , + 'entity_id': 'binary_sensor.dcp_j562dw_service_requested', + 'last_changed': , + 'last_reported': , + 'last_updated': , + 'state': 'off', + }) +# --- diff --git a/tests/components/brother/snapshots/test_diagnostics.ambr b/tests/components/brother/snapshots/test_diagnostics.ambr index 78c3a35dbefb..4f06ce1b4658 100644 --- a/tests/components/brother/snapshots/test_diagnostics.ambr +++ b/tests/components/brother/snapshots/test_diagnostics.ambr @@ -53,7 +53,10 @@ 'pf_kit_1_remaining_pages': 48741, 'pf_kit_mp_remaining_life': None, 'pf_kit_mp_remaining_pages': None, - 'printer_errors': None, + 'printer_errors': list([ + 'door_open', + 'low_toner', + ]), 'printer_status': 'idle', 'status': 'waiting', 'uptime': '2024-03-03T15:04:24+00:00', diff --git a/tests/components/brother/test_binary_sensor.py b/tests/components/brother/test_binary_sensor.py new file mode 100644 index 000000000000..27f28787a550 --- /dev/null +++ b/tests/components/brother/test_binary_sensor.py @@ -0,0 +1,149 @@ +"""Test binary sensor of Brother integration.""" + +from dataclasses import replace +from unittest.mock import AsyncMock, patch + +from freezegun.api import FrozenDateTimeFactory +import pytest +from syrupy.assertion import SnapshotAssertion + +from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN +from homeassistant.components.brother.const import UPDATE_INTERVAL +from homeassistant.const import STATE_OFF, STATE_ON, STATE_UNAVAILABLE, Platform +from homeassistant.core import HomeAssistant +from homeassistant.helpers import entity_registry as er + +from . import init_integration +from .conftest import BROTHER_DATA + +from tests.common import MockConfigEntry, async_fire_time_changed, snapshot_platform + + +@pytest.mark.usefixtures("entity_registry_enabled_by_default") +async def test_binary_sensors( + hass: HomeAssistant, + entity_registry: er.EntityRegistry, + snapshot: SnapshotAssertion, + mock_brother_client: AsyncMock, + mock_config_entry: MockConfigEntry, +) -> None: + """Test states of the binary sensors.""" + with patch("homeassistant.components.brother.PLATFORMS", [Platform.BINARY_SENSOR]): + await init_integration(hass, mock_config_entry) + + await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id) + + +@pytest.mark.usefixtures("entity_registry_enabled_by_default") +async def test_binary_sensors_ink( + hass: HomeAssistant, + entity_registry: er.EntityRegistry, + snapshot: SnapshotAssertion, + mock_ink_brother_client: AsyncMock, + mock_ink_config_entry: MockConfigEntry, +) -> None: + """Test states of the binary sensors for an inkjet printer.""" + with patch("homeassistant.components.brother.PLATFORMS", [Platform.BINARY_SENSOR]): + await init_integration(hass, mock_ink_config_entry) + + await snapshot_platform( + hass, entity_registry, snapshot, mock_ink_config_entry.entry_id + ) + + +@pytest.mark.parametrize( + "entity_id", + [ + "binary_sensor.hl_l2340dw_input_tray_empty", + "binary_sensor.hl_l2340dw_input_tray_missing", + "binary_sensor.hl_l2340dw_low_paper", + "binary_sensor.hl_l2340dw_output_tray_full", + "binary_sensor.hl_l2340dw_output_tray_missing", + "binary_sensor.hl_l2340dw_output_tray_near_full", + "binary_sensor.hl_l2340dw_preventive_maintenance_overdue", + "binary_sensor.hl_l2340dw_service_requested", + ], +) +async def test_binary_sensors_disabled_by_default( + hass: HomeAssistant, + entity_registry: er.EntityRegistry, + mock_brother_client: AsyncMock, + mock_config_entry: MockConfigEntry, + entity_id: str, +) -> None: + """Test the less critical errors are disabled by default.""" + await init_integration(hass, mock_config_entry) + + assert (entry := entity_registry.async_get(entity_id)) + assert entry.disabled_by is er.RegistryEntryDisabler.INTEGRATION + + assert hass.states.get(entity_id) is None + + +async def test_no_binary_sensors_when_printer_errors_unavailable( + hass: HomeAssistant, + mock_brother_client: AsyncMock, + mock_config_entry: MockConfigEntry, +) -> None: + """Test no binary sensors are created when the printer does not report errors.""" + mock_brother_client.async_update.return_value = replace( + BROTHER_DATA, printer_errors=None + ) + + await init_integration(hass, mock_config_entry) + + assert hass.states.async_entity_ids(BINARY_SENSOR_DOMAIN) == [] + + +@pytest.mark.usefixtures("entity_registry_enabled_by_default") +@pytest.mark.parametrize( + ("entity_id", "expected_state"), + [ + ("binary_sensor.hl_l2340dw_door_open", STATE_ON), + ("binary_sensor.hl_l2340dw_low_toner", STATE_ON), + ("binary_sensor.hl_l2340dw_low_paper", STATE_OFF), + ("binary_sensor.hl_l2340dw_no_toner", STATE_OFF), + ], +) +async def test_binary_sensor_state_reflects_printer_errors( + hass: HomeAssistant, + mock_brother_client: AsyncMock, + mock_config_entry: MockConfigEntry, + entity_id: str, + expected_state: str, +) -> None: + """Test the binary sensor state matches the active printer errors.""" + await init_integration(hass, mock_config_entry) + + assert (state := hass.states.get(entity_id)) + assert state.state == expected_state + + +async def test_availability( + hass: HomeAssistant, + freezer: FrozenDateTimeFactory, + mock_brother_client: AsyncMock, + mock_config_entry: MockConfigEntry, +) -> None: + """Ensure that we mark the entities unavailable correctly when device is offline.""" + entity_id = "binary_sensor.hl_l2340dw_door_open" + await init_integration(hass, mock_config_entry) + + assert (state := hass.states.get(entity_id)) + assert state.state == STATE_ON + + mock_brother_client.async_update.side_effect = ConnectionError + freezer.tick(UPDATE_INTERVAL) + async_fire_time_changed(hass) + await hass.async_block_till_done() + + assert (state := hass.states.get(entity_id)) + assert state.state == STATE_UNAVAILABLE + + mock_brother_client.async_update.side_effect = None + freezer.tick(UPDATE_INTERVAL) + async_fire_time_changed(hass) + await hass.async_block_till_done() + + assert (state := hass.states.get(entity_id)) + assert state.state == STATE_ON