diff --git a/custom_components/solaredge_modbus_multi/binary_sensor.py b/custom_components/solaredge_modbus_multi/binary_sensor.py index 89f18378..5985680a 100644 --- a/custom_components/solaredge_modbus_multi/binary_sensor.py +++ b/custom_components/solaredge_modbus_multi/binary_sensor.py @@ -4,7 +4,10 @@ import logging -from homeassistant.components.binary_sensor import BinarySensorEntity +from homeassistant.components.binary_sensor import ( + BinarySensorDeviceClass, + BinarySensorEntity, +) from homeassistant.config_entries import ConfigEntry from homeassistant.core import HomeAssistant, callback from homeassistant.helpers.entity import EntityCategory @@ -30,6 +33,9 @@ async def async_setup_entry( if hub.option_detect_extras and inverter.advanced_power_control: entities.append(AdvPowerControlEnabled(inverter, config_entry, coordinator)) + if hub.option_detect_extras: + entities.append(GridStatusOnOff(inverter, config_entry, coordinator)) + if entities: async_add_entities(entities) @@ -92,3 +98,32 @@ def name(self) -> str: @property def is_on(self) -> bool: return self._platform.decoded_model["AdvPwrCtrlEn"] == 0x1 + + +class GridStatusOnOff(SolarEdgeBinarySensorBase): + """Grid Status On Off. This is undocumented from discussions.""" + + device_class = BinarySensorDeviceClass.POWER + icon = "mdi:transmission-tower" + + @property + def available(self) -> bool: + return ( + super().available and "I_Grid_Status" in self._platform.decoded_model.keys() + ) + + @property + def unique_id(self) -> str: + return f"{self._platform.uid_base}_grid_status_on_off" + + @property + def name(self) -> str: + return "Grid Status" + + @property + def entity_registry_enabled_default(self) -> bool: + return "I_Grid_Status" in self._platform.decoded_model.keys() + + @property + def is_on(self) -> bool: + return not self._platform.decoded_model["I_Grid_Status"] diff --git a/custom_components/solaredge_modbus_multi/hub.py b/custom_components/solaredge_modbus_multi/hub.py index e19f6b1c..b9038e8e 100644 --- a/custom_components/solaredge_modbus_multi/hub.py +++ b/custom_components/solaredge_modbus_multi/hub.py @@ -753,6 +753,7 @@ def __init__(self, device_id: int, hub: SolarEdgeModbusMultiHub) -> None: self.global_power_control = None self.advanced_power_control = None self.site_limit_control = None + self._grid_status = None async def init_device(self) -> None: """Set up data about the device from modbus.""" @@ -1300,6 +1301,45 @@ async def read_modbus_data(self) -> None: f"No response from inverter ID {self.inverter_unit_id}" ) + """ Grid On/Off Status """ + if self._grid_status is not False: + try: + inverter_data = await self.hub.modbus_read_holding_registers( + unit=self.inverter_unit_id, address=40113, rcount=2 + ) + + decoder = BinaryPayloadDecoder.fromRegisters( + inverter_data.registers, + byteorder=Endian.BIG, + wordorder=Endian.LITTLE, + ) + + self.decoded_model.update( + OrderedDict( + [ + ("I_Grid_Status", decoder.decode_32bit_uint()), + ] + ) + ) + self._grid_status = True + + except ModbusIllegalAddress: + try: + del self.decoded_model["I_Grid_Status"] + except KeyError: + pass + + self._grid_status = False + + _LOGGER.debug( + (f"I{self.inverter_unit_id}: " "Grid On/Off NOT available") + ) + + except ModbusIOError: + raise ModbusReadError( + f"No response from inverter ID {self.inverter_unit_id}" + ) + for name, value in iter(self.decoded_model.items()): if isinstance(value, float): display_value = float_to_hex(value) diff --git a/custom_components/solaredge_modbus_multi/manifest.json b/custom_components/solaredge_modbus_multi/manifest.json index 80783116..2f6fbea3 100644 --- a/custom_components/solaredge_modbus_multi/manifest.json +++ b/custom_components/solaredge_modbus_multi/manifest.json @@ -10,5 +10,5 @@ "issue_tracker": "https://github.com/WillCodeForCats/solaredge-modbus-multi/issues", "loggers": ["custom_components.solaredge_modbus_multi"], "requirements": ["pymodbus>=3.6.6"], - "version": "2.4.16" + "version": "2.4.18" }