Add sensors for detailed Enphase inverter readings (#146916)

* Add extra details to Enphase inverters

* Bump pyenphase version to 2.1.0

* Add new inverter sensors and translations

* Add new endpoint

* Start updating tests

* Remove duplicate class

* Add `max_reported` sensor

* Move translation strings to correct location

* Update fixtures and snapshots

* Update unit tests

* Fix linting

* Apply suggestions from code review

Co-authored-by: Arie Catsman <120491684+catsmanac@users.noreply.github.com>

* Fix Telegram bot parsing of inline keyboard (#146376)

* bug fix for inline keyboard

* update inline keyboard test

* Update tests/components/telegram_bot/test_telegram_bot.py

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

* revert last_message_id and updated tests

* removed TypeError test

---------

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

* Handle the new JSON payload from traccar clients (#147254)

* Set `entity_id`

* Update unit tests

* Bump aioamazondevices to 3.1.14 (#147257)

* Bump pyseventeentrack to 1.1.1 (#147253)

Update pyseventeentrack requirement to version 1.1.1

* Bump uiprotect to version 7.14.1 (#147280)

* Fix `state_class`es for energy production

* Make `max_reported` `name` more descriptive

* Update snapshots

* Reuse some translations

* Remove unnecessary translation keys

* Update unit tests

* Update homeassistant/components/enphase_envoy/strings.json

* Update homeassistant/components/enphase_envoy/strings.json

* Fix

---------

Co-authored-by: Arie Catsman <120491684+catsmanac@users.noreply.github.com>
Co-authored-by: hanwg <han.wuguang@gmail.com>
Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
Co-authored-by: Joakim Sørensen <joasoe@proton.me>
Co-authored-by: Simone Chemelli <simone.chemelli@gmail.com>
Co-authored-by: Shai Ungar <shai.ungar@riskified.com>
Co-authored-by: Raphael Hehl <7577984+RaHehl@users.noreply.github.com>
Co-authored-by: Joost Lekkerkerker <joostlek@outlook.com>
This commit is contained in:
Alex Biddulph
2025-06-24 04:59:18 +10:00
committed by GitHub
parent 6af290eb74
commit fc91047d8d
17 changed files with 6334 additions and 27 deletions

View File

@@ -38,9 +38,19 @@
"inverters": {
"1": {
"serial_number": "1",
"last_report_date": 1,
"last_report_watts": 1,
"max_report_watts": 1
"last_report_date": 1750460765,
"last_report_watts": 116,
"max_report_watts": 325,
"dc_voltage": 33.793,
"dc_current": 3.668,
"ac_voltage": 243.438,
"ac_current": 0.504,
"ac_frequency": 50.01,
"temperature": 23,
"energy_produced": 32.254,
"energy_today": 134,
"lifetime_energy": 130209,
"last_report_duration": 903
}
},
"tariff": null,

View File

@@ -78,7 +78,17 @@
"serial_number": "1",
"last_report_date": 1,
"last_report_watts": 1,
"max_report_watts": 1
"max_report_watts": 1,
"dc_voltage": null,
"dc_current": null,
"ac_voltage": null,
"ac_current": null,
"ac_frequency": null,
"temperature": null,
"energy_produced": null,
"energy_today": null,
"lifetime_energy": null,
"last_report_duration": null
}
},
"tariff": {

View File

@@ -220,7 +220,17 @@
"serial_number": "1",
"last_report_date": 1,
"last_report_watts": 1,
"max_report_watts": 1
"max_report_watts": 1,
"dc_voltage": null,
"dc_current": null,
"ac_voltage": null,
"ac_current": null,
"ac_frequency": null,
"temperature": null,
"energy_produced": null,
"energy_today": null,
"lifetime_energy": null,
"last_report_duration": null
}
},
"tariff": {

View File

@@ -208,7 +208,17 @@
"serial_number": "1",
"last_report_date": 1,
"last_report_watts": 1,
"max_report_watts": 1
"max_report_watts": 1,
"dc_voltage": null,
"dc_current": null,
"ac_voltage": null,
"ac_current": null,
"ac_frequency": null,
"temperature": null,
"energy_produced": null,
"energy_today": null,
"lifetime_energy": null,
"last_report_duration": null
}
},
"tariff": {

View File

@@ -412,7 +412,17 @@
"serial_number": "1",
"last_report_date": 1,
"last_report_watts": 1,
"max_report_watts": 1
"max_report_watts": 1,
"dc_voltage": null,
"dc_current": null,
"ac_voltage": null,
"ac_current": null,
"ac_frequency": null,
"temperature": null,
"energy_produced": null,
"energy_today": null,
"lifetime_energy": null,
"last_report_duration": null
}
},
"tariff": {

View File

@@ -227,7 +227,17 @@
"serial_number": "1",
"last_report_date": 1,
"last_report_watts": 1,
"max_report_watts": 1
"max_report_watts": 1,
"dc_voltage": null,
"dc_current": null,
"ac_voltage": null,
"ac_current": null,
"ac_frequency": null,
"temperature": null,
"energy_produced": null,
"energy_today": null,
"lifetime_energy": null,
"last_report_duration": null
}
},
"tariff": {

View File

@@ -73,7 +73,17 @@
"serial_number": "1",
"last_report_date": 1,
"last_report_watts": 1,
"max_report_watts": 1
"max_report_watts": 1,
"dc_voltage": null,
"dc_current": null,
"ac_voltage": null,
"ac_current": null,
"ac_frequency": null,
"temperature": null,
"energy_produced": null,
"energy_today": null,
"lifetime_energy": null,
"last_report_duration": null
}
},
"tariff": {

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -54,7 +54,7 @@ async def test_with_pre_v7_firmware(
await setup_integration(hass, config_entry)
assert (entity_state := hass.states.get("sensor.inverter_1"))
assert entity_state.state == "1"
assert entity_state.state == "116"
@pytest.mark.freeze_time("2024-07-23 00:00:00+00:00")
@@ -85,7 +85,7 @@ async def test_token_in_config_file(
await setup_integration(hass, entry)
assert (entity_state := hass.states.get("sensor.inverter_1"))
assert entity_state.state == "1"
assert entity_state.state == "116"
@respx.mock
@@ -128,7 +128,7 @@ async def test_expired_token_in_config(
await setup_integration(hass, entry)
assert (entity_state := hass.states.get("sensor.inverter_1"))
assert entity_state.state == "1"
assert entity_state.state == "116"
async def test_coordinator_update_error(
@@ -226,7 +226,7 @@ async def test_coordinator_token_refresh_error(
await setup_integration(hass, entry)
assert (entity_state := hass.states.get("sensor.inverter_1"))
assert entity_state.state == "1"
assert entity_state.state == "116"
async def test_config_no_unique_id(

View File

@@ -772,6 +772,70 @@ async def test_sensor_inverter_data(
) == dt_util.utc_from_timestamp(inverter.last_report_date)
@pytest.mark.parametrize(
("mock_envoy"),
[
"envoy",
],
indirect=["mock_envoy"],
)
@pytest.mark.usefixtures("entity_registry_enabled_by_default")
async def test_sensor_inverter_detailed_data(
hass: HomeAssistant,
mock_envoy: AsyncMock,
config_entry: MockConfigEntry,
) -> None:
"""Test enphase_envoy inverter detailed entities values."""
with patch("homeassistant.components.enphase_envoy.PLATFORMS", [Platform.SENSOR]):
await setup_integration(hass, config_entry)
entity_base = f"{Platform.SENSOR}.inverter"
for sn, inverter in mock_envoy.data.inverters.items():
assert (dc_voltage := hass.states.get(f"{entity_base}_{sn}_dc_voltage"))
assert float(dc_voltage.state) == (inverter.dc_voltage)
assert (dc_current := hass.states.get(f"{entity_base}_{sn}_dc_current"))
assert float(dc_current.state) == (inverter.dc_current)
assert (ac_voltage := hass.states.get(f"{entity_base}_{sn}_ac_voltage"))
assert float(ac_voltage.state) == (inverter.ac_voltage)
assert (ac_current := hass.states.get(f"{entity_base}_{sn}_ac_current"))
assert float(ac_current.state) == (inverter.ac_current)
assert (frequency := hass.states.get(f"{entity_base}_{sn}_frequency"))
assert float(frequency.state) == (inverter.ac_frequency)
assert (temperature := hass.states.get(f"{entity_base}_{sn}_temperature"))
assert int(temperature.state) == (inverter.temperature)
assert (
lifetime_energy := hass.states.get(
f"{entity_base}_{sn}_lifetime_energy_produced"
)
)
assert float(lifetime_energy.state) == (inverter.lifetime_energy / 1000.0)
assert (
energy_produced_today := hass.states.get(
f"{entity_base}_{sn}_energy_produced_today"
)
)
assert int(energy_produced_today.state) == (inverter.energy_today)
assert (
last_report_duration := hass.states.get(
f"{entity_base}_{sn}_last_report_duration"
)
)
assert int(last_report_duration.state) == (inverter.last_report_duration)
assert (
energy_produced := hass.states.get(
f"{entity_base}_{sn}_energy_produced_since_previous_report"
)
)
assert float(energy_produced.state) == (inverter.energy_produced)
assert (
lifetime_maximum_power := hass.states.get(
f"{entity_base}_{sn}_lifetime_maximum_power"
)
)
assert int(lifetime_maximum_power.state) == (inverter.max_report_watts)
@pytest.mark.parametrize(
("mock_envoy"),
[
@@ -797,9 +861,23 @@ async def test_sensor_inverter_disabled_by_integration(
INVERTER_BASE = f"{Platform.SENSOR}.inverter"
assert all(
f"{INVERTER_BASE}_{sn}_last_reported"
f"{INVERTER_BASE}_{sn}_{key}"
in integration_disabled_entities(entity_registry, config_entry)
for sn in mock_envoy.data.inverters
for key in (
"dc_voltage",
"dc_current",
"ac_voltage",
"ac_current",
"frequency",
"temperature",
"lifetime_energy_produced",
"energy_produced_today",
"last_report_duration",
"energy_produced_since_previous_report",
"last_reported",
"lifetime_maximum_power",
)
)