From 21937494d191f438f875df3a0bf8b359dbe2a2c1 Mon Sep 17 00:00:00 2001 From: Jonas Petersson Date: Mon, 14 Sep 2026 16:49:38 +0200 Subject: [PATCH] Add glass break device class for binary_sensor (#181332) Co-authored-by: Jonas Petersson <499325+catellie@users.noreply.github.com> Co-authored-by: Codex --- .../components/binary_sensor/__init__.py | 3 +++ .../binary_sensor/device_condition.py | 8 ++++++++ .../components/binary_sensor/device_trigger.py | 6 ++++++ .../components/binary_sensor/icons.json | 3 +++ .../components/binary_sensor/strings.json | 11 +++++++++++ homeassistant/generated/device_classes.json | 1 + tests/components/binary_sensor/test_init.py | 18 ++++++++++++++++++ 7 files changed, 50 insertions(+) diff --git a/homeassistant/components/binary_sensor/__init__.py b/homeassistant/components/binary_sensor/__init__.py index 14767114bb23..50acd4c6fa9b 100644 --- a/homeassistant/components/binary_sensor/__init__.py +++ b/homeassistant/components/binary_sensor/__init__.py @@ -55,6 +55,9 @@ class BinarySensorDeviceClass(StrEnum): # On means gas detected, Off means no gas (clear) GAS = "gas" + # On means glass break detected, Off means no glass break (clear) + GLASS_BREAK = "glass_break" + # On means hot, Off means normal HEAT = "heat" diff --git a/homeassistant/components/binary_sensor/device_condition.py b/homeassistant/components/binary_sensor/device_condition.py index 7e5c1f514043..ea27a1f727a1 100644 --- a/homeassistant/components/binary_sensor/device_condition.py +++ b/homeassistant/components/binary_sensor/device_condition.py @@ -37,6 +37,8 @@ CONF_IS_CONNECTED = "is_connected" CONF_IS_NOT_CONNECTED = "is_not_connected" CONF_IS_GAS = "is_gas" CONF_IS_NO_GAS = "is_no_gas" +CONF_IS_GLASS_BREAK = "is_glass_break" +CONF_IS_NO_GLASS_BREAK = "is_no_glass_break" CONF_IS_HOT = "is_hot" CONF_IS_NOT_HOT = "is_not_hot" CONF_IS_LIGHT = "is_light" @@ -83,6 +85,7 @@ IS_ON = [ CONF_IS_COLD, CONF_IS_CONNECTED, CONF_IS_GAS, + CONF_IS_GLASS_BREAK, CONF_IS_HOT, CONF_IS_LIGHT, CONF_IS_NOT_LOCKED, @@ -123,6 +126,7 @@ IS_OFF = [ CONF_IS_NOT_UNSAFE, CONF_IS_NO_CO, CONF_IS_NO_GAS, + CONF_IS_NO_GLASS_BREAK, CONF_IS_NO_LIGHT, CONF_IS_NO_MOTION, CONF_IS_NO_PROBLEM, @@ -167,6 +171,10 @@ ENTITY_CONDITIONS = { {CONF_TYPE: CONF_IS_GAS}, {CONF_TYPE: CONF_IS_NO_GAS}, ], + BinarySensorDeviceClass.GLASS_BREAK: [ + {CONF_TYPE: CONF_IS_GLASS_BREAK}, + {CONF_TYPE: CONF_IS_NO_GLASS_BREAK}, + ], BinarySensorDeviceClass.HEAT: [ {CONF_TYPE: CONF_IS_HOT}, {CONF_TYPE: CONF_IS_NOT_HOT}, diff --git a/homeassistant/components/binary_sensor/device_trigger.py b/homeassistant/components/binary_sensor/device_trigger.py index f9958ae0a046..dbba3ddbed70 100644 --- a/homeassistant/components/binary_sensor/device_trigger.py +++ b/homeassistant/components/binary_sensor/device_trigger.py @@ -31,6 +31,8 @@ CONF_CONNECTED = "connected" CONF_NOT_CONNECTED = "not_connected" CONF_GAS = "gas" CONF_NO_GAS = "no_gas" +CONF_GLASS_BREAK = "glass_break" +CONF_NO_GLASS_BREAK = "no_glass_break" CONF_HOT = "hot" CONF_NOT_HOT = "not_hot" CONF_LIGHT = "light" @@ -104,6 +106,10 @@ ENTITY_TRIGGERS = { {CONF_TYPE: CONF_GAS}, {CONF_TYPE: CONF_NO_GAS}, ], + BinarySensorDeviceClass.GLASS_BREAK: [ + {CONF_TYPE: CONF_GLASS_BREAK}, + {CONF_TYPE: CONF_NO_GLASS_BREAK}, + ], BinarySensorDeviceClass.HEAT: [ {CONF_TYPE: CONF_HOT}, {CONF_TYPE: CONF_NOT_HOT}, diff --git a/homeassistant/components/binary_sensor/icons.json b/homeassistant/components/binary_sensor/icons.json index 929ca8114e37..94b26e7d4edb 100644 --- a/homeassistant/components/binary_sensor/icons.json +++ b/homeassistant/components/binary_sensor/icons.json @@ -54,6 +54,9 @@ "on": "mdi:alert-circle" } }, + "glass_break": { + "default": "mdi:glass-fragile" + }, "heat": { "default": "mdi:thermometer", "state": { diff --git a/homeassistant/components/binary_sensor/strings.json b/homeassistant/components/binary_sensor/strings.json index 08d16fd03966..cb9e08a69a89 100644 --- a/homeassistant/components/binary_sensor/strings.json +++ b/homeassistant/components/binary_sensor/strings.json @@ -7,6 +7,7 @@ "is_cold": "{entity_name} is cold", "is_connected": "{entity_name} is connected", "is_gas": "{entity_name} is detecting gas", + "is_glass_break": "{entity_name} is detecting glass break", "is_hot": "{entity_name} is hot", "is_light": "{entity_name} is detecting light", "is_locked": "{entity_name} is locked", @@ -15,6 +16,7 @@ "is_moving": "{entity_name} is moving", "is_no_co": "{entity_name} is not detecting carbon monoxide", "is_no_gas": "{entity_name} is not detecting gas", + "is_no_glass_break": "{entity_name} is not detecting glass break", "is_no_light": "{entity_name} is not detecting light", "is_no_motion": "{entity_name} is not detecting motion", "is_no_problem": "{entity_name} is not detecting problem", @@ -64,6 +66,7 @@ "cold": "{entity_name} became cold", "connected": "{entity_name} connected", "gas": "{entity_name} started detecting gas", + "glass_break": "{entity_name} detected glass break", "hot": "{entity_name} became hot", "light": "{entity_name} started detecting light", "locked": "{entity_name} locked", @@ -72,6 +75,7 @@ "moving": "{entity_name} started moving", "no_co": "{entity_name} stopped detecting carbon monoxide", "no_gas": "{entity_name} stopped detecting gas", + "no_glass_break": "{entity_name} stopped detecting glass break", "no_light": "{entity_name} stopped detecting light", "no_motion": "{entity_name} stopped detecting motion", "no_problem": "{entity_name} stopped detecting problem", @@ -176,6 +180,13 @@ "on": "Detected" } }, + "glass_break": { + "name": "Glass break", + "state": { + "off": "Clear", + "on": "Glass break detected" + } + }, "heat": { "name": "Heat", "state": { diff --git a/homeassistant/generated/device_classes.json b/homeassistant/generated/device_classes.json index ecae4ad378f5..c2c19177da35 100644 --- a/homeassistant/generated/device_classes.json +++ b/homeassistant/generated/device_classes.json @@ -8,6 +8,7 @@ "door", "garage_door", "gas", + "glass_break", "heat", "light", "lock", diff --git a/tests/components/binary_sensor/test_init.py b/tests/components/binary_sensor/test_init.py index b0a26faf927e..c5721f4b7f2d 100644 --- a/tests/components/binary_sensor/test_init.py +++ b/tests/components/binary_sensor/test_init.py @@ -6,6 +6,9 @@ from unittest import mock import pytest from homeassistant.components import binary_sensor +from homeassistant.components.binary_sensor import BinarySensorDeviceClass +from homeassistant.components.binary_sensor.device_condition import ENTITY_CONDITIONS +from homeassistant.components.binary_sensor.device_trigger import ENTITY_TRIGGERS from homeassistant.config_entries import ConfigEntry, ConfigFlow from homeassistant.const import STATE_OFF, STATE_ON, EntityCategory, Platform from homeassistant.core import HomeAssistant @@ -196,3 +199,18 @@ async def test_entity_category_config_raises_error( "Entity binary_sensor.test2 cannot be added as the" " entity category is set to config" in caplog.text ) + + +def test_glass_break_device_class() -> None: + """Test glass break device class enum value and automation mappings.""" + assert BinarySensorDeviceClass.GLASS_BREAK == "glass_break" + assert BinarySensorDeviceClass.GLASS_BREAK in ENTITY_CONDITIONS + assert BinarySensorDeviceClass.GLASS_BREAK in ENTITY_TRIGGERS + conditions = ENTITY_CONDITIONS[BinarySensorDeviceClass.GLASS_BREAK] + assert len(conditions) == 2 + condition_types = {c["type"] for c in conditions} + assert condition_types == {"is_glass_break", "is_no_glass_break"} + triggers = ENTITY_TRIGGERS[BinarySensorDeviceClass.GLASS_BREAK] + assert len(triggers) == 2 + trigger_types = {t["type"] for t in triggers} + assert trigger_types == {"glass_break", "no_glass_break"}