Documentation
¶
Overview ¶
Package iec61850 provides a pure-Go IEC 61850 MMS client library built on top of github.com/otfabric/go-mms.
This package exposes IEC 61850 concepts — logical devices, logical nodes, data objects, data attributes, functional constraints, object references, report control blocks, datasets, quality, timestamps — as first-class Go types. Users work with IEC 61850 semantics, not raw MMS domains, item IDs, or alternate access selectors.
Quick start ¶
client, err := iec61850.Dial(ctx, "10.0.0.1:102", iec61850.DialOptions{})
if err != nil {
log.Fatal(err)
}
defer client.Close(ctx)
// Browse the server model.
devices, _ := client.ListLogicalDevices(ctx)
for _, ld := range devices {
nodes, _ := client.ListLogicalNodes(ctx, ld.Name)
fmt.Println(ld.Name, nodes)
}
Layering ¶
This package sits above the protocol stack:
- go-tpkt / go-cotp: transport
- go-mms: generic MMS protocol
- go-iec61850 (this package): IEC 61850 semantics
IEC 61850 semantics (references, functional constraints, typed values, reports, datasets, SCL) live here. The MMS wire protocol lives in go-mms. This separation is intentional and must be maintained.
Object references ¶
IEC 61850 object references follow the format:
LD/LN.DO.DA[FC]
Use ParseRef to parse references and Ref.String to format them. The Ref type provides helpers for parent/child navigation and MMS domain/item-ID translation.
Functional constraints ¶
Functional constraints (FCs) classify data attributes by purpose: ST (status), MX (measured), SP (setpoint), CF (configuration), etc. Use FunctionalConstraint.IsValid or ParseFC to validate FC strings. Note that ParseRef accepts unknown FC values by default; use FunctionalConstraint.IsValid for semantic validation after parsing.
API groups ¶
The package is organised into functional groups:
- Browse / model discovery: Client.ListLogicalDevices, Client.ListLogicalNodes, Client.ListDataObjects, Client.ListChildren, Client.Tree, Client.TreeWithOptions, Client.FindPaths, Client.GetVariableType
- Read / write: Client.Read, Client.ReadRaw, Client.ReadComponent, Client.Write, Client.ReadMultiple, Client.WriteMultiple
- Datasets: Client.ListDataSets, Client.GetDataSet, Client.ReadDataSet, Client.CreateDataSet, Client.DeleteDataSet
- Reports: Client.ListReports, Client.SubscribeReport, Client.GetReportControlBlock, Client.SetReportControlBlock, Client.TriggerGI, Client.ReserveURCB, Client.ReleaseURCB
- Controls: Client.Operate, Client.Select, Client.SelectWithValue, Client.Cancel, Client.ReadCtlModel, Client.ReadLastApplError
- Setting groups: Client.GetSettingGroupInfo, Client.SelectActiveSG, Client.SelectEditSG, Client.ConfirmEditSG, Client.GetEditSGValue, Client.SetEditSGValue, Client.GetActiveSGValue
- Journals: Client.ListJournals, Client.ReadJournal, Client.ReadJournalAfter, Client.ReadJournalAll, Client.ReadJournalAfterAll
- Files: Client.ListFiles, Client.ReadFile, Client.DownloadFile, Client.DeleteFile, Client.RenameFile, Client.ObtainFile, Client.GetFileAttributes
- SCL: scl.Parse, scl.ParseFile, scl.Generate, scl.Validate, scl.Flatten, scl.WriteCSV, scl.PrintTree, scl.ExportDataSets, scl.ExportReports
- Server runtime reports: Server.EnableReports, Server.SetValue, Server.ReportEngine, ReportEngine.HandleRCBWrite, ReportEngine.NotifyValueChanged, ReportEngine.Stop
- Server setting groups: Server.EnableSettingGroups, Server.SettingGroupEngine, Server.ChangeActiveSettingGroup, SettingGroupEngine.HandleSGCBWrite, SettingGroupEngine.GetActiveSettingGroup, SettingGroupEngine.GetEditSettingGroup
- Server journals: Server.EnableJournals, Server.JournalEngine, JournalEngine.LogEvent, JournalEngine.LogValueWrite, JournalEngine.Provider, MemoryJournalProvider, NewMemoryJournalProvider
- Server services: ServerOptions (Identity, FileProvider, Authenticate, OnConnect, OnDisconnect), Server.Capabilities, Server.HandleIdentify, Server.HandleStatus, ServiceCapabilities
IEC references vs MMS names ¶
This package uses IEC 61850 object references (LD/LN.DO.DA[FC]) throughout its public API. The underlying MMS names use a different convention:
- MMS domain = logical device name
- MMS item ID = LN$FC$DO$DA (components joined by $)
- MMS dataset/NVL name = LLN0$dsName
Use Ref.ToMMS for conversion when needed.
Errors ¶
The package defines sentinel errors (ErrInvalidReference, ErrNotFound, ErrInvalidArgument, ErrProtocol, etc.) for use with errors.Is, and typed error structs (ReferenceError, DecodeError, DataAccessError, etc.) for use with errors.As. Lower-level go-mms errors are wrapped with fmt.Errorf and %w to preserve the error chain.
Server (experimental) ¶
The Server type provides an experimental server-side model built from SCL. It handles variable registration, datasets, report control block structures, runtime report delivery, control operations, setting groups, and journal services. Use Server.EnableReports to activate the runtime report engine, Server.EnableSettingGroups to activate setting group support, Server.EnableJournals to activate runtime journal generation, and Server.SetValue to inject process values that automatically trigger data-change reports and journal entries. MMS client writes to RCB and SGCB subfields are automatically dispatched to the corresponding runtime engines via a write interceptor.
ServerOptions provides first-class fields for common server configuration: ServerIdentity for MMS Identify, FileProvider for MMS file services, Authenticate for association security, and OnConnect/OnDisconnect for connection lifecycle hooks. The MMS Status service is always registered and returns operational status. Use Server.Capabilities to query which services are active at runtime. Call Server.Close for orderly shutdown of runtime engines.
Concurrency ¶
All server runtime engines (reports, controls, setting groups, journals) are safe for concurrent use. Lock ordering follows engine-level lock → per-element lock. The control runtime uses per-registration mutexes for SBO state; the report engine uses engine-level RWMutex → per-RCB mutex. These have been validated with concurrent stress tests and Go's race detector.
Cross-LN dataset references are not supported. See Server and NewServerModelFromSCL for details and known limitations.
Logging ¶
All logging uses log/slog. Inject a logger via DialOptions.Logger, ClientOptions.Logger, or ServerOptions.Logger. When nil, no logging is emitted. On Dial/NewServer, a nil nested MMS logger inherits the IEC logger; iso.WithLogger is independent. See OBSERVABILITY.md.
Index ¶
- Constants
- Variables
- func BoolCtlVal(v bool) *mms.Value
- func BspCtlVal(bits []byte, bitLen int) *mms.Value
- func DpCtlVal(on bool) *mms.Value
- func EncodeQuality(q Quality) *mms.Value
- func EncodeTimestamp(ts Timestamp) *mms.Value
- func EnumCtlVal(v int32) *mms.Value
- func FloatCtlVal(v float32) *mms.Value
- func HasDuplicateRefs(refs []Ref) bool
- func IntCtlVal(v int32) *mms.Value
- func NewServerModelFromSCL(s *scl.SCL, iedName, apName string) (*servermodel.Model, error)
- func StringCtlVal(v string) *mms.Value
- type AddCause
- type BrowseNode
- type CacheStrategy
- type CancelParams
- type CheckConditions
- type Client
- func (c *Client) Abort(ctx context.Context) error
- func (c *Client) Cancel(ctx context.Context, ref Ref, params CancelParams) error
- func (c *Client) Close(ctx context.Context) error
- func (c *Client) ConfirmEditSG(ctx context.Context, ld string) error
- func (c *Client) CreateDataSet(ctx context.Context, ld, dsName string, members []DataSetMember) error
- func (c *Client) DeleteDataSet(ctx context.Context, ld, dsName string) error
- func (c *Client) DeleteFile(ctx context.Context, fileName string) error
- func (c *Client) DownloadFile(ctx context.Context, fileName string, w io.Writer) (*FileEntry, error)
- func (c *Client) FindPaths(ctx context.Context, query FindQuery) ([]Ref, error)
- func (c *Client) GetActiveSGValue(ctx context.Context, ref Ref) (*Value, error)
- func (c *Client) GetDataSet(ctx context.Context, ld, dsName string) (*DataSet, error)
- func (c *Client) GetEditSGValue(ctx context.Context, ref Ref) (*Value, error)
- func (c *Client) GetFileAttributes(ctx context.Context, fileName string) (*FileEntry, error)
- func (c *Client) GetReportControlBlock(ctx context.Context, ld, rcbItemID string) (*ReportControlBlock, error)
- func (c *Client) GetSettingGroupInfo(ctx context.Context, ld string) (*SettingGroupInfo, error)
- func (c *Client) GetVariableType(ctx context.Context, ref Ref) (*mms.TypeSpec, error)
- func (c *Client) InvalidateCache()
- func (c *Client) InvalidateLDCache(ld string)
- func (c *Client) ListChildren(ctx context.Context, ref Ref) ([]BrowseNode, error)
- func (c *Client) ListDataObjects(ctx context.Context, ld, ln string) ([]DataObject, error)
- func (c *Client) ListDataSets(ctx context.Context, ld string) ([]string, error)
- func (c *Client) ListFiles(ctx context.Context, pattern string) ([]FileEntry, error)
- func (c *Client) ListJournals(ctx context.Context, ld string) ([]string, error)
- func (c *Client) ListLogicalDevices(ctx context.Context) ([]LogicalDevice, error)
- func (c *Client) ListLogicalNodes(ctx context.Context, ld string) ([]LogicalNode, error)
- func (c *Client) ListReports(ctx context.Context, ld string) ([]string, error)
- func (c *Client) ListReportsVerified(ctx context.Context, ld string) ([]string, error)
- func (c *Client) MMS() *mms.Client
- func (c *Client) ObtainFile(ctx context.Context, sourceFile, destinationFile string) error
- func (c *Client) Operate(ctx context.Context, ref Ref, params OperateParams) error
- func (c *Client) Read(ctx context.Context, ref Ref) (*Value, error)
- func (c *Client) ReadComponent(ctx context.Context, ref Ref, component string) (*Value, error)
- func (c *Client) ReadCtlModel(ctx context.Context, ref Ref) (CtlModel, error)
- func (c *Client) ReadDataSet(ctx context.Context, ld, dsName string) ([]DataSetValue, error)
- func (c *Client) ReadFile(ctx context.Context, fileName string) ([]byte, *FileEntry, error)
- func (c *Client) ReadJournal(ctx context.Context, ld, journal string, start, stop time.Time) (*JournalReadResult, error)
- func (c *Client) ReadJournalAfter(ctx context.Context, ld, journal string, afterTime time.Time, afterID []byte) (*JournalReadResult, error)
- func (c *Client) ReadJournalAfterAll(ctx context.Context, ld, journal string, afterTime time.Time, afterID []byte) ([]JournalEntry, error)
- func (c *Client) ReadJournalAll(ctx context.Context, ld, journal string, start, stop time.Time) ([]JournalEntry, error)
- func (c *Client) ReadLastApplError(ctx context.Context, ref Ref) (*LastApplError, error)
- func (c *Client) ReadMultiple(ctx context.Context, refs []Ref) ([]ReadResult, error)
- func (c *Client) ReadRaw(ctx context.Context, ref Ref) (*mms.Value, error)
- func (c *Client) RefreshCache(ctx context.Context) error
- func (c *Client) RefreshLDCache(ctx context.Context, ld string) error
- func (c *Client) ReleaseURCB(ctx context.Context, ld, rcbItemID string) error
- func (c *Client) RenameFile(ctx context.Context, currentName, newName string) error
- func (c *Client) ReserveURCB(ctx context.Context, ld, rcbItemID string) error
- func (c *Client) Select(ctx context.Context, ref Ref) (string, error)
- func (c *Client) SelectActiveSG(ctx context.Context, ld string, sg uint8) error
- func (c *Client) SelectEditSG(ctx context.Context, ld string, sg uint8) error
- func (c *Client) SelectWithValue(ctx context.Context, ref Ref, params OperateParams) error
- func (c *Client) SetEditSGValue(ctx context.Context, ref Ref, value *mms.Value) error
- func (c *Client) SetReportControlBlock(ctx context.Context, ld, rcbItemID string, update RCBUpdate) error
- func (c *Client) SubscribeReport(ctx context.Context, rptID string, opts SubscribeReportOptions) (*ReportSubscription, error)
- func (c *Client) Tree(ctx context.Context) (*ModelNode, error)
- func (c *Client) TreeWithOptions(ctx context.Context, opts TreeOptions) (*ModelNode, error)
- func (c *Client) TriggerGI(ctx context.Context, ld, rcbItemID string) error
- func (c *Client) Write(ctx context.Context, ref Ref, value *mms.Value) error
- func (c *Client) WriteMultiple(ctx context.Context, requests []WriteRequest) ([]WriteResult, error)
- type ClientOptions
- type ConnectionEvent
- type ControlError
- type ControlHandler
- type ControlRequest
- type CtlModel
- type DataAccessError
- type DataObject
- type DataSet
- type DataSetMember
- type DataSetValue
- type DecodeError
- type DialOptions
- type FileEntry
- type FindQuery
- type FunctionalConstraint
- type JournalEngine
- type JournalEngineOption
- type JournalEntry
- type JournalReadResult
- type JournalVariable
- type LastApplError
- type LogicalDevice
- type LogicalNode
- type MatchMode
- type MemoryJournalOption
- type MemoryJournalProvider
- func (p *MemoryJournalProvider) AddEntry(domain, journal string, occTime time.Time, vars []mms.JournalVariable) []byte
- func (p *MemoryJournalProvider) EntryCount(domain, journal string) int
- func (p *MemoryJournalProvider) ListJournals(_ context.Context, domain string) ([]string, error)
- func (p *MemoryJournalProvider) ReadStartAfter(_ context.Context, domain, journal string, afterID []byte, afterTime time.Time, ...) (*mms.JournalResult, error)
- func (p *MemoryJournalProvider) ReadTimeRange(_ context.Context, domain, journal string, start, stop time.Time, ...) (*mms.JournalResult, error)
- func (p *MemoryJournalProvider) RegisterJournal(domain, journal string)
- type ModelError
- type ModelNode
- type OperateParams
- type OptFlds
- type OrCat
- type Origin
- type OverflowPolicy
- type Quality
- type RCBFieldMask
- type RCBType
- type RCBUpdate
- type ReadResult
- type ReasonCode
- type Ref
- func (r Ref) Child(name string) (Ref, error)
- func (r Ref) Depth() int
- func (r Ref) HasPath() bool
- func (r Ref) IsLD() bool
- func (r Ref) IsLN() bool
- func (r Ref) IsObject() bool
- func (r Ref) ObjectReference() string
- func (r Ref) Parent() (Ref, bool)
- func (r Ref) String() string
- func (r Ref) ToMMS() (domain mms.DomainID, itemID mms.ItemID, err error)
- func (r Ref) Validate() error
- func (r Ref) WithFC(fc FunctionalConstraint) Ref
- type ReferenceError
- type ReportControlBlock
- type ReportEngine
- func (re *ReportEngine) HandleRCBWrite(ctx context.Context, ldName, rcbItemID, subfield string, val *mms.Value, ...) error
- func (re *ReportEngine) NotifyValueChanged(ctx context.Context, storeKey string)
- func (re *ReportEngine) SetRCBBufMax(ldName, rcbItemID string, max int) bool
- func (re *ReportEngine) Stop()
- type ReportError
- type ReportIndication
- type ReportSubscription
- type RptMatchMode
- type SCLParseError
- type Server
- func (s *Server) Capabilities() ServiceCapabilities
- func (s *Server) ChangeActiveSettingGroup(ctx context.Context, ld string, sg uint8) error
- func (s *Server) Close()
- func (s *Server) EnableJournals(opts ...JournalEngineOption) *JournalEngine
- func (s *Server) EnableReports() *ReportEngine
- func (s *Server) EnableSettingGroups(handler SettingGroupHandler)
- func (s *Server) HandleIdentify(id ServerIdentity)
- func (s *Server) HandleStatus()
- func (s *Server) JournalEngine() *JournalEngine
- func (s *Server) ListenAndServe(ctx context.Context, ln mms.TransportListener) error
- func (s *Server) MMS() *mms.Server
- func (s *Server) Model() *servermodel.Model
- func (s *Server) RegisterControl(ldName, doRef string, ctlModel CtlModel, handler ControlHandler) error
- func (s *Server) ReportEngine() *ReportEngine
- func (s *Server) Serve(ctx context.Context, conn mms.Transport) error
- func (s *Server) SetValue(ctx context.Context, storeKey string, val *mms.Value)
- func (s *Server) SettingGroupEngine() *SettingGroupEngine
- func (s *Server) ValueStore() *servermodel.ValueStore
- type ServerIdentity
- type ServerOptions
- type ServiceCapabilities
- type SettingGroupEngine
- type SettingGroupHandler
- type SettingGroupInfo
- type StrictnessOptions
- type SubscribeReportOptions
- type TimeQuality
- type Timestamp
- type TreeOptions
- type TrgOps
- type Validity
- type Value
- func ArrayValue(elements []*Value) (*Value, error)
- func BoolValue(b bool) *Value
- func FloatValue(f float64) *Value
- func IntValue(i int64) *Value
- func NewValue(v *mms.Value) *Value
- func OctetStringValue(data []byte) *Value
- func QualityValue(q Quality) *Value
- func StringValue(s string) *Value
- func StructureValue(elements []*Value) (*Value, error)
- func TimestampValue(ts Timestamp) *Value
- func UintValue(u uint64) *Value
- func UnsafeArrayValue(elements []*Value) *Value
- func UnsafeStructureValue(elements []*Value) *Value
- func (v *Value) BitString() ([]byte, error)
- func (v *Value) Bool() (bool, error)
- func (v *Value) Elements() ([]*Value, error)
- func (v *Value) Float32() (float32, error)
- func (v *Value) Float64() (float64, error)
- func (v *Value) Int32() (int32, error)
- func (v *Value) Int64() (int64, error)
- func (v *Value) IsArray() bool
- func (v *Value) IsStructure() bool
- func (v *Value) MMS() *mms.Value
- func (v *Value) MmsString() (string, error)
- func (v *Value) OctetString() ([]byte, error)
- func (v *Value) Quality() (Quality, error)
- func (v *Value) String() string
- func (v *Value) Timestamp() (Timestamp, error)
- func (v *Value) Type() mms.ValueType
- func (v *Value) Uint32() (uint32, error)
- func (v *Value) Uint64() (uint64, error)
- func (v *Value) VisibleString() (string, error)
- type WriteRequest
- type WriteResult
Examples ¶
Constants ¶
const DefaultSelectTimeout = 30 * time.Second
DefaultSelectTimeout is the default SBO select timeout applied when no per-registration timeout is configured.
Uses wall-clock time via time.Since. On systems where the wall clock can jump (NTP corrections, suspend/resume), the effective timeout may differ from the intended duration. For safety-critical applications, consider shorter timeouts and monitoring clock skew.
Variables ¶
var ( // ErrInvalidReference indicates a syntactically invalid IEC 61850 // object reference. ErrInvalidReference = errors.New("iec61850: invalid reference") // ErrInvalidFunctionalConstraint indicates an unrecognized // functional constraint value. ErrInvalidFunctionalConstraint = errors.New("iec61850: invalid functional constraint") // ErrNotFound indicates that the requested IEC 61850 object does // not exist on the server. ErrNotFound = errors.New("iec61850: not found") // ErrTypeMismatch indicates that a value's type does not match the // expected IEC 61850 type. ErrTypeMismatch = errors.New("iec61850: type mismatch") // ErrUnsupportedService indicates that the requested service is not // supported by the server or this library. ErrUnsupportedService = errors.New("iec61850: unsupported service") // ErrSubscriptionClosed indicates that a report subscription has // been closed. ErrSubscriptionClosed = errors.New("iec61850: subscription closed") // ErrSCLParse indicates a failure to parse an SCL file. ErrSCLParse = errors.New("iec61850: SCL parse error") // ErrModelMismatch indicates a mismatch between the expected and // actual data model. ErrModelMismatch = errors.New("iec61850: model mismatch") // ErrUnsupportedCDC indicates an unsupported Common Data Class. ErrUnsupportedCDC = errors.New("iec61850: unsupported CDC") // ErrReportDecode indicates a failure to decode a report payload. ErrReportDecode = errors.New("iec61850: report decode error") // ErrDatasetDecode indicates a failure to decode dataset contents. ErrDatasetDecode = errors.New("iec61850: dataset decode error") // ErrClosed indicates that the client connection has been closed. ErrClosed = errors.New("iec61850: connection closed") // ErrDataAccess indicates a per-variable data access failure // returned by the server for an individual read or write. ErrDataAccess = errors.New("iec61850: data access error") // ErrInvalidArgument indicates that a caller-supplied argument is // invalid (empty required field, nil value, etc.). Use [errors.Is] // to distinguish argument errors from server-side failures. ErrInvalidArgument = errors.New("iec61850: invalid argument") // ErrProtocol indicates a protocol-level mismatch between the // client and server, such as an unexpected response count or // missing mandatory fields in a response. ErrProtocol = errors.New("iec61850: protocol error") // ErrControlFailed indicates that a control operation (operate, // select, cancel) was rejected or failed. ErrControlFailed = errors.New("iec61850: control failed") // ErrSelectFailed indicates that a select or select-with-value // request was denied by the server. ErrSelectFailed = errors.New("iec61850: select failed") // ErrOperateFailed indicates that an operate request was denied // or could not be executed. ErrOperateFailed = errors.New("iec61850: operate failed") // ErrCancelFailed indicates that a cancel request was denied // or could not be executed. ErrCancelFailed = errors.New("iec61850: cancel failed") // ErrNotControllable indicates that the target data object's // ctlModel is status-only and does not support control. ErrNotControllable = errors.New("iec61850: not controllable") )
Sentinel errors for major IEC 61850 failure categories.
Use errors.Is to test against these values.
Functions ¶
func BspCtlVal ¶
BspCtlVal creates a bitstring control value for BSC (binary step controllable) CDCs.
func DpCtlVal ¶
DpCtlVal creates a Dbpos (double-point) control value using a two-bit bitstring: 01=off, 10=on.
func EncodeQuality ¶
EncodeQuality encodes an IEC 61850 quality as an MMS bit string value.
func EncodeTimestamp ¶
EncodeTimestamp encodes an IEC 61850 timestamp as an MMS UTCTime value, including the TimeQuality byte.
The quality byte encodes leap-second awareness, clock failure, clock synchronization, and sub-second accuracy bits.
func EnumCtlVal ¶
EnumCtlVal creates an enumerated control value.
func FloatCtlVal ¶
FloatCtlVal creates a floating-point control value (for APC controllable analogue CDCs).
func HasDuplicateRefs ¶
HasDuplicateRefs reports whether the given ref slice contains duplicate entries (same LD/LN/Path/FC). Use this before Client.ReadMultiple or Client.WriteMultiple to detect accidental duplicates that the bulk APIs preserve by design.
func NewServerModelFromSCL ¶
NewServerModelFromSCL builds a server data model from an SCL configuration. The iedName selects the IED; apName selects the AccessPoint (empty uses the first AccessPoint with a Server).
This is a convenience wrapper around servermodel.FromSCL.
func StringCtlVal ¶
StringCtlVal creates a visible-string control value.
Types ¶
type AddCause ¶
type AddCause int
AddCause represents the AdditionalCause field in LastApplError, indicating why a control command was refused or failed.
const ( AddCauseUnknown AddCause = 0 AddCauseNotSupported AddCause = 1 AddCauseBlocked AddCause = 2 AddCauseSelectFailed AddCause = 3 AddCauseInvalidPosition AddCause = 4 AddCausePositionReached AddCause = 5 AddCauseParameterChange AddCause = 6 AddCauseStepLimit AddCause = 7 AddCauseBlockedBySwitch AddCause = 8 AddCauseBlockedByInterlocking AddCause = 9 AddCauseBlockedBySynchrocheck AddCause = 10 AddCauseCommandAlreadyExec AddCause = 11 AddCauseBlockedByHealth AddCause = 12 AddCause1of1 AddCause = 13 AddCauseAbort AddCause = 14 AddCauseTimeLimit AddCause = 15 AddCauseBlockedByMode AddCause = 16 AddCauseBlockedByProcess AddCause = 17 )
type BrowseNode ¶
type BrowseNode struct {
// Name is the local component name (e.g., "stVal", "mag").
Name string
// Reference is the full IEC 61850 object reference.
Reference Ref
}
BrowseNode represents a generic browse child returned by Client.ListChildren. Unlike DataObject, a BrowseNode does not imply that the node is a data object — it may be a sub-data object, data attribute, or any other child in the FC-merged browse view.
type CacheStrategy ¶
type CacheStrategy int
CacheStrategy controls client-side caching of IEC 61850 model discovery results to reduce server load during repeated browse operations.
const ( // CacheNone disables caching. Every browse/discovery call hits // the server. This is the default. CacheNone CacheStrategy = iota // CacheExplicit enables a cache that is only populated via // explicit calls to [Client.RefreshCache] or // [Client.RefreshLDCache]. Browse methods consult the cache // if populated, otherwise fetch from the server without // storing the result. Use [Client.InvalidateCache] to clear. CacheExplicit // CacheLazy transparently caches results on first access. // Subsequent accesses reuse cached data. Explicit invalidation // and refresh are still available via [Client.InvalidateCache] // and [Client.RefreshCache]. CacheLazy )
type CancelParams ¶
type CancelParams struct {
// CtlVal is the control value from the original Operate that
// is being cancelled. Required.
CtlVal *mms.Value
// Origin identifies the command originator. When nil, a default
// Origin with OrCatRemoteControl and empty OrIdent is used.
Origin *Origin
// CtlNum is the control sequence number that matches the
// original Operate.
CtlNum uint8
// OperTm is the scheduled operation time from the original
// Operate. A zero value means the original was immediate.
OperTm time.Time
}
CancelParams contains parameters for an IEC 61850 Cancel command.
type CheckConditions ¶
type CheckConditions uint8
CheckConditions represents the Check bitstring in a control command. Bit 0 = synchrocheck, Bit 1 = interlockCheck.
const ( CheckSynchroCheck CheckConditions = 1 << 0 CheckInterlockCheck CheckConditions = 1 << 1 )
func (CheckConditions) Has ¶
func (c CheckConditions) Has(flag CheckConditions) bool
Has reports whether the given check bit is set.
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
func Dial ¶
Dial establishes a new IEC 61850 MMS connection to the specified address (host:port).
The context controls the connection timeout. The caller must call Client.Close when done.
Example ¶
ExampleDial demonstrates connecting to a remote IED and reading a value.
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
client, err := Dial(ctx, "192.0.2.1:102", DialOptions{
IEDName: "IED1",
})
if err != nil {
cancel()
log.Fatal(err)
}
defer cancel()
defer func() { _ = client.Close(ctx) }()
ref, err := ParseRef("LD1/GGIO1.Ind1.stVal[ST]")
if err != nil {
log.Fatal(err)
}
val, err := client.Read(ctx, ref)
if err != nil {
log.Fatal(err)
}
fmt.Println(val)
func NewClient ¶
func NewClient(mmsClient *mms.Client, opts ClientOptions) (*Client, error)
NewClient creates an IEC 61850 client wrapping an already-created mms.Client. The caller retains ownership of the MMS client and is responsible for closing it separately.
Returns an error if mmsClient is nil.
Use this when you need custom MMS connection setup or want to share a single MMS client across layers.
func (*Client) Abort ¶
Abort performs a hard, immediate abort of the connection without graceful shutdown. Use this for emergency teardown or protocol desync recovery.
If the client was created via NewClient, Abort only marks the IEC 61850 layer as closed without aborting the MMS client.
Abort is idempotent.
func (*Client) Cancel ¶
Cancel sends a cancel command for a previously selected control.
The CancelParams should match the CtlVal, Origin, and CtlNum of the original Operate or SelectWithValue.
func (*Client) Close ¶
Close performs a graceful shutdown of the IEC 61850 client.
If the client was created via Dial, Close also closes the underlying MMS connection. If created via NewClient, the caller is responsible for closing the MMS client.
The client transitions through open → closing → closed. During the closing phase, subscription cleanup runs (disabling RCBs, releasing URCBs). Remote cleanup errors during this phase are logged at Debug level because the connection may already be half-closed.
Close is idempotent.
func (*Client) ConfirmEditSG ¶
ConfirmEditSG confirms the current edit session by writing CnfEdit=true to the SGCB. The server copies the edited SE values into the edit group's storage and clears the edit session.
This must be called after Client.SelectEditSG and any Client.SetEditSGValue calls to commit the changes.
func (*Client) CreateDataSet ¶
func (c *Client) CreateDataSet(ctx context.Context, ld, dsName string, members []DataSetMember) error
CreateDataSet creates a dynamic (deletable) data set on the server.
The ld parameter is the logical device (MMS domain) that owns the data set, dsName is the data set name as an MMS item ID (e.g. "LLN0$dsNew"), and members lists the FCDAs.
Each member must have a valid Ref with LN and FC, or explicit DomainID/ItemID. Members may reference data in different logical devices (cross-LD members); when a member's Ref.LD is empty, the owning ld is used as the default domain. The data set itself is always created under the specified ld.
Member field precedence: if DomainID and ItemID are set explicitly, they are used as-is. Otherwise they are derived from the member's Ref via Ref.ToMMS, defaulting the domain to ld when Ref.LD is empty.
Dynamic data sets can be deleted with Client.DeleteDataSet.
func (*Client) DeleteDataSet ¶
DeleteDataSet deletes a dynamic data set from the server.
Only dynamically created data sets (Deletable=true) can be deleted. Attempting to delete a static (SCL-configured) data set returns an error from the server.
func (*Client) DeleteFile ¶
DeleteFile deletes a file on the server.
func (*Client) DownloadFile ¶
func (c *Client) DownloadFile(ctx context.Context, fileName string, w io.Writer) (*FileEntry, error)
DownloadFile streams a file from the server to the provided writer. This is the preferred method for large files as it does not buffer the entire file in memory.
The returned FileEntry contains the file metadata (size, timestamp). The actual number of bytes written may differ from FileEntry.Size if the server reports an approximate size.
func (*Client) FindPaths ¶
FindPaths searches the server model for references matching the query. This performs model discovery and then filters the results.
The Pattern field in FindQuery supports glob matching via path.Match. Matching is applied to the full object reference string (e.g., "LD/LN.DO.DA"):
- '*' matches any characters within a single path component (does not cross '/')
- '?' matches a single character
- '[' brackets match character classes
For patterns that need to cross component boundaries, consider using MatchRegex mode instead.
Pattern matching is performed against the object reference without the [FC] suffix. If the same object path exists under multiple FCs (e.g. ST and MX), it yields one result per FC because the full reference string (including FC) is used as the deduplication key. To get path-level deduplication, set FindQuery.FC to restrict results to a single functional constraint.
The FC field, when non-empty, filters to attributes with that FC. Results are deduplicated by full reference string (path + FC).
func (*Client) GetActiveSGValue ¶
GetActiveSGValue reads a data attribute value from the currently active setting group (FC=SG).
The ref must include LD, LN, and data path — the FC is forced to SG. This returns the active group's value regardless of any ongoing edit session.
func (*Client) GetDataSet ¶
GetDataSet retrieves the definition (members) of a data set.
The ld parameter is the logical device (MMS domain) and dsName is the data set name as an MMS NVL item ID (e.g. "LLN0$dsName"). The returned DataSet.Reference uses IEC 61850 format (e.g. "LD/LLN0.dsName").
func (*Client) GetEditSGValue ¶
GetEditSGValue reads a data attribute value from the current edit setting group (FC=SE). The ref must include LD, LN, and data path — the FC is forced to SE.
An edit session must be active (via Client.SelectEditSG) for the server to return edit-group values.
func (*Client) GetFileAttributes ¶
GetFileAttributes retrieves the metadata (size, last modified) for a single file without reading its contents.
Implementation note: MMS does not define a dedicated metadata-only call. This method opens and immediately closes the file to obtain the metadata from the FileOpen response. If go-mms gains a pure metadata accessor (e.g., via FileDirectory with an exact path), this should switch to that to avoid the open/close overhead and potential server-side side effects.
func (*Client) GetReportControlBlock ¶
func (c *Client) GetReportControlBlock(ctx context.Context, ld, rcbItemID string) (*ReportControlBlock, error)
GetReportControlBlock reads all attributes of a report control block from the server.
The ld parameter is the logical device (MMS domain) and rcbItemID is the RCB's MMS item ID (e.g. "LLN0$BR$brcb01" or "LLN0$RP$urcb01").
Example ¶
ExampleClient_GetReportControlBlock demonstrates reading an RCB's current attributes without subscribing.
ctx := context.Background()
client, err := Dial(ctx, "192.0.2.1:102", DialOptions{})
if err != nil {
log.Fatal(err)
}
defer func() { _ = client.Close(ctx) }()
rcb, err := client.GetReportControlBlock(ctx, "LD1", "LLN0$RP$urcb01")
if err != nil {
log.Fatal(err)
}
fmt.Printf("RptID=%q DatSet=%q ConfRev=%d RptEna=%v\n",
rcb.RptID, rcb.DatSet, rcb.ConfRev, rcb.RptEna)
func (*Client) GetSettingGroupInfo ¶
GetSettingGroupInfo reads the Setting Group Control Block (SGCB) from the given logical device and returns the current state.
The SGCB is located at LLN0$SP$SGCB in every LD that supports setting groups. Returns an error if the SGCB cannot be read or decoded.
func (*Client) GetVariableType ¶
GetVariableType retrieves the MMS type specification for a variable. The ref must be an object reference (LD/LN with path) and must include a functional constraint.
func (*Client) InvalidateCache ¶
func (c *Client) InvalidateCache()
InvalidateCache clears all cached model data without re-fetching. Subsequent browse calls will fetch fresh data from the server. This is a no-op when caching is disabled (CacheNone).
func (*Client) InvalidateLDCache ¶
InvalidateLDCache clears cached variable data and dataset definitions for a single logical device. This is a no-op when caching is disabled (CacheNone).
func (*Client) ListChildren ¶
ListChildren returns the direct browse children (sub-data objects and data attributes) under the specified reference.
The ref must include at least LD and LN. When ref has a path (e.g., LD/LN.DO), this returns the direct children of that path. When ref has only LD/LN, this is equivalent to Client.ListDataObjects but returns BrowseNode instead of DataObject.
Because MMS variable names are FC-qualified, the returned children are a merged view across all functional constraints. A child name like "stVal" may exist under both ST and MX; this method returns it once. Use Client.TreeWithOptions with IncludeFCs to discover which FCs apply, or specify an FC when reading/writing.
Results are sorted alphabetically by name.
func (*Client) ListDataObjects ¶
ListDataObjects returns the top-level data objects under the specified logical node.
The data objects are discovered by listing all named variables in the parent MMS domain, filtering for the specified LN, and extracting unique data object names (third $-delimited segment).
Results are sorted alphabetically by name.
func (*Client) ListDataSets ¶
ListDataSets returns the names of all data sets (MMS Named Variable Lists) defined in the specified logical device (MMS domain).
The returned names are MMS item IDs (e.g., "LLN0$dsName").
Results are sorted alphabetically by name for deterministic output.
func (*Client) ListFiles ¶
ListFiles returns the directory listing for the given file path pattern on the server. An empty pattern lists the root directory.
Pagination is handled internally; all matching entries are returned. Results are sorted by name for stable, deterministic output.
func (*Client) ListJournals ¶
ListJournals returns the names of all journals (logs) defined in the specified logical device (MMS domain).
func (*Client) ListLogicalDevices ¶
func (c *Client) ListLogicalDevices(ctx context.Context) ([]LogicalDevice, error)
ListLogicalDevices returns the logical devices (MMS domains) available on the server.
Results are sorted alphabetically by name.
func (*Client) ListLogicalNodes ¶
ListLogicalNodes returns the logical nodes within the specified logical device.
The logical nodes are discovered by listing all named variables in the MMS domain and extracting the unique first $-delimited segment (the LN name in IEC 61850 MMS mapping).
Results are sorted alphabetically by name.
func (*Client) ListReports ¶
ListReports returns the names of all report control blocks in the specified logical device.
Discovery is by MMS item-name pattern: an item ID with exactly three '$'-separated segments where the second segment is "BR" or "RP" is treated as a RCB. This is a heuristic — it does not perform semantic verification (e.g., reading RCB attributes) to confirm the variable is actually a report control block.
When StrictnessOptions.VerifyReportCandidates is true, each candidate is read from the server and decoded; items that fail to decode as a valid RCB structure are excluded. This is equivalent to calling Client.ListReportsVerified.
The results include both buffered (BRCB, FC=BR) and unbuffered (URCB, FC=RP) report control blocks. Each returned name is an MMS item ID like "LLN0$BR$brcbName01" or "LLN0$RP$urcbName01".
Results are sorted alphabetically by name for deterministic output.
func (*Client) ListReportsVerified ¶
ListReportsVerified returns verified report control block names by reading each heuristic candidate from the server and confirming it decodes as a valid RCB structure. This is slower than [ListReports] (one MMS read per candidate) but eliminates false positives from naming collisions.
Candidates that fail to read or decode are silently excluded from the result and logged at Debug level.
func (*Client) MMS ¶
MMS returns the underlying mms.Client for advanced operations that are not exposed by the IEC 61850 API.
Warning — unsafe escape hatch ¶
The returned pointer is shared with this Client. Operations performed on it bypass all IEC 61850 state management and can silently corrupt higher-level invariants including:
- Model cache freshness (raw MMS writes can change server state without invalidating the cached browse results).
- Report subscription state (disabling or re-enabling an RCB directly may desynchronize the subscription table).
- Connection lifecycle (calling Close or Abort on the returned client while the IEC 61850 layer owns it leads to double-close or use-after-close).
Rules:
- Do NOT call Close or Abort on the returned client when the Client was created via Dial (the IEC 61850 layer owns it).
- After Client.Close or Client.Abort, the returned MMS client follows the underlying go-mms closed semantics (all calls return mms.ErrClosed).
- Treat this as a read-only escape hatch (e.g. Identify, Status, GetNameList) unless you fully understand the interaction with the IEC 61850 layer's state.
Most users should not need this method.
func (*Client) ObtainFile ¶
ObtainFile instructs the server to copy a file from sourceFile to destinationFile. This is the standard MMS file transfer mechanism for "uploading" data — the server fetches the source file.
In IEC 61850 deployments, ObtainFile is typically used for configuration file transfer (e.g. SCL/CID files) where the server pulls a file from an engineering workstation or another IED.
Note: MMS does not define a direct client-to-server file write (push) operation. ObtainFile is the closest equivalent, but it requires the server to be able to reach the source file path.
func (*Client) Operate ¶
Operate performs a direct-operate control command on the specified data object.
The ref identifies the controllable data object (e.g. "LD/LN.SPCSO1"). It must include LD and LN with a data-object path but must NOT include FC — the library writes to CO/Oper automatically.
For SBO control models, use Client.Select or Client.SelectWithValue before calling Operate.
If params.CtlNum is zero, an auto-incrementing sequence number is used. If params.Origin is nil, a default Origin with OrCatRemoteControl is used.
func (*Client) Read ¶
Read reads a single IEC 61850 data attribute and returns it as an IEC 61850 Value.
The ref must include LD, LN, and FC.
LN-level reads are supported: when the ref has LD + LN + FC but no path, the server returns the full structured value for all data attributes under that LN and FC combination.
For raw MMS values without the IEC 61850 wrapper, use Client.ReadRaw.
func (*Client) ReadComponent ¶
ReadComponent reads a named component (sub-attribute) of a data object or data attribute.
This is a convenience API equivalent to reading with a ref that has the component appended to the path. For example, reading component "stVal" from ref "LD/LN.Mod[ST]" is equivalent to reading "LD/LN.Mod.stVal[ST]".
The ref must include LD, LN, FC, and at least one path component (the parent structure). The component name must be non-empty and must not contain separator characters.
func (*Client) ReadCtlModel ¶
ReadCtlModel reads the ctlModel attribute of a controllable data object. This determines which control flow (direct, SBO, enhanced) should be used.
The ref identifies the data object (e.g. "LD/LN.SPCSO1") without FC — the library reads from CF/ctlModel automatically.
func (*Client) ReadDataSet ¶
ReadDataSet reads all member values of a data set in a single MMS request.
The ld parameter is the logical device (MMS domain) and dsName is the data set name (MMS item ID, e.g. "LLN0$dsName").
To understand the structure of the returned values, first call Client.GetDataSet to obtain the member definitions.
func (*Client) ReadFile ¶
ReadFile reads an entire file from the server and returns its contents.
For large files, prefer Client.DownloadFile which streams to an io.Writer without buffering the entire file in memory.
func (*Client) ReadJournal ¶
func (c *Client) ReadJournal(ctx context.Context, ld, journal string, start, stop time.Time) (*JournalReadResult, error)
ReadJournal reads journal entries within the given time range [start, stop] from the specified journal in the logical device.
The returned entries are in chronological order. When JournalReadResult.MoreFollows is true, use Client.ReadJournalAfter with the last entry's OccurrenceTime and EntryID to page through remaining entries.
func (*Client) ReadJournalAfter ¶
func (c *Client) ReadJournalAfter(ctx context.Context, ld, journal string, afterTime time.Time, afterID []byte) (*JournalReadResult, error)
ReadJournalAfter reads journal entries starting after the given cursor position. Use the last entry's OccurrenceTime and EntryID from a previous [ReadJournal] or [ReadJournalAfter] call to page through journal data.
func (*Client) ReadJournalAfterAll ¶
func (c *Client) ReadJournalAfterAll(ctx context.Context, ld, journal string, afterTime time.Time, afterID []byte) ([]JournalEntry, error)
ReadJournalAfterAll reads all journal entries starting after the given cursor, automatically following pagination until all entries are retrieved.
This is the paginating equivalent of Client.ReadJournalAfter.
func (*Client) ReadJournalAll ¶
func (c *Client) ReadJournalAll(ctx context.Context, ld, journal string, start, stop time.Time) ([]JournalEntry, error)
ReadJournalAll reads all journal entries within the given time range, automatically following pagination (MoreFollows) until all entries are retrieved.
Entries are returned in chronological order. The stop condition is MoreFollows=false from the server. Same-timestamp cursor semantics are handled correctly via EntryID-based continuation.
For very large journals, consider using the paginated Client.ReadJournal / Client.ReadJournalAfter pair to control memory usage.
func (*Client) ReadLastApplError ¶
ReadLastApplError reads and decodes the LastApplError from the logical node containing the given control object.
LastApplError is a structured attribute under the LN at FC=CO that provides the reason for the most recent control failure. Returns nil (no error value) if the attribute is not present or cannot be decoded.
func (*Client) ReadMultiple ¶
ReadMultiple reads multiple IEC 61850 data objects or data attributes in a single MMS request.
Each ref must be an object reference (LD, LN, FC, and at least one path component). LN-level bulk reads are not supported; use Client.Read for those. Results are returned in the same order as the input refs.
Duplicate refs are preserved: if the same ref appears multiple times, each occurrence produces a separate result at the corresponding index. The server may return identical or different values depending on timing.
Per-item errors (e.g., object not found) are reported in ReadResult.Err as a *DataAccessError rather than failing the entire operation.
Mixed-domain and mixed-FC reads are supported: refs may span different logical devices and functional constraints within a single call.
If the MMS request itself fails (e.g., connection error), a non-nil error is returned and the result slice is nil.
func (*Client) ReadRaw ¶
ReadRaw reads a single IEC 61850 data attribute and returns the underlying mms.Value directly, without IEC 61850 wrapping.
This is useful when callers need full control over MMS value interpretation or want to avoid the Value abstraction overhead.
Both object-level (LD/LN.DO.DA[FC]) and LN-level (LD/LN[FC]) reads are supported. LN-level reads return the full structured value for the LN + FC combination as a single MMS structure.
func (*Client) RefreshCache ¶
RefreshCache re-fetches all cached model data from the server. This is a no-op when caching is disabled (CacheNone).
Use this after server model changes to ensure the client sees the latest structure. The cache is rebuilt atomically: on failure, the previous cache state is preserved.
func (*Client) RefreshLDCache ¶
RefreshLDCache re-fetches cached variable data for a single logical device. This is a no-op when caching is disabled (CacheNone).
Only the per-LD variable list is refreshed; the global logical device list is not modified. If the LD was added or removed on the server, call Client.RefreshCache instead to refresh both.
Both the raw item list and any derived parsed-ref cache for the LD are replaced atomically. Dataset definitions are preserved — call Client.InvalidateLDCache to clear those as well.
func (*Client) ReleaseURCB ¶
ReleaseURCB releases a previously reserved unbuffered report control block.
The caller should disable the report (RptEna=false) before releasing to avoid undefined behavior.
func (*Client) RenameFile ¶
RenameFile renames a file on the server.
func (*Client) ReserveURCB ¶
ReserveURCB reserves an unbuffered report control block for exclusive use by this client.
Reservation is required before configuring or enabling a URCB. The reservation remains until explicitly released via Client.ReleaseURCB or the connection is closed.
func (*Client) Select ¶
Select performs a select-before-operate (SBO) select command.
This is used with CtlModelSBONormal. The server returns the selected object reference on success. The client must then call Client.Operate within the server's select timeout.
For enhanced security SBO (CtlModelSBOEnhanced), use Client.SelectWithValue instead.
Interoperability note ¶
The SBO decode path assumes the server returns a VisibleString from a normal MMS read on the SBO subattribute. An empty string is interpreted as "select denied". This matches IEC 61850-8-1 § 22.2 for normal-security SBO but behaviour may vary across devices. Validate against your target devices before relying on this in production.
func (*Client) SelectActiveSG ¶
SelectActiveSG writes a new active setting group number to the SGCB. The server activates the specified group, making its SE values available via FC=SG reads.
The sg parameter must be in [1, NumOfSGs]. Use Client.GetSettingGroupInfo to discover the valid range.
func (*Client) SelectEditSG ¶
SelectEditSG selects a setting group for editing. This reserves the edit session; the server sets EditSG in the SGCB to the requested group number. Only one client may hold an edit session at a time.
After selecting, use Client.GetEditSGValue and Client.SetEditSGValue to read/write SE-constrained values for the edit group. Call Client.ConfirmEditSG to commit changes.
The sg parameter must be in [1, NumOfSGs].
func (*Client) SelectWithValue ¶
SelectWithValue performs a select-before-operate with enhanced security (SBOw) by writing the full Oper structure to the SBOw subattribute.
This is used with CtlModelSBOEnhanced. On success the select is held by the server; the client must then call Client.Operate with the same parameters within the server's select timeout.
func (*Client) SetEditSGValue ¶
SetEditSGValue writes a data attribute value into the current edit setting group (FC=SE). The ref must include LD, LN, and data path — the FC is forced to SE.
An edit session must be active (via Client.SelectEditSG). The change is not committed until Client.ConfirmEditSG is called.
func (*Client) SetReportControlBlock ¶
func (c *Client) SetReportControlBlock(ctx context.Context, ld, rcbItemID string, update RCBUpdate) error
SetReportControlBlock writes selected attributes of a report control block. Only fields specified by RCBUpdate.Fields are sent to the server.
This mask-based approach prevents accidental partial writes that could leave the RCB in an inconsistent state.
func (*Client) SubscribeReport ¶
func (c *Client) SubscribeReport(ctx context.Context, rptID string, opts SubscribeReportOptions) (*ReportSubscription, error)
SubscribeReport creates a subscription that delivers decoded IEC 61850 reports matching the specified RptID pattern.
The caller must read from the ReportSubscription.Reports channel to avoid backpressure. Overflow behavior is controlled by SubscribeReportOptions.OverflowPolicy.
Lifecycle options (AutoEnable, GIOnSubscribe, ReserveURCB) allow the subscription to configure and enable the RCB automatically. These require LD and RCBItemID to be set in options. The caller can still configure RCBs manually via Client.SetReportControlBlock and subscribe passively by not setting any lifecycle options.
Call ReportSubscription.Close when done. The subscription is also closed when the client is closed.
Lifecycle operations are not atomic. If subscription setup fails partway through, some RCB state (e.g., Resv, DatSet) may already have been changed on the server. Rollback is best-effort: the library attempts to undo prior writes, but network or server errors during cleanup are logged and otherwise ignored.
SetReportControlBlock write ordering: configuration fields are written first, RptEna is always written last. This is an IEC 61850 invariant — the library does not promise atomic RCB updates. See Client.SetReportControlBlock for details.
Example ¶
ExampleClient_SubscribeReport demonstrates subscribing to a URCB and receiving data-change reports.
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
client, err := Dial(ctx, "192.0.2.1:102", DialOptions{})
if err != nil {
cancel()
log.Fatal(err)
}
defer cancel()
defer func() { _ = client.Close(ctx) }()
sub, err := client.SubscribeReport(ctx, "urcb01", SubscribeReportOptions{
LD: "LD1",
RCBItemID: "LLN0$RP$urcb01",
AutoEnable: true,
GIOnSubscribe: true,
QueueSize: 64,
OverflowPolicy: OverflowDropNewest,
})
if err != nil {
log.Fatal(err)
}
defer func() { _ = sub.Close() }()
for rpt := range sub.Reports() {
for i, v := range rpt.Values {
if i < len(rpt.ReasonCodes) {
fmt.Printf("member[%d]: reason=%v value=%v\n", i, rpt.ReasonCodes[i], v)
} else {
fmt.Printf("member[%d]: value=%v\n", i, v)
}
}
}
func (*Client) Tree ¶
Tree builds the full IEC 61850 model tree from the server. This performs multiple MMS GetNameList calls to discover the complete hierarchy: logical devices → logical nodes → data objects/attributes.
The returned root ModelNode is a synthetic container (Name="root", empty Reference) whose Children are the logical device nodes. It does not represent a real IEC 61850 object.
The tree merges structure across functional constraints: the same data object path may appear under multiple FCs (e.g., ST and MX), and the tree returns it as a single node. Enable TreeOptions.IncludeFCs to annotate each node with its observed FCs. Without FC annotation, a returned node is a browse view, not a directly readable reference — callers must choose an FC before reading or writing.
The tree includes all data objects and attributes discovered from the MMS variable names. For type information, use Client.GetVariableType on individual nodes.
This operation may be slow on servers with large models.
func (*Client) TreeWithOptions ¶
TreeWithOptions builds the IEC 61850 model tree with configurable filtering and annotation.
Like Client.Tree, the returned tree merges structure across functional constraints. Use TreeOptions.IncludeFCs to annotate nodes with their observed FCs so that callers can determine which FCs are valid for each node before performing read/write operations.
See Client.Tree for the simpler zero-options variant.
func (*Client) TriggerGI ¶
TriggerGI triggers a General Interrogation on a report control block.
For BRCBs, this writes GI=true to the RCB. The server responds by sending a report containing all data set members with reason=GI.
For URCBs, the same mechanism applies but the RCB must be enabled and reserved (if applicable) first.
func (*Client) Write ¶
Write writes a single IEC 61850 data attribute.
The ref must include LD, LN, FC, and a path to the target data attribute. The value is written as-is to the MMS layer.
Returns an error if the write is rejected by the server.
Example ¶
ExampleClient_Write demonstrates writing a value to an attribute.
ctx := context.Background()
client, err := Dial(ctx, "192.0.2.1:102", DialOptions{})
if err != nil {
log.Fatal(err)
}
defer func() { _ = client.Close(ctx) }()
ref, err := ParseRef("LD1/LLN0.Mod.stVal[ST]")
if err != nil {
log.Fatal(err)
}
if err := client.Write(ctx, ref, mms.NewInteger(1)); err != nil {
log.Fatal(err)
}
func (*Client) WriteMultiple ¶
func (c *Client) WriteMultiple(ctx context.Context, requests []WriteRequest) ([]WriteResult, error)
WriteMultiple writes multiple IEC 61850 data attributes in a single MMS request.
Each request must include a valid ref (LD, LN, FC, path) and a non-nil value. Results are returned in the same order as the input requests. Per-item errors are reported in WriteResult.Err as a *DataAccessError.
Duplicate refs are preserved: if the same ref appears multiple times, each write is sent in order. The final server-side value is the last successful write.
Mixed-domain and mixed-FC writes are supported: requests may span different logical devices and functional constraints within a single call. Write order is preserved.
If the MMS request itself fails, a non-nil error is returned and the result slice is nil.
type ClientOptions ¶
type ClientOptions struct {
// Logger, when non-nil, enables structured logging for IEC 61850
// operations. When nil (the default), no logging is emitted.
Logger *slog.Logger
// Strictness controls validation behavior.
Strictness StrictnessOptions
// Cache controls the client-side caching strategy for model
// discovery results (logical devices, logical nodes, data
// objects, tree). The default ([CacheNone]) disables caching.
Cache CacheStrategy
// IEDName, when non-empty, is the IED identifier prefix used by
// the target server to form MMS domain names. See [DialOptions.IEDName].
IEDName string
}
ClientOptions configures an IEC 61850 client created via NewClient from an existing mms.Client.
type ConnectionEvent ¶
type ConnectionEvent struct{}
ConnectionEvent is passed to ServerOptions.OnConnect and ServerOptions.OnDisconnect callbacks.
The event currently provides no connection-specific context because the underlying MMS layer does not expose the mms.ServerConn at the transport-accept boundary. Future versions may add a connection identifier or authentication token when the MMS API supports it.
type ControlError ¶
type ControlError struct {
// Ref is the IEC 61850 object reference of the controlled object.
Ref string
// Operation is the control operation that failed (e.g. "operate",
// "select", "cancel").
Operation string
// AddCause is the additional cause reported by the server via
// LastApplError, if available. Zero means unknown or not read.
AddCause AddCause
// Wrapped is the underlying error.
Wrapped error
}
ControlError is a typed error for control operation failures. It captures the object reference, the operation attempted, and the server-reported additional cause when available.
func (*ControlError) Error ¶
func (e *ControlError) Error() string
func (*ControlError) Unwrap ¶
func (e *ControlError) Unwrap() []error
Unwrap returns a slice of errors so that errors.Is matches both the operation-specific sentinel (e.g. ErrOperateFailed) and the wrapped cause, if any.
type ControlHandler ¶
type ControlHandler struct {
// SelectTimeout overrides [DefaultSelectTimeout] for this control
// object. The select reservation expires this long after a
// successful Select or SelectWithValue. A zero value means use
// [DefaultSelectTimeout].
SelectTimeout time.Duration
// OnSelect is called when a client issues a Select (SBO) or
// SelectWithValue (SBOw) request. Return nil to accept the
// select, or an error (preferably wrapping [ErrSelectFailed]
// with an [AddCause]) to deny it.
//
// If nil, selects are accepted unconditionally.
OnSelect func(ctx context.Context, req ControlRequest) error
// OnOperate is called when a client issues an Operate request.
// Return nil to accept the operate, or an error (preferably
// wrapping [ErrOperateFailed] with an [AddCause]) to deny it.
//
// If nil, operates are accepted unconditionally and the value
// is written to the ValueStore.
OnOperate func(ctx context.Context, req ControlRequest) error
// OnCancel is called when a client issues a Cancel request.
// Return nil to accept the cancellation, or an error to deny.
//
// If nil, cancels are accepted unconditionally.
OnCancel func(ctx context.Context, req ControlRequest) error
}
ControlHandler defines the server-side callbacks for a controllable data object. Implement the methods relevant to the control model; unset (nil) handlers use default accept/reject behavior.
All handler methods receive a context from the MMS layer and a ControlRequest describing the command.
type ControlRequest ¶
type ControlRequest struct {
// Ref is the IEC 61850 object reference of the controlled object.
Ref string
// Operation is "operate", "select", or "cancel".
Operation string
// CtlVal is the control value.
CtlVal *mms.Value
// Origin is the command originator.
Origin Origin
// CtlNum is the control sequence number.
CtlNum uint8
// OperTm is the scheduled operation time (zero for immediate).
OperTm time.Time
// Test indicates whether this is a test command.
Test bool
// Check contains synchrocheck/interlockCheck bits.
Check CheckConditions
}
ControlRequest contains the decoded parameters from a client control command (Operate, Select, or Cancel).
type CtlModel ¶
type CtlModel int
CtlModel represents the IEC 61850 control model (ctlModel attribute). It determines whether the controllable data object uses direct operation, select-before-operate, or enhanced security variants.
const ( // CtlModelStatusOnly means the data object is not controllable. CtlModelStatusOnly CtlModel = 0 // CtlModelDirectNormal is direct-operate with normal security. // The client writes to Oper without a prior Select. CtlModelDirectNormal CtlModel = 1 // CtlModelSBONormal is select-before-operate with normal security. // The client reads SBO (select), then writes to Oper. CtlModelSBONormal CtlModel = 2 // CtlModelDirectEnhanced is direct-operate with enhanced security. // Like CtlModelDirectNormal, but the server validates origin, // ctlNum, and timestamps for command verification. CtlModelDirectEnhanced CtlModel = 3 // CtlModelSBOEnhanced is select-before-operate with enhanced // security. The client writes to SBOw (select-with-value), then // writes to Oper, with full origin/ctlNum/timestamp verification. CtlModelSBOEnhanced CtlModel = 4 )
func (CtlModel) IsControllable ¶
IsControllable reports whether this control model supports any control operation (i.e., is not status-only).
func (CtlModel) IsEnhanced ¶
IsEnhanced reports whether this control model uses enhanced security (origin/ctlNum/timestamp verification).
type DataAccessError ¶
DataAccessError is a typed per-item error for bulk read/write operations. It wraps the MMS-level error code into an IEC 61850 error that supports errors.Is with ErrDataAccess.
func (*DataAccessError) Error ¶
func (e *DataAccessError) Error() string
func (*DataAccessError) Unwrap ¶
func (e *DataAccessError) Unwrap() error
type DataObject ¶
type DataObject struct {
// Name is the component name (e.g., "Mod", "stVal", "mag").
Name string
// Reference is the full IEC 61850 object reference.
Reference Ref
// FC is the functional constraint, when unambiguous. Empty during
// browse/tree discovery where the same object may appear under
// multiple FCs. Populated only when a single FC applies or when
// explicitly set by the caller.
FC FunctionalConstraint
// Children contains sub-objects (nested DOs or DAs).
// Populated only when the tree is built via [Client.Tree] or
// explicit recursive browsing.
Children []DataObject
}
DataObject represents a browsed model component, which may be a data object, sub-data object, or data attribute. It captures name, reference, and optional MMS type information.
type DataSet ¶
type DataSet struct {
// Reference is a display-friendly data set identifier in
// IEC 61850 format (e.g., "LD/LLN0.dsName"). This is a
// convenience string, not a [Ref] and not suitable for
// programmatic use with [Client.ReadDataSet] or
// [Client.DeleteDataSet] — those require the raw (ld, dsName)
// MMS identifiers used when the DataSet was obtained.
Reference string
// Deletable indicates whether the data set can be deleted by the
// client. Static (SCL-configured) data sets are not deletable;
// dynamically created data sets are.
Deletable bool
// Members lists the data set members in definition order.
Members []DataSetMember
}
DataSet represents an IEC 61850 data set (MMS Named Variable List).
A data set groups related data attributes for efficient bulk reading and for use as the trigger source of report control blocks.
type DataSetMember ¶
type DataSetMember struct {
// Ref is the IEC 61850 object reference for this member.
// Includes LD, LN, path, and FC when available.
Ref Ref
// DomainID is the MMS domain name.
DomainID string
// ItemID is the MMS item ID (LN$FC$DO$DA path).
ItemID string
}
DataSetMember represents a single member (FCDA) of a data set.
type DataSetValue ¶
type DataSetValue struct {
// Member is the data set member definition.
Member DataSetMember
// Value is the decoded value. Nil when Err is non-nil.
Value *Value
// Err is the per-member error, if any.
Err error
}
DataSetValue holds the result of reading a single data set member.
type DecodeError ¶
DecodeError indicates a failure during semantic decoding of an MMS value into an IEC 61850 type.
func (*DecodeError) Error ¶
func (e *DecodeError) Error() string
func (*DecodeError) Unwrap ¶
func (e *DecodeError) Unwrap() error
type DialOptions ¶
type DialOptions struct {
// MMS holds the underlying MMS dial options. These are passed
// through to [iso.Dial] via [iso.WithClientDialOptions].
MMS mms.DialOptions
// Logger, when non-nil, enables structured logging for IEC 61850
// operations. When nil (the default), no logging is emitted.
//
// When [DialOptions.MMS].Logger is also nil, this logger is passed
// through to the underlying [mms.Client]. ISO transport logging
// ([iso.WithLogger]) is independent and is not set from here.
Logger *slog.Logger
// Strictness controls validation behavior.
Strictness StrictnessOptions
// Cache controls the client-side caching strategy for model
// discovery results. The default ([CacheNone]) disables caching.
Cache CacheStrategy
// IEDName, when non-empty, is the IED identifier prefix used by
// the target server to form MMS domain names.
//
// Compliant IEC 61850-8-1 servers form MMS domain names by
// concatenating the IED name and the LD instance name (e.g.
// IEDName="InteropIED" + LDInst="InteropLD" →
// domain="InteropIEDInteropLD"). When IEDName is set, the
// client automatically strips the prefix when reporting logical
// device names and prepends it when making MMS requests, so
// callers can always use the bare LD instance name.
IEDName string
}
DialOptions configures an IEC 61850 client connection established via Dial.
type FileEntry ¶
type FileEntry struct {
// Name is the file path as returned by the server.
Name string
// Size is the file size in bytes.
Size int64
// LastModified is the file's last modification timestamp.
LastModified time.Time
}
FileEntry describes a single file on an IEC 61850 / MMS server.
type FindQuery ¶
type FindQuery struct {
// Pattern is matched against the object reference (without FC
// suffix). The matching algorithm is determined by [MatchMode].
//
// Glob examples (default):
// "*/LLN0*" — all LLN0 nodes across all LDs
// "LD1/GGIO1.Ind*" — all Ind objects under GGIO1
//
// Regex examples:
// ".*GGIO1\\.Ind[12]" — Ind1 and Ind2 under any GGIO1
Pattern string
// MatchMode selects the pattern matching algorithm. The default
// ([MatchGlob]) preserves backward compatibility.
MatchMode MatchMode
// FC optionally filters results to a specific functional
// constraint. When empty, all FCs are included.
FC FunctionalConstraint
// LDFilter, when non-empty, restricts the search to a single
// logical device. This avoids fetching variable lists from
// every LD, which can be expensive on servers with many domains.
LDFilter string
// MaxDepth limits traversal depth based on [Ref.Depth]. Zero means
// unlimited. Depth values correspond to:
// 1 = LD only
// 2 = LN
// 3 = first data object level (LD/LN.DO)
// 4+ = deeper data attributes
MaxDepth int
}
FindQuery specifies search criteria for Client.FindPaths.
type FunctionalConstraint ¶
type FunctionalConstraint string
FunctionalConstraint identifies the purpose of a data attribute within the IEC 61850 data model. Each FC classifies what kind of information the attribute carries (status, measured value, setpoint, configuration, etc.).
const ( // FCST is Status information. FCST FunctionalConstraint = "ST" // FCMX is Measurands (analog values). FCMX FunctionalConstraint = "MX" // FCSP is Setpoint. FCSP FunctionalConstraint = "SP" // FCSV is Substitution. FCSV FunctionalConstraint = "SV" // FCCF is Configuration. FCCF FunctionalConstraint = "CF" // FCDC is Description. FCDC FunctionalConstraint = "DC" // FCSG is Setting group. FCSG FunctionalConstraint = "SG" // FCSE is Setting group editable. FCSE FunctionalConstraint = "SE" // FCSR is Service response / service tracking. FCSR FunctionalConstraint = "SR" // FCOR is Operate received. FCOR FunctionalConstraint = "OR" // FCBL is Blocking. FCBL FunctionalConstraint = "BL" // FCEX is Extended definition. FCEX FunctionalConstraint = "EX" // FCCO is Control. FCCO FunctionalConstraint = "CO" // FCUS is Unicast SV. FCUS FunctionalConstraint = "US" // FCMS is Multicast SV. FCMS FunctionalConstraint = "MS" // FCRP is Unbuffered report. FCRP FunctionalConstraint = "RP" // FCBR is Buffered report. FCBR FunctionalConstraint = "BR" // FCLG is Log control blocks. FCLG FunctionalConstraint = "LG" // FCGO is GOOSE control blocks. FCGO FunctionalConstraint = "GO" )
func AllFunctionalConstraints ¶
func AllFunctionalConstraints() []FunctionalConstraint
AllFunctionalConstraints returns all valid functional constraint values in a stable, specification-defined order. The returned slice is a copy — callers may modify it freely.
func ParseFC ¶
func ParseFC(s string) (FunctionalConstraint, error)
ParseFC parses a string as a functional constraint. Returns ErrInvalidFunctionalConstraint if the string is not a recognized FC value.
func (FunctionalConstraint) Description ¶
func (fc FunctionalConstraint) Description() string
Description returns a human-readable description of the functional constraint (e.g., "Status" for ST). Returns "Unknown" for unrecognized values.
func (FunctionalConstraint) IsValid ¶
func (fc FunctionalConstraint) IsValid() bool
IsValid reports whether fc is a recognized functional constraint.
func (FunctionalConstraint) String ¶
func (fc FunctionalConstraint) String() string
String returns the two-letter FC code.
type JournalEngine ¶
type JournalEngine struct {
// contains filtered or unexported fields
}
JournalEngine is the server-side runtime journal engine. It generates journal (log) entries in response to value changes and application events, storing them in a MemoryJournalProvider that backs the MMS journal services.
The engine is created by Server.EnableJournals and attached to the server's MMS layer as the mms.JournalProvider.
func (*JournalEngine) LogEvent ¶
func (e *JournalEngine) LogEvent(domain, journal string, occTime time.Time, vars []mms.JournalVariable) []byte
LogEvent records a custom application event in the specified journal. The domain is the logical device name and journal is the MMS journal name (typically "LLN0$logName"). Variables contain the data to record.
func (*JournalEngine) LogValueWrite ¶
LogValueWrite records a value-write entry in all journals defined for the logical device that contains the given store key. Every write is logged regardless of whether the value actually changed; this provides an audit trail rather than semantic change detection. The store key format is "ldName/itemID".
func (*JournalEngine) Provider ¶
func (e *JournalEngine) Provider() *MemoryJournalProvider
Provider returns the underlying MemoryJournalProvider used by this engine, allowing direct inspection of stored entries.
type JournalEngineOption ¶
type JournalEngineOption func(*JournalEngine)
JournalEngineOption configures the JournalEngine.
func WithJournalMaxEntries ¶
func WithJournalMaxEntries(n int) JournalEngineOption
WithJournalMaxEntries sets the maximum entries per journal in the underlying MemoryJournalProvider. Default is 10000.
func WithJournalProvider ¶
func WithJournalProvider(p *MemoryJournalProvider) JournalEngineOption
WithJournalProvider replaces the default MemoryJournalProvider with a pre-configured one. This is useful when the caller needs direct access to the provider for inspection or pre-population.
type JournalEntry ¶
type JournalEntry struct {
// EntryID is the opaque entry identifier assigned by the server.
// It is used as a cursor for pagination via [Client.ReadJournalAfter].
EntryID []byte
// OccurrenceTime is the timestamp when the event occurred.
OccurrenceTime time.Time
// Variables contains the data values recorded in this entry.
Variables []JournalVariable
}
JournalEntry represents a single entry in an IEC 61850 journal (log).
type JournalReadResult ¶
type JournalReadResult struct {
// Entries contains the journal entries in chronological order.
Entries []JournalEntry
// MoreFollows indicates that additional entries are available
// beyond those returned. Use [Client.ReadJournalAfter] with the
// last entry's OccurrenceTime and EntryID to retrieve the next page.
MoreFollows bool
}
JournalReadResult holds the result of a journal read operation, including pagination state.
type JournalVariable ¶
type JournalVariable struct {
// Tag identifies the variable (typically an MMS variable name).
Tag string
// Value is the recorded value. Wraps the underlying [mms.Value].
Value *Value
}
JournalVariable represents a single variable recorded in a journal entry.
type LastApplError ¶
type LastApplError struct {
// CntrlObj is the object reference of the control that failed.
CntrlObj string
// Error is the IEC 61850 service error class.
Error int
// Origin is the originator that issued the failed command.
Origin Origin
// AddCause provides the specific additional cause.
AddCause AddCause
}
LastApplError contains the decoded result of a LastApplError read, providing server-side failure reason for a control command.
type LogicalDevice ¶
type LogicalDevice struct {
// Name is the logical device name (MMS domain ID).
Name string
}
LogicalDevice represents a logical device discovered on the server. A logical device maps to an MMS domain.
type LogicalNode ¶
type LogicalNode struct {
// Name is the logical node name (e.g., "LLN0", "GGIO1").
Name string
// LD is the parent logical device name.
LD string
}
LogicalNode represents a logical node within a logical device. In the MMS mapping, logical nodes appear as the first $-delimited segment of named variables within a domain.
func (LogicalNode) Ref ¶
func (ln LogicalNode) Ref() Ref
Ref returns the IEC 61850 object reference for this logical node.
type MatchMode ¶
type MatchMode int
MatchMode selects the pattern matching algorithm for FindQuery.
const ( // MatchGlob uses [path.Match] glob semantics (default). '*' // matches any characters within a single component, '?' matches // a single character. MatchGlob MatchMode = iota // MatchRegex uses Go [regexp] semantics. The pattern is compiled // with [regexp.Compile] and matched against the full object // reference string. MatchRegex )
type MemoryJournalOption ¶
type MemoryJournalOption func(*MemoryJournalProvider)
MemoryJournalOption configures a MemoryJournalProvider.
func WithMaxEntries ¶
func WithMaxEntries(n int) MemoryJournalOption
WithMaxEntries sets the maximum number of entries per journal. When exceeded, the oldest entries are dropped. Default is 10000.
type MemoryJournalProvider ¶
type MemoryJournalProvider struct {
// contains filtered or unexported fields
}
MemoryJournalProvider is a thread-safe, in-memory implementation of mms.JournalProvider. It stores entries per (domain, journal) pair with configurable maximum capacity. When the capacity is exceeded, the oldest entries are discarded (ring-buffer semantics).
Entry IDs are auto-assigned as monotonically increasing 8-byte big-endian integers, guaranteeing strict ordering even when multiple entries share the same OccurrenceTime. This makes cursor pagination deterministic and skip-free.
This provider is intended for testing, development, and lightweight server deployments. For production use with large journal volumes, a persistent provider backed by a database or file storage should be used instead.
func NewMemoryJournalProvider ¶
func NewMemoryJournalProvider(opts ...MemoryJournalOption) *MemoryJournalProvider
NewMemoryJournalProvider creates a new in-memory journal provider.
func (*MemoryJournalProvider) AddEntry ¶
func (p *MemoryJournalProvider) AddEntry(domain, journal string, occTime time.Time, vars []mms.JournalVariable) []byte
AddEntry appends a journal entry with the given timestamp and variable data. The EntryID is assigned automatically. Returns the assigned EntryID.
The provided variables are defensively copied so that later mutation of the caller's slice or the values within it does not corrupt the journal history.
If the journal does not exist, it is created implicitly.
func (*MemoryJournalProvider) EntryCount ¶
func (p *MemoryJournalProvider) EntryCount(domain, journal string) int
EntryCount returns the number of entries in the specified journal.
func (*MemoryJournalProvider) ListJournals ¶
ListJournals implements mms.JournalProvider. Results are sorted for deterministic output.
func (*MemoryJournalProvider) ReadStartAfter ¶
func (p *MemoryJournalProvider) ReadStartAfter(_ context.Context, domain, journal string, afterID []byte, afterTime time.Time, maxEntries int) (*mms.JournalResult, error)
ReadStartAfter implements mms.JournalProvider.
func (*MemoryJournalProvider) ReadTimeRange ¶
func (p *MemoryJournalProvider) ReadTimeRange(_ context.Context, domain, journal string, start, stop time.Time, maxEntries int) (*mms.JournalResult, error)
ReadTimeRange implements mms.JournalProvider.
func (*MemoryJournalProvider) RegisterJournal ¶
func (p *MemoryJournalProvider) RegisterJournal(domain, journal string)
RegisterJournal creates an empty journal. This must be called before [AddEntry] to establish the journal's existence. Calling RegisterJournal for an already-registered journal is a no-op.
type ModelError ¶
ModelError indicates a mismatch or inconsistency in the IEC 61850 data model.
func (*ModelError) Error ¶
func (e *ModelError) Error() string
func (*ModelError) Unwrap ¶
func (e *ModelError) Unwrap() error
type ModelNode ¶
type ModelNode struct {
// Name is the local name of this node (LD name, LN name, or
// path component name).
Name string
// Reference is the object reference for this node. During browse/
// tree discovery the FC field is typically empty because the same
// path may appear under multiple FCs. Use [Ref.WithFC],
// [ModelNode.FC], or [ModelNode.FCs] to obtain an FC-qualified
// reference suitable for read/write operations.
Reference Ref
// FC is the functional constraint when a single unambiguous FC
// applies. Set only when exactly one FC is observed for this
// node (e.g., via [TreeOptions.IncludeFCs] or caller-assigned).
FC FunctionalConstraint
// FCs contains all functional constraints observed for this
// node. Populated when [TreeOptions.IncludeFCs] is true.
// Multiple entries indicate the node appears under several FCs
// (common for DOs containing attributes in ST, MX, CF, etc.).
// Empty when FC annotation is not requested.
FCs []FunctionalConstraint
// Type contains MMS type information when available (from
// GetVariableAccessAttributes). Nil when type info has not
// been retrieved.
Type *mms.TypeSpec
// Children contains the child nodes in the hierarchy.
Children []*ModelNode
}
ModelNode represents a node in the IEC 61850 data model tree. Used by Client.Tree to represent the full model hierarchy.
type OperateParams ¶
type OperateParams struct {
// CtlVal is the control value to write. Required.
// Use [BoolCtlVal], [IntCtlVal], [FloatCtlVal], [EnumCtlVal],
// or [StringCtlVal] to construct it.
CtlVal *mms.Value
// Origin identifies the command originator. When nil, a default
// Origin with OrCatRemoteControl and empty OrIdent is used.
Origin *Origin
// CtlNum is the control sequence number. For enhanced security
// models, this must be unique per select/operate cycle. When
// zero, the library auto-increments an internal counter.
CtlNum uint8
// OperTm is the scheduled operation time. A zero value means
// "operate now" (no timed command).
OperTm time.Time
// Test, when true, sets the Test bit to indicate a test command
// that should not cause physical action.
Test bool
// Check specifies synchrocheck/interlockCheck conditions.
Check CheckConditions
}
OperateParams contains all parameters for an IEC 61850 control Operate or SelectWithValue command.
At minimum, CtlVal must be set. For enhanced security models, Origin, CtlNum, and timestamps are also required. The library fills in sensible defaults for unset fields when possible.
type OptFlds ¶
type OptFlds uint16
OptFlds represents the optional fields bit mask of a report control block. Each bit controls whether the corresponding field is included in generated reports.
const ( OptFldSeqNum OptFlds = 1 << 0 // Sequence number OptFldTimeStamp OptFlds = 1 << 1 // Report timestamp OptFldReasonCode OptFlds = 1 << 2 // Inclusion reason per member OptFldDataSet OptFlds = 1 << 3 // Dataset reference OptFldDataRef OptFlds = 1 << 4 // Data references OptFldBufOvfl OptFlds = 1 << 5 // Buffer overflow flag OptFldEntryID OptFlds = 1 << 6 // Entry ID (BRCB) OptFldConfRev OptFlds = 1 << 7 // Configuration revision OptFldSegmentation OptFlds = 1 << 8 // Segmentation info )
Optional field flags for OptFlds.
type OrCat ¶
type OrCat int
OrCat represents the originator category (orCat) in the Origin structure of IEC 61850 control commands.
type Origin ¶
type Origin struct {
// OrCat is the originator category.
OrCat OrCat
// OrIdent is the originator identifier (application-specific,
// typically an IP address or operator ID).
OrIdent []byte
}
Origin identifies the originator of a control command.
type OverflowPolicy ¶
type OverflowPolicy int
OverflowPolicy controls what happens when a subscription's report channel is full.
URCB vs BRCB loss semantics ¶
For URCB (unbuffered) reports, report loss at the application queue level is expected and accepted — the server makes no durability promise. When OverflowDropNewest or OverflowDropOldest is used, lost reports are silently discarded and the client will not observe a gap indicator. This matches the standard URCB contract: reports are best-effort.
For BRCB (buffered) reports, application queue overflow is a different concern from the server-side BRCB buffer overflow:
Server-side BRCB buffer overflow occurs when the in-memory buffer (default: 1000 entries) fills up before any client enables the BRCB. The server drops the oldest entry and sets BufOvfl=true in the next delivered report so the client knows a gap exists.
Client-side application queue overflow (this type) occurs when the client's in-process channel (QueueSize) fills up while reports are being delivered. The chosen OverflowPolicy applies here; the server is unaware of this loss. For BRCB use cases that require no loss, set QueueSize large enough and consume reports promptly, or use OverflowBlock.
Choosing a policy ¶
- OverflowDropNewest: default. Safe for all uses. Report loss is visible in SeqNum gaps.
- OverflowDropOldest: prefer fresher data; older values are discarded.
- OverflowBlock: zero-loss delivery. Blocks report dispatch for all subscriptions on this connection if the channel is full.
- OverflowCallback: custom handling (e.g., metrics, reconnect trigger).
const ( // OverflowDropNewest drops the incoming report when the channel // is full (default). A warning is logged. OverflowDropNewest OverflowPolicy = iota // OverflowDropOldest discards the oldest buffered report to // make room for the new one. OverflowDropOldest // OverflowBlock blocks the dispatcher until space is available. // Use with caution: this can block all report delivery. OverflowBlock // OverflowCallback invokes the OnOverflow callback (if set) // and drops the report. If no callback is set, behaves like // [OverflowDropNewest]. OverflowCallback )
type Quality ¶
type Quality uint16
Quality represents an IEC 61850 quality bit string (13 bits).
Quality is stored as a uint16 where bit positions match the IEC 61850 standard and the C libiec61850 convention:
- bits 0–1: Validity
- bit 2: Overflow
- bit 3: OutOfRange
- bit 4: BadReference
- bit 5: Oscillatory
- bit 6: Failure
- bit 7: OldData
- bit 8: Inconsistent
- bit 9: Inaccurate
- bit 10: Source (substituted)
- bit 11: Test
- bit 12: OperatorBlocked
const ( QualityOverflow Quality = 1 << 2 QualityOutOfRange Quality = 1 << 3 QualityBadReference Quality = 1 << 4 QualityOscillatory Quality = 1 << 5 QualityFailure Quality = 1 << 6 QualityOldData Quality = 1 << 7 QualityInconsistent Quality = 1 << 8 QualityInaccurate Quality = 1 << 9 )
Detail quality flags (bits 2–9).
const ( QualitySourceSubstituted Quality = 1 << 10 QualityTest Quality = 1 << 11 QualityOperatorBlocked Quality = 1 << 12 )
Source, test, and operator flags (bits 10–12).
func DecodeQuality ¶
DecodeQuality decodes an IEC 61850 quality from an MMS bit string value. Returns a DecodeError if the value is not a bit string or has fewer than 13 bits.
func (Quality) IsGood ¶
IsGood returns true when validity is ValidityGood and no detail quality flags are set.
func (Quality) WithValidity ¶
WithValidity returns a copy of the quality with the given validity.
type RCBFieldMask ¶
type RCBFieldMask uint32
RCBFieldMask specifies which RCB fields to write in a Client.SetReportControlBlock call. Only fields with the corresponding mask bit set are written to the server.
const ( RCBFieldRptID RCBFieldMask = 1 << 0 // Write RptID RCBFieldRptEna RCBFieldMask = 1 << 1 // Write RptEna RCBFieldDatSet RCBFieldMask = 1 << 2 // Write DatSet RCBFieldOptFlds RCBFieldMask = 1 << 3 // Write OptFlds RCBFieldBufTm RCBFieldMask = 1 << 4 // Write BufTm RCBFieldTrgOps RCBFieldMask = 1 << 5 // Write TrgOps RCBFieldIntgPd RCBFieldMask = 1 << 6 // Write IntgPd RCBFieldGI RCBFieldMask = 1 << 7 // Write GI RCBFieldResv RCBFieldMask = 1 << 8 // Write Resv (URCB) RCBFieldPurgeBuf RCBFieldMask = 1 << 9 // Write PurgeBuf (BRCB) RCBFieldEntryID RCBFieldMask = 1 << 10 // Write EntryID (BRCB) RCBFieldResvTms RCBFieldMask = 1 << 11 // Write ResvTms (URCB) )
RCB field mask constants for RCBUpdate.
type RCBType ¶
type RCBType int
RCBType distinguishes buffered from unbuffered report control blocks.
func (RCBType) FC ¶
func (t RCBType) FC() FunctionalConstraint
FC returns the functional constraint for this RCB type.
type RCBUpdate ¶
type RCBUpdate struct {
// Fields selects which attributes to write.
Fields RCBFieldMask
RptID string
RptEna bool
DatSet string
OptFlds OptFlds
BufTm uint32
TrgOps TrgOps
IntgPd uint32
GI bool
Resv bool
PurgeBuf bool
EntryID []byte
ResvTms int32
}
RCBUpdate specifies the RCB fields to write and their new values.
type ReadResult ¶
type ReadResult struct {
// Ref is the reference that was read.
Ref Ref
// Value is the decoded value. Nil when Err is non-nil.
Value *Value
// Err is the per-item error, if any. When the MMS server
// returns a per-variable DataAccessError, Err is set and
// Value is nil.
Err error
}
ReadResult holds the outcome of reading a single variable as part of a bulk read operation.
type ReasonCode ¶
type ReasonCode uint8
ReasonCode represents the reason for inclusion of a data set member in a report.
const ( ReasonDataChanged ReasonCode = 1 << 0 // Included due to data change ReasonQualityChanged ReasonCode = 1 << 1 // Included due to quality change ReasonDataUpdate ReasonCode = 1 << 2 // Included due to data update ReasonIntegrity ReasonCode = 1 << 3 // Included due to integrity scan ReasonGI ReasonCode = 1 << 4 // Included due to GI )
Reason code values for report member inclusion.
func (ReasonCode) String ¶
func (r ReasonCode) String() string
String returns a comma-separated list of set reason flags, matching the multi-bit style used by OptFlds.String and TrgOps.String.
type Ref ¶
type Ref struct {
// LD is the logical device name.
LD string
// LN is the logical node name (e.g., "LLN0", "GGIO1").
LN string
// Path contains the data object / data attribute path components.
// Empty when the reference points to a logical node.
Path []string
// FC is the functional constraint. Empty when not specified.
FC FunctionalConstraint
}
Ref is a parsed IEC 61850 object reference.
An IEC 61850 object reference identifies a node in the data model hierarchy: LogicalDevice / LogicalNode . DataObject . DataAttribute. An optional functional constraint can be appended in brackets.
Format: LD/LN.DO.DA[FC]
A Ref may represent different levels of the hierarchy:
- LD-only (LN empty, no path) — identifies a logical device for browsing and GetNameList operations. Not all operations accept LD-only refs; read/write require at least LN + FC.
- LN-level (LN set, no path) — identifies a logical node.
- Object-level (LN set, path present) — identifies a data object or data attribute.
Examples:
simpleIOGenericIO/GGIO1.Ind1.stVal[ST] simpleIOGenericIO/GGIO1.Ind1.stVal simpleIOGenericIO/LLN0
func ParseRef ¶
ParseRef parses an IEC 61850 object reference string.
Accepted formats:
LD/LN.DO.DA[FC] — full reference with functional constraint LD/LN.DO.DA — reference without FC LD/LN — logical node reference LD — logical device reference (LN will be empty)
Returns a *ReferenceError wrapping ErrInvalidReference on malformed input.
The parser accepts references of any reasonable length. Use ParseRefStrict to enforce the conservative 129-character limit inspired by IEC 61850-7-2 VisibleString129.
Unknown FC values (not in the standard set) are accepted. Use StrictnessOptions.RejectUnknownFC at call sites or FunctionalConstraint.IsValid for semantic FC validation.
Example ¶
ExampleParseRef demonstrates parsing an IEC 61850 object reference string.
ref, err := ParseRef("LD1/GGIO1.Ind1.stVal[ST]")
if err != nil {
log.Fatal(err)
}
fmt.Println(ref.LD) // "LD1"
fmt.Println(ref.LN) // "GGIO1"
fmt.Println(ref.Path[0]) // "Ind1"
fmt.Println(ref.Path[1]) // "stVal"
fmt.Println(ref.FC) // "ST"
func ParseRefStrict ¶
ParseRefStrict is like ParseRef but enforces a maximum reference length of 129 characters, inspired by the IEC 61850-7-2 MMS VisibleString129 type for ObjectReference attributes.
func RefFromMMS ¶
RefFromMMS constructs a Ref from an MMS domain ID and item ID.
The item ID is expected to follow the IEC 61850 MMS mapping convention: LN$FC$path$components. The FC is extracted from the second $-delimited segment.
Unknown FCs are accepted and stored as-is. This matches the library's "accept by default, reject via strictness" philosophy. Use StrictnessOptions.RejectUnknownFC at call sites to enforce stricter validation.
Returns an error for empty domain or empty segments within the item ID.
func (Ref) Child ¶
Child returns a new reference with name appended to the path. Returns an error if r has no logical node (LD-only), if name is empty, or if name contains separator characters (/, ., $, [, ]).
func (Ref) Depth ¶
Depth returns the depth of the reference in the hierarchy.
- 0: zero-value ref (empty LD)
- 1: LD only
- 2: LD/LN
- 3+: LD/LN + path components (depth = 2 + len(Path))
func (Ref) HasPath ¶
HasPath reports whether the reference includes a data object or data attribute path.
func (Ref) IsObject ¶
IsObject reports whether the reference points to a data object or data attribute (LN set with at least one path component).
func (Ref) ObjectReference ¶
ObjectReference returns the reference formatted without the FC bracket suffix.
func (Ref) Parent ¶
Parent returns the parent reference. For a DA reference, this returns the parent DO or LN. Returns false if r is already at the top level (LD-only).
The functional constraint is preserved when the returned parent still refers to a logical node or object path. When the parent is LD-only, the FC is dropped because LD[FC] is not a meaningful IEC 61850 reference shape.
func (Ref) ToMMS ¶
ToMMS converts the reference to MMS domain and item ID.
Calls Ref.Validate before conversion. Requires a valid FC when the reference includes a path.
LN-level refs without FC (e.g., Ref{LD:"LD1", LN:"LLN0"}) produce a bare item ID of "LLN0". This is used for GetNameList and other browse-oriented MMS operations. It is not the normal read/write mapping — MMS read/write at the LN level is a special IEC 61850 convention that returns the complete named-variable subtree. Normal attribute access requires FC-qualified refs.
Examples:
Ref{LD:"LD1", LN:"LLN0"} → domain="LD1", itemID="LLN0"
Ref{LD:"LD1", LN:"LLN0", Path:[]string{"Mod","stVal"}, FC:FCST} → domain="LD1", itemID="LLN0$ST$Mod$stVal"
func (Ref) Validate ¶
Validate checks the structural invariants of the Ref.
Rules:
- LD must be non-empty
- if LN is empty, Path must also be empty
- if LN is empty, FC must also be empty (FC requires at least LN)
- no empty path components
- if FC is non-empty, it must be exactly 2 characters (length check only — unknown FC values are accepted; use FunctionalConstraint.IsValid for semantic validation)
- components must not contain separators (/, ., $, [, ])
func (Ref) WithFC ¶
func (r Ref) WithFC(fc FunctionalConstraint) Ref
WithFC returns a copy of r with the functional constraint set to fc.
type ReferenceError ¶
ReferenceError is a typed error for malformed or invalid IEC 61850 object references.
func (*ReferenceError) Error ¶
func (e *ReferenceError) Error() string
func (*ReferenceError) Unwrap ¶
func (e *ReferenceError) Unwrap() error
type ReportControlBlock ¶
type ReportControlBlock struct {
// Reference is a display-only pseudo-reference derived from the
// MMS item ID by replacing '$' with '.' (e.g. "LD/LLN0.BR.brcb01").
// This is not a proper IEC 61850 object reference because BR/RP
// is a functional constraint, not a path component. Use the LD
// and MMS item ID from the original [Client.GetReportControlBlock]
// call for programmatic access.
Reference string
// Type is BRCB or URCB.
Type RCBType
// RptID is the report identifier.
RptID string
// RptEna indicates whether the report is enabled.
RptEna bool
// DatSet is the data set reference.
DatSet string
// ConfRev is the configuration revision number.
ConfRev uint32
// OptFlds is the optional fields bit mask.
OptFlds OptFlds
// BufTm is the buffer time in milliseconds.
BufTm uint32
// SqNum is the current sequence number.
SqNum uint32
// TrgOps is the trigger options bit mask.
TrgOps TrgOps
// IntgPd is the integrity period in milliseconds.
IntgPd uint32
// GI indicates a general interrogation request.
GI bool
// Resv is the reservation flag (URCB only).
Resv bool
// ResvTms is the reservation time in ms (BRCB only, optional).
ResvTms int32
// EntryID is the entry identifier (BRCB only).
EntryID []byte
// PurgeBuf indicates a purge buffer request (BRCB only).
PurgeBuf bool
// Owner is the client owner identifier (optional, edition 2+).
Owner []byte
}
ReportControlBlock holds the decoded attributes of a report control block read from a server.
type ReportEngine ¶
type ReportEngine struct {
// contains filtered or unexported fields
}
ReportEngine is the server-side runtime report engine. It monitors value changes in the servermodel.ValueStore and generates IEC 61850 InformationReports to connected clients based on RCB configuration (trigger options, optional fields, dataset bindings).
The engine is created by Server.EnableReports and runs until the server is shut down or ReportEngine.Stop is called.
Interoperability note ¶
The report encoding follows IEC 61850-8-1 field ordering (RptID, OptFlds, optional fields by flag order, SubSeqNum, MoreSegments, inclusion bitmap, values, reason codes). However, IEC 61850 report encoding is unforgiving — small ordering or type mismatches can cause decode failures on the receiving side. The encoding has been validated in loopback tests with the go-iec61850 client decoder but should be verified against real devices or libiec61850 before being considered production-ready.
func (*ReportEngine) HandleRCBWrite ¶
func (re *ReportEngine) HandleRCBWrite(ctx context.Context, ldName, rcbItemID, subfield string, val *mms.Value, conn ...*mms.ServerConn) error
HandleRCBWrite is called when a client writes to an RCB subfield. It intercepts RptEna, GI, Resv, and PurgeBuf writes to trigger the appropriate runtime behavior. The optional conn parameter identifies the MMS connection that issued the write, used for URCB connection-scoped delivery.
func (*ReportEngine) NotifyValueChanged ¶
func (re *ReportEngine) NotifyValueChanged(ctx context.Context, storeKey string)
NotifyValueChanged is called when a data attribute value is changed in the ValueStore. It checks all enabled RCBs for relevant triggers and generates reports as needed.
func (*ReportEngine) SetRCBBufMax ¶ added in v1.0.2
func (re *ReportEngine) SetRCBBufMax(ldName, rcbItemID string, max int) bool
SetRCBBufMax sets the maximum buffer capacity for the named BRCB. Returns false if the RCB is not found. Intended for testing; use with caution in production code.
func (*ReportEngine) Stop ¶
func (re *ReportEngine) Stop()
Stop shuts down the report engine, stopping all integrity timers and disabling all RCBs.
type ReportError ¶
ReportError indicates a failure related to report control block operations or report decoding.
func (*ReportError) Error ¶
func (e *ReportError) Error() string
func (*ReportError) Unwrap ¶
func (e *ReportError) Unwrap() error
type ReportIndication ¶
type ReportIndication struct {
// RptID is the report identifier.
RptID string
// OptFlds is the optional fields mask from this report.
OptFlds OptFlds
// SeqNum is the sequence number (present when OptFldSeqNum is set).
SeqNum uint32
// SubSeqNum is the sub-sequence number for segmented reports.
SubSeqNum uint32
// MoreSegments indicates additional report segments follow.
MoreSegments bool
// DatSet is the data set reference (present when OptFldDataSet is set).
DatSet string
// BufOvfl indicates buffer overflow (present when OptFldBufOvfl is set).
BufOvfl bool
// EntryID is the entry identifier (present when OptFldEntryID is set).
EntryID []byte
// ConfRev is the configuration revision (present when OptFldConfRev is set).
ConfRev uint32
// Timestamp is the report timestamp (present when OptFldTimeStamp
// is set). Decoded from UTCTime or BinaryTime depending on the
// server's encoding.
Timestamp time.Time
// Inclusion is a bitmask indicating which data set members are
// included in this report.
Inclusion []bool
// DataReferences contains data references for included members
// (present when OptFldDataRef is set).
DataReferences []string
// Values contains the values for included members, in order of
// inclusion. Only entries where Inclusion[i] is true have values.
Values []*Value
// ReasonCodes contains the reason for inclusion for each included
// member (present when OptFldReasonCode is set).
ReasonCodes []ReasonCode
}
ReportIndication represents a decoded IEC 61850 report received from the server via an InformationReport.
type ReportSubscription ¶
type ReportSubscription struct {
// contains filtered or unexported fields
}
ReportSubscription represents an active subscription to IEC 61850 reports. Reports are delivered to the channel returned by [Reports].
Call ReportSubscription.Close to unsubscribe and release resources. Close is idempotent and safe to call from any goroutine.
func (*ReportSubscription) Close ¶
func (s *ReportSubscription) Close() error
Close terminates the report subscription. It is idempotent and safe to call from any goroutine.
If the subscription was created with lifecycle options (AutoEnable, ReserveURCB), Close performs best-effort remote cleanup: disable the RCB (RptEna=false), then release the URCB reservation. Remote cleanup errors are logged but never prevent local shutdown.
After Close, the [Reports] channel is closed and no further reports are delivered.
func (*ReportSubscription) Reports ¶
func (s *ReportSubscription) Reports() <-chan *ReportIndication
Reports returns a read-only channel that delivers decoded report indications. The channel is closed when the subscription is closed or the client connection is terminated.
type RptMatchMode ¶
type RptMatchMode int
RptMatchMode selects how incoming report IDs are matched against the subscription's RptID pattern.
const ( // RptMatchExact matches the RptID exactly (default). RptMatchExact RptMatchMode = iota // RptMatchGlob uses [path.Match] glob semantics. '*' matches // any characters within a segment, '?' matches one character. RptMatchGlob )
type SCLParseError ¶
SCLParseError indicates a failure during SCL file parsing.
func (*SCLParseError) Error ¶
func (e *SCLParseError) Error() string
func (*SCLParseError) Unwrap ¶
func (e *SCLParseError) Unwrap() error
type Server ¶
type Server struct {
// contains filtered or unexported fields
}
Server is an IEC 61850 MMS server built from an SCL data model.
Stability ¶
The server API is stable as of v1.0.0. It supports variable registration, control operations (direct normal, SBO normal, and SBOw enhanced security with connection-scoped ownership enforcement), runtime report delivery (data-change, quality-change, integrity-period, GI triggers, BRCB replay on re-enable), setting groups (active/edit selection, confirmation, handler callbacks), and journal services (runtime log entry generation with in-memory storage).
Known limitations ¶
- SCL array/count attributes are parsed but not expanded during server model registration. DA elements with count > 1 are registered as scalar variables.
- Enum BTypes are mapped to generic integers (INT8) without stronger enum-type semantics.
- Dataset and report cross-references are validated only within the same logical node. Cross-LN dataset references are not supported.
- Runtime report engine sends URCBs to the enabling connection and broadcasts BRCBs to all connections. Multi-client URCB arbitration and segmented report generation are not yet implemented.
- BRCB buffering is in-memory with configurable depth. There is no persistent buffer storage or replay-on-reconnect.
- Control handlers support SBO ownership enforcement and enhanced-security ctlNum verification, but interlocking, synchrocheck, and command termination are application responsibility via callbacks.
Architecture ¶
The Server wraps a mms.Server and populates its variable registry from an IEC 61850 data model derived from an SCL file. Data attribute values are stored in a thread-safe [ValueStore] that backs the MMS read/write callbacks. Call Server.Close for orderly shutdown of runtime engines when the server is no longer needed.
func NewServer ¶
func NewServer(model *servermodel.Model, opts ServerOptions) (*Server, error)
NewServer creates an IEC 61850 server from the given data model.
The model is typically built via NewServerModelFromSCL. After construction, call Server.Serve or Server.ListenAndServe to accept client connections.
Example ¶
ExampleNewServer demonstrates creating and serving a minimal IEC 61850 server built from an in-process SCL model.
// Build the server model from SCL.
model, err := NewServerModelFromSCL(testServerSCLWithURCB(), "IED1", "")
if err != nil {
log.Fatal(err)
}
// Create the server.
srv, err := NewServer(model, ServerOptions{})
if err != nil {
log.Fatal(err)
}
// Optionally start the report engine.
re := srv.EnableReports()
defer re.Stop()
// Register a custom control handler.
_ = srv.RegisterControl("LD1", "GGIO1.SPCSO1", CtlModelDirectNormal, ControlHandler{
OnOperate: func(ctx context.Context, req ControlRequest) error {
val, _ := req.CtlVal.Bool()
log.Printf("operate: ctlVal=%v", val)
return nil
},
})
// Serve connections (typically via iso.Listen for production use).
ctx := context.Background()
_ = ctx
// In a real program:
// ln, _ := iso.Listen(":102")
// log.Fatal(srv.ListenAndServe(ctx, ln))
func (*Server) Capabilities ¶
func (s *Server) Capabilities() ServiceCapabilities
Capabilities returns a snapshot of which IEC 61850 services are currently active on this server. This is useful for diagnostics and for verifying that all expected services have been enabled before starting to accept connections.
func (*Server) ChangeActiveSettingGroup ¶
ChangeActiveSettingGroup programmatically changes the active setting group for the given LD. This is for server-side use (e.g., operator override). The handler's OnActiveSGChanged callback is invoked.
func (*Server) Close ¶
func (s *Server) Close()
Close performs an orderly shutdown of the server's runtime engines. It stops the report engine (integrity timers, delivery goroutines) and clears references to the journal and setting group engines. Close is idempotent and safe to call multiple times.
Note: Close does not close the underlying MMS server or any active connections. Use context cancellation to stop Server.Serve or Server.ListenAndServe. The journal and setting group engines are stateless (no background goroutines), so they only need reference clearing for garbage collection.
func (*Server) EnableJournals ¶
func (s *Server) EnableJournals(opts ...JournalEngineOption) *JournalEngine
EnableJournals creates and starts the JournalEngine for this server. It scans the model for log definitions, registers journals, and makes the provider available as mms.JournalProvider.
If the MMS server was constructed with a MemoryJournalProvider in [ServerOptions.MMS.JournalProvider], EnableJournals automatically adopts it so that client MMS ReadJournal requests are served from the same data the engine writes to. If no provider was configured, the engine creates one internally. In that case, the engine records entries for programmatic access via JournalEngine.Provider, but client MMS journal reads will not be served (they require the provider to be set at server construction time).
To ensure full client↔server journal support:
jp := iec61850.NewMemoryJournalProvider()
srv, _ := iec61850.NewServer(model, iec61850.ServerOptions{
MMS: mms.ServerOptions{JournalProvider: jp},
})
engine := srv.EnableJournals(iec61850.WithJournalProvider(jp))
func (*Server) EnableReports ¶
func (s *Server) EnableReports() *ReportEngine
EnableReports creates and starts the ReportEngine for this server. It scans all RCBs in the model, creates runtime state for each, and begins monitoring for GI/integrity triggers.
Call this after NewServer and before Server.Serve or Server.ListenAndServe.
func (*Server) EnableSettingGroups ¶
func (s *Server) EnableSettingGroups(handler SettingGroupHandler)
EnableSettingGroups initialises the setting group engine for the server. It scans the server model for SGCB definitions and registers them with the provided handler.
This should be called after NewServer and before accepting connections.
func (*Server) HandleIdentify ¶
func (s *Server) HandleIdentify(id ServerIdentity)
HandleIdentify registers the MMS Identify handler using the given identity. This is called automatically by NewServer when ServerOptions.Identity is set.
func (*Server) HandleStatus ¶
func (s *Server) HandleStatus()
HandleStatus registers a static MMS Status response. The server always reports operational status.
func (*Server) JournalEngine ¶
func (s *Server) JournalEngine() *JournalEngine
JournalEngine returns the journal engine, or nil if journals have not been enabled via Server.EnableJournals.
func (*Server) ListenAndServe ¶
ListenAndServe accepts connections on the given listener and serves each in a new goroutine. This blocks until the context is cancelled or the listener is closed.
Each accepted connection is handled by Server.Serve in its own goroutine, which ensures that connection lifecycle hooks are invoked.
func (*Server) MMS ¶
MMS returns the underlying MMS server for advanced configuration (e.g., registering Identify/Status handlers or a FileProvider).
func (*Server) Model ¶
func (s *Server) Model() *servermodel.Model
Model returns the server's data model. The returned pointer is shared with the server internals. The caller must not modify the model after server creation — doing so may corrupt the MMS variable registry and cause undefined runtime behaviour.
func (*Server) RegisterControl ¶
func (s *Server) RegisterControl(ldName, doRef string, ctlModel CtlModel, handler ControlHandler) error
RegisterControl registers a ControlHandler for the controllable data object identified by ldName and doRef (e.g. "GGIO1.SPCSO1"). The ctlModel determines the expected control flow.
The handler callbacks are invoked from within the MMS write path when a client writes to the Oper, SBO, SBOw, or Cancel subattributes.
Example ¶
ExampleServer_RegisterControl demonstrates registering a direct control.
model, err := NewServerModelFromSCL(testServerSCLWithURCB(), "IED1", "")
if err != nil {
log.Fatal(err)
}
srv, err := NewServer(model, ServerOptions{})
if err != nil {
log.Fatal(err)
}
defer srv.Close()
_ = srv.RegisterControl("LD1", "GGIO1.SPCSO1", CtlModelDirectNormal, ControlHandler{
OnOperate: func(ctx context.Context, req ControlRequest) error {
val, _ := req.CtlVal.Bool()
log.Printf("operate SPCSO1: %v", val)
return nil
},
OnCancel: func(ctx context.Context, req ControlRequest) error {
log.Println("SPCSO1 cancelled")
return nil
},
})
func (*Server) ReportEngine ¶
func (s *Server) ReportEngine() *ReportEngine
ReportEngine returns the report engine, or nil if reports have not been enabled via Server.EnableReports.
func (*Server) Serve ¶
Serve handles a single MMS transport connection. This blocks until the connection is closed or the context is cancelled.
If ServerOptions.OnConnect or ServerOptions.OnDisconnect are configured, OnConnect is called when the transport is accepted (before the MMS association handshake completes), and OnDisconnect is called when the Serve call returns (after the connection is fully closed). This means OnConnect fires even if the association subsequently fails during authentication or handshake.
func (*Server) SetValue ¶
SetValue updates a data attribute value in the store and notifies the report engine (if enabled) of the change. The storeKey follows the format "ldName/itemID" (see servermodel.StoreKey).
This is the primary way to inject process values into a running server and have them trigger reports automatically.
Example ¶
ExampleServer_SetValue demonstrates pushing a data value into the server model, which triggers data-change reports to subscribed clients.
model, err := NewServerModelFromSCL(testServerSCLWithURCB(), "IED1", "")
if err != nil {
log.Fatal(err)
}
srv, err := NewServer(model, ServerOptions{})
if err != nil {
log.Fatal(err)
}
re := srv.EnableReports()
defer re.Stop()
defer srv.Close()
// Push a new value — this triggers a dchg report to subscribed clients.
srv.SetValue(context.Background(), "LD1/LLN0$ST$Mod$stVal", mms.NewInteger(1))
func (*Server) SettingGroupEngine ¶
func (s *Server) SettingGroupEngine() *SettingGroupEngine
SettingGroupEngine returns the setting group engine, or nil if setting groups have not been enabled via Server.EnableSettingGroups.
func (*Server) ValueStore ¶
func (s *Server) ValueStore() *servermodel.ValueStore
ValueStore returns the server's value store for direct value manipulation (e.g., updating data attribute values from process inputs).
When reports are enabled, prefer Server.SetValue which automatically triggers change-detection and report generation.
type ServerIdentity ¶
type ServerIdentity struct {
// Vendor is the vendor/manufacturer name (e.g. "OTFabric").
Vendor string
// Model is the device model or product name.
Model string
// Revision is the firmware or software revision string.
Revision string
}
ServerIdentity describes the IEC 61850 server identity returned by the MMS Identify service. Setting this on ServerOptions automatically registers an Identify handler on the MMS server.
type ServerOptions ¶
type ServerOptions struct {
// Logger, when non-nil, enables structured logging. When
// [ServerOptions.MMS].Logger is also nil, this logger is passed
// through to the underlying [mms.Server]. ISO transport logging
// ([iso.WithLogger]) is independent and is not set from here.
Logger *slog.Logger
// Identity, when non-nil, registers the MMS Identify handler so
// that clients can query vendor/model/revision. Without this,
// Identify requests are rejected with service-unsupported.
Identity *ServerIdentity
// FileProvider, when non-nil, enables MMS file services
// (FileOpen, FileRead, FileClose, FileDelete, FileDirectory).
// This is a convenience field; it is equivalent to setting
// MMS.FileProvider.
FileProvider mms.FileProvider
// Authenticate, when non-nil, is called during association
// establishment to accept or reject peers. This is a convenience
// field; it is equivalent to setting MMS.Authenticate.
Authenticate mms.Authenticator
// OnConnect, when non-nil, is called when a new transport
// connection is accepted, before the MMS association handshake.
// This fires even if the association subsequently fails.
OnConnect func(ConnectionEvent)
// OnDisconnect, when non-nil, is called when a transport
// connection's [Server.Serve] call returns (the connection is
// fully closed regardless of how it ended).
OnDisconnect func(ConnectionEvent)
// MMS holds the underlying MMS server options. Fields set here
// take precedence over convenience fields above (FileProvider,
// Authenticate) when both are set.
MMS mms.ServerOptions
}
ServerOptions configures the IEC 61850 server.
type ServiceCapabilities ¶
type ServiceCapabilities struct {
// Variables is always true (the server always registers variables).
Variables bool
// DataSets is true when the model contains dataset definitions.
// This is a model-level property, not a runtime toggle.
DataSets bool
// Reports is true when [Server.EnableReports] has been called
// (runtime-enabled, not just configured in the model).
Reports bool
// Controls is true when at least one control has been registered
// via [Server.RegisterControl] (runtime-enabled).
Controls bool
// SettingGroups is true when [Server.EnableSettingGroups] has been
// called (runtime-enabled, not just present in the model).
SettingGroups bool
// Journals is true when [Server.EnableJournals] has been called
// (runtime-enabled, not just present in the model).
Journals bool
// Files is true when a [mms.FileProvider] was configured.
Files bool
// Identify is true when server identity was configured.
Identify bool
}
ServiceCapabilities reports which IEC 61850 server-side services are active on this server instance.
There is a distinction between "configured" (the model contains the necessary definitions) and "runtime-enabled" (the application called the Enable method). For reports, setting groups, and journals the boolean reflects runtime enablement, not merely model presence. Use this to verify that all expected services have been enabled before accepting connections.
func (ServiceCapabilities) String ¶
func (c ServiceCapabilities) String() string
String returns a human-readable summary of enabled services, useful for diagnostics and startup logging.
type SettingGroupEngine ¶
type SettingGroupEngine struct {
// contains filtered or unexported fields
}
SettingGroupEngine manages server-side setting group control blocks. It intercepts SGCB writes (ActSG, EditSG, CnfEdit) and enforces the setting group lifecycle.
Interoperability note ¶
This implementation covers the core setting group workflow (active selection, edit reservation, confirm/commit). Reservation timeouts, multi-connection ownership tracking, and persistent setting group storage are not yet implemented. These are documented in KNOWN_LIMITATIONS.md.
func (*SettingGroupEngine) GetActiveSettingGroup ¶
func (e *SettingGroupEngine) GetActiveSettingGroup(ldName string) uint8
GetActiveSettingGroup returns the currently active setting group for the given LD. Returns 0 if no SGCB is registered.
func (*SettingGroupEngine) GetEditSettingGroup ¶
func (e *SettingGroupEngine) GetEditSettingGroup(ldName string) uint8
GetEditSettingGroup returns the setting group currently under edit for the given LD. Returns 0 if no edit session is active.
func (*SettingGroupEngine) HandleSGCBWrite ¶
func (e *SettingGroupEngine) HandleSGCBWrite(ctx context.Context, ldName, subfield string, val *mms.Value) error
HandleSGCBWrite intercepts writes to SGCB subfields and enforces setting group semantics. Returns nil if the write is handled (accepted or rejected with an MMS error); returns an error to propagate to the MMS layer as a write failure.
Supported subfields: ActSG, EditSG, CnfEdit.
type SettingGroupHandler ¶
type SettingGroupHandler struct {
// OnActiveSGChanged is called when a client selects a new active
// setting group. Return a non-nil error to reject the activation.
// The newSG is 1-based.
OnActiveSGChanged func(ctx context.Context, ld string, newSG uint8) error
// OnEditSGSelected is called when a client selects a group for
// editing. Return a non-nil error to reject the selection (e.g.,
// if another edit session is in progress from a different source).
OnEditSGSelected func(ctx context.Context, ld string, editSG uint8) error
// OnConfirmEdit is called when a client confirms an edit session.
// The application should persist or apply the edited values.
// Return a non-nil error to reject the confirmation.
OnConfirmEdit func(ctx context.Context, ld string, editSG uint8) error
}
SettingGroupHandler provides application callbacks for setting group operations. All callbacks are optional; nil callbacks accept the operation unconditionally.
type SettingGroupInfo ¶
type SettingGroupInfo struct {
// NumOfSGs is the total number of setting groups (1-based).
NumOfSGs uint8
// ActSG is the currently active setting group number (1-based).
ActSG uint8
// EditSG is the group currently selected for editing (0 = none).
EditSG uint8
// CnfEdit is true when the server has confirmed the edit.
CnfEdit bool
// ResvTms is the reservation timeout in seconds (0 = no timeout).
// This field is optional; not all servers expose it.
ResvTms uint16
}
SettingGroupInfo holds the state of a Setting Group Control Block (SGCB) as defined in IEC 61850-7-2 §16.
The SGCB is a special control block under LLN0 at FC=SP that governs multiple setting groups. Each setting group provides a complete set of SE-constrained data attribute values; one group is "active" (read by clients via FC=SG) and one may be under edit (written via FC=SE).
MMS mapping ¶
The SGCB is mapped to MMS as "LLN0$SP$SGCB" with the following structure members in order:
[0] NumOfSGs (Unsigned8) — total number of setting groups [1] ActSG (Unsigned8) — currently active setting group [2] EditSG (Unsigned8) — currently selected edit group (0 = none) [3] CnfEdit (BOOLEAN) — confirm-edit flag [4] LActTm (UTCTime) — last activation timestamp [5] ResvTms (Unsigned16) — reservation timeout in seconds (optional)
type StrictnessOptions ¶
type StrictnessOptions struct {
// RejectUnknownFC, when true, causes browse and tree operations
// to return an error when an item ID contains a functional
// constraint that is not in the IEC 61850 standard set. When
// false (the default), unknown FCs are silently accepted and
// stored as-is.
RejectUnknownFC bool
// VerifyReportCandidates, when true, causes [Client.ListReports]
// to read and decode each heuristic RCB candidate, excluding
// items that fail to decode as valid RCB structures. When false
// (the default), discovery uses the fast naming-heuristic only.
VerifyReportCandidates bool
}
StrictnessOptions controls how strictly the client validates server responses and reference formats. The zero value uses pragmatic defaults suitable for interop with real-world IEC 61850 servers.
type SubscribeReportOptions ¶
type SubscribeReportOptions struct {
// QueueSize is the buffer size for the report channel. Defaults
// to 64 if zero.
QueueSize int
// OverflowPolicy controls behavior when the channel is full.
// Default is [OverflowDropNewest].
OverflowPolicy OverflowPolicy
// OnOverflow is called when a report is dropped due to overflow
// (only used with [OverflowCallback]). Called from the dispatch
// goroutine — must not block.
OnOverflow func(*ReportIndication)
// MatchMode selects how the RptID is matched. Default is exact.
MatchMode RptMatchMode
// CloneReports, when true, delivers a shallow copy of each
// [ReportIndication] to this subscription instead of sharing
// a pointer with other subscriptions. This allows safe mutation
// of Values, DataReferences, and ReasonCodes slices without
// affecting other subscribers.
CloneReports bool
// AutoEnable, when true, enables the RCB (RptEna=true) as part
// of subscribing. Requires LD and RCBItemID to be set.
AutoEnable bool
// GIOnSubscribe, when true, triggers a General Interrogation
// after enabling. Requires AutoEnable or that the RCB is
// already enabled.
GIOnSubscribe bool
// ReserveURCB, when true, reserves the URCB before enabling.
// Only meaningful for unbuffered RCBs.
ReserveURCB bool
// LD is the logical device for lifecycle operations
// (AutoEnable, GIOnSubscribe, ReserveURCB). Required when
// any lifecycle option is set.
LD string
// RCBItemID is the RCB MMS item ID for lifecycle operations.
// Required when any lifecycle option is set.
RCBItemID string
}
SubscribeReportOptions configures a report subscription.
type TimeQuality ¶
type TimeQuality struct {
// LeapSecondKnown indicates whether leap second information
// is known (bit 7 of quality byte).
LeapSecondKnown bool
// ClockFailure indicates a clock hardware failure
// (bit 6 of quality byte).
ClockFailure bool
// ClockNotSynchronized indicates the clock is not synchronized
// to an external time source (bit 5 of quality byte).
ClockNotSynchronized bool
// TimeAccuracy is the number of significant bits in the
// fraction-of-second field (bits 0–4, range 0–31). Higher
// values indicate better precision. Zero means unspecified.
TimeAccuracy int
}
TimeQuality represents the time quality byte of an IEC 61850 timestamp.
type Timestamp ¶
type Timestamp struct {
// Time is the timestamp value.
Time time.Time
// Quality contains time quality flags. Zero-valued when
// decoded from go-mms (time quality not yet exposed by
// the MMS layer).
Quality TimeQuality
}
Timestamp represents an IEC 61850 timestamp (UTCTime) with optional time quality information.
The IEC 61850 timestamp is an 8-byte structure:
- bytes 0–3: seconds since Unix epoch
- bytes 4–6: fraction of second (24-bit binary fraction)
- byte 7: time quality
EncodeTimestamp preserves the full TimeQuality in the UTCTimeQuality byte. DecodeTimestamp quality fidelity depends on go-mms exposing UTCTimeQuality(); if the MMS layer does not populate the quality byte, decoded quality will be zero-valued.
func DecodeTimestamp ¶
DecodeTimestamp decodes an IEC 61850 timestamp from an MMS UTCTime value. Returns a DecodeError if the value is not a UTCTime.
Time quality flags (leap second awareness, clock failure, clock synchronization, sub-second accuracy) are decoded from the go-mms UTCTimeQuality byte.
type TreeOptions ¶
type TreeOptions struct {
// LDFilter, when non-empty, restricts the tree to a single
// logical device matching this name.
LDFilter string
// MaxDepth limits how deep the tree is built. Zero means
// unlimited. Depth counts model-hierarchy levels starting at
// the logical device level (consistent with [Ref.Depth]):
// 1 = LD nodes only
// 2 = LD + LN nodes
// 3 = LD + LN + first DO level
// 4+ = deeper data attributes
//
// Note: the returned root node is a synthetic container that
// sits outside the depth model. Its children are the LD nodes
// (depth 1). MaxDepth=1 therefore returns a root whose
// children are bare LD nodes with no further expansion.
MaxDepth int
// IncludeFCs annotates tree nodes with functional constraint
// information. When true, each leaf/intermediate node will
// have its FCs field populated with all FCs observed for that
// node in the MMS item IDs. The single FC field is set when
// only one FC applies.
IncludeFCs bool
}
TreeOptions configures the tree-building behavior for Client.TreeWithOptions.
type TrgOps ¶
type TrgOps uint8
TrgOps represents the trigger options bit mask of a report control block.
const ( TrgOpDataChanged TrgOps = 1 << 0 // Data change TrgOpQualityChanged TrgOps = 1 << 1 // Quality change TrgOpDataUpdate TrgOps = 1 << 2 // Data update TrgOpIntegrity TrgOps = 1 << 3 // Integrity period TrgOpGI TrgOps = 1 << 4 // General interrogation )
Trigger option flags for TrgOps.
type Validity ¶
type Validity int
Validity represents the validity portion of an IEC 61850 quality.
const ( // ValidityGood indicates the value is valid. ValidityGood Validity = 0 // ValidityReserved is reserved for future use. ValidityReserved Validity = 1 // ValidityInvalid indicates the value is not valid. ValidityInvalid Validity = 2 // ValidityQuestionable indicates the value may not be valid. ValidityQuestionable Validity = 3 )
type Value ¶
type Value struct {
// contains filtered or unexported fields
}
Value wraps an mms.Value with IEC 61850 semantic accessors.
Value provides typed accessor methods that return errors instead of ok booleans, and IEC 61850-specific decoders for Quality and Timestamp. Use Value.MMS to access the underlying MMS value when needed.
Values are created by NewValue, the constructor functions (BoolValue, IntValue, etc.), or returned from read operations.
func ArrayValue ¶
ArrayValue creates a Value from a slice of element Values with validation. Returns an error if any element is nil.
Use UnsafeArrayValue for the unchecked fast path when all elements are guaranteed non-nil.
func OctetStringValue ¶
OctetStringValue creates a Value from a byte slice.
func QualityValue ¶
QualityValue creates a Value from a Quality.
func StringValue ¶
StringValue creates a Value from a string (MMS VisibleString).
func StructureValue ¶
StructureValue creates a Value from a slice of element Values with validation. Returns an error if any element is nil.
Use UnsafeStructureValue for the unchecked fast path when all elements are guaranteed non-nil.
func TimestampValue ¶
TimestampValue creates a Value from a Timestamp.
func UnsafeArrayValue ¶
UnsafeArrayValue creates a Value from a slice of element Values without nil-checking. Nil elements produce a malformed MMS array that will fail encoding. Prefer ArrayValue unless performance requires skipping validation.
func UnsafeStructureValue ¶
UnsafeStructureValue creates a Value from a slice of element Values without nil-checking. Nil elements produce a malformed MMS structure that will fail encoding. Prefer StructureValue unless performance requires skipping validation.
func (*Value) BitString ¶
BitString returns the raw bit string bytes. The returned slice may alias the underlying MMS value memory. Copy it if ownership or later mutation is required. Returns a DecodeError if the value is nil or not a bit string.
func (*Value) Bool ¶
Bool returns the value as a bool. Returns a DecodeError if the value is nil or not a boolean.
func (*Value) Elements ¶
Elements returns the structure or array elements as Values. Use Value.IsStructure and Value.IsArray to determine which container kind the value holds before calling this method. Returns a DecodeError if the value is nil or not a structure or array.
func (*Value) Float32 ¶
Float32 returns the value as a float32. Returns a DecodeError if the value is nil or not a float.
func (*Value) Float64 ¶
Float64 returns the value as a float64. Returns a DecodeError if the value is nil or not a float.
func (*Value) Int32 ¶
Int32 returns the value as an int32. Returns a DecodeError if the value is nil or not an integer.
func (*Value) Int64 ¶
Int64 returns the value as an int64. Returns a DecodeError if the value is nil or not an integer.
func (*Value) IsStructure ¶
IsStructure reports whether the value is an MMS structure.
func (*Value) MMS ¶
MMS returns the underlying mms.Value. This is the escape hatch for operations not covered by the IEC 61850 typed accessors.
func (*Value) MmsString ¶
MmsString returns the value as a string (MMS MmsString / UTF-8). Returns a DecodeError if the value is nil or not an MMS string.
func (*Value) OctetString ¶
OctetString returns the value as a byte slice. The returned slice may alias the underlying MMS value memory. Copy it if ownership or later mutation is required. Returns a DecodeError if the value is nil or not an octet string.
func (*Value) Quality ¶
Quality decodes the value as an IEC 61850 quality bit string. Returns a DecodeError if the value is nil or not a 13-bit bit string.
func (*Value) Timestamp ¶
Timestamp decodes the value as an IEC 61850 timestamp. Returns a DecodeError if the value is nil or not a UTCTime.
func (*Value) Type ¶
Type returns the MMS value type. Returns mms.ValueTypeDataAccessError when the Value or its underlying MMS value is nil.
func (*Value) Uint32 ¶
Uint32 returns the value as a uint32. Returns a DecodeError if the value is nil or not an unsigned integer.
func (*Value) Uint64 ¶
Uint64 returns the value as a uint64. Returns a DecodeError if the value is nil or not an unsigned integer.
func (*Value) VisibleString ¶
VisibleString returns the value as a string (MMS VisibleString). Returns a DecodeError if the value is nil or not a visible string.
type WriteRequest ¶
type WriteRequest struct {
// Ref is the target reference. Must include LD, LN, FC,
// and at least one path component.
Ref Ref
// Value is the MMS value to write.
Value *mms.Value
}
WriteRequest specifies a single variable to write as part of a bulk write operation.
type WriteResult ¶
type WriteResult struct {
// Ref is the reference that was written.
Ref Ref
// Success is true if the write was accepted by the server.
Success bool
// Err is the per-item error, if any.
Err error
}
WriteResult holds the outcome of writing a single variable as part of a bulk write operation.
Source Files
¶
- browse.go
- bulk.go
- cache.go
- client.go
- control.go
- control_server.go
- control_types.go
- dataset.go
- doc.go
- errors.go
- fc.go
- file.go
- journal.go
- journal_engine.go
- journal_provider.go
- logging.go
- model.go
- options.go
- quality.go
- read.go
- ref.go
- report.go
- report_engine.go
- server.go
- server_services.go
- setting_groups.go
- setting_groups_server.go
- timestamp.go
- values.go
- write.go
Directories
¶
| Path | Synopsis |
|---|---|
|
examples
|
|
|
basic-client
command
Command basic-client demonstrates connecting to an IEC 61850 server, listing logical devices and nodes, and reading the first browsed data attribute.
|
Command basic-client demonstrates connecting to an IEC 61850 server, listing logical devices and nodes, and reading the first browsed data attribute. |
|
browse-tree
command
Command browse-tree demonstrates building and printing the IEC 61850 model tree from a server, optionally with FC annotations.
|
Command browse-tree demonstrates building and printing the IEC 61850 model tree from a server, optionally with FC annotations. |
|
control
command
Command control demonstrates IEC 61850 control operations: reading the control model, performing direct-operate, and select-before-operate workflows.
|
Command control demonstrates IEC 61850 control operations: reading the control model, performing direct-operate, and select-before-operate workflows. |
|
files
command
Command files demonstrates listing and reading files from an IEC 61850 server.
|
Command files demonstrates listing and reading files from an IEC 61850 server. |
|
ied-client
command
Command ied-client is an end-to-end example of how a production IEC 61850 client application is structured using go-iec61850.
|
Command ied-client is an end-to-end example of how a production IEC 61850 client application is structured using go-iec61850. |
|
ied-server
command
Command ied-server is an end-to-end example of how a production IEC 61850 server application is structured using go-iec61850.
|
Command ied-server is an end-to-end example of how a production IEC 61850 server application is structured using go-iec61850. |
|
reports
command
Command reports demonstrates subscribing to an IEC 61850 buffered report and printing incoming indications.
|
Command reports demonstrates subscribing to an IEC 61850 buffered report and printing incoming indications. |
|
internal
|
|
|
mapping
Package mapping provides internal helpers for translating between MMS named variables and IEC 61850 model structure.
|
Package mapping provides internal helpers for translating between MMS named variables and IEC 61850 model structure. |
|
sclindex
Package sclindex is reserved for centralizing SCL DataTypeTemplates lookup and cycle-detection logic that is currently duplicated across the servermodel and (future) client-side model expansion packages.
|
Package sclindex is reserved for centralizing SCL DataTypeTemplates lookup and cycle-detection logic that is currently duplicated across the servermodel and (future) client-side model expansion packages. |
|
servermodel
Package servermodel defines the IEC 61850 server-side data model.
|
Package servermodel defines the IEC 61850 server-side data model. |
|
Package scl provides parsing and inspection of IEC 61850 SCL (Substation Configuration Language) files.
|
Package scl provides parsing and inspection of IEC 61850 SCL (Substation Configuration Language) files. |
|
cmd/sclgen
command
Command sclgen generates internal Go types from IEC 61850 SCL XSD schemas.
|
Command sclgen generates internal Go types from IEC 61850 SCL XSD schemas. |
|
cmd/sclparse
command
Command sclparse inspects, validates, and summarizes IEC 61850 SCL files.
|
Command sclparse inspects, validates, and summarizes IEC 61850 SCL files. |
|
index
Package index provides a shared, indexed view of a parsed SCL model.
|
Package index provides a shared, indexed view of a parsed SCL model. |
|
internal/genir
Package genir provides the intermediate representation for the SCL code generator.
|
Package genir provides the intermediate representation for the SCL code generator. |
|
internal/raw/v17
Package v17 contains generated raw XML types for IEC 61850 SCL schema version v17.
|
Package v17 contains generated raw XML types for IEC 61850 SCL schema version v17. |
|
internal/raw/v2007b
Package v2007b contains generated raw XML types for IEC 61850 SCL schema version v2007b.
|
Package v2007b contains generated raw XML types for IEC 61850 SCL schema version v2007b. |
|
internal/raw/v2007b4
Package v2007b4 contains generated raw XML types for IEC 61850 SCL schema version v2007b4.
|
Package v2007b4 contains generated raw XML types for IEC 61850 SCL schema version v2007b4. |
|
internal/raw/v2007c5
Package v2007c5 contains generated raw XML types for IEC 61850 SCL schema version v2007c5.
|
Package v2007c5 contains generated raw XML types for IEC 61850 SCL schema version v2007c5. |
|
validate
Package validate provides semantic validation of a parsed SCL model.
|
Package validate provides semantic validation of a parsed SCL model. |