Skip to content

Releases: otfabric/go-modbus

v1.1.3

Choose a tag to compare

@github-actions github-actions released this 30 Jul 20:29

Date: 2026-07-30
Previous release: v1.1.2

Summary

Patch release: bump go-serial to v0.1.6. No API, behaviour, or wire-semantics changes.

Changes

Dependencies

  • go-serial — v0.1.5 → v0.1.6 (docs/tooling; no serial API change).

Unchanged

  • Library API, codec, sunspec, server/client behaviour, and supported function codes are identical to v1.1.2.

v1.1.2

Choose a tag to compare

@github-actions github-actions released this 29 Jul 23:03

Date: 2026-07-30
Previous release: v1.1.1

Summary

Patch release: align the README Go version with go.mod, document write retry at-least-once semantics, add thin ERRORS.md / OBSERVABILITY.md guides, trim README overlap with API.md, and harden the Makefile (govulncheck, isolate from a parent go.work). No API, behaviour, or wire-semantics changes.

Changes

Documentation

  • ERRORS.md — Short error taxonomy: library/transport failures vs wire Modbus exceptions; quick-reference table; pointers into API.md § 4 and retry notes.
  • OBSERVABILITY.md — Silent-by-default logging, debug frame-payload caveats, ClientMetrics vs optional AttemptMetrics; pointers into API.md § 5–6.
  • README — Install floor corrected from Go 1.21 to Go 1.23 (matches badge / go.mod); links to the new guides; Logging / Error / Metrics sections trimmed.
  • README — New Project structure section (top-level folders and key docs).
  • README — Retry, Pool sections trimmed to short summaries that point at API.md.
  • API.md § 7 — New Write operations and at-least-once delivery note: retries apply to reads and writes alike; the classifier does not inspect function code; a retry after bytes may have been sent can deliver a write at least once. Prefer NoRetry / nil policy (or application-level idempotency) for non-idempotent writes.
  • Godoc — Config.RetryPolicy and public/internal RetryPolicy document the same write-safety caveat.

Build / tooling

  • Makefile vuln — govulncheck ./..., included in make check.
  • Makefile — exports GOWORK=off so checks ignore a parent otfabric/go.work that does not list this module.

Unchanged

  • Retry defaults remain nil / NoRetry(). No change to retry classification or when writes are retried — behaviour is documented only.
  • Library API, codec, sunspec, server/client behaviour, and supported function codes are identical to v1.1.1.

v1.1.1

Choose a tag to compare

@github-actions github-actions released this 08 Jul 02:56

Date: 2026-07-08
Previous release: v1.1.0

Summary

Patch release preparing the repository for public open-source release under the MIT License: standardized root license and SPDX headers, normalized README badges for a public GitHub repo, and a dependency bump of github.com/otfabric/go-serial to the latest public v0.1.5. No API, behaviour, or wire-semantics changes.

Changes

License & open-source hygiene

  • LICENSE — Replaced LICENSE.txt with a root-level LICENSE file using standard MIT text (Copyright (c) 2026 OT Fabric).
  • SPDX headers — Added // SPDX-License-Identifier: MIT to all first-party .go source files (141 files).
  • README — License section normalized to point at LICENSE.

README badges

  • Standardized badge block — Reordered and updated badges for public release: Go version (1.23+, from go.mod), pkg.go.dev, License, CI, Codecov, Release.
  • Go Reference — Added pkg.go.dev badge linking to github.com/otfabric/go-modbus.
  • Codecov — Removed embedded ?token=... from the badge URL; uses the public codecov.io/gh/otfabric/go-modbus endpoint (works after repo is public and first upload completes).
  • Go Report Card — Removed; the service is no longer maintained.
  • Release badge — Normalized to label=release.

Dependencies

  • go-serial — Bumped from v0.1.3 to v0.1.5 (github.com/otfabric/go-serial).

Unchanged

  • No breaking changes. Library API, codec, sunspec, server/client behaviour, and supported function codes are identical to v1.1.0.

v1.1.0

Choose a tag to compare

@github-actions github-actions released this 05 Jul 05:10

Date: 2026-07-05
Previous release: v1.0.4

Summary

