loupedeck-commander 1.4.0 → 1.4.2
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/LICENSE +201 -201
- package/README.md +131 -131
- package/common/ApplicationConfig.mjs +300 -281
- package/common/BaseLoupeDeckHandler.mjs +393 -381
- package/common/ButtonField.mjs +168 -166
- package/common/button.mjs +533 -520
- package/common/cmd-executer.mjs +16 -16
- package/common/index.mjs +5 -5
- package/common/utils.mjs +106 -106
- package/config.yaml +8 -6
- package/index.mjs +3 -3
- package/interfaces/baseif.mjs +71 -71
- package/interfaces/httpif.mjs +90 -90
- package/interfaces/interfaces.mjs +34 -34
- package/interfaces/opcuaif.mjs +484 -481
- package/interfaces/shellif.mjs +58 -58
- package/package.json +32 -32
- package/profile-1.yaml +186 -186
- package/profile-2.yaml +213 -213
- package/test.mjs +40 -40
|
@@ -1,281 +1,300 @@
|
|
|
1
|
-
import { readConfigFile as readConfigFile, writeJSONFile,syncParams, writeYAMLFile } from './utils.mjs'
|
|
2
|
-
|
|
3
|
-
export class ApplicationConfig {
|
|
4
|
-
application = 'undefined'
|
|
5
|
-
profiles = []
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
this.
|
|
60
|
-
this
|
|
61
|
-
this
|
|
62
|
-
this
|
|
63
|
-
|
|
64
|
-
this.
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
"
|
|
249
|
-
"
|
|
250
|
-
"
|
|
251
|
-
"
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
"
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
1
|
+
import { readConfigFile as readConfigFile, writeJSONFile,syncParams, writeYAMLFile } from './utils.mjs'
|
|
2
|
+
|
|
3
|
+
export class ApplicationConfig {
|
|
4
|
+
application = 'undefined'
|
|
5
|
+
profiles = []
|
|
6
|
+
parameters = {}
|
|
7
|
+
initialized = false
|
|
8
|
+
|
|
9
|
+
loadFromFile (fileName) {
|
|
10
|
+
console.info(`ApplicationConfig: Loading Config File ${fileName}`)
|
|
11
|
+
const config = readConfigFile(fileName)
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
if (!config){
|
|
15
|
+
console.info(`ApplicationConfig: Could not read/parse Config File ${fileName} - breaking here`)
|
|
16
|
+
}else if (!config.application){
|
|
17
|
+
console.info(`ApplicationConfig: Config File ${fileName} does not contain an application attribute - breaking here`)
|
|
18
|
+
}else if (!config.profiles){
|
|
19
|
+
console.info(`ApplicationConfig: Config File ${fileName} does not contain a profiles attribute - breaking here`)
|
|
20
|
+
}
|
|
21
|
+
else{
|
|
22
|
+
this.application = config.application
|
|
23
|
+
this.parameters = new ParametersConfig()
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
for (let i = 0; i < config.profiles.length; i++) {
|
|
27
|
+
const profile = new Profile(config.profiles[i],config.profiles.length,i)
|
|
28
|
+
profile.setParams(config.parameters)
|
|
29
|
+
if (profile.loaded){
|
|
30
|
+
this.profiles.push(profile)
|
|
31
|
+
}else{
|
|
32
|
+
return false
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
this.initialized=true
|
|
37
|
+
}
|
|
38
|
+
return this.initialized
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
class Profile {
|
|
43
|
+
name = ''
|
|
44
|
+
profile = 'example'
|
|
45
|
+
description = ''
|
|
46
|
+
|
|
47
|
+
touch = {}
|
|
48
|
+
knobs = {}
|
|
49
|
+
buttons = {}
|
|
50
|
+
parameters = {}
|
|
51
|
+
default = {}
|
|
52
|
+
#file = ''
|
|
53
|
+
loaded = false
|
|
54
|
+
#error = true
|
|
55
|
+
#profileCount = 0
|
|
56
|
+
#index = 0
|
|
57
|
+
|
|
58
|
+
constructor (data,profileCount,index) {
|
|
59
|
+
this.name = data.name
|
|
60
|
+
this.#file = data.file
|
|
61
|
+
this.#profileCount = profileCount
|
|
62
|
+
this.#index = index
|
|
63
|
+
this.touch = new TouchConfig({})
|
|
64
|
+
this.buttons = new ButtonConfig().buttons
|
|
65
|
+
this.knobs = new KnobsConfig().knobs
|
|
66
|
+
this.parameters = new ParametersConfig().parameters
|
|
67
|
+
this.default = new DefaultConfig().default
|
|
68
|
+
|
|
69
|
+
this.loadFromFile(this.#file)
|
|
70
|
+
if (this.#error) {
|
|
71
|
+
this.saveToFile(`profile-${this.name}-sav.json`)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
loadFromFile (fileName) {
|
|
76
|
+
console.info(`ProfileConfig: Loading Profile File ${fileName}, Index ${this.#index}`)
|
|
77
|
+
const config = readConfigFile(fileName)
|
|
78
|
+
if (config === undefined) {
|
|
79
|
+
console.warn(`ProfileConfig: Cannot parse/load Profile File ${fileName}`)
|
|
80
|
+
return false
|
|
81
|
+
}else if (!config.profile){
|
|
82
|
+
console.warn(`ProfileConfig: File ${fileName} is missing a profile attribute`)
|
|
83
|
+
return false
|
|
84
|
+
}else if (!config.touch){
|
|
85
|
+
console.warn(`ProfileConfig: File ${fileName} is missing a touch attribute`)
|
|
86
|
+
return false
|
|
87
|
+
}else if (!config.parameters){
|
|
88
|
+
console.warn(`ProfileConfig: File ${fileName} is missing a parameters attribute`)
|
|
89
|
+
return false
|
|
90
|
+
}else if (!config.buttons){
|
|
91
|
+
console.info(`ProfileConfig: File ${fileName} is missing a buttons attribute - will be used to switch profiles by default`)
|
|
92
|
+
// return false
|
|
93
|
+
}
|
|
94
|
+
this.profile = config.profile
|
|
95
|
+
this.description = config.description
|
|
96
|
+
// Load Parameters.parameters = config.parameters
|
|
97
|
+
this.parameters = new ParametersConfig(config.parameters).parameters
|
|
98
|
+
this.default = new DefaultConfig(config.default).default
|
|
99
|
+
|
|
100
|
+
// Load the Configurations for Touch-Displays
|
|
101
|
+
this.touch = new TouchConfig(config.touch,this.default)
|
|
102
|
+
// Load the Configurations for Button-Areas
|
|
103
|
+
|
|
104
|
+
this.buttons = new ButtonConfig(config.buttons,this.#profileCount,this.#index).buttons
|
|
105
|
+
this.knobs = new KnobsConfig(config.knobs).knobs
|
|
106
|
+
|
|
107
|
+
this.#error = false
|
|
108
|
+
this.loaded = true
|
|
109
|
+
return this.loaded
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
setParams(parameters){
|
|
113
|
+
if (parameters === undefined)
|
|
114
|
+
return
|
|
115
|
+
|
|
116
|
+
let keys = Object.keys(parameters)
|
|
117
|
+
for (var i=0;i<keys.length;i++){
|
|
118
|
+
let key = keys[i]
|
|
119
|
+
if (!(key in this.parameters)){
|
|
120
|
+
this.parameters[key] = parameters[key]
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
saveToFile (fileName) {
|
|
127
|
+
fileName = fileName.toLowerCase()
|
|
128
|
+
|
|
129
|
+
console.info(`ProfileConfig: Save To Config File ${fileName}`)
|
|
130
|
+
if(fileName.endsWith('.json')) {
|
|
131
|
+
writeJSONFile(fileName, this)
|
|
132
|
+
writeYAMLFile(fileName.replace('.json','.yaml'), this)
|
|
133
|
+
}else if(fileName.endsWith('.yaml')) {
|
|
134
|
+
writeYAMLFile(fileName, this)
|
|
135
|
+
writeJSONFile(fileName.replace('.yaml','.json'), this)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Class that handles the different configs for the touch displays of the device covering Loupedeck Live (without knob) and also CT (with knob)
|
|
142
|
+
*/
|
|
143
|
+
class TouchConfig {
|
|
144
|
+
center = {
|
|
145
|
+
"0" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } } },
|
|
146
|
+
"1" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } } },
|
|
147
|
+
"2" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } } },
|
|
148
|
+
"3" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } } },
|
|
149
|
+
"4" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } } },
|
|
150
|
+
"5" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } } },
|
|
151
|
+
"6" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } } },
|
|
152
|
+
"7" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } } },
|
|
153
|
+
"8" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } } },
|
|
154
|
+
"9" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } } },
|
|
155
|
+
"10" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } } },
|
|
156
|
+
"11" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } } },
|
|
157
|
+
} // CENTER Display Config - Available in CT & LIVE
|
|
158
|
+
left = {
|
|
159
|
+
"0" : { "states" : { "on" : { "color": "#000000", "cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
160
|
+
} // LEFT Display Config - Available in CT & LIVE
|
|
161
|
+
right = {
|
|
162
|
+
"0" : { "states" : { "on" : { "color": "#000000", "cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
163
|
+
} // RIGHT Display Config - Available in CT & LIVE
|
|
164
|
+
//knob = {} // KNOB Display Config - Available only in CT
|
|
165
|
+
|
|
166
|
+
constructor (data,defaultState) {
|
|
167
|
+
this.loadFromJSON(data,defaultState)
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
loadFromJSON (data,defaultState) {
|
|
171
|
+
if (!data)
|
|
172
|
+
return
|
|
173
|
+
if (!data.center)
|
|
174
|
+
return
|
|
175
|
+
if (!data.left)
|
|
176
|
+
return
|
|
177
|
+
if (!data.right)
|
|
178
|
+
return
|
|
179
|
+
//if (!data.knob)
|
|
180
|
+
// return
|
|
181
|
+
this.center = data.center
|
|
182
|
+
this.left = data.left
|
|
183
|
+
this.right = data.right
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Sychronize the states of the buttons with the default state - add missing options from default state
|
|
187
|
+
*/
|
|
188
|
+
var buttons = Object.keys(this.center)
|
|
189
|
+
for (var buttonID=0;buttonID<buttons.length;buttonID++){
|
|
190
|
+
if (!this.center[buttonID])
|
|
191
|
+
continue
|
|
192
|
+
var states = Object.keys(this.center[buttonID].states)
|
|
193
|
+
for (var stateID=0;stateID<states.length;stateID++){
|
|
194
|
+
var stateKey = states[stateID]
|
|
195
|
+
var stateOld = this.center[buttonID].states[stateKey]
|
|
196
|
+
this.center[buttonID].states[stateKey] = syncParams(stateOld,defaultState)
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Class that handles the different configs for the touch displays of the device covering Loupedeck Live (without knob) and also CT (with knob)
|
|
204
|
+
*/
|
|
205
|
+
class ButtonConfig {
|
|
206
|
+
buttons = {}
|
|
207
|
+
defaultButtons = {
|
|
208
|
+
"0" : {"states" : { "off" : { "filter": "pressed", "color": "#005500", "brightness" : 0 }, "half" : { "filter": "pressed", "brightness" : 0.5, "vibrate": 0x58, "color": "#00aa00" } , "on" : { "filter": "pressed", "brightness" : 1, "color": "#00ff00" } }, params: { group : "brightness"} },
|
|
209
|
+
"1" : {"states" : { "off" : { "filter": "pressed", "color": "#000055", "profile": 0, }, "on" : { "filter": "pressed", "color": "#00ff00" } }, params: { group : "profiles"} },
|
|
210
|
+
"2" : {"states" : { "off" : { "filter": "pressed", "color": "#000055", "profile": 1, }, "on" : { "filter": "pressed", "color": "#00ff00" } }, params: { group : "profiles"} },
|
|
211
|
+
"3" : {"states" : { "off" : { "filter": "pressed", "color": "#000055", "profile": 2, }, "on" : { "filter": "pressed", "color": "#00ff00" } }, params: { group : "profiles"} },
|
|
212
|
+
"4" : {"states" : { "off" : { "filter": "pressed", "color": "#000055", "profile": 3, }, "on" : { "filter": "pressed", "color": "#00ff00" } }, params: { group : "profiles"} },
|
|
213
|
+
"5" : {"states" : { "off" : { "filter": "pressed", "color": "#000055", "profile": 4, }, "on" : { "filter": "pressed", "color": "#00ff00" } }, params: { group : "profiles"} },
|
|
214
|
+
"6" : {"states" : { "off" : { "filter": "pressed", "color": "#000055", "profile": 5, }, "on" : { "filter": "pressed", "color": "#00ff00" } }, params: { group : "profiles"} },
|
|
215
|
+
"7" : {"states" : { "off" : { "filter": "pressed", "color": "#000055", "profile": 6, }, "on" : { "filter": "pressed", "color": "#00ff00" } }, params: { group : "profiles"} }
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
constructor (data,profileCount,index) {
|
|
219
|
+
if (data)
|
|
220
|
+
return this.loadFromJSON(data)
|
|
221
|
+
// Default to profile switching buttons
|
|
222
|
+
var keys = Object.keys(this.defaultButtons)
|
|
223
|
+
for (let i = 0; i <= profileCount; i++) {
|
|
224
|
+
var key = keys[i]
|
|
225
|
+
this.buttons[key] = this.defaultButtons[key]
|
|
226
|
+
if (i==(index+1)){
|
|
227
|
+
this.buttons[key].params.default = "on"
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
loadFromJSON (data) {
|
|
235
|
+
if (!data)
|
|
236
|
+
return
|
|
237
|
+
this.buttons = data
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Class that handles the different configs for the touch displays of the device covering Loupedeck Live (without knob) and also CT (with knob)
|
|
243
|
+
*/
|
|
244
|
+
class KnobsConfig {
|
|
245
|
+
knobs = {
|
|
246
|
+
"knobTL" : { "states" : { "on" : { "cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
247
|
+
"knobCL" : { "states" : { "on" : { "cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
248
|
+
"knobBL" : { "states" : { "on" : { "cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
249
|
+
"knobTR" : { "states" : { "on" : { "cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
250
|
+
"knobCR" : { "states" : { "on" : { "cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
251
|
+
"knobBR" : { "states" : { "on" : { "cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
252
|
+
} // KNOB Config - Available only in CT
|
|
253
|
+
|
|
254
|
+
constructor (data) {
|
|
255
|
+
this.loadFromJSON(data)
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
loadFromJSON (data) {
|
|
259
|
+
if (!data)
|
|
260
|
+
return
|
|
261
|
+
this.knobs = data
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
class ParametersConfig {
|
|
266
|
+
parameters = {
|
|
267
|
+
"hostname": "127.0.0.1",
|
|
268
|
+
"endpointurl": "opc.tcp://{hostname}:4840",
|
|
269
|
+
"nodeid" : "ns=0;s=nodeID",
|
|
270
|
+
"min" : 0,
|
|
271
|
+
"max" : 100
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
constructor (data) {
|
|
275
|
+
this.loadFromJSON(data)
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
loadFromJSON (data) {
|
|
279
|
+
if (!data)
|
|
280
|
+
return
|
|
281
|
+
this.parameters = data
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
class DefaultConfig {
|
|
286
|
+
default = {
|
|
287
|
+
// "filter": "released",
|
|
288
|
+
"color": "#111111"
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
constructor (data) {
|
|
292
|
+
this.loadFromJSON(data)
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
loadFromJSON (data) {
|
|
296
|
+
if (!data)
|
|
297
|
+
return
|
|
298
|
+
this.default = data
|
|
299
|
+
}
|
|
300
|
+
}
|