node-opcua-client-proxy 2.140.0 → 2.141.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.
@@ -8,9 +8,9 @@ import { DataValue } from "node-opcua-data-value";
8
8
  import { NodeId } from "node-opcua-nodeid";
9
9
  import { Argument } from "node-opcua-service-call";
10
10
  import { WriteValueOptions } from "node-opcua-service-write";
11
- import { StatusCode, StatusCodes } from "node-opcua-status-code";
12
11
  import { DataType, Variant } from "node-opcua-variant";
13
12
  import { UAProxyManager } from "./proxy_manager";
13
+ import { StatusCode } from "node-opcua-status-code";
14
14
 
15
15
  export interface ArgumentEx extends Argument {
16
16
  _basicDataType: DataType;
@@ -100,7 +100,7 @@ export class ProxyBaseNode extends EventEmitter {
100
100
  /**
101
101
  * get a updated Value of the Variable , by using a ReadRequest
102
102
  */
103
- public readValue(callback: (err: Error | null, variant?: Variant) => void): void {
103
+ public async readValue(): Promise<Variant> {
104
104
  assert(this.proxyManager);
105
105
 
106
106
  const session = this.proxyManager.session;
@@ -110,20 +110,15 @@ export class ProxyBaseNode extends EventEmitter {
110
110
  attributeId: AttributeIds.Value,
111
111
  nodeId: this.nodeId
112
112
  };
113
- this.proxyManager.session.read(nodeToRead, (err: Error | null, dataValue?: DataValue) => {
114
- // istanbul ignore next
115
- if (err) {
116
- return callback(err);
117
- }
118
- const data = dataValue!.value;
119
- callback(null, data);
120
- });
113
+ const dataValue = await this.proxyManager.session.read(nodeToRead);
114
+ const data = dataValue!.value;
115
+ return data;
121
116
  }
122
117
 
123
118
  /**
124
119
  * set the Value of the Variable, by using a WriteRequest
125
120
  */
126
- public writeValue(dataValue: DataValue, callback: (err?: Error) => void): void {
121
+ public async writeValue(dataValue: DataValue): Promise<StatusCode> {
127
122
  assert(this.proxyManager);
128
123
 
129
124
  const session = this.proxyManager.session;
@@ -134,17 +129,9 @@ export class ProxyBaseNode extends EventEmitter {
134
129
  nodeId: this.nodeId,
135
130
  value: dataValue
136
131
  };
137
- this.proxyManager.session.write(nodeToWrite, (err: Error | null, statusCode?: StatusCode) => {
138
- // istanbul ignore next
139
- if (err) {
140
- return callback(err);
141
- }
142
- if (statusCode && statusCode.isNotGood()) {
143
- callback(new Error(statusCode!.toString()));
144
- } else {
145
- callback();
146
- }
147
- });
132
+ const statusCode = await this.proxyManager.session.write(nodeToWrite);
133
+
134
+ return statusCode;
148
135
  }
149
136
 
150
137
  public toString(): string {
@@ -157,8 +144,4 @@ export class ProxyBaseNode extends EventEmitter {
157
144
 
158
145
  return str.join("\n");
159
146
  }
160
- }
161
- // tslint:disable:no-var-requires
162
- const thenify = require("thenify");
163
- ProxyBaseNode.prototype.readValue = thenify.withCallback(ProxyBaseNode.prototype.readValue);
164
- ProxyBaseNode.prototype.writeValue = thenify.withCallback(ProxyBaseNode.prototype.writeValue);
147
+ }
@@ -3,7 +3,6 @@
3
3
  */
4
4
  // tslint:disable:no-shadowed-variable
5
5
  import { EventEmitter } from "stream";
6
- import async from "async";
7
6
  import { assert } from "node-opcua-assert";
8
7
 
9
8
  import { AttributeIds, NodeClass, coerceAccessLevelFlag } from "node-opcua-data-model";
@@ -11,18 +10,17 @@ import { NodeId, coerceNodeId } from "node-opcua-nodeid";
11
10
  import { DataValue, TimestampsToReturn } from "node-opcua-data-value";
12
11
  import { NodeIdLike } from "node-opcua-nodeid";
13
12
  import { CreateSubscriptionRequestOptions, MonitoringParametersOptions } from "node-opcua-service-subscription";
14
- import { StatusCodes, CallbackT } from "node-opcua-status-code";
15
- import { ErrorCallback } from "node-opcua-status-code";
16
- import { IBasicSessionCallback } from "node-opcua-pseudo-session";
13
+ import { StatusCodes } from "node-opcua-status-code";
14
+ import { IBasicSessionAsync, IBasicSessionGetArgumentDefinitionAsync } from "node-opcua-pseudo-session";
17
15
  import { ReadValueIdOptions } from "node-opcua-service-read";
18
16
  import { Variant } from "node-opcua-variant";
19
17
  import { make_debugLog } from "node-opcua-debug";
20
18
 
21
19
  import { readUAStructure } from "./object_explorer";
22
20
  import { makeRefId } from "./proxy";
23
- import { ProxyBaseNode } from "./proxy_base_node";
24
21
  import { ProxyObject } from "./proxy_object";
25
22
  import { ProxyStateMachineType } from "./state_machine_proxy";
23
+ import { ProxyNode } from "./proxy_transition";
26
24
 
27
25
  const debugLog = make_debugLog(__filename);
28
26
 
@@ -35,16 +33,18 @@ export interface IProxy1 {
35
33
  export interface IProxy extends EventEmitter, IProxy1 {
36
34
  dataValue: DataValue;
37
35
  }
38
- function getObject(proxyManager: UAProxyManager, nodeId: NodeIdLike | NodeId, options: any, callback: any) {
36
+
37
+ async function internalGetObject(
38
+ proxyManager: UAProxyManager,
39
+ nodeId: NodeIdLike | NodeId, options: any
40
+ ): Promise<ProxyNode> {
41
+
39
42
  const session = proxyManager.session;
40
43
 
41
44
  nodeId = coerceNodeId(nodeId) as NodeId;
42
45
 
43
46
  if (nodeId.isEmpty()) {
44
- setImmediate(() => {
45
- callback(new Error(" Invalid empty node in getObject"));
46
- });
47
- return;
47
+ throw new Error(" Invalid empty node in getObject");
48
48
  }
49
49
 
50
50
  const nodesToRead = [
@@ -62,7 +62,7 @@ function getObject(proxyManager: UAProxyManager, nodeId: NodeIdLike | NodeId, op
62
62
  }
63
63
  ];
64
64
 
65
- function read_accessLevels(clientObject: any, callback: ErrorCallback) {
65
+ async function read_accessLevels(clientObject: any) {
66
66
  const nodesToRead = [
67
67
  {
68
68
  attributeId: AttributeIds.Value,
@@ -78,113 +78,74 @@ function getObject(proxyManager: UAProxyManager, nodeId: NodeIdLike | NodeId, op
78
78
  }
79
79
  ];
80
80
 
81
- session.read(nodesToRead, (err: Error | null, dataValues?: DataValue[]) => {
82
- if (err) {
83
- return callback(err);
84
- }
85
-
86
- dataValues = dataValues || [];
81
+ const dataValues = await session.read(nodesToRead);
87
82
 
88
- if (dataValues[0].statusCode.isGood()) {
89
- clientObject.dataValue = dataValues[0].value;
90
- }
91
- if (dataValues[1].statusCode.isGood()) {
92
- clientObject.userAccessLevel = coerceAccessLevelFlag(dataValues[1].value.value);
93
- }
94
- if (dataValues[2].statusCode.isGood()) {
95
- clientObject.accessLevel = coerceAccessLevelFlag(dataValues[2].value.value);
96
- }
97
- callback(err!);
98
- });
83
+ if (dataValues[0].statusCode.isGood()) {
84
+ clientObject.dataValue = dataValues[0].value;
85
+ }
86
+ if (dataValues[1].statusCode.isGood()) {
87
+ clientObject.userAccessLevel = coerceAccessLevelFlag(dataValues[1].value.value);
88
+ }
89
+ if (dataValues[2].statusCode.isGood()) {
90
+ clientObject.accessLevel = coerceAccessLevelFlag(dataValues[2].value.value);
91
+ }
99
92
  }
100
93
 
101
94
  let clientObject: any;
102
95
 
103
- async.series(
104
- [
105
- (callback: ErrorCallback) => {
106
- // readAttributes like browseName and references
107
- session.read(nodesToRead, (err: Error | null, dataValues?: DataValue[]) => {
108
- if (!err) {
109
- dataValues = dataValues!;
110
-
111
- if (dataValues[0].statusCode.equals(StatusCodes.BadNodeIdUnknown)) {
112
- return callback(new Error("Invalid Node " + nodeId.toString()));
113
- }
114
-
115
- clientObject = new ProxyObject(proxyManager, nodeId as NodeId);
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
-
121
- if (clientObject.nodeClass === NodeClass.Variable) {
122
- return read_accessLevels(clientObject, callback);
123
- }
124
- }
125
- callback(err!);
126
- });
127
- },
96
+ const dataValues = await session.read(nodesToRead);
128
97
 
129
- (callback: ErrorCallback) => {
130
- // install monitored item
131
- if (clientObject.nodeClass === NodeClass.Variable) {
132
- return proxyManager._monitor_value(clientObject, callback);
133
- }
134
- callback();
135
- },
98
+ if (dataValues[0].statusCode.equals(StatusCodes.BadNodeIdUnknown)) {
99
+ throw new Error("Invalid Node " + nodeId.toString());
100
+ }
136
101
 
137
- (callback: ErrorCallback) => {
138
- readUAStructure(proxyManager, clientObject, callback);
139
- }
102
+ clientObject = new ProxyObject(proxyManager, nodeId as NodeId);
140
103
 
141
- //
142
- ],
143
- (err) => {
144
- // istanbul ignore next
145
- if (err) {
146
- return callback(err);
147
- }
148
- callback(null, clientObject);
149
- }
150
- );
104
+ clientObject.browseName = dataValues[0].value.value;
105
+ clientObject.description = dataValues[1].value ? dataValues[1].value.value : "";
106
+ clientObject.nodeClass = dataValues[2].value.value;
107
+
108
+ if (clientObject.nodeClass === NodeClass.Variable) {
109
+ await read_accessLevels(clientObject);
110
+ }
111
+ // install monitored item
112
+ if (clientObject.nodeClass === NodeClass.Variable) {
113
+ await proxyManager._monitor_value(clientObject);
114
+ }
115
+
116
+ return await readUAStructure(proxyManager, clientObject);
151
117
  }
152
118
 
153
119
  export interface IClientSubscription {
154
120
  monitor(
155
121
  itemToMonitor: ReadValueIdOptions,
156
122
  monitoringParameters: MonitoringParametersOptions,
157
- timestampToReturn: TimestampsToReturn,
158
- callback: CallbackT<IClientMonitoredItemBase>
159
- ): void;
123
+ timestampToReturn: TimestampsToReturn
124
+ ): Promise<IClientMonitoredItemBase>;
160
125
 
161
- terminate(callback: () => void): void;
126
+ terminate(): Promise<void>;
162
127
  on(eventName: "terminated", eventHandler: () => void): void;
163
128
  }
164
129
 
165
130
  export interface IClientMonitoredItemBase {
166
131
  on(eventName: "changed", eventHandler: (data: DataValue | Variant[]) => void): void;
167
132
  }
168
- export interface IBasicSessionWithSubscription extends IBasicSessionCallback {
169
- createSubscription2(options: CreateSubscriptionRequestOptions, callback: CallbackT<IClientSubscription>): void;
133
+ export interface IBasicSessionWithSubscriptionAsync extends IBasicSessionAsync, IBasicSessionGetArgumentDefinitionAsync {
134
+ createSubscription2(options: CreateSubscriptionRequestOptions): Promise<IClientSubscription>;
170
135
  }
171
136
 
172
137
  // tslint:disable-next-line: max-classes-per-file
173
138
  export class UAProxyManager {
174
- public readonly session: IBasicSessionWithSubscription;
139
+ public readonly session: IBasicSessionWithSubscriptionAsync;
175
140
  public subscription?: IClientSubscription;
176
- private _map: any;
141
+ #_map: any;
177
142
 
178
- constructor(session: IBasicSessionWithSubscription) {
143
+ constructor(session: IBasicSessionWithSubscriptionAsync) {
179
144
  this.session = session;
180
- this._map = {};
181
- // create a subscription
145
+ this.#_map = {};
182
146
  }
183
147
 
184
- public async start(): Promise<void>;
185
- public start(callback: (err?: Error) => void): void;
186
- public start(...args: any[]): any {
187
- const callback = args[0] as (err?: Error) => void;
148
+ public async start(): Promise<void> {
188
149
 
189
150
  const createSubscriptionRequest: CreateSubscriptionRequestOptions = {
190
151
  maxNotificationsPerPublish: 1000,
@@ -195,68 +156,44 @@ export class UAProxyManager {
195
156
  requestedPublishingInterval: 100
196
157
  };
197
158
 
198
- this.session.createSubscription2(createSubscriptionRequest, (err: Error | null, subscription?: IClientSubscription) => {
199
- if (err) {
200
- return callback(err);
201
- }
202
- this.subscription = subscription!;
203
- this.subscription!.on("terminated", () => {
204
- this.subscription = undefined;
205
- });
206
- callback();
159
+ const subscription = await this.session.createSubscription2(createSubscriptionRequest);
160
+ this.subscription = subscription!;
161
+ this.subscription!.on("terminated", () => {
162
+ this.subscription = undefined;
207
163
  });
208
164
  }
209
165
 
210
- public async stop(): Promise<void>;
211
- public stop(callback: (err?: Error) => void): void;
212
-
213
- public stop(...args: any[]): any {
214
- const callback = args[0] as (err?: Error) => void;
215
-
166
+ public async stop(): Promise<void> {
216
167
  if (this.subscription) {
217
- this.subscription.terminate(() => {
218
- this.subscription = undefined;
219
- callback();
220
- });
168
+ await this.subscription.terminate();
169
+ this.subscription = undefined;
221
170
  } else {
222
- callback(new Error("UAProxyManager already stopped ?"));
171
+ // throw new Error("UAProxyManager already stopped ?");
223
172
  }
224
173
  }
225
174
 
226
175
  // todo: rename getObject as getNode
227
- public async getObject(nodeId: NodeIdLike): Promise<any>;
228
-
229
- public getObject(nodeId: NodeIdLike, callback: (err: Error | null, object?: any) => void): void;
230
- public getObject(...args: any[]): any {
231
- const nodeId = args[0] as NodeIdLike;
232
- const callback = args[1] as (err: Error | null, object?: any) => void;
233
-
176
+ public async getObject(nodeId: NodeIdLike): Promise<ProxyNode> {
234
177
  let options: any = {};
178
+ options = options || {};
179
+ options.depth = options.depth || 1;
235
180
 
236
- setImmediate(() => {
237
- options = options || {};
238
- options.depth = options.depth || 1;
239
-
240
- const key = nodeId.toString();
241
- // the object already exist in the map ?
242
- if (Object.prototype.hasOwnProperty.call(this._map, key)) {
243
- return callback(null, this._map[key]);
244
- }
181
+ const key = nodeId.toString();
182
+ // the object already exist in the map ?
183
+ if (Object.prototype.hasOwnProperty.call(this.#_map, key)) {
184
+ return this.#_map[key];
185
+ }
245
186
 
246
- getObject(this, nodeId, options, (err: Error | null, obj?: ProxyBaseNode) => {
247
- if (!err) {
248
- this._map[key] = obj;
249
- }
250
- callback(err, obj);
251
- });
252
- });
187
+ const obj = await internalGetObject(this, nodeId, options);
188
+ this.#_map[key] = obj;
189
+ return obj;
253
190
  }
254
191
 
255
- public _monitor_value(proxyObject: IProxy, callback: ErrorCallback): void {
192
+ public async _monitor_value(proxyObject: IProxy): Promise<void> {
256
193
  if (!this.subscription) {
257
194
  // debugLog("cannot monitor _monitor_value: no subscription");
258
195
  // some server do not provide subscription support, do not treat this as an error.
259
- return callback(); // new Error("No subscription"));
196
+ return; // new Error("No subscription"));
260
197
  }
261
198
 
262
199
  const itemToMonitor: ReadValueIdOptions = {
@@ -272,32 +209,25 @@ export class UAProxyManager {
272
209
  };
273
210
  const requestedParameters = TimestampsToReturn.Both;
274
211
 
275
- this.subscription.monitor(
276
- itemToMonitor,
277
- monitoringParameters,
278
- requestedParameters,
279
-
280
- (err: Error | null, monitoredItem?: IClientMonitoredItemBase) => {
281
- Object.defineProperty(proxyObject, "__monitoredItem", { value: monitoredItem, enumerable: false });
282
- proxyObject.__monitoredItem!.on("changed", (dataValue: DataValue) => {
283
- proxyObject.dataValue = dataValue;
284
- proxyObject.emit("value_changed", dataValue);
285
- });
286
- proxyObject.__monitoredItem!.on("err", (err: Error) => {
287
- debugLog("Proxy: cannot monitor variable ", itemToMonitor.nodeId?.toString(), err.message);
288
- });
289
- callback(err!);
290
- }
291
- );
212
+ const monitoredItem = await this.subscription.monitor(itemToMonitor, monitoringParameters, requestedParameters);
213
+
214
+ Object.defineProperty(proxyObject, "__monitoredItem", { value: monitoredItem, enumerable: false });
215
+ proxyObject.__monitoredItem!.on("changed", (dataValue: DataValue) => {
216
+ proxyObject.dataValue = dataValue;
217
+ proxyObject.emit("value_changed", dataValue);
218
+ });
219
+ proxyObject.__monitoredItem!.on("err", (err: Error) => {
220
+ debugLog("Proxy: cannot monitor variable ", itemToMonitor.nodeId?.toString(), err.message);
221
+ });
292
222
  }
293
223
 
294
- public _monitor_execution_flag(proxyObject: IProxy1, callback: (err?: Error) => void): void {
224
+ public async _monitor_execution_flag(proxyObject: IProxy1): Promise<void> {
295
225
  // note : proxyObject must wrap a method
296
226
  assert(proxyObject.nodeId instanceof NodeId);
297
227
 
298
228
  if (!this.subscription) {
299
229
  // some server do not provide subscription support, do not treat this as an error.
300
- return callback(); // new Error("No subscription"));
230
+ return; // new Error("No subscription"));
301
231
  }
302
232
 
303
233
  const itemToMonitor = {
@@ -314,47 +244,22 @@ export class UAProxyManager {
314
244
  };
315
245
  const requestedParameters = TimestampsToReturn.Neither;
316
246
 
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
- proxyObject.__monitoredItem_execution_flag!.on("changed", (dataValue: DataValue) => {
328
- proxyObject.executableFlag = dataValue.value.value;
329
- });
330
-
331
- callback(err!);
332
- }
333
- );
334
- }
247
+ const monitoredItem = await this.subscription.monitor(itemToMonitor, monitoringParameters, requestedParameters);
248
+ Object.defineProperty(proxyObject, "__monitoredItem_execution_flag", {
249
+ value: monitoredItem,
335
250
 
336
- public getStateMachineType(
337
- nodeId: NodeIdLike,
338
- callback: (err: Error | null, stateMachineType?: ProxyStateMachineType) => void
339
- ): void {
251
+ enumerable: false
252
+ });
253
+ proxyObject.__monitoredItem_execution_flag!.on("changed", (dataValue: DataValue) => {
254
+ proxyObject.executableFlag = dataValue.value.value;
255
+ });
256
+ }
257
+ public async getStateMachineType(nodeId: NodeIdLike): Promise<ProxyStateMachineType> {
340
258
  if (typeof nodeId === "string") {
341
259
  const org_nodeId = nodeId;
342
260
  nodeId = makeRefId(nodeId);
343
261
  }
344
-
345
- this.getObject(nodeId, (err: Error | null, obj: any) => {
346
- // read fromState and toState Reference on
347
- let stateMachineType;
348
- if (!err) {
349
- stateMachineType = new ProxyStateMachineType(obj);
350
- }
351
- callback(err, stateMachineType);
352
- });
262
+ const obj = await this.getObject(nodeId);
263
+ return new ProxyStateMachineType(obj);
353
264
  }
354
265
  }
355
-
356
- // tslint:disable-next-line:no-var-requires
357
- const thenify = require("thenify");
358
- UAProxyManager.prototype.start = thenify.withCallback(UAProxyManager.prototype.start);
359
- UAProxyManager.prototype.stop = thenify.withCallback(UAProxyManager.prototype.stop);
360
- UAProxyManager.prototype.getObject = thenify.withCallback(UAProxyManager.prototype.getObject);
@@ -9,9 +9,7 @@ export interface ProxyNode {
9
9
  $components: ProxyNode[];
10
10
  typeDefinition?: { toString(): string };
11
11
  }
12
- /**
13
- * @module node-opcua-client-proxy
14
- */
12
+
15
13
  export class ProxyTransition {
16
14
  private _node: ProxyNode;
17
15
 
@@ -11,6 +11,7 @@ export class ProxyStateMachineType {
11
11
  public transitions: ProxyTransition[];
12
12
 
13
13
  constructor(obj: ProxyNode) {
14
+
14
15
  const localInitialState = obj.$components.filter((component: any) => {
15
16
  if (!component.typeDefinition) {
16
17
  return false;