bohdan-s / SunGather

GNU General Public License v3.0
141 stars 57 forks source link

Futurerequest: add a wallbox e.g. AC011E-01 #184

Open HubertusH opened 1 month ago

HubertusH commented 1 month ago

Hello everyone, would it also be possible to query a wallbox such as the AC011E-01? Then you could also read out this data. This would be practical as it would also allow you to calculate the charging power. Currently, the inverter only displays the total power consumed.

Thank you and best regards Hubertus

michbeck100 commented 1 month ago

No, Sungather is designed for Sungrow inverters. Not for wallboxes

HubertusH commented 1 month ago

Ok, I have found the registers that the inverter has to read the information from the wallbox.


"_address   name                description                                 unit    type        len factor  offset  formula role    room    poll    wp  cw  isScale"
"21200      Total_Energy        Bisher geladene Gesamtleistung              wh      uint32be    2   1           state       true    true    false   false"
"21202      SetOutI             Ausgangsstrom | 0,1A | 6A-63A               A       uint16be    1   1           state       true    true    false   false"
"21203      PhaseSwitch         PhaseSwitch | 0=3ph 1=1ph                           uint16be    1   1           state       true    true    false   false"
"21210      Charger_Enable      Charger Enable |  0=disable 1=enable                uint16be    1   1           state       true    true    false   false"
"21211      START_STOP_CHARGING Ladung Starten | Stoppen 0=Start 1=Stop             uint16be    1   1           state       true    true    false   false"
"21212      Total_Energy        Total_Energy                                Wh      uint32be    2   1           state       true    true    false   false"
"21224      Year                Year                                                uint16be    1   1           state       true    true    false   false"
"21225      Month               Month                                               uint16be    1   1           state       true    true    false   false"
"21226      Day                 Day                                                 uint16be    1   1           state       true    true    false   false"
"21227      Hour                Hour                                                uint16be    1   1           state       true    true    false   false"
"21228      Minute              Minute                                              uint16be    1   1           state       true    true    false   false"
"21229      Second              Second                                              uint16be    1   1           state       true    true    false   false"
"21230      Dev_Address         Bus Adresse | deafult 248                           uint16be    1   1           state       true    true    false   false"
"21231      Enery_per_Km        Energie pro Km                                      uint16be    1   1           state       true    true    false   false"

This also works via modbus client if you enter the correct Clint ID (in my case "2").

 modbus 192.168.179.9:502 -s 2 21203
Parsed 0 registers definitions from 1 files
21203: 0 0x0

I then created a register.yaml:

version:  0.2.3
vendor: Sungrow
registers:
  - read:
    - name: "Total_Energy"
      level: 2
      address: 21200
      datatype: "U32"
    - name: "SetOutI"
      level: 2
      address: 21202
      datatype: "U32"
    - name: "PhaseSwitch"
      level: 2
      address: 21203
      datatype: "U16"
      datarange:
        - response: 0x00
          value: "3ph"
        - response: 0x01
          value: "1ph"

scan: # these have to be 1 less than the first register
  - read:
    - start: 21200
      range: 4
    - start: 21210
      range: 3
    - start: 21224
      range: 12
  - hold:
    - start: 21200
      range: 4
    - start: 21210
      range: 3
    - start: 21224
      range: 12

but always get an IndexError at startup:

 python3 sungather.py -c /home/pi/SunGather/Wallbox/config.yaml -r /home/pi/SunGather/Wallbox/registers-wallbox.yaml --runonce -v 10