Server-side Read Device Identification (FC43) and a full back-to-back conformance suite. The server now supports FC43 / MEI type 0x0E (Read Device Identification) via a new optional DeviceIdentificationHandler interface, with the server owning all MEI framing, category filtering, ordering, and MoreFollows/NextObjectID pagination. This completes server-side coverage of the target function-code set (FC1–6, 15, 16, 22, 23, 43) used to exercise gateways with modbusctl. Alongside the feature, a comprehensive client-vs-server back-to-back test suite is added (deterministic conformance, property-based differential testing, and native fuzzing) and normal unit-test coverage is expanded, raising core package coverage from ~79% to ~88%. Additive change only — no existing API, behaviour, or wire semantics change.

Changes

Server — FC43 Read Device Identification

  • New optional interface — DeviceIdentificationHandler with HandleDeviceIdentification(ctx, *DeviceIdentificationRequest) (*DeviceIdentificationResponse, error). If the RequestHandler also implements it, FC43 is dispatched to it; otherwise the server returns Illegal Function.
  • Server-owned framing — The handler returns the complete object set plus a conformity level; the server performs MEI validation (only 0x0E accepted), Read-Device-ID-code validation (basic/regular/extended/individual), category filtering, object-ID ordering, single-response PDU sizing, and stream pagination via MoreFollows / NextObjectID. Individual access to an unknown object returns Illegal Data Address.
  • Conformity derivation — When the handler leaves ConformityLevel unset (0), the server derives a sensible level from the object set and advertises individual access.
  • Dispatch — server_transport.go routes FCEncapsulatedInterface to the new handleReadDeviceIdentification.

Tests — back-to-back conformance suite

  • Harness (backtoback_test.go) — Reference in-memory device implementing every server handler interface, startPair helper for connected client/server pairs over TCP and TCP+TLS on ephemeral ports, a forEachTransport matrix runner, and MBAP invariant assertion helpers.
  • Deterministic conformance (conformance_test.go) — Per-FC round-trip / echo / packing / boundary / exception tables across the TCP and TLS matrix, including FC22/23/43 semantics.
  • Adversarial server branches (conformance_adversarial_test.go) — Raw-TCP malformed frames for FC05/06/15/16/22/23/43 asserting correct exception codes or link close on protocol errors.
  • Property-based (property_test.go) — Seeded randomized differential testing against a shadow model for read/write/mask/read-write-multiple, plus randomized FC43 pagination reassembly.
  • Fuzzing (fuzz_test.go) — FuzzServerRequest (arbitrary PDUs to a running server) and FuzzClientResponseParse (arbitrary bytes to the client parser) with seed corpora; seeds run as regular tests under go test.

Tests — expanded unit coverage

  • Programmable mock server (mockserver_test.go) for scripting adversarial client-facing responses.
  • Client protocol/response validation (client_protocol_test.go) — wrong FC, byte-count and echo mismatches, and error branches for FIFO, read/write-multiple, file records, and register-byte writes.
  • Diagnostics & probing (client_diag_test.go) — FC08 wrappers (happy + bad-length), Diagnostics, ReadExceptionStatus, comm-event counter/log, ReportServerID, and ProbeFunction/SupportsFunction outcomes.
  • Serial wrapper (serial_test.go) — configuration and not-open error paths that need no hardware.
  • Construction/dial errors (construction_errors_test.go) — client and server config validation plus TCP/RTU/TLS dial and listen failures.
  • Coverage — Core package statement coverage increased from ~79.2% to ~88.0%; go test -race, go vet ./..., and golangci-lint are clean.

Build / CI

  • Makefile — New fuzz target running both fuzz targets for a configurable FUZZTIME (default 30s).
  • ci.yml — Added an opt-in fuzz job (make fuzz FUZZTIME=5m) gated behind a workflow_dispatch boolean input run_fuzz (default false), so it runs only on a manual trigger with the toggle enabled and keeps push/PR CI fast; seed corpora still run as unit tests in the main job.

Documentation

  • README.md — Server capabilities table and notes updated for FC43 and its optional handler.
  • API.md — Documented DeviceIdentificationHandler and its request/response types, and the server's auto-framing/pagination behaviour.

Examples

  • examples/tcp_server — exampleHandler now implements DeviceIdentificationHandler, serving static identification objects.

Unchanged

  • No breaking changes. FC43 support and all new tests are additive; existing library API, codec, sunspec, wire behaviour, and previously supported function codes are identical to v1.0.4.

v1.0.4

Choose a tag to compare

@github-actions github-actions released this 23 Mar 13:45

Date: 2026-03-23
Previous release: v1.0.3

Summary

Binary name fix. The binary name is now correctly set to modbus-cli iso sclgen.

