mirror of
https://github.com/home-assistant/core.git
synced 2025-04-23 08:47:57 +00:00
Add device class gas
and enable statistics for it (#54110)
Co-authored-by: Martin Hjelmare <marhje52@gmail.com> Co-authored-by: Erik Montnemery <erik@montnemery.com>
This commit is contained in:
parent
94a264afaf
commit
e23750b2a4
@ -9,6 +9,7 @@ from homeassistant.components.sensor import STATE_CLASS_MEASUREMENT
|
||||
from homeassistant.const import (
|
||||
DEVICE_CLASS_CURRENT,
|
||||
DEVICE_CLASS_ENERGY,
|
||||
DEVICE_CLASS_GAS,
|
||||
DEVICE_CLASS_POWER,
|
||||
DEVICE_CLASS_VOLTAGE,
|
||||
)
|
||||
@ -256,6 +257,7 @@ SENSORS: tuple[DSMRSensorEntityDescription, ...] = (
|
||||
is_gas=True,
|
||||
force_update=True,
|
||||
icon="mdi:fire",
|
||||
device_class=DEVICE_CLASS_GAS,
|
||||
last_reset=dt.utc_from_timestamp(0),
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
@ -266,6 +268,7 @@ SENSORS: tuple[DSMRSensorEntityDescription, ...] = (
|
||||
is_gas=True,
|
||||
force_update=True,
|
||||
icon="mdi:fire",
|
||||
device_class=DEVICE_CLASS_GAS,
|
||||
last_reset=dt.utc_from_timestamp(0),
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
@ -276,6 +279,7 @@ SENSORS: tuple[DSMRSensorEntityDescription, ...] = (
|
||||
is_gas=True,
|
||||
force_update=True,
|
||||
icon="mdi:fire",
|
||||
device_class=DEVICE_CLASS_GAS,
|
||||
last_reset=dt.utc_from_timestamp(0),
|
||||
state_class=STATE_CLASS_MEASUREMENT,
|
||||
),
|
||||
|
@ -16,7 +16,12 @@ import voluptuous as vol
|
||||
|
||||
from homeassistant.components.sensor import PLATFORM_SCHEMA, SensorEntity
|
||||
from homeassistant.config_entries import SOURCE_IMPORT, ConfigEntry
|
||||
from homeassistant.const import CONF_HOST, CONF_PORT, EVENT_HOMEASSISTANT_STOP
|
||||
from homeassistant.const import (
|
||||
CONF_HOST,
|
||||
CONF_PORT,
|
||||
EVENT_HOMEASSISTANT_STOP,
|
||||
VOLUME_CUBIC_METERS,
|
||||
)
|
||||
from homeassistant.core import CoreState, HomeAssistant, callback
|
||||
from homeassistant.helpers import config_validation as cv
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
@ -56,6 +61,8 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend(
|
||||
}
|
||||
)
|
||||
|
||||
UNIT_CONVERSION = {"m3": VOLUME_CUBIC_METERS}
|
||||
|
||||
|
||||
async def async_setup_platform(
|
||||
hass: HomeAssistant,
|
||||
@ -260,7 +267,10 @@ class DSMREntity(SensorEntity):
|
||||
@property
|
||||
def native_unit_of_measurement(self) -> str | None:
|
||||
"""Return the unit of measurement of this entity, if any."""
|
||||
return self.get_dsmr_object_attr("unit")
|
||||
unit_of_measurement = self.get_dsmr_object_attr("unit")
|
||||
if unit_of_measurement in UNIT_CONVERSION:
|
||||
return UNIT_CONVERSION[unit_of_measurement]
|
||||
return unit_of_measurement
|
||||
|
||||
@staticmethod
|
||||
def translate_tariff(value: str, dsmr_version: str) -> str | None:
|
||||
|
@ -11,13 +11,19 @@ from sqlalchemy import bindparam
|
||||
from sqlalchemy.ext import baked
|
||||
from sqlalchemy.orm.scoping import scoped_session
|
||||
|
||||
from homeassistant.const import PRESSURE_PA, TEMP_CELSIUS
|
||||
from homeassistant.const import (
|
||||
PRESSURE_PA,
|
||||
TEMP_CELSIUS,
|
||||
VOLUME_CUBIC_FEET,
|
||||
VOLUME_CUBIC_METERS,
|
||||
)
|
||||
from homeassistant.core import Event, HomeAssistant, callback
|
||||
from homeassistant.helpers import entity_registry
|
||||
import homeassistant.util.dt as dt_util
|
||||
import homeassistant.util.pressure as pressure_util
|
||||
import homeassistant.util.temperature as temperature_util
|
||||
from homeassistant.util.unit_system import UnitSystem
|
||||
import homeassistant.util.volume as volume_util
|
||||
|
||||
from .const import DOMAIN
|
||||
from .models import (
|
||||
@ -64,6 +70,11 @@ UNIT_CONVERSIONS = {
|
||||
)
|
||||
if x is not None
|
||||
else None,
|
||||
VOLUME_CUBIC_METERS: lambda x, units: volume_util.convert(
|
||||
x, VOLUME_CUBIC_METERS, _configured_unit(VOLUME_CUBIC_METERS, units)
|
||||
)
|
||||
if x is not None
|
||||
else None,
|
||||
}
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
@ -214,6 +225,10 @@ def _configured_unit(unit: str, units: UnitSystem) -> str:
|
||||
return units.pressure_unit
|
||||
if unit == TEMP_CELSIUS:
|
||||
return units.temperature_unit
|
||||
if unit == VOLUME_CUBIC_METERS:
|
||||
if units.is_metric:
|
||||
return VOLUME_CUBIC_METERS
|
||||
return VOLUME_CUBIC_FEET
|
||||
return unit
|
||||
|
||||
|
||||
|
@ -17,6 +17,7 @@ from homeassistant.const import (
|
||||
DEVICE_CLASS_CO2,
|
||||
DEVICE_CLASS_CURRENT,
|
||||
DEVICE_CLASS_ENERGY,
|
||||
DEVICE_CLASS_GAS,
|
||||
DEVICE_CLASS_HUMIDITY,
|
||||
DEVICE_CLASS_ILLUMINANCE,
|
||||
DEVICE_CLASS_MONETARY,
|
||||
@ -65,6 +66,7 @@ DEVICE_CLASSES: Final[list[str]] = [
|
||||
DEVICE_CLASS_POWER, # power (W/kW)
|
||||
DEVICE_CLASS_POWER_FACTOR, # power factor (%)
|
||||
DEVICE_CLASS_VOLTAGE, # voltage (V)
|
||||
DEVICE_CLASS_GAS, # gas (m³ or ft³)
|
||||
]
|
||||
|
||||
DEVICE_CLASSES_SCHEMA: Final = vol.All(vol.Lower, vol.In(DEVICE_CLASSES))
|
||||
|
@ -16,6 +16,7 @@ from homeassistant.const import (
|
||||
DEVICE_CLASS_CO2,
|
||||
DEVICE_CLASS_CURRENT,
|
||||
DEVICE_CLASS_ENERGY,
|
||||
DEVICE_CLASS_GAS,
|
||||
DEVICE_CLASS_HUMIDITY,
|
||||
DEVICE_CLASS_ILLUMINANCE,
|
||||
DEVICE_CLASS_POWER,
|
||||
@ -46,6 +47,7 @@ CONF_IS_CO2 = "is_carbon_dioxide"
|
||||
CONF_IS_CURRENT = "is_current"
|
||||
CONF_IS_ENERGY = "is_energy"
|
||||
CONF_IS_HUMIDITY = "is_humidity"
|
||||
CONF_IS_GAS = "is_gas"
|
||||
CONF_IS_ILLUMINANCE = "is_illuminance"
|
||||
CONF_IS_POWER = "is_power"
|
||||
CONF_IS_POWER_FACTOR = "is_power_factor"
|
||||
@ -61,6 +63,7 @@ ENTITY_CONDITIONS = {
|
||||
DEVICE_CLASS_CO2: [{CONF_TYPE: CONF_IS_CO2}],
|
||||
DEVICE_CLASS_CURRENT: [{CONF_TYPE: CONF_IS_CURRENT}],
|
||||
DEVICE_CLASS_ENERGY: [{CONF_TYPE: CONF_IS_ENERGY}],
|
||||
DEVICE_CLASS_GAS: [{CONF_TYPE: CONF_IS_GAS}],
|
||||
DEVICE_CLASS_HUMIDITY: [{CONF_TYPE: CONF_IS_HUMIDITY}],
|
||||
DEVICE_CLASS_ILLUMINANCE: [{CONF_TYPE: CONF_IS_ILLUMINANCE}],
|
||||
DEVICE_CLASS_POWER: [{CONF_TYPE: CONF_IS_POWER}],
|
||||
@ -83,6 +86,7 @@ CONDITION_SCHEMA = vol.All(
|
||||
CONF_IS_CO2,
|
||||
CONF_IS_CURRENT,
|
||||
CONF_IS_ENERGY,
|
||||
CONF_IS_GAS,
|
||||
CONF_IS_HUMIDITY,
|
||||
CONF_IS_ILLUMINANCE,
|
||||
CONF_IS_POWER,
|
||||
|
@ -19,6 +19,7 @@ from homeassistant.const import (
|
||||
DEVICE_CLASS_CO2,
|
||||
DEVICE_CLASS_CURRENT,
|
||||
DEVICE_CLASS_ENERGY,
|
||||
DEVICE_CLASS_GAS,
|
||||
DEVICE_CLASS_HUMIDITY,
|
||||
DEVICE_CLASS_ILLUMINANCE,
|
||||
DEVICE_CLASS_POWER,
|
||||
@ -44,6 +45,7 @@ CONF_CO = "carbon_monoxide"
|
||||
CONF_CO2 = "carbon_dioxide"
|
||||
CONF_CURRENT = "current"
|
||||
CONF_ENERGY = "energy"
|
||||
CONF_GAS = "gas"
|
||||
CONF_HUMIDITY = "humidity"
|
||||
CONF_ILLUMINANCE = "illuminance"
|
||||
CONF_POWER = "power"
|
||||
@ -60,6 +62,7 @@ ENTITY_TRIGGERS = {
|
||||
DEVICE_CLASS_CO2: [{CONF_TYPE: CONF_CO2}],
|
||||
DEVICE_CLASS_CURRENT: [{CONF_TYPE: CONF_CURRENT}],
|
||||
DEVICE_CLASS_ENERGY: [{CONF_TYPE: CONF_ENERGY}],
|
||||
DEVICE_CLASS_GAS: [{CONF_TYPE: CONF_GAS}],
|
||||
DEVICE_CLASS_HUMIDITY: [{CONF_TYPE: CONF_HUMIDITY}],
|
||||
DEVICE_CLASS_ILLUMINANCE: [{CONF_TYPE: CONF_ILLUMINANCE}],
|
||||
DEVICE_CLASS_POWER: [{CONF_TYPE: CONF_POWER}],
|
||||
@ -83,6 +86,7 @@ TRIGGER_SCHEMA = vol.All(
|
||||
CONF_CO2,
|
||||
CONF_CURRENT,
|
||||
CONF_ENERGY,
|
||||
CONF_GAS,
|
||||
CONF_HUMIDITY,
|
||||
CONF_ILLUMINANCE,
|
||||
CONF_POWER,
|
||||
|
@ -11,6 +11,7 @@ from homeassistant.components.sensor import (
|
||||
ATTR_STATE_CLASS,
|
||||
DEVICE_CLASS_BATTERY,
|
||||
DEVICE_CLASS_ENERGY,
|
||||
DEVICE_CLASS_GAS,
|
||||
DEVICE_CLASS_HUMIDITY,
|
||||
DEVICE_CLASS_MONETARY,
|
||||
DEVICE_CLASS_PRESSURE,
|
||||
@ -35,11 +36,14 @@ from homeassistant.const import (
|
||||
TEMP_CELSIUS,
|
||||
TEMP_FAHRENHEIT,
|
||||
TEMP_KELVIN,
|
||||
VOLUME_CUBIC_FEET,
|
||||
VOLUME_CUBIC_METERS,
|
||||
)
|
||||
from homeassistant.core import HomeAssistant, State
|
||||
import homeassistant.util.dt as dt_util
|
||||
import homeassistant.util.pressure as pressure_util
|
||||
import homeassistant.util.temperature as temperature_util
|
||||
import homeassistant.util.volume as volume_util
|
||||
|
||||
from . import ATTR_LAST_RESET, DOMAIN
|
||||
|
||||
@ -53,6 +57,7 @@ DEVICE_CLASS_OR_UNIT_STATISTICS = {
|
||||
DEVICE_CLASS_POWER: {"mean", "min", "max"},
|
||||
DEVICE_CLASS_PRESSURE: {"mean", "min", "max"},
|
||||
DEVICE_CLASS_TEMPERATURE: {"mean", "min", "max"},
|
||||
DEVICE_CLASS_GAS: {"sum"},
|
||||
PERCENTAGE: {"mean", "min", "max"},
|
||||
}
|
||||
|
||||
@ -62,6 +67,7 @@ DEVICE_CLASS_UNITS = {
|
||||
DEVICE_CLASS_POWER: POWER_WATT,
|
||||
DEVICE_CLASS_PRESSURE: PRESSURE_PA,
|
||||
DEVICE_CLASS_TEMPERATURE: TEMP_CELSIUS,
|
||||
DEVICE_CLASS_GAS: VOLUME_CUBIC_METERS,
|
||||
}
|
||||
|
||||
UNIT_CONVERSIONS: dict[str, dict[str, Callable]] = {
|
||||
@ -92,6 +98,11 @@ UNIT_CONVERSIONS: dict[str, dict[str, Callable]] = {
|
||||
TEMP_FAHRENHEIT: temperature_util.fahrenheit_to_celsius,
|
||||
TEMP_KELVIN: temperature_util.kelvin_to_celsius,
|
||||
},
|
||||
# Convert volume to cubic meter
|
||||
DEVICE_CLASS_GAS: {
|
||||
VOLUME_CUBIC_METERS: lambda x: x,
|
||||
VOLUME_CUBIC_FEET: volume_util.cubic_feet_to_cubic_meter,
|
||||
},
|
||||
}
|
||||
|
||||
# Keep track of entities for which a warning about unsupported unit has been logged
|
||||
|
@ -5,6 +5,7 @@
|
||||
"is_battery_level": "Current {entity_name} battery level",
|
||||
"is_carbon_monoxide": "Current {entity_name} carbon monoxide concentration level",
|
||||
"is_carbon_dioxide": "Current {entity_name} carbon dioxide concentration level",
|
||||
"is_gas": "Current {entity_name} gas",
|
||||
"is_humidity": "Current {entity_name} humidity",
|
||||
"is_illuminance": "Current {entity_name} illuminance",
|
||||
"is_power": "Current {entity_name} power",
|
||||
@ -21,6 +22,7 @@
|
||||
"battery_level": "{entity_name} battery level changes",
|
||||
"carbon_monoxide": "{entity_name} carbon monoxide concentration changes",
|
||||
"carbon_dioxide": "{entity_name} carbon dioxide concentration changes",
|
||||
"gas": "{entity_name} gas changes",
|
||||
"humidity": "{entity_name} humidity changes",
|
||||
"illuminance": "{entity_name} illuminance changes",
|
||||
"power": "{entity_name} power changes",
|
||||
|
@ -18,10 +18,12 @@ from homeassistant.const import (
|
||||
ATTR_ICON,
|
||||
ATTR_NAME,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
DEVICE_CLASS_GAS,
|
||||
ENERGY_KILO_WATT_HOUR,
|
||||
PERCENTAGE,
|
||||
POWER_WATT,
|
||||
TEMP_CELSIUS,
|
||||
VOLUME_CUBIC_METERS,
|
||||
)
|
||||
from homeassistant.util import dt as dt_util
|
||||
|
||||
@ -38,7 +40,6 @@ DEFAULT_MIN_TEMP = 6.0
|
||||
|
||||
CURRENCY_EUR = "EUR"
|
||||
VOLUME_CM3 = "CM3"
|
||||
VOLUME_M3 = "M3"
|
||||
VOLUME_LHOUR = "L/H"
|
||||
VOLUME_LMIN = "L/MIN"
|
||||
|
||||
@ -125,7 +126,8 @@ SENSOR_ENTITIES = {
|
||||
ATTR_NAME: "Average Daily Gas Usage",
|
||||
ATTR_SECTION: "gas_usage",
|
||||
ATTR_MEASUREMENT: "day_average",
|
||||
ATTR_UNIT_OF_MEASUREMENT: VOLUME_M3,
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_GAS,
|
||||
ATTR_UNIT_OF_MEASUREMENT: VOLUME_CUBIC_METERS,
|
||||
ATTR_ICON: "mdi:gas-cylinder",
|
||||
ATTR_DEFAULT_ENABLED: False,
|
||||
},
|
||||
@ -133,7 +135,8 @@ SENSOR_ENTITIES = {
|
||||
ATTR_NAME: "Gas Usage Today",
|
||||
ATTR_SECTION: "gas_usage",
|
||||
ATTR_MEASUREMENT: "day_usage",
|
||||
ATTR_UNIT_OF_MEASUREMENT: VOLUME_M3,
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_GAS,
|
||||
ATTR_UNIT_OF_MEASUREMENT: VOLUME_CUBIC_METERS,
|
||||
ATTR_ICON: "mdi:gas-cylinder",
|
||||
},
|
||||
"gas_daily_cost": {
|
||||
@ -147,9 +150,10 @@ SENSOR_ENTITIES = {
|
||||
ATTR_NAME: "Gas Meter",
|
||||
ATTR_SECTION: "gas_usage",
|
||||
ATTR_MEASUREMENT: "meter",
|
||||
ATTR_UNIT_OF_MEASUREMENT: VOLUME_M3,
|
||||
ATTR_UNIT_OF_MEASUREMENT: VOLUME_CUBIC_METERS,
|
||||
ATTR_ICON: "mdi:gas-cylinder",
|
||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||
ATTR_DEVICE_CLASS: DEVICE_CLASS_GAS,
|
||||
ATTR_LAST_RESET: dt_util.utc_from_timestamp(0),
|
||||
ATTR_DEFAULT_ENABLED: False,
|
||||
},
|
||||
@ -321,7 +325,7 @@ SENSOR_ENTITIES = {
|
||||
ATTR_NAME: "Average Daily Water Usage",
|
||||
ATTR_SECTION: "water_usage",
|
||||
ATTR_MEASUREMENT: "day_average",
|
||||
ATTR_UNIT_OF_MEASUREMENT: VOLUME_M3,
|
||||
ATTR_UNIT_OF_MEASUREMENT: VOLUME_CUBIC_METERS,
|
||||
ATTR_ICON: "mdi:water",
|
||||
ATTR_DEFAULT_ENABLED: False,
|
||||
},
|
||||
@ -329,7 +333,7 @@ SENSOR_ENTITIES = {
|
||||
ATTR_NAME: "Water Usage Today",
|
||||
ATTR_SECTION: "water_usage",
|
||||
ATTR_MEASUREMENT: "day_usage",
|
||||
ATTR_UNIT_OF_MEASUREMENT: VOLUME_M3,
|
||||
ATTR_UNIT_OF_MEASUREMENT: VOLUME_CUBIC_METERS,
|
||||
ATTR_ICON: "mdi:water",
|
||||
ATTR_DEFAULT_ENABLED: False,
|
||||
},
|
||||
@ -337,7 +341,7 @@ SENSOR_ENTITIES = {
|
||||
ATTR_NAME: "Water Meter",
|
||||
ATTR_SECTION: "water_usage",
|
||||
ATTR_MEASUREMENT: "meter",
|
||||
ATTR_UNIT_OF_MEASUREMENT: VOLUME_M3,
|
||||
ATTR_UNIT_OF_MEASUREMENT: VOLUME_CUBIC_METERS,
|
||||
ATTR_ICON: "mdi:water",
|
||||
ATTR_DEFAULT_ENABLED: False,
|
||||
ATTR_STATE_CLASS: STATE_CLASS_MEASUREMENT,
|
||||
|
@ -247,6 +247,7 @@ DEVICE_CLASS_SIGNAL_STRENGTH: Final = "signal_strength"
|
||||
DEVICE_CLASS_TEMPERATURE: Final = "temperature"
|
||||
DEVICE_CLASS_TIMESTAMP: Final = "timestamp"
|
||||
DEVICE_CLASS_VOLTAGE: Final = "voltage"
|
||||
DEVICE_CLASS_GAS: Final = "gas"
|
||||
|
||||
# #### STATES ####
|
||||
STATE_ON: Final = "on"
|
||||
|
@ -6,6 +6,8 @@ from numbers import Number
|
||||
from homeassistant.const import (
|
||||
UNIT_NOT_RECOGNIZED_TEMPLATE,
|
||||
VOLUME,
|
||||
VOLUME_CUBIC_FEET,
|
||||
VOLUME_CUBIC_METERS,
|
||||
VOLUME_FLUID_OUNCE,
|
||||
VOLUME_GALLONS,
|
||||
VOLUME_LITERS,
|
||||
@ -17,19 +19,31 @@ VALID_UNITS: tuple[str, ...] = (
|
||||
VOLUME_MILLILITERS,
|
||||
VOLUME_GALLONS,
|
||||
VOLUME_FLUID_OUNCE,
|
||||
VOLUME_CUBIC_METERS,
|
||||
VOLUME_CUBIC_FEET,
|
||||
)
|
||||
|
||||
|
||||
def __liter_to_gallon(liter: float) -> float:
|
||||
def liter_to_gallon(liter: float) -> float:
|
||||
"""Convert a volume measurement in Liter to Gallon."""
|
||||
return liter * 0.2642
|
||||
|
||||
|
||||
def __gallon_to_liter(gallon: float) -> float:
|
||||
def gallon_to_liter(gallon: float) -> float:
|
||||
"""Convert a volume measurement in Gallon to Liter."""
|
||||
return gallon * 3.785
|
||||
|
||||
|
||||
def cubic_meter_to_cubic_feet(cubic_meter: float) -> float:
|
||||
"""Convert a volume measurement in cubic meter to cubic feet."""
|
||||
return cubic_meter * 35.3146667
|
||||
|
||||
|
||||
def cubic_feet_to_cubic_meter(cubic_feet: float) -> float:
|
||||
"""Convert a volume measurement in cubic feet to cubic meter."""
|
||||
return cubic_feet * 0.0283168466
|
||||
|
||||
|
||||
def convert(volume: float, from_unit: str, to_unit: str) -> float:
|
||||
"""Convert a temperature from one unit to another."""
|
||||
if from_unit not in VALID_UNITS:
|
||||
@ -45,8 +59,12 @@ def convert(volume: float, from_unit: str, to_unit: str) -> float:
|
||||
|
||||
result: float = volume
|
||||
if from_unit == VOLUME_LITERS and to_unit == VOLUME_GALLONS:
|
||||
result = __liter_to_gallon(volume)
|
||||
result = liter_to_gallon(volume)
|
||||
elif from_unit == VOLUME_GALLONS and to_unit == VOLUME_LITERS:
|
||||
result = __gallon_to_liter(volume)
|
||||
result = gallon_to_liter(volume)
|
||||
elif from_unit == VOLUME_CUBIC_METERS and to_unit == VOLUME_CUBIC_FEET:
|
||||
result = cubic_meter_to_cubic_feet(volume)
|
||||
elif from_unit == VOLUME_CUBIC_FEET and to_unit == VOLUME_CUBIC_METERS:
|
||||
result = cubic_feet_to_cubic_meter(volume)
|
||||
|
||||
return result
|
||||
|
@ -24,6 +24,7 @@ from homeassistant.const import (
|
||||
ATTR_ICON,
|
||||
ATTR_UNIT_OF_MEASUREMENT,
|
||||
DEVICE_CLASS_ENERGY,
|
||||
DEVICE_CLASS_GAS,
|
||||
DEVICE_CLASS_POWER,
|
||||
ENERGY_KILO_WATT_HOUR,
|
||||
STATE_UNKNOWN,
|
||||
@ -104,7 +105,7 @@ async def test_default_setup(hass, dsmr_connection_fixture):
|
||||
GAS_METER_READING: MBusObject(
|
||||
[
|
||||
{"value": datetime.datetime.fromtimestamp(1551642213)},
|
||||
{"value": Decimal(745.695), "unit": VOLUME_CUBIC_METERS},
|
||||
{"value": Decimal(745.695), "unit": "m3"},
|
||||
]
|
||||
),
|
||||
}
|
||||
@ -164,7 +165,7 @@ async def test_default_setup(hass, dsmr_connection_fixture):
|
||||
# check if gas consumption is parsed correctly
|
||||
gas_consumption = hass.states.get("sensor.gas_consumption")
|
||||
assert gas_consumption.state == "745.695"
|
||||
assert gas_consumption.attributes.get(ATTR_DEVICE_CLASS) is None
|
||||
assert gas_consumption.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_GAS
|
||||
assert gas_consumption.attributes.get(ATTR_ICON) == "mdi:fire"
|
||||
assert gas_consumption.attributes.get(ATTR_LAST_RESET) is not None
|
||||
assert gas_consumption.attributes.get(ATTR_STATE_CLASS) == STATE_CLASS_MEASUREMENT
|
||||
@ -228,7 +229,7 @@ async def test_v4_meter(hass, dsmr_connection_fixture):
|
||||
HOURLY_GAS_METER_READING: MBusObject(
|
||||
[
|
||||
{"value": datetime.datetime.fromtimestamp(1551642213)},
|
||||
{"value": Decimal(745.695), "unit": VOLUME_CUBIC_METERS},
|
||||
{"value": Decimal(745.695), "unit": "m3"},
|
||||
]
|
||||
),
|
||||
ELECTRICITY_ACTIVE_TARIFF: CosemObject([{"value": "0001", "unit": ""}]),
|
||||
@ -263,8 +264,8 @@ async def test_v4_meter(hass, dsmr_connection_fixture):
|
||||
# check if gas consumption is parsed correctly
|
||||
gas_consumption = hass.states.get("sensor.gas_consumption")
|
||||
assert gas_consumption.state == "745.695"
|
||||
assert gas_consumption.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_GAS
|
||||
assert gas_consumption.attributes.get("unit_of_measurement") == VOLUME_CUBIC_METERS
|
||||
assert gas_consumption.attributes.get(ATTR_DEVICE_CLASS) is None
|
||||
assert gas_consumption.attributes.get(ATTR_ICON) == "mdi:fire"
|
||||
assert gas_consumption.attributes.get(ATTR_LAST_RESET) is not None
|
||||
assert gas_consumption.attributes.get(ATTR_STATE_CLASS) == STATE_CLASS_MEASUREMENT
|
||||
@ -299,7 +300,7 @@ async def test_v5_meter(hass, dsmr_connection_fixture):
|
||||
HOURLY_GAS_METER_READING: MBusObject(
|
||||
[
|
||||
{"value": datetime.datetime.fromtimestamp(1551642213)},
|
||||
{"value": Decimal(745.695), "unit": VOLUME_CUBIC_METERS},
|
||||
{"value": Decimal(745.695), "unit": "m3"},
|
||||
]
|
||||
),
|
||||
ELECTRICITY_ACTIVE_TARIFF: CosemObject([{"value": "0001", "unit": ""}]),
|
||||
@ -334,7 +335,7 @@ async def test_v5_meter(hass, dsmr_connection_fixture):
|
||||
# check if gas consumption is parsed correctly
|
||||
gas_consumption = hass.states.get("sensor.gas_consumption")
|
||||
assert gas_consumption.state == "745.695"
|
||||
assert gas_consumption.attributes.get(ATTR_DEVICE_CLASS) is None
|
||||
assert gas_consumption.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_GAS
|
||||
assert gas_consumption.attributes.get(ATTR_ICON) == "mdi:fire"
|
||||
assert gas_consumption.attributes.get(ATTR_LAST_RESET) is not None
|
||||
assert gas_consumption.attributes.get(ATTR_STATE_CLASS) == STATE_CLASS_MEASUREMENT
|
||||
@ -370,7 +371,7 @@ async def test_luxembourg_meter(hass, dsmr_connection_fixture):
|
||||
HOURLY_GAS_METER_READING: MBusObject(
|
||||
[
|
||||
{"value": datetime.datetime.fromtimestamp(1551642213)},
|
||||
{"value": Decimal(745.695), "unit": VOLUME_CUBIC_METERS},
|
||||
{"value": Decimal(745.695), "unit": "m3"},
|
||||
]
|
||||
),
|
||||
LUXEMBOURG_ELECTRICITY_USED_TARIFF_GLOBAL: CosemObject(
|
||||
@ -415,7 +416,7 @@ async def test_luxembourg_meter(hass, dsmr_connection_fixture):
|
||||
# check if gas consumption is parsed correctly
|
||||
gas_consumption = hass.states.get("sensor.gas_consumption")
|
||||
assert gas_consumption.state == "745.695"
|
||||
assert gas_consumption.attributes.get(ATTR_DEVICE_CLASS) is None
|
||||
assert gas_consumption.attributes.get(ATTR_DEVICE_CLASS) == DEVICE_CLASS_GAS
|
||||
assert gas_consumption.attributes.get(ATTR_ICON) == "mdi:fire"
|
||||
assert gas_consumption.attributes.get(ATTR_LAST_RESET) is not None
|
||||
assert gas_consumption.attributes.get(ATTR_STATE_CLASS) == STATE_CLASS_MEASUREMENT
|
||||
@ -450,7 +451,7 @@ async def test_belgian_meter(hass, dsmr_connection_fixture):
|
||||
BELGIUM_HOURLY_GAS_METER_READING: MBusObject(
|
||||
[
|
||||
{"value": datetime.datetime.fromtimestamp(1551642213)},
|
||||
{"value": Decimal(745.695), "unit": VOLUME_CUBIC_METERS},
|
||||
{"value": Decimal(745.695), "unit": "m3"},
|
||||
]
|
||||
),
|
||||
ELECTRICITY_ACTIVE_TARIFF: CosemObject([{"value": "0001", "unit": ""}]),
|
||||
@ -485,7 +486,7 @@ async def test_belgian_meter(hass, dsmr_connection_fixture):
|
||||
# check if gas consumption is parsed correctly
|
||||
gas_consumption = hass.states.get("sensor.gas_consumption")
|
||||
assert gas_consumption.state == "745.695"
|
||||
assert gas_consumption.attributes.get(ATTR_DEVICE_CLASS) is None
|
||||
assert gas_consumption.attributes.get(ATTR_DEVICE_CLASS) is DEVICE_CLASS_GAS
|
||||
assert gas_consumption.attributes.get(ATTR_ICON) == "mdi:fire"
|
||||
assert gas_consumption.attributes.get(ATTR_LAST_RESET) is not None
|
||||
assert gas_consumption.attributes.get(ATTR_STATE_CLASS) == STATE_CLASS_MEASUREMENT
|
||||
|
@ -86,7 +86,7 @@ async def test_get_triggers(hass, device_reg, entity_reg, enable_custom_integrat
|
||||
if device_class != "none"
|
||||
]
|
||||
triggers = await async_get_device_automations(hass, "trigger", device_entry.id)
|
||||
assert len(triggers) == 13
|
||||
assert len(triggers) == 14
|
||||
assert triggers == expected_triggers
|
||||
|
||||
|
||||
|
@ -39,6 +39,11 @@ TEMPERATURE_SENSOR_ATTRIBUTES = {
|
||||
"state_class": "measurement",
|
||||
"unit_of_measurement": "°C",
|
||||
}
|
||||
GAS_SENSOR_ATTRIBUTES = {
|
||||
"device_class": "gas",
|
||||
"state_class": "measurement",
|
||||
"unit_of_measurement": "m³",
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
@ -154,11 +159,13 @@ def test_compile_hourly_statistics_unsupported(hass_recorder, caplog, attributes
|
||||
[
|
||||
("energy", "kWh", "kWh", 1),
|
||||
("energy", "Wh", "kWh", 1 / 1000),
|
||||
("monetary", "€", "€", 1),
|
||||
("monetary", "EUR", "EUR", 1),
|
||||
("monetary", "SEK", "SEK", 1),
|
||||
("gas", "m³", "m³", 1),
|
||||
("gas", "ft³", "m³", 0.0283168466),
|
||||
],
|
||||
)
|
||||
def test_compile_hourly_energy_statistics(
|
||||
def test_compile_hourly_sum_statistics(
|
||||
hass_recorder, caplog, device_class, unit, native_unit, factor
|
||||
):
|
||||
"""Test compiling hourly statistics."""
|
||||
@ -174,7 +181,7 @@ def test_compile_hourly_energy_statistics(
|
||||
}
|
||||
seq = [10, 15, 20, 10, 30, 40, 50, 60, 70]
|
||||
|
||||
four, eight, states = record_energy_states(
|
||||
four, eight, states = record_meter_states(
|
||||
hass, zero, "sensor.test1", attributes, seq
|
||||
)
|
||||
hist = history.get_significant_states(
|
||||
@ -254,14 +261,14 @@ def test_compile_hourly_energy_statistics_unsupported(hass_recorder, caplog):
|
||||
seq3 = [0, 0, 5, 10, 30, 50, 60, 80, 90]
|
||||
seq4 = [0, 0, 5, 10, 30, 50, 60, 80, 90]
|
||||
|
||||
four, eight, states = record_energy_states(
|
||||
four, eight, states = record_meter_states(
|
||||
hass, zero, "sensor.test1", sns1_attr, seq1
|
||||
)
|
||||
_, _, _states = record_energy_states(hass, zero, "sensor.test2", sns2_attr, seq2)
|
||||
_, _, _states = record_meter_states(hass, zero, "sensor.test2", sns2_attr, seq2)
|
||||
states = {**states, **_states}
|
||||
_, _, _states = record_energy_states(hass, zero, "sensor.test3", sns3_attr, seq3)
|
||||
_, _, _states = record_meter_states(hass, zero, "sensor.test3", sns3_attr, seq3)
|
||||
states = {**states, **_states}
|
||||
_, _, _states = record_energy_states(hass, zero, "sensor.test4", sns4_attr, seq4)
|
||||
_, _, _states = record_meter_states(hass, zero, "sensor.test4", sns4_attr, seq4)
|
||||
states = {**states, **_states}
|
||||
|
||||
hist = history.get_significant_states(
|
||||
@ -336,14 +343,14 @@ def test_compile_hourly_energy_statistics_multiple(hass_recorder, caplog):
|
||||
seq3 = [0, 0, 5, 10, 30, 50, 60, 80, 90]
|
||||
seq4 = [0, 0, 5, 10, 30, 50, 60, 80, 90]
|
||||
|
||||
four, eight, states = record_energy_states(
|
||||
four, eight, states = record_meter_states(
|
||||
hass, zero, "sensor.test1", sns1_attr, seq1
|
||||
)
|
||||
_, _, _states = record_energy_states(hass, zero, "sensor.test2", sns2_attr, seq2)
|
||||
_, _, _states = record_meter_states(hass, zero, "sensor.test2", sns2_attr, seq2)
|
||||
states = {**states, **_states}
|
||||
_, _, _states = record_energy_states(hass, zero, "sensor.test3", sns3_attr, seq3)
|
||||
_, _, _states = record_meter_states(hass, zero, "sensor.test3", sns3_attr, seq3)
|
||||
states = {**states, **_states}
|
||||
_, _, _states = record_energy_states(hass, zero, "sensor.test4", sns4_attr, seq4)
|
||||
_, _, _states = record_meter_states(hass, zero, "sensor.test4", sns4_attr, seq4)
|
||||
states = {**states, **_states}
|
||||
hist = history.get_significant_states(
|
||||
hass, zero - timedelta.resolution, eight + timedelta.resolution
|
||||
@ -632,6 +639,8 @@ def test_compile_hourly_statistics_fails(hass_recorder, caplog):
|
||||
("humidity", None, None, "mean"),
|
||||
("monetary", "USD", "USD", "sum"),
|
||||
("monetary", "None", "None", "sum"),
|
||||
("gas", "m³", "m³", "sum"),
|
||||
("gas", "ft³", "m³", "sum"),
|
||||
("pressure", "Pa", "Pa", "mean"),
|
||||
("pressure", "hPa", "Pa", "mean"),
|
||||
("pressure", "mbar", "Pa", "mean"),
|
||||
@ -697,7 +706,7 @@ def test_list_statistic_ids_unsupported(hass_recorder, caplog, _attributes):
|
||||
def record_states(hass, zero, entity_id, attributes):
|
||||
"""Record some test states.
|
||||
|
||||
We inject a bunch of state updates for temperature sensors.
|
||||
We inject a bunch of state updates for measurement sensors.
|
||||
"""
|
||||
attributes = dict(attributes)
|
||||
|
||||
@ -725,10 +734,10 @@ def record_states(hass, zero, entity_id, attributes):
|
||||
return four, states
|
||||
|
||||
|
||||
def record_energy_states(hass, zero, entity_id, _attributes, seq):
|
||||
def record_meter_states(hass, zero, entity_id, _attributes, seq):
|
||||
"""Record some test states.
|
||||
|
||||
We inject a bunch of state updates for energy sensors.
|
||||
We inject a bunch of state updates for meter sensors.
|
||||
"""
|
||||
|
||||
def set_state(entity_id, state, **kwargs):
|
||||
|
@ -9,6 +9,7 @@ from homeassistant.const import (
|
||||
PERCENTAGE,
|
||||
PRESSURE_HPA,
|
||||
SIGNAL_STRENGTH_DECIBELS,
|
||||
VOLUME_CUBIC_METERS,
|
||||
)
|
||||
|
||||
from tests.common import MockEntity
|
||||
@ -30,6 +31,7 @@ UNITS_OF_MEASUREMENT = {
|
||||
sensor.DEVICE_CLASS_ENERGY: "kWh", # energy (Wh/kWh)
|
||||
sensor.DEVICE_CLASS_POWER_FACTOR: PERCENTAGE, # power factor (no unit, min: -1.0, max: 1.0)
|
||||
sensor.DEVICE_CLASS_VOLTAGE: "V", # voltage (V)
|
||||
sensor.DEVICE_CLASS_GAS: VOLUME_CUBIC_METERS, # gas (m³)
|
||||
}
|
||||
|
||||
ENTITIES = {}
|
||||
|
@ -3,6 +3,8 @@
|
||||
import pytest
|
||||
|
||||
from homeassistant.const import (
|
||||
VOLUME_CUBIC_FEET,
|
||||
VOLUME_CUBIC_METERS,
|
||||
VOLUME_FLUID_OUNCE,
|
||||
VOLUME_GALLONS,
|
||||
VOLUME_LITERS,
|
||||
@ -47,3 +49,21 @@ def test_convert_from_gallons():
|
||||
"""Test conversion from gallons to other units."""
|
||||
gallons = 5
|
||||
assert volume_util.convert(gallons, VOLUME_GALLONS, VOLUME_LITERS) == 18.925
|
||||
|
||||
|
||||
def test_convert_from_cubic_meters():
|
||||
"""Test conversion from cubic meter to other units."""
|
||||
cubic_meters = 5
|
||||
assert (
|
||||
volume_util.convert(cubic_meters, VOLUME_CUBIC_METERS, VOLUME_CUBIC_FEET)
|
||||
== 176.5733335
|
||||
)
|
||||
|
||||
|
||||
def test_convert_from_cubic_feet():
|
||||
"""Test conversion from cubic feet to cubic meters to other units."""
|
||||
cubic_feets = 500
|
||||
assert (
|
||||
volume_util.convert(cubic_feets, VOLUME_CUBIC_FEET, VOLUME_CUBIC_METERS)
|
||||
== 14.1584233
|
||||
)
|
||||
|
Loading…
x
Reference in New Issue
Block a user