2024-05-28 17:29:17 INFO     Starting SunGather 0.5.2
2024-05-28 17:29:17 INFO     Need Help? https://github.com/bohdan-s/SunGather
2024-05-28 17:29:17 INFO     NEW HomeAssistant Add-on: https://github.com/bohdan-s/hassio-repository
2024-05-28 17:29:18 INFO     Loaded config: /home/pi/SunGather/Wallbox/config.yaml
2024-05-28 17:29:19 INFO     Loaded registers: /home/pi/SunGather/Wallbox/registers-wallbox.yaml
2024-05-28 17:29:19 INFO     Registers file version: 0.2.3
2024-05-28 17:29:19 INFO     Logging to console set to: DEBUG
2024-05-28 17:29:19 DEBUG    Inverter Config Loaded: {'host': '192.168.179.9', 'port': 502, 'timeout': 10, 'retries': 3, 'slave': 2, 'scan_interval': 30, 'connection': 'modbus', 'model': 'AC011E-01', 'smart_meter': False, 'use_local_time': False, 'log_console': 'WARNING', 'log_file': 'OFF', 'level': 2}
2024-05-28 17:29:19 INFO     Loading SungrowClient 0.1.0
2024-05-28 17:29:19 DEBUG    Checking Modbus Connection
2024-05-28 17:29:19 INFO     Modbus client is not connected, attempting to reconnect
2024-05-28 17:29:19 INFO     Connection: ModbusTcpClient(192.168.179.9:502)
2024-05-28 17:29:19 DEBUG    Connection to Modbus server established. Socket ('192.168.179.77', 41381)
2024-05-28 17:29:22 INFO     Bypassing Model Detection, Using config: AC011E-01
Traceback (most recent call last):
  File "/home/pi/SunGather/Wallbox/sungather.py", line 195, in <module>
    main()
  File "/home/pi/SunGather/Wallbox/sungather.py", line 129, in main
    inverter.configure_registers(registersfile)
  File "/home/pi/.local/lib/python3.9/site-packages/SungrowClient/SungrowClient.py", line 159, in configure_registers
    for register in registersfile['registers'][1]['hold']:
IndexError: list index out of range
ludifu commented 1 month ago

Did you notice this comment:

scan: # these have to be 1 less than the first register

HubertusH commented 1 month ago

oh dear ;-) ok i have changed that to:

scan: # these have to be 1 less than the first register
  - read:
    - start: 21199
      range: 10

  - hold:
    - start: 21199
      range: 10

but the error remains - I may not have understood the "hold" parameter.

Thanks & greetings Hubertus

ludifu commented 1 month ago

Edited (sigh) ...

Change this:

        - response: 0x01
          value: "1ph"

scan: # these have to be 1 less than the first register

into this:

        - response: 0x01
          value: "1ph"
  - hold:

scan: # these have to be 1 less than the first register
HubertusH commented 1 month ago

Thank you - one step further! Because the error message with the "year" came up, I set use_local_time to true. But it still doesn't run smoothly. The key "year" is not set in my config.

python3 sungather.py -c /home/pi/SunGather/Wallbox/config.yaml -r /home/pi/SunGather/Wallbox/registers-wallbox.yaml -v 30 --runonce
2024-05-29 10:19:43 INFO     Starting SunGather 0.5.2
2024-05-29 10:19:43 INFO     Need Help? https://github.com/bohdan-s/SunGather
2024-05-29 10:19:43 INFO     NEW HomeAssistant Add-on: https://github.com/bohdan-s/hassio-repository
2024-05-29 10:19:44 INFO     Loaded config: /home/pi/SunGather/Wallbox/config.yaml
2024-05-29 10:19:44 INFO     Loaded registers: /home/pi/SunGather/Wallbox/registers-wallbox.yaml
2024-05-29 10:19:44 INFO     Registers file version: 0.2.3
+----------------------------------------------+
| Inverter Configuration Settings              |
+----------------------------------------------+
| Config             | Value                   |
+--------------------+-------------------------+
| host               | 192.168.179.9           |
| port               | 502                     |
| timeout            | 10                      |
| retries            | 3                       |
| RetryOnEmpty       | False                   |
| model              | AC011E-01               |
| serial_number      | None                    |
| level              | 2                       |
| scan_interval      | 30                      |
| use_local_time     | True                    |
| smart_meter        | False                   |
| connection         | modbus                  |
| slave              | 2                       |
| start_time         |                         |
+----------------------------------------------+
2024-05-29 10:19:47 ERROR    Failed to scrape: 'year'
Traceback (most recent call last):
  File "/home/pi/SunGather/Wallbox/sungather.py", line 156, in main
    success = inverter.scrape()
  File "/home/pi/.local/lib/python3.9/site-packages/SungrowClient/SungrowClient.py", line 379, in scrape
    del self.latest_scrape["year"]
