StephanJoubert / home_assistant_solarman

Home Assistant component for Solarman collectors used with a variety of inverters.
Apache License 2.0
507 stars 191 forks source link

Passive mode and forced charge/discharge on sofar_g3hyd.yaml #571

Closed vermut closed 1 month ago

vermut commented 2 months ago

As you know, there are secret codes to enable passive mode and manually force charge/discharge. image

This is useful when you want fine control of your charging combined with EMHASS for example.

I was wondering why it's not implemented yet as a read registers? Should I do it or there is a community policy or opinion?

And what about writing registers to set this mode? Can this integration do that somehow or it's purely read mode and I should just implement those modbus calls separately?

Sample force-discharge 1000W code

from pysolarmanv5.pysolarmanv5 import PySolarmanV5

sofar = PySolarmanV5('172.16.x.x', 2222222222, verbose=True)
sofar.write_multiple_holding_registers(register_addr=4368, values=[3])
print(sofar.read_holding_registers(register_addr=4368, quantity=1))
sofar.write_multiple_holding_registers(register_addr=4487, values=[0xFFFF, 0xFC18, 0xFFFF, 0xFC18, 0xFFFF, 0xFC18])
execcr commented 1 month ago

Have you tried your code? just to know

vermut commented 1 month ago

Yes, it works for me. Here is a nicer version:

from pysolarmanv5.pysolarmanv5 import PySolarmanV5

sofar = PySolarmanV5('172.16.10.211', 2700663862, verbose=True)

MODE_SELF_USE = 0
MODE_TIME_OF_USE = 1
MODE_PASSIVE = 3

def set_passive_mode(charge_rate: int):
    set_mode(MODE_PASSIVE)

    # Convert charge_rate to two 16-bit words
    high_word = (charge_rate >> 16) & 0xFFFF
    low_word = charge_rate & 0xFFFF

    # Repeat the words three times
    values = [high_word, low_word] * 3

    ret = sofar.write_multiple_holding_registers(register_addr=4487, values=values)
    assert ret == len(values), "Wrong number of values returned"

def set_mode(mode):
    ret = sofar.read_holding_registers(register_addr=4368, quantity=1)
    if ret != [mode]:
        print("Updating mode")
        ret = sofar.write_multiple_holding_registers(register_addr=4368, values=[mode])
        assert ret == 1, "Wrong number of values returned"

# set_passive_mode(-10000)
set_mode(MODE_SELF_USE)

I'm just asking if I need another integration to WRITE data or @StephanJoubert 's solution has place for it.

vermut commented 1 month ago

Actually I just realized that there is write register service call and it works. So I'd just create a helper to properly parse negative values for passivemode discharge.

service: solarman.write_multiple_holding_registers
data:
  register: 4368
  values: 0