loupedeck-commander 1.2.6 → 1.2.7

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.
@@ -19,7 +19,7 @@ export class ApplicationConfig {
19
19
  else{
20
20
  this.application = config.application
21
21
  for (let i = 0; i < config.profiles.length; i++) {
22
- const profile = new Profile(config.profiles[i])
22
+ const profile = new Profile(config.profiles[i],config.profiles.length,i)
23
23
  if (profile.loaded){
24
24
  this.profiles.push(profile)
25
25
  }else{
@@ -45,10 +45,14 @@ class Profile {
45
45
  #file = ''
46
46
  loaded = false
47
47
  #error = true
48
+ #profileCount = 0
49
+ #index = 0
48
50
 
49
- constructor (data) {
51
+ constructor (data,profileCount,index) {
50
52
  this.name = data.name
51
53
  this.#file = data.file
54
+ this.#profileCount = profileCount
55
+ this.#index = index
52
56
  this.touch = new TouchConfig({})
53
57
  this.buttons = new ButtonConfig().buttons
54
58
  this.knobs = new KnobsConfig().knobs
@@ -59,7 +63,7 @@ class Profile {
59
63
  }
60
64
 
61
65
  loadFromFile (fileName) {
62
- console.info(`ProfileConfig: Loading Profile File ${fileName}`)
66
+ console.info(`ProfileConfig: Loading Profile File ${fileName}, Index ${this.#index}`)
63
67
  const config = readJSONFile(fileName)
64
68
  if (config === undefined) {
65
69
  console.warn(`ProfileConfig: Cannot parse/load Profile File ${fileName}`)
@@ -70,12 +74,12 @@ class Profile {
70
74
  }else if (!config.touch){
71
75
  console.warn(`ProfileConfig: File ${fileName} is missing a touch attribute`)
72
76
  return false
73
- }else if (!config.buttons){
74
- console.warn(`ProfileConfig: File ${fileName} is missing a buttons attribute`)
75
- return false
76
77
  }else if (!config.parameters){
77
78
  console.warn(`ProfileConfig: File ${fileName} is missing a parameters attribute`)
78
79
  return false
80
+ }else if (!config.buttons){
81
+ console.info(`ProfileConfig: File ${fileName} is missing a buttons attribute - will be used to switch profiles by default`)
82
+ // return false
79
83
  }
80
84
  this.profile = config.profile
81
85
  this.description = config.description
@@ -84,7 +88,7 @@ class Profile {
84
88
  this.touch = new TouchConfig(config.touch)
85
89
  // Load the Configurations for Button-Areas
86
90
 
87
- this.buttons = new ButtonConfig(config.buttons).buttons
91
+ this.buttons = new ButtonConfig(config.buttons,this.#profileCount,this.#index).buttons
88
92
  this.knobs = new KnobsConfig(config.knobs).knobs
89
93
  // Load Parameters.parameters = config.parameters
90
94
  this.parameters = new ParametersConfig(config.parameters).parameters
@@ -154,19 +158,32 @@ class TouchConfig {
154
158
  * Class that handles the different configs for the touch displays of the device covering Loupedeck Live (without knob) and also CT (with knob)
155
159
  */
156
160
  class ButtonConfig {
157
- buttons = {
158
- "0" : { "states" : { "off" : { "color": "#000000", "cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#550000", "cmd": "echo \"{id} {state}\"" } }, group : "" },
159
- "1" : { "states" : { "off" : { "color": "#000000", "cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#ff0000", "cmd": "echo \"{id} {state}\"" } }, group : "" },
160
- "2" : { "states" : { "off" : { "color": "#000000", "cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#005500", "cmd": "echo \"{id} {state}\"" } }, group : "" },
161
- "3" : { "states" : { "off" : { "color": "#000000", "cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "cmd": "echo \"{id} {state}\"" } }, group : "" },
162
- "4" : { "states" : { "off" : { "color": "#000000", "cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#000055", "cmd": "echo \"{id} {state}\"" } }, group : "" },
163
- "5" : { "states" : { "off" : { "color": "#000000", "cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#0000ff", "cmd": "echo \"{id} {state}\"" } }, group : "" },
164
- "6" : { "states" : { "off" : { "color": "#000000", "cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#555500", "cmd": "echo \"{id} {state}\"" } }, group : "" },
165
- "7" : { "states" : { "off" : { "color": "#000000", "cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#ffff00", "cmd": "echo \"{id} {state}\"" } }, group : "" },
161
+ buttons = {}
162
+ defaultButtons = {
163
+ "0" : {"states" : { "off" : { "filter": "pressed", "color": "#000000", "cmd": "echo \"{id} {state}\"" }, "on" : { "filter": "pressed","color": "#ff0000", "cmd": "echo \"{id} {state}\"" } }, group : "onoff" },
164
+ "1" : {"states" : { "off" : { "filter": "pressed", "color": "#000055", "cmd": "echo \"{id} {state}\"" }, "on" : { "filter": "pressed", "profile": 0, "color": "#00ff00", "cmd": "echo \"{id} {state}\"" } }, group : "profiles" },
165
+ "2" : {"states" : { "off" : { "filter": "pressed", "color": "#000055", "cmd": "echo \"{id} {state}\"" }, "on" : { "filter": "pressed", "profile": 1, "color": "#00ff00", "cmd": "echo \"{id} {state}\"" } }, group : "profiles" },
166
+ "3" : {"states" : { "off" : { "filter": "pressed", "color": "#000055", "cmd": "echo \"{id} {state}\"" }, "on" : { "filter": "pressed", "profile": 2, "color": "#00ff00", "cmd": "echo \"{id} {state}\"" } }, group : "profiles" },
167
+ "4" : {"states" : { "off" : { "filter": "pressed", "color": "#000055", "cmd": "echo \"{id} {state}\"" }, "on" : { "filter": "pressed", "profile": 3, "color": "#00ff00", "cmd": "echo \"{id} {state}\"" } }, group : "profiles" },
168
+ "5" : {"states" : { "off" : { "filter": "pressed", "color": "#000055", "cmd": "echo \"{id} {state}\"" }, "on" : { "filter": "pressed", "profile": 4, "color": "#00ff00", "cmd": "echo \"{id} {state}\"" } }, group : "profiles" },
169
+ "6" : {"states" : { "off" : { "filter": "pressed", "color": "#000055", "cmd": "echo \"{id} {state}\"" }, "on" : { "filter": "pressed", "profile": 5, "color": "#00ff00", "cmd": "echo \"{id} {state}\"" } }, group : "profiles" },
170
+ "7" : {"states" : { "off" : { "filter": "pressed", "color": "#000055", "cmd": "echo \"{id} {state}\"" }, "on" : { "filter": "pressed", "profile": 6, "color": "#00ff00", "cmd": "echo \"{id} {state}\"" } }, group : "profiles" },
166
171
  }
167
172
 
168
- constructor (data) {
169
- this.loadFromJSON(data)
173
+ constructor (data,profileCount,index) {
174
+ if (data)
175
+ return this.loadFromJSON(data)
176
+ // Default to profile switching buttons
177
+ var keys = Object.keys(this.defaultButtons)
178
+ for (let i = 0; i <= profileCount; i++) {
179
+ var key = keys[i]
180
+ this.buttons[key] = this.defaultButtons[key]
181
+ if (i==(index+1)){
182
+ this.buttons[key].default = "on"
183
+ }
184
+
185
+ }
186
+
170
187
  }
171
188
 
172
189
  loadFromJSON (data) {
@@ -134,6 +134,13 @@ export class BaseLoupeDeckHandler {
134
134
  const dLeft = this.device.displays.left
135
135
  const dRight = this.device.displays.right
136
136
  const dCenter = this.device.displays.center
137
+
138
+ this.screens.center = undefined
139
+ this.screens.left = undefined
140
+ this.screens.right = undefined
141
+ this.buttons = undefined
142
+ this.knobs = undefined
143
+
137
144
 
138
145
  this.screens.center = new ButtonField('center', this.device.rows, this.device.columns, dCenter.width, dCenter.height, profile.touch.center,profile)
139
146
  this.screens.left = new ButtonField('left', 1, 1, dLeft.width, dLeft.height, profile.touch.left,profile)
@@ -222,7 +229,7 @@ export class BaseLoupeDeckHandler {
222
229
  const id = event.id
223
230
  if (Number.isInteger(id)){
224
231
  ok = await this.buttons.pressed(id)
225
- await this.buttons.draw(this.device)
232
+ //await this.buttons.draw(this.device)
226
233
  }else{
227
234
  ok = await this.knobs.pressed(id)
228
235
  }
@@ -237,7 +244,7 @@ export class BaseLoupeDeckHandler {
237
244
  const id = event.id
238
245
  if (Number.isInteger(id) && this.buttons){
239
246
  ok = await this.buttons.released(id)
240
- await this.buttons.draw(this.device)
247
+ //await this.buttons.draw(this.device)
241
248
  }else{
242
249
  if(this.knobs)
243
250
  ok = await this.knobs.released(id)
@@ -64,9 +64,9 @@ export class ButtonField {
64
64
  #keys = []
65
65
  #type
66
66
  #name
67
- #config
67
+ #profile
68
68
 
69
- constructor (name, rows, columns, width, height, data, config) {
69
+ constructor (name, rows, columns, width, height, data, profile) {
70
70
  console.info(`ButtonField ${name.padEnd(10, ' ')} Buttons: ${rows} x ${columns} , Pixels ${width} x ${height}`)
71
71
  this.#name = name
72
72
  this.width = width
@@ -75,17 +75,17 @@ export class ButtonField {
75
75
  this.#columns = columns
76
76
  this.#screen = this.width > 0 && this.height > 0
77
77
  this.#type = 'button'
78
+ this.#profile = profile
78
79
  if (this.#screen) { this.#type = 'touch' }
79
80
 
80
81
  const keys = Object.keys(data)
81
82
  for (let i = 0; i < keys.length; i++) {
82
83
  const key = keys[i]
83
- const tb = new Button(`${this.#type}-${key}`, width / columns, height / rows, data[key],key,config.parameters)
84
+ const tb = new Button(`${this.#type}-${key}`, width / columns, height / rows, data[key],key,this.#profile.parameters)
84
85
  this.#buttons[key] = tb
85
86
  }
86
87
 
87
88
  this.#keys = keys
88
- this.#config = config
89
89
  }
90
90
 
91
91
 
@@ -124,10 +124,10 @@ export class ButtonField {
124
124
  for (let i = 0; i < this.#keys.length; i++) {
125
125
  const key = this.#keys[i]
126
126
  if (isNaN(key)) {
127
- await this.#buttons[key].load(this.#config)
127
+ await this.#buttons[key].load(this.#profile)
128
128
  } else {
129
129
  const iVal = parseInt(key, 10)
130
- await this.#buttons[iVal].load(this.#config)
130
+ await this.#buttons[iVal].load(this.#profile)
131
131
  }
132
132
  }
133
133
  }
@@ -190,7 +190,7 @@ export class ButtonField {
190
190
  }
191
191
 
192
192
  export class Button {
193
- #config
193
+ #profile
194
194
  width = 0
195
195
  height = 0
196
196
 
@@ -260,7 +260,10 @@ export class Button {
260
260
  if (data.nodeid){
261
261
  this.#nodeid = format(data.nodeid, params)
262
262
  }
263
-
263
+ if (data.default) {
264
+ this.#index = this.#keys.indexOf(data.default)
265
+ }
266
+
264
267
  }
265
268
 
266
269
  setState (index = 0) {
@@ -282,7 +285,7 @@ export class Button {
282
285
  id:idx,
283
286
  color: `rgba(${r}, ${g}, ${b})`
284
287
  }
285
- // console.log(' Set Button Color',val.id,elem.color, val.color)
288
+ // console.log(' Set Button Color',id, val.id,elem.color, val.color)
286
289
  device.setButtonColor(val)
287
290
  } catch (error) {
288
291
  console.error(' Error', error)
@@ -315,7 +318,7 @@ export class Button {
315
318
  }
316
319
 
317
320
  async load (globalConfig) {
318
- this.#config = globalConfig
321
+ this.#profile = globalConfig
319
322
  for (let i = 0; i < this.#keys.length; i++) {
320
323
  const key = this.#keys[i]
321
324
  const elem = this.#states[key]
@@ -392,7 +395,7 @@ export class Button {
392
395
 
393
396
  updateState(index,eventType){
394
397
  this.#index = index
395
- this.#event = eventType
398
+ this.#event = eventType
396
399
  // Update the State according to the correctly pressed state
397
400
  if (this.#index < 0) { this.#index = this.#keys.length - 1 }
398
401
  this.#index %= this.#keys.length
@@ -479,7 +482,7 @@ export class Button {
479
482
  return
480
483
  }
481
484
 
482
- if (elem.profile){
485
+ if (elem.profile !== undefined) {
483
486
  profileEmitter.emit("profileChanged", elem.profile)
484
487
  }
485
488
 
@@ -492,7 +495,7 @@ export class Button {
492
495
  // and also all attributes of elem + global config
493
496
  const params = {
494
497
  text: this.getCurrentText(),
495
- ...this.#config.parameters,
498
+ ...this.#profile.parameters,
496
499
  ...elem,
497
500
  id: this.id,
498
501
  key: this.key,
package/config.json CHANGED
@@ -4,6 +4,10 @@
4
4
  {
5
5
  "name": "profile-1",
6
6
  "file": "profile-1.json"
7
+ },
8
+ {
9
+ "name": "profile-2",
10
+ "file": "profile-2.json"
7
11
  }
8
12
  ]
9
13
  }
@@ -14,7 +14,9 @@ export class BaseIf extends EventEmitter {
14
14
 
15
15
  this.cmd = cmd
16
16
  this.options = options
17
- this.formattedCommand = this.formatString(cmd, options)
17
+ this.formattedCommand = this.formatString(cmd, options)
18
+ this.LogDebug("Formatted command: ", this.formattedCommand,"\n")
19
+ this.LogDebug("Options",JSON.stringify(options),"\n" )
18
20
  return this.formattedCommand
19
21
  }
20
22
 
@@ -55,6 +55,12 @@ export class OPCUAIf extends BaseIf {
55
55
  this.LogInfo(`OPCUAIf Stopped\n`)
56
56
  }
57
57
 
58
+ /**
59
+ * Initialize the OPCUA client and subscribe to monitored items.
60
+ * @param {*} options
61
+ * @param {*} config
62
+ * @param {*} callbackFunction
63
+ */
58
64
  async init( options = {},config = {},callbackFunction){
59
65
  var res = this.Check(options)
60
66
  if (res<0){
@@ -70,7 +76,7 @@ export class OPCUAIf extends BaseIf {
70
76
 
71
77
  await this.Connect(this.#endpointurl);
72
78
 
73
- let fields = [config.touch.center, config.knobs]
79
+ let fields = [config.touch.center, config.knobs, config.buttons]
74
80
  const fieldKeys = Object.keys(fields)
75
81
  for (let f = 0; f < fieldKeys.length; f++) {
76
82
  let field=fields[f]
@@ -91,6 +97,11 @@ export class OPCUAIf extends BaseIf {
91
97
  }
92
98
  }
93
99
 
100
+ /**
101
+ *
102
+ * @param {*} elem : Elem Object
103
+ * @param {*} options
104
+ */
94
105
  async monitorStates(elem,options){
95
106
  const stateKeys = Object.keys(elem.states)
96
107
  for (let i = 0; i < stateKeys.length; i++) {
@@ -104,6 +115,16 @@ export class OPCUAIf extends BaseIf {
104
115
  }
105
116
  }
106
117
 
118
+ /**
119
+ * Convert the given value to the specified type.
120
+ * @param {*} value : The value to convert.
121
+ * @param {*} type : The type to convert to. Can be one of the following:
122
+ * - DataType.Int16
123
+ * - DataType.Int32
124
+ * - DataType.Float
125
+ * - DataType.String
126
+ * @returns the converted value.
127
+ */
107
128
  convert(value,type){
108
129
  switch(type){
109
130
  case DataType.Int16:
@@ -121,6 +142,10 @@ export class OPCUAIf extends BaseIf {
121
142
  return value
122
143
  return parseFloat(value)
123
144
  break;
145
+ case DataType.String:
146
+ if (typeof value == "number")
147
+ return value.toString();
148
+ return value
124
149
  default:
125
150
  return value
126
151
  }
@@ -135,13 +160,13 @@ export class OPCUAIf extends BaseIf {
135
160
 
136
161
  var nodeId = super.formatString(opcuaNode, options)
137
162
 
138
- var type = this.types[opcuaNode]
163
+ var type = this.types[nodeId]
139
164
  var value = options.value
140
165
  if (typeof value == "string")
141
166
  value = super.formatString(options.value, options)
142
167
 
143
168
  var convertedValue = this.convert(value,type)
144
- //this.LogInfo(`OPCUAIf: write ${nodeId} => ${value}\n`)
169
+ this.LogInfo(`OPCUAIf: write ${nodeId} => ${value}\n`)
145
170
  await this.Write(nodeId,convertedValue,type)
146
171
 
147
172
  var NewState = "waiting"
@@ -0,0 +1,5 @@
1
+ # Numbers Icons
2
+
3
+ Downloaded from:
4
+
5
+ - https://www.freepik.com/author/moniruldislam/icons/generic-color-lineal-color_10172?query=Number#from_element=families
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
package/package.json CHANGED
@@ -1,19 +1,19 @@
1
1
  {
2
2
  "name": "loupedeck-commander",
3
- "version": "1.2.6",
3
+ "version": "1.2.7",
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": {
7
- "test": "echo \"INFO: no test specified\" && exit 0",
7
+ "test": "node test.mjs",
8
8
  "lint": "echo \"INFO: no linter specified\" && exit 0",
9
9
  "format": "echo \"INFO: no format rule specified\" && exit 0",
10
10
  "start": "node index.mjs"
11
11
  },
12
12
  "dependencies": {
13
- "canvas": "^2.11.2",
14
- "loupedeck": "^6.0.1",
13
+ "canvas": "^3.1.0",
14
+ "loupedeck": "^7.0.0",
15
15
  "mkdirp": "^3.0.1",
16
- "node-opcua": "^2.138.1",
16
+ "node-opcua": "^2.153.0",
17
17
  "string-template": "^1.0.0"
18
18
  },
19
19
  "author": "Thomas Schneider",
package/profile-1.json CHANGED
@@ -228,7 +228,8 @@
228
228
  "knobBL": {
229
229
  "states": {
230
230
  "on": {
231
- "cmd": "echo \"{id} {state}\""
231
+ "cmd": "echo \"{id} {state}\"",
232
+ "opcua": "ns=2;s=Is{simnbr}.Audio.in.VolumeAccustic"
232
233
  }
233
234
  },
234
235
  "group": ""
@@ -258,117 +259,11 @@
258
259
  "group": ""
259
260
  }
260
261
  },
261
- "buttons": {
262
- "0": {
263
- "states": {
264
- "off": {
265
- "color": "#000000",
266
- "cmd": "echo \"{id} {state}\""
267
- },
268
- "on": {
269
- "color": "#550000",
270
- "cmd": "echo \"{id} {state}\""
271
- }
272
- },
273
- "group": ""
274
- },
275
- "1": {
276
- "states": {
277
- "off": {
278
- "color": "#000000",
279
- "cmd": "echo \"{id} {state}\""
280
- },
281
- "on": {
282
- "color": "#ff0000",
283
- "cmd": "echo \"{id} {state}\""
284
- }
285
- },
286
- "group": ""
287
- },
288
- "2": {
289
- "states": {
290
- "off": {
291
- "color": "#000000",
292
- "cmd": "echo \"{id} {state}\""
293
- },
294
- "on": {
295
- "color": "#005500",
296
- "cmd": "echo \"{id} {state}\""
297
- }
298
- },
299
- "group": ""
300
- },
301
- "3": {
302
- "states": {
303
- "off": {
304
- "color": "#000000",
305
- "cmd": "echo \"{id} {state}\""
306
- },
307
- "on": {
308
- "color": "#00ff00",
309
- "cmd": "echo \"{id} {state}\""
310
- }
311
- },
312
- "group": ""
313
- },
314
- "4": {
315
- "states": {
316
- "off": {
317
- "color": "#000000",
318
- "cmd": "echo \"{id} {state}\""
319
- },
320
- "on": {
321
- "color": "#000055",
322
- "cmd": "echo \"{id} {state}\""
323
- }
324
- },
325
- "group": ""
326
- },
327
- "5": {
328
- "states": {
329
- "off": {
330
- "color": "#000000",
331
- "cmd": "echo \"{id} {state}\""
332
- },
333
- "on": {
334
- "color": "#0000ff",
335
- "cmd": "echo \"{id} {state}\""
336
- }
337
- },
338
- "group": ""
339
- },
340
- "6": {
341
- "states": {
342
- "off": {
343
- "color": "#000000",
344
- "cmd": "echo \"{id} {state}\""
345
- },
346
- "on": {
347
- "color": "#555500",
348
- "cmd": "echo \"{id} {state}\""
349
- }
350
- },
351
- "group": ""
352
- },
353
- "7": {
354
- "states": {
355
- "off": {
356
- "color": "#000000",
357
- "cmd": "echo \"{id} {state}\""
358
- },
359
- "on": {
360
- "color": "#ffff00",
361
- "cmd": "echo \"{id} {state}\"",
362
- "http": "http://{hostname}:7778/control/connections",
363
- "opcua": "ns=4;s=Is{simnbr}.Kvm.out.Source"
364
- }
365
- },
366
- "group": ""
367
- }
368
- },
369
262
  "parameters": {
370
263
  "hostname": "127.0.0.1",
264
+ "simnbr": "1",
371
265
  "endpointurl": "opc.tcp://{hostname}:4840",
372
- "nodeid" : "ns=0;s=nodeID"
266
+ "nodeid" : "ns=0;s=nodeID",
267
+ "verbose": true
373
268
  }
374
269
  }
package/profile-2.json ADDED
@@ -0,0 +1,290 @@
1
+ {
2
+ "name": "profile-1",
3
+ "profile": "example",
4
+ "description": "",
5
+ "touch": {
6
+ "center": {
7
+ "0": {
8
+ "default": "one",
9
+ "states": {
10
+ "off": {
11
+ "color": "#000099",
12
+ "cmd": "echo \"{id} {state}\""
13
+ },
14
+ "one": {
15
+ "color": "#00ff00",
16
+ "image": "numbers/one_9278045.png",
17
+ "cmd": "echo \"{id} {state}\""
18
+ },
19
+ "two": {
20
+ "color": "#00ff00",
21
+ "image": "numbers/two_9278103.png",
22
+ "cmd": "echo \"{id} {state}\""
23
+ },
24
+ "three": {
25
+ "color": "#00ff00",
26
+ "image": "numbers/three_9278150.png",
27
+ "cmd": "echo \"{id} {state}\""
28
+ },
29
+ "four": {
30
+ "color": "#00ff00",
31
+ "image": "numbers/four_9278183.png",
32
+ "cmd": "echo \"{id} {state}\""
33
+ },
34
+ "five": {
35
+ "color": "#00ff00",
36
+ "image": "numbers/five_9278222.png",
37
+ "cmd": "echo \"{id} {state}\""
38
+ }
39
+ }
40
+ },
41
+ "1": {
42
+ "default": "two",
43
+ "states": {
44
+ "off": {
45
+ "color": "#000099",
46
+ "cmd": "echo \"{id} {state}\""
47
+ },
48
+ "one": {
49
+ "color": "#00ff00",
50
+ "image": "numbers/one_9278045.png",
51
+ "cmd": "echo \"{id} {state}\""
52
+ },
53
+ "two": {
54
+ "color": "#00ff00",
55
+ "image": "numbers/two_9278103.png",
56
+ "cmd": "echo \"{id} {state}\""
57
+ },
58
+ "three": {
59
+ "color": "#00ff00",
60
+ "image": "numbers/three_9278150.png",
61
+ "cmd": "echo \"{id} {state}\""
62
+ },
63
+ "four": {
64
+ "color": "#00ff00",
65
+ "image": "numbers/four_9278183.png",
66
+ "cmd": "echo \"{id} {state}\""
67
+ },
68
+ "five": {
69
+ "color": "#00ff00",
70
+ "image": "numbers/five_9278222.png",
71
+ "cmd": "echo \"{id} {state}\""
72
+ }
73
+ }
74
+ },
75
+ "2": {
76
+ "default": "three",
77
+ "states": {
78
+ "off": {
79
+ "color": "#000099",
80
+ "cmd": "echo \"{id} {state}\""
81
+ },
82
+ "one": {
83
+ "color": "#00ff00",
84
+ "image": "numbers/one_9278045.png",
85
+ "cmd": "echo \"{id} {state}\""
86
+ },
87
+ "two": {
88
+ "color": "#00ff00",
89
+ "image": "numbers/two_9278103.png",
90
+ "cmd": "echo \"{id} {state}\""
91
+ },
92
+ "three": {
93
+ "color": "#00ff00",
94
+ "image": "numbers/three_9278150.png",
95
+ "cmd": "echo \"{id} {state}\""
96
+ },
97
+ "four": {
98
+ "color": "#00ff00",
99
+ "image": "numbers/four_9278183.png",
100
+ "cmd": "echo \"{id} {state}\""
101
+ },
102
+ "five": {
103
+ "color": "#00ff00",
104
+ "image": "numbers/five_9278222.png",
105
+ "cmd": "echo \"{id} {state}\""
106
+ }
107
+ }
108
+ },
109
+ "3": {
110
+ "default": "four",
111
+ "states": {
112
+ "off": {
113
+ "color": "#000099",
114
+ "cmd": "echo \"{id} {state}\""
115
+ },
116
+ "one": {
117
+ "color": "#00ff00",
118
+ "image": "numbers/one_9278045.png",
119
+ "cmd": "echo \"{id} {state}\""
120
+ },
121
+ "two": {
122
+ "color": "#00ff00",
123
+ "image": "numbers/two_9278103.png",
124
+ "cmd": "echo \"{id} {state}\""
125
+ },
126
+ "three": {
127
+ "color": "#00ff00",
128
+ "image": "numbers/three_9278150.png",
129
+ "cmd": "echo \"{id} {state}\""
130
+ },
131
+ "four": {
132
+ "color": "#00ff00",
133
+ "image": "numbers/four_9278183.png",
134
+ "cmd": "echo \"{id} {state}\""
135
+ },
136
+ "five": {
137
+ "color": "#00ff00",
138
+ "image": "numbers/five_9278222.png",
139
+ "cmd": "echo \"{id} {state}\""
140
+ }
141
+ }
142
+ },
143
+ "4": {
144
+ "default": "five",
145
+ "states": {
146
+ "off": {
147
+ "color": "#000099",
148
+ "cmd": "echo \"{id} {state}\""
149
+ },
150
+ "one": {
151
+ "color": "#00ff00",
152
+ "image": "numbers/one_9278045.png",
153
+ "cmd": "echo \"{id} {state}\""
154
+ },
155
+ "two": {
156
+ "color": "#00ff00",
157
+ "image": "numbers/two_9278103.png",
158
+ "cmd": "echo \"{id} {state}\""
159
+ },
160
+ "three": {
161
+ "color": "#00ff00",
162
+ "image": "numbers/three_9278150.png",
163
+ "cmd": "echo \"{id} {state}\""
164
+ },
165
+ "four": {
166
+ "color": "#00ff00",
167
+ "image": "numbers/four_9278183.png",
168
+ "cmd": "echo \"{id} {state}\""
169
+ },
170
+ "five": {
171
+ "color": "#00ff00",
172
+ "image": "numbers/five_9278222.png",
173
+ "cmd": "echo \"{id} {state}\""
174
+ }
175
+ }
176
+ },
177
+ "5": {
178
+ "states": {
179
+ "off": {
180
+ "color": "#000099",
181
+ "cmd": "echo \"{id} {state}\""
182
+ },
183
+ "one": {
184
+ "color": "#00ff00",
185
+ "image": "numbers/one_9278045.png",
186
+ "cmd": "echo \"{id} {state}\""
187
+ },
188
+ "two": {
189
+ "color": "#00ff00",
190
+ "image": "numbers/two_9278103.png",
191
+ "cmd": "echo \"{id} {state}\""
192
+ },
193
+ "three": {
194
+ "color": "#00ff00",
195
+ "image": "numbers/three_9278150.png",
196
+ "cmd": "echo \"{id} {state}\""
197
+ },
198
+ "four": {
199
+ "color": "#00ff00",
200
+ "image": "numbers/four_9278183.png",
201
+ "cmd": "echo \"{id} {state}\""
202
+ },
203
+ "five": {
204
+ "color": "#00ff00",
205
+ "image": "numbers/five_9278222.png",
206
+ "cmd": "echo \"{id} {state}\""
207
+ }
208
+ }
209
+ }
210
+ },
211
+ "left": {
212
+ "0": {
213
+ "states": {
214
+ "on": {
215
+ "color": "#000000",
216
+ "cmd": "echo \"{id} {state}\""
217
+ }
218
+ }
219
+ }
220
+ },
221
+ "right": {
222
+ "0": {
223
+ "states": {
224
+ "on": {
225
+ "color": "#000000",
226
+ "cmd": "echo \"{id} {state}\""
227
+ }
228
+ }
229
+ }
230
+ }
231
+ },
232
+ "knobs": {
233
+ "knobTL": {
234
+ "states": {
235
+ "on": {
236
+ "cmd": "echo \"{id} {state}\""
237
+ }
238
+ },
239
+ "group": ""
240
+ },
241
+ "knobCL": {
242
+ "states": {
243
+ "on": {
244
+ "cmd": "echo \"{id} {state}\""
245
+ }
246
+ },
247
+ "group": ""
248
+ },
249
+ "knobBL": {
250
+ "states": {
251
+ "on": {
252
+ "cmd": "echo \"{id} {state}\"",
253
+ "opcua": "ns=2;s=Is{simnbr}.Audio.in.VolumeAccustic"
254
+ }
255
+ },
256
+ "group": ""
257
+ },
258
+ "knobTR": {
259
+ "states": {
260
+ "on": {
261
+ "cmd": "echo \"{id} {state}\""
262
+ }
263
+ },
264
+ "group": ""
265
+ },
266
+ "knobCR": {
267
+ "states": {
268
+ "on": {
269
+ "cmd": "echo \"{id} {state}\""
270
+ }
271
+ },
272
+ "group": ""
273
+ },
274
+ "knobBR": {
275
+ "states": {
276
+ "on": {
277
+ "cmd": "echo \"{id} {state}\""
278
+ }
279
+ },
280
+ "group": ""
281
+ }
282
+ },
283
+ "parameters": {
284
+ "hostname": "127.0.0.1",
285
+ "simnbr": "1",
286
+ "endpointurl": "opc.tcp://{hostname}:4840",
287
+ "nodeid" : "ns=0;s=nodeID",
288
+ "verbose": true
289
+ }
290
+ }
@@ -0,0 +1,373 @@
1
+ {
2
+ "name": "profile-1",
3
+ "profile": "example",
4
+ "description": "",
5
+ "touch": {
6
+ "center": {
7
+ "0": {
8
+ "states": {
9
+ "off": {
10
+ "color": "#000099",
11
+ "image": "icons/home.png",
12
+ "cmd": "echo \"{id} {state}\""
13
+ },
14
+ "on": {
15
+ "color": "#00ff00",
16
+ "image": "icons/home.png",
17
+ "cmd": "echo \"{id} {state}\""
18
+ }
19
+ },
20
+ "group": ""
21
+ },
22
+ "1": {
23
+ "states": {
24
+ "off": {
25
+ "color": "#000099",
26
+ "image": "icons/home.png",
27
+ "cmd": "echo \"{id} {state}\""
28
+ },
29
+ "on": {
30
+ "color": "#00ff00",
31
+ "image": "icons/home.png",
32
+ "cmd": "echo \"{id} {state}\""
33
+ }
34
+ },
35
+ "group": ""
36
+ },
37
+ "2": {
38
+ "states": {
39
+ "off": {
40
+ "color": "#000099",
41
+ "image": "icons/home.png",
42
+ "cmd": "echo \"{id} {state}\""
43
+ },
44
+ "on": {
45
+ "color": "#00ff00",
46
+ "image": "icons/home.png",
47
+ "cmd": "echo \"{id} {state}\""
48
+ }
49
+ },
50
+ "group": ""
51
+ },
52
+ "3": {
53
+ "states": {
54
+ "off": {
55
+ "color": "#000099",
56
+ "image": "icons/home.png",
57
+ "cmd": "echo \"{id} {state}\""
58
+ },
59
+ "on": {
60
+ "color": "#00ff00",
61
+ "image": "icons/home.png",
62
+ "cmd": "echo \"{id} {state}\""
63
+ }
64
+ },
65
+ "group": ""
66
+ },
67
+ "4": {
68
+ "states": {
69
+ "off": {
70
+ "color": "#000099",
71
+ "image": "icons/home.png",
72
+ "cmd": "echo \"{id} {state}\""
73
+ },
74
+ "on": {
75
+ "color": "#00ff00",
76
+ "image": "icons/home.png",
77
+ "cmd": "echo \"{id} {state}\""
78
+ }
79
+ },
80
+ "group": ""
81
+ },
82
+ "5": {
83
+ "states": {
84
+ "off": {
85
+ "color": "#000099",
86
+ "image": "icons/home.png",
87
+ "cmd": "echo \"{id} {state}\""
88
+ },
89
+ "on": {
90
+ "color": "#00ff00",
91
+ "image": "icons/home.png",
92
+ "cmd": "echo \"{id} {state}\""
93
+ }
94
+ },
95
+ "group": ""
96
+ },
97
+ "6": {
98
+ "states": {
99
+ "off": {
100
+ "color": "#000099",
101
+ "image": "icons/home.png",
102
+ "cmd": "echo \"{id} {state}\""
103
+ },
104
+ "on": {
105
+ "color": "#00ff00",
106
+ "image": "icons/home.png",
107
+ "cmd": "echo \"{id} {state}\""
108
+ }
109
+ },
110
+ "group": ""
111
+ },
112
+ "7": {
113
+ "states": {
114
+ "off": {
115
+ "color": "#000099",
116
+ "image": "icons/home.png",
117
+ "cmd": "echo \"{id} {state}\""
118
+ },
119
+ "on": {
120
+ "color": "#00ff00",
121
+ "image": "icons/home.png",
122
+ "cmd": "echo \"{id} {state}\""
123
+ }
124
+ },
125
+ "group": ""
126
+ },
127
+ "8": {
128
+ "states": {
129
+ "off": {
130
+ "color": "#000099",
131
+ "image": "icons/home.png",
132
+ "cmd": "echo \"{id} {state}\""
133
+ },
134
+ "on": {
135
+ "color": "#00ff00",
136
+ "image": "icons/home.png",
137
+ "cmd": "echo \"{id} {state}\""
138
+ }
139
+ },
140
+ "group": ""
141
+ },
142
+ "9": {
143
+ "states": {
144
+ "off": {
145
+ "color": "#000099",
146
+ "image": "icons/home.png",
147
+ "cmd": "echo \"{id} {state}\""
148
+ },
149
+ "on": {
150
+ "color": "#00ff00",
151
+ "image": "icons/home.png",
152
+ "cmd": "echo \"{id} {state}\""
153
+ }
154
+ },
155
+ "group": ""
156
+ },
157
+ "10": {
158
+ "states": {
159
+ "off": {
160
+ "color": "#000099",
161
+ "image": "icons/home.png",
162
+ "cmd": "echo \"{id} {state}\""
163
+ },
164
+ "on": {
165
+ "color": "#00ff00",
166
+ "image": "icons/home.png",
167
+ "cmd": "echo \"{id} {state}\""
168
+ }
169
+ },
170
+ "group": ""
171
+ },
172
+ "11": {
173
+ "states": {
174
+ "off": {
175
+ "color": "#000099",
176
+ "image": "icons/home.png",
177
+ "cmd": "echo \"{id} {state}\""
178
+ },
179
+ "on": {
180
+ "color": "#00ff00",
181
+ "image": "icons/home.png",
182
+ "cmd": "echo \"{id} {state}\""
183
+ }
184
+ },
185
+ "group": ""
186
+ }
187
+ },
188
+ "left": {
189
+ "0": {
190
+ "states": {
191
+ "on": {
192
+ "color": "#000000",
193
+ "cmd": "echo \"{id} {state}\""
194
+ }
195
+ },
196
+ "group": ""
197
+ }
198
+ },
199
+ "right": {
200
+ "0": {
201
+ "states": {
202
+ "on": {
203
+ "color": "#000000",
204
+ "cmd": "echo \"{id} {state}\""
205
+ }
206
+ },
207
+ "group": ""
208
+ }
209
+ }
210
+ },
211
+ "knobs": {
212
+ "knobTL": {
213
+ "states": {
214
+ "on": {
215
+ "cmd": "echo \"{id} {state}\""
216
+ }
217
+ },
218
+ "group": ""
219
+ },
220
+ "knobCL": {
221
+ "states": {
222
+ "on": {
223
+ "cmd": "echo \"{id} {state}\""
224
+ }
225
+ },
226
+ "group": ""
227
+ },
228
+ "knobBL": {
229
+ "states": {
230
+ "on": {
231
+ "cmd": "echo \"{id} {state}\""
232
+ }
233
+ },
234
+ "group": ""
235
+ },
236
+ "knobTR": {
237
+ "states": {
238
+ "on": {
239
+ "cmd": "echo \"{id} {state}\""
240
+ }
241
+ },
242
+ "group": ""
243
+ },
244
+ "knobCR": {
245
+ "states": {
246
+ "on": {
247
+ "cmd": "echo \"{id} {state}\""
248
+ }
249
+ },
250
+ "group": ""
251
+ },
252
+ "knobBR": {
253
+ "states": {
254
+ "on": {
255
+ "cmd": "echo \"{id} {state}\""
256
+ }
257
+ },
258
+ "group": ""
259
+ }
260
+ },
261
+ "buttons": {
262
+ "0": {
263
+ "states": {
264
+ "off": {
265
+ "color": "#000000",
266
+ "cmd": "echo \"{id} {state}\""
267
+ },
268
+ "on": {
269
+ "color": "#550000",
270
+ "cmd": "echo \"{id} {state}\""
271
+ }
272
+ },
273
+ "group": ""
274
+ },
275
+ "1": {
276
+ "states": {
277
+ "off": {
278
+ "color": "#000000",
279
+ "cmd": "echo \"{id} {state}\""
280
+ },
281
+ "on": {
282
+ "color": "#ff0000",
283
+ "cmd": "echo \"{id} {state}\""
284
+ }
285
+ },
286
+ "group": ""
287
+ },
288
+ "2": {
289
+ "states": {
290
+ "off": {
291
+ "color": "#000000",
292
+ "cmd": "echo \"{id} {state}\""
293
+ },
294
+ "on": {
295
+ "color": "#005500",
296
+ "cmd": "echo \"{id} {state}\""
297
+ }
298
+ },
299
+ "group": ""
300
+ },
301
+ "3": {
302
+ "states": {
303
+ "off": {
304
+ "color": "#000000",
305
+ "cmd": "echo \"{id} {state}\""
306
+ },
307
+ "on": {
308
+ "color": "#00ff00",
309
+ "cmd": "echo \"{id} {state}\""
310
+ }
311
+ },
312
+ "group": ""
313
+ },
314
+ "4": {
315
+ "states": {
316
+ "off": {
317
+ "color": "#000000",
318
+ "cmd": "echo \"{id} {state}\""
319
+ },
320
+ "on": {
321
+ "color": "#000055",
322
+ "cmd": "echo \"{id} {state}\""
323
+ }
324
+ },
325
+ "group": ""
326
+ },
327
+ "5": {
328
+ "states": {
329
+ "off": {
330
+ "color": "#000000",
331
+ "cmd": "echo \"{id} {state}\""
332
+ },
333
+ "on": {
334
+ "color": "#0000ff",
335
+ "cmd": "echo \"{id} {state}\""
336
+ }
337
+ },
338
+ "group": ""
339
+ },
340
+ "6": {
341
+ "states": {
342
+ "off": {
343
+ "color": "#000000",
344
+ "cmd": "echo \"{id} {state}\""
345
+ },
346
+ "on": {
347
+ "color": "#555500",
348
+ "cmd": "echo \"{id} {state}\""
349
+ }
350
+ },
351
+ "group": ""
352
+ },
353
+ "7": {
354
+ "states": {
355
+ "off": {
356
+ "color": "#000000",
357
+ "cmd": "echo \"{id} {state}\""
358
+ },
359
+ "on": {
360
+ "color": "#ffff00",
361
+ "cmd": "echo \"{id} {state}\""
362
+ }
363
+ },
364
+ "group": ""
365
+ }
366
+ },
367
+ "parameters": {
368
+ "hostname": "127.0.0.1",
369
+ "endpointurl": "opc.tcp://{hostname}:4840",
370
+ "nodeid": "ns=0;s=nodeID"
371
+ },
372
+ "loaded": false
373
+ }