v1.0.3

Choose a tag to compare

@github-actions github-actions released this 23 Mar 13:36

Date: 2026-03-23
Previous release: v1.0.2

Summary

CLI overhaul. The modbus-cli command line tool is migrated from flag to cobra, gaining shell completion (bash, zsh, fish, powershell), a version subcommand with full build metadata, and structured help. Build-time version injection switches from an embedded version.txt to ldflags (version, tag, commit, buildDate). The Go module minimum version is bumped to 1.23. CI and release workflows are updated to the v2 shared workflows with multi-version testing and a separate binary release job for modbus-cli.

Changes

CLI — cobra migration

  • Framework — Replaced flag with github.com/spf13/cobra. All existing flags are preserved as persistent cobra flags with identical names and defaults.
  • Shell completion — Built-in completion subcommand generates completion scripts for bash, zsh, fish, and powershell. Flag values (--parity, --endianness, --word-order) and operation prefixes (rc:, rh:, scan:, etc.) have custom completion functions.
  • Help — Cobra-generated help replaces the monolithic displayHelp(). The Long description includes the full operations reference; examples are shown via the Example field.
  • Backward compatible — Operations are still passed as positional arguments using the existing colon-separated DSL. No command syntax changes.

CLI — version subcommand

  • modbus-cli version — Prints version, tag, commit, and build date. All four fields are injected via ldflags at build time; without ldflags (e.g. go run) sensible defaults are shown (dev, none, unknown).
  • Removed — cmd/modbus-cli/version.txt deleted. The --version / -v flag is removed; use the version subcommand instead.
  • ldflags contract — -s -w -X main.version=${VERSION} -X main.tag=${TAG} -X main.commit=${COMMIT} -X main.buildDate=${BUILD_DATE}.

CI/CD

  • ci.yml — Updated to shared workflow otfabric/.github/.github/workflows/go-ci.yml@v2. Explicit Go version matrix: 1.23, 1.24, 1.25, 1.26.
  • release.yml — Split into two jobs: release-package (library, go-package-release.yml@v2) and release-modbus-cli-binary (CLI binary, go-binary-release.yml@v2 with ldflags injection). Major tag update disabled.

Build

  • Makefile — build-cmd derives VERSION, TAG, COMMIT, and BUILD_DATE from git and injects them via ldflags. All four variables are overridable (?=). Fixed pre-existing BIN_DIR trailing-space bug caused by inline comment.

Dependencies

  • Go — Minimum version bumped from 1.21 to 1.23.
  • go-serial — Bumped from v0.1.2 to v0.1.3.
  • cobra — Added github.com/spf13/cobra v1.10.2 (and transitive deps spf13/pflag, mousetrap).

Documentation

  • README.md — CLI help output updated: version subcommand description changed to "Print build version information"; --version flag removed from flags listing.

Unchanged

  • No changes to the Modbus library API, codec, sunspec, or server. All types, functions, and constants are identical to v1.0.2.

go-modbus v1.0.2

Choose a tag to compare

@github-actions github-actions released this 21 Mar 07:08

Date: 2026-03-21
Previous release: v1.0.1

Summary

Patch release: unit test coverage expansion and CI/CD simplification. Four new test files add ~700 lines of coverage across the codec client API, ADU wire encoding, and protocol error paths. CI and release workflows are replaced with org-level reusable workflows from otfabric/.github. The go-serial dependency is bumped to v0.1.2. No API or behavioural changes.

Changes

Tests

  • codec/client_test.go — New. Covers ReadFromClient, WriteToClient, ReadRuntimeFromClient, WriteRuntimeToClient, DecodeWithDescriptor, EncodeWithDescriptor, and their error paths (nil codec, read/write failures, zero descriptors, encode errors).
  • coverage_extra_test.go — New. Additional edge-case coverage across the codebase.
  • internal/adu/wire_test.go — New. ADU wire encoding round-trip and boundary tests.
  • internal/protocol/errors_test.go — New. Protocol error type and sentinel tests.

CI/CD

  • ci.yml — Replaced inline multi-version matrix workflow with the shared reusable workflow otfabric/.github/.github/workflows/go-ci.yml@v1.
  • release.yml — Replaced inline release workflow with the shared reusable workflow otfabric/.github/.github/workflows/go-release.yml@v1. Supports update-major-tag and release-name-prefix.

Dependencies

  • go-serial — Bumped from v0.1.1 to v0.1.2.

