From 1d34f1d40c886c69a7923f325df981bf0cf03d3c Mon Sep 17 00:00:00 2001 From: Vincent Wolsink Date: Fri, 2 Aug 2024 16:09:33 +0200 Subject: [PATCH] Stop reading from home.json --- .../enphase_envoy/binary_sensor.py | 106 ++++-------------- .../enphase_envoy/envoy_reader.py | 27 +---- .../endpoint_ensemble_inventory.json | 42 ++++++- 3 files changed, 65 insertions(+), 110 deletions(-) diff --git a/custom_components/enphase_envoy/binary_sensor.py b/custom_components/enphase_envoy/binary_sensor.py index 279be4f..01a1efd 100644 --- a/custom_components/enphase_envoy/binary_sensor.py +++ b/custom_components/enphase_envoy/binary_sensor.py @@ -9,6 +9,7 @@ COORDINATOR, DOMAIN, NAME, + READER, BINARY_SENSORS, resolve_hardware_id, get_model_name, @@ -23,6 +24,7 @@ async def async_setup_entry( data = hass.data[DOMAIN][config_entry.entry_id] coordinator = data[COORDINATOR] name = data[NAME] + reader = data[READER] entities = [] for sensor_description in BINARY_SENSORS: @@ -41,18 +43,6 @@ async def async_setup_entry( coordinator, ) ) - elif sensor_description.key == "grid_status": - if coordinator.data.get("grid_status") is not None: - entities.append( - EnvoyGridStatusEntity( - sensor_description, - sensor_description.name, - name, - config_entry.unique_id, - None, - coordinator, - ) - ) elif sensor_description.key == "relays": if coordinator.data.get("relays") is not None: @@ -113,75 +103,27 @@ async def async_setup_entry( ) ) - elif sensor_description.key == "firmware": - if coordinator.data.get("envoy_info", {}).get("update_status") is not None: - entity_name = f"{name} {sensor_description.name}" - serial_number = name.split(None, 1)[-1] - entities.append( - EnvoyFirmwareEntity( - sensor_description, - entity_name, - name, - config_entry.unique_id, - serial_number, - coordinator, - ) + else: + data = coordinator.data.get(sensor_description.key) + if data is None: + continue + + entity_name = f"{name} {sensor_description.name}" + entities.append( + EnvoyBinaryEntity( + sensor_description, + entity_name, + name, + config_entry.unique_id, + None, + coordinator, + reader, ) + ) async_add_entities(entities) -class EnvoyGridStatusEntity(CoordinatorEntity, BinarySensorEntity): - def __init__( - self, - description, - name, - device_name, - device_serial_number, - serial_number, - coordinator, - ): - self.entity_description = description - self._name = name - self._serial_number = serial_number - self._device_name = device_name - self._device_serial_number = device_serial_number - CoordinatorEntity.__init__(self, coordinator) - - @property - def name(self): - """Return the name of the sensor.""" - return self._name - - @property - def unique_id(self): - """Return the unique id of the sensor.""" - if self._serial_number: - return self._serial_number - if self._device_serial_number: - return f"{self._device_serial_number}_{self.entity_description.key}" - - @property - def device_info(self) -> DeviceInfo or None: - """Return the device_info of the device.""" - if not self._device_serial_number: - return None - - model = self.coordinator.data.get("envoy_info", {}).get("model", "Standard") - - return DeviceInfo( - identifiers={(DOMAIN, str(self._device_serial_number))}, - manufacturer="Enphase", - model=f"Envoy-S {model}", - name=self._device_name, - ) - - @property - def is_on(self) -> bool: - """Return the status of the requested attribute.""" - return self.coordinator.data.get("grid_status") == "closed" - - class EnvoyInverterEntity(CoordinatorEntity, BinarySensorEntity): def __init__( self, @@ -356,19 +298,9 @@ def __init__( parent_device=parent_device, ) - -class EnvoyFirmwareEntity(EnvoyBinaryEntity): @property def is_on(self) -> bool | None: - """Return true if the binary sensor is on.""" - if self.coordinator.data.get("envoy_info"): - update_status = self.coordinator.data.get("envoy_info").get("update_status") - return update_status != "satisfied" - return False - - @property - def extra_state_attributes(self) -> None: - return None + return self.coordinator.data.get(self.entity_description.key) class EnvoyRelayEntity(EnvoyBinaryEntity): diff --git a/custom_components/enphase_envoy/envoy_reader.py b/custom_components/enphase_envoy/envoy_reader.py index 2ded5b4..3129020 100644 --- a/custom_components/enphase_envoy/envoy_reader.py +++ b/custom_components/enphase_envoy/envoy_reader.py @@ -20,7 +20,6 @@ from json.decoder import JSONDecodeError from .envoy_endpoints import ( - ENDPOINT_URL_HOME_JSON, ENDPOINT_URL_INFO_XML, ENDPOINT_URL_PRODUCTION_JSON, ENDPOINT_URL_PRODUCTION_V1, @@ -376,8 +375,6 @@ class EnvoyStandard(EnvoyData): "endpoint_info.envoy_info.device.imeter" # true/false value ) envoy_software_value = "endpoint_info.envoy_info.device.software" - envoy_software_build_epoch_value = "endpoint_home_json.software_build_epoch" - envoy_update_status_value = "endpoint_home_json.update_status" serial_number_value = "endpoint_info.envoy_info.device.sn" grid_profile_value = "endpoint_installer_agf.selected_profile" grid_profiles_available_value = "endpoint_installer_agf.profiles" @@ -387,8 +384,6 @@ def envoy_info(self): return { "pn": self.get("envoy_pn"), "software": self.get("envoy_software"), - "software_build_epoch": self.get("envoy_software_build_epoch"), - "update_status": self.get("envoy_update_status_value"), "model": getattr(self, "ALIAS", self.__class__.__name__[5:]), } @@ -412,21 +407,13 @@ def production_power(self): if force_off != None: return not force_off - # This is a enpower / battery value, if the value is None it will increase - # the cache time of the endpoint, as the information is not required - # to be as up-to-date, since it pretty stale information anyway for - # non-battery setups. - # how to prevent from continuesly fetching home.json when no batteries - @envoy_property(required_endpoint="endpoint_home_json") + @envoy_property(required_endpoint="endpoint_ensemble_inventory") def grid_status(self): - grid_status = self._resolve_path("endpoint_home_json.enpower.grid_status") - if grid_status == None: - # This is the only property we use that actually should be refreshed often. - # So if the value is None (e.g. not found), - # then we ought to cache the result more often. - self.reader.uri_registry["endpoint_home_json"]["cache_time"] = 86400 - - return grid_status + grid_status = self._resolve_path( + "endpoint_ensemble_inventory.[?(@.type=='ENPOWER')].devices[0].mains_oper_state" + ) + if grid_status != None: + return grid_status == "closed" inverters_data_value = path_by_token( owner="endpoint_production_inverters.[?(@.devType==1)]", @@ -697,8 +684,6 @@ def url(endpoint, *a, **kw): url("ensemble_inventory", ENDPOINT_URL_ENSEMBLE_INVENTORY, cache=20) url("ensemble_secctrl", ENDPOINT_URL_ENSEMBLE_SECCTRL, cache=20) url("ensemble_power", ENDPOINT_URL_ENSEMBLE_POWER, cache=20) - # cache for home_json will be set based on grid_status availability - url("home_json", ENDPOINT_URL_HOME_JSON) iurl("devstatus", ENDPOINT_URL_DEVSTATUS, cache=20) iurl("production_power", ENDPOINT_URL_PRODUCTION_POWER, cache=20) url("info", ENDPOINT_URL_INFO_XML, cache=86400) diff --git a/test_data/envoy_metered/endpoint_ensemble_inventory.json b/test_data/envoy_metered/endpoint_ensemble_inventory.json index f838bbe..319337d 100644 --- a/test_data/envoy_metered/endpoint_ensemble_inventory.json +++ b/test_data/envoy_metered/endpoint_ensemble_inventory.json @@ -90,5 +90,43 @@ "encharge_capacity": 3500 } ] - } -] \ No newline at end of file + }, + { + "type":"ENPOWER", + "devices":[ + { + "part_num":"860-00276-r28", + "installed":1621354111, + "serial_num":"xxx", + "device_status":[ + "envoy.global.ok", + "prop.done" + ], + "last_rpt_date":1621464851, + "admin_state":24, + "admin_state_str":"ENPWR_STATE_OPER_CLOSED", + "created_date":1621354111, + "img_load_date":1621354111, + "img_pnum_running":"1.2.2064_release/20.34", + "zigbee_dongle_fw_version":"0x1009", + "operating":true, + "communicating":true, + "temperature":79, + "comm_level_sub_ghz":5, + "comm_level_2_4_ghz":5, + "mains_admin_state":"closed", + "mains_oper_state":"closed", + "Enpwr_grid_mode":"multimode-ongrid", + "Enchg_grid_mode":"multimode-ongrid", + "Enpwr_relay_state_bm":496, + "Enpwr_curr_state_id":16 + } + ] + }, + { + "grid_profile_name":"IEEE 1547 default 2015", + "id":"91937832-159a-410a-9594-0a964372e096:0", + "grid_profile_version":"1.0.11", + "item_count":2997 + } +]