Migrate Enphase envoy from httpx to aiohttp (#146283)

Co-authored-by: J. Nick Koston <nick@koston.org>
This commit is contained in:
Arie Catsman 2025-06-07 17:52:54 +02:00 committed by GitHub
parent 7f9f106729
commit ae5606aa2f
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 22 additions and 35 deletions

View File

@ -2,7 +2,6 @@
from __future__ import annotations
import httpx
from pyenphase import Envoy
from homeassistant.config_entries import ConfigEntry
@ -10,14 +9,9 @@ from homeassistant.const import CONF_HOST
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryNotReady
from homeassistant.helpers import device_registry as dr
from homeassistant.helpers.httpx_client import get_async_client
from homeassistant.helpers.aiohttp_client import async_create_clientsession
from .const import (
DOMAIN,
OPTION_DISABLE_KEEP_ALIVE,
OPTION_DISABLE_KEEP_ALIVE_DEFAULT_VALUE,
PLATFORMS,
)
from .const import DOMAIN, PLATFORMS
from .coordinator import EnphaseConfigEntry, EnphaseUpdateCoordinator
@ -25,19 +19,8 @@ async def async_setup_entry(hass: HomeAssistant, entry: EnphaseConfigEntry) -> b
"""Set up Enphase Envoy from a config entry."""
host = entry.data[CONF_HOST]
options = entry.options
envoy = (
Envoy(
host,
httpx.AsyncClient(
verify=False, limits=httpx.Limits(max_keepalive_connections=0)
),
)
if options.get(
OPTION_DISABLE_KEEP_ALIVE, OPTION_DISABLE_KEEP_ALIVE_DEFAULT_VALUE
)
else Envoy(host, get_async_client(hass, verify_ssl=False))
)
session = async_create_clientsession(hass, verify_ssl=False)
envoy = Envoy(host, session)
coordinator = EnphaseUpdateCoordinator(hass, envoy, entry)
await coordinator.async_config_entry_first_refresh()

View File

@ -24,7 +24,7 @@ from homeassistant.const import (
CONF_USERNAME,
)
from homeassistant.core import HomeAssistant, callback
from homeassistant.helpers.httpx_client import get_async_client
from homeassistant.helpers.aiohttp_client import async_get_clientsession
from homeassistant.helpers.service_info.zeroconf import ZeroconfServiceInfo
from homeassistant.helpers.typing import VolDictType
@ -63,7 +63,7 @@ async def validate_input(
description_placeholders: dict[str, str],
) -> Envoy:
"""Validate the user input allows us to connect."""
envoy = Envoy(host, get_async_client(hass, verify_ssl=False))
envoy = Envoy(host, async_get_clientsession(hass, verify_ssl=False))
try:
await envoy.setup()
await envoy.authenticate(username=username, password=password)

View File

@ -6,6 +6,7 @@ import copy
from datetime import datetime
from typing import TYPE_CHECKING, Any
from aiohttp import ClientResponse
from attr import asdict
from pyenphase.envoy import Envoy
from pyenphase.exceptions import EnvoyError
@ -69,14 +70,14 @@ async def _get_fixture_collection(envoy: Envoy, serial: str) -> dict[str, Any]:
for end_point in end_points:
try:
response = await envoy.request(end_point)
fixture_data[end_point] = response.text.replace("\n", "").replace(
serial, CLEAN_TEXT
response: ClientResponse = await envoy.request(end_point)
fixture_data[end_point] = (
(await response.text()).replace("\n", "").replace(serial, CLEAN_TEXT)
)
fixture_data[f"{end_point}_log"] = json_dumps(
{
"headers": dict(response.headers.items()),
"code": response.status_code,
"code": response.status,
}
)
except EnvoyError as err:

View File

@ -5,7 +5,7 @@ from __future__ import annotations
from collections.abc import Callable, Coroutine
from typing import Any, Concatenate
from httpx import HTTPError
from aiohttp import ClientError
from pyenphase import EnvoyData
from pyenphase.exceptions import EnvoyError
@ -16,7 +16,7 @@ from homeassistant.helpers.update_coordinator import CoordinatorEntity
from .const import DOMAIN
from .coordinator import EnphaseUpdateCoordinator
ACTIONERRORS = (EnvoyError, HTTPError)
ACTIONERRORS = (EnvoyError, ClientError)
class EnvoyBaseEntity(CoordinatorEntity[EnphaseUpdateCoordinator]):

View File

@ -7,7 +7,7 @@
"iot_class": "local_polling",
"loggers": ["pyenphase"],
"quality_scale": "platinum",
"requirements": ["pyenphase==1.26.1"],
"requirements": ["pyenphase==2.0.1"],
"zeroconf": [
{
"type": "_enphase-envoy._tcp.local."

2
requirements_all.txt generated
View File

@ -1958,7 +1958,7 @@ pyeiscp==0.0.7
pyemoncms==0.1.1
# homeassistant.components.enphase_envoy
pyenphase==1.26.1
pyenphase==2.0.1
# homeassistant.components.envisalink
pyenvisalink==4.7

View File

@ -1630,7 +1630,7 @@ pyeiscp==0.0.7
pyemoncms==0.1.1
# homeassistant.components.enphase_envoy
pyenphase==1.26.1
pyenphase==2.0.1
# homeassistant.components.everlights
pyeverlights==0.1.0

View File

@ -5,6 +5,7 @@ from typing import Any
from unittest.mock import AsyncMock, Mock, patch
import jwt
import multidict
from pyenphase import (
EnvoyACBPower,
EnvoyBatteryAggregate,
@ -101,9 +102,11 @@ async def mock_envoy(
mock_envoy.auth = EnvoyTokenAuth("127.0.0.1", token=token, envoy_serial="1234")
mock_envoy.serial_number = "1234"
mock = Mock()
mock.status_code = 200
mock.text = "Testing request \nreplies."
mock.headers = {"Hello": "World"}
mock.status = 200
aiohttp_text = AsyncMock()
aiohttp_text.return_value = "Testing request \nreplies."
mock.text = aiohttp_text
mock.headers = multidict.MultiDict([("Hello", "World")])
mock_envoy.request.return_value = mock
# determine fixture file name, default envoy if no request passed