forked from xiegeo/modbusone
-
Notifications
You must be signed in to change notification settings - Fork 0
/
simple_handler.go
144 lines (132 loc) · 4.17 KB
/
simple_handler.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
132
133
134
135
136
137
138
139
140
141
142
143
144
package modbusone
import (
"errors"
)
// ErrFcNotSupported is another version of EcIllegalFunction, encountering of
// this error shows the error is locally generated, not a remote ExceptionCode.
var ErrFcNotSupported = errors.New("this FunctionCode is not supported")
var _ ProtocolHandler = &SimpleHandler{} // Asserts SimpleHandler implants ProtocolHandler.
// SimpleHandler implements ProtocolHandler, any nil function returns ErrFcNotSupported.
type SimpleHandler struct {
// ReadDiscreteInputs handles server side FC=2
ReadDiscreteInputs func(address, quantity uint16) ([]bool, error)
// ReadDiscreteInputs handles client side FC=2
WriteDiscreteInputs func(address uint16, values []bool) error
// ReadCoils handles client side FC=5&15, server side FC=1
ReadCoils func(address, quantity uint16) ([]bool, error)
// WriteCoils handles client side FC=1, server side FC=5&15
WriteCoils func(address uint16, values []bool) error
// ReadInputRegisters handles server side FC=4
ReadInputRegisters func(address, quantity uint16) ([]uint16, error)
// ReadDiscreteInputs handles client side FC=4
WriteInputRegisters func(address uint16, values []uint16) error
// ReadHoldingRegisters handles client side FC=6&16, server side FC=3
ReadHoldingRegisters func(address, quantity uint16) ([]uint16, error)
// WriteHoldingRegisters handles client side FC=3, server side FC=6&16
WriteHoldingRegisters func(address uint16, values []uint16) error
// OnErrorImp handles OnError
OnErrorImp func(req PDU, errRep PDU)
}
// OnRead is called by a Server, set Read... to catch the calls.
func (h *SimpleHandler) OnRead(req PDU) ([]byte, error) {
fc := req.GetFunctionCode()
address := req.GetAddress()
count, err := req.GetRequestCount()
if err != nil {
return nil, err
}
switch fc {
case FcReadDiscreteInputs:
if h.ReadDiscreteInputs == nil {
return nil, ErrFcNotSupported
}
values, err := h.ReadDiscreteInputs(address, count)
if err != nil {
return nil, err
}
return BoolsToData(values, fc)
case FcReadCoils, FcWriteSingleCoil, FcWriteMultipleCoils:
if h.ReadCoils == nil {
return nil, ErrFcNotSupported
}
values, err := h.ReadCoils(address, count)
if err != nil {
return nil, err
}
return BoolsToData(values, fc)
case FcReadInputRegisters:
if h.ReadInputRegisters == nil {
return nil, ErrFcNotSupported
}
values, err := h.ReadInputRegisters(address, count)
if err != nil {
return nil, err
}
return RegistersToData(values)
case FcReadHoldingRegisters, FcWriteSingleRegister, FcWriteMultipleRegisters:
if h.ReadHoldingRegisters == nil {
return nil, ErrFcNotSupported
}
values, err := h.ReadHoldingRegisters(address, count)
if err != nil {
return nil, err
}
return RegistersToData(values)
}
return nil, ErrFcNotSupported
}
// OnWrite is called by a Server, set Write... to catch the calls.
func (h *SimpleHandler) OnWrite(req PDU, data []byte) error {
fc := req.GetFunctionCode()
address := req.GetAddress()
count, err := req.GetRequestCount()
if err != nil {
return err
}
switch fc {
case FcReadDiscreteInputs:
if h.WriteDiscreteInputs == nil {
return ErrFcNotSupported
}
values, err := DataToBools(data, count, fc)
if err != nil {
return err
}
return h.WriteDiscreteInputs(address, values)
case FcReadCoils, FcWriteSingleCoil, FcWriteMultipleCoils:
if h.WriteCoils == nil {
return ErrFcNotSupported
}
values, err := DataToBools(data, count, fc)
if err != nil {
return err
}
return h.WriteCoils(address, values)
case FcReadInputRegisters:
if h.WriteInputRegisters == nil {
return ErrFcNotSupported
}
values, err := DataToRegisters(data)
if err != nil {
return err
}
return h.WriteInputRegisters(address, values)
case FcReadHoldingRegisters, FcWriteSingleRegister, FcWriteMultipleRegisters:
if h.WriteHoldingRegisters == nil {
return ErrFcNotSupported
}
values, err := DataToRegisters(data)
if err != nil {
return err
}
return h.WriteHoldingRegisters(address, values)
}
return ErrFcNotSupported
}
// OnError is called by a Server, set OnErrorImp to catch the calls.
func (h *SimpleHandler) OnError(req PDU, errRep PDU) {
if h.OnErrorImp == nil {
return
}
h.OnErrorImp(req, errRep)
}