loupedeck-commander 1.2.8 → 1.2.9

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/config.json CHANGED
@@ -4,10 +4,6 @@
4
4
  {
5
5
  "name": "profile-1",
6
6
  "file": "profile-1.json"
7
- },
8
- {
9
- "name": "profile-2",
10
- "file": "profile-2.json"
11
7
  }
12
8
  ]
13
9
  }
@@ -33,6 +33,7 @@ export class OPCUAIf extends BaseIf {
33
33
  #sub
34
34
  #connected
35
35
  #endpointurl
36
+ #publishingInterval
36
37
  monitoreditems
37
38
  types
38
39
  buttons
@@ -40,14 +41,14 @@ export class OPCUAIf extends BaseIf {
40
41
  super()
41
42
 
42
43
  this.LogInfo(`OPCUAIf Constructed`);
43
- }
44
+ }
44
45
 
45
- async stop(){
46
+ async stop() {
46
47
  if (!this.#client)
47
48
  return
48
-
49
+
49
50
  this.LogInfo(`OPCUAIf Stopping\n`)
50
- await this.#client.closeSession(this.#session,true)
51
+ await this.#client.closeSession(this.#session, true)
51
52
  await this.#client.disconnect()
52
53
  this.#connected = false
53
54
  this.#client = null
@@ -60,41 +61,47 @@ export class OPCUAIf extends BaseIf {
60
61
  * @param {*} config
61
62
  * @param {*} callbackFunction
62
63
  */
63
- async init( options = {},config = {}){
64
+ async init(options = {}, config = {}) {
64
65
  var res = this.Check(options)
65
- if (res<0){
66
+ if (res < 0) {
66
67
  this.LogError(`OPCUAIf: Missing essential options in dictionary => Quitting $res $options\n`)
67
68
  }
68
- try{
69
- this.#endpointurl = this.formatString(options.endpointurl,options)
69
+ try {
70
+ this.#endpointurl = this.formatString(options.endpointurl, options)
71
+ if (options.publishingInterval)
72
+ this.#publishingInterval = options.publishingInterval
73
+ else{
74
+ this.#publishingInterval = 250;
75
+ this.LogInfo(`OPCUAIf init using default publishingInterval: ${this.#publishingInterval}ms\n`);
76
+ }
70
77
  this.monitoreditems = {}
71
78
  this.types = {}
72
79
  this.buttons = {}
73
80
  this.LogInfo(`OPCUAIf init ${this.#endpointurl}\n`);
74
-
81
+
75
82
  await this.Connect(this.#endpointurl);
76
83
 
77
84
  let fields = [config.touch.center, config.knobs, config.buttons]
78
85
  const fieldKeys = Object.keys(fields)
79
86
  for (let f = 0; f < fieldKeys.length; f++) {
80
- let field=fields[f]
87
+ let field = fields[f]
81
88
  const keys = Object.keys(field)
82
89
  for (let i = 0; i < keys.length; i++) {
83
90
  const key = keys[i]
84
91
  const elem = field[key]
85
92
  // groupnode
86
- if (elem.nodeid){
87
- let format = this.formatString(elem.nodeid,options)
93
+ if (elem.nodeid) {
94
+ let format = this.formatString(elem.nodeid, options)
88
95
  let monitoredItemId = await this.Subscribe(format)
89
96
  this.buttons[monitoredItemId] = i
90
97
  }
91
98
  // statenode
92
- if (elem.statenodeid){
93
- let format = this.formatString(elem.statenodeid,options)
99
+ if (elem.statenodeid) {
100
+ let format = this.formatString(elem.statenodeid, options)
94
101
  let monitoredItemId = await this.Subscribe(format)
95
102
  this.buttons[monitoredItemId] = i
96
103
  }
97
- await this.monitorStates(elem,options)
104
+ await this.monitorStates(elem, options)
98
105
  }
99
106
  }
100
107
  } catch (error) {
@@ -107,17 +114,17 @@ export class OPCUAIf extends BaseIf {
107
114
  * @param {*} elem : Elem Object
108
115
  * @param {*} options
109
116
  */
110
- async monitorStates(elem,options){
117
+ async monitorStates(elem, options) {
111
118
  const stateKeys = Object.keys(elem.states)
112
119
  for (let i = 0; i < stateKeys.length; i++) {
113
120
  const key2 = stateKeys[i]
114
121
  const state = elem.states[key2]
115
- if (state.opcua){
116
- let format = this.formatString(state.opcua,options)
122
+ if (state.opcua) {
123
+ let format = this.formatString(state.opcua, options)
117
124
  let monitoredItemId = await this.Subscribe(format)
118
125
  this.buttons[monitoredItemId] = i
119
126
  }
120
- }
127
+ }
121
128
  }
122
129
 
123
130
  /**
@@ -130,17 +137,17 @@ export class OPCUAIf extends BaseIf {
130
137
  * - DataType.String
131
138
  * @returns the converted value.
132
139
  */
133
- convert(value,type){
134
- switch(type){
140
+ convert(value, type) {
141
+ switch (type) {
135
142
  case DataType.Int16:
136
143
  case DataType.Int32:
137
- if (typeof value == "number"){
144
+ if (typeof value == "number") {
138
145
  if (Number.isInteger(value))
139
146
  return value
140
- else
147
+ else
141
148
  return Math.trunc(value)
142
149
  }
143
- return parseInt(value,10)
150
+ return parseInt(value, 10)
144
151
  break
145
152
  case DataType.Float:
146
153
  if (typeof value == "number")
@@ -154,8 +161,8 @@ export class OPCUAIf extends BaseIf {
154
161
  case DataType.Boolean:
155
162
  if (typeof value == "number" && value === 1)
156
163
  return true
157
- if (typeof value == "string"){
158
- if (["true","on"].includes(value)){
164
+ if (typeof value == "string") {
165
+ if (["true", "on"].includes(value)) {
159
166
  return true
160
167
  }
161
168
  }
@@ -165,10 +172,10 @@ export class OPCUAIf extends BaseIf {
165
172
  }
166
173
  }
167
174
 
168
- async call (opcuaNode, options = {}) {
175
+ async call(opcuaNode, options = {}) {
169
176
  var res = this.Check(options)
170
- if (res<0){
171
- // this.LogError(`OPCUAIf call: Missing essential options in dictionary => Quitting $res\n`)
177
+ if (res < 0) {
178
+ // this.LogError(`OPCUAIf call: Missing essential options in dictionary => Quitting $res\n`)
172
179
  return false
173
180
  }
174
181
 
@@ -179,34 +186,41 @@ export class OPCUAIf extends BaseIf {
179
186
  if (typeof value == "string")
180
187
  value = super.formatString(options.value, options)
181
188
 
182
- var convertedValue = this.convert(value,type)
189
+ var convertedValue = this.convert(value, type)
183
190
  this.LogInfo(`OPCUAIf: write ${nodeId} => ${value}\n`)
184
- await this.Write(nodeId,convertedValue,type)
191
+ await this.Write(nodeId, convertedValue, type)
185
192
 
186
193
  var NewState = "waiting"
187
194
  return NewState
188
195
  }
189
196
 
190
197
  Check(options) {
191
- var res= super.Check(options)
192
- if (res <0){
193
- this.LogError(`OPCUAIf: mandatory parameter missing\n`)
198
+ var res = super.Check(options)
199
+ if (res < 0) {
200
+ this.LogError(`OPCUAIf: mandatory parameter missing\n`)
194
201
  return res
195
202
  }
196
- if (!"endpointurl" in options){
197
- this.LogError(`OPCUAIf: mandatory parameter endpointurl missing\n`)
198
- return -11}
199
- if (!"nodeid" in options){
200
- this.LogError(`OPCUAIf: mandatory parameter nodeid missing\n`)
201
- return -12}
202
- if (!"value" in options){
203
- this.LogError(`OPCUAIf: mandatory parameter value missing\n`)
204
- return -13}
203
+ if (!"endpointurl" in options) {
204
+ this.LogError(`OPCUAIf: mandatory parameter endpointurl missing\n`)
205
+ return -11
206
+ }
207
+ if (!"publishingInterval" in options) {
208
+ this.LogError(`OPCUAIf: mandatory parameter publishingInterval missing\n`)
209
+ return -11
210
+ }
211
+ if (!"nodeid" in options) {
212
+ this.LogError(`OPCUAIf: mandatory parameter nodeid missing\n`)
213
+ return -12
214
+ }
215
+ if (!"value" in options) {
216
+ this.LogError(`OPCUAIf: mandatory parameter value missing\n`)
217
+ return -13
218
+ }
205
219
  return 0
206
220
  }
207
221
 
208
222
  async Disconnect() {
209
- if (this.#client){
223
+ if (this.#client) {
210
224
  this.LogInfo(`OPCUAIf: Disconnect\n`);
211
225
  await this.#client.Disconnect()
212
226
  this.LogInfo(`OPCUAIf: Disconnected\n`);
@@ -216,7 +230,7 @@ export class OPCUAIf extends BaseIf {
216
230
  let self = this
217
231
  this.#client = OPCUAClient.create({
218
232
  applicationName: "NodeOPCUA-Client",
219
-
233
+
220
234
  endpointMustExist: false,
221
235
  // keepSessionAlive: true,
222
236
  requestedSessionTimeout: 60 * 1000,
@@ -227,44 +241,44 @@ export class OPCUAIf extends BaseIf {
227
241
  maxDelay: 5000,
228
242
  initialDelay: 2500
229
243
  },
230
-
244
+
231
245
  defaultSecureTokenLifetime: 20000,
232
246
  tokenRenewalInterval: 1000
233
247
  });
234
-
248
+
235
249
  this.#client.on("backoff", (retry, delay) => {
236
- if((retry%10) == 0)
250
+ if ((retry % 10) == 0)
237
251
  self.LogInfo(`OPCUAIf Try Reconnection ${retry} next attempt in ${delay}ms ${self.#endpointurl}\n`);
238
252
  });
239
-
253
+
240
254
  this.#client.on("connection_lost", () => {
241
255
  self.LogInfo(`OPCUAIf: Connection lost\n`);
242
256
  });
243
-
257
+
244
258
  this.#client.on("connection_reestablished", () => {
245
259
  self.LogInfo(`OPCUAIf: Connection re-established\n`);
246
260
  });
247
-
261
+
248
262
  this.#client.on("connection_failed", () => {
249
263
  self.LogInfo(`OPCUAIf: Connection failed\n`);
250
264
  });
251
265
  this.#client.on("start_reconnection", () => {
252
266
  self.LogInfo(`OPCUAIf: Starting reconnection\n`);
253
267
  });
254
-
268
+
255
269
  this.#client.on("after_reconnection", (err) => {
256
270
  self.LogInfo(`OPCUAIf: After Reconnection event => ${err}\n`);
257
271
  });
258
272
  this.#client.on("security_token_renewed", () => {
259
273
  self.LogDebug(`OPCUAIf: security_token_renewed\n`);
260
274
  })
261
- this.#client.on("lifetime_75", (token) => {})
262
-
275
+ this.#client.on("lifetime_75", (token) => { })
276
+
263
277
  this.LogInfo(`OPCUAIf: connecting client to ${url}\n`);//, this.#session.toString());
264
278
  await this.#client.connect(url);
265
-
279
+
266
280
  this.#session = await this.#client.createSession();
267
-
281
+
268
282
  this.#session.on("session_closed", (statusCode) => {
269
283
  self.LogInfo(`OPCUAIf: Session has been closed\n`);
270
284
  })
@@ -277,13 +291,14 @@ export class OPCUAIf extends BaseIf {
277
291
  this.#session.on("keepalive_failure", () => {
278
292
  self.LogInfo(`OPCUAIf: KeepAlive failure\n`);
279
293
  });
280
-
294
+
295
+ // create subscription with a custom publishing interval:
281
296
  this.#sub = await this.#session.createSubscription2({
282
297
  maxNotificationsPerPublish: 9000,
283
298
  publishingEnabled: true,
284
299
  requestedLifetimeCount: 10,
285
300
  requestedMaxKeepAliveCount: 10,
286
- requestedPublishingInterval: 1000
301
+ requestedPublishingInterval: this.#publishingInterval
287
302
  });
288
303
 
289
304
  this.LogInfo(`OPCUAIf: session created\n`);//, this.#session.toString());
@@ -292,7 +307,7 @@ export class OPCUAIf extends BaseIf {
292
307
  this.#connected = true
293
308
  this.#endpointurl = url
294
309
  }
295
-
310
+
296
311
  async Subscribe(nodeID) {
297
312
  // install monitored item
298
313
 
@@ -300,7 +315,7 @@ export class OPCUAIf extends BaseIf {
300
315
  for (let i = 0; i < keys.length; i++) {
301
316
  const key = keys[i]
302
317
  const elem = this.monitoreditems[key]
303
- if (elem == nodeID){
318
+ if (elem == nodeID) {
304
319
  // already registered => return itemid
305
320
  return key
306
321
  }
@@ -315,14 +330,14 @@ export class OPCUAIf extends BaseIf {
315
330
  discardOldest: true,
316
331
  queueSize: 10
317
332
  };
318
-
319
- if (!this.#sub){
333
+
334
+ if (!this.#sub) {
320
335
  this.LogError(`OPCUAIf: not register monitored items $itemToMonitor\n`);
321
336
  return
322
337
  }
323
338
  const monitoredItem = await this.#sub.monitor(itemToMonitor, monitoringParameters, TimestampsToReturn.Both);
324
339
  this.monitoreditems[monitoredItem.monitoredItemId] = nodeID
325
- var self=this
340
+ var self = this
326
341
  monitoredItem.on("changed", function (dataValue) {
327
342
  var nodeId = self.monitoreditems[this.monitoredItemId]
328
343
  var buttonID = self.buttons[this.monitoredItemId]
@@ -330,55 +345,59 @@ export class OPCUAIf extends BaseIf {
330
345
  self.types[nodeId] = dataValue.value.dataType
331
346
  // publish the value to subscribers:
332
347
  self.LogInfo(`OPCUAIf: monitored item changed: ${nodeId} => ${dataValue.value.value}\n`);
333
- self.emit('monitored item changed',buttonID,nodeId, dataValue.value.value)
348
+ self.emit('monitored item changed', buttonID, nodeId, dataValue.value.value)
334
349
  });
335
350
 
336
351
  return monitoredItem.monitoredItemId;
337
352
  }
338
-
353
+
339
354
  async Read(nodeID) {
340
355
  const nodeToRead = {
341
356
  nodeId: nodeID,
342
357
  attributeId: AttributeIds.Value
343
358
  };
344
- if (!this.#connected){
359
+ if (!this.#connected) {
345
360
  this.LogError(`OPCUAIf: not connected, cannot read ${nodeID}\n`);
346
361
  return
347
362
  }
348
363
  const dataValue2 = await this.#session.read(nodeToRead, 0);
349
- this.LogError("OPCUAIf: read nodeID ",nodeID, dataValue2.toString(),"\n");
364
+ this.LogError("OPCUAIf: read nodeID ", nodeID, dataValue2.toString(), "\n");
350
365
  return dataValue2
351
366
  }
352
367
 
353
- async Write(nodeID,value,datatype=DataType.String) {
368
+ async Write(nodeID, value, datatype = DataType.String) {
354
369
  let self = this
355
- if (!this.#connected){
356
- self.LogError("OPCUAIf: not connected, cannot write",nodeID, value,"\n");
370
+ if (!this.#connected) {
371
+ self.LogError("OPCUAIf: not connected, cannot write", nodeID, value, "\n");
357
372
  return
358
373
  }
359
374
  var nodesToWrite = [{
360
375
  nodeId: nodeID,
361
376
  attributeId: AttributeIds.Value,
362
377
  indexRange: null,
363
- value: {
364
- value: {
378
+ value: {
379
+ value: {
365
380
  dataType: datatype,
366
381
  value: value
367
382
  }
368
- }
383
+ }
369
384
  }];
370
- await this.#session.write(nodesToWrite, function(err,statusCodes) {
371
- if (!err) {
372
- if (statusCodes && statusCodes[0].value != 0){
373
- self.LogInfo(`OPCUAIf: error with Node: "${nodeID}", status ${statusCodes[0]}\n`);
374
- }else{
375
- self.LogInfo(`OPCUAIf: wrote ${nodeID} => ${value}\n`);
385
+ try {
386
+ await this.#session.write(nodesToWrite, function (err, statusCodes) {
387
+ if (!err) {
388
+ if (statusCodes && statusCodes[0].value != 0) {
389
+ self.LogInfo(`OPCUAIf: error with Node: "${nodeID}", status ${statusCodes[0]}\n`);
390
+ } else {
391
+ self.LogInfo(`OPCUAIf: wrote ${nodeID} => ${value}\n`);
392
+ }
393
+ } else {
394
+ self.LogError("OPCUAIf: write NOT ok", nodeID, value, "\n");
395
+ self.LogError(err)
376
396
  }
377
- }else{
378
- self.LogError("OPCUAIf: write NOT ok",nodeID, value,"\n");
379
- self.LogError(err)
380
- }
381
- });
397
+ });
398
+ } catch (err) {
399
+ self.LogError("OPCUAIf: write NOT ok", nodeID, value, "\n");
400
+ self.LogError(err)
401
+ }
382
402
  }
383
403
  }
384
-
@@ -6,23 +6,23 @@ import { BaseIf } from './baseif.mjs'
6
6
  * Our Special-Handler just used the Default - and adds Vibration after triggers through Button-Releases
7
7
  */
8
8
  export class SHELLif extends BaseIf {
9
- async call (cmd, options = {}) {
9
+ async call(cmd, options = {}) {
10
10
  var res = this.Check(options)
11
- if (res<0){
12
- return false
11
+ if (res < 0) {
12
+ return false
13
13
  }
14
14
  let formattedCmd = super.call(cmd, options)
15
15
  return await this.sh(formattedCmd)
16
16
  }
17
17
 
18
- async stop(){
18
+ async stop() {
19
19
  this.LogInfo("SHELLif: Stopping")
20
20
  }
21
21
 
22
22
  Check(options) {
23
- var res= super.Check(options)
24
- if (res <0){
25
- this.LogError(`SHELLif: mandatory parameter missing\n`)
23
+ var res = super.Check(options)
24
+ if (res < 0) {
25
+ this.LogError(`SHELLif: mandatory parameter missing\n`)
26
26
  return res
27
27
  }
28
28
  }
@@ -32,22 +32,27 @@ export class SHELLif extends BaseIf {
32
32
  * @param {*} cmd
33
33
  * @returns
34
34
  */
35
- async sh (cmd) {
36
- let self = this;
35
+ async sh(cmd) {
36
+ let self = this;
37
37
  this.LogDebug(`ShellIf: runCmd: ${cmd}\n`)
38
-
38
+
39
39
  return new Promise(function (resolve, reject) {
40
- exec(cmd, (err, stdout, stderr) => {
41
- if (stdout.length>0)
42
- self.LogInfo(`SHELLif Out: ${stdout}`)
43
- if (stderr.length>0)
44
- self.LogError(`SHELLif Err: ${stderr}`)
45
- if (err) {
46
- reject(err)
47
- } else {
48
- resolve({ stdout, stderr })
49
- }
50
- })
40
+ try {
41
+ exec(cmd, (err, stdout, stderr) => {
42
+ if (stdout.length > 0)
43
+ self.LogInfo(`SHELLif Out: ${stdout}`)
44
+ if (stderr.length > 0)
45
+ self.LogError(`SHELLif Err: ${stderr}`)
46
+ if (err) {
47
+ resolve(err)
48
+ } else {
49
+ resolve({ stdout, stderr })
50
+ }
51
+ })
52
+ } catch (e) {
53
+ console.error(`Error in script: ${e}`)
54
+ resolve()
55
+ }
51
56
  })
52
57
  }
53
58
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "loupedeck-commander",
3
- "version": "1.2.8",
3
+ "version": "1.2.9",
4
4
  "description": "A system to ease working with LoupeDeck devices using CMD-line, OPC/UA or HTTP-client interfaces",
5
5
  "main": "index.mjs",
6
6
  "scripts": {
package/profile-1.json CHANGED
@@ -229,7 +229,7 @@
229
229
  "states": {
230
230
  "on": {
231
231
  "cmd": "echo \"{id} {state}\"",
232
- "opcua": "ns=2;s=Is{simnbr}.Audio.in.VolumeAccustic"
232
+ "opcua": "ns=1;s={simnbr}.Function1"
233
233
  }
234
234
  },
235
235
  "group": ""
@@ -263,6 +263,7 @@
263
263
  "hostname": "127.0.0.1",
264
264
  "simnbr": "1",
265
265
  "endpointurl": "opc.tcp://{hostname}:4840",
266
+ "publishingInterval" : 200,
266
267
  "nodeid" : "ns=0;s=nodeID",
267
268
  "verbose": true
268
269
  }