@@ -7,43 +7,63 @@ const storage = require('node-persist');
7
7
const {
8
8
bridgeIp,
9
9
userId,
10
- aPin, bPin, togglePin
10
+ a1Pin, b1Pin, toggle1Pin,
11
+ a2Pin, b2Pin, toggle2Pin,
12
+ a3Pin, b3Pin, toggle3Pin
11
13
} = require ( './config.json' ) ;
12
14
13
- const FIELDS = { 'bri' : 8 , 'hue' : 1024 , 'sat' : 8 } ;
15
+ const FIELDS = { 'hue' : 1024 , 'sat' : 8 , 'bri' : 8 } ;
16
+ const SELECT_PATTERN = [ 1 , 2 , 3 , 2 , 1 , 3 ] ;
14
17
15
18
class RotaryEncoder extends EventEmitter {
16
- constructor ( { a, b, toggle} ) {
19
+ constructor ( {
20
+ a1, b1, toggle1,
21
+ a2, b2, toggle2,
22
+ a3, b3, toggle3,
23
+ } ) {
17
24
super ( ) ;
18
- this . gpioA = new Gpio ( a , 'in' , 'both' ) ;
19
- this . gpioB = new Gpio ( b , 'in' , 'both' ) ;
20
- this . gpioToggle = new Gpio ( toggle , 'in' , 'rising' , { debounceTimeout : 10 } ) ;
21
- this . gpioA . watch ( ( err , value ) => {
25
+ this . gpio1A = new Gpio ( a1 , 'in' , 'both' ) ;
26
+ this . gpio1B = new Gpio ( b1 , 'in' , 'both' ) ;
27
+ this . gpio1Toggle = new Gpio ( toggle1 , 'in' , 'rising' , { debounceTimeout : 10 } ) ;
28
+ this . gpio2A = new Gpio ( a2 , 'in' , 'both' ) ;
29
+ this . gpio2B = new Gpio ( b2 , 'in' , 'both' ) ;
30
+ this . gpio2Toggle = new Gpio ( toggle2 , 'in' , 'rising' , { debounceTimeout : 10 } ) ;
31
+ this . gpio3A = new Gpio ( a3 , 'in' , 'both' ) ;
32
+ this . gpio3B = new Gpio ( b3 , 'in' , 'both' ) ;
33
+ this . gpio3Toggle = new Gpio ( toggle3 , 'in' , 'rising' , { debounceTimeout : 10 } ) ;
34
+ this . _watch ( 1 , this . gpio1A , this . gpio1B , this . gpio1Toggle ) ;
35
+ this . _watch ( 2 , this . gpio2A , this . gpio2B , this . gpio2Toggle ) ;
36
+ this . _watch ( 3 , this . gpio3A , this . gpio3B , this . gpio3Toggle ) ;
37
+ }
38
+
39
+ _watch ( index , gpioA , gpioB , gpioToggle ) {
40
+ gpioA . watch ( ( err , value ) => {
22
41
if ( err ) {
23
42
this . emit ( 'error' , err ) ;
24
43
return ;
25
44
}
26
45
const a = value ;
27
46
28
47
try {
29
- const b = this . gpioB . readSync ( ) ;
48
+ const b = gpioB . readSync ( ) ;
30
49
if ( a === b ) {
31
- this . emit ( 'rotation' , 1 ) ;
50
+ this . emit ( 'rotation' + index , 1 ) ;
32
51
} else {
33
- this . emit ( 'rotation' , - 1 ) ;
52
+ this . emit ( 'rotation' + index , - 1 ) ;
34
53
}
35
54
} catch ( ex ) {
36
55
this . emit ( 'error' , ex ) ;
37
56
}
38
57
} ) ;
39
- this . gpioToggle . watch ( ( err , value ) => {
58
+ gpioToggle . watch ( ( err , value ) => {
40
59
if ( err ) {
41
60
this . emit ( 'error' , err ) ;
42
61
return ;
43
62
}
44
- this . emit ( 'toggle' ) ;
63
+ this . emit ( 'toggle' + index ) ;
45
64
} ) ;
46
- }
65
+
66
+ }
47
67
}
48
68
49
69
class HueAPI {
@@ -162,6 +182,7 @@ function throttlePromise(fn,{ reduce, debounce, delay } = { reduce: null, deboun
162
182
completed ( ) ;
163
183
}
164
184
} ) . catch ( ( e ) => {
185
+ console . log ( e . stack ) ;
165
186
running = false ;
166
187
if ( ! waiting ) {
167
188
completed ( ) ;
@@ -203,7 +224,7 @@ class LightGroupController {
203
224
this . api = api ;
204
225
this . worker = worker ;
205
226
this . groupState = null ;
206
- this . fieldIndex = 0 ;
227
+ this . matchIndex = 0 ;
207
228
}
208
229
209
230
async init ( ) {
@@ -215,41 +236,68 @@ class LightGroupController {
215
236
216
237
async onEvent ( event , args ) {
217
238
switch ( event ) {
218
- case 'rotation' : {
219
- const field = Object . keys ( FIELDS ) [ this . fieldIndex ] ;
220
- const change = {
221
- [ field ] : FIELDS [ field ] * args ,
222
- 'on' : true
223
- } ;
224
- if ( this . groupState ) {
225
- Object . keys ( change ) . forEach ( k => {
226
- if ( typeof change [ k ] === 'number' ) {
227
- this . groupState [ k ] += change [ k ]
228
- } else {
229
- this . groupState [ k ] = change [ k ]
230
- }
231
- } ) ;
232
- this . worker . send ( 'lightgroup_control' , this . groupState ) ;
239
+ case 'rotation1' :
240
+ await this . _rotate ( 'bri' , args ) ;
241
+ break ;
242
+ case 'rotation2' :
243
+ await this . _rotate ( 'sat' , args ) ;
244
+ break ;
245
+ case 'rotation3' :
246
+ await this . _rotate ( 'hue' , args ) ;
247
+ break ;
248
+
249
+ case 'toggle1' :
250
+ case 'toggle2' :
251
+ case 'toggle3' : {
252
+ if ( this . matchIndex === SELECT_PATTERN . length ) {
253
+ return ;
254
+ }
255
+
256
+ // check if the user has entered the select screen pattern
257
+ const index = parseInt ( event [ event . length - 1 ] , 10 ) ;
258
+ if ( index === SELECT_PATTERN [ this . matchIndex ++ ] ) {
259
+ if ( this . matchIndex === SELECT_PATTERN . length ) {
260
+ const newController = new LightGroupSelector ( this . api , this . worker ) ;
261
+ await newController . init ( ) ;
262
+ controller = newController ;
263
+ return ;
264
+ }
265
+ } else {
266
+ this . matchIndex = 0 ;
233
267
}
234
268
235
- const response = await this . api . putGroup ( this . groupId , Object . keys ( change ) . reduce ( ( prev , next ) => {
236
- const value = change [ next ] ;
237
- prev [ next + ( typeof value === 'number' ? '_inc' : '' ) ] = value ;
238
- return prev ;
239
- } , { } ) ) ;
269
+ const response = await this . api . putGroup ( this . groupId , {
270
+ 'on' : this . groupState ? ! this . groupState . on : true
271
+ } ) ;
240
272
await this . init ( ) ;
241
273
break ;
242
274
}
275
+ }
276
+ }
243
277
244
- case 'toggle' : {
245
- this . fieldIndex ++ ;
246
- if ( this . fieldIndex >= Object . keys ( FIELDS ) . length ) {
247
- this . fieldIndex = 0 ;
278
+ async _rotate ( field , value ) {
279
+ const change = {
280
+ [ field ] : FIELDS [ field ] * value ,
281
+ 'on' : true
282
+ } ;
283
+ if ( this . groupState ) {
284
+ Object . keys ( change ) . forEach ( k => {
285
+ if ( typeof change [ k ] === 'number' ) {
286
+ this . groupState [ k ] += change [ k ]
287
+ } else {
288
+ this . groupState [ k ] = change [ k ]
248
289
}
249
- break ;
250
- }
290
+ } ) ;
291
+ this . worker . send ( 'lightgroup_control' , this . groupState ) ;
251
292
}
252
- }
293
+
294
+ const response = await this . api . putGroup ( this . groupId , Object . keys ( change ) . reduce ( ( prev , next ) => {
295
+ const value = change [ next ] ;
296
+ prev [ next + ( typeof value === 'number' ? '_inc' : '' ) ] = value ;
297
+ return prev ;
298
+ } , { } ) ) ;
299
+ await this . init ( ) ;
300
+ }
253
301
}
254
302
255
303
class LightGroupSelector {
@@ -270,7 +318,9 @@ class LightGroupSelector {
270
318
271
319
async onEvent ( event , args ) {
272
320
switch ( event ) {
273
- case 'rotation' : {
321
+ case 'rotation1' :
322
+ case 'rotation2' :
323
+ case 'rotation3' : {
274
324
this . selected += ( args > 0 ? 1 : - 1 ) ;
275
325
if ( this . selected >= this . options . length ) {
276
326
this . selected = this . options . length - 1 ;
@@ -284,7 +334,9 @@ class LightGroupSelector {
284
334
break ;
285
335
}
286
336
287
- case 'toggle' : {
337
+ case 'toggle1' :
338
+ case 'toggle2' :
339
+ case 'toggle3' : {
288
340
const groupId = this . options [ this . selected ] . key ;
289
341
console . log ( 'Selected groupId: ' + groupId ) ;
290
342
await storage . setItem ( 'groupId' , groupId ) ;
@@ -303,9 +355,15 @@ storage.init().then(async () => {
303
355
const api = new HueAPI ( bridgeIp , userId ) ;
304
356
const uiWorker = new Worker ( ) ;
305
357
const encoder = new RotaryEncoder ( {
306
- a : aPin ,
307
- b : bPin ,
308
- toggle : togglePin
358
+ a1 : a1Pin ,
359
+ b1 : b1Pin ,
360
+ toggle1 : toggle1Pin ,
361
+ a2 : a2Pin ,
362
+ b2 : b2Pin ,
363
+ toggle2 : toggle2Pin ,
364
+ a3 : a3Pin ,
365
+ b3 : b3Pin ,
366
+ toggle3 : toggle3Pin
309
367
} ) ;
310
368
311
369
const groupId = await storage . getItem ( 'groupId' ) ;
@@ -317,11 +375,13 @@ storage.init().then(async () => {
317
375
}
318
376
await controller . init ( ) ;
319
377
320
- encoder . on ( 'rotation' , throttlePromise ( ( value ) => controller . onEvent ( 'rotation' , value ) , {
321
- debounce : 100 ,
322
- delay : 500 ,
323
- reduce : ( prev , next ) => [ prev [ 0 ] + next [ 0 ] ]
324
- } ) ) ;
378
+ for ( let i = 1 ; i <= 3 ; ++ i ) {
379
+ encoder . on ( 'rotation' + i , throttlePromise ( ( value ) => controller . onEvent ( 'rotation' + i , value ) , {
380
+ debounce : 100 ,
381
+ delay : 500 ,
382
+ reduce : ( prev , next ) => [ prev [ 0 ] + next [ 0 ] ]
383
+ } ) ) ;
384
+ encoder . on ( 'toggle' + i , ( ) => controller . onEvent ( 'toggle' + i ) ) ;
385
+ }
325
386
326
- encoder . on ( 'toggle' , ( ) => controller . onEvent ( 'toggle' ) ) ;
327
387
} ) ;
0 commit comments