loupedeck-commander 1.4.1 → 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.
@@ -1,300 +1,300 @@
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].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
- }
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
+ }