node-opcua-client-proxy 2.54.0 → 2.57.0

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.
@@ -1,361 +1,369 @@
1
- /**
2
- * @module node-opcua-client-proxy
3
- */
4
- // tslint:disable:no-shadowed-variable
5
- import * as async from "async";
6
- import { assert } from "node-opcua-assert";
7
-
8
- import { AttributeIds, NodeClass, coerceAccessLevelFlag } from "node-opcua-data-model";
9
- import { NodeId, coerceNodeId } from "node-opcua-nodeid";
10
- import { DataValue, TimestampsToReturn } from "node-opcua-data-value";
11
- import { NodeIdLike } from "node-opcua-nodeid";
12
- import { CreateSubscriptionRequestOptions, MonitoringParametersOptions } from "node-opcua-service-subscription";
13
- import { StatusCodes, CallbackT, StatusCode } from "node-opcua-status-code";
14
- import { ErrorCallback } from "node-opcua-status-code";
15
- import { IBasicSession } from "node-opcua-pseudo-session";
16
- import { ReadValueIdOptions } from "node-opcua-service-read";
17
- import { Variant } from "node-opcua-variant";
18
-
19
- import { readUAStructure } from "./object_explorer";
20
- import { makeRefId } from "./proxy";
21
- import { ProxyBaseNode } from "./proxy_base_node";
22
- import { ProxyObject } from "./proxy_object";
23
- import { ProxyStateMachineType } from "./state_machine_proxy";
24
- import { WriteValueOptions } from "node-opcua-service-write";
25
-
26
- function getObject(proxyManager: UAProxyManager, nodeId: NodeIdLike | NodeId, options: any, callback: any) {
27
- const session = proxyManager.session;
28
-
29
- nodeId = coerceNodeId(nodeId) as NodeId;
30
-
31
- if (nodeId.isEmpty()) {
32
- setImmediate(() => {
33
- callback(new Error(" Invalid empty node in getObject"));
34
- });
35
- return;
36
- }
37
-
38
- const nodesToRead = [
39
- {
40
- attributeId: AttributeIds.BrowseName,
41
- nodeId
42
- },
43
- {
44
- attributeId: AttributeIds.Description,
45
- nodeId
46
- },
47
- {
48
- attributeId: AttributeIds.NodeClass,
49
- nodeId
50
- }
51
- ];
52
-
53
- function read_accessLevels(clientObject: any, callback: ErrorCallback) {
54
- const nodesToRead = [
55
- {
56
- attributeId: AttributeIds.Value,
57
- nodeId
58
- },
59
- {
60
- attributeId: AttributeIds.UserAccessLevel,
61
- nodeId
62
- },
63
- {
64
- attributeId: AttributeIds.AccessLevel,
65
- nodeId
66
- }
67
- ];
68
-
69
- session.read(nodesToRead, (err: Error | null, dataValues?: DataValue[]) => {
70
- if (err) {
71
- return callback(err);
72
- }
73
-
74
- dataValues = dataValues || [];
75
-
76
- if (dataValues[0].statusCode === StatusCodes.Good) {
77
- clientObject.dataValue = dataValues[0].value;
78
- }
79
- if (dataValues[1].statusCode === StatusCodes.Good) {
80
- clientObject.userAccessLevel = coerceAccessLevelFlag(dataValues[1].value.value);
81
- }
82
- if (dataValues[2].statusCode === StatusCodes.Good) {
83
- clientObject.accessLevel = coerceAccessLevelFlag(dataValues[2].value.value);
84
- }
85
- callback(err!);
86
- });
87
- }
88
-
89
- let clientObject: any;
90
-
91
- async.series(
92
- [
93
- (callback: ErrorCallback) => {
94
- // readAttributes like browseName and references
95
- session.read(nodesToRead, (err: Error | null, dataValues?: DataValue[]) => {
96
- if (!err) {
97
- dataValues = dataValues!;
98
-
99
- if (dataValues[0].statusCode === StatusCodes.BadNodeIdUnknown) {
100
- // xx console.log(" INVALID NODE ", nodeId.toString());
101
- return callback(new Error("Invalid Node " + nodeId.toString()));
102
- }
103
-
104
- clientObject = new ProxyObject(proxyManager, nodeId as NodeId);
105
-
106
- /// x console.log("xxxx ,s",results.map(function(a){ return a.toString();}));
107
-
108
- clientObject.browseName = dataValues[0].value.value;
109
- clientObject.description = dataValues[1].value ? dataValues[1].value.value : "";
110
- clientObject.nodeClass = dataValues[2].value.value;
111
- // xx console.log("xxx nodeClass = ",clientObject.nodeClass.toString());
112
-
113
- if (clientObject.nodeClass === NodeClass.Variable) {
114
- return read_accessLevels(clientObject, callback);
115
- }
116
- }
117
- callback(err!);
118
- });
119
- },
120
-
121
- (callback: ErrorCallback) => {
122
- // install monitored item
123
- if (clientObject.nodeClass === NodeClass.Variable) {
124
- /*console.log(
125
- "xxxx -> monitoring",
126
- clientObject.nodeId.toString(),
127
- clientObject.nodeClass.toString(),
128
- clientObject.browseName.toString()
129
- );
130
- */
131
- return proxyManager._monitor_value(clientObject, callback);
132
- }
133
- callback();
134
- },
135
-
136
- (callback: ErrorCallback) => {
137
- readUAStructure(proxyManager, clientObject, callback);
138
- }
139
-
140
- //
141
- ],
142
- (err) => {
143
- // istanbul ignore next
144
- if (err) {
145
- return callback(err);
146
- }
147
- callback(null, clientObject);
148
- }
149
- );
150
- }
151
-
152
- export interface IClientSubscription {
153
- monitor(
154
- itemToMonitor: ReadValueIdOptions,
155
- monitoringParameters: MonitoringParametersOptions,
156
- timestampToReturn: TimestampsToReturn,
157
- callback: CallbackT<IClientMonitoredItemBase>
158
- ): void;
159
-
160
- terminate(callback: () => void): void;
161
- on(eventName: "terminated", eventHandler: () => void): void;
162
- }
163
-
164
- export interface IClientMonitoredItemBase {
165
- on(eventName: "changed", eventHandler: (data: DataValue | Variant[]) => void): void;
166
- }
167
- export interface IBasicSessionWithSubscription extends IBasicSession {
168
- createSubscription2(options: CreateSubscriptionRequestOptions, callback: CallbackT<IClientSubscription>): void;
169
- }
170
-
171
- // tslint:disable-next-line: max-classes-per-file
172
- export class UAProxyManager {
173
- public readonly session: IBasicSessionWithSubscription;
174
- public subscription?: IClientSubscription;
175
- private _map: any;
176
-
177
- constructor(session: IBasicSessionWithSubscription) {
178
- this.session = session;
179
- this._map = {};
180
- // create a subscription
181
- }
182
-
183
- public async start(): Promise<void>;
184
- public start(callback: (err?: Error) => void): void;
185
- public start(...args: any[]): any {
186
- const callback = args[0] as (err?: Error) => void;
187
-
188
- const createSubscriptionRequest: CreateSubscriptionRequestOptions = {
189
- maxNotificationsPerPublish: 1000,
190
- priority: 10,
191
- publishingEnabled: true,
192
- requestedLifetimeCount: 6000,
193
- requestedMaxKeepAliveCount: 100,
194
- requestedPublishingInterval: 100
195
- };
196
-
197
- this.session.createSubscription2(createSubscriptionRequest, (err: Error | null, subscription?: IClientSubscription) => {
198
- if (err) {
199
- return callback(err);
200
- }
201
- this.subscription = subscription!;
202
- this.subscription!.on("terminated", () => {
203
- this.subscription = undefined;
204
- });
205
- callback();
206
- });
207
- }
208
-
209
- public async stop(): Promise<void>;
210
- public stop(callback: (err?: Error) => void): void;
211
-
212
- public stop(...args: any[]): any {
213
- const callback = args[0] as (err?: Error) => void;
214
-
215
- if (this.subscription) {
216
- this.subscription.terminate(() => {
217
- this.subscription = undefined;
218
- callback();
219
- });
220
- } else {
221
- callback(new Error("UAProxyManager already stopped ?"));
222
- }
223
- }
224
-
225
- // todo: rename getObject as getNode
226
- public async getObject(nodeId: NodeIdLike): Promise<any>;
227
-
228
- public getObject(nodeId: NodeIdLike, callback: (err: Error | null, object?: any) => void): void;
229
- public getObject(...args: any[]): any {
230
- const nodeId = args[0] as NodeIdLike;
231
- const callback = args[1] as (err: Error | null, object?: any) => void;
232
-
233
- let options: any = {};
234
-
235
- setImmediate(() => {
236
- options = options || {};
237
- options.depth = options.depth || 1;
238
-
239
- const key = nodeId.toString();
240
- // the object already exist in the map ?
241
- if (this._map.hasOwnProperty(key)) {
242
- return callback(null, this._map[key]);
243
- }
244
-
245
- getObject(this, nodeId, options, (err: Error | null, obj?: ProxyBaseNode) => {
246
- if (!err) {
247
- this._map[key] = obj;
248
- }
249
- callback(err, obj);
250
- });
251
- });
252
- }
253
-
254
- public _monitor_value(proxyObject: any, callback: ErrorCallback) {
255
- if (!this.subscription) {
256
- // debugLog("cannot monitor _monitor_value: no subscription");
257
- // some server do not provide subscription support, do not treat this as an error.
258
- return callback(); // new Error("No subscription"));
259
- }
260
-
261
- const itemToMonitor: ReadValueIdOptions = {
262
- // ReadValueId
263
- attributeId: AttributeIds.Value,
264
- nodeId: proxyObject.nodeId
265
- };
266
- const monitoringParameters: MonitoringParametersOptions = {
267
- // MonitoringParameters
268
- discardOldest: true,
269
- queueSize: 10,
270
- samplingInterval: 0 /* event-based */
271
- };
272
- const requestedParameters = TimestampsToReturn.Both;
273
-
274
- this.subscription.monitor(
275
- itemToMonitor,
276
- monitoringParameters,
277
- requestedParameters,
278
-
279
- (err: Error | null, monitoredItem?: IClientMonitoredItemBase) => {
280
- Object.defineProperty(proxyObject, "__monitoredItem", { value: monitoredItem, enumerable: false });
281
- proxyObject.__monitoredItem.on("changed", (dataValue: DataValue) => {
282
- proxyObject.dataValue = dataValue;
283
- proxyObject.emit("value_changed", dataValue);
284
- });
285
- proxyObject.__monitoredItem.on("err", (err: Error) => {
286
- // tslint:disable-next-line: no-console
287
- console.log("Proxy: cannot monitor variable ", itemToMonitor.nodeId?.toString(), err.message);
288
- });
289
- callback(err!);
290
- }
291
- );
292
- }
293
-
294
- public _monitor_execution_flag(proxyObject: any, callback: (err?: Error) => void) {
295
- // note : proxyObject must wrap a method
296
- assert(proxyObject.nodeId instanceof NodeId);
297
-
298
- if (!this.subscription) {
299
- // some server do not provide subscription support, do not treat this as an error.
300
- return callback(); // new Error("No subscription"));
301
- }
302
-
303
- const itemToMonitor = {
304
- // ReadValueId
305
- attributeId: AttributeIds.Executable,
306
- nodeId: proxyObject.nodeId
307
- };
308
-
309
- const monitoringParameters = {
310
- // MonitoringParameters
311
- discardOldest: true,
312
- queueSize: 10,
313
- samplingInterval: 0 /* event-based */
314
- };
315
- const requestedParameters = TimestampsToReturn.Neither;
316
-
317
- this.subscription.monitor(
318
- itemToMonitor,
319
- monitoringParameters,
320
- requestedParameters,
321
- (err: Error | null, monitoredItem?: IClientMonitoredItemBase) => {
322
- Object.defineProperty(proxyObject, "__monitoredItem_execution_flag", {
323
- value: monitoredItem,
324
-
325
- enumerable: false
326
- });
327
-
328
- proxyObject.__monitoredItem_execution_flag.on("changed", (dataValue: DataValue) => {
329
- proxyObject.executableFlag = dataValue.value.value;
330
- });
331
-
332
- callback(err!);
333
- }
334
- );
335
- }
336
-
337
- public getStateMachineType(
338
- nodeId: NodeIdLike,
339
- callback: (err: Error | null, stateMachineType?: ProxyStateMachineType) => void
340
- ) {
341
- if (typeof nodeId === "string") {
342
- const org_nodeId = nodeId;
343
- nodeId = makeRefId(nodeId);
344
- }
345
-
346
- this.getObject(nodeId, (err: Error | null, obj: any) => {
347
- // read fromState and toState Reference on
348
- let stateMachineType;
349
- if (!err) {
350
- stateMachineType = new ProxyStateMachineType(obj);
351
- }
352
- callback(err, stateMachineType);
353
- });
354
- }
355
- }
356
-
357
- // tslint:disable-next-line:no-var-requires
358
- const thenify = require("thenify");
359
- UAProxyManager.prototype.start = thenify.withCallback(UAProxyManager.prototype.start);
360
- UAProxyManager.prototype.stop = thenify.withCallback(UAProxyManager.prototype.stop);
361
- UAProxyManager.prototype.getObject = thenify.withCallback(UAProxyManager.prototype.getObject);
1
+ /**
2
+ * @module node-opcua-client-proxy
3
+ */
4
+ // tslint:disable:no-shadowed-variable
5
+ import { EventEmitter } from "stream";
6
+ import * as async from "async";
7
+ import { assert } from "node-opcua-assert";
8
+
9
+ import { AttributeIds, NodeClass, coerceAccessLevelFlag } from "node-opcua-data-model";
10
+ import { NodeId, coerceNodeId } from "node-opcua-nodeid";
11
+ import { DataValue, TimestampsToReturn } from "node-opcua-data-value";
12
+ import { NodeIdLike } from "node-opcua-nodeid";
13
+ import { CreateSubscriptionRequestOptions, MonitoringParametersOptions } from "node-opcua-service-subscription";
14
+ import { StatusCodes, CallbackT, StatusCode } from "node-opcua-status-code";
15
+ import { ErrorCallback } from "node-opcua-status-code";
16
+ import { IBasicSession } from "node-opcua-pseudo-session";
17
+ import { ReadValueIdOptions } from "node-opcua-service-read";
18
+ import { Variant } from "node-opcua-variant";
19
+
20
+ import { readUAStructure } from "./object_explorer";
21
+ import { makeRefId } from "./proxy";
22
+ import { ProxyBaseNode } from "./proxy_base_node";
23
+ import { ProxyObject } from "./proxy_object";
24
+ import { ProxyStateMachineType } from "./state_machine_proxy";
25
+
26
+ export interface IProxy1 {
27
+ nodeId: NodeId;
28
+ executableFlag?: boolean;
29
+ __monitoredItem_execution_flag?: EventEmitter;
30
+ __monitoredItem?: EventEmitter;
31
+ }
32
+ export interface IProxy extends EventEmitter, IProxy1 {
33
+ dataValue: DataValue;
34
+ }
35
+ function getObject(proxyManager: UAProxyManager, nodeId: NodeIdLike | NodeId, options: any, callback: any) {
36
+ const session = proxyManager.session;
37
+
38
+ nodeId = coerceNodeId(nodeId) as NodeId;
39
+
40
+ if (nodeId.isEmpty()) {
41
+ setImmediate(() => {
42
+ callback(new Error(" Invalid empty node in getObject"));
43
+ });
44
+ return;
45
+ }
46
+
47
+ const nodesToRead = [
48
+ {
49
+ attributeId: AttributeIds.BrowseName,
50
+ nodeId
51
+ },
52
+ {
53
+ attributeId: AttributeIds.Description,
54
+ nodeId
55
+ },
56
+ {
57
+ attributeId: AttributeIds.NodeClass,
58
+ nodeId
59
+ }
60
+ ];
61
+
62
+ function read_accessLevels(clientObject: any, callback: ErrorCallback) {
63
+ const nodesToRead = [
64
+ {
65
+ attributeId: AttributeIds.Value,
66
+ nodeId
67
+ },
68
+ {
69
+ attributeId: AttributeIds.UserAccessLevel,
70
+ nodeId
71
+ },
72
+ {
73
+ attributeId: AttributeIds.AccessLevel,
74
+ nodeId
75
+ }
76
+ ];
77
+
78
+ session.read(nodesToRead, (err: Error | null, dataValues?: DataValue[]) => {
79
+ if (err) {
80
+ return callback(err);
81
+ }
82
+
83
+ dataValues = dataValues || [];
84
+
85
+ if (dataValues[0].statusCode === StatusCodes.Good) {
86
+ clientObject.dataValue = dataValues[0].value;
87
+ }
88
+ if (dataValues[1].statusCode === StatusCodes.Good) {
89
+ clientObject.userAccessLevel = coerceAccessLevelFlag(dataValues[1].value.value);
90
+ }
91
+ if (dataValues[2].statusCode === StatusCodes.Good) {
92
+ clientObject.accessLevel = coerceAccessLevelFlag(dataValues[2].value.value);
93
+ }
94
+ callback(err!);
95
+ });
96
+ }
97
+
98
+ let clientObject: any;
99
+
100
+ async.series(
101
+ [
102
+ (callback: ErrorCallback) => {
103
+ // readAttributes like browseName and references
104
+ session.read(nodesToRead, (err: Error | null, dataValues?: DataValue[]) => {
105
+ if (!err) {
106
+ dataValues = dataValues!;
107
+
108
+ if (dataValues[0].statusCode === StatusCodes.BadNodeIdUnknown) {
109
+ // xx console.log(" INVALID NODE ", nodeId.toString());
110
+ return callback(new Error("Invalid Node " + nodeId.toString()));
111
+ }
112
+
113
+ clientObject = new ProxyObject(proxyManager, nodeId as NodeId);
114
+
115
+ /// x console.log("xxxx ,s",results.map(function(a){ return a.toString();}));
116
+
117
+ clientObject.browseName = dataValues[0].value.value;
118
+ clientObject.description = dataValues[1].value ? dataValues[1].value.value : "";
119
+ clientObject.nodeClass = dataValues[2].value.value;
120
+ // xx console.log("xxx nodeClass = ",clientObject.nodeClass.toString());
121
+
122
+ if (clientObject.nodeClass === NodeClass.Variable) {
123
+ return read_accessLevels(clientObject, callback);
124
+ }
125
+ }
126
+ callback(err!);
127
+ });
128
+ },
129
+
130
+ (callback: ErrorCallback) => {
131
+ // install monitored item
132
+ if (clientObject.nodeClass === NodeClass.Variable) {
133
+ /*console.log(
134
+ "xxxx -> monitoring",
135
+ clientObject.nodeId.toString(),
136
+ clientObject.nodeClass.toString(),
137
+ clientObject.browseName.toString()
138
+ );
139
+ */
140
+ return proxyManager._monitor_value(clientObject, callback);
141
+ }
142
+ callback();
143
+ },
144
+
145
+ (callback: ErrorCallback) => {
146
+ readUAStructure(proxyManager, clientObject, callback);
147
+ }
148
+
149
+ //
150
+ ],
151
+ (err) => {
152
+ // istanbul ignore next
153
+ if (err) {
154
+ return callback(err);
155
+ }
156
+ callback(null, clientObject);
157
+ }
158
+ );
159
+ }
160
+
161
+ export interface IClientSubscription {
162
+ monitor(
163
+ itemToMonitor: ReadValueIdOptions,
164
+ monitoringParameters: MonitoringParametersOptions,
165
+ timestampToReturn: TimestampsToReturn,
166
+ callback: CallbackT<IClientMonitoredItemBase>
167
+ ): void;
168
+
169
+ terminate(callback: () => void): void;
170
+ on(eventName: "terminated", eventHandler: () => void): void;
171
+ }
172
+
173
+ export interface IClientMonitoredItemBase {
174
+ on(eventName: "changed", eventHandler: (data: DataValue | Variant[]) => void): void;
175
+ }
176
+ export interface IBasicSessionWithSubscription extends IBasicSession {
177
+ createSubscription2(options: CreateSubscriptionRequestOptions, callback: CallbackT<IClientSubscription>): void;
178
+ }
179
+
180
+ // tslint:disable-next-line: max-classes-per-file
181
+ export class UAProxyManager {
182
+ public readonly session: IBasicSessionWithSubscription;
183
+ public subscription?: IClientSubscription;
184
+ private _map: any;
185
+
186
+ constructor(session: IBasicSessionWithSubscription) {
187
+ this.session = session;
188
+ this._map = {};
189
+ // create a subscription
190
+ }
191
+
192
+ public async start(): Promise<void>;
193
+ public start(callback: (err?: Error) => void): void;
194
+ public start(...args: any[]): any {
195
+ const callback = args[0] as (err?: Error) => void;
196
+
197
+ const createSubscriptionRequest: CreateSubscriptionRequestOptions = {
198
+ maxNotificationsPerPublish: 1000,
199
+ priority: 10,
200
+ publishingEnabled: true,
201
+ requestedLifetimeCount: 6000,
202
+ requestedMaxKeepAliveCount: 100,
203
+ requestedPublishingInterval: 100
204
+ };
205
+
206
+ this.session.createSubscription2(createSubscriptionRequest, (err: Error | null, subscription?: IClientSubscription) => {
207
+ if (err) {
208
+ return callback(err);
209
+ }
210
+ this.subscription = subscription!;
211
+ this.subscription!.on("terminated", () => {
212
+ this.subscription = undefined;
213
+ });
214
+ callback();
215
+ });
216
+ }
217
+
218
+ public async stop(): Promise<void>;
219
+ public stop(callback: (err?: Error) => void): void;
220
+
221
+ public stop(...args: any[]): any {
222
+ const callback = args[0] as (err?: Error) => void;
223
+
224
+ if (this.subscription) {
225
+ this.subscription.terminate(() => {
226
+ this.subscription = undefined;
227
+ callback();
228
+ });
229
+ } else {
230
+ callback(new Error("UAProxyManager already stopped ?"));
231
+ }
232
+ }
233
+
234
+ // todo: rename getObject as getNode
235
+ public async getObject(nodeId: NodeIdLike): Promise<any>;
236
+
237
+ public getObject(nodeId: NodeIdLike, callback: (err: Error | null, object?: any) => void): void;
238
+ public getObject(...args: any[]): any {
239
+ const nodeId = args[0] as NodeIdLike;
240
+ const callback = args[1] as (err: Error | null, object?: any) => void;
241
+
242
+ let options: any = {};
243
+
244
+ setImmediate(() => {
245
+ options = options || {};
246
+ options.depth = options.depth || 1;
247
+
248
+ const key = nodeId.toString();
249
+ // the object already exist in the map ?
250
+ if (Object.prototype.hasOwnProperty.call(this._map, key)) {
251
+ return callback(null, this._map[key]);
252
+ }
253
+
254
+ getObject(this, nodeId, options, (err: Error | null, obj?: ProxyBaseNode) => {
255
+ if (!err) {
256
+ this._map[key] = obj;
257
+ }
258
+ callback(err, obj);
259
+ });
260
+ });
261
+ }
262
+
263
+ public _monitor_value(proxyObject: IProxy, callback: ErrorCallback): void {
264
+ if (!this.subscription) {
265
+ // debugLog("cannot monitor _monitor_value: no subscription");
266
+ // some server do not provide subscription support, do not treat this as an error.
267
+ return callback(); // new Error("No subscription"));
268
+ }
269
+
270
+ const itemToMonitor: ReadValueIdOptions = {
271
+ // ReadValueId
272
+ attributeId: AttributeIds.Value,
273
+ nodeId: proxyObject.nodeId
274
+ };
275
+ const monitoringParameters: MonitoringParametersOptions = {
276
+ // MonitoringParameters
277
+ discardOldest: true,
278
+ queueSize: 10,
279
+ samplingInterval: 0 /* event-based */
280
+ };
281
+ const requestedParameters = TimestampsToReturn.Both;
282
+
283
+ this.subscription.monitor(
284
+ itemToMonitor,
285
+ monitoringParameters,
286
+ requestedParameters,
287
+
288
+ (err: Error | null, monitoredItem?: IClientMonitoredItemBase) => {
289
+ Object.defineProperty(proxyObject, "__monitoredItem", { value: monitoredItem, enumerable: false });
290
+ proxyObject.__monitoredItem!.on("changed", (dataValue: DataValue) => {
291
+ proxyObject.dataValue = dataValue;
292
+ proxyObject.emit("value_changed", dataValue);
293
+ });
294
+ proxyObject.__monitoredItem!.on("err", (err: Error) => {
295
+ // tslint:disable-next-line: no-console
296
+ console.log("Proxy: cannot monitor variable ", itemToMonitor.nodeId?.toString(), err.message);
297
+ });
298
+ callback(err!);
299
+ }
300
+ );
301
+ }
302
+
303
+ public _monitor_execution_flag(proxyObject: IProxy1, callback: (err?: Error) => void): void {
304
+ // note : proxyObject must wrap a method
305
+ assert(proxyObject.nodeId instanceof NodeId);
306
+
307
+ if (!this.subscription) {
308
+ // some server do not provide subscription support, do not treat this as an error.
309
+ return callback(); // new Error("No subscription"));
310
+ }
311
+
312
+ const itemToMonitor = {
313
+ // ReadValueId
314
+ attributeId: AttributeIds.Executable,
315
+ nodeId: proxyObject.nodeId
316
+ };
317
+
318
+ const monitoringParameters = {
319
+ // MonitoringParameters
320
+ discardOldest: true,
321
+ queueSize: 10,
322
+ samplingInterval: 0 /* event-based */
323
+ };
324
+ const requestedParameters = TimestampsToReturn.Neither;
325
+
326
+ this.subscription.monitor(
327
+ itemToMonitor,
328
+ monitoringParameters,
329
+ requestedParameters,
330
+ (err: Error | null, monitoredItem?: IClientMonitoredItemBase) => {
331
+ Object.defineProperty(proxyObject, "__monitoredItem_execution_flag", {
332
+ value: monitoredItem,
333
+
334
+ enumerable: false
335
+ });
336
+ proxyObject.__monitoredItem_execution_flag!.on("changed", (dataValue: DataValue) => {
337
+ proxyObject.executableFlag = dataValue.value.value;
338
+ });
339
+
340
+ callback(err!);
341
+ }
342
+ );
343
+ }
344
+
345
+ public getStateMachineType(
346
+ nodeId: NodeIdLike,
347
+ callback: (err: Error | null, stateMachineType?: ProxyStateMachineType) => void
348
+ ): void {
349
+ if (typeof nodeId === "string") {
350
+ const org_nodeId = nodeId;
351
+ nodeId = makeRefId(nodeId);
352
+ }
353
+
354
+ this.getObject(nodeId, (err: Error | null, obj: any) => {
355
+ // read fromState and toState Reference on
356
+ let stateMachineType;
357
+ if (!err) {
358
+ stateMachineType = new ProxyStateMachineType(obj);
359
+ }
360
+ callback(err, stateMachineType);
361
+ });
362
+ }
363
+ }
364
+
365
+ // tslint:disable-next-line:no-var-requires
366
+ const thenify = require("thenify");
367
+ UAProxyManager.prototype.start = thenify.withCallback(UAProxyManager.prototype.start);
368
+ UAProxyManager.prototype.stop = thenify.withCallback(UAProxyManager.prototype.stop);
369
+ UAProxyManager.prototype.getObject = thenify.withCallback(UAProxyManager.prototype.getObject);