From 9ab4b4e7e88679dd7596e9d3a08d63852505d7c6 Mon Sep 17 00:00:00 2001 From: Vincent Wolsink Date: Thu, 2 Nov 2023 19:06:10 +0100 Subject: [PATCH 1/2] Add get_grid_profiles and set_grid_profile services --- custom_components/enphase_envoy/__init__.py | 34 ++++++++++++++++++- .../enphase_envoy/envoy_reader.py | 17 ++++++++++ custom_components/enphase_envoy/services.yaml | 8 +++++ 3 files changed, 58 insertions(+), 1 deletion(-) create mode 100644 custom_components/enphase_envoy/services.yaml diff --git a/custom_components/enphase_envoy/__init__.py b/custom_components/enphase_envoy/__init__.py index 5090c4f..5ae109a 100644 --- a/custom_components/enphase_envoy/__init__.py +++ b/custom_components/enphase_envoy/__init__.py @@ -20,7 +20,15 @@ CONF_USERNAME, EVENT_HOMEASSISTANT_STOP, ) -from homeassistant.core import HomeAssistant, callback, CoreState, Event +from homeassistant.core import ( + HomeAssistant, + callback, + CoreState, + Event, + ServiceCall, + ServiceResponse, + SupportsResponse, +) from homeassistant.exceptions import ConfigEntryAuthFailed from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed from homeassistant.helpers.storage import Store @@ -137,6 +145,30 @@ async def async_update_data(): ), ) + async def get_grid_profiles(call: ServiceCall) -> ServiceResponse: + return { + "selected_profile": coordinator.data.get("grid_profile"), + "available_profiles": [ + k["profile_id"] for k in coordinator.data.get("grid_profiles_available") + ], + } + + hass.services.async_register( + DOMAIN, + "get_grid_profiles", + get_grid_profiles, + supports_response=SupportsResponse.ONLY, + ) + + async def set_grid_profile(call: ServiceCall): + await envoy_reader.set_grid_profile(call.data["profile"]) + + hass.services.async_register( + DOMAIN, + "set_grid_profile", + set_grid_profile, + ) + @Throttle(time_between_realtime_updates) def update_production_meters(streamdata: StreamData): new_data = {} diff --git a/custom_components/enphase_envoy/envoy_reader.py b/custom_components/enphase_envoy/envoy_reader.py index 9663eed..8ee3f2f 100644 --- a/custom_components/enphase_envoy/envoy_reader.py +++ b/custom_components/enphase_envoy/envoy_reader.py @@ -36,6 +36,7 @@ ENDPOINT_URL_PRODUCTION_REPORT = "https://{}/ivp/meters/reports/production" ENDPOINT_URL_PDM_ENERGY = "https://{}/ivp/pdm/energy" ENDPOINT_URL_INSTALLER_AGF = "https://{}/installer/agf/index.json" +ENDPOINT_URL_INSTALLER_AGF_SET_PROFILE = "https://{}/installer/agf/set_profile.json" ENVOY_MODEL_M = "Metered" ENVOY_MODEL_S = "Standard" @@ -377,6 +378,7 @@ class EnvoyStandard(EnvoyData): envoy_update_status_value = "endpoint_home_json_results.update_status" serial_number_value = "endpoint_info_results.envoy_info.device.sn" grid_profile_value = "endpoint_installer_agf.selected_profile" + grid_profiles_available_value = "endpoint_installer_agf.profiles" @envoy_property() def envoy_info(self): @@ -1331,6 +1333,21 @@ async def set_production_power(self, power_on): # Make sure the next poll will update the endpoint. self._clear_endpoint_cache("endpoint_production_power") + async def set_grid_profile(self, profile_id): + if self.endpoint_installer_agf is not None: + formatted_url = ENDPOINT_URL_INSTALLER_AGF_SET_PROFILE.format(self.host) + resp = await self._async_put( + formatted_url, data={"selected_profile": profile_id} + ) + + if "accepted" not in resp.text: + raise EnvoyError( + f"Failed setting grid profile: {resp.json().get('message')} - {resp.json().get('reason')}" + ) + + self._clear_endpoint_cache("endpoint_installer_agf") + return resp + def run_stream(self): print("Reading stream...") loop = asyncio.get_event_loop() diff --git a/custom_components/enphase_envoy/services.yaml b/custom_components/enphase_envoy/services.yaml new file mode 100644 index 0000000..550864c --- /dev/null +++ b/custom_components/enphase_envoy/services.yaml @@ -0,0 +1,8 @@ +get_grid_profiles: +set_grid_profile: + fields: + profile: + required: true + example: "EN 50549-1:2019 RfG E02 Netherlands:1.2.4" + selector: + text: From 8cf5bcc98d2c1ab6088192b8fbea0c10b60f6a87 Mon Sep 17 00:00:00 2001 From: Vincent Wolsink Date: Thu, 2 Nov 2023 20:30:20 +0100 Subject: [PATCH 2/2] Add translations for services --- .../enphase_envoy/translations/en.json | 16 ++++ .../enphase_envoy/translations/nl.json | 94 +++++++++++-------- 2 files changed, 71 insertions(+), 39 deletions(-) diff --git a/custom_components/enphase_envoy/translations/en.json b/custom_components/enphase_envoy/translations/en.json index 2167cba..bac1eec 100644 --- a/custom_components/enphase_envoy/translations/en.json +++ b/custom_components/enphase_envoy/translations/en.json @@ -42,5 +42,21 @@ } } } + }, + "services": { + "set_grid_profile": { + "name": "Set grid profile", + "description": "Sets the grid profile the Envoy will upload to the inverters.", + "fields": { + "profile": { + "name": "Profile", + "description": "Grid profile ID" + } + } + }, + "get_grid_profiles": { + "name": "Get grid profiles", + "description": "Get currently selected and all available profiles." + } } } diff --git a/custom_components/enphase_envoy/translations/nl.json b/custom_components/enphase_envoy/translations/nl.json index cd32d3b..28ee402 100644 --- a/custom_components/enphase_envoy/translations/nl.json +++ b/custom_components/enphase_envoy/translations/nl.json @@ -1,46 +1,62 @@ { - "config": { - "abort": { - "already_configured": "Apparaat is al geconfigureerd", - "reauth_successful": "Herauthenticatie was succesvol" - }, - "error": { - "cannot_connect": "Kan geen verbinding maken", - "invalid_auth": "Ongeldige authenticatie", - "unknown": "Onverwachte fout" - }, - "flow_title": "{serial} ({host})", - "step": { - "user": { - "data": { - "host": "Host", - "password": "Enlighten Wachtwoord", - "username": "Enlighten Gebruikersnaam", - "serial": "Envoy Serienummer", - "disable_installer_account_use": "Ik heb geen installer of DHZ enphase account, alleen Home owner" - }, - "description": "Voer de hostname/ip en serienummer van je Envoy in. Gebruik je Enlighten installer account gegevens." - } - } - }, - "options": { + "config": { + "abort": { + "already_configured": "Apparaat is al geconfigureerd", + "reauth_successful": "Herauthenticatie was succesvol" + }, + "error": { + "cannot_connect": "Kan geen verbinding maken", + "invalid_auth": "Ongeldige authenticatie", + "unknown": "Onverwachte fout" + }, + "flow_title": "{serial} ({host})", "step": { - "user": { - "title": "Envoy opties", - "data": { - "enable_realtime_updates": "Gebruik real-time updates (werkt alleen met metered envoys)", - "realtime_update_throttle": "Minimale tijd tussen real-time updates [s]", - "disable_negative_production": "Voorkom negatieve productie waardes", - "time_between_update": "Minimum tijd tussen entity updates [s]", - "getdata_timeout": "Maximum tijd voor het ophalen van data vanaf envoy [s]", - "enable_additional_metrics": "[Metered only] Extra metrics inschakelen, zoals total amps, frequency, apparent en reactive power en power factor.", - "disable_installer_account_use": "Haal geen data op die een installateur of DHZ enphase account vereisen" - }, - "data_description": { - "realtime_update_throttle": "Dit interval is van toepassing op real-time updates (om eventuele overload met updates te voorkomen)", - "time_between_update": "Dit interval is alleen van toepassing voor het pollen van URLs" + "user": { + "data": { + "host": "Host", + "password": "Enlighten Wachtwoord", + "username": "Enlighten Gebruikersnaam", + "serial": "Envoy Serienummer", + "disable_installer_account_use": "Ik heb geen installer of DHZ enphase account, alleen Home owner" + }, + "description": "Voer de hostname/ip en serienummer van je Envoy in. Gebruik je Enlighten installer account gegevens." } + } + }, + "options": { + "step": { + "user": { + "title": "Envoy opties", + "data": { + "enable_realtime_updates": "Gebruik real-time updates (werkt alleen met metered envoys)", + "realtime_update_throttle": "Minimale tijd tussen real-time updates [s]", + "disable_negative_production": "Voorkom negatieve productie waardes", + "time_between_update": "Minimum tijd tussen entity updates [s]", + "getdata_timeout": "Maximum tijd voor het ophalen van data vanaf envoy [s]", + "enable_additional_metrics": "[Metered only] Extra metrics inschakelen, zoals total amps, frequency, apparent en reactive power en power factor.", + "disable_installer_account_use": "Haal geen data op die een installateur of DHZ enphase account vereisen" + }, + "data_description": { + "realtime_update_throttle": "Dit interval is van toepassing op real-time updates (om eventuele overload met updates te voorkomen)", + "time_between_update": "Dit interval is alleen van toepassing voor het pollen van URLs" } } } + }, + "services": { + "set_grid_profile": { + "name": "Stel netwerkprofiel in", + "description": "Stel het netwerkprofiel in dat de Envoy toepast op de omvormers.", + "fields": { + "profile": { + "name": "Profiel", + "description": "Netwerkprofiel ID" + } + } + }, + "get_grid_profiles": { + "name": "Haal netwerkprofielen op", + "description": "Haal huidige geselecteerde en alle beschikbare netwerkprofielen op." + } + } }