Start | End | Block description |
---|---|---|
3972 | 3972 | Unknown |
4096 | 4111 | Brand and model name |
4112 | 4239 | Empty |
4320 | 4320 | Date and time |
4352 | 4415 | Same as 5120-5183 |
4416 | 4607 | Empty |
4608 | 4671 | Unknown, maybe settings (seems static) |
4672 | 4863 | Empty |
5120 | 5183 | BMS status |
5184 | 5199 | Empty |
5200 | 5215 | BMS SN |
5216 | 5231 | Pack 0-x - Module 0-x Voltage |
5232 | 5295 | Empty |
5296 | 5311 | Pack 0-x - Module 0-x Temperature |
5312 | 5375 | Empty |
5376 | 5503 | Pack 0 Module 0-4 Cell Voltage |
5504 | 6143 | ?? Pack 1-5 Module 0-4 Cell Voltage |
6144 | 6271 | Pack 0 Module 0-4 Cell Temperature |
6272 | 6911 | ?? Pack 1-5 Module 0-4 Cell Temperature |
-
-
Save nagisa/435bdf783e4b13b8e810106b0852081e to your computer and use it in GitHub Desktop.
requests: | |
# Brand, Device name, FW Version | |
- start: 4096 | |
end: 4106 | |
mb_functioncode: 0x03 | |
# Device Date and Time - TODO | |
#- start: 4320 | |
# end: 4325 | |
# mb_functioncode: 0x03 | |
# BMS Status | |
- start: 5120 | |
end: 5135 | |
mb_functioncode: 0x03 | |
# Cell/Module Max/Min Temperature and Voltage | |
- start: 5136 | |
end: 5151 | |
mb_functioncode: 0x03 | |
# Total Charge, Discharge | |
- start: 5152 | |
end: 5167 | |
mb_functioncode: 0x03 | |
# Pack, Module, Cell count | |
- start: 5174 | |
end: 5175 | |
mb_functioncode: 0x03 | |
# Device SN | |
- start: 5200 | |
end: 5207 | |
mb_functioncode: 0x03 | |
# Pack 0 Module 0-3 Voltage | |
- start: 5216 | |
end: 5219 | |
mb_functioncode: 0x03 | |
# Pack 0 Module 0-3 Temperature | |
- start: 5296 | |
end: 5299 | |
mb_functioncode: 0x03 | |
# Pack 0 Module 0-3 Cells Voltage | |
#- start: 5376 | |
# end: 5465 | |
# mb_functioncode: 0x03 | |
# Pack 0 Module 0-3 Cells Temperature | |
#- start: 6144 | |
# end: 6233 | |
# mb_functioncode: 0x03 | |
parameters: | |
- group: Basic information | |
items: | |
- name: "Device SN" | |
class: "" | |
state_class: "" | |
uom: "" | |
scale: 1 | |
rule: 5 | |
registers: [ 5200,5201,5202,5203,5204,5205,5206,5207 ] | |
isstr: true | |
#- name: "Device Time" # TODO - cant parse format is [y, m, d, h, m, s] | |
# class: "" | |
# state_class: "" | |
# uom: "" | |
# scale: 1 | |
# rule: 8 | |
# registers: [4320,4321,4322,4323,4324,4325] | |
# isstr: true | |
- name: "Brand" | |
class: "" | |
state_class: "" | |
uom: "" | |
scale: 1 | |
rule: 5 | |
registers: [ 4096,4097,4098 ] | |
isstr: true | |
- name: "Device Name" | |
class: "" | |
state_class: "" | |
uom: "" | |
scale: 1 | |
rule: 5 | |
registers: [ 4101,4102,4103,4104,4105 ] | |
isstr: true | |
- name: "FW Version" | |
class: "" | |
state_class: "" | |
uom: "" | |
scale: 1 | |
rule: 7 | |
registers: [ 4106 ] # 00000001 00000110 = V1.6 | |
isstr: true | |
# NOTE: buggy, counter jumps up by a couple MWh once in a while | |
- name: "Total Charge" | |
class: "energy" | |
state_class: "total_increasing" | |
uom: "kWh" | |
scale: 1 | |
rule: 1 | |
registers: [ 5164 ] | |
icon: 'mdi:battery-plus' | |
# NOTE: buggy, counter jumps up by a couple MWh once in a while | |
- name: "Total Discharge" | |
class: "energy" | |
state_class: "total_increasing" | |
uom: "kWh" | |
scale: 1 | |
rule: 1 | |
registers: [ 5166 ] | |
icon: 'mdi:battery-minus' | |
#- name: "Battery Pack (parallel)" # not tested | |
# class: "" | |
# state_class: "" | |
# uom: "" | |
# scale: 1 | |
# rule: 1 | |
# registers: [5173] | |
- name: "Battery Module (series)" | |
class: "" | |
state_class: "" | |
uom: "" | |
scale: 1 | |
rule: 1 | |
registers: [ 5174 ] | |
- name: "Battery Cell (series)" | |
class: "" | |
state_class: "" | |
uom: "" | |
scale: 1 | |
rule: 1 | |
registers: [ 5175 ] | |
- group: Battery | |
items: | |
- name: "Battery Voltage" | |
class: "voltage" | |
state_class: "measurement" | |
uom: "V" | |
scale: 0.1 | |
rule: 1 | |
registers: [ 5123 ] | |
icon: 'mdi:battery' | |
- name: "Battery Current" | |
class: "current" | |
state_class: "measurement" | |
uom: "A" | |
scale: 0.01 | |
rule: 2 | |
registers: [ 5125 ] | |
icon: 'mdi:current-dc' | |
- name: "Battery Temperature" | |
class: "temperature" | |
state_class: "measurement" | |
uom: "°C" | |
scale: 0.1 | |
rule: 2 | |
registers: [ 5126 ] | |
icon: 'mdi:thermometer' | |
- name: "Battery Charge" | |
class: "battery" | |
state_class: "measurement" | |
uom: "%" | |
scale: 1 | |
rule: 1 | |
registers: [ 5127 ] | |
icon: 'mdi:battery' | |
- name: "Battery Cycle Times" | |
class: "" | |
state_class: "" | |
uom: "" | |
scale: 1 | |
rule: 1 | |
registers: [ 5128 ] | |
icon: 'mdi:battery-heart' | |
- name: "Max Charging Voltage" | |
class: "voltage" | |
state_class: "measurement" | |
uom: "V" | |
scale: 0.1 | |
rule: 1 | |
registers: [ 5129 ] | |
- name: "Max Charging Current" | |
class: "current" | |
state_class: "measurement" | |
uom: "A" | |
scale: 0.01 | |
rule: 2 | |
registers: [ 5131 ] | |
icon: 'mdi:current-dc' | |
- name: "Min Discharging Voltage" | |
class: "voltage" | |
state_class: "measurement" | |
uom: "V" | |
scale: 0.1 | |
rule: 1 | |
registers: [ 5132 ] | |
- name: "Max Discharging Current" | |
class: "current" | |
state_class: "measurement" | |
uom: "A" | |
scale: 0.01 | |
rule: 2 | |
registers: [ 5134 ] | |
icon: 'mdi:current-dc' | |
- name: "Max Cell Voltage" | |
class: "voltage" | |
state_class: "measurement" | |
uom: "V" | |
scale: 0.001 | |
rule: 1 | |
registers: [ 5136 ] | |
icon: 'mdi:battery' | |
- name: "Min Cell Voltage" | |
class: "voltage" | |
state_class: "measurement" | |
uom: "V" | |
scale: 0.001 | |
rule: 1 | |
registers: [ 5137 ] | |
icon: 'mdi:battery' | |
- name: "Max Cell Voltage ID" | |
class: "" | |
state_class: "" | |
uom: "" | |
scale: 1 | |
rule: 1 | |
registers: [ 5138 ] | |
- name: "Min Cell Voltage ID" | |
class: "" | |
state_class: "" | |
uom: "" | |
scale: 1 | |
rule: 1 | |
registers: [ 5139 ] | |
- name: "Max Cell Temperature" | |
class: "temperature" | |
state_class: "measurement" | |
uom: "°C" | |
scale: 0.1 | |
rule: 2 | |
registers: [ 5140 ] | |
icon: 'mdi:thermometer' | |
- name: "Min Cell Temperature" | |
class: "temperature" | |
state_class: "measurement" | |
uom: "°C" | |
scale: 0.1 | |
rule: 2 | |
registers: [ 5141 ] | |
icon: 'mdi:thermometer' | |
- name: "Max Cell Temperature ID" | |
class: "" | |
state_class: "" | |
uom: "" | |
scale: 1 | |
rule: 1 | |
registers: [ 5142 ] | |
- name: "Min Cell Temperature ID" | |
class: "" | |
state_class: "" | |
uom: "" | |
scale: 1 | |
rule: 1 | |
registers: [ 5143 ] | |
- name: "Max Module Voltage" | |
class: "voltage" | |
state_class: "measurement" | |
uom: "V" | |
scale: 0.01 | |
rule: 1 | |
registers: [ 5144 ] | |
icon: 'mdi:battery' | |
- name: "Min Module Voltage" | |
class: "voltage" | |
state_class: "measurement" | |
uom: "V" | |
scale: 0.01 | |
rule: 1 | |
registers: [ 5145 ] | |
icon: 'mdi:battery' | |
- name: "Max Module Voltage ID" | |
class: "" | |
state_class: "" | |
uom: "" | |
scale: 1 | |
rule: 1 | |
registers: [ 5146 ] | |
- name: "Min Module Voltage ID" | |
class: "" | |
state_class: "" | |
uom: "" | |
scale: 1 | |
rule: 1 | |
registers: [ 5147 ] | |
- name: "Max Module Temperature" | |
class: "temperature" | |
state_class: "measurement" | |
uom: "°C" | |
scale: 0.1 | |
rule: 2 | |
registers: [ 5148 ] | |
icon: 'mdi:thermometer' | |
- name: "Min Module Temperature" | |
class: "temperature" | |
state_class: "measurement" | |
uom: "°C" | |
scale: 0.1 | |
rule: 2 | |
registers: [ 5149 ] | |
icon: 'mdi:thermometer' | |
- name: "Max Module Temperature ID" | |
class: "" | |
state_class: "" | |
uom: "" | |
scale: 1 | |
rule: 1 | |
registers: [ 5150 ] | |
- name: "Min Module Temperature ID" | |
class: "" | |
state_class: "" | |
uom: "" | |
scale: 1 | |
rule: 1 | |
registers: [ 5151 ] | |
- name: "Battery SOH" | |
class: "battery" | |
state_class: "measurement" | |
uom: "%" | |
scale: 1 | |
rule: 1 | |
registers: [ 5152 ] | |
icon: 'mdi:battery' | |
# NOTE: buggy, counter jumps up by a couple MWh once in a while | |
- name: "Today Charge" | |
class: "energy" | |
state_class: "total_increasing" | |
uom: "kWh" | |
scale: 0.001 | |
rule: 1 | |
registers: [ 5160 ] | |
# NOTE: buggy, counter jumps up by a couple MWh once in a while | |
- name: "Today Discharge" | |
class: "energy" | |
state_class: "total_increasing" | |
uom: "kWh" | |
scale: 0.001 | |
rule: 1 | |
registers: [ 5162 ] | |
- group: Battery Module 0 | |
items: | |
- name: "Battery Module 0 Voltage" | |
class: "voltage" | |
state_class: "measurement" | |
uom: "V" | |
scale: 0.01 | |
rule: 1 | |
registers: [ 5216 ] | |
icon: 'mdi:battery' | |
- name: "Battery Module 0 Temperature" | |
class: "temperature" | |
state_class: "measurement" | |
uom: "°C" | |
scale: 0.1 | |
rule: 2 | |
registers: [ 5296 ] | |
icon: 'mdi:thermometer' | |
- group: Battery Module 1 | |
items: | |
- name: "Battery Module 1 Voltage" | |
class: "voltage" | |
state_class: "measurement" | |
uom: "V" | |
scale: 0.01 | |
rule: 1 | |
registers: [ 5217 ] | |
icon: 'mdi:battery' | |
- name: "Battery Module 1 Temperature" | |
class: "temperature" | |
state_class: "measurement" | |
uom: "°C" | |
scale: 0.1 | |
rule: 2 | |
registers: [ 5297 ] | |
icon: 'mdi:thermometer' | |
- group: Battery Module 2 | |
items: | |
- name: "Battery Module 2 Voltage" | |
class: "voltage" | |
state_class: "measurement" | |
uom: "V" | |
scale: 0.01 | |
rule: 1 | |
registers: [ 5218 ] | |
icon: 'mdi:battery' | |
- name: "Battery Module 2 Temperature" | |
class: "temperature" | |
state_class: "measurement" | |
uom: "°C" | |
scale: 0.1 | |
rule: 2 | |
registers: [ 5298 ] | |
icon: 'mdi:thermometer' |
""" Scan Modbus registers to find valid registers""" | |
from pysolarmanv5 import PySolarmanV5, V5FrameError | |
import umodbus.exceptions | |
import argparse | |
# Docs: | |
# - https://pysolarmanv5.readthedocs.io/en/stable/solarmanv5_protocol.html | |
# - https://github.com/jmccrohan/pysolarmanv5 | |
# | |
# Usage: | |
# pip install pysolarmanv5 | |
# python solarmanPylontechScan.py 5120 5199 > scan_240224_10_10.csv | |
deviceIP="192.168.x.x" # string IP address | |
deviceSerialNumber=123456789 # int device serial number | |
def main(): | |
parser = argparse.ArgumentParser() | |
parser.add_argument("address", help="Address to start scanning from", type=int) | |
parser.add_argument("addressStop", help="Last address to scan", type=int) | |
args = parser.parse_args() | |
if args.address < 0: | |
print("Address must be greater than or equal to 0") | |
return | |
if args.addressStop < 0: | |
print("AddressStop must be greater than or equal to 0") | |
return | |
if args.addressStop < args.address: | |
print("AddressStop must be greater than or equal to address") | |
return | |
modbus = PySolarmanV5( | |
deviceIP, deviceSerialNumber, port=8899, mb_slave_id=1, verbose=False | |
) | |
# print as csv header | |
print("Register, Register Hex, Length, Value Int, Value Hex, Value Bin1, Value Bin2") | |
for x in range(args.address, args.addressStop): | |
try: | |
val = modbus.read_holding_registers(register_addr=x, quantity=1)[0] | |
binLeft = (val >> 8) & 0xff | |
binRight = val & 0xff | |
# csv row | |
print(f"{x}, {x:#06x}, 1, {val:05}, {val:#06x}, {binLeft:08b}, {binRight:08b}") | |
except (V5FrameError, umodbus.exceptions.IllegalDataAddressError): | |
print(f"{x}, {x:#06x}, 1") | |
continue | |
modbus.disconnect() | |
if __name__ == "__main__": | |
main() | |
There isn't anything published. I imagine the person whom I forked this from determined a basic layout by tracing the I/O between the battery and the wifi module when it is working in the cloud mode and then the remainder is an informed guess.
I have also asked support a couple times for some official docs, only to get ghosted.
amazing work than, thanks a lot for sharing.
There isn't anything published. I imagine the person whom I forked this from determined a basic layout by tracing the I/O between the battery and the wifi module when it is working in the cloud mode and then the remainder is an informed guess.
I have also asked support a couple times for some official docs, only to get ghosted.
I had to read all the registry values and compare them to the official Solarman Business app data. There were some predictions based on the layout for additional batteries, even though I have only three connected in parallel.
from where did you get the the registry map? I am googling for an hour now to find a official protocoll documentation..