forked from home-assistant/core
Compare commits
207 Commits
2023.4.0b2
...
2023.4.6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cdbdf1ba4f | ||
|
|
d58f62cb5e | ||
|
|
f1c4605fba | ||
|
|
deb55a74da | ||
|
|
30da629285 | ||
|
|
26b28001c5 | ||
|
|
64f8059f00 | ||
|
|
8363183943 | ||
|
|
e19279fda5 | ||
|
|
591ffe2340 | ||
|
|
fc4e8e5e7b | ||
|
|
36d2accb5b | ||
|
|
38de9765df | ||
|
|
6b02892c28 | ||
|
|
c544da7426 | ||
|
|
71f0f53ddc | ||
|
|
03c517b066 | ||
|
|
b05fcd7904 | ||
|
|
940861e2be | ||
|
|
559ce6a275 | ||
|
|
273e1fd2be | ||
|
|
5ddc18f8ed | ||
|
|
489a6e766b | ||
|
|
572f2cc167 | ||
|
|
5321c60058 | ||
|
|
00a86757fa | ||
|
|
b06d624d43 | ||
|
|
89b1d5bb68 | ||
|
|
bf389440dc | ||
|
|
2b9cc39d2b | ||
|
|
afe3fd5ec0 | ||
|
|
e29d5a1356 | ||
|
|
5f7b447d7a | ||
|
|
0e3f462bfb | ||
|
|
8feab57d59 | ||
|
|
2bda40d352 | ||
|
|
47398f03dd | ||
|
|
3f0f5dc303 | ||
|
|
b5ac3ee288 | ||
|
|
51c99d26b4 | ||
|
|
f77ce413be | ||
|
|
7a8159052e | ||
|
|
8ec6afb85a | ||
|
|
bbf2d0e6ad | ||
|
|
c073cee049 | ||
|
|
e9f1148c0a | ||
|
|
a420007e80 | ||
|
|
64a9bfcc22 | ||
|
|
fd53eda5c6 | ||
|
|
d6574b4a2e | ||
|
|
8eb75beb96 | ||
|
|
68920a12aa | ||
|
|
a806e070a2 | ||
|
|
a87c78ca20 | ||
|
|
48df638f5d | ||
|
|
c601266f9c | ||
|
|
30d615f206 | ||
|
|
2db8d70c2f | ||
|
|
3efffe7688 | ||
|
|
dc777f78b8 | ||
|
|
4cd00da319 | ||
|
|
3f6486db3e | ||
|
|
2d41fe837c | ||
|
|
34394d90c0 | ||
|
|
fa29aea68e | ||
|
|
7928b31087 | ||
|
|
e792350be6 | ||
|
|
5f0553dd22 | ||
|
|
8f6b77235e | ||
|
|
8ababc75d4 | ||
|
|
0a8f399655 | ||
|
|
19567e7fee | ||
|
|
3a137cb24c | ||
|
|
935af6904d | ||
|
|
4fed5ad21c | ||
|
|
9dc15687b5 | ||
|
|
38a0eca223 | ||
|
|
6836e0b511 | ||
|
|
cab88b72b8 | ||
|
|
07421927ec | ||
|
|
828a2779a0 | ||
|
|
7392a5780c | ||
|
|
804270a797 | ||
|
|
7f5f286648 | ||
|
|
0a70a29e92 | ||
|
|
dc2f2e8d3f | ||
|
|
6522a3ad1b | ||
|
|
be65d4f33e | ||
|
|
0c15c75781 | ||
|
|
2bf51a033b | ||
|
|
cfd8695aaa | ||
|
|
e8a6a2e105 | ||
|
|
73a960af34 | ||
|
|
bbb571fdf8 | ||
|
|
c944be8215 | ||
|
|
5e903e04cf | ||
|
|
6884b0a421 | ||
|
|
a1c7159304 | ||
|
|
d65791027f | ||
|
|
5ffa0cba39 | ||
|
|
f5be600383 | ||
|
|
9b2e26c270 | ||
|
|
e25edea815 | ||
|
|
849000d5ac | ||
|
|
cb06541fda | ||
|
|
70d1e733f6 | ||
|
|
0b3012071e | ||
|
|
42b7ed115f | ||
|
|
513a13f369 | ||
|
|
f341d0787e | ||
|
|
c8ee45b53c | ||
|
|
b4e2dd4e06 | ||
|
|
c663d8754b | ||
|
|
968a4e4818 | ||
|
|
833b95722e | ||
|
|
096e814929 | ||
|
|
cff493fb98 | ||
|
|
d67265bb66 | ||
|
|
6e51f0d6f5 | ||
|
|
82977f33ed | ||
|
|
fb2d432d32 | ||
|
|
0d019a3c4c | ||
|
|
65b877bb77 | ||
|
|
2a23583d67 | ||
|
|
80fe5051b3 | ||
|
|
2dfe33d177 | ||
|
|
617037a92d | ||
|
|
8f60a2bdd4 | ||
|
|
9f7b2ba6c1 | ||
|
|
af34e25c89 | ||
|
|
c43dc37713 | ||
|
|
0d6177dbdb | ||
|
|
f03b9036c5 | ||
|
|
1848a723cd | ||
|
|
8230a52e0a | ||
|
|
d0e9470c7c | ||
|
|
b50354f362 | ||
|
|
e4b3a146be | ||
|
|
1861a621b2 | ||
|
|
0746e09256 | ||
|
|
0166cd082b | ||
|
|
0a74f946db | ||
|
|
d04b45a821 | ||
|
|
a5a6641bb4 | ||
|
|
1420cda837 | ||
|
|
cba5751ca2 | ||
|
|
a3e66b5dde | ||
|
|
83dd52ab1f | ||
|
|
da1e5f6a3c | ||
|
|
8f9868024c | ||
|
|
c90396cd57 | ||
|
|
509c1ca99c | ||
|
|
431fbee641 | ||
|
|
28983bca85 | ||
|
|
601498617d | ||
|
|
6c208f655d | ||
|
|
eaaf24d326 | ||
|
|
0c12d45581 | ||
|
|
c2e46db76d | ||
|
|
47c8b7804d | ||
|
|
8d302aea9e | ||
|
|
3a73425888 | ||
|
|
f9e4fe016f | ||
|
|
5835ae03bc | ||
|
|
71608d4795 | ||
|
|
e38590e40a | ||
|
|
9e3b54f539 | ||
|
|
24ff2ddae5 | ||
|
|
621de8bb5f | ||
|
|
6cbf9288b5 | ||
|
|
9f95da7793 | ||
|
|
cb5326b798 | ||
|
|
1aa6d3e896 | ||
|
|
1c8d4b8bb8 | ||
|
|
8669ee3685 | ||
|
|
20d8bbbd0c | ||
|
|
e10e3ee7cc | ||
|
|
83b7018be2 | ||
|
|
6d967ac535 | ||
|
|
77bc745bed | ||
|
|
8fe7b01baa | ||
|
|
5e5888b37a | ||
|
|
90de51fff3 | ||
|
|
89230b75be | ||
|
|
cbe3cabf0a | ||
|
|
c259c1afe3 | ||
|
|
1ff93518b5 | ||
|
|
aa6cf3d208 | ||
|
|
2a28d40dc8 | ||
|
|
c006b3b1df | ||
|
|
bacd77a03a | ||
|
|
75694307e2 | ||
|
|
1189b2ad70 | ||
|
|
d5d5bb0732 | ||
|
|
6242dd2214 | ||
|
|
03f085d7be | ||
|
|
b3348c3e6f | ||
|
|
590db0fa74 | ||
|
|
f56ccf90d9 | ||
|
|
c63f8e714e | ||
|
|
a20771f571 | ||
|
|
2d482f1f57 | ||
|
|
499962f4ee | ||
|
|
88a407361c | ||
|
|
89dc6db5a7 | ||
|
|
de9e7e47fe | ||
|
|
ab66664f20 |
@@ -228,8 +228,6 @@ build.json @home-assistant/supervisor
|
||||
/homeassistant/components/cups/ @fabaff
|
||||
/homeassistant/components/daikin/ @fredrike
|
||||
/tests/components/daikin/ @fredrike
|
||||
/homeassistant/components/darksky/ @fabaff
|
||||
/tests/components/darksky/ @fabaff
|
||||
/homeassistant/components/debugpy/ @frenck
|
||||
/tests/components/debugpy/ @frenck
|
||||
/homeassistant/components/deconz/ @Kane610
|
||||
|
||||
@@ -239,6 +239,7 @@ async def load_registries(hass: core.HomeAssistant) -> None:
|
||||
|
||||
# Load the registries and cache the result of platform.uname().processor
|
||||
entity.async_setup(hass)
|
||||
template.async_setup(hass)
|
||||
await asyncio.gather(
|
||||
area_registry.async_load(hass),
|
||||
device_registry.async_load(hass),
|
||||
|
||||
@@ -68,7 +68,7 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
|
||||
AirlySensorEntityDescription(
|
||||
key=ATTR_API_CAQI,
|
||||
icon="mdi:air-filter",
|
||||
name=ATTR_API_CAQI,
|
||||
translation_key="caqi",
|
||||
native_unit_of_measurement="CAQI",
|
||||
suggested_display_precision=0,
|
||||
attrs=lambda data: {
|
||||
@@ -80,7 +80,7 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
|
||||
AirlySensorEntityDescription(
|
||||
key=ATTR_API_PM1,
|
||||
device_class=SensorDeviceClass.PM1,
|
||||
name="PM1.0",
|
||||
translation_key="pm1",
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_display_precision=0,
|
||||
@@ -88,7 +88,7 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
|
||||
AirlySensorEntityDescription(
|
||||
key=ATTR_API_PM25,
|
||||
device_class=SensorDeviceClass.PM25,
|
||||
name="PM2.5",
|
||||
translation_key="pm25",
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_display_precision=0,
|
||||
@@ -100,7 +100,7 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
|
||||
AirlySensorEntityDescription(
|
||||
key=ATTR_API_PM10,
|
||||
device_class=SensorDeviceClass.PM10,
|
||||
name=ATTR_API_PM10,
|
||||
translation_key="pm10",
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_display_precision=0,
|
||||
@@ -112,7 +112,7 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
|
||||
AirlySensorEntityDescription(
|
||||
key=ATTR_API_HUMIDITY,
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
name=ATTR_API_HUMIDITY.capitalize(),
|
||||
translation_key="humidity",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_display_precision=1,
|
||||
@@ -120,7 +120,7 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
|
||||
AirlySensorEntityDescription(
|
||||
key=ATTR_API_PRESSURE,
|
||||
device_class=SensorDeviceClass.PRESSURE,
|
||||
name=ATTR_API_PRESSURE.capitalize(),
|
||||
translation_key="pressure",
|
||||
native_unit_of_measurement=UnitOfPressure.HPA,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_display_precision=0,
|
||||
@@ -128,14 +128,14 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
|
||||
AirlySensorEntityDescription(
|
||||
key=ATTR_API_TEMPERATURE,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
name=ATTR_API_TEMPERATURE.capitalize(),
|
||||
translation_key="temperature",
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_display_precision=1,
|
||||
),
|
||||
AirlySensorEntityDescription(
|
||||
key=ATTR_API_CO,
|
||||
name="Carbon monoxide",
|
||||
translation_key="co",
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_display_precision=0,
|
||||
@@ -147,7 +147,7 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
|
||||
AirlySensorEntityDescription(
|
||||
key=ATTR_API_NO2,
|
||||
device_class=SensorDeviceClass.NITROGEN_DIOXIDE,
|
||||
name="Nitrogen dioxide",
|
||||
translation_key="no2",
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_display_precision=0,
|
||||
@@ -159,7 +159,7 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
|
||||
AirlySensorEntityDescription(
|
||||
key=ATTR_API_SO2,
|
||||
device_class=SensorDeviceClass.SULPHUR_DIOXIDE,
|
||||
name="Sulphur dioxide",
|
||||
translation_key="so2",
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_display_precision=0,
|
||||
@@ -171,7 +171,7 @@ SENSOR_TYPES: tuple[AirlySensorEntityDescription, ...] = (
|
||||
AirlySensorEntityDescription(
|
||||
key=ATTR_API_O3,
|
||||
device_class=SensorDeviceClass.OZONE,
|
||||
name="Ozone",
|
||||
translation_key="o3",
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
suggested_display_precision=0,
|
||||
|
||||
@@ -26,5 +26,42 @@
|
||||
"requests_remaining": "Remaining allowed requests",
|
||||
"requests_per_day": "Allowed requests per day"
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"caqi": {
|
||||
"name": "Common air quality index"
|
||||
},
|
||||
"pm1": {
|
||||
"name": "[%key:component::sensor::entity_component::pm1::name%]"
|
||||
},
|
||||
"pm25": {
|
||||
"name": "[%key:component::sensor::entity_component::pm25::name%]"
|
||||
},
|
||||
"pm10": {
|
||||
"name": "[%key:component::sensor::entity_component::pm10::name%]"
|
||||
},
|
||||
"humidity": {
|
||||
"name": "[%key:component::sensor::entity_component::humidity::name%]"
|
||||
},
|
||||
"pressure": {
|
||||
"name": "[%key:component::sensor::entity_component::pressure::name%]"
|
||||
},
|
||||
"temperature": {
|
||||
"name": "[%key:component::sensor::entity_component::temperature::name%]"
|
||||
},
|
||||
"co": {
|
||||
"name": "[%key:component::sensor::entity_component::carbon_monoxide::name%]"
|
||||
},
|
||||
"no2": {
|
||||
"name": "[%key:component::sensor::entity_component::nitrogen_dioxide::name%]"
|
||||
},
|
||||
"so2": {
|
||||
"name": "[%key:component::sensor::entity_component::sulphur_dioxide::name%]"
|
||||
},
|
||||
"o3": {
|
||||
"name": "[%key:component::sensor::entity_component::ozone::name%]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
"integration_type": "hub",
|
||||
"iot_class": "cloud_push",
|
||||
"loggers": ["aioambient"],
|
||||
"requirements": ["aioambient==2021.11.0"]
|
||||
"requirements": ["aioambient==2023.04.0"]
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ async def async_setup(hass: HomeAssistant, _: ConfigType) -> bool:
|
||||
|
||||
# Send every day
|
||||
async_track_time_interval(
|
||||
hass, analytics.send_analytics, INTERVAL, "analytics daily"
|
||||
hass, analytics.send_analytics, INTERVAL, name="analytics daily"
|
||||
)
|
||||
|
||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STARTED, start_schedule)
|
||||
|
||||
@@ -38,7 +38,10 @@ class AugustSubscriberMixin:
|
||||
def _async_setup_listeners(self):
|
||||
"""Create interval and stop listeners."""
|
||||
self._unsub_interval = async_track_time_interval(
|
||||
self._hass, self._async_refresh, self._update_interval, "august refresh"
|
||||
self._hass,
|
||||
self._async_refresh,
|
||||
self._update_interval,
|
||||
name="august refresh",
|
||||
)
|
||||
|
||||
@callback
|
||||
|
||||
@@ -101,7 +101,7 @@ class BaseHaScanner(ABC):
|
||||
self.hass,
|
||||
self._async_scanner_watchdog,
|
||||
SCANNER_WATCHDOG_INTERVAL,
|
||||
f"{self.name} Bluetooth scanner watchdog",
|
||||
name=f"{self.name} Bluetooth scanner watchdog",
|
||||
)
|
||||
|
||||
@hass_callback
|
||||
@@ -230,7 +230,7 @@ class BaseHaRemoteScanner(BaseHaScanner):
|
||||
self.hass,
|
||||
self._async_expire_devices,
|
||||
timedelta(seconds=30),
|
||||
f"{self.name} Bluetooth scanner device expire",
|
||||
name=f"{self.name} Bluetooth scanner device expire",
|
||||
)
|
||||
cancel_stop = self.hass.bus.async_listen(
|
||||
EVENT_HOMEASSISTANT_STOP, self._async_save_history
|
||||
@@ -345,12 +345,27 @@ class BaseHaRemoteScanner(BaseHaScanner):
|
||||
tx_power=NO_RSSI_VALUE if tx_power is None else tx_power,
|
||||
platform_data=(),
|
||||
)
|
||||
device = BLEDevice(
|
||||
address=address,
|
||||
name=local_name,
|
||||
details=self._details | details,
|
||||
rssi=rssi, # deprecated, will be removed in newer bleak
|
||||
)
|
||||
if prev_discovery:
|
||||
#
|
||||
# Bleak updates the BLEDevice via create_or_update_device.
|
||||
# We need to do the same to ensure integrations that already
|
||||
# have the BLEDevice object get the updated details when they
|
||||
# change.
|
||||
#
|
||||
# https://github.com/hbldh/bleak/blob/222618b7747f0467dbb32bd3679f8cfaa19b1668/bleak/backends/scanner.py#L203
|
||||
#
|
||||
device = prev_device
|
||||
device.name = local_name
|
||||
device.details = self._details | details
|
||||
# pylint: disable-next=protected-access
|
||||
device._rssi = rssi # deprecated, will be removed in newer bleak
|
||||
else:
|
||||
device = BLEDevice(
|
||||
address=address,
|
||||
name=local_name,
|
||||
details=self._details | details,
|
||||
rssi=rssi, # deprecated, will be removed in newer bleak
|
||||
)
|
||||
self._discovered_device_advertisement_datas[address] = (
|
||||
device,
|
||||
advertisement_data,
|
||||
|
||||
@@ -276,7 +276,7 @@ class BluetoothManager:
|
||||
self.hass,
|
||||
self._async_check_unavailable,
|
||||
timedelta(seconds=UNAVAILABLE_TRACK_SECONDS),
|
||||
"Bluetooth manager unavailable tracking",
|
||||
name="Bluetooth manager unavailable tracking",
|
||||
)
|
||||
|
||||
@hass_callback
|
||||
|
||||
@@ -10,9 +10,10 @@ from .wrappers import HaBleakClientWrapper, HaBleakScannerWrapper
|
||||
|
||||
ORIGINAL_BLEAK_SCANNER = bleak.BleakScanner
|
||||
ORIGINAL_BLEAK_CLIENT = bleak.BleakClient
|
||||
ORIGINAL_BLEAK_RETRY_CONNECTOR_CLIENT = (
|
||||
ORIGINAL_BLEAK_RETRY_CONNECTOR_CLIENT_WITH_SERVICE_CACHE = (
|
||||
bleak_retry_connector.BleakClientWithServiceCache
|
||||
)
|
||||
ORIGINAL_BLEAK_RETRY_CONNECTOR_CLIENT = bleak_retry_connector.BleakClient
|
||||
|
||||
|
||||
def install_multiple_bleak_catcher() -> None:
|
||||
@@ -23,6 +24,7 @@ def install_multiple_bleak_catcher() -> None:
|
||||
bleak.BleakScanner = HaBleakScannerWrapper # type: ignore[misc, assignment]
|
||||
bleak.BleakClient = HaBleakClientWrapper # type: ignore[misc]
|
||||
bleak_retry_connector.BleakClientWithServiceCache = HaBleakClientWithServiceCache # type: ignore[misc,assignment] # noqa: E501
|
||||
bleak_retry_connector.BleakClient = HaBleakClientWrapper # type: ignore[misc] # noqa: E501
|
||||
|
||||
|
||||
def uninstall_multiple_bleak_catcher() -> None:
|
||||
@@ -30,6 +32,9 @@ def uninstall_multiple_bleak_catcher() -> None:
|
||||
bleak.BleakScanner = ORIGINAL_BLEAK_SCANNER # type: ignore[misc]
|
||||
bleak.BleakClient = ORIGINAL_BLEAK_CLIENT # type: ignore[misc]
|
||||
bleak_retry_connector.BleakClientWithServiceCache = ( # type: ignore[misc]
|
||||
ORIGINAL_BLEAK_RETRY_CONNECTOR_CLIENT_WITH_SERVICE_CACHE
|
||||
)
|
||||
bleak_retry_connector.BleakClient = ( # type: ignore[misc]
|
||||
ORIGINAL_BLEAK_RETRY_CONNECTOR_CLIENT
|
||||
)
|
||||
|
||||
|
||||
@@ -70,6 +70,7 @@ async def async_setup_scanner( # noqa: C901
|
||||
yaml_path = hass.config.path(YAML_DEVICES)
|
||||
devs_to_track: set[str] = set()
|
||||
devs_no_track: set[str] = set()
|
||||
devs_advertise_time: dict[str, float] = {}
|
||||
devs_track_battery = {}
|
||||
interval: timedelta = config.get(CONF_SCAN_INTERVAL, SCAN_INTERVAL)
|
||||
# if track new devices is true discover new devices
|
||||
@@ -178,6 +179,7 @@ async def async_setup_scanner( # noqa: C901
|
||||
"""Update from a ble callback."""
|
||||
mac = service_info.address
|
||||
if mac in devs_to_track:
|
||||
devs_advertise_time[mac] = service_info.time
|
||||
now = dt_util.utcnow()
|
||||
hass.async_create_task(async_see_device(mac, service_info.name))
|
||||
if (
|
||||
@@ -205,7 +207,9 @@ async def async_setup_scanner( # noqa: C901
|
||||
# there have been no callbacks because the RSSI or
|
||||
# other properties have not changed.
|
||||
for service_info in bluetooth.async_discovered_service_info(hass, False):
|
||||
_async_update_ble(service_info, bluetooth.BluetoothChange.ADVERTISEMENT)
|
||||
# Only call _async_update_ble if the advertisement time has changed
|
||||
if service_info.time != devs_advertise_time.get(service_info.address):
|
||||
_async_update_ble(service_info, bluetooth.BluetoothChange.ADVERTISEMENT)
|
||||
|
||||
cancels = [
|
||||
bluetooth.async_register_callback(
|
||||
|
||||
@@ -177,7 +177,7 @@ class BondEntity(Entity):
|
||||
self.hass,
|
||||
self._async_update_if_bpup_not_alive,
|
||||
_FALLBACK_SCAN_INTERVAL,
|
||||
f"Bond {self.entity_id} fallback polling",
|
||||
name=f"Bond {self.entity_id} fallback polling",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -36,14 +36,14 @@ class BraviaTVButtonDescription(
|
||||
BUTTONS: tuple[BraviaTVButtonDescription, ...] = (
|
||||
BraviaTVButtonDescription(
|
||||
key="reboot",
|
||||
name="Reboot",
|
||||
translation_key="restart",
|
||||
device_class=ButtonDeviceClass.RESTART,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
press_action=lambda coordinator: coordinator.async_reboot_device(),
|
||||
),
|
||||
BraviaTVButtonDescription(
|
||||
key="terminate_apps",
|
||||
name="Terminate apps",
|
||||
translation_key="terminate_apps",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
press_action=lambda coordinator: coordinator.async_terminate_apps(),
|
||||
),
|
||||
|
||||
@@ -44,5 +44,15 @@
|
||||
"not_bravia_device": "The device is not a Bravia TV.",
|
||||
"reauth_successful": "[%key:common::config_flow::abort::reauth_successful%]"
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"button": {
|
||||
"restart": {
|
||||
"name": "[%key:component::button::entity_component::restart::name%]"
|
||||
},
|
||||
"terminate_apps": {
|
||||
"name": "Terminate apps"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,61 +25,61 @@ from .entity import BroadlinkEntity
|
||||
SENSOR_TYPES: tuple[SensorEntityDescription, ...] = (
|
||||
SensorEntityDescription(
|
||||
key="temperature",
|
||||
name="Temperature",
|
||||
translation_key="temperature",
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="air_quality",
|
||||
name="Air quality",
|
||||
translation_key="air_quality",
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="humidity",
|
||||
name="Humidity",
|
||||
translation_key="humidity",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="light",
|
||||
name="Light",
|
||||
translation_key="light",
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="noise",
|
||||
name="Noise",
|
||||
translation_key="noise",
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="power",
|
||||
name="Current power",
|
||||
translation_key="power",
|
||||
native_unit_of_measurement=UnitOfPower.WATT,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="volt",
|
||||
name="Voltage",
|
||||
translation_key="voltage",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="current",
|
||||
name="Current",
|
||||
translation_key="current",
|
||||
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
|
||||
device_class=SensorDeviceClass.CURRENT,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="overload",
|
||||
name="Overload",
|
||||
translation_key="overload",
|
||||
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
|
||||
device_class=SensorDeviceClass.CURRENT,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="totalconsum",
|
||||
name="Total consumption",
|
||||
translation_key="total_consumption",
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
|
||||
@@ -43,5 +43,39 @@
|
||||
"invalid_host": "[%key:common::config_flow::error::invalid_host%]",
|
||||
"unknown": "[%key:common::config_flow::error::unknown%]"
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"temperature": {
|
||||
"name": "[%key:component::sensor::entity_component::temperature::name%]"
|
||||
},
|
||||
"air_quality": {
|
||||
"name": "[%key:component::sensor::entity_component::aqi::name%]"
|
||||
},
|
||||
"humidity": {
|
||||
"name": "[%key:component::sensor::entity_component::humidity::name%]"
|
||||
},
|
||||
"light": {
|
||||
"name": "[%key:component::sensor::entity_component::illuminance::name%]"
|
||||
},
|
||||
"noise": {
|
||||
"name": "Noise"
|
||||
},
|
||||
"power": {
|
||||
"name": "[%key:component::sensor::entity_component::power::name%]"
|
||||
},
|
||||
"voltage": {
|
||||
"name": "[%key:component::sensor::entity_component::voltage::name%]"
|
||||
},
|
||||
"current": {
|
||||
"name": "[%key:component::sensor::entity_component::current::name%]"
|
||||
},
|
||||
"overload": {
|
||||
"name": "Overload"
|
||||
},
|
||||
"total_consumption": {
|
||||
"name": "Total consumption"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,14 +53,14 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="status",
|
||||
icon="mdi:printer",
|
||||
name="Status",
|
||||
translation_key="status",
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
value=lambda data: data.status,
|
||||
),
|
||||
BrotherSensorEntityDescription(
|
||||
key="page_counter",
|
||||
icon="mdi:file-document-outline",
|
||||
name="Page counter",
|
||||
translation_key="page_counter",
|
||||
native_unit_of_measurement=UNIT_PAGES,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -69,7 +69,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="bw_counter",
|
||||
icon="mdi:file-document-outline",
|
||||
name="B/W counter",
|
||||
translation_key="bw_pages",
|
||||
native_unit_of_measurement=UNIT_PAGES,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -78,7 +78,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="color_counter",
|
||||
icon="mdi:file-document-outline",
|
||||
name="Color counter",
|
||||
translation_key="color_pages",
|
||||
native_unit_of_measurement=UNIT_PAGES,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -87,7 +87,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="duplex_unit_pages_counter",
|
||||
icon="mdi:file-document-outline",
|
||||
name="Duplex unit pages counter",
|
||||
translation_key="duplex_unit_page_counter",
|
||||
native_unit_of_measurement=UNIT_PAGES,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -96,7 +96,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="drum_remaining_life",
|
||||
icon="mdi:chart-donut",
|
||||
name="Drum remaining life",
|
||||
translation_key="drum_remaining_life",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -105,7 +105,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="drum_remaining_pages",
|
||||
icon="mdi:chart-donut",
|
||||
name="Drum remaining pages",
|
||||
translation_key="drum_remaining_pages",
|
||||
native_unit_of_measurement=UNIT_PAGES,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -114,7 +114,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="drum_counter",
|
||||
icon="mdi:chart-donut",
|
||||
name="Drum counter",
|
||||
translation_key="drum_page_counter",
|
||||
native_unit_of_measurement=UNIT_PAGES,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -123,7 +123,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="black_drum_remaining_life",
|
||||
icon="mdi:chart-donut",
|
||||
name="Black drum remaining life",
|
||||
translation_key="black_drum_remaining_life",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -132,7 +132,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="black_drum_remaining_pages",
|
||||
icon="mdi:chart-donut",
|
||||
name="Black drum remaining pages",
|
||||
translation_key="black_drum_remaining_pages",
|
||||
native_unit_of_measurement=UNIT_PAGES,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -141,7 +141,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="black_drum_counter",
|
||||
icon="mdi:chart-donut",
|
||||
name="Black drum counter",
|
||||
translation_key="black_drum_page_counter",
|
||||
native_unit_of_measurement=UNIT_PAGES,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -150,7 +150,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="cyan_drum_remaining_life",
|
||||
icon="mdi:chart-donut",
|
||||
name="Cyan drum remaining life",
|
||||
translation_key="cyan_drum_remaining_life",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -159,7 +159,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="cyan_drum_remaining_pages",
|
||||
icon="mdi:chart-donut",
|
||||
name="Cyan drum remaining pages",
|
||||
translation_key="cyan_drum_remaining_pages",
|
||||
native_unit_of_measurement=UNIT_PAGES,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -168,7 +168,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="cyan_drum_counter",
|
||||
icon="mdi:chart-donut",
|
||||
name="Cyan drum counter",
|
||||
translation_key="cyan_drum_page_counter",
|
||||
native_unit_of_measurement=UNIT_PAGES,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -177,7 +177,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="magenta_drum_remaining_life",
|
||||
icon="mdi:chart-donut",
|
||||
name="Magenta drum remaining life",
|
||||
translation_key="magenta_drum_remaining_life",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -186,7 +186,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="magenta_drum_remaining_pages",
|
||||
icon="mdi:chart-donut",
|
||||
name="Magenta drum remaining pages",
|
||||
translation_key="magenta_drum_remaining_pages",
|
||||
native_unit_of_measurement=UNIT_PAGES,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -195,7 +195,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="magenta_drum_counter",
|
||||
icon="mdi:chart-donut",
|
||||
name="Magenta drum counter",
|
||||
translation_key="magenta_drum_page_counter",
|
||||
native_unit_of_measurement=UNIT_PAGES,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -204,7 +204,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="yellow_drum_remaining_life",
|
||||
icon="mdi:chart-donut",
|
||||
name="Yellow drum remaining life",
|
||||
translation_key="yellow_drum_remaining_life",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -213,7 +213,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="yellow_drum_remaining_pages",
|
||||
icon="mdi:chart-donut",
|
||||
name="Yellow drum remaining pages",
|
||||
translation_key="yellow_drum_remaining_pages",
|
||||
native_unit_of_measurement=UNIT_PAGES,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -222,7 +222,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="yellow_drum_counter",
|
||||
icon="mdi:chart-donut",
|
||||
name="Yellow drum counter",
|
||||
translation_key="yellow_drum_page_counter",
|
||||
native_unit_of_measurement=UNIT_PAGES,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -231,7 +231,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="belt_unit_remaining_life",
|
||||
icon="mdi:current-ac",
|
||||
name="Belt unit remaining life",
|
||||
translation_key="belt_unit_remaining_life",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -240,7 +240,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="fuser_remaining_life",
|
||||
icon="mdi:water-outline",
|
||||
name="Fuser remaining life",
|
||||
translation_key="fuser_remaining_life",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -249,7 +249,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="laser_remaining_life",
|
||||
icon="mdi:spotlight-beam",
|
||||
name="Laser remaining life",
|
||||
translation_key="laser_remaining_life",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -258,7 +258,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="pf_kit_1_remaining_life",
|
||||
icon="mdi:printer-3d",
|
||||
name="PF Kit 1 remaining life",
|
||||
translation_key="pf_kit_1_remaining_life",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -267,7 +267,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="pf_kit_mp_remaining_life",
|
||||
icon="mdi:printer-3d",
|
||||
name="PF Kit MP remaining life",
|
||||
translation_key="pf_kit_mp_remaining_life",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -276,7 +276,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="black_toner_remaining",
|
||||
icon="mdi:printer-3d-nozzle",
|
||||
name="Black toner remaining",
|
||||
translation_key="black_toner_remaining",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -285,7 +285,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="cyan_toner_remaining",
|
||||
icon="mdi:printer-3d-nozzle",
|
||||
name="Cyan toner remaining",
|
||||
translation_key="cyan_toner_remaining",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -294,7 +294,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="magenta_toner_remaining",
|
||||
icon="mdi:printer-3d-nozzle",
|
||||
name="Magenta toner remaining",
|
||||
translation_key="magenta_toner_remaining",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -303,7 +303,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="yellow_toner_remaining",
|
||||
icon="mdi:printer-3d-nozzle",
|
||||
name="Yellow toner remaining",
|
||||
translation_key="yellow_toner_remaining",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -312,7 +312,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="black_ink_remaining",
|
||||
icon="mdi:printer-3d-nozzle",
|
||||
name="Black ink remaining",
|
||||
translation_key="black_ink_remaining",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -321,7 +321,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="cyan_ink_remaining",
|
||||
icon="mdi:printer-3d-nozzle",
|
||||
name="Cyan ink remaining",
|
||||
translation_key="cyan_ink_remaining",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -330,7 +330,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="magenta_ink_remaining",
|
||||
icon="mdi:printer-3d-nozzle",
|
||||
name="Magenta ink remaining",
|
||||
translation_key="magenta_ink_remaining",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -339,7 +339,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
BrotherSensorEntityDescription(
|
||||
key="yellow_ink_remaining",
|
||||
icon="mdi:printer-3d-nozzle",
|
||||
name="Yellow ink remaining",
|
||||
translation_key="yellow_ink_remaining",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -347,7 +347,7 @@ SENSOR_TYPES: tuple[BrotherSensorEntityDescription, ...] = (
|
||||
),
|
||||
BrotherSensorEntityDescription(
|
||||
key="uptime",
|
||||
name="Uptime",
|
||||
translation_key="last_restart",
|
||||
entity_registry_enabled_default=False,
|
||||
device_class=SensorDeviceClass.TIMESTAMP,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
|
||||
@@ -25,5 +25,111 @@
|
||||
"unsupported_model": "This printer model is not supported.",
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"status": {
|
||||
"name": "Status"
|
||||
},
|
||||
"page_counter": {
|
||||
"name": "Page counter"
|
||||
},
|
||||
"bw_pages": {
|
||||
"name": "B/W pages"
|
||||
},
|
||||
"color_pages": {
|
||||
"name": "Color pages"
|
||||
},
|
||||
"duplex_unit_page_counter": {
|
||||
"name": "Duplex unit page counter"
|
||||
},
|
||||
"drum_remaining_life": {
|
||||
"name": "Drum remaining life"
|
||||
},
|
||||
"drum_remaining_pages": {
|
||||
"name": "Drum remaining pages"
|
||||
},
|
||||
"drum_page_counter": {
|
||||
"name": "Drum page counter"
|
||||
},
|
||||
"black_drum_remaining_life": {
|
||||
"name": "Black drum remaining life"
|
||||
},
|
||||
"black_drum_remaining_pages": {
|
||||
"name": "Black drum remaining pages"
|
||||
},
|
||||
"black_drum_page_counter": {
|
||||
"name": "Black drum page counter"
|
||||
},
|
||||
"cyan_drum_remaining_life": {
|
||||
"name": "Cyan drum remaining life"
|
||||
},
|
||||
"cyan_drum_remaining_pages": {
|
||||
"name": "Cyan drum remaining pages"
|
||||
},
|
||||
"cyan_drum_page_counter": {
|
||||
"name": "Cyan drum page counter"
|
||||
},
|
||||
"magenta_drum_remaining_life": {
|
||||
"name": "Magenta drum remaining life"
|
||||
},
|
||||
"magenta_drum_remaining_pages": {
|
||||
"name": "Magenta drum remaining pages"
|
||||
},
|
||||
"magenta_drum_page_counter": {
|
||||
"name": "Magenta drum page counter"
|
||||
},
|
||||
"yellow_drum_remaining_life": {
|
||||
"name": "Yellow drum remaining life"
|
||||
},
|
||||
"yellow_drum_remaining_pages": {
|
||||
"name": "Yellow drum remaining pages"
|
||||
},
|
||||
"yellow_drum_page_counter": {
|
||||
"name": "Yellow drum page counter"
|
||||
},
|
||||
"belt_unit_remaining_life": {
|
||||
"name": "Belt unit remaining life"
|
||||
},
|
||||
"fuser_remaining_life": {
|
||||
"name": "Fuser remaining life"
|
||||
},
|
||||
"laser_remaining_life": {
|
||||
"name": "Laser remaining life"
|
||||
},
|
||||
"pf_kit_1_remaining_life": {
|
||||
"name": "PF Kit 1 remaining life"
|
||||
},
|
||||
"pf_kit_mp_remaining_life": {
|
||||
"name": "PF Kit MP remaining life"
|
||||
},
|
||||
"black_toner_remaining": {
|
||||
"name": "Black toner remaining"
|
||||
},
|
||||
"cyan_toner_remaining": {
|
||||
"name": "Cyan toner remaining"
|
||||
},
|
||||
"magenta_toner_remaining": {
|
||||
"name": "Magenta toner remaining"
|
||||
},
|
||||
"yellow_toner_remaining": {
|
||||
"name": "Yellow toner remaining"
|
||||
},
|
||||
"black_ink_remaining": {
|
||||
"name": "Black ink remaining"
|
||||
},
|
||||
"cyan_ink_remaining": {
|
||||
"name": "Cyan ink remaining"
|
||||
},
|
||||
"magenta_ink_remaining": {
|
||||
"name": "Magenta ink remaining"
|
||||
},
|
||||
"yellow_ink_remaining": {
|
||||
"name": "Yellow ink remaining"
|
||||
},
|
||||
"last_restart": {
|
||||
"name": "Last restart"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -67,6 +67,13 @@ SCAN_INTERVAL = datetime.timedelta(seconds=60)
|
||||
# Don't support rrules more often than daily
|
||||
VALID_FREQS = {"DAILY", "WEEKLY", "MONTHLY", "YEARLY"}
|
||||
|
||||
# Ensure events created in Home Assistant have a positive duration
|
||||
MIN_NEW_EVENT_DURATION = datetime.timedelta(seconds=1)
|
||||
|
||||
# Events must have a non-negative duration e.g. Google Calendar can create zero
|
||||
# duration events in the UI.
|
||||
MIN_EVENT_DURATION = datetime.timedelta(seconds=0)
|
||||
|
||||
|
||||
def _has_timezone(*keys: Any) -> Callable[[dict[str, Any]], dict[str, Any]]:
|
||||
"""Assert that all datetime values have a timezone."""
|
||||
@@ -116,17 +123,18 @@ def _as_local_timezone(*keys: Any) -> Callable[[dict[str, Any]], dict[str, Any]]
|
||||
return validate
|
||||
|
||||
|
||||
def _has_duration(
|
||||
start_key: str, end_key: str
|
||||
def _has_min_duration(
|
||||
start_key: str, end_key: str, min_duration: datetime.timedelta
|
||||
) -> Callable[[dict[str, Any]], dict[str, Any]]:
|
||||
"""Verify that the time span between start and end is positive."""
|
||||
"""Verify that the time span between start and end has a minimum duration."""
|
||||
|
||||
def validate(obj: dict[str, Any]) -> dict[str, Any]:
|
||||
"""Test that all keys in the dict are in order."""
|
||||
if (start := obj.get(start_key)) and (end := obj.get(end_key)):
|
||||
duration = end - start
|
||||
if duration.total_seconds() <= 0:
|
||||
raise vol.Invalid(f"Expected positive event duration ({start}, {end})")
|
||||
if duration < min_duration:
|
||||
raise vol.Invalid(
|
||||
f"Expected minimum event duration of {min_duration} ({start}, {end})"
|
||||
)
|
||||
return obj
|
||||
|
||||
return validate
|
||||
@@ -204,8 +212,8 @@ CREATE_EVENT_SCHEMA = vol.All(
|
||||
),
|
||||
_has_consistent_timezone(EVENT_START_DATETIME, EVENT_END_DATETIME),
|
||||
_as_local_timezone(EVENT_START_DATETIME, EVENT_END_DATETIME),
|
||||
_has_duration(EVENT_START_DATE, EVENT_END_DATE),
|
||||
_has_duration(EVENT_START_DATETIME, EVENT_END_DATETIME),
|
||||
_has_min_duration(EVENT_START_DATE, EVENT_END_DATE, MIN_NEW_EVENT_DURATION),
|
||||
_has_min_duration(EVENT_START_DATETIME, EVENT_END_DATETIME, MIN_NEW_EVENT_DURATION),
|
||||
)
|
||||
|
||||
WEBSOCKET_EVENT_SCHEMA = vol.Schema(
|
||||
@@ -221,7 +229,7 @@ WEBSOCKET_EVENT_SCHEMA = vol.Schema(
|
||||
_has_same_type(EVENT_START, EVENT_END),
|
||||
_has_consistent_timezone(EVENT_START, EVENT_END),
|
||||
_as_local_timezone(EVENT_START, EVENT_END),
|
||||
_has_duration(EVENT_START, EVENT_END),
|
||||
_has_min_duration(EVENT_START, EVENT_END, MIN_NEW_EVENT_DURATION),
|
||||
)
|
||||
)
|
||||
|
||||
@@ -236,9 +244,8 @@ CALENDAR_EVENT_SCHEMA = vol.Schema(
|
||||
},
|
||||
_has_same_type("start", "end"),
|
||||
_has_timezone("start", "end"),
|
||||
_has_consistent_timezone("start", "end"),
|
||||
_as_local_timezone("start", "end"),
|
||||
_has_duration("start", "end"),
|
||||
_has_min_duration("start", "end", MIN_EVENT_DURATION),
|
||||
),
|
||||
extra=vol.ALLOW_EXTRA,
|
||||
)
|
||||
@@ -346,6 +353,16 @@ class CalendarEvent:
|
||||
f"Failed to validate CalendarEvent: {err}"
|
||||
) from err
|
||||
|
||||
# It is common to set a start an end date to be the same thing for
|
||||
# an all day event, but that is not a valid duration. Fix to have a
|
||||
# duration of one day.
|
||||
if (
|
||||
not isinstance(self.start, datetime.datetime)
|
||||
and not isinstance(self.end, datetime.datetime)
|
||||
and self.start == self.end
|
||||
):
|
||||
self.end = self.start + datetime.timedelta(days=1)
|
||||
|
||||
|
||||
def _event_dict_factory(obj: Iterable[tuple[str, Any]]) -> dict[str, str]:
|
||||
"""Convert CalendarEvent dataclass items to dictionary of attributes."""
|
||||
|
||||
@@ -380,7 +380,7 @@ async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
entity.async_write_ha_state()
|
||||
|
||||
unsub = async_track_time_interval(
|
||||
hass, update_tokens, TOKEN_CHANGE_INTERVAL, "Camera update tokens"
|
||||
hass, update_tokens, TOKEN_CHANGE_INTERVAL, name="Camera update tokens"
|
||||
)
|
||||
|
||||
@callback
|
||||
|
||||
@@ -14,6 +14,6 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/cast",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["casttube", "pychromecast"],
|
||||
"requirements": ["pychromecast==13.0.6"],
|
||||
"requirements": ["pychromecast==13.0.7"],
|
||||
"zeroconf": ["_googlecast._tcp.local."]
|
||||
}
|
||||
|
||||
@@ -137,8 +137,11 @@ class CommandSensor(SensorEntity):
|
||||
_LOGGER.warning("Unable to parse output as JSON: %s", value)
|
||||
else:
|
||||
_LOGGER.warning("Empty reply found when expecting JSON data")
|
||||
if self._value_template is None:
|
||||
self._attr_native_value = None
|
||||
return
|
||||
|
||||
elif self._value_template is not None:
|
||||
if self._value_template is not None:
|
||||
self._attr_native_value = (
|
||||
self._value_template.async_render_with_possible_json_value(
|
||||
value,
|
||||
|
||||
@@ -32,6 +32,7 @@ from .const import DEFAULT_EXPOSED_ATTRIBUTES, DEFAULT_EXPOSED_DOMAINS, DOMAIN
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
_DEFAULT_ERROR_TEXT = "Sorry, I couldn't understand that"
|
||||
_ENTITY_REGISTRY_UPDATE_FIELDS = ["aliases", "name", "original_name"]
|
||||
|
||||
REGEX_TYPE = type(re.compile(""))
|
||||
|
||||
@@ -450,8 +451,10 @@ class DefaultAgent(AbstractConversationAgent):
|
||||
|
||||
@core.callback
|
||||
def _async_handle_entity_registry_changed(self, event: core.Event) -> None:
|
||||
"""Clear names list cache when an entity changes aliases."""
|
||||
if event.data["action"] == "update" and "aliases" not in event.data["changes"]:
|
||||
"""Clear names list cache when an entity registry entry has changed."""
|
||||
if event.data["action"] == "update" and not any(
|
||||
field in event.data["changes"] for field in _ENTITY_REGISTRY_UPDATE_FIELDS
|
||||
):
|
||||
return
|
||||
self._slot_lists = None
|
||||
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
"""The darksky component."""
|
||||
@@ -1,9 +0,0 @@
|
||||
{
|
||||
"domain": "darksky",
|
||||
"name": "Dark Sky",
|
||||
"codeowners": ["@fabaff"],
|
||||
"documentation": "https://www.home-assistant.io/integrations/darksky",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["forecastio"],
|
||||
"requirements": ["python-forecastio==1.4.0"]
|
||||
}
|
||||
@@ -1,927 +0,0 @@
|
||||
"""Support for Dark Sky weather service."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass, field
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
from typing import Literal, NamedTuple
|
||||
|
||||
import forecastio
|
||||
from requests.exceptions import ConnectionError as ConnectError, HTTPError, Timeout
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
PLATFORM_SCHEMA,
|
||||
SensorDeviceClass,
|
||||
SensorEntity,
|
||||
SensorEntityDescription,
|
||||
SensorStateClass,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONF_API_KEY,
|
||||
CONF_LATITUDE,
|
||||
CONF_LONGITUDE,
|
||||
CONF_MONITORED_CONDITIONS,
|
||||
CONF_NAME,
|
||||
CONF_SCAN_INTERVAL,
|
||||
DEGREE,
|
||||
PERCENTAGE,
|
||||
UV_INDEX,
|
||||
UnitOfLength,
|
||||
UnitOfPrecipitationDepth,
|
||||
UnitOfPressure,
|
||||
UnitOfSpeed,
|
||||
UnitOfTemperature,
|
||||
UnitOfVolumetricFlux,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
from homeassistant.util import Throttle
|
||||
from homeassistant.util.unit_system import METRIC_SYSTEM
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
CONF_FORECAST = "forecast"
|
||||
CONF_HOURLY_FORECAST = "hourly_forecast"
|
||||
CONF_LANGUAGE = "language"
|
||||
CONF_UNITS = "units"
|
||||
|
||||
DEFAULT_LANGUAGE = "en"
|
||||
DEFAULT_NAME = "Dark Sky"
|
||||
SCAN_INTERVAL = timedelta(seconds=300)
|
||||
|
||||
DEPRECATED_SENSOR_TYPES = {
|
||||
"apparent_temperature_max",
|
||||
"apparent_temperature_min",
|
||||
"temperature_max",
|
||||
"temperature_min",
|
||||
}
|
||||
|
||||
MAP_UNIT_SYSTEM: dict[
|
||||
Literal["si", "us", "ca", "uk", "uk2"],
|
||||
Literal["si_unit", "us_unit", "ca_unit", "uk_unit", "uk2_unit"],
|
||||
] = {
|
||||
"si": "si_unit",
|
||||
"us": "us_unit",
|
||||
"ca": "ca_unit",
|
||||
"uk": "uk_unit",
|
||||
"uk2": "uk2_unit",
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class DarkskySensorEntityDescription(SensorEntityDescription):
|
||||
"""Describes Darksky sensor entity."""
|
||||
|
||||
si_unit: str | None = None
|
||||
us_unit: str | None = None
|
||||
ca_unit: str | None = None
|
||||
uk_unit: str | None = None
|
||||
uk2_unit: str | None = None
|
||||
forecast_mode: list[str] = field(default_factory=list)
|
||||
|
||||
|
||||
SENSOR_TYPES: dict[str, DarkskySensorEntityDescription] = {
|
||||
"summary": DarkskySensorEntityDescription(
|
||||
key="summary",
|
||||
name="Summary",
|
||||
forecast_mode=["currently", "hourly", "daily"],
|
||||
),
|
||||
"minutely_summary": DarkskySensorEntityDescription(
|
||||
key="minutely_summary",
|
||||
name="Minutely Summary",
|
||||
forecast_mode=[],
|
||||
),
|
||||
"hourly_summary": DarkskySensorEntityDescription(
|
||||
key="hourly_summary",
|
||||
name="Hourly Summary",
|
||||
forecast_mode=[],
|
||||
),
|
||||
"daily_summary": DarkskySensorEntityDescription(
|
||||
key="daily_summary",
|
||||
name="Daily Summary",
|
||||
forecast_mode=[],
|
||||
),
|
||||
"icon": DarkskySensorEntityDescription(
|
||||
key="icon",
|
||||
name="Icon",
|
||||
forecast_mode=["currently", "hourly", "daily"],
|
||||
),
|
||||
"nearest_storm_distance": DarkskySensorEntityDescription(
|
||||
key="nearest_storm_distance",
|
||||
name="Nearest Storm Distance",
|
||||
si_unit=UnitOfLength.KILOMETERS,
|
||||
us_unit=UnitOfLength.MILES,
|
||||
ca_unit=UnitOfLength.KILOMETERS,
|
||||
uk_unit=UnitOfLength.KILOMETERS,
|
||||
uk2_unit=UnitOfLength.MILES,
|
||||
icon="mdi:weather-lightning",
|
||||
forecast_mode=["currently"],
|
||||
),
|
||||
"nearest_storm_bearing": DarkskySensorEntityDescription(
|
||||
key="nearest_storm_bearing",
|
||||
name="Nearest Storm Bearing",
|
||||
si_unit=DEGREE,
|
||||
us_unit=DEGREE,
|
||||
ca_unit=DEGREE,
|
||||
uk_unit=DEGREE,
|
||||
uk2_unit=DEGREE,
|
||||
icon="mdi:weather-lightning",
|
||||
forecast_mode=["currently"],
|
||||
),
|
||||
"precip_type": DarkskySensorEntityDescription(
|
||||
key="precip_type",
|
||||
name="Precip",
|
||||
icon="mdi:weather-pouring",
|
||||
forecast_mode=["currently", "minutely", "hourly", "daily"],
|
||||
),
|
||||
"precip_intensity": DarkskySensorEntityDescription(
|
||||
key="precip_intensity",
|
||||
name="Precip Intensity",
|
||||
si_unit=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
|
||||
us_unit=UnitOfVolumetricFlux.INCHES_PER_HOUR,
|
||||
ca_unit=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
|
||||
uk_unit=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
|
||||
uk2_unit=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
|
||||
icon="mdi:weather-rainy",
|
||||
forecast_mode=["currently", "minutely", "hourly", "daily"],
|
||||
),
|
||||
"precip_probability": DarkskySensorEntityDescription(
|
||||
key="precip_probability",
|
||||
name="Precip Probability",
|
||||
si_unit=PERCENTAGE,
|
||||
us_unit=PERCENTAGE,
|
||||
ca_unit=PERCENTAGE,
|
||||
uk_unit=PERCENTAGE,
|
||||
uk2_unit=PERCENTAGE,
|
||||
icon="mdi:water-percent",
|
||||
forecast_mode=["currently", "minutely", "hourly", "daily"],
|
||||
),
|
||||
"precip_accumulation": DarkskySensorEntityDescription(
|
||||
key="precip_accumulation",
|
||||
name="Precip Accumulation",
|
||||
device_class=SensorDeviceClass.PRECIPITATION,
|
||||
si_unit=UnitOfPrecipitationDepth.CENTIMETERS,
|
||||
us_unit=UnitOfPrecipitationDepth.INCHES,
|
||||
ca_unit=UnitOfPrecipitationDepth.CENTIMETERS,
|
||||
uk_unit=UnitOfPrecipitationDepth.CENTIMETERS,
|
||||
uk2_unit=UnitOfPrecipitationDepth.CENTIMETERS,
|
||||
icon="mdi:weather-snowy",
|
||||
forecast_mode=["hourly", "daily"],
|
||||
),
|
||||
"temperature": DarkskySensorEntityDescription(
|
||||
key="temperature",
|
||||
name="Temperature",
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
si_unit=UnitOfTemperature.CELSIUS,
|
||||
us_unit=UnitOfTemperature.FAHRENHEIT,
|
||||
ca_unit=UnitOfTemperature.CELSIUS,
|
||||
uk_unit=UnitOfTemperature.CELSIUS,
|
||||
uk2_unit=UnitOfTemperature.CELSIUS,
|
||||
forecast_mode=["currently", "hourly"],
|
||||
),
|
||||
"apparent_temperature": DarkskySensorEntityDescription(
|
||||
key="apparent_temperature",
|
||||
name="Apparent Temperature",
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
si_unit=UnitOfTemperature.CELSIUS,
|
||||
us_unit=UnitOfTemperature.FAHRENHEIT,
|
||||
ca_unit=UnitOfTemperature.CELSIUS,
|
||||
uk_unit=UnitOfTemperature.CELSIUS,
|
||||
uk2_unit=UnitOfTemperature.CELSIUS,
|
||||
forecast_mode=["currently", "hourly"],
|
||||
),
|
||||
"dew_point": DarkskySensorEntityDescription(
|
||||
key="dew_point",
|
||||
name="Dew Point",
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
si_unit=UnitOfTemperature.CELSIUS,
|
||||
us_unit=UnitOfTemperature.FAHRENHEIT,
|
||||
ca_unit=UnitOfTemperature.CELSIUS,
|
||||
uk_unit=UnitOfTemperature.CELSIUS,
|
||||
uk2_unit=UnitOfTemperature.CELSIUS,
|
||||
forecast_mode=["currently", "hourly", "daily"],
|
||||
),
|
||||
"wind_speed": DarkskySensorEntityDescription(
|
||||
key="wind_speed",
|
||||
name="Wind Speed",
|
||||
device_class=SensorDeviceClass.WIND_SPEED,
|
||||
si_unit=UnitOfSpeed.METERS_PER_SECOND,
|
||||
us_unit=UnitOfSpeed.MILES_PER_HOUR,
|
||||
ca_unit=UnitOfSpeed.KILOMETERS_PER_HOUR,
|
||||
uk_unit=UnitOfSpeed.MILES_PER_HOUR,
|
||||
uk2_unit=UnitOfSpeed.MILES_PER_HOUR,
|
||||
forecast_mode=["currently", "hourly", "daily"],
|
||||
),
|
||||
"wind_bearing": DarkskySensorEntityDescription(
|
||||
key="wind_bearing",
|
||||
name="Wind Bearing",
|
||||
si_unit=DEGREE,
|
||||
us_unit=DEGREE,
|
||||
ca_unit=DEGREE,
|
||||
uk_unit=DEGREE,
|
||||
uk2_unit=DEGREE,
|
||||
icon="mdi:compass",
|
||||
forecast_mode=["currently", "hourly", "daily"],
|
||||
),
|
||||
"wind_gust": DarkskySensorEntityDescription(
|
||||
key="wind_gust",
|
||||
name="Wind Gust",
|
||||
device_class=SensorDeviceClass.WIND_SPEED,
|
||||
si_unit=UnitOfSpeed.METERS_PER_SECOND,
|
||||
us_unit=UnitOfSpeed.MILES_PER_HOUR,
|
||||
ca_unit=UnitOfSpeed.KILOMETERS_PER_HOUR,
|
||||
uk_unit=UnitOfSpeed.MILES_PER_HOUR,
|
||||
uk2_unit=UnitOfSpeed.MILES_PER_HOUR,
|
||||
icon="mdi:weather-windy-variant",
|
||||
forecast_mode=["currently", "hourly", "daily"],
|
||||
),
|
||||
"cloud_cover": DarkskySensorEntityDescription(
|
||||
key="cloud_cover",
|
||||
name="Cloud Coverage",
|
||||
si_unit=PERCENTAGE,
|
||||
us_unit=PERCENTAGE,
|
||||
ca_unit=PERCENTAGE,
|
||||
uk_unit=PERCENTAGE,
|
||||
uk2_unit=PERCENTAGE,
|
||||
icon="mdi:weather-partly-cloudy",
|
||||
forecast_mode=["currently", "hourly", "daily"],
|
||||
),
|
||||
"humidity": DarkskySensorEntityDescription(
|
||||
key="humidity",
|
||||
name="Humidity",
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
si_unit=PERCENTAGE,
|
||||
us_unit=PERCENTAGE,
|
||||
ca_unit=PERCENTAGE,
|
||||
uk_unit=PERCENTAGE,
|
||||
uk2_unit=PERCENTAGE,
|
||||
forecast_mode=["currently", "hourly", "daily"],
|
||||
),
|
||||
"pressure": DarkskySensorEntityDescription(
|
||||
key="pressure",
|
||||
name="Pressure",
|
||||
device_class=SensorDeviceClass.PRESSURE,
|
||||
si_unit=UnitOfPressure.MBAR,
|
||||
us_unit=UnitOfPressure.MBAR,
|
||||
ca_unit=UnitOfPressure.MBAR,
|
||||
uk_unit=UnitOfPressure.MBAR,
|
||||
uk2_unit=UnitOfPressure.MBAR,
|
||||
forecast_mode=["currently", "hourly", "daily"],
|
||||
),
|
||||
"visibility": DarkskySensorEntityDescription(
|
||||
key="visibility",
|
||||
name="Visibility",
|
||||
si_unit=UnitOfLength.KILOMETERS,
|
||||
us_unit=UnitOfLength.MILES,
|
||||
ca_unit=UnitOfLength.KILOMETERS,
|
||||
uk_unit=UnitOfLength.KILOMETERS,
|
||||
uk2_unit=UnitOfLength.MILES,
|
||||
icon="mdi:eye",
|
||||
forecast_mode=["currently", "hourly", "daily"],
|
||||
),
|
||||
"ozone": DarkskySensorEntityDescription(
|
||||
key="ozone",
|
||||
name="Ozone",
|
||||
device_class=SensorDeviceClass.OZONE,
|
||||
si_unit="DU",
|
||||
us_unit="DU",
|
||||
ca_unit="DU",
|
||||
uk_unit="DU",
|
||||
uk2_unit="DU",
|
||||
forecast_mode=["currently", "hourly", "daily"],
|
||||
),
|
||||
"apparent_temperature_max": DarkskySensorEntityDescription(
|
||||
key="apparent_temperature_max",
|
||||
name="Daily High Apparent Temperature",
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
si_unit=UnitOfTemperature.CELSIUS,
|
||||
us_unit=UnitOfTemperature.FAHRENHEIT,
|
||||
ca_unit=UnitOfTemperature.CELSIUS,
|
||||
uk_unit=UnitOfTemperature.CELSIUS,
|
||||
uk2_unit=UnitOfTemperature.CELSIUS,
|
||||
forecast_mode=["daily"],
|
||||
),
|
||||
"apparent_temperature_high": DarkskySensorEntityDescription(
|
||||
key="apparent_temperature_high",
|
||||
name="Daytime High Apparent Temperature",
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
si_unit=UnitOfTemperature.CELSIUS,
|
||||
us_unit=UnitOfTemperature.FAHRENHEIT,
|
||||
ca_unit=UnitOfTemperature.CELSIUS,
|
||||
uk_unit=UnitOfTemperature.CELSIUS,
|
||||
uk2_unit=UnitOfTemperature.CELSIUS,
|
||||
forecast_mode=["daily"],
|
||||
),
|
||||
"apparent_temperature_min": DarkskySensorEntityDescription(
|
||||
key="apparent_temperature_min",
|
||||
name="Daily Low Apparent Temperature",
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
si_unit=UnitOfTemperature.CELSIUS,
|
||||
us_unit=UnitOfTemperature.FAHRENHEIT,
|
||||
ca_unit=UnitOfTemperature.CELSIUS,
|
||||
uk_unit=UnitOfTemperature.CELSIUS,
|
||||
uk2_unit=UnitOfTemperature.CELSIUS,
|
||||
forecast_mode=["daily"],
|
||||
),
|
||||
"apparent_temperature_low": DarkskySensorEntityDescription(
|
||||
key="apparent_temperature_low",
|
||||
name="Overnight Low Apparent Temperature",
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
si_unit=UnitOfTemperature.CELSIUS,
|
||||
us_unit=UnitOfTemperature.FAHRENHEIT,
|
||||
ca_unit=UnitOfTemperature.CELSIUS,
|
||||
uk_unit=UnitOfTemperature.CELSIUS,
|
||||
uk2_unit=UnitOfTemperature.CELSIUS,
|
||||
forecast_mode=["daily"],
|
||||
),
|
||||
"temperature_max": DarkskySensorEntityDescription(
|
||||
key="temperature_max",
|
||||
name="Daily High Temperature",
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
si_unit=UnitOfTemperature.CELSIUS,
|
||||
us_unit=UnitOfTemperature.FAHRENHEIT,
|
||||
ca_unit=UnitOfTemperature.CELSIUS,
|
||||
uk_unit=UnitOfTemperature.CELSIUS,
|
||||
uk2_unit=UnitOfTemperature.CELSIUS,
|
||||
forecast_mode=["daily"],
|
||||
),
|
||||
"temperature_high": DarkskySensorEntityDescription(
|
||||
key="temperature_high",
|
||||
name="Daytime High Temperature",
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
si_unit=UnitOfTemperature.CELSIUS,
|
||||
us_unit=UnitOfTemperature.FAHRENHEIT,
|
||||
ca_unit=UnitOfTemperature.CELSIUS,
|
||||
uk_unit=UnitOfTemperature.CELSIUS,
|
||||
uk2_unit=UnitOfTemperature.CELSIUS,
|
||||
forecast_mode=["daily"],
|
||||
),
|
||||
"temperature_min": DarkskySensorEntityDescription(
|
||||
key="temperature_min",
|
||||
name="Daily Low Temperature",
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
si_unit=UnitOfTemperature.CELSIUS,
|
||||
us_unit=UnitOfTemperature.FAHRENHEIT,
|
||||
ca_unit=UnitOfTemperature.CELSIUS,
|
||||
uk_unit=UnitOfTemperature.CELSIUS,
|
||||
uk2_unit=UnitOfTemperature.CELSIUS,
|
||||
forecast_mode=["daily"],
|
||||
),
|
||||
"temperature_low": DarkskySensorEntityDescription(
|
||||
key="temperature_low",
|
||||
name="Overnight Low Temperature",
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
si_unit=UnitOfTemperature.CELSIUS,
|
||||
us_unit=UnitOfTemperature.FAHRENHEIT,
|
||||
ca_unit=UnitOfTemperature.CELSIUS,
|
||||
uk_unit=UnitOfTemperature.CELSIUS,
|
||||
uk2_unit=UnitOfTemperature.CELSIUS,
|
||||
forecast_mode=["daily"],
|
||||
),
|
||||
"precip_intensity_max": DarkskySensorEntityDescription(
|
||||
key="precip_intensity_max",
|
||||
name="Daily Max Precip Intensity",
|
||||
si_unit=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
|
||||
us_unit=UnitOfVolumetricFlux.INCHES_PER_HOUR,
|
||||
ca_unit=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
|
||||
uk_unit=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
|
||||
uk2_unit=UnitOfVolumetricFlux.MILLIMETERS_PER_HOUR,
|
||||
icon="mdi:thermometer",
|
||||
forecast_mode=["daily"],
|
||||
),
|
||||
"uv_index": DarkskySensorEntityDescription(
|
||||
key="uv_index",
|
||||
name="UV Index",
|
||||
si_unit=UV_INDEX,
|
||||
us_unit=UV_INDEX,
|
||||
ca_unit=UV_INDEX,
|
||||
uk_unit=UV_INDEX,
|
||||
uk2_unit=UV_INDEX,
|
||||
icon="mdi:weather-sunny",
|
||||
forecast_mode=["currently", "hourly", "daily"],
|
||||
),
|
||||
"moon_phase": DarkskySensorEntityDescription(
|
||||
key="moon_phase",
|
||||
name="Moon Phase",
|
||||
icon="mdi:weather-night",
|
||||
forecast_mode=["daily"],
|
||||
),
|
||||
"sunrise_time": DarkskySensorEntityDescription(
|
||||
key="sunrise_time",
|
||||
name="Sunrise",
|
||||
icon="mdi:white-balance-sunny",
|
||||
forecast_mode=["daily"],
|
||||
),
|
||||
"sunset_time": DarkskySensorEntityDescription(
|
||||
key="sunset_time",
|
||||
name="Sunset",
|
||||
icon="mdi:weather-night",
|
||||
forecast_mode=["daily"],
|
||||
),
|
||||
"alerts": DarkskySensorEntityDescription(
|
||||
key="alerts",
|
||||
name="Alerts",
|
||||
icon="mdi:alert-circle-outline",
|
||||
forecast_mode=[],
|
||||
),
|
||||
}
|
||||
|
||||
|
||||
class ConditionPicture(NamedTuple):
|
||||
"""Entity picture and icon for condition."""
|
||||
|
||||
entity_picture: str
|
||||
icon: str
|
||||
|
||||
|
||||
CONDITION_PICTURES: dict[str, ConditionPicture] = {
|
||||
"clear-day": ConditionPicture(
|
||||
entity_picture="/static/images/darksky/weather-sunny.svg",
|
||||
icon="mdi:weather-sunny",
|
||||
),
|
||||
"clear-night": ConditionPicture(
|
||||
entity_picture="/static/images/darksky/weather-night.svg",
|
||||
icon="mdi:weather-night",
|
||||
),
|
||||
"rain": ConditionPicture(
|
||||
entity_picture="/static/images/darksky/weather-pouring.svg",
|
||||
icon="mdi:weather-pouring",
|
||||
),
|
||||
"snow": ConditionPicture(
|
||||
entity_picture="/static/images/darksky/weather-snowy.svg",
|
||||
icon="mdi:weather-snowy",
|
||||
),
|
||||
"sleet": ConditionPicture(
|
||||
entity_picture="/static/images/darksky/weather-hail.svg",
|
||||
icon="mdi:weather-snowy-rainy",
|
||||
),
|
||||
"wind": ConditionPicture(
|
||||
entity_picture="/static/images/darksky/weather-windy.svg",
|
||||
icon="mdi:weather-windy",
|
||||
),
|
||||
"fog": ConditionPicture(
|
||||
entity_picture="/static/images/darksky/weather-fog.svg",
|
||||
icon="mdi:weather-fog",
|
||||
),
|
||||
"cloudy": ConditionPicture(
|
||||
entity_picture="/static/images/darksky/weather-cloudy.svg",
|
||||
icon="mdi:weather-cloudy",
|
||||
),
|
||||
"partly-cloudy-day": ConditionPicture(
|
||||
entity_picture="/static/images/darksky/weather-partlycloudy.svg",
|
||||
icon="mdi:weather-partly-cloudy",
|
||||
),
|
||||
"partly-cloudy-night": ConditionPicture(
|
||||
entity_picture="/static/images/darksky/weather-cloudy.svg",
|
||||
icon="mdi:weather-night-partly-cloudy",
|
||||
),
|
||||
}
|
||||
|
||||
# Language Supported Codes
|
||||
LANGUAGE_CODES = [
|
||||
"ar",
|
||||
"az",
|
||||
"be",
|
||||
"bg",
|
||||
"bn",
|
||||
"bs",
|
||||
"ca",
|
||||
"cs",
|
||||
"da",
|
||||
"de",
|
||||
"el",
|
||||
"en",
|
||||
"ja",
|
||||
"ka",
|
||||
"kn",
|
||||
"ko",
|
||||
"eo",
|
||||
"es",
|
||||
"et",
|
||||
"fi",
|
||||
"fr",
|
||||
"he",
|
||||
"hi",
|
||||
"hr",
|
||||
"hu",
|
||||
"id",
|
||||
"is",
|
||||
"it",
|
||||
"kw",
|
||||
"lv",
|
||||
"ml",
|
||||
"mr",
|
||||
"nb",
|
||||
"nl",
|
||||
"pa",
|
||||
"pl",
|
||||
"pt",
|
||||
"ro",
|
||||
"ru",
|
||||
"sk",
|
||||
"sl",
|
||||
"sr",
|
||||
"sv",
|
||||
"ta",
|
||||
"te",
|
||||
"tet",
|
||||
"tr",
|
||||
"uk",
|
||||
"ur",
|
||||
"x-pig-latin",
|
||||
"zh",
|
||||
"zh-tw",
|
||||
]
|
||||
|
||||
ALLOWED_UNITS = ["auto", "si", "us", "ca", "uk", "uk2"]
|
||||
|
||||
ALERTS_ATTRS = ["time", "description", "expires", "severity", "uri", "regions", "title"]
|
||||
|
||||
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||
{
|
||||
vol.Required(CONF_MONITORED_CONDITIONS): vol.All(
|
||||
cv.ensure_list, [vol.In(SENSOR_TYPES)]
|
||||
),
|
||||
vol.Required(CONF_API_KEY): cv.string,
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
vol.Optional(CONF_UNITS): vol.In(ALLOWED_UNITS),
|
||||
vol.Optional(CONF_LANGUAGE, default=DEFAULT_LANGUAGE): vol.In(LANGUAGE_CODES),
|
||||
vol.Inclusive(
|
||||
CONF_LATITUDE, "coordinates", "Latitude and longitude must exist together"
|
||||
): cv.latitude,
|
||||
vol.Inclusive(
|
||||
CONF_LONGITUDE, "coordinates", "Latitude and longitude must exist together"
|
||||
): cv.longitude,
|
||||
vol.Optional(CONF_FORECAST): vol.All(cv.ensure_list, [vol.Range(min=0, max=7)]),
|
||||
vol.Optional(CONF_HOURLY_FORECAST): vol.All(
|
||||
cv.ensure_list, [vol.Range(min=0, max=48)]
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
def setup_platform(
|
||||
hass: HomeAssistant,
|
||||
config: ConfigType,
|
||||
add_entities: AddEntitiesCallback,
|
||||
discovery_info: DiscoveryInfoType | None = None,
|
||||
) -> None:
|
||||
"""Set up the Dark Sky sensor."""
|
||||
latitude = config.get(CONF_LATITUDE, hass.config.latitude)
|
||||
longitude = config.get(CONF_LONGITUDE, hass.config.longitude)
|
||||
language = config.get(CONF_LANGUAGE)
|
||||
interval = config.get(CONF_SCAN_INTERVAL, SCAN_INTERVAL)
|
||||
|
||||
if CONF_UNITS in config:
|
||||
units = config[CONF_UNITS]
|
||||
elif hass.config.units is METRIC_SYSTEM:
|
||||
units = "si"
|
||||
else:
|
||||
units = "us"
|
||||
|
||||
forecast_data = DarkSkyData(
|
||||
api_key=config.get(CONF_API_KEY),
|
||||
latitude=latitude,
|
||||
longitude=longitude,
|
||||
units=units,
|
||||
language=language,
|
||||
interval=interval,
|
||||
)
|
||||
forecast_data.update()
|
||||
forecast_data.update_currently()
|
||||
|
||||
# If connection failed don't setup platform.
|
||||
if forecast_data.data is None:
|
||||
return
|
||||
|
||||
name = config.get(CONF_NAME)
|
||||
|
||||
forecast = config.get(CONF_FORECAST)
|
||||
forecast_hour = config.get(CONF_HOURLY_FORECAST)
|
||||
sensors: list[SensorEntity] = []
|
||||
for variable in config[CONF_MONITORED_CONDITIONS]:
|
||||
if variable in DEPRECATED_SENSOR_TYPES:
|
||||
_LOGGER.warning("Monitored condition %s is deprecated", variable)
|
||||
description = SENSOR_TYPES[variable]
|
||||
if not description.forecast_mode or "currently" in description.forecast_mode:
|
||||
if variable == "alerts":
|
||||
sensors.append(DarkSkyAlertSensor(forecast_data, description, name))
|
||||
else:
|
||||
sensors.append(DarkSkySensor(forecast_data, description, name))
|
||||
|
||||
if forecast is not None and "daily" in description.forecast_mode:
|
||||
sensors.extend(
|
||||
[
|
||||
DarkSkySensor(
|
||||
forecast_data, description, name, forecast_day=forecast_day
|
||||
)
|
||||
for forecast_day in forecast
|
||||
]
|
||||
)
|
||||
if forecast_hour is not None and "hourly" in description.forecast_mode:
|
||||
sensors.extend(
|
||||
[
|
||||
DarkSkySensor(
|
||||
forecast_data, description, name, forecast_hour=forecast_h
|
||||
)
|
||||
for forecast_h in forecast_hour
|
||||
]
|
||||
)
|
||||
|
||||
add_entities(sensors, True)
|
||||
|
||||
|
||||
class DarkSkySensor(SensorEntity):
|
||||
"""Implementation of a Dark Sky sensor."""
|
||||
|
||||
_attr_attribution = "Powered by Dark Sky"
|
||||
entity_description: DarkskySensorEntityDescription
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
forecast_data,
|
||||
description: DarkskySensorEntityDescription,
|
||||
name,
|
||||
forecast_day=None,
|
||||
forecast_hour=None,
|
||||
) -> None:
|
||||
"""Initialize the sensor."""
|
||||
self.entity_description = description
|
||||
self.forecast_data = forecast_data
|
||||
self.forecast_day = forecast_day
|
||||
self.forecast_hour = forecast_hour
|
||||
self._icon: str | None = None
|
||||
|
||||
if forecast_day is not None:
|
||||
self._attr_name = f"{name} {description.name} {forecast_day}d"
|
||||
elif forecast_hour is not None:
|
||||
self._attr_name = f"{name} {description.name} {forecast_hour}h"
|
||||
else:
|
||||
self._attr_name = f"{name} {description.name}"
|
||||
|
||||
@property
|
||||
def unit_system(self):
|
||||
"""Return the unit system of this entity."""
|
||||
return self.forecast_data.unit_system
|
||||
|
||||
@property
|
||||
def entity_picture(self) -> str | None:
|
||||
"""Return the entity picture to use in the frontend, if any."""
|
||||
if self._icon is None or "summary" not in self.entity_description.key:
|
||||
return None
|
||||
|
||||
if self._icon in CONDITION_PICTURES:
|
||||
return CONDITION_PICTURES[self._icon].entity_picture
|
||||
|
||||
return None
|
||||
|
||||
def update_unit_of_measurement(self) -> None:
|
||||
"""Update units based on unit system."""
|
||||
unit_key = MAP_UNIT_SYSTEM.get(self.unit_system, "si_unit")
|
||||
self._attr_native_unit_of_measurement = getattr(
|
||||
self.entity_description, unit_key
|
||||
)
|
||||
|
||||
@property
|
||||
def icon(self) -> str | None:
|
||||
"""Icon to use in the frontend, if any."""
|
||||
if (
|
||||
"summary" in self.entity_description.key
|
||||
and self._icon in CONDITION_PICTURES
|
||||
):
|
||||
return CONDITION_PICTURES[self._icon].icon
|
||||
|
||||
return self.entity_description.icon
|
||||
|
||||
def update(self) -> None:
|
||||
"""Get the latest data from Dark Sky and updates the states."""
|
||||
# Call the API for new forecast data. Each sensor will re-trigger this
|
||||
# same exact call, but that's fine. We cache results for a short period
|
||||
# of time to prevent hitting API limits. Note that Dark Sky will
|
||||
# charge users for too many calls in 1 day, so take care when updating.
|
||||
self.forecast_data.update()
|
||||
self.update_unit_of_measurement()
|
||||
|
||||
sensor_type = self.entity_description.key
|
||||
if sensor_type == "minutely_summary":
|
||||
self.forecast_data.update_minutely()
|
||||
minutely = self.forecast_data.data_minutely
|
||||
self._attr_native_value = getattr(minutely, "summary", "")
|
||||
self._icon = getattr(minutely, "icon", "")
|
||||
elif sensor_type == "hourly_summary":
|
||||
self.forecast_data.update_hourly()
|
||||
hourly = self.forecast_data.data_hourly
|
||||
self._attr_native_value = getattr(hourly, "summary", "")
|
||||
self._icon = getattr(hourly, "icon", "")
|
||||
elif self.forecast_hour is not None:
|
||||
self.forecast_data.update_hourly()
|
||||
hourly = self.forecast_data.data_hourly
|
||||
if hasattr(hourly, "data"):
|
||||
self._attr_native_value = self.get_state(
|
||||
hourly.data[self.forecast_hour]
|
||||
)
|
||||
else:
|
||||
self._attr_native_value = 0
|
||||
elif sensor_type == "daily_summary":
|
||||
self.forecast_data.update_daily()
|
||||
daily = self.forecast_data.data_daily
|
||||
self._attr_native_value = getattr(daily, "summary", "")
|
||||
self._icon = getattr(daily, "icon", "")
|
||||
elif self.forecast_day is not None:
|
||||
self.forecast_data.update_daily()
|
||||
daily = self.forecast_data.data_daily
|
||||
if hasattr(daily, "data"):
|
||||
self._attr_native_value = self.get_state(daily.data[self.forecast_day])
|
||||
else:
|
||||
self._attr_native_value = 0
|
||||
else:
|
||||
self.forecast_data.update_currently()
|
||||
currently = self.forecast_data.data_currently
|
||||
self._attr_native_value = self.get_state(currently)
|
||||
|
||||
def get_state(self, data):
|
||||
"""Return a new state based on the type.
|
||||
|
||||
If the sensor type is unknown, the current state is returned.
|
||||
"""
|
||||
sensor_type = self.entity_description.key
|
||||
lookup_type = convert_to_camel(sensor_type)
|
||||
|
||||
if (state := getattr(data, lookup_type, None)) is None:
|
||||
return None
|
||||
|
||||
if "summary" in sensor_type:
|
||||
self._icon = getattr(data, "icon", "")
|
||||
|
||||
# Some state data needs to be rounded to whole values or converted to
|
||||
# percentages
|
||||
if sensor_type in {"precip_probability", "cloud_cover", "humidity"}:
|
||||
return round(state * 100, 1)
|
||||
|
||||
if sensor_type in {
|
||||
"dew_point",
|
||||
"temperature",
|
||||
"apparent_temperature",
|
||||
"temperature_low",
|
||||
"apparent_temperature_low",
|
||||
"temperature_min",
|
||||
"apparent_temperature_min",
|
||||
"temperature_high",
|
||||
"apparent_temperature_high",
|
||||
"temperature_max",
|
||||
"apparent_temperature_max",
|
||||
"precip_accumulation",
|
||||
"pressure",
|
||||
"ozone",
|
||||
"uvIndex",
|
||||
}:
|
||||
return round(state, 1)
|
||||
return state
|
||||
|
||||
|
||||
class DarkSkyAlertSensor(SensorEntity):
|
||||
"""Implementation of a Dark Sky sensor."""
|
||||
|
||||
entity_description: DarkskySensorEntityDescription
|
||||
_attr_native_value: int | None
|
||||
|
||||
def __init__(
|
||||
self, forecast_data, description: DarkskySensorEntityDescription, name
|
||||
) -> None:
|
||||
"""Initialize the sensor."""
|
||||
self.entity_description = description
|
||||
self.forecast_data = forecast_data
|
||||
self._alerts = None
|
||||
|
||||
self._attr_name = f"{name} {description.name}"
|
||||
|
||||
@property
|
||||
def icon(self):
|
||||
"""Icon to use in the frontend, if any."""
|
||||
if self._attr_native_value is not None and self._attr_native_value > 0:
|
||||
return "mdi:alert-circle"
|
||||
return "mdi:alert-circle-outline"
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self):
|
||||
"""Return the state attributes."""
|
||||
return self._alerts
|
||||
|
||||
def update(self) -> None:
|
||||
"""Get the latest data from Dark Sky and updates the states."""
|
||||
# Call the API for new forecast data. Each sensor will re-trigger this
|
||||
# same exact call, but that's fine. We cache results for a short period
|
||||
# of time to prevent hitting API limits. Note that Dark Sky will
|
||||
# charge users for too many calls in 1 day, so take care when updating.
|
||||
self.forecast_data.update()
|
||||
self.forecast_data.update_alerts()
|
||||
alerts = self.forecast_data.data_alerts
|
||||
self._attr_native_value = self.get_state(alerts)
|
||||
|
||||
def get_state(self, data):
|
||||
"""Return a new state based on the type.
|
||||
|
||||
If the sensor type is unknown, the current state is returned.
|
||||
"""
|
||||
alerts = {}
|
||||
if data is None:
|
||||
self._alerts = alerts
|
||||
return data
|
||||
|
||||
multiple_alerts = len(data) > 1
|
||||
for i, alert in enumerate(data):
|
||||
for attr in ALERTS_ATTRS:
|
||||
if multiple_alerts:
|
||||
dkey = f"{attr}_{i!s}"
|
||||
else:
|
||||
dkey = attr
|
||||
alerts[dkey] = getattr(alert, attr)
|
||||
self._alerts = alerts
|
||||
|
||||
return len(data)
|
||||
|
||||
|
||||
def convert_to_camel(data):
|
||||
"""Convert snake case (foo_bar_bat) to camel case (fooBarBat).
|
||||
|
||||
This is not pythonic, but needed for certain situations.
|
||||
"""
|
||||
components = data.split("_")
|
||||
capital_components = "".join(x.title() for x in components[1:])
|
||||
return f"{components[0]}{capital_components}"
|
||||
|
||||
|
||||
class DarkSkyData:
|
||||
"""Get the latest data from Darksky."""
|
||||
|
||||
def __init__(self, api_key, latitude, longitude, units, language, interval):
|
||||
"""Initialize the data object."""
|
||||
self._api_key = api_key
|
||||
self.latitude = latitude
|
||||
self.longitude = longitude
|
||||
self.units = units
|
||||
self.language = language
|
||||
self._connect_error = False
|
||||
|
||||
self.data = None
|
||||
self.unit_system = None
|
||||
self.data_currently = None
|
||||
self.data_minutely = None
|
||||
self.data_hourly = None
|
||||
self.data_daily = None
|
||||
self.data_alerts = None
|
||||
|
||||
# Apply throttling to methods using configured interval
|
||||
self.update = Throttle(interval)(self._update)
|
||||
self.update_currently = Throttle(interval)(self._update_currently)
|
||||
self.update_minutely = Throttle(interval)(self._update_minutely)
|
||||
self.update_hourly = Throttle(interval)(self._update_hourly)
|
||||
self.update_daily = Throttle(interval)(self._update_daily)
|
||||
self.update_alerts = Throttle(interval)(self._update_alerts)
|
||||
|
||||
def _update(self):
|
||||
"""Get the latest data from Dark Sky."""
|
||||
try:
|
||||
self.data = forecastio.load_forecast(
|
||||
self._api_key,
|
||||
self.latitude,
|
||||
self.longitude,
|
||||
units=self.units,
|
||||
lang=self.language,
|
||||
)
|
||||
if self._connect_error:
|
||||
self._connect_error = False
|
||||
_LOGGER.info("Reconnected to Dark Sky")
|
||||
except (ConnectError, HTTPError, Timeout, ValueError) as error:
|
||||
if not self._connect_error:
|
||||
self._connect_error = True
|
||||
_LOGGER.error("Unable to connect to Dark Sky: %s", error)
|
||||
self.data = None
|
||||
self.unit_system = self.data and self.data.json["flags"]["units"]
|
||||
|
||||
def _update_currently(self):
|
||||
"""Update currently data."""
|
||||
self.data_currently = self.data and self.data.currently()
|
||||
|
||||
def _update_minutely(self):
|
||||
"""Update minutely data."""
|
||||
self.data_minutely = self.data and self.data.minutely()
|
||||
|
||||
def _update_hourly(self):
|
||||
"""Update hourly data."""
|
||||
self.data_hourly = self.data and self.data.hourly()
|
||||
|
||||
def _update_daily(self):
|
||||
"""Update daily data."""
|
||||
self.data_daily = self.data and self.data.daily()
|
||||
|
||||
def _update_alerts(self):
|
||||
"""Update alerts data."""
|
||||
self.data_alerts = self.data and self.data.alerts()
|
||||
@@ -1,281 +0,0 @@
|
||||
"""Support for retrieving meteorological data from Dark Sky."""
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import timedelta
|
||||
import logging
|
||||
|
||||
import forecastio
|
||||
from requests.exceptions import ConnectionError as ConnectError, HTTPError, Timeout
|
||||
import voluptuous as vol
|
||||
|
||||
from homeassistant.components.weather import (
|
||||
ATTR_CONDITION_CLEAR_NIGHT,
|
||||
ATTR_CONDITION_CLOUDY,
|
||||
ATTR_CONDITION_FOG,
|
||||
ATTR_CONDITION_HAIL,
|
||||
ATTR_CONDITION_LIGHTNING,
|
||||
ATTR_CONDITION_PARTLYCLOUDY,
|
||||
ATTR_CONDITION_RAINY,
|
||||
ATTR_CONDITION_SNOWY,
|
||||
ATTR_CONDITION_SNOWY_RAINY,
|
||||
ATTR_CONDITION_SUNNY,
|
||||
ATTR_CONDITION_WINDY,
|
||||
ATTR_FORECAST_CONDITION,
|
||||
ATTR_FORECAST_NATIVE_PRECIPITATION,
|
||||
ATTR_FORECAST_NATIVE_TEMP,
|
||||
ATTR_FORECAST_NATIVE_TEMP_LOW,
|
||||
ATTR_FORECAST_NATIVE_WIND_SPEED,
|
||||
ATTR_FORECAST_TIME,
|
||||
ATTR_FORECAST_WIND_BEARING,
|
||||
PLATFORM_SCHEMA,
|
||||
WeatherEntity,
|
||||
)
|
||||
from homeassistant.const import (
|
||||
CONF_API_KEY,
|
||||
CONF_LATITUDE,
|
||||
CONF_LONGITUDE,
|
||||
CONF_MODE,
|
||||
CONF_NAME,
|
||||
UnitOfLength,
|
||||
UnitOfPrecipitationDepth,
|
||||
UnitOfPressure,
|
||||
UnitOfSpeed,
|
||||
UnitOfTemperature,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import ConfigType, DiscoveryInfoType
|
||||
from homeassistant.util import Throttle
|
||||
from homeassistant.util.dt import utc_from_timestamp
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
ATTRIBUTION = "Powered by Dark Sky"
|
||||
|
||||
FORECAST_MODE = ["hourly", "daily"]
|
||||
|
||||
MAP_CONDITION = {
|
||||
"clear-day": ATTR_CONDITION_SUNNY,
|
||||
"clear-night": ATTR_CONDITION_CLEAR_NIGHT,
|
||||
"rain": ATTR_CONDITION_RAINY,
|
||||
"snow": ATTR_CONDITION_SNOWY,
|
||||
"sleet": ATTR_CONDITION_SNOWY_RAINY,
|
||||
"wind": ATTR_CONDITION_WINDY,
|
||||
"fog": ATTR_CONDITION_FOG,
|
||||
"cloudy": ATTR_CONDITION_CLOUDY,
|
||||
"partly-cloudy-day": ATTR_CONDITION_PARTLYCLOUDY,
|
||||
"partly-cloudy-night": ATTR_CONDITION_PARTLYCLOUDY,
|
||||
"hail": ATTR_CONDITION_HAIL,
|
||||
"thunderstorm": ATTR_CONDITION_LIGHTNING,
|
||||
"tornado": None,
|
||||
}
|
||||
|
||||
CONF_UNITS = "units"
|
||||
|
||||
DEFAULT_NAME = "Dark Sky"
|
||||
|
||||
PLATFORM_SCHEMA = vol.All(
|
||||
cv.removed(CONF_UNITS),
|
||||
PLATFORM_SCHEMA.extend(
|
||||
{
|
||||
vol.Required(CONF_API_KEY): cv.string,
|
||||
vol.Optional(CONF_LATITUDE): cv.latitude,
|
||||
vol.Optional(CONF_LONGITUDE): cv.longitude,
|
||||
vol.Optional(CONF_MODE, default="hourly"): vol.In(FORECAST_MODE),
|
||||
vol.Optional(CONF_UNITS): vol.In(["auto", "si", "us", "ca", "uk", "uk2"]),
|
||||
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
|
||||
}
|
||||
),
|
||||
)
|
||||
|
||||
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=3)
|
||||
|
||||
|
||||
def setup_platform(
|
||||
hass: HomeAssistant,
|
||||
config: ConfigType,
|
||||
add_entities: AddEntitiesCallback,
|
||||
discovery_info: DiscoveryInfoType | None = None,
|
||||
) -> None:
|
||||
"""Set up the Dark Sky weather."""
|
||||
latitude = config.get(CONF_LATITUDE, hass.config.latitude)
|
||||
longitude = config.get(CONF_LONGITUDE, hass.config.longitude)
|
||||
name = config.get(CONF_NAME)
|
||||
mode = config.get(CONF_MODE)
|
||||
|
||||
units = "si"
|
||||
dark_sky = DarkSkyData(config.get(CONF_API_KEY), latitude, longitude, units)
|
||||
|
||||
add_entities([DarkSkyWeather(name, dark_sky, mode)], True)
|
||||
|
||||
|
||||
class DarkSkyWeather(WeatherEntity):
|
||||
"""Representation of a weather condition."""
|
||||
|
||||
_attr_native_precipitation_unit = UnitOfPrecipitationDepth.MILLIMETERS
|
||||
_attr_native_pressure_unit = UnitOfPressure.MBAR
|
||||
_attr_native_temperature_unit = UnitOfTemperature.CELSIUS
|
||||
_attr_native_visibility_unit = UnitOfLength.KILOMETERS
|
||||
_attr_native_wind_speed_unit = UnitOfSpeed.METERS_PER_SECOND
|
||||
|
||||
def __init__(self, name, dark_sky, mode):
|
||||
"""Initialize Dark Sky weather."""
|
||||
self._name = name
|
||||
self._dark_sky = dark_sky
|
||||
self._mode = mode
|
||||
|
||||
self._ds_data = None
|
||||
self._ds_currently = None
|
||||
self._ds_hourly = None
|
||||
self._ds_daily = None
|
||||
|
||||
@property
|
||||
def available(self) -> bool:
|
||||
"""Return if weather data is available from Dark Sky."""
|
||||
return self._ds_data is not None
|
||||
|
||||
@property
|
||||
def attribution(self):
|
||||
"""Return the attribution."""
|
||||
return ATTRIBUTION
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
"""Return the name of the sensor."""
|
||||
return self._name
|
||||
|
||||
@property
|
||||
def native_temperature(self):
|
||||
"""Return the temperature."""
|
||||
return self._ds_currently.get("temperature")
|
||||
|
||||
@property
|
||||
def humidity(self):
|
||||
"""Return the humidity."""
|
||||
return round(self._ds_currently.get("humidity") * 100.0, 2)
|
||||
|
||||
@property
|
||||
def native_wind_speed(self):
|
||||
"""Return the wind speed."""
|
||||
return self._ds_currently.get("windSpeed")
|
||||
|
||||
@property
|
||||
def wind_bearing(self):
|
||||
"""Return the wind bearing."""
|
||||
return self._ds_currently.get("windBearing")
|
||||
|
||||
@property
|
||||
def ozone(self):
|
||||
"""Return the ozone level."""
|
||||
return self._ds_currently.get("ozone")
|
||||
|
||||
@property
|
||||
def native_pressure(self):
|
||||
"""Return the pressure."""
|
||||
return self._ds_currently.get("pressure")
|
||||
|
||||
@property
|
||||
def native_visibility(self):
|
||||
"""Return the visibility."""
|
||||
return self._ds_currently.get("visibility")
|
||||
|
||||
@property
|
||||
def condition(self):
|
||||
"""Return the weather condition."""
|
||||
return MAP_CONDITION.get(self._ds_currently.get("icon"))
|
||||
|
||||
@property
|
||||
def forecast(self):
|
||||
"""Return the forecast array."""
|
||||
|
||||
# Per conversation with Joshua Reyes of Dark Sky, to get the total
|
||||
# forecasted precipitation, you have to multiple the intensity by
|
||||
# the hours for the forecast interval
|
||||
def calc_precipitation(intensity, hours):
|
||||
amount = None
|
||||
if intensity is not None:
|
||||
amount = round((intensity * hours), 1)
|
||||
return amount if amount > 0 else None
|
||||
|
||||
data = None
|
||||
|
||||
if self._mode == "daily":
|
||||
data = [
|
||||
{
|
||||
ATTR_FORECAST_TIME: utc_from_timestamp(
|
||||
entry.d.get("time")
|
||||
).isoformat(),
|
||||
ATTR_FORECAST_NATIVE_TEMP: entry.d.get("temperatureHigh"),
|
||||
ATTR_FORECAST_NATIVE_TEMP_LOW: entry.d.get("temperatureLow"),
|
||||
ATTR_FORECAST_NATIVE_PRECIPITATION: calc_precipitation(
|
||||
entry.d.get("precipIntensity"), 24
|
||||
),
|
||||
ATTR_FORECAST_NATIVE_WIND_SPEED: entry.d.get("windSpeed"),
|
||||
ATTR_FORECAST_WIND_BEARING: entry.d.get("windBearing"),
|
||||
ATTR_FORECAST_CONDITION: MAP_CONDITION.get(entry.d.get("icon")),
|
||||
}
|
||||
for entry in self._ds_daily.data
|
||||
]
|
||||
else:
|
||||
data = [
|
||||
{
|
||||
ATTR_FORECAST_TIME: utc_from_timestamp(
|
||||
entry.d.get("time")
|
||||
).isoformat(),
|
||||
ATTR_FORECAST_NATIVE_TEMP: entry.d.get("temperature"),
|
||||
ATTR_FORECAST_NATIVE_PRECIPITATION: calc_precipitation(
|
||||
entry.d.get("precipIntensity"), 1
|
||||
),
|
||||
ATTR_FORECAST_CONDITION: MAP_CONDITION.get(entry.d.get("icon")),
|
||||
}
|
||||
for entry in self._ds_hourly.data
|
||||
]
|
||||
|
||||
return data
|
||||
|
||||
def update(self) -> None:
|
||||
"""Get the latest data from Dark Sky."""
|
||||
self._dark_sky.update()
|
||||
|
||||
self._ds_data = self._dark_sky.data
|
||||
currently = self._dark_sky.currently
|
||||
self._ds_currently = currently.d if currently else {}
|
||||
self._ds_hourly = self._dark_sky.hourly
|
||||
self._ds_daily = self._dark_sky.daily
|
||||
|
||||
|
||||
class DarkSkyData:
|
||||
"""Get the latest data from Dark Sky."""
|
||||
|
||||
def __init__(self, api_key, latitude, longitude, units):
|
||||
"""Initialize the data object."""
|
||||
self._api_key = api_key
|
||||
self.latitude = latitude
|
||||
self.longitude = longitude
|
||||
self.requested_units = units
|
||||
|
||||
self.data = None
|
||||
self.currently = None
|
||||
self.hourly = None
|
||||
self.daily = None
|
||||
self._connect_error = False
|
||||
|
||||
@Throttle(MIN_TIME_BETWEEN_UPDATES)
|
||||
def update(self):
|
||||
"""Get the latest data from Dark Sky."""
|
||||
try:
|
||||
self.data = forecastio.load_forecast(
|
||||
self._api_key, self.latitude, self.longitude, units=self.requested_units
|
||||
)
|
||||
self.currently = self.data.currently()
|
||||
self.hourly = self.data.hourly()
|
||||
self.daily = self.data.daily()
|
||||
if self._connect_error:
|
||||
self._connect_error = False
|
||||
_LOGGER.info("Reconnected to Dark Sky")
|
||||
except (ConnectError, HTTPError, Timeout, ValueError) as error:
|
||||
if not self._connect_error:
|
||||
self._connect_error = True
|
||||
_LOGGER.error("Unable to connect to Dark Sky. %s", error)
|
||||
self.data = None
|
||||
@@ -348,7 +348,7 @@ class ScannerEntity(BaseTrackerEntity):
|
||||
self.mac_address,
|
||||
self.unique_id,
|
||||
)
|
||||
if self.is_connected:
|
||||
if self.is_connected and self.ip_address:
|
||||
_async_connected_device_registered(
|
||||
hass,
|
||||
self.mac_address,
|
||||
@@ -405,7 +405,7 @@ class ScannerEntity(BaseTrackerEntity):
|
||||
"""Return the device state attributes."""
|
||||
attr: dict[str, StateType] = {}
|
||||
attr.update(super().state_attributes)
|
||||
if self.ip_address is not None:
|
||||
if self.ip_address:
|
||||
attr[ATTR_IP] = self.ip_address
|
||||
if self.mac_address is not None:
|
||||
attr[ATTR_MAC] = self.mac_address
|
||||
|
||||
@@ -427,7 +427,7 @@ def async_setup_scanner_platform(
|
||||
hass,
|
||||
async_device_tracker_scan,
|
||||
interval,
|
||||
f"device_tracker {platform} legacy scan",
|
||||
name=f"device_tracker {platform} legacy scan",
|
||||
)
|
||||
hass.async_create_task(async_device_tracker_scan(None))
|
||||
|
||||
|
||||
@@ -260,7 +260,10 @@ class NetworkWatcher(WatcherBase):
|
||||
"""Start scanning for new devices on the network."""
|
||||
self._discover_hosts = DiscoverHosts()
|
||||
self._unsub = async_track_time_interval(
|
||||
self.hass, self.async_start_discover, SCAN_INTERVAL, "DHCP network watcher"
|
||||
self.hass,
|
||||
self.async_start_discover,
|
||||
SCAN_INTERVAL,
|
||||
name="DHCP network watcher",
|
||||
)
|
||||
self.async_start_discover()
|
||||
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["aiodiscover", "dnspython", "pyroute2", "scapy"],
|
||||
"quality_scale": "internal",
|
||||
"requirements": ["scapy==2.5.0", "aiodiscover==1.4.15"]
|
||||
"requirements": ["scapy==2.5.0", "aiodiscover==1.4.16"]
|
||||
}
|
||||
|
||||
@@ -48,49 +48,49 @@ class DSMRReaderSensorEntityDescription(SensorEntityDescription):
|
||||
SENSORS: tuple[DSMRReaderSensorEntityDescription, ...] = (
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/reading/electricity_delivered_1",
|
||||
name="Low tariff usage",
|
||||
translation_key="low_tariff_usage",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/reading/electricity_returned_1",
|
||||
name="Low tariff returned",
|
||||
translation_key="low_tariff_returned",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/reading/electricity_delivered_2",
|
||||
name="High tariff usage",
|
||||
translation_key="high_tariff_usage",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/reading/electricity_returned_2",
|
||||
name="High tariff returned",
|
||||
translation_key="high_tariff_returned",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/reading/electricity_currently_delivered",
|
||||
name="Current power usage",
|
||||
translation_key="current_power_usage",
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
native_unit_of_measurement=UnitOfPower.KILO_WATT,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/reading/electricity_currently_returned",
|
||||
name="Current power return",
|
||||
translation_key="current_power_return",
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
native_unit_of_measurement=UnitOfPower.KILO_WATT,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/reading/phase_currently_delivered_l1",
|
||||
name="Current power usage L1",
|
||||
translation_key="current_power_usage_l1",
|
||||
entity_registry_enabled_default=False,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
native_unit_of_measurement=UnitOfPower.KILO_WATT,
|
||||
@@ -98,7 +98,7 @@ SENSORS: tuple[DSMRReaderSensorEntityDescription, ...] = (
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/reading/phase_currently_delivered_l2",
|
||||
name="Current power usage L2",
|
||||
translation_key="current_power_usage_l2",
|
||||
entity_registry_enabled_default=False,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
native_unit_of_measurement=UnitOfPower.KILO_WATT,
|
||||
@@ -106,7 +106,7 @@ SENSORS: tuple[DSMRReaderSensorEntityDescription, ...] = (
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/reading/phase_currently_delivered_l3",
|
||||
name="Current power usage L3",
|
||||
translation_key="current_power_usage_l3",
|
||||
entity_registry_enabled_default=False,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
native_unit_of_measurement=UnitOfPower.KILO_WATT,
|
||||
@@ -114,7 +114,7 @@ SENSORS: tuple[DSMRReaderSensorEntityDescription, ...] = (
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/reading/phase_currently_returned_l1",
|
||||
name="Current power return L1",
|
||||
translation_key="current_power_return_l1",
|
||||
entity_registry_enabled_default=False,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
native_unit_of_measurement=UnitOfPower.KILO_WATT,
|
||||
@@ -122,7 +122,7 @@ SENSORS: tuple[DSMRReaderSensorEntityDescription, ...] = (
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/reading/phase_currently_returned_l2",
|
||||
name="Current power return L2",
|
||||
translation_key="current_power_return_l2",
|
||||
entity_registry_enabled_default=False,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
native_unit_of_measurement=UnitOfPower.KILO_WATT,
|
||||
@@ -130,7 +130,7 @@ SENSORS: tuple[DSMRReaderSensorEntityDescription, ...] = (
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/reading/phase_currently_returned_l3",
|
||||
name="Current power return L3",
|
||||
translation_key="current_power_return_l3",
|
||||
entity_registry_enabled_default=False,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
native_unit_of_measurement=UnitOfPower.KILO_WATT,
|
||||
@@ -138,7 +138,7 @@ SENSORS: tuple[DSMRReaderSensorEntityDescription, ...] = (
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/reading/extra_device_delivered",
|
||||
name="Gas meter usage",
|
||||
translation_key="gas_meter_usage",
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:fire",
|
||||
native_unit_of_measurement=UnitOfVolume.CUBIC_METERS,
|
||||
@@ -146,7 +146,7 @@ SENSORS: tuple[DSMRReaderSensorEntityDescription, ...] = (
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/reading/phase_voltage_l1",
|
||||
name="Current voltage L1",
|
||||
translation_key="current_voltage_l1",
|
||||
entity_registry_enabled_default=False,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
@@ -154,7 +154,7 @@ SENSORS: tuple[DSMRReaderSensorEntityDescription, ...] = (
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/reading/phase_voltage_l2",
|
||||
name="Current voltage L2",
|
||||
translation_key="current_voltage_l2",
|
||||
entity_registry_enabled_default=False,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
@@ -162,7 +162,7 @@ SENSORS: tuple[DSMRReaderSensorEntityDescription, ...] = (
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/reading/phase_voltage_l3",
|
||||
name="Current voltage L3",
|
||||
translation_key="current_voltage_l3",
|
||||
entity_registry_enabled_default=False,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
@@ -170,7 +170,7 @@ SENSORS: tuple[DSMRReaderSensorEntityDescription, ...] = (
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/reading/phase_power_current_l1",
|
||||
name="Phase power current L1",
|
||||
translation_key="phase_power_current_l1",
|
||||
entity_registry_enabled_default=False,
|
||||
device_class=SensorDeviceClass.CURRENT,
|
||||
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
|
||||
@@ -178,7 +178,7 @@ SENSORS: tuple[DSMRReaderSensorEntityDescription, ...] = (
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/reading/phase_power_current_l2",
|
||||
name="Phase power current L2",
|
||||
translation_key="phase_power_current_l2",
|
||||
entity_registry_enabled_default=False,
|
||||
device_class=SensorDeviceClass.CURRENT,
|
||||
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
|
||||
@@ -186,7 +186,7 @@ SENSORS: tuple[DSMRReaderSensorEntityDescription, ...] = (
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/reading/phase_power_current_l3",
|
||||
name="Phase power current L3",
|
||||
translation_key="phase_power_current_l3",
|
||||
entity_registry_enabled_default=False,
|
||||
device_class=SensorDeviceClass.CURRENT,
|
||||
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
|
||||
@@ -194,384 +194,386 @@ SENSORS: tuple[DSMRReaderSensorEntityDescription, ...] = (
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/reading/timestamp",
|
||||
name="Telegram timestamp",
|
||||
translation_key="telegram_timestamp",
|
||||
entity_registry_enabled_default=False,
|
||||
device_class=SensorDeviceClass.TIMESTAMP,
|
||||
state=dt_util.parse_datetime,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/consumption/gas/delivered",
|
||||
name="Gas usage",
|
||||
translation_key="gas_usage",
|
||||
device_class=SensorDeviceClass.GAS,
|
||||
native_unit_of_measurement=UnitOfVolume.CUBIC_METERS,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/consumption/gas/currently_delivered",
|
||||
name="Current gas usage",
|
||||
translation_key="current_gas_usage",
|
||||
native_unit_of_measurement=UnitOfVolume.CUBIC_METERS,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/consumption/gas/read_at",
|
||||
name="Gas meter read",
|
||||
translation_key="gas_meter_read",
|
||||
entity_registry_enabled_default=False,
|
||||
device_class=SensorDeviceClass.TIMESTAMP,
|
||||
state=dt_util.parse_datetime,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/day-consumption/electricity1",
|
||||
name="Low tariff usage (daily)",
|
||||
translation_key="daily_low_tariff_usage",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/day-consumption/electricity2",
|
||||
name="High tariff usage (daily)",
|
||||
translation_key="daily_high_tariff_usage",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/day-consumption/electricity1_returned",
|
||||
name="Low tariff return (daily)",
|
||||
translation_key="daily_low_tariff_return",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/day-consumption/electricity2_returned",
|
||||
name="High tariff return (daily)",
|
||||
translation_key="daily_high_tariff_return",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/day-consumption/electricity_merged",
|
||||
name="Power usage total (daily)",
|
||||
translation_key="daily_power_usage_total",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/day-consumption/electricity_returned_merged",
|
||||
name="Power return total (daily)",
|
||||
translation_key="daily_power_return_total",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/day-consumption/electricity1_cost",
|
||||
name="Low tariff cost (daily)",
|
||||
translation_key="daily_low_tariff_cost",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=CURRENCY_EURO,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/day-consumption/electricity2_cost",
|
||||
name="High tariff cost (daily)",
|
||||
translation_key="daily_high_tariff_cost",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=CURRENCY_EURO,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/day-consumption/electricity_cost_merged",
|
||||
name="Power total cost (daily)",
|
||||
translation_key="daily_power_total_cost",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=CURRENCY_EURO,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/day-consumption/gas",
|
||||
name="Gas usage (daily)",
|
||||
translation_key="daily_gas_usage",
|
||||
icon="mdi:counter",
|
||||
native_unit_of_measurement=UnitOfVolume.CUBIC_METERS,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/day-consumption/gas_cost",
|
||||
name="Gas cost",
|
||||
translation_key="gas_cost",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=CURRENCY_EURO,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/day-consumption/total_cost",
|
||||
name="Total cost",
|
||||
translation_key="total_cost",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=CURRENCY_EURO,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/day-consumption/energy_supplier_price_electricity_delivered_1",
|
||||
name="Low tariff delivered price",
|
||||
translation_key="low_tariff_delivered_price",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=PRICE_EUR_KWH,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/day-consumption/energy_supplier_price_electricity_delivered_2",
|
||||
name="High tariff delivered price",
|
||||
translation_key="high_tariff_delivered_price",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=PRICE_EUR_KWH,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/day-consumption/energy_supplier_price_electricity_returned_1",
|
||||
name="Low tariff returned price",
|
||||
translation_key="low_tariff_returned_price",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=PRICE_EUR_KWH,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/day-consumption/energy_supplier_price_electricity_returned_2",
|
||||
name="High tariff returned price",
|
||||
translation_key="high_tariff_returned_price",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=PRICE_EUR_KWH,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/day-consumption/energy_supplier_price_gas",
|
||||
name="Gas price",
|
||||
translation_key="gas_price",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=PRICE_EUR_M3,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/day-consumption/fixed_cost",
|
||||
name="Current day fixed cost",
|
||||
translation_key="current_day_fixed_cost",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=CURRENCY_EURO,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/meter-stats/dsmr_version",
|
||||
name="DSMR version",
|
||||
translation_key="dsmr_version",
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:alert-circle",
|
||||
state=dsmr_transform,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/meter-stats/electricity_tariff",
|
||||
name="Electricity tariff",
|
||||
translation_key="electricity_tariff",
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
options=["low", "high"],
|
||||
icon="mdi:flash",
|
||||
state=tariff_transform,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/meter-stats/power_failure_count",
|
||||
name="Power failure count",
|
||||
translation_key="power_failure_count",
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:flash",
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/meter-stats/long_power_failure_count",
|
||||
name="Long power failure count",
|
||||
translation_key="long_power_failure_count",
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:flash",
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/meter-stats/voltage_sag_count_l1",
|
||||
name="Voltage sag L1",
|
||||
translation_key="voltage_sag_l1",
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:flash",
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/meter-stats/voltage_sag_count_l2",
|
||||
name="Voltage sag L2",
|
||||
translation_key="voltage_sag_l2",
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:flash",
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/meter-stats/voltage_sag_count_l3",
|
||||
name="Voltage sag L3",
|
||||
translation_key="voltage_sag_l3",
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:flash",
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/meter-stats/voltage_swell_count_l1",
|
||||
name="Voltage swell L1",
|
||||
translation_key="voltage_swell_l1",
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:flash",
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/meter-stats/voltage_swell_count_l2",
|
||||
name="Voltage swell L2",
|
||||
translation_key="voltage_swell_l2",
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:flash",
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/meter-stats/voltage_swell_count_l3",
|
||||
name="Voltage swell L3",
|
||||
translation_key="voltage_swell_l3",
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:flash",
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/meter-stats/rejected_telegrams",
|
||||
name="Rejected telegrams",
|
||||
translation_key="rejected_telegrams",
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:flash",
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-month/electricity1",
|
||||
name="Current month low tariff usage",
|
||||
translation_key="current_month_low_tariff_usage",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-month/electricity2",
|
||||
name="Current month high tariff usage",
|
||||
translation_key="current_month_high_tariff_usage",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-month/electricity1_returned",
|
||||
name="Current month low tariff returned",
|
||||
translation_key="current_month_low_tariff_returned",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-month/electricity2_returned",
|
||||
name="Current month high tariff returned",
|
||||
translation_key="current_month_high_tariff_returned",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-month/electricity_merged",
|
||||
name="Current month power usage total",
|
||||
translation_key="current_month_power_usage_total",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-month/electricity_returned_merged",
|
||||
name="Current month power return total",
|
||||
translation_key="current_month_power_return_total",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-month/electricity1_cost",
|
||||
name="Current month low tariff cost",
|
||||
translation_key="current_month_low_tariff_cost",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=CURRENCY_EURO,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-month/electricity2_cost",
|
||||
name="Current month high tariff cost",
|
||||
translation_key="current_month_high_tariff_cost",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=CURRENCY_EURO,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-month/electricity_cost_merged",
|
||||
name="Current month power total cost",
|
||||
translation_key="current_month_power_total_cost",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=CURRENCY_EURO,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-month/gas",
|
||||
name="Current month gas usage",
|
||||
translation_key="current_month_gas_usage",
|
||||
icon="mdi:counter",
|
||||
native_unit_of_measurement=UnitOfVolume.CUBIC_METERS,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-month/gas_cost",
|
||||
name="Current month gas cost",
|
||||
translation_key="current_month_gas_cost",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=CURRENCY_EURO,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-month/fixed_cost",
|
||||
name="Current month fixed cost",
|
||||
translation_key="current_month_fixed_cost",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=CURRENCY_EURO,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-month/total_cost",
|
||||
name="Current month total cost",
|
||||
translation_key="current_month_total_cost",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=CURRENCY_EURO,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-year/electricity1",
|
||||
name="Current year low tariff usage",
|
||||
translation_key="current_year_low_tariff_usage",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-year/electricity2",
|
||||
name="Current year high tariff usage",
|
||||
translation_key="current_year_high_tariff_usage",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-year/electricity1_returned",
|
||||
name="Current year low tariff returned",
|
||||
translation_key="current_year_low_tariff_returned",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-year/electricity2_returned",
|
||||
name="Current year high tariff returned",
|
||||
translation_key="current_year_high_tariff_returned",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-year/electricity_merged",
|
||||
name="Current year power usage total",
|
||||
translation_key="current_year_power_usage_total",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-year/electricity_returned_merged",
|
||||
name="Current year power returned total",
|
||||
translation_key="current_year_power_returned_total",
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-year/electricity1_cost",
|
||||
name="Current year low tariff cost",
|
||||
translation_key="current_year_low_tariff_cost",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=CURRENCY_EURO,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-year/electricity2_cost",
|
||||
name="Current year high tariff cost",
|
||||
translation_key="current_year_high_tariff_cost",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=CURRENCY_EURO,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-year/electricity_cost_merged",
|
||||
name="Current year power total cost",
|
||||
translation_key="current_year_power_total_cost",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=CURRENCY_EURO,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-year/gas",
|
||||
name="Current year gas usage",
|
||||
translation_key="current_year_gas_usage",
|
||||
icon="mdi:counter",
|
||||
native_unit_of_measurement=UnitOfVolume.CUBIC_METERS,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-year/gas_cost",
|
||||
name="Current year gas cost",
|
||||
translation_key="current_year_gas_cost",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=CURRENCY_EURO,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-year/fixed_cost",
|
||||
name="Current year fixed cost",
|
||||
translation_key="current_year_fixed_cost",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=CURRENCY_EURO,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/current-year/total_cost",
|
||||
name="Current year total cost",
|
||||
translation_key="current_year_total_cost",
|
||||
icon="mdi:currency-eur",
|
||||
native_unit_of_measurement=CURRENCY_EURO,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/consumption/quarter-hour-peak-electricity/average_delivered",
|
||||
name="Previous quarter-hour peak usage",
|
||||
translation_key="previous_quarter_hour_peak_usage",
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
native_unit_of_measurement=UnitOfPower.KILO_WATT,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/consumption/quarter-hour-peak-electricity/read_at_start",
|
||||
name="Quarter-hour peak start time",
|
||||
translation_key="quarter_hour_peak_start_time",
|
||||
entity_registry_enabled_default=False,
|
||||
device_class=SensorDeviceClass.TIMESTAMP,
|
||||
state=dt_util.parse_datetime,
|
||||
),
|
||||
DSMRReaderSensorEntityDescription(
|
||||
key="dsmr/consumption/quarter-hour-peak-electricity/read_at_end",
|
||||
name="Quarter-hour peak end time",
|
||||
translation_key="quarter_hour_peak_end_time",
|
||||
entity_registry_enabled_default=False,
|
||||
device_class=SensorDeviceClass.TIMESTAMP,
|
||||
state=dt_util.parse_datetime,
|
||||
|
||||
@@ -23,6 +23,7 @@ async def async_setup_entry(
|
||||
class DSMRSensor(SensorEntity):
|
||||
"""Representation of a DSMR sensor that is updated via MQTT."""
|
||||
|
||||
_attr_has_entity_name = True
|
||||
entity_description: DSMRReaderSensorEntityDescription
|
||||
|
||||
def __init__(
|
||||
|
||||
@@ -8,5 +8,256 @@
|
||||
"description": "Make sure to configure the 'split topic' data sources in DSMR Reader."
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"low_tariff_usage": {
|
||||
"name": "Low tariff usage"
|
||||
},
|
||||
"low_tariff_returned": {
|
||||
"name": "Low tariff returned"
|
||||
},
|
||||
"high_tariff_usage": {
|
||||
"name": "High tariff usage"
|
||||
},
|
||||
"high_tariff_returned": {
|
||||
"name": "High tariff returned"
|
||||
},
|
||||
"current_power_usage": {
|
||||
"name": "Current power usage"
|
||||
},
|
||||
"current_power_return": {
|
||||
"name": "Current power return"
|
||||
},
|
||||
"current_power_usage_l1": {
|
||||
"name": "Current power usage L1"
|
||||
},
|
||||
"current_power_usage_l2": {
|
||||
"name": "Current power usage L2"
|
||||
},
|
||||
"current_power_usage_l3": {
|
||||
"name": "Current power usage L3"
|
||||
},
|
||||
"current_power_return_l1": {
|
||||
"name": "Current power return L1"
|
||||
},
|
||||
"current_power_return_l2": {
|
||||
"name": "Current power return L2"
|
||||
},
|
||||
"current_power_return_l3": {
|
||||
"name": "Current power return L3"
|
||||
},
|
||||
"gas_meter_usage": {
|
||||
"name": "Gas meter usage"
|
||||
},
|
||||
"current_voltage_l1": {
|
||||
"name": "Current voltage L1"
|
||||
},
|
||||
"current_voltage_l2": {
|
||||
"name": "Current voltage L2"
|
||||
},
|
||||
"current_voltage_l3": {
|
||||
"name": "Current voltage L3"
|
||||
},
|
||||
"phase_power_current_l1": {
|
||||
"name": "Phase power current L1"
|
||||
},
|
||||
"phase_power_current_l2": {
|
||||
"name": "Phase power current L2"
|
||||
},
|
||||
"phase_power_current_l3": {
|
||||
"name": "Phase power current L3"
|
||||
},
|
||||
"telegram_timestamp": {
|
||||
"name": "Telegram timestamp"
|
||||
},
|
||||
"gas_usage": {
|
||||
"name": "Gas usage"
|
||||
},
|
||||
"current_gas_usage": {
|
||||
"name": "Current gas usage"
|
||||
},
|
||||
"gas_meter_read": {
|
||||
"name": "Gas meter read"
|
||||
},
|
||||
"daily_low_tariff_usage": {
|
||||
"name": "Low tariff usage (daily)"
|
||||
},
|
||||
"daily_high_tariff_usage": {
|
||||
"name": "High tariff usage (daily)"
|
||||
},
|
||||
"daily_low_tariff_return": {
|
||||
"name": "Low tariff return (daily)"
|
||||
},
|
||||
"daily_high_tariff_return": {
|
||||
"name": "High tariff return (daily)"
|
||||
},
|
||||
"daily_power_usage_total": {
|
||||
"name": "Power usage total (daily)"
|
||||
},
|
||||
"daily_power_return_total": {
|
||||
"name": "Power return total (daily)"
|
||||
},
|
||||
"daily_low_tariff_cost": {
|
||||
"name": "Low tariff cost (daily)"
|
||||
},
|
||||
"daily_high_tariff_cost": {
|
||||
"name": "High tariff cost (daily)"
|
||||
},
|
||||
"daily_power_total_cost": {
|
||||
"name": "Power total cost (daily)"
|
||||
},
|
||||
"daily_gas_usage": {
|
||||
"name": "Gas usage (daily)"
|
||||
},
|
||||
"gas_cost": {
|
||||
"name": "Gas cost"
|
||||
},
|
||||
"total_cost": {
|
||||
"name": "Total cost"
|
||||
},
|
||||
"low_tariff_delivered_price": {
|
||||
"name": "Low tariff delivered price"
|
||||
},
|
||||
"high_tariff_delivered_price": {
|
||||
"name": "High tariff delivered price"
|
||||
},
|
||||
"low_tariff_returned_price": {
|
||||
"name": "Low tariff returned price"
|
||||
},
|
||||
"high_tariff_returned_price": {
|
||||
"name": "High tariff returned price"
|
||||
},
|
||||
"gas_price": {
|
||||
"name": "Gas Price"
|
||||
},
|
||||
"current_day_fixed_cost": {
|
||||
"name": "Current day fixed cost"
|
||||
},
|
||||
"dsmr_version": {
|
||||
"name": "DSMR version"
|
||||
},
|
||||
"electricity_tariff": {
|
||||
"name": "Electricity tariff",
|
||||
"state": {
|
||||
"low": "Low",
|
||||
"high": "High"
|
||||
}
|
||||
},
|
||||
"power_failure_count": {
|
||||
"name": "Power failure count"
|
||||
},
|
||||
"long_power_failure_count": {
|
||||
"name": "Long power failure count"
|
||||
},
|
||||
"voltage_sag_l1": {
|
||||
"name": "Voltage sag L1"
|
||||
},
|
||||
"voltage_sag_l2": {
|
||||
"name": "Voltage sag L2"
|
||||
},
|
||||
"voltage_sag_l3": {
|
||||
"name": "Voltage sag L3"
|
||||
},
|
||||
"voltage_swell_l1": {
|
||||
"name": "Voltage swell L1"
|
||||
},
|
||||
"voltage_swell_l2": {
|
||||
"name": "Voltage swell L2"
|
||||
},
|
||||
"voltage_swell_l3": {
|
||||
"name": "Voltage swell L3"
|
||||
},
|
||||
"rejected_telegrams": {
|
||||
"name": "Rejected telegrams"
|
||||
},
|
||||
"current_month_low_tariff_usage": {
|
||||
"name": "Current month low tariff usage"
|
||||
},
|
||||
"current_month_high_tariff_usage": {
|
||||
"name": "Current month high tariff usage"
|
||||
},
|
||||
"current_month_low_tariff_returned": {
|
||||
"name": "Current month low tariff returned"
|
||||
},
|
||||
"current_month_high_tariff_returned": {
|
||||
"name": "Current month high tariff returned"
|
||||
},
|
||||
"current_month_power_usage_total": {
|
||||
"name": "Current month power usage total"
|
||||
},
|
||||
"current_month_power_return_total": {
|
||||
"name": "Current month power return total"
|
||||
},
|
||||
"current_month_low_tariff_cost": {
|
||||
"name": "Current month low tariff cost"
|
||||
},
|
||||
"current_month_high_tariff_cost": {
|
||||
"name": "Current month high tariff cost"
|
||||
},
|
||||
"current_month_power_total_cost": {
|
||||
"name": "Current month power total cost"
|
||||
},
|
||||
"current_month_gas_usage": {
|
||||
"name": "Current month gas usage"
|
||||
},
|
||||
"current_month_gas_cost": {
|
||||
"name": "Current month gas cost"
|
||||
},
|
||||
"current_month_fixed_cost": {
|
||||
"name": "Current month fixed cost"
|
||||
},
|
||||
"current_month_total_cost": {
|
||||
"name": "Current month total cost"
|
||||
},
|
||||
"current_year_low_tariff_usage": {
|
||||
"name": "Current year low tariff usage"
|
||||
},
|
||||
"current_year_high_tariff_usage": {
|
||||
"name": "Current year high tariff usage"
|
||||
},
|
||||
"current_year_low_tariff_returned": {
|
||||
"name": "Current year low tariff returned"
|
||||
},
|
||||
"current_year_high_tariff_returned": {
|
||||
"name": "Current year high tariff returned"
|
||||
},
|
||||
"current_year_power_usage_total": {
|
||||
"name": "Current year power usage total"
|
||||
},
|
||||
"current_year_power_returned_total": {
|
||||
"name": "Current year power returned total"
|
||||
},
|
||||
"current_year_low_tariff_cost": {
|
||||
"name": "Current year low tariff cost"
|
||||
},
|
||||
"current_year_high_tariff_cost": {
|
||||
"name": "Current year high tariff cost"
|
||||
},
|
||||
"current_year_power_total_cost": {
|
||||
"name": "Current year power total cost"
|
||||
},
|
||||
"current_year_gas_usage": {
|
||||
"name": "Current year gas usage"
|
||||
},
|
||||
"current_year_gas_cost": {
|
||||
"name": "Current year gas cost"
|
||||
},
|
||||
"current_year_fixed_cost": {
|
||||
"name": "Current year fixed cost"
|
||||
},
|
||||
"current_year_total_cost": {
|
||||
"name": "Current year total cost"
|
||||
},
|
||||
"previous_quarter_hour_peak_usage": {
|
||||
"name": "Previous quarter-hour peak usage"
|
||||
},
|
||||
"quarter_hour_peak_start_time": {
|
||||
"name": "Quarter-hour peak start time"
|
||||
},
|
||||
"quarter_hour_peak_end_time": {
|
||||
"name": "Quarter-hour peak end time"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
"integration_type": "hub",
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["sml"],
|
||||
"requirements": ["pysml==0.0.9"]
|
||||
"requirements": ["pysml==0.0.10"]
|
||||
}
|
||||
|
||||
@@ -290,7 +290,7 @@ async def async_setup_platform(
|
||||
hass,
|
||||
DOMAIN,
|
||||
"deprecated_yaml",
|
||||
breaks_in_ha_version="2023.2.0",
|
||||
breaks_in_ha_version="2023.6.0",
|
||||
is_fixable=False,
|
||||
severity=IssueSeverity.WARNING,
|
||||
translation_key="deprecated_yaml",
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/environment_canada",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["env_canada"],
|
||||
"requirements": ["env_canada==0.5.29"]
|
||||
"requirements": ["env_canada==0.5.33"]
|
||||
}
|
||||
|
||||
@@ -345,11 +345,19 @@ async def async_setup_entry( # noqa: C901
|
||||
disconnect_cb()
|
||||
entry_data.disconnect_callbacks = []
|
||||
entry_data.available = False
|
||||
# Clear out the states so that we will always dispatch
|
||||
# Mark state as stale so that we will always dispatch
|
||||
# the next state update of that type when the device reconnects
|
||||
for state_keys in entry_data.state.values():
|
||||
state_keys.clear()
|
||||
entry_data.async_update_device_state(hass)
|
||||
entry_data.stale_state = {
|
||||
(type(entity_state), key)
|
||||
for state_dict in entry_data.state.values()
|
||||
for key, entity_state in state_dict.items()
|
||||
}
|
||||
if not hass.is_stopping:
|
||||
# Avoid marking every esphome entity as unavailable on shutdown
|
||||
# since it generates a lot of state changed events and database
|
||||
# writes when we already know we're shutting down and the state
|
||||
# will be cleared anyway.
|
||||
entry_data.async_update_device_state(hass)
|
||||
|
||||
async def on_connect_error(err: Exception) -> None:
|
||||
"""Start reauth flow if appropriate connect error type."""
|
||||
|
||||
@@ -70,6 +70,10 @@ class RuntimeEntryData:
|
||||
client: APIClient
|
||||
store: Store
|
||||
state: dict[type[EntityState], dict[int, EntityState]] = field(default_factory=dict)
|
||||
# When the disconnect callback is called, we mark all states
|
||||
# as stale so we will always dispatch a state update when the
|
||||
# device reconnects. This is the same format as state_subscriptions.
|
||||
stale_state: set[tuple[type[EntityState], int]] = field(default_factory=set)
|
||||
info: dict[str, dict[int, EntityInfo]] = field(default_factory=dict)
|
||||
|
||||
# A second list of EntityInfo objects
|
||||
@@ -206,9 +210,11 @@ class RuntimeEntryData:
|
||||
"""Distribute an update of state information to the target."""
|
||||
key = state.key
|
||||
state_type = type(state)
|
||||
stale_state = self.stale_state
|
||||
current_state_by_type = self.state[state_type]
|
||||
current_state = current_state_by_type.get(key, _SENTINEL)
|
||||
if current_state == state:
|
||||
subscription_key = (state_type, key)
|
||||
if current_state == state and subscription_key not in stale_state:
|
||||
_LOGGER.debug(
|
||||
"%s: ignoring duplicate update with and key %s: %s",
|
||||
self.name,
|
||||
@@ -222,8 +228,8 @@ class RuntimeEntryData:
|
||||
key,
|
||||
state,
|
||||
)
|
||||
stale_state.discard(subscription_key)
|
||||
current_state_by_type[key] = state
|
||||
subscription_key = (state_type, key)
|
||||
if subscription_key in self.state_subscriptions:
|
||||
self.state_subscriptions[subscription_key]()
|
||||
|
||||
|
||||
@@ -14,6 +14,6 @@
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["aioesphomeapi", "noiseprotocol"],
|
||||
"requirements": ["aioesphomeapi==13.6.0", "esphome-dashboard-api==1.2.3"],
|
||||
"requirements": ["aioesphomeapi==13.6.1", "esphome-dashboard-api==1.2.3"],
|
||||
"zeroconf": ["_esphomelib._tcp.local."]
|
||||
}
|
||||
|
||||
@@ -95,6 +95,7 @@ HA_OPMODES_HVAC = {
|
||||
HVACMode.COOL: 2,
|
||||
HVACMode.AUTO: 3,
|
||||
HVACMode.FAN_ONLY: 6,
|
||||
HVACMode.DRY: 8,
|
||||
}
|
||||
|
||||
TARGET_TEMP_ACTIONS = (
|
||||
|
||||
@@ -9,7 +9,9 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession
|
||||
|
||||
from .const import DOMAIN, LOGGER
|
||||
|
||||
DATA_SCHEMA = vol.Schema({vol.Required("username"): str, vol.Required("password"): str})
|
||||
DATA_SCHEMA = vol.Schema(
|
||||
{vol.Required(CONF_USERNAME): str, vol.Required(CONF_PASSWORD): str}
|
||||
)
|
||||
|
||||
|
||||
async def validate_input(hass: core.HomeAssistant, data):
|
||||
@@ -20,18 +22,11 @@ async def validate_input(hass: core.HomeAssistant, data):
|
||||
|
||||
session = async_get_clientsession(hass)
|
||||
try:
|
||||
api = await async_get_api(
|
||||
data[CONF_USERNAME], data[CONF_PASSWORD], session=session
|
||||
)
|
||||
await async_get_api(data[CONF_USERNAME], data[CONF_PASSWORD], session=session)
|
||||
except RequestError as request_error:
|
||||
LOGGER.error("Error connecting to the Flo API: %s", request_error)
|
||||
raise CannotConnect from request_error
|
||||
|
||||
user_info = await api.user.get_info()
|
||||
a_location_id = user_info["locations"][0]["id"]
|
||||
location_info = await api.location.get_info(a_location_id)
|
||||
return {"title": location_info["nickname"]}
|
||||
|
||||
|
||||
class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
"""Handle a config flow for flo."""
|
||||
@@ -45,8 +40,10 @@ class ConfigFlow(config_entries.ConfigFlow, domain=DOMAIN):
|
||||
await self.async_set_unique_id(user_input[CONF_USERNAME])
|
||||
self._abort_if_unique_id_configured()
|
||||
try:
|
||||
info = await validate_input(self.hass, user_input)
|
||||
return self.async_create_entry(title=info["title"], data=user_input)
|
||||
await validate_input(self.hass, user_input)
|
||||
return self.async_create_entry(
|
||||
title=user_input[CONF_USERNAME], data=user_input
|
||||
)
|
||||
except CannotConnect:
|
||||
errors["base"] = "cannot_connect"
|
||||
|
||||
|
||||
@@ -51,5 +51,5 @@
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["flux_led"],
|
||||
"quality_scale": "platinum",
|
||||
"requirements": ["flux_led==0.28.36"]
|
||||
"requirements": ["flux_led==0.28.37"]
|
||||
}
|
||||
|
||||
@@ -38,14 +38,14 @@ class FritzBinarySensorEntityDescription(
|
||||
SENSOR_TYPES: tuple[FritzBinarySensorEntityDescription, ...] = (
|
||||
FritzBinarySensorEntityDescription(
|
||||
key="is_connected",
|
||||
name="Connection",
|
||||
translation_key="is_connected",
|
||||
device_class=BinarySensorDeviceClass.CONNECTIVITY,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
value_fn=lambda status, _: bool(status.is_connected),
|
||||
),
|
||||
FritzBinarySensorEntityDescription(
|
||||
key="is_linked",
|
||||
name="Link",
|
||||
translation_key="is_linked",
|
||||
device_class=BinarySensorDeviceClass.PLUG,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
value_fn=lambda status, _: bool(status.is_linked),
|
||||
|
||||
@@ -39,28 +39,28 @@ class FritzButtonDescription(ButtonEntityDescription, FritzButtonDescriptionMixi
|
||||
BUTTONS: Final = [
|
||||
FritzButtonDescription(
|
||||
key="firmware_update",
|
||||
name="Firmware Update",
|
||||
translation_key="firmware_update",
|
||||
device_class=ButtonDeviceClass.UPDATE,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
press_action=lambda avm_wrapper: avm_wrapper.async_trigger_firmware_update(),
|
||||
),
|
||||
FritzButtonDescription(
|
||||
key="reboot",
|
||||
name="Reboot",
|
||||
translation_key="reboot",
|
||||
device_class=ButtonDeviceClass.RESTART,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
press_action=lambda avm_wrapper: avm_wrapper.async_trigger_reboot(),
|
||||
),
|
||||
FritzButtonDescription(
|
||||
key="reconnect",
|
||||
name="Reconnect",
|
||||
translation_key="reconnect",
|
||||
device_class=ButtonDeviceClass.RESTART,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
press_action=lambda avm_wrapper: avm_wrapper.async_trigger_reconnect(),
|
||||
),
|
||||
FritzButtonDescription(
|
||||
key="cleanup",
|
||||
name="Cleanup",
|
||||
translation_key="cleanup",
|
||||
icon="mdi:broom",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
press_action=lambda avm_wrapper: avm_wrapper.async_trigger_cleanup(),
|
||||
@@ -86,6 +86,7 @@ class FritzButton(ButtonEntity):
|
||||
"""Defines a Fritz!Box base button."""
|
||||
|
||||
entity_description: FritzButtonDescription
|
||||
_attr_has_entity_name = True
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -97,11 +98,11 @@ class FritzButton(ButtonEntity):
|
||||
self.entity_description = description
|
||||
self.avm_wrapper = avm_wrapper
|
||||
|
||||
self._attr_name = f"{device_friendly_name} {description.name}"
|
||||
self._attr_unique_id = f"{self.avm_wrapper.unique_id}-{description.key}"
|
||||
|
||||
self._attr_device_info = DeviceInfo(
|
||||
connections={(CONNECTION_NETWORK_MAC, avm_wrapper.mac)}
|
||||
connections={(CONNECTION_NETWORK_MAC, avm_wrapper.mac)},
|
||||
name=device_friendly_name,
|
||||
)
|
||||
|
||||
async def async_press(self) -> None:
|
||||
|
||||
@@ -1043,7 +1043,6 @@ class FritzBoxBaseCoordinatorEntity(update_coordinator.CoordinatorEntity):
|
||||
)
|
||||
self.entity_description = description
|
||||
self._device_name = device_name
|
||||
self._attr_name = description.name
|
||||
self._attr_unique_id = f"{avm_wrapper.unique_id}-{description.key}"
|
||||
|
||||
@property
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/fritz",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["fritzconnection"],
|
||||
"requirements": ["fritzconnection==1.11.0", "xmltodict==0.13.0"],
|
||||
"requirements": ["fritzconnection==1.12.0", "xmltodict==0.13.0"],
|
||||
"ssdp": [
|
||||
{
|
||||
"st": "urn:schemas-upnp-org:device:fritzbox:1"
|
||||
|
||||
@@ -152,20 +152,20 @@ class FritzSensorEntityDescription(SensorEntityDescription, FritzEntityDescripti
|
||||
SENSOR_TYPES: tuple[FritzSensorEntityDescription, ...] = (
|
||||
FritzSensorEntityDescription(
|
||||
key="external_ip",
|
||||
name="External IP",
|
||||
translation_key="external_ip",
|
||||
icon="mdi:earth",
|
||||
value_fn=_retrieve_external_ip_state,
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="external_ipv6",
|
||||
name="External IPv6",
|
||||
translation_key="external_ipv6",
|
||||
icon="mdi:earth",
|
||||
value_fn=_retrieve_external_ipv6_state,
|
||||
is_suitable=lambda info: info.ipv6_active,
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="device_uptime",
|
||||
name="Device Uptime",
|
||||
translation_key="device_uptime",
|
||||
device_class=SensorDeviceClass.TIMESTAMP,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
value_fn=_retrieve_device_uptime_state,
|
||||
@@ -173,14 +173,14 @@ SENSOR_TYPES: tuple[FritzSensorEntityDescription, ...] = (
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="connection_uptime",
|
||||
name="Connection Uptime",
|
||||
translation_key="connection_uptime",
|
||||
device_class=SensorDeviceClass.TIMESTAMP,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
value_fn=_retrieve_connection_uptime_state,
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="kb_s_sent",
|
||||
name="Upload Throughput",
|
||||
translation_key="kb_s_sent",
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=UnitOfDataRate.KILOBYTES_PER_SECOND,
|
||||
device_class=SensorDeviceClass.DATA_RATE,
|
||||
@@ -189,7 +189,7 @@ SENSOR_TYPES: tuple[FritzSensorEntityDescription, ...] = (
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="kb_s_received",
|
||||
name="Download Throughput",
|
||||
translation_key="kb_s_received",
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
native_unit_of_measurement=UnitOfDataRate.KILOBYTES_PER_SECOND,
|
||||
device_class=SensorDeviceClass.DATA_RATE,
|
||||
@@ -198,7 +198,7 @@ SENSOR_TYPES: tuple[FritzSensorEntityDescription, ...] = (
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="max_kb_s_sent",
|
||||
name="Max Connection Upload Throughput",
|
||||
translation_key="max_kb_s_sent",
|
||||
native_unit_of_measurement=UnitOfDataRate.KILOBITS_PER_SECOND,
|
||||
device_class=SensorDeviceClass.DATA_RATE,
|
||||
icon="mdi:upload",
|
||||
@@ -207,7 +207,7 @@ SENSOR_TYPES: tuple[FritzSensorEntityDescription, ...] = (
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="max_kb_s_received",
|
||||
name="Max Connection Download Throughput",
|
||||
translation_key="max_kb_s_received",
|
||||
native_unit_of_measurement=UnitOfDataRate.KILOBITS_PER_SECOND,
|
||||
device_class=SensorDeviceClass.DATA_RATE,
|
||||
icon="mdi:download",
|
||||
@@ -216,7 +216,7 @@ SENSOR_TYPES: tuple[FritzSensorEntityDescription, ...] = (
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="gb_sent",
|
||||
name="GB sent",
|
||||
translation_key="gb_sent",
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
native_unit_of_measurement=UnitOfInformation.GIGABYTES,
|
||||
device_class=SensorDeviceClass.DATA_SIZE,
|
||||
@@ -225,7 +225,7 @@ SENSOR_TYPES: tuple[FritzSensorEntityDescription, ...] = (
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="gb_received",
|
||||
name="GB received",
|
||||
translation_key="gb_received",
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
native_unit_of_measurement=UnitOfInformation.GIGABYTES,
|
||||
device_class=SensorDeviceClass.DATA_SIZE,
|
||||
@@ -234,7 +234,7 @@ SENSOR_TYPES: tuple[FritzSensorEntityDescription, ...] = (
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="link_kb_s_sent",
|
||||
name="Link Upload Throughput",
|
||||
translation_key="link_kb_s_sent",
|
||||
native_unit_of_measurement=UnitOfDataRate.KILOBITS_PER_SECOND,
|
||||
device_class=SensorDeviceClass.DATA_RATE,
|
||||
icon="mdi:upload",
|
||||
@@ -242,7 +242,7 @@ SENSOR_TYPES: tuple[FritzSensorEntityDescription, ...] = (
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="link_kb_s_received",
|
||||
name="Link Download Throughput",
|
||||
translation_key="link_kb_s_received",
|
||||
native_unit_of_measurement=UnitOfDataRate.KILOBITS_PER_SECOND,
|
||||
device_class=SensorDeviceClass.DATA_RATE,
|
||||
icon="mdi:download",
|
||||
@@ -250,7 +250,7 @@ SENSOR_TYPES: tuple[FritzSensorEntityDescription, ...] = (
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="link_noise_margin_sent",
|
||||
name="Link Upload Noise Margin",
|
||||
translation_key="link_noise_margin_sent",
|
||||
native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS,
|
||||
icon="mdi:upload",
|
||||
value_fn=_retrieve_link_noise_margin_sent_state,
|
||||
@@ -258,7 +258,7 @@ SENSOR_TYPES: tuple[FritzSensorEntityDescription, ...] = (
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="link_noise_margin_received",
|
||||
name="Link Download Noise Margin",
|
||||
translation_key="link_noise_margin_received",
|
||||
native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS,
|
||||
icon="mdi:download",
|
||||
value_fn=_retrieve_link_noise_margin_received_state,
|
||||
@@ -266,7 +266,7 @@ SENSOR_TYPES: tuple[FritzSensorEntityDescription, ...] = (
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="link_attenuation_sent",
|
||||
name="Link Upload Power Attenuation",
|
||||
translation_key="link_attenuation_sent",
|
||||
native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS,
|
||||
icon="mdi:upload",
|
||||
value_fn=_retrieve_link_attenuation_sent_state,
|
||||
@@ -274,7 +274,7 @@ SENSOR_TYPES: tuple[FritzSensorEntityDescription, ...] = (
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="link_attenuation_received",
|
||||
name="Link Download Power Attenuation",
|
||||
translation_key="link_attenuation_received",
|
||||
native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS,
|
||||
icon="mdi:download",
|
||||
value_fn=_retrieve_link_attenuation_received_state,
|
||||
|
||||
@@ -52,5 +52,39 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"binary_sensor": {
|
||||
"is_connected": { "name": "Connection" },
|
||||
"is_linked": { "name": "Link" }
|
||||
},
|
||||
"button": {
|
||||
"cleanup": { "name": "Cleanup" },
|
||||
"firmware_update": { "name": "Firmware update" },
|
||||
"reboot": {
|
||||
"name": "[%key:component::button::entity_component::restart::name%]"
|
||||
},
|
||||
"reconnect": { "name": "Reconnect" }
|
||||
},
|
||||
"sensor": {
|
||||
"connection_uptime": { "name": "Connection uptime" },
|
||||
"device_uptime": { "name": "Last restart" },
|
||||
"external_ip": { "name": "External IP" },
|
||||
"external_ipv6": { "name": "External IPv6" },
|
||||
"gb_received": { "name": "GB received" },
|
||||
"gb_sent": { "name": "GB sent" },
|
||||
"kb_s_received": { "name": "Download throughput" },
|
||||
"kb_s_sent": { "name": "Upload throughput" },
|
||||
"link_attenuation_received": {
|
||||
"name": "Link download power attenuation"
|
||||
},
|
||||
"link_attenuation_sent": { "name": "Link upload power attenuation" },
|
||||
"link_kb_s_received": { "name": "Link download throughput" },
|
||||
"link_kb_s_sent": { "name": "Link upload throughput" },
|
||||
"link_noise_margin_received": { "name": "Link download noise margin" },
|
||||
"link_noise_margin_sent": { "name": "Link upload noise margin" },
|
||||
"max_kb_s_received": { "name": "Max connection download throughput" },
|
||||
"max_kb_s_sent": { "name": "Max connection upload throughput" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,8 +113,8 @@ class FritzBoxEntity(CoordinatorEntity[FritzboxDataUpdateCoordinator], ABC):
|
||||
|
||||
self.ain = ain
|
||||
if entity_description is not None:
|
||||
self._attr_has_entity_name = True
|
||||
self.entity_description = entity_description
|
||||
self._attr_name = f"{self.data.name} {entity_description.name}"
|
||||
self._attr_unique_id = f"{ain}_{entity_description.key}"
|
||||
else:
|
||||
self._attr_name = self.data.name
|
||||
|
||||
@@ -40,14 +40,14 @@ class FritzBinarySensorEntityDescription(
|
||||
BINARY_SENSOR_TYPES: Final[tuple[FritzBinarySensorEntityDescription, ...]] = (
|
||||
FritzBinarySensorEntityDescription(
|
||||
key="alarm",
|
||||
name="Alarm",
|
||||
translation_key="alarm",
|
||||
device_class=BinarySensorDeviceClass.WINDOW,
|
||||
suitable=lambda device: device.has_alarm, # type: ignore[no-any-return]
|
||||
is_on=lambda device: device.alert_state, # type: ignore[no-any-return]
|
||||
),
|
||||
FritzBinarySensorEntityDescription(
|
||||
key="lock",
|
||||
name="Button Lock on Device",
|
||||
translation_key="lock",
|
||||
device_class=BinarySensorDeviceClass.LOCK,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
suitable=lambda device: device.lock is not None,
|
||||
@@ -55,7 +55,7 @@ BINARY_SENSOR_TYPES: Final[tuple[FritzBinarySensorEntityDescription, ...]] = (
|
||||
),
|
||||
FritzBinarySensorEntityDescription(
|
||||
key="device_lock",
|
||||
name="Button Lock via UI",
|
||||
translation_key="device_lock",
|
||||
device_class=BinarySensorDeviceClass.LOCK,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
suitable=lambda device: device.device_lock is not None,
|
||||
@@ -87,17 +87,6 @@ class FritzboxBinarySensor(FritzBoxDeviceEntity, BinarySensorEntity):
|
||||
|
||||
entity_description: FritzBinarySensorEntityDescription
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
coordinator: FritzboxDataUpdateCoordinator,
|
||||
ain: str,
|
||||
entity_description: FritzBinarySensorEntityDescription,
|
||||
) -> None:
|
||||
"""Initialize the FritzBox entity."""
|
||||
super().__init__(coordinator, ain, entity_description)
|
||||
self._attr_name = f"{self.data.name} {entity_description.name}"
|
||||
self._attr_unique_id = f"{ain}_{entity_description.key}"
|
||||
|
||||
@property
|
||||
def is_on(self) -> bool | None:
|
||||
"""Return true if sensor is on."""
|
||||
|
||||
@@ -91,7 +91,7 @@ def value_scheduled_preset(device: FritzhomeDevice) -> str:
|
||||
SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
|
||||
FritzSensorEntityDescription(
|
||||
key="temperature",
|
||||
name="Temperature",
|
||||
translation_key="temperature",
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -101,7 +101,7 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="humidity",
|
||||
name="Humidity",
|
||||
translation_key="humidity",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -110,7 +110,7 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="battery",
|
||||
name="Battery",
|
||||
translation_key="battery",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.BATTERY,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
@@ -119,7 +119,7 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="power_consumption",
|
||||
name="Power Consumption",
|
||||
translation_key="power_consumption",
|
||||
native_unit_of_measurement=UnitOfPower.WATT,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -128,7 +128,7 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="voltage",
|
||||
name="Voltage",
|
||||
translation_key="voltage",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -137,7 +137,7 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="electric_current",
|
||||
name="Electric Current",
|
||||
translation_key="electric_current",
|
||||
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
|
||||
device_class=SensorDeviceClass.CURRENT,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -146,7 +146,7 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="total_energy",
|
||||
name="Total Energy",
|
||||
translation_key="total_energy",
|
||||
native_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
@@ -156,7 +156,7 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
|
||||
# Thermostat Sensors
|
||||
FritzSensorEntityDescription(
|
||||
key="comfort_temperature",
|
||||
name="Comfort Temperature",
|
||||
translation_key="comfort_temperature",
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
suitable=suitable_comfort_temperature,
|
||||
@@ -164,7 +164,7 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="eco_temperature",
|
||||
name="Eco Temperature",
|
||||
translation_key="eco_temperature",
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
suitable=suitable_eco_temperature,
|
||||
@@ -172,7 +172,7 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="nextchange_temperature",
|
||||
name="Next Scheduled Temperature",
|
||||
translation_key="nextchange_temperature",
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
suitable=suitable_nextchange_temperature,
|
||||
@@ -180,20 +180,20 @@ SENSOR_TYPES: Final[tuple[FritzSensorEntityDescription, ...]] = (
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="nextchange_time",
|
||||
name="Next Scheduled Change Time",
|
||||
translation_key="nextchange_time",
|
||||
device_class=SensorDeviceClass.TIMESTAMP,
|
||||
suitable=suitable_nextchange_time,
|
||||
native_value=lambda device: utc_from_timestamp(device.nextchange_endperiod),
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="nextchange_preset",
|
||||
name="Next Scheduled Preset",
|
||||
translation_key="nextchange_preset",
|
||||
suitable=suitable_nextchange_temperature,
|
||||
native_value=value_nextchange_preset,
|
||||
),
|
||||
FritzSensorEntityDescription(
|
||||
key="scheduled_preset",
|
||||
name="Current Scheduled Preset",
|
||||
translation_key="scheduled_preset",
|
||||
suitable=suitable_nextchange_temperature,
|
||||
native_value=value_scheduled_preset,
|
||||
),
|
||||
|
||||
@@ -36,5 +36,41 @@
|
||||
"error": {
|
||||
"invalid_auth": "[%key:common::config_flow::error::invalid_auth%]"
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"binary_sensor": {
|
||||
"alarm": { "name": "Alarm" },
|
||||
"device_lock": { "name": "Button lock via UI" },
|
||||
"lock": { "name": "Button lock on device" }
|
||||
},
|
||||
"sensor": {
|
||||
"battery": {
|
||||
"name": "[%key:component::sensor::entity_component::battery::name%]"
|
||||
},
|
||||
"comfort_temperature": { "name": "Comfort temperature" },
|
||||
"eco_temperature": { "name": "Eco temperature" },
|
||||
"electric_current": {
|
||||
"name": "[%key:component::sensor::entity_component::current::name%]"
|
||||
},
|
||||
"humidity": {
|
||||
"name": "[%key:component::sensor::entity_component::humidity::name%]"
|
||||
},
|
||||
"nextchange_preset": { "name": "Next scheduled preset" },
|
||||
"nextchange_temperature": { "name": "Next scheduled temperature" },
|
||||
"nextchange_time": { "name": "Next scheduled change time" },
|
||||
"power_consumption": {
|
||||
"name": "[%key:component::sensor::entity_component::power::name%]"
|
||||
},
|
||||
"scheduled_preset": { "name": "Current scheduled preset" },
|
||||
"temperature": {
|
||||
"name": "[%key:component::sensor::entity_component::temperature::name%]"
|
||||
},
|
||||
"total_energy": {
|
||||
"name": "[%key:component::sensor::entity_component::energy::name%]"
|
||||
},
|
||||
"voltage": {
|
||||
"name": "[%key:component::sensor::entity_component::voltage::name%]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
"integration_type": "device",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["fritzconnection"],
|
||||
"requirements": ["fritzconnection==1.11.0"]
|
||||
"requirements": ["fritzconnection==1.12.0"]
|
||||
}
|
||||
|
||||
@@ -89,28 +89,24 @@ class FroniusSensorEntityDescription(SensorEntityDescription):
|
||||
INVERTER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
FroniusSensorEntityDescription(
|
||||
key="energy_day",
|
||||
name="Energy day",
|
||||
native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="energy_year",
|
||||
name="Energy year",
|
||||
native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="energy_total",
|
||||
name="Energy total",
|
||||
native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="frequency_ac",
|
||||
name="Frequency AC",
|
||||
default_value=0,
|
||||
native_unit_of_measurement=UnitOfFrequency.HERTZ,
|
||||
device_class=SensorDeviceClass.FREQUENCY,
|
||||
@@ -119,7 +115,6 @@ INVERTER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="current_ac",
|
||||
name="Current AC",
|
||||
default_value=0,
|
||||
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
|
||||
device_class=SensorDeviceClass.CURRENT,
|
||||
@@ -127,7 +122,6 @@ INVERTER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="current_dc",
|
||||
name="Current DC",
|
||||
default_value=0,
|
||||
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
|
||||
device_class=SensorDeviceClass.CURRENT,
|
||||
@@ -136,7 +130,6 @@ INVERTER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="current_dc_2",
|
||||
name="Current DC 2",
|
||||
default_value=0,
|
||||
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
|
||||
device_class=SensorDeviceClass.CURRENT,
|
||||
@@ -145,7 +138,6 @@ INVERTER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_ac",
|
||||
name="Power AC",
|
||||
default_value=0,
|
||||
native_unit_of_measurement=UnitOfPower.WATT,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
@@ -153,7 +145,6 @@ INVERTER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="voltage_ac",
|
||||
name="Voltage AC",
|
||||
default_value=0,
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
@@ -162,7 +153,6 @@ INVERTER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="voltage_dc",
|
||||
name="Voltage DC",
|
||||
default_value=0,
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
@@ -171,7 +161,6 @@ INVERTER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="voltage_dc_2",
|
||||
name="Voltage DC 2",
|
||||
default_value=0,
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
@@ -181,28 +170,23 @@ INVERTER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
# device status entities
|
||||
FroniusSensorEntityDescription(
|
||||
key="inverter_state",
|
||||
name="Inverter state",
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="error_code",
|
||||
name="Error code",
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="status_code",
|
||||
name="Status code",
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="led_state",
|
||||
name="LED state",
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="led_color",
|
||||
name="LED color",
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
@@ -211,19 +195,16 @@ INVERTER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
LOGGER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
FroniusSensorEntityDescription(
|
||||
key="co2_factor",
|
||||
name="CO₂ factor",
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
icon="mdi:molecule-co2",
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="cash_factor",
|
||||
name="Grid export tariff",
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
icon="mdi:cash-plus",
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="delivery_factor",
|
||||
name="Grid import tariff",
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
icon="mdi:cash-minus",
|
||||
),
|
||||
@@ -232,7 +213,6 @@ LOGGER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
FroniusSensorEntityDescription(
|
||||
key="current_ac_phase_1",
|
||||
name="Current AC phase 1",
|
||||
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
|
||||
device_class=SensorDeviceClass.CURRENT,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -240,7 +220,6 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="current_ac_phase_2",
|
||||
name="Current AC phase 2",
|
||||
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
|
||||
device_class=SensorDeviceClass.CURRENT,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -248,7 +227,6 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="current_ac_phase_3",
|
||||
name="Current AC phase 3",
|
||||
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
|
||||
device_class=SensorDeviceClass.CURRENT,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -256,7 +234,6 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="energy_reactive_ac_consumed",
|
||||
name="Energy reactive AC consumed",
|
||||
native_unit_of_measurement=ENERGY_VOLT_AMPERE_REACTIVE_HOUR,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
icon="mdi:lightning-bolt-outline",
|
||||
@@ -264,7 +241,6 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="energy_reactive_ac_produced",
|
||||
name="Energy reactive AC produced",
|
||||
native_unit_of_measurement=ENERGY_VOLT_AMPERE_REACTIVE_HOUR,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
icon="mdi:lightning-bolt-outline",
|
||||
@@ -272,7 +248,6 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="energy_real_ac_minus",
|
||||
name="Energy real AC minus",
|
||||
native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
@@ -280,7 +255,6 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="energy_real_ac_plus",
|
||||
name="Energy real AC plus",
|
||||
native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
@@ -288,33 +262,28 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="energy_real_consumed",
|
||||
name="Energy real consumed",
|
||||
native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="energy_real_produced",
|
||||
name="Energy real produced",
|
||||
native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="frequency_phase_average",
|
||||
name="Frequency phase average",
|
||||
native_unit_of_measurement=UnitOfFrequency.HERTZ,
|
||||
device_class=SensorDeviceClass.FREQUENCY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="meter_location",
|
||||
name="Meter location",
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_apparent_phase_1",
|
||||
name="Power apparent phase 1",
|
||||
native_unit_of_measurement=UnitOfApparentPower.VOLT_AMPERE,
|
||||
device_class=SensorDeviceClass.APPARENT_POWER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -323,7 +292,6 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_apparent_phase_2",
|
||||
name="Power apparent phase 2",
|
||||
native_unit_of_measurement=UnitOfApparentPower.VOLT_AMPERE,
|
||||
device_class=SensorDeviceClass.APPARENT_POWER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -332,7 +300,6 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_apparent_phase_3",
|
||||
name="Power apparent phase 3",
|
||||
native_unit_of_measurement=UnitOfApparentPower.VOLT_AMPERE,
|
||||
device_class=SensorDeviceClass.APPARENT_POWER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -341,7 +308,6 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_apparent",
|
||||
name="Power apparent",
|
||||
native_unit_of_measurement=UnitOfApparentPower.VOLT_AMPERE,
|
||||
device_class=SensorDeviceClass.APPARENT_POWER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -350,34 +316,29 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_factor_phase_1",
|
||||
name="Power factor phase 1",
|
||||
device_class=SensorDeviceClass.POWER_FACTOR,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_factor_phase_2",
|
||||
name="Power factor phase 2",
|
||||
device_class=SensorDeviceClass.POWER_FACTOR,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_factor_phase_3",
|
||||
name="Power factor phase 3",
|
||||
device_class=SensorDeviceClass.POWER_FACTOR,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_factor",
|
||||
name="Power factor",
|
||||
device_class=SensorDeviceClass.POWER_FACTOR,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_reactive_phase_1",
|
||||
name="Power reactive phase 1",
|
||||
native_unit_of_measurement=POWER_VOLT_AMPERE_REACTIVE,
|
||||
device_class=SensorDeviceClass.REACTIVE_POWER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -386,7 +347,6 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_reactive_phase_2",
|
||||
name="Power reactive phase 2",
|
||||
native_unit_of_measurement=POWER_VOLT_AMPERE_REACTIVE,
|
||||
device_class=SensorDeviceClass.REACTIVE_POWER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -395,7 +355,6 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_reactive_phase_3",
|
||||
name="Power reactive phase 3",
|
||||
native_unit_of_measurement=POWER_VOLT_AMPERE_REACTIVE,
|
||||
device_class=SensorDeviceClass.REACTIVE_POWER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -404,7 +363,6 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_reactive",
|
||||
name="Power reactive",
|
||||
native_unit_of_measurement=POWER_VOLT_AMPERE_REACTIVE,
|
||||
device_class=SensorDeviceClass.REACTIVE_POWER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -413,7 +371,6 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_real_phase_1",
|
||||
name="Power real phase 1",
|
||||
native_unit_of_measurement=UnitOfPower.WATT,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -421,7 +378,6 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_real_phase_2",
|
||||
name="Power real phase 2",
|
||||
native_unit_of_measurement=UnitOfPower.WATT,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -429,7 +385,6 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_real_phase_3",
|
||||
name="Power real phase 3",
|
||||
native_unit_of_measurement=UnitOfPower.WATT,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -437,14 +392,12 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_real",
|
||||
name="Power real",
|
||||
native_unit_of_measurement=UnitOfPower.WATT,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="voltage_ac_phase_1",
|
||||
name="Voltage AC phase 1",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -452,7 +405,6 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="voltage_ac_phase_2",
|
||||
name="Voltage AC phase 2",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -460,7 +412,6 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="voltage_ac_phase_3",
|
||||
name="Voltage AC phase 3",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -468,7 +419,6 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="voltage_ac_phase_to_phase_12",
|
||||
name="Voltage AC phase 1-2",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -476,7 +426,6 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="voltage_ac_phase_to_phase_23",
|
||||
name="Voltage AC phase 2-3",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -484,7 +433,6 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="voltage_ac_phase_to_phase_31",
|
||||
name="Voltage AC phase 3-1",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -495,38 +443,32 @@ METER_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
OHMPILOT_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
FroniusSensorEntityDescription(
|
||||
key="energy_real_ac_consumed",
|
||||
name="Energy consumed",
|
||||
native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_real_ac",
|
||||
name="Power",
|
||||
native_unit_of_measurement=UnitOfPower.WATT,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="temperature_channel_1",
|
||||
name="Temperature channel 1",
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="error_code",
|
||||
name="Error code",
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="state_code",
|
||||
name="State code",
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="state_message",
|
||||
name="State message",
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
]
|
||||
@@ -534,7 +476,6 @@ OHMPILOT_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
POWER_FLOW_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
FroniusSensorEntityDescription(
|
||||
key="energy_day",
|
||||
name="Energy day",
|
||||
native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
@@ -542,7 +483,6 @@ POWER_FLOW_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="energy_year",
|
||||
name="Energy year",
|
||||
native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
@@ -550,7 +490,6 @@ POWER_FLOW_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="energy_total",
|
||||
name="Energy total",
|
||||
native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
|
||||
device_class=SensorDeviceClass.ENERGY,
|
||||
state_class=SensorStateClass.TOTAL_INCREASING,
|
||||
@@ -558,12 +497,10 @@ POWER_FLOW_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="meter_mode",
|
||||
name="Meter mode",
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_battery",
|
||||
name="Power battery",
|
||||
default_value=0,
|
||||
native_unit_of_measurement=UnitOfPower.WATT,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
@@ -571,7 +508,6 @@ POWER_FLOW_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_grid",
|
||||
name="Power grid",
|
||||
default_value=0,
|
||||
native_unit_of_measurement=UnitOfPower.WATT,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
@@ -579,7 +515,6 @@ POWER_FLOW_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_load",
|
||||
name="Power load",
|
||||
default_value=0,
|
||||
native_unit_of_measurement=UnitOfPower.WATT,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
@@ -587,7 +522,6 @@ POWER_FLOW_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="power_photovoltaics",
|
||||
name="Power photovoltaics",
|
||||
default_value=0,
|
||||
native_unit_of_measurement=UnitOfPower.WATT,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
@@ -595,7 +529,6 @@ POWER_FLOW_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="relative_autonomy",
|
||||
name="Relative autonomy",
|
||||
default_value=0,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -603,7 +536,6 @@ POWER_FLOW_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="relative_self_consumption",
|
||||
name="Relative self consumption",
|
||||
default_value=0,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -614,19 +546,16 @@ POWER_FLOW_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
STORAGE_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
FroniusSensorEntityDescription(
|
||||
key="capacity_maximum",
|
||||
name="Capacity maximum",
|
||||
native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="capacity_designed",
|
||||
name="Capacity designed",
|
||||
native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="current_dc",
|
||||
name="Current DC",
|
||||
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
|
||||
device_class=SensorDeviceClass.CURRENT,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -634,7 +563,6 @@ STORAGE_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="voltage_dc",
|
||||
name="Voltage DC",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -642,7 +570,6 @@ STORAGE_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="voltage_dc_maximum_cell",
|
||||
name="Voltage DC maximum cell",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -651,7 +578,6 @@ STORAGE_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="voltage_dc_minimum_cell",
|
||||
name="Voltage DC minimum cell",
|
||||
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||
device_class=SensorDeviceClass.VOLTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -660,14 +586,12 @@ STORAGE_ENTITY_DESCRIPTIONS: list[FroniusSensorEntityDescription] = [
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="state_of_charge",
|
||||
name="State of charge",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.BATTERY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
FroniusSensorEntityDescription(
|
||||
key="temperature_cell",
|
||||
name="Temperature cell",
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
@@ -696,6 +620,7 @@ class _FroniusSensorEntity(CoordinatorEntity["FroniusCoordinatorBase"], SensorEn
|
||||
)
|
||||
self.solar_net_id = solar_net_id
|
||||
self._attr_native_value = self._get_entity_value()
|
||||
self._attr_translation_key = self.entity_description.key
|
||||
|
||||
def _device_data(self) -> dict[str, Any]:
|
||||
"""Extract information for SolarNet device from coordinator data."""
|
||||
|
||||
@@ -21,5 +21,219 @@
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
|
||||
"invalid_host": "[%key:common::config_flow::error::invalid_host%]"
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"energy_day": {
|
||||
"name": "Energy day"
|
||||
},
|
||||
"energy_year": {
|
||||
"name": "Energy year"
|
||||
},
|
||||
"energy_total": {
|
||||
"name": "Total energy"
|
||||
},
|
||||
"frequency_ac": {
|
||||
"name": "[%key:component::sensor::entity_component::frequency::name%]"
|
||||
},
|
||||
"current_ac": {
|
||||
"name": "AC current"
|
||||
},
|
||||
"current_dc": {
|
||||
"name": "DC current"
|
||||
},
|
||||
"current_dc_2": {
|
||||
"name": "DC current 2"
|
||||
},
|
||||
"power_ac": {
|
||||
"name": "AC power"
|
||||
},
|
||||
"voltage_ac": {
|
||||
"name": "AC voltage"
|
||||
},
|
||||
"voltage_dc": {
|
||||
"name": "DC voltage"
|
||||
},
|
||||
"voltage_dc_2": {
|
||||
"name": "DC voltage 2"
|
||||
},
|
||||
"inverter_state": {
|
||||
"name": "Inverter state"
|
||||
},
|
||||
"error_code": {
|
||||
"name": "Error code"
|
||||
},
|
||||
"status_code": {
|
||||
"name": "Status code"
|
||||
},
|
||||
"led_state": {
|
||||
"name": "LED state"
|
||||
},
|
||||
"led_color": {
|
||||
"name": "LED color"
|
||||
},
|
||||
"co2_factor": {
|
||||
"name": "CO₂ factor"
|
||||
},
|
||||
"cash_factor": {
|
||||
"name": "Grid export tariff"
|
||||
},
|
||||
"delivery_factor": {
|
||||
"name": "Grid import tariff"
|
||||
},
|
||||
"current_ac_phase_1": {
|
||||
"name": "Current phase 1"
|
||||
},
|
||||
"current_ac_phase_2": {
|
||||
"name": "Current phase 2"
|
||||
},
|
||||
"current_ac_phase_3": {
|
||||
"name": "Current phase 3"
|
||||
},
|
||||
"energy_reactive_ac_consumed": {
|
||||
"name": "Reactive energy consumed"
|
||||
},
|
||||
"energy_reactive_ac_produced": {
|
||||
"name": "Reactive energy produced"
|
||||
},
|
||||
"energy_real_ac_minus": {
|
||||
"name": "Real energy minus"
|
||||
},
|
||||
"energy_real_ac_plus": {
|
||||
"name": "Real energy plus"
|
||||
},
|
||||
"energy_real_consumed": {
|
||||
"name": "Real energy consumed"
|
||||
},
|
||||
"energy_real_produced": {
|
||||
"name": "Real energy produced"
|
||||
},
|
||||
"frequency_phase_average": {
|
||||
"name": "Frequency phase average"
|
||||
},
|
||||
"meter_location": {
|
||||
"name": "Meter location"
|
||||
},
|
||||
"power_apparent_phase_1": {
|
||||
"name": "Apparent power phase 1"
|
||||
},
|
||||
"power_apparent_phase_2": {
|
||||
"name": "Apparent power phase 2"
|
||||
},
|
||||
"power_apparent_phase_3": {
|
||||
"name": "Apparent power phase 3"
|
||||
},
|
||||
"power_apparent": {
|
||||
"name": "[%key:component::sensor::entity_component::apparent_power::name%]"
|
||||
},
|
||||
"power_factor_phase_1": {
|
||||
"name": "Power factor phase 1"
|
||||
},
|
||||
"power_factor_phase_2": {
|
||||
"name": "Power factor phase 2"
|
||||
},
|
||||
"power_factor_phase_3": {
|
||||
"name": "Power factor phase 3"
|
||||
},
|
||||
"power_factor": {
|
||||
"name": "[%key:component::sensor::entity_component::power_factor::name%]"
|
||||
},
|
||||
"power_reactive_phase_1": {
|
||||
"name": "Reactive power phase 1"
|
||||
},
|
||||
"power_reactive_phase_2": {
|
||||
"name": "Reactive power phase 2"
|
||||
},
|
||||
"power_reactive_phase_3": {
|
||||
"name": "Reactive power phase 3"
|
||||
},
|
||||
"power_reactive": {
|
||||
"name": "Reactive power"
|
||||
},
|
||||
"power_real_phase_1": {
|
||||
"name": "Real power phase 1"
|
||||
},
|
||||
"power_real_phase_2": {
|
||||
"name": "Real power phase 2"
|
||||
},
|
||||
"power_real_phase_3": {
|
||||
"name": "Real power phase 3"
|
||||
},
|
||||
"power_real": {
|
||||
"name": "Real power"
|
||||
},
|
||||
"voltage_ac_phase_1": {
|
||||
"name": "Voltage phase 1"
|
||||
},
|
||||
"voltage_ac_phase_2": {
|
||||
"name": "Voltage phase 2"
|
||||
},
|
||||
"voltage_ac_phase_3": {
|
||||
"name": "Voltage phase 3"
|
||||
},
|
||||
"voltage_ac_phase_to_phase_12": {
|
||||
"name": "Voltage phase 1-2"
|
||||
},
|
||||
"voltage_ac_phase_to_phase_23": {
|
||||
"name": "Voltage phase 2-3"
|
||||
},
|
||||
"voltage_ac_phase_to_phase_31": {
|
||||
"name": "Voltage phase 3-1"
|
||||
},
|
||||
"energy_real_ac_consumed": {
|
||||
"name": "Energy consumed"
|
||||
},
|
||||
"power_real_ac": {
|
||||
"name": "[%key:component::sensor::entity_component::power::name%]"
|
||||
},
|
||||
"temperature_channel_1": {
|
||||
"name": "[%key:component::sensor::entity_component::temperature::name%]"
|
||||
},
|
||||
"state_code": {
|
||||
"name": "State code"
|
||||
},
|
||||
"state_message": {
|
||||
"name": "State message"
|
||||
},
|
||||
"meter_mode": {
|
||||
"name": "Meter mode"
|
||||
},
|
||||
"power_battery": {
|
||||
"name": "Power battery"
|
||||
},
|
||||
"power_grid": {
|
||||
"name": "Power grid"
|
||||
},
|
||||
"power_load": {
|
||||
"name": "Power load"
|
||||
},
|
||||
"power_photovoltaics": {
|
||||
"name": "Power photovoltaics"
|
||||
},
|
||||
"relative_autonomy": {
|
||||
"name": "Relative autonomy"
|
||||
},
|
||||
"relative_self_consumption": {
|
||||
"name": "Relative self consumption"
|
||||
},
|
||||
"capacity_maximum": {
|
||||
"name": "Maximum capacity "
|
||||
},
|
||||
"capacity_designed": {
|
||||
"name": "Designed capacity"
|
||||
},
|
||||
"voltage_dc_maximum_cell": {
|
||||
"name": "Maximum cell voltage"
|
||||
},
|
||||
"voltage_dc_minimum_cell": {
|
||||
"name": "Minimum cell voltage"
|
||||
},
|
||||
"state_of_charge": {
|
||||
"name": "State of charge"
|
||||
},
|
||||
"temperature_cell": {
|
||||
"name": "[%key:component::sensor::entity_component::temperature::name%]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,5 +20,5 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/frontend",
|
||||
"integration_type": "system",
|
||||
"quality_scale": "internal",
|
||||
"requirements": ["home-assistant-frontend==20230330.0"]
|
||||
"requirements": ["home-assistant-frontend==20230411.1"]
|
||||
}
|
||||
|
||||
@@ -60,7 +60,6 @@ class GiosSensorEntityDescription(SensorEntityDescription, GiosSensorRequiredKey
|
||||
SENSOR_TYPES: tuple[GiosSensorEntityDescription, ...] = (
|
||||
GiosSensorEntityDescription(
|
||||
key=ATTR_AQI,
|
||||
name="AQI",
|
||||
value=lambda sensors: sensors.aqi.value if sensors.aqi else None,
|
||||
icon="mdi:air-filter",
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
@@ -69,35 +68,34 @@ SENSOR_TYPES: tuple[GiosSensorEntityDescription, ...] = (
|
||||
),
|
||||
GiosSensorEntityDescription(
|
||||
key=ATTR_C6H6,
|
||||
name="C6H6",
|
||||
value=lambda sensors: sensors.c6h6.value if sensors.c6h6 else None,
|
||||
suggested_display_precision=0,
|
||||
icon="mdi:molecule",
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
translation_key="c6h6",
|
||||
),
|
||||
GiosSensorEntityDescription(
|
||||
key=ATTR_CO,
|
||||
name="CO",
|
||||
value=lambda sensors: sensors.co.value if sensors.co else None,
|
||||
suggested_display_precision=0,
|
||||
icon="mdi:molecule",
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
translation_key="co",
|
||||
),
|
||||
GiosSensorEntityDescription(
|
||||
key=ATTR_NO2,
|
||||
name="NO2",
|
||||
value=lambda sensors: sensors.no2.value if sensors.no2 else None,
|
||||
suggested_display_precision=0,
|
||||
device_class=SensorDeviceClass.NITROGEN_DIOXIDE,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
translation_key="no2",
|
||||
),
|
||||
GiosSensorEntityDescription(
|
||||
key=ATTR_NO2,
|
||||
subkey="index",
|
||||
name="NO2 index",
|
||||
value=lambda sensors: sensors.no2.index if sensors.no2 else None,
|
||||
icon="mdi:molecule",
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
@@ -106,17 +104,16 @@ SENSOR_TYPES: tuple[GiosSensorEntityDescription, ...] = (
|
||||
),
|
||||
GiosSensorEntityDescription(
|
||||
key=ATTR_O3,
|
||||
name="O3",
|
||||
value=lambda sensors: sensors.o3.value if sensors.o3 else None,
|
||||
suggested_display_precision=0,
|
||||
device_class=SensorDeviceClass.OZONE,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
translation_key="o3",
|
||||
),
|
||||
GiosSensorEntityDescription(
|
||||
key=ATTR_O3,
|
||||
subkey="index",
|
||||
name="O3 index",
|
||||
value=lambda sensors: sensors.o3.index if sensors.o3 else None,
|
||||
icon="mdi:molecule",
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
@@ -125,17 +122,16 @@ SENSOR_TYPES: tuple[GiosSensorEntityDescription, ...] = (
|
||||
),
|
||||
GiosSensorEntityDescription(
|
||||
key=ATTR_PM10,
|
||||
name="PM10",
|
||||
value=lambda sensors: sensors.pm10.value if sensors.pm10 else None,
|
||||
suggested_display_precision=0,
|
||||
device_class=SensorDeviceClass.PM10,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
translation_key="pm10",
|
||||
),
|
||||
GiosSensorEntityDescription(
|
||||
key=ATTR_PM10,
|
||||
subkey="index",
|
||||
name="PM10 index",
|
||||
value=lambda sensors: sensors.pm10.index if sensors.pm10 else None,
|
||||
icon="mdi:molecule",
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
@@ -144,17 +140,16 @@ SENSOR_TYPES: tuple[GiosSensorEntityDescription, ...] = (
|
||||
),
|
||||
GiosSensorEntityDescription(
|
||||
key=ATTR_PM25,
|
||||
name="PM2.5",
|
||||
value=lambda sensors: sensors.pm25.value if sensors.pm25 else None,
|
||||
suggested_display_precision=0,
|
||||
device_class=SensorDeviceClass.PM25,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
translation_key="pm25",
|
||||
),
|
||||
GiosSensorEntityDescription(
|
||||
key=ATTR_PM25,
|
||||
subkey="index",
|
||||
name="PM2.5 index",
|
||||
value=lambda sensors: sensors.pm25.index if sensors.pm25 else None,
|
||||
icon="mdi:molecule",
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
@@ -163,17 +158,16 @@ SENSOR_TYPES: tuple[GiosSensorEntityDescription, ...] = (
|
||||
),
|
||||
GiosSensorEntityDescription(
|
||||
key=ATTR_SO2,
|
||||
name="SO2",
|
||||
value=lambda sensors: sensors.so2.value if sensors.so2 else None,
|
||||
suggested_display_precision=0,
|
||||
device_class=SensorDeviceClass.SULPHUR_DIOXIDE,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
translation_key="so2",
|
||||
),
|
||||
GiosSensorEntityDescription(
|
||||
key=ATTR_SO2,
|
||||
subkey="index",
|
||||
name="SO2 index",
|
||||
value=lambda sensors: sensors.so2.index if sensors.so2 else None,
|
||||
icon="mdi:molecule",
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"aqi": {
|
||||
"name": "[%key:component::sensor::entity_component::aqi::name%]",
|
||||
"state": {
|
||||
"very_bad": "Very bad",
|
||||
"bad": "Bad",
|
||||
@@ -35,7 +36,17 @@
|
||||
"very_good": "Very good"
|
||||
}
|
||||
},
|
||||
"c6h6": {
|
||||
"name": "Benzene"
|
||||
},
|
||||
"co": {
|
||||
"name": "[%key:component::sensor::entity_component::carbon_monoxide::name%]"
|
||||
},
|
||||
"no2": {
|
||||
"name": "[%key:component::sensor::entity_component::nitrogen_dioxide::name%]"
|
||||
},
|
||||
"no2_index": {
|
||||
"name": "Nitrogen dioxide index",
|
||||
"state": {
|
||||
"very_bad": "[%key:component::gios::entity::sensor::aqi::state::very_bad%]",
|
||||
"bad": "[%key:component::gios::entity::sensor::aqi::state::bad%]",
|
||||
@@ -45,7 +56,11 @@
|
||||
"very_good": "[%key:component::gios::entity::sensor::aqi::state::very_good%]"
|
||||
}
|
||||
},
|
||||
"o3": {
|
||||
"name": "[%key:component::sensor::entity_component::ozone::name%]"
|
||||
},
|
||||
"o3_index": {
|
||||
"name": "Ozone index",
|
||||
"state": {
|
||||
"very_bad": "[%key:component::gios::entity::sensor::aqi::state::very_bad%]",
|
||||
"bad": "[%key:component::gios::entity::sensor::aqi::state::bad%]",
|
||||
@@ -55,7 +70,11 @@
|
||||
"very_good": "[%key:component::gios::entity::sensor::aqi::state::very_good%]"
|
||||
}
|
||||
},
|
||||
"pm10": {
|
||||
"name": "[%key:component::sensor::entity_component::pm10::name%]"
|
||||
},
|
||||
"pm10_index": {
|
||||
"name": "Particulate matter 10 μm index",
|
||||
"state": {
|
||||
"very_bad": "[%key:component::gios::entity::sensor::aqi::state::very_bad%]",
|
||||
"bad": "[%key:component::gios::entity::sensor::aqi::state::bad%]",
|
||||
@@ -65,7 +84,11 @@
|
||||
"very_good": "[%key:component::gios::entity::sensor::aqi::state::very_good%]"
|
||||
}
|
||||
},
|
||||
"pm25": {
|
||||
"name": "[%key:component::sensor::entity_component::pm25::name%]"
|
||||
},
|
||||
"pm25_index": {
|
||||
"name": "Particulate matter 2.5 μm index",
|
||||
"state": {
|
||||
"very_bad": "[%key:component::gios::entity::sensor::aqi::state::very_bad%]",
|
||||
"bad": "[%key:component::gios::entity::sensor::aqi::state::bad%]",
|
||||
@@ -75,7 +98,11 @@
|
||||
"very_good": "[%key:component::gios::entity::sensor::aqi::state::very_good%]"
|
||||
}
|
||||
},
|
||||
"so2": {
|
||||
"name": "[%key:component::sensor::entity_component::sulphur_dioxide::name%]"
|
||||
},
|
||||
"so2_index": {
|
||||
"name": "Sulphur dioxide index",
|
||||
"state": {
|
||||
"very_bad": "[%key:component::gios::entity::sensor::aqi::state::very_bad%]",
|
||||
"bad": "[%key:component::gios::entity::sensor::aqi::state::bad%]",
|
||||
|
||||
@@ -6,5 +6,5 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/goodwe",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["goodwe"],
|
||||
"requirements": ["goodwe==0.2.29"]
|
||||
"requirements": ["goodwe==0.2.30"]
|
||||
}
|
||||
|
||||
@@ -285,17 +285,18 @@ async def async_setup_add_event_service(
|
||||
raise ValueError(
|
||||
"Missing required fields to set start or end date/datetime"
|
||||
)
|
||||
|
||||
event = Event(
|
||||
summary=call.data[EVENT_SUMMARY],
|
||||
description=call.data[EVENT_DESCRIPTION],
|
||||
start=start,
|
||||
end=end,
|
||||
)
|
||||
if location := call.data.get(EVENT_LOCATION):
|
||||
event.location = location
|
||||
try:
|
||||
await calendar_service.async_create_event(
|
||||
call.data[EVENT_CALENDAR_ID],
|
||||
Event(
|
||||
summary=call.data[EVENT_SUMMARY],
|
||||
description=call.data[EVENT_DESCRIPTION],
|
||||
location=call.data[EVENT_LOCATION],
|
||||
start=start,
|
||||
end=end,
|
||||
),
|
||||
event,
|
||||
)
|
||||
except ApiException as err:
|
||||
raise HomeAssistantError(str(err)) from err
|
||||
|
||||
@@ -508,9 +508,10 @@ class GoogleCalendarEntity(
|
||||
"start": start,
|
||||
"end": end,
|
||||
EVENT_DESCRIPTION: kwargs.get(EVENT_DESCRIPTION),
|
||||
EVENT_LOCATION: kwargs.get(EVENT_LOCATION),
|
||||
}
|
||||
)
|
||||
if location := kwargs.get(EVENT_LOCATION):
|
||||
event.location = location
|
||||
if rrule := kwargs.get(EVENT_RRULE):
|
||||
event.recurrence = [f"{RRULE_PREFIX}{rrule}"]
|
||||
|
||||
@@ -597,18 +598,20 @@ async def async_create_event(entity: GoogleCalendarEntity, call: ServiceCall) ->
|
||||
if start is None or end is None:
|
||||
raise ValueError("Missing required fields to set start or end date/datetime")
|
||||
|
||||
event = Event(
|
||||
summary=call.data[EVENT_SUMMARY],
|
||||
description=call.data[EVENT_DESCRIPTION],
|
||||
start=start,
|
||||
end=end,
|
||||
)
|
||||
if location := call.data.get(EVENT_LOCATION):
|
||||
event.location = location
|
||||
try:
|
||||
await cast(
|
||||
CalendarSyncUpdateCoordinator, entity.coordinator
|
||||
).sync.api.async_create_event(
|
||||
entity.calendar_id,
|
||||
Event(
|
||||
summary=call.data[EVENT_SUMMARY],
|
||||
description=call.data[EVENT_DESCRIPTION],
|
||||
location=call.data[EVENT_LOCATION],
|
||||
start=start,
|
||||
end=end,
|
||||
),
|
||||
event,
|
||||
)
|
||||
except ApiException as err:
|
||||
raise HomeAssistantError(str(err)) from err
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/calendar.google/",
|
||||
"iot_class": "cloud_polling",
|
||||
"loggers": ["googleapiclient"],
|
||||
"requirements": ["gcal-sync==4.1.2", "oauth2client==4.1.3"]
|
||||
"requirements": ["gcal-sync==4.1.4", "oauth2client==4.1.3"]
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ LANG_TO_BROADCAST_COMMAND = {
|
||||
"it": ("Trasmetti {0}", "Trasmetti in {1} {0}"),
|
||||
"ja": ("{0}とブロードキャストして", "{0}と{1}にブロードキャストして"),
|
||||
"ko": ("{0} 라고 방송해 줘", "{0} 라고 {1}에 방송해 줘"),
|
||||
"pt": ("Transmite {0}", "Transmite para {1} {0}"),
|
||||
"pt": ("Transmitir {0}", "Transmitir {0} para {1}"),
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -870,23 +870,25 @@ class HassioDataUpdateCoordinator(DataUpdateCoordinator):
|
||||
self.hassio.get_os_info(),
|
||||
)
|
||||
|
||||
addons = [
|
||||
addon
|
||||
for addon in self.hass.data[DATA_SUPERVISOR_INFO].get("addons", [])
|
||||
if addon[ATTR_STATE] == ATTR_STARTED
|
||||
all_addons = self.hass.data[DATA_SUPERVISOR_INFO].get("addons", [])
|
||||
started_addons = [
|
||||
addon for addon in all_addons if addon[ATTR_STATE] == ATTR_STARTED
|
||||
]
|
||||
stats_data = await asyncio.gather(
|
||||
*[self._update_addon_stats(addon[ATTR_SLUG]) for addon in addons]
|
||||
*[self._update_addon_stats(addon[ATTR_SLUG]) for addon in started_addons]
|
||||
)
|
||||
self.hass.data[DATA_ADDONS_STATS] = dict(stats_data)
|
||||
self.hass.data[DATA_ADDONS_CHANGELOGS] = dict(
|
||||
await asyncio.gather(
|
||||
*[self._update_addon_changelog(addon[ATTR_SLUG]) for addon in addons]
|
||||
*[
|
||||
self._update_addon_changelog(addon[ATTR_SLUG])
|
||||
for addon in all_addons
|
||||
]
|
||||
)
|
||||
)
|
||||
self.hass.data[DATA_ADDONS_INFO] = dict(
|
||||
await asyncio.gather(
|
||||
*[self._update_addon_info(addon[ATTR_SLUG]) for addon in addons]
|
||||
*[self._update_addon_info(addon[ATTR_SLUG]) for addon in all_addons]
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ class DeviceWithPrograms(HomeConnectDevice):
|
||||
programs_available = self.appliance.get_programs_available()
|
||||
except (HomeConnectError, ValueError):
|
||||
_LOGGER.debug("Unable to fetch available programs. Probably offline")
|
||||
programs_available = None
|
||||
programs_available = []
|
||||
return programs_available
|
||||
|
||||
def get_program_switches(self):
|
||||
|
||||
@@ -272,7 +272,8 @@ class HKDevice:
|
||||
self.hass,
|
||||
self.async_update_available_state,
|
||||
timedelta(seconds=BLE_AVAILABILITY_CHECK_INTERVAL),
|
||||
f"HomeKit Controller {self.unique_id} BLE availability check poll",
|
||||
name=f"HomeKit Controller {self.unique_id} BLE availability "
|
||||
"check poll",
|
||||
)
|
||||
)
|
||||
# BLE devices always get an RSSI sensor as well
|
||||
@@ -290,7 +291,7 @@ class HKDevice:
|
||||
self.hass,
|
||||
self.async_request_update,
|
||||
self.pairing.poll_interval,
|
||||
f"HomeKit Controller {self.unique_id} availability check poll",
|
||||
name=f"HomeKit Controller {self.unique_id} availability check poll",
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@@ -14,6 +14,6 @@
|
||||
"documentation": "https://www.home-assistant.io/integrations/homekit_controller",
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["aiohomekit", "commentjson"],
|
||||
"requirements": ["aiohomekit==2.6.1"],
|
||||
"requirements": ["aiohomekit==2.6.3"],
|
||||
"zeroconf": ["_hap._tcp.local.", "_hap._udp.local."]
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
"""Support for HomeWizard buttons."""
|
||||
|
||||
from homeassistant.components.button import ButtonEntity
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.const import EntityCategory
|
||||
@@ -16,7 +17,7 @@ async def async_setup_entry(
|
||||
) -> None:
|
||||
"""Set up the Identify button."""
|
||||
coordinator: HWEnergyDeviceUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
|
||||
if coordinator.data.features.has_identify:
|
||||
if coordinator.supports_identify():
|
||||
async_add_entities([HomeWizardIdentifyButton(coordinator, entry)])
|
||||
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ from __future__ import annotations
|
||||
from dataclasses import dataclass
|
||||
from datetime import timedelta
|
||||
|
||||
from homewizard_energy.features import Features
|
||||
from homewizard_energy.models import Data, Device, State, System
|
||||
|
||||
from homeassistant.const import Platform
|
||||
@@ -30,6 +29,5 @@ class DeviceResponseEntry:
|
||||
|
||||
device: Device
|
||||
data: Data
|
||||
features: Features
|
||||
state: State | None
|
||||
state: State | None = None
|
||||
system: System | None = None
|
||||
|
||||
@@ -4,7 +4,9 @@ from __future__ import annotations
|
||||
import logging
|
||||
|
||||
from homewizard_energy import HomeWizardEnergy
|
||||
from homewizard_energy.errors import DisabledError, RequestError
|
||||
from homewizard_energy.const import SUPPORTS_IDENTIFY, SUPPORTS_STATE, SUPPORTS_SYSTEM
|
||||
from homewizard_energy.errors import DisabledError, RequestError, UnsupportedError
|
||||
from homewizard_energy.models import Device
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry
|
||||
from homeassistant.core import HomeAssistant
|
||||
@@ -22,6 +24,8 @@ class HWEnergyDeviceUpdateCoordinator(DataUpdateCoordinator[DeviceResponseEntry]
|
||||
api: HomeWizardEnergy
|
||||
api_disabled: bool = False
|
||||
|
||||
_unsupported_error: bool = False
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
hass: HomeAssistant,
|
||||
@@ -39,12 +43,24 @@ class HWEnergyDeviceUpdateCoordinator(DataUpdateCoordinator[DeviceResponseEntry]
|
||||
data = DeviceResponseEntry(
|
||||
device=await self.api.device(),
|
||||
data=await self.api.data(),
|
||||
features=await self.api.features(),
|
||||
state=await self.api.state(),
|
||||
)
|
||||
|
||||
if data.features.has_system:
|
||||
data.system = await self.api.system()
|
||||
try:
|
||||
if self.supports_state(data.device):
|
||||
data.state = await self.api.state()
|
||||
|
||||
if self.supports_system(data.device):
|
||||
data.system = await self.api.system()
|
||||
|
||||
except UnsupportedError as ex:
|
||||
# Old firmware, ignore
|
||||
if not self._unsupported_error:
|
||||
self._unsupported_error = True
|
||||
_LOGGER.warning(
|
||||
"%s is running an outdated firmware version (%s). Contact HomeWizard support to update your device",
|
||||
self.entry.title,
|
||||
ex,
|
||||
)
|
||||
|
||||
except RequestError as ex:
|
||||
raise UpdateFailed(ex) from ex
|
||||
@@ -61,4 +77,27 @@ class HWEnergyDeviceUpdateCoordinator(DataUpdateCoordinator[DeviceResponseEntry]
|
||||
|
||||
self.api_disabled = False
|
||||
|
||||
self.data = data
|
||||
return data
|
||||
|
||||
def supports_state(self, device: Device | None = None) -> bool:
|
||||
"""Return True if the device supports state."""
|
||||
|
||||
if device is None:
|
||||
device = self.data.device
|
||||
|
||||
return device.product_type in SUPPORTS_STATE
|
||||
|
||||
def supports_system(self, device: Device | None = None) -> bool:
|
||||
"""Return True if the device supports system."""
|
||||
if device is None:
|
||||
device = self.data.device
|
||||
|
||||
return device.product_type in SUPPORTS_SYSTEM
|
||||
|
||||
def supports_identify(self, device: Device | None = None) -> bool:
|
||||
"""Return True if the device supports identify."""
|
||||
if device is None:
|
||||
device = self.data.device
|
||||
|
||||
return device.product_type in SUPPORTS_IDENTIFY
|
||||
|
||||
@@ -8,6 +8,6 @@
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["homewizard_energy"],
|
||||
"quality_scale": "platinum",
|
||||
"requirements": ["python-homewizard-energy==1.8.0"],
|
||||
"requirements": ["python-homewizard-energy==2.0.1"],
|
||||
"zeroconf": ["_hwenergy._tcp.local."]
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ async def async_setup_entry(
|
||||
) -> None:
|
||||
"""Set up numbers for device."""
|
||||
coordinator: HWEnergyDeviceUpdateCoordinator = hass.data[DOMAIN][entry.entry_id]
|
||||
if coordinator.data.state:
|
||||
if coordinator.supports_state():
|
||||
async_add_entities([HWEnergyNumberEntity(coordinator, entry)])
|
||||
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ from .helpers import homewizard_exception_handler
|
||||
class HomeWizardEntityDescriptionMixin:
|
||||
"""Mixin values for HomeWizard entities."""
|
||||
|
||||
create_fn: Callable[[DeviceResponseEntry], bool]
|
||||
create_fn: Callable[[HWEnergyDeviceUpdateCoordinator], bool]
|
||||
available_fn: Callable[[DeviceResponseEntry], bool]
|
||||
is_on_fn: Callable[[DeviceResponseEntry], bool | None]
|
||||
set_fn: Callable[[HomeWizardEnergy, bool], Awaitable[Any]]
|
||||
@@ -46,7 +46,7 @@ SWITCHES = [
|
||||
HomeWizardSwitchEntityDescription(
|
||||
key="power_on",
|
||||
device_class=SwitchDeviceClass.OUTLET,
|
||||
create_fn=lambda data: data.state is not None,
|
||||
create_fn=lambda coordinator: coordinator.supports_state(),
|
||||
available_fn=lambda data: data.state is not None and not data.state.switch_lock,
|
||||
is_on_fn=lambda data: data.state.power_on if data.state else None,
|
||||
set_fn=lambda api, active: api.state_set(power_on=active),
|
||||
@@ -57,7 +57,7 @@ SWITCHES = [
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
icon="mdi:lock",
|
||||
icon_off="mdi:lock-open",
|
||||
create_fn=lambda data: data.state is not None,
|
||||
create_fn=lambda coordinator: coordinator.supports_state(),
|
||||
available_fn=lambda data: data.state is not None,
|
||||
is_on_fn=lambda data: data.state.switch_lock if data.state else None,
|
||||
set_fn=lambda api, active: api.state_set(switch_lock=active),
|
||||
@@ -68,7 +68,7 @@ SWITCHES = [
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
icon="mdi:cloud",
|
||||
icon_off="mdi:cloud-off-outline",
|
||||
create_fn=lambda data: data.system is not None,
|
||||
create_fn=lambda coordinator: coordinator.supports_system(),
|
||||
available_fn=lambda data: data.system is not None,
|
||||
is_on_fn=lambda data: data.system.cloud_enabled if data.system else None,
|
||||
set_fn=lambda api, active: api.system_set(cloud_enabled=active),
|
||||
@@ -91,7 +91,7 @@ async def async_setup_entry(
|
||||
entry=entry,
|
||||
)
|
||||
for description in SWITCHES
|
||||
if description.available_fn(coordinator.data)
|
||||
if description.create_fn(coordinator)
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
"""Support for Honeywell (US) Total Connect Comfort climate systems."""
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
import datetime
|
||||
from typing import Any
|
||||
|
||||
from aiohttp import ClientConnectionError
|
||||
import aiosomecomfort
|
||||
|
||||
from homeassistant.components.climate import (
|
||||
@@ -421,10 +423,7 @@ class HoneywellUSThermostat(ClimateEntity):
|
||||
try:
|
||||
await self._device.refresh()
|
||||
self._attr_available = True
|
||||
except (
|
||||
aiosomecomfort.SomeComfortError,
|
||||
OSError,
|
||||
):
|
||||
except aiosomecomfort.SomeComfortError:
|
||||
try:
|
||||
await self._data.client.login()
|
||||
|
||||
@@ -433,5 +432,12 @@ class HoneywellUSThermostat(ClimateEntity):
|
||||
await self.hass.async_create_task(
|
||||
self.hass.config_entries.async_reload(self._data.entry_id)
|
||||
)
|
||||
except aiosomecomfort.SomeComfortError:
|
||||
except (
|
||||
aiosomecomfort.SomeComfortError,
|
||||
ClientConnectionError,
|
||||
asyncio.TimeoutError,
|
||||
):
|
||||
self._attr_available = False
|
||||
|
||||
except (ClientConnectionError, asyncio.TimeoutError):
|
||||
self._attr_available = False
|
||||
|
||||
@@ -8,7 +8,7 @@ import email
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
from aioimaplib import AUTH, IMAP4_SSL, SELECTED, AioImapException
|
||||
from aioimaplib import AUTH, IMAP4_SSL, NONAUTH, SELECTED, AioImapException
|
||||
import async_timeout
|
||||
|
||||
from homeassistant.config_entries import ConfigEntry, ConfigEntryState
|
||||
@@ -36,10 +36,12 @@ async def connect_to_server(data: Mapping[str, Any]) -> IMAP4_SSL:
|
||||
"""Connect to imap server and return client."""
|
||||
client = IMAP4_SSL(data[CONF_SERVER], data[CONF_PORT])
|
||||
await client.wait_hello_from_server()
|
||||
await client.login(data[CONF_USERNAME], data[CONF_PASSWORD])
|
||||
if client.protocol.state != AUTH:
|
||||
if client.protocol.state == NONAUTH:
|
||||
await client.login(data[CONF_USERNAME], data[CONF_PASSWORD])
|
||||
if client.protocol.state not in {AUTH, SELECTED}:
|
||||
raise InvalidAuth("Invalid username or password")
|
||||
await client.select(data[CONF_FOLDER])
|
||||
if client.protocol.state == AUTH:
|
||||
await client.select(data[CONF_FOLDER])
|
||||
if client.protocol.state != SELECTED:
|
||||
raise InvalidFolder(f"Folder {data[CONF_FOLDER]} is invalid")
|
||||
return client
|
||||
@@ -192,7 +194,11 @@ class ImapDataUpdateCoordinator(DataUpdateCoordinator[int | None]):
|
||||
if count
|
||||
else None
|
||||
)
|
||||
if count and last_message_id is not None:
|
||||
if (
|
||||
count
|
||||
and last_message_id is not None
|
||||
and self._last_message_id != last_message_id
|
||||
):
|
||||
self._last_message_id = last_message_id
|
||||
await self._async_process_event(last_message_id)
|
||||
|
||||
@@ -207,10 +213,9 @@ class ImapDataUpdateCoordinator(DataUpdateCoordinator[int | None]):
|
||||
await self.imap_client.stop_wait_server_push()
|
||||
await self.imap_client.close()
|
||||
await self.imap_client.logout()
|
||||
except (AioImapException, asyncio.TimeoutError) as ex:
|
||||
except (AioImapException, asyncio.TimeoutError):
|
||||
if log_error:
|
||||
self.async_set_update_error(ex)
|
||||
_LOGGER.warning("Error while cleaning up imap connection")
|
||||
_LOGGER.debug("Error while cleaning up imap connection")
|
||||
self.imap_client = None
|
||||
|
||||
async def shutdown(self, *_) -> None:
|
||||
@@ -234,18 +239,18 @@ class ImapPollingDataUpdateCoordinator(ImapDataUpdateCoordinator):
|
||||
UpdateFailed,
|
||||
asyncio.TimeoutError,
|
||||
) as ex:
|
||||
self.async_set_update_error(ex)
|
||||
await self._cleanup()
|
||||
self.async_set_update_error(ex)
|
||||
raise UpdateFailed() from ex
|
||||
except InvalidFolder as ex:
|
||||
_LOGGER.warning("Selected mailbox folder is invalid")
|
||||
self.async_set_update_error(ex)
|
||||
await self._cleanup()
|
||||
self.async_set_update_error(ex)
|
||||
raise ConfigEntryError("Selected mailbox folder is invalid.") from ex
|
||||
except InvalidAuth as ex:
|
||||
_LOGGER.warning("Username or password incorrect, starting reauthentication")
|
||||
self.async_set_update_error(ex)
|
||||
await self._cleanup()
|
||||
self.async_set_update_error(ex)
|
||||
raise ConfigEntryAuthFailed() from ex
|
||||
|
||||
|
||||
@@ -274,30 +279,30 @@ class ImapPushDataUpdateCoordinator(ImapDataUpdateCoordinator):
|
||||
try:
|
||||
number_of_messages = await self._async_fetch_number_of_messages()
|
||||
except InvalidAuth as ex:
|
||||
await self._cleanup()
|
||||
_LOGGER.warning(
|
||||
"Username or password incorrect, starting reauthentication"
|
||||
)
|
||||
self.config_entry.async_start_reauth(self.hass)
|
||||
self.async_set_update_error(ex)
|
||||
await self._cleanup()
|
||||
await asyncio.sleep(BACKOFF_TIME)
|
||||
except InvalidFolder as ex:
|
||||
_LOGGER.warning("Selected mailbox folder is invalid")
|
||||
await self._cleanup()
|
||||
self.config_entry.async_set_state(
|
||||
self.hass,
|
||||
ConfigEntryState.SETUP_ERROR,
|
||||
"Selected mailbox folder is invalid.",
|
||||
)
|
||||
self.async_set_update_error(ex)
|
||||
await self._cleanup()
|
||||
await asyncio.sleep(BACKOFF_TIME)
|
||||
except (
|
||||
UpdateFailed,
|
||||
AioImapException,
|
||||
asyncio.TimeoutError,
|
||||
) as ex:
|
||||
self.async_set_update_error(ex)
|
||||
await self._cleanup()
|
||||
self.async_set_update_error(ex)
|
||||
await asyncio.sleep(BACKOFF_TIME)
|
||||
continue
|
||||
else:
|
||||
@@ -310,12 +315,11 @@ class ImapPushDataUpdateCoordinator(ImapDataUpdateCoordinator):
|
||||
await idle
|
||||
|
||||
except (AioImapException, asyncio.TimeoutError):
|
||||
_LOGGER.warning(
|
||||
_LOGGER.debug(
|
||||
"Lost %s (will attempt to reconnect after %s s)",
|
||||
self.config_entry.data[CONF_SERVER],
|
||||
BACKOFF_TIME,
|
||||
)
|
||||
self.async_set_update_error(UpdateFailed("Lost connection"))
|
||||
await self._cleanup()
|
||||
await asyncio.sleep(BACKOFF_TIME)
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
"iot_class": "local_push",
|
||||
"loggers": ["pyinsteon", "pypubsub"],
|
||||
"requirements": [
|
||||
"pyinsteon==1.4.0",
|
||||
"pyinsteon==1.4.2",
|
||||
"insteon-frontend-home-assistant==0.3.4"
|
||||
],
|
||||
"usb": [
|
||||
|
||||
@@ -142,8 +142,11 @@ class ControllerDevice(ClimateEntity):
|
||||
|
||||
# If mode RAS, or mode master with CtrlZone 13 then can set master temperature,
|
||||
# otherwise the unit determines which zone to use as target. See interface manual p. 8
|
||||
# It appears some systems may have a different numbering system, so will trigger
|
||||
# this if the control zone is > total zones.
|
||||
if (
|
||||
controller.ras_mode == "master" and controller.zone_ctrl == 13
|
||||
controller.ras_mode == "master"
|
||||
and controller.zone_ctrl > controller.zones_total
|
||||
) or controller.ras_mode == "RAS":
|
||||
self._attr_supported_features |= ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
|
||||
|
||||
@@ -7,5 +7,5 @@
|
||||
"integration_type": "service",
|
||||
"iot_class": "local_polling",
|
||||
"loggers": ["aiopyarr"],
|
||||
"requirements": ["aiopyarr==22.11.0"]
|
||||
"requirements": ["aiopyarr==23.4.0"]
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"loggers": ["aiolifx", "aiolifx_effects", "bitstring"],
|
||||
"quality_scale": "platinum",
|
||||
"requirements": [
|
||||
"aiolifx==0.8.9",
|
||||
"aiolifx==0.8.10",
|
||||
"aiolifx_effects==0.3.2",
|
||||
"aiolifx_themes==0.4.5"
|
||||
]
|
||||
|
||||
@@ -12,5 +12,5 @@
|
||||
"integration_type": "hub",
|
||||
"iot_class": "cloud_push",
|
||||
"loggers": ["pylitterbot"],
|
||||
"requirements": ["pylitterbot==2023.1.2"]
|
||||
"requirements": ["pylitterbot==2023.4.0"]
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from aiolivisi.const import CAPABILITY_CONFIG
|
||||
|
||||
from homeassistant.components.climate import (
|
||||
ClimateEntity,
|
||||
ClimateEntityFeature,
|
||||
@@ -65,8 +67,6 @@ class LivisiClimate(LivisiEntity, ClimateEntity):
|
||||
_attr_hvac_mode = HVACMode.HEAT
|
||||
_attr_temperature_unit = UnitOfTemperature.CELSIUS
|
||||
_attr_supported_features = ClimateEntityFeature.TARGET_TEMPERATURE
|
||||
_attr_target_temperature_high = MAX_TEMPERATURE
|
||||
_attr_target_temperature_low = MIN_TEMPERATURE
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
@@ -83,6 +83,10 @@ class LivisiClimate(LivisiEntity, ClimateEntity):
|
||||
self._temperature_capability = self.capabilities["RoomTemperature"]
|
||||
self._humidity_capability = self.capabilities["RoomHumidity"]
|
||||
|
||||
config = device.get(CAPABILITY_CONFIG, {}).get("RoomSetpoint", {})
|
||||
self._attr_max_temp = config.get("maxTemperature", MAX_TEMPERATURE)
|
||||
self._attr_min_temp = config.get("minTemperature", MIN_TEMPERATURE)
|
||||
|
||||
async def async_set_temperature(self, **kwargs: Any) -> None:
|
||||
"""Set new target temperature."""
|
||||
response = await self.aio_livisi.async_vrcc_set_temperature(
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime
|
||||
from datetime import date, datetime, timedelta
|
||||
import logging
|
||||
from typing import Any
|
||||
|
||||
@@ -186,14 +186,23 @@ def _parse_event(event: dict[str, Any]) -> Event:
|
||||
|
||||
def _get_calendar_event(event: Event) -> CalendarEvent:
|
||||
"""Return a CalendarEvent from an API event."""
|
||||
start: datetime | date
|
||||
end: datetime | date
|
||||
if isinstance(event.start, datetime) and isinstance(event.end, datetime):
|
||||
start = dt_util.as_local(event.start)
|
||||
end = dt_util.as_local(event.end)
|
||||
if (end - start) <= timedelta(seconds=0):
|
||||
end = start + timedelta(minutes=30)
|
||||
else:
|
||||
start = event.start
|
||||
end = event.end
|
||||
if (end - start) < timedelta(days=0):
|
||||
end = start + timedelta(days=1)
|
||||
|
||||
return CalendarEvent(
|
||||
summary=event.summary,
|
||||
start=dt_util.as_local(event.start)
|
||||
if isinstance(event.start, datetime)
|
||||
else event.start,
|
||||
end=dt_util.as_local(event.end)
|
||||
if isinstance(event.end, datetime)
|
||||
else event.end,
|
||||
start=start,
|
||||
end=end,
|
||||
description=event.description,
|
||||
uid=event.uid,
|
||||
rrule=event.rrule.as_rrule_str() if event.rrule else None,
|
||||
|
||||
@@ -32,42 +32,42 @@ from .const import ATTR_SENSOR_ID, CONF_SENSOR_ID, DOMAIN
|
||||
SENSORS: tuple[SensorEntityDescription, ...] = (
|
||||
SensorEntityDescription(
|
||||
key="temperature",
|
||||
name="Temperature",
|
||||
translation_key="temperature",
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="humidity",
|
||||
name="Humidity",
|
||||
translation_key="humidity",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="pressure",
|
||||
name="Pressure",
|
||||
translation_key="pressure",
|
||||
native_unit_of_measurement=UnitOfPressure.PA,
|
||||
device_class=SensorDeviceClass.PRESSURE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="pressure_at_sealevel",
|
||||
name="Pressure at sealevel",
|
||||
translation_key="pressure_at_sealevel",
|
||||
native_unit_of_measurement=UnitOfPressure.PA,
|
||||
device_class=SensorDeviceClass.PRESSURE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="P1",
|
||||
name="PM10",
|
||||
translation_key="pm10",
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
device_class=SensorDeviceClass.PM10,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
),
|
||||
SensorEntityDescription(
|
||||
key="P2",
|
||||
name="PM2.5",
|
||||
translation_key="pm25",
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
device_class=SensorDeviceClass.PM25,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
|
||||
@@ -13,5 +13,25 @@
|
||||
"invalid_sensor": "Sensor not available or invalid",
|
||||
"cannot_connect": "[%key:common::config_flow::error::cannot_connect%]"
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"humidity": {
|
||||
"name": "[%key:component::sensor::entity_component::humidity::name%]"
|
||||
},
|
||||
"pressure": {
|
||||
"name": "[%key:component::sensor::entity_component::pressure::name%]"
|
||||
},
|
||||
"pressure_at_sealevel": { "name": "Pressure at sealevel" },
|
||||
"pm10": {
|
||||
"name": "[%key:component::sensor::entity_component::pm10::name%]"
|
||||
},
|
||||
"pm25": {
|
||||
"name": "[%key:component::sensor::entity_component::pm25::name%]"
|
||||
},
|
||||
"temperature": {
|
||||
"name": "[%key:component::sensor::entity_component::temperature::name%]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ from homeassistant.const import (
|
||||
STATE_ALARM_TRIGGERED,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.event import async_track_point_in_time
|
||||
@@ -285,56 +286,34 @@ class ManualAlarm(alarm.AlarmControlPanelEntity, RestoreEntity):
|
||||
|
||||
async def async_alarm_disarm(self, code: str | None = None) -> None:
|
||||
"""Send disarm command."""
|
||||
if not self._async_validate_code(code, STATE_ALARM_DISARMED):
|
||||
return
|
||||
|
||||
self._async_validate_code(code, STATE_ALARM_DISARMED)
|
||||
self._state = STATE_ALARM_DISARMED
|
||||
self._state_ts = dt_util.utcnow()
|
||||
self.async_write_ha_state()
|
||||
|
||||
async def async_alarm_arm_home(self, code: str | None = None) -> None:
|
||||
"""Send arm home command."""
|
||||
if self.code_arm_required and not self._async_validate_code(
|
||||
code, STATE_ALARM_ARMED_HOME
|
||||
):
|
||||
return
|
||||
|
||||
self._async_validate_code(code, STATE_ALARM_ARMED_HOME)
|
||||
self._async_update_state(STATE_ALARM_ARMED_HOME)
|
||||
|
||||
async def async_alarm_arm_away(self, code: str | None = None) -> None:
|
||||
"""Send arm away command."""
|
||||
if self.code_arm_required and not self._async_validate_code(
|
||||
code, STATE_ALARM_ARMED_AWAY
|
||||
):
|
||||
return
|
||||
|
||||
self._async_validate_code(code, STATE_ALARM_ARMED_AWAY)
|
||||
self._async_update_state(STATE_ALARM_ARMED_AWAY)
|
||||
|
||||
async def async_alarm_arm_night(self, code: str | None = None) -> None:
|
||||
"""Send arm night command."""
|
||||
if self.code_arm_required and not self._async_validate_code(
|
||||
code, STATE_ALARM_ARMED_NIGHT
|
||||
):
|
||||
return
|
||||
|
||||
self._async_validate_code(code, STATE_ALARM_ARMED_NIGHT)
|
||||
self._async_update_state(STATE_ALARM_ARMED_NIGHT)
|
||||
|
||||
async def async_alarm_arm_vacation(self, code: str | None = None) -> None:
|
||||
"""Send arm vacation command."""
|
||||
if self.code_arm_required and not self._async_validate_code(
|
||||
code, STATE_ALARM_ARMED_VACATION
|
||||
):
|
||||
return
|
||||
|
||||
self._async_validate_code(code, STATE_ALARM_ARMED_VACATION)
|
||||
self._async_update_state(STATE_ALARM_ARMED_VACATION)
|
||||
|
||||
async def async_alarm_arm_custom_bypass(self, code: str | None = None) -> None:
|
||||
"""Send arm custom bypass command."""
|
||||
if self.code_arm_required and not self._async_validate_code(
|
||||
code, STATE_ALARM_ARMED_CUSTOM_BYPASS
|
||||
):
|
||||
return
|
||||
|
||||
self._async_validate_code(code, STATE_ALARM_ARMED_CUSTOM_BYPASS)
|
||||
self._async_update_state(STATE_ALARM_ARMED_CUSTOM_BYPASS)
|
||||
|
||||
async def async_alarm_trigger(self, code: str | None = None) -> None:
|
||||
@@ -383,18 +362,22 @@ class ManualAlarm(alarm.AlarmControlPanelEntity, RestoreEntity):
|
||||
|
||||
def _async_validate_code(self, code, state):
|
||||
"""Validate given code."""
|
||||
if self._code is None:
|
||||
return True
|
||||
if (
|
||||
state != STATE_ALARM_DISARMED and not self.code_arm_required
|
||||
) or self._code is None:
|
||||
return
|
||||
|
||||
if isinstance(self._code, str):
|
||||
alarm_code = self._code
|
||||
else:
|
||||
alarm_code = self._code.async_render(
|
||||
parse_result=False, from_state=self._state, to_state=state
|
||||
)
|
||||
check = not alarm_code or code == alarm_code
|
||||
if not check:
|
||||
_LOGGER.warning("Invalid code given for %s", state)
|
||||
return check
|
||||
|
||||
if not alarm_code or code == alarm_code:
|
||||
return
|
||||
|
||||
raise HomeAssistantError("Invalid alarm code provided")
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self) -> dict[str, Any]:
|
||||
|
||||
@@ -29,6 +29,7 @@ from homeassistant.const import (
|
||||
STATE_ALARM_TRIGGERED,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, callback
|
||||
from homeassistant.exceptions import HomeAssistantError
|
||||
import homeassistant.helpers.config_validation as cv
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.event import (
|
||||
@@ -345,56 +346,34 @@ class ManualMQTTAlarm(alarm.AlarmControlPanelEntity):
|
||||
|
||||
async def async_alarm_disarm(self, code: str | None = None) -> None:
|
||||
"""Send disarm command."""
|
||||
if not self._async_validate_code(code, STATE_ALARM_DISARMED):
|
||||
return
|
||||
|
||||
self._async_validate_code(code, STATE_ALARM_DISARMED)
|
||||
self._state = STATE_ALARM_DISARMED
|
||||
self._state_ts = dt_util.utcnow()
|
||||
self.async_schedule_update_ha_state()
|
||||
|
||||
async def async_alarm_arm_home(self, code: str | None = None) -> None:
|
||||
"""Send arm home command."""
|
||||
if self.code_arm_required and not self._async_validate_code(
|
||||
code, STATE_ALARM_ARMED_HOME
|
||||
):
|
||||
return
|
||||
|
||||
self._async_validate_code(code, STATE_ALARM_ARMED_HOME)
|
||||
self._async_update_state(STATE_ALARM_ARMED_HOME)
|
||||
|
||||
async def async_alarm_arm_away(self, code: str | None = None) -> None:
|
||||
"""Send arm away command."""
|
||||
if self.code_arm_required and not self._async_validate_code(
|
||||
code, STATE_ALARM_ARMED_AWAY
|
||||
):
|
||||
return
|
||||
|
||||
self._async_validate_code(code, STATE_ALARM_ARMED_AWAY)
|
||||
self._async_update_state(STATE_ALARM_ARMED_AWAY)
|
||||
|
||||
async def async_alarm_arm_night(self, code: str | None = None) -> None:
|
||||
"""Send arm night command."""
|
||||
if self.code_arm_required and not self._async_validate_code(
|
||||
code, STATE_ALARM_ARMED_NIGHT
|
||||
):
|
||||
return
|
||||
|
||||
self._async_validate_code(code, STATE_ALARM_ARMED_NIGHT)
|
||||
self._async_update_state(STATE_ALARM_ARMED_NIGHT)
|
||||
|
||||
async def async_alarm_arm_vacation(self, code: str | None = None) -> None:
|
||||
"""Send arm vacation command."""
|
||||
if self.code_arm_required and not self._async_validate_code(
|
||||
code, STATE_ALARM_ARMED_VACATION
|
||||
):
|
||||
return
|
||||
|
||||
self._async_validate_code(code, STATE_ALARM_ARMED_VACATION)
|
||||
self._async_update_state(STATE_ALARM_ARMED_VACATION)
|
||||
|
||||
async def async_alarm_arm_custom_bypass(self, code: str | None = None) -> None:
|
||||
"""Send arm custom bypass command."""
|
||||
if self.code_arm_required and not self._async_validate_code(
|
||||
code, STATE_ALARM_ARMED_CUSTOM_BYPASS
|
||||
):
|
||||
return
|
||||
|
||||
self._async_validate_code(code, STATE_ALARM_ARMED_CUSTOM_BYPASS)
|
||||
self._async_update_state(STATE_ALARM_ARMED_CUSTOM_BYPASS)
|
||||
|
||||
async def async_alarm_trigger(self, code: str | None = None) -> None:
|
||||
@@ -436,18 +415,22 @@ class ManualMQTTAlarm(alarm.AlarmControlPanelEntity):
|
||||
|
||||
def _async_validate_code(self, code, state):
|
||||
"""Validate given code."""
|
||||
if self._code is None:
|
||||
return True
|
||||
if (
|
||||
state != STATE_ALARM_DISARMED and not self.code_arm_required
|
||||
) or self._code is None:
|
||||
return
|
||||
|
||||
if isinstance(self._code, str):
|
||||
alarm_code = self._code
|
||||
else:
|
||||
alarm_code = self._code.async_render(
|
||||
from_state=self._state, to_state=state, parse_result=False
|
||||
)
|
||||
check = not alarm_code or code == alarm_code
|
||||
if not check:
|
||||
_LOGGER.warning("Invalid code given for %s", state)
|
||||
return check
|
||||
|
||||
if not alarm_code or code == alarm_code:
|
||||
return
|
||||
|
||||
raise HomeAssistantError("Invalid alarm code provided")
|
||||
|
||||
@property
|
||||
def extra_state_attributes(self) -> dict[str, Any]:
|
||||
|
||||
@@ -48,7 +48,10 @@ class LocalSource(MediaSource):
|
||||
@callback
|
||||
def async_full_path(self, source_dir_id: str, location: str) -> Path:
|
||||
"""Return full path."""
|
||||
return Path(self.hass.config.media_dirs[source_dir_id], location)
|
||||
base_path = self.hass.config.media_dirs[source_dir_id]
|
||||
full_path = Path(base_path, location)
|
||||
full_path.relative_to(base_path)
|
||||
return full_path
|
||||
|
||||
@callback
|
||||
def async_parse_identifier(self, item: MediaSourceItem) -> tuple[str, str]:
|
||||
@@ -65,6 +68,9 @@ class LocalSource(MediaSource):
|
||||
except ValueError as err:
|
||||
raise Unresolvable("Invalid path.") from err
|
||||
|
||||
if Path(location).is_absolute():
|
||||
raise Unresolvable("Invalid path.")
|
||||
|
||||
return source_dir_id, location
|
||||
|
||||
async def async_resolve_media(self, item: MediaSourceItem) -> PlayMedia:
|
||||
|
||||
@@ -113,6 +113,7 @@ RELOADABLE_PLATFORMS = [
|
||||
Platform.CAMERA,
|
||||
Platform.CLIMATE,
|
||||
Platform.COVER,
|
||||
Platform.DEVICE_TRACKER,
|
||||
Platform.FAN,
|
||||
Platform.HUMIDIFIER,
|
||||
Platform.LIGHT,
|
||||
|
||||
@@ -41,15 +41,6 @@ _LOGGER = logging.getLogger(__name__)
|
||||
|
||||
async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
|
||||
"""Set up the MQTT state feed."""
|
||||
# Make sure MQTT is available and the entry is loaded
|
||||
if not hass.config_entries.async_entries(
|
||||
mqtt.DOMAIN
|
||||
) or not await hass.config_entries.async_wait_component(
|
||||
hass.config_entries.async_entries(mqtt.DOMAIN)[0]
|
||||
):
|
||||
_LOGGER.error("MQTT integration is not available")
|
||||
return False
|
||||
|
||||
conf: ConfigType = config[DOMAIN]
|
||||
publish_filter = convert_include_exclude_filter(conf)
|
||||
base_topic: str = conf[CONF_BASE_TOPIC]
|
||||
|
||||
@@ -23,7 +23,7 @@ _LOGGER = logging.getLogger(__name__)
|
||||
|
||||
RESTART_BUTTON: ButtonEntityDescription = ButtonEntityDescription(
|
||||
key="restart",
|
||||
name="Restart",
|
||||
translation_key="restart",
|
||||
device_class=ButtonDeviceClass.RESTART,
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
)
|
||||
|
||||
@@ -89,7 +89,7 @@ class NAMSensorEntityDescription(SensorEntityDescription, NAMSensorRequiredKeysM
|
||||
SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_BME280_HUMIDITY,
|
||||
name="BME280 humidity",
|
||||
translation_key="bme280_humidity",
|
||||
suggested_display_precision=1,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
@@ -98,7 +98,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_BME280_PRESSURE,
|
||||
name="BME280 pressure",
|
||||
translation_key="bme280_pressure",
|
||||
suggested_display_precision=0,
|
||||
native_unit_of_measurement=UnitOfPressure.HPA,
|
||||
device_class=SensorDeviceClass.PRESSURE,
|
||||
@@ -107,7 +107,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_BME280_TEMPERATURE,
|
||||
name="BME280 temperature",
|
||||
translation_key="bme280_temperature",
|
||||
suggested_display_precision=1,
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
@@ -116,7 +116,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_BMP180_PRESSURE,
|
||||
name="BMP180 pressure",
|
||||
translation_key="bmp180_pressure",
|
||||
suggested_display_precision=0,
|
||||
native_unit_of_measurement=UnitOfPressure.HPA,
|
||||
device_class=SensorDeviceClass.PRESSURE,
|
||||
@@ -125,7 +125,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_BMP180_TEMPERATURE,
|
||||
name="BMP180 temperature",
|
||||
translation_key="bmp180_temperature",
|
||||
suggested_display_precision=1,
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
@@ -134,7 +134,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_BMP280_PRESSURE,
|
||||
name="BMP280 pressure",
|
||||
translation_key="bmp280_pressure",
|
||||
suggested_display_precision=0,
|
||||
native_unit_of_measurement=UnitOfPressure.HPA,
|
||||
device_class=SensorDeviceClass.PRESSURE,
|
||||
@@ -143,7 +143,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_BMP280_TEMPERATURE,
|
||||
name="BMP280 temperature",
|
||||
translation_key="bmp280_temperature",
|
||||
suggested_display_precision=1,
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
@@ -152,7 +152,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_HECA_HUMIDITY,
|
||||
name="HECA humidity",
|
||||
translation_key="heca_humidity",
|
||||
suggested_display_precision=1,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
@@ -161,7 +161,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_HECA_TEMPERATURE,
|
||||
name="HECA temperature",
|
||||
translation_key="heca_temperature",
|
||||
suggested_display_precision=1,
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
@@ -170,7 +170,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_MHZ14A_CARBON_DIOXIDE,
|
||||
name="MH-Z14A carbon dioxide",
|
||||
translation_key="mhz14a_carbon_dioxide",
|
||||
suggested_display_precision=0,
|
||||
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
|
||||
device_class=SensorDeviceClass.CO2,
|
||||
@@ -179,22 +179,21 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_PMSX003_CAQI,
|
||||
name="PMSx003 CAQI",
|
||||
translation_key="pmsx003_caqi",
|
||||
icon="mdi:air-filter",
|
||||
value=lambda sensors: sensors.pms_caqi,
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_PMSX003_CAQI_LEVEL,
|
||||
name="PMSx003 CAQI level",
|
||||
translation_key="pmsx003_caqi_level",
|
||||
icon="mdi:air-filter",
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
options=["very_low", "low", "medium", "high", "very_high"],
|
||||
translation_key="caqi_level",
|
||||
value=lambda sensors: sensors.pms_caqi_level,
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_PMSX003_P0,
|
||||
name="PMSx003 particulate matter 1.0",
|
||||
translation_key="pmsx003_pm1",
|
||||
suggested_display_precision=0,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
device_class=SensorDeviceClass.PM1,
|
||||
@@ -203,7 +202,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_PMSX003_P1,
|
||||
name="PMSx003 particulate matter 10",
|
||||
translation_key="pmsx003_pm10",
|
||||
suggested_display_precision=0,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
device_class=SensorDeviceClass.PM10,
|
||||
@@ -212,7 +211,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_PMSX003_P2,
|
||||
name="PMSx003 particulate matter 2.5",
|
||||
translation_key="pmsx003_pm25",
|
||||
suggested_display_precision=0,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
device_class=SensorDeviceClass.PM25,
|
||||
@@ -221,22 +220,21 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_SDS011_CAQI,
|
||||
name="SDS011 CAQI",
|
||||
translation_key="sds011_caqi",
|
||||
icon="mdi:air-filter",
|
||||
value=lambda sensors: sensors.sds011_caqi,
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_SDS011_CAQI_LEVEL,
|
||||
name="SDS011 CAQI level",
|
||||
translation_key="sds011_caqi_level",
|
||||
icon="mdi:air-filter",
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
options=["very_low", "low", "medium", "high", "very_high"],
|
||||
translation_key="caqi_level",
|
||||
value=lambda sensors: sensors.sds011_caqi_level,
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_SDS011_P1,
|
||||
name="SDS011 particulate matter 10",
|
||||
translation_key="sds011_pm10",
|
||||
suggested_display_precision=0,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
device_class=SensorDeviceClass.PM10,
|
||||
@@ -245,7 +243,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_SDS011_P2,
|
||||
name="SDS011 particulate matter 2.5",
|
||||
translation_key="sds011_pm25",
|
||||
suggested_display_precision=0,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
device_class=SensorDeviceClass.PM25,
|
||||
@@ -254,7 +252,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_SHT3X_HUMIDITY,
|
||||
name="SHT3X humidity",
|
||||
translation_key="sht3x_humidity",
|
||||
suggested_display_precision=1,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
@@ -263,7 +261,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_SHT3X_TEMPERATURE,
|
||||
name="SHT3X temperature",
|
||||
translation_key="sht3x_temperature",
|
||||
suggested_display_precision=1,
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
@@ -272,22 +270,21 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_SPS30_CAQI,
|
||||
name="SPS30 CAQI",
|
||||
translation_key="sps30_caqi",
|
||||
icon="mdi:air-filter",
|
||||
value=lambda sensors: sensors.sps30_caqi,
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_SPS30_CAQI_LEVEL,
|
||||
name="SPS30 CAQI level",
|
||||
translation_key="sps30_caqi_level",
|
||||
icon="mdi:air-filter",
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
options=["very_low", "low", "medium", "high", "very_high"],
|
||||
translation_key="caqi_level",
|
||||
value=lambda sensors: sensors.sps30_caqi_level,
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_SPS30_P0,
|
||||
name="SPS30 particulate matter 1.0",
|
||||
translation_key="sps30_pm1",
|
||||
suggested_display_precision=0,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
device_class=SensorDeviceClass.PM1,
|
||||
@@ -296,7 +293,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_SPS30_P1,
|
||||
name="SPS30 particulate matter 10",
|
||||
translation_key="sps30_pm10",
|
||||
suggested_display_precision=0,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
device_class=SensorDeviceClass.PM10,
|
||||
@@ -305,7 +302,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_SPS30_P2,
|
||||
name="SPS30 particulate matter 2.5",
|
||||
translation_key="sps30_pm25",
|
||||
suggested_display_precision=0,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
device_class=SensorDeviceClass.PM25,
|
||||
@@ -314,7 +311,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_SPS30_P4,
|
||||
name="SPS30 particulate matter 4.0",
|
||||
translation_key="sps30_pm4",
|
||||
suggested_display_precision=0,
|
||||
native_unit_of_measurement=CONCENTRATION_MICROGRAMS_PER_CUBIC_METER,
|
||||
icon="mdi:molecule",
|
||||
@@ -323,7 +320,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_DHT22_HUMIDITY,
|
||||
name="DHT22 humidity",
|
||||
translation_key="dht22_humidity",
|
||||
suggested_display_precision=1,
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
device_class=SensorDeviceClass.HUMIDITY,
|
||||
@@ -332,7 +329,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_DHT22_TEMPERATURE,
|
||||
name="DHT22 temperature",
|
||||
translation_key="dht22_temperature",
|
||||
suggested_display_precision=1,
|
||||
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
|
||||
device_class=SensorDeviceClass.TEMPERATURE,
|
||||
@@ -341,7 +338,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_SIGNAL_STRENGTH,
|
||||
name="Signal strength",
|
||||
translation_key="signal_strength",
|
||||
suggested_display_precision=0,
|
||||
native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
|
||||
device_class=SensorDeviceClass.SIGNAL_STRENGTH,
|
||||
@@ -352,7 +349,7 @@ SENSORS: tuple[NAMSensorEntityDescription, ...] = (
|
||||
),
|
||||
NAMSensorEntityDescription(
|
||||
key=ATTR_UPTIME,
|
||||
name="Uptime",
|
||||
translation_key="last_restart",
|
||||
device_class=SensorDeviceClass.TIMESTAMP,
|
||||
entity_registry_enabled_default=False,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
|
||||
@@ -39,8 +39,47 @@
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"button": {
|
||||
"restart": {
|
||||
"name": "[%key:component::button::entity_component::restart::name%]"
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"caqi_level": {
|
||||
"bme280_humidity": {
|
||||
"name": "BME280 humidity"
|
||||
},
|
||||
"bme280_pressure": {
|
||||
"name": "BME280 pressure"
|
||||
},
|
||||
"bme280_temperature": {
|
||||
"name": "BME280 temperature"
|
||||
},
|
||||
"bmp180_pressure": {
|
||||
"name": "BMP180 pressure"
|
||||
},
|
||||
"bmp180_temperature": {
|
||||
"name": "BMP180 temperature"
|
||||
},
|
||||
"bmp280_pressure": {
|
||||
"name": "BMP280 pressure"
|
||||
},
|
||||
"bmp280_temperature": {
|
||||
"name": "BMP280 temperature"
|
||||
},
|
||||
"heca_humidity": {
|
||||
"name": "HECA humidity"
|
||||
},
|
||||
"heca_temperature": {
|
||||
"name": "HECA temperature"
|
||||
},
|
||||
"mhz14a_carbon_dioxide": {
|
||||
"name": "MH-Z14A carbon dioxide"
|
||||
},
|
||||
"pmsx003_caqi": {
|
||||
"name": "PMSx003 common air quality index"
|
||||
},
|
||||
"pmsx003_caqi_level": {
|
||||
"name": "PMSx003 common air quality index level",
|
||||
"state": {
|
||||
"very_low": "Very low",
|
||||
"low": "Low",
|
||||
@@ -48,6 +87,77 @@
|
||||
"high": "High",
|
||||
"very_high": "Very high"
|
||||
}
|
||||
},
|
||||
"pmsx003_pm1": {
|
||||
"name": "PMSx003 particulate matter 1 μm"
|
||||
},
|
||||
"pmsx003_pm10": {
|
||||
"name": "PMSx003 particulate matter 10 μm"
|
||||
},
|
||||
"pmsx003_pm25": {
|
||||
"name": "PMSx003 particulate matter 2.5 μm"
|
||||
},
|
||||
"sds011_caqi": {
|
||||
"name": "SDS011 common air quality index"
|
||||
},
|
||||
"sds011_caqi_level": {
|
||||
"name": "SDS011 common air quality index level",
|
||||
"state": {
|
||||
"very_low": "[%key:component::nam::entity::sensor::pmsx003_caqi_level::state::very_low%]",
|
||||
"low": "[%key:component::nam::entity::sensor::pmsx003_caqi_level::state::low%]",
|
||||
"medium": "[%key:component::nam::entity::sensor::pmsx003_caqi_level::state::medium%]",
|
||||
"high": "[%key:component::nam::entity::sensor::pmsx003_caqi_level::state::high%]",
|
||||
"very_high": "[%key:component::nam::entity::sensor::pmsx003_caqi_level::state::very_high%]"
|
||||
}
|
||||
},
|
||||
"sds011_pm10": {
|
||||
"name": "SDS011 particulate matter 10 μm"
|
||||
},
|
||||
"sds011_pm25": {
|
||||
"name": "SDS011 particulate matter 2.5 μm"
|
||||
},
|
||||
"sht3x_humidity": {
|
||||
"name": "SHT3X humidity"
|
||||
},
|
||||
"sht3x_temperature": {
|
||||
"name": "SHT3X temperature"
|
||||
},
|
||||
"sps30_caqi": {
|
||||
"name": "SPS30 common air quality index"
|
||||
},
|
||||
"sps30_caqi_level": {
|
||||
"name": "SPS30 common air quality index level",
|
||||
"state": {
|
||||
"very_low": "[%key:component::nam::entity::sensor::pmsx003_caqi_level::state::very_low%]",
|
||||
"low": "[%key:component::nam::entity::sensor::pmsx003_caqi_level::state::low%]",
|
||||
"medium": "[%key:component::nam::entity::sensor::pmsx003_caqi_level::state::medium%]",
|
||||
"high": "[%key:component::nam::entity::sensor::pmsx003_caqi_level::state::high%]",
|
||||
"very_high": "[%key:component::nam::entity::sensor::pmsx003_caqi_level::state::very_high%]"
|
||||
}
|
||||
},
|
||||
"sps30_pm1": {
|
||||
"name": "SPS30 particulate matter 1 μm"
|
||||
},
|
||||
"sps30_pm10": {
|
||||
"name": "SPS30 particulate matter 10 μm"
|
||||
},
|
||||
"sps30_pm25": {
|
||||
"name": "SPS30 particulate matter 2.5 μm"
|
||||
},
|
||||
"sps30_pm4": {
|
||||
"name": "SPS30 Particulate matter 4 μm"
|
||||
},
|
||||
"dht22_humidity": {
|
||||
"name": "DHT22 humidity"
|
||||
},
|
||||
"dht22_temperature": {
|
||||
"name": "DHT22 temperature"
|
||||
},
|
||||
"signal_strength": {
|
||||
"name": "[%key:component::sensor::entity_component::signal_strength::name%]"
|
||||
},
|
||||
"last_restart": {
|
||||
"name": "Last restart"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ class TemperatureSensor(SensorBase):
|
||||
|
||||
_attr_device_class = SensorDeviceClass.TEMPERATURE
|
||||
_attr_native_unit_of_measurement = UnitOfTemperature.CELSIUS
|
||||
_attr_name = "Temperature"
|
||||
_attr_translation_key = "temperature"
|
||||
|
||||
@property
|
||||
def native_value(self) -> float:
|
||||
@@ -96,7 +96,7 @@ class HumiditySensor(SensorBase):
|
||||
|
||||
_attr_device_class = SensorDeviceClass.HUMIDITY
|
||||
_attr_native_unit_of_measurement = PERCENTAGE
|
||||
_attr_name = "Humidity"
|
||||
_attr_translation_key = "humidity"
|
||||
|
||||
@property
|
||||
def native_value(self) -> int:
|
||||
|
||||
@@ -98,5 +98,15 @@
|
||||
"title": "Nest Authentication Credentials must be updated",
|
||||
"description": "To improve security and reduce phishing risk Google has deprecated the authentication method used by Home Assistant.\n\n**This requires action by you to resolve** ([more info]({more_info_url}))\n\n1. Visit the integrations page\n1. Click Reconfigure on the Nest integration.\n1. Home Assistant will walk you through the steps to upgrade to Web Authentication.\n\nSee the Nest [integration instructions]({documentation_url}) for troubleshooting information."
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"sensor": {
|
||||
"temperature": {
|
||||
"name": "[%key:component::sensor::entity_component::temperature::name%]"
|
||||
},
|
||||
"humidity": {
|
||||
"name": "[%key:component::sensor::entity_component::humidity::name%]"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,14 +43,14 @@ SENSORS = (
|
||||
NextDnsBinarySensorEntityDescription[ConnectionStatus](
|
||||
key="this_device_nextdns_connection_status",
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
name="This device NextDNS connection status",
|
||||
translation_key="device_connection_status",
|
||||
device_class=BinarySensorDeviceClass.CONNECTIVITY,
|
||||
state=lambda data, _: data.connected,
|
||||
),
|
||||
NextDnsBinarySensorEntityDescription[ConnectionStatus](
|
||||
key="this_device_profile_connection_status",
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
name="This device profile connection status",
|
||||
translation_key="device_profile_connection_status",
|
||||
device_class=BinarySensorDeviceClass.CONNECTIVITY,
|
||||
state=lambda data, profile_id: profile_id == data.profile_id,
|
||||
),
|
||||
|
||||
@@ -15,7 +15,7 @@ PARALLEL_UPDATES = 1
|
||||
|
||||
CLEAR_LOGS_BUTTON = ButtonEntityDescription(
|
||||
key="clear_logs",
|
||||
name="Clear logs",
|
||||
translation_key="clear_logs",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
)
|
||||
|
||||
|
||||
@@ -60,7 +60,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
coordinator_type=ATTR_STATUS,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
icon="mdi:dns",
|
||||
name="DNS queries",
|
||||
translation_key="all_queries",
|
||||
native_unit_of_measurement="queries",
|
||||
state_class=SensorStateClass.TOTAL,
|
||||
value=lambda data: data.all_queries,
|
||||
@@ -70,7 +70,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
coordinator_type=ATTR_STATUS,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
icon="mdi:dns",
|
||||
name="DNS queries blocked",
|
||||
translation_key="blocked_queries",
|
||||
native_unit_of_measurement="queries",
|
||||
state_class=SensorStateClass.TOTAL,
|
||||
value=lambda data: data.blocked_queries,
|
||||
@@ -80,7 +80,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
coordinator_type=ATTR_STATUS,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
icon="mdi:dns",
|
||||
name="DNS queries relayed",
|
||||
translation_key="relayed_queries",
|
||||
native_unit_of_measurement="queries",
|
||||
state_class=SensorStateClass.TOTAL,
|
||||
value=lambda data: data.relayed_queries,
|
||||
@@ -90,7 +90,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
coordinator_type=ATTR_STATUS,
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
icon="mdi:dns",
|
||||
name="DNS queries blocked ratio",
|
||||
translation_key="blocked_queries_ratio",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value=lambda data: data.blocked_queries_ratio,
|
||||
@@ -101,7 +101,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:dns",
|
||||
name="DNS-over-HTTPS queries",
|
||||
translation_key="doh_queries",
|
||||
native_unit_of_measurement="queries",
|
||||
state_class=SensorStateClass.TOTAL,
|
||||
value=lambda data: data.doh_queries,
|
||||
@@ -112,7 +112,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:dns",
|
||||
name="DNS-over-HTTP/3 queries",
|
||||
translation_key="doh3_queries",
|
||||
native_unit_of_measurement="queries",
|
||||
state_class=SensorStateClass.TOTAL,
|
||||
value=lambda data: data.doh3_queries,
|
||||
@@ -123,7 +123,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:dns",
|
||||
name="DNS-over-TLS queries",
|
||||
translation_key="dot_queries",
|
||||
native_unit_of_measurement="queries",
|
||||
state_class=SensorStateClass.TOTAL,
|
||||
value=lambda data: data.dot_queries,
|
||||
@@ -134,7 +134,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:dns",
|
||||
name="DNS-over-QUIC queries",
|
||||
translation_key="doq_queries",
|
||||
native_unit_of_measurement="queries",
|
||||
state_class=SensorStateClass.TOTAL,
|
||||
value=lambda data: data.doq_queries,
|
||||
@@ -145,7 +145,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:dns",
|
||||
name="TCP queries",
|
||||
translation_key="tcp_queries",
|
||||
native_unit_of_measurement="queries",
|
||||
state_class=SensorStateClass.TOTAL,
|
||||
value=lambda data: data.tcp_queries,
|
||||
@@ -156,7 +156,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:dns",
|
||||
name="UDP queries",
|
||||
translation_key="udp_queries",
|
||||
native_unit_of_measurement="queries",
|
||||
state_class=SensorStateClass.TOTAL,
|
||||
value=lambda data: data.udp_queries,
|
||||
@@ -167,7 +167,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:dns",
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
name="DNS-over-HTTPS queries ratio",
|
||||
translation_key="doh_queries_ratio",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value=lambda data: data.doh_queries_ratio,
|
||||
@@ -178,7 +178,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:dns",
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
name="DNS-over-HTTP/3 queries ratio",
|
||||
translation_key="doh3_queries_ratio",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value=lambda data: data.doh3_queries_ratio,
|
||||
@@ -189,7 +189,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:dns",
|
||||
name="DNS-over-TLS queries ratio",
|
||||
translation_key="dot_queries_ratio",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value=lambda data: data.dot_queries_ratio,
|
||||
@@ -200,7 +200,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:dns",
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
name="DNS-over-QUIC queries ratio",
|
||||
translation_key="doq_queries_ratio",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value=lambda data: data.doq_queries_ratio,
|
||||
@@ -211,7 +211,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:dns",
|
||||
name="TCP queries ratio",
|
||||
translation_key="tcp_queries_ratio",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value=lambda data: data.tcp_queries_ratio,
|
||||
@@ -222,7 +222,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:dns",
|
||||
name="UDP queries ratio",
|
||||
translation_key="udp_queries_ratio",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value=lambda data: data.udp_queries_ratio,
|
||||
@@ -233,7 +233,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:lock",
|
||||
name="Encrypted queries",
|
||||
translation_key="encrypted_queries",
|
||||
native_unit_of_measurement="queries",
|
||||
state_class=SensorStateClass.TOTAL,
|
||||
value=lambda data: data.encrypted_queries,
|
||||
@@ -244,7 +244,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:lock-open",
|
||||
name="Unencrypted queries",
|
||||
translation_key="unencrypted_queries",
|
||||
native_unit_of_measurement="queries",
|
||||
state_class=SensorStateClass.TOTAL,
|
||||
value=lambda data: data.unencrypted_queries,
|
||||
@@ -255,7 +255,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:lock",
|
||||
name="Encrypted queries ratio",
|
||||
translation_key="encrypted_queries_ratio",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value=lambda data: data.encrypted_queries_ratio,
|
||||
@@ -266,7 +266,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:ip",
|
||||
name="IPv4 queries",
|
||||
translation_key="ipv4_queries",
|
||||
native_unit_of_measurement="queries",
|
||||
state_class=SensorStateClass.TOTAL,
|
||||
value=lambda data: data.ipv4_queries,
|
||||
@@ -277,7 +277,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:ip",
|
||||
name="IPv6 queries",
|
||||
translation_key="ipv6_queries",
|
||||
native_unit_of_measurement="queries",
|
||||
state_class=SensorStateClass.TOTAL,
|
||||
value=lambda data: data.ipv6_queries,
|
||||
@@ -288,7 +288,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:ip",
|
||||
name="IPv6 queries ratio",
|
||||
translation_key="ipv6_queries_ratio",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value=lambda data: data.ipv6_queries_ratio,
|
||||
@@ -299,7 +299,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:lock-check",
|
||||
name="DNSSEC validated queries",
|
||||
translation_key="validated_queries",
|
||||
native_unit_of_measurement="queries",
|
||||
state_class=SensorStateClass.TOTAL,
|
||||
value=lambda data: data.validated_queries,
|
||||
@@ -310,7 +310,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:lock-alert",
|
||||
name="DNSSEC not validated queries",
|
||||
translation_key="not_validated_queries",
|
||||
native_unit_of_measurement="queries",
|
||||
state_class=SensorStateClass.TOTAL,
|
||||
value=lambda data: data.not_validated_queries,
|
||||
@@ -321,7 +321,7 @@ SENSORS: tuple[NextDnsSensorEntityDescription, ...] = (
|
||||
entity_category=EntityCategory.DIAGNOSTIC,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:lock-check",
|
||||
name="DNSSEC validated queries ratio",
|
||||
translation_key="validated_queries_ratio",
|
||||
native_unit_of_measurement=PERCENTAGE,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
value=lambda data: data.validated_queries_ratio,
|
||||
|
||||
@@ -25,5 +25,294 @@
|
||||
"info": {
|
||||
"can_reach_server": "Reach server"
|
||||
}
|
||||
},
|
||||
"entity": {
|
||||
"binary_sensor": {
|
||||
"device_connection_status": {
|
||||
"name": "Device connection status"
|
||||
},
|
||||
"device_profile_connection_status": {
|
||||
"name": "Device profile connection status"
|
||||
}
|
||||
},
|
||||
"button": {
|
||||
"clear_logs": {
|
||||
"name": "Clear logs"
|
||||
}
|
||||
},
|
||||
"sensor": {
|
||||
"all_queries": {
|
||||
"name": "DNS queries"
|
||||
},
|
||||
"blocked_queries": {
|
||||
"name": "DNS queries blocked"
|
||||
},
|
||||
"blocked_queries_ratio": {
|
||||
"name": "DNS queries blocked ratio"
|
||||
},
|
||||
"doh3_queries": {
|
||||
"name": "DNS-over-HTTP/3 queries"
|
||||
},
|
||||
"doh3_queries_ratio": {
|
||||
"name": "DNS-over-HTTP/3 queries ratio"
|
||||
},
|
||||
"doh_queries": {
|
||||
"name": "DNS-over-HTTPS queries"
|
||||
},
|
||||
"doh_queries_ratio": {
|
||||
"name": "DNS-over-HTTPS queries ratio"
|
||||
},
|
||||
"doq_queries": {
|
||||
"name": "DNS-over-QUIC queries"
|
||||
},
|
||||
"doq_queries_ratio": {
|
||||
"name": "DNS-over-QUIC queries ratio"
|
||||
},
|
||||
"dot_queries": {
|
||||
"name": "DNS-over-TLS queries"
|
||||
},
|
||||
"dot_queries_ratio": {
|
||||
"name": "DNS-over-TLS queries ratio"
|
||||
},
|
||||
"encrypted_queries": {
|
||||
"name": "Encrypted queries"
|
||||
},
|
||||
"encrypted_queries_ratio": {
|
||||
"name": "Encrypted queries ratio"
|
||||
},
|
||||
"ipv4_queries": {
|
||||
"name": "IPv4 queries"
|
||||
},
|
||||
"ipv6_queries": {
|
||||
"name": "IPv6 queries"
|
||||
},
|
||||
"ipv6_queries_ratio": {
|
||||
"name": "IPv6 queries ratio"
|
||||
},
|
||||
"not_validated_queries": {
|
||||
"name": "DNSSEC not validated queries"
|
||||
},
|
||||
"relayed_queries": {
|
||||
"name": "DNS queries relayed"
|
||||
},
|
||||
"tcp_queries": {
|
||||
"name": "TCP queries"
|
||||
},
|
||||
"tcp_queries_ratio": {
|
||||
"name": "TCP queries ratio"
|
||||
},
|
||||
"udp_queries": {
|
||||
"name": "UDP queries"
|
||||
},
|
||||
"udp_queries_ratio": {
|
||||
"name": "UDP queries ratio"
|
||||
},
|
||||
"unencrypted_queries": {
|
||||
"name": "Unencrypted queries"
|
||||
},
|
||||
"validated_queries": {
|
||||
"name": "DNSSEC validated queries"
|
||||
},
|
||||
"validated_queries_ratio": {
|
||||
"name": "DNSSEC validated queries ratio"
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
"ai_threat_detection": {
|
||||
"name": "AI-Driven threat detection"
|
||||
},
|
||||
"allow_affiliate": {
|
||||
"name": "Allow affiliate & tracking links"
|
||||
},
|
||||
"anonymized_ecs": {
|
||||
"name": "Anonymized EDNS client subnet"
|
||||
},
|
||||
"block_9gag": {
|
||||
"name": "Block 9GAG"
|
||||
},
|
||||
"block_amazon": {
|
||||
"name": "Block Amazon"
|
||||
},
|
||||
"block_blizzard": {
|
||||
"name": "Block Blizzard"
|
||||
},
|
||||
"block_bypass_methods": {
|
||||
"name": "Block bypass methods"
|
||||
},
|
||||
"block_csam": {
|
||||
"name": "Block child sexual abuse material"
|
||||
},
|
||||
"block_dailymotion": {
|
||||
"name": "Block Dailymotion"
|
||||
},
|
||||
"block_dating": {
|
||||
"name": "Block dating"
|
||||
},
|
||||
"block_ddns": {
|
||||
"name": "Block dynamic DNS hostnames"
|
||||
},
|
||||
"block_discord": {
|
||||
"name": "Block Discord"
|
||||
},
|
||||
"block_disguised_trackers": {
|
||||
"name": "Block disguised third-party trackers"
|
||||
},
|
||||
"block_disneyplus": {
|
||||
"name": "Block Disney Plus"
|
||||
},
|
||||
"block_ebay": {
|
||||
"name": "Block eBay"
|
||||
},
|
||||
"block_facebook": {
|
||||
"name": "Block Facebook"
|
||||
},
|
||||
"block_fortnite": {
|
||||
"name": "Block Fortnite"
|
||||
},
|
||||
"block_gambling": {
|
||||
"name": "Block gambling"
|
||||
},
|
||||
"block_hulu": {
|
||||
"name": "Block Hulu"
|
||||
},
|
||||
"block_imgur": {
|
||||
"name": "Block Imgur"
|
||||
},
|
||||
"block_instagram": {
|
||||
"name": "Block Instagram"
|
||||
},
|
||||
"block_leagueoflegends": {
|
||||
"name": "Block League of Legends"
|
||||
},
|
||||
"block_messenger": {
|
||||
"name": "Block Messenger"
|
||||
},
|
||||
"block_minecraft": {
|
||||
"name": "Block Minecraft"
|
||||
},
|
||||
"block_netflix": {
|
||||
"name": "Block Netflix"
|
||||
},
|
||||
"block_nrd": {
|
||||
"name": "Block newly registered domains"
|
||||
},
|
||||
"block_page": {
|
||||
"name": "Block page"
|
||||
},
|
||||
"block_parked_domains": {
|
||||
"name": "Block parked domains"
|
||||
},
|
||||
"block_pinterest": {
|
||||
"name": "Block Pinterest"
|
||||
},
|
||||
"block_piracy": {
|
||||
"name": "Block piracy"
|
||||
},
|
||||
"block_porn": {
|
||||
"name": "Block porn"
|
||||
},
|
||||
"block_primevideo": {
|
||||
"name": "Block Prime Video"
|
||||
},
|
||||
"block_reddit": {
|
||||
"name": "Block Reddit"
|
||||
},
|
||||
"block_roblox": {
|
||||
"name": "Block Roblox"
|
||||
},
|
||||
"block_signal": {
|
||||
"name": "Block Signal"
|
||||
},
|
||||
"block_skype": {
|
||||
"name": "Block Skype"
|
||||
},
|
||||
"block_snapchat": {
|
||||
"name": "Block Snapchat"
|
||||
},
|
||||
"block_social_networks": {
|
||||
"name": "Block social networks"
|
||||
},
|
||||
"block_spotify": {
|
||||
"name": "Block Spotify"
|
||||
},
|
||||
"block_steam": {
|
||||
"name": "Block Steam"
|
||||
},
|
||||
"block_telegram": {
|
||||
"name": "Block Telegram"
|
||||
},
|
||||
"block_tiktok": {
|
||||
"name": "Block TikTok"
|
||||
},
|
||||
"block_tinder": {
|
||||
"name": "Block Tinder"
|
||||
},
|
||||
"block_tumblr": {
|
||||
"name": "Block Tumblr"
|
||||
},
|
||||
"block_twitch": {
|
||||
"name": "Block Twitch"
|
||||
},
|
||||
"block_twitter": {
|
||||
"name": "Block Twitter"
|
||||
},
|
||||
"block_vimeo": {
|
||||
"name": "Block Vimeo"
|
||||
},
|
||||
"block_vk": {
|
||||
"name": "Block VK"
|
||||
},
|
||||
"block_whatsapp": {
|
||||
"name": "Block WhatsApp"
|
||||
},
|
||||
"block_xboxlive": {
|
||||
"name": "Block Xbox Live"
|
||||
},
|
||||
"block_youtube": {
|
||||
"name": "Block YouTube"
|
||||
},
|
||||
"block_zoom": {
|
||||
"name": "Block Zoom"
|
||||
},
|
||||
"cache_boost": {
|
||||
"name": "Cache boost"
|
||||
},
|
||||
"cname_flattening": {
|
||||
"name": "CNAME flattening"
|
||||
},
|
||||
"cryptojacking_protection": {
|
||||
"name": "Cryptojacking protection"
|
||||
},
|
||||
"dga_protection": {
|
||||
"name": "Domain generation algorithms protection"
|
||||
},
|
||||
"dns_rebinding_protection": {
|
||||
"name": "DNS rebinding protection"
|
||||
},
|
||||
"google_safe_browsing": {
|
||||
"name": "Google safe browsing"
|
||||
},
|
||||
"idn_homograph_attacks_protection": {
|
||||
"name": "IDN homograph attacks protection"
|
||||
},
|
||||
"logs": {
|
||||
"name": "Logs"
|
||||
},
|
||||
"safesearch": {
|
||||
"name": "Force SafeSearch"
|
||||
},
|
||||
"threat_intelligence_feeds": {
|
||||
"name": "Threat intelligence feeds"
|
||||
},
|
||||
"typosquatting_protection": {
|
||||
"name": "Typosquatting protection"
|
||||
},
|
||||
"web3": {
|
||||
"name": "Web3"
|
||||
},
|
||||
"youtube_restricted_mode": {
|
||||
"name": "Force YouTube restricted mode"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,156 +41,156 @@ class NextDnsSwitchEntityDescription(
|
||||
SWITCHES = (
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_page",
|
||||
name="Block page",
|
||||
translation_key="block_page",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
icon="mdi:web-cancel",
|
||||
state=lambda data: data.block_page,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="cache_boost",
|
||||
name="Cache boost",
|
||||
translation_key="cache_boost",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
icon="mdi:memory",
|
||||
state=lambda data: data.cache_boost,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="cname_flattening",
|
||||
name="CNAME flattening",
|
||||
translation_key="cname_flattening",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
icon="mdi:tournament",
|
||||
state=lambda data: data.cname_flattening,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="anonymized_ecs",
|
||||
name="Anonymized EDNS client subnet",
|
||||
translation_key="anonymized_ecs",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
icon="mdi:incognito",
|
||||
state=lambda data: data.anonymized_ecs,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="logs",
|
||||
name="Logs",
|
||||
translation_key="logs",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
icon="mdi:file-document-outline",
|
||||
state=lambda data: data.logs,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="web3",
|
||||
name="Web3",
|
||||
translation_key="web3",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
icon="mdi:web",
|
||||
state=lambda data: data.web3,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="allow_affiliate",
|
||||
name="Allow affiliate & tracking links",
|
||||
translation_key="allow_affiliate",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
state=lambda data: data.allow_affiliate,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_disguised_trackers",
|
||||
name="Block disguised third-party trackers",
|
||||
translation_key="block_disguised_trackers",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
state=lambda data: data.block_disguised_trackers,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="ai_threat_detection",
|
||||
name="AI-Driven threat detection",
|
||||
translation_key="ai_threat_detection",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
state=lambda data: data.ai_threat_detection,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_csam",
|
||||
name="Block child sexual abuse material",
|
||||
translation_key="block_csam",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
state=lambda data: data.block_csam,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_ddns",
|
||||
name="Block dynamic DNS hostnames",
|
||||
translation_key="block_ddns",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
state=lambda data: data.block_ddns,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_nrd",
|
||||
name="Block newly registered domains",
|
||||
translation_key="block_nrd",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
state=lambda data: data.block_nrd,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_parked_domains",
|
||||
name="Block parked domains",
|
||||
translation_key="block_parked_domains",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
state=lambda data: data.block_parked_domains,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="cryptojacking_protection",
|
||||
name="Cryptojacking protection",
|
||||
translation_key="cryptojacking_protection",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
state=lambda data: data.cryptojacking_protection,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="dga_protection",
|
||||
name="Domain generation algorithms protection",
|
||||
translation_key="dga_protection",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
state=lambda data: data.dga_protection,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="dns_rebinding_protection",
|
||||
name="DNS rebinding protection",
|
||||
translation_key="dns_rebinding_protection",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
icon="mdi:dns",
|
||||
state=lambda data: data.dns_rebinding_protection,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="google_safe_browsing",
|
||||
name="Google safe browsing",
|
||||
translation_key="google_safe_browsing",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
icon="mdi:google",
|
||||
state=lambda data: data.google_safe_browsing,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="idn_homograph_attacks_protection",
|
||||
name="IDN homograph attacks protection",
|
||||
translation_key="idn_homograph_attacks_protection",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
state=lambda data: data.idn_homograph_attacks_protection,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="threat_intelligence_feeds",
|
||||
name="Threat intelligence feeds",
|
||||
translation_key="threat_intelligence_feeds",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
state=lambda data: data.threat_intelligence_feeds,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="typosquatting_protection",
|
||||
name="Typosquatting protection",
|
||||
translation_key="typosquatting_protection",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
icon="mdi:keyboard-outline",
|
||||
state=lambda data: data.typosquatting_protection,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_bypass_methods",
|
||||
name="Block bypass methods",
|
||||
translation_key="block_bypass_methods",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
state=lambda data: data.block_bypass_methods,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="safesearch",
|
||||
name="Force SafeSearch",
|
||||
translation_key="safesearch",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
icon="mdi:search-web",
|
||||
state=lambda data: data.safesearch,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="youtube_restricted_mode",
|
||||
name="Force YouTube restricted mode",
|
||||
translation_key="youtube_restricted_mode",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
icon="mdi:youtube",
|
||||
state=lambda data: data.youtube_restricted_mode,
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_9gag",
|
||||
name="Block 9GAG",
|
||||
translation_key="block_9gag",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:file-gif-box",
|
||||
@@ -198,7 +198,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_amazon",
|
||||
name="Block Amazon",
|
||||
translation_key="block_amazon",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:cart-outline",
|
||||
@@ -206,7 +206,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_blizzard",
|
||||
name="Block Blizzard",
|
||||
translation_key="block_blizzard",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:sword-cross",
|
||||
@@ -214,7 +214,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_dailymotion",
|
||||
name="Block Dailymotion",
|
||||
translation_key="block_dailymotion",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:movie-search-outline",
|
||||
@@ -222,7 +222,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_discord",
|
||||
name="Block Discord",
|
||||
translation_key="block_discord",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:message-text",
|
||||
@@ -230,7 +230,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_disneyplus",
|
||||
name="Block Disney Plus",
|
||||
translation_key="block_disneyplus",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:movie-search-outline",
|
||||
@@ -238,7 +238,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_ebay",
|
||||
name="Block eBay",
|
||||
translation_key="block_ebay",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:basket-outline",
|
||||
@@ -246,7 +246,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_facebook",
|
||||
name="Block Facebook",
|
||||
translation_key="block_facebook",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:facebook",
|
||||
@@ -254,7 +254,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_fortnite",
|
||||
name="Block Fortnite",
|
||||
translation_key="block_fortnite",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:tank",
|
||||
@@ -270,7 +270,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_imgur",
|
||||
name="Block Imgur",
|
||||
translation_key="block_imgur",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:camera-image",
|
||||
@@ -278,7 +278,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_instagram",
|
||||
name="Block Instagram",
|
||||
translation_key="block_instagram",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:instagram",
|
||||
@@ -286,7 +286,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_leagueoflegends",
|
||||
name="Block League of Legends",
|
||||
translation_key="block_leagueoflegends",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:sword",
|
||||
@@ -294,7 +294,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_messenger",
|
||||
name="Block Messenger",
|
||||
translation_key="block_messenger",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:message-text",
|
||||
@@ -302,7 +302,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_minecraft",
|
||||
name="Block Minecraft",
|
||||
translation_key="block_minecraft",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:minecraft",
|
||||
@@ -310,7 +310,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_netflix",
|
||||
name="Block Netflix",
|
||||
translation_key="block_netflix",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:netflix",
|
||||
@@ -318,7 +318,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_pinterest",
|
||||
name="Block Pinterest",
|
||||
translation_key="block_pinterest",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:pinterest",
|
||||
@@ -326,7 +326,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_primevideo",
|
||||
name="Block Prime Video",
|
||||
translation_key="block_primevideo",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:filmstrip",
|
||||
@@ -334,7 +334,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_reddit",
|
||||
name="Block Reddit",
|
||||
translation_key="block_reddit",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:reddit",
|
||||
@@ -342,7 +342,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_roblox",
|
||||
name="Block Roblox",
|
||||
translation_key="block_roblox",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:robot",
|
||||
@@ -350,7 +350,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_signal",
|
||||
name="Block Signal",
|
||||
translation_key="block_signal",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:chat-outline",
|
||||
@@ -358,7 +358,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_skype",
|
||||
name="Block Skype",
|
||||
translation_key="block_skype",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:skype",
|
||||
@@ -366,7 +366,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_snapchat",
|
||||
name="Block Snapchat",
|
||||
translation_key="block_snapchat",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:snapchat",
|
||||
@@ -374,7 +374,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_spotify",
|
||||
name="Block Spotify",
|
||||
translation_key="block_spotify",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:spotify",
|
||||
@@ -382,7 +382,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_steam",
|
||||
name="Block Steam",
|
||||
translation_key="block_steam",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:steam",
|
||||
@@ -390,7 +390,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_telegram",
|
||||
name="Block Telegram",
|
||||
translation_key="block_telegram",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:send-outline",
|
||||
@@ -398,7 +398,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_tiktok",
|
||||
name="Block TikTok",
|
||||
translation_key="block_tiktok",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:music-note",
|
||||
@@ -406,7 +406,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_tinder",
|
||||
name="Block Tinder",
|
||||
translation_key="block_tinder",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:fire",
|
||||
@@ -414,7 +414,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_tumblr",
|
||||
name="Block Tumblr",
|
||||
translation_key="block_tumblr",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:image-outline",
|
||||
@@ -422,7 +422,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_twitch",
|
||||
name="Block Twitch",
|
||||
translation_key="block_twitch",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:twitch",
|
||||
@@ -430,7 +430,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_twitter",
|
||||
name="Block Twitter",
|
||||
translation_key="block_twitter",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:twitter",
|
||||
@@ -438,7 +438,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_vimeo",
|
||||
name="Block Vimeo",
|
||||
translation_key="block_vimeo",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:vimeo",
|
||||
@@ -446,7 +446,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_vk",
|
||||
name="Block VK",
|
||||
translation_key="block_vk",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:power-socket-eu",
|
||||
@@ -454,7 +454,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_whatsapp",
|
||||
name="Block WhatsApp",
|
||||
translation_key="block_whatsapp",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:whatsapp",
|
||||
@@ -462,7 +462,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_xboxlive",
|
||||
name="Block Xbox Live",
|
||||
translation_key="block_xboxlive",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:microsoft-xbox",
|
||||
@@ -470,7 +470,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_youtube",
|
||||
name="Block YouTube",
|
||||
translation_key="block_youtube",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:youtube",
|
||||
@@ -478,7 +478,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_zoom",
|
||||
name="Block Zoom",
|
||||
translation_key="block_zoom",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:video",
|
||||
@@ -486,7 +486,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_dating",
|
||||
name="Block dating",
|
||||
translation_key="block_dating",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:candelabra",
|
||||
@@ -494,7 +494,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_gambling",
|
||||
name="Block gambling",
|
||||
translation_key="block_gambling",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:slot-machine",
|
||||
@@ -502,7 +502,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_piracy",
|
||||
name="Block piracy",
|
||||
translation_key="block_piracy",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:pirate",
|
||||
@@ -510,7 +510,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_porn",
|
||||
name="Block porn",
|
||||
translation_key="block_porn",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:movie-off",
|
||||
@@ -518,7 +518,7 @@ SWITCHES = (
|
||||
),
|
||||
NextDnsSwitchEntityDescription[Settings](
|
||||
key="block_social_networks",
|
||||
name="Block social networks",
|
||||
translation_key="block_social_networks",
|
||||
entity_category=EntityCategory.CONFIG,
|
||||
entity_registry_enabled_default=False,
|
||||
icon="mdi:facebook",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user