loupedeck-commander 1.0.1 → 1.2.0
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/README.md +31 -8
- package/VERSION.md +33 -0
- package/common/ApplicationConfig.mjs +3 -0
- package/common/BaseLoupeDeckHandler.mjs +111 -28
- package/common/touchbuttons.mjs +304 -274
- package/config-test.json +9 -0
- package/eslint.config.mjs +9 -0
- package/{ExampleDeviceHandler.mjs → example/ExampleDeviceHandler.mjs} +3 -4
- package/example/example.mjs +21 -0
- package/icons/bulb_filled.png +0 -0
- package/interfaces/baseif.mjs +57 -0
- package/interfaces/httpif.mjs +86 -0
- package/interfaces/opcuaif.mjs +287 -0
- package/interfaces/opcuaif_test.mjs +31 -0
- package/interfaces/pubel.js +95 -0
- package/interfaces/shellif.mjs +46 -0
- package/package.json +9 -11
- package/profile-1.json +60 -96
- package/profile-2.json +164 -0
- package/test.mjs +23 -0
- package/example.mjs +0 -13
package/common/touchbuttons.mjs
CHANGED
|
@@ -1,16 +1,37 @@
|
|
|
1
1
|
import { loadImage } from 'canvas'
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
import * as shellif from '../interfaces/shellif.mjs'
|
|
4
|
+
import * as httpif from '../interfaces/httpif.mjs'
|
|
5
|
+
import * as opcuaif from '../interfaces/opcuaif.mjs'
|
|
3
6
|
import format from 'string-template'
|
|
4
7
|
import { calcDelta } from './utils.mjs'
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
export var opcuainterface = undefined
|
|
10
|
+
var httpinterface = undefined
|
|
11
|
+
var shellinterface = undefined
|
|
12
|
+
|
|
13
|
+
export async function InitializeInterfaces(appConfig,callbackFunction){
|
|
14
|
+
if (opcuainterface === undefined ){
|
|
15
|
+
opcuainterface = new opcuaif.OPCUAIf()
|
|
16
|
+
opcuainterface.init(appConfig.parameters,appConfig,callbackFunction)
|
|
17
|
+
}
|
|
18
|
+
if (httpinterface === undefined)
|
|
19
|
+
httpinterface = new httpif.HTTPif()
|
|
20
|
+
if (shellinterface === undefined)
|
|
21
|
+
shellinterface = new shellif.SHELLif()
|
|
22
|
+
|
|
12
23
|
}
|
|
13
24
|
|
|
25
|
+
export async function StopInterfaces(){
|
|
26
|
+
if (opcuainterface !== undefined )
|
|
27
|
+
await opcuainterface.stop()
|
|
28
|
+
if (httpinterface !== undefined)
|
|
29
|
+
await httpinterface.stop()
|
|
30
|
+
if (shellinterface !== undefined)
|
|
31
|
+
await shellinterface.stop()
|
|
32
|
+
|
|
33
|
+
}
|
|
34
|
+
|
|
14
35
|
export const ButtonIndex = {
|
|
15
36
|
BUTN_0: 0,
|
|
16
37
|
BUTN_1: 1,
|
|
@@ -29,35 +50,69 @@ const ButtonType = {
|
|
|
29
50
|
PUSH: 'PUSH'
|
|
30
51
|
}
|
|
31
52
|
|
|
32
|
-
export class
|
|
33
|
-
#buttons =
|
|
53
|
+
export class ButtonField {
|
|
54
|
+
#buttons = {}
|
|
55
|
+
#screen
|
|
34
56
|
width = 0
|
|
35
57
|
height = 0
|
|
36
58
|
#rows = 0
|
|
37
59
|
#columns = 0
|
|
60
|
+
#keys = []
|
|
61
|
+
#type
|
|
38
62
|
#name
|
|
39
|
-
|
|
40
|
-
|
|
63
|
+
#config
|
|
64
|
+
|
|
65
|
+
constructor (name, rows, columns, width, height, data, config) {
|
|
66
|
+
console.info(`ButtonField ${name.padEnd(10, ' ')} Buttons: ${rows} x ${columns} , Pixels ${width} x ${height}`)
|
|
41
67
|
this.#name = name
|
|
42
68
|
this.width = width
|
|
43
69
|
this.height = height
|
|
44
70
|
this.#rows = rows
|
|
45
71
|
this.#columns = columns
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
72
|
+
this.#screen = this.width > 0 && this.height > 0
|
|
73
|
+
this.#type = 'button'
|
|
74
|
+
if (this.#screen) { this.#type = 'touch' }
|
|
75
|
+
|
|
76
|
+
const keys = Object.keys(data)
|
|
77
|
+
for (let i = 0; i < keys.length; i++) {
|
|
78
|
+
const key = keys[i]
|
|
79
|
+
const tb = new Button(`${this.#type}-${key}`, width / columns, height / rows, data[key],key,config.parameters)
|
|
80
|
+
this.#buttons[key] = tb
|
|
49
81
|
}
|
|
82
|
+
|
|
83
|
+
this.#keys = keys
|
|
84
|
+
this.#config = config
|
|
50
85
|
}
|
|
51
86
|
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
const row = Math.floor(i / device.columns)
|
|
56
|
-
const column = i % device.columns
|
|
87
|
+
//setProfileConfig (config) {
|
|
88
|
+
// this.#config = config
|
|
89
|
+
// }
|
|
57
90
|
|
|
58
|
-
|
|
91
|
+
async draw (device) {
|
|
92
|
+
if (!this.#screen) {
|
|
93
|
+
// physical buttons:
|
|
94
|
+
for (let i = 0; i < this.#keys.length; i++) {
|
|
95
|
+
const key = this.#keys[i]
|
|
96
|
+
this.#buttons[key].drawPhysical(device, key)
|
|
59
97
|
}
|
|
60
|
-
}
|
|
98
|
+
} else {
|
|
99
|
+
// screen:
|
|
100
|
+
device.drawScreen(this.#name, ctx => {
|
|
101
|
+
ctx.globalCompositeOperation = 'source-atop'
|
|
102
|
+
for (let i = 0; i < this.#keys.length; i++) {
|
|
103
|
+
const key = this.#keys[i]
|
|
104
|
+
const iValue = parseInt(key, 10)
|
|
105
|
+
const row = Math.floor(iValue / device.columns)
|
|
106
|
+
const column = iValue % device.columns
|
|
107
|
+
|
|
108
|
+
this.#buttons[key].draw(row, column, ctx)
|
|
109
|
+
}
|
|
110
|
+
})
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
setState (id, val) {
|
|
115
|
+
this.#buttons[id].setState(val)
|
|
61
116
|
}
|
|
62
117
|
|
|
63
118
|
setIntState (id, val) {
|
|
@@ -65,127 +120,103 @@ export class TouchButtonField {
|
|
|
65
120
|
}
|
|
66
121
|
|
|
67
122
|
async load () {
|
|
68
|
-
for (let i = 0; i < this.#
|
|
69
|
-
|
|
123
|
+
for (let i = 0; i < this.#keys.length; i++) {
|
|
124
|
+
const key = this.#keys[i]
|
|
125
|
+
if (isNaN(key)) {
|
|
126
|
+
await this.#buttons[key].load(this.#config)
|
|
127
|
+
} else {
|
|
128
|
+
const iVal = parseInt(key, 10)
|
|
129
|
+
await this.#buttons[iVal].load(this.#config)
|
|
130
|
+
}
|
|
70
131
|
}
|
|
71
132
|
}
|
|
72
133
|
|
|
73
134
|
async pressed (id) {
|
|
74
|
-
|
|
75
|
-
await this.#buttons[id].pressed()
|
|
135
|
+
this.checkAndCreateButton(id)
|
|
136
|
+
const result = await this.#buttons[id].pressed()
|
|
137
|
+
if (!result) {
|
|
138
|
+
console.info(`pressed ${this.#type} ${id}`)
|
|
139
|
+
}
|
|
140
|
+
return result
|
|
76
141
|
}
|
|
77
142
|
|
|
78
143
|
async released (id) {
|
|
79
|
-
// console.info(`released ${id}`)
|
|
80
144
|
const result = await this.#buttons[id].released()
|
|
81
145
|
if (result) {
|
|
82
146
|
// disable all other buttons of the group, if this one had been activated:
|
|
83
|
-
for (let i = 0; i < this.#
|
|
84
|
-
|
|
85
|
-
if (
|
|
86
|
-
|
|
147
|
+
for (let i = 0; i < this.#keys.length; i++) {
|
|
148
|
+
let key = this.#keys[i]
|
|
149
|
+
if (!isNaN(key)) { key = parseInt(key, 10) }
|
|
150
|
+
if (id === key) { continue }
|
|
151
|
+
if (this.#buttons[key].group === this.#buttons[id].group) {
|
|
152
|
+
this.#buttons[key].setState(0)
|
|
87
153
|
}
|
|
88
154
|
}
|
|
89
155
|
}
|
|
156
|
+
if (!result) {
|
|
157
|
+
console.info(`released ${this.#type} ${id}`)
|
|
158
|
+
}
|
|
90
159
|
return result
|
|
91
160
|
}
|
|
92
|
-
}
|
|
93
161
|
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
this.#name = name
|
|
100
|
-
const keys = Object.keys(data)
|
|
101
|
-
for (let i = 0; i < keys.length; i++) {
|
|
102
|
-
const key = keys[i]
|
|
103
|
-
const tb = new TouchButton(key, 1, 1, data[key])
|
|
104
|
-
this.#buttons[key] = tb
|
|
105
|
-
}
|
|
162
|
+
async changed(buttonID,nodeid,val){
|
|
163
|
+
for (let i = 0; i < this.#keys.length; i++) {
|
|
164
|
+
let bID = this.#keys[i]
|
|
165
|
+
const result = await this.#buttons[bID].changed(i,nodeid,val)
|
|
166
|
+
}
|
|
106
167
|
}
|
|
107
168
|
|
|
108
|
-
async
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
}
|
|
169
|
+
async rotated (id, delta) {
|
|
170
|
+
this.checkAndCreateButton(id)
|
|
171
|
+
const result = await this.#buttons[id].rotated(delta)
|
|
172
|
+
if (!result) { console.info(`rotated ${this.#type} ${id} ${delta}`) }
|
|
173
|
+
return result
|
|
114
174
|
}
|
|
115
175
|
|
|
116
|
-
async
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
176
|
+
async touchmove (id, x, y) {
|
|
177
|
+
this.checkAndCreateButton(id)
|
|
178
|
+
const result = await this.#buttons[id].touchmove(x, y)
|
|
179
|
+
if (!result) { console.info(`touchmove ${id} ${x} ${y}`) }
|
|
180
|
+
return result
|
|
122
181
|
}
|
|
123
182
|
|
|
124
183
|
checkAndCreateButton (id) {
|
|
125
184
|
if (!(id in this.#buttons)) {
|
|
126
|
-
const tb = new
|
|
185
|
+
const tb = new Button(id, 1, 1, id)
|
|
127
186
|
this.#buttons[id] = tb
|
|
128
187
|
}
|
|
129
188
|
}
|
|
130
|
-
|
|
131
|
-
setIntState (id, val) {
|
|
132
|
-
this.checkAndCreateButton(id)
|
|
133
|
-
this.#buttons[id].setIntState(val)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
async pressed (id) {
|
|
137
|
-
// console.info(`pressed ${id}`)
|
|
138
|
-
this.checkAndCreateButton(id)
|
|
139
|
-
return await this.#buttons[id].pressed()
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
async released (id) {
|
|
143
|
-
// console.info(`released ${id}`)
|
|
144
|
-
this.checkAndCreateButton(id)
|
|
145
|
-
return await this.#buttons[id].released()
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
async rotated (id, delta) {
|
|
149
|
-
// console.info(`rotated ${id} ${delta}`)
|
|
150
|
-
this.checkAndCreateButton(id)
|
|
151
|
-
return await this.#buttons[id].rotated(delta)
|
|
152
|
-
}
|
|
153
189
|
}
|
|
154
190
|
|
|
155
|
-
export class
|
|
191
|
+
export class Button {
|
|
192
|
+
#config
|
|
156
193
|
width = 0
|
|
157
194
|
height = 0
|
|
158
|
-
|
|
159
|
-
#type
|
|
160
|
-
|
|
161
|
-
#states = []
|
|
195
|
+
|
|
196
|
+
#type = ButtonType.TOGGLE
|
|
197
|
+
|
|
162
198
|
#min = 0
|
|
163
199
|
#max = 100
|
|
164
200
|
#value = 50
|
|
165
|
-
#data
|
|
166
201
|
#name = undefined
|
|
202
|
+
#nodeid = ""
|
|
167
203
|
|
|
168
|
-
#
|
|
169
|
-
#
|
|
170
|
-
|
|
171
|
-
// on: '#110011'
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
#rgbs = {
|
|
175
|
-
off: [0, 0, 0]
|
|
176
|
-
// on: [0, 255, 0]
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
#commands = {
|
|
180
|
-
off: '',
|
|
181
|
-
on: ''
|
|
182
|
-
}
|
|
204
|
+
#index = 0
|
|
205
|
+
#keys
|
|
206
|
+
#states
|
|
183
207
|
|
|
184
208
|
group = ''
|
|
185
209
|
|
|
186
210
|
text = ''
|
|
187
211
|
font = '16px Arial'
|
|
188
212
|
|
|
213
|
+
#x
|
|
214
|
+
#y
|
|
215
|
+
#moveLeft
|
|
216
|
+
#moveRight
|
|
217
|
+
#moveUp
|
|
218
|
+
#moveDown
|
|
219
|
+
|
|
189
220
|
// Timestamp when button was pressed
|
|
190
221
|
timeStampPressed
|
|
191
222
|
// Timestamp when button was released
|
|
@@ -194,35 +225,24 @@ export class TouchButton {
|
|
|
194
225
|
timeHold
|
|
195
226
|
// Minimum ammount of time in ms to press a button:
|
|
196
227
|
minPressed = 25
|
|
228
|
+
key = -1
|
|
197
229
|
|
|
198
|
-
constructor (id, width, height, data) {
|
|
230
|
+
constructor (id, width, height, data,key,params) {
|
|
199
231
|
this.id = id
|
|
232
|
+
this.key = key
|
|
200
233
|
this.width = width
|
|
201
234
|
this.height = height
|
|
202
235
|
this.#index = 0
|
|
203
|
-
this.#style = ButtonStyle.NONE
|
|
204
|
-
this.#type = ButtonType.TOGGLE
|
|
205
|
-
this.#states = Object.keys(this.#rgbs)
|
|
206
236
|
|
|
207
|
-
if (data) {
|
|
237
|
+
if (data && data.states) {
|
|
208
238
|
this.group = data.group
|
|
209
|
-
this.#style = ButtonStyle.PHYSICAL
|
|
210
|
-
if (data.images && Object.keys(data.images).length > 0) {
|
|
211
|
-
this.#style = ButtonStyle.IMAGE
|
|
212
|
-
this.#states = Object.keys(data.images)
|
|
213
|
-
} else if (data.colors && Object.keys(data.colors).length > 0) {
|
|
214
|
-
this.#style = ButtonStyle.COLOR
|
|
215
|
-
this.#states = Object.keys(data.colors)
|
|
216
|
-
} else if (data.rgb && Object.keys(data.rgb).length > 0) {
|
|
217
|
-
this.#states = Object.keys(data.rgb)
|
|
218
|
-
}
|
|
219
|
-
if (data.commands) {
|
|
220
|
-
this.#commands = data.commands
|
|
221
|
-
}
|
|
222
239
|
|
|
240
|
+
this.#states = data.states
|
|
241
|
+
this.#keys = Object.keys(this.#states)
|
|
223
242
|
if (data.type) {
|
|
224
243
|
this.#type = data.type.toUpperCase()
|
|
225
244
|
}
|
|
245
|
+
|
|
226
246
|
if (data.minPressed) {
|
|
227
247
|
this.minPressed = data.minPressed
|
|
228
248
|
}
|
|
@@ -230,12 +250,15 @@ export class TouchButton {
|
|
|
230
250
|
if (data.text) {
|
|
231
251
|
this.text = data.text
|
|
232
252
|
}
|
|
233
|
-
this.#data = data
|
|
234
253
|
}
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
254
|
+
if (this.#states === undefined) {
|
|
255
|
+
this.#states = {}
|
|
256
|
+
this.#keys = []
|
|
257
|
+
}
|
|
258
|
+
if (data.nodeid){
|
|
259
|
+
this.#nodeid = format(data.nodeid, params)
|
|
260
|
+
}
|
|
261
|
+
|
|
239
262
|
}
|
|
240
263
|
|
|
241
264
|
setState (index = 0) {
|
|
@@ -243,174 +266,78 @@ export class TouchButton {
|
|
|
243
266
|
}
|
|
244
267
|
|
|
245
268
|
async drawPhysical (device, id) {
|
|
269
|
+
const elem = this.getCurrentElement()
|
|
270
|
+
if (!elem || !elem.color) { return }
|
|
271
|
+
|
|
272
|
+
const r = parseInt(elem.color.slice(1, 3), 16)
|
|
273
|
+
const g = parseInt(elem.color.slice(3, 5), 16)
|
|
274
|
+
const b = parseInt(elem.color.slice(5, 7), 16)
|
|
275
|
+
|
|
246
276
|
try {
|
|
277
|
+
var idx = parseInt(id, 10);
|
|
278
|
+
|
|
247
279
|
const val = {
|
|
248
|
-
id,
|
|
249
|
-
color:
|
|
280
|
+
id:idx,
|
|
281
|
+
color: `rgba(${r}, ${g}, ${b})`
|
|
250
282
|
}
|
|
283
|
+
//console.log(' Set Button Color',val.id, val.color)
|
|
251
284
|
device.setButtonColor(val)
|
|
252
285
|
} catch (error) {
|
|
253
|
-
|
|
286
|
+
console.error(' Error', error)
|
|
254
287
|
}
|
|
255
288
|
}
|
|
256
289
|
|
|
257
290
|
async draw (row, column, ctx) {
|
|
258
291
|
const x = column * this.width
|
|
259
292
|
const y = row * this.height
|
|
260
|
-
switch (this.#style) {
|
|
261
|
-
case ButtonStyle.IMAGE:
|
|
262
|
-
ctx.drawImage(this.getCurrentStateImage(), x, y, this.width, this.height)
|
|
263
|
-
break
|
|
264
|
-
case ButtonStyle.COLOR:
|
|
265
|
-
// Draw a Colored Rectangle
|
|
266
|
-
ctx.fillStyle = this.getCurrentStateFill()
|
|
267
|
-
ctx.fillRect(x, y, this.width, this.height)
|
|
268
|
-
break
|
|
269
|
-
case ButtonStyle.NONE:
|
|
270
|
-
// Draw a Colored Rectangle
|
|
271
|
-
ctx.fillStyle = this.getCurrentStateFill(0)
|
|
272
|
-
ctx.fillRect(x, y, this.width, this.height)
|
|
273
|
-
break
|
|
274
|
-
}
|
|
275
293
|
|
|
276
|
-
|
|
277
|
-
ctx.font = this.font
|
|
278
|
-
ctx.fillText(this.text, x + 10, y - 10)
|
|
279
|
-
}
|
|
294
|
+
const elem = this.getCurrentElement()
|
|
280
295
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
case ButtonStyle.COLOR:
|
|
289
|
-
bLoaded = await this.loadAsColor()
|
|
290
|
-
break
|
|
291
|
-
case ButtonStyle.PHYSICAL:
|
|
292
|
-
bLoaded = await this.loadAsRGB()
|
|
293
|
-
break
|
|
294
|
-
default:
|
|
295
|
-
bLoaded = true
|
|
296
|
+
if (elem) {
|
|
297
|
+
if (elem.color) {
|
|
298
|
+
ctx.fillStyle = elem.color
|
|
299
|
+
ctx.fillRect(x, y, this.width, this.height)
|
|
300
|
+
}
|
|
301
|
+
if (elem.imgBuffer) {
|
|
302
|
+
ctx.drawImage(elem.imgBuffer, x, y, this.width, this.height)
|
|
296
303
|
}
|
|
297
304
|
}
|
|
298
|
-
}
|
|
299
305
|
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
return false
|
|
305
|
-
}
|
|
306
|
+
// ctx.fillStyle = '#000000'
|
|
307
|
+
// ctx.font = this.font
|
|
308
|
+
// ctx.fillText(this.text, x + 10, y - 10)
|
|
309
|
+
}
|
|
306
310
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
311
|
+
async load (globalConfig) {
|
|
312
|
+
this.#config = globalConfig
|
|
313
|
+
for (let i = 0; i < this.#keys.length; i++) {
|
|
314
|
+
const key = this.#keys[i]
|
|
315
|
+
const elem = this.#states[key]
|
|
316
|
+
const file = elem.image
|
|
310
317
|
if (file !== undefined && file !== '') {
|
|
311
318
|
try {
|
|
312
|
-
this.#
|
|
319
|
+
this.#states[key].imgBuffer = await loadImage(file)
|
|
313
320
|
} catch (e) {
|
|
314
321
|
console.error('No such image', file)
|
|
315
|
-
this.#style = ButtonStyle.COLOR
|
|
316
|
-
delete this.#images[key]
|
|
317
322
|
return false
|
|
318
323
|
}
|
|
319
|
-
} else {
|
|
320
|
-
// this is not an image type
|
|
321
324
|
}
|
|
325
|
+
//const uastate = elem.state
|
|
326
|
+
//if (uastate){
|
|
327
|
+
// await opcuainterface.Subscribe(uastate)
|
|
328
|
+
//}
|
|
322
329
|
}
|
|
323
|
-
return true
|
|
324
330
|
}
|
|
325
331
|
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
this.#states = Object.keys(this.#colors)
|
|
330
|
-
return true
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
for (let i = 0; i < this.#states.length; i++) {
|
|
334
|
-
const key = this.#states[i]
|
|
335
|
-
if (this.#data.colors && key in this.#data.colors) {
|
|
336
|
-
const color = this.#data.colors[key]
|
|
337
|
-
if (color !== undefined && color !== '') {
|
|
338
|
-
this.#colors[key] = color
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
|
-
}
|
|
342
|
-
return true
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
async loadAsRGB () {
|
|
346
|
-
if (this.#states.length <= 0) {
|
|
347
|
-
// use default colors
|
|
348
|
-
this.#states = Object.keys(this.#colors)
|
|
349
|
-
return true
|
|
350
|
-
}
|
|
351
|
-
|
|
352
|
-
if (this.#data.rgb) {
|
|
353
|
-
const keys = Object.keys(this.#data.rgb)
|
|
354
|
-
for (let i = 0; i < keys.length; i++) {
|
|
355
|
-
const key = this.#states[i]
|
|
356
|
-
const rgb = this.#data.rgb[key]
|
|
357
|
-
if (rgb !== undefined && rgb !== '') {
|
|
358
|
-
this.#rgbs[key] = rgb
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
return true
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
getCurrentStateImage () {
|
|
367
|
-
const key = this.#states[this.#index]
|
|
368
|
-
return this.#images[key]
|
|
369
|
-
}
|
|
370
|
-
|
|
371
|
-
getCurrentStateFill (forceIndex = -1) {
|
|
372
|
-
let key
|
|
373
|
-
if (forceIndex >= 0) {
|
|
374
|
-
key = this.#states[forceIndex]
|
|
375
|
-
} else {
|
|
376
|
-
key = this.#states[this.#index]
|
|
377
|
-
}
|
|
378
|
-
return this.#colors[key]
|
|
379
|
-
}
|
|
380
|
-
|
|
381
|
-
getCurrentRGB () {
|
|
382
|
-
const key = this.#states[this.#index]
|
|
383
|
-
const rgb = this.#rgbs[key]
|
|
384
|
-
|
|
385
|
-
return `rgba(${rgb[0]}, ${rgb[1]}, ${rgb[2]})`
|
|
332
|
+
getCurrentElement () {
|
|
333
|
+
const key = this.#keys[this.#index]
|
|
334
|
+
return this.#states[key]
|
|
386
335
|
}
|
|
387
336
|
|
|
388
337
|
getCurrentText () {
|
|
389
338
|
return this.text
|
|
390
339
|
}
|
|
391
340
|
|
|
392
|
-
getCurrentCommand () {
|
|
393
|
-
const key = this.#states[this.#index]
|
|
394
|
-
const cmd = this.#commands[key]
|
|
395
|
-
|
|
396
|
-
if (!cmd) { return '' }
|
|
397
|
-
// Call an action
|
|
398
|
-
const params = {
|
|
399
|
-
id: this.id,
|
|
400
|
-
state: key,
|
|
401
|
-
min: this.#min,
|
|
402
|
-
max: this.#max,
|
|
403
|
-
value: this.#value,
|
|
404
|
-
text: this.getCurrentText()
|
|
405
|
-
}
|
|
406
|
-
/* const keys = Object.keys(this.#data.config)
|
|
407
|
-
keys.forEach(key => {
|
|
408
|
-
params[key] = this.#data.config[key]
|
|
409
|
-
}) */
|
|
410
|
-
|
|
411
|
-
return format(cmd, params)
|
|
412
|
-
}
|
|
413
|
-
|
|
414
341
|
setIntState (val) {
|
|
415
342
|
this.#index = val
|
|
416
343
|
}
|
|
@@ -418,27 +345,21 @@ export class TouchButton {
|
|
|
418
345
|
pressed () {
|
|
419
346
|
this.timeStampPressed = Date.now()
|
|
420
347
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
break
|
|
424
|
-
default:
|
|
425
|
-
this.#index++
|
|
426
|
-
this.#index %= this.#states.length
|
|
427
|
-
}
|
|
348
|
+
this.#index++
|
|
349
|
+
this.updateState(this.#index)
|
|
428
350
|
return true
|
|
429
351
|
}
|
|
430
352
|
|
|
431
353
|
released () {
|
|
354
|
+
if (!this.getCurrentElement()) { return false }
|
|
432
355
|
this.timeStampReleased = Date.now()
|
|
433
356
|
this.timeHold = this.timeStampReleased - this.timeStampPressed
|
|
434
357
|
|
|
435
|
-
if (this.#style === ButtonStyle.NONE) { return }
|
|
436
|
-
|
|
437
358
|
if (this.timeHold < this.minPressed) {
|
|
438
359
|
// Update the State according to the not correct pressed state
|
|
439
360
|
console.log('Did not hold minimum time of ', this.minPressed, 'only', this.timeHold)
|
|
440
361
|
this.#index--
|
|
441
|
-
if (this.#index < 0) { this.#index = this.#
|
|
362
|
+
if (this.#index < 0) { this.#index = this.#keys.length - 1 }
|
|
442
363
|
return false
|
|
443
364
|
}
|
|
444
365
|
|
|
@@ -449,25 +370,134 @@ export class TouchButton {
|
|
|
449
370
|
break
|
|
450
371
|
default:
|
|
451
372
|
this.#index--
|
|
452
|
-
if (this.#index < 0) { this.#index = this.#
|
|
373
|
+
if (this.#index < 0) { this.#index = this.#keys.length - 1 }
|
|
453
374
|
|
|
454
375
|
break
|
|
455
376
|
}
|
|
377
|
+
|
|
378
|
+
this.updateState(this.#index)
|
|
379
|
+
|
|
380
|
+
return true // this.runCommand()
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
updateState(index){
|
|
384
|
+
this.#index = index
|
|
385
|
+
// Update the State according to the correctly pressed state
|
|
386
|
+
if (this.#index < 0) { this.#index = this.#keys.length - 1 }
|
|
387
|
+
this.#index %= this.#keys.length
|
|
456
388
|
this.runCommand()
|
|
389
|
+
//console.log("TODO: expect newState", newState)
|
|
457
390
|
return true // this.runCommand()
|
|
458
391
|
}
|
|
459
392
|
|
|
460
393
|
async rotated (delta) {
|
|
394
|
+
if (!this.getCurrentElement()) { return false }
|
|
395
|
+
|
|
461
396
|
this.#value = calcDelta(this.#value, delta, this.#max)
|
|
462
397
|
return this.runCommand()
|
|
463
398
|
}
|
|
464
399
|
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
if (
|
|
468
|
-
|
|
469
|
-
|
|
400
|
+
async changed(buttonID,nodeid,val){
|
|
401
|
+
// Only handle updates within the same group identified by nodeid
|
|
402
|
+
if (nodeid !== this.#nodeid){
|
|
403
|
+
return
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
this.#index = 0;
|
|
407
|
+
for (let i = 0; i < this.#keys.length; i++) {
|
|
408
|
+
let key = this.#keys[i]
|
|
409
|
+
// check if the state-name is same as the value we get from outside:
|
|
410
|
+
if (val == key){
|
|
411
|
+
this.#index = i;
|
|
412
|
+
break;
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
// check if the nodeid is the same and the value is one of the states
|
|
416
|
+
let state = this.#states[key]
|
|
417
|
+
if (!state.value)
|
|
418
|
+
continue
|
|
419
|
+
|
|
420
|
+
const params = {
|
|
421
|
+
id: buttonID,
|
|
422
|
+
key: buttonID,
|
|
423
|
+
...state
|
|
424
|
+
}
|
|
425
|
+
let val1 = format(state.value,params)
|
|
426
|
+
if (val1 === val){
|
|
427
|
+
this.#index = i;
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
430
|
+
break;
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
async touchmove (x, y) {
|
|
435
|
+
// if (!this.getCurrentElement()) { return false }
|
|
436
|
+
|
|
437
|
+
if (x > this.#x) {
|
|
438
|
+
this.#moveRight = true
|
|
439
|
+
this.#moveLeft = false
|
|
440
|
+
} else if (x < this.#x) {
|
|
441
|
+
this.#moveRight = false
|
|
442
|
+
this.#moveLeft = true
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
if (y > this.#y) {
|
|
446
|
+
this.#moveDown = true
|
|
447
|
+
this.#moveUp = false
|
|
448
|
+
} else if (y < this.#y) {
|
|
449
|
+
this.#moveDown = false
|
|
450
|
+
this.#moveUp = true
|
|
470
451
|
}
|
|
452
|
+
|
|
453
|
+
this.#x = x
|
|
454
|
+
this.#y = y
|
|
455
|
+
// console.log(`d: ${this.#moveDown} r: ${this.#moveRight} `)
|
|
471
456
|
return false
|
|
472
457
|
}
|
|
458
|
+
|
|
459
|
+
async runCommand () {
|
|
460
|
+
const elem = this.getCurrentElement()
|
|
461
|
+
if (!elem || (!elem.cmd && !elem.http && !elem.opcua)) {
|
|
462
|
+
return
|
|
463
|
+
}
|
|
464
|
+
// Call an action - include dynamic parameters
|
|
465
|
+
// and also all attributes of elem + global config
|
|
466
|
+
const params = {
|
|
467
|
+
id: this.id,
|
|
468
|
+
key: this.key,
|
|
469
|
+
state: this.#keys[this.#index],
|
|
470
|
+
min: this.#min,
|
|
471
|
+
max: this.#max,
|
|
472
|
+
value: this.#value,
|
|
473
|
+
text: this.getCurrentText(),
|
|
474
|
+
...this.#config.parameters,
|
|
475
|
+
...elem
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
let res = ''
|
|
479
|
+
if ('cmd' in elem) {
|
|
480
|
+
if (shellinterface){
|
|
481
|
+
res = await shellinterface.call(elem.cmd, params)
|
|
482
|
+
}else{
|
|
483
|
+
console.warn("shellinterface not started")
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
if ('http' in elem) {
|
|
487
|
+
if (httpinterface){
|
|
488
|
+
res = await httpinterface.call(elem.http, params)
|
|
489
|
+
}else{
|
|
490
|
+
console.warn("httpinterface not started")
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
if ('opcua' in elem) {
|
|
494
|
+
if (opcuainterface){
|
|
495
|
+
res = await opcuainterface.call(elem.opcua, params)
|
|
496
|
+
}else{
|
|
497
|
+
console.warn("opcuainterface not started")
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
return res
|
|
502
|
+
}
|
|
473
503
|
}
|