KeyError: 'year'
Failed to scrape: 'year'
Traceback (most recent call last):
  File "/home/pi/SunGather/Wallbox/sungather.py", line 156, in main
    success = inverter.scrape()
  File "/home/pi/.local/lib/python3.9/site-packages/SungrowClient/SungrowClient.py", line 379, in scrape
    del self.latest_scrape["year"]
KeyError: 'year'
2024-05-29 10:19:47 WARNING  Data collection failed, skipped exporting data. Retying in 30 secs
Data collection failed, skipped exporting data. Retying in 30 secs

Thanks & greetings Hubertus

ludifu commented 1 month ago

It really only scrapes what you defined in registers:. If the yaml you posted earlier is complete there are only 3 registers defined, not including year.

Background information: The scan:section is used to first read all data in the defined address areas. In a second step Sungather extracts all defined registers from these areas. After this it has some logic to convert date information into a date field and delete the single year, month, day, etc. fields. Thus the del self.latest_scrape["year"]code snippet. This cannot be changed by configuration. So you must pull all those date fields.

HubertusH commented 1 month ago

Thank you !

i defined "Year":

    - name: "Year"
      level: 2
      address: 21224
      datatype: "U16"
      unit: "YYYY"

but "year" is case sensitiv and now with "year" lowercase it works. So - for you: a query of the wallbox connected to the inverter (in this case the AC011E-01) also works.

MANY THANKS for the support. Great.

Sunny greetings Hubertus

ludifu commented 1 month ago

Well, thanks to you for researching this wallbox stuff!

HubertusH commented 1 month ago

Super only a few formatting problems remain ;-) The documentary writes:

"_address   name                description                                 unit    type        len factor  offset  formula role    room    poll    wp  cw  isScale"
"21200      Total_Energy        Bisher geladene Gesamtleistung              wh      uint32be    2   1           state       true    true    false   false"
"21202      SetOutI             Ausgangsstrom | 0,1A | 6A-63A               A       uint16be    1   1           state       true    true    false   false"
"21203      PhaseSwitch         PhaseSwitch | 0=3ph 1=1ph                           uint16be    1   1           state       true    true    false   false"
"21210      Charger_Enable      Charger Enable |  0=disable 1=enable                uint16be    1   1           state       true    true    false   false"
"21211      START_STOP_CHARGING Ladung Starten | Stoppen 0=Start 1=Stop             uint16be    1   1           state       true    true    false   false"
"21212      Total_Energy        Total_Energy                                Wh      uint32be    2   1           state       true    true    false   false"
"21224      Year                Year                                                uint16be    1   1           state       true    true    false   false"
"21225      Month               Month                                               uint16be    1   1           state       true    true    false   false"
"21226      Day                 Day                                                 uint16be    1   1           state       true    true    false   false"
"21227      Hour                Hour                                                uint16be    1   1           state       true    true    false   false"
"21228      Minute              Minute                                              uint16be    1   1           state       true    true    false   false"
"21229      Second              Second                                              uint16be    1   1           state       true    true    false   false"
"21230      Dev_Address         Bus Adresse | deafult 248                           uint16be    1   1           state       true    true    false   false"
"21231      Enery_per_Km        Energie pro Km                                      uint16be    1   1           state       true    true    false   false"

the results from modbus tool fit so far:


modbus 192.168.179.9 -s 2 21200 = 38174 // according to APP "38.2" would be correct
modbus 192.168.179.9 -s 2 21202 = 60 
modbus 192.168.179.9 -s 2 21203 = 0        // only "0" or "1"
modbus 192.168.179.9 -s 2 21210 = 1        // only "0" or "1" 
modbus 192.168.179.9 -s 2 21211 = 0        // only "0" or "1"
modbus 192.168.179.9 -s 2 21230 = 248    //  default is 248 !
modbus 192.168.179.9 -s 2 21231 = 50

