mirror of
https://github.com/home-assistant/core.git
synced 2025-07-26 06:37:52 +00:00
Add Sensor for Refoss Integration (#116965)
Co-authored-by: Robert Resch <robert@resch.dev>
This commit is contained in:
parent
1eb8b5a27c
commit
3224224bf8
@ -1110,6 +1110,7 @@ omit =
|
|||||||
homeassistant/components/refoss/bridge.py
|
homeassistant/components/refoss/bridge.py
|
||||||
homeassistant/components/refoss/coordinator.py
|
homeassistant/components/refoss/coordinator.py
|
||||||
homeassistant/components/refoss/entity.py
|
homeassistant/components/refoss/entity.py
|
||||||
|
homeassistant/components/refoss/sensor.py
|
||||||
homeassistant/components/refoss/switch.py
|
homeassistant/components/refoss/switch.py
|
||||||
homeassistant/components/refoss/util.py
|
homeassistant/components/refoss/util.py
|
||||||
homeassistant/components/rejseplanen/sensor.py
|
homeassistant/components/rejseplanen/sensor.py
|
||||||
|
@ -15,6 +15,7 @@ from .const import COORDINATORS, DATA_DISCOVERY_SERVICE, DISCOVERY_SCAN_INTERVAL
|
|||||||
from .util import refoss_discovery_server
|
from .util import refoss_discovery_server
|
||||||
|
|
||||||
PLATFORMS: Final = [
|
PLATFORMS: Final = [
|
||||||
|
Platform.SENSOR,
|
||||||
Platform.SWITCH,
|
Platform.SWITCH,
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -19,3 +19,14 @@ DOMAIN = "refoss"
|
|||||||
COORDINATOR = "coordinator"
|
COORDINATOR = "coordinator"
|
||||||
|
|
||||||
MAX_ERRORS = 2
|
MAX_ERRORS = 2
|
||||||
|
|
||||||
|
CHANNEL_DISPLAY_NAME: dict[str, dict[int, str]] = {
|
||||||
|
"em06": {
|
||||||
|
1: "A1",
|
||||||
|
2: "B1",
|
||||||
|
3: "C1",
|
||||||
|
4: "A2",
|
||||||
|
5: "B2",
|
||||||
|
6: "C2",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -18,11 +18,6 @@ class RefossEntity(CoordinatorEntity[RefossDataUpdateCoordinator]):
|
|||||||
|
|
||||||
mac = coordinator.device.mac
|
mac = coordinator.device.mac
|
||||||
self.channel_id = channel
|
self.channel_id = channel
|
||||||
if channel == 0:
|
|
||||||
self._attr_name = None
|
|
||||||
else:
|
|
||||||
self._attr_name = str(channel)
|
|
||||||
|
|
||||||
self._attr_unique_id = f"{mac}_{channel}"
|
self._attr_unique_id = f"{mac}_{channel}"
|
||||||
self._attr_device_info = DeviceInfo(
|
self._attr_device_info = DeviceInfo(
|
||||||
connections={(CONNECTION_NETWORK_MAC, mac)},
|
connections={(CONNECTION_NETWORK_MAC, mac)},
|
||||||
|
174
homeassistant/components/refoss/sensor.py
Normal file
174
homeassistant/components/refoss/sensor.py
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
"""Support for refoss sensors."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from collections.abc import Callable
|
||||||
|
from dataclasses import dataclass
|
||||||
|
|
||||||
|
from refoss_ha.controller.electricity import ElectricityXMix
|
||||||
|
|
||||||
|
from homeassistant.components.sensor import (
|
||||||
|
SensorDeviceClass,
|
||||||
|
SensorEntity,
|
||||||
|
SensorEntityDescription,
|
||||||
|
SensorStateClass,
|
||||||
|
)
|
||||||
|
from homeassistant.config_entries import ConfigEntry
|
||||||
|
from homeassistant.const import (
|
||||||
|
UnitOfElectricCurrent,
|
||||||
|
UnitOfElectricPotential,
|
||||||
|
UnitOfEnergy,
|
||||||
|
UnitOfPower,
|
||||||
|
)
|
||||||
|
from homeassistant.core import HomeAssistant, callback
|
||||||
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
from homeassistant.helpers.typing import StateType
|
||||||
|
|
||||||
|
from .bridge import RefossDataUpdateCoordinator
|
||||||
|
from .const import (
|
||||||
|
CHANNEL_DISPLAY_NAME,
|
||||||
|
COORDINATORS,
|
||||||
|
DISPATCH_DEVICE_DISCOVERED,
|
||||||
|
DOMAIN,
|
||||||
|
)
|
||||||
|
from .entity import RefossEntity
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass(frozen=True)
|
||||||
|
class RefossSensorEntityDescription(SensorEntityDescription):
|
||||||
|
"""Describes Refoss sensor entity."""
|
||||||
|
|
||||||
|
subkey: str | None = None
|
||||||
|
fn: Callable[[float], float] | None = None
|
||||||
|
|
||||||
|
|
||||||
|
SENSORS: dict[str, tuple[RefossSensorEntityDescription, ...]] = {
|
||||||
|
"em06": (
|
||||||
|
RefossSensorEntityDescription(
|
||||||
|
key="power",
|
||||||
|
translation_key="power",
|
||||||
|
device_class=SensorDeviceClass.POWER,
|
||||||
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
|
native_unit_of_measurement=UnitOfPower.WATT,
|
||||||
|
suggested_display_precision=2,
|
||||||
|
subkey="power",
|
||||||
|
fn=lambda x: x / 1000.0,
|
||||||
|
),
|
||||||
|
RefossSensorEntityDescription(
|
||||||
|
key="voltage",
|
||||||
|
translation_key="voltage",
|
||||||
|
device_class=SensorDeviceClass.VOLTAGE,
|
||||||
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
|
native_unit_of_measurement=UnitOfElectricPotential.MILLIVOLT,
|
||||||
|
suggested_display_precision=2,
|
||||||
|
suggested_unit_of_measurement=UnitOfElectricPotential.VOLT,
|
||||||
|
subkey="voltage",
|
||||||
|
),
|
||||||
|
RefossSensorEntityDescription(
|
||||||
|
key="current",
|
||||||
|
translation_key="current",
|
||||||
|
device_class=SensorDeviceClass.CURRENT,
|
||||||
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
|
native_unit_of_measurement=UnitOfElectricCurrent.MILLIAMPERE,
|
||||||
|
suggested_display_precision=2,
|
||||||
|
suggested_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
|
||||||
|
subkey="current",
|
||||||
|
),
|
||||||
|
RefossSensorEntityDescription(
|
||||||
|
key="factor",
|
||||||
|
translation_key="power_factor",
|
||||||
|
device_class=SensorDeviceClass.POWER_FACTOR,
|
||||||
|
state_class=SensorStateClass.MEASUREMENT,
|
||||||
|
suggested_display_precision=2,
|
||||||
|
subkey="factor",
|
||||||
|
),
|
||||||
|
RefossSensorEntityDescription(
|
||||||
|
key="energy",
|
||||||
|
translation_key="this_month_energy",
|
||||||
|
device_class=SensorDeviceClass.ENERGY,
|
||||||
|
state_class=SensorStateClass.TOTAL,
|
||||||
|
native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
|
||||||
|
suggested_display_precision=2,
|
||||||
|
subkey="mConsume",
|
||||||
|
fn=lambda x: x if x > 0 else 0,
|
||||||
|
),
|
||||||
|
RefossSensorEntityDescription(
|
||||||
|
key="energy_returned",
|
||||||
|
translation_key="this_month_energy_returned",
|
||||||
|
device_class=SensorDeviceClass.ENERGY,
|
||||||
|
state_class=SensorStateClass.TOTAL,
|
||||||
|
native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
|
||||||
|
suggested_display_precision=2,
|
||||||
|
subkey="mConsume",
|
||||||
|
fn=lambda x: abs(x) if x < 0 else 0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
async def async_setup_entry(
|
||||||
|
hass: HomeAssistant,
|
||||||
|
config_entry: ConfigEntry,
|
||||||
|
async_add_entities: AddEntitiesCallback,
|
||||||
|
) -> None:
|
||||||
|
"""Set up the Refoss device from a config entry."""
|
||||||
|
|
||||||
|
@callback
|
||||||
|
def init_device(coordinator):
|
||||||
|
"""Register the device."""
|
||||||
|
device = coordinator.device
|
||||||
|
|
||||||
|
if not isinstance(device, ElectricityXMix):
|
||||||
|
return
|
||||||
|
descriptions = SENSORS.get(device.device_type)
|
||||||
|
new_entities = []
|
||||||
|
for channel in device.channels:
|
||||||
|
for description in descriptions:
|
||||||
|
entity = RefossSensor(
|
||||||
|
coordinator=coordinator,
|
||||||
|
channel=channel,
|
||||||
|
description=description,
|
||||||
|
)
|
||||||
|
new_entities.append(entity)
|
||||||
|
|
||||||
|
async_add_entities(new_entities)
|
||||||
|
|
||||||
|
for coordinator in hass.data[DOMAIN][COORDINATORS]:
|
||||||
|
init_device(coordinator)
|
||||||
|
|
||||||
|
config_entry.async_on_unload(
|
||||||
|
async_dispatcher_connect(hass, DISPATCH_DEVICE_DISCOVERED, init_device)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class RefossSensor(RefossEntity, SensorEntity):
|
||||||
|
"""Refoss Sensor Device."""
|
||||||
|
|
||||||
|
entity_description: RefossSensorEntityDescription
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
coordinator: RefossDataUpdateCoordinator,
|
||||||
|
channel: int,
|
||||||
|
description: RefossSensorEntityDescription,
|
||||||
|
) -> None:
|
||||||
|
"""Init Refoss sensor."""
|
||||||
|
super().__init__(coordinator, channel)
|
||||||
|
self.entity_description = description
|
||||||
|
self._attr_unique_id = f"{super().unique_id}{description.key}"
|
||||||
|
device_type = coordinator.device.device_type
|
||||||
|
channel_name = CHANNEL_DISPLAY_NAME[device_type][channel]
|
||||||
|
self._attr_translation_placeholders = {"channel_name": channel_name}
|
||||||
|
|
||||||
|
@property
|
||||||
|
def native_value(self) -> StateType:
|
||||||
|
"""Return the native value."""
|
||||||
|
value = self.coordinator.device.get_value(
|
||||||
|
self.channel_id, self.entity_description.subkey
|
||||||
|
)
|
||||||
|
if value is None:
|
||||||
|
return None
|
||||||
|
if self.entity_description.fn is not None:
|
||||||
|
return self.entity_description.fn(value)
|
||||||
|
return value
|
@ -9,5 +9,27 @@
|
|||||||
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
|
"single_instance_allowed": "[%key:common::config_flow::abort::single_instance_allowed%]",
|
||||||
"no_devices_found": "[%key:common::config_flow::abort::no_devices_found%]"
|
"no_devices_found": "[%key:common::config_flow::abort::no_devices_found%]"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"entity": {
|
||||||
|
"sensor": {
|
||||||
|
"power": {
|
||||||
|
"name": "{channel_name} power"
|
||||||
|
},
|
||||||
|
"voltage": {
|
||||||
|
"name": "{channel_name} voltage"
|
||||||
|
},
|
||||||
|
"current": {
|
||||||
|
"name": "{channel_name} current"
|
||||||
|
},
|
||||||
|
"power_factor": {
|
||||||
|
"name": "{channel_name} power factor"
|
||||||
|
},
|
||||||
|
"this_month_energy": {
|
||||||
|
"name": "{channel_name} this month energy"
|
||||||
|
},
|
||||||
|
"this_month_energy_returned": {
|
||||||
|
"name": "{channel_name} this month energy returned"
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@ from homeassistant.core import HomeAssistant, callback
|
|||||||
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
from homeassistant.helpers.dispatcher import async_dispatcher_connect
|
||||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||||
|
|
||||||
|
from .bridge import RefossDataUpdateCoordinator
|
||||||
from .const import COORDINATORS, DISPATCH_DEVICE_DISCOVERED, DOMAIN
|
from .const import COORDINATORS, DISPATCH_DEVICE_DISCOVERED, DOMAIN
|
||||||
from .entity import RefossEntity
|
from .entity import RefossEntity
|
||||||
|
|
||||||
@ -48,6 +49,15 @@ async def async_setup_entry(
|
|||||||
class RefossSwitch(RefossEntity, SwitchEntity):
|
class RefossSwitch(RefossEntity, SwitchEntity):
|
||||||
"""Refoss Switch Device."""
|
"""Refoss Switch Device."""
|
||||||
|
|
||||||
|
def __init__(
|
||||||
|
self,
|
||||||
|
coordinator: RefossDataUpdateCoordinator,
|
||||||
|
channel: int,
|
||||||
|
) -> None:
|
||||||
|
"""Init Refoss switch."""
|
||||||
|
super().__init__(coordinator, channel)
|
||||||
|
self._attr_name = str(channel)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def is_on(self) -> bool | None:
|
def is_on(self) -> bool | None:
|
||||||
"""Return true if switch is on."""
|
"""Return true if switch is on."""
|
||||||
|
Loading…
x
Reference in New Issue
Block a user