@things-factory/integration-opc 8.0.0-beta.0 → 8.0.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -3
- package/server/engine/connector/index.ts +0 -2
- package/server/engine/connector/opc-ua-server.ts +0 -145
- package/server/engine/connector/opc-ua.ts +0 -212
- package/server/engine/index.ts +0 -2
- package/server/engine/task/index.ts +0 -5
- package/server/engine/task/opc-ua-read.ts +0 -77
- package/server/engine/task/opc-ua-start-monitor.ts +0 -88
- package/server/engine/task/opc-ua-stop-monitor.ts +0 -37
- package/server/engine/task/opc-ua-write.ts +0 -80
- package/server/engine/task/utils.ts +0 -30
- package/server/index.ts +0 -2
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/integration-opc",
|
|
3
|
-
"version": "8.0.0-beta.
|
|
3
|
+
"version": "8.0.0-beta.2",
|
|
4
4
|
"main": "dist-server/index.js",
|
|
5
5
|
"browser": "client/index.js",
|
|
6
6
|
"things-factory": true,
|
|
@@ -23,8 +23,8 @@
|
|
|
23
23
|
"clean": "npm run clean:server"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@things-factory/integration-base": "^8.0.0-beta.
|
|
26
|
+
"@things-factory/integration-base": "^8.0.0-beta.2",
|
|
27
27
|
"node-opcua": "^2.110.0"
|
|
28
28
|
},
|
|
29
|
-
"gitHead": "
|
|
29
|
+
"gitHead": "f03431a09435511b2595515658f9cb8f78ba4ebb"
|
|
30
30
|
}
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import { StatusCodes, OPCUAServer, Variant, DataType } from 'node-opcua'
|
|
2
|
-
import { ConnectionManager, Connector, Connection } from '@things-factory/integration-base'
|
|
3
|
-
|
|
4
|
-
export class OPCUAServerConnector implements Connector {
|
|
5
|
-
async ready(connectionConfigs) {
|
|
6
|
-
await Promise.all(connectionConfigs.map(this.connect))
|
|
7
|
-
|
|
8
|
-
ConnectionManager.logger.info('opc-ua-servers are ready')
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
async connect(config) {
|
|
12
|
-
var {
|
|
13
|
-
name: productName,
|
|
14
|
-
endpoint: port, // the port of the listening socket of the server
|
|
15
|
-
params: {
|
|
16
|
-
resourcePath, // this path will be added to the endpoint resource name
|
|
17
|
-
buildNumber,
|
|
18
|
-
buildDate
|
|
19
|
-
}
|
|
20
|
-
} = config
|
|
21
|
-
|
|
22
|
-
const server = new OPCUAServer({
|
|
23
|
-
port,
|
|
24
|
-
resourcePath,
|
|
25
|
-
buildInfo: {
|
|
26
|
-
productName,
|
|
27
|
-
buildNumber,
|
|
28
|
-
buildDate: buildDate ? new Date(buildDate) : new Date()
|
|
29
|
-
}
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
await server.initialize()
|
|
33
|
-
ConnectionManager.logger.info('initialized')
|
|
34
|
-
|
|
35
|
-
const addressSpace = server.engine.addressSpace
|
|
36
|
-
const namespace = addressSpace.getOwnNamespace()
|
|
37
|
-
|
|
38
|
-
// declare a new object
|
|
39
|
-
const device = namespace.addObject({
|
|
40
|
-
organizedBy: addressSpace.rootFolder.objects,
|
|
41
|
-
browseName: 'MyDevice'
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
// add some variables
|
|
45
|
-
// add a variable named MyVariable1 to the newly created folder "MyDevice"
|
|
46
|
-
let variable1 = 1
|
|
47
|
-
|
|
48
|
-
// emulate variable1 changing every 500 ms
|
|
49
|
-
setInterval(() => {
|
|
50
|
-
variable1 += 1
|
|
51
|
-
}, 500)
|
|
52
|
-
|
|
53
|
-
namespace.addVariable({
|
|
54
|
-
componentOf: device,
|
|
55
|
-
browseName: 'MyVariable1',
|
|
56
|
-
dataType: 'Double',
|
|
57
|
-
value: {
|
|
58
|
-
get: () => new Variant({ dataType: DataType.Double, value: variable1 })
|
|
59
|
-
}
|
|
60
|
-
})
|
|
61
|
-
|
|
62
|
-
// add a variable named MyVariable2 to the newly created folder "MyDevice"
|
|
63
|
-
let variable2 = 10.0
|
|
64
|
-
|
|
65
|
-
namespace.addVariable({
|
|
66
|
-
componentOf: device,
|
|
67
|
-
nodeId: 'ns=1;b=1020FFAA', // some opaque NodeId in namespace 4
|
|
68
|
-
browseName: 'MyVariable2',
|
|
69
|
-
dataType: 'Double',
|
|
70
|
-
minimumSamplingInterval: 1234, // we need to specify a minimumSamplingInterval when using a getter
|
|
71
|
-
value: {
|
|
72
|
-
get: () => new Variant({ dataType: DataType.Double, value: variable2 }),
|
|
73
|
-
set: variant => {
|
|
74
|
-
variable2 = parseFloat(variant.value)
|
|
75
|
-
return StatusCodes.Good
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
})
|
|
79
|
-
const os = require('os')
|
|
80
|
-
/**
|
|
81
|
-
* returns the percentage of free memory on the running machine
|
|
82
|
-
* @return {double}
|
|
83
|
-
*/
|
|
84
|
-
function available_memory() {
|
|
85
|
-
// var value = process.memoryUsage().heapUsed / 1000000;
|
|
86
|
-
const percentageMemUsed = (os.freemem() / os.totalmem()) * 100.0
|
|
87
|
-
return percentageMemUsed
|
|
88
|
-
}
|
|
89
|
-
namespace.addVariable({
|
|
90
|
-
componentOf: device,
|
|
91
|
-
|
|
92
|
-
nodeId: 's=free_memory', // a string nodeID
|
|
93
|
-
browseName: 'FreeMemory',
|
|
94
|
-
dataType: 'Double',
|
|
95
|
-
value: {
|
|
96
|
-
get: () => new Variant({ dataType: DataType.Double, value: available_memory() })
|
|
97
|
-
}
|
|
98
|
-
})
|
|
99
|
-
|
|
100
|
-
server.start(function () {
|
|
101
|
-
ConnectionManager.logger.info('Server is now listening ... ( press CTRL+C to stop)')
|
|
102
|
-
ConnectionManager.logger.info('port ', server.endpoints[0].port)
|
|
103
|
-
const endpointUrl = server.endpoints[0].endpointDescriptions()[0].endpointUrl
|
|
104
|
-
ConnectionManager.logger.info(' the primary server endpoint url is ', endpointUrl)
|
|
105
|
-
})
|
|
106
|
-
|
|
107
|
-
ConnectionManager.addConnectionInstance(config, server)
|
|
108
|
-
|
|
109
|
-
ConnectionManager.logger.info(`opc-ua-server connection(${config.name}:${port}) is connected`)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
async disconnect(connection: Connection) {
|
|
113
|
-
var server = ConnectionManager.removeConnectionInstance(connection)
|
|
114
|
-
server && server._server.close()
|
|
115
|
-
|
|
116
|
-
ConnectionManager.logger.info(`opc-ua-server connection(${connection.name}) is disconnected`)
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
get parameterSpec() {
|
|
120
|
-
return [
|
|
121
|
-
{
|
|
122
|
-
type: 'number',
|
|
123
|
-
name: 'port',
|
|
124
|
-
label: 'port'
|
|
125
|
-
},
|
|
126
|
-
{
|
|
127
|
-
type: 'string',
|
|
128
|
-
name: 'productName',
|
|
129
|
-
label: 'product-name'
|
|
130
|
-
},
|
|
131
|
-
{
|
|
132
|
-
type: 'string',
|
|
133
|
-
name: 'buildNumber',
|
|
134
|
-
label: 'build-number'
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
type: 'string',
|
|
138
|
-
name: 'buildDate',
|
|
139
|
-
label: 'build-date'
|
|
140
|
-
}
|
|
141
|
-
]
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
ConnectionManager.registerConnector('opc-ua-server', new OPCUAServerConnector())
|
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
OPCUAClient,
|
|
3
|
-
BrowseResult,
|
|
4
|
-
ReferenceDescription,
|
|
5
|
-
AttributeIds,
|
|
6
|
-
StatusCodes,
|
|
7
|
-
TimestampsToReturn,
|
|
8
|
-
DataValue,
|
|
9
|
-
DataType,
|
|
10
|
-
StatusCode,
|
|
11
|
-
ClientMonitoredItem,
|
|
12
|
-
Variant
|
|
13
|
-
} from 'node-opcua'
|
|
14
|
-
|
|
15
|
-
import { Connection, ConnectionManager, Connector } from '@things-factory/integration-base'
|
|
16
|
-
|
|
17
|
-
export class OPCUAConnector implements Connector {
|
|
18
|
-
async ready(connectionConfigs) {
|
|
19
|
-
await Promise.all(connectionConfigs.map(this.connect))
|
|
20
|
-
|
|
21
|
-
ConnectionManager.logger.info('opc-ua connections are ready')
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
async connect(config) {
|
|
25
|
-
var {
|
|
26
|
-
name,
|
|
27
|
-
endpoint,
|
|
28
|
-
params: {
|
|
29
|
-
maxRetry = 2,
|
|
30
|
-
initialDelay = 2000,
|
|
31
|
-
maxDelay = 10 * 1000,
|
|
32
|
-
requestedPublishingInterval = 1000,
|
|
33
|
-
requestedLifetimeCount = 100,
|
|
34
|
-
requestedMaxKeepAliveCount = 20,
|
|
35
|
-
maxNotificationsPerPublish = 10,
|
|
36
|
-
publishingEnabled = true,
|
|
37
|
-
priority = 10
|
|
38
|
-
}
|
|
39
|
-
} = config
|
|
40
|
-
|
|
41
|
-
const client = OPCUAClient.create({
|
|
42
|
-
endpoint_must_exist: false,
|
|
43
|
-
connectionStrategy: {
|
|
44
|
-
maxRetry,
|
|
45
|
-
initialDelay,
|
|
46
|
-
maxDelay
|
|
47
|
-
}
|
|
48
|
-
})
|
|
49
|
-
|
|
50
|
-
client.on('backoff', () => ConnectionManager.logger.info('retrying connection'))
|
|
51
|
-
|
|
52
|
-
await client.connect(endpoint)
|
|
53
|
-
|
|
54
|
-
const session = await client.createSession()
|
|
55
|
-
|
|
56
|
-
const browseResult: BrowseResult = (await session.browse('RootFolder')) as BrowseResult
|
|
57
|
-
|
|
58
|
-
ConnectionManager.logger.info(
|
|
59
|
-
browseResult.references.map((r: ReferenceDescription) => r.browseName.toString()).join('\n')
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
const subscription = await session.createSubscription2({
|
|
63
|
-
requestedPublishingInterval,
|
|
64
|
-
requestedLifetimeCount,
|
|
65
|
-
requestedMaxKeepAliveCount,
|
|
66
|
-
maxNotificationsPerPublish,
|
|
67
|
-
publishingEnabled,
|
|
68
|
-
priority
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
subscription
|
|
72
|
-
.on('started', () =>
|
|
73
|
-
ConnectionManager.logger.info('subscription started - subscriptionId=', subscription.subscriptionId)
|
|
74
|
-
)
|
|
75
|
-
.on('keepalive', () => ConnectionManager.logger.info('keepalive'))
|
|
76
|
-
.on('terminated', () => ConnectionManager.logger.info('subscription terminated'))
|
|
77
|
-
|
|
78
|
-
try {
|
|
79
|
-
ConnectionManager.addConnectionInstance(config, {
|
|
80
|
-
read: async function (node, attribute, { logger }): Promise<DataValue> {
|
|
81
|
-
const dataValue = await session.read({ nodeId: node, attributeId: Number(attribute) })
|
|
82
|
-
if (dataValue.statusCode !== StatusCodes.Good) {
|
|
83
|
-
logger.info('Could not read ', node)
|
|
84
|
-
}
|
|
85
|
-
logger.info(` dataValue = ${dataValue.value.toString()}`)
|
|
86
|
-
|
|
87
|
-
return dataValue
|
|
88
|
-
},
|
|
89
|
-
write: async function (node, dataValue, dataType, { logger }): Promise<StatusCode> {
|
|
90
|
-
const resultVariant = new Variant({
|
|
91
|
-
dataType,
|
|
92
|
-
value: dataValue
|
|
93
|
-
})
|
|
94
|
-
|
|
95
|
-
const statusCode = await session.write({
|
|
96
|
-
nodeId: node,
|
|
97
|
-
attributeId: AttributeIds.Value,
|
|
98
|
-
value: {
|
|
99
|
-
value: resultVariant
|
|
100
|
-
}
|
|
101
|
-
})
|
|
102
|
-
|
|
103
|
-
logger.info('statusCode = ', statusCode.name)
|
|
104
|
-
return statusCode
|
|
105
|
-
},
|
|
106
|
-
startMonitor: async function (
|
|
107
|
-
node,
|
|
108
|
-
callback: (dataValue: DataValue) => void,
|
|
109
|
-
options: { samplingInterval: number; discardOldest: boolean; queueSize: number },
|
|
110
|
-
{ logger }
|
|
111
|
-
): Promise<ClientMonitoredItem> {
|
|
112
|
-
const { samplingInterval = 100, discardOldest = true, queueSize = 10 } = options || {}
|
|
113
|
-
const monitoredItem = await subscription.monitor(
|
|
114
|
-
{
|
|
115
|
-
nodeId: node,
|
|
116
|
-
attributeId: AttributeIds.Value
|
|
117
|
-
},
|
|
118
|
-
{
|
|
119
|
-
samplingInterval,
|
|
120
|
-
discardOldest,
|
|
121
|
-
queueSize
|
|
122
|
-
},
|
|
123
|
-
TimestampsToReturn.Both
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
monitoredItem.on('changed', callback)
|
|
127
|
-
return monitoredItem
|
|
128
|
-
},
|
|
129
|
-
stopMonitor: async function (monitoredItem, { logger }): Promise<void> {
|
|
130
|
-
await monitoredItem.terminate()
|
|
131
|
-
return monitoredItem
|
|
132
|
-
},
|
|
133
|
-
close: async function (): Promise<void> {
|
|
134
|
-
await subscription?.terminate()
|
|
135
|
-
await session?.close()
|
|
136
|
-
await client?.disconnect()
|
|
137
|
-
}
|
|
138
|
-
})
|
|
139
|
-
|
|
140
|
-
ConnectionManager.logger.info(`opc-ua connection(${name}:${endpoint}) is connected`)
|
|
141
|
-
} catch (error) {
|
|
142
|
-
ConnectionManager.logger.info(`opc-ua connection(${name}:${endpoint}) failed to connect`)
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
async disconnect(connection: Connection) {
|
|
147
|
-
var { close } = ConnectionManager.removeConnectionInstance(connection)
|
|
148
|
-
await close()
|
|
149
|
-
|
|
150
|
-
ConnectionManager.logger.info(`opc-ua connection(${connection.name}) is disconnected`)
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
get parameterSpec() {
|
|
154
|
-
return [
|
|
155
|
-
{
|
|
156
|
-
type: 'number',
|
|
157
|
-
name: 'maxRetry',
|
|
158
|
-
label: 'max-retry'
|
|
159
|
-
},
|
|
160
|
-
{
|
|
161
|
-
type: 'number',
|
|
162
|
-
name: 'initialDelay',
|
|
163
|
-
label: 'initial-delay'
|
|
164
|
-
},
|
|
165
|
-
{
|
|
166
|
-
type: 'number',
|
|
167
|
-
name: 'maxDelay',
|
|
168
|
-
label: 'max-delay'
|
|
169
|
-
},
|
|
170
|
-
{
|
|
171
|
-
type: 'number',
|
|
172
|
-
name: 'requestedPublishingInterval',
|
|
173
|
-
label: 'requested-publishing-interval'
|
|
174
|
-
},
|
|
175
|
-
{
|
|
176
|
-
type: 'number',
|
|
177
|
-
name: 'requestedLifetimeCount',
|
|
178
|
-
label: 'requested-lifetime-count'
|
|
179
|
-
},
|
|
180
|
-
{
|
|
181
|
-
type: 'number',
|
|
182
|
-
name: 'requestedMaxKeepAliveCount',
|
|
183
|
-
label: 'requested-max-keep-alive-count'
|
|
184
|
-
},
|
|
185
|
-
{
|
|
186
|
-
type: 'number',
|
|
187
|
-
name: 'maxNotificationsPerPublish',
|
|
188
|
-
label: 'max-notifications-per-publish'
|
|
189
|
-
},
|
|
190
|
-
{
|
|
191
|
-
type: 'boolean',
|
|
192
|
-
name: 'publishingEnabled',
|
|
193
|
-
label: 'publishing-enabled'
|
|
194
|
-
},
|
|
195
|
-
{
|
|
196
|
-
type: 'number',
|
|
197
|
-
name: 'priority',
|
|
198
|
-
label: 'priority'
|
|
199
|
-
}
|
|
200
|
-
]
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
get taskPrefixes() {
|
|
204
|
-
return ['opc-ua']
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
get help() {
|
|
208
|
-
return 'integration/connector/opc-ua'
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
ConnectionManager.registerConnector('opc-ua', new OPCUAConnector())
|
package/server/engine/index.ts
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { ConnectionManager, TaskRegistry } from '@things-factory/integration-base'
|
|
2
|
-
import { DataType, DataValue, AttributeIds } from 'node-opcua'
|
|
3
|
-
import { DataTypeString } from './utils'
|
|
4
|
-
|
|
5
|
-
async function OPCUARead(step, { logger, domain }) {
|
|
6
|
-
var {
|
|
7
|
-
connection,
|
|
8
|
-
params: { node, attribute }
|
|
9
|
-
} = step
|
|
10
|
-
|
|
11
|
-
var client = ConnectionManager.getConnectionInstanceByName(domain, connection)
|
|
12
|
-
if (!client) {
|
|
13
|
-
throw new Error(`no connection : ${connection}`)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
if (!node) {
|
|
17
|
-
throw new Error('node parameter should be defined')
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
var { read } = client
|
|
21
|
-
var content: DataValue = await read(node, attribute, { logger })
|
|
22
|
-
|
|
23
|
-
return {
|
|
24
|
-
data: {
|
|
25
|
-
dataType: DataTypeString[content?.value.dataType],
|
|
26
|
-
value: content?.value.value
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
OPCUARead.parameterSpec = [
|
|
32
|
-
{
|
|
33
|
-
type: 'string',
|
|
34
|
-
name: 'node',
|
|
35
|
-
label: 'node'
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
type: 'select',
|
|
39
|
-
label: 'attribute',
|
|
40
|
-
name: 'attribute',
|
|
41
|
-
property: {
|
|
42
|
-
options: [
|
|
43
|
-
{ display: 'Value', value: AttributeIds.Value },
|
|
44
|
-
{ display: 'DataType', value: AttributeIds.DataType },
|
|
45
|
-
{ display: 'NodeId', value: AttributeIds.NodeId },
|
|
46
|
-
{ display: 'NodeClass', value: AttributeIds.NodeClass },
|
|
47
|
-
{ display: 'BrowseName', value: AttributeIds.BrowseName },
|
|
48
|
-
{ display: 'DisplayName', value: AttributeIds.DisplayName },
|
|
49
|
-
{ display: 'Description', value: AttributeIds.Description },
|
|
50
|
-
{ display: 'WriteMask', value: AttributeIds.WriteMask },
|
|
51
|
-
{ display: 'UserWriteMask', value: AttributeIds.UserWriteMask },
|
|
52
|
-
{ display: 'IsAbstract', value: AttributeIds.IsAbstract },
|
|
53
|
-
{ display: 'Symmetric', value: AttributeIds.Symmetric },
|
|
54
|
-
{ display: 'InverseName', value: AttributeIds.InverseName },
|
|
55
|
-
{ display: 'ContainsNoLoops', value: AttributeIds.ContainsNoLoops },
|
|
56
|
-
{ display: 'EventNotifier', value: AttributeIds.EventNotifier },
|
|
57
|
-
{ display: 'ValueRank', value: AttributeIds.ValueRank },
|
|
58
|
-
{ display: 'ArrayDimensions', value: AttributeIds.ArrayDimensions },
|
|
59
|
-
{ display: 'AccessLevel', value: AttributeIds.AccessLevel },
|
|
60
|
-
{ display: 'UserAccessLevel', value: AttributeIds.UserAccessLevel },
|
|
61
|
-
{ display: 'MinimumSamplingInterval', value: AttributeIds.MinimumSamplingInterval },
|
|
62
|
-
{ display: 'Historizing', value: AttributeIds.Historizing },
|
|
63
|
-
{ display: 'Executable', value: AttributeIds.Executable },
|
|
64
|
-
{ display: 'UserExecutable', value: AttributeIds.UserExecutable },
|
|
65
|
-
{ display: 'DataTypeDefinition', value: AttributeIds.DataTypeDefinition },
|
|
66
|
-
{ display: 'RolePermissions', value: AttributeIds.RolePermissions },
|
|
67
|
-
{ display: 'UserRolePermissions', value: AttributeIds.UserRolePermissions },
|
|
68
|
-
{ display: 'AccessRestrictions', value: AttributeIds.AccessRestrictions },
|
|
69
|
-
{ display: 'AccessLevelEx', value: AttributeIds.AccessLevelEx }
|
|
70
|
-
]
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
]
|
|
74
|
-
|
|
75
|
-
OPCUARead.help = 'integration/task/opc-ua-read'
|
|
76
|
-
|
|
77
|
-
TaskRegistry.registerTaskHandler('opc-ua-read', OPCUARead)
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { ConnectionManager, TaskRegistry } from '@things-factory/integration-base'
|
|
2
|
-
import { DataValue } from 'node-opcua'
|
|
3
|
-
import { sleep } from '@things-factory/utils'
|
|
4
|
-
|
|
5
|
-
async function OPCUAStartMonitor(step, context) {
|
|
6
|
-
var {
|
|
7
|
-
connection,
|
|
8
|
-
params: { node, samplingInterval, discardOldest, queueSize }
|
|
9
|
-
} = step
|
|
10
|
-
|
|
11
|
-
const { logger, domain, closures, __opcua_moinitor } = context
|
|
12
|
-
if (!__opcua_moinitor) {
|
|
13
|
-
context.__opcua_moinitor = {}
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
var client = ConnectionManager.getConnectionInstanceByName(domain, connection)
|
|
17
|
-
if (!client) {
|
|
18
|
-
throw new Error(`no connection : ${connection}`)
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
if (!context.__opcua_moinitor[node]) {
|
|
22
|
-
var MONINTORED_VALUE
|
|
23
|
-
context.__opcua_moinitor[node] = async () => {
|
|
24
|
-
while (!MONINTORED_VALUE) {
|
|
25
|
-
await sleep(100)
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
var monitoringValue = MONINTORED_VALUE
|
|
29
|
-
|
|
30
|
-
MONINTORED_VALUE = null
|
|
31
|
-
|
|
32
|
-
return monitoringValue
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
var { startMonitor, stopMonitor } = client
|
|
36
|
-
var monitoredItem = await startMonitor(
|
|
37
|
-
node,
|
|
38
|
-
(dataValue: DataValue) => {
|
|
39
|
-
MONINTORED_VALUE = dataValue?.value.value
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
samplingInterval,
|
|
43
|
-
discardOldest,
|
|
44
|
-
queueSize
|
|
45
|
-
},
|
|
46
|
-
{ logger }
|
|
47
|
-
)
|
|
48
|
-
|
|
49
|
-
closures.push(async () => {
|
|
50
|
-
try {
|
|
51
|
-
monitoredItem && (await stopMonitor(monitoredItem, { logger }))
|
|
52
|
-
} catch (e) {
|
|
53
|
-
logger.error(e)
|
|
54
|
-
}
|
|
55
|
-
})
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
var monitoringValue = await context.__opcua_moinitor[node]()
|
|
59
|
-
|
|
60
|
-
return { data: monitoringValue }
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
OPCUAStartMonitor.parameterSpec = [
|
|
64
|
-
{
|
|
65
|
-
type: 'string',
|
|
66
|
-
name: 'node',
|
|
67
|
-
label: 'node'
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
type: 'number',
|
|
71
|
-
name: 'samplingInterval',
|
|
72
|
-
label: 'sampling-interval'
|
|
73
|
-
},
|
|
74
|
-
{
|
|
75
|
-
type: 'boolean',
|
|
76
|
-
name: 'discardOldest',
|
|
77
|
-
label: 'discard-oldest'
|
|
78
|
-
},
|
|
79
|
-
{
|
|
80
|
-
type: 'number',
|
|
81
|
-
name: 'queueSize',
|
|
82
|
-
label: 'queue-size'
|
|
83
|
-
}
|
|
84
|
-
]
|
|
85
|
-
|
|
86
|
-
OPCUAStartMonitor.help = 'integration/task/opc-ua-start-monitor'
|
|
87
|
-
|
|
88
|
-
TaskRegistry.registerTaskHandler('opc-ua-start-monitor', OPCUAStartMonitor)
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { access } from '@things-factory/utils'
|
|
2
|
-
import { ConnectionManager, TaskRegistry } from '@things-factory/integration-base'
|
|
3
|
-
|
|
4
|
-
import { ClientMonitoredItem } from 'node-opcua'
|
|
5
|
-
|
|
6
|
-
async function OPCUAStopMonitor(step, { logger, domain, data }) {
|
|
7
|
-
var {
|
|
8
|
-
connection,
|
|
9
|
-
params: { monitorItem }
|
|
10
|
-
} = step
|
|
11
|
-
|
|
12
|
-
var client = ConnectionManager.getConnectionInstanceByName(domain, connection)
|
|
13
|
-
if (!client) {
|
|
14
|
-
throw new Error(`no connection : ${connection}`)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const item = access(monitorItem, data)
|
|
18
|
-
|
|
19
|
-
var { stopMonitor } = client
|
|
20
|
-
var monitoredItem: ClientMonitoredItem = await stopMonitor(item, { logger })
|
|
21
|
-
|
|
22
|
-
return {
|
|
23
|
-
data: monitoredItem.statusCode
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
OPCUAStopMonitor.parameterSpec = [
|
|
28
|
-
{
|
|
29
|
-
type: 'scenario-step-input',
|
|
30
|
-
name: 'monitorItem',
|
|
31
|
-
label: 'monitor-item'
|
|
32
|
-
}
|
|
33
|
-
]
|
|
34
|
-
|
|
35
|
-
OPCUAStopMonitor.help = 'integration/task/opc-ua-stop-monitor'
|
|
36
|
-
|
|
37
|
-
TaskRegistry.registerTaskHandler('opc-ua-stop-monitor', OPCUAStopMonitor)
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import { access } from '@things-factory/utils'
|
|
2
|
-
import { ConnectionManager, TaskRegistry } from '@things-factory/integration-base'
|
|
3
|
-
import { StatusCode, DataType } from 'node-opcua'
|
|
4
|
-
|
|
5
|
-
async function OPCUAWrite(step, { logger, domain, data }) {
|
|
6
|
-
var {
|
|
7
|
-
connection,
|
|
8
|
-
params: { node, accessor, type }
|
|
9
|
-
} = step
|
|
10
|
-
|
|
11
|
-
var client = ConnectionManager.getConnectionInstanceByName(domain, connection)
|
|
12
|
-
if (!client) {
|
|
13
|
-
throw new Error(`no connection : ${connection}`)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const value = access(accessor, data)
|
|
17
|
-
|
|
18
|
-
var { write } = client
|
|
19
|
-
var content: StatusCode = await write(node, value, type, { logger })
|
|
20
|
-
|
|
21
|
-
return {
|
|
22
|
-
data: {
|
|
23
|
-
name: content.name,
|
|
24
|
-
description: content.description,
|
|
25
|
-
result: content.isGood()
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
OPCUAWrite.parameterSpec = [
|
|
31
|
-
{
|
|
32
|
-
type: 'string',
|
|
33
|
-
name: 'node',
|
|
34
|
-
label: 'node'
|
|
35
|
-
},
|
|
36
|
-
{
|
|
37
|
-
type: 'scenario-step-input',
|
|
38
|
-
name: 'accessor',
|
|
39
|
-
label: 'accessor'
|
|
40
|
-
},
|
|
41
|
-
{
|
|
42
|
-
type: 'select',
|
|
43
|
-
label: 'type',
|
|
44
|
-
name: 'type',
|
|
45
|
-
property: {
|
|
46
|
-
options: [
|
|
47
|
-
{ display: 'Null', value: DataType.Null },
|
|
48
|
-
{ display: 'Boolean', value: DataType.Boolean },
|
|
49
|
-
{ display: 'SByte', value: DataType.SByte },
|
|
50
|
-
{ display: 'Byte', value: DataType.Byte },
|
|
51
|
-
{ display: 'Int16', value: DataType.Int16 },
|
|
52
|
-
{ display: 'UInt16', value: DataType.UInt16 },
|
|
53
|
-
{ display: 'Int32', value: DataType.Int32 },
|
|
54
|
-
{ display: 'UInt32', value: DataType.UInt32 },
|
|
55
|
-
{ display: 'Int64', value: DataType.Int64 },
|
|
56
|
-
{ display: 'UInt64', value: DataType.UInt64 },
|
|
57
|
-
{ display: 'Float', value: DataType.Float },
|
|
58
|
-
{ display: 'Double', value: DataType.Double },
|
|
59
|
-
{ display: 'String', value: DataType.String },
|
|
60
|
-
{ display: 'DateTime', value: DataType.DateTime },
|
|
61
|
-
{ display: 'Guid', value: DataType.Guid },
|
|
62
|
-
{ display: 'ByteString', value: DataType.ByteString },
|
|
63
|
-
{ display: 'XmlElement', value: DataType.XmlElement },
|
|
64
|
-
{ display: 'NodeId', value: DataType.NodeId },
|
|
65
|
-
{ display: 'ExpandedNodeId', value: DataType.ExpandedNodeId },
|
|
66
|
-
{ display: 'StatusCode', value: DataType.StatusCode },
|
|
67
|
-
{ display: 'QualifiedName', value: DataType.QualifiedName },
|
|
68
|
-
{ display: 'LocalizedText', value: DataType.LocalizedText },
|
|
69
|
-
{ display: 'ExtensionObject', value: DataType.ExtensionObject },
|
|
70
|
-
{ display: 'Variant', value: DataType.Variant },
|
|
71
|
-
{ display: 'DataValue', value: DataType.DataValue },
|
|
72
|
-
{ display: 'DiagnosticInfo', value: DataType.DiagnosticInfo }
|
|
73
|
-
]
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
]
|
|
77
|
-
|
|
78
|
-
OPCUAWrite.help = 'integration/task/opc-ua-write'
|
|
79
|
-
|
|
80
|
-
TaskRegistry.registerTaskHandler('opc-ua-write', OPCUAWrite)
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { DataType } from 'node-opcua'
|
|
2
|
-
|
|
3
|
-
export const DataTypeString = {
|
|
4
|
-
[DataType.Null]: 'Null',
|
|
5
|
-
[DataType.Boolean]: 'Boolean',
|
|
6
|
-
[DataType.SByte]: 'SByte',
|
|
7
|
-
[DataType.Byte]: 'Byte',
|
|
8
|
-
[DataType.Int16]: 'Int16',
|
|
9
|
-
[DataType.UInt16]: 'UInt16',
|
|
10
|
-
[DataType.Int32]: 'Int32',
|
|
11
|
-
[DataType.UInt32]: 'UInt32',
|
|
12
|
-
[DataType.Int64]: 'Int64',
|
|
13
|
-
[DataType.UInt64]: 'UInt64',
|
|
14
|
-
[DataType.Float]: 'Float',
|
|
15
|
-
[DataType.Double]: 'Double',
|
|
16
|
-
[DataType.String]: 'String',
|
|
17
|
-
[DataType.DateTime]: 'DateTime',
|
|
18
|
-
[DataType.Guid]: 'Guid',
|
|
19
|
-
[DataType.ByteString]: 'ByteString',
|
|
20
|
-
[DataType.XmlElement]: 'XmlElement',
|
|
21
|
-
[DataType.NodeId]: 'NodeId',
|
|
22
|
-
[DataType.ExpandedNodeId]: 'ExpandedNodeId',
|
|
23
|
-
[DataType.StatusCode]: 'StatusCode',
|
|
24
|
-
[DataType.QualifiedName]: 'QualifiedName',
|
|
25
|
-
[DataType.LocalizedText]: 'LocalizedText',
|
|
26
|
-
[DataType.ExtensionObject]: 'ExtensionObject',
|
|
27
|
-
[DataType.DataValue]: 'DataValue',
|
|
28
|
-
[DataType.Variant]: 'Variant',
|
|
29
|
-
[DataType.DiagnosticInfo]: 'DiagnosticInfo'
|
|
30
|
-
}
|
package/server/index.ts
DELETED