synchrophasor

package module
v0.0.0-...-cfadfad Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 25, 2025 License: GPL-3.0 Imports: 12 Imported by: 0

README

synchrophasor

Go implementation of IEEE C37.118-2011 protocol for synchrophasor data transfer.

⚠️ IMPORTANT DISCLAIMER

THIS IS A PROOF OF CONCEPT ONLY!

This library is highly experimental, unstable, and NOT intended for production use. It has not been thoroughly tested or validated. If it works at all, consider yourself lucky.

DO NOT USE THIS LIBRARY IN ANY REAL-WORLD APPLICATION, especially not in critical infrastructure, power systems, or any environment where failure could result in damage, injury, or financial loss.

The author assumes NO responsibility for any consequences arising from the use of this software. By using this library, you acknowledge that you do so entirely at your own risk.

About

This library is a Go port of Open-C37.118 by Massimiliano "marsolla" Marsolla (original C implementation, GPL-3.0) and provides PMU (Phasor Measurement Unit) and PDC (Phasor Data Concentrator) implementations.

Test data from pypmu by iicsys (BSD-3-Clause).

Installation

go get github.com/JSchlarb/synchrophasor

or via helm

helm upgrade --install -n pmu-simulator --create-namespace pmu-simulator  oci://ghcr.io/jschlarb/synchrophasor/helm/pmu-simulator

Quick Start

PMU Server
import "github.com/JSchlarb/synchrophasor"

// Create and configure a PMU
pmu := synchrophasor.NewPMU()
station := synchrophasor.NewPMUStation("Station1", 1, false, true, true, true)
station.AddPhasor("VA", 915527, synchrophasor.PhunitVoltage)
// ... add more channels ...

pmu.Config2.AddPMUStation(station)
pmu.Start("0.0.0.0:4712")
PDC Client
pdc := synchrophasor.NewPDC(1)
err := pdc.Connect("localhost:4712")
config, err := pdc.GetConfig(2)
pdc.Start() // Start receiving data

Examples

See the examples/ directory for other implementations:

  • pmu-server/ - Simple PMU server
  • pdc-client/ - Simple PDC client implementation

License

This project is licensed under the GNU General Public License v3.0 - see the LICENSE file for details.

Acknowledgments

Documentation

Overview

Package synchrophasor implements IEEE C37.118-2011 protocol for synchrophasor data transfer

Index

Constants

View Source
const (
	FrameTypeData   = 0
	FrameTypeHeader = 1
	FrameTypeCfg1   = 2
	FrameTypeCfg2   = 3
	FrameTypeCmd    = 4
	FrameTypeCfg3   = 5
)

Frame type constants

View Source
const (
	SyncAA   = 0xAA
	SyncData = 0x01
	SyncHdr  = 0x11
	SyncCfg1 = 0x21
	SyncCfg2 = 0x31
	SyncCmd  = 0x41
	SyncCfg3 = 0x51
)

Sync byte constants

View Source
const (
	CmdStop   = 0x01
	CmdStart  = 0x02
	CmdHeader = 0x03
	CmdCfg1   = 0x04
	CmdCfg2   = 0x05
	CmdCfg3   = 0x06
	CmdExt    = 0x08
)

Command codes

View Source
const (
	FreqNom60Hz = 0
	FreqNom50Hz = 1
)

Nominal frequency constants

View Source
const (
	PhunitVoltage = 0
	PhunitCurrent = 1
)

Phasor unit types

View Source
const (
	AnunitPow  = 0
	AnunitRMS  = 1
	AnunitPeak = 2
)

Analog unit types

Variables

View Source
var (
	ErrInvalidFrame     = errors.New("invalid frame")
	ErrCRCFailed        = errors.New("CRC check failed")
	ErrInvalidParameter = errors.New("invalid parameter")
	ErrInvalidSize      = errors.New("invalid size")
	ErrNotImpl          = errors.New("function not implemented")
)

Custom error types

Functions

func CalcCRC

func CalcCRC(data []byte) uint16

CalcCRC calculates CRC-CCITT for the given data

func UnpackFrame

func UnpackFrame(data []byte, cfg *ConfigFrame) (interface{}, error)

UnpackFrame unpacks any frame type from bytes

Types

type C37118

type C37118 struct {
	Sync      uint16
	FrameSize uint16
	IDCode    uint16
	SOC       uint32
	FracSec   uint32
	CHK       uint16
}

C37118 is the base structure for all frame types

func (*C37118) SetTime

func (c *C37118) SetTime(soc *uint32, fracSec *uint32)

SetTime sets SOC and FracSec, calculating them if not provided

func (*C37118) SetTimeWithQuality

