Add support for Aranet radiation devices (#115239)

* sensor: added radiation dose sensor type and units

* Add support for Aranet Radiation devices

* Fix Aranet Radiation CI issues

* Revert "sensor: added radiation dose sensor type and units"

This reverts commit 28736a7da760d3490e879bb7fe5b17f8f2b851f4.

* aranet4: bump version to 2.3.3

* aranet radiation: remove removed sesnor consts

* aranet radiation: use radioactive icon by default

---------

Co-authored-by: Shay Levy <levyshay1@gmail.com>
This commit is contained in:
Anrijs 2024-04-25 22:38:20 +03:00 committed by GitHub
parent a8b41c90c5
commit 8649489117
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 108 additions and 5 deletions

View File

@ -127,8 +127,8 @@ build.json @home-assistant/supervisor
/tests/components/aprilaire/ @chamberlain2007 /tests/components/aprilaire/ @chamberlain2007
/homeassistant/components/aprs/ @PhilRW /homeassistant/components/aprs/ @PhilRW
/tests/components/aprs/ @PhilRW /tests/components/aprs/ @PhilRW
/homeassistant/components/aranet/ @aschmitz @thecode /homeassistant/components/aranet/ @aschmitz @thecode @anrijs
/tests/components/aranet/ @aschmitz @thecode /tests/components/aranet/ @aschmitz @thecode @anrijs
/homeassistant/components/arcam_fmj/ @elupus /homeassistant/components/arcam_fmj/ @elupus
/tests/components/arcam_fmj/ @elupus /tests/components/arcam_fmj/ @elupus
/homeassistant/components/arris_tg2492lg/ @vanbalken /homeassistant/components/arris_tg2492lg/ @vanbalken

View File

@ -1,3 +1,4 @@
"""Constants for the Aranet integration.""" """Constants for the Aranet integration."""
DOMAIN = "aranet" DOMAIN = "aranet"
ARANET_MANUFACTURER_NAME = "SAF Tehnika"

View File

@ -0,0 +1,12 @@
{
"entity": {
"sensor": {
"radiation_total": {
"default": "mdi:radioactive"
},
"radiation_rate": {
"default": "mdi:radioactive"
}
}
}
}

View File

@ -13,7 +13,7 @@
"connectable": false "connectable": false
} }
], ],
"codeowners": ["@aschmitz", "@thecode"], "codeowners": ["@aschmitz", "@thecode", "@anrijs"],
"config_flow": true, "config_flow": true,
"dependencies": ["bluetooth_adapters"], "dependencies": ["bluetooth_adapters"],
"documentation": "https://www.home-assistant.io/integrations/aranet", "documentation": "https://www.home-assistant.io/integrations/aranet",

View File

