Skip to content

Commit

Permalink
Update documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
fboundy committed Nov 28, 2024
1 parent 9e13cb8 commit 331d599
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 20 deletions.
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,54 @@
# ❗Request for maintainers
As you might have noticed I'm having trouble to spend enough time on maintaining this integration. For the continuity of this integration it would be great if it could be maintained and further developed by a small team of volunteers. Are you interested and do you have coding experience? [Drop me a line](https://github.com/hultenvp/solis-sensor/discussions/376).

# Control Beta Test

This repo includes a beta version of device control using the same API as the SolisCloud app. This opeartes slighty differently depending on your HMI firmware version. This should be detected automatically:

## Version 4A00 and Earlier

The following controls should update the inverter immediately:

- Energy Storage Control Switch
- Overdischarge SOC
- Force Charge SOC
- Backup SOC

The timed change controls are all sent to the API using one command and so they won't update untill the Update Charge/Discharge button is pressed. The controls included in this are all three sets of the following (where N is slots 1-3)
- Timed Charge Current N
- Timed Charge Start Time N
- Timed Charge End Time N
- Timed Discharge Current N
- Timed Discharge Start Time N
- Timed Discharge End Time N

<b>Note that all three slots are sent at the same time</b>

## Version 4B00 and Later

Six slots are available and include an SOC limit and a voltage (though the purpose of the voltage is not clear). Only the start and end times for each Charge/Discharge slot need top to be sent to the inverter together so the following are updated immediately (where N is slot 1-6):
- Energy Storage Control Switch (fewer available modes than pre-4B00)
- Overdischarge SOC
- Force Charge SOC
- Backup SOC
- Timed Charge Current N
- Timed Charge SOC N
- Timed Charge Voltage N
- Timed Discharge Current N
- Timed Discharge SOC N
- Timed Discharge Voltage N

Each pair of start/end times has an associated button pushfor charge there are 6:

- Timed Charge Start Time N
- Timed Charge End Time N
- Button Update Charge Time N

And discharge:
- Timed Discharge Start Time N
- Timed Discharge End Time N
- Button Update Discharge Time N

# SolisCloud sensor integration
HomeAssistant sensor for SolisCloud portal.
Still questions after the readme? Read the [wiki](https://github.com/hultenvp/solis-sensor/wiki) or look at the [discussions page](https://github.com/hultenvp/solis-sensor/discussions)
Expand Down
5 changes: 4 additions & 1 deletion custom_components/solis/button.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,4 +93,7 @@ def do_update(self, value, last_updated):
async def async_press(self) -> None:
"""Handle the button press."""
for entity in self._entities:
_LOGGER.debug(f"{entity.name:s} {entity.state} {entity.index}")
_LOGGER.debug(f"{entity.name:s} {entity.to_string:s} {entity.index}")
value = self. _joiner.join([entity.to_string for entity in self._entities])
_LOGGER.debug(f"{self._cid} {value}")
await self.write_control_data(value)
3 changes: 3 additions & 0 deletions custom_components/solis/number.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,9 @@ def do_update(self, value, last_updated):
return True
return False

def to_string(self):
return str(self._attr_native_value)

async def async_set_native_value(self, value: float) -> None:
_LOGGER.debug(f"async_set_native_value for {self._name}")
self._attr_native_value = value
Expand Down
9 changes: 6 additions & 3 deletions custom_components/solis/soliscloud_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ def _collect_inverter_data(self, payload: dict[str, Any]) -> None:
if value is not None:
self._data[dictkey] = value

async def get_control_data(self, device_serial: str) -> dict[str, Any] | None:
async def get_control_data(self, device_serial: str, cid="") -> dict[str, Any] | None:
control_data = {}

if device_serial not in self._hmi_fb00:
Expand Down Expand Up @@ -454,7 +454,10 @@ async def get_control_data(self, device_serial: str) -> dict[str, Any] | None:
_LOGGER.debug(f"Unable to determine HMI firmware version for Inverter SN {device_serial}")

if device_serial in self._hmi_fb00:
controls = ALL_CONTROLS[self._hmi_fb00[device_serial]]
if cid == "":
controls = ALL_CONTROLS[self._hmi_fb00[device_serial]]
else:
controls=[cid]
for cid in controls:
params = {"inverterSn": str(device_serial), "cid": str(cid)}
result = await self._post_data_json(AT_READ, params, csrf=True)
Expand Down Expand Up @@ -764,7 +767,7 @@ async def write_control_data(self, device_serial: str, cid: str, value: str):
if jsondata["code"] == "0":
_LOGGER.debug(f"Set code returned OK. Reading code back.")
await asyncio.sleep(CONTROL_DELAY)
control_data = await self.get_control_data(device_serial, [cid])
control_data = await self.get_control_data(device_serial, cid=str(cid))
_LOGGER.debug(f"Data read back: {control_data.get(str(cid), None)}")

else:
Expand Down
42 changes: 26 additions & 16 deletions custom_components/solis/time.py
Original file line number Diff line number Diff line change
Expand Up @@ -99,27 +99,37 @@ def do_update(self, value, last_updated):
# return super().do_update(value, last_updated)
_LOGGER.debug(f"Update state for {self._name}")
_LOGGER.debug(f">>> Initial value: {value}")
value = self.split(value).split(":")
_LOGGER.debug(f">>> Split value: {value}")
value = datetime(
year=YEAR,
month=MONTH,
day=DAY,
hour=int(value[0]),
minute=int(value[1]),
).time()
_LOGGER.debug(f">>> Datetime value: {value}")

if self.hass and self._attr_native_value != value:
self._attr_native_value = value
values = self.split(value).split(":")
_LOGGER.debug(f">>> Split value: {values}")
time_value = None
try:
time_value = datetime(
year=YEAR,
month=MONTH,
day=DAY,
hour=int(values[0]),
minute=int(values[1]),
).time()
_LOGGER.debug(f">>> Datetime value: {time_value}")
except:
_LOGGER.debug("Unable to convert {value} to time")

if time_value is None:
return False
elif self.hass and self._attr_native_value != time_value:
self._attr_native_value = time_value
self._attributes[LAST_UPDATED] = last_updated
self.async_write_ha_state()
return True
return False

async def async_set_native_value(self, value: float) -> None:
_LOGGER.debug(f"async_set_native_value for {self._name}")
@property
def to_string(self):
return self._attr_native_value.strftime('%H,%M')

async def async_set_value(self, value: float) -> None:
_LOGGER.debug(f"async_set_value to {value} for {self._name}")
self._attr_native_value = value
self._attributes[LAST_UPDATED] = datetime.now()
self.async_write_ha_state()
# await self.write_control_data(str(value))
#await self.write_control_data(str(value))

0 comments on commit 331d599

Please sign in to comment.