func (c *C37118) SetTimeWithQuality(
	soc uint32, frSeconds uint32, leapDir string, leapOcc bool, leapPen bool, timeQuality uint8)

SetTimeWithQuality sets SOC and FracSec with specific parameters

type CommandFrame

type CommandFrame struct {
	C37118
	CMD        uint16
	ExtraFrame []byte
}

CommandFrame represents a command frame

func NewCommandFrame

func NewCommandFrame() *CommandFrame

NewCommandFrame creates a new command frame

func (*CommandFrame) Pack

func (c *CommandFrame) Pack() ([]byte, error)

Pack converts command frame to bytes

func (*CommandFrame) Unpack

func (c *CommandFrame) Unpack(data []byte) error

Unpack parses bytes into command frame

type Config1Frame

type Config1Frame struct {
	ConfigFrame
}

Config1Frame represents a configuration frame version 1, extending the base ConfigFrame type.

func NewConfig1Frame

func NewConfig1Frame() *Config1Frame

NewConfig1Frame creates a new configuration frame version 1

type ConfigFrame

type ConfigFrame struct {
	C37118
	TimeBase       uint32
	NumPMU         uint16
	DataRate       int16
	PMUStationList []*PMUStation
}

ConfigFrame represents a configuration frame

func NewConfigFrame

func NewConfigFrame() *ConfigFrame

NewConfigFrame creates a new configuration frame

func (*ConfigFrame) AddPMUStation

func (c *ConfigFrame) AddPMUStation(pmu *PMUStation)

AddPMUStation adds a PMU station to the configuration

func (*ConfigFrame) GetPMUStationByIDCode

func (c *ConfigFrame) GetPMUStationByIDCode(idCode uint16) *PMUStation

GetPMUStationByIDCode returns PMU station by ID code

func (*ConfigFrame) Pack

func (c *ConfigFrame) Pack() ([]byte, error)

Pack converts configuration frame to bytes

func (*ConfigFrame) Unpack

func (c *ConfigFrame) Unpack(data []byte) error

Unpack parses bytes into configuration frame

type DataFrame

type DataFrame struct {
	C37118
	AssociatedConfig *ConfigFrame
}

DataFrame represents a data frame

func NewDataFrame

func NewDataFrame(cfg *ConfigFrame) *DataFrame

NewDataFrame creates a new data frame

func (*DataFrame) GetMeasurements

func (d *DataFrame) GetMeasurements() map[string]interface{}

GetMeasurements returns the measurements in a structured format

func (*DataFrame) Pack

func (d *DataFrame) Pack() ([]byte, error)

Pack converts data frame to bytes

func (*DataFrame) Unpack

func (d *DataFrame) Unpack(data []byte) error

Unpack parses bytes into data frame

type FrameType

type FrameType int

FrameType represents the type of frame

func GetFrameType

func GetFrameType(data []byte) (FrameType, error)

GetFrameType extracts frame type from byte data

type HeaderFrame

type HeaderFrame struct {
	C37118
	Data string
}

HeaderFrame represents a header frame

func NewHeaderFrame

func NewHeaderFrame(idCode uint16, info string) *HeaderFrame

NewHeaderFrame creates a new header frame

func (*HeaderFrame) Pack

func (h *HeaderFrame) Pack() ([]byte, error)

Pack converts header frame to bytes

func (*HeaderFrame) Unpack

func (h *HeaderFrame) Unpack(data []byte) error

Unpack parses bytes into header frame

type MetricsRecorder

type MetricsRecorder interface {
	RecordClientConnected()
	RecordClientDisconnected()
	RecordCommand(cmdType string)
	RecordDataFrameSent(size int)
	RecordConfigFrameSent(size int)
	RecordHeaderFrameSent(size int)
	RecordBytesReceived(size int)
	RecordFrameError(errorType string)
	UpdateDataFrameRate(rate float64)
}

MetricsRecorder is an interface for tracking various metrics related to client connections and data processing. RecordClientConnected logs a new client connection. RecordClientDisconnected logs a client disconnection. RecordCommand tracks the type of command being processed. RecordDataFrameSent tracks the size of data frames sent out. RecordConfigFrameSent tracks the size of configuration frames sent out. RecordHeaderFrameSent tracks the size of header frames sent out. RecordBytesReceived logs the size of data received. RecordFrameError tracks the type of frame error encountered. UpdateDataFrameRate updates the rate of data frame processing.

type PDC

type PDC struct {
	Socket     net.Conn
	IDCode     uint16
	PMUConfig1 *Config1Frame
	PMUConfig2 *ConfigFrame
	PMUHeader  *HeaderFrame
	Buffer     []byte
}

