Skip to content

SunSpec model discovery

Matt Magoffin edited this page Nov 30, 2022 · 1 revision

When working with SunSpec-compliant devices, sometimes it can be useful to look at the Modbus registers published according to the SunSpec standard. This guide describes how you can do this, using the mbpoll Modbus tool.

Identify the SunSpec base starting address

SunSpec allows manufacturers to use one of three starting Modbus registers: 40000, 50000, or 0. Starting at one of those addresses you will find the "magic" SunS marker that signals the start of the SunSpec register block. In hexidecimal the two 16-bit register values you're looking for are 0x5375 0x6E53.

SunSpec defines standard "models" of information. A model represents a class of device, like a meter or inverter. Each model has a defined numeric ID and a register layout published in the SunSpec standard. Starting from the base SunSpec address, any number of "model blocks" can appear, which are simply contiguous ranges of register addresses. Each block starts with a 2-register header with the model ID followed by the length of the rest of the block.

Once you discover a SunSpec model, you can look up that model in the SunSpec standard to understand what the individual registers within that block actually represent.

Conceptually the register layout looks like this:

+-------+--------+
| 50000 | 0x5375 | Su
| 50001 | 0x6E53 | nS
+-------+--------+
| 50002 | 0x0001 | Model ID: 1
| 50003 | 0x0041 | Model length: 65
| ....  |  ....  |
| 50068 | 0x6173 |
+-------+--------+
| 50069 | ?????? | Model ID: X
| 50070 | ?????? | Model length : N
| ....  |  ....  |
+-------+--------+
| ????? | 0xFFFF | Model ID: EOF
| ????? | 0x0000 |
+-------+--------+

Remember, there can be any number of blocks so do discover all the models you must follow an iterative process of discovering each one by one.

Using mbpoll, query for 4 holding registers using hex output, and verify you find the SunS start:

mbpoll -q -m tcp -a 141 -0 -1 -t 4:hex 192.168.6.15 -r 50000 -c 4
[50000]:        0x5375
[50001]:        0x6E53
[50002]:        0x0001
[50003]:        0x0041

This checks out, so we know the starting address is 50000, and the first model has ID 1 and a length of 65 registers (0x41 = 65).

Query the next model block, and the following model ID and length

Next query for the newly discovered model 1 starting at the next address (50004) for its discovered length + 2 (65 + 2 = 67):

mbpoll -q -m tcp -a 141 -0 -1 -t 4:hex 192.168.6.15 -r 50004 -c 67
[50004]:        0x4D65
[50005]:        0x6173
...
[50069]:        0x00CB
[50070]:        0x0069

We discovered that the next available model, in 50069, is 203, and has a length of 105.

Keep querying each newly discovered model block until you discover the EOL

The SunSpec models will end with the special model ID 0xFFFF so we must continue looking for models until we find that one. Starting from the next address (50071) we must query for 105 + 2 = 107 registers. That is too many registers to request in one query, so we just have to split that into two smaller ranges, I show 57 and 50 here:

mbpoll -q -m tcp -a 141 -0 -1 -t 4:hex 192.168.6.15 -r 50071 -c 57
[50071]: 	0x0000
[50072]: 	0x0000
...
[50126]: 	0x0000
[50127]: 	0x0000
mbpoll -q -m tcp -a 141 -0 -1 -t 4:hex 192.168.6.15 -r 50128 -c 50
[50128]: 	0x0000
[50129]: 	0x0000
...
[50176]: 	0x00D5
[50177]: 	0x007C

We discover that the next model, in 50176, is 213 and the next model length is 124 so we must query for 124 + 2 = 126 registers. That is too many to request in one query, so we just have to split that into two smaller ranges, I show 63 and 63 here:

mbpoll -q -m tcp -a 141 -0 -1 -t 4:hex 192.168.6.15 -r 50178 -c 63
[50178]: 	0x0000
[50179]: 	0x0000
...
[50239]: 	0x0000
[50240]: 	0x0000
mbpoll -q -m tcp -a 141 -0 -1 -t 4:hex 192.168.6.15 -r 50241 -c 63
[50241]: 	0x0000
[50242]: 	0x0000
...
[50302]: 	0xFFFF
[50303]: 	0x0000

Finally, we reached the "no more models" model ID 0xFFFF so we have discovered all models.

Clone this wiki locally