* Add unique_id and use DataUpdateCoordinator in Fronius (#57879)
* initial refactoring commit - meters
- config_flow (no strings, no tests yet)
- import yaml config
- FroniusSolarNet class for holding Fronius object , coordinators and some common data
- meter descriptions
- update coordinator
- entities (including devices)
* storage controllers
* error handling on init; inverter unique_id
* inverters
* power_flow
* fix VA, var, varh not valid for device_class power/energy
and add custom icons
* add SolarNet device for system wide values
* cleanup
* config_flow strings
* test config_flow
* use pyfronius 0.7.0
* enable strict typing
* remove TODO comments
* fix lint errors; move FroniusSensorEntity to sensor.py
* power_flow as optional coordinator
API V0 doesn't support power_flow endpoint
* show error message in logs
* prevent parallel requests to one host
* logger_info coordinator
* store FroniusSolarNet reference directly in coordinator
* cleanup coordinators when unloading entry
* round floats returned by Fronius API
* default icons for grid im/export tariffs
* small typing fix
* Update homeassistant/components/fronius/sensor.py
Co-authored-by: Brett Adams <Bre77@users.noreply.github.com>
* DC icons
* prepend names with "Fronius" and device type
to get more reasonable default entity_ids (eg. have them next to each other when alphabetically sorted)
* remove config_flow and devices
* rename _FroniusUpdateCoordinator to FroniusCoordinatorBase
and mark ABC
* move SensorEntityDescriptions to sensor.py
* Revert "move SensorEntityDescriptions to sensor.py"
This reverts commit 2e5a726eb6
.
* Don't raise ConfigEntryNotReady and use regular refresh method
* move bridge initialization out of helper class
* no coverage tests
* power_flow update interval 10 seconds
* move SensorEntityDescriptions to sensor.py
without introducing a circular dependency
* deprecation warning for CONF_MONITORED_CONDITIONS
* remove extra_state_attributes form meter sensor entities
* readd diagnostic entities
* decouple default entity_id from default name
* use key instead of name for entity_id
and make deprecated config key optional
* adjust tests
* use old entity_ids
these changes are now backwards compatible
* check coverage
* simplify entity description definitions
* restore entity names of previous implementation
Co-authored-by: Brett Adams <Bre77@users.noreply.github.com>
* Add config_flow for Fronius integration (#59677)
* Cleanup Fronius config_flow and tests (#60094)
* Add devices to Fronius integration (#60104)
* New entity names for Fronius entities (#60215)
* Adaptive update interval for Fronius coordinators (#60192)
Co-authored-by: Brett Adams <Bre77@users.noreply.github.com>
241 lines
9.3 KiB
Python
241 lines
9.3 KiB
Python
"""Tests for the Fronius sensor platform."""
|
|
from homeassistant.components.fronius.coordinator import (
|
|
FroniusInverterUpdateCoordinator,
|
|
FroniusPowerFlowUpdateCoordinator,
|
|
)
|
|
from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
|
|
from homeassistant.const import STATE_UNKNOWN
|
|
from homeassistant.util import dt
|
|
|
|
from . import mock_responses, setup_fronius_integration
|
|
|
|
from tests.common import async_fire_time_changed
|
|
|
|
|
|
async def test_symo_inverter(hass, aioclient_mock):
|
|
"""Test Fronius Symo inverter entities."""
|
|
|
|
def assert_state(entity_id, expected_state):
|
|
state = hass.states.get(entity_id)
|
|
assert state.state == str(expected_state)
|
|
|
|
# Init at night
|
|
mock_responses(aioclient_mock, night=True)
|
|
await setup_fronius_integration(hass)
|
|
|
|
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 55
|
|
assert_state("sensor.current_dc_fronius_inverter_1_http_fronius", 0)
|
|
assert_state("sensor.energy_day_fronius_inverter_1_http_fronius", 10828)
|
|
assert_state("sensor.energy_total_fronius_inverter_1_http_fronius", 44186900)
|
|
assert_state("sensor.energy_year_fronius_inverter_1_http_fronius", 25507686)
|
|
assert_state("sensor.voltage_dc_fronius_inverter_1_http_fronius", 16)
|
|
|
|
# Second test at daytime when inverter is producing
|
|
mock_responses(aioclient_mock, night=False)
|
|
async_fire_time_changed(
|
|
hass, dt.utcnow() + FroniusInverterUpdateCoordinator.default_interval
|
|
)
|
|
await hass.async_block_till_done()
|
|
|
|
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 59
|
|
# 4 additional AC entities
|
|
assert_state("sensor.current_dc_fronius_inverter_1_http_fronius", 2.19)
|
|
assert_state("sensor.energy_day_fronius_inverter_1_http_fronius", 1113)
|
|
assert_state("sensor.energy_total_fronius_inverter_1_http_fronius", 44188000)
|
|
assert_state("sensor.energy_year_fronius_inverter_1_http_fronius", 25508798)
|
|
assert_state("sensor.voltage_dc_fronius_inverter_1_http_fronius", 518)
|
|
assert_state("sensor.current_ac_fronius_inverter_1_http_fronius", 5.19)
|
|
assert_state("sensor.frequency_ac_fronius_inverter_1_http_fronius", 49.94)
|
|
assert_state("sensor.power_ac_fronius_inverter_1_http_fronius", 1190)
|
|
assert_state("sensor.voltage_ac_fronius_inverter_1_http_fronius", 227.90)
|
|
|
|
|
|
async def test_symo_logger(hass, aioclient_mock):
|
|
"""Test Fronius Symo logger entities."""
|
|
|
|
def assert_state(entity_id, expected_state):
|
|
state = hass.states.get(entity_id)
|
|
assert state
|
|
assert state.state == str(expected_state)
|
|
|
|
mock_responses(aioclient_mock)
|
|
await setup_fronius_integration(hass)
|
|
|
|
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 59
|
|
# ignored constant entities:
|
|
# hardware_platform, hardware_version, product_type
|
|
# software_version, time_zone, time_zone_location
|
|
# time_stamp, unique_identifier, utc_offset
|
|
#
|
|
# states are rounded to 2 decimals
|
|
assert_state(
|
|
"sensor.cash_factor_fronius_logger_info_0_http_fronius",
|
|
0.078,
|
|
)
|
|
assert_state(
|
|
"sensor.co2_factor_fronius_logger_info_0_http_fronius",
|
|
0.53,
|
|
)
|
|
assert_state(
|
|
"sensor.delivery_factor_fronius_logger_info_0_http_fronius",
|
|
0.15,
|
|
)
|
|
|
|
|
|
async def test_symo_meter(hass, aioclient_mock):
|
|
"""Test Fronius Symo meter entities."""
|
|
|
|
def assert_state(entity_id, expected_state):
|
|
state = hass.states.get(entity_id)
|
|
assert state
|
|
assert state.state == str(expected_state)
|
|
|
|
mock_responses(aioclient_mock)
|
|
await setup_fronius_integration(hass)
|
|
|
|
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 59
|
|
# ignored entities:
|
|
# manufacturer, model, serial, enable, timestamp, visible, meter_location
|
|
#
|
|
# states are rounded to 2 decimals
|
|
assert_state("sensor.current_ac_phase_1_fronius_meter_0_http_fronius", 7.755)
|
|
assert_state("sensor.current_ac_phase_2_fronius_meter_0_http_fronius", 6.68)
|
|
assert_state("sensor.current_ac_phase_3_fronius_meter_0_http_fronius", 10.102)
|
|
assert_state(
|
|
"sensor.energy_reactive_ac_consumed_fronius_meter_0_http_fronius", 59960790
|
|
)
|
|
assert_state(
|
|
"sensor.energy_reactive_ac_produced_fronius_meter_0_http_fronius", 723160
|
|
)
|
|
assert_state("sensor.energy_real_ac_minus_fronius_meter_0_http_fronius", 35623065)
|
|
assert_state("sensor.energy_real_ac_plus_fronius_meter_0_http_fronius", 15303334)
|
|
assert_state("sensor.energy_real_consumed_fronius_meter_0_http_fronius", 15303334)
|
|
assert_state("sensor.energy_real_produced_fronius_meter_0_http_fronius", 35623065)
|
|
assert_state("sensor.frequency_phase_average_fronius_meter_0_http_fronius", 50)
|
|
assert_state("sensor.power_apparent_phase_1_fronius_meter_0_http_fronius", 1772.793)
|
|
assert_state("sensor.power_apparent_phase_2_fronius_meter_0_http_fronius", 1527.048)
|
|
assert_state("sensor.power_apparent_phase_3_fronius_meter_0_http_fronius", 2333.562)
|
|
assert_state("sensor.power_apparent_fronius_meter_0_http_fronius", 5592.57)
|
|
assert_state("sensor.power_factor_phase_1_fronius_meter_0_http_fronius", -0.99)
|
|
assert_state("sensor.power_factor_phase_2_fronius_meter_0_http_fronius", -0.99)
|
|
assert_state("sensor.power_factor_phase_3_fronius_meter_0_http_fronius", 0.99)
|
|
assert_state("sensor.power_factor_fronius_meter_0_http_fronius", 1)
|
|
assert_state("sensor.power_reactive_phase_1_fronius_meter_0_http_fronius", 51.48)
|
|
assert_state("sensor.power_reactive_phase_2_fronius_meter_0_http_fronius", 115.63)
|
|
assert_state("sensor.power_reactive_phase_3_fronius_meter_0_http_fronius", -164.24)
|
|
assert_state("sensor.power_reactive_fronius_meter_0_http_fronius", 2.87)
|
|
assert_state("sensor.power_real_phase_1_fronius_meter_0_http_fronius", 1765.55)
|
|
assert_state("sensor.power_real_phase_2_fronius_meter_0_http_fronius", 1515.8)
|
|
assert_state("sensor.power_real_phase_3_fronius_meter_0_http_fronius", 2311.22)
|
|
assert_state("sensor.power_real_fronius_meter_0_http_fronius", 5592.57)
|
|
assert_state("sensor.voltage_ac_phase_1_fronius_meter_0_http_fronius", 228.6)
|
|
assert_state("sensor.voltage_ac_phase_2_fronius_meter_0_http_fronius", 228.6)
|
|
assert_state("sensor.voltage_ac_phase_3_fronius_meter_0_http_fronius", 231)
|
|
assert_state(
|
|
"sensor.voltage_ac_phase_to_phase_12_fronius_meter_0_http_fronius", 395.9
|
|
)
|
|
assert_state(
|
|
"sensor.voltage_ac_phase_to_phase_23_fronius_meter_0_http_fronius", 398
|
|
)
|
|
assert_state(
|
|
"sensor.voltage_ac_phase_to_phase_31_fronius_meter_0_http_fronius", 398
|
|
)
|
|
|
|
|
|
async def test_symo_power_flow(hass, aioclient_mock):
|
|
"""Test Fronius Symo power flow entities."""
|
|
async_fire_time_changed(hass, dt.utcnow())
|
|
|
|
def assert_state(entity_id, expected_state):
|
|
state = hass.states.get(entity_id)
|
|
assert state.state == str(expected_state)
|
|
|
|
# First test at night
|
|
mock_responses(aioclient_mock, night=True)
|
|
await setup_fronius_integration(hass)
|
|
|
|
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 55
|
|
# ignored: location, mode, timestamp
|
|
#
|
|
# states are rounded to 2 decimals
|
|
assert_state(
|
|
"sensor.energy_day_fronius_power_flow_0_http_fronius",
|
|
10828,
|
|
)
|
|
assert_state(
|
|
"sensor.energy_total_fronius_power_flow_0_http_fronius",
|
|
44186900,
|
|
)
|
|
assert_state(
|
|
"sensor.energy_year_fronius_power_flow_0_http_fronius",
|
|
25507686,
|
|
)
|
|
assert_state(
|
|
"sensor.power_battery_fronius_power_flow_0_http_fronius",
|
|
STATE_UNKNOWN,
|
|
)
|
|
assert_state(
|
|
"sensor.power_grid_fronius_power_flow_0_http_fronius",
|
|
975.31,
|
|
)
|
|
assert_state(
|
|
"sensor.power_load_fronius_power_flow_0_http_fronius",
|
|
-975.31,
|
|
)
|
|
assert_state(
|
|
"sensor.power_photovoltaics_fronius_power_flow_0_http_fronius",
|
|
STATE_UNKNOWN,
|
|
)
|
|
assert_state(
|
|
"sensor.relative_autonomy_fronius_power_flow_0_http_fronius",
|
|
0,
|
|
)
|
|
assert_state(
|
|
"sensor.relative_self_consumption_fronius_power_flow_0_http_fronius",
|
|
STATE_UNKNOWN,
|
|
)
|
|
|
|
# Second test at daytime when inverter is producing
|
|
mock_responses(aioclient_mock, night=False)
|
|
async_fire_time_changed(
|
|
hass, dt.utcnow() + FroniusPowerFlowUpdateCoordinator.default_interval
|
|
)
|
|
await hass.async_block_till_done()
|
|
# still 55 because power_flow update interval is shorter than others
|
|
assert len(hass.states.async_all(domain_filter=SENSOR_DOMAIN)) == 55
|
|
assert_state(
|
|
"sensor.energy_day_fronius_power_flow_0_http_fronius",
|
|
1101.7001,
|
|
)
|
|
assert_state(
|
|
"sensor.energy_total_fronius_power_flow_0_http_fronius",
|
|
44188000,
|
|
)
|
|
assert_state(
|
|
"sensor.energy_year_fronius_power_flow_0_http_fronius",
|
|
25508788,
|
|
)
|
|
assert_state(
|
|
"sensor.power_battery_fronius_power_flow_0_http_fronius",
|
|
STATE_UNKNOWN,
|
|
)
|
|
assert_state(
|
|
"sensor.power_grid_fronius_power_flow_0_http_fronius",
|
|
1703.74,
|
|
)
|
|
assert_state(
|
|
"sensor.power_load_fronius_power_flow_0_http_fronius",
|
|
-2814.74,
|
|
)
|
|
assert_state(
|
|
"sensor.power_photovoltaics_fronius_power_flow_0_http_fronius",
|
|
1111,
|
|
)
|
|
assert_state(
|
|
"sensor.relative_autonomy_fronius_power_flow_0_http_fronius",
|
|
39.4708,
|
|
)
|
|
assert_state(
|
|
"sensor.relative_self_consumption_fronius_power_flow_0_http_fronius",
|
|
100,
|
|
)
|