| 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 |
Last active
December 11, 2025 14:26
-
-
Save pavelmaca/170c282bdb9e20b6c624e8c7633be3b2 to your computer and use it in GitHub Desktop.
Pylontech Force H2 - Solarman Modbus RTU registry map
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 | |
| - name: "Total Charge" | |
| class: "energy" | |
| state_class: "total_increasing" | |
| uom: "kWh" | |
| scale: 1 | |
| rule: 1 | |
| registers: [ 5164 ] | |
| icon: 'mdi:battery-plus' | |
| - 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' | |
| - name: "Today Charge" | |
| class: "energy" | |
| state_class: "total_increasing" | |
| uom: "kWh" | |
| scale: 0.001 | |
| rule: 1 | |
| registers: [ 5160 ] | |
| - 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' |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| """ 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() |
My batteries don't go into any sort of sleep states at all as far as I can tell.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
As @nagisa stated this has been VERY helpful, thanks a lot!
I can confirm that almost all registers work in the same way on a Pylontech X1 (SC0500) by using modbus-rtu on the RS485 port.
Have you @nagisa @pavelmaca found out how to wake the battery from deep sleep over these signals? Maybe there are also write signals to achieve this?