Add more mysensors sensor attributes (#53566)

This commit is contained in:
Martin Hjelmare 2021-07-27 19:48:37 +02:00 committed by GitHub
parent 27d42e0cd8
commit a133eae88e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 141 additions and 45 deletions

View File

@ -1,16 +1,27 @@
"""Support for MySensors sensors."""
from __future__ import annotations
from datetime import datetime
from awesomeversion import AwesomeVersion
from homeassistant.components import mysensors
from homeassistant.components.sensor import DOMAIN, SensorEntity
from homeassistant.components.sensor import (
DOMAIN,
STATE_CLASS_MEASUREMENT,
SensorEntity,
)
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
CONDUCTIVITY,
DEGREE,
DEVICE_CLASS_CURRENT,
DEVICE_CLASS_ENERGY,
DEVICE_CLASS_HUMIDITY,
DEVICE_CLASS_ILLUMINANCE,
DEVICE_CLASS_POWER,
DEVICE_CLASS_TEMPERATURE,
DEVICE_CLASS_VOLTAGE,
ELECTRIC_CURRENT_AMPERE,
ELECTRIC_POTENTIAL_MILLIVOLT,
ELECTRIC_POTENTIAL_VOLT,
@ -30,42 +41,68 @@ from homeassistant.const import (
from homeassistant.core import HomeAssistant
from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.helpers.entity_platform import AddEntitiesCallback
from homeassistant.util.dt import utc_from_timestamp
from .const import MYSENSORS_DISCOVERY, DiscoveryInfo
from .helpers import on_unload
SENSORS: dict[str, list[str | None] | dict[str, list[str | None]]] = {
"V_TEMP": [None, None, DEVICE_CLASS_TEMPERATURE],
"V_HUM": [PERCENTAGE, "mdi:water-percent", DEVICE_CLASS_HUMIDITY],
"V_DIMMER": [PERCENTAGE, "mdi:percent", None],
"V_PERCENTAGE": [PERCENTAGE, "mdi:percent", None],
"V_PRESSURE": [None, "mdi:gauge", None],
"V_FORECAST": [None, "mdi:weather-partly-cloudy", None],
"V_RAIN": [None, "mdi:weather-rainy", None],
"V_RAINRATE": [None, "mdi:weather-rainy", None],
"V_WIND": [None, "mdi:weather-windy", None],
"V_GUST": [None, "mdi:weather-windy", None],
"V_DIRECTION": [DEGREE, "mdi:compass", None],
"V_WEIGHT": [MASS_KILOGRAMS, "mdi:weight-kilogram", None],
"V_DISTANCE": [LENGTH_METERS, "mdi:ruler", None],
"V_IMPEDANCE": ["ohm", None, None],
"V_WATT": [POWER_WATT, None, None],
"V_KWH": [ENERGY_KILO_WATT_HOUR, None, None],
"V_LIGHT_LEVEL": [PERCENTAGE, "mdi:white-balance-sunny", None],
"V_FLOW": [LENGTH_METERS, "mdi:gauge", None],
"V_VOLUME": [f"{VOLUME_CUBIC_METERS}", None, None],
"V_TEMP": [None, None, DEVICE_CLASS_TEMPERATURE, STATE_CLASS_MEASUREMENT],
"V_HUM": [
PERCENTAGE,
"mdi:water-percent",
DEVICE_CLASS_HUMIDITY,
STATE_CLASS_MEASUREMENT,
],
"V_DIMMER": [PERCENTAGE, "mdi:percent", None, None],
"V_PERCENTAGE": [PERCENTAGE, "mdi:percent", None, None],
"V_PRESSURE": [None, "mdi:gauge", None, None],
"V_FORECAST": [None, "mdi:weather-partly-cloudy", None, None],
"V_RAIN": [None, "mdi:weather-rainy", None, None],
"V_RAINRATE": [None, "mdi:weather-rainy", None, None],
"V_WIND": [None, "mdi:weather-windy", None, None],
"V_GUST": [None, "mdi:weather-windy", None, None],
"V_DIRECTION": [DEGREE, "mdi:compass", None, None],
"V_WEIGHT": [MASS_KILOGRAMS, "mdi:weight-kilogram", None, None],
"V_DISTANCE": [LENGTH_METERS, "mdi:ruler", None, None],
"V_IMPEDANCE": ["ohm", None, None, None],
"V_WATT": [POWER_WATT, None, DEVICE_CLASS_POWER, STATE_CLASS_MEASUREMENT],
"V_KWH": [
ENERGY_KILO_WATT_HOUR,
None,
DEVICE_CLASS_ENERGY,
STATE_CLASS_MEASUREMENT,
],
"V_LIGHT_LEVEL": [PERCENTAGE, "mdi:white-balance-sunny", None, None],
"V_FLOW": [LENGTH_METERS, "mdi:gauge", None, None],
"V_VOLUME": [VOLUME_CUBIC_METERS, None, None, None],
"V_LEVEL": {
"S_SOUND": [SOUND_PRESSURE_DB, "mdi:volume-high", None],
"S_VIBRATION": [FREQUENCY_HERTZ, None, None],
"S_LIGHT_LEVEL": [LIGHT_LUX, "mdi:white-balance-sunny", None],
"S_SOUND": [SOUND_PRESSURE_DB, "mdi:volume-high", None, None],
"S_VIBRATION": [FREQUENCY_HERTZ, None, None, None],
"S_LIGHT_LEVEL": [
LIGHT_LUX,
"mdi:white-balance-sunny",
DEVICE_CLASS_ILLUMINANCE,
STATE_CLASS_MEASUREMENT,
],
},
"V_VOLTAGE": [ELECTRIC_POTENTIAL_VOLT, "mdi:flash", None],
"V_CURRENT": [ELECTRIC_CURRENT_AMPERE, "mdi:flash-auto", None],
"V_PH": ["pH", None, None],
"V_ORP": [ELECTRIC_POTENTIAL_MILLIVOLT, None, None],
"V_EC": [CONDUCTIVITY, None, None],
"V_VAR": ["var", None, None],
"V_VA": [POWER_VOLT_AMPERE, None, None],
"V_VOLTAGE": [
ELECTRIC_POTENTIAL_VOLT,
"mdi:flash",
DEVICE_CLASS_VOLTAGE,
STATE_CLASS_MEASUREMENT,
],
"V_CURRENT": [
ELECTRIC_CURRENT_AMPERE,
"mdi:flash-auto",
DEVICE_CLASS_CURRENT,
STATE_CLASS_MEASUREMENT,
],
"V_PH": ["pH", None, None, None],
"V_ORP": [ELECTRIC_POTENTIAL_MILLIVOLT, None, None, None],
"V_EC": [CONDUCTIVITY, None, None, None],
"V_VAR": ["var", None, None, None],
"V_VA": [POWER_VOLT_AMPERE, None, None, None],
}
@ -124,6 +161,20 @@ class MySensorsSensor(mysensors.device.MySensorsEntity, SensorEntity):
"""Return the icon to use in the frontend, if any."""
return self._get_sensor_type()[1]
@property
def last_reset(self) -> datetime | None:
"""Return the time when the sensor was last reset, if any."""
set_req = self.gateway.const.SetReq
if set_req(self.value_type).name == "V_KWH":
return utc_from_timestamp(0)
return None
@property
def state_class(self) -> str | None:
"""Return the state class of this entity."""
return self._get_sensor_type()[3]
@property
def unit_of_measurement(self) -> str | None:
"""Return the unit of measurement of this entity."""
@ -148,10 +199,12 @@ class MySensorsSensor(mysensors.device.MySensorsEntity, SensorEntity):
pres = self.gateway.const.Presentation
set_req = self.gateway.const.SetReq
_sensor_type = SENSORS.get(set_req(self.value_type).name, [None, None, None])
_sensor_type = SENSORS.get(
set_req(self.value_type).name, [None, None, None, None]
)
if isinstance(_sensor_type, dict):
sensor_type = _sensor_type.get(
pres(self.child_type).name, [None, None, None]
pres(self.child_type).name, [None, None, None, None]
)
else:
sensor_type = _sensor_type

View File

@ -1,7 +1,6 @@
"""Support for MySensors switches."""
from __future__ import annotations
from contextlib import suppress
from typing import Any
import voluptuous as vol
@ -109,18 +108,6 @@ async def async_setup_entry(
class MySensorsSwitch(mysensors.device.MySensorsEntity, SwitchEntity):
"""Representation of the value of a MySensors Switch child node."""
@property
def current_power_w(self) -> float | None:
"""Return the current power usage in W."""
set_req = self.gateway.const.SetReq
value = self._values.get(set_req.V_WATT)
float_value: float | None = None
if value is not None:
with suppress(ValueError):
float_value = float(value)
return float_value
@property
def is_on(self) -> bool:
"""Return True if switch is on."""

View File

@ -156,3 +156,17 @@ def gps_sensor(gateway_nodes, gps_sensor_state) -> Sensor:
nodes = update_gateway_nodes(gateway_nodes, gps_sensor_state)
node = nodes[1]
return node
@pytest.fixture(name="power_sensor_state", scope="session")
def power_sensor_state_fixture() -> dict:
"""Load the power sensor state."""
return load_nodes_state("mysensors/power_sensor_state.json")
@pytest.fixture
def power_sensor(gateway_nodes, power_sensor_state) -> Sensor:
"""Load the power sensor."""
nodes = update_gateway_nodes(gateway_nodes, power_sensor_state)
node = nodes[1]
return node

View File

@ -1,6 +1,15 @@
"""Provide tests for mysensors sensor platform."""
from homeassistant.components.sensor import ATTR_STATE_CLASS, STATE_CLASS_MEASUREMENT
from homeassistant.const import (
ATTR_DEVICE_CLASS,
ATTR_UNIT_OF_MEASUREMENT,
DEVICE_CLASS_POWER,
POWER_WATT,
)
async def test_gps_sensor(hass, gps_sensor, integration):
"""Test a gps sensor."""
entity_id = "sensor.gps_sensor_1_1"
@ -8,3 +17,15 @@ async def test_gps_sensor(hass, gps_sensor, integration):
state = hass.states.get(entity_id)
assert state.state == "40.741894,-73.989311,12"
async def test_power_sensor(hass, power_sensor, integration):
"""Test a power sensor."""
entity_id = "sensor.power_sensor_1_1"
state = hass.states.get(entity_id)
assert state.state == "1200"
assert state.attributes[ATTR_DEVICE_CLASS] == DEVICE_CLASS_POWER
assert state.attributes[ATTR_UNIT_OF_MEASUREMENT] == POWER_WATT
assert state.attributes[ATTR_STATE_CLASS] == STATE_CLASS_MEASUREMENT

View File

@ -0,0 +1,21 @@
{
"1": {
"sensor_id": 1,
"children": {
"1": {
"id": 1,
"type": 13,
"description": "",
"values": {
"17": "1200"
}
}
},
"type": 17,
"sketch_name": "Power Sensor",
"sketch_version": "1.0",
"battery_level": 0,
"protocol_version": "2.3.2",
"heartbeat": 0
}
}