Other

  • README.md — Codecov badge URL updated to use token-authenticated endpoint.
  • .gitignore — Added *.out pattern for coverage output files.

Unchanged

  • No API, behaviour, or functional changes. All types, functions, and constants are identical to v1.0.1.

v1.0.1

Choose a tag to compare

@github-actions github-actions released this 16 Mar 22:46

Release v1.0.1

Date: 2026-03-16
Previous release: v1.0.0

Summary

Module rename: The Go module path has been changed from github.com/otfabric/modbus to github.com/otfabric/go-modbus. This aligns the repository name with the Go convention of prefixing Go-specific libraries with go-. No functional changes.

Changes

Changed

  • Module path — go.mod module declaration changed from github.com/otfabric/modbus to github.com/otfabric/go-modbus. All internal import paths updated accordingly.
  • README.md — Title, badge URLs, install command, TOC anchor, and all import examples updated to go-modbus.
  • API.md / ARCHITECTURE.md / CODECS.md — All import path references updated.
  • CI — Release workflow name updated to otfabric/go-modbus.

Migration

Update your go.mod and all import paths:

github.com/otfabric/modbus       → github.com/otfabric/go-modbus
github.com/otfabric/modbus/codec  → github.com/otfabric/go-modbus/codec
github.com/otfabric/modbus/sunspec → github.com/otfabric/go-modbus/sunspec

The Go package name remains modbus (e.g. modbus.New(...), modbus.Config{...}). Only the module and import paths change.

Unchanged

  • No API, behaviour, or functional changes. All types, functions, and constants are identical to v1.0.0.

v1.0.0

Choose a tag to compare

@github-actions github-actions released this 16 Mar 22:03

Release v1.0.0

Date: 2026-03-16
Previous release: v0.4.2

Summary

Major release. The library reaches API stability with a comprehensive architectural refactor, full Modbus protocol compliance, and a clean package structure. The monolithic client and server have been split into focused files; internal subsystems (adu, transport, session, protocol, logging) are properly encapsulated in internal/ packages; the codec and sunspec subpackages are standalone importable modules. All public type names have been streamlined (Config, Client, Server, ServerConfig) and legacy helpers removed. Protocol compliance now covers all standard Modbus function codes including FC07, FC0B, FC0C client and server support, tightened FC43/14 validation, and comprehensive FC08 diagnostic wrappers.

Breaking changes

Renamed types

Old name New name Notes
ClientConfiguration Config Flat config struct
ModbusClient Client
NewClient(*ClientConfiguration) New(Config) Now takes value, not pointer
ServerConfiguration ServerConfig
ModbusServer Server
NewServer(*ServerConfiguration, ...) NewServer(*ServerConfig, ...)
ReportServerIdResponse ReportServerIDResponse Consistent Go naming

Moved to subpackages

Old location (root) New location Import path
ReadWithCodec, WriteWithCodec, all codec types codec/ github.com/otfabric/modbus/codec
DetectSunSpec, ReadSunSpecModelHeaders, DiscoverSunSpec sunspec/ github.com/otfabric/modbus/sunspec

Root-package convenience methods on Client still exist for SunSpec, delegating to the subpackage.

Removed

  • SetEncoding — Removed. Byte and word order are defined per-codec via RegisterLayout.
  • ReadBytes / WriteBytes — Use ReadRegisterBytes / WriteRegisterBytes for raw byte transport; use codecs for typed interpretation.
  • All legacy typed read/write helpers — ReadUint16(s), ReadUint32(s), ReadFloat32(s), WriteInt16(s), WriteAscii, WriteBCD, etc. Use ReadRegisters / WriteRegisters for raw access; use codec.ReadFromClient / codec.WriteToClient for typed access.
  • client_runtime.go / client_codec.go — Runtime and codec client helpers moved into codec/client.go.

Changed

  • Logger default — Config.Logger defaults to a no-op logger (logging disabled) instead of slog.Default(). Use NewStdLogger, NewSlogLogger, or NewFieldLogger to enable logging.
  • Config.DialTimeout — New field. Zero uses sensible defaults (5s TCP/UDP, 15s TLS). Does not apply to serial RTU.
  • NewConfig() — New constructor that accepts TransportConfig, ExecutionConfig, and ObservabilityConfig for structured configuration as an alternative to the flat Config literal.
  • Error types — ExceptionError, ProtocolError, ParameterError, and ConfigurationError are now type aliases re-exported from internal/protocol. Behaviour is identical; errors.Is and errors.As work as before.