PDC represents a PDC client

func NewPDC

func NewPDC(idCode uint16) *PDC

NewPDC creates a new PDC instance

func (*PDC) Connect

func (p *PDC) Connect(address string) error

Connect connects to a PMU

func (*PDC) Disconnect

func (p *PDC) Disconnect()

Disconnect closes the connection

func (*PDC) GetConfig

func (p *PDC) GetConfig(version int) (*ConfigFrame, error)

GetConfig requests configuration frame

func (*PDC) GetHeader

func (p *PDC) GetHeader() (*HeaderFrame, error)

GetHeader requests header frame

func (*PDC) ReadFrame

func (p *PDC) ReadFrame() (interface{}, error)

ReadFrame reads a frame from the socket

func (*PDC) SendCommand

func (p *PDC) SendCommand(cmdCode uint16) error

SendCommand sends a command to PMU

func (*PDC) Start

func (p *PDC) Start() error

Start requests PMU to start sending data

func (*PDC) Stop

func (p *PDC) Stop() error

Stop requests PMU to stop sending data

type PMU

type PMU struct {
	Config1      *Config1Frame
	Config2      *ConfigFrame
	Header       *HeaderFrame
	DataRate     int16
	Socket       net.Listener
	Clients      []net.Conn
	ClientsMutex sync.Mutex
	Running      bool
	SendData     map[net.Conn]bool
	SendDataMux  sync.Mutex
	// contains filtered or unexported fields
}

PMU represents a PMU server

func NewPMU

func NewPMU() *PMU

NewPMU creates a new PMU instance

func (*PMU) LogConfiguration

func (p *PMU) LogConfiguration()

LogConfiguration logs the complete PMU configuration

func (*PMU) SetLogger

func (p *PMU) SetLogger(logger *log.Logger)

SetLogger sets the logger for the PMU

func (*PMU) SetMetrics

func (p *PMU) SetMetrics(m MetricsRecorder)

SetMetrics sets the metrics recorder for the PMU

func (*PMU) Start

func (p *PMU) Start(address string) error

Start starts the PMU server

func (*PMU) Stop

func (p *PMU) Stop()

Stop stops the PMU server

type PMUStation

type PMUStation struct {
	C37118
	STN           string
	Format        uint16
	Phnmr         uint16
	Annmr         uint16
	Dgnmr         uint16
	CHNAMPhasor   []string
	CHNAMAnalog   []string
	CHNAMDigital  []string
	Phunit        []uint32
	Anunit        []uint32
	Dgunit        []uint32
	Fnom          uint16
	CfgCnt        uint16
	Stat          uint16
	PhasorValues  []complex128
	AnalogValues  []float32
	DigitalValues [][]bool
	Freq          float32
	DFreq         float32
}

PMUStation represents a PMU station configuration

func NewPMUStation

func NewPMUStation(name string, idCode uint16, freqType, analogType, phasorType, coordType bool) *PMUStation

NewPMUStation creates a new PMU station with given parameters

func (*PMUStation) AddAnalog

func (p *PMUStation) AddAnalog(name string, factor uint32, anType uint8)

AddAnalog adds an analog channel

func (*PMUStation) AddDigital

func (p *PMUStation) AddDigital(names []string, normal, valid uint16)

AddDigital adds a digital channel with 16 bits

func (*PMUStation) AddPhasor

func (p *PMUStation) AddPhasor(name string, factor uint32, phType uint8)

AddPhasor adds a phasor channel

func (*PMUStation) FormatAnalogType

func (p *PMUStation) FormatAnalogType() bool

FormatAnalogType returns true if analog format is float

func (*PMUStation) FormatCoord

func (p *PMUStation) FormatCoord() bool

FormatCoord returns true if phasor format is polar

func (*PMUStation) FormatFreqType

func (p *PMUStation) FormatFreqType() bool

FormatFreqType returns true if freq/dfreq format is float

func (*PMUStation) FormatPhasorType

func (p *PMUStation) FormatPhasorType() bool

FormatPhasorType returns true if phasor format is float

func (*PMUStation) GetNominalFrequency

func (p *PMUStation) GetNominalFrequency() float32

GetNominalFrequency returns the nominal frequency based on Fnom setting

func (*PMUStation) GetPhasorFactor

func (p *PMUStation) GetPhasorFactor(index int) uint32

GetPhasorFactor returns the factor for a phasor channel

func (*PMUStation) SetFormat

func (p *PMUStation) SetFormat(freqType, analogType, phasorType, coordType bool)

SetFormat sets the format word

Directories

Path Synopsis
examples
pdc-client command
example pdc client
example pdc client
pmu-server command
example simulator
example simulator

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL