Skip to content

Command-line tool

sunspecctl is the command-line tool bundled with go-sunspec. It detects SunSpec devices, lists their models, and reads or polls decoded points with scale factors and units applied. It only reads: there is no command that writes to a device.

For transport-level SunSpec work (marker, base address, model headers, capturing every model to a file), modbusctl has its own SunSpec commands, covered at the end of this page.

Pre-built binaries for Linux (x86-64, ARM64, ARMv7), macOS (Apple Silicon, Intel) and Windows (x86-64, ARM64) are on the go-sunspec releases page, with a sunspecctl-<version>-checksums.txt file of SHA-256 sums.

Terminal window
VERSION=$(curl -fsSLI -o /dev/null -w '%{url_effective}' https://github.com/otfabric/go-sunspec/releases/latest | sed 's|.*/v||')
case "$(uname -m)" in
x86_64) ARCH=amd64 ;;
aarch64|arm64) ARCH=arm64 ;;
armv7l) ARCH=armv7 ;;
esac
FILE="sunspecctl-${VERSION}-linux-${ARCH}.tar.gz"
BASE="https://github.com/otfabric/go-sunspec/releases/download/v${VERSION}"
curl -fsSLO "${BASE}/${FILE}"
curl -fsSLO "${BASE}/sunspecctl-${VERSION}-checksums.txt"
grep "${FILE}" "sunspecctl-${VERSION}-checksums.txt" | sha256sum -c -
mkdir -p sunspecctl-dl && tar -xzf "${FILE}" -C sunspecctl-dl
sudo install -m 0755 "$(find sunspecctl-dl -type f -name 'sunspecctl*' | head -n1)" /usr/local/bin/sunspecctl

For a serial port without sudo, add your user to the dialout group: sudo usermod -aG dialout "$USER", then log out and back in.

The README also has a PowerShell script for Windows that verifies the checksum and adds the binary to your PATH. Check the install with sunspecctl version.

All commands share these global flags:

Flag Default Description
--url tcp://localhost:502 Modbus device URL
--unit-id 1 Modbus unit ID
--timeout 10s Operation timeout
--json false Output as JSON
--raw false Include raw register hex in the output
--baud 0 (19200) Serial baud rate for rtu:// and ascii://
--data-bits 0 (8 for RTU, 7 for ASCII) Serial data bits, 5 to 8
--parity none none, even or odd
--stop-bits 0 (2 without parity, 1 with) Serial stop bits, 1 or 2

--url takes any go-modbus scheme: tcp://host:port, rtu://<device> (rtu:///dev/ttyUSB0, rtu://COM3), ascii://<device>, udp://host:port, rtuovertcp://host:port for a serial-to-Ethernet gateway, and the others listed in the Modbus overview. The serial flags are ignored for network URLs.

sunspecctl
├── detect Detect SunSpec device presence
├── models List discovered SunSpec models
├── read Read and decode all models
├── read-model Read and decode a specific model by ID
├── read-point Read a single named point from a model
├── poll Repeatedly read and decode all models
├── poll-model Repeatedly read and decode a specific model by ID
├── poll-point Repeatedly read a single named point from a model
├── completion Generate shell completion script (bash/zsh/fish/powershell)
└── version Print the sunspecctl version
  1. Check that the device speaks SunSpec and find its base address:

    Terminal window
    sunspecctl detect --url tcp://192.168.1.100:502
  2. List the models it implements:

    Terminal window
    sunspecctl models --url tcp://192.168.1.100:502
  3. Read one model, or one point:

    Terminal window
    sunspecctl read-model --id 101 --url tcp://192.168.1.100:502
    sunspecctl read-point --model 101 --point W --url tcp://192.168.1.100:502
  4. Read and decode everything, with the raw registers alongside:

    Terminal window
    sunspecctl read --url tcp://192.168.1.100:502 --raw

Over RS-485 or through a gateway:

Terminal window
# SunSpec over Modbus RTU at 9600 8N1, device address 3
sunspecctl models --url rtu:///dev/ttyUSB0 --baud 9600 --stop-bits 1 --unit-id 3
# A serial device behind an RS-485-to-Ethernet gateway
sunspecctl read --url rtuovertcp://192.168.1.50:4001 --unit-id 3

If detect finds nothing, check the unit ID first (many inverters do not answer on unit 1), then whether SunSpec or Modbus has to be enabled in the device settings. The library can probe other base addresses and input registers; the documented CLI flags do not expose those options.

poll, poll-model and poll-point work like their read counterparts but repeat:

Flag Default Description
--interval 30s Time between polls (s, m, h)
--count 0 Number of polls; 0 runs until Ctrl-C
Terminal window
# All models every 10 seconds
sunspecctl poll --interval 10s --url tcp://192.168.1.100:502
# Model 101 five times, once per minute
sunspecctl poll-model --id 101 --interval 1m --count 5 --url tcp://192.168.1.100:502
# AC power of a three-phase inverter every 5 seconds, as JSON
sunspecctl poll-point --model 103 --point W --interval 5s --json --url tcp://192.168.1.100:502

The default output is a human-readable table. --json gives structured output for jq and scripts, and --raw adds the raw register hex next to the decoded values. When a value looks wrong, sunspecctl read --raw shows the registers behind it; include that output, together with detect and models, when you report a device problem.

The README does not document exit codes or environment variables for sunspecctl. Do not rely on specific non-zero codes in scripts; check for zero and parse --json output.

sunspecctl only reads, so it cannot change a setpoint. It still sends real Modbus requests: use it only on devices and networks you are authorized to access, and keep inverter, meter and battery Modbus ports off the Internet. Output can contain serial numbers, network addresses and production figures, so treat it as operational data.

modbusctl works at the Modbus level. Its SunSpec commands find the marker and enumerate model headers, but do not decode points.

Command What it does
client sunspec detect Is the unit SunSpec, and at which base? --bases 0,40000,50000 to probe specific bases, --verbose for the attempt log
client sunspec models The model chain: start and end address, model ID, length, end model. --base skips detection; --max-models and --max-address-span bound the walk
client sunspec map A readable address map. --show-header-regs, --show-next, --compact
client sunspec probe One-shot summary: FC03, FC04 and FC43 support plus SunSpec detection
Terminal window
modbusctl client sunspec detect --ip 192.168.1.10 --unit 1 --regtype holding --bases 0,40000,50000 --verbose --format json
modbusctl client sunspec models --ip 192.168.1.10 --unit 1 --base 40000 --max-models 64 --format json
modbusctl client sunspec map --url tcp://192.168.1.10:502 --unit 1
modbusctl client sunspec probe --url tcp://192.168.1.10:502 --unit 1

--regtype accepts holding or input, which is how you reach a device that keeps its SunSpec map in input registers from the command line. All four commands take --format text|json|table.

To capture every model body to a file, use the SunSpec scan algorithm. It detects the base, walks the chain and reads each model in chunks of up to 125 registers:

Terminal window
modbusctl client scan --ip 192.168.1.10 --algo sunspec --output sunspec.mcap
modbusctl client scan --ip 192.168.1.10 --algo sunspec --sunspec-base 40000 --output sunspec.mcap

The resulting MCAP file can be served back as a Modbus TCP device with modbusctl server static --input sunspec.mcap --port 1502.