but the output from Sungather doesn't really fit:

+----------------------------------------------------------------------+
| Address | Register                            | Value                |
+---------+-------------------------------------+----------------------+
| ----    | device_type_code                    | AC011E-01            |
| 21200   | Total_Energy                        | 1093795840 wh        |
| 21202   | SetOutI                             | 842543673 A          |
| 21203   | PhaseSwitch                         | 12856                |
| 21210   | ChargerEnable                       | 0                    |
| 21211   | StartStopCharging                   | 0                    |
| 21212   | TotalEnergy2                        | 0 wh                 |
| 21230   | Dev_Adress                          | 17709                |
| 21231   | Energy_per_Km                       | 12853                |
| vr002   | timestamp                           | 2024-05-29 13:36:02  |
+----------------------------------------------------------------------+

the matching register configuration:

version:  0.2.3
vendor: Sungrow
registers:
  - read:
    - name: "Total_Energy"
      level: 2
      address: 21200
      datatype: "U32"
      unit: "wh"
    - name: "SetOutI"
      level: 2
      address: 21202
      datatype: "U32"
      unit: "A"
    - name: "PhaseSwitch"
      level: 2
      address: 21203
      datatype: "U16"
#      datarange:
#        - response: 0x00
##          value: "3ph"
#        - response: 0x01
#          value: "1ph"
    - name: "ChargerEnable"
      level: 2
      address: 21210
      datatype: "U16"
    - name: "StartStopCharging"
      level: 2
      address: 21211
      datatype: "U16"
    - name: "TotalEnergy2"
      level: 2
      address: 21212
      datatype: "U32"
      unit: "wh"
    - name: "year"
      level: 2
      address: 21224
      datatype: "U16"
      unit: "YYYY"
    - name: "month"
      level: 2
      address: 21225
      datatype: "U16"
      unit: "MM"
    - name: "day"
      level: 2
      address: 21226
      datatype: "U16"
    - name: "hour"
      level: 2
      address: 21227
      datatype: "U16"
    - name: "minute"
      level: 2
      address: 21228
      datatype: "U16"
    - name: "second"
      level: 2
      address: 21229
      datatype: "U16"
    - name: "Dev_Adress"
      level: 2
      address: 21230
      datatype: "U16"
    - name: "Energy_per_Km"
      level: 2
      address: 21231
      datatype: "U16"

maybe you have an idea how to get the values displayed correctly

Otherwise, YES, it was great to work this out together.

Greetings Hubertus

HubertusH commented 1 month ago

Another important note for other users: querying the registers of the wallbox only works on the WInetS connection - these registers are not available on the LAN connection!

ludifu commented 1 month ago

Try accuracy:

    - name: "Total_Energy"
      level: 2
      address: 21200
      datatype: "U32"
      unit: "wh"
      accuracy: 0.001

And I suggest you put this register into the holdsection. At least the settings parametert MUST be hold parameters as you cannot write to read parameters. Possibly this whole section belongs in the hold section.

ludifu commented 1 month ago

Another important note for other users: querying the registers of the wallbox only works on the WInetS connection - these registers are not available on the LAN connection!

This is a pity - but good to know. However check reading the registers from the hold section (see my other post) before this is final.

HubertusH commented 1 month ago

Now the chaos is complete ;-)

I have looked in your "registers-sungrow". There the registers for "year" etc. are in the hold section. If I do the same I get the error message:

2024-05-31 10:38:49 ERROR    Failed to scrape: 'year'
Traceback (most recent call last):
  File "/home/pi/SunGather/Wallbox/sungather.py", line 156, in main
    success = inverter.scrape()
  File "/home/pi/.local/lib/python3.9/site-packages/SungrowClient/SungrowClient.py", line 379, in scrape
    del self.latest_scrape["year"]
