Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions custom_components/solaredge_modbus_multi/helpers.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import struct


def scale_factor(value: int, sf: int):
try:
return value * (10 ** sf)
Expand All @@ -9,6 +12,10 @@ def watts_to_kilowatts(value):
return round(value * 0.001, 3)


def float_to_hex(f):
return hex(struct.unpack("<I", struct.pack("<f", f))[0])


def parse_modbus_string(s: str) -> str:
s = s.decode(encoding="utf-8", errors="ignore")
s = s.replace("\x00", "").rstrip()
Expand Down
132 changes: 89 additions & 43 deletions custom_components/solaredge_modbus_multi/sensor.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
SUNSPEC_SF_RANGE,
VENDOR_STATUS,
)
from .helpers import scale_factor, update_accum, watts_to_kilowatts
from .helpers import float_to_hex, scale_factor, update_accum, watts_to_kilowatts

_LOGGER = logging.getLogger(__name__)

Expand Down Expand Up @@ -256,17 +256,45 @@ def extra_state_attributes(self):
attrs = {}

try:
attrs["batt_charge_peak"] = self._platform.decoded_common[
"B_MaxChargePeakPower"
]
attrs["batt_discharge_peak"] = self._platform.decoded_common[
"B_MaxDischargePeakPower"
]
attrs["batt_max_charge"] = self._platform.decoded_common["B_MaxChargePower"]
attrs["batt_max_discharge"] = self._platform.decoded_common[
"B_MaxDischargePower"
]
attrs["batt_rated_energy"] = self._platform.decoded_common["B_RatedEnergy"]
if (
float_to_hex(self._platform.decoded_common["B_MaxChargePeakPower"])
!= 0xFF7FFFFF
):
attrs["batt_charge_peak"] = self._platform.decoded_common[
"B_MaxChargePeakPower"
]

if (
float_to_hex(self._platform.decoded_common["B_MaxDischargePeakPower"])
!= 0xFF7FFFFF
):
attrs["batt_discharge_peak"] = self._platform.decoded_common[
"B_MaxDischargePeakPower"
]

if (
float_to_hex(self._platform.decoded_common["B_MaxChargePower"])
!= 0xFF7FFFFF
):
attrs["batt_max_charge"] = self._platform.decoded_common[
"B_MaxChargePower"
]

if (
float_to_hex(self._platform.decoded_common["B_MaxDischargePower"])
!= 0xFF7FFFFF
):
attrs["batt_max_discharge"] = self._platform.decoded_common[
"B_MaxDischargePower"
]

if (
float_to_hex(self._platform.decoded_common["B_RatedEnergy"])
!= 0xFF7FFFFF
):
attrs["batt_rated_energy"] = self._platform.decoded_common[
"B_RatedEnergy"
]

except KeyError:
pass
Expand Down Expand Up @@ -1466,10 +1494,12 @@ def name(self) -> str:
def native_value(self):
try:
if (
self._platform.decoded_model["B_Temp_Average"]
float_to_hex(self._platform.decoded_model["B_Temp_Average"])
== SUNSPEC_NOT_IMPL_FLOAT32
or self._platform.decoded_model["B_Temp_Average"] == 0xFF7FFFFF
or self._platform.decoded_model["B_Temp_Average"] == 0x7F7FFFFF
or float_to_hex(self._platform.decoded_model["B_Temp_Average"])
== 0xFF7FFFFF
or float_to_hex(self._platform.decoded_model["B_Temp_Average"])
== 0x7F7FFFFF
):
return None

Expand Down Expand Up @@ -1497,9 +1527,12 @@ def entity_registry_enabled_default(self) -> bool:
def native_value(self):
try:
if (
self._platform.decoded_model["B_Temp_Max"] == SUNSPEC_NOT_IMPL_FLOAT32
or self._platform.decoded_model["B_Temp_Max"] == 0xFF7FFFFF
or self._platform.decoded_model["B_Temp_Max"] == 0x7F7FFFFF
float_to_hex(self._platform.decoded_model["B_Temp_Max"])
== SUNSPEC_NOT_IMPL_FLOAT32
or float_to_hex(self._platform.decoded_model["B_Temp_Max"])
== 0xFF7FFFFF
or float_to_hex(self._platform.decoded_model["B_Temp_Max"])
== 0x7F7FFFFF
):
return None

Expand All @@ -1515,9 +1548,12 @@ class SolarEdgeBatteryVoltage(DCVoltage):
def native_value(self):
try:
if (
self._platform.decoded_model["B_DC_Voltage"] == SUNSPEC_NOT_IMPL_FLOAT32
or self._platform.decoded_model["B_DC_Voltage"] == 0xFF7FFFFF
or self._platform.decoded_model["B_DC_Voltage"] == 0x7F7FFFFF
float_to_hex(self._platform.decoded_model["B_DC_Voltage"])
== SUNSPEC_NOT_IMPL_FLOAT32
or float_to_hex(self._platform.decoded_model["B_DC_Voltage"])
== 0xFF7FFFFF
or float_to_hex(self._platform.decoded_model["B_DC_Voltage"])
== 0x7F7FFFFF
):
return None

