1
0
mirror of https://github.com/home-assistant/core.git synced 2025-12-24 12:59:34 +00:00

Improve Growatt Server config flow with region dropdown (#159329)

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
johanzander
2025-12-19 15:33:35 +01:00
committed by GitHub
parent 6e05cc4898
commit e0cb56a38c
5 changed files with 58 additions and 28 deletions

View File

@@ -16,6 +16,7 @@ from homeassistant.const import (
CONF_USERNAME, CONF_USERNAME,
) )
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.helpers.selector import SelectSelector, SelectSelectorConfig
from .const import ( from .const import (
ABORT_NO_PLANTS, ABORT_NO_PLANTS,
@@ -23,12 +24,13 @@ from .const import (
AUTH_PASSWORD, AUTH_PASSWORD,
CONF_AUTH_TYPE, CONF_AUTH_TYPE,
CONF_PLANT_ID, CONF_PLANT_ID,
CONF_REGION,
DEFAULT_URL, DEFAULT_URL,
DOMAIN, DOMAIN,
ERROR_CANNOT_CONNECT, ERROR_CANNOT_CONNECT,
ERROR_INVALID_AUTH, ERROR_INVALID_AUTH,
LOGIN_INVALID_AUTH_CODE, LOGIN_INVALID_AUTH_CODE,
SERVER_URLS, SERVER_URLS_NAMES,
) )
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@@ -67,10 +69,13 @@ class GrowattServerConfigFlow(ConfigFlow, domain=DOMAIN):
self.auth_type = AUTH_PASSWORD self.auth_type = AUTH_PASSWORD
# Traditional username/password authentication # Traditional username/password authentication
# Convert region name to URL - guaranteed to exist since vol.In validates it
server_url = SERVER_URLS_NAMES[user_input[CONF_REGION]]
self.api = growattServer.GrowattApi( self.api = growattServer.GrowattApi(
add_random_user_id=True, agent_identifier=user_input[CONF_USERNAME] add_random_user_id=True, agent_identifier=user_input[CONF_USERNAME]
) )
self.api.server_url = user_input[CONF_URL] self.api.server_url = server_url
try: try:
login_response = await self.hass.async_add_executor_job( login_response = await self.hass.async_add_executor_job(
@@ -91,6 +96,8 @@ class GrowattServerConfigFlow(ConfigFlow, domain=DOMAIN):
self.user_id = login_response["user"]["id"] self.user_id = login_response["user"]["id"]
self.data = user_input self.data = user_input
# Store the actual URL, not the region name
self.data[CONF_URL] = server_url
self.data[CONF_AUTH_TYPE] = self.auth_type self.data[CONF_AUTH_TYPE] = self.auth_type
return await self.async_step_plant() return await self.async_step_plant()
@@ -104,8 +111,11 @@ class GrowattServerConfigFlow(ConfigFlow, domain=DOMAIN):
self.auth_type = AUTH_API_TOKEN self.auth_type = AUTH_API_TOKEN
# Using token authentication # Using token authentication
token = user_input[CONF_TOKEN] # Convert region name to URL - guaranteed to exist since vol.In validates it
self.api = growattServer.OpenApiV1(token=token) server_url = SERVER_URLS_NAMES[user_input[CONF_REGION]]
self.api = growattServer.OpenApiV1(token=user_input[CONF_TOKEN])
self.api.server_url = server_url
# Verify token by fetching plant list # Verify token by fetching plant list
try: try:
@@ -127,6 +137,8 @@ class GrowattServerConfigFlow(ConfigFlow, domain=DOMAIN):
) )
return self._async_show_token_form({"base": ERROR_CANNOT_CONNECT}) return self._async_show_token_form({"base": ERROR_CANNOT_CONNECT})
self.data = user_input self.data = user_input
# Store the actual URL, not the region name
self.data[CONF_URL] = server_url
self.data[CONF_AUTH_TYPE] = self.auth_type self.data[CONF_AUTH_TYPE] = self.auth_type
return await self.async_step_plant() return await self.async_step_plant()
@@ -139,7 +151,12 @@ class GrowattServerConfigFlow(ConfigFlow, domain=DOMAIN):
{ {
vol.Required(CONF_USERNAME): str, vol.Required(CONF_USERNAME): str,
vol.Required(CONF_PASSWORD): str, vol.Required(CONF_PASSWORD): str,
vol.Required(CONF_URL, default=DEFAULT_URL): vol.In(SERVER_URLS), vol.Required(CONF_REGION, default=DEFAULT_URL): SelectSelector(
SelectSelectorConfig(
options=list(SERVER_URLS_NAMES.keys()),
translation_key="region",
)
),
} }
) )
@@ -155,6 +172,12 @@ class GrowattServerConfigFlow(ConfigFlow, domain=DOMAIN):
data_schema = vol.Schema( data_schema = vol.Schema(
{ {
vol.Required(CONF_TOKEN): str, vol.Required(CONF_TOKEN): str,
vol.Required(CONF_REGION, default=DEFAULT_URL): SelectSelector(
SelectSelectorConfig(
options=list(SERVER_URLS_NAMES.keys()),
translation_key="region",
)
),
} }
) )

View File

