Compare commits

..

89 Commits

Author SHA1 Message Date
Erik 6206754422 Adjust design according to review feedback 2026-06-29 23:06:46 +02:00
Erik 81dcee72e0 Address review comments 2026-06-29 22:40:26 +02:00
Erik 6ed7e315fd Report errors in numerical entity triggers 2026-06-29 10:28:01 +02:00
Karl Beecken 60f3bb58a0 Bump teltasync to 0.4.0 (#175084) 2026-06-29 01:10:28 +02:00
Nathan Spencer f56e13c249 Add router serial number to device info (#175063) 2026-06-28 22:21:15 +02:00
Ludovic BOUÉ fed2df4f7b Bump python-roborock to 5.22.0 (#175074)
Co-authored-by: Ludovic BOUÉ <938089+lboue@users.noreply.github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 22:19:04 +02:00
Michael 8662982236 Migrate govee_ble to UnitOfDensity and UnitOfRatio enums (#175069) 2026-06-28 19:28:07 +02:00
Michael c618496c95 Migrate govee_ble to UnitOfDensity and UnitOfRatio enums (#175070) 2026-06-28 19:26:32 +02:00
Michael 40ef9828c4 Migrate sensirion_ble to UnitOfDensity and UnitOfRatio enums (#175072) 2026-06-28 19:25:51 +02:00
Ludovic BOUÉ ac92775538 Roborock Q10 DND switch (#174851)
Co-authored-by: Ludovic BOUÉ <938089+lboue@users.noreply.github.com>
Co-authored-by: Copilot <copilot@github.com>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-28 19:00:32 +02:00
Michael 4fbff0bd82 Migrate qingping to UnitOfDensity and UnitOfRatio enums (#175071) 2026-06-28 18:55:04 +02:00
Michael a076fcea2d Migrate xiaomi_ble to UnitOfDensity and UnitOfRatio enums (#175073) 2026-06-28 18:47:18 +02:00
Michael d3f6fff3be Migrate bthome to UnitOfDensity and UnitOfRatio enums (#175068) 2026-06-28 18:43:54 +02:00
renovate[bot] ea55fa2a2a Update coverage to 7.14.2 (#175051)
Co-authored-by: Mick Vleeshouwer <mick@imick.nl>
2026-06-28 15:21:19 +02:00
TimL cb35849a63 Add reconfiguration flow to SMLIGHT integration (#174952) 2026-06-28 14:26:45 +02:00
Mick Vleeshouwer e701afd7a7 Bump pyoverkiz to 2.0.3 (#175058) 2026-06-28 14:38:43 +03:00
Tom 3c285f766a Limit amount of ProxmoxVE entities enabled by default (#175004) 2026-06-28 12:30:55 +02:00
Manu 680b652ef2 Catch timeout errors in Steam config flow (#175052) 2026-06-28 08:09:45 +02:00
Michael bf09fa8c0d Update victron_ble test snapshots (#175043) 2026-06-28 03:08:08 +02:00
Michael 1469429510 Migrate alexa_devices to UnitOfDensity / UnitOfRatio enums (#174992) 2026-06-28 01:04:52 +02:00
Michael 476224c6f0 Migrate drop_connect to UnitOfDensity / UnitOfRatio enums (#175000) 2026-06-27 23:50:55 +02:00
Michael 7053d81920 Migrate ecobee to UnitOfDensity / UnitOfRatio enums (#175001) 2026-06-27 23:50:35 +02:00
Michael 1b2776d1f0 Migrate emoncms to UnitOfDensity / UnitOfRatio enums (#175002) 2026-06-27 23:50:29 +02:00
Michael f8a61d760c Migrate epion to UnitOfDensity / UnitOfRatio enums (#175003) 2026-06-27 23:49:34 +02:00
Michael e65d491849 Migrate foobot to UnitOfDensity / UnitOfRatio enums (#175006) 2026-06-27 23:49:19 +02:00
Michael efd615a461 Migrate homematic to UnitOfDensity / UnitOfRatio enums (#175009) 2026-06-27 23:47:10 +02:00
Michael 6e5e16c29d Migrate intelliclima to UnitOfDensity / UnitOfRatio enums (#175010) 2026-06-27 23:46:53 +02:00
Michael a1f78fbab4 Migrate omnilogic to UnitOfDensity / UnitOfRatio enums (#175018) 2026-06-27 23:45:46 +02:00
Michael f774c211a5 Migrate freshr to UnitOfDensity / UnitOfRatio enums (#175007) 2026-06-27 23:45:25 +02:00
Michael 3e23c9d13f Migrate lcn to UnitOfDensity / UnitOfRatio enums (#175011) 2026-06-27 23:42:53 +02:00
Michael 4c26f53358 Migrate lg_thinq to UnitOfDensity / UnitOfRatio enums (#175012) 2026-06-27 23:40:45 +02:00
Michael f5cae385fd Migrate luftdaten to UnitOfDensity / UnitOfRatio enums (#175013) 2026-06-27 23:39:57 +02:00
Michael 3aa68c93a7 Migrate serial_pm to UnitOfDensity / UnitOfRatio enums (#175025) 2026-06-27 23:39:55 +02:00
Michael d57539bfa3 Migrate microbees to UnitOfDensity / UnitOfRatio enums (#175014) 2026-06-27 23:39:41 +02:00
Michael ac0377885f Migrate vallox to UnitOfDensity / UnitOfRatio enums (#175033) 2026-06-27 23:39:40 +02:00
Michael b9676496d5 Migrate mill to UnitOfDensity / UnitOfRatio enums (#175015) 2026-06-27 23:39:13 +02:00
Michael 7435d6fe54 Migrate netatmo to UnitOfDensity / UnitOfRatio enums (#175017) 2026-06-27 23:39:01 +02:00
Michael 57f7c4305a Migrate awair to UnitOfDensity / UnitOfRatio enums (#175016) 2026-06-27 23:38:50 +02:00
Michael 24b1f5d1cf Migrate ondilo_ico to UnitOfDensity / UnitOfRatio enums (#175019) 2026-06-27 23:38:34 +02:00
Michael 915230df44 Migrate opensensemap to UnitOfDensity / UnitOfRatio enums (#175020) 2026-06-27 23:38:23 +02:00
Michael ca9735bb5d Migrate purpleair to UnitOfDensity / UnitOfRatio enums (#175022) 2026-06-27 23:38:14 +02:00
Michael 9cecc5516f Migrate renson to UnitOfDensity / UnitOfRatio enums (#175023) 2026-06-27 23:38:08 +02:00
Michael e75b7fb83b Migrate smartthings to UnitOfDensity / UnitOfRatio enums (#175026) 2026-06-27 23:37:53 +02:00
Michael 089bcd9183 Migrate switchbot to UnitOfDensity / UnitOfRatio enums (#175027) 2026-06-27 23:37:44 +02:00
Michael 363d477dac Migrate switchbot_cloud to UnitOfDensity / UnitOfRatio enums (#175028) 2026-06-27 23:37:32 +02:00
Michael 16772c1ecf Migrate tasmota to UnitOfDensity / UnitOfRatio enums (#175030) 2026-06-27 23:37:23 +02:00
Michael d1007086bd Migrate uhoo to UnitOfDensity / UnitOfRatio enums (#175032) 2026-06-27 23:37:16 +02:00
Michael 566f004401 Migrate venstar to UnitOfDensity / UnitOfRatio enums (#175034) 2026-06-27 23:37:04 +02:00
Michael 41c9a124b1 Migrate pooldose to UnitOfDensity / UnitOfRatio enums (#175031) 2026-06-27 23:33:29 +02:00
Michael dc9750a5cd Migrate xiaomi_miio to UnitOfDensity / UnitOfRatio enums (#175036) 2026-06-27 23:29:00 +02:00
Michael 1e43debac6 Migrate vesync to UnitOfDensity / UnitOfRatio enums (#175035) 2026-06-27 23:28:14 +02:00
Michael d319440508 Migrate openweathermap to UnitOfDensity / UnitOfRatio enums (#175021) 2026-06-27 23:27:15 +02:00
Michael 09c815205b Migrate yolink to UnitOfDensity / UnitOfRatio enums (#175037) 2026-06-27 23:25:46 +02:00
Michael 87809394ef Migrate matter (remaining files) to UnitOfRatio enum (#175038) 2026-06-27 23:25:01 +02:00
Michael 4cfc1d893e Migrate tuya (remaining files) to UnitOfRatio enum (#175039) 2026-06-27 23:24:04 +02:00
Michael 953ebba1f1 Migrate sensibo to UnitOfDensity / UnitOfRatio enums (#175024) 2026-06-27 23:22:29 +02:00
Michael ee96a2e4f1 Migrate google_air_quality to UnitOfDensity / UnitOfRatio enums (#175008) 2026-06-27 23:19:29 +02:00
Michael 5af703b5ed Migrate zwave_js to UnitOfDensity / UnitOfRatio enums (#175040) 2026-06-27 23:19:07 +02:00
Michael 1301d36442 Migrate overkiz (remaining files) to UnitOfRatio enum (#175041) 2026-06-27 23:18:51 +02:00
Michael 956f3fd821 Migrate fibaro to UnitOfDensity / UnitOfRatio enums (#175005) 2026-06-27 23:07:58 +02:00
Michael 8797a2ec5e Migrate deconz to UnitOfDensity / UnitOfRatio enums (#174999) 2026-06-27 21:32:37 +02:00
Michael 528ea500a9 Migrate compit to UnitOfDensity / UnitOfRatio enums (#174998) 2026-06-27 21:31:04 +02:00
Michael 433ff53630 Migrate broadlink to UnitOfDensity / UnitOfRatio enums (#174997) 2026-06-27 21:30:37 +02:00
Michael eebb8b5b91 Migrate bosch_shc to UnitOfDensity / UnitOfRatio enums (#174996) 2026-06-27 21:30:10 +02:00
Michael e0c881758b Migrate aranet to UnitOfDensity / UnitOfRatio enums (#174995) 2026-06-27 21:29:42 +02:00
Michael 46cf3e8289 Migrate airthings to UnitOfDensity / UnitOfRatio enums (#174986) 2026-06-27 21:27:51 +02:00
Michael 1d7ea1fc72 Migrate airobot to UnitOfDensity / UnitOfRatio enums (#174985) 2026-06-27 21:27:20 +02:00
Michael 9219643803 Migrate arve to UnitOfDensity / UnitOfRatio enums (#174982) 2026-06-27 21:26:52 +02:00
Michael b202a0d7ab Migrate altruist to UnitOfDensity / UnitOfRatio enums (#174993) 2026-06-27 21:26:10 +02:00
Michael 67801ab604 Migrate ambient_network to UnitOfDensity / UnitOfRatio enums (#174994) 2026-06-27 21:25:41 +02:00
Michael 227aee5232 Migrate airvisual to UnitOfDensity / UnitOfRatio enums (#174987) 2026-06-27 21:25:05 +02:00
Michael e465549f03 Migrate airvisual_pro to UnitOfDensity / UnitOfRatio enums (#174988) 2026-06-27 21:24:31 +02:00
Michael 6efd9093ce Migrate airzone_cloud to UnitOfDensity / UnitOfRatio enums (#174989) 2026-06-27 21:13:37 +02:00
Michael 7044dae281 Migrate airgradient to UnitOfDensity / UnitOfRatio enums (#174984) 2026-06-27 19:01:03 +02:00
Manu 9d34e83f71 Remove Clementine Music Player (#174970) 2026-06-27 17:39:48 +02:00
Manu ff45b81145 Remove Microsoft Face (#174977) 2026-06-27 17:37:38 +02:00
Willem-Jan van Rootselaar 486385e308 Bump python-bsblan to version 6.1.4 (#174974) 2026-06-27 18:02:38 +03:00
Raj Laud 11113ce1f4 Add Orion XS and Inverter support to Victron BLE (#169834)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-27 16:48:19 +02:00
Øyvind Matheson Wergeland 31dc1f9519 Drop nobo_hub custom select device class (#170135)
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
2026-06-27 16:44:57 +02:00
On Freund 926900d0ca Bump pymonoprice to 0.6.1 (#174951)
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-27 09:49:03 -04:00
OzGav 06b429d0b7 Update music-assistant-client to 1.3.6 (#174968) 2026-06-27 15:31:17 +02:00
Åke Strandberg 9fb2d14fdb Handle SSE updates of single miele devices (#174955) 2026-06-27 15:26:57 +02:00
Manu 0e6279e273 Remove Watson TTS integration (#174967) 2026-06-27 15:17:41 +02:00
TimL 02ddd4c3f4 Bump Pysmlight to v0.5.0 (#174947) 2026-06-27 15:58:27 +03:00
Michael c147321aba Migrate demo to UnitOfRatio enums (#174966) 2026-06-27 15:56:34 +03:00
Michael f0e75ebb83 Bump aioimmich to 0.15.1 (#174962) 2026-06-27 15:55:18 +03:00
Manu 7ae85d8d97 Remove BlinkStick (#174961) 2026-06-27 14:29:30 +02:00
g4bri3lDev 43802961e9 Fix swallowed exception in opendisplay upload_image action handler (#170660) 2026-06-27 14:19:47 +02:00
Øyvind Matheson Wergeland 97844d7ee0 Filter already-configured hubs from nobo_hub config flow (#169593)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-06-27 14:18:53 +02:00
194 changed files with 7487 additions and 3504 deletions
Generated
-1
View File
@@ -1986,7 +1986,6 @@ CLAUDE.md @home-assistant/core
/tests/components/waterfurnace/ @sdague @masterkoppa
/homeassistant/components/watergate/ @adam-the-hero
/tests/components/watergate/ @adam-the-hero
/homeassistant/components/watson_tts/ @rutkai
/homeassistant/components/watts/ @theobld-ww @devender-verma-ww @ssi-spyro
/tests/components/watts/ @theobld-ww @devender-verma-ww @ssi-spyro
/homeassistant/components/watttime/ @bachya
-3
View File
@@ -7,9 +7,6 @@
"azure_event_hub",
"azure_service_bus",
"azure_storage",
"microsoft_face_detect",
"microsoft_face_identify",
"microsoft_face",
"microsoft",
"onedrive",
"onedrive_for_business",
@@ -12,7 +12,7 @@ from homeassistant.components.number import (
NumberEntity,
NumberEntityDescription,
)
from homeassistant.const import PERCENTAGE, EntityCategory
from homeassistant.const import EntityCategory, UnitOfRatio
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
@@ -40,7 +40,7 @@ DISPLAY_BRIGHTNESS = AirGradientNumberEntityDescription(
native_min_value=0,
native_max_value=100,
native_step=1,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
value_fn=lambda config: config.display_brightness,
set_value_fn=lambda client, value: client.set_display_brightness(value),
)
@@ -52,7 +52,7 @@ LED_BAR_BRIGHTNESS = AirGradientNumberEntityDescription(
native_min_value=0,
native_max_value=100,
native_step=1,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
value_fn=lambda config: config.led_bar_brightness,
set_value_fn=lambda client, value: client.set_led_bar_brightness(value),
)
+11 -12
View File
@@ -19,11 +19,10 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
EntityCategory,
UnitOfDensity,
UnitOfRatio,
UnitOfTemperature,
UnitOfTime,
)
@@ -57,21 +56,21 @@ MEASUREMENT_SENSOR_TYPES: tuple[AirGradientMeasurementSensorEntityDescription, .
AirGradientMeasurementSensorEntityDescription(
key="pm01",
device_class=SensorDeviceClass.PM1,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda status: status.pm01,
),
AirGradientMeasurementSensorEntityDescription(
key="pm02",
device_class=SensorDeviceClass.PM25,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda status: status.pm02,
),
AirGradientMeasurementSensorEntityDescription(
key="pm10",
device_class=SensorDeviceClass.PM10,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda status: status.pm10,
),
@@ -85,7 +84,7 @@ MEASUREMENT_SENSOR_TYPES: tuple[AirGradientMeasurementSensorEntityDescription, .
AirGradientMeasurementSensorEntityDescription(
key="humidity",
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda status: status.relative_humidity,
),
@@ -113,7 +112,7 @@ MEASUREMENT_SENSOR_TYPES: tuple[AirGradientMeasurementSensorEntityDescription, .
AirGradientMeasurementSensorEntityDescription(
key="co2",
device_class=SensorDeviceClass.CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda status: status.rco2,
),
@@ -144,7 +143,7 @@ MEASUREMENT_SENSOR_TYPES: tuple[AirGradientMeasurementSensorEntityDescription, .
key="pm02_raw",
translation_key="raw_pm02",
device_class=SensorDeviceClass.PM25,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
value_fn=lambda status: status.raw_pm02,
@@ -190,7 +189,7 @@ CONFIG_LED_BAR_SENSOR_TYPES: tuple[AirGradientConfigSensorEntityDescription, ...
AirGradientConfigSensorEntityDescription(
key="led_bar_brightness",
translation_key="led_bar_brightness",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda config: config.led_bar_brightness,
),
@@ -216,9 +215,9 @@ CONFIG_DISPLAY_SENSOR_TYPES: tuple[AirGradientConfigSensorEntityDescription, ...
AirGradientConfigSensorEntityDescription(
key="display_brightness",
translation_key="display_brightness",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda config: config.display_brightness,
value_fn=lambda config: config.led_bar_brightness,
),
)
+3 -4
View File
@@ -14,9 +14,8 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
EntityCategory,
UnitOfRatio,
UnitOfTemperature,
UnitOfTime,
)
@@ -59,7 +58,7 @@ SENSOR_TYPES: tuple[AirobotSensorEntityDescription, ...] = (
AirobotSensorEntityDescription(
key="humidity",
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda status: status.hum_air,
),
@@ -75,7 +74,7 @@ SENSOR_TYPES: tuple[AirobotSensorEntityDescription, ...] = (
AirobotSensorEntityDescription(
key="co2",
device_class=SensorDeviceClass.CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda status: status.co2,
supported_fn=lambda status: status.has_co2_sensor,
+9 -11
View File
@@ -11,14 +11,12 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_BILLION,
CONCENTRATION_PARTS_PER_MILLION,
LIGHT_LUX,
PERCENTAGE,
SIGNAL_STRENGTH_DECIBELS,
EntityCategory,
UnitOfDensity,
UnitOfPressure,
UnitOfRatio,
UnitOfSoundPressure,
UnitOfTemperature,
)
@@ -49,7 +47,7 @@ SENSORS: dict[str, SensorEntityDescription] = {
"humidity": SensorEntityDescription(
key="humidity",
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
),
@@ -70,7 +68,7 @@ SENSORS: dict[str, SensorEntityDescription] = {
"battery": SensorEntityDescription(
key="battery",
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
@@ -78,20 +76,20 @@ SENSORS: dict[str, SensorEntityDescription] = {
"co2": SensorEntityDescription(
key="co2",
device_class=SensorDeviceClass.CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
),
"voc": SensorEntityDescription(
key="voc",
device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS_PARTS,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_BILLION,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
),
"light": SensorEntityDescription(
key="light",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
translation_key="light",
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
@@ -126,14 +124,14 @@ SENSORS: dict[str, SensorEntityDescription] = {
),
"pm1": SensorEntityDescription(
key="pm1",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM1,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
),
"pm25": SensorEntityDescription(
key="pm25",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM25,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
+8 -9
View File
@@ -12,14 +12,13 @@ from homeassistant.const import (
ATTR_LATITUDE,
ATTR_LONGITUDE,
ATTR_STATE,
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_BILLION,
CONCENTRATION_PARTS_PER_MILLION,
CONF_COUNTRY,
CONF_LATITUDE,
CONF_LONGITUDE,
CONF_SHOW_ON_MAP,
CONF_STATE,
UnitOfDensity,
UnitOfRatio,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
@@ -94,12 +93,12 @@ POLLUTANT_LEVELS = {
}
POLLUTANT_UNITS = {
"co": CONCENTRATION_PARTS_PER_MILLION,
"n2": CONCENTRATION_PARTS_PER_BILLION,
"o3": CONCENTRATION_PARTS_PER_BILLION,
"p1": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
"p2": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
"s2": CONCENTRATION_PARTS_PER_BILLION,
"co": UnitOfRatio.PARTS_PER_MILLION,
"n2": UnitOfRatio.PARTS_PER_BILLION,
"o3": UnitOfRatio.PARTS_PER_BILLION,
"p1": UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
"p2": UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
"s2": UnitOfRatio.PARTS_PER_BILLION,
}
@@ -11,10 +11,9 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
EntityCategory,
UnitOfDensity,
UnitOfRatio,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant, callback
@@ -57,21 +56,21 @@ SENSOR_DESCRIPTIONS = (
key="battery_level",
device_class=SensorDeviceClass.BATTERY,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda settings, status, measurements, history: status["battery"],
),
AirVisualProMeasurementDescription(
key="carbon_dioxide",
device_class=SensorDeviceClass.CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda settings, status, measurements, history: measurements["co2"],
),
AirVisualProMeasurementDescription(
key="humidity",
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda settings, status, measurements, history: measurements[
"humidity"
@@ -80,21 +79,21 @@ SENSOR_DESCRIPTIONS = (
AirVisualProMeasurementDescription(
key="particulate_matter_0_1",
translation_key="pm01",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda settings, status, measurements, history: measurements["pm0_1"],
),
AirVisualProMeasurementDescription(
key="particulate_matter_1_0",
device_class=SensorDeviceClass.PM1,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda settings, status, measurements, history: measurements["pm1_0"],
),
AirVisualProMeasurementDescription(
key="particulate_matter_2_5",
device_class=SensorDeviceClass.PM25,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda settings, status, measurements, history: measurements["pm2_5"],
),
@@ -110,7 +109,7 @@ SENSOR_DESCRIPTIONS = (
AirVisualProMeasurementDescription(
key="voc",
device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda settings, status, measurements, history: measurements["voc"],
),
@@ -35,13 +35,13 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
PERCENTAGE,
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
EntityCategory,
UnitOfDensity,
UnitOfElectricCurrent,
UnitOfInformation,
UnitOfPressure,
UnitOfRatio,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant, callback
@@ -141,7 +141,7 @@ WEBSERVER_SENSOR_TYPES: Final[tuple[SensorEntityDescription, ...]] = (
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
key=AZD_CPU_USAGE,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
translation_key="cpu_usage",
),
@@ -172,19 +172,19 @@ ZONE_SENSOR_TYPES: Final[tuple[SensorEntityDescription, ...]] = (
SensorEntityDescription(
device_class=SensorDeviceClass.PM1,
key=AZD_AQ_PM_1,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
device_class=SensorDeviceClass.PM25,
key=AZD_AQ_PM_2P5,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
device_class=SensorDeviceClass.PM10,
key=AZD_AQ_PM_10,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
@@ -196,20 +196,20 @@ ZONE_SENSOR_TYPES: Final[tuple[SensorEntityDescription, ...]] = (
SensorEntityDescription(
device_class=SensorDeviceClass.HUMIDITY,
key=AZD_HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
device_class=SensorDeviceClass.BATTERY,
key=AZD_THERMOSTAT_BATTERY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
key=AZD_THERMOSTAT_COVERAGE,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
translation_key="thermostat_coverage",
),
@@ -18,13 +18,7 @@ from homeassistant.components.sensor import (
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_MILLION,
LIGHT_LUX,
PERCENTAGE,
UnitOfTemperature,
)
from homeassistant.const import LIGHT_LUX, UnitOfDensity, UnitOfRatio, UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.typing import StateType
@@ -97,25 +91,25 @@ SENSORS: Final = (
AmazonSensorEntityDescription(
key="Humidity",
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
AmazonSensorEntityDescription(
key="PM10",
device_class=SensorDeviceClass.PM10,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
),
AmazonSensorEntityDescription(
key="PM25",
device_class=SensorDeviceClass.PM25,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
),
AmazonSensorEntityDescription(
key="CO",
device_class=SensorDeviceClass.CO,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
),
AmazonSensorEntityDescription(
+11 -12
View File
@@ -12,12 +12,11 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
EntityCategory,
UnitOfDensity,
UnitOfPressure,
UnitOfRatio,
UnitOfSoundPressure,
UnitOfTemperature,
)
@@ -45,7 +44,7 @@ SENSOR_DESCRIPTIONS = [
device_class=SensorDeviceClass.HUMIDITY,
key="BME280_humidity",
translation_key="humidity",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
suggested_display_precision=2,
translation_placeholders={"sensor_name": "BME280"},
),
@@ -70,7 +69,7 @@ SENSOR_DESCRIPTIONS = [
device_class=SensorDeviceClass.HUMIDITY,
key="BME680_humidity",
translation_key="humidity",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
suggested_display_precision=2,
translation_placeholders={"sensor_name": "BME680"},
),
@@ -129,7 +128,7 @@ SENSOR_DESCRIPTIONS = [
device_class=SensorDeviceClass.HUMIDITY,
key="HTU21D_humidity",
translation_key="humidity",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
suggested_display_precision=2,
translation_placeholders={"sensor_name": "HTU21D"},
),
@@ -145,21 +144,21 @@ SENSOR_DESCRIPTIONS = [
device_class=SensorDeviceClass.PM10,
translation_key="pm_10",
key="SDS_P1",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
suggested_display_precision=2,
),
AltruistSensorEntityDescription(
device_class=SensorDeviceClass.PM25,
translation_key="pm_25",
key="SDS_P2",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
suggested_display_precision=2,
),
AltruistSensorEntityDescription(
device_class=SensorDeviceClass.HUMIDITY,
key="SHT3X_humidity",
translation_key="humidity",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
suggested_display_precision=2,
translation_placeholders={"sensor_name": "SHT3X"},
),
@@ -194,7 +193,7 @@ SENSOR_DESCRIPTIONS = [
),
AltruistSensorEntityDescription(
device_class=SensorDeviceClass.CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
translation_key="co2",
key="CCS_CO2",
suggested_display_precision=2,
@@ -203,7 +202,7 @@ SENSOR_DESCRIPTIONS = [
AltruistSensorEntityDescription(
device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS,
key="CCS_TVOC",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
suggested_display_precision=2,
),
AltruistSensorEntityDescription(
@@ -215,7 +214,7 @@ SENSOR_DESCRIPTIONS = [
AltruistSensorEntityDescription(
device_class=SensorDeviceClass.CO2,
translation_key="co2",
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
key="SCD4x_co2",
suggested_display_precision=2,
translation_placeholders={"sensor_name": "SCD4x"},
@@ -10,15 +10,14 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_MILLION,
CONF_MAC,
DEGREE,
PERCENTAGE,
UnitOfDensity,
UnitOfIrradiance,
UnitOfLength,
UnitOfPrecipitationDepth,
UnitOfPressure,
UnitOfRatio,
UnitOfSpeed,
UnitOfTemperature,
UnitOfVolumetricFlux,
@@ -94,7 +93,7 @@ SENSOR_DESCRIPTIONS = (
),
SensorEntityDescription(
key=TYPE_CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
device_class=SensorDeviceClass.CO2,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=2,
@@ -134,7 +133,7 @@ SENSOR_DESCRIPTIONS = (
),
SensorEntityDescription(
key=TYPE_HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
device_class=SensorDeviceClass.HUMIDITY,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=1,
@@ -188,14 +187,14 @@ SENSOR_DESCRIPTIONS = (
SensorEntityDescription(
key=TYPE_PM25_24H,
translation_key="pm25_24h_average",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM25,
suggested_display_precision=1,
entity_registry_enabled_default=False,
),
SensorEntityDescription(
key=TYPE_PM25,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM25,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=1,
@@ -28,6 +28,7 @@ from homeassistant.const import (
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers import config_validation as cv, llm
from homeassistant.helpers.httpx_client import get_async_client
from homeassistant.helpers.selector import (
NumberSelector,
NumberSelectorConfig,
@@ -65,7 +66,7 @@ from .const import (
TOOL_SEARCH_UNSUPPORTED_MODELS,
PromptCaching,
)
from .coordinator import async_create_client, model_alias
from .coordinator import model_alias
if TYPE_CHECKING:
from . import AnthropicConfigEntry
@@ -94,7 +95,9 @@ async def validate_input(hass: HomeAssistant, data: dict[str, Any]) -> None:
Data has the keys from STEP_USER_DATA_SCHEMA with values provided by the user.
"""
client = await async_create_client(hass, data[CONF_API_KEY])
client = anthropic.AsyncAnthropic(
api_key=data[CONF_API_KEY], http_client=get_async_client(hass)
)
await client.models.list(timeout=10.0)
@@ -546,8 +549,9 @@ class ConversationSubentryFlowHandler(ConfigSubentryFlow):
location_data: dict[str, str] = {}
zone_home = self.hass.states.get(ENTITY_ID_HOME)
if zone_home is not None:
client = await async_create_client(
self.hass, self._get_entry().data[CONF_API_KEY]
client = anthropic.AsyncAnthropic(
api_key=self._get_entry().data[CONF_API_KEY],
http_client=get_async_client(self.hass),
)
location_schema = vol.Schema(
{
@@ -1,7 +1,6 @@
"""Coordinator for the Anthropic integration."""
import datetime
from functools import partial
from typing import override
import anthropic
@@ -21,19 +20,6 @@ UPDATE_INTERVAL_DISCONNECTED = datetime.timedelta(minutes=1)
type AnthropicConfigEntry = ConfigEntry[AnthropicCoordinator]
async def async_create_client(
hass: HomeAssistant, api_key: str
) -> anthropic.AsyncAnthropic:
"""Create an Anthropic client."""
return await hass.async_add_executor_job(
partial(
anthropic.AsyncAnthropic,
api_key=api_key,
http_client=get_async_client(hass),
)
)
@callback
def model_alias(model_id: str) -> str:
"""Resolve alias from versioned model name."""
@@ -47,8 +33,7 @@ def model_alias(model_id: str) -> str:
class AnthropicCoordinator(DataUpdateCoordinator[list[anthropic.types.ModelInfo]]):
"""Coordinator using different intervals after success and failure."""
config_entry: AnthropicConfigEntry
_client: anthropic.AsyncAnthropic
client: anthropic.AsyncAnthropic
def __init__(self, hass: HomeAssistant, config_entry: AnthropicConfigEntry) -> None:
"""Initialize the coordinator."""
@@ -61,17 +46,8 @@ class AnthropicCoordinator(DataUpdateCoordinator[list[anthropic.types.ModelInfo]
update_method=self.async_update_data,
always_update=False,
)
@property
def client(self) -> anthropic.AsyncAnthropic:
"""Return the Anthropic client."""
return self._client
@override
async def _async_setup(self) -> None:
"""Set up the coordinator."""
self._client = await async_create_client(
self.hass, self.config_entry.data[CONF_API_KEY]
self.client = anthropic.AsyncAnthropic(
api_key=config_entry.data[CONF_API_KEY], http_client=get_async_client(hass)
)
@callback
+4 -5
View File
@@ -23,10 +23,9 @@ from homeassistant.const import (
ATTR_MODEL,
ATTR_NAME,
ATTR_SW_VERSION,
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
EntityCategory,
UnitOfPressure,
UnitOfRatio,
UnitOfTemperature,
UnitOfTime,
)
@@ -62,7 +61,7 @@ SENSOR_DESCRIPTIONS = {
key="humidity",
name="Humidity",
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
"pressure": AranetSensorEntityDescription(
@@ -83,7 +82,7 @@ SENSOR_DESCRIPTIONS = {
key="co2",
name="Carbon Dioxide",
device_class=SensorDeviceClass.CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
),
"radiation_rate": AranetSensorEntityDescription(
@@ -115,7 +114,7 @@ SENSOR_DESCRIPTIONS = {
key="battery",
name="Battery",
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
),
+5 -10
View File
@@ -12,12 +12,7 @@ from homeassistant.components.sensor import (
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
UnitOfTemperature,
)
from homeassistant.const import UnitOfDensity, UnitOfRatio, UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
@@ -35,7 +30,7 @@ class ArveDeviceEntityDescription(SensorEntityDescription):
SENSORS: tuple[ArveDeviceEntityDescription, ...] = (
ArveDeviceEntityDescription(
key="CO2",
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
device_class=SensorDeviceClass.CO2,
value_fn=lambda arve_data: arve_data.co2,
state_class=SensorStateClass.MEASUREMENT,
@@ -48,21 +43,21 @@ SENSORS: tuple[ArveDeviceEntityDescription, ...] = (
),
ArveDeviceEntityDescription(
key="Humidity",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
device_class=SensorDeviceClass.HUMIDITY,
value_fn=lambda arve_data: arve_data.humidity,
state_class=SensorStateClass.MEASUREMENT,
),
ArveDeviceEntityDescription(
key="PM10",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM10,
value_fn=lambda arve_data: arve_data.pm10,
state_class=SensorStateClass.MEASUREMENT,
),
ArveDeviceEntityDescription(
key="PM25",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM25,
value_fn=lambda arve_data: arve_data.pm25,
state_class=SensorStateClass.MEASUREMENT,
+9 -12
View File
@@ -16,12 +16,9 @@ from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
ATTR_CONNECTIONS,
ATTR_SW_VERSION,
CONCENTRATION_GRAMS_PER_CUBIC_METER,
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_BILLION,
CONCENTRATION_PARTS_PER_MILLION,
LIGHT_LUX,
PERCENTAGE,
UnitOfDensity,
UnitOfRatio,
UnitOfSoundPressure,
UnitOfTemperature,
)
@@ -61,7 +58,7 @@ class AwairSensorEntityDescription(SensorEntityDescription):
SENSOR_TYPE_SCORE = AwairSensorEntityDescription(
key=API_SCORE,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
translation_key="score",
unique_id_tag="score", # matches legacy format
state_class=SensorStateClass.MEASUREMENT,
@@ -71,7 +68,7 @@ SENSOR_TYPES: tuple[AwairSensorEntityDescription, ...] = (
AwairSensorEntityDescription(
key=API_HUMID,
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
unique_id_tag="HUMID", # matches legacy format
state_class=SensorStateClass.MEASUREMENT,
),
@@ -93,7 +90,7 @@ SENSOR_TYPES: tuple[AwairSensorEntityDescription, ...] = (
AwairSensorEntityDescription(
key=API_VOC,
device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS_PARTS,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_BILLION,
unique_id_tag="VOC", # matches legacy format
state_class=SensorStateClass.MEASUREMENT,
),
@@ -107,7 +104,7 @@ SENSOR_TYPES: tuple[AwairSensorEntityDescription, ...] = (
AwairSensorEntityDescription(
key=API_CO2,
device_class=SensorDeviceClass.CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
unique_id_tag="CO2", # matches legacy format
state_class=SensorStateClass.MEASUREMENT,
),
@@ -123,7 +120,7 @@ SENSOR_TYPES: tuple[AwairSensorEntityDescription, ...] = (
AwairSensorEntityDescription(
key=API_ABS_HUMID,
device_class=SensorDeviceClass.ABSOLUTE_HUMIDITY,
native_unit_of_measurement=CONCENTRATION_GRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.GRAMS_PER_CUBIC_METER,
unique_id_tag="absolute_humidity",
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
@@ -134,14 +131,14 @@ SENSOR_TYPES_DUST: tuple[AwairSensorEntityDescription, ...] = (
AwairSensorEntityDescription(
key=API_PM25,
device_class=SensorDeviceClass.PM25,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
unique_id_tag="PM25", # matches legacy format
state_class=SensorStateClass.MEASUREMENT,
),
AwairSensorEntityDescription(
key=API_PM10,
device_class=SensorDeviceClass.PM10,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
unique_id_tag="PM10", # matches legacy format
state_class=SensorStateClass.MEASUREMENT,
),
@@ -1 +0,0 @@
"""The BlinkStick integration."""
@@ -1,87 +0,0 @@
"""Support for BlinkStick lights."""
# mypy: ignore-errors
from typing import Any
# from blinkstick import blinkstick
import voluptuous as vol
from homeassistant.components.light import (
ATTR_BRIGHTNESS,
ATTR_HS_COLOR,
PLATFORM_SCHEMA as LIGHT_PLATFORM_SCHEMA,
ColorMode,
LightEntity,
)
from homeassistant.const import CONF_NAME
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
from homeassistant.util import color as color_util
CONF_SERIAL = "serial"
DEFAULT_NAME = "Blinkstick"
PLATFORM_SCHEMA = LIGHT_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_SERIAL): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
}
)
def setup_platform(
hass: HomeAssistant,
config: ConfigType,
add_entities: AddEntitiesCallback,
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up BlinkStick device specified by serial number."""
name = config[CONF_NAME]
serial = config[CONF_SERIAL]
stick = blinkstick.find_by_serial(serial)
add_entities([BlinkStickLight(stick, name)], True)
class BlinkStickLight(LightEntity):
"""Representation of a BlinkStick light."""
_attr_color_mode = ColorMode.HS
_attr_supported_color_modes = {ColorMode.HS}
def __init__(self, stick, name):
"""Initialize the light."""
self._stick = stick
self._attr_name = name
def update(self) -> None:
"""Read back the device state."""
rgb_color = self._stick.get_color()
hsv = color_util.color_RGB_to_hsv(*rgb_color)
self._attr_hs_color = hsv[:2]
self._attr_brightness = int(hsv[2])
self._attr_is_on = self.brightness is not None and self.brightness > 0
def turn_on(self, **kwargs: Any) -> None:
"""Turn the device on."""
if ATTR_HS_COLOR in kwargs:
self._attr_hs_color = kwargs[ATTR_HS_COLOR]
brightness: int = kwargs.get(ATTR_BRIGHTNESS, 255)
self._attr_brightness = brightness
self._attr_is_on = bool(brightness)
assert self.hs_color
rgb_color = color_util.color_hsv_to_RGB(
self.hs_color[0], self.hs_color[1], brightness / 255 * 100
)
self._stick.set_color(red=rgb_color[0], green=rgb_color[1], blue=rgb_color[2])
def turn_off(self, **kwargs: Any) -> None:
"""Turn the device off."""
self._stick.turn_off()
@@ -1,11 +0,0 @@
{
"domain": "blinksticklight",
"name": "BlinkStick",
"codeowners": [],
"disabled": "This integration is disabled because it uses non-open source code to operate.",
"documentation": "https://www.home-assistant.io/integrations/blinksticklight",
"iot_class": "local_polling",
"loggers": ["blinkstick"],
"quality_scale": "legacy",
"requirements": ["BlinkStick==1.2.0"]
}
@@ -1,5 +0,0 @@
extend = "../../../pyproject.toml"
lint.extend-ignore = [
"F821"
]
+4 -5
View File
@@ -13,10 +13,9 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
UnitOfEnergy,
UnitOfPower,
UnitOfRatio,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant
@@ -58,13 +57,13 @@ SENSOR_DESCRIPTIONS: dict[str, SHCSensorEntityDescription] = {
HUMIDITY_SENSOR: SHCSensorEntityDescription(
key=HUMIDITY_SENSOR,
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
value_fn=lambda device: device.humidity,
),
PURITY_SENSOR: SHCSensorEntityDescription(
key=PURITY_SENSOR,
translation_key=PURITY_SENSOR,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
value_fn=lambda device: device.purity,
),
AIR_QUALITY_SENSOR: SHCSensorEntityDescription(
@@ -112,7 +111,7 @@ SENSOR_DESCRIPTIONS: dict[str, SHCSensorEntityDescription] = {
key=VALVE_TAPPET_SENSOR,
translation_key=VALVE_TAPPET_SENSOR,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
value_fn=lambda device: device.position,
attributes_fn=lambda device: {
"valve_tappet_state": device.valvestate.name,
+6 -6
View File
@@ -10,12 +10,12 @@ from homeassistant.components.sensor import (
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
PERCENTAGE,
UnitOfDensity,
UnitOfElectricCurrent,
UnitOfElectricPotential,
UnitOfEnergy,
UnitOfPower,
UnitOfRatio,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant
@@ -37,25 +37,25 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
),
SensorEntityDescription(
key="pm10",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM10,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
key="pm2_5",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM25,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
key="pm1",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM1,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
key="humidity",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
device_class=SensorDeviceClass.HUMIDITY,
state_class=SensorStateClass.MEASUREMENT,
),
@@ -8,7 +8,7 @@
"iot_class": "local_polling",
"loggers": ["bsblan"],
"quality_scale": "silver",
"requirements": ["python-bsblan==6.1.3"],
"requirements": ["python-bsblan==6.1.4"],
"zeroconf": [
{
"name": "bsb-lan*",
+9 -10
View File
@@ -18,15 +18,13 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_MILLION,
DEGREE,
LIGHT_LUX,
PERCENTAGE,
REVOLUTIONS_PER_MINUTE,
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
EntityCategory,
UnitOfConductivity,
UnitOfDensity,
UnitOfElectricCurrent,
UnitOfElectricPotential,
UnitOfEnergy,
@@ -34,6 +32,7 @@ from homeassistant.const import (
UnitOfMass,
UnitOfPower,
UnitOfPressure,
UnitOfRatio,
UnitOfSpeed,
UnitOfTemperature,
UnitOfTime,
@@ -63,7 +62,7 @@ SENSOR_DESCRIPTIONS = {
(BTHomeSensorDeviceClass.BATTERY, Units.PERCENTAGE): SensorEntityDescription(
key=f"{BTHomeSensorDeviceClass.BATTERY}_{Units.PERCENTAGE}",
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
),
@@ -96,7 +95,7 @@ SENSOR_DESCRIPTIONS = {
): SensorEntityDescription(
key=f"{BTHomeSensorDeviceClass.CO2}_{Units.CONCENTRATION_PARTS_PER_MILLION}",
device_class=SensorDeviceClass.CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
),
# Current (Ampere)
@@ -182,7 +181,7 @@ SENSOR_DESCRIPTIONS = {
(BTHomeSensorDeviceClass.HUMIDITY, Units.PERCENTAGE): SensorEntityDescription(
key=f"{BTHomeSensorDeviceClass.HUMIDITY}_{Units.PERCENTAGE}",
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
# Illuminance (lux)
@@ -216,7 +215,7 @@ SENSOR_DESCRIPTIONS = {
(BTHomeSensorDeviceClass.MOISTURE, Units.PERCENTAGE): SensorEntityDescription(
key=f"{BTHomeSensorDeviceClass.MOISTURE}_{Units.PERCENTAGE}",
device_class=SensorDeviceClass.MOISTURE,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
# Packet Id (-)
@@ -234,7 +233,7 @@ SENSOR_DESCRIPTIONS = {
): SensorEntityDescription(
key=f"{BTHomeSensorDeviceClass.PM10}_{Units.CONCENTRATION_MICROGRAMS_PER_CUBIC_METER}",
device_class=SensorDeviceClass.PM10,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
),
# PM2.5 (μg/m3)
@@ -244,7 +243,7 @@ SENSOR_DESCRIPTIONS = {
): SensorEntityDescription(
key=f"{BTHomeSensorDeviceClass.PM25}_{Units.CONCENTRATION_MICROGRAMS_PER_CUBIC_METER}",
device_class=SensorDeviceClass.PM25,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
),
# Power (Watt)
@@ -357,7 +356,7 @@ SENSOR_DESCRIPTIONS = {
): SensorEntityDescription(
key=f"{BTHomeSensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS}_{Units.CONCENTRATION_MICROGRAMS_PER_CUBIC_METER}",
device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
),
# Voltage (volt)
@@ -1 +0,0 @@
"""The clementine component."""
@@ -1,10 +0,0 @@
{
"domain": "clementine",
"name": "Clementine Music Player",
"codeowners": [],
"documentation": "https://www.home-assistant.io/integrations/clementine",
"iot_class": "local_polling",
"loggers": ["clementineremote"],
"quality_scale": "legacy",
"requirements": ["python-clementine-remote==1.0.1"]
}
@@ -1,166 +0,0 @@
"""Support for Clementine Music Player as media player."""
from datetime import timedelta
import time
from typing import override
from clementineremote import ClementineRemote
import voluptuous as vol
from homeassistant.components.media_player import (
PLATFORM_SCHEMA as MEDIA_PLAYER_PLATFORM_SCHEMA,
MediaPlayerEntity,
MediaPlayerEntityFeature,
MediaPlayerState,
MediaType,
)
from homeassistant.const import CONF_ACCESS_TOKEN, CONF_HOST, CONF_NAME, CONF_PORT
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
DEFAULT_NAME = "Clementine Remote"
DEFAULT_PORT = 5500
SCAN_INTERVAL = timedelta(seconds=5)
PLATFORM_SCHEMA = MEDIA_PLAYER_PLATFORM_SCHEMA.extend(
{
vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_ACCESS_TOKEN): cv.positive_int,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_PORT, default=DEFAULT_PORT): cv.port,
}
)
def setup_platform(
hass: HomeAssistant,
config: ConfigType,
add_entities: AddEntitiesCallback,
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up the Clementine platform."""
host = config[CONF_HOST]
port = config[CONF_PORT]
token = config.get(CONF_ACCESS_TOKEN)
client = ClementineRemote(host, port, token, reconnect=True)
add_entities([ClementineDevice(client, config[CONF_NAME])])
class ClementineDevice(MediaPlayerEntity):
"""Representation of Clementine Player."""
_attr_media_content_type = MediaType.MUSIC
_attr_supported_features = (
MediaPlayerEntityFeature.PAUSE
| MediaPlayerEntityFeature.VOLUME_STEP
| MediaPlayerEntityFeature.PREVIOUS_TRACK
| MediaPlayerEntityFeature.VOLUME_SET
| MediaPlayerEntityFeature.NEXT_TRACK
| MediaPlayerEntityFeature.SELECT_SOURCE
| MediaPlayerEntityFeature.PLAY
)
_attr_volume_step = 0.04
def __init__(self, client, name):
"""Initialize the Clementine device."""
self._client = client
self._attr_name = name
def update(self) -> None:
"""Retrieve the latest data from the Clementine Player."""
try:
client = self._client
if client.state == "Playing":
self._attr_state = MediaPlayerState.PLAYING
elif client.state == "Paused":
self._attr_state = MediaPlayerState.PAUSED
elif client.state == "Disconnected":
self._attr_state = MediaPlayerState.OFF
else:
self._attr_state = MediaPlayerState.PAUSED
if client.last_update and (time.time() - client.last_update > 40):
self._attr_state = MediaPlayerState.OFF
volume = float(client.volume) if client.volume else 0.0
self._attr_volume_level = volume / 100.0
if client.active_playlist_id in client.playlists:
self._attr_source = client.playlists[client.active_playlist_id]["name"]
else:
self._attr_source = "Unknown"
self._attr_source_list = [s["name"] for s in client.playlists.values()]
if client.current_track:
self._attr_media_title = client.current_track["title"]
self._attr_media_artist = client.current_track["track_artist"]
self._attr_media_album_name = client.current_track["track_album"]
self._attr_media_image_hash = client.current_track["track_id"]
else:
self._attr_media_image_hash = None
except Exception:
self._attr_state = MediaPlayerState.OFF
raise
@override
def select_source(self, source: str) -> None:
"""Select input source."""
client = self._client
sources = [s for s in client.playlists.values() if s["name"] == source]
if len(sources) == 1:
client.change_song(sources[0]["id"], 0)
@override
async def async_get_media_image(self) -> tuple[bytes | None, str | None]:
"""Fetch media image of current playing image."""
if self._client.current_track:
image = bytes(self._client.current_track["art"])
return (image, "image/png")
return None, None
@override
def mute_volume(self, mute: bool) -> None:
"""Send mute command."""
self._client.set_volume(0)
@override
def set_volume_level(self, volume: float) -> None:
"""Set volume level."""
self._client.set_volume(int(100 * volume))
def media_play_pause(self) -> None:
"""Simulate play pause media player."""
if self.state == MediaPlayerState.PLAYING:
self.media_pause()
else:
self.media_play()
@override
def media_play(self) -> None:
"""Send play command."""
self._attr_state = MediaPlayerState.PLAYING
self._client.play()
@override
def media_pause(self) -> None:
"""Send media pause command to media player."""
self._attr_state = MediaPlayerState.PAUSED
self._client.pause()
@override
def media_next_track(self) -> None:
"""Send next track command."""
self._client.next()
@override
def media_previous_track(self) -> None:
"""Send the previous track command."""
self._client.previous()
+11 -12
View File
@@ -13,12 +13,11 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
UnitOfDensity,
UnitOfElectricCurrent,
UnitOfEnergy,
UnitOfPower,
UnitOfRatio,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant
@@ -117,7 +116,7 @@ DESCRIPTIONS: dict[CompitParameter, SensorEntityDescription] = {
device_class=SensorDeviceClass.BATTERY,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
),
CompitParameter.BOILER_TEMPERATURE: SensorEntityDescription(
key=CompitParameter.BOILER_TEMPERATURE.value,
@@ -204,14 +203,14 @@ DESCRIPTIONS: dict[CompitParameter, SensorEntityDescription] = {
device_class=SensorDeviceClass.CO2,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
),
CompitParameter.CO2_PERCENT: SensorEntityDescription(
key=CompitParameter.CO2_PERCENT.value,
translation_key="co2_percent",
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
),
CompitParameter.COLLECTOR_POWER: SensorEntityDescription(
key=CompitParameter.COLLECTOR_POWER.value,
@@ -290,7 +289,7 @@ DESCRIPTIONS: dict[CompitParameter, SensorEntityDescription] = {
translation_key="fuel_level",
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
),
CompitParameter.HEATING1_TARGET_TEMPERATURE: SensorEntityDescription(
key=CompitParameter.HEATING1_TARGET_TEMPERATURE.value,
@@ -333,7 +332,7 @@ DESCRIPTIONS: dict[CompitParameter, SensorEntityDescription] = {
device_class=SensorDeviceClass.HUMIDITY,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
),
CompitParameter.LOWER_SOURCE_TEMPERATURE: SensorEntityDescription(
key=CompitParameter.LOWER_SOURCE_TEMPERATURE.value,
@@ -401,14 +400,14 @@ DESCRIPTIONS: dict[CompitParameter, SensorEntityDescription] = {
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
device_class=SensorDeviceClass.PM1,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
),
CompitParameter.PM4_LEVEL_MEASURED: SensorEntityDescription(
key=CompitParameter.PM4_LEVEL_MEASURED.value,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
device_class=SensorDeviceClass.PM4,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
),
CompitParameter.PM10_LEVEL: SensorEntityDescription(
key=CompitParameter.PM10_LEVEL.value,
@@ -422,7 +421,7 @@ DESCRIPTIONS: dict[CompitParameter, SensorEntityDescription] = {
key=CompitParameter.PM10_MEASURED.value,
device_class=SensorDeviceClass.PM10,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
),
CompitParameter.PM25_LEVEL: SensorEntityDescription(
key=CompitParameter.PM25_LEVEL.value,
@@ -436,7 +435,7 @@ DESCRIPTIONS: dict[CompitParameter, SensorEntityDescription] = {
key=CompitParameter.PM25_MEASURED.value,
device_class=SensorDeviceClass.PM25,
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
),
CompitParameter.PROTECTION_TEMPERATURE: SensorEntityDescription(
key=CompitParameter.PROTECTION_TEMPERATURE.value,
+21 -4
View File
@@ -8,6 +8,7 @@ from homeassistant.helpers.automation import DomainSpec
from homeassistant.helpers.trigger import (
ENTITY_STATE_TRIGGER_SCHEMA,
EntityTriggerBase,
NotTriggeredReasonReporter,
Trigger,
)
@@ -30,7 +31,11 @@ class CounterBaseIntegerTrigger(EntityTriggerBase):
_schema = ENTITY_STATE_TRIGGER_SCHEMA
@override
def is_valid_state(self, state: State) -> bool:
def is_valid_state(
self,
state: State,
report_not_triggered: NotTriggeredReasonReporter,
) -> bool:
"""Check if the new state is valid."""
return _is_integer_state(state)
@@ -63,7 +68,11 @@ class CounterMaxReachedTrigger(CounterValueBaseTrigger):
"""Trigger for when a counter reaches its maximum value."""
@override
def is_valid_state(self, state: State) -> bool:
def is_valid_state(
self,
state: State,
report_not_triggered: NotTriggeredReasonReporter,
) -> bool:
"""Check if the new state matches the expected state(s)."""
if (max_value := state.attributes.get(CONF_MAXIMUM)) is None:
return False
@@ -74,7 +83,11 @@ class CounterMinReachedTrigger(CounterValueBaseTrigger):
"""Trigger for when a counter reaches its minimum value."""
@override
def is_valid_state(self, state: State) -> bool:
def is_valid_state(
self,
state: State,
report_not_triggered: NotTriggeredReasonReporter,
) -> bool:
"""Check if the new state matches the expected state(s)."""
if (min_value := state.attributes.get(CONF_MINIMUM)) is None:
return False
@@ -85,7 +98,11 @@ class CounterResetTrigger(CounterValueBaseTrigger):
"""Trigger for reset of counter entities."""
@override
def is_valid_state(self, state: State) -> bool:
def is_valid_state(
self,
state: State,
report_not_triggered: NotTriggeredReasonReporter,
) -> bool:
"""Check if the new state matches the expected state(s)."""
if (init_state := state.attributes.get(CONF_INITIAL)) is None:
return False
+10 -2
View File
@@ -5,7 +5,11 @@ from typing import override
from homeassistant.const import STATE_OFF, STATE_ON
from homeassistant.core import HomeAssistant, State
from homeassistant.helpers.trigger import EntityTriggerBase, Trigger
from homeassistant.helpers.trigger import (
EntityTriggerBase,
NotTriggeredReasonReporter,
Trigger,
)
from .const import ATTR_IS_CLOSED, DOMAIN, CoverDeviceClass
from .models import CoverDomainSpec
@@ -24,7 +28,11 @@ class CoverTriggerBase(EntityTriggerBase):
return state.state
@override
def is_valid_state(self, state: State) -> bool:
def is_valid_state(
self,
state: State,
report_not_triggered: NotTriggeredReasonReporter,
) -> bool:
"""Check if the state matches the target cover state."""
domain_spec = self._domain_specs[state.domain]
return self._get_value(state) == domain_spec.target_value
+12 -14
View File
@@ -35,15 +35,13 @@ from homeassistant.components.sensor import (
from homeassistant.const import (
ATTR_TEMPERATURE,
ATTR_VOLTAGE,
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_BILLION,
CONCENTRATION_PARTS_PER_MILLION,
LIGHT_LUX,
PERCENTAGE,
EntityCategory,
UnitOfDensity,
UnitOfEnergy,
UnitOfPower,
UnitOfPressure,
UnitOfRatio,
UnitOfTemperature,
UnitOfTime,
)
@@ -138,7 +136,7 @@ ENTITY_DESCRIPTIONS: tuple[DeconzSensorDescription, ...] = (
name_suffix="PPB",
old_unique_id_suffix="ppb",
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_BILLION,
),
DeconzSensorDescription[AirQuality](
key="air_quality_formaldehyde",
@@ -149,7 +147,7 @@ ENTITY_DESCRIPTIONS: tuple[DeconzSensorDescription, ...] = (
name_suffix="CH2O",
device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
),
DeconzSensorDescription[AirQuality](
key="air_quality_co2",
@@ -160,7 +158,7 @@ ENTITY_DESCRIPTIONS: tuple[DeconzSensorDescription, ...] = (
name_suffix="CO2",
device_class=SensorDeviceClass.CO2,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
),
DeconzSensorDescription[AirQuality](
key="air_quality_pm2_5",
@@ -171,7 +169,7 @@ ENTITY_DESCRIPTIONS: tuple[DeconzSensorDescription, ...] = (
name_suffix="PM25",
device_class=SensorDeviceClass.PM25,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
),
DeconzSensorDescription[CarbonDioxide](
key="carbon_dioxide",
@@ -181,7 +179,7 @@ ENTITY_DESCRIPTIONS: tuple[DeconzSensorDescription, ...] = (
instance_check=CarbonDioxide,
device_class=SensorDeviceClass.CO2,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_BILLION,
),
DeconzSensorDescription[Consumption](
key="consumption",
@@ -210,7 +208,7 @@ ENTITY_DESCRIPTIONS: tuple[DeconzSensorDescription, ...] = (
instance_check=Formaldehyde,
device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_BILLION,
),
DeconzSensorDescription[GenericStatus](
key="status",
@@ -227,7 +225,7 @@ ENTITY_DESCRIPTIONS: tuple[DeconzSensorDescription, ...] = (
instance_check=Humidity,
device_class=SensorDeviceClass.HUMIDITY,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
suggested_display_precision=1,
),
DeconzSensorDescription[LightLevel](
@@ -248,7 +246,7 @@ ENTITY_DESCRIPTIONS: tuple[DeconzSensorDescription, ...] = (
instance_check=Moisture,
device_class=SensorDeviceClass.MOISTURE,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
suggested_display_precision=1,
),
DeconzSensorDescription[ParticulateMatter](
@@ -260,7 +258,7 @@ ENTITY_DESCRIPTIONS: tuple[DeconzSensorDescription, ...] = (
name_suffix="PM25",
device_class=SensorDeviceClass.PM25,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
),
DeconzSensorDescription[Power](
key="power",
@@ -310,7 +308,7 @@ ENTITY_DESCRIPTIONS: tuple[DeconzSensorDescription, ...] = (
old_unique_id_suffix="battery",
device_class=SensorDeviceClass.BATTERY,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
entity_category=EntityCategory.DIAGNOSTIC,
),
DeconzSensorDescription[SensorResources](
+6 -7
View File
@@ -12,11 +12,10 @@ from homeassistant.components.sensor import (
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
EntityCategory,
UnitOfEnergy,
UnitOfPower,
UnitOfRatio,
UnitOfTemperature,
UnitOfVolume,
)
@@ -52,7 +51,7 @@ async def async_setup_entry(
12,
SensorDeviceClass.BATTERY,
SensorStateClass.MEASUREMENT,
PERCENTAGE,
UnitOfRatio.PERCENTAGE,
entity_category=EntityCategory.DIAGNOSTIC,
entity_name="Battery",
),
@@ -63,7 +62,7 @@ async def async_setup_entry(
54,
SensorDeviceClass.HUMIDITY,
SensorStateClass.MEASUREMENT,
PERCENTAGE,
UnitOfRatio.PERCENTAGE,
),
DemoSensor(
"sensor_3",
@@ -72,7 +71,7 @@ async def async_setup_entry(
54,
SensorDeviceClass.CO,
SensorStateClass.MEASUREMENT,
CONCENTRATION_PARTS_PER_MILLION,
UnitOfRatio.PARTS_PER_MILLION,
),
DemoSensor(
"sensor_4",
@@ -81,7 +80,7 @@ async def async_setup_entry(
54,
SensorDeviceClass.CO2,
SensorStateClass.MEASUREMENT,
CONCENTRATION_PARTS_PER_MILLION,
UnitOfRatio.PARTS_PER_MILLION,
),
DemoSensor(
"battery_4",
@@ -90,7 +89,7 @@ async def async_setup_entry(
99,
SensorDeviceClass.BATTERY,
SensorStateClass.MEASUREMENT,
PERCENTAGE,
UnitOfRatio.PERCENTAGE,
entity_category=EntityCategory.DIAGNOSTIC,
entity_name="Battery",
),
+10 -2
View File
@@ -10,7 +10,11 @@ from homeassistant.components.event import (
)
from homeassistant.core import HomeAssistant, State
from homeassistant.helpers.automation import DomainSpec
from homeassistant.helpers.trigger import StatelessEntityTriggerBase, Trigger
from homeassistant.helpers.trigger import (
NotTriggeredReasonReporter,
StatelessEntityTriggerBase,
Trigger,
)
class DoorbellRangTrigger(StatelessEntityTriggerBase):
@@ -19,7 +23,11 @@ class DoorbellRangTrigger(StatelessEntityTriggerBase):
_domain_specs = {EVENT_DOMAIN: DomainSpec(device_class=EventDeviceClass.DOORBELL)}
@override
def is_valid_state(self, state: State) -> bool:
def is_valid_state(
self,
state: State,
report_not_triggered: NotTriggeredReasonReporter,
) -> bool:
"""Check if the event type is ring."""
return state.attributes.get(ATTR_EVENT_TYPE) == DoorbellEventType.RING
@@ -12,11 +12,10 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
TEMPERATURE,
EntityCategory,
UnitOfPressure,
UnitOfRatio,
UnitOfTemperature,
UnitOfVolume,
UnitOfVolumeFlowRate,
@@ -141,7 +140,7 @@ SENSORS: list[DROPSensorEntityDescription] = [
DROPSensorEntityDescription(
key=BATTERY,
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
suggested_display_precision=0,
value_fn=lambda device: device.drop_api.battery(),
state_class=SensorStateClass.MEASUREMENT,
@@ -158,7 +157,7 @@ SENSORS: list[DROPSensorEntityDescription] = [
DROPSensorEntityDescription(
key=INLET_TDS,
translation_key=INLET_TDS,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
value_fn=lambda device: device.drop_api.inlet_tds(),
@@ -166,7 +165,7 @@ SENSORS: list[DROPSensorEntityDescription] = [
DROPSensorEntityDescription(
key=OUTLET_TDS,
translation_key=OUTLET_TDS,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=0,
value_fn=lambda device: device.drop_api.outlet_tds(),
@@ -174,7 +173,7 @@ SENSORS: list[DROPSensorEntityDescription] = [
DROPSensorEntityDescription(
key=CARTRIDGE_1_LIFE,
translation_key=CARTRIDGE_1_LIFE,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
suggested_display_precision=0,
@@ -183,7 +182,7 @@ SENSORS: list[DROPSensorEntityDescription] = [
DROPSensorEntityDescription(
key=CARTRIDGE_2_LIFE,
translation_key=CARTRIDGE_2_LIFE,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
suggested_display_precision=0,
@@ -192,7 +191,7 @@ SENSORS: list[DROPSensorEntityDescription] = [
DROPSensorEntityDescription(
key=CARTRIDGE_3_LIFE,
translation_key=CARTRIDGE_3_LIFE,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
suggested_display_precision=0,
+4 -9
View File
@@ -11,12 +11,7 @@ from homeassistant.components.sensor import (
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
UnitOfTemperature,
)
from homeassistant.const import UnitOfDensity, UnitOfRatio, UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
@@ -42,14 +37,14 @@ SENSOR_TYPES: tuple[EcobeeSensorEntityDescription, ...] = (
),
EcobeeSensorEntityDescription(
key="humidity",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
device_class=SensorDeviceClass.HUMIDITY,
state_class=SensorStateClass.MEASUREMENT,
runtime_key=None,
),
EcobeeSensorEntityDescription(
key="co2PPM",
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
device_class=SensorDeviceClass.CO2,
state_class=SensorStateClass.MEASUREMENT,
runtime_key="actualCO2",
@@ -57,7 +52,7 @@ SENSOR_TYPES: tuple[EcobeeSensorEntityDescription, ...] = (
EcobeeSensorEntityDescription(
key="vocPPM",
device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
runtime_key="actualVOC",
),
+5 -6
View File
@@ -9,17 +9,16 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_MILLION,
CONF_URL,
PERCENTAGE,
UnitOfApparentPower,
UnitOfDensity,
UnitOfElectricCurrent,
UnitOfElectricPotential,
UnitOfEnergy,
UnitOfFrequency,
UnitOfPower,
UnitOfPressure,
UnitOfRatio,
UnitOfSoundPressure,
UnitOfSpeed,
UnitOfTemperature,
@@ -158,19 +157,19 @@ SENSORS: dict[str | None, SensorEntityDescription] = {
"μg/m³": SensorEntityDescription(
key="concentration|microgram_per_cubic_meter",
translation_key="concentration",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
),
"ppm": SensorEntityDescription(
key="concentration|microgram_parts_per_million",
translation_key="concentration",
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
),
"%": SensorEntityDescription(
key="percent",
translation_key="percent",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
}
+3 -8
View File
@@ -8,12 +8,7 @@ from homeassistant.components.sensor import (
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
UnitOfPressure,
UnitOfTemperature,
)
from homeassistant.const import UnitOfPressure, UnitOfRatio, UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
@@ -26,7 +21,7 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription(
device_class=SensorDeviceClass.CO2,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
key="co2",
suggested_display_precision=0,
),
@@ -40,7 +35,7 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription(
device_class=SensorDeviceClass.HUMIDITY,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
key="humidity",
suggested_display_precision=1,
),
+6 -1
View File
@@ -10,6 +10,7 @@ from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.automation import DomainSpec
from homeassistant.helpers.trigger import (
ENTITY_STATE_TRIGGER_SCHEMA,
NotTriggeredReasonReporter,
StatelessEntityTriggerBase,
Trigger,
TriggerConfig,
@@ -42,7 +43,11 @@ class EventReceivedTrigger(StatelessEntityTriggerBase):
self._event_types = set(self._options[CONF_EVENT_TYPE])
@override
def is_valid_state(self, state: State) -> bool:
def is_valid_state(
self,
state: State,
report_not_triggered: NotTriggeredReasonReporter,
) -> bool:
"""Check if the event type matches one of the configured types."""
return state.attributes.get(ATTR_EVENT_TYPE) in self._event_types
+4 -5
View File
@@ -13,12 +13,11 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_PARTS_PER_MILLION,
LIGHT_LUX,
PERCENTAGE,
Platform,
UnitOfEnergy,
UnitOfPower,
UnitOfRatio,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant
@@ -39,20 +38,20 @@ MAIN_SENSOR_TYPES: dict[str, SensorEntityDescription] = {
"com.fibaro.smokeSensor": SensorEntityDescription(
key="com.fibaro.smokeSensor",
name="Smoke",
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
icon="mdi:fire",
),
"CO2": SensorEntityDescription(
key="CO2",
name="CO2",
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
device_class=SensorDeviceClass.CO2,
state_class=SensorStateClass.MEASUREMENT,
),
"com.fibaro.humiditySensor": SensorEntityDescription(
key="com.fibaro.humiditySensor",
name="Humidity",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
device_class=SensorDeviceClass.HUMIDITY,
state_class=SensorStateClass.MEASUREMENT,
),
+7 -9
View File
@@ -16,12 +16,10 @@ from homeassistant.components.sensor import (
)
from homeassistant.const import (
ATTR_TEMPERATURE,
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_BILLION,
CONCENTRATION_PARTS_PER_MILLION,
CONF_TOKEN,
CONF_USERNAME,
PERCENTAGE,
UnitOfDensity,
UnitOfRatio,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant
@@ -44,7 +42,7 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription(
key="pm",
name=ATTR_PM2_5,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
icon="mdi:cloud",
),
SensorEntityDescription(
@@ -56,25 +54,25 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription(
key="hum",
name=ATTR_HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
icon="mdi:water-percent",
),
SensorEntityDescription(
key="co2",
name=ATTR_CARBON_DIOXIDE,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
icon="mdi:molecule-co2",
),
SensorEntityDescription(
key="voc",
name=ATTR_VOLATILE_ORGANIC_COMPOUNDS,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_BILLION,
icon="mdi:cloud",
),
SensorEntityDescription(
key="allpollu",
name=ATTR_FOOBOT_INDEX,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
icon="mdi:percent",
),
)
+3 -8
View File
@@ -13,12 +13,7 @@ from homeassistant.components.sensor import (
SensorStateClass,
StateType,
)
from homeassistant.const import (
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
UnitOfTemperature,
UnitOfVolumeFlowRate,
)
from homeassistant.const import UnitOfRatio, UnitOfTemperature, UnitOfVolumeFlowRate
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
@@ -54,14 +49,14 @@ _T2 = FreshrSensorEntityDescription(
_CO2 = FreshrSensorEntityDescription(
key="co2",
device_class=SensorDeviceClass.CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda r: r.co2,
)
_HUM = FreshrSensorEntityDescription(
key="hum",
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda r: r.hum,
)
@@ -14,11 +14,7 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.config_entries import ConfigSubentry
from homeassistant.const import (
CONCENTRATION_PARTS_PER_MILLION,
CONF_LATITUDE,
CONF_LONGITUDE,
)
from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE, UnitOfRatio
from homeassistant.core import HomeAssistant
from homeassistant.helpers.device_registry import DeviceEntryType, DeviceInfo
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
@@ -125,7 +121,7 @@ AIR_QUALITY_SENSOR_TYPES: tuple[AirQualitySensorEntityDescription, ...] = (
native_unit_of_measurement_fn=lambda x: x.pollutants.co.concentration.units,
exists_fn=lambda x: "co" in {p.code for p in x.pollutants},
value_fn=lambda x: x.pollutants.co.concentration.value,
suggested_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
suggested_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
),
AirQualitySensorEntityDescription(
key="nh3",
+6 -7
View File
@@ -19,10 +19,9 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
UnitOfDensity,
UnitOfRatio,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant
@@ -44,13 +43,13 @@ SENSOR_DESCRIPTIONS = {
(DeviceClass.HUMIDITY, Units.PERCENTAGE): SensorEntityDescription(
key=f"{DeviceClass.HUMIDITY}_{Units.PERCENTAGE}",
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
(DeviceClass.BATTERY, Units.PERCENTAGE): SensorEntityDescription(
key=f"{DeviceClass.BATTERY}_{Units.PERCENTAGE}",
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
(
@@ -69,13 +68,13 @@ SENSOR_DESCRIPTIONS = {
): SensorEntityDescription(
key=f"{DeviceClass.PM25}_{Units.CONCENTRATION_MICROGRAMS_PER_CUBIC_METER}",
device_class=SensorDeviceClass.PM25,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
),
(DeviceClass.CO2, Units.CONCENTRATION_PARTS_PER_MILLION): SensorEntityDescription(
key=f"{DeviceClass.CO2}_{Units.CONCENTRATION_PARTS_PER_MILLION}",
device_class=SensorDeviceClass.CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
),
}
+13 -14
View File
@@ -12,11 +12,9 @@ from homeassistant.components.sensor import (
)
from homeassistant.const import (
ATTR_NAME,
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_MILLION,
DEGREE,
LIGHT_LUX,
PERCENTAGE,
UnitOfDensity,
UnitOfElectricCurrent,
UnitOfElectricPotential,
UnitOfEnergy,
@@ -24,6 +22,7 @@ from homeassistant.const import (
UnitOfPower,
UnitOfPrecipitationDepth,
UnitOfPressure,
UnitOfRatio,
UnitOfSpeed,
UnitOfTemperature,
UnitOfVolume,
@@ -57,7 +56,7 @@ HM_STATE_HA_CAST = {
SENSOR_DESCRIPTIONS: dict[str, SensorEntityDescription] = {
"HUMIDITY": SensorEntityDescription(
key="HUMIDITY",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
device_class=SensorDeviceClass.HUMIDITY,
state_class=SensorStateClass.MEASUREMENT,
),
@@ -129,7 +128,7 @@ SENSOR_DESCRIPTIONS: dict[str, SensorEntityDescription] = {
),
"CONCENTRATION": SensorEntityDescription(
key="CONCENTRATION",
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
device_class=SensorDeviceClass.CO2,
state_class=SensorStateClass.MEASUREMENT,
),
@@ -204,15 +203,15 @@ SENSOR_DESCRIPTIONS: dict[str, SensorEntityDescription] = {
),
"VALVE_STATE": SensorEntityDescription(
key="VALVE_STATE",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
),
"CARRIER_SENSE_LEVEL": SensorEntityDescription(
key="CARRIER_SENSE_LEVEL",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
),
"DUTY_CYCLE_LEVEL": SensorEntityDescription(
key="DUTY_CYCLE_LEVEL",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
),
"BRIGHTNESS": SensorEntityDescription(
key="BRIGHTNESS",
@@ -221,37 +220,37 @@ SENSOR_DESCRIPTIONS: dict[str, SensorEntityDescription] = {
),
"MASS_CONCENTRATION_PM_1": SensorEntityDescription(
key="MASS_CONCENTRATION_PM_1",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM1,
state_class=SensorStateClass.MEASUREMENT,
),
"MASS_CONCENTRATION_PM_2_5": SensorEntityDescription(
key="MASS_CONCENTRATION_PM_2_5",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM25,
state_class=SensorStateClass.MEASUREMENT,
),
"MASS_CONCENTRATION_PM_10": SensorEntityDescription(
key="MASS_CONCENTRATION_PM_10",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM10,
state_class=SensorStateClass.MEASUREMENT,
),
"MASS_CONCENTRATION_PM_1_24H_AVERAGE": SensorEntityDescription(
key="MASS_CONCENTRATION_PM_1_24H_AVERAGE",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM1,
state_class=SensorStateClass.MEASUREMENT,
),
"MASS_CONCENTRATION_PM_2_5_24H_AVERAGE": SensorEntityDescription(
key="MASS_CONCENTRATION_PM_2_5_24H_AVERAGE",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM25,
state_class=SensorStateClass.MEASUREMENT,
),
"MASS_CONCENTRATION_PM_10_24H_AVERAGE": SensorEntityDescription(
key="MASS_CONCENTRATION_PM_10_24H_AVERAGE",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM10,
state_class=SensorStateClass.MEASUREMENT,
),
@@ -9,5 +9,5 @@
"iot_class": "local_polling",
"loggers": ["aioimmich"],
"quality_scale": "platinum",
"requirements": ["aioimmich==0.15.0"]
"requirements": ["aioimmich==0.15.1"]
}
+4 -5
View File
@@ -17,10 +17,9 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
UnitOfPressure,
UnitOfRatio,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant
@@ -39,13 +38,13 @@ SENSOR_DESCRIPTIONS = {
(DeviceClass.HUMIDITY, Units.PERCENTAGE): SensorEntityDescription(
key=f"{DeviceClass.HUMIDITY}_{Units.PERCENTAGE}",
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
(DeviceClass.BATTERY, Units.PERCENTAGE): SensorEntityDescription(
key=f"{DeviceClass.BATTERY}_{Units.PERCENTAGE}",
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
(
@@ -61,7 +60,7 @@ SENSOR_DESCRIPTIONS = {
(DeviceClass.CO2, Units.CONCENTRATION_PARTS_PER_MILLION): SensorEntityDescription(
key=f"{DeviceClass.CO2}_{Units.CONCENTRATION_PARTS_PER_MILLION}",
device_class=SensorDeviceClass.CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
),
(DeviceClass.PRESSURE, Units.PRESSURE_HPA): SensorEntityDescription(
@@ -12,11 +12,7 @@ from homeassistant.components.sensor import (
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
UnitOfTemperature,
)
from homeassistant.const import UnitOfRatio, UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
@@ -46,14 +42,14 @@ INTELLICLIMA_SENSORS: tuple[IntelliClimaSensorEntityDescription, ...] = (
key="humidity",
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
value_fn=lambda device_data: float(device_data.rh),
),
IntelliClimaSensorEntityDescription(
key="voc",
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS_PARTS,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
value_fn=lambda device_data: float(device_data.voc_state),
),
)
+3 -4
View File
@@ -14,15 +14,14 @@ from homeassistant.components.sensor import (
SensorEntity,
)
from homeassistant.const import (
CONCENTRATION_PARTS_PER_MILLION,
CONF_DOMAIN,
CONF_ENTITIES,
CONF_SOURCE,
CONF_UNIT_OF_MEASUREMENT,
LIGHT_LUX,
PERCENTAGE,
UnitOfElectricCurrent,
UnitOfElectricPotential,
UnitOfRatio,
UnitOfSpeed,
UnitOfTemperature,
)
@@ -67,8 +66,8 @@ UNIT_OF_MEASUREMENT_MAPPING = {
pypck.lcn_defs.VarUnit.METERPERSECOND: UnitOfSpeed.METERS_PER_SECOND,
pypck.lcn_defs.VarUnit.VOLT: UnitOfElectricPotential.VOLT,
pypck.lcn_defs.VarUnit.AMPERE: UnitOfElectricCurrent.AMPERE,
pypck.lcn_defs.VarUnit.PPM: CONCENTRATION_PARTS_PER_MILLION,
pypck.lcn_defs.VarUnit.PERCENT: PERCENTAGE,
pypck.lcn_defs.VarUnit.PPM: UnitOfRatio.PARTS_PER_MILLION,
pypck.lcn_defs.VarUnit.PERCENT: UnitOfRatio.PERCENTAGE,
}
+3 -3
View File
@@ -15,7 +15,7 @@ from homeassistant.components.number import (
NumberMode,
)
from homeassistant.components.script import scripts_with_entity
from homeassistant.const import PERCENTAGE, UnitOfTemperature, UnitOfTime
from homeassistant.const import UnitOfRatio, UnitOfTemperature, UnitOfTime
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
@@ -41,13 +41,13 @@ NUMBER_DESC: dict[ThinQProperty, NumberEntityDescription] = {
),
ThinQProperty.LIGHT_STATUS: NumberEntityDescription(
key=ThinQProperty.LIGHT_STATUS,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
translation_key=ThinQProperty.LIGHT_STATUS,
),
ThinQProperty.TARGET_HUMIDITY: NumberEntityDescription(
key=ThinQProperty.TARGET_HUMIDITY,
device_class=NumberDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
translation_key=ThinQProperty.TARGET_HUMIDITY,
),
ThinQProperty.TARGET_TEMPERATURE: NumberEntityDescription(
+14 -14
View File
@@ -18,9 +18,9 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
PERCENTAGE,
UnitOfDensity,
UnitOfEnergy,
UnitOfRatio,
UnitOfTemperature,
UnitOfTime,
)
@@ -37,25 +37,25 @@ AIR_QUALITY_SENSOR_DESC: dict[ThinQProperty, SensorEntityDescription] = {
ThinQProperty.PM1: SensorEntityDescription(
key=ThinQProperty.PM1,
device_class=SensorDeviceClass.PM1,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
),
ThinQProperty.PM2: SensorEntityDescription(
key=ThinQProperty.PM2,
device_class=SensorDeviceClass.PM25,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
),
ThinQProperty.PM10: SensorEntityDescription(
key=ThinQProperty.PM10,
device_class=SensorDeviceClass.PM10,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
),
ThinQProperty.HUMIDITY: SensorEntityDescription(
key=ThinQProperty.HUMIDITY,
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
ThinQProperty.MONITORING_ENABLED: SensorEntityDescription(
@@ -106,12 +106,12 @@ FILTER_INFO_SENSOR_DESC: dict[ThinQProperty, SensorEntityDescription] = {
),
ThinQProperty.FILTER_REMAIN_PERCENT: SensorEntityDescription(
key=ThinQProperty.FILTER_REMAIN_PERCENT,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
translation_key=ThinQProperty.FILTER_LIFETIME,
),
ThinQProperty.TOP_FILTER_REMAIN_PERCENT: SensorEntityDescription(
key=ThinQProperty.TOP_FILTER_REMAIN_PERCENT,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
translation_key=ThinQProperty.TOP_FILTER_REMAIN_PERCENT,
),
}
@@ -119,7 +119,7 @@ HUMIDITY_SENSOR_DESC: dict[ThinQProperty, SensorEntityDescription] = {
ThinQProperty.CURRENT_HUMIDITY: SensorEntityDescription(
key=ThinQProperty.CURRENT_HUMIDITY,
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
)
}
@@ -215,7 +215,7 @@ RECIPE_SENSOR_DESC: dict[ThinQProperty, SensorEntityDescription] = {
),
ThinQProperty.BEER_REMAIN: SensorEntityDescription(
key=ThinQProperty.BEER_REMAIN,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
translation_key=ThinQProperty.BEER_REMAIN,
),
}
@@ -227,7 +227,7 @@ REFRIGERATION_SENSOR_DESC: dict[ThinQProperty, SensorEntityDescription] = {
),
ThinQProperty.FRESH_AIR_FILTER_REMAIN_PERCENT: SensorEntityDescription(
key=ThinQProperty.FRESH_AIR_FILTER_REMAIN_PERCENT,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
translation_key=ThinQProperty.FRESH_AIR_FILTER,
),
}
@@ -318,17 +318,17 @@ WATER_FILTER_INFO_SENSOR_DESC: dict[ThinQProperty, SensorEntityDescription] = {
),
ThinQProperty.WATER_FILTER_1_REMAIN_PERCENT: SensorEntityDescription(
key=ThinQProperty.WATER_FILTER_1_REMAIN_PERCENT,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
translation_key=ThinQProperty.WATER_FILTER_1_REMAIN_PERCENT,
),
ThinQProperty.WATER_FILTER_2_REMAIN_PERCENT: SensorEntityDescription(
key=ThinQProperty.WATER_FILTER_2_REMAIN_PERCENT,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
translation_key=ThinQProperty.WATER_FILTER_2_REMAIN_PERCENT,
),
ThinQProperty.WATER_FILTER_3_REMAIN_PERCENT: SensorEntityDescription(
key=ThinQProperty.WATER_FILTER_3_REMAIN_PERCENT,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
translation_key=ThinQProperty.WATER_FILTER_3_REMAIN_PERCENT,
),
}
+5 -5
View File
@@ -11,10 +11,10 @@ from homeassistant.components.sensor import (
from homeassistant.const import (
ATTR_LATITUDE,
ATTR_LONGITUDE,
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONF_SHOW_ON_MAP,
PERCENTAGE,
UnitOfDensity,
UnitOfPressure,
UnitOfRatio,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant
@@ -36,7 +36,7 @@ SENSORS: tuple[SensorEntityDescription, ...] = (
),
SensorEntityDescription(
key="humidity",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
device_class=SensorDeviceClass.HUMIDITY,
state_class=SensorStateClass.MEASUREMENT,
),
@@ -55,13 +55,13 @@ SENSORS: tuple[SensorEntityDescription, ...] = (
),
SensorEntityDescription(
key="P1",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM10,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
key="P2",
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM25,
state_class=SensorStateClass.MEASUREMENT,
),
+3 -3
View File
@@ -16,10 +16,10 @@ from homeassistant.components.number import (
NumberMode,
)
from homeassistant.const import (
PERCENTAGE,
EntityCategory,
Platform,
UnitOfLength,
UnitOfRatio,
UnitOfTemperature,
UnitOfTime,
)
@@ -354,7 +354,7 @@ DISCOVERY_SCHEMAS = [
platform=Platform.NUMBER,
entity_description=MatterNumberEntityDescription(
key="pump_setpoint",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
translation_key="pump_setpoint",
native_max_value=100,
native_min_value=0.5,
@@ -516,7 +516,7 @@ DISCOVERY_SCHEMAS = [
entity_description=MatterRangeNumberEntityDescription(
key="speaker_setpoint",
translation_key="speaker_setpoint",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
command=lambda value: clusters.LevelControl.Commands.MoveToLevel(
level=int(value)
),
@@ -9,6 +9,7 @@ from homeassistant.helpers.trigger import (
EntityNumericalStateCrossedThresholdTriggerBase,
EntityNumericalStateTriggerBase,
EntityTriggerBase,
NotTriggeredReasonReporter,
Trigger,
make_entity_transition_trigger,
)
@@ -60,7 +61,11 @@ class _MediaPlayerMutedStateTriggerBase(EntityTriggerBase):
return self.is_muted(from_state) != self.is_muted(to_state)
@override
def is_valid_state(self, state: State) -> bool:
def is_valid_state(
self,
state: State,
report_not_triggered: NotTriggeredReasonReporter,
) -> bool:
"""Check if the new state matches the expected state."""
if not self._has_volume_attributes(state):
return False
+3 -9
View File
@@ -10,13 +10,7 @@ from homeassistant.components.sensor import (
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_PARTS_PER_MILLION,
LIGHT_LUX,
PERCENTAGE,
UnitOfPower,
UnitOfTemperature,
)
from homeassistant.const import LIGHT_LUX, UnitOfPower, UnitOfRatio, UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
@@ -42,14 +36,14 @@ SENSOR_TYPES = {
14: SensorEntityDescription(
device_class=SensorDeviceClass.CO2,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
key="carbon_dioxide",
suggested_display_precision=1,
),
16: SensorEntityDescription(
device_class=SensorDeviceClass.HUMIDITY,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
key="humidity",
suggested_display_precision=1,
),
@@ -1,344 +0,0 @@
"""Support for Microsoft face recognition."""
import asyncio
from collections.abc import Coroutine
import json
import logging
from typing import Any, override
import aiohttp
from aiohttp.hdrs import CONTENT_TYPE
import voluptuous as vol
from homeassistant.components import camera
from homeassistant.const import ATTR_NAME, CONF_API_KEY, CONF_TIMEOUT, CONTENT_TYPE_JSON
from homeassistant.core import HomeAssistant, ServiceCall
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.entity import Entity
from homeassistant.helpers.entity_component import EntityComponent
from homeassistant.helpers.typing import ConfigType
from homeassistant.util import slugify
from homeassistant.util.hass_dict import HassKey
_LOGGER = logging.getLogger(__name__)
ATTR_CAMERA_ENTITY = "camera_entity"
ATTR_GROUP = "group"
ATTR_PERSON = "person"
CONF_AZURE_REGION = "azure_region"
DEFAULT_TIMEOUT = 10
DOMAIN = "microsoft_face"
DATA_MICROSOFT_FACE: HassKey[MicrosoftFace] = HassKey(DOMAIN)
FACE_API_URL = "api.cognitive.microsoft.com/face/v1.0/{0}"
SERVICE_CREATE_GROUP = "create_group"
SERVICE_CREATE_PERSON = "create_person"
SERVICE_DELETE_GROUP = "delete_group"
SERVICE_DELETE_PERSON = "delete_person"
SERVICE_FACE_PERSON = "face_person"
SERVICE_TRAIN_GROUP = "train_group"
CONFIG_SCHEMA = vol.Schema(
{
DOMAIN: vol.Schema(
{
vol.Required(CONF_API_KEY): cv.string,
vol.Optional(CONF_AZURE_REGION, default="westus"): cv.string,
vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): cv.positive_int,
}
)
},
extra=vol.ALLOW_EXTRA,
)
SCHEMA_GROUP_SERVICE = vol.Schema({vol.Required(ATTR_NAME): cv.string})
SCHEMA_PERSON_SERVICE = SCHEMA_GROUP_SERVICE.extend(
{vol.Required(ATTR_GROUP): cv.slugify}
)
SCHEMA_FACE_SERVICE = vol.Schema(
{
vol.Required(ATTR_PERSON): cv.string,
vol.Required(ATTR_GROUP): cv.slugify,
vol.Required(ATTR_CAMERA_ENTITY): cv.entity_id,
}
)
SCHEMA_TRAIN_SERVICE = vol.Schema({vol.Required(ATTR_GROUP): cv.slugify})
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
"""Set up Microsoft Face."""
component = EntityComponent[MicrosoftFaceGroupEntity](
logging.getLogger(__name__), DOMAIN, hass
)
entities: dict[str, MicrosoftFaceGroupEntity] = {}
domain_config: dict[str, Any] = config[DOMAIN]
azure_region: str = domain_config[CONF_AZURE_REGION]
api_key: str = domain_config[CONF_API_KEY]
timeout: int = domain_config[CONF_TIMEOUT]
face = MicrosoftFace(
hass,
azure_region,
api_key,
timeout,
component,
entities,
)
try:
# read exists group/person from cloud and create entities
await face.update_store()
except HomeAssistantError as err:
_LOGGER.error("Can't load data from face api: %s", err)
return False
hass.data[DATA_MICROSOFT_FACE] = face
async def async_create_group(service: ServiceCall) -> None:
"""Create a new person group."""
name = service.data[ATTR_NAME]
g_id = slugify(name)
try:
await face.call_api("put", f"persongroups/{g_id}", {"name": name})
face.store[g_id] = {}
old_entity = entities.pop(g_id, None)
if old_entity:
await component.async_remove_entity(old_entity.entity_id)
entities[g_id] = MicrosoftFaceGroupEntity(face, g_id, name)
await component.async_add_entities([entities[g_id]])
# pylint: disable-next=home-assistant-action-swallowed-exception
except HomeAssistantError as err:
_LOGGER.error("Can't create group '%s' with error: %s", g_id, err)
hass.services.async_register(
DOMAIN, SERVICE_CREATE_GROUP, async_create_group, schema=SCHEMA_GROUP_SERVICE
)
async def async_delete_group(service: ServiceCall) -> None:
"""Delete a person group."""
g_id = slugify(service.data[ATTR_NAME])
try:
await face.call_api("delete", f"persongroups/{g_id}")
face.store.pop(g_id)
entity = entities.pop(g_id)
await component.async_remove_entity(entity.entity_id)
# pylint: disable-next=home-assistant-action-swallowed-exception
except HomeAssistantError as err:
_LOGGER.error("Can't delete group '%s' with error: %s", g_id, err)
hass.services.async_register(
DOMAIN, SERVICE_DELETE_GROUP, async_delete_group, schema=SCHEMA_GROUP_SERVICE
)
async def async_train_group(service: ServiceCall) -> None:
"""Train a person group."""
g_id = service.data[ATTR_GROUP]
try:
await face.call_api("post", f"persongroups/{g_id}/train")
# pylint: disable-next=home-assistant-action-swallowed-exception
except HomeAssistantError as err:
_LOGGER.error("Can't train group '%s' with error: %s", g_id, err)
hass.services.async_register(
DOMAIN, SERVICE_TRAIN_GROUP, async_train_group, schema=SCHEMA_TRAIN_SERVICE
)
async def async_create_person(service: ServiceCall) -> None:
"""Create a person in a group."""
name = service.data[ATTR_NAME]
g_id = service.data[ATTR_GROUP]
try:
user_data = await face.call_api(
"post", f"persongroups/{g_id}/persons", {"name": name}
)
face.store[g_id][name] = user_data["personId"]
entities[g_id].async_write_ha_state()
# pylint: disable-next=home-assistant-action-swallowed-exception
except HomeAssistantError as err:
_LOGGER.error("Can't create person '%s' with error: %s", name, err)
hass.services.async_register(
DOMAIN, SERVICE_CREATE_PERSON, async_create_person, schema=SCHEMA_PERSON_SERVICE
)
async def async_delete_person(service: ServiceCall) -> None:
"""Delete a person in a group."""
name = service.data[ATTR_NAME]
g_id = service.data[ATTR_GROUP]
p_id = face.store[g_id].get(name)
try:
await face.call_api("delete", f"persongroups/{g_id}/persons/{p_id}")
face.store[g_id].pop(name)
entities[g_id].async_write_ha_state()
# pylint: disable-next=home-assistant-action-swallowed-exception
except HomeAssistantError as err:
_LOGGER.error("Can't delete person '%s' with error: %s", p_id, err)
hass.services.async_register(
DOMAIN, SERVICE_DELETE_PERSON, async_delete_person, schema=SCHEMA_PERSON_SERVICE
)
async def async_face_person(service: ServiceCall) -> None:
"""Add a new face picture to a person."""
g_id = service.data[ATTR_GROUP]
p_id = face.store[g_id].get(service.data[ATTR_PERSON])
camera_entity = service.data[ATTR_CAMERA_ENTITY]
try:
image = await camera.async_get_image(hass, camera_entity)
await face.call_api(
"post",
f"persongroups/{g_id}/persons/{p_id}/persistedFaces",
image.content,
binary=True,
)
# pylint: disable-next=home-assistant-action-swallowed-exception
except HomeAssistantError as err:
_LOGGER.error(
"Can't add an image of a person '%s' with error: %s", p_id, err
)
hass.services.async_register(
DOMAIN, SERVICE_FACE_PERSON, async_face_person, schema=SCHEMA_FACE_SERVICE
)
return True
class MicrosoftFaceGroupEntity(Entity):
"""Person-Group state/data Entity."""
_attr_should_poll = False
def __init__(self, api: MicrosoftFace, g_id: str, name: str) -> None:
"""Initialize person/group entity."""
self.entity_id = f"{DOMAIN}.{g_id}"
self._api = api
self._id = g_id
self._attr_name = name
@property
@override
def state(self) -> int:
"""Return the state of the entity."""
return len(self._api.store[self._id])
@property
@override
def extra_state_attributes(self) -> dict[str, Any]:
"""Return device specific state attributes."""
return dict(self._api.store[self._id])
class MicrosoftFace:
"""Microsoft Face api for Home Assistant."""
def __init__(
self,
hass: HomeAssistant,
server_loc: str,
api_key: str,
timeout: int,
component: EntityComponent[MicrosoftFaceGroupEntity],
entities: dict[str, MicrosoftFaceGroupEntity],
) -> None:
"""Initialize Microsoft Face api."""
self.hass = hass
self.websession = async_get_clientsession(hass)
self.timeout = timeout
self._api_key = api_key
self._server_url = f"https://{server_loc}.{FACE_API_URL}"
self._store: dict[str, dict[str, Any]] = {}
self._component = component
self._entities = entities
@property
def store(self) -> dict[str, dict[str, Any]]:
"""Store group/person data and IDs."""
return self._store
async def update_store(self) -> None:
"""Load all group/person data into local store."""
groups = await self.call_api("get", "persongroups")
remove_tasks: list[Coroutine[Any, Any, None]] = []
new_entities = []
for group in groups:
g_id = group["personGroupId"]
self._store[g_id] = {}
old_entity = self._entities.pop(g_id, None)
if old_entity:
remove_tasks.append(
self._component.async_remove_entity(old_entity.entity_id)
)
self._entities[g_id] = MicrosoftFaceGroupEntity(self, g_id, group["name"])
new_entities.append(self._entities[g_id])
persons = await self.call_api("get", f"persongroups/{g_id}/persons")
for person in persons:
self._store[g_id][person["name"]] = person["personId"]
if remove_tasks:
await asyncio.gather(*remove_tasks)
await self._component.async_add_entities(new_entities)
async def call_api(self, method, function, data=None, binary=False, params=None):
"""Make an api call."""
headers = {"Ocp-Apim-Subscription-Key": self._api_key}
url = self._server_url.format(function)
payload = None
if binary:
headers[CONTENT_TYPE] = "application/octet-stream"
payload = data
else:
headers[CONTENT_TYPE] = CONTENT_TYPE_JSON
if data is not None:
payload = json.dumps(data).encode()
else:
payload = None
try:
async with asyncio.timeout(self.timeout):
response = await self.websession.request(
method, url, data=payload, headers=headers, params=params
)
answer = await response.json()
_LOGGER.debug("Read from microsoft face api: %s", answer)
if response.status < 300:
return answer
_LOGGER.warning(
"Error %d microsoft face api %s", response.status, response.url
)
raise HomeAssistantError(answer["error"]["message"])
except aiohttp.ClientError:
_LOGGER.warning("Can't connect to microsoft face api")
except TimeoutError:
_LOGGER.warning("Timeout from microsoft face api %s", response.url)
raise HomeAssistantError("Network error on microsoft face api.")
@@ -1,22 +0,0 @@
{
"services": {
"create_group": {
"service": "mdi:account-multiple-plus"
},
"create_person": {
"service": "mdi:account-plus"
},
"delete_group": {
"service": "mdi:account-multiple-remove"
},
"delete_person": {
"service": "mdi:account-remove"
},
"face_person": {
"service": "mdi:face-man"
},
"train_group": {
"service": "mdi:account-multiple-check"
}
}
}
@@ -1,9 +0,0 @@
{
"domain": "microsoft_face",
"name": "Microsoft Face",
"codeowners": [],
"dependencies": ["camera"],
"documentation": "https://www.home-assistant.io/integrations/microsoft_face",
"iot_class": "cloud_push",
"quality_scale": "legacy"
}
@@ -1,62 +0,0 @@
create_group:
fields:
name:
required: true
example: family
selector:
text:
create_person:
fields:
group:
required: true
example: family
selector:
text:
name:
required: true
example: Hans
selector:
text:
delete_group:
fields:
name:
required: true
example: family
selector:
text:
delete_person:
fields:
group:
required: true
example: family
selector:
text:
name:
required: true
example: Hans
selector:
text:
face_person:
fields:
camera_entity:
required: true
example: camera.door
selector:
text:
group:
required: true
example: family
selector:
text:
person:
required: true
example: Hans
selector:
text:
train_group:
fields:
group:
required: true
example: family
selector:
text:
@@ -1,80 +0,0 @@
{
"services": {
"create_group": {
"description": "Creates a new person group.",
"fields": {
"name": {
"description": "Name of the group.",
"name": "[%key:common::config_flow::data::name%]"
}
},
"name": "Create group"
},
"create_person": {
"description": "Creates a new person in the group.",
"fields": {
"group": {
"description": "Name of the group.",
"name": "Group"
},
"name": {
"description": "Name of the person.",
"name": "[%key:common::config_flow::data::name%]"
}
},
"name": "Create person"
},
"delete_group": {
"description": "Deletes a new person group.",
"fields": {
"name": {
"description": "Name of the group.",
"name": "[%key:common::config_flow::data::name%]"
}
},
"name": "Delete group"
},
"delete_person": {
"description": "Deletes a person in the group.",
"fields": {
"group": {
"description": "Name of the group.",
"name": "Group"
},
"name": {
"description": "[%key:component::microsoft_face::services::create_person::fields::name::description%]",
"name": "[%key:common::config_flow::data::name%]"
}
},
"name": "Delete person"
},
"face_person": {
"description": "Adds a new picture to a person.",
"fields": {
"camera_entity": {
"description": "Camera to take a picture.",
"name": "Camera entity"
},
"group": {
"description": "Name of the group.",
"name": "Group"
},
"person": {
"description": "[%key:component::microsoft_face::services::create_person::fields::name::description%]",
"name": "Person"
}
},
"name": "Face person"
},
"train_group": {
"description": "Trains a person group.",
"fields": {
"group": {
"description": "Name of the group.",
"name": "Group"
}
},
"name": "Train group"
}
}
}
@@ -1 +0,0 @@
"""The microsoft_face_detect component."""
@@ -1,125 +0,0 @@
"""Component that will help set the Microsoft face detect processing."""
import logging
from typing import TYPE_CHECKING, override
import voluptuous as vol
from homeassistant.components.image_processing import (
ATTR_AGE,
ATTR_GENDER,
ATTR_GLASSES,
PLATFORM_SCHEMA as IMAGE_PROCESSING_PLATFORM_SCHEMA,
FaceInformation,
ImageProcessingFaceEntity,
)
from homeassistant.components.microsoft_face import DATA_MICROSOFT_FACE, MicrosoftFace
from homeassistant.const import CONF_ENTITY_ID, CONF_NAME, CONF_SOURCE
from homeassistant.core import HomeAssistant, split_entity_id
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
_LOGGER = logging.getLogger(__name__)
SUPPORTED_ATTRIBUTES = [ATTR_AGE, ATTR_GENDER, ATTR_GLASSES]
CONF_ATTRIBUTES = "attributes"
DEFAULT_ATTRIBUTES = [ATTR_AGE, ATTR_GENDER]
def validate_attributes(list_attributes):
"""Validate face attributes."""
for attr in list_attributes:
if attr not in SUPPORTED_ATTRIBUTES:
raise vol.Invalid(f"Invalid attribute {attr}")
return list_attributes
PLATFORM_SCHEMA = IMAGE_PROCESSING_PLATFORM_SCHEMA.extend(
{
vol.Optional(CONF_ATTRIBUTES, default=DEFAULT_ATTRIBUTES): vol.All(
cv.ensure_list, validate_attributes
)
}
)
async def async_setup_platform(
hass: HomeAssistant,
config: ConfigType,
async_add_entities: AddEntitiesCallback,
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up the Microsoft Face detection platform."""
api = hass.data[DATA_MICROSOFT_FACE]
attributes: list[str] = config[CONF_ATTRIBUTES]
source: list[dict[str, str]] = config[CONF_SOURCE]
async_add_entities(
MicrosoftFaceDetectEntity(
camera[CONF_ENTITY_ID], api, attributes, camera.get(CONF_NAME)
)
for camera in source
)
class MicrosoftFaceDetectEntity(ImageProcessingFaceEntity):
"""Microsoft Face API entity for identify."""
def __init__(
self,
camera_entity: str,
api: MicrosoftFace,
attributes: list[str],
name: str | None,
) -> None:
"""Initialize Microsoft Face."""
super().__init__()
self._api = api
self._attr_camera_entity = camera_entity
self._attributes = attributes
if name:
self._attr_name = name
else:
self._attr_name = f"MicrosoftFace {split_entity_id(camera_entity)[1]}"
@override
async def async_process_image(self, image: bytes) -> None:
"""Process image.
This method is a coroutine.
"""
face_data = None
try:
face_data = await self._api.call_api(
"post",
"detect",
image,
binary=True,
params={"returnFaceAttributes": ",".join(self._attributes)},
)
except HomeAssistantError as err:
_LOGGER.error("Can't process image on microsoft face: %s", err)
return
if not face_data:
face_data = []
faces: list[FaceInformation] = []
for face in face_data:
face_attr = FaceInformation()
for attr in self._attributes:
if TYPE_CHECKING:
assert attr in SUPPORTED_ATTRIBUTES
if attr in face["faceAttributes"]:
face_attr[attr] = face["faceAttributes"][attr] # type: ignore[literal-required]
if face_attr:
faces.append(face_attr)
self.async_process_faces(faces, len(face_data))
@@ -1,9 +0,0 @@
{
"domain": "microsoft_face_detect",
"name": "Microsoft Face Detect",
"codeowners": [],
"dependencies": ["microsoft_face"],
"documentation": "https://www.home-assistant.io/integrations/microsoft_face_detect",
"iot_class": "cloud_push",
"quality_scale": "legacy"
}
@@ -1 +0,0 @@
"""The microsoft_face_identify component."""
@@ -1,121 +0,0 @@
"""Component that will help set the Microsoft face for verify processing."""
import logging
from typing import override
import voluptuous as vol
from homeassistant.components.image_processing import (
ATTR_CONFIDENCE,
CONF_CONFIDENCE,
PLATFORM_SCHEMA as IMAGE_PROCESSING_PLATFORM_SCHEMA,
FaceInformation,
ImageProcessingFaceEntity,
)
from homeassistant.components.microsoft_face import DATA_MICROSOFT_FACE, MicrosoftFace
from homeassistant.const import ATTR_NAME, CONF_ENTITY_ID, CONF_NAME, CONF_SOURCE
from homeassistant.core import HomeAssistant, split_entity_id
from homeassistant.exceptions import HomeAssistantError
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
_LOGGER = logging.getLogger(__name__)
CONF_GROUP = "group"
PLATFORM_SCHEMA = IMAGE_PROCESSING_PLATFORM_SCHEMA.extend(
{vol.Required(CONF_GROUP): cv.slugify}
)
async def async_setup_platform(
hass: HomeAssistant,
config: ConfigType,
async_add_entities: AddEntitiesCallback,
discovery_info: DiscoveryInfoType | None = None,
) -> None:
"""Set up the Microsoft Face identify platform."""
api = hass.data[DATA_MICROSOFT_FACE]
face_group: str = config[CONF_GROUP]
confidence: float = config[CONF_CONFIDENCE]
source: list[dict[str, str]] = config[CONF_SOURCE]
async_add_entities(
MicrosoftFaceIdentifyEntity(
camera[CONF_ENTITY_ID],
api,
face_group,
confidence,
camera.get(CONF_NAME),
)
for camera in source
)
class MicrosoftFaceIdentifyEntity(ImageProcessingFaceEntity):
"""Representation of the Microsoft Face API entity for identify."""
def __init__(
self,
camera_entity: str,
api: MicrosoftFace,
face_group: str,
confidence: float,
name: str | None,
) -> None:
"""Initialize the Microsoft Face API."""
super().__init__()
self._api = api
self._attr_camera_entity = camera_entity
self._attr_confidence = confidence
self._face_group = face_group
if name:
self._attr_name = name
else:
self._attr_name = f"MicrosoftFace {split_entity_id(camera_entity)[1]}"
@override
async def async_process_image(self, image: bytes) -> None:
"""Process image.
This method is a coroutine.
"""
detect = []
try:
face_data = await self._api.call_api("post", "detect", image, binary=True)
if face_data:
face_ids = [data["faceId"] for data in face_data]
detect = await self._api.call_api(
"post",
"identify",
{"faceIds": face_ids, "personGroupId": self._face_group},
)
except HomeAssistantError as err:
_LOGGER.error("Can't process image on Microsoft face: %s", err)
return
# Parse data
known_faces: list[FaceInformation] = []
total = 0
for face in detect:
total += 1
if not face["candidates"]:
continue
data = face["candidates"][0]
name = ""
for s_name, s_id in self._api.store[self._face_group].items():
if data["personId"] == s_id:
name = s_name
break
known_faces.append(
{ATTR_NAME: name, ATTR_CONFIDENCE: data["confidence"] * 100}
)
self.async_process_faces(known_faces, total)
@@ -1,9 +0,0 @@
{
"domain": "microsoft_face_identify",
"name": "Microsoft Face Identify",
"codeowners": [],
"dependencies": ["microsoft_face"],
"documentation": "https://www.home-assistant.io/integrations/microsoft_face_identify",
"iot_class": "cloud_push",
"quality_scale": "legacy"
}
+10 -4
View File
@@ -114,20 +114,26 @@ class MieleDataUpdateCoordinator(DataUpdateCoordinator[MieleCoordinatorData]):
async def callback_update_data(self, devices_json: dict[str, dict]) -> None:
"""Handle data update from the API."""
devices = {
updated_devices = {
device_id: MieleDevice(device) for device_id, device in devices_json.items()
}
self.async_set_updated_data(
MieleCoordinatorData(devices=devices, actions=self.data.actions)
MieleCoordinatorData(
devices={**self.data.devices, **updated_devices},
actions=self.data.actions,
)
)
async def callback_update_actions(self, actions_json: dict[str, dict]) -> None:
"""Handle data update from the API."""
actions = {
updated_actions = {
device_id: MieleAction(action) for device_id, action in actions_json.items()
}
self.async_set_updated_data(
MieleCoordinatorData(devices=self.data.devices, actions=actions)
MieleCoordinatorData(
devices=self.data.devices,
actions={**self.data.actions, **updated_actions},
)
)
+8 -10
View File
@@ -11,12 +11,10 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_PARTS_PER_BILLION,
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
EntityCategory,
UnitOfEnergy,
UnitOfPower,
UnitOfRatio,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant, callback
@@ -65,7 +63,7 @@ HEATER_SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription(
key="control_signal",
translation_key="control_signal",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
)
@@ -80,26 +78,26 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription(
key=HUMIDITY,
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
key=BATTERY,
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
),
SensorEntityDescription(
key=ECO2,
device_class=SensorDeviceClass.CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
translation_key="estimated_co2",
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
key=TVOC,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_BILLION,
translation_key="tvoc",
state_class=SensorStateClass.MEASUREMENT,
),
@@ -109,7 +107,7 @@ LOCAL_SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription(
key="control_signal",
translation_key="control_signal",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
@@ -133,7 +131,7 @@ SOCKET_SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription(
key=HUMIDITY,
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
*HEATER_SENSOR_TYPES,
@@ -4,7 +4,7 @@ from dataclasses import dataclass
import logging
from pymonoprice import Monoprice, get_monoprice
from serial import SerialException
from serialx import SerialException
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import CONF_PORT, Platform
@@ -4,7 +4,7 @@ import logging
from typing import Any, override
from pymonoprice import get_monoprice
from serial import SerialException
from serialx import SerialException
import voluptuous as vol
from homeassistant.config_entries import (
@@ -7,5 +7,5 @@
"integration_type": "hub",
"iot_class": "local_polling",
"loggers": ["pymonoprice"],
"requirements": ["pymonoprice==0.5"]
"requirements": ["pymonoprice==0.6.1"]
}
@@ -3,7 +3,7 @@
import logging
from typing import override
from serial import SerialException
from serialx import SerialException
from homeassistant import core
from homeassistant.components.media_player import (
+7 -8
View File
@@ -19,13 +19,12 @@ from homeassistant.components.sensor import (
from homeassistant.const import (
ATTR_LATITUDE,
ATTR_LONGITUDE,
CONCENTRATION_PARTS_PER_MILLION,
DEGREE,
PERCENTAGE,
EntityCategory,
UnitOfPower,
UnitOfPrecipitationDepth,
UnitOfPressure,
UnitOfRatio,
UnitOfSoundPressure,
UnitOfSpeed,
UnitOfTemperature,
@@ -163,7 +162,7 @@ NETATMO_WEATHER_SENSOR_DESCRIPTIONS: Final[list[NetatmoSensorEntityDescription]]
NetatmoSensorEntityDescription(
key="co2",
netatmo_name="co2",
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.CO2,
),
@@ -190,7 +189,7 @@ NETATMO_WEATHER_SENSOR_DESCRIPTIONS: Final[list[NetatmoSensorEntityDescription]]
NetatmoSensorEntityDescription(
key="humidity",
netatmo_name="humidity",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.HUMIDITY,
),
@@ -221,7 +220,7 @@ NETATMO_WEATHER_SENSOR_DESCRIPTIONS: Final[list[NetatmoSensorEntityDescription]]
key="battery_percent",
netatmo_name="battery",
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.BATTERY,
),
@@ -336,7 +335,7 @@ PUBLIC_WEATHER_STATION_TYPES: tuple[
),
NetatmoPublicWeatherSensorEntityDescription(
key="humidity",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.HUMIDITY,
value_fn=lambda area: area.get_latest_humidities(),
@@ -408,7 +407,7 @@ NETATMO_CLIMATE_BATTERY_SENSOR_DESCRIPTIONS: Final[
key="battery",
netatmo_name="battery",
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.BATTERY,
)
@@ -419,7 +418,7 @@ NETATMO_OPENING_SENSOR_DESCRIPTIONS: Final[list[NetatmoSensorEntityDescription]]
key="battery",
netatmo_name="battery",
entity_category=EntityCategory.DIAGNOSTIC,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.BATTERY,
is_sticky=True,
@@ -80,6 +80,7 @@ class NetgearRouterEntity(Entity):
manufacturer="Netgear",
name=router.device_name,
model=router.model,
serial_number=router.serial_number,
sw_version=router.firmware_version,
hw_version=router.hardware_version,
configuration_url=configuration_url,
@@ -25,6 +25,8 @@ from .const import (
DOMAIN,
OVERRIDE_TYPE_CONSTANT,
OVERRIDE_TYPE_NOW,
SERIAL_LENGTH,
SERIAL_PREFIX_LENGTH,
)
DATA_NOBO_HUB_IMPL = "nobo_hub_flow_implementation"
@@ -49,7 +51,20 @@ class NoboHubConfigFlow(ConfigFlow, domain=DOMAIN):
) -> ConfigFlowResult:
"""Handle the initial step."""
if self._discovered_hubs is None:
self._discovered_hubs = dict(await nobo.async_discover_hubs())
# Wait 5s — real-world gaps up to ~4s have been observed.
discovered = dict(await nobo.async_discover_hubs(autodiscover_wait=5.0))
# Hide hubs that already have a config entry. Include matching on IP
# as serial prefix is not unique.
configured = {
(entry.data[CONF_IP_ADDRESS], entry.unique_id[:SERIAL_PREFIX_LENGTH])
for entry in self._async_current_entries(include_ignore=False)
if entry.unique_id
}
self._discovered_hubs = {
ip: prefix
for ip, prefix in discovered.items()
if (ip, prefix) not in configured
}
if not self._discovered_hubs:
# No hubs auto discovered
@@ -227,7 +242,7 @@ class NoboHubConfigFlow(ConfigFlow, domain=DOMAIN):
)
async def _test_connection(self, serial: str, ip_address: str) -> str:
if not len(serial) == 12 or not serial.isdigit():
if len(serial) != SERIAL_LENGTH or not serial.isdigit():
raise NoboHubConnectError("invalid_serial")
try:
socket.inet_aton(ip_address)
@@ -9,6 +9,11 @@ CONF_OVERRIDE_TYPE = "override_type"
OVERRIDE_TYPE_CONSTANT = "constant"
OVERRIDE_TYPE_NOW = "now"
# Hub serial: 9-digit batch prefix + 3-digit per-hub suffix. Discovery
# broadcasts only the prefix; the user supplies the suffix.
SERIAL_PREFIX_LENGTH = 9
SERIAL_LENGTH = SERIAL_PREFIX_LENGTH + 3
NOBO_MANUFACTURER = "Glen Dimplex Nordic AS"
ATTR_HARDWARE_VERSION: Final = "hardware_version"
ATTR_SOFTWARE_VERSION: Final = "software_version"
@@ -64,11 +64,7 @@ rules:
docs-use-cases: todo
dynamic-devices: todo
entity-category: todo
entity-device-class:
status: todo
comment: >
Custom device class on global override select being dropped in
PR #170135.
entity-device-class: done
entity-disabled-by-default: todo
entity-translations: todo
exception-translations: todo
@@ -53,7 +53,6 @@ class NoboGlobalSelector(NoboBaseEntity, SelectEntity):
"""Global override selector for Nobø Ecohub."""
_attr_translation_key = "global_override"
_attr_device_class = "nobo_hub__override"
_modes = {
nobo.API.OVERRIDE_MODE_NORMAL: "none",
nobo.API.OVERRIDE_MODE_AWAY: "away",
+6 -7
View File
@@ -4,10 +4,9 @@ from typing import Any, override
from homeassistant.components.sensor import SensorDeviceClass, SensorEntity
from homeassistant.const import (
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
UnitOfElectricPotential,
UnitOfMass,
UnitOfRatio,
UnitOfTemperature,
UnitOfVolume,
)
@@ -139,7 +138,7 @@ class OmniLogicPumpSpeedSensor(OmnilogicSensor):
pump_speed = self.coordinator.data[self._item_id][self._state_key]
if pump_type == "VARIABLE":
self._attr_native_unit_of_measurement = PERCENTAGE
self._attr_native_unit_of_measurement = UnitOfRatio.PERCENTAGE
state = pump_speed
elif pump_type == "DUAL":
self._attr_native_unit_of_measurement = None
@@ -279,7 +278,7 @@ SENSOR_TYPES: dict[tuple[int, str], list[dict[str, Any]]] = {
"kind": "filter_pump_speed",
"device_class": None,
"icon": "mdi:speedometer",
"unit": PERCENTAGE,
"unit": UnitOfRatio.PERCENTAGE,
"guard_condition": [
{"Filter-Type": "FMT_SINGLE_SPEED"},
],
@@ -292,7 +291,7 @@ SENSOR_TYPES: dict[tuple[int, str], list[dict[str, Any]]] = {
"kind": "pump_speed",
"device_class": None,
"icon": "mdi:speedometer",
"unit": PERCENTAGE,
"unit": UnitOfRatio.PERCENTAGE,
"guard_condition": [
{"Type": "PMP_SINGLE_SPEED"},
],
@@ -305,7 +304,7 @@ SENSOR_TYPES: dict[tuple[int, str], list[dict[str, Any]]] = {
"kind": "chlorinator",
"device_class": None,
"icon": "mdi:gauge",
"unit": PERCENTAGE,
"unit": UnitOfRatio.PERCENTAGE,
"guard_condition": [
{
"Shared-Type": "BOW_SHARED_EQUIPMENT",
@@ -322,7 +321,7 @@ SENSOR_TYPES: dict[tuple[int, str], list[dict[str, Any]]] = {
"kind": "salt_level",
"device_class": None,
"icon": "mdi:gauge",
"unit": CONCENTRATION_PARTS_PER_MILLION,
"unit": UnitOfRatio.PARTS_PER_MILLION,
"guard_condition": [
{
"Shared-Type": "BOW_SHARED_EQUIPMENT",
@@ -9,10 +9,9 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
EntityCategory,
UnitOfElectricPotential,
UnitOfRatio,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant, callback
@@ -50,12 +49,12 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription(
key="tds",
translation_key="tds",
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
key="battery",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
device_class=SensorDeviceClass.BATTERY,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
@@ -63,7 +62,7 @@ SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription(
key="rssi",
translation_key="rssi",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
),
@@ -2,7 +2,6 @@
import asyncio
from collections.abc import Callable
import contextlib
from datetime import timedelta
from enum import IntEnum
import io
@@ -188,9 +187,7 @@ async def _async_upload_image(call: ServiceCall) -> None:
current = asyncio.current_task()
if (prev := entry.runtime_data.upload_task) is not None and not prev.done():
prev.cancel()
# pylint: disable-next=home-assistant-action-swallowed-exception
with contextlib.suppress(asyncio.CancelledError):
await prev
await asyncio.wait({prev})
entry.runtime_data.upload_task = current
try:
@@ -11,11 +11,11 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
DEGREE,
LIGHT_LUX,
PERCENTAGE,
UnitOfDensity,
UnitOfPressure,
UnitOfRatio,
UnitOfSpeed,
UnitOfTemperature,
)
@@ -44,21 +44,21 @@ SENSOR_DESCRIPTIONS: tuple[OpenSenseMapSensorEntityDescription, ...] = (
OpenSenseMapSensorEntityDescription(
key="pm2_5",
device_class=SensorDeviceClass.PM25,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.pm2_5,
),
OpenSenseMapSensorEntityDescription(
key="pm10",
device_class=SensorDeviceClass.PM10,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.pm10,
),
OpenSenseMapSensorEntityDescription(
key="pm1_0",
device_class=SensorDeviceClass.PM1,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.pm1_0,
),
@@ -72,7 +72,7 @@ SENSOR_DESCRIPTIONS: tuple[OpenSenseMapSensorEntityDescription, ...] = (
OpenSenseMapSensorEntityDescription(
key="humidity",
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.humidity,
),
@@ -9,12 +9,12 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
DEGREE,
PERCENTAGE,
UV_INDEX,
UnitOfDensity,
UnitOfLength,
UnitOfPressure,
UnitOfRatio,
UnitOfSpeed,
UnitOfTemperature,
UnitOfVolumetricFlux,
@@ -107,7 +107,7 @@ WEATHER_SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
),
SensorEntityDescription(
key=ATTR_API_HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
device_class=SensorDeviceClass.HUMIDITY,
state_class=SensorStateClass.MEASUREMENT,
),
@@ -121,7 +121,7 @@ WEATHER_SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
SensorEntityDescription(
key=ATTR_API_CLOUDS,
translation_key=ATTR_API_CLOUDS,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
@@ -174,43 +174,43 @@ AIRPOLLUTION_SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
),
SensorEntityDescription(
key=ATTR_API_AIRPOLLUTION_CO,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.CO,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_API_AIRPOLLUTION_NO,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.NITROGEN_MONOXIDE,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_API_AIRPOLLUTION_NO2,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.NITROGEN_DIOXIDE,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_API_AIRPOLLUTION_O3,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.OZONE,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_API_AIRPOLLUTION_SO2,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.SULPHUR_DIOXIDE,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_API_AIRPOLLUTION_PM2_5,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM25,
state_class=SensorStateClass.MEASUREMENT,
),
SensorEntityDescription(
key=ATTR_API_AIRPOLLUTION_PM10,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM10,
state_class=SensorStateClass.MEASUREMENT,
),
+5 -7
View File
@@ -13,11 +13,8 @@ from pyoverkiz.enums import (
)
from homeassistant.const import (
CONCENTRATION_PARTS_PER_BILLION,
CONCENTRATION_PARTS_PER_MILLION,
DEGREE,
LIGHT_LUX,
PERCENTAGE,
Platform,
UnitOfElectricCurrent,
UnitOfElectricPotential,
@@ -26,6 +23,7 @@ from homeassistant.const import (
UnitOfLength,
UnitOfPower,
UnitOfPressure,
UnitOfRatio,
UnitOfSpeed,
UnitOfTemperature,
UnitOfTime,
@@ -165,19 +163,19 @@ OVERKIZ_UNIT_TO_HA: dict[str, str] = {
),
MeasuredValueType.FOSSIL_ENERGY_IN_WH: UnitOfEnergy.WATT_HOUR,
MeasuredValueType.GRADIENT_IN_PERCENTAGE_PER_SECOND: (
f"{PERCENTAGE}/{UnitOfTime.SECONDS}"
f"{UnitOfRatio.PERCENTAGE}/{UnitOfTime.SECONDS}"
),
MeasuredValueType.LENGTH_IN_METER: UnitOfLength.METERS,
MeasuredValueType.LINEAR_SPEED_IN_METER_PER_SECOND: UnitOfSpeed.METERS_PER_SECOND,
MeasuredValueType.LUMINANCE_IN_LUX: LIGHT_LUX,
MeasuredValueType.PARTS_PER_BILLION: CONCENTRATION_PARTS_PER_BILLION,
MeasuredValueType.PARTS_PER_MILLION: CONCENTRATION_PARTS_PER_MILLION,
MeasuredValueType.PARTS_PER_BILLION: UnitOfRatio.PARTS_PER_BILLION,
MeasuredValueType.PARTS_PER_MILLION: UnitOfRatio.PARTS_PER_MILLION,
MeasuredValueType.PARTS_PER_QUADRILLION: "ppq",
MeasuredValueType.PARTS_PER_TRILLION: "ppt",
MeasuredValueType.POWER_PER_SQUARE_METER: UnitOfIrradiance.WATTS_PER_SQUARE_METER,
MeasuredValueType.PRESSURE_IN_HPA: UnitOfPressure.HPA,
MeasuredValueType.PRESSURE_IN_MILLI_BAR: UnitOfPressure.MBAR,
MeasuredValueType.RELATIVE_VALUE_IN_PERCENTAGE: PERCENTAGE,
MeasuredValueType.RELATIVE_VALUE_IN_PERCENTAGE: UnitOfRatio.PERCENTAGE,
MeasuredValueType.TEMPERATURE_IN_CELCIUS: UnitOfTemperature.CELSIUS,
MeasuredValueType.TEMPERATURE_IN_KELVIN: UnitOfTemperature.KELVIN,
MeasuredValueType.TIME_IN_SECOND: UnitOfTime.SECONDS,
@@ -14,7 +14,7 @@
"integration_type": "hub",
"iot_class": "local_polling",
"loggers": ["boto3", "botocore", "pyoverkiz", "s3transfer"],
"requirements": ["pyoverkiz[nexity]==2.0.2"],
"requirements": ["pyoverkiz[nexity]==2.0.3"],
"zeroconf": [
{
"name": "gateway*",
+4 -4
View File
@@ -9,9 +9,9 @@ from homeassistant.components.number import (
NumberEntityDescription,
)
from homeassistant.const import (
CONCENTRATION_PARTS_PER_MILLION,
EntityCategory,
UnitOfElectricPotential,
UnitOfRatio,
UnitOfTime,
)
from homeassistant.core import HomeAssistant
@@ -46,7 +46,7 @@ NUMBER_DESCRIPTIONS: tuple[NumberEntityDescription, ...] = (
key="cl_target",
translation_key="cl_target",
entity_category=EntityCategory.CONFIG,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
),
NumberEntityDescription(
key="ofa_ph_lower",
@@ -78,13 +78,13 @@ NUMBER_DESCRIPTIONS: tuple[NumberEntityDescription, ...] = (
key="ofa_cl_lower",
translation_key="ofa_cl_lower",
entity_category=EntityCategory.CONFIG,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
),
NumberEntityDescription(
key="ofa_cl_upper",
translation_key="ofa_cl_upper",
entity_category=EntityCategory.CONFIG,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
),
NumberEntityDescription(
key="time_off_ph_dosing",
+2 -2
View File
@@ -11,9 +11,9 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_PARTS_PER_MILLION,
EntityCategory,
UnitOfElectricPotential,
UnitOfRatio,
UnitOfTime,
)
from homeassistant.core import HomeAssistant
@@ -51,7 +51,7 @@ SENSOR_DESCRIPTIONS: tuple[PooldoseSensorEntityDescription, ...] = (
PooldoseSensorEntityDescription(
key="cl",
translation_key="cl",
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
),
PooldoseSensorEntityDescription(
key="flow_rate",
@@ -76,6 +76,7 @@ NODE_SENSORS: tuple[ProxmoxNodeBinarySensorEntityDescription, ...] = (
),
device_class=BinarySensorDeviceClass.PROBLEM,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
),
)
@@ -71,7 +71,7 @@ rules:
dynamic-devices: done
entity-category: done
entity-device-class: done
entity-disabled-by-default: todo
entity-disabled-by-default: done
entity-translations: done
exception-translations: done
icon-translations: done
@@ -71,6 +71,9 @@ NODE_SENSORS: tuple[ProxmoxNodeSensorEntityDescription, ...] = (
key="node_max_cpu",
translation_key="node_max_cpu",
value_fn=lambda data: data.node["maxcpu"],
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
),
ProxmoxNodeSensorEntityDescription(
key="node_disk",
@@ -82,6 +85,7 @@ NODE_SENSORS: tuple[ProxmoxNodeSensorEntityDescription, ...] = (
suggested_display_precision=1,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
),
ProxmoxNodeSensorEntityDescription(
key="node_max_disk",
@@ -93,6 +97,7 @@ NODE_SENSORS: tuple[ProxmoxNodeSensorEntityDescription, ...] = (
suggested_display_precision=1,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
),
ProxmoxNodeSensorEntityDescription(
key="node_memory",
@@ -104,6 +109,7 @@ NODE_SENSORS: tuple[ProxmoxNodeSensorEntityDescription, ...] = (
suggested_display_precision=1,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
),
ProxmoxNodeSensorEntityDescription(
key="node_max_memory",
@@ -152,6 +158,7 @@ NODE_SENSORS: tuple[ProxmoxNodeSensorEntityDescription, ...] = (
),
device_class=SensorDeviceClass.TIMESTAMP,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
),
ProxmoxNodeSensorEntityDescription(
key="node_backup_duration",
@@ -166,6 +173,7 @@ NODE_SENSORS: tuple[ProxmoxNodeSensorEntityDescription, ...] = (
suggested_unit_of_measurement=UnitOfTime.MINUTES,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
),
)
@@ -174,6 +182,9 @@ VM_SENSORS: tuple[ProxmoxVMSensorEntityDescription, ...] = (
key="vm_max_cpu",
translation_key="vm_max_cpu",
value_fn=lambda data: data["cpus"],
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
),
ProxmoxVMSensorEntityDescription(
key="vm_cpu",
@@ -194,6 +205,7 @@ VM_SENSORS: tuple[ProxmoxVMSensorEntityDescription, ...] = (
suggested_display_precision=1,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
),
ProxmoxVMSensorEntityDescription(
key="vm_max_memory",
@@ -235,6 +247,7 @@ VM_SENSORS: tuple[ProxmoxVMSensorEntityDescription, ...] = (
suggested_display_precision=1,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
),
ProxmoxVMSensorEntityDescription(
key="vm_max_disk",
@@ -246,6 +259,7 @@ VM_SENSORS: tuple[ProxmoxVMSensorEntityDescription, ...] = (
suggested_display_precision=1,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
),
ProxmoxVMSensorEntityDescription(
key="vm_status",
@@ -264,6 +278,7 @@ VM_SENSORS: tuple[ProxmoxVMSensorEntityDescription, ...] = (
suggested_display_precision=1,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.TOTAL_INCREASING,
entity_registry_enabled_default=False,
),
ProxmoxVMSensorEntityDescription(
key="vm_netout",
@@ -275,6 +290,7 @@ VM_SENSORS: tuple[ProxmoxVMSensorEntityDescription, ...] = (
suggested_display_precision=1,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.TOTAL_INCREASING,
entity_registry_enabled_default=False,
),
)
@@ -283,6 +299,9 @@ CONTAINER_SENSORS: tuple[ProxmoxContainerSensorEntityDescription, ...] = (
key="container_max_cpu",
translation_key="container_max_cpu",
value_fn=lambda data: data["cpus"],
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
),
ProxmoxContainerSensorEntityDescription(
key="container_cpu",
@@ -303,6 +322,7 @@ CONTAINER_SENSORS: tuple[ProxmoxContainerSensorEntityDescription, ...] = (
suggested_display_precision=1,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
),
ProxmoxContainerSensorEntityDescription(
key="container_max_memory",
@@ -344,6 +364,7 @@ CONTAINER_SENSORS: tuple[ProxmoxContainerSensorEntityDescription, ...] = (
suggested_display_precision=1,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
),
ProxmoxContainerSensorEntityDescription(
key="container_max_disk",
@@ -355,6 +376,7 @@ CONTAINER_SENSORS: tuple[ProxmoxContainerSensorEntityDescription, ...] = (
suggested_display_precision=1,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.MEASUREMENT,
entity_registry_enabled_default=False,
),
ProxmoxContainerSensorEntityDescription(
key="container_status",
@@ -373,6 +395,7 @@ CONTAINER_SENSORS: tuple[ProxmoxContainerSensorEntityDescription, ...] = (
suggested_display_precision=1,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.TOTAL_INCREASING,
entity_registry_enabled_default=False,
),
ProxmoxContainerSensorEntityDescription(
key="container_netout",
@@ -384,6 +407,7 @@ CONTAINER_SENSORS: tuple[ProxmoxContainerSensorEntityDescription, ...] = (
suggested_display_precision=1,
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.TOTAL_INCREASING,
entity_registry_enabled_default=False,
),
)
+6 -6
View File
@@ -13,11 +13,11 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
PERCENTAGE,
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
EntityCategory,
UnitOfDensity,
UnitOfPressure,
UnitOfRatio,
UnitOfTemperature,
UnitOfTime,
UnitOfVolume,
@@ -43,7 +43,7 @@ SENSOR_DESCRIPTIONS = [
PurpleAirSensorEntityDescription(
key="humidity",
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda sensor: sensor.humidity,
),
@@ -74,7 +74,7 @@ SENSOR_DESCRIPTIONS = [
PurpleAirSensorEntityDescription(
key="pm1.0_mass_concentration",
device_class=SensorDeviceClass.PM1,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda sensor: sensor.pm1_0,
),
@@ -89,7 +89,7 @@ SENSOR_DESCRIPTIONS = [
PurpleAirSensorEntityDescription(
key="pm10.0_mass_concentration",
device_class=SensorDeviceClass.PM10,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda sensor: sensor.pm10_0,
),
@@ -104,7 +104,7 @@ SENSOR_DESCRIPTIONS = [
PurpleAirSensorEntityDescription(
key="pm2.5_mass_concentration",
device_class=SensorDeviceClass.PM25,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda sensor: sensor.pm2_5,
),
+7 -8
View File
@@ -20,13 +20,12 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_MILLION,
LIGHT_LUX,
PERCENTAGE,
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
EntityCategory,
UnitOfDensity,
UnitOfPressure,
UnitOfRatio,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant
@@ -40,7 +39,7 @@ SENSOR_DESCRIPTIONS = {
(QingpingSensorDeviceClass.BATTERY, Units.PERCENTAGE): SensorEntityDescription(
key=f"{QingpingSensorDeviceClass.BATTERY}_{Units.PERCENTAGE}",
device_class=SensorDeviceClass.BATTERY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
entity_category=EntityCategory.DIAGNOSTIC,
),
@@ -50,13 +49,13 @@ SENSOR_DESCRIPTIONS = {
): SensorEntityDescription(
key=f"{QingpingSensorDeviceClass.CO2}_{Units.CONCENTRATION_PARTS_PER_MILLION}",
device_class=SensorDeviceClass.CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
),
(QingpingSensorDeviceClass.HUMIDITY, Units.PERCENTAGE): SensorEntityDescription(
key=f"{QingpingSensorDeviceClass.HUMIDITY}_{Units.PERCENTAGE}",
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
(QingpingSensorDeviceClass.ILLUMINANCE, Units.LIGHT_LUX): SensorEntityDescription(
@@ -71,7 +70,7 @@ SENSOR_DESCRIPTIONS = {
): SensorEntityDescription(
key=f"{QingpingSensorDeviceClass.PM10}_{Units.CONCENTRATION_MICROGRAMS_PER_CUBIC_METER}",
device_class=SensorDeviceClass.PM10,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
),
(
@@ -80,7 +79,7 @@ SENSOR_DESCRIPTIONS = {
): SensorEntityDescription(
key=f"{QingpingSensorDeviceClass.PM25}_{Units.CONCENTRATION_MICROGRAMS_PER_CUBIC_METER}",
device_class=SensorDeviceClass.PM25,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
),
(QingpingSensorDeviceClass.PRESSURE, Units.PRESSURE_MBAR): SensorEntityDescription(
+7 -8
View File
@@ -34,8 +34,7 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
UnitOfRatio,
UnitOfTemperature,
UnitOfTime,
UnitOfVolumeFlowRate,
@@ -78,7 +77,7 @@ SENSORS: tuple[RensonSensorEntityDescription, ...] = (
raw_format=True,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
),
RensonSensorEntityDescription(
key="AIR_FIELD",
@@ -86,7 +85,7 @@ SENSORS: tuple[RensonSensorEntityDescription, ...] = (
field=AIR_QUALITY_FIELD,
state_class=SensorStateClass.MEASUREMENT,
raw_format=True,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
),
RensonSensorEntityDescription(
key="CURRENT_LEVEL_FIELD",
@@ -145,7 +144,7 @@ SENSORS: tuple[RensonSensorEntityDescription, ...] = (
raw_format=False,
device_class=SensorDeviceClass.HUMIDITY,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
),
RensonSensorEntityDescription(
key="MANUAL_LEVEL_FIELD",
@@ -194,7 +193,7 @@ SENSORS: tuple[RensonSensorEntityDescription, ...] = (
translation_key="co2_threshold",
field=CO2_THRESHOLD_FIELD,
raw_format=False,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
entity_registry_enabled_default=False,
),
RensonSensorEntityDescription(
@@ -202,7 +201,7 @@ SENSORS: tuple[RensonSensorEntityDescription, ...] = (
translation_key="co2_hysteresis",
field=CO2_HYSTERESIS_FIELD,
raw_format=False,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
entity_registry_enabled_default=False,
),
RensonSensorEntityDescription(
@@ -221,7 +220,7 @@ SENSORS: tuple[RensonSensorEntityDescription, ...] = (
raw_format=False,
device_class=SensorDeviceClass.POWER_FACTOR,
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
),
)
@@ -20,7 +20,7 @@
"loggers": ["roborock"],
"quality_scale": "silver",
"requirements": [
"python-roborock==5.21.0",
"python-roborock==5.22.0",
"vacuum-map-parser-roborock==0.1.5"
]
}
+92 -3
View File
@@ -5,6 +5,8 @@ from dataclasses import dataclass
import logging
from typing import Any, override
from roborock.devices.traits.b01 import Q10PropertiesApi
from roborock.devices.traits.b01.q10 import DoNotDisturbTrait
from roborock.devices.traits.v1 import PropertiesApi
from roborock.devices.traits.v1.common import RoborockSwitchBase
from roborock.exceptions import RoborockException
@@ -19,12 +21,17 @@ from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .const import DOMAIN
from .coordinator import (
RoborockB01Q10UpdateCoordinator,
RoborockConfigEntry,
RoborockCoordinatorType,
RoborockDataUpdateCoordinator,
RoborockDataUpdateCoordinatorA01,
)
from .entity import RoborockCoordinatedEntityA01, RoborockEntityV1
from .entity import (
RoborockCoordinatedEntityA01,
RoborockCoordinatedEntityB01Q10,
RoborockEntityV1,
)
_LOGGER = logging.getLogger(__name__)
@@ -79,6 +86,13 @@ class RoborockSwitchDescriptionA01(SwitchEntityDescription):
data_protocol: RoborockDyadDataProtocol | RoborockZeoProtocol
@dataclass(frozen=True, kw_only=True)
class RoborockSwitchDescriptionQ10(SwitchEntityDescription):
"""Class to describe a Roborock Q10 switch entity."""
trait: Callable[[Q10PropertiesApi], DoNotDisturbTrait | None]
A01_SWITCH_DESCRIPTIONS: list[RoborockSwitchDescriptionA01] = [
RoborockSwitchDescriptionA01(
key="sound_setting",
@@ -89,6 +103,16 @@ A01_SWITCH_DESCRIPTIONS: list[RoborockSwitchDescriptionA01] = [
]
Q10_SWITCH_DESCRIPTIONS: list[RoborockSwitchDescriptionQ10] = [
RoborockSwitchDescriptionQ10(
key="do_not_disturb",
translation_key="dnd_switch",
entity_category=EntityCategory.CONFIG,
trait=lambda traits: traits.do_not_disturb,
)
]
async def async_setup_entry(
hass: HomeAssistant,
config_entry: RoborockConfigEntry,
@@ -109,10 +133,11 @@ async def async_setup_entry(
f"{description.key}_{coordinator.duid_slug}",
coordinator,
description,
trait,
v1_trait,
)
for description in SWITCH_DESCRIPTIONS
if (trait := description.trait(coordinator.properties_api)) is not None
if (v1_trait := description.trait(coordinator.properties_api))
is not None
)
elif isinstance(coordinator, RoborockDataUpdateCoordinatorA01):
entities.extend(
@@ -123,6 +148,17 @@ async def async_setup_entry(
for description in A01_SWITCH_DESCRIPTIONS
if description.data_protocol in coordinator.request_protocols
)
elif isinstance(coordinator, RoborockB01Q10UpdateCoordinator):
entities.extend(
RoborockSwitchQ10(
f"{description.key}_{coordinator.duid_slug}",
coordinator,
description,
q10_trait,
)
for description in Q10_SWITCH_DESCRIPTIONS
if (q10_trait := description.trait(coordinator.api)) is not None
)
async_add_entities(entities)
for coordinator in coordinators.values():
@@ -241,3 +277,56 @@ class RoborockSwitchA01(RoborockCoordinatedEntityA01, SwitchEntity):
if status is None:
return None
return bool(status)
class RoborockSwitchQ10(RoborockCoordinatedEntityB01Q10, SwitchEntity):
"""A class to toggle a setting on a Roborock Q10 device."""
entity_description: RoborockSwitchDescriptionQ10
coordinator: RoborockB01Q10UpdateCoordinator
def __init__(
self,
unique_id: str,
coordinator: RoborockB01Q10UpdateCoordinator,
description: RoborockSwitchDescriptionQ10,
trait: DoNotDisturbTrait,
) -> None:
"""Initialize the entity."""
self.entity_description = description
self._trait = trait
super().__init__(unique_id, coordinator)
@override
async def async_added_to_hass(self) -> None:
"""Register a trait listener for push-based state updates."""
await super().async_added_to_hass()
self.async_on_remove(self._trait.add_update_listener(self.async_write_ha_state))
@override
async def async_turn_off(self, **kwargs: Any) -> None:
"""Turn off the switch."""
try:
await self._trait.disable()
except RoborockException as err:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="update_options_failed",
) from err
@override
async def async_turn_on(self, **kwargs: Any) -> None:
"""Turn on the switch."""
try:
await self._trait.enable()
except RoborockException as err:
raise HomeAssistantError(
translation_domain=DOMAIN,
translation_key="update_options_failed",
) from err
@property
@override
def is_on(self) -> bool | None:
"""Return True if entity is on."""
return self._trait.is_on
+2 -2
View File
@@ -11,7 +11,7 @@ from homeassistant.components.number import (
NumberEntity,
NumberEntityDescription,
)
from homeassistant.const import PERCENTAGE, EntityCategory, UnitOfTemperature
from homeassistant.const import EntityCategory, UnitOfRatio, UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
@@ -48,7 +48,7 @@ DEVICE_NUMBER_TYPES = (
key="calibration_hum",
translation_key="calibration_humidity",
device_class=NumberDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
remote_key="humidity",
entity_category=EntityCategory.CONFIG,
entity_registry_enabled_default=False,
+9 -11
View File
@@ -14,13 +14,11 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_BILLION,
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
EntityCategory,
UnitOfDensity,
UnitOfElectricPotential,
UnitOfRatio,
UnitOfTemperature,
)
from homeassistant.core import HomeAssistant
@@ -87,7 +85,7 @@ MOTION_SENSOR_TYPES: tuple[SensiboMotionSensorEntityDescription, ...] = (
SensiboMotionSensorEntityDescription(
key="humidity",
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.humidity,
),
@@ -181,7 +179,7 @@ AIRQ_SENSOR_TYPES: tuple[SensiboDeviceSensorEntityDescription, ...] = (
SensiboDeviceSensorEntityDescription(
key="airq_tvoc",
translation_key="airq_tvoc",
native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_BILLION,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.tvoc,
extra_fn=None,
@@ -190,7 +188,7 @@ AIRQ_SENSOR_TYPES: tuple[SensiboDeviceSensorEntityDescription, ...] = (
key="airq_co2",
translation_key="airq_co2",
device_class=SensorDeviceClass.CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.co2,
extra_fn=None,
@@ -202,7 +200,7 @@ ELEMENT_SENSOR_TYPES: tuple[SensiboDeviceSensorEntityDescription, ...] = (
SensiboDeviceSensorEntityDescription(
key="pm25",
device_class=SensorDeviceClass.PM25,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.pm25,
extra_fn=None,
@@ -210,7 +208,7 @@ ELEMENT_SENSOR_TYPES: tuple[SensiboDeviceSensorEntityDescription, ...] = (
SensiboDeviceSensorEntityDescription(
key="tvoc",
translation_key="tvoc",
native_unit_of_measurement=CONCENTRATION_PARTS_PER_BILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_BILLION,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.tvoc,
extra_fn=None,
@@ -218,14 +216,14 @@ ELEMENT_SENSOR_TYPES: tuple[SensiboDeviceSensorEntityDescription, ...] = (
SensiboDeviceSensorEntityDescription(
key="co2",
device_class=SensorDeviceClass.CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
value_fn=lambda data: data.co2,
extra_fn=None,
),
SensiboDeviceSensorEntityDescription(
key="ethanol",
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
translation_key="ethanol",
value_fn=lambda data: data.etoh,
@@ -22,11 +22,7 @@ from homeassistant.components.sensor import (
SensorEntityDescription,
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_PARTS_PER_MILLION,
PERCENTAGE,
UnitOfTemperature,
)
from homeassistant.const import UnitOfRatio, UnitOfTemperature
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from homeassistant.helpers.sensor import sensor_device_info_to_hass_device_info
@@ -42,13 +38,13 @@ SENSOR_DESCRIPTIONS: dict[
): SensorEntityDescription(
key=f"{SSDSensorDeviceClass.CO2}_{Units.CONCENTRATION_PARTS_PER_MILLION}",
device_class=SensorDeviceClass.CO2,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
),
(SSDSensorDeviceClass.HUMIDITY, Units.PERCENTAGE): SensorEntityDescription(
key=f"{SSDSensorDeviceClass.HUMIDITY}_{Units.PERCENTAGE}",
device_class=SensorDeviceClass.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
),
(SSDSensorDeviceClass.TEMPERATURE, Units.TEMP_CELSIUS): SensorEntityDescription(
+2 -2
View File
@@ -10,7 +10,7 @@ from homeassistant.components.sensor import (
PLATFORM_SCHEMA as SENSOR_PLATFORM_SCHEMA,
SensorEntity,
)
from homeassistant.const import CONCENTRATION_MICROGRAMS_PER_CUBIC_METER, CONF_NAME
from homeassistant.const import CONF_NAME, UnitOfDensity
from homeassistant.core import HomeAssistant
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.entity_platform import AddEntitiesCallback
@@ -94,7 +94,7 @@ class ParticulateMatterSensor(SensorEntity):
@override
def native_unit_of_measurement(self):
"""Return the unit of measurement of this entity, if any."""
return CONCENTRATION_MICROGRAMS_PER_CUBIC_METER
return UnitOfDensity
def update(self) -> None:
"""Read from sensor and update the state."""
+18 -19
View File
@@ -15,16 +15,15 @@ from homeassistant.components.sensor import (
SensorStateClass,
)
from homeassistant.const import (
CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
CONCENTRATION_PARTS_PER_MILLION,
LIGHT_LUX,
PERCENTAGE,
EntityCategory,
UnitOfArea,
UnitOfDensity,
UnitOfEnergy,
UnitOfMass,
UnitOfPower,
UnitOfPressure,
UnitOfRatio,
UnitOfTemperature,
UnitOfVolume,
UnitOfVolumeFlowRate,
@@ -240,7 +239,7 @@ CAPABILITY_TO_SENSORS: dict[
SmartThingsSensorEntityDescription(
key=Attribute.VOLUME,
translation_key="audio_volume",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
deprecated=(
lambda status: (
("2025.10.0", "media_player")
@@ -255,7 +254,7 @@ CAPABILITY_TO_SENSORS: dict[
Attribute.BATTERY: [
SmartThingsSensorEntityDescription(
key=Attribute.BATTERY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
device_class=SensorDeviceClass.BATTERY,
entity_category=EntityCategory.DIAGNOSTIC,
)
@@ -288,7 +287,7 @@ CAPABILITY_TO_SENSORS: dict[
Attribute.CARBON_DIOXIDE: [
SmartThingsSensorEntityDescription(
key=Attribute.CARBON_DIOXIDE,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
device_class=SensorDeviceClass.CO2,
state_class=SensorStateClass.MEASUREMENT,
)
@@ -310,7 +309,7 @@ CAPABILITY_TO_SENSORS: dict[
Attribute.CARBON_MONOXIDE_LEVEL: [
SmartThingsSensorEntityDescription(
key=Attribute.CARBON_MONOXIDE_LEVEL,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
device_class=SensorDeviceClass.CO,
state_class=SensorStateClass.MEASUREMENT,
)
@@ -356,7 +355,7 @@ CAPABILITY_TO_SENSORS: dict[
SmartThingsSensorEntityDescription(
key=Attribute.WATER_FILTER_USAGE,
translation_key="water_filter_usage",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
)
]
@@ -468,7 +467,7 @@ CAPABILITY_TO_SENSORS: dict[
SmartThingsSensorEntityDescription(
key=Attribute.DUST_LEVEL,
device_class=SensorDeviceClass.PM10,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
)
],
@@ -476,7 +475,7 @@ CAPABILITY_TO_SENSORS: dict[
SmartThingsSensorEntityDescription(
key=Attribute.FINE_DUST_LEVEL,
device_class=SensorDeviceClass.PM25,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
)
],
@@ -507,7 +506,7 @@ CAPABILITY_TO_SENSORS: dict[
SmartThingsSensorEntityDescription(
key=Attribute.EQUIVALENT_CARBON_DIOXIDE_MEASUREMENT,
translation_key="equivalent_carbon_dioxide",
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
device_class=SensorDeviceClass.CO2,
state_class=SensorStateClass.MEASUREMENT,
)
@@ -528,7 +527,7 @@ CAPABILITY_TO_SENSORS: dict[
Attribute.FINE_DUST_LEVEL: [
SmartThingsSensorEntityDescription(
key=Attribute.FINE_DUST_LEVEL,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
state_class=SensorStateClass.MEASUREMENT,
device_class=SensorDeviceClass.PM25,
)
@@ -540,7 +539,7 @@ CAPABILITY_TO_SENSORS: dict[
SmartThingsSensorEntityDescription(
key=Attribute.FORMALDEHYDE_LEVEL,
translation_key="formaldehyde",
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
)
]
@@ -594,7 +593,7 @@ CAPABILITY_TO_SENSORS: dict[
SmartThingsSensorEntityDescription(
key=Attribute.INFRARED_LEVEL,
translation_key="infrared_level",
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
state_class=SensorStateClass.MEASUREMENT,
)
]
@@ -869,7 +868,7 @@ CAPABILITY_TO_SENSORS: dict[
Attribute.HUMIDITY: [
SmartThingsSensorEntityDescription(
key=Attribute.HUMIDITY,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
device_class=SensorDeviceClass.HUMIDITY,
state_class=SensorStateClass.MEASUREMENT,
)
@@ -1095,7 +1094,7 @@ CAPABILITY_TO_SENSORS: dict[
SmartThingsSensorEntityDescription(
key=Attribute.TVOC_LEVEL,
device_class=SensorDeviceClass.VOLATILE_ORGANIC_COMPOUNDS_PARTS,
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
native_unit_of_measurement=UnitOfRatio.PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT,
)
]
@@ -1124,7 +1123,7 @@ CAPABILITY_TO_SENSORS: dict[
Attribute.VERY_FINE_DUST_LEVEL: [
SmartThingsSensorEntityDescription(
key=Attribute.VERY_FINE_DUST_LEVEL,
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
native_unit_of_measurement=UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
device_class=SensorDeviceClass.PM1,
state_class=SensorStateClass.MEASUREMENT,
)
@@ -1223,7 +1222,7 @@ CAPABILITY_TO_SENSORS: dict[
key=Attribute.HOOD_FILTER_USAGE,
translation_key="hood_filter_usage",
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=PERCENTAGE,
native_unit_of_measurement=UnitOfRatio.PERCENTAGE,
entity_category=EntityCategory.DIAGNOSTIC,
)
]
@@ -1319,7 +1318,7 @@ UNITS = {
"ccf": UnitOfVolume.CENTUM_CUBIC_FEET,
"lux": LIGHT_LUX,
"mG": None,
"μg/m^3": CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
"μg/m^3": UnitOfDensity.MICROGRAMS_PER_CUBIC_METER,
"kPa": UnitOfPressure.KPA,
}

Some files were not shown because too many files have changed in this diff Show More