Skip to content

Commit

Permalink
Merge pull request #42 from mpredfearn/mpredfearn/add_export_control
Browse files Browse the repository at this point in the history
Add export control
  • Loading branch information
binsentsu authored Aug 1, 2022
2 parents fada071 + b4a9fe9 commit 6214dd9
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 5 deletions.
43 changes: 40 additions & 3 deletions custom_components/solaredge_modbus/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
DEFAULT_READ_BATTERY1,
DEFAULT_READ_BATTERY2,
BATTERY_STATUSSES,
EXPORT_CONTROL_MODE,
EXPORT_CONTROL_LIMIT_MODE,
STOREDGE_CONTROL_MODE,
STOREDGE_AC_CHARGE_POLICY,
STOREDGE_CHARGE_DISCHARGE_MODE
Expand Down Expand Up @@ -208,6 +210,16 @@ def connect(self):
with self._lock:
self._client.connect()

@property
def has_meter(self):
"""Return true if a meter is available"""
return self.read_meter1 or self.read_meter2 or self.read_meter3

@property
def has_battery(self):
"""Return true if a battery is available"""
return self.read_battery1 or self.read_battery2

def read_holding_registers(self, unit, address, count):
"""Read holding registers."""
with self._lock:
Expand Down Expand Up @@ -669,15 +681,40 @@ def read_modbus_data_inverter(self):
return False

def read_modbus_data_storage(self):
if not self.read_battery1 and not self.read_battery2:
return True
if self.has_battery:
count = 0x12 # Read storedge block as well
elif self.has_meter:
count = 4 # Just read export control block
else:
return True # Nothing to read here

storage_data = self.read_holding_registers(unit=1, address=57348, count=14)
storage_data = self.read_holding_registers(unit=1, address=0xE000, count=count)
if not storage_data.isError():
decoder = BinaryPayloadDecoder.fromRegisters(
storage_data.registers, byteorder=Endian.Big,wordorder=Endian.Little
)

#0xE000 - 1 - Export control mode
export_control_mode = decoder.decode_16bit_uint() & 7
if export_control_mode in EXPORT_CONTROL_MODE:
self.data["export_control_mode"] = EXPORT_CONTROL_MODE[export_control_mode]
else:
self.data["export_control_mode"] = export_control_mode

#0xE001 - 1 - Export control limit mode
export_control_limit_mode = decoder.decode_16bit_uint() & 1
if export_control_limit_mode in EXPORT_CONTROL_MODE:
self.data["export_control_limit_mode"] = EXPORT_CONTROL_LIMIT_MODE[export_control_limit_mode]
else:
self.data["export_control_limit_mode"] = export_control_limit_mode

#0xE002 - 2 - Export control site limit
self.data["export_control_site_limit"] = round(decoder.decode_32bit_float(), 3)

if not self.has_battery:
# Done with the export control block
return True

#0xE004 - 1 - storage control mode
storage_control_mode = decoder.decode_16bit_uint()
if storage_control_mode in STOREDGE_CONTROL_MODE:
Expand Down
21 changes: 21 additions & 0 deletions custom_components/solaredge_modbus/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,18 @@
10: "Sleep"
}

EXPORT_CONTROL_MODE = {
0: "Disabled",
1: "Direct Export Limitation",
2: "Indirect Export Limitation",
4: "Production Limitation"
}

EXPORT_CONTROL_LIMIT_MODE = {
0: "Total",
1: "Per phase"
}

STOREDGE_CONTROL_MODE = {
0: "Disabled",
1: "Maximize Self Consumption",
Expand All @@ -308,6 +320,15 @@
7: "Maximize self consumption",
}

EXPORT_CONTROL_SELECT_TYPES = [
["Export control mode", "export_control_mode", 0xE000, EXPORT_CONTROL_MODE],
["Export control limit mode", "export_control_limit_mode", 0xE001, EXPORT_CONTROL_LIMIT_MODE],
]

EXPORT_CONTROL_NUMBER_TYPES = [
["Export control site limit", "export_control_site_limit", 0xE002, "f", {"min": 0, "max": 10000, "unit": "W"}],
]

STORAGE_SELECT_TYPES = [
["Storage Control Mode", "storage_contol_mode", 0xE004, STOREDGE_CONTROL_MODE],
["Storage AC Charge Policy", "storage_ac_charge_policy", 0xE005, STOREDGE_AC_CHARGE_POLICY],
Expand Down
19 changes: 18 additions & 1 deletion custom_components/solaredge_modbus/number.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from .const import (
DOMAIN,
ATTR_MANUFACTURER,
EXPORT_CONTROL_NUMBER_TYPES,
STORAGE_NUMBER_TYPES,
)

Expand Down Expand Up @@ -32,7 +33,23 @@ async def async_setup_entry(hass, entry, async_add_entities) -> None:

entities = []

if hub.read_battery1 == True or hub.read_battery2 == True:
# If a meter is available add export control
if hub.has_meter:
for number_info in EXPORT_CONTROL_NUMBER_TYPES:
number = SolarEdgeNumber(
hub_name,
hub,
device_info,
number_info[0],
number_info[1],
number_info[2],
number_info[3],
number_info[4],
)
entities.append(number)

# If a battery is available add storage control
if hub.has_battery:
for number_info in STORAGE_NUMBER_TYPES:
number = SolarEdgeNumber(
hub_name,
Expand Down
18 changes: 17 additions & 1 deletion custom_components/solaredge_modbus/select.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
from .const import (
DOMAIN,
ATTR_MANUFACTURER,
EXPORT_CONTROL_SELECT_TYPES,
STORAGE_SELECT_TYPES,
)

Expand All @@ -29,7 +30,22 @@ async def async_setup_entry(hass, entry, async_add_entities) -> None:

entities = []

if hub.read_battery1 == True or hub.read_battery2 == True:
# If a meter is available add export control
if hub.has_meter:
for select_info in EXPORT_CONTROL_SELECT_TYPES:
select = SolarEdgeSelect(
hub_name,
hub,
device_info,
select_info[0],
select_info[1],
select_info[2],
select_info[3],
)
entities.append(select)

# If a battery is available add storage control
if hub.has_battery:
for select_info in STORAGE_SELECT_TYPES:
select = SolarEdgeSelect(
hub_name,
Expand Down

0 comments on commit 6214dd9

Please sign in to comment.