Expand All @@ -1536,9 +1572,12 @@ class SolarEdgeBatteryCurrent(DCCurrent):
def native_value(self):
try:
if (
self._platform.decoded_model["B_DC_Current"] == SUNSPEC_NOT_IMPL_FLOAT32
or self._platform.decoded_model["B_DC_Current"] == 0xFF7FFFFF
or self._platform.decoded_model["B_DC_Current"] == 0x7F7FFFFF
float_to_hex(self._platform.decoded_model["B_DC_Current"])
== SUNSPEC_NOT_IMPL_FLOAT32
or float_to_hex(self._platform.decoded_model["B_DC_Current"])
== 0xFF7FFFFF
or float_to_hex(self._platform.decoded_model["B_DC_Current"])
== 0x7F7FFFFF
):
return None

Expand All @@ -1559,9 +1598,12 @@ class SolarEdgeBatteryPower(DCPower):
def native_value(self):
try:
if (
self._platform.decoded_model["B_DC_Power"] == SUNSPEC_NOT_IMPL_FLOAT32
or self._platform.decoded_model["B_DC_Power"] == 0xFF7FFFFF
or self._platform.decoded_model["B_DC_Power"] == 0x7F7FFFFF
float_to_hex(self._platform.decoded_model["B_DC_Power"])
== SUNSPEC_NOT_IMPL_FLOAT32
or float_to_hex(self._platform.decoded_model["B_DC_Power"])
== 0xFF7FFFFF
or float_to_hex(self._platform.decoded_model["B_DC_Power"])
== 0x7F7FFFFF
):
return None

Expand Down Expand Up @@ -1673,9 +1715,10 @@ def name(self) -> str:
@property
def native_value(self):
if (
self._platform.decoded_model["B_Energy_Max"] == SUNSPEC_NOT_IMPL_FLOAT32
or self._platform.decoded_model["B_Energy_Max"] == 0xFF7FFFFF
or self._platform.decoded_model["B_Energy_Max"] == 0x7F7FFFFF
float_to_hex(self._platform.decoded_model["B_Energy_Max"])
== SUNSPEC_NOT_IMPL_FLOAT32
or float_to_hex(self._platform.decoded_model["B_Energy_Max"]) == 0xFF7FFFFF
or float_to_hex(self._platform.decoded_model["B_Energy_Max"]) == 0x7F7FFFFF
):
return None

Expand Down Expand Up @@ -1703,10 +1746,12 @@ def name(self) -> str:
@property
def native_value(self):
if (
self._platform.decoded_model["B_Energy_Available"]
float_to_hex(self._platform.decoded_model["B_Energy_Available"])
== SUNSPEC_NOT_IMPL_FLOAT32
or self._platform.decoded_model["B_Energy_Available"] == 0xFF7FFFFF
or self._platform.decoded_model["B_Energy_Available"] == 0x7F7FFFFF
or float_to_hex(self._platform.decoded_model["B_Energy_Available"])
== 0xFF7FFFFF
or float_to_hex(self._platform.decoded_model["B_Energy_Available"])
== 0x7F7FFFFF
):
return None

Expand Down Expand Up @@ -1736,9 +1781,10 @@ def name(self) -> str:
@property
def native_value(self):
if (
self._platform.decoded_model["B_SOH"] == SUNSPEC_NOT_IMPL_FLOAT32
or self._platform.decoded_model["B_SOH"] == 0xFF7FFFFF
or self._platform.decoded_model["B_SOH"] == 0x7F7FFFFF
float_to_hex(self._platform.decoded_model["B_SOH"])
== SUNSPEC_NOT_IMPL_FLOAT32
or float_to_hex(self._platform.decoded_model["B_SOH"]) == 0xFF7FFFFF
or float_to_hex(self._platform.decoded_model["B_SOH"]) == 0x7F7FFFFF
or self._platform.decoded_model["B_SOH"] < 0
or self._platform.decoded_model["B_SOH"] > 100
):
Expand Down Expand Up @@ -1767,9 +1813,10 @@ def name(self) -> str:
@property
def native_value(self):
if (
self._platform.decoded_model["B_SOE"] == SUNSPEC_NOT_IMPL_FLOAT32
or self._platform.decoded_model["B_SOE"] == 0xFF7FFFFF
or self._platform.decoded_model["B_SOE"] == 0x7F7FFFFF
float_to_hex(self._platform.decoded_model["B_SOE"])
== SUNSPEC_NOT_IMPL_FLOAT32
or float_to_hex(self._platform.decoded_model["B_SOE"]) == 0xFF7FFFFF
or float_to_hex(self._platform.decoded_model["B_SOE"]) == 0x7F7FFFFF
or self._platform.decoded_model["B_SOE"] < 0
or self._platform.decoded_model["B_SOE"] > 100
):
Expand Down Expand Up @@ -1800,10 +1847,9 @@ def extra_state_attributes(self):
attrs = {}

try:
if self._platform.decoded_model["B_Status"] in BATTERY_STATUS:
attrs["status_text"] = BATTERY_STATUS[
self._platform.decoded_model["B_Status"]
]
attrs["status_text"] = BATTERY_STATUS[
self._platform.decoded_model["B_Status"]
]

except KeyError:
pass
Expand Down