@ -23,6 +23,7 @@ from homeassistant.components.sensor import (
SensorStateClass, SensorStateClass,
) )
from homeassistant.const import ( from homeassistant.const import (
ATTR_MANUFACTURER,
ATTR_NAME, ATTR_NAME,
ATTR_SW_VERSION, ATTR_SW_VERSION,
CONCENTRATION_PARTS_PER_MILLION, CONCENTRATION_PARTS_PER_MILLION,
@ -37,7 +38,7 @@ from homeassistant.helpers.device_registry import DeviceInfo
from homeassistant.helpers.entity import EntityDescription from homeassistant.helpers.entity import EntityDescription
from homeassistant.helpers.entity_platform import AddEntitiesCallback from homeassistant.helpers.entity_platform import AddEntitiesCallback
from .const import DOMAIN from .const import ARANET_MANUFACTURER_NAME, DOMAIN
@dataclass(frozen=True) @dataclass(frozen=True)
@ -48,6 +49,7 @@ class AranetSensorEntityDescription(SensorEntityDescription):
# Restrict the type to satisfy the type checker and catch attempts # Restrict the type to satisfy the type checker and catch attempts
# to use UNDEFINED in the entity descriptions. # to use UNDEFINED in the entity descriptions.
name: str | None = None name: str | None = None
scale: float | int = 1
SENSOR_DESCRIPTIONS = { SENSOR_DESCRIPTIONS = {
@ -79,6 +81,24 @@ SENSOR_DESCRIPTIONS = {
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION, native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
state_class=SensorStateClass.MEASUREMENT, state_class=SensorStateClass.MEASUREMENT,
), ),
"radiation_rate": AranetSensorEntityDescription(
key="radiation_rate",
translation_key="radiation_rate",
name="Radiation Dose Rate",
native_unit_of_measurement="μSv/h",
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=2,
scale=0.001,
),
"radiation_total": AranetSensorEntityDescription(
key="radiation_total",
translation_key="radiation_total",
name="Radiation Total Dose",
native_unit_of_measurement="mSv",
state_class=SensorStateClass.MEASUREMENT,
suggested_display_precision=4,
scale=0.000001,
),
"battery": AranetSensorEntityDescription( "battery": AranetSensorEntityDescription(
key="battery", key="battery",
name="Battery", name="Battery",
@ -115,6 +135,7 @@ def _sensor_device_info_to_hass(
hass_device_info = DeviceInfo({}) hass_device_info = DeviceInfo({})
if adv.readings and adv.readings.name: if adv.readings and adv.readings.name:
hass_device_info[ATTR_NAME] = adv.readings.name hass_device_info[ATTR_NAME] = adv.readings.name
hass_device_info[ATTR_MANUFACTURER] = ARANET_MANUFACTURER_NAME
if adv.manufacturer_data: if adv.manufacturer_data:
hass_device_info[ATTR_SW_VERSION] = str(adv.manufacturer_data.version) hass_device_info[ATTR_SW_VERSION] = str(adv.manufacturer_data.version)
return hass_device_info return hass_device_info
@ -132,6 +153,7 @@ def sensor_update_to_bluetooth_data_update(
val = getattr(adv.readings, key) val = getattr(adv.readings, key)
if val == -1: if val == -1:
continue continue
val *= desc.scale
data[tag] = val data[tag] = val
names[tag] = desc.name names[tag] = desc.name
descs[tag] = desc descs[tag] = desc

View File

@ -17,7 +17,7 @@
}, },
"abort": { "abort": {
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]", "already_configured": "[%key:common::config_flow::abort::already_configured_device%]",
"integrations_diabled": "This device doesn't have integrations enabled. Please enable smart home integrations using the app and try again.", "integrations_disabled": "This device doesn't have integrations enabled. Please enable smart home integrations using the app and try again.",
"no_devices_found": "No unconfigured Aranet devices found.", "no_devices_found": "No unconfigured Aranet devices found.",
"outdated_version": "This device is using outdated firmware. Please update it to at least v1.2.0 and try again." "outdated_version": "This device is using outdated firmware. Please update it to at least v1.2.0 and try again."
} }

View File

@ -73,3 +73,11 @@ VALID_ARANET2_DATA_SERVICE_INFO = fake_service_info(
1794: b"\x01!\x04\x04\x01\x00\x00\x00\x00\x00\xf0\x01\x00\x00\x0c\x02\x00O\x00<\x00\x01\x00\x80" 1794: b"\x01!\x04\x04\x01\x00\x00\x00\x00\x00\xf0\x01\x00\x00\x0c\x02\x00O\x00<\x00\x01\x00\x80"
}, },
) )
VALID_ARANET_RADIATION_DATA_SERVICE_INFO = fake_service_info(
"Aranet\u2622 12345",
"0000fce0-0000-1000-8000-00805f9b34fb",
{
1794: b"\x02!&\x04\x01\x00`-\x00\x00\x08\x98\x05\x00n\x00\x00d\x00,\x01\xfd\x00\xc7"
},
)

View File

@ -8,6 +8,7 @@ from homeassistant.core import HomeAssistant
from . import ( from . import (
DISABLED_INTEGRATIONS_SERVICE_INFO, DISABLED_INTEGRATIONS_SERVICE_INFO,
VALID_ARANET2_DATA_SERVICE_INFO, VALID_ARANET2_DATA_SERVICE_INFO,
VALID_ARANET_RADIATION_DATA_SERVICE_INFO,
VALID_DATA_SERVICE_INFO, VALID_DATA_SERVICE_INFO,
) )
@ -15,6 +16,65 @@ from tests.common import MockConfigEntry
from tests.components.bluetooth import inject_bluetooth_service_info from tests.components.bluetooth import inject_bluetooth_service_info
async def test_sensors_aranet_radiation(
hass: HomeAssistant, entity_registry_enabled_by_default: None
) -> None:
"""Test setting up creates the sensors for Aranet Radiation device."""
entry = MockConfigEntry(
domain=DOMAIN,
unique_id="aa:bb:cc:dd:ee:ff",
)
entry.add_to_hass(hass)
assert await hass.config_entries.async_setup(entry.entry_id)
await hass.async_block_till_done()
assert len(hass.states.async_all("sensor")) == 0
inject_bluetooth_service_info(hass, VALID_ARANET_RADIATION_DATA_SERVICE_INFO)
await hass.async_block_till_done()
assert len(hass.states.async_all("sensor")) == 4
batt_sensor = hass.states.get("sensor.aranet_12345_battery")
batt_sensor_attrs = batt_sensor.attributes
assert batt_sensor.state == "100"
assert batt_sensor_attrs[ATTR_FRIENDLY_NAME] == "Aranet\u2622 12345 Battery"
assert batt_sensor_attrs[ATTR_UNIT_OF_MEASUREMENT] == "%"
assert batt_sensor_attrs[ATTR_STATE_CLASS] == "measurement"
humid_sensor = hass.states.get("sensor.aranet_12345_radiation_total_dose")
humid_sensor_attrs = humid_sensor.attributes
assert humid_sensor.state == "0.011616"
assert (
humid_sensor_attrs[ATTR_FRIENDLY_NAME]
== "Aranet\u2622 12345 Radiation Total Dose"
)
assert humid_sensor_attrs[ATTR_UNIT_OF_MEASUREMENT] == "mSv"
assert humid_sensor_attrs[ATTR_STATE_CLASS] == "measurement"
temp_sensor = hass.states.get("sensor.aranet_12345_radiation_dose_rate")
temp_sensor_attrs = temp_sensor.attributes
assert temp_sensor.state == "0.11"
assert (
temp_sensor_attrs[ATTR_FRIENDLY_NAME]
== "Aranet\u2622 12345 Radiation Dose Rate"
)
assert temp_sensor_attrs[ATTR_UNIT_OF_MEASUREMENT] == "μSv/h"
assert temp_sensor_attrs[ATTR_STATE_CLASS] == "measurement"
interval_sensor = hass.states.get("sensor.aranet_12345_update_interval")
interval_sensor_attrs = interval_sensor.attributes
assert interval_sensor.state == "300"
assert (
interval_sensor_attrs[ATTR_FRIENDLY_NAME]
== "Aranet\u2622 12345 Update Interval"
)
assert interval_sensor_attrs[ATTR_UNIT_OF_MEASUREMENT] == "s"
assert interval_sensor_attrs[ATTR_STATE_CLASS] == "measurement"
assert await hass.config_entries.async_unload(entry.entry_id)
await hass.async_block_till_done()
async def test_sensors_aranet2( async def test_sensors_aranet2(
hass: HomeAssistant, entity_registry_enabled_by_default: None hass: HomeAssistant, entity_registry_enabled_by_default: None
) -> None: ) -> None: