diff --git a/custom_components/enphase_envoy/__init__.py b/custom_components/enphase_envoy/__init__.py index c5dd143..29a498b 100644 --- a/custom_components/enphase_envoy/__init__.py +++ b/custom_components/enphase_envoy/__init__.py @@ -89,6 +89,11 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry) -> bool: disable_negative_production=options.get("disable_negative_production", False), disabled_endpoints=disabled_endpoints, lifetime_production_correction=options.get("lifetime_production_correction", 0), + device_data_endpoint=( + "endpoint_devstatus" + if options.get("devstatus_device_data", False) + else "endpoint_device_data" + ), ) await envoy_reader._sync_store(load=True) diff --git a/custom_components/enphase_envoy/config_flow.py b/custom_components/enphase_envoy/config_flow.py index f1c3728..04f2d58 100644 --- a/custom_components/enphase_envoy/config_flow.py +++ b/custom_components/enphase_envoy/config_flow.py @@ -289,6 +289,10 @@ async def async_step_user(self, user_input=None): "enable_pcu_comm_check", default=self.config_entry.options.get("enable_pcu_comm_check", False), ): bool, + vol.Optional( + "devstatus_device_data", + default=self.config_entry.options.get("devstatus_device_data", False), + ): bool, vol.Optional( "lifetime_production_correction", default=self.config_entry.options.get( diff --git a/custom_components/enphase_envoy/envoy_endpoints.py b/custom_components/enphase_envoy/envoy_endpoints.py index 1a471cb..af8ec6a 100644 --- a/custom_components/enphase_envoy/envoy_endpoints.py +++ b/custom_components/enphase_envoy/envoy_endpoints.py @@ -73,7 +73,7 @@ "url": "https://{}/ivp/pdm/device_data", "cache": 0, "installer_required": False, - "optional": False, + "optional": True, }, "devstatus": { "url": "https://{}/ivp/peb/devstatus", diff --git a/custom_components/enphase_envoy/envoy_reader.py b/custom_components/enphase_envoy/envoy_reader.py index 0a07c97..29e77c7 100644 --- a/custom_components/enphase_envoy/envoy_reader.py +++ b/custom_components/enphase_envoy/envoy_reader.py @@ -75,7 +75,9 @@ def parse_devstatus(data): "dc_current": "dcCurrentINmA", "ac_voltage": "acVoltageINmV", "ac_power": "acPowerINmW", + "gone": "communicating", } + device_type = {1: "pcu", 12: "nsrb"} idd = [] for itemtype, content in data.items(): @@ -96,6 +98,10 @@ def parse_devstatus(data): _LOGGER.debug(f"Found device status field {field}: {value}") if dataset[field].endswith(("mA", "mV", "mHz")): device_data[field] = int(value) / 1000 + elif field == "type": + device_data[field] = device_type.get(value, value) + elif field == "gone": + device_data[field] = not value else: device_data[field] = value idd.append(device_data) @@ -336,6 +342,7 @@ def required_endpoints(self): return self._required_endpoints endpoints = set() + endpoints.add(self.reader.device_data_endpoint) # Loop through all local attributes, and return unique first required jsonpath attribute. for attr in dir(self): @@ -498,17 +505,17 @@ def relay_info(self): "serial_num", ) - @envoy_property(required_endpoint="endpoint_device_data") + @envoy_property() def inverter_device_data(self): - return self._path_to_dict("endpoint_device_data.[?(@.type=='pcu')]", "sn") + return self._path_to_dict( + f"{self.reader.device_data_endpoint}.[?(@.type=='pcu')]", "sn" + ) - @envoy_property(required_endpoint="endpoint_device_data") + @envoy_property() def relay_device_data(self): - return self._path_to_dict("endpoint_device_data.[?(@.type=='nsrb')]", "sn") - - @envoy_property(required_endpoint="endpoint_devstatus") - def inverter_device_status(self): - return self._path_to_dict("endpoint_devstatus.[?(@.type==1)]", "sn") + return self._path_to_dict( + f"{self.reader.device_data_endpoint}.[?(@.type=='nsrb')]", "sn" + ) @envoy_property(required_endpoint="endpoint_ensemble_inventory") def batteries(self): @@ -679,6 +686,7 @@ def __init__( disable_negative_production=False, disabled_endpoints=[], lifetime_production_correction=0, + device_data_endpoint="endpoint_device_data", ): """Init the EnvoyReader.""" self.host = host.lower() @@ -703,6 +711,7 @@ def __init__( self.required_endpoints = set() # in case we would need it.. self.disabled_endpoints = disabled_endpoints self.lifetime_production_correction = lifetime_production_correction + self.device_data_endpoint = device_data_endpoint self.uri_registry = {} for key, endpoint in ENVOY_ENDPOINTS.items(): diff --git a/custom_components/enphase_envoy/sensor.py b/custom_components/enphase_envoy/sensor.py index 888f835..43481a0 100644 --- a/custom_components/enphase_envoy/sensor.py +++ b/custom_components/enphase_envoy/sensor.py @@ -100,24 +100,27 @@ async def async_setup_entry( ) elif sensor_description.key.startswith("inverter_data_"): - _LOGGER.debug(f"Inverter Data Sensor {sensor_description}") if coordinator.data.get("inverter_device_data"): - _LOGGER.debug(f"Inverter Data Sensor DATA {sensor_description}") for inverter in coordinator.data["inverter_device_data"].keys(): - _LOGGER.debug(f"Inverter Data Sensor DATA {inverter}") - device_name = f"Inverter {inverter}" - serial_number = inverter - entities.append( - EnvoyInverterEntity( - description=sensor_description, - name=f"{device_name} {sensor_description.name}", - device_name=device_name, - device_serial_number=serial_number, - serial_number=None, - coordinator=coordinator, - parent_device=config_entry.unique_id, + if ( + coordinator.data["inverter_device_data"][inverter].get( + sensor_description.key[14:] + ) + is not None + ): + device_name = f"Inverter {inverter}" + serial_number = inverter + entities.append( + EnvoyInverterEntity( + description=sensor_description, + name=f"{device_name} {sensor_description.name}", + device_name=device_name, + device_serial_number=serial_number, + serial_number=None, + coordinator=coordinator, + parent_device=config_entry.unique_id, + ) ) - ) elif sensor_description.key.startswith("inverter_info_"): if coordinator.data.get("inverter_info"): @@ -137,35 +140,38 @@ async def async_setup_entry( ) elif sensor_description.key.startswith("relay_data_"): - _LOGGER.debug(f"Relay Data Sensor {sensor_description}") if coordinator.data.get("relay_device_data"): - _LOGGER.debug(f"Relay Data Sensor DATA {sensor_description}") for relay in coordinator.data["relay_device_data"].keys(): - _LOGGER.debug(f"Relay Data Sensor DATA {relay}") - device_name = f"Relay {relay}" - serial_number = relay - - if sensor_description.key.endswith(("l1", "l2", "l3")): - line = sensor_description.key[-2:].replace("l", "line") - line_connected = ( - coordinator.data.get("relay_info", {}) - .get(relay, {}) - .get(f"{line}-connected") + if ( + coordinator.data["relay_device_data"][relay].get( + sensor_description.key[11:] ) - if line_connected is False: - continue - - entities.append( - EnvoyRelayEntity( - description=sensor_description, - name=f"{device_name} {sensor_description.name}", - device_name=device_name, - device_serial_number=serial_number, - serial_number=None, - coordinator=coordinator, - parent_device=config_entry.unique_id, + is not None + ): + device_name = f"Relay {relay}" + serial_number = relay + + if sensor_description.key.endswith(("l1", "l2", "l3")): + line = sensor_description.key[-2:].replace("l", "line") + line_connected = ( + coordinator.data.get("relay_info", {}) + .get(relay, {}) + .get(f"{line}-connected") + ) + if line_connected is False: + continue + + entities.append( + EnvoyRelayEntity( + description=sensor_description, + name=f"{device_name} {sensor_description.name}", + device_name=device_name, + device_serial_number=serial_number, + serial_number=None, + coordinator=coordinator, + parent_device=config_entry.unique_id, + ) ) - ) elif sensor_description.key.startswith("relay_info_"): if coordinator.data.get("relay_info"): diff --git a/custom_components/enphase_envoy/strings.json b/custom_components/enphase_envoy/strings.json index cff469b..462a059 100644 --- a/custom_components/enphase_envoy/strings.json +++ b/custom_components/enphase_envoy/strings.json @@ -36,6 +36,7 @@ "enable_additional_metrics": "[Metered only] Enable additional metrics like total amps, frequency, apparent and reactive power and power factor.", "disable_installer_account_use": "Do not collect data that requires installer or DIY enphase account", "enable_pcu_comm_check": "Enable powerline communication level sensors (slow)", + "devstatus_device_data": "Use alternative endpoint 'devstatus' (installer account only) for device sensors", "lifetime_production_correction": "Correction of lifetime production value (Wh)", "disabled_endpoints": "[Advanced] Disabled Envoy endpoints" }, diff --git a/custom_components/enphase_envoy/translations/en.json b/custom_components/enphase_envoy/translations/en.json index f42fc8b..e570f8b 100644 --- a/custom_components/enphase_envoy/translations/en.json +++ b/custom_components/enphase_envoy/translations/en.json @@ -35,6 +35,7 @@ "enable_additional_metrics": "[Envoy-S Metered] Enable additional metrics like total amps, frequency, apparent and reactive power and power factor.", "disable_installer_account_use": "Do not collect data that requires installer or DIY enphase account", "enable_pcu_comm_check": "Enable powerline communication level sensors (slow)", + "devstatus_device_data": "Use alternative endpoint 'devstatus' (installer account only) for device sensors", "lifetime_production_correction": "Correction of lifetime production value (Wh)", "disabled_endpoints": "[Advanced] Disabled Envoy endpoints" }, diff --git a/custom_components/enphase_envoy/translations/nl.json b/custom_components/enphase_envoy/translations/nl.json index 6f940d2..967a9e5 100644 --- a/custom_components/enphase_envoy/translations/nl.json +++ b/custom_components/enphase_envoy/translations/nl.json @@ -35,6 +35,7 @@ "enable_additional_metrics": "[Envoy-S Metered] 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", "enable_pcu_comm_check": "Powerline communication level sensors inschakelen (langzaam)", + "devstatus_device_data": "Gebruik alternatief endpoint 'devstatus' (alleen installer account) voor apparaat sensoren", "lifetime_production_correction": "Correctie van lifetime production waarde (Wh)", "disabled_endpoints": "[Geavanceerd] Uitgeschakelde Envoy endpoints" },