KeyError: 'year'
Failed to scrape: 'year'
Traceback (most recent call last):
  File "/home/pi/SunGather/Wallbox/sungather.py", line 156, in main
    success = inverter.scrape()
  File "/home/pi/.local/lib/python3.9/site-packages/SungrowClient/SungrowClient.py", line 379, in scrape
    del self.latest_scrape["year"]
KeyError: 'year'

I then put these registers back in the read section - at least that part works.

An additional question: my serial number of the wallbox is "A2292803764" but with the query data type "UTF-8" I only get "A2292803".

I will now test the registers one by one and get back to you with the next problem :-))

Greetings Hubertus

Translated with www.DeepL.com/Translator (free version)

ludifu commented 1 month ago

The registers for year etc. are not the same as those from the inverter, because it is another unit / slave.

Testing register by register is a good idea. (However year and month etc. will probably not be in different sections.) But those registers that deliver strange values are good candidates. The data you reported is not only off by an accuracy factor ...

The problem with serial number and UTF8 is a bug in Sungather. (There has been an issue about this here before: The person reporting this had the problem of two identical serial numbers because they were different in only the last digit.) Sungather simply assumes too few bytes of data. And this is hardcoded way in the original version of Sungather and cannot be configured.

Btw. are you sure you get "A2292803" and not "A229280376" (only omitting the "4")?

HubertusH commented 1 week ago

wow - the biggest mistake on my part was that an offset of "1" must be observed for the INet connection. But not for all registers. :-)

Now, after a lot of testing, it works:

+----------------------------------------------------------------------+
| Address | Register                            | Value                |
+---------+-------------------------------------+----------------------+
| ----    | device_type_code                    | AC011E-01            |
| vr001   | run_state                           | OFF                  |
| vr003   | last_reset                          | 2024-06-21 10:10:25  |
| vr006   | daily_export_to_grid                | 0.0 kWh              |
| vr007   | daily_import_from_grid              | 0.0 kWh              |
| 21201   | serial_number                       | A229280376           |
| 21207   | PhaseSwitch                         | 0                    |
| 21262   | Rated_Voltage                       | 230 V                |
| 21263   | WorkMode                            | Netzwerk             |
| 21268   | Charger_Status                      | Enable               |
| 21300   | Total_Energy                        | 172.7 kWh            |
| 21302   | Charging_Voltage_R                  | 0.0 V                |
| 21303   | Charging_Current_R                  | 0.0 A                |
| 21304   | Charging_Voltage_S                  | 0.0 V                |
| 21305   | Charging_Current_S                  | 0.0 A                |
| 21306   | Charging_Voltage_T                  | 0.0 V                |
| 21307   | Charging_Current_T                  | 0.0 A                |
| 21308   | Charging_Power                      | 0.0 kW               |
| 21310   | Charging_Engery                     | 12.67 kWh            |
| 21314   | Start_Mode                          | None                 |
| 21316   | Power_Regulation                    | forbidden            |
| 21317   | Charging_Status                     | Idle                 |
| 21318   | Charge_Start_Time                   | 1718883655           |
| 21320   | Charge_End__Time                    | 1718894336           |
| 21316   | Hold-Status                         | 0                    |
| vr002   | timestamp                           | 2024-06-21 10:10:25  |
| vr004   | export_to_grid                      | 0 W                  |
| vr005   | import_from_grid                    | 0 W                  |
+----------------------------------------------------------------------+
Logged 28 registers to Console

I have also attached my register file registers-wallbox.yaml.txt

The "PhaseSwitch" register has not yet been confirmed. But you can also see the function, whether single-phase or multi-phase, from the Charging_xxx_y registers. If only one phase is charging, the power is Charging_Voltage_R Charging_Current_R for all three phases (simplified formula) Charging_Voltage_R Charging_Current_R * 1.732 (square root of 3).

Small problems remain:

Sungrow has confirmed that the registers of the wallbox are only available via the WINetS connection. If you could use two instances of sungather this would not be a problem.

Greetings Hubertus