forked from Pittini/iobroker-LightControl
-
Notifications
You must be signed in to change notification settings - Fork 0
/
LightControl.js
1844 lines (1637 loc) · 90.1 KB
/
LightControl.js
1
2
3
4
5
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
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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
const Version = "2.0.19_01" //vom 6.1.2022 - Skript um Lichter in Helligkeit, Farbe und Farbtemp global zu steuern - Git: https://github.com/Pittini/iobroker-LightControl - Forum: https://forum.iobroker.net/topic/36578/vorlage-lightcontrol
log("starting LightControl V." + Version);
const praefix = "javascript.0.inUse.LightControl2" // Skriptordner
const LuxSensor = ''; // Datenpunkt des globalen Luxsensors, wird verwendet wenn in der Gruppe kein gesonderter definiert wird
const IsPresenceDp = ""//"radar2.0.Mario._here"; // Datenpunkt für Anwesenheit (true/false)
const PresenceCountDp = "radar2.0._nHere"; // Datenpunkt für Anwesenheitszähler
const logging = true; // Logging an/aus
const RampSteps = 20; //Wieviele Schritte zum dimmen? Bitte nicht zu hoch setzen, wird zwar smoother, kann aber zu timing Problemen führen wenn gleichzeitig eine kurze Zeit in den Objekten gewählt.
const minCt = 2700; //Regelbereich für Farbtemperatur in Kelvin für Adaptive Ct
const maxCt = 6500;//Regelbereich für Farbtemperatur in Kelvin für Adaptive Ct
const minBri = 10; //Mindesthelligkeit für AdaptiveBri
const LightGroups = {
0: {
description: "Badezimmer",
lights: {
0: {
description: "Deckenlampen",
power: { oid: "hue.0.Bad.allOn", onVal: true, offVal: false },
bri: { oid: "hue.0.Bad.bri", minVal: 0, maxVal: 254, defaultVal: 123 },
ct: { oid: "hue.0.Bad.ct", minVal: 0, maxVal: 254 },
sat: { oid: "", minVal: null, maxVal: null },
modeswitch: { oid: "", whiteModeVal: false, colorModeVal: true },
color: { oid: "", type: "", default: "" }
}
},
sensors: {
0: { id: 'hue.0.Bad_Bewegungsmelder.presence', motionVal: true, noMotionVal: false }
}
},
1: {
description: "Wohnzimmer",
lights: {
0: {
description: "Deckenlampen",
power: { oid: "hue.0.Wohnzimmer.allOn", onVal: true, offVal: false },
bri: { oid: "hue.0.Wohnzimmer.level", minVal: 0, maxVal: 100, defaultVal: 80 },
ct: { oid: "hue.0.Wohnzimmer.ct", minVal: 0, maxVal: 254 },
sat: { oid: "hue.0.Wohnzimmer.sat", minVal: 0, maxVal: 254 },
modeswitch: { oid: "", whiteModeVal: false, colorModeVal: true },
color: { oid: "hue.0.Wohnzimmer.xy", type: "xy", default: "" }
}
},
sensors: {
}
},
2: {
description: "Schlafzimmer",
lights: {
0: {
description: "Deckenlampen",
power: { oid: "hue.0.Wohnzimmer_Ambiance.allOn", onVal: true, offVal: false },
bri: { oid: "hue.0.Wohnzimmer_Ambiance.bri", minVal: 0, maxVal: 254, defaultVal: 230 },
ct: { oid: "hue.0.Wohnzimmer_Ambiance.ct", minVal: 0, maxVal: 254 },
sat: { oid: "hue.0.Wohnzimmer_Ambiance.sat", minVal: 0, maxVal: 254 },
modeswitch: { oid: "", whiteModeVal: false, colorModeVal: true },
color: { oid: "hue.0.Wohnzimmer_Ambiance.xy", type: "xy", default: "" }
},
1: {
description: "360-BottleLamp",
power: { oid: "wled.0.40f520259aa0.on", onVal: true, offVal: false },
bri: { oid: "wled.0.40f520259aa0.bri", minVal: 0, maxVal: 254, defaultVal: 200 },
ct: { oid: "", minVal: null, maxVal: null },
sat: { oid: "", minVal: null, maxVal: null },
modeswitch: { oid: "", whiteModeVal: false, colorModeVal: true },
color: { oid: "wled.0.40f520259aa0", type: "wled", default: "" }
},
2: {
description: "DeskLamp",
power: { oid: "wled.0.50029168eeac.on", onVal: true, offVal: false },
bri: { oid: "wled.0.50029168eeac.bri", minVal: 0, maxVal: 254, defaultVal: 200 },
ct: { oid: "", minVal: null, maxVal: null },
sat: { oid: "", minVal: null, maxVal: null },
modeswitch: { oid: "", whiteModeVal: false, colorModeVal: true },
color: { oid: "wled.0.50029168eeac", type: "wled", default: "" }
}
},
sensors: {
}
},
3: {
description: "Ambiente EG",
lights: {
0: {
description: "Hue Go 1",
power: { oid: "hue.1.Hue_go_1.on", onVal: true, offVal: false },
bri: { oid: "hue.1.hue.1.Hue_go_1.bri", minVal: 0, maxVal: 254, defaultVal: 230 },
ct: { oid: "hue.1.Hue_go_1.ct", minVal: 0, maxVal: 254 },
sat: { oid: "hue.1.Hue_go_1.sat", minVal: 0, maxVal: 254 },
modeswitch: { oid: "", whiteModeVal: false, colorModeVal: true },
color: { oid: "hue.1.Hue_go_1.xy", type: "xy", default: "0.5812,0.3911" }
},
1: {
description: "Lightstrip Couch",
power: { oid: "hue.1.Wohnzimmer_Lightstrip_Couch.on", onVal: true, offVal: false },
bri: { oid: "hue.1.hue.1.Wohnzimmer_Lightstrip_Couch.bri", minVal: 0, maxVal: 254, defaultVal: 230 },
ct: { oid: "hue.1.Wohnzimmer_Lightstrip_Couch.ct", minVal: 0, maxVal: 254 },
sat: { oid: "hue.1.Wohnzimmer_Lightstrip_Couch.sat", minVal: 0, maxVal: 254 },
modeswitch: { oid: "", whiteModeVal: false, colorModeVal: true },
color: { oid: "hue.1.Wohnzimmer_Lightstrip_Couch.xy", type: "xy", default: "0.5756,0.3713" }
},
2: {
description: "Lightstrip TV",
power: { oid: "hue.1.Wohnzimmer_Lightstrip_TV.on", onVal: true, offVal: false },
bri: { oid: "hue.1.hue.1.Wohnzimmer_Lightstrip_TV.bri", minVal: 0, maxVal: 254, defaultVal: 230 },
ct: { oid: "hue.1.Wohnzimmer_Lightstrip_TV.ct", minVal: 0, maxVal: 254 },
sat: { oid: "hue.1.Wohnzimmer_Lightstrip_TV.sat", minVal: 0, maxVal: 254 },
modeswitch: { oid: "", whiteModeVal: false, colorModeVal: true },
color: { oid: "hue.1.Wohnzimmer_Lightstrip_TV.xy", type: "xy", default: "0.5296,0.4299" }
},
},
sensors: {
}
}/*,
4: {
description: "Test",
lights: {
0: {
description: "Testlampe",
power: { oid: "0_userdata.0.TestDatenpunkte.Lampen.power", onVal: true, offVal: false },
bri: { oid: "0_userdata.0.TestDatenpunkte.Lampen.bri", minVal: 0, maxVal: 100, defaultVal: 100 },
ct: { oid: "0_userdata.0.TestDatenpunkte.Lampen.ct", minVal: 2100, maxVal: null },
sat: { oid: "", minVal: null, maxVal: null },
modeswitch: { oid: "", whiteModeVal: false, colorModeVal: true },
color: { oid: "", type: "", default: "" }
}
},
sensors: {
}
}
*/
};
// ------------------ AB HIER NIX MEHR ÄNDERN --------------------------
let RampOnIntervalObject = {};
let RampOffIntervalObject = {};
let AutoOffTimeoutObject = {};
let TickerIntervalObj = {};
let BlinkIntervalObj = {};
let ActualGenericLux = 0;
let ActualPresence = true;
let ActualPresenceCount = 1;
const suncalc = require('suncalc');
const result = getObject("system.adapter.javascript.0");
const lat = result.native.latitude;
const long = result.native.longitude;
const GroupAllTemplate = {
power: { id: praefix + ".all.power", common: { read: true, write: true, name: "Masterpower", type: "boolean", role: "switch.power", def: false } },
anyOn: { id: praefix + ".all.anyOn", common: { read: true, write: false, name: "Any Group is On", type: "boolean", role: "indicator.state", def: false } },
}
const GroupTemplate = {
power: { id: "", common: { read: true, write: true, name: "Power", type: "boolean", role: "switch.power", def: false } },
dimmUp: { id: "", common: { read: true, write: true, name: "DimmUp", type: "boolean", role: "button", def: false } },
dimmDown: { id: "", common: { read: true, write: true, name: "DimmDown", type: "boolean", role: "button", def: false } },
dimmAmount: { id: "", common: { read: true, write: true, name: "Brightnesssteps for dimming", type: "number", role: "level.brightness", def: 10, min: 2, max: 50, unit: "%" } },
bri: { id: "", common: { read: true, write: true, name: "Brightness", type: "number", role: "level.brightness", def: 100, min: 0, max: 100, unit: "%" } },
ct: { id: "", common: { read: true, write: true, name: "Colortemperature", type: "number", role: "level.color.temperature", def: 3300, min: 2100, max: 6500, unit: "K" } },
color: { id: "", common: { read: true, write: true, name: "Color", type: "string", role: "level.color.rgb", def: "#FFFFFF" } },
luxSensorOid: { id: "", common: { read: true, write: true, name: "ObjectId for Luxsensor", type: "string", role: "state", def: LuxSensor } },
adaptiveBri: { id: "", common: { read: true, write: true, name: "Adaptive Brightness", type: "boolean", role: "switch.enable", def: false } },
adaptiveCt: { id: "", common: { read: true, write: true, name: "Adaptive Colortemperature", type: "boolean", role: "switch.enable", def: false } },
adaptiveCtMode: { id: "", common: { read: true, write: true, name: "Mode for Adaptive Colortemperature", type: "string", role: "switch.mode", def: "solar", states: { linear: "Linear", solar: "Solar", solarInterpolated: "Solar interpolated", timed: "StartYourDay" } } },
adaptiveCtTime: { id: "", common: { read: true, write: true, name: "Startzeit Adaptive Colortemperature bei Modus: StartYourDay", type: "string", unit: "Uhr", role: "value", def: "06:00" } },
powerCleaningLight: { id: "", common: { read: true, write: true, name: "Power", type: "boolean", role: "switch.power", def: false } },
isMotion: { id: "", common: { read: true, write: false, name: "Combines the states of all Sensors for this Group", type: "boolean", role: "indicator.motion", def: false } },
autoOffTimed: {
enabled: { id: "", common: { read: true, write: true, name: "Timecontrolled auto off enabled?", type: "boolean", role: "switch.enable", def: false } },
autoOffTime: { id: "", common: { read: true, write: true, name: "Time until auto off", type: "number", role: "level.timer", def: 120, min: 0, unit: "sek" } },
noAutoOffWhenMotion: { id: "", common: { read: true, write: true, name: "No timed auto off if motion detected", type: "boolean", role: "switch", def: true } }
},
autoOffLux: {
enabled: { id: "", common: { read: true, write: true, name: "Brightness controlled auto off enabled?", type: "boolean", role: "switch.enable", def: false } },
minLux: { id: "", common: { read: true, write: true, name: "Brightness for auto off", type: "number", role: "level.brightness", def: 500, min: 0, unit: "lux" } },
dailyLock: { id: "", common: { read: true, write: false, name: "Switch lock", type: "boolean", role: "indicator", def: false } },
operator: { id: "", common: { read: true, write: true, name: "Should auto off happen if brightness more or less minLux", type: "string", role: "state", def: ">" } }
},
autoOnMotion: {
enabled: { id: "", common: { read: true, write: true, name: "Motion controlled auto on enabled?", type: "boolean", role: "switch.enable", def: false } },
minLux: { id: "", common: { read: true, write: true, name: "Brightness for auto on motion", type: "number", role: "level.brightness", def: 300, min: 0, unit: "lux" } },
bri: { id: "", common: { read: true, write: true, name: "Brightness of lights when auto on, if empty using groupstandard", type: "number", role: "level.brightness", def: 0, min: 0, max: 100, unit: "%" } },
color: { id: "", common: { read: true, write: true, name: "Color of lights when auto on, if empty using groupstandard", type: "string", role: "level.color.rgb", def: "" } }
},
autoOnLux: {
enabled: { id: "", common: { read: true, write: true, name: "Brightness controlled auto on enabled?", type: "boolean", role: "switch.enable", def: false } },
minLux: { id: "", common: { read: true, write: true, name: "Brightness for auto on", type: "number", role: "level.brightness", def: 50, min: 0, unit: "lux" } },
bri: { id: "", common: { read: true, write: true, name: "Brightness of lights when auto on, if empty using groupstandard", type: "number", role: "level.brightness", def: 0, min: 0, max: 100, unit: "%" } },
color: { id: "", common: { read: true, write: true, name: "Color of lights when auto on, if empty using groupstandard", type: "string", role: "level.color.rgb", def: "" } },
switchOnlyWhenPresence: { id: "", common: { read: true, write: true, name: "Switch only if there is somebody at home?", type: "boolean", role: "switch", def: true } },
switchOnlyWhenNoPresence: { id: "", common: { read: true, write: true, name: "Switch only if there is nobody at home?", type: "boolean", role: "switch", def: false } },
dailyLock: { id: "", common: { read: true, write: false, name: "Switch lock", type: "boolean", role: "indicator", def: false } },
operator: { id: "", common: { read: true, write: true, name: "Should auto on happen if brightness more or less minLux", type: "string", role: "state", def: "<" } }
},
autoOnPresenceIncrease: {
enabled: { id: "", common: { read: true, write: true, name: "Presence controlled auto on enabled?", type: "boolean", role: "switch.enable", def: false } },
minLux: { id: "", common: { read: true, write: true, name: "Necessary brightness for auto on", type: "number", role: "level.brightness", def: 50, min: 0, unit: "lux" } },
bri: { id: "", common: { read: true, write: true, name: "Brightness of lights when auto on, if empty using groupstandard", type: "number", role: "level.brightness", def: 0, max: 100, min: 0, unit: "%" } },
color: { id: "", common: { read: true, write: true, name: "Color of lights when auto on, if empty using groupstandard", type: "string", role: "level.color.rgb", def: "" } }
},
rampOn: {
enabled: { id: "", common: { read: true, write: true, name: "Ramping on enabled?", type: "boolean", role: "switch.enable", def: false } },
time: { id: "", common: { read: true, write: true, name: "Time in seconds for ramping on duration", type: "number", role: "level", def: 10, min: 0, unit: "sec" } },
switchOutletsLast: { id: "", common: { read: true, write: true, name: "Switch outlets after ramping?", type: "boolean", role: "switch.enable", def: true } }
},
rampOff: {
enabled: { id: "", common: { read: true, write: true, name: "Ramping off enabled?", type: "boolean", role: "switch.enable", def: false } },
time: { id: "", common: { read: true, write: true, name: "Time in seconds for ramping off duration", type: "number", role: "level", def: 10, min: 0, unit: "sec" } },
switchOutletsLast: { id: "", common: { read: true, write: true, name: "Switch outlets after ramping?", type: "boolean", role: "switch.enable", def: false } }
},
blink: {
enabled: { id: "", common: { read: true, write: true, name: "Blinking enabled?", type: "boolean", role: "button.start", def: false } },
frequency: { id: "", common: { read: true, write: true, name: "Blink frequency in seconds", type: "number", role: "level", def: 1, min: 1, unit: "sek" } },
blinks: { id: "", common: { read: true, write: true, name: "How many blinks at activation?", type: "number", role: "level", def: 3, min: 1 } },
bri: { id: "", common: { read: true, write: true, name: "Brightness of lights when blinking, if empty using groupstandard", type: "number", role: "level.brightness", def: 100, max: 100, min: 0, unit: "%" } },
color: { id: "", common: { read: true, write: true, name: "Color of lights when blinking, if empty using groupstandard", type: "string", role: "level.color.rgb", def: "#FF0000" } }
},
alexa: {
bri: { id: "", common: { read: true, write: true, name: "Brightness", type: "number", role: "level.dimmer", def: 100, min: 0, max: 100, unit: "%", smartName: {de: "", smartType: "LIGHT"} } },
//hue: { id: "", common: { read: false, write: true, name: "Buntwert", type: "number", role: "level.color.hue", smartName: {de: "", smartType: "LIGHT"} } },
//ct: { id: "", common: { read: true, write: true, name: "Colortemperature", type: "number", role: "level.color.temperature", min: 0, max: 360, smartName: {de: "", smartType: "LIGHT"} } },
//sat: { id: "", common: { read: false, write: true, name: "Saturation", type: "number", role: "level.color.saturation", min: 0, max: 100, smartName: {de: "", smartType: "LIGHT"} } },
rgb: { id: "", common: { read: true, write: true, name: "Color", type: "string", role: "level.color.rgb", def: "#FF0000", smartName: {de: "", smartType: "LIGHT"} } }
}
}
main();
async function GlobalLuxHandling() {
// Globale Luxwerte holen und Trigger setzen
if (LuxSensor != "") {
ActualGenericLux = (await getStateAsync(LuxSensor)).val;
// log("ActualGenericLux=" + ActualGenericLux)
on({ id: LuxSensor, change: "ne", ack: true }, function (dp) { //Trigger erstellen, außer Dp ist readonly
if (logging) log("Triggered Luxsensor " + LuxSensor + " new value is " + dp.state.val);
ActualGenericLux = dp.state.val;
RefreshGenericLuxValues();
});
};
}
async function GlobalPresenceHandling() {
if (PresenceCountDp != "") {
ActualPresenceCount = (await getStateAsync(PresenceCountDp)).val;
on({ id: PresenceCountDp, change: "any", ack: true }, function (dp) { //Trigger erstellen, außer Dp ist readonly
if (dp.state.val > dp.state.val) {
if (logging) log("Triggered PresenceCountDp " + PresenceCountDp + " new value is " + dp.state.val);
ActualPresenceCount = dp.state.val;
AutoOnPresenceIncrease();
}
else if (dp.state.val == 0) {
if (logging) log("Alle sind aus dem Haus, Lichter werden aus geschaltet!");
setState("javascript.0.LightControl2.all.power", false);
}
});
};
if (IsPresenceDp != "") {
ActualPresence = (await getStateAsync(IsPresenceDp)).val;
on({ id: IsPresenceDp, change: "ne", ack: true }, function (dp) { //Trigger erstellen, außer Dp ist readonly
if (logging) log("Triggered IsPresenceDp " + IsPresenceDp + " new value is " + dp.state.val);
ActualPresence = dp.state.val;
AutoOnPresenceIncrease();
});
};
if (ActualPresenceCount == 0) {
ActualPresence = false;
} else {
ActualPresence = true;
};
}
async function init() {
let DpCount = 0;
//Datenpunkte anlegen, Objekte erweitern, Daten einlesen, Trigger erzeugen
for (let Group in LightGroups) { //Gruppen durchgehen
await DoAllTheSensorThings(Group); //Sonderfall sensors
for (let prop1 in GroupTemplate) { // Template Properties 1. Ebene durchgehen
if (typeof GroupTemplate[prop1].id == "undefined") { //Wenn keine id zu finden, nächste, 2. Ebene durchlaufen
LightGroups[Group][prop1] = {}; //2te Ebene im Objekt anlegen
for (let z in GroupTemplate[prop1]) {
GroupTemplate[prop1][z].id = praefix + "." + Group + "." + prop1 + "." + z;
if (!await existsStateAsync(GroupTemplate[prop1][z].id)) {// Prüfen ob state noch nicht vorhanden
if (prop1 == "alexa") { // Prüfen ob der State ein alexa State ist.
if (logging) log("Add Room information to smartName: " + GroupTemplate[prop1][z].id);
GroupTemplate[prop1][z].common.smartName.de = (LightGroups[Group].description + " Licht"); // // Raum zum smartNamen hinzufügen
}
await createStateAsync(GroupTemplate[prop1][z].id, GroupTemplate[prop1][z].common);//State anlegen
log("Init: Created datapoint " + GroupTemplate[prop1][z].id);
DpCount++;
} else {
if (logging) log("Init: Datapoint " + GroupTemplate[prop1][z].id + " still exists, skipping creation and reading data");
};
LightGroups[Group][prop1][z] = (await getStateAsync(GroupTemplate[prop1][z].id)).val; //Daten in Lightgroups einlesen (auch wenn neu erzeugt), dann
if (GroupTemplate[prop1][z].common.write) {
// log("Setting Trigger for: " + GroupTemplate[prop1][z].id)
on({ id: GroupTemplate[prop1][z].id, change: "any", ack: false }, function (dp) { //Trigger erstellen
if (logging) log("Triggered " + dp.id + " new value is " + dp.state.val)
LightGroups[Group][prop1][z] = dp.state.val;
Controller(Group, prop1 + "." + z, dp.oldState.val, dp.state.val);
});
};
};
if (!await existsObjectAsync(praefix + "." + Group + "." + prop1)) { // Channel erstellen wenn noch nicht vorhanden
await setObjectAsync(praefix + "." + Group + "." + prop1, { type: 'channel', common: { name: LightGroups[Group].description + " " + prop1 }, native: {} });
log("Init: Subchannel " + praefix + "." + Group + "." + prop1 + " created");
};
} else {
GroupTemplate[prop1].id = praefix + "." + Group + "." + prop1;
if (!await existsStateAsync(GroupTemplate[prop1].id)) { // Prüfen ob state noch nicht vorhanden
await createStateAsync(GroupTemplate[prop1].id, GroupTemplate[prop1].common); //State anlegen
log("Init: Created datapoint " + GroupTemplate[prop1].id);
DpCount++;
} else {
if (logging) log("Init:Datapoint " + GroupTemplate[prop1].id + " still exists, skipping creation and reading data");
};
LightGroups[Group][prop1] = (await getStateAsync(GroupTemplate[prop1].id)).val; //Daten in Lightgroups einlesen (auch wenn neu erzeugt), dann
// log("LightGroups[" + Group + "][" + prop1 + "]=" + LightGroups[Group][prop1])
if (logging) log("Init: Read data from:" + praefix + "." + Group + "." + prop1 + ", value is " + LightGroups[Group][prop1]);
//LuxGroupsensor Handling
if (prop1 == "luxSensorOid") await DoAllTheLuxSensorThings(Group, prop1);
if (GroupTemplate[prop1].common.write) { //Trigger für alle Template Dps erstellen, außer Dp ist readonly
// log("Init: Setting Trigger for: " + GroupTemplate[prop1].id)
on({ id: GroupTemplate[prop1].id, change: "any", ack: false }, function (dp) {
// log("Init: Triggered " + dp.id + " new value is " + dp.state.val);
LightGroups[Group][prop1] = dp.state.val;
// if (prop1 == "luxSensorOid") ChangeLuxSensorTrigger(Group, prop1, dp.oldState.val, dp.state.val);
Controller(Group, prop1, dp.oldState.val, dp.state.val);
});
};
};
};
if (!await existsObjectAsync(praefix + "." + Group)) { //Gruppenchannel anlegen wenn noch nicht vorhanden
await setObjectAsync(praefix + "." + Group, { type: 'channel', common: { name: LightGroups[Group].description }, native: {} });
log("Init: Channel " + praefix + "." + Group + " created");
};
// await setStateAsync(praefix + "." + Group + ".autoOnLux.dailyLock", false, true);
// await setStateAsync(praefix + "." + Group + ".autoOffLux.dailyLock", false, true);
LightGroups[Group].autoOnLux.dailyLockCounter = 0;
LightGroups[Group].autoOffLux.dailyLockCounter = 0;
};
for (let prop1 in GroupAllTemplate) { // Sondergruppe "all" anlegen
if (!await existsStateAsync(GroupAllTemplate[prop1].id)) {// Prüfen ob state noch nicht vorhanden
await createStateAsync(GroupAllTemplate[prop1].id, GroupAllTemplate[prop1].common);//State anlegen
log("Init: Created datapoint " + GroupAllTemplate[prop1].id);
DpCount++;
} else {
if (logging) log("Init: Datapoint " + GroupAllTemplate[prop1].id + " still exists, skipping creation and setting trigger");
};
if (GroupAllTemplate[prop1].common.write) { //Trigger für alle Template Dps erstellen, außer Dp ist readonly
on({ id: GroupAllTemplate[prop1].id, change: "any", ack: false }, function (dp) {
log("Init: Triggered " + dp.id + " new value is " + dp.state.val);
if (prop1 == "power") SetMasterPower(dp.oldState.val, dp.state.val);
});
}
};
if (!await existsObjectAsync(praefix + "." + "all")) { //Gruppenchannel anlegen wenn noch nicht vorhanden
await setObjectAsync(praefix + "." + "all", { type: 'channel', common: { name: "Sammelfunktion um alle Gruppen gleichzeitig zu steuern" }, native: {} });
log("Init: Channel " + praefix + "." + "all" + " created");
};
log("Init: Created " + DpCount + " Datapoints");
onStop(function () { //Bei Scriptende alle Intervalle und Timeouts löschen
clearRampOnIntervals(null);
clearRampOffIntervals(null);
clearBlinkIntervals(null);
clearAutoOffTimeouts(null);
clearInterval(TickerIntervalObj);
}, 10);
return true;
}
async function SetMasterPower(oldVal, NewVal) {
log("Reaching SetMasterPower");
for (let Group in LightGroups) {
log("Switching Group " + LightGroups[Group].description + ", Id:" + praefix + "." + Group + ".power" + " to " + NewVal);
await setStateAsync(praefix + "." + Group + ".power", NewVal, false);
};
}
async function SetLightState() {
log("Reaching Light States anyOn and Masterswitch");
let groupLength = Object.keys(LightGroups).length;
setStateAsync(praefix + ".all.anyOn", (await countGroups() > 0) ? true : false , true);
setStateAsync(praefix + ".all.power", (await countGroups() === groupLength) ? true : false, true);
}
async function countGroups() {
let i = 0;
for (let Group in LightGroups) {
if ((await getStateAsync(praefix + "." + Group + ".power")).val) {
i++;
};
};
return i;
}
async function clearRampOnIntervals(Group) {
// log("Reaching ClearRampOnInterval(Group) Group=" + Group);
if (Group == null) {
for (let x in LightGroups) {
if (typeof RampOnIntervalObject[x] == "object") {
if (logging) log("RampOnInterval for Group=" + x + " deleted.");
await clearInterval(RampOnIntervalObject[x]);
};
};
} else {
if (typeof RampOnIntervalObject[Group] == "object") {
if (logging) log("RampOnInterval for Group=" + Group + " deleted.");
await clearInterval(RampOnIntervalObject[Group]);
};
};
}
function clearRampOffIntervals(Group) {
// log("Reaching ClearRampOffInterval(Group) Group=" + Group);
if (Group == null) {
for (let x in LightGroups) {
if (typeof RampOffIntervalObject[x] == "object") {
if (logging) log("RampOffInterval for Group=" + x + " deleted.");
clearInterval(RampOffIntervalObject[x]);
};
};
} else {
if (typeof RampOffIntervalObject[Group] == "object") {
if (logging) log("RampOffInterval for Group=" + Group + " deleted.");
clearInterval(RampOffIntervalObject[Group]);
};
};
}
async function clearAutoOffTimeouts(Group) {
// log("Reaching clearAutoOffTimeout(Group) Group=" + Group);
if (Group == null) {
for (let x in LightGroups) {
if (typeof AutoOffTimeoutObject[x] == "object") {
if (logging) log("clearAutoOffTimeout: AutoOffTimeout for Group=" + x + " deleted.");
await clearInterval(AutoOffTimeoutObject[x]);
};
};
} else {
if (typeof AutoOffTimeoutObject[Group] == "object") {
if (logging) log("clearAutoOffTimeout: Timeout for Group=" + Group + " deleted.");
await clearInterval(AutoOffTimeoutObject[Group]);
};
};
}
function clearBlinkIntervals(Group) {
if (Group == null) {
for (let x in LightGroups) {
if (typeof BlinkIntervalObj[x] == "object") {
if (logging) log("BlinkInterval for Group=" + x + " deleted.");
clearInterval(BlinkIntervalObj[x]);
};
};
} else {
if (typeof BlinkIntervalObj[Group] == "object") {
if (logging) log("BlinkInterval for Group=" + Group + " deleted.");
clearInterval(BlinkIntervalObj[Group]);
};
};
}
/* ------------------------- FUNCTIONS FÜR LUXSENSOR HANDLNG --------------------------------- */
function ChangeLuxSensorTrigger(Group, prop, oldsensor, newsensor) { //Used by controller
log("Changed LuxSensor detected, from: " + oldsensor + " to: " + newsensor + " deleting old subscription and create new one. ");
if (oldsensor != "") unsubscribe(oldsensor);
if (newsensor != "") {
on({ id: newsensor, change: "ne" }, function (dp) { //Trigger für Luxsensor erstellen
if (logging) log("Triggered " + LightGroups[Group][prop] + " new value is " + dp.state.val)
LightGroups[Group].actualLux = dp.state.val;
Controller(Group, "actualLux", dp.oldState.val, dp.state.val);
});
};
}
async function DoAllTheLuxSensorThings(Group, prop) { //Used by init
if (logging) log("Reaching DoAllTheLuxSensorThings for Group" + Group + " prop=" + LightGroups[Group][prop])
if (prop == "luxSensorOid" && LightGroups[Group][prop] != "") {
if (logging) log("LightGroups[" + Group + "].luxSensorOid=" + LightGroups[Group][prop])
if (LightGroups[Group][prop] == LuxSensor) { //Wenn StandardLuxsensor für Gruppe verwendet Wert nicht wiederholt lesen sondern Globalen Luxwert verwenden
LightGroups[Group].actualLux = ActualGenericLux;
if (logging) log("Group " + Group + " using generic luxsensor, value is: " + LightGroups[Group].actualLux);
} else {
LightGroups[Group].actualLux = (await getStateAsync(LightGroups[Group][prop])).val; //Individuellen Gruppen luxwert lesen
if (logging) log("Group " + Group + " using individual luxsensor " + LightGroups[Group][prop] + ", value is: " + LightGroups[Group].actualLux);
on({ id: LightGroups[Group][prop], change: "ne" }, function (dp) { //Trigger für individuelle Luxsensoren erstellen
log("Triggered individual luxsensor " + LightGroups[Group][prop] + " new value is " + dp.state.val)
LightGroups[Group].actualLux = dp.state.val;
// log("LightGroups[" + Group + "].actualLux = " + LightGroups[Group].actualLux);
Controller(Group, "actualLux", dp.oldState.val, dp.state.val);
});
};
} else {
log("No Luxsensor for " + Group + " defined, skip handling");
};
}
function RefreshGenericLuxValues() { // Used by Init - refreshing ALL Groups using the generic Luxsensor with new value
if (logging) log("Reaching RefreshGenericLuxValues ")
for (let Group in LightGroups) {
if (LightGroups[Group].luxSensorOid != "" && LightGroups[Group].luxSensorOid == LuxSensor) {// Prüfen ob generischer Luxsensor vorhanden.
// if (logging) log("Triggered Generic LuxSensor " + LightGroups[Group].luxSensorOid + " new value for " + Group + " is " + ActualGenericLux)
LightGroups[Group].actualLux = ActualGenericLux;
Controller(Group, "actualLux", LightGroups[Group].actualLux, ActualGenericLux);
};
};
}
/* ------------------------- FUNCTIONS FÜR (MOTION)SENSOR HANDLNG --------------------------------- */
async function DoAllTheSensorThings(Group) {
if (logging) log("Reaching DoAllTheSensorThings");
for (let sensorCount in LightGroups[Group].sensors) {
if ((await getStateAsync(LightGroups[Group].sensors[sensorCount].id)).val == LightGroups[Group].sensors[sensorCount].motionVal) {//Inhalt lesen und neues Property anlegen und füllen
LightGroups[Group].sensors[sensorCount].isMotion = true;
} else {
LightGroups[Group].sensors[sensorCount].isMotion = false;
};
//Trigger für Dp Inhalt erzeugen wenn nicht leer
if (LightGroups[Group].sensors[sensorCount].id != "") {
on({ id: LightGroups[Group].sensors[sensorCount].id, change: "ne", ack: true }, function (dp) { //Trigger erstellen für eingetragenen Sensor
if (logging) log("Triggered linked Sensor " + dp.id + " new value is " + dp.state.val);
if (dp.state.val == LightGroups[Group].sensors[sensorCount].motionVal) {//Inhalt lesen und neues Property anlegen und füllen
LightGroups[Group].sensors[sensorCount].isMotion = true;
} else {
LightGroups[Group].sensors[sensorCount].isMotion = false;
};
SummarizeSensors(Group);
});
} else {
log(Group + "." + LightGroups[Group].sensors[sensorCount].id + " has no data, skipping trigger creation");
};
};
}
function SummarizeSensors(Group) {
if (logging) log("Reaching SummarizeSensors, Group=" + Group);
let Motionstate = false;
for (let sensorCount in LightGroups[Group].sensors) {
if (LightGroups[Group].sensors[sensorCount].isMotion) {
if (logging) log("Gruppe=" + Group + " Sensor " + sensorCount + " with target " + LightGroups[Group].sensors[sensorCount].id + " has value " + LightGroups[Group].sensors[sensorCount].isMotion);
Motionstate = true;
};
};
if (logging) log("Summarized IsMotion for Group " + Group + " = " + Motionstate);
if (LightGroups[Group].isMotion != Motionstate) {
setState(praefix + "." + Group + ".isMotion", Motionstate, true)
Controller(Group, "isMotion", LightGroups[Group].isMotion, Motionstate);
};
}
/* ------------------------- FUNCTIONS FÜR LICHT HANDLNG --------------------------------- */
async function SetBrightness(Group, Brightness) {
if (logging) log("Reaching SetBrightness, Group=" + Group + " Brightness=" + Brightness);
if (Brightness <= 2) Brightness = 2;
if (Brightness > 100) Brightness = 100;
if (LightGroups[Group].power) {
await setDeviceBri(Group, Brightness);
};
setState(praefix + "." + Group + "." + "bri", Brightness, true); //Ausführung mit Ack bestätigen
return true;
}
function AdaptiveBri(Group) {
if (logging) log("Reaching AdaptiveBri for Group " + Group + " actual Lux=" + LightGroups[Group].actualLux + " generic lux=" + ActualGenericLux);
let TempBri = 0;
if (LightGroups[Group].adaptiveBri) {
if (LightGroups[Group].actualLux == 0) {
TempBri = minBri;
} else if (LightGroups[Group].actualLux >= 10000) {
TempBri = 100;
} else if (LightGroups[Group].actualLux > 0 && LightGroups[Group].actualLux < 10000) {
TempBri = LightGroups[Group].actualLux / 100;
if (TempBri < minBri) TempBri = minBri;
};
// await SetBrightness(Group, Math.round(TempBri));
};
return Math.round(TempBri);
}
async function setDeviceBri(Group, Brightness) { //Subfunktion für setBri, setzt direkt die Helligkeit der Devices
for (let Light in LightGroups[Group].lights) { //Alle Lampen der Gruppe durchgehen
if (LightGroups[Group].lights[Light].bri.oid != "") { //Prüfen ob Eintrag für Helligkeit vorhanden
await setStateAsync(LightGroups[Group].lights[Light].bri.oid, Math.round(Brightness / 100 * LightGroups[Group].lights[Light].bri.defaultVal), false);
};
};
}
async function SetCt(Group, ct = LightGroups[Group].ct) {
if (logging) log("Reaching SetCt, Group=" + Group + " Ct=" + LightGroups[Group].ct);
let TempCt = 0;
if (LightGroups[Group].power) {
for (let Light in LightGroups[Group].lights) { //Alle Lampen der Gruppe durchgehen
if (LightGroups[Group].lights[Light].ct.oid != "") { //Prüfen ob Eintrag für Farbtemperatur vorhanden
if (LightGroups[Group].lights[Light].ct.minVal < 1000) {//Prüfen ob Konvertierung nötig (Es wird davon ausgegangen dass Werte unter 1000 keine Kelvin sind)
TempCt = ConvertKelvin(LightGroups[Group].lights[Light].ct.minVal, LightGroups[Group].lights[Light].ct.maxVal, ct);
} else { //Keine Konvertierung nötig
TempCt = ct;
};
await setStateAsync(LightGroups[Group].lights[Light].ct.oid, TempCt, false);
};
};
};
setState(praefix + "." + Group + ".ct", LightGroups[Group].ct, true) //Ack mit true bestätigen nach abarbeitung
return true;
}
function ConvertKelvin(MinVal, MaxVal, Ct) {
if (logging) log("Reaching ConvertKelvin");
let KelvinRange = maxCt - minCt; //Wertebereich Kelvin
let ValRange = MaxVal - MinVal; //Wertebereich Val
// log("KelvinRange=" + KelvinRange + " ValRange=" + ValRange + " Ct=" + Ct)
let KelvinProz = (Ct - minCt) / (KelvinRange / 100) //Prozent des aktuellen Kelvinwertes
let ValProz = ValRange / 100 //1% des Value Wertebereichs
let ConvertedCt = Math.round(ValProz * KelvinProz + MinVal)
// log("ConvertedCt=" + ConvertedCt + " KelvinProz=" + KelvinProz + " ValProz=" + ValProz)
return ConvertedCt;
}
function AdaptiveCt() {
let ActualTime = new Date().getTime();
let CtRange = maxCt - minCt; //Regelbereich
let adaptiveCtLinear = 0;
let adaptiveCtSolar = 0;
let adaptiveCtSolarInterpolated = 0;
let adaptiveCtTimed = 0;
let sunset = getAstroDate("sunset").getTime(); //Sonnenuntergang
let sunrise = getAstroDate("sunrise").getTime(); //Sonnenaufgang
let solarNoon = getAstroDate("solarNoon").getTime(); //Höchster Sonnenstand (Mittag)
let morningTime = 0;
let sunMinutesDay = (sunset - sunrise) / 1000 / 60;
let RangePerMinute = CtRange / sunMinutesDay;
let now = new Date();
let sunpos = suncalc.getPosition(now, lat, long);
let sunposNoon = suncalc.getPosition(solarNoon, lat, long);
if (compareTime(sunrise, solarNoon, 'between')) {
// log("Aufsteigend")
adaptiveCtLinear = Math.round(minCt + ((ActualTime - sunrise) / 1000 / 60) * RangePerMinute * 2); // Linear = ansteigende Rampe von Sonnenaufgang bis Sonnenmittag, danach abfallend bis Sonnenuntergang
} else if (compareTime(solarNoon, sunset, 'between')) {
// log("Absteigend")
adaptiveCtLinear = Math.round(maxCt - ((ActualTime - solarNoon) / 1000 / 60) * RangePerMinute * 2);
};
if (compareTime(sunrise, sunset, 'between')) {
adaptiveCtSolar = Math.round(minCt + sunMinutesDay * RangePerMinute * sunpos.altitude); // Solar = Sinusrampe entsprechend direkter Elevation, max Ct differiert nach Jahreszeiten
adaptiveCtSolarInterpolated = Math.round(minCt + sunMinutesDay * RangePerMinute * sunpos.altitude * (1 / sunposNoon.altitude));// SolarInterpolated = Wie Solar, jedoch wird der Wert so hochgerechnet dass immer zum Sonnenmittag maxCt gesetzt wird, unabhängig der Jahreszeit
};
if (logging) log("adaptiveCtLinear=" + adaptiveCtLinear + " adaptiveCtSolar=" + adaptiveCtSolar + " adaptiveCtSolarInterpolated=" + adaptiveCtSolarInterpolated + " adaptiveCtTimed=" + adaptiveCtTimed);
for (let Group in LightGroups) {
switch (LightGroups[Group].adaptiveCtMode) {
case "linear":
if (LightGroups[Group].adaptiveCt && LightGroups[Group].ct != adaptiveCtLinear) {
setState(praefix + "." + Group + ".ct", adaptiveCtLinear, false) //Ack false um SetCt zu triggern
};
break;
case "solar":
if (LightGroups[Group].adaptiveCt && LightGroups[Group].ct != adaptiveCtSolar) {
setState(praefix + "." + Group + ".ct", adaptiveCtSolar, false) //Ack false um SetCt zu triggern
};
break;
case "solarInterpolated":
if (LightGroups[Group].adaptiveCt && LightGroups[Group].ct != adaptiveCtSolarInterpolated) {
setState(praefix + "." + Group + ".ct", adaptiveCtSolarInterpolated, false) //Ack false um SetCt zu triggern
};
break;
case "timed":
if (LightGroups[Group].adaptiveCt && LightGroups[Group].ct != adaptiveCtTimed) {
morningTime = getDateObject(LightGroups[Group].adaptiveCtTime).getTime(); // Aufstehzeit
sunMinutesDay = (sunset - morningTime) / 1000 / 60;
RangePerMinute = CtRange / sunMinutesDay;
if (compareTime(morningTime, sunset, 'between')) {
// log("Absteigend von Morgens bis Abends")
adaptiveCtTimed = Math.round(maxCt - ((ActualTime - morningTime) / 1000 / 60) * RangePerMinute);
};
setState(praefix + "." + Group + ".ct", adaptiveCtTimed, false) //Ack false um SetCt zu triggern
};
break;
};
};
}
async function SetWhiteSubstituteColor(Group) {
if (logging) log("Reaching WhiteSubstituteColor for Group" + Group + " = " + LightGroups[Group].description + " LightGroups[Group].power=" + LightGroups[Group].power + " LightGroups[Group].color =" + LightGroups[Group].color)
if (LightGroups[Group].power && LightGroups[Group].color.toUpperCase() == "#FFFFFF") { //Nur ausführen bei anschalten und Farbe weiß
// log("anschalten und Farbe weiß")
if (LightGroups[Group].ct < ((maxCt - minCt) / 4 + minCt) || LightGroups[Group].ct > ((maxCt - minCt) / 4 * 3 + minCt)) { //Ct Regelbereich vierteln, erstes viertel ist ww, 2tes und drittes wieder kw, das letzte ww
// log("Warmweiss - ct=" + LightGroups[Group].ct + " (maxCt - minCt) / 4 + minCt=" + ((maxCt - minCt) / 4 + minCt) + " (maxCt - minCt) / 4 * 3 + minCt=" + ((maxCt - minCt) / 4 * 3 + minCt))
for (let Light in LightGroups[Group].lights) {
if (LightGroups[Group].lights[Light].ct.oid == "" && LightGroups[Group].lights[Light].color.oid != "" && LightGroups[Group].lights[Light].color.warmWhiteColor != "" && LightGroups[Group].lights[Light].color.dayLightColor != "") {
await setStateAsync(LightGroups[Group].lights[Light].color.oid, LightGroups[Group].lights[Light].color.warmWhiteColor, false);
};
};
} else { //Hier kw
// log("Kaltweiss")
for (let Light in LightGroups[Group].lights) {
if (LightGroups[Group].lights[Light].ct.oid == "" && LightGroups[Group].lights[Light].color.oid != "" && LightGroups[Group].lights[Light].color.warmWhiteColor != "" && LightGroups[Group].lights[Light].color.dayLightColor != "") {
await setStateAsync(LightGroups[Group].lights[Light].color.oid, LightGroups[Group].lights[Light].color.dayLightColor, false);
};
};
};
};
}
async function SetColorMode(Group) {
log("Reaching SetColorMode for Group " + Group)
if (LightGroups[Group].power) {
for (let Light in LightGroups[Group].lights) { //Alle Lampen der Gruppe durchgehen
if (LightGroups[Group].lights[Light].modeswitch.oid != "") { //Prüfen ob Datenpunkt für Colormode vorhanden
if (LightGroups[Group].color.toUpperCase() == "#FFFFFF") { //bei Farbe weiss
await setStateAsync(LightGroups[Group].lights[Light].modeswitch.oid, LightGroups[Group].lights[Light].modeswitch.whiteModeVal, false);
log("Device=" + LightGroups[Group].lights[Light].modeswitch.oid + " Val=" + LightGroups[Group].lights[Light].modeswitch.whiteModeVal)
} else { //Bei allen anderen Farben
await setStateAsync(LightGroups[Group].lights[Light].modeswitch.oid, LightGroups[Group].lights[Light].modeswitch.colorModeVal, false);
};
};
};
};
return true;
}
async function SetColor(Group, Color) {
log("Reaching SetColor for Group " + Group + " power=" + LightGroups[Group].power + " Color=" + Color);
let rgbTemp = ConvertHexToRgb(Color);
if (LightGroups[Group].power) {
for (let Light in LightGroups[Group].lights) { //Alle Lampen der Gruppe durchgehen
if (LightGroups[Group].lights[Light].color.oid != "") { //Prüfen ob Datenpunkt für Color vorhanden
// log("SetColor: LightGroups[Group].lights[Light].color.type=" + LightGroups[Group].lights[Light].color.type)
switch (LightGroups[Group].lights[Light].color.type) {
case "hex": //Keine Konvertierung nötig
await setStateAsync(LightGroups[Group].lights[Light].color.oid, Color, false);
break;
case "rgb":
await setStateAsync(LightGroups[Group].lights[Light].color.oid, rgbTemp, false);
break;
case "xy":
await setStateAsync(LightGroups[Group].lights[Light].color.oid, ConvertRgbToXy(rgbTemp), false);
break;
case "wled":
//await setStateAsync(LightGroups[Group].lights[Light].modeswitch.oid, 99, false)
await SetWLED(LightGroups[Group].lights[Light].color.oid, Color);
break;
default:
log("SetColor: Unknown colortype, please specify", "warn");
};
};
};
setState(praefix + "." + Group + ".color", LightGroups[Group].color, true) //Ack mit true bestätigen nach abarbeitung
return true;
} else {
return false;
};
}
async function SetWLED(id, Color) {
let cacheSelectorWledPS = $("channel[state.id=" + id + "*.ps]");
let cacheSelectorWledFX = $("channel[state.id=" + id + ".*.0.fx]");
let cacheSelectorWledRGB = $("channel[state.id=" + id + ".*.0.col.0_HEX]");
if (logging) log(cacheSelectorWledRGB.length + " Segmente gefunden");
cacheSelectorWledPS.each(async function (id, i) {
await setStateAsync(id, 99, false);
if (logging) log("Preset: Setze " + id + " auf 99");
});
/*cacheSelectorWledFX.each(async function (id, i) {
await setStateAsync(id, 0, false);
if (logging) log("Effect: Setze " + id + " auf 0");
});
*/
cacheSelectorWledRGB.each(async function (id, i) {
await setStateAsync(id, Color, false);
if (logging) log("Color: Setze " + id + " auf " + Color);
});
}
/* ------------------------- FUNCTIONS FOR Switching On/Off --------------------------------- */
async function SimpleGroupPowerOnOff(Group, OnOff) {
if (OnOff) { //Anschalten
log("SimpleGroupPowerOnOff: Normales anschalten ohne Ramping für " + LightGroups[Group].description);
for (let Light in LightGroups[Group].lights) {
if ((await getStateAsync(LightGroups[Group].lights[Light].power.oid)).val == LightGroups[Group].lights[Light].power.offVal) { //Prüfen ob Device schon an
await setStateAsync(LightGroups[Group].lights[Light].power.oid, LightGroups[Group].lights[Light].power.onVal);
// log("SimpleGroupPowerOnOff: Switching " + Light + " " + LightGroups[Group].lights[Light].power.oid + " to: " + OnOff);
};
};
} else { //Ausschalten
log("SimpleGroupPowerOnOff: Normales ausschalten ohne Ramping für " + LightGroups[Group].description);
if (typeof AutoOffTimeoutObject[Group] == "object") clearTimeout(AutoOffTimeoutObject[Group]);
for (let Light in LightGroups[Group].lights) {
if ((await getStateAsync(LightGroups[Group].lights[Light].power.oid)).val == LightGroups[Group].lights[Light].power.onVal) {
await setStateAsync(LightGroups[Group].lights[Light].power.oid, LightGroups[Group].lights[Light].power.offVal);
// log("SimpleGroupPowerOnOff: Switching " + Light + " " + LightGroups[Group].lights[Light].power.oid + " to: " + OnOff);
};
};
};
setState(praefix + "." + Group + ".power", OnOff, true); // Power on mit ack bestätigen, bzw. bei Auto Funktionen nach Ausführung den DP setzen
LightGroups[Group].power = OnOff;
return true;
}
async function GroupPowerOnOff(Group, OnOff) {
log("Reaching GroupPowerOnOff for Group " + Group + " (" + LightGroups[Group].description + "), OnOff=" + OnOff + " rampOn=" + LightGroups[Group].rampOn.enabled + " - " + JSON.stringify(LightGroups[Group].rampOn) + " rampOff=" + LightGroups[Group].rampOff.enabled + " - " + JSON.stringify(LightGroups[Group].rampOff));
let LoopCount = 0;
//Normales schalten ohne Ramping
if (OnOff && !LightGroups[Group].rampOn.enabled) { //Anschalten
// log("GroupPowerOnOff: Normales anschalten ohne Ramping für " + LightGroups[Group].description);
await SimpleGroupPowerOnOff(Group, OnOff);
if (LightGroups[Group].autoOffTimed.enabled) { //Wenn Zeitabschaltung aktiv und Anschaltung, AutoOff aktivieren
AutoOffTimed(Group); //
};
} else if (!OnOff && !LightGroups[Group].rampOff.enabled) { //Ausschalten
// log("GroupPowerOnOff: Normales ausschalten ohne Ramping für " + LightGroups[Group].description);
if (LightGroups[Group].rampOn.enabled) {//Vor dem ausschalten Helligkeit auf 2 (0+1 wird bei manchchen Devices als aus gewertet) um bei rampon nicht mit voller Pulle zu starten
await setDeviceBri(Group, 2);
};
await SimpleGroupPowerOnOff(Group, OnOff);
};
// Anschalten mit ramping
if (OnOff && LightGroups[Group].rampOn.enabled && LightGroups[Group].rampOn.switchOutletsLast) { //Anschalten mit Ramping und einfache Lampen/Steckdosen zuletzt
log("Anschalten mit Ramping und einfache Lampen zuletzt für " + LightGroups[Group].description);
for (let Light in LightGroups[Group].lights) { //Alles anschalten wo
if (LightGroups[Group].lights[Light].bri.oid != "") { //bri nicht leer
await setStateAsync(LightGroups[Group].lights[Light].power.oid, LightGroups[Group].lights[Light].power.onVal);
// log("GroupPowerOnOff: Ca Switching " + Light + " " + LightGroups[Group].lights[Light].power.oid + " to: " + OnOff + " now setting brightness");
};
};
if (typeof RampOnIntervalObject[Group] == "object") clearInterval(RampOnIntervalObject[Group]);
RampOnIntervalObject[Group] = setInterval(function () { // Interval starten
LoopCount++;
// SetBrightness(Group, Math.round(RampSteps * LoopCount * (LightGroups[Group].bri / 100)));
setDeviceBri(Group, Math.round(RampSteps * LoopCount * (LightGroups[Group].bri / 100)))
if (LoopCount >= RampSteps) { //Interval stoppen und einfache Lampen schalten
for (let Light in LightGroups[Group].lights) { //Alles anschalten wo
if (LightGroups[Group].lights[Light].bri.oid == "") { //bri leer
setStateAsync(LightGroups[Group].lights[Light].power.oid, LightGroups[Group].lights[Light].power.onVal);
// log("GroupPowerOnOff: Cb Switching " + Light + " " + LightGroups[Group].lights[Light].power.oid + " to: " + OnOff);
};
};
if (LightGroups[Group].autoOffTimed.enabled) { //Wenn Zeitabschaltung aktiv und Anschaltung, AutoOff aktivieren
AutoOffTimed(Group); //
};
if (typeof RampOnIntervalObject[Group] == "object") clearInterval(RampOnIntervalObject[Group]);
};
}, Math.round(LightGroups[Group].rampOn.time / RampSteps) * 1000); //
}
else if (OnOff && LightGroups[Group].rampOn.enabled && !LightGroups[Group].rampOn.switchOutletsLast) { //Anschalten mit Ramping und einfache Lampen zuerst
log("GroupPowerOnOff: Anschalten mit Ramping und einfache Lampen zuerst für " + LightGroups[Group].description);
for (let Light in LightGroups[Group].lights) { //Alles anschalten
await setStateAsync(LightGroups[Group].lights[Light].power.oid, LightGroups[Group].lights[Light].power.onVal);
// log("GroupPowerOnOff: D Switching " + Light + " " + LightGroups[Group].lights[Light].power.oid + " to: " + OnOff + " now setting brightness");
};
if (typeof RampOnIntervalObject[Group] == "object") clearInterval(RampOnIntervalObject[Group]);
RampOnIntervalObject[Group] = setInterval(function () { // Interval starten
//SetBrightness(Group, Math.round(RampSteps * LoopCount * (LightGroups[Group].bri / 100)));
setDeviceBri(Group, Math.round(RampSteps * LoopCount * (LightGroups[Group].bri / 100)))
LoopCount++;
// log("Loopcount=" + LoopCount + " - " + " Rampsteps=" + RampSteps + " RampOnTime= " + LightGroups[Group].rampOn.time)
if (LoopCount >= RampSteps) {
if (LightGroups[Group].autoOffTimed.enabled) { //Wenn Zeitabschaltung aktiv und Anschaltung, AutoOff aktivieren
AutoOffTimed(Group); //
};
if (typeof RampOnIntervalObject[Group] == "object") clearInterval(RampOnIntervalObject[Group]);
}
}, Math.round(LightGroups[Group].rampOn.time / RampSteps) * 1000); //
}
//Ausschalten mit Ramping
else if (!OnOff && LightGroups[Group].rampOff.enabled && LightGroups[Group].rampOff.switchOutletsLast) { ////Ausschalten mit Ramping und einfache Lampen zuletzt
log("GroupPowerOnOff: Ausschalten mit Ramping und einfache Lampen zuletzt für " + LightGroups[Group].description);
if (typeof RampOffIntervalObject[Group] == "object") clearInterval(RampOffIntervalObject[Group]);
RampOffIntervalObject[Group] = setInterval(function () { // Interval starten
// SetBrightness(Group, LightGroups[Group].bri - LightGroups[Group].bri / RampSteps - Math.round(RampSteps * LoopCount * (LightGroups[Group].bri / 100)));
setDeviceBri(Group, LightGroups[Group].bri - LightGroups[Group].bri / RampSteps - Math.round(RampSteps * LoopCount * (LightGroups[Group].bri / 100)));
LoopCount++;
// log("Loopcount=" + LoopCount + " - " + " Rampsteps=" + RampSteps + " RampOffTime= " + LightGroups[Group].rampOff.time)
if (LoopCount >= RampSteps) {
if (typeof RampOffIntervalObject[Group] == "object") clearInterval(RampOffIntervalObject[Group]);
for (let Light in LightGroups[Group].lights) {
if (LightGroups[Group].lights[Light].bri.oid == "") { //prüfen ob Helligkeitsdatenpunkt vorhanden
setStateAsync(LightGroups[Group].lights[Light].power.oid, LightGroups[Group].lights[Light].power.offVal); //Einfache Lampen ausschalten, dann
// log("GroupPowerOnOff: F Switching " + Light + " " + LightGroups[Group].lights[Light].power.oid + " to: " + OnOff);
};
};
};
}, Math.round(LightGroups[Group].rampOff.time / RampSteps) * 1000); //
}
else if (!OnOff && LightGroups[Group].rampOff.enabled && !LightGroups[Group].rampOff.switchOutletsLast) { ////Ausschalten mit Ramping und einfache Lampen zuerst
log("GroupPowerOnOff: Ausschalten mit Ramping und einfache Lampen zuerst für " + LightGroups[Group].description);
for (let Light in LightGroups[Group].lights) {
if (LightGroups[Group].lights[Light].bri.oid == "") { //prüfen ob Helligkeitsdatenpunkt vorhanden, wenn nein
await setStateAsync(LightGroups[Group].lights[Light].power.oid, LightGroups[Group].lights[Light].power.offVal); //Einfache Lampen ausschalten, dann
// log("GroupPowerOnOff: F Switching " + Light + " " + LightGroups[Group].lights[Light].power.oid + " to: " + OnOff);
};
};
if (typeof RampOffIntervalObject[Group] == "object") clearInterval(RampOffIntervalObject[Group]);
RampOffIntervalObject[Group] = setInterval(function () { // Interval starten
LightGroups[Group].power = true; //Power intern wieder auf true, um Bri auszuführen wo auf power geprüft wird
setDeviceBri(Group, LightGroups[Group].bri - LightGroups[Group].bri / RampSteps - Math.round(RampSteps * LoopCount * (LightGroups[Group].bri / 100)));
LoopCount++;
// log("GroupPowerOnOff: Loopcount=" + LoopCount + " - " + " Rampsteps=" + RampSteps + " RampOffTime= " + LightGroups[Group].rampOff.time);
if (LoopCount >= RampSteps) {
LightGroups[Group].power = false;
DeviceSwitch(Group, OnOff);
if (typeof RampOffIntervalObject[Group] == "object") clearInterval(RampOffIntervalObject[Group]);
};
}, Math.round(LightGroups[Group].rampOff.time / RampSteps) * 1000); //
};
setState(praefix + "." + Group + ".power", OnOff, true); // Power on mit ack bestätigen, bzw. bei Auto Funktionen nach Ausführung den DP setzen
LightGroups[Group].power = OnOff;
return true;
}
async function DeviceSwitch(Group, OnOff) { //Ausgelagert von GroupOnOff da im Interval kein await möglich
for (let Light in LightGroups[Group].lights) {
if (LightGroups[Group].lights[Light].bri.oid != "") { //prüfen ob Helligkeitsdatenpunkt vorhanden, wenn ja
await setStateAsync(LightGroups[Group].lights[Light].power.oid, LightGroups[Group].lights[Light].power.offVal); //Lampen schalten
log("DeviceSwitch: Switching " + Light + " " + LightGroups[Group].lights[Light].power.oid + " to: " + OnOff);
};
};
}
async function GroupPowerCleaningLightOnOff(Group, OnOff) {
if (logging) log("Reaching GroupPowerCleaningLightOnOff")
if (OnOff) { //Anschalten
for (let Light in LightGroups[Group].lights) {