@@ -3,6 +3,7 @@
from homeassistant.const import Platform from homeassistant.const import Platform
CONF_PLANT_ID = "plant_id" CONF_PLANT_ID = "plant_id"
CONF_REGION = "region"
# API key support # API key support
@@ -18,13 +19,14 @@ DEFAULT_PLANT_ID = "0"
DEFAULT_NAME = "Growatt" DEFAULT_NAME = "Growatt"
SERVER_URLS = [ SERVER_URLS_NAMES = {
"https://openapi.growatt.com/", # Other regional server "north_america": "https://openapi-us.growatt.com/",
"https://openapi-cn.growatt.com/", # Chinese server "australia_new_zealand": "https://openapi-au.growatt.com/",
"https://openapi-us.growatt.com/", # North American server "china": "https://openapi-cn.growatt.com/",
"https://openapi-au.growatt.com/", # Australia Server "other_regions": "https://openapi.growatt.com/",
"http://server.smten.com/", # smten server "smten_server": "http://server.smten.com/",
] "era_server": "http://ess-server.atesspower.com/",
}
DEPRECATED_URLS = [ DEPRECATED_URLS = [
"https://server.growatt.com/", "https://server.growatt.com/",
@@ -32,7 +34,7 @@ DEPRECATED_URLS = [
"https://server-us.growatt.com/", "https://server-us.growatt.com/",
] ]
DEFAULT_URL = SERVER_URLS[0] DEFAULT_URL = "other_regions"
DOMAIN = "growatt_server" DOMAIN = "growatt_server"

View File

@@ -24,9 +24,7 @@ rules:
# Silver # Silver
action-exceptions: done action-exceptions: done
config-entry-unloading: done config-entry-unloading: done
docs-configuration-parameters: docs-configuration-parameters: done
status: todo
comment: Update server URL dropdown to show regional descriptions (e.g., 'China', 'United States') instead of raw URLs.
docs-installation-parameters: todo docs-installation-parameters: todo
entity-unavailable: done entity-unavailable: done
integration-owner: done integration-owner: done

View File

@@ -13,7 +13,7 @@
"password_auth": { "password_auth": {
"data": { "data": {
"password": "[%key:common::config_flow::data::password%]", "password": "[%key:common::config_flow::data::password%]",
"url": "[%key:common::config_flow::data::url%]", "url": "Server region",
"username": "[%key:common::config_flow::data::username%]" "username": "[%key:common::config_flow::data::username%]"
}, },
"title": "Enter your Growatt login credentials" "title": "Enter your Growatt login credentials"
@@ -26,7 +26,8 @@
}, },
"token_auth": { "token_auth": {
"data": { "data": {
"token": "API Token" "token": "API Token",
"url": "Server region"
}, },
"description": "Token authentication is only supported for MIN/TLX devices. For other device types, please use username/password authentication.", "description": "Token authentication is only supported for MIN/TLX devices. For other device types, please use username/password authentication.",
"title": "Enter your API token" "title": "Enter your API token"
@@ -530,6 +531,16 @@
"grid_first": "Grid first", "grid_first": "Grid first",
"load_first": "Load first" "load_first": "Load first"
} }
},
"region": {
"options": {
"australia_new_zealand": "Australia and New Zealand",
"china": "China",
"era_server": "Era server (Atess Power)",
"north_america": "North America",
"other_regions": "Other regions",
"smten_server": "SMTEN server"
}
} }
}, },
"services": { "services": {

View File

@@ -13,19 +13,14 @@ from homeassistant.components.growatt_server.const import (
AUTH_PASSWORD, AUTH_PASSWORD,
CONF_AUTH_TYPE, CONF_AUTH_TYPE,
CONF_PLANT_ID, CONF_PLANT_ID,
CONF_REGION,
DEFAULT_URL, DEFAULT_URL,
DOMAIN, DOMAIN,
ERROR_CANNOT_CONNECT, ERROR_CANNOT_CONNECT,
ERROR_INVALID_AUTH, ERROR_INVALID_AUTH,
LOGIN_INVALID_AUTH_CODE, LOGIN_INVALID_AUTH_CODE,
) )
from homeassistant.const import ( from homeassistant.const import CONF_NAME, CONF_PASSWORD, CONF_TOKEN, CONF_USERNAME
CONF_NAME,
CONF_PASSWORD,
CONF_TOKEN,
CONF_URL,
CONF_USERNAME,
)
from homeassistant.core import HomeAssistant from homeassistant.core import HomeAssistant
from homeassistant.data_entry_flow import FlowResultType from homeassistant.data_entry_flow import FlowResultType
@@ -34,11 +29,12 @@ from tests.common import MockConfigEntry
FIXTURE_USER_INPUT_PASSWORD = { FIXTURE_USER_INPUT_PASSWORD = {
CONF_USERNAME: "username", CONF_USERNAME: "username",
CONF_PASSWORD: "password", CONF_PASSWORD: "password",
CONF_URL: DEFAULT_URL, CONF_REGION: DEFAULT_URL,
} }
FIXTURE_USER_INPUT_TOKEN = { FIXTURE_USER_INPUT_TOKEN = {
CONF_TOKEN: "test_api_token_12345", CONF_TOKEN: "test_api_token_12345",
CONF_REGION: DEFAULT_URL,
} }
GROWATT_PLANT_LIST_RESPONSE = { GROWATT_PLANT_LIST_RESPONSE = {
@@ -109,8 +105,8 @@ async def test_show_auth_menu(hass: HomeAssistant) -> None:
@pytest.mark.parametrize( @pytest.mark.parametrize(
("auth_type", "expected_fields"), ("auth_type", "expected_fields"),
[ [
("password_auth", [CONF_USERNAME, CONF_PASSWORD, CONF_URL]), ("password_auth", [CONF_USERNAME, CONF_PASSWORD, CONF_REGION]),
("token_auth", [CONF_TOKEN]), ("token_auth", [CONF_TOKEN, CONF_REGION]),
], ],
) )
async def test_auth_form_display( async def test_auth_form_display(