-
Notifications
You must be signed in to change notification settings - Fork 16
/
exchange.go
131 lines (114 loc) · 4.63 KB
/
exchange.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
package part5
import (
"encoding/binary"
"math"
"github.com/pascaldekloe/part5/info"
)
// Exchange supplies communication with another station.
type Exchange[Orig info.OrigAddr, Com info.ComAddr, Obj info.ObjAddr] struct {
info.System[Orig, Com, Obj] // parameters
// The originator address is optional, depending on the System.
OrigAddr Orig
// The common address must be non zero.
ComAddr Com
}
// NewDataUnit returns a new ASDU without payload; .Info is empty.
func (x Exchange[Orig, Com, Obj]) NewDataUnit(t info.TypeID, e info.Enc, c info.Cause) info.DataUnit[Orig, Com, Obj] {
u := x.System.NewDataUnit()
u.Type = t
u.Enc = e
u.Cause = c
u.Orig = x.OrigAddr
u.Addr = x.ComAddr
return u
}
// Command has the controlling perspective of an Exchange.
type Command[Orig info.OrigAddr, Com info.ComAddr, Obj info.ObjAddr] struct {
Exchange[Orig, Com, Obj]
}
// Command returns the controlling perspective of an Exchange.
func (x Exchange[Orig, Com, Obj]) Command() Command[Orig, Com, Obj] {
return Command[Orig, Com, Obj]{x}
}
// Activation commands address one information object.
func (cmd Command[Orig, Com, Obj]) act(t info.TypeID, addr Obj) info.DataUnit[Orig, Com, Obj] {
u := cmd.Exchange.NewDataUnit(t, 1, info.Act)
for i := 0; i < len(addr); i++ {
u.Info = append(u.Info, addr[i])
}
return u
}
// SingleCmd returns single command: C_SC_NA_1 act(ivation),
// conform chapter 7.3.2.1 of companion standard 101.
func (cmd Command[Orig, Com, Obj]) SingleCmd(addr Obj, pt info.SinglePt, q info.CmdQual) info.DataUnit[Orig, Com, Obj] {
u := cmd.act(info.C_SC_NA_1, addr)
u.Info = append(u.Info, byte(pt&1)|byte(q&^1))
return u
}
// DoubleCmd returns double command: C_DC_NA_1 act(ivation),
// conform chapter 7.3.2.2 of companion standard 101.
func (cmd Command[Orig, Com, Obj]) DoubleCmd(addr Obj, pt info.DoublePt, q info.CmdQual) info.DataUnit[Orig, Com, Obj] {
u := cmd.act(info.C_DC_NA_1, addr)
u.Info = append(u.Info, byte(pt&3)|byte(q&^3))
return u
}
// RegulCmd returns regulating-step command: C_RC_NA_1 act(ivation),
// conform chapter 7.3.2.3 of companion standard 101.
// Regul must be either Lower or Higher. The other two states
// (0 and 3) are not permitted.
func (cmd Command[Orig, Com, Obj]) RegulCmd(addr Obj, r info.Regul, q info.CmdQual) info.DataUnit[Orig, Com, Obj] {
u := cmd.act(info.C_RC_NA_1, addr)
u.Info = append(u.Info, byte(r&3)|byte(q&^3))
return u
}
// NormSetPt returns set-point command: C_SE_NA_1 act(ivation),
// conform chapter 7.3.2.4 of companion standard 101.
func (cmd Command[Orig, Com, Obj]) NormSetPt(addr Obj, value info.Norm, q info.SetPtQual) info.DataUnit[Orig, Com, Obj] {
u := cmd.act(info.C_SE_NA_1, addr)
u.Info = append(u.Info, value[0], value[1])
u.Info = append(u.Info, byte(q))
return u
}
// ScaledSetPt returns set-point command: C_SE_NB_1 act(ivation),
// conform chapter 7.3.2.5 of companion standard 101.
func (cmd Command[Orig, Com, Obj]) ScaledSetPt(addr Obj, value int16, q info.SetPtQual) info.DataUnit[Orig, Com, Obj] {
u := cmd.act(info.C_SE_NB_1, addr)
u.Info = append(u.Info, byte(value), byte(value>>8))
u.Info = append(u.Info, byte(q))
return u
}
// FloatSetPt returns set-point command: C_SE_NC_1 act(ivation),
// conform chapter 7.3.2.6 of companion standard 101.
func (cmd Command[Orig, Com, Obj]) FloatSetPt(addr Obj, value float32, q info.SetPtQual) info.DataUnit[Orig, Com, Obj] {
u := cmd.act(info.C_SE_NC_1, addr)
u.Info = binary.LittleEndian.AppendUint32(u.Info,
math.Float32bits(value))
u.Info = append(u.Info, byte(q))
return u
}
// Inro returns interrogation command: C_IC_NA_1 act(ivation),
// conform chapter 7.3.4.1 of companion standard 101.
func (cmd Command[Orig, Com, Obj]) Inro() info.DataUnit[Orig, Com, Obj] {
return cmd.InroGroup(0)
}
// InroGroup returns interrogation command: C_IC_NA_1 act(ivation),
// conform chapter 7.3.4.1 of companion standard 101.
// Group can be disabled with 0 for (global) station interrogation.
// Otherwise, use a group identifier in range [1..16].
func (cmd Command[Orig, Com, Obj]) InroGroup(group uint) info.DataUnit[Orig, Com, Obj] {
var addr Obj // fixed to zero
u := cmd.act(info.C_IC_NA_1, addr)
// The qualifier of interrogation codes are listed
// at chapter 7.2.6.22 of companion standard 101.
u.Info = append(u.Info, byte(group+20))
return u
}
// TestCmd returns test command: C_TS_NA_1 act(ivation),
// conform chapter 7.3.4.5 of companion standard 101.
func (cmd Command[Orig, Com, Obj]) TestCmd() info.DataUnit[Orig, Com, Obj] {
var addr Obj // fixed to zero
u := cmd.act(info.C_TS_NA_1, addr)
// fixed bit-pattern from chapter 7.2.6.14 of companion standard 101
u.Info = append(u.Info, 0b1010_1010, 0b0101_0101)
return u
}