Documentation
¶
Overview ¶
Package controller implements a PROFINET IO-Controller (conformance class A, RT_CLASS_1/2): it finds its devices by station name with DCP, optionally assigns their IP address, establishes an application relationship with each, parameterizes it, exchanges cyclic IO data, acknowledges alarms, reads and writes records and re-establishes the AR after a failure.
Each device runs its own lifecycle on its own goroutine; a failure of one does not affect the others. Process data is exchanged through Device.SetOutput and Device.Input.
Index ¶
- func CanTransition(from, to State) bool
- type ARInfo
- type AlarmEvent
- type Config
- type Controller
- func (c *Controller) AddDevice(cfg DeviceConfig) (*Device, error)
- func (c *Controller) Close() error
- func (c *Controller) DCP() *dcp.Client
- func (c *Controller) Device(name string) (*Device, bool)
- func (c *Controller) Devices() []*Device
- func (c *Controller) ObjectUUID() rpc.UUID
- func (c *Controller) RPC() *rpc.Client
- type Device
- func (d *Device) AR() (ARInfo, bool)
- func (d *Device) ARUUID() rpc.UUID
- func (d *Device) Close() error
- func (d *Device) ConsumerStatus(slot, subslot uint16) (uint8, bool)
- func (d *Device) IP() dcp.IPSuite
- func (d *Device) Input(slot, subslot uint16) (data []byte, iops uint8, ok bool)
- func (d *Device) MAC() ethernet.MAC
- func (d *Device) ModuleDiff() *pnio.ModuleDiffBlock
- func (d *Device) Name() string
- func (d *Device) ReadDiagnosis(ctx context.Context) ([]pnio.DiagnosisData, error)
- func (d *Device) ReadIM0(ctx context.Context) (pnio.IM0, error)
- func (d *Device) ReadRecord(ctx context.Context, rec Record, maxLen uint32) ([]byte, error)
- func (d *Device) SetOutput(slot, subslot uint16, data []byte, iops uint8) error
- func (d *Device) State() (State, error)
- func (d *Device) Stats() DeviceStats
- func (d *Device) WaitState(ctx context.Context, s State) error
- func (d *Device) WriteMultiple(ctx context.Context, items []WriteItem) ([]pnio.Status, error)
- func (d *Device) WriteRecord(ctx context.Context, rec Record, data []byte) error
- type DeviceConfig
- type DeviceStats
- type IOCRInfo
- type ListenPacketFunc
- type Parameter
- type Record
- type RecordClient
- func (r *RecordClient) Addr() net.Addr
- func (r *RecordClient) Connect(ctx context.Context, req *pnio.ConnectRequest) (*pnio.ConnectResponse, error)
- func (r *RecordClient) Control(ctx context.Context, c pnio.ControlBlock) error
- func (r *RecordClient) OpenSupervisor(ctx context.Context, cfg SupervisorConfig) (*SupervisorAR, error)
- func (r *RecordClient) Read(ctx context.Context, ar rpc.UUID, rec Record, maxLen uint32) ([]byte, error)
- func (r *RecordClient) ReadDiagnosis(ctx context.Context, ar rpc.UUID, slot, subslot uint16, sub bool) ([]pnio.DiagnosisData, error)
- func (r *RecordClient) ReadIM0(ctx context.Context, ar rpc.UUID, slot, subslot uint16) (pnio.IM0, error)
- func (r *RecordClient) Write(ctx context.Context, ar rpc.UUID, rec Record, data []byte) error
- func (r *RecordClient) WriteMultiple(ctx context.Context, ar rpc.UUID, items []WriteItem) ([]pnio.Status, error)
- type State
- type SupervisorAR
- func (s *SupervisorAR) Read(ctx context.Context, rec Record, maxLen uint32) ([]byte, error)
- func (s *SupervisorAR) Release(ctx context.Context) error
- func (s *SupervisorAR) SessionKey() uint16
- func (s *SupervisorAR) UUID() rpc.UUID
- func (s *SupervisorAR) Write(ctx context.Context, rec Record, data []byte) error
- func (s *SupervisorAR) WriteMultiple(ctx context.Context, items []WriteItem) ([]pnio.Status, error)
- type SupervisorConfig
- type WriteItem
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func CanTransition ¶
CanTransition reports whether the lifecycle allows from → to.
Types ¶
type ARInfo ¶
type ARInfo struct {
UUID rpc.UUID `json:"arUUID"`
SessionKey uint16 `json:"sessionKey"`
Type pnio.ARType `json:"arType"`
RTClass pnio.RTClass `json:"rtClass"`
// Advanced reports the advanced startup mode.
Advanced bool `json:"advanced"`
// DeviceAddr is the device's RPC endpoint.
DeviceAddr string `json:"deviceAddr"`
// LocalAlarmRef and RemoteAlarmRef are the alarm references of the
// controller and of the device.
LocalAlarmRef uint16 `json:"localAlarmRef"`
RemoteAlarmRef uint16 `json:"remoteAlarmRef"`
// Input and Output are the two IOCRs.
Input IOCRInfo `json:"input"`
Output IOCRInfo `json:"output"`
}
ARInfo describes the established AR of a device: what Connect negotiated.
type AlarmEvent ¶
type AlarmEvent struct {
Device string
Notification pnio.AlarmNotification
Received time.Time
}
AlarmEvent is an alarm a device sent; the controller acknowledges it.
type Config ¶
type Config struct {
// Mux is the Layer 2 port; required.
Mux *l2.Mux
// ListenPacket opens the RPC sockets. nil uses the operating system's
// UDP stack.
ListenPacket ListenPacketFunc
// RPCPort is the port of the controller's RPC server, which receives
// the devices' ApplicationReady. Devices send it to 34964, the
// default.
RPCPort int
// StationName is the controller's name in the AR (CMInitiatorStation
// Name). Empty means "go-profinet-controller".
StationName string
// VendorID, DeviceID and Instance form the controller's object UUID.
VendorID, DeviceID, Instance uint16
// DCP configures the DCP requester.
DCP dcp.ClientOptions
// Logger receives diagnostics. nil logs nothing.
Logger profinet.Logger
}
Config configures a Controller.
type Controller ¶
type Controller struct {
// contains filtered or unexported fields
}
Controller is a PROFINET IO-Controller. It is safe for concurrent use.
func (*Controller) AddDevice ¶
func (c *Controller) AddDevice(cfg DeviceConfig) (*Device, error)
AddDevice adds a device and starts its lifecycle.
func (*Controller) Close ¶
func (c *Controller) Close() error
Close releases every AR and stops the controller.
func (*Controller) DCP ¶
func (c *Controller) DCP() *dcp.Client
DCP returns the controller's DCP requester, for discovery and explicit configuration of devices.
func (*Controller) Device ¶
func (c *Controller) Device(name string) (*Device, bool)
Device returns the device with a station name.
func (*Controller) Devices ¶
func (c *Controller) Devices() []*Device
Devices returns the devices added to the controller.
func (*Controller) ObjectUUID ¶
func (c *Controller) ObjectUUID() rpc.UUID
ObjectUUID returns the controller's PNIO object UUID.
func (*Controller) RPC ¶
func (c *Controller) RPC() *rpc.Client
RPC returns the controller's RPC client.
type Device ¶
type Device struct {
// contains filtered or unexported fields
}
Device is a device of the controller.
func (*Device) AR ¶
AR returns the description of the device's current AR; false when none is established.
func (*Device) Close ¶
Close releases the AR (when established) and stops the lifecycle. The device is removed from the controller.
func (*Device) ConsumerStatus ¶
ConsumerStatus returns the device's consumer status (IOCS) of a submodule's outputs.
func (*Device) Input ¶
Input returns a copy of the input data of a submodule and its provider status from the last cyclic frame.
func (*Device) ModuleDiff ¶
func (d *Device) ModuleDiff() *pnio.ModuleDiffBlock
ModuleDiff returns the ModuleDiffBlock of the last Connect, nil when the real configuration matched.
func (*Device) ReadDiagnosis ¶
ReadDiagnosis reads the diagnosis of the whole device.
func (*Device) ReadRecord ¶
ReadRecord reads a record within the AR.
func (*Device) SetOutput ¶
SetOutput sets the output data and provider status of a submodule for the next cyclic frames.
func (*Device) Stats ¶
func (d *Device) Stats() DeviceStats
Stats returns the counters of the device and of its current AR.
func (*Device) WriteMultiple ¶
WriteMultiple writes several records in one call.
type DeviceConfig ¶
type DeviceConfig struct {
// StationName is the device's NameOfStation; required.
StationName string
// Model is the expected configuration; required. Its identity's vendor
// and device ID must match what the device reports in DCP.
Model *model.Device
// IP is the IP suite the device should have. When AssignIP is true
// and the device reports a different one, it is set with DCP
// (temporarily, or permanently with PermanentIP). Without AssignIP the
// device's own address is used.
IP dcp.IPSuite
AssignIP bool
PermanentIP bool
// SendClockFactor (units of 31.25 µs) and ReductionRatio define the
// cycle; zero means 32 (1 ms) and 4: a cycle of 4 ms.
SendClockFactor, ReductionRatio uint16
// DataHoldFactor and WatchdogFactor are in cycles; zero means 10.
// PLCs commonly use 3, which a general-purpose operating system does
// not hold: its scheduling stalls of 10 to 20 ms expire a hold of 3
// cycles of 4 ms (see docs/CYCLIC.md).
DataHoldFactor, WatchdogFactor uint16
// Advanced selects the advanced startup mode with RTClass 2;
// otherwise the legacy startup with RTClass 1 is used.
Advanced bool
// ActivityTimeout is the CM initiator activity timeout; zero means
// 10 s.
ActivityTimeout time.Duration
// RTATimeoutFactor (units of 100 ms) and RTARetries configure the
// alarm transport; zero means 5 and 3.
RTATimeoutFactor, RTARetries uint16
// Parameters are written after Connect and before PrmEnd.
Parameters []Parameter
// RPCTimeout bounds each RPC call; zero means 5 s.
RPCTimeout time.Duration
// ReconnectMin and ReconnectMax bound the backoff between attempts;
// zero means 200 ms and 10 s.
ReconnectMin, ReconnectMax time.Duration
// OnAlarm receives every alarm, on the alarm goroutine of the AR; it
// must not block.
OnAlarm func(AlarmEvent)
// OnState receives every state change, before WaitState returns for it.
OnState func(from, to State, err error)
}
DeviceConfig configures a device of the controller.
type DeviceStats ¶
type DeviceStats struct {
Connects, Aborts uint64
Provider rt.ProviderStats
Consumer rt.ConsumerStats
Cycle rt.TaskStats
Alarms uint64
}
DeviceStats are the counters of a device.
type IOCRInfo ¶
type IOCRInfo struct {
Type pnio.IOCRType `json:"type"`
FrameID uint16 `json:"frameId"`
// DataLength is the length of the C_SDU.
DataLength uint16 `json:"dataLength"`
SendClockFactor uint16 `json:"sendClockFactor"`
ReductionRatio uint16 `json:"reductionRatio"`
WatchdogFactor uint16 `json:"watchdogFactor"`
DataHoldFactor uint16 `json:"dataHoldFactor"`
// Cycle is SendClockFactor × 31.25 µs × ReductionRatio.
Cycle time.Duration `json:"cycle"`
// Objects are the data objects of the C_SDU and IOCS the consumer
// statuses it carries, at their offsets.
Objects []rt.Object `json:"objects"`
IOCS []rt.Status `json:"iocs"`
}
IOCRInfo describes one IOCR of an AR.
type ListenPacketFunc ¶
ListenPacketFunc opens a UDP socket; net.ListenConfig.ListenPacket and netstack.Stack.ListenPacket have this signature.
type RecordClient ¶
type RecordClient struct {
// contains filtered or unexported fields
}
RecordClient performs the acyclic PNIO services of one device: Read, Write, ReadImplicit, Control and Release. It is safe for concurrent use.
func NewRecordClient ¶
NewRecordClient returns a client for the device at addr (its RPC endpoint, port 34964) with PNIO object UUID object (see pnio.ObjectUUID). Its calls share one RPC activity, as the calls of one AR must; they run one at a time.
func (*RecordClient) Addr ¶
func (r *RecordClient) Addr() net.Addr
Addr returns the device's RPC address.
func (*RecordClient) Connect ¶
func (r *RecordClient) Connect(ctx context.Context, req *pnio.ConnectRequest) (*pnio.ConnectResponse, error)
Connect sends a Connect request and returns the decoded response.
func (*RecordClient) Control ¶
func (r *RecordClient) Control(ctx context.Context, c pnio.ControlBlock) error
Control sends a control block (PrmEnd, PrmBegin) and checks the Done acknowledgement.
func (*RecordClient) OpenSupervisor ¶
func (r *RecordClient) OpenSupervisor(ctx context.Context, cfg SupervisorConfig) (*SupervisorAR, error)
OpenSupervisor establishes a device access AR with the device of r.
func (*RecordClient) Read ¶
func (r *RecordClient) Read(ctx context.Context, ar rpc.UUID, rec Record, maxLen uint32) ([]byte, error)
Read reads a record within an AR (ar is the AR UUID) or, with a nil ar, implicitly (ReadImplicit, no AR needed). maxLen bounds the data; zero means 4096. A PNIO error is returned as a *pnio.StatusError.
func (*RecordClient) ReadDiagnosis ¶
func (r *RecordClient) ReadDiagnosis(ctx context.Context, ar rpc.UUID, slot, subslot uint16, sub bool) ([]pnio.DiagnosisData, error)
ReadDiagnosis reads the diagnosis of the device (index 0xF80C), or of one submodule when slot and subslot are given with sub true (0x800C).
func (*RecordClient) ReadIM0 ¶
func (r *RecordClient) ReadIM0(ctx context.Context, ar rpc.UUID, slot, subslot uint16) (pnio.IM0, error)
ReadIM0 reads I&M0 of a submodule (the DAP: slot 0, subslot 1).
func (*RecordClient) WriteMultiple ¶
func (r *RecordClient) WriteMultiple(ctx context.Context, ar rpc.UUID, items []WriteItem) ([]pnio.Status, error)
WriteMultiple writes several records in one call (index 0xE040). It returns the status of each item; err reports a transport failure or a failed call without per-item results.
type State ¶
type State uint8
State is the state of a device's lifecycle on the controller.
const ( StateOffline State = iota StateResolving StateConnecting StateParameterizing StateWaitAppReady StateRunning StateStopped )
States. A device goes Offline → Resolving → Connecting → Parameterizing → WaitApplicationReady → Running; a failure in any of them goes back to Offline (and after the backoff to Resolving); Close goes to Stopped.
type SupervisorAR ¶
type SupervisorAR struct {
// contains filtered or unexported fields
}
SupervisorAR is a device access AR: an IOSAR with the DeviceAccess property, through which an engineering tool reads and writes records of a device without IO data, alarms or parameterization, and without the expected configuration of an IOCAR. Devices that do not support it reject the Connect.
func (*SupervisorAR) Release ¶
func (s *SupervisorAR) Release(ctx context.Context) error
Release releases the AR. Releasing it again does nothing.
func (*SupervisorAR) SessionKey ¶
func (s *SupervisorAR) SessionKey() uint16
SessionKey returns the session key of the AR.
func (*SupervisorAR) Write ¶
Write writes a record within the AR.
Write changes the configuration of an industrial device. Only call it on an explicit request of the user.
func (*SupervisorAR) WriteMultiple ¶
WriteMultiple writes several records in one call.
type SupervisorConfig ¶
type SupervisorConfig struct {
// InitiatorMAC is the tool's MAC address; required.
InitiatorMAC ethernet.MAC
// InitiatorObject is the tool's PNIO object UUID (pnio.ObjectUUID);
// required. Nothing calls it: a device access AR has no
// ApplicationReady.
InitiatorObject rpc.UUID
// StationName is the tool's name in the AR. Empty means
// "go-profinet-supervisor".
StationName string
// ActivityTimeout is the CM initiator activity timeout after which
// the device closes an AR the tool left behind; zero means 10 s.
ActivityTimeout time.Duration
}
SupervisorConfig configures a device access AR.