-
Notifications
You must be signed in to change notification settings - Fork 14
/
variable_node.go
241 lines (214 loc) · 7.01 KB
/
variable_node.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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
package server
import (
"context"
"sync"
"github.com/awcullen/opcua/ua"
)
type VariableNode struct {
sync.RWMutex
nodeId ua.NodeID
nodeClass ua.NodeClass
browseName ua.QualifiedName
displayName ua.LocalizedText
description ua.LocalizedText
rolePermissions []ua.RolePermissionType
accessRestrictions uint16
references []ua.Reference
value ua.DataValue
dataType ua.NodeID
valueRank int32
arrayDimensions []uint32
accessLevel byte
minimumSamplingInterval float64
historizing bool
readValueHandler func(context.Context, ua.ReadValueID) ua.DataValue
writeValueHandler func(context.Context, ua.WriteValue) ua.StatusCode
}
var _ Node = (*VariableNode)(nil)
func NewVariableNode(nodeID ua.NodeID, browseName ua.QualifiedName, displayName ua.LocalizedText, description ua.LocalizedText, rolePermissions []ua.RolePermissionType, references []ua.Reference, value ua.DataValue, dataType ua.NodeID, valueRank int32, arrayDimensions []uint32, accessLevel byte, minimumSamplingInterval float64, historizing bool) *VariableNode {
return &VariableNode{
nodeId: nodeID,
nodeClass: ua.NodeClassVariable,
browseName: browseName,
displayName: displayName,
description: description,
rolePermissions: rolePermissions,
accessRestrictions: 0,
references: references,
value: value,
dataType: dataType,
valueRank: valueRank,
arrayDimensions: arrayDimensions,
accessLevel: accessLevel,
minimumSamplingInterval: minimumSamplingInterval,
historizing: historizing,
}
}
// NodeID returns the NodeID attribute of this node.
func (n *VariableNode) NodeID() ua.NodeID {
return n.nodeId
}
// NodeClass returns the NodeClass attribute of this node.
func (n *VariableNode) NodeClass() ua.NodeClass {
return n.nodeClass
}
// BrowseName returns the BrowseName attribute of this node.
func (n *VariableNode) BrowseName() ua.QualifiedName {
return n.browseName
}
// DisplayName returns the DisplayName attribute of this node.
func (n *VariableNode) DisplayName() ua.LocalizedText {
return n.displayName
}
// Description returns the Description attribute of this node.
func (n *VariableNode) Description() ua.LocalizedText {
return n.description
}
// RolePermissions returns the RolePermissions attribute of this node.
func (n *VariableNode) RolePermissions() []ua.RolePermissionType {
return n.rolePermissions
}
// UserRolePermissions returns the RolePermissions attribute of this node for the current user.
func (n *VariableNode) UserRolePermissions(ctx context.Context) []ua.RolePermissionType {
filteredPermissions := []ua.RolePermissionType{}
session, ok := ctx.Value(SessionKey).(*Session)
if !ok {
return filteredPermissions
}
roles := session.UserRoles()
rolePermissions := n.RolePermissions()
if rolePermissions == nil {
rolePermissions = session.Server().RolePermissions()
}
for _, role := range roles {
for _, rp := range rolePermissions {
if rp.RoleID == role {
filteredPermissions = append(filteredPermissions, rp)
}
}
}
return filteredPermissions
}
// References returns the References of this node.
func (n *VariableNode) References() []ua.Reference {
n.RLock()
res := n.references
n.RUnlock()
return res
}
// SetReferences sets the References of the Variable.
func (n *VariableNode) SetReferences(value []ua.Reference) {
n.Lock()
n.references = value
n.Unlock()
}
// Value returns the value of the Variable.
func (n *VariableNode) Value() ua.DataValue {
n.RLock()
res := n.value
n.RUnlock()
return res
}
// SetValue sets the value of the Variable.
func (n *VariableNode) SetValue(value ua.DataValue) {
n.Lock()
n.value = value
n.Unlock()
}
// DataType returns the DataType attribute of this node.
func (n *VariableNode) DataType() ua.NodeID {
return n.dataType
}
// ValueRank returns the ValueRank attribute of this node.
func (n *VariableNode) ValueRank() int32 {
return n.valueRank
}
// ArrayDimensions returns the ArrayDimensions attribute of this node.
func (n *VariableNode) ArrayDimensions() []uint32 {
return n.arrayDimensions
}
// AccessLevel returns the AccessLevel attribute of this node.
func (n *VariableNode) AccessLevel() byte {
return n.accessLevel
}
// UserAccessLevel returns the AccessLevel attribute of this node for this user.
func (n *VariableNode) UserAccessLevel(ctx context.Context) byte {
accessLevel := n.accessLevel
session, ok := ctx.Value(SessionKey).(*Session)
if !ok {
return 0
}
roles := session.UserRoles()
rolePermissions := n.RolePermissions()
if rolePermissions == nil {
rolePermissions = session.Server().RolePermissions()
}
var currentRead, currentWrite, historyRead bool
for _, role := range roles {
for _, rp := range rolePermissions {
if rp.RoleID == role {
if rp.Permissions&ua.PermissionTypeRead != 0 {
currentRead = true
}
if rp.Permissions&ua.PermissionTypeWrite != 0 {
currentWrite = true
}
if rp.Permissions&ua.PermissionTypeReadHistory != 0 {
historyRead = true
}
}
}
}
if !currentRead {
accessLevel &^= ua.AccessLevelsCurrentRead
}
if !currentWrite {
accessLevel &^= ua.AccessLevelsCurrentWrite
}
if !historyRead {
accessLevel &^= ua.AccessLevelsHistoryRead
}
return accessLevel
}
// MinimumSamplingInterval returns the MinimumSamplingInterval attribute of this node.
func (n *VariableNode) MinimumSamplingInterval() float64 {
return n.minimumSamplingInterval
}
// Historizing returns the Historizing attribute of this node.
func (n *VariableNode) Historizing() bool {
n.RLock()
ret := n.historizing
n.RUnlock()
return ret
}
// SetHistorizing sets the Historizing attribute of this node.
func (n *VariableNode) SetHistorizing(historizing bool) {
n.Lock()
n.historizing = historizing
n.Unlock()
}
// SetReadValueHandler sets the ReadValueHandler of this node.
func (n *VariableNode) SetReadValueHandler(value func(context.Context, ua.ReadValueID) ua.DataValue) {
n.Lock()
n.readValueHandler = value
n.Unlock()
}
// SetWriteValueHandler sets the WriteValueHandler of this node.
func (n *VariableNode) SetWriteValueHandler(value func(context.Context, ua.WriteValue) ua.StatusCode) {
n.Lock()
n.writeValueHandler = value
n.Unlock()
}
// IsAttributeIDValid returns true if attributeId is supported for the node.
func (n *VariableNode) IsAttributeIDValid(attributeID uint32) bool {
switch attributeID {
case ua.AttributeIDNodeID, ua.AttributeIDNodeClass, ua.AttributeIDBrowseName,
ua.AttributeIDDisplayName, ua.AttributeIDDescription, ua.AttributeIDRolePermissions,
ua.AttributeIDUserRolePermissions, ua.AttributeIDValue, ua.AttributeIDDataType,
ua.AttributeIDValueRank, ua.AttributeIDArrayDimensions, ua.AttributeIDAccessLevel,
ua.AttributeIDUserAccessLevel, ua.AttributeIDMinimumSamplingInterval, ua.AttributeIDHistorizing:
return true
default:
return false
}
}