Added

Modbus protocol compliance (FC07, FC0B, FC0C)

  • ReadExceptionStatus (FC07) — Client method returning the 8-bit exception status coil output. Server-side ExceptionStatusHandler optional interface.
  • GetCommEventCounter (FC0B) — Client method returning *CommEventCounterResponse (Status + EventCount). Server-side CommEventCounterHandler optional interface.
  • GetCommEventLog (FC0C) — Client method returning *CommEventLogResponse (Status + EventCount + MessageCount + Events). Server-side CommEventLogHandler optional interface.
  • RTU response length — ExpectedRTUResponseLength now handles FC0B (fixed 4-byte) and FC0C (byte-count-prefixed), with exception entries for both.

FC08 Diagnostics — typed convenience wrappers

  • DiagnosticForceListenOnlyMode — Sub-function 0x0004; no response expected (serial-line semantics).
  • DiagnosticClearCounters — Sub-function 0x000A; validates 2-byte echo.
  • DiagnosticBusCommunicationErrorCount, DiagnosticBusExceptionErrorCount, DiagnosticServerMessageCount, DiagnosticServerNoResponseCount, DiagnosticServerNAKCount, DiagnosticServerBusyCount, DiagnosticBusCharacterOverrunCount — Each returns a uint16 counter with 2-byte payload validation.
  • DiagnosticClearOverrunCounterAndFlag — Sub-function 0x0014; validates 2-byte echo.

FC43/14 (Read Device Identification) — tightened validation

  • Conformity level validated against spec-allowed values (0x01–0x03, 0x81–0x83).
  • MoreFollows + NextObjectID consistency check (NextObjectID must be 0x00 when MoreFollows is 0x00).
  • Individual access enforces MoreFollows = 0x00 and exactly one object.
  • SupportsStreamAccess() and SupportsIndividualAccess() helpers on DeviceIdentification.
  • MEI type 13 (CANopen General Reference) explicitly documented as unsupported.

Server optional handlers (FC07, FC0B, FC0C)

  • ExceptionStatusHandler, CommEventCounterHandler, CommEventLogHandler — Follow the existing optional-handler pattern (MaskWriteHandler, ReadWriteHandler). If not implemented, server returns Illegal Function.

Architecture refactor

  • Client split — client.go (config, lifecycle), client_exec.go (request execution), client_bits.go (coil/discrete ops), client_registers.go (register ops), client_device_id.go (FC43), client_diagnostics.go (FC07/FC08/FC0B/FC0C), client_file.go (FC20/FC21), client_probe.go (device detection).
  • Server split — server.go (config, interfaces), server_transport.go (dispatch), server_bits.go (coil/DI handling), server_registers.go (register handling).
  • Internal packages — internal/adu (MBAP, RTU CRC, wire encoding), internal/transport (TCP, RTU), internal/session (engine, pool, retry), internal/protocol (constants, FC, errors, detection), internal/logging (prefixed adapter).
  • Codec subpackage — codec/ is a standalone public package with codec.ReadFromClient / codec.WriteToClient, codec.RegisterLayout, all codec constructors, runtime codecs, and discovery.
  • SunSpec subpackage — sunspec/ is a standalone public package with sunspec.Detect, sunspec.ReadModelHeaders, sunspec.Discover.
  • CLI restructured — cmd/modbus-cli/ split into main.go, parser.go, execute.go, scan.go, help.go.
  • ARCHITECTURE.md — New document describing the package layout, dependency graph, ownership rules, locking model, and request/response flow.

Transport-neutral policy

All function codes are supported on every transport (TCP, TLS, UDP, RTU, RTU-over-TCP/UDP). The spec labels FC07, FC08, FC0B, FC0C as "Serial Line only," but gateways make them reachable over any lower layer. The library does not restrict any FC by transport type.

Protocol validation

  • protocol_validate.go — Centralised request validation helpers used by client methods.
  • protocol_limits_test.go — Explicit tests for global Modbus PDU/ADU size limits (MBAP max 254, RTU max 256, PDU max 253, TCP ADU max 260).

