Add support for V2C Trydan 2.1.7 (#117147)
* Support for firmware 2.1.7 * add device ID as unique_id * add device ID as unique_id * add test device id as unique_id * backward compatibility * move outside try * Sensor return type Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * not needed * make slave error enum state * fix enum * Update homeassistant/components/v2c/sensor.py Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * Update homeassistant/components/v2c/strings.json Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * Update homeassistant/components/v2c/strings.json Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com> * simplify tests * fix misspellings from upstream library * add sensor tests * just enough coverage for enum sensor * Refactor V2C tests (#117264) * Refactor V2C tests * fix rebase issues * ruff * review * fix https://github.com/home-assistant/core/issues/117296 --------- Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>pull/118497/head^2
parent
43c69c71c2
commit
822273a6a3
|
@ -1528,7 +1528,6 @@ omit =
|
|||
homeassistant/components/v2c/coordinator.py
|
||||
homeassistant/components/v2c/entity.py
|
||||
homeassistant/components/v2c/number.py
|
||||
homeassistant/components/v2c/sensor.py
|
||||
homeassistant/components/v2c/switch.py
|
||||
homeassistant/components/vallox/__init__.py
|
||||
homeassistant/components/vallox/coordinator.py
|
||||
|
|
|
@ -31,6 +31,9 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool:
|
|||
|
||||
hass.data.setdefault(DOMAIN, {})[entry.entry_id] = coordinator
|
||||
|
||||
if coordinator.data.ID and entry.unique_id != coordinator.data.ID:
|
||||
hass.config_entries.async_update_entry(entry, unique_id=coordinator.data.ID)
|
||||
|
||||
await hass.config_entries.async_forward_entry_setups(entry, PLATFORMS)
|
||||
|
||||
return True
|
||||
|
|
|
@ -41,13 +41,18 @@ class V2CConfigFlow(ConfigFlow, domain=DOMAIN):
|
|||
)
|
||||
|
||||
try:
|
||||
await evse.get_data()
|
||||
data = await evse.get_data()
|
||||
|
||||
except TrydanError:
|
||||
errors["base"] = "cannot_connect"
|
||||
except Exception:
|
||||
_LOGGER.exception("Unexpected exception")
|
||||
errors["base"] = "unknown"
|
||||
else:
|
||||
if data.ID:
|
||||
await self.async_set_unique_id(data.ID)
|
||||
self._abort_if_unique_id_configured()
|
||||
|
||||
return self.async_create_entry(
|
||||
title=f"EVSE {user_input[CONF_HOST]}", data=user_input
|
||||
)
|
||||
|
|
|
@ -15,6 +15,12 @@
|
|||
},
|
||||
"fv_power": {
|
||||
"default": "mdi:solar-power-variant"
|
||||
},
|
||||
"slave_error": {
|
||||
"default": "mdi:alert"
|
||||
},
|
||||
"battery_power": {
|
||||
"default": "mdi:home-battery"
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
|
|
|
@ -5,5 +5,5 @@
|
|||
"config_flow": true,
|
||||
"documentation": "https://www.home-assistant.io/integrations/v2c",
|
||||
"iot_class": "local_polling",
|
||||
"requirements": ["pytrydan==0.6.0"]
|
||||
"requirements": ["pytrydan==0.6.1"]
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ from dataclasses import dataclass
|
|||
import logging
|
||||
|
||||
from pytrydan import TrydanData
|
||||
from pytrydan.models.trydan import SlaveCommunicationState
|
||||
|
||||
from homeassistant.components.sensor import (
|
||||
SensorDeviceClass,
|
||||
|
@ -18,6 +19,7 @@ from homeassistant.config_entries import ConfigEntry
|
|||
from homeassistant.const import UnitOfEnergy, UnitOfPower, UnitOfTime
|
||||
from homeassistant.core import HomeAssistant
|
||||
from homeassistant.helpers.entity_platform import AddEntitiesCallback
|
||||
from homeassistant.helpers.typing import StateType
|
||||
|
||||
from .const import DOMAIN
|
||||
from .coordinator import V2CUpdateCoordinator
|
||||
|
@ -30,9 +32,11 @@ _LOGGER = logging.getLogger(__name__)
|
|||
class V2CSensorEntityDescription(SensorEntityDescription):
|
||||
"""Describes an EVSE Power sensor entity."""
|
||||
|
||||
value_fn: Callable[[TrydanData], float]
|
||||
value_fn: Callable[[TrydanData], StateType]
|
||||
|
||||
|
||||
_SLAVE_ERROR_OPTIONS = [error.name.lower() for error in SlaveCommunicationState]
|
||||
|
||||
TRYDAN_SENSORS = (
|
||||
V2CSensorEntityDescription(
|
||||
key="charge_power",
|
||||
|
@ -75,6 +79,23 @@ TRYDAN_SENSORS = (
|
|||
device_class=SensorDeviceClass.POWER,
|
||||
value_fn=lambda evse_data: evse_data.fv_power,
|
||||
),
|
||||
V2CSensorEntityDescription(
|
||||
key="slave_error",
|
||||
translation_key="slave_error",
|
||||
value_fn=lambda evse_data: evse_data.slave_error.name.lower(),
|
||||
entity_registry_enabled_default=False,
|
||||
device_class=SensorDeviceClass.ENUM,
|
||||
options=_SLAVE_ERROR_OPTIONS,
|
||||
),
|
||||
V2CSensorEntityDescription(
|
||||
key="battery_power",
|
||||
translation_key="battery_power",
|
||||
native_unit_of_measurement=UnitOfPower.WATT,
|
||||
state_class=SensorStateClass.MEASUREMENT,
|
||||
device_class=SensorDeviceClass.POWER,
|
||||
value_fn=lambda evse_data: evse_data.battery_power,
|
||||
entity_registry_enabled_default=False,
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
|
@ -108,6 +129,6 @@ class V2CSensorBaseEntity(V2CBaseEntity, SensorEntity):
|
|||
self._attr_unique_id = f"{entry_id}_{description.key}"
|
||||
|
||||
@property
|
||||
def native_value(self) -> float | None:
|
||||
def native_value(self) -> StateType:
|
||||
"""Return the state of the sensor."""
|
||||
return self.entity_description.value_fn(self.data)
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
{
|
||||
"config": {
|
||||
"abort": {
|
||||
"already_configured": "[%key:common::config_flow::abort::already_configured_device%]"
|
||||
},
|
||||
"step": {
|
||||
"user": {
|
||||
"data": {
|
||||
|
@ -47,6 +50,49 @@
|
|||
},
|
||||
"fv_power": {
|
||||
"name": "Photovoltaic power"
|
||||
},
|
||||
"battery_power": {
|
||||
"name": "Battery power"
|
||||
},
|
||||
"slave_error": {
|
||||
"name": "Slave error",
|
||||
"state": {
|
||||
"no_error": "No error",
|
||||
"communication": "Communication",
|
||||
"reading": "Reading",
|
||||
"slave": "Slave",
|
||||
"waiting_wifi": "Waiting for Wi-Fi",
|
||||
"waiting_communication": "Waiting communication",
|
||||
"wrong_ip": "Wrong IP",
|
||||
"slave_not_found": "Slave not found",
|
||||
"wrong_slave": "Wrong slave",
|
||||
"no_response": "No response",
|
||||
"clamp_not_connected": "Clamp not connected",
|
||||
"illegal_function": "Illegal function",
|
||||
"illegal_data_address": "Illegal data address",
|
||||
"illegal_data_value": "Illegal data value",
|
||||
"server_device_failure": "Server device failure",
|
||||
"acknowledge": "Acknowledge",
|
||||
"server_device_busy": "Server device busy",
|
||||
"negative_acknowledge": "Negative acknowledge",
|
||||
"memory_parity_error": "Memory parity error",
|
||||
"gateway_path_unavailable": "Gateway path unavailable",
|
||||
"gateway_target_no_resp": "Gateway target no response",
|
||||
"server_rtu_inactive244_timeout": "Server RTU inactive/timeout",
|
||||
"invalid_server": "Invalid server",
|
||||
"crc_error": "CRC error",
|
||||
"fc_mismatch": "FC mismatch",
|
||||
"server_id_mismatch": "Server id mismatch",
|
||||
"packet_length_error": "Packet length error",
|
||||
"parameter_count_error": "Parameter count error",
|
||||
"parameter_limit_error": "Parameter limit error",
|
||||
"request_queue_full": "Request queue full",
|
||||
"illegal_ip_or_port": "Illegal IP or port",
|
||||
"ip_connection_failed": "IP connection failed",
|
||||
"tcp_head_mismatch": "TCP head mismatch",
|
||||
"empty_message": "Empty message",
|
||||
"undefined_error": "Undefined error"
|
||||
}
|
||||
}
|
||||
},
|
||||
"switch": {
|
||||
|
|
|
@ -2352,7 +2352,7 @@ pytradfri[async]==9.0.1
|
|||
pytrafikverket==0.3.10
|
||||
|
||||
# homeassistant.components.v2c
|
||||
pytrydan==0.6.0
|
||||
pytrydan==0.6.1
|
||||
|
||||
# homeassistant.components.usb
|
||||
pyudev==0.24.1
|
||||
|
|
|
@ -1831,7 +1831,7 @@ pytradfri[async]==9.0.1
|
|||
pytrafikverket==0.3.10
|
||||
|
||||
# homeassistant.components.v2c
|
||||
pytrydan==0.6.0
|
||||
pytrydan==0.6.1
|
||||
|
||||
# homeassistant.components.usb
|
||||
pyudev==0.24.1
|
||||
|
|
|
@ -48,4 +48,5 @@ def mock_v2c_client() -> Generator[AsyncMock, None, None]:
|
|||
client = mock_client.return_value
|
||||
get_data_json = load_json_object_fixture("get_data.json", DOMAIN)
|
||||
client.get_data.return_value = TrydanData.from_api(get_data_json)
|
||||
client.firmware_version = get_data_json["FirmwareVersion"]
|
||||
yield client
|
||||
|
|
|
@ -1,4 +1,340 @@
|
|||
# serializer version: 1
|
||||
# name: test_sensor
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'power',
|
||||
'friendly_name': 'EVSE 1.1.1.1 Photovoltaic power',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': <UnitOfPower.WATT: 'W'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.evse_1_1_1_1_photovoltaic_power',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '0.0',
|
||||
})
|
||||
list([
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.evse_1_1_1_1_charge_power',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.POWER: 'power'>,
|
||||
'original_icon': 'mdi:ev-station',
|
||||
'original_name': 'Charge power',
|
||||
'platform': 'v2c',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'charge_power',
|
||||
'unique_id': '45a36e55aaddb2137c5f6602e0c38e72_charge_power',
|
||||
'unit_of_measurement': <UnitOfPower.WATT: 'W'>,
|
||||
}),
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.evse_1_1_1_1_charge_energy',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.ENERGY: 'energy'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Charge energy',
|
||||
'platform': 'v2c',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'charge_energy',
|
||||
'unique_id': '45a36e55aaddb2137c5f6602e0c38e72_charge_energy',
|
||||
'unit_of_measurement': <UnitOfEnergy.KILO_WATT_HOUR: 'kWh'>,
|
||||
}),
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.TOTAL_INCREASING: 'total_increasing'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.evse_1_1_1_1_charge_time',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.DURATION: 'duration'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Charge time',
|
||||
'platform': 'v2c',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'charge_time',
|
||||
'unique_id': '45a36e55aaddb2137c5f6602e0c38e72_charge_time',
|
||||
'unit_of_measurement': <UnitOfTime.SECONDS: 's'>,
|
||||
}),
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.evse_1_1_1_1_house_power',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.POWER: 'power'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'House power',
|
||||
'platform': 'v2c',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'house_power',
|
||||
'unique_id': '45a36e55aaddb2137c5f6602e0c38e72_house_power',
|
||||
'unit_of_measurement': <UnitOfPower.WATT: 'W'>,
|
||||
}),
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.evse_1_1_1_1_photovoltaic_power',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.POWER: 'power'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Photovoltaic power',
|
||||
'platform': 'v2c',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'fv_power',
|
||||
'unique_id': '45a36e55aaddb2137c5f6602e0c38e72_fv_power',
|
||||
'unit_of_measurement': <UnitOfPower.WATT: 'W'>,
|
||||
}),
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'options': list([
|
||||
'no_error',
|
||||
'communication',
|
||||
'reading',
|
||||
'slave',
|
||||
'waiting_wifi',
|
||||
'waiting_communication',
|
||||
'wrong_ip',
|
||||
'slave_not_found',
|
||||
'wrong_slave',
|
||||
'no_response',
|
||||
'clamp_not_connected',
|
||||
'illegal_function',
|
||||
'illegal_data_address',
|
||||
'illegal_data_value',
|
||||
'server_device_failure',
|
||||
'acknowledge',
|
||||
'server_device_busy',
|
||||
'negative_acknowledge',
|
||||
'memory_parity_error',
|
||||
'gateway_path_unavailable',
|
||||
'gateway_target_no_resp',
|
||||
'server_rtu_inactive244_timeout',
|
||||
'invalid_server',
|
||||
'crc_error',
|
||||
'fc_missmatch',
|
||||
'server_id_missmatch',
|
||||
'packet_length_error',
|
||||
'parameter_count_error',
|
||||
'parameter_limit_error',
|
||||
'request_queue_full',
|
||||
'illegal_ip_or_port',
|
||||
'ip_connection_failed',
|
||||
'tcp_head_missmatch',
|
||||
'empty_message',
|
||||
'undefined_error',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': <RegistryEntryDisabler.INTEGRATION: 'integration'>,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.evse_1_1_1_1_slave_error',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Slave error',
|
||||
'platform': 'v2c',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'slave_error',
|
||||
'unique_id': '45a36e55aaddb2137c5f6602e0c38e72_slave_error',
|
||||
'unit_of_measurement': None,
|
||||
}),
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': <RegistryEntryDisabler.INTEGRATION: 'integration'>,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.evse_1_1_1_1_battery_power',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.POWER: 'power'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Battery power',
|
||||
'platform': 'v2c',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'battery_power',
|
||||
'unique_id': '45a36e55aaddb2137c5f6602e0c38e72_battery_power',
|
||||
'unit_of_measurement': <UnitOfPower.WATT: 'W'>,
|
||||
}),
|
||||
])
|
||||
# ---
|
||||
# name: test_sensor[sensor.evse_1_1_1_1_battery_power-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.evse_1_1_1_1_battery_power',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.POWER: 'power'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Battery power',
|
||||
'platform': 'v2c',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'battery_power',
|
||||
'unique_id': 'da58ee91f38c2406c2a36d0a1a7f8569_battery_power',
|
||||
'unit_of_measurement': <UnitOfPower.WATT: 'W'>,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor[sensor.evse_1_1_1_1_battery_power-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'power',
|
||||
'friendly_name': 'EVSE 1.1.1.1 Battery power',
|
||||
'state_class': <SensorStateClass.MEASUREMENT: 'measurement'>,
|
||||
'unit_of_measurement': <UnitOfPower.WATT: 'W'>,
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.evse_1_1_1_1_battery_power',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': '0.0',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor[sensor.evse_1_1_1_1_charge_energy-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
|
@ -255,3 +591,125 @@
|
|||
'state': '0.0',
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor[sensor.evse_1_1_1_1_slave_error-entry]
|
||||
EntityRegistryEntrySnapshot({
|
||||
'aliases': set({
|
||||
}),
|
||||
'area_id': None,
|
||||
'capabilities': dict({
|
||||
'options': list([
|
||||
'no_error',
|
||||
'communication',
|
||||
'reading',
|
||||
'slave',
|
||||
'waiting_wifi',
|
||||
'waiting_communication',
|
||||
'wrong_ip',
|
||||
'slave_not_found',
|
||||
'wrong_slave',
|
||||
'no_response',
|
||||
'clamp_not_connected',
|
||||
'illegal_function',
|
||||
'illegal_data_address',
|
||||
'illegal_data_value',
|
||||
'server_device_failure',
|
||||
'acknowledge',
|
||||
'server_device_busy',
|
||||
'negative_acknowledge',
|
||||
'memory_parity_error',
|
||||
'gateway_path_unavailable',
|
||||
'gateway_target_no_resp',
|
||||
'server_rtu_inactive244_timeout',
|
||||
'invalid_server',
|
||||
'crc_error',
|
||||
'fc_mismatch',
|
||||
'server_id_mismatch',
|
||||
'packet_length_error',
|
||||
'parameter_count_error',
|
||||
'parameter_limit_error',
|
||||
'request_queue_full',
|
||||
'illegal_ip_or_port',
|
||||
'ip_connection_failed',
|
||||
'tcp_head_mismatch',
|
||||
'empty_message',
|
||||
'undefined_error',
|
||||
]),
|
||||
}),
|
||||
'config_entry_id': <ANY>,
|
||||
'device_class': None,
|
||||
'device_id': <ANY>,
|
||||
'disabled_by': None,
|
||||
'domain': 'sensor',
|
||||
'entity_category': None,
|
||||
'entity_id': 'sensor.evse_1_1_1_1_slave_error',
|
||||
'has_entity_name': True,
|
||||
'hidden_by': None,
|
||||
'icon': None,
|
||||
'id': <ANY>,
|
||||
'labels': set({
|
||||
}),
|
||||
'name': None,
|
||||
'options': dict({
|
||||
}),
|
||||
'original_device_class': <SensorDeviceClass.ENUM: 'enum'>,
|
||||
'original_icon': None,
|
||||
'original_name': 'Slave error',
|
||||
'platform': 'v2c',
|
||||
'previous_unique_id': None,
|
||||
'supported_features': 0,
|
||||
'translation_key': 'slave_error',
|
||||
'unique_id': 'da58ee91f38c2406c2a36d0a1a7f8569_slave_error',
|
||||
'unit_of_measurement': None,
|
||||
})
|
||||
# ---
|
||||
# name: test_sensor[sensor.evse_1_1_1_1_slave_error-state]
|
||||
StateSnapshot({
|
||||
'attributes': ReadOnlyDict({
|
||||
'device_class': 'enum',
|
||||
'friendly_name': 'EVSE 1.1.1.1 Slave error',
|
||||
'options': list([
|
||||
'no_error',
|
||||
'communication',
|
||||
'reading',
|
||||
'slave',
|
||||
'waiting_wifi',
|
||||
'waiting_communication',
|
||||
'wrong_ip',
|
||||
'slave_not_found',
|
||||
'wrong_slave',
|
||||
'no_response',
|
||||
'clamp_not_connected',
|
||||
'illegal_function',
|
||||
'illegal_data_address',
|
||||
'illegal_data_value',
|
||||
'server_device_failure',
|
||||
'acknowledge',
|
||||
'server_device_busy',
|
||||
'negative_acknowledge',
|
||||
'memory_parity_error',
|
||||
'gateway_path_unavailable',
|
||||
'gateway_target_no_resp',
|
||||
'server_rtu_inactive244_timeout',
|
||||
'invalid_server',
|
||||
'crc_error',
|
||||
'fc_mismatch',
|
||||
'server_id_mismatch',
|
||||
'packet_length_error',
|
||||
'parameter_count_error',
|
||||
'parameter_limit_error',
|
||||
'request_queue_full',
|
||||
'illegal_ip_or_port',
|
||||
'ip_connection_failed',
|
||||
'tcp_head_mismatch',
|
||||
'empty_message',
|
||||
'undefined_error',
|
||||
]),
|
||||
}),
|
||||
'context': <ANY>,
|
||||
'entity_id': 'sensor.evse_1_1_1_1_slave_error',
|
||||
'last_changed': <ANY>,
|
||||
'last_reported': <ANY>,
|
||||
'last_updated': <ANY>,
|
||||
'state': 'waiting_wifi',
|
||||
})
|
||||
# ---
|
||||
|
|
|
@ -25,3 +25,43 @@ async def test_sensor(
|
|||
with patch("homeassistant.components.v2c.PLATFORMS", [Platform.SENSOR]):
|
||||
await init_integration(hass, mock_config_entry)
|
||||
await snapshot_platform(hass, entity_registry, snapshot, mock_config_entry.entry_id)
|
||||
|
||||
from homeassistant.components.v2c.sensor import _SLAVE_ERROR_OPTIONS
|
||||
|
||||
assert [
|
||||
"no_error",
|
||||
"communication",
|
||||
"reading",
|
||||
"slave",
|
||||
"waiting_wifi",
|
||||
"waiting_communication",
|
||||
"wrong_ip",
|
||||
"slave_not_found",
|
||||
"wrong_slave",
|
||||
"no_response",
|
||||
"clamp_not_connected",
|
||||
"illegal_function",
|
||||
"illegal_data_address",
|
||||
"illegal_data_value",
|
||||
"server_device_failure",
|
||||
"acknowledge",
|
||||
"server_device_busy",
|
||||
"negative_acknowledge",
|
||||
"memory_parity_error",
|
||||
"gateway_path_unavailable",
|
||||
"gateway_target_no_resp",
|
||||
"server_rtu_inactive244_timeout",
|
||||
"invalid_server",
|
||||
"crc_error",
|
||||
"fc_mismatch",
|
||||
"server_id_mismatch",
|
||||
"packet_length_error",
|
||||
"parameter_count_error",
|
||||
"parameter_limit_error",
|
||||
"request_queue_full",
|
||||
"illegal_ip_or_port",
|
||||
"ip_connection_failed",
|
||||
"tcp_head_mismatch",
|
||||
"empty_message",
|
||||
"undefined_error",
|
||||
] == _SLAVE_ERROR_OPTIONS
|
||||
|
|
Loading…
Reference in New Issue