Giter VIP home page Giter VIP logo

deye-controller's Introduction

DEYE-controller

  • A library and simple tools for interaction with DEYE hybrid inverters
  • The communication with the inverter requires a SOLARMAN datalogger
  • pysloarmanv5 based library
  • Command line tools (exposed after install):
    • deye-read - read everything from the inverter (use --help for filters/options)
    • deye-regcheck - for quick check on specific register(s)
    • deye-scan is a scanner for dataloggers in the local network (not DEYE related)
    • deye-regwrite - for writing to individual registers
  • Tested with:
    • SUN-12K-SG04LP3 / LSW-3

INSTALL

pip install deye-controller

TODO List

  • Support single phase inverters, eventually with auto detection.

Examples

  • Basic usage:

    • read a register from the inverter
    >>> from deye_controller import HoldingRegisters, WritableRegisters
    >>> from pysolarmanv5 import PySolarmanV5
    >>> inv = PySolarmanV5('192.168.1.100', 2712345678)
    >>> register = HoldingRegisters.BMSBatteryCapacity
    >>> res = inv.read_holding_registers(register.address, register.len)
    >>> register.value = res[0] if register.len == 1 else res
    >>> print(register.description, register.format(), register.suffix)
    bms_battery_SOC 24 %
    >>> inv.disconnect()
    • write
    >>> from deye_controller import HoldingRegisters, WritableRegisters
    >>> from pysolarmanv5 import PySolarmanV5
    >>> inv = PySolarmanV5('192.168.1.100', 2712345678)
    >>> register = WritableRegisters.SellModeSOC3
    >>> register.set(23)
    
    >>> inv.write_multiple_holding_registers(register.address, [register.modbus_value])
    1
    >>> inv.disconnect()
  • SellMode programming:

    >>> from deye_controller import SellProgrammer
    >>> prog = SellProgrammer('192.168.1.108', 2799999999)
    >>> prog.show_as_screen()
    ____________________________________________________
    | Grid  |  Gen  |      Time     |   Pwr    |  SOC % |
    |       |       | 00:00 | 03:00 |     3500 |   100% |
    |       |       | 03:00 | 04:00 |     3500 |    30% |
    |       |       | 04:00 | 05:00 |     3500 |    30% |
    |       |       | 05:00 | 10:00 |     3500 |    30% |
    |       |       | 10:00 | 23:00 |     3500 |   100% |
    |       |       | 23:00 | 00:00 |     3500 |    30% |
    ----------------------------------------------------
    >>> prog.update_program(3, start_t='6:30', power=2500, soc=35, grid_ch=True)
    Program updated
     >>> prog.show_as_screen()  # For visual confirmation of the settings
    ____________________________________________________
    | Grid  |  Gen  |      Time     |   Pwr    |  SOC % |
    |       |       | 00:00 | 03:00 |     3500 |   100% |
    |       |       | 03:00 | 04:00 |     3500 |    30% |
    |       |       | 04:00 | 06:30 |     3500 |    30% |
    ||       | 06:30 | 10:00 |     2500 |    35% |
    |       |       | 10:00 | 23:00 |     3500 |   100% |
    |       |       | 23:00 | 00:00 |     3500 |    30% |
    ----------------------------------------------------
    >>> prog.upload_settings()  # In order to upload the settings to the inverter
    >>> prog.disconnect()  # Needed if PySolarmanV5 >= 3.0.0

Notes

  • It is possible the inverter to be completely deactivated by writing 0 to register 80 WritableRegisters.SwitchOnOff.set(False) but it will raise an alarm and will show error F19. The normal state is restored as soon as the register is set to its default value 1.
  • The WritableRegisters.GridExportLimit register can be used if the grid export is not desired when the battery is charged and the PV generation exceeds the load.

deye-controller's People

Contributors

githubdante avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

deye-controller's Issues

Generator Port Values and settings

Hi,

I cannot access the GeneratorTotalPower in the Class HoldingRegisters. Could you please explain how to access the values here?
Thanks in advance

feature request - AC temperature

First of all I'd like to say thank you for this software.

I see the temperature of the AC side in the app, so the inverter must have it as information.

Can this information be provided in the deye-read output ?

0-02-05-aaafbed55455113c06570e9cdac4d0a7efb642e5a094a1db627b5cfbdad88b34_1e12a1555deaf4

Attempting to make it work with my SUN-6K-SG03LP1-EU

Hello.

I have one SUN-6K-SG03LP1-EU with one Pylontech 5000 and I'm trying to use this code to read and write from/to the inverter.

I'm having a bit of a hard time understanding how it work as I don't recognize the language/coding show in the examples despite having some programming background (mostly C).

