Skip to content

v0.3.0

Choose a tag to compare

@github-actions github-actions released this 28 Oct 04:14
425bbc1

Date: 2026-10-28

Summary

Two more interop stacks and GOOSE. mms-interop-dscsystems runs
dscsystems/go-iec61850 (pure Go, GPL-3.0) and mms-interop-iec61850-rust
runs csp0924/iec61850-rust (Rust, MIT OR Apache-2.0) behind the same
commands and JSON Lines as the libiec61850 adapter. libiec61850,
dscsystems and iec61850-rust all gain a GOOSE publisher and subscriber
with one shared contract, fixture and Docker L2 recipe.

Changes

Added

  • Image ghcr.io/otfabric/mms-interop-dscsystems (adapters/dscsystems/, GPL-3.0 with LICENSE and NOTICE in that directory), pinned to dscsystems/go-iec61850 commit 6bf3f37 (v0.6.5-1-g6bf3f37): dscsystems-mms-server, -mms-client, -ied-server, -ied-client, -ied-controller, -ied-reporter, -goose-publisher, -goose-subscriber. Flags, fixture defaults, ready events and output lines mirror the libiec61850 commands, so a harness switches stack by image and command prefix.
  • Image ghcr.io/otfabric/mms-interop-iec61850-rust (adapters/iec61850-rust/, with upstream's LICENSE-MIT, LICENSE-APACHE and a NOTICE), pinned to csp0924/iec61850-rust commit d4e8952 (v0.2.0) and built with Rust 1.95.0: the same eight commands under the iec61850-rust- prefix. Upstream has no generic MMS server, so the adapter runs the association with upstream's ISO layers and encodes the remaining services itself. No command is unsupported; one that were would answer {"event":"error","code":"unsupported",...} and exit 4.
  • libiec61850-goose-publisher and libiec61850-goose-subscriber (raw GoosePublisher / GooseReceiver API).
  • GOOSE contract (docs/goose.md): the publisher announces --values as stNum 1, retransmits MinTime → doubling → MaxTime, takes {"cmd":"set"} / {"cmd":"stop"} on stdin and emits published per frame; the subscriber emits one goose event per frame (gocbRef, datSet, goID, appID, dst, src, stNum, sqNum, timeAllowedToLive, confRev, test, simulation, ndsCom, numDatSetEntries, t, values) and supervision timeout/ok per gocbRef. test is goosePdu field [7], simulation the Edition 2 S bit of Reserved1.
  • Fixture revision goose-v1 (fixtures/goose/): interop-goose.cid (interop.icd plus datasets dsGooseAll — boolean, integer, unsigned, float32, quality, utc-time, Dbpos, nested MV structure — and dsGooseBool, GSEControl gcbAll/gcbBool and their GSE addresses) and goose.json (on-wire references, members, initial and update values). scripts/validate-fixtures.py checks both against each other and against interop.icd; the fixture workflow runs genmodel on the CID.
  • scripts/goose-crosscheck.sh: publisher → subscriber check between two images on a Docker bridge, optionally from the host side of the bridge. CI runs it between every pair of libiec61850, dscsystems and iec61850-rust (all nine directions), with and without the flags, and from the host side.
  • docker compose --profile goose (bridge goose0), make build-dscsystems, make build-iec61850-rust, make goose-crosscheck.
  • fixtures/capabilities.json: the new commands, gooseFixtureRevision, the dscsystems upstream, and seven dscsystems known limitations (alternate access ranges in the server; alternate access, NVL writes, association-scope NVLs and FileOpen lastModified in the client; Enum type description and ST writes in the IED server), the iec61850-rust upstream, and five iec61850-rust known limitations (RptEna without Resv and ST writes in the IED server, abort in the MMS client, ObtainFile role reversal and domain/VMD NVL deletion in the MMS server).

Changed

  • CI runs on pull requests, builds and smoke-tests all four images (including MMS and IED pairs of dscsystems and iec61850-rust against libiec61850) and vets the Go adapter; the release workflow builds and publishes the dscsystems and iec61850-rust images for linux/amd64 and linux/arm64 and records their digests and upstream commits in manifest.json.
  • The libiec61850 image ships fixtures/goose/; its GOOSE binaries carry cap_net_raw+ep, so they run as the non-root adapter user in a container with NET_RAW.

Notes

  • The dscsystems MMS server sends both InformationReport forms of the fixture, listOfVariable first; the libiec61850 server sends only the named-list form. It seeks FileOpen initialPosition, which libiec61850 does not.
  • The dscsystems IED server returns directory names in model order, libiec61850 sorted.
  • The iec61850-rust MMS server keeps its file store in memory (--filestore is accepted and ignored), lists directories sorted by path, seeks FileOpen initialPosition and, like dscsystems, sends both InformationReport forms.
  • A Go test on macOS cannot reach the GOOSE adapters natively: run it in a container on the bridge network (docs/goose.md).

Adapter images

Image Digest
ghcr.io/otfabric/mms-interop-libiec61850:v0.3.0 sha256:18e7e5c249f74e708a0699bd64732cd238ad9579574431a16b27b9c6000232a0
ghcr.io/otfabric/mms-interop-iec61850bean:v0.3.0 sha256:8d76b3cc065c2b18cc031bb26b2b879a7b433e164f9664ce9a3363241db65514
ghcr.io/otfabric/mms-interop-dscsystems:v0.3.0 (GPL-3.0) sha256:f0b233737c1bd6e9cc6cfe7338bb287ed0e5b4a6b589b7496ae2409501dc6deb
ghcr.io/otfabric/mms-interop-iec61850-rust:v0.3.0 sha256:ebd09921ef9b22ed9a318256eb2fac74268dde7f18a17f9e8300aba46c624110

Pinning in consumer repositories

LIBIEC61850_IMAGE=ghcr.io/otfabric/mms-interop-libiec61850@sha256:18e7e5c249f74e708a0699bd64732cd238ad9579574431a16b27b9c6000232a0
IEC61850BEAN_IMAGE=ghcr.io/otfabric/mms-interop-iec61850bean@sha256:8d76b3cc065c2b18cc031bb26b2b879a7b433e164f9664ce9a3363241db65514
DSCSYSTEMS_IMAGE=ghcr.io/otfabric/mms-interop-dscsystems@sha256:f0b233737c1bd6e9cc6cfe7338bb287ed0e5b4a6b589b7496ae2409501dc6deb
IEC61850RUST_IMAGE=ghcr.io/otfabric/mms-interop-iec61850-rust@sha256:ebd09921ef9b22ed9a318256eb2fac74268dde7f18a17f9e8300aba46c624110

See manifest.json for full provenance (libiec61850 commit SHA, iec61850bean version, dscsystems/go-iec61850 and iec61850-rust commit SHAs, fixture revisions).