diff --git a/esphome/components/binary_sensor/__init__.py b/esphome/components/binary_sensor/__init__.py index 600c9efe5..91f63de9e 100644 --- a/esphome/components/binary_sensor/__init__.py +++ b/esphome/components/binary_sensor/__init__.py @@ -27,13 +27,13 @@ from esphome.const import ( CONF_TIMING, CONF_TRIGGER_ID, CONF_MQTT_ID, - DEVICE_CLASS_EMPTY, DEVICE_CLASS_BATTERY, DEVICE_CLASS_BATTERY_CHARGING, DEVICE_CLASS_CARBON_MONOXIDE, DEVICE_CLASS_COLD, DEVICE_CLASS_CONNECTIVITY, DEVICE_CLASS_DOOR, + DEVICE_CLASS_EMPTY, DEVICE_CLASS_GARAGE_DOOR, DEVICE_CLASS_GAS, DEVICE_CLASS_HEAT, @@ -62,13 +62,13 @@ from esphome.util import Registry CODEOWNERS = ["@esphome/core"] DEVICE_CLASSES = [ - DEVICE_CLASS_EMPTY, DEVICE_CLASS_BATTERY, DEVICE_CLASS_BATTERY_CHARGING, DEVICE_CLASS_CARBON_MONOXIDE, DEVICE_CLASS_COLD, DEVICE_CLASS_CONNECTIVITY, DEVICE_CLASS_DOOR, + DEVICE_CLASS_EMPTY, DEVICE_CLASS_GARAGE_DOOR, DEVICE_CLASS_GAS, DEVICE_CLASS_HEAT, diff --git a/esphome/components/button/__init__.py b/esphome/components/button/__init__.py index b0611a62e..7329a7955 100644 --- a/esphome/components/button/__init__.py +++ b/esphome/components/button/__init__.py @@ -11,6 +11,7 @@ from esphome.const import ( CONF_ON_PRESS, CONF_TRIGGER_ID, CONF_MQTT_ID, + DEVICE_CLASS_EMPTY, DEVICE_CLASS_RESTART, DEVICE_CLASS_UPDATE, ) @@ -21,6 +22,7 @@ CODEOWNERS = ["@esphome/core"] IS_PLATFORM_COMPONENT = True DEVICE_CLASSES = [ + DEVICE_CLASS_EMPTY, DEVICE_CLASS_RESTART, DEVICE_CLASS_UPDATE, ] diff --git a/esphome/components/cover/__init__.py b/esphome/components/cover/__init__.py index d2421f07d..90e5ee1f0 100644 --- a/esphome/components/cover/__init__.py +++ b/esphome/components/cover/__init__.py @@ -17,6 +17,17 @@ from esphome.const import ( CONF_STOP, CONF_MQTT_ID, CONF_TRIGGER_ID, + DEVICE_CLASS_AWNING, + DEVICE_CLASS_BLIND, + DEVICE_CLASS_CURTAIN, + DEVICE_CLASS_DAMPER, + DEVICE_CLASS_DOOR, + DEVICE_CLASS_EMPTY, + DEVICE_CLASS_GARAGE, + DEVICE_CLASS_GATE, + DEVICE_CLASS_SHADE, + DEVICE_CLASS_SHUTTER, + DEVICE_CLASS_WINDOW, ) from esphome.core import CORE, coroutine_with_priority from esphome.cpp_helpers import setup_entity @@ -25,17 +36,17 @@ IS_PLATFORM_COMPONENT = True CODEOWNERS = ["@esphome/core"] DEVICE_CLASSES = [ - "", - "awning", - "blind", - "curtain", - "damper", - "door", - "garage", - "gate", - "shade", - "shutter", - "window", + DEVICE_CLASS_AWNING, + DEVICE_CLASS_BLIND, + DEVICE_CLASS_CURTAIN, + DEVICE_CLASS_DAMPER, + DEVICE_CLASS_DOOR, + DEVICE_CLASS_EMPTY, + DEVICE_CLASS_GARAGE, + DEVICE_CLASS_GATE, + DEVICE_CLASS_SHADE, + DEVICE_CLASS_SHUTTER, + DEVICE_CLASS_WINDOW, ] cover_ns = cg.esphome_ns.namespace("cover") diff --git a/esphome/components/number/__init__.py b/esphome/components/number/__init__.py index 463557e3b..1d2dac9bd 100644 --- a/esphome/components/number/__init__.py +++ b/esphome/components/number/__init__.py @@ -17,19 +17,23 @@ from esphome.const import ( CONF_VALUE, CONF_OPERATION, CONF_CYCLE, - DEVICE_CLASS_DISTANCE, - DEVICE_CLASS_EMPTY, DEVICE_CLASS_APPARENT_POWER, DEVICE_CLASS_AQI, + DEVICE_CLASS_ATMOSPHERIC_PRESSURE, DEVICE_CLASS_BATTERY, DEVICE_CLASS_CARBON_DIOXIDE, DEVICE_CLASS_CARBON_MONOXIDE, DEVICE_CLASS_CURRENT, + DEVICE_CLASS_DATA_RATE, + DEVICE_CLASS_DATA_SIZE, + DEVICE_CLASS_DISTANCE, + DEVICE_CLASS_EMPTY, DEVICE_CLASS_ENERGY, DEVICE_CLASS_FREQUENCY, DEVICE_CLASS_GAS, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_ILLUMINANCE, + DEVICE_CLASS_IRRADIANCE, DEVICE_CLASS_MOISTURE, DEVICE_CLASS_MONETARY, DEVICE_CLASS_NITROGEN_DIOXIDE, @@ -46,6 +50,7 @@ from esphome.const import ( DEVICE_CLASS_PRESSURE, DEVICE_CLASS_REACTIVE_POWER, DEVICE_CLASS_SIGNAL_STRENGTH, + DEVICE_CLASS_SOUND_PRESSURE, DEVICE_CLASS_SPEED, DEVICE_CLASS_SULPHUR_DIOXIDE, DEVICE_CLASS_TEMPERATURE, @@ -53,8 +58,8 @@ from esphome.const import ( DEVICE_CLASS_VOLTAGE, DEVICE_CLASS_VOLUME, DEVICE_CLASS_WATER, - DEVICE_CLASS_WIND_SPEED, DEVICE_CLASS_WEIGHT, + DEVICE_CLASS_WIND_SPEED, ) from esphome.core import CORE, coroutine_with_priority from esphome.cpp_helpers import setup_entity @@ -63,10 +68,13 @@ CODEOWNERS = ["@esphome/core"] DEVICE_CLASSES = [ DEVICE_CLASS_APPARENT_POWER, DEVICE_CLASS_AQI, + DEVICE_CLASS_ATMOSPHERIC_PRESSURE, DEVICE_CLASS_BATTERY, DEVICE_CLASS_CARBON_DIOXIDE, DEVICE_CLASS_CARBON_MONOXIDE, DEVICE_CLASS_CURRENT, + DEVICE_CLASS_DATA_RATE, + DEVICE_CLASS_DATA_SIZE, DEVICE_CLASS_DISTANCE, DEVICE_CLASS_EMPTY, DEVICE_CLASS_ENERGY, @@ -74,6 +82,7 @@ DEVICE_CLASSES = [ DEVICE_CLASS_GAS, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_ILLUMINANCE, + DEVICE_CLASS_IRRADIANCE, DEVICE_CLASS_MOISTURE, DEVICE_CLASS_MONETARY, DEVICE_CLASS_NITROGEN_DIOXIDE, @@ -83,13 +92,14 @@ DEVICE_CLASSES = [ DEVICE_CLASS_PM1, DEVICE_CLASS_PM10, DEVICE_CLASS_PM25, - DEVICE_CLASS_POWER_FACTOR, DEVICE_CLASS_POWER, + DEVICE_CLASS_POWER_FACTOR, DEVICE_CLASS_PRECIPITATION, DEVICE_CLASS_PRECIPITATION_INTENSITY, DEVICE_CLASS_PRESSURE, DEVICE_CLASS_REACTIVE_POWER, DEVICE_CLASS_SIGNAL_STRENGTH, + DEVICE_CLASS_SOUND_PRESSURE, DEVICE_CLASS_SPEED, DEVICE_CLASS_SULPHUR_DIOXIDE, DEVICE_CLASS_TEMPERATURE, diff --git a/esphome/components/sensor/__init__.py b/esphome/components/sensor/__init__.py index 7842cef4d..54fdfcffd 100644 --- a/esphome/components/sensor/__init__.py +++ b/esphome/components/sensor/__init__.py @@ -29,21 +29,25 @@ from esphome.const import ( CONF_WINDOW_SIZE, CONF_MQTT_ID, CONF_FORCE_UPDATE, - DEVICE_CLASS_DISTANCE, - DEVICE_CLASS_DURATION, - DEVICE_CLASS_EMPTY, DEVICE_CLASS_APPARENT_POWER, DEVICE_CLASS_AQI, + DEVICE_CLASS_ATMOSPHERIC_PRESSURE, DEVICE_CLASS_BATTERY, DEVICE_CLASS_CARBON_DIOXIDE, DEVICE_CLASS_CARBON_MONOXIDE, DEVICE_CLASS_CURRENT, + DEVICE_CLASS_DATA_RATE, + DEVICE_CLASS_DATA_SIZE, DEVICE_CLASS_DATE, + DEVICE_CLASS_DISTANCE, + DEVICE_CLASS_DURATION, + DEVICE_CLASS_EMPTY, DEVICE_CLASS_ENERGY, DEVICE_CLASS_FREQUENCY, DEVICE_CLASS_GAS, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_ILLUMINANCE, + DEVICE_CLASS_IRRADIANCE, DEVICE_CLASS_MOISTURE, DEVICE_CLASS_MONETARY, DEVICE_CLASS_NITROGEN_DIOXIDE, @@ -60,6 +64,7 @@ from esphome.const import ( DEVICE_CLASS_PRESSURE, DEVICE_CLASS_REACTIVE_POWER, DEVICE_CLASS_SIGNAL_STRENGTH, + DEVICE_CLASS_SOUND_PRESSURE, DEVICE_CLASS_SPEED, DEVICE_CLASS_SULPHUR_DIOXIDE, DEVICE_CLASS_TEMPERATURE, @@ -68,8 +73,8 @@ from esphome.const import ( DEVICE_CLASS_VOLTAGE, DEVICE_CLASS_VOLUME, DEVICE_CLASS_WATER, - DEVICE_CLASS_WIND_SPEED, DEVICE_CLASS_WEIGHT, + DEVICE_CLASS_WIND_SPEED, ) from esphome.core import CORE, coroutine_with_priority from esphome.cpp_generator import MockObjClass @@ -78,21 +83,25 @@ from esphome.util import Registry CODEOWNERS = ["@esphome/core"] DEVICE_CLASSES = [ - DEVICE_CLASS_EMPTY, DEVICE_CLASS_APPARENT_POWER, DEVICE_CLASS_AQI, + DEVICE_CLASS_ATMOSPHERIC_PRESSURE, DEVICE_CLASS_BATTERY, DEVICE_CLASS_CARBON_DIOXIDE, DEVICE_CLASS_CARBON_MONOXIDE, DEVICE_CLASS_CURRENT, + DEVICE_CLASS_DATA_RATE, + DEVICE_CLASS_DATA_SIZE, DEVICE_CLASS_DATE, DEVICE_CLASS_DISTANCE, DEVICE_CLASS_DURATION, + DEVICE_CLASS_EMPTY, DEVICE_CLASS_ENERGY, DEVICE_CLASS_FREQUENCY, DEVICE_CLASS_GAS, DEVICE_CLASS_HUMIDITY, DEVICE_CLASS_ILLUMINANCE, + DEVICE_CLASS_IRRADIANCE, DEVICE_CLASS_MOISTURE, DEVICE_CLASS_MONETARY, DEVICE_CLASS_NITROGEN_DIOXIDE, @@ -109,6 +118,7 @@ DEVICE_CLASSES = [ DEVICE_CLASS_PRESSURE, DEVICE_CLASS_REACTIVE_POWER, DEVICE_CLASS_SIGNAL_STRENGTH, + DEVICE_CLASS_SOUND_PRESSURE, DEVICE_CLASS_SPEED, DEVICE_CLASS_SULPHUR_DIOXIDE, DEVICE_CLASS_TEMPERATURE, diff --git a/esphome/const.py b/esphome/const.py index e5d0b0bb1..bd593bbc8 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -916,80 +916,87 @@ UNIT_VOLT_AMPS_REACTIVE_HOURS = "VARh" UNIT_WATT = "W" UNIT_WATT_HOURS = "Wh" -# device classes of binary_sensor component -DEVICE_CLASS_BATTERY_CHARGING = "battery_charging" -DEVICE_CLASS_COLD = "cold" -DEVICE_CLASS_CONNECTIVITY = "connectivity" -DEVICE_CLASS_DOOR = "door" -DEVICE_CLASS_GARAGE_DOOR = "garage_door" -DEVICE_CLASS_HEAT = "heat" -DEVICE_CLASS_LIGHT = "light" -DEVICE_CLASS_LOCK = "lock" -DEVICE_CLASS_MOTION = "motion" -DEVICE_CLASS_MOVING = "moving" -DEVICE_CLASS_OCCUPANCY = "occupancy" -DEVICE_CLASS_OPENING = "opening" -DEVICE_CLASS_PLUG = "plug" -DEVICE_CLASS_PRESENCE = "presence" -DEVICE_CLASS_PROBLEM = "problem" -DEVICE_CLASS_RUNNING = "running" -DEVICE_CLASS_SAFETY = "safety" -DEVICE_CLASS_SMOKE = "smoke" -DEVICE_CLASS_SOUND = "sound" -DEVICE_CLASS_TAMPER = "tamper" -DEVICE_CLASS_VIBRATION = "vibration" -DEVICE_CLASS_WINDOW = "window" -# device classes of both binary_sensor and sensor component -DEVICE_CLASS_EMPTY = "" -DEVICE_CLASS_BATTERY = "battery" -DEVICE_CLASS_CARBON_MONOXIDE = "carbon_monoxide" -DEVICE_CLASS_GAS = "gas" -DEVICE_CLASS_MOISTURE = "moisture" -DEVICE_CLASS_POWER = "power" -# device classes of sensor component +# device classes DEVICE_CLASS_APPARENT_POWER = "apparent_power" DEVICE_CLASS_AQI = "aqi" +DEVICE_CLASS_ATMOSPHERIC_PRESSURE = "atmospheric_pressure" +DEVICE_CLASS_AWNING = "awning" +DEVICE_CLASS_BATTERY = "battery" +DEVICE_CLASS_BATTERY_CHARGING = "battery_charging" +DEVICE_CLASS_BLIND = "blind" DEVICE_CLASS_CARBON_DIOXIDE = "carbon_dioxide" +DEVICE_CLASS_CARBON_MONOXIDE = "carbon_monoxide" +DEVICE_CLASS_COLD = "cold" +DEVICE_CLASS_CONNECTIVITY = "connectivity" DEVICE_CLASS_CURRENT = "current" +DEVICE_CLASS_CURTAIN = "curtain" +DEVICE_CLASS_DAMPER = "damper" +DEVICE_CLASS_DATA_RATE = "data_rate" +DEVICE_CLASS_DATA_SIZE = "data_size" DEVICE_CLASS_DATE = "date" DEVICE_CLASS_DISTANCE = "distance" +DEVICE_CLASS_DOOR = "door" DEVICE_CLASS_DURATION = "duration" +DEVICE_CLASS_EMPTY = "" DEVICE_CLASS_ENERGY = "energy" DEVICE_CLASS_FREQUENCY = "frequency" +DEVICE_CLASS_GARAGE = "garage" +DEVICE_CLASS_GARAGE_DOOR = "garage_door" +DEVICE_CLASS_GAS = "gas" +DEVICE_CLASS_GATE = "gate" +DEVICE_CLASS_HEAT = "heat" DEVICE_CLASS_HUMIDITY = "humidity" DEVICE_CLASS_ILLUMINANCE = "illuminance" +DEVICE_CLASS_IRRADIANCE = "irradiance" +DEVICE_CLASS_LIGHT = "light" +DEVICE_CLASS_LOCK = "lock" +DEVICE_CLASS_MOISTURE = "moisture" DEVICE_CLASS_MONETARY = "monetary" +DEVICE_CLASS_MOTION = "motion" +DEVICE_CLASS_MOVING = "moving" DEVICE_CLASS_NITROGEN_DIOXIDE = "nitrogen_dioxide" DEVICE_CLASS_NITROGEN_MONOXIDE = "nitrogen_monoxide" DEVICE_CLASS_NITROUS_OXIDE = "nitrous_oxide" +DEVICE_CLASS_OCCUPANCY = "occupancy" +DEVICE_CLASS_OPENING = "opening" +DEVICE_CLASS_OUTLET = "outlet" DEVICE_CLASS_OZONE = "ozone" +DEVICE_CLASS_PLUG = "plug" DEVICE_CLASS_PM1 = "pm1" DEVICE_CLASS_PM10 = "pm10" DEVICE_CLASS_PM25 = "pm25" +DEVICE_CLASS_POWER = "power" DEVICE_CLASS_POWER_FACTOR = "power_factor" DEVICE_CLASS_PRECIPITATION = "precipitation" DEVICE_CLASS_PRECIPITATION_INTENSITY = "precipitation_intensity" +DEVICE_CLASS_PRESENCE = "presence" DEVICE_CLASS_PRESSURE = "pressure" +DEVICE_CLASS_PROBLEM = "problem" DEVICE_CLASS_REACTIVE_POWER = "reactive_power" +DEVICE_CLASS_RESTART = "restart" +DEVICE_CLASS_RUNNING = "running" +DEVICE_CLASS_SAFETY = "safety" +DEVICE_CLASS_SHADE = "shade" +DEVICE_CLASS_SHUTTER = "shutter" DEVICE_CLASS_SIGNAL_STRENGTH = "signal_strength" +DEVICE_CLASS_SMOKE = "smoke" +DEVICE_CLASS_SOUND = "sound" +DEVICE_CLASS_SOUND_PRESSURE = "sound_pressure" DEVICE_CLASS_SPEED = "speed" DEVICE_CLASS_SULPHUR_DIOXIDE = "sulphur_dioxide" +DEVICE_CLASS_SWITCH = "switch" +DEVICE_CLASS_TAMPER = "tamper" DEVICE_CLASS_TEMPERATURE = "temperature" DEVICE_CLASS_TIMESTAMP = "timestamp" +DEVICE_CLASS_UPDATE = "update" +DEVICE_CLASS_VIBRATION = "vibration" DEVICE_CLASS_VOLATILE_ORGANIC_COMPOUNDS = "volatile_organic_compounds" DEVICE_CLASS_VOLTAGE = "voltage" DEVICE_CLASS_VOLUME = "volume" DEVICE_CLASS_WATER = "water" -DEVICE_CLASS_WIND_SPEED = "wind_speed" DEVICE_CLASS_WEIGHT = "weight" -# device classes of both binary_sensor and button component -DEVICE_CLASS_UPDATE = "update" -# device classes of button component -DEVICE_CLASS_RESTART = "restart" -# device classes of switch component -DEVICE_CLASS_OUTLET = "outlet" -DEVICE_CLASS_SWITCH = "switch" - +DEVICE_CLASS_WINDOW = "window" +DEVICE_CLASS_WIND_SPEED = "wind_speed" # state classes STATE_CLASS_NONE = "" diff --git a/script/sync-device_class.py b/script/sync-device_class.py new file mode 100755 index 000000000..882655561 --- /dev/null +++ b/script/sync-device_class.py @@ -0,0 +1,67 @@ +#!/usr/bin/env python3 + +import re + +from homeassistant.components.binary_sensor import BinarySensorDeviceClass +from homeassistant.components.button import ButtonDeviceClass +from homeassistant.components.cover import CoverDeviceClass +from homeassistant.components.number import NumberDeviceClass +from homeassistant.components.sensor import SensorDeviceClass +from homeassistant.components.switch import SwitchDeviceClass + +BLOCKLIST = ( + # requires special support on HA side + "enum", +) + +DOMAINS = { + "binary_sensor": BinarySensorDeviceClass, + "button": ButtonDeviceClass, + "cover": CoverDeviceClass, + "number": NumberDeviceClass, + "sensor": SensorDeviceClass, + "switch": SwitchDeviceClass, +} + + +def sub(path, pattern, repl): + with open(path, "r") as handle: + content = handle.read() + content = re.sub(pattern, repl, content, flags=re.MULTILINE, count=1) + with open(path, "w") as handle: + handle.write(content) + + +def main(): + classes = {"EMPTY": ""} + allowed = {} + + for domain, enum in DOMAINS.items(): + available = { + cls.value.upper(): cls.value for cls in enum if cls.value not in BLOCKLIST + } + + classes.update(available) + allowed[domain] = list(available.keys()) + ["EMPTY"] + + # replace constant defines in const.py + out = "" + for cls in sorted(classes): + out += f'DEVICE_CLASS_{cls.upper()} = "{classes[cls]}"\n' + sub("esphome/const.py", '(DEVICE_CLASS_\w+ = "\w*"\r?\n)+', out) + + for domain in sorted(allowed): + # replace imports + out = "" + for item in sorted(allowed[domain]): + out += f" DEVICE_CLASS_{item.upper()},\n" + + sub( + f"esphome/components/{domain}/__init__.py", + "( DEVICE_CLASS_\w+,\r?\n)+", + out, + ) + + +if __name__ == "__main__": + main()