1
0
mirror of https://github.com/home-assistant/core.git synced 2026-04-17 15:44:52 +01:00

Add binary sensor platform and tests to NRGkick integration (#164629)

Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
Andreas Jakl
2026-03-03 13:55:10 +01:00
committed by GitHub
parent 2c75e3289a
commit 9cb6e02c5f
10 changed files with 252 additions and 69 deletions

View File

@@ -11,6 +11,7 @@ from homeassistant.helpers.aiohttp_client import async_get_clientsession
from .coordinator import NRGkickConfigEntry, NRGkickDataUpdateCoordinator
PLATFORMS: list[Platform] = [
Platform.BINARY_SENSOR,
Platform.NUMBER,
Platform.SENSOR,
Platform.SWITCH,

View File

@@ -0,0 +1,76 @@
"""Binary sensor platform for NRGkick."""
from __future__ import annotations
from collections.abc import Callable
from dataclasses import dataclass
from homeassistant.components.binary_sensor import (
BinarySensorEntity,
BinarySensorEntityDescription,
)
from homeassistant.core import HomeAssistant
from homeassistant.helpers.entity_platform import AddConfigEntryEntitiesCallback
from .coordinator import NRGkickConfigEntry, NRGkickData, NRGkickDataUpdateCoordinator
from .entity import NRGkickEntity, get_nested_dict_value
PARALLEL_UPDATES = 0
@dataclass(frozen=True, kw_only=True)
class NRGkickBinarySensorEntityDescription(BinarySensorEntityDescription):
"""Class describing NRGkick binary sensor entities."""
is_on_fn: Callable[[NRGkickData], bool | None]
BINARY_SENSORS: tuple[NRGkickBinarySensorEntityDescription, ...] = (
NRGkickBinarySensorEntityDescription(
key="charge_permitted",
translation_key="charge_permitted",
is_on_fn=lambda data: (
bool(value)
if (
value := get_nested_dict_value(
data.values, "general", "charge_permitted"
)
)
is not None
else None
),
),
)
async def async_setup_entry(
_hass: HomeAssistant,
entry: NRGkickConfigEntry,
async_add_entities: AddConfigEntryEntitiesCallback,
) -> None:
"""Set up NRGkick binary sensors based on a config entry."""
coordinator = entry.runtime_data
async_add_entities(
NRGkickBinarySensor(coordinator, description) for description in BINARY_SENSORS
)
class NRGkickBinarySensor(NRGkickEntity, BinarySensorEntity):
"""Representation of a NRGkick binary sensor."""
entity_description: NRGkickBinarySensorEntityDescription
def __init__(
self,
coordinator: NRGkickDataUpdateCoordinator,
entity_description: NRGkickBinarySensorEntityDescription,
) -> None:
"""Initialize the binary sensor."""
super().__init__(coordinator, entity_description.key)
self.entity_description = entity_description
@property
def is_on(self) -> bool | None:
"""Return the state of the binary sensor."""
return self.entity_description.is_on_fn(self.coordinator.data)

View File

@@ -14,6 +14,17 @@ from .const import DOMAIN
from .coordinator import NRGkickDataUpdateCoordinator
def get_nested_dict_value(data: Any, *keys: str) -> Any:
"""Safely get a nested value from dict-like API responses."""
current: Any = data
for key in keys:
try:
current = current.get(key)
except AttributeError:
return None
return current
class NRGkickEntity(CoordinatorEntity[NRGkickDataUpdateCoordinator]):
"""Base class for NRGkick entities with common device info setup."""

View File

@@ -1,5 +1,10 @@
{
"entity": {
"binary_sensor": {
"charge_permitted": {
"default": "mdi:ev-station"
}
},
"number": {
"current_set": {
"default": "mdi:current-ac"

View File

@@ -45,22 +45,11 @@ from .const import (
WARNING_CODE_MAP,
)
from .coordinator import NRGkickConfigEntry, NRGkickData, NRGkickDataUpdateCoordinator
from .entity import NRGkickEntity
from .entity import NRGkickEntity, get_nested_dict_value
PARALLEL_UPDATES = 0
def _get_nested_dict_value(data: Any, *keys: str) -> Any:
"""Safely get a nested value from dict-like API responses."""
current: Any = data
for key in keys:
try:
current = current.get(key)
except AttributeError:
return None
return current
@dataclass(frozen=True, kw_only=True)
class NRGkickSensorEntityDescription(SensorEntityDescription):
"""Class describing NRGkick sensor entities."""
@@ -159,7 +148,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
suggested_display_precision=2,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.info, "general", "rated_current"
),
),
@@ -167,7 +156,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
NRGkickSensorEntityDescription(
key="connector_phase_count",
translation_key="connector_phase_count",
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.info, "connector", "phase_count"
),
),
@@ -178,7 +167,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
suggested_display_precision=2,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.info, "connector", "max_current"
),
),
@@ -189,7 +178,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
options=_enum_options_from_mapping(CONNECTOR_TYPE_MAP),
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda data: _map_code_to_translation_key(
cast(StateType, _get_nested_dict_value(data.info, "connector", "type")),
cast(StateType, get_nested_dict_value(data.info, "connector", "type")),
CONNECTOR_TYPE_MAP,
),
),
@@ -198,7 +187,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
translation_key="connector_serial",
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda data: _get_nested_dict_value(data.info, "connector", "serial"),
value_fn=lambda data: get_nested_dict_value(data.info, "connector", "serial"),
),
# INFO - Grid
NRGkickSensorEntityDescription(
@@ -208,7 +197,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
suggested_display_precision=2,
value_fn=lambda data: _get_nested_dict_value(data.info, "grid", "voltage"),
value_fn=lambda data: get_nested_dict_value(data.info, "grid", "voltage"),
),
NRGkickSensorEntityDescription(
key="grid_frequency",
@@ -217,7 +206,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfFrequency.HERTZ,
suggested_display_precision=2,
value_fn=lambda data: _get_nested_dict_value(data.info, "grid", "frequency"),
value_fn=lambda data: get_nested_dict_value(data.info, "grid", "frequency"),
),
# INFO - Network
NRGkickSensorEntityDescription(
@@ -225,7 +214,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
translation_key="network_ssid",
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda data: _get_nested_dict_value(data.info, "network", "ssid"),
value_fn=lambda data: get_nested_dict_value(data.info, "network", "ssid"),
),
NRGkickSensorEntityDescription(
key="network_rssi",
@@ -234,7 +223,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=SIGNAL_STRENGTH_DECIBELS_MILLIWATT,
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda data: _get_nested_dict_value(data.info, "network", "rssi"),
value_fn=lambda data: get_nested_dict_value(data.info, "network", "rssi"),
),
# INFO - Cellular (optional, only if cellular module is available)
NRGkickSensorEntityDescription(
@@ -246,7 +235,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
entity_registry_enabled_default=False,
requires_sim_module=True,
value_fn=lambda data: _map_code_to_translation_key(
cast(StateType, _get_nested_dict_value(data.info, "cellular", "mode")),
cast(StateType, get_nested_dict_value(data.info, "cellular", "mode")),
CELLULAR_MODE_MAP,
),
),
@@ -259,7 +248,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
requires_sim_module=True,
value_fn=lambda data: _get_nested_dict_value(data.info, "cellular", "rssi"),
value_fn=lambda data: get_nested_dict_value(data.info, "cellular", "rssi"),
),
NRGkickSensorEntityDescription(
key="cellular_operator",
@@ -267,7 +256,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
requires_sim_module=True,
value_fn=lambda data: _get_nested_dict_value(data.info, "cellular", "operator"),
value_fn=lambda data: get_nested_dict_value(data.info, "cellular", "operator"),
),
# VALUES - Energy
NRGkickSensorEntityDescription(
@@ -278,7 +267,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
suggested_display_precision=3,
suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "energy", "total_charged_energy"
),
),
@@ -290,7 +279,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
native_unit_of_measurement=UnitOfEnergy.WATT_HOUR,
suggested_display_precision=3,
suggested_unit_of_measurement=UnitOfEnergy.KILO_WATT_HOUR,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "energy", "charged_energy"
),
),
@@ -302,7 +291,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfElectricPotential.VOLT,
suggested_display_precision=2,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "charging_voltage"
),
),
@@ -313,7 +302,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
suggested_display_precision=2,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "charging_current"
),
),
@@ -326,7 +315,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
suggested_display_precision=2,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "grid_frequency"
),
),
@@ -339,7 +328,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
suggested_display_precision=2,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "peak_power"
),
),
@@ -350,7 +339,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfPower.WATT,
suggested_display_precision=2,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "total_active_power"
),
),
@@ -362,7 +351,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
native_unit_of_measurement=UnitOfReactivePower.VOLT_AMPERE_REACTIVE,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "total_reactive_power"
),
),
@@ -374,7 +363,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
native_unit_of_measurement=UnitOfApparentPower.VOLT_AMPERE,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "total_apparent_power"
),
),
@@ -386,7 +375,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
native_unit_of_measurement=PERCENTAGE,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "total_power_factor"
),
),
@@ -400,7 +389,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
suggested_display_precision=2,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "l1", "voltage"
),
),
@@ -411,7 +400,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
suggested_display_precision=2,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "l1", "current"
),
),
@@ -422,7 +411,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfPower.WATT,
suggested_display_precision=2,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "l1", "active_power"
),
),
@@ -434,7 +423,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
native_unit_of_measurement=UnitOfReactivePower.VOLT_AMPERE_REACTIVE,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "l1", "reactive_power"
),
),
@@ -446,7 +435,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
native_unit_of_measurement=UnitOfApparentPower.VOLT_AMPERE,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "l1", "apparent_power"
),
),
@@ -458,7 +447,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
native_unit_of_measurement=PERCENTAGE,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "l1", "power_factor"
),
),
@@ -472,7 +461,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
suggested_display_precision=2,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "l2", "voltage"
),
),
@@ -483,7 +472,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
suggested_display_precision=2,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "l2", "current"
),
),
@@ -494,7 +483,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfPower.WATT,
suggested_display_precision=2,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "l2", "active_power"
),
),
@@ -506,7 +495,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
native_unit_of_measurement=UnitOfReactivePower.VOLT_AMPERE_REACTIVE,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "l2", "reactive_power"
),
),
@@ -518,7 +507,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
native_unit_of_measurement=UnitOfApparentPower.VOLT_AMPERE,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "l2", "apparent_power"
),
),
@@ -530,7 +519,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
native_unit_of_measurement=PERCENTAGE,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "l2", "power_factor"
),
),
@@ -544,7 +533,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
suggested_display_precision=2,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "l3", "voltage"
),
),
@@ -555,7 +544,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfElectricCurrent.AMPERE,
suggested_display_precision=2,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "l3", "current"
),
),
@@ -566,7 +555,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfPower.WATT,
suggested_display_precision=2,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "l3", "active_power"
),
),
@@ -578,7 +567,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
native_unit_of_measurement=UnitOfReactivePower.VOLT_AMPERE_REACTIVE,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "l3", "reactive_power"
),
),
@@ -590,7 +579,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
native_unit_of_measurement=UnitOfApparentPower.VOLT_AMPERE,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "l3", "apparent_power"
),
),
@@ -602,7 +591,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
native_unit_of_measurement=PERCENTAGE,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "l3", "power_factor"
),
),
@@ -616,7 +605,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
suggested_display_precision=2,
entity_category=EntityCategory.DIAGNOSTIC,
entity_registry_enabled_default=False,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "powerflow", "n", "current"
),
),
@@ -626,7 +615,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
translation_key="charging_rate",
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfSpeed.KILOMETERS_PER_HOUR,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "general", "charging_rate"
),
),
@@ -638,12 +627,12 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
_seconds_to_stable_timestamp(
cast(
StateType,
_get_nested_dict_value(
get_nested_dict_value(
data.values, "general", "vehicle_connect_time"
),
)
)
if _get_nested_dict_value(data.values, "general", "status")
if get_nested_dict_value(data.values, "general", "status")
!= ChargingStatus.STANDBY
else None
),
@@ -655,7 +644,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTime.SECONDS,
suggested_unit_of_measurement=UnitOfTime.MINUTES,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "general", "vehicle_charging_time"
),
),
@@ -665,7 +654,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
device_class=SensorDeviceClass.ENUM,
options=_enum_options_from_mapping(STATUS_MAP),
value_fn=lambda data: _map_code_to_translation_key(
cast(StateType, _get_nested_dict_value(data.values, "general", "status")),
cast(StateType, get_nested_dict_value(data.values, "general", "status")),
STATUS_MAP,
),
),
@@ -675,7 +664,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
entity_category=EntityCategory.DIAGNOSTIC,
state_class=SensorStateClass.TOTAL_INCREASING,
suggested_display_precision=0,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "general", "charge_count"
),
),
@@ -687,7 +676,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda data: _map_code_to_translation_key(
cast(
StateType, _get_nested_dict_value(data.values, "general", "rcd_trigger")
StateType, get_nested_dict_value(data.values, "general", "rcd_trigger")
),
RCD_TRIGGER_MAP,
),
@@ -700,8 +689,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda data: _map_code_to_translation_key(
cast(
StateType,
_get_nested_dict_value(data.values, "general", "warning_code"),
StateType, get_nested_dict_value(data.values, "general", "warning_code")
),
WARNING_CODE_MAP,
),
@@ -714,7 +702,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda data: _map_code_to_translation_key(
cast(
StateType, _get_nested_dict_value(data.values, "general", "error_code")
StateType, get_nested_dict_value(data.values, "general", "error_code")
),
ERROR_CODE_MAP,
),
@@ -727,7 +715,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "temperatures", "housing"
),
),
@@ -738,7 +726,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "temperatures", "connector_l1"
),
),
@@ -749,7 +737,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "temperatures", "connector_l2"
),
),
@@ -760,7 +748,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "temperatures", "connector_l3"
),
),
@@ -771,7 +759,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "temperatures", "domestic_plug_1"
),
),
@@ -782,7 +770,7 @@ SENSORS: tuple[NRGkickSensorEntityDescription, ...] = (
state_class=SensorStateClass.MEASUREMENT,
native_unit_of_measurement=UnitOfTemperature.CELSIUS,
entity_category=EntityCategory.DIAGNOSTIC,
value_fn=lambda data: _get_nested_dict_value(
value_fn=lambda data: get_nested_dict_value(
data.values, "temperatures", "domestic_plug_2"
),
),

View File

@@ -78,6 +78,11 @@
}
},
"entity": {
"binary_sensor": {
"charge_permitted": {
"name": "Charge permitted"
}
},
"number": {
"current_set": {
"name": "Charging current"

View File

@@ -41,6 +41,7 @@
"charging_rate": 11.0,
"vehicle_connect_time": 100,
"vehicle_charging_time": 50,
"charge_permitted": 1,
"charge_count": 5,
"rcd_trigger": 0,
"warning_code": 0,

View File

@@ -0,0 +1,50 @@
# serializer version: 1
# name: test_binary_sensor_entities[binary_sensor.nrgkick_test_charge_permitted-entry]
EntityRegistryEntrySnapshot({
'aliases': set({
}),
'area_id': None,
'capabilities': None,
'config_entry_id': <ANY>,
'config_subentry_id': <ANY>,
'device_class': None,
'device_id': <ANY>,
'disabled_by': None,
'domain': 'binary_sensor',
'entity_category': None,
'entity_id': 'binary_sensor.nrgkick_test_charge_permitted',
'has_entity_name': True,
'hidden_by': None,
'icon': None,
'id': <ANY>,
'labels': set({
}),
'name': None,
'object_id_base': 'Charge permitted',
'options': dict({
}),
'original_device_class': None,
'original_icon': None,
'original_name': 'Charge permitted',
'platform': 'nrgkick',
'previous_unique_id': None,
'suggested_object_id': None,
'supported_features': 0,
'translation_key': 'charge_permitted',
'unique_id': 'TEST123456_charge_permitted',
'unit_of_measurement': None,
})
# ---
# name: test_binary_sensor_entities[binary_sensor.nrgkick_test_charge_permitted-state]
StateSnapshot({
'attributes': ReadOnlyDict({
'friendly_name': 'NRGkick Test Charge permitted',
}),
'context': <ANY>,
'entity_id': 'binary_sensor.nrgkick_test_charge_permitted',
'last_changed': <ANY>,
'last_reported': <ANY>,
'last_updated': <ANY>,
'state': 'on',
})
# ---

View File

@@ -53,6 +53,7 @@
}),
'general': dict({
'charge_count': 5,
'charge_permitted': 1,
'charging_rate': 11.0,
'error_code': 0,
'rcd_trigger': 0,

View File

@@ -0,0 +1,45 @@
"""Tests for the NRGkick binary sensor platform."""
from __future__ import annotations
from unittest.mock import AsyncMock
import pytest
from syrupy.assertion import SnapshotAssertion
from homeassistant.const import STATE_OFF, Platform
from homeassistant.core import HomeAssistant
from homeassistant.helpers import entity_registry as er
from . import setup_integration
from tests.common import MockConfigEntry, snapshot_platform
pytestmark = pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_binary_sensor_entities(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_nrgkick_api: AsyncMock,
entity_registry: er.EntityRegistry,
snapshot: SnapshotAssertion,
) -> None:
"""Test binary sensor entities."""
await setup_integration(hass, mock_config_entry, platforms=[Platform.BINARY_SENSOR])
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
async def test_charge_permitted_off(
hass: HomeAssistant,
mock_config_entry: MockConfigEntry,
mock_nrgkick_api: AsyncMock,
) -> None:
"""Test charge permitted binary sensor when charging is not permitted."""
mock_nrgkick_api.get_values.return_value["general"]["charge_permitted"] = 0
await setup_integration(hass, mock_config_entry, platforms=[Platform.BINARY_SENSOR])
assert (state := hass.states.get("binary_sensor.nrgkick_test_charge_permitted"))
assert state.state == STATE_OFF