Tests

  • client_diagnostics_test.go — FC07, FC0B, FC0C client tests (happy path, exceptions, malformed payloads).
  • server_serial_fc_test.go — Server dispatch tests for FC07/FC0B/FC0C with and without optional handlers.
  • fc43_test.go — Expanded with conformity level validation, MoreFollows/NextObjectID, individual access constraints, bad object ID behaviour (stream restart from 0, individual exception 02), SupportsStreamAccess/SupportsIndividualAccess helpers.
  • protocol_limits_test.go — MBAP bounds, RTU frame max, PDU max, TCP ADU max, protocol ID validation, quantity constants.
  • coverage_extra_test.go — Additional coverage for edge cases across the codebase.

Documentation

  • README.md — Updated FC tables (client and server), transport-neutral policy note, MEI 43/13 note, API tiers table, five-tier architecture description.
  • API.md — New sections for FC07/FC0B/FC0C, FC08 convenience wrappers, conformity level helpers, FC43 validation rules, MEI 43/13, server optional handler interfaces (FC07/FC0B/FC0C). Updated table of contents.
  • ARCHITECTURE.md — New file documenting package layout, dependency graph, ownership rules, client locking model, and codec/SunSpec architecture.
  • CODECS.md — Minor alignment with codec subpackage move.

v0.4.2

Choose a tag to compare

@github-actions github-actions released this 16 Mar 02:26

Release v0.4.2

Date: 2026-03-17
Previous release: v0.4.1

Summary

Patch release: time codec family for typed time.Time read/write. Three formats are supported — seconds since 2000 (s2000), calendar YMDhms (6 registers), and IEC 60870-5 CP56Time2a (4 registers) — with UTC, local, and default-UTC variants. All time codecs use CodecFamilyTime / CodecValueTime, strict calendar validation, and consistent CodecValueError on invalid values (including CP56 decode failures). Descriptor registration and runtime registry support discovery and CLI use.

Changes

Added

  • Time codecs — NewDateTime2S2000Codec() (2 regs, uint32 seconds since 2000-01-01 UTC), NewDateTime3S2000Codec() (3 regs, 48-bit seconds), NewDateTimeYMDhmsUTCCodec(), NewDateTimeYMDhmsLocalCodec(), NewDateTimeYMDhmsCodec() (6 regs: year, month, day, hour, minute, second), NewDateTimeIEC870UTCCodec(), NewDateTimeIEC870LocalCodec(), NewDateTimeIEC870Codec() (4 regs, CP56Time2a, 7-byte payload + pad). Stable IDs: datetime2_s2000, datetime3_s2000, datetime_ymdhms_utc, datetime_ymdhms_local, datetime_ymdhms, datetime_iec870_utc, datetime_iec870_local, datetime_iec870.
  • CodecFamilyTime / CodecValueTime — New family and value kind for time codecs; used by descriptors and FindRuntimeCodecs / discovery.
  • Layout metadata for s2000 — datetime2_s2000 and datetime3_s2000 descriptors expose layout 4321 and 654321 for tooling; YMDhms and IEC870 are structural formats and do not expose layout metadata.
  • Strict calendar validation — Helper strictDateTime rejects invalid dates (e.g. Feb 31, April 31, non-leap Feb 29); YMDhms and CP56 decode paths use it. Coarse range checks (month 1–12, day 1–31, etc.) return targeted errors; normalisation failures yield a single “invalid calendar date/time” error.
  • CP56 behaviour — Decode ignores status/flag bits and uses only timestamp fields; encode writes a clean timestamp (flag bits unset). Eighth byte of the 4-register frame is padding and ignored on decode. Millisecond precision (milliseconds within minute 0–59999) is preserved. Year 2000–2127; decode maps year byte 0→2000, 127→2127.
  • Nil-location guards — strictDateTime, decodeCP56Time2a, encodeCP56Time2a, and the YMDhms/IEC870 codec EncodeRegisters methods reject nil *time.Location with a clear error instead of panicking.
  • CP56 decode errors as CodecValueError — dateTimeIEC870Codec.DecodeRegisters wraps CP56 decode failures in *CodecValueError so errors.Is(err, ErrCodecValue) works for value-validation tests and callers.

Documentation

  • CODECS.md — §5 Time codecs: s2000, YMDhms, CP56Time2a; UTC/default/local semantics; DOW written on encode, ignored on decode.
  • README.md — Supported Go types table includes time.Time via time codecs; codec list mentions time codecs.
  • API.md — Time codec constructors and stable IDs already documented; aligned with CODECS.md.

Unchanged

  • No breaking changes. Serial transport, TCP/TLS, codec API, and all other behaviour unchanged.