Skip to content

Commit

Permalink
Merge pull request #137 from vincentwolsink/deprecate_home_json
Browse files Browse the repository at this point in the history
Stop reading from home.json
  • Loading branch information
vincentwolsink authored Aug 2, 2024
2 parents fbb3134 + 1d34f1d commit 05f7297
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 110 deletions.
106 changes: 19 additions & 87 deletions custom_components/enphase_envoy/binary_sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
COORDINATOR,
DOMAIN,
NAME,
READER,
BINARY_SENSORS,
resolve_hardware_id,
get_model_name,
Expand All @@ -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:
Expand All @@ -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:
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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):
Expand Down
27 changes: 6 additions & 21 deletions custom_components/enphase_envoy/envoy_reader.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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"
Expand All @@ -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:]),
}

Expand All @@ -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)]",
Expand Down Expand Up @@ -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)
Expand Down
42 changes: 40 additions & 2 deletions test_data/envoy_metered/endpoint_ensemble_inventory.json
Original file line number Diff line number Diff line change
Expand Up @@ -90,5 +90,43 @@
"encharge_capacity": 3500
}
]
}
]
},
{
"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
}
]

0 comments on commit 05f7297

Please sign in to comment.