I managed to install it, but doesn't seem to be reading the inverter correctly:

I read the inverter serial number correctly, so it is working up to some level.

[dividi@rocky deye-controller-master]$ deye-read 192.168.192.12 2913021234
[ Device_Type]: Hybrid
[ Modbus_Address]: 1
[ Inverter_Serial]: 2401081234
[ Rated_Power]: 0
Traceback (most recent call last):
File "/home/dividi/.local/bin/deye-read", line 8, in
sys.exit(read_from_inverter())
File "/home/dividi/.local/lib/python3.9/site-packages/deye_controller/deye_reader.py", line 105, in read_from_inverter
read_inverter(opts.address, opts.serial, batt_only=opts.battery, power_only=opts.power, combo=opts.combo,
File "/home/dividi/.local/lib/python3.9/site-packages/deye_controller/deye_reader.py", line 46, in read_inverter
string = '[{:>35s}]: {} {}'.format(reg.description.title(), reg.format(), suffix)
File "/home/dividi/.local/lib/python3.9/site-packages/deye_controller/modbus/protocol.py", line 141, in format
as_bytes = to_bytes(self.value)
File "/home/dividi/.local/lib/python3.9/site-packages/deye_controller/modbus/utils.py", line 15, in to_bytes
return bytes.fromhex(''.join([struct.pack('>h', x).hex() for x in val]))
File "/home/dividi/.local/lib/python3.9/site-packages/deye_controller/modbus/utils.py", line 15, in
return bytes.fromhex(''.join([struct.pack('>h', x).hex() for x in val]))
struct.error: 'h' format requires -32768 <= number <= 32767
[dividi@rocky deye-controller-master]$

Is there any hint hot to get this working, possibly need to adapt some code to my inverter, but I don't yet have a ModBus manual that I'm sure is accurate for my inverter.

Thanks in advance.

Cheers.

deye-read get all parameter 0 value

Hi @githubDante

I attach screens of official app
Immagine WhatsApp 2024-02-03 ore 18 59 35_481af064
Immagine WhatsApp 2024-02-03 ore 18 59 35_0aefca21
Immagine WhatsApp 2024-02-03 ore 18 59 35_026c4a55
Immagine WhatsApp 2024-02-03 ore 18 59 35_32c6bf9d

I have launched these commands

deye-read 192.168.0.105 2726848581
get all parameters to 0 value. why?

deye-scan 192.168.0.255

    LoggerSN:   2726848581
    IP:         192.168.0.105
    MAC:        E8FDF879E708

and subsequent

deye-read 192.168.0.105 2726848581
[ Device_Type]: Hybrid
[ Modbus_Address]: 1
[ Inverter_Serial]: 2212132808
[ Rated_Power]: 0
[ Inverter_Time]: 1970-01-01 00:00:00
[ Comm_Address]: 6685
[ Switch_On_Off]: Inactive
[ Control_Mode]: LeadBattery
[ Batt_Equalization_V]: 0.0 V
[ Batt_Absorbtion_V]: 20.49 V
[ Batt_Float_V]: 0.0 V
[ Batt_Capacity]: 0 Ah
[ Batt_Empty_V]: 0.0 V
[ Zero_Export_Power]: 0 W
[ Tempco]: 565 mV/*C
[ Max_Charge_Amps]: 78 A
[ Max_Discharge_Amps]: 21 A
[ Battery_Control_Mode]: Error
[ Battery_Wake_Up]: Inactive
[ Battery_Resistance]: 0 mOhm
[ Battery_Charging_Eff]: 0.0 %
[ Battery_Shutdown_Capacity]: 0 %
[ Battery_Recovery_Capacity]: 0 %
[ Battery_Low_Capacity]: 0 %
[ Battery_Shutdown_Voltage]: 0.0 V
[ Battery_Restart_Voltage]: 378.89 V
[ Battery_Low_Voltage]: 4.18 V
[ Grid_Charge_Start_Voltage]: 55.0 V
[ Grid_Charge_Start_Soc]: 0 %
[ Grid_Charge_Current]: 0 A
[ Grid_Max_Output_Pwr]: 5394 W
[ Solar_Sell]: Inactive
[ Sell_Time_Of_Use]: ['TimeOfUse - ENABLED', 'TimeOfUse - TUESDAY', 'TimeOfUse - THURSDAY']
[ Sell_Point_T1]: 00:90
[ Sell_Point_T2]: 24:73
[ Sell_Point_T3]: 00:52
[ Sell_Point_T4]: 00:00
[ Sell_Point_T5]: 00:52
[ Sell_Point_T6]: 00:00
[ Sell_Point_T1_Watts]: 2401 W
[ Sell_Point_T2_Watts]: 0 W
[ Sell_Point_T3_Watts]: 2401 W
[ Sell_Point_T4_Watts]: 2474 W
[ Sell_Point_T5_Watts]: 0 W
[ Sell_Point_T6_Watts]: 0 W
[ Sell_Point_T1_Volts]: 0.0 V
[ Sell_Point_T2_Volts]: 0.0 V
[ Sell_Point_T3_Volts]: 0.0 V
[ Sell_Point_T4_Volts]: 0.0 V
[ Sell_Point_T5_Volts]: 2.1 V
[ Sell_Point_T6_Volts]: 0.0 V
[ Sell_Point_T1_Soc]: 0 %
[ Sell_Point_T2_Soc]: 0 %
[ Sell_Point_T3_Soc]: 0 %
[ Sell_Point_T4_Soc]: 0 %
[ Sell_Point_T5_Soc]: 0 %
[ Sell_Point_T6_Soc]: 0 %
[ Charge_Point_T1]: GridGenDisabled
[ Charge_Point_T2]: GridGenDisabled
[ Charge_Point_T3]: GridGenDisabled
[ Charge_Point_T4]: GridGenDisabled
[ Charge_Point_T5]: GridGenDisabled
[ Charge_Point_T6]: GridGenDisabled
[ Export_To_Grid_Cutoff]: {'enabled': <TwoBitState.Undefined_1: 0>, 'generator_peak_shaving': <TwoBitState.Undefined_2: 1>, 'grid_peak_shaving': <TwoBitState.Undefined_2: 1>, 'on_grid_always_on': <TwoBitState.Disabled: 2>, 'external_relay': <TwoBitState.Undefined_2: 1>, 'report_loss_of_lithium': <TwoBitState.Undefined_1: 0>}
[ Grid_Freq_Selection]: 60 Hz
[ Grid_High_Voltage]: 40.4 V
[ Grid_Low_Voltage]: 0.0 V
[ Grid_High_Frequency]: 0.0 Hz
[ Grid_Low_Frequency]: 0.0 Hz
[ Generator_To_Grid]: Inactive
[ Gen_Peak_Shaving_Pwr]: 434 W
[ Grid_Peak_Shaving_Pwr]: 837 W
[ Smart_Load_Open_Delay]: 5000 Minutes
[ Output_Power_Factor]: 500.0 %
[ Bms_Charged_Voltage]: 1.0 V
[ Bms_Discharged_Voltage]: 1.3 V
[ Bms_Charge_Current_Limit]: 0 A
[ Bms_Discharge_Current_Limit]: 0 A
[ Bms_Battery_Soc]: 1 %
[ Bms_Battery_Voltage]: 0.19 V
[ Bms_Battery_Current]: 990 A
[ Bms_Battery_Temp]: -98.0 °C
[ Bms_Max_Charge_Current]: 35 A
[ Bms_Max_Discharge_Current]: 35 A
[ Bms_Battery_Alarm]: Inactive
[ Bms_Battery_Fault_Location]: 5250
[ Bms_Battery_Symbol_2]: 5100
Unknown CAN/MODBUS protocol: 80
[ Bms_Type]: PYLONTech_CAN
[ Bms_Battery_Soh]: 0
[ Max_Solar_Sell_Pwr]: 10 W
[ Inverter_State]: StandBy
[ Active_Power_Today]: 0.0 kWh
[ Reactive_Power_Today]: 0.0 kVarh
[ Grid_Connection_Today]: 0.0 minutes
[ Battery_Charge_Today]: 0.0 kWh
[ Battery_Discharge_Today]: 0.0 kWh
[ Battery_Charge_Total]: 0.0 kWh
[ Battery_Discharge_Total]: 0.0 kWh
[ Today_Bought_From_Grid]: 0.0 kWh
[ Today_Sold_To_Grid]: 0.0 kWh
[ Total_Bought_From_Grid]: 0.0 kWh
[ Total_Sold_To_Grid]: 0.0 kWh
[ Today_To_Load]: 0.0 kWh
[ Total_To_Load]: 0.0 kWh
[ Today_From_Pv]: 0.0 kWh
[ Today_From_Pv_S1]: 0.0 kWh
[ Today_From_Pv_S2]: 0.0 kWh
[ Total_From_Pv]: 0.0 kWh
[ Battery_Temperature]: 0.0 °C
[ Battery_Voltage]: 0.0 V
[ Battery_Soc]: 0.0 %
[ Battery_Out_Power]: 0 W
[ Battery_Out_Current]: 0.0 A
[ Battery_Corrected_Ah]: 0 Ah
[ Grid_Phase_A_Volt]: 0.0 V
[ Grid_Phase_B_Volt]: 0.0 V
[ Grid_Phase_C_Volt]: 0.0 V
[ Grid_Phase_Ab_Volt]: 0.0 V
[ Grid_Phase_Bc_Volt]: 0.0 V
[ Grid_Phase_Ca_Volt]: 0.0 V
[ Grid_Phase_A_In_Power]: 0 W
[ Grid_Phase_B_In_Power]: 0 W
[ Grid_Phase_C_In_Power]: 0 W
[ Grid_Active_Side_Side_In_Power]: 0 W
[Grid_Active_Side_Side_Apparent_Power]: 0 W
[ Grid_In_Frequency]: 0.0 Hz
[ Grid_Phase_A_In_Current]: 0.0 A
[ Grid_Phase_B_In_Current]: 0.0 A
[ Grid_Phase_C_In_Current]: 0.0 A
[ Grid_Phase_A_Out_Of_Grid_Current]: 0.0 A
[ Grid_Phase_B_Out_Of_Grid_Current]: 0.0 A
[ Grid_Phase_C_Out_Of_Grid_Current]: 0.0 A
[ Grid_Phase_A_Out_Of_Grid_Power]: 0 W
[ Grid_Phase_B_Out_Of_Grid_Power]: 0 W
[ Grid_Phase_C_Out_Of_Grid_Power]: 0 W
[ Grid_Total_Out_Of_Grid_Power]: 0 W
[Grid_Total_Out_Of_Grid_Apparent_Power]: 0 W
[ Grid_Phase_A__Power]: 0 W
[ Grid_Phase_B__Power]: 0 W
[ Grid_Phase_C__Power]: 0 W
[ Grid_Total_Power]: 0 W
[ Grid_Phase_A_Volt_Out]: 0.0 V
[ Grid_Phase_B_Volt_Out]: 0.0 V
[ Grid_Phase_C_Volt_Out]: 0.0 V
[ Inverter_Phase_A_Out_Current]: 0.0 A
[ Inverter_Phase_B_Out_Current]: 0.0 A
[ Inverter_Phase_C_Out_Current]: 0.0 A
[ Inverter_Phase_A_Out_Power]: 0 W
[ Inverter_Phase_B_Out_Power]: 0 W
[ Inverter_Phase_C_Out_Power]: 0 W
[ Inverter_Total_Out_Power]: 0 W
[ Inverter_Total_Apparent_Out_Power]: 0 W
[ Inverter_Out_Frequency]: 0.0 Hz
[ Ups_Phase_A_Power]: 0 W
[ Ups_Phase_B_Power]: 0 W
[ Ups_Phase_C_Power]: 0 W
[ Ups_Total_Power]: 0 W
[ Load_Phase_A_Volt]: 0.0 V
[ Load_Phase_B_Volt]: 0.0 V
[ Load_Phase_C_Volt]: 0.0 V
[ Load_Phase_A_Current]: 0.0 A
[ Load_Phase_B_Current]: 0.0 A
[ Load_Phase_C_Current]: 0.0 A
[ Load_Phase_A_Power]: 0 W
[ Load_Phase_B_Power]: 0 W
[ Load_Phase_C_Power]: 0 W
[ Load_Total_Power]: 0 W
[ Pv1_In_Power]: 0 W
[ Pv2_In_Power]: 0 W
[ Pv1_Volt]: 0.0 V
[ Pv1_Current]: 0.0 A
[ Pv2_Volt]: 0.0 V
[ Pv2_Current]: 0.0 A

Possibility and example for change Gen Port Working Mode

Hello,

ich search for a solution to change with a time based script the Gen Port Working Mode from "MicrInv Input" to "Genrator Input". It is possible to write this with your controller?
The benefit is to reduse the grid usage by night to zero.

Thank you.

struct.error: 'h' format requires -32768 <= number <= 32767 -> value is 32851

Hello,

since yesterday i get this error. Nothing was changed by me:

reading of this value get the follow error: TotalSellGrid = LongType(524, 'total_sold_to_grid', 10, suffix='kWh')

DEBUG:pysolarmanv5.pysolarmanv5:Socket setup completed... <socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('10.10.0.48', 59274), raddr=('10.10.0.49', 8899)>
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 55 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 02 71 00 01 d5 a9 38 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 55 10 17 7c 4a a2 02 01 c2 c1 56 00 6e 1a 00 00 c2 c5 58 64 01 03 02 fd 82 78 b5 77 15
DEBUG:pysolarmanv5.pysolarmanv5:Socket setup completed... <socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6, laddr=('10.10.0.48', 59282), raddr=('10.10.0.49', 8899)>
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 54 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 00 00 01 84 0a d4 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 54 11 17 7c 4a a2 02 01 c3 c1 56 00 6f 1a 00 00 c2 c5 58 64 01 03 02 00 05 78 47 91 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 55 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 01 00 01 d5 ca e7 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 55 12 17 7c 4a a2 02 01 c3 c1 56 00 6f 1a 00 00 c2 c5 58 64 01 03 02 00 01 79 84 cd 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 56 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 03 00 05 75 c9 8d 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 1d 00 10 15 56 13 17 7c 4a a2 02 01 c3 c1 56 00 6f 1a 00 00 c2 c5 58 64 01 03 0a 32 32 31 32 30 32 38 30 31 39 fd 20 f9 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 57 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 08 00 01 05 c8 1e 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 57 14 17 7c 4a a2 02 01 c3 c1 56 00 6f 1a 00 00 c2 c5 58 64 01 03 02 00 00 b8 44 cf 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 58 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 3e 00 03 64 07 f5 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 19 00 10 15 58 15 17 7c 4a a2 02 01 c3 c1 56 00 6f 1a 00 00 c2 c5 58 64 01 03 06 17 07 0d 07 0b 18 23 c5 1a 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 59 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 4a 00 01 a5 dc 16 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 59 16 17 7c 4a a2 02 01 c3 c1 56 00 6f 1a 00 00 c2 c5 58 64 01 03 02 00 01 79 84 d5 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 5a 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 50 00 01 84 1b 3b 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 5a 17 17 7c 4a a2 02 01 c3 c1 56 00 6f 1a 00 00 c2 c5 58 64 01 03 02 00 01 79 84 d7 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 5b 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 62 00 01 25 d4 a8 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 5b 18 17 7c 4a a2 02 01 c3 c1 56 00 70 1a 00 00 c2 c5 58 64 01 03 02 00 00 b8 44 d8 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 5c 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 66 00 01 64 15 2d 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 5c 19 17 7c 4a a2 02 01 c3 c1 56 00 70 1a 00 00 c2 c5 58 64 01 03 02 01 18 b9 de 8e 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 5d 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 68 00 01 05 d6 92 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 5d 1a 17 7c 4a a2 02 01 c3 c1 56 00 70 1a 00 00 c2 c5 58 64 01 03 02 00 19 79 8e 00 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 5e 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 6c 00 01 44 17 17 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 5e 1b 17 7c 4a a2 02 01 c3 c1 56 00 70 1a 00 00 c2 c5 58 64 01 03 02 00 69 78 6a 2d 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 5f 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 6d 00 01 15 d7 aa 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 5f 1c 17 7c 4a a2 02 01 c3 c1 56 00 70 1a 00 00 c2 c5 58 64 01 03 02 00 87 f8 26 89 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 60 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 6f 00 01 b4 17 8c 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 60 1d 17 7c 4a a2 02 01 c4 c1 56 00 70 1a 00 00 c2 c5 58 64 01 03 02 00 00 b8 44 e3 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 61 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 72 00 01 24 11 fa 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 61 1e 17 7c 4a a2 02 01 c4 c1 56 00 70 1a 00 00 c2 c5 58 64 01 03 02 03 de 38 ec ee 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 62 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 73 00 01 75 d1 0d 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 62 1f 17 7c 4a a2 02 01 c4 c1 56 00 70 1a 00 00 c2 c5 58 64 01 03 02 00 0a 38 43 70 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 63 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 74 00 01 c4 10 9d 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 63 20 17 7c 4a a2 02 01 c4 c1 56 00 70 1a 00 00 c2 c5 58 64 01 03 02 00 19 79 8e 0d 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 64 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 75 00 01 95 d0 30 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 64 21 17 7c 4a a2 02 01 c4 c1 56 00 70 1a 00 00 c2 c5 58 64 01 03 02 00 14 b8 4b 06 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 65 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 76 00 01 65 d0 02 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 65 22 17 7c 4a a2 02 01 c4 c1 56 00 70 1a 00 00 c2 c5 58 64 01 03 02 12 c0 b4 b4 2b 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 66 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 77 00 01 34 10 13 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 66 23 17 7c 4a a2 02 01 c4 c1 56 00 71 1a 00 00 c2 c5 58 64 01 03 02 14 00 b7 44 03 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 67 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 78 00 01 04 13 e8 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 67 24 17 7c 4a a2 02 01 c4 c1 56 00 71 1a 00 00 c2 c5 58 64 01 03 02 13 60 b5 5c 7a 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 68 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 7e 00 01 e4 12 ce 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 68 25 17 7c 4a a2 02 01 c4 c1 56 00 71 1a 00 00 c2 c5 58 64 01 03 02 13 24 b5 6f 53 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 69 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 7f 00 01 b5 d2 61 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 69 26 17 7c 4a a2 02 01 c4 c1 56 00 71 1a 00 00 c2 c5 58 64 01 03 02 00 1e 38 4c 9c 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 6a 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 80 00 01 85 e2 43 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 6a 27 17 7c 4a a2 02 01 c4 c1 56 00 71 1a 00 00 c2 c5 58 64 01 03 02 00 28 b8 5a 36 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 6b 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 8f 00 01 b5 e1 82 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 6b 28 17 7c 4a a2 02 01 c5 c1 56 00 71 1a 00 00 c2 c5 58 64 01 03 02 01 f4 b8 53 ff 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 6c 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 bd 00 01 14 2e 5d 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 6c 29 17 7c 4a a2 02 01 c5 c1 56 00 71 1a 00 00 c2 c5 58 64 01 03 02 00 01 79 84 ff 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 6d 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 c0 00 01 84 36 d9 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 6d 2a 17 7c 4a a2 02 01 c5 c1 56 00 71 1a 00 00 c2 c5 58 64 01 03 02 00 64 b9 af cf 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 6e 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 00 c1 00 01 d5 f6 ec 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 6e 2b 17 7c 4a a2 02 01 c5 c1 56 00 72 1a 00 00 c2 c5 58 64 01 03 02 03 e8 b8 fa a3 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 6f 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 01 f4 00 01 c4 04 1e 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 6f 2c 17 7c 4a a2 02 01 c5 c1 56 00 72 1a 00 00 c2 c5 58 64 01 03 02 00 02 39 85 c8 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 70 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 01 f5 00 01 95 c4 b1 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 70 2d 17 7c 4a a2 02 01 c5 c1 56 00 72 1a 00 00 c2 c5 58 64 01 03 02 00 00 b8 44 06 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 71 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 01 f6 00 01 65 c4 83 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 71 2e 17 7c 4a a2 02 01 c5 c1 56 00 72 1a 00 00 c2 c5 58 64 01 03 02 00 00 b8 44 08 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 72 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 01 f7 00 01 34 04 94 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 72 2f 17 7c 4a a2 02 01 c5 c1 56 00 72 1a 00 00 c2 c5 58 64 01 03 02 00 00 b8 44 0a 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 73 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 02 02 00 01 24 72 ff 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 73 30 17 7c 4a a2 02 01 c6 c1 56 00 72 1a 00 00 c2 c5 58 64 01 03 02 00 11 78 48 e2 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 74 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 02 03 00 01 75 b2 92 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 74 31 17 7c 4a a2 02 01 c6 c1 56 00 72 1a 00 00 c2 c5 58 64 01 03 02 00 17 f8 4a 6c 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 75 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 02 04 00 02 84 72 64 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 17 00 10 15 75 32 17 7c 4a a2 02 01 c6 c1 56 00 72 1a 00 00 c2 c5 58 64 01 03 04 0f 36 00 00 19 29 a0 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 76 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 02 06 00 02 25 b2 48 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 17 00 10 15 76 33 17 7c 4a a2 02 01 c6 c1 56 00 72 1a 00 00 c2 c5 58 64 01 03 04 0f 4a 00 00 d8 f1 3d 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 77 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 02 08 00 01 04 70 e7 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 77 34 17 7c 4a a2 02 01 c6 c1 56 00 72 1a 00 00 c2 c5 58 64 01 03 02 00 06 38 46 9d 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 78 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 02 09 00 01 55 b0 7a 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 15 00 10 15 78 35 17 7c 4a a2 02 01 c6 c1 56 00 72 1a 00 00 c2 c5 58 64 01 03 02 00 05 78 47 df 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 79 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 02 0a 00 02 e5 b1 0e 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 17 00 10 15 79 36 17 7c 4a a2 02 01 c6 c1 56 00 72 1a 00 00 c2 c5 58 64 01 03 04 02 98 00 00 7a 64 99 15
DEBUG:pysolarmanv5.pysolarmanv5:SENT: a5 17 00 10 45 7a 00 17 7c 4a a2 02 00 00 00 00 00 00 00 00 00 00 00 00 00 00 01 03 02 0c 00 02 05 b0 30 15
DEBUG:pysolarmanv5.pysolarmanv5:RECD: a5 17 00 10 15 7a 37 17 7c 4a a2 02 01 c6 c1 56 00 73 1a 00 00 c2 c5 58 64 01 03 04 80 53 00 00 23 e2 fc 15

[0, 3894]
[0, 3894]
[0, 3914]
[0, 3914]
[0, 664]
[0, 664]
[0, 32851]
Traceback (most recent call last):
  File "/usr/script/deye_controller/myReader.py", line 155, in <module>
    runtime_deye = leseDeyeInverterDaten(aktuelle_zeit)
  File "/usr/script/deye_controller/myReader.py", line 81, in leseDeyeInverterDaten
    master_data_dict, runtime = deye_reader.read_inverter('10.10.0.49', 2722790423,subdict=True)
  File "/usr/script/deye_controller/deye_reader.py", line 71, in read_inverter
    data_dict[iteratiorentry.description]=convertinttofloat(iteratiorentry.format())
  File "/usr/script/deye_controller/modbus/protocol.py", line 86, in format
    v = to_bytes(self.value[::-1])
  File "/usr/script/deye_controller/modbus/utils.py", line 16, in to_bytes
    return bytes.fromhex(''.join([struct.pack('>h', x).hex() for x in val]))
  File "/usr/script/deye_controller/modbus/utils.py", line 16, in <listcomp>
    return bytes.fromhex(''.join([struct.pack('>h', x).hex() for x in val]))
struct.error: 'h' format requires -32768 <= number <= 32767`

work mode

Hi, thanks for your project. I can set the prog table successfully.

Is it also possible to set the work mode ?

I checked the WritableRegisters but cannot find it. I want to switch between "Selling First" and "Zero Export to CT"

thanks

not able to get the JSON file

installed last version 0.1.3

running command:

deye-read 192.168.0.151 [serial] --json

i get:

Traceback (most recent call last):
  File "c:\program files\python38\lib\runpy.py", line 194, in _run_module_as_main
    return _run_code(code, main_globals, None,
  File "c:\program files\python38\lib\runpy.py", line 87, in _run_code
    exec(code, run_globals)
  File "C:\Program Files\Python38\Scripts\deye-read.exe\__main__.py", line 7, in <module>
  File "c:\program files\python38\lib\site-packages\deye_controller\deye_reader.py", line 95, in read_from_inverter
    read_inverter(opts.address, opts.serial, batt_only=opts.battery, power_only=opts.power, combo=opts.combo,
  File "c:\program files\python38\lib\site-packages\deye_controller\deye_reader.py", line 32, in read_inverter
    res = inv.read_holding_registers(group.start_address, group.len)
  File "c:\program files\python38\lib\site-packages\pysolarmanv5\pysolarmanv5.py", line 508, in read_holding_registers
    modbus_values = self._get_modbus_response(mb_request_frame)
  File "c:\program files\python38\lib\site-packages\pysolarmanv5\pysolarmanv5.py", line 385, in _get_modbus_response
    mb_response_frame = self._send_receive_modbus_frame(mb_request_frame)
  File "c:\program files\python38\lib\site-packages\pysolarmanv5\pysolarmanv5.py", line 373, in _send_receive_modbus_frame
    mb_response_frame = self._v5_frame_decoder(v5_response_frame)
  File "c:\program files\python38\lib\site-packages\pysolarmanv5\pysolarmanv5.py", line 249, in _v5_frame_decoder
    raise V5FrameError("V5 frame contains invalid sequence number")
pysolarmanv5.pysolarmanv5.V5FrameError: V5 frame contains invalid sequence number

with out --json switch all is good

Cannot read register 145 Solar Sell

I am trying to read and write register number 145. I will get following error:

deye-regtest 192.168.1.x 2705xxxx 145

raise IllegalDataValueError('Quantify field of request must be a '
umodbus.exceptions.IllegalDataValueError: The value contained in the request data field is not an allowable value
for the server.

Documentation: more info on usage of the code

is a good approach and i will like to use it in my automation but i need more info on the usage of the code.

i.e in example provided the is a syntax like:

register = HoldingRegisters.BMSBatteryCapacity
BMSBatteryCapacity is an example but where we can find the rest?

similar for WritableRegisters :)

Output to PVOutput

Dear Sir! Would it be very difficult to somehow implement/combine whatever https://github.com/XtheOne/Inverter-Data-Logger uses for sending data to PVoutput via their API? I am asking because I have an idea for using deye-controller together with Inverter-Data-Logger for filling my profile in PVoutput, which will then be read by the Homey app with the ultimate goal of triggering an iOS shortcut for turning on a device in the Tuya ecosystem when there is PV generation higher than a pre-defined value. Probably the worst possible idea, but I know nothing of python and home assistant and I cannot do it myself...yet :)

SellProgrammer modbus mapping

Evening

I'm playing around with the sellprogrammer as i would like to change grid charge status depending on load shedding stage.

Out of the box, the connecting is working, but i'm getting some interesting return values.

deye-controller$ ./get_mode.py


| Grid | Gen | Time | Pwr | SOC % |
| | | 00:59 | 22:14 | 2202 | 0% |
| | | 22:14 | 09:57 | 0 | 0% |
| | | 09:57 | 00:00 | 2202 | 0% |
| | | 00:00 | 09:57 | 2226 | 0% |
| | | 09:57 | 22:26 | 0 | 0% |
| | | 22:26 | 00:59 | 0 | 0% |

and a few seconds later

deye-controller$ ./get_mode.py


| Grid | Gen | Time | Pwr | SOC % |
| | | 00:59 | 22:30 | 2202 | 0% |
| | | 22:30 | 09:57 | 0 | 0% |
| | | 09:57 | 00:00 | 2202 | 0% |
| | | 00:00 | 09:57 | 2226 | 0% |
| | | 09:57 | 22:26 | 0 | 0% |
| | | 22:26 | 00:59 | 0 | 0% |

Everything above is actually invalid.

Obviously your mapping to an inverter you had the ability to test on, so i'm not going to twist your arm, i'm happy to do it myself, but i would like to know what documentation you used to discover the correct registers?! My python skill is not too bad, but i don't actually know any resources that indicate the correct indexes! Would the best way be to just dump everything, and start changing a setting on the inverter and than basically register by register reverse engineer the structure, or is there documentation somewhere as guidance?

I'm on an 8kw sunsynk.

Pleasant evening further!

Many issues to a mega tool

First of all this looks fantastic even though I come with a lot of questions (sorry). I can now see that this will work. First, a prologue where I am standing and my approach.

  • I have a 12 kWp Sungrow plant with a Sungrow 16 kWh battery for storage.

  • I use Home Assistant and Node-Red to control my house and the Sungrow PV plant. At a given time, I can force my Sungrow over a ModBus protocol to discharge/charge since I use Tibber and buy cheap power from October to March when needed at the right time. The rest of the year, the system works on self-consumption since I have a surplus anyway, and the inverter puts the rest into the battery (work still needs to be done to make the coding in Node-Red a bit nicer since I'm not a programmer but a DIY man).

  • Now, I have the Deye Sun 12k with 4x5.12 kWh (44-57V) installed in the garage, now for the 24/7/365 base load. The Sungrow will take the peaks, heavy loads, and the wallbox since it is just faster and can deliver up to 11 kW directly.

  • I use the integration from Solman in Home Assistant. So, for the Deye, I would like to take control like the Sungrow and control when to charge/discharge. I tried with ESP32 and Modbus (https://github.com/klatremis/esphome-for-deye) but tried everything I know (changed the tx/rx, 1000 times the Modbus pins), then with Elfin ew11 Modbus2Wifi and tried the https://kellerza.github.io/sunsynk/reference/multi-options, even with a different Elfin Modbus2Wifi but the same setup, no connection. Same integration from Kellerza. Then it is possible to use a Raspi or SBC, also to communicate USB2Modbus, so I did the setup, but I use Dietpi as a derivative for the Linux/Debian, so even my RasPi 4 or my NanoPi R2S, both with Dietpi Debian, now I get a problem with the installation of cmake. Here's the cooking menu, and it stops at point 6.

  1. sudo apt-get install git
  2. sudo apt-get install cmake
  3. git clone https://github.com/3cky/mbusd.git mbusd.git
  4. cd mbusd.git
  5. mkdir -p build && cd build
  6. cmake -DCMAKE_INSTALL_PREFIX=/usr ..
  7. make
  8. sudo make install
  9. sudo nano /etc/mbusd/mbusd.conf.example
  10. systemctl start [email protected]
    (nicht zwingend notwendig)11. journalctl -u [email protected] -f -n 10
  11. sudo systemctl enable [email protected]

And here it would be possible to control the Deye. But at given time Im stopped here.................

Now, I saw your article here, and in Home Assistant, I use the integration Solarman and the WiFi dongle at my Deye. It works perfectly and can SEE all values but can't send commands to control my Deye.

So, here are my questions (every start is hard).

  1. On what system does this Deye control run (PC, Raspi),
  2. Is it Linux/Debian?
  3. Can I use Node-Red for this? Or how do I communicate with your code so that I can use it for my issues?

Here are some pics where I would love to control the Deye (the rest for monitoring is the HA from Solarman integrated).

So my goal is to change the values over the system work mode
Work Mode1: Selling First, Zero Export to laod/Ct and Energy pattern (batt/load first)
Work Mode2: all parameters

Battery Settings, Batt Set 2 the Ampere (at me the 80A in the pic) and the Grid charge and Grid Signal.

Thanks in advance and have a marry xmas.

BR
Europer

2023-12-23 15_21_42-Settings – Home Assistant und 1 weitere Seite - Persönlich – Microsoft​ Edge
20231217_140952
20231217_141001
20231221_212352

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.