loupedeck-commander 1.3.0 → 1.3.1

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/README.md CHANGED
@@ -42,8 +42,8 @@ npm install -s loupedeck-commander
42
42
  Create a new configuration file with at least one profile or copy from here,
43
43
  and replace the image references with your own icons (90x90px size):
44
44
 
45
- - [config.json](https://gitlab.com/keckxde/loupedeck-commander/-/blob/main/config.json)
46
- - [profile-1.json](https://gitlab.com/keckxde/loupedeck-commander/-/blob/main/profile-1.json)
45
+ - [config.yaml](https://gitlab.com/keckxde/loupedeck-commander/-/blob/main/config.yaml)
46
+ - [profile-1.yaml](https://gitlab.com/keckxde/loupedeck-commander/-/blob/main/profile-1.yaml)
47
47
 
48
48
  Create a `index.mjs` file to open up your loupedeck connection:
49
49
 
@@ -51,7 +51,7 @@ Create a `index.mjs` file to open up your loupedeck connection:
51
51
  # save as index.mjs
52
52
  import { BaseLoupeDeckHandler } from 'loupedeck-commander'
53
53
 
54
- const handler = new BaseLoupeDeckHandler('config.json')
54
+ const handler = new BaseLoupeDeckHandler('config.yaml')
55
55
 
56
56
  /**
57
57
  * Stop the handlers when a signal like SIGINT or SIGTERM arrive
@@ -1,4 +1,4 @@
1
- import { readJSONFile, writeJSONFile,syncParams } from './utils.mjs'
1
+ import { readConfigFile as readConfigFile, writeJSONFile,syncParams, writeYAMLFile } from './utils.mjs'
2
2
 
3
3
  export class ApplicationConfig {
4
4
  application = 'undefined'
@@ -7,7 +7,8 @@ export class ApplicationConfig {
7
7
 
8
8
  loadFromFile (fileName) {
9
9
  console.info(`ApplicationConfig: Loading Config File ${fileName}`)
10
- const config = readJSONFile(fileName)
10
+ const config = readConfigFile(fileName)
11
+
11
12
 
12
13
  if (!config){
13
14
  console.info(`ApplicationConfig: Could not read/parse Config File ${fileName} - breaking here`)
@@ -66,7 +67,7 @@ class Profile {
66
67
 
67
68
  loadFromFile (fileName) {
68
69
  console.info(`ProfileConfig: Loading Profile File ${fileName}, Index ${this.#index}`)
69
- const config = readJSONFile(fileName)
70
+ const config = readConfigFile(fileName)
70
71
  if (config === undefined) {
71
72
  console.warn(`ProfileConfig: Cannot parse/load Profile File ${fileName}`)
72
73
  return false
@@ -105,7 +106,13 @@ class Profile {
105
106
  fileName = fileName.toLowerCase()
106
107
 
107
108
  console.info(`ProfileConfig: Save To Config File ${fileName}`)
108
- writeJSONFile(fileName, this)
109
+ if(fileName.endsWith('.json')) {
110
+ writeJSONFile(fileName, this)
111
+ writeYAMLFile(fileName.replace('.json','.yaml'), this)
112
+ }else if(fileName.endsWith('.yaml')) {
113
+ writeYAMLFile(fileName, this)
114
+ writeJSONFile(fileName.replace('.yaml','.json'), this)
115
+ }
109
116
  }
110
117
  }
111
118
 
package/common/button.mjs CHANGED
@@ -22,7 +22,7 @@ export class Button {
22
22
  #enforcedIndex = -1
23
23
  #event
24
24
  #keys
25
- #states
25
+ #states
26
26
  // Timestamp when button was pressed
27
27
  timeStampPressed
28
28
  // Timestamp when button was released
@@ -31,48 +31,48 @@ export class Button {
31
31
  timeHold
32
32
  #counter = 0
33
33
 
34
- constructor (id, width, height, data={},key,profile = {}) {
34
+ constructor(id, width, height, data = {}, key, profile = {}) {
35
35
  this.#states = {}
36
36
  this.#keys = []
37
-
37
+
38
38
  this.id = id
39
39
  this.#index = 0
40
40
  this.#enforcedIndex = -1
41
41
 
42
42
  this.#profile = profile
43
43
  this.#params = {
44
- "key" : key,
45
- "state" : '',
46
- "width" : width,
47
- "height" : height,
48
- "min" : 0,
49
- "max" : 100,
50
- "x" : 0,
51
- "y" : 0,
52
- "color" : '#000000',
53
- "text" : '',
54
- "textColor" : '#ffffff',
55
- "textAlign" : 'center',
56
- "textBaseline": 'top',
57
- "font" :'16px Arial',
58
- "value" : 50,
59
- "minPressed": 25,
60
- "moveLeft" : false,
61
- "moveRight" : false,
62
- "moveUp" : false,
63
- "moveDown" : false,
64
- "nodeid" : '',
65
- "type" : ButtonType.TOGGLE,
66
- "group" : key,
67
- "filter" : "",
68
- "blink" : false,
69
- "vibrate" : false,
70
- "profile" : "",
71
- "brightness" : undefined,
72
- "default" : "0"
73
- }
74
-
75
- if (profile.parameters){
44
+ "key": key,
45
+ "state": '',
46
+ "width": width,
47
+ "height": height,
48
+ "min": 0,
49
+ "max": 100,
50
+ "x": 0,
51
+ "y": 0,
52
+ "color": '#000000',
53
+ "text": '',
54
+ "textColor": '#ffffff',
55
+ "textAlign": 'center',
56
+ "textBaseline": 'top',
57
+ "font": '16px Arial',
58
+ "value": 50,
59
+ "minPressed": 25,
60
+ "moveLeft": false,
61
+ "moveRight": false,
62
+ "moveUp": false,
63
+ "moveDown": false,
64
+ "nodeid": '',
65
+ "type": ButtonType.TOGGLE,
66
+ "group": key,
67
+ "filter": "",
68
+ "blink": false,
69
+ "vibrate": false,
70
+ "profile": "",
71
+ "brightness": undefined,
72
+ "default": "0"
73
+ }
74
+
75
+ if (profile.parameters) {
76
76
  let params = Object.keys(profile.parameters)
77
77
  for (let i = 0; i < params.length; i++) {
78
78
  const k = params[i]
@@ -83,7 +83,7 @@ export class Button {
83
83
  this.#params.key = key
84
84
 
85
85
  // New approach: Use all data from data.params:
86
- if (data.params){
86
+ if (data.params) {
87
87
  this.#params = {
88
88
  ...this.#params,
89
89
  ...data.params
@@ -98,16 +98,16 @@ export class Button {
98
98
  this.#states = data.states
99
99
  this.#keys = Object.keys(this.#states)
100
100
 
101
- var defaultIndex = this.#keys.indexOf(this.#params.default)
101
+ var defaultIndex = this.#keys.indexOf(this.#params.default)
102
102
  if (defaultIndex >= 0) {
103
103
  this.#index = defaultIndex
104
104
  } else {
105
105
  this.#params.default = this.#keys[0]
106
- console.info(` button ${id} default set to ${this.#params.default}, available states`, this.#keys)
106
+ // console.info(` button ${id} default set to ${this.#params.default}, available states`, this.#keys)
107
107
  }
108
108
  this.#params.state = this.#keys[this.#index]
109
109
  }
110
-
110
+
111
111
  // Set the default value for the button:
112
112
 
113
113
  // Legacy approach: Use data directly:
@@ -119,11 +119,11 @@ export class Button {
119
119
  console.warn("Legacy approach: text is deprecated, use params.text instead")
120
120
  this.#params.text = data.text
121
121
  }
122
- if (data.nodeid){
122
+ if (data.nodeid) {
123
123
  this.#params.nodeid = format(data.nodeid, this.getParams({}))
124
- console.warn("Legacy approach: nodeid is deprecated, use params.nodeid instead",this.#params.nodeid)
124
+ console.warn("Legacy approach: nodeid is deprecated, use params.nodeid instead", this.#params.nodeid)
125
125
  }
126
- if (data.type){
126
+ if (data.type) {
127
127
  console.warn("Legacy approach: type is deprecated, use params.type instead")
128
128
  this.#params.type = data.type
129
129
  }
@@ -133,18 +133,24 @@ export class Button {
133
133
  this.#index = this.#keys.indexOf(data.default)
134
134
  }
135
135
 
136
- if (data.group){
136
+ if (data.group) {
137
137
  console.warn("Legacy approach: group is deprecated, use params.group instead")
138
138
  this.#params.group = format(data.group, this.getParams({}))
139
139
  }
140
140
  // End Legacy approach
141
141
  }
142
142
 
143
- setState (index = 0) {
143
+ setState(index = 0) {
144
144
  this.#index = index
145
145
  }
146
146
 
147
- async drawPhysical (device, id) {
147
+ /**
148
+ * Draw a physical button (color in RGBA format) on a device
149
+ * @param {*} device
150
+ * @param {*} id - id of the physical button
151
+ * @returns
152
+ */
153
+ async drawPhysical(device, id) {
148
154
  const elem = this.getCurrentElement()
149
155
  if (!elem || !elem.color) { return }
150
156
 
@@ -156,52 +162,95 @@ export class Button {
156
162
  var idx = parseInt(id, 10);
157
163
 
158
164
  const val = {
159
- id:idx,
165
+ id: idx,
160
166
  color: `rgba(${r}, ${g}, ${b})`
161
167
  }
162
- // console.log(' Set Button Color',id, val.id,elem.color, val.color)
168
+ // console.log(' Set Button Color',id, val.id,elem.color, val.color)
163
169
  device.setButtonColor(val)
164
170
  } catch (error) {
165
171
  console.error(' Error', error)
166
172
  }
167
173
  }
168
174
 
169
- async draw (row, column, ctx) {
175
+ /**
176
+ * Draw the Touch-Screen Elementat the given row and column
177
+ * @param {*} row
178
+ * @param {*} column
179
+ * @param {*} ctx
180
+ */
181
+ async draw(row, column, ctx) {
182
+ // Calculate the x/y position based on the row and column and the width/height properties of the button
170
183
  const x = column * this.#params.width
171
184
  const y = row * this.#params.height
172
185
 
173
- const elem = this.getCurrentElement()
174
- let params = this.getParams(elem)
175
-
176
- if (elem) {
177
- if(elem.blink && this.#counter % 2 == 0) {
178
- // If blink is set, we switch the color to inverted color
179
- let oldColor = elem.color
180
- elem.color = params.textColor
181
- elem.textColor = oldColor
182
- //console.log("Blinking Button",this.#index,elem.color)
183
- }
186
+ // Modifications in draw:
187
+ // - Support color and textColor settings also in params section which
188
+ // can be overwriten by button state property. This way color and textColor
189
+ // can be defined overall for all states without repeating them in every state.
190
+ // - Same for blink property.
184
191
 
185
- ctx.fillStyle = params.color
186
- ctx.fillRect(x, y, params.width, params.height)
187
-
188
- if (elem.imgBuffer) {
189
- ctx.drawImage(elem.imgBuffer, x, y, params.width, params.height)
190
- }
192
+ let params = this.getParams(this.getCurrentElement())
193
+
194
+ let color = params.color
195
+ let textColor = params.textColor
196
+
197
+ if (params.blink && this.#counter % 2 == 0) {
198
+ // If blink is set, we switch textcolor and background color:
199
+ color = params.textColor
200
+ textColor = params.color
201
+ }
202
+
203
+ // Apply the color as fillStyle:
204
+ ctx.fillStyle = color
205
+ // Draw the background of the button::
206
+ ctx.fillRect(x, y, params.width, params.height)
207
+
208
+ // if we have an icon/image draw it on top of the button
209
+ if (params.imgBuffer) {
210
+ ctx.drawImage(params.imgBuffer, x, y, params.width, params.height)
191
211
  }
192
- if (params.text != undefined && params.text != '') {
193
- ctx.fillStyle = params.textColor
212
+ // if we have a text defined, draw it on top:
213
+ if (params.text != undefined && params.text != '') {
214
+ ctx.fillStyle = textColor
194
215
  ctx.font = params.font
195
216
  ctx.textBaseline = params.textBaseline;
196
217
  ctx.textAlign = params.textAlign;
197
- let dynamicText = format(params.text, this.getParams(elem))
198
- ctx.fillText(dynamicText,x+6,y+6)
218
+ let dynamicText = format(params.text, params)
219
+ let tx = x
220
+ let ty = y
221
+ // Handle Text Horizontal Alignment
222
+ switch (params.textAlign) {
223
+ case "center":
224
+ tx += this.#params.width / 2;
225
+ break;
226
+ case "left":
227
+ tx += 6;
228
+ break;
229
+ case "right":
230
+ tx += this.#params.width - 6;
231
+ break;
232
+ }
233
+ // Handle Text Vertical Alignment
234
+ switch (params.textBaseline) {
235
+ case "middle":
236
+ ty += this.#params.height / 2;
237
+ break;
238
+ case "top":
239
+ ty += 6;
240
+ ctx.textBaseline = "top";
241
+ break;
242
+ case "bottom":
243
+ ty += this.#params.height - 6;
244
+ ctx.textBaseline = "bottom";
245
+ break;
246
+ }
247
+ ctx.fillText(dynamicText, x + 6, y + 6)
199
248
  }
200
249
 
201
250
  this.#counter = this.#counter + 1
202
251
  }
203
252
 
204
- async load (globalConfig) {
253
+ async load(globalConfig) {
205
254
  this.#profile = globalConfig
206
255
  for (let i = 0; i < this.#keys.length; i++) {
207
256
  const key = this.#keys[i]
@@ -218,34 +267,41 @@ export class Button {
218
267
  }
219
268
  }
220
269
 
221
- getCurrentElement () {
270
+ getCurrentElement() {
222
271
  const state = this.#keys[this.#index]
223
272
  return this.#states[state]
224
273
  }
225
274
 
226
- getLastElement () {
227
- let i=this.#index-1
228
- if (i < 0) { i = this.#keys.length - 1 }
229
-
230
- const lastState = this.#keys[i]
231
- return this.#states[lastState]
232
- }
233
-
234
- pressed () {
275
+ /**
276
+ * Triggered when either a physical button, touchscreen button or Knob Button was pressed
277
+ * Updates the timeStampPressed and timeHold, and checks if the button was hold long enough (minPressed attribute)
278
+ * If the button type was not TOGGLE, it will decrease the index to the previous state.
279
+ * @returns
280
+ */
281
+ pressed() {
235
282
  this.timeStampPressed = Date.now()
236
-
283
+ this.updateState(this.#index, "pressed", true)
237
284
  this.#index++
238
285
 
239
- if (this.#enforcedIndex>=0){
240
- console.log("Enforced Index",this.#enforcedIndex )
286
+ if (this.#enforcedIndex >= 0) {
287
+ console.log("Enforced Index", this.#enforcedIndex)
241
288
  this.#index = this.#enforcedIndex
242
289
  }
243
290
 
244
- this.updateState(this.#index,"pressed",true)
291
+ // Update the State according to the correctly pressed state
292
+ if (this.#index < 0) { this.#index = this.#keys.length - 1 }
293
+ this.#index %= this.#keys.length
294
+
245
295
  return true
246
296
  }
247
297
 
248
- released () {
298
+ /**
299
+ * Triggered when either a physical button, touchscreen button or Knob Button was released
300
+ * Updates the timeStampReleased and timeHold, and checks if the button was hold long enough (minPressed attribute)
301
+ * If the button type was not TOGGLE, it will decrease the index to the previous state.
302
+ * @returns
303
+ */
304
+ released() {
249
305
  let elem = this.getCurrentElement()
250
306
  if (!elem) { return false }
251
307
  this.timeStampReleased = Date.now()
@@ -255,7 +311,6 @@ export class Button {
255
311
  if (this.timeHold < this.#params.minPressed) {
256
312
  // Update the State according to the not correct pressed state
257
313
  console.log('Did not hold minimum time of ', this.#params.minPressed, 'only', this.timeHold)
258
- //if (this.#index < 0) { this.#index = this.#keys.length - 1 }
259
314
  bExecute = false
260
315
  }
261
316
 
@@ -266,34 +321,41 @@ export class Button {
266
321
  break
267
322
  default:
268
323
  this.#index--
269
- //if (this.#index < 0) { this.#index = this.#keys.length - 1 }
270
324
  break
271
325
  }
272
326
 
273
- if (this.#enforcedIndex>=0){
274
- console.log("Enforced Index",this.#enforcedIndex )
327
+ if (this.#enforcedIndex >= 0 && this.#enforcedIndex != this.#index) {
328
+ // If we have an enforced index, we set it to the enforced index:
329
+ console.log("Enforcing Index", this.#enforcedIndex, "instead of", this.#index)
275
330
  this.#index = this.#enforcedIndex
276
331
  }
277
-
278
-
279
- this.updateState(this.#index,"released",bExecute)
280
-
281
- return true // this.runCommand()
282
- }
283
332
 
284
- updateState(index,eventType,bExecute){
285
- this.#index = index
286
- this.#event = eventType
287
333
  // Update the State according to the correctly pressed state
288
334
  if (this.#index < 0) { this.#index = this.#keys.length - 1 }
289
335
  this.#index %= this.#keys.length
336
+
337
+
338
+ this.updateState(this.#index, "released", bExecute)
339
+
340
+ return true
341
+ }
342
+
343
+
344
+ updateState(index, eventType, bExecute) {
345
+ this.#index = index
346
+ this.#event = eventType
290
347
  if (bExecute)
291
348
  this.runCommand()
292
- //console.log("TODO: expect newState", newState)
293
- return true // this.runCommand()
349
+ return true
294
350
  }
295
351
 
296
- async rotated (delta) {
352
+ /**
353
+ * Triggered when one of the physical KNOBS is rotated
354
+ * Calculates the new value based on the delta, and store it in the params.value
355
+ * @param {*} delta
356
+ * @returns
357
+ */
358
+ async rotated(delta) {
297
359
  if (!this.getCurrentElement()) { return false }
298
360
 
299
361
  this.#event = "rotated"
@@ -301,50 +363,47 @@ export class Button {
301
363
  return this.runCommand()
302
364
  }
303
365
 
304
- async changed(buttonID,nodeid,val){
366
+ /**
367
+ * This function is called when the value of a button is changed from outside (e.g. coming from an opcua subscription)
368
+ * @param {*} buttonID: the ID of the button that caused the change
369
+ * @param {*} nodeid: the nodeid that changed
370
+ * @param {*} val : the current value of the given nodeid
371
+ * @returns
372
+ */
373
+ async changed(buttonID, nodeid, val) {
305
374
  // Only handle updates within the same group identified by nodeid
306
- if (nodeid !== this.#params.nodeid){
307
- return
375
+ if (nodeid !== this.#params.nodeid) {
376
+ return
308
377
  }
309
378
 
310
379
  this.#index = 0;
311
380
  this.#enforcedIndex = -1;
312
381
  for (let i = 0; i < this.#keys.length; i++) {
313
- let key = this.#keys[i]
382
+ let stateStr = this.#keys[i].toString()
383
+ let valStr = val.toString()
314
384
  // check if the state-name is same as the value we get from outside:
315
- if (val == key){
316
- this.#index = i;
317
- console.info("enforce index", buttonID,nodeid,val,i)
318
- this.#enforcedIndex = this.#index;
385
+ if (valStr == stateStr) {
386
+ if (i !== this.#index) {
387
+ console.info("Changed index", this.id, nodeid, val, i)
388
+ this.#index = i;
389
+ console.info("enforce State index", this.id, nodeid, val, i)
390
+ this.#enforcedIndex = this.#index;
391
+ }
319
392
  break;
320
393
  }
321
-
322
- // check if the nodeid is the same and the value is one of the states
323
- // todo überarbeiten
324
- let state = this.#states[key]
325
- if (state.value === undefined)
326
- continue
327
-
328
- const params = {
329
- id: buttonID,
330
- key: buttonID,
331
- state : key,
332
- ...state
333
- }
334
- if (state && state.value !== undefined){
335
- let strVal = state.value.toString()
336
- let val1 = format(strVal,params)
337
- if (val1 === val?.toString()){
338
- this.#index = i;
339
- break;
340
- }
341
- }
342
- //break;
343
394
  }
344
395
  }
345
396
 
346
- async touchmove (x, y) {
347
- // if (!this.getCurrentElement()) { return false }
397
+ /**
398
+ * Handle a touchmove event on a touchscreen button
399
+ * This function calculates the new value based on the x and y coordinates of the touchmove event.
400
+ * It updates the moveLeft, moveRight, moveUp and moveDown parameters based on the x and y coordinates.
401
+ * It also calculates the delta for the value based on the y coordinate and updates the value parameter.
402
+ * @param {*} x
403
+ * @param {*} y
404
+ * @returns
405
+ */
406
+ async touchmove(x, y) {
348
407
 
349
408
  let delta = 0
350
409
  if (x > this.#params.x) {
@@ -365,8 +424,8 @@ export class Button {
365
424
  delta = 1
366
425
  }
367
426
 
368
- this.#params.x = (x%100)
369
- this.#params.y = (y%100)
427
+ this.#params.x = (x % 100)
428
+ this.#params.y = (y % 100)
370
429
 
371
430
  // Calculate delta for value no touchmove up/down
372
431
  this.#params.value = calcDelta(this.#params.value, delta, this.#params.min, this.#params.max)
@@ -375,7 +434,7 @@ export class Button {
375
434
  return false
376
435
  }
377
436
 
378
- getParams(elem){
437
+ getParams(elem) {
379
438
  // Call an action - include dynamic parameters
380
439
  // and also all attributes of elem + global config
381
440
  const params = {
@@ -385,71 +444,54 @@ export class Button {
385
444
  id: this.id,
386
445
  //key: this.key,
387
446
  event: this.#event,
388
- pressed : this.#event == "pressed",
389
- released : this.#event == "released",
390
- rotated : this.#event == "rotated",
391
- // state: this.#keys[this.#index]
447
+ pressed: this.#event == "pressed",
448
+ released: this.#event == "released",
449
+ rotated: this.#event == "rotated",
392
450
  }
393
451
  return params
394
452
  }
395
453
 
396
- async runCommand () {
397
- const elem = this.getCurrentElement()
454
+ /**
455
+ * Run a command based on the current element's parameters.
456
+ * This function checks if the current element has a command, http request or opcua request defined.
457
+ * If so, it will execute the command using the respective interface (shell, http or opcua).
458
+ * It will also emit profile and brightness changes if defined in the parameters.
459
+ * @returns
460
+ */
461
+ async runCommand() {
462
+ //const elem = this.getCurrentElement()
463
+ let params = this.getParams(this.getCurrentElement())
464
+
398
465
  // Only continue, if we have an element:
399
- if (!elem) {
466
+ if (!params) {
400
467
  return
401
468
  }
402
469
  // Filter for Event Type:
403
- if (elem.filter && elem.filter != this.#event){
470
+ if (params.filter && params.filter != this.#event) {
404
471
  return
405
472
  }
406
473
 
407
- if (elem.profile !== undefined) {
408
- profileEmitter.emit("profileChanged", elem.profile)
474
+ if (params.profile !== undefined && params.profile !== '') {
475
+ profileEmitter.emit("profileChanged", params.profile)
409
476
  }
410
477
 
411
- if (elem.brightness !== undefined) {
412
- profileEmitter.emit("brightnessChanged", elem.brightness)
478
+ if (params.brightness !== undefined) {
479
+ profileEmitter.emit("brightnessChanged", params.brightness)
413
480
  }
414
481
 
415
- if (elem.vibrate !== undefined) {
416
- profileEmitter.emit("vibrate", elem.vibrate)
482
+ if (params.vibrate !== undefined) {
483
+ profileEmitter.emit("vibrate", params.vibrate)
417
484
  }
418
485
 
419
- // Only continue, if we have an element, that contains some kind of command:
420
- if (!elem.cmd && !elem.http && !elem.opcua) {
421
- return
422
- }
423
-
424
- let params = this.getParams(elem)
425
486
  let res = ''
426
- if ('cmd' in elem) {
427
- if (shellinterface){
428
- res = await shellinterface.call(elem.cmd, params)
429
- }else{
430
- console.warn("shellinterface not started")
431
- }
487
+ if ('cmd' in params && shellinterface) {
488
+ res = await shellinterface.call(params.cmd, params)
432
489
  }
433
- if ('http' in elem) {
434
- if (httpinterface){
435
- res = await httpinterface.call(elem.http, params)
436
- }else{
437
- console.warn("httpinterface not started")
438
- }
490
+ if ('http' in params && httpinterface) {
491
+ res = await httpinterface.call(params.http, params)
439
492
  }
440
- if ('opcua' in elem) {
441
- if (opcuainterface){
442
- res = await opcuainterface.call(elem.opcua, params)
443
-
444
- /** TODO: CHECK THIS - don't think it's ever used any more */
445
- /*if (this.#data.statenodeid){
446
- let stateParams = params
447
- params.value = params.state
448
- res = await opcuainterface.call(this.#data.statenodeid, params)
449
- }*/
450
- }else{
451
- console.warn("opcuainterface not started")
452
- }
493
+ if ('opcua' in params && opcuainterface) {
494
+ res = await opcuainterface.call(params.opcua, params)
453
495
  }
454
496
 
455
497
  return res