Repository navigation
Releases: otfabric/go-sunspec
Release list
v0.4.2
Date: 2026-10-11
Previous release: v0.4.1
Summary
Patch release: adopts go-modbus v1.3.0. No API or model changes.
Changes
Changed
- go-modbus — requires
github.com/otfabric/go-modbusv1.3.0 (was v1.2.1). What callers ofClientand users ofsunspecctlnotice on TCP: after a request times out the connection is replaced, so a late response is never taken for the answer to the next request; an open client reconnects by itself after a dropped connection (the request that hits the dead connection still fails); and cancelling the context of a call interrupts the request in flight.
Unchanged
- No API, wire-format or model changes. Import path remains
github.com/otfabric/go-sunspec.
v0.4.1
Date: 2026-10-09
Previous release: v0.4.0
Summary
Patch release: sync the SunSpec model definitions with upstream. One model changed: the units of a point in model 122. This is the first update found by the weekly models check added in v0.4.0 (#1). No API changes.
Changes
Changed
- Model 122 (Measurements_Status) — the units of
WAval(available watts) are nowW; upstream changed them fromvar.DecodedPoint.Unitsfor this point changes from"var"to"W", and so does the unitsunspecctlprints next to it. The point's type, size, scale factor (WAval_SF) and value are unchanged. models/model_122.json— refreshed from sunspec/modelsmasterwith./sync-models.sh; still 112 compiled models.registry/models_gen.go— regenerated withmake generate.
Unchanged
- No other model differs from upstream (
./check-models.shreports the local copy in sync), and there are no API, wire or behaviour changes. Import path remainsgithub.com/otfabric/go-sunspec.
v0.4.0
Date: 2026-10-09
Previous release: v0.3.1
Summary
Models are now decoded as the full tree of groups their definition describes, which fixes the DER curve and trip models that were decoded incompletely; this changes the shape of the decoded model and of the registry (see Breaking changes). sunspecctl can now reach SunSpec devices on serial lines with non-default settings, the repository watches the official SunSpec model definitions for changes every week, and the project gets the same quality gates as the rest of the otfabric library family: full doc comments, a much larger test suite, and stricter lint, formatting and coverage checks. Built on go-modbus v1.2.1.
Breaking changes
There are API changes in this release. The module is pre-1.0 and the changes are needed to represent SunSpec models correctly.
- Decoded models are a group tree.
DecodedModel.FixedBlockandDecodedModel.RepeatingBlocksare replaced byDecodedModel.Group, a*DecodedGroupwith the model's ownPointsand, inGroups, the instances of the groups nested inside it, to any depth.DecodedBlockis renamedDecodedGroup; it gainsNameandGroups, andGroupIndexbecomesIndex(0 for the top-level group, 1..N for nested instances).dm.FixedBlock.Points→dm.Group.Pointsdm.RepeatingBlocks→dm.Group.Groups(ordm.Group.GroupsNamed("module"))- New helpers:
DecodedModel.Point,DecodedGroup.Point,FindPoint,GroupsNamed,Walk.
- The registry is a group tree.
ModelMeta.FixedBlockandModelMeta.RepeatingBlockare replaced byModelMeta.Group.GroupMetagainsDesc,Type,Count,CountPointandGroups; itsRepeatingfield is now the methodRepeating().ModelMeta.RepeatingLength()is removed;FixedLength()remains. New helpersGroupMeta.GroupandGroupMeta.Point. DecodedPoint.RegisterOffsetis now the offset from the model's ID register (the index inRawRegisters); it used to be relative to the point's block.sunspecctltable output labels nested groups by name and instance, indented under their parent ([module 1],[Crv 2]→[Pt 1]), instead of[Repeating[0]]. JSON output follows the newDecodedModelshape.- Warning texts for registers that do not fit a group changed, and warnings from nested groups carry the group path.
Changes
Added
sunspecctlserial settings — new global flags--baud,--data-bits,--parity(none,even,odd) and--stop-bitsforrtu://andascii://URLs. Previously only--urlwas passed on, so a serial device could be reached only at the go-modbus defaults (19200 baud, no parity, 2 stop bits). Example:sunspecctl models --url rtu:///dev/ttyUSB0 --baud 9600 --stop-bits 1 --unit-id 3. Invalid values are rejected before the port is opened. The flags are ignored for network URLs.- Modbus ASCII —
ascii://<device>andasciiovertcp://host:portURLs work with the library and the CLI, through go-modbus v1.2. - Weekly SunSpec models check — a GitHub Actions workflow (
models-check.yml) comparesmodels/with sunspec/models every Monday. When upstream has new, changed or removed models it opens an issue (or updates the open one) showing what changed — the points that differ and the JSON diff — and closes it oncemodels/is back in sync. check-models.sh/make models-check— the read-only check behind that workflow.--diffprints the point-level and JSON differences;--diff-file FILEwrites them to a file.- CONTRIBUTING.md, SECURITY.md, codecov.yml (project target 90%).
.golangci.yml— the lint configurationmake lint-cirefers to (errcheck, govet, staticcheck, ineffassign, misspell, godot, nilerr, exhaustive, gofmt, goimports).make fmt-check— part ofmake check. Formatting is done with thegofmtof the Go version ingo.mod(the one CI uses), and the check fails if thatgofmtor the locally installed one would change a file.
Changed
- README — rewritten: what the library does and for whom, supported models, decoded values, serial and other transports, CLI installation, FAQ.
- Doc comments — every exported identifier in
sunspec,registryandtestutilis documented. - Tests — statement coverage raised from 58% to 98% of the library and tooling packages, and from 4% to 99% for
sunspecctl; the generator, the model parser, the fixture server and everysunspecctlcommand are now tested. A test regenerates the registry frommodels/and fails ifregistry/models_gen.gois out of date. - Coverage gate —
make checknow measures every package (it was the library packages only) and requires 90% (was 75%). CI testscmd/sunspecctltoo. - Not-implemented detection for strings and addresses — a
stringpoint that is all NUL, anipaddrof0.0.0.0, an all-zeroipv6addrand aneui48ofFF:FF:FF:FF:FF:FFare now reported withImplemented: false, as the SunSpec specification defines. They used to be reported as implemented, sosunspecctllisted empty rows for them. Behaviour change for code that relied onImplementedbeing true for these.
Fixed
- Models with nested or sibling groups were decoded incompletely. The registry kept one fixed and one repeating block per model. The DER curve and trip models (705–710, 712) and 64410/64411 lost the groups nested inside their repeating group (the curve points), and model 704 kept only the first of its four sibling groups, treated as repeating. Every group of every model is now in the registry and decoded.
- Group counts are taken from the model. The number of instances of a nested group now comes from its count point (
NCrv,NPt,NStr, …) or its fixed count, as the model defines; a group without a count occurs exactly once. Only groups defined with count 0 repeat for the remaining length of the model, as before. - Scale factors in nested groups. A named scale factor is looked up in the point's own group instance first and then in the enclosing groups, so curve points scaled by a factor defined at the top of the model are scaled. A scale factor that a nested group reports as not implemented does not hide a usable one further out.
- Scaled values had floating-point artefacts. A value such as 95 with scale factor -2 came out as
0.9500000000000001; it is now exactly0.95. - EUI-48 (MAC address) points were decoded from the wrong registers. An
eui48point is four registers with the address in the low 48 bits; the decoder read the first three registers, which shifted the address by two bytes and dropped its last two. Affects models 11 and 16. - JSON encoding failed for float models with unimplemented points. A float point the device reports as not implemented is NaN, which
encoding/jsonrejects, sosunspecctl read --json(andread-model,read-point,poll*) failed on models such as 111–113 and 211–214, and so didjson.Marshalon aDecodedModel.DecodedPointnow encodes non-finite values asnull; field names are unchanged. - Reads that reached the end of the address space wrapped around. A model read split into several Modbus requests could wrap from register 65535 to 0 and return those registers as if they were contiguous. Such a range is now rejected before any I/O.
- Panics on nil or malformed input replaced by errors or safe behaviour: a nil
*modbus.Client(Detect,Discover,Open,ReadModel,ReadPoint,ReadAll),NewDevicewith a nil discovery result,DecodeModelwith a nil schema,registry.Register(nil), and caller-supplied schemas whose points have a negative offset or fewer registers than their type needs. - Enum symbols with negative values no longer match an unimplemented
enum32value.
Dependencies
- Go 1.23+
- otfabric/go-modbus
v1.1.3→ v1.2.1 (Modbus ASCII transport, corrected function probing, server and engine fixes; see its release notes) - spf13/cobra v1.10.2 (CLI only)
v0.3.1
Date: 2026-07-30
Previous release: v0.3.0
Summary
Patch release: bump go-modbus to v1.1.3 (pulls go-serial v0.1.6). No API or
behaviour changes.
Changes
Dependencies
- go-modbus —
v1.1.1→ v1.1.3 - go-serial (indirect) —
v0.1.5→ v0.1.6
Unchanged
- No API, wire, or behavioural changes. Import path remains
github.com/otfabric/go-sunspec.
v0.3.0
Date: 2026-07-29
Summary
Align documentation and error contracts with the rest of the otfabric library family. Sync SunSpec JSON models from upstream and regenerate the compiled registry. Minor release: new exported error types and removal of an unused sentinel.
Changes
Added
- doc.go — package overview covering scope, ownership, concurrency, and entry points.
- API.md / ERRORS.md — public API and error taxonomy.
- DecodeError — typed decode failure with model/point location fields.
- ErrPointNotFound — sentinel for missing point names in
ReadPoint. - Runnable examples for
DecodeModeland registry lookups. - Makefile
vuln—govulncheck ./..., included inmake check. - Makefile coverage targets —
coverage,coverage-html,coverage-check(minimum 75% on library packages.and./registry), andcoverage-clean. - models/README.md — documents upstream source of the JSON model definitions (sunspec/models
json/onmaster). - Additional unit/integration coverage for
Detect,ReadPoint,toGMSunspecOptions, IPv6 decode, scale application, and registry length helpers.
Changed
- README — quickstart handles
modbus.New/Openerrors; documents ownership, concurrency, inherited Modbus observability; correctsregistry.All()return type; documents model provenance and Apache-2.0 upstream license. - ErrUnknownModel — comment clarifies it means “not in discovery”, not “no local schema”.
- ErrPartialRead — wraps the underlying Modbus cause with
%w. - Makefile — exports
GOWORK=offso checks and builds ignore a parentgo.workand run as a standalone module;make checkenforces the coverage gate. - SunSpec models — refreshed
models/*.jsonfrom sunspec/modelsmastervia./sync-models.sh(59 files updated; still 112 compiled models). Mostly description-text cleanup; model 64415 gainsSubscribedResourceandSubscriptionEna. - registry/models_gen.go — regenerated with
make generateto match the synced JSON.
Removed
- ErrUnsupportedPointType — unused. Unsupported point types continue to produce
DecodedModelwarnings with raw registers retained.
Dependencies
- Go 1.23+
- otfabric/go-modbus v1.1.1
- spf13/cobra v1.10.2 (CLI only)
v0.2.3
Date: 2026-07-08
Summary
Prepare the repository for public open-source release under the MIT License. Add license files and SPDX headers, and standardize README badges for publication.
Changes
Added
- LICENSE — root MIT license file (
Copyright (c) 2026 OT Fabric). - SPDX headers —
// SPDX-License-Identifier: MITon all first-party Go source files. - README — license section and table of contents.
Changed
- README badges — standardized badge block for public release: added pkg.go.dev reference, removed Go Report Card, switched Codecov to a tokenless public URL, and normalized the release badge label.
- go-modbus — upgraded
github.com/otfabric/go-modbusfrom v1.0.4 to v1.1.1.
Dependencies
- Go 1.23+
- otfabric/go-modbus v1.1.1
- spf13/cobra v1.10.2 (CLI only)
v0.2.2
Date: 2026-03-23
Summary
Remove stale github.com/otfabric/sunspec dependency left over from the repository rename. All internal imports and documentation now use the current module path github.com/otfabric/go-sunspec.
Changes
Changed
- Module imports — replaced all
github.com/otfabric/sunspecimports withgithub.com/otfabric/go-sunspecacross 10 source files. - go.mod / go.sum — removed the
github.com/otfabric/sunspec v0.2.0dependency (circular self-reference under the old name). - README — updated title, badges, install command, code examples, project structure, and dependency list to reflect the
go-sunspec/go-modbusmodule paths.
Dependencies
- Go 1.23+
- otfabric/go-modbus v1.0.4
- spf13/cobra v1.10.2 (CLI only)
v0.2.1
Date: 2026-03-23
Summary
Enhance sunspecctl build metadata and improve project layout. The CLI binary now embeds full version, tag, commit, and build-date information via -ldflags, and local builds output to ./bin/.
Changes
Changed
- Version command —
sunspecctl versionnow prints version, git tag, commit hash, and build date (previously only printed the version string). Supports--jsonfor structured output. - Build-time ldflags — Makefile passes
-X main.version,-X main.tag,-X main.commit, and-X main.buildDateto match the CI release workflow. - Build output directory —
make buildandmake build-clinow output the binary to./bin/sunspecctlinstead of the project root.make installandmake cleanupdated accordingly.
Added
- Release workflow — new
release-sunspecctl-binaryjob inrelease.ymlpublishes cross-platformsunspecctlbinaries via the sharedgo-binary-releaseworkflow with full ldflags.
Dependencies
- Go 1.23+
- otfabric/go-modbus v1.0.4
- otfabric/sunspec v0.2.0
- spf13/cobra v1.10.2 (CLI only)
v0.2.0
Release v0.2.0
Date: 2026-03-17
Summary
Migrate from github.com/otfabric/modbus to github.com/otfabric/go-modbus. The library now uses the shared transport and register API from go-modbus and delegates SunSpec marker detection and model-header enumeration to go-modbus/sunspec, while keeping this package as the high-level decoded SunSpec API.
Changes
Breaking
- Modbus dependency —
github.com/otfabric/modbusv0.2.2 replaced bygithub.com/otfabric/go-modbusv1.0.1. Import paths and type names change:- Import:
github.com/otfabric/go-modbus(andgithub.com/otfabric/go-modbus/sunspecwhere low-level discovery types are needed) *modbus.ModbusClient→*modbus.Clientmodbus.ClientConfiguration→modbus.Configmodbus.NewClient(...)→modbus.New(...)modbus.ServerConfiguration→modbus.ServerConfig(test utilities)
- Import:
- Public API — SunSpec result types are now owned by this package instead of re-exported from modbus:
Detect()now returns*sunspec.DetectionResult(was*modbus.SunSpecDetectionResult)ModelInstance.Headeris nowsunspec.ModelHeader(wasmodbus.SunSpecModelHeader)DiscoveryResult.Rawis now*gmsunspec.DiscoveryResult(was*modbus.SunSpecDiscoveryResult). New typesDetectionResult,ProbeAttempt, andModelHeaderare defined in this package.
Added
- CLI —
newClient()now setsTimeout,DialTimeout(5s), andLogger(NopLogger) explicitly for clearer transport behaviour.
Unchanged
- Discovery flow, registry enrichment, decode API, and CLI commands (
detect,models,read,read-model,read-point,poll, etc.) are unchanged. Behaviour and output shape remain compatible.
Dependencies
- Go 1.21+
- otfabric/go-modbus v1.0.1
- spf13/cobra v1.10.2 (CLI only)
v0.1.3
Release v0.1.3
Date: 2026-03-12
Summary
Export SunSpec protocol constants so downstream consumers (e.g. strategies parsing raw ScanResult.Data) can reference the canonical marker, end-model sentinel, and default base address values directly instead of maintaining mirrored copies.
Changes
Changed
- Dependency upgrade —
github.com/otfabric/modbusv0.2.1 → v0.2.2 - SunSpec constants — The following values are now re-exported from the modbus library:
SunSpecMarkerReg0(0x5375) /SunSpecMarkerReg1(0x6E53) — "SunS" marker registersSunSpecEndModelID(0xFFFF) /SunSpecEndModelLength(0) — end-of-chain sentinelSunSpecDefaultBaseAddresses([]uint16{0, 40000, 50000, 1, 39999, 40001, 49999, 50001}) — default probe addresses
- Test utilities —
testutil.NewSunSpecFixturenow uses the modbus constants instead of hardcoded magic numbers
Unchanged
- All SunSpec discovery methods, types, and behaviour unchanged. This is a purely additive API change.
Dependencies
- Go 1.21+
- otfabric/modbus v0.2.2
- spf13/cobra v1.10.2 (CLI only)