loupedeck-commander 1.2.3 → 1.2.4
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 -0
- package/README.md +131 -131
- package/VERSION.md +32 -32
- package/common/ApplicationConfig.mjs +219 -84
- package/common/BaseLoupeDeckHandler.mjs +333 -326
- package/common/cmd-executer.mjs +16 -16
- package/common/index.mjs +5 -5
- package/common/touchbuttons.mjs +534 -534
- package/common/utils.mjs +30 -29
- package/config.json +8 -8
- package/eslint.config.mjs +8 -8
- package/example/ExampleDeviceHandler.mjs +44 -44
- package/example/example.mjs +21 -21
- package/index.mjs +3 -3
- package/interfaces/baseif.mjs +69 -69
- package/interfaces/httpif.mjs +90 -81
- package/interfaces/opcuaif.mjs +296 -291
- package/interfaces/shellif.mjs +53 -47
- package/package.json +29 -29
- package/profile-1.json +373 -280
- package/test.mjs +26 -22
|
@@ -1,84 +1,219 @@
|
|
|
1
|
-
import { readJSONFile, writeJSONFile } 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
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
this.
|
|
81
|
-
this.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
1
|
+
import { readJSONFile, writeJSONFile } from './utils.mjs'
|
|
2
|
+
|
|
3
|
+
export class ApplicationConfig {
|
|
4
|
+
application = 'undefined'
|
|
5
|
+
profiles = []
|
|
6
|
+
initialized = false
|
|
7
|
+
|
|
8
|
+
loadFromFile (fileName) {
|
|
9
|
+
console.info(`ApplicationConfig: Loading Config File ${fileName}`)
|
|
10
|
+
const config = readJSONFile(fileName)
|
|
11
|
+
|
|
12
|
+
if (!config){
|
|
13
|
+
console.info(`ApplicationConfig: Could not read/parse Config File ${fileName} - breaking here`)
|
|
14
|
+
}else if (!config.application){
|
|
15
|
+
console.info(`ApplicationConfig: Config File ${fileName} does not contain an application attribute - breaking here`)
|
|
16
|
+
}else if (!config.profiles){
|
|
17
|
+
console.info(`ApplicationConfig: Config File ${fileName} does not contain a profiles attribute - breaking here`)
|
|
18
|
+
}
|
|
19
|
+
else{
|
|
20
|
+
this.application = config.application
|
|
21
|
+
for (let i = 0; i < config.profiles.length; i++) {
|
|
22
|
+
const profile = new Profile(config.profiles[i])
|
|
23
|
+
if (profile.loaded){
|
|
24
|
+
this.profiles.push(profile)
|
|
25
|
+
}else{
|
|
26
|
+
return false
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
this.initialized=true
|
|
31
|
+
}
|
|
32
|
+
return this.initialized
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
class Profile {
|
|
37
|
+
name = ''
|
|
38
|
+
profile = 'example'
|
|
39
|
+
description = ''
|
|
40
|
+
|
|
41
|
+
touch = {}
|
|
42
|
+
knobs = {}
|
|
43
|
+
buttons = {}
|
|
44
|
+
parameters = {}
|
|
45
|
+
#file = ''
|
|
46
|
+
loaded = false
|
|
47
|
+
#error = true
|
|
48
|
+
|
|
49
|
+
constructor (data) {
|
|
50
|
+
this.name = data.name
|
|
51
|
+
this.#file = data.file
|
|
52
|
+
this.touch = new TouchConfig({})
|
|
53
|
+
this.buttons = new ButtonConfig().buttons
|
|
54
|
+
this.knobs = new KnobsConfig().knobs
|
|
55
|
+
this.parameters = new ParametersConfig().parameters
|
|
56
|
+
|
|
57
|
+
this.loadFromFile(this.#file)
|
|
58
|
+
if (this.#error) { this.saveToFile(`profile-${this.name}-sav.json`) }
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
loadFromFile (fileName) {
|
|
62
|
+
console.info(`ProfileConfig: Loading Profile File ${fileName}`)
|
|
63
|
+
const config = readJSONFile(fileName)
|
|
64
|
+
if (config === undefined) {
|
|
65
|
+
console.warn(`ProfileConfig: Cannot parse/load Profile File ${fileName}`)
|
|
66
|
+
return false
|
|
67
|
+
}else if (!config.profile){
|
|
68
|
+
console.warn(`ProfileConfig: File ${fileName} is missing a profile attribute`)
|
|
69
|
+
return false
|
|
70
|
+
}else if (!config.touch){
|
|
71
|
+
console.warn(`ProfileConfig: File ${fileName} is missing a touch attribute`)
|
|
72
|
+
return false
|
|
73
|
+
}else if (!config.buttons){
|
|
74
|
+
console.warn(`ProfileConfig: File ${fileName} is missing a buttons attribute`)
|
|
75
|
+
return false
|
|
76
|
+
}else if (!config.parameters){
|
|
77
|
+
console.warn(`ProfileConfig: File ${fileName} is missing a parameters attribute`)
|
|
78
|
+
return false
|
|
79
|
+
}
|
|
80
|
+
this.profile = config.profile
|
|
81
|
+
this.description = config.description
|
|
82
|
+
|
|
83
|
+
// Load the Configurations for Touch-Displays
|
|
84
|
+
this.touch = new TouchConfig(config.touch)
|
|
85
|
+
// Load the Configurations for Button-Areas
|
|
86
|
+
|
|
87
|
+
this.buttons = new ButtonConfig(config.buttons).buttons
|
|
88
|
+
this.knobs = new KnobsConfig(config.knobs).knobs
|
|
89
|
+
// Load Parameters.parameters = config.parameters
|
|
90
|
+
this.parameters = new ParametersConfig(config.parameters).parameters
|
|
91
|
+
|
|
92
|
+
this.#error = false
|
|
93
|
+
this.loaded = true
|
|
94
|
+
return this.loaded
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
saveToFile (fileName) {
|
|
98
|
+
fileName = fileName.toLowerCase()
|
|
99
|
+
|
|
100
|
+
console.info(`ProfileConfig: Save To Config File ${fileName}`)
|
|
101
|
+
writeJSONFile(fileName, this)
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Class that handles the different configs for the touch displays of the device covering Loupedeck Live (without knob) and also CT (with knob)
|
|
107
|
+
*/
|
|
108
|
+
class TouchConfig {
|
|
109
|
+
center = {
|
|
110
|
+
"0" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
111
|
+
"1" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
112
|
+
"2" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
113
|
+
"3" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
114
|
+
"4" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
115
|
+
"5" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
116
|
+
"6" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
117
|
+
"7" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
118
|
+
"8" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
119
|
+
"9" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
120
|
+
"10" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
121
|
+
"11" : { "states" : { "off" : { "color": "#000099", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" }, "on" : { "color": "#00ff00", "image": "icons/home.png","cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
122
|
+
} // CENTER Display Config - Available in CT & LIVE
|
|
123
|
+
left = {
|
|
124
|
+
"0" : { "states" : { "on" : { "color": "#000000", "cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
125
|
+
} // LEFT Display Config - Available in CT & LIVE
|
|
126
|
+
right = {
|
|
127
|
+
"0" : { "states" : { "on" : { "color": "#000000", "cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
128
|
+
} // RIGHT Display Config - Available in CT & LIVE
|
|
129
|
+
//knob = {} // KNOB Display Config - Available only in CT
|
|
130
|
+
|
|
131
|
+
constructor (data) {
|
|
132
|
+
this.loadFromJSON(data)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
loadFromJSON (data) {
|
|
136
|
+
if (!data)
|
|
137
|
+
return
|
|
138
|
+
if (!data.center)
|
|
139
|
+
return
|
|
140
|
+
if (!data.left)
|
|
141
|
+
return
|
|
142
|
+
if (!data.right)
|
|
143
|
+
return
|
|
144
|
+
//if (!data.knob)
|
|
145
|
+
// return
|
|
146
|
+
this.center = data.center
|
|
147
|
+
this.left = data.left
|
|
148
|
+
this.right = data.right
|
|
149
|
+
//this.knob = data.knob
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Class that handles the different configs for the touch displays of the device covering Loupedeck Live (without knob) and also CT (with knob)
|
|
155
|
+
*/
|
|
156
|
+
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 : "" },
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
constructor (data) {
|
|
169
|
+
this.loadFromJSON(data)
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
loadFromJSON (data) {
|
|
173
|
+
if (!data)
|
|
174
|
+
return
|
|
175
|
+
this.buttons = data
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Class that handles the different configs for the touch displays of the device covering Loupedeck Live (without knob) and also CT (with knob)
|
|
181
|
+
*/
|
|
182
|
+
class KnobsConfig {
|
|
183
|
+
knobs = {
|
|
184
|
+
"knobTL" : { "states" : { "on" : { "cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
185
|
+
"knobCL" : { "states" : { "on" : { "cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
186
|
+
"knobBL" : { "states" : { "on" : { "cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
187
|
+
"knobTR" : { "states" : { "on" : { "cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
188
|
+
"knobCR" : { "states" : { "on" : { "cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
189
|
+
"knobBR" : { "states" : { "on" : { "cmd": "echo \"{id} {state}\"" } }, group : "" },
|
|
190
|
+
} // KNOB Config - Available only in CT
|
|
191
|
+
|
|
192
|
+
constructor (data) {
|
|
193
|
+
this.loadFromJSON(data)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
loadFromJSON (data) {
|
|
197
|
+
if (!data)
|
|
198
|
+
return
|
|
199
|
+
this.knobs = data
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
class ParametersConfig {
|
|
204
|
+
parameters = {
|
|
205
|
+
"hostname": "127.0.0.1",
|
|
206
|
+
"endpointurl": "opc.tcp://{hostname}:4840",
|
|
207
|
+
"nodeid" : "ns=0;s=nodeID"
|
|
208
|
+
} // KNOB Config - Available only in CT
|
|
209
|
+
|
|
210
|
+
constructor (data) {
|
|
211
|
+
this.loadFromJSON(data)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
loadFromJSON (data) {
|
|
215
|
+
if (!data)
|
|
216
|
+
return
|
|
217
|
+
this.parameters = data
|
|
218
|
+
}
|
|
219
|
+
}
|