Skip to content

Commit

Permalink
Add support for Aranet radiation devices (home-assistant#115239)
Browse files Browse the repository at this point in the history
* 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 28736a7.

* 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 <[email protected]>
  • Loading branch information
Anrijs and thecode authored Apr 25, 2024
1 parent a8b41c9 commit 8649489
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 5 deletions.
4 changes: 2 additions & 2 deletions CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -127,8 +127,8 @@ build.json @home-assistant/supervisor
/tests/components/aprilaire/ @chamberlain2007
/homeassistant/components/aprs/ @PhilRW
/tests/components/aprs/ @PhilRW
/homeassistant/components/aranet/ @aschmitz @thecode
/tests/components/aranet/ @aschmitz @thecode
/homeassistant/components/aranet/ @aschmitz @thecode @anrijs
/tests/components/aranet/ @aschmitz @thecode @anrijs
/homeassistant/components/arcam_fmj/ @elupus
/tests/components/arcam_fmj/ @elupus
/homeassistant/components/arris_tg2492lg/ @vanbalken
Expand Down
1 change: 1 addition & 0 deletions homeassistant/components/aranet/const.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""Constants for the Aranet integration."""

DOMAIN = "aranet"
ARANET_MANUFACTURER_NAME = "SAF Tehnika"
12 changes: 12 additions & 0 deletions homeassistant/components/aranet/icons.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"entity": {
"sensor": {
"radiation_total": {
"default": "mdi:radioactive"
},
"radiation_rate": {
"default": "mdi:radioactive"
}
}
}
}
2 changes: 1 addition & 1 deletion homeassistant/components/aranet/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"connectable": false
}
],
"codeowners": ["@aschmitz", "@thecode"],
"codeowners": ["@aschmitz", "@thecode", "@anrijs"],
"config_flow": true,
"dependencies": ["bluetooth_adapters"],
"documentation": "https://www.home-assistant.io/integrations/aranet",
Expand Down
24 changes: 23 additions & 1 deletion homeassistant/components/aranet/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
SensorStateClass,
)
from homeassistant.const import (
ATTR_MANUFACTURER,
ATTR_NAME,
ATTR_SW_VERSION,
CONCENTRATION_PARTS_PER_MILLION,
Expand All @@ -37,7 +38,7 @@
from homeassistant.helpers.entity import EntityDescription
from homeassistant.helpers.entity_platform import AddEntitiesCallback

from .const import DOMAIN
from .const import ARANET_MANUFACTURER_NAME, DOMAIN


@dataclass(frozen=True)
Expand All @@ -48,6 +49,7 @@ class AranetSensorEntityDescription(SensorEntityDescription):
# Restrict the type to satisfy the type checker and catch attempts
# to use UNDEFINED in the entity descriptions.
name: str | None = None
scale: float | int = 1


SENSOR_DESCRIPTIONS = {
Expand Down Expand Up @@ -79,6 +81,24 @@ class AranetSensorEntityDescription(SensorEntityDescription):
native_unit_of_measurement=CONCENTRATION_PARTS_PER_MILLION,
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(
key="battery",
name="Battery",
Expand Down Expand Up @@ -115,6 +135,7 @@ def _sensor_device_info_to_hass(
hass_device_info = DeviceInfo({})
if adv.readings and adv.readings.name:
hass_device_info[ATTR_NAME] = adv.readings.name
hass_device_info[ATTR_MANUFACTURER] = ARANET_MANUFACTURER_NAME
if adv.manufacturer_data:
hass_device_info[ATTR_SW_VERSION] = str(adv.manufacturer_data.version)
return hass_device_info
Expand All @@ -132,6 +153,7 @@ def sensor_update_to_bluetooth_data_update(
val = getattr(adv.readings, key)
if val == -1:
continue
val *= desc.scale
data[tag] = val
names[tag] = desc.name
descs[tag] = desc
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/aranet/strings.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
},
"abort": {
"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.",
"outdated_version": "This device is using outdated firmware. Please update it to at least v1.2.0 and try again."
}
Expand Down
8 changes: 8 additions & 0 deletions tests/components/aranet/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,11 @@ def fake_service_info(name, service_uuid, manufacturer_data):
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"
},
)
60 changes: 60 additions & 0 deletions tests/components/aranet/test_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,73 @@
from . import (
DISABLED_INTEGRATIONS_SERVICE_INFO,
VALID_ARANET2_DATA_SERVICE_INFO,
VALID_ARANET_RADIATION_DATA_SERVICE_INFO,
VALID_DATA_SERVICE_INFO,
)

from tests.common import MockConfigEntry
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(
hass: HomeAssistant, entity_registry_enabled_by_default: None
) -> None:
Expand Down

0 comments on commit 8649489

Please sign in to comment.