iobroker.sprinklecontrol 0.2.13 → 0.2.14
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/{Lizenz → LICENSE} +21 -21
- package/README.md +60 -110
- package/admin/i18n/de/translations.json +134 -0
- package/admin/i18n/en/translations.json +134 -0
- package/admin/i18n/es/translations.json +134 -0
- package/admin/i18n/fr/translations.json +134 -0
- package/admin/i18n/it/translations.json +134 -0
- package/admin/i18n/nl/translations.json +134 -0
- package/admin/i18n/pl/translations.json +134 -0
- package/admin/i18n/pt/translations.json +134 -0
- package/admin/i18n/ru/translations.json +134 -0
- package/admin/i18n/uk/translations.json +134 -0
- package/admin/i18n/zh-cn/translations.json +134 -0
- package/admin/index_m.html +904 -907
- package/admin/index_m.js +779 -779
- package/admin/style.css +453 -158
- package/admin/words.js +143 -136
- package/io-package.json +256 -189
- package/lib/adapter-config.d.ts +19 -16
- package/lib/evaporation.js +443 -412
- package/lib/myConfig.js +373 -359
- package/lib/sendMessageText.js +162 -199
- package/lib/tools.js +148 -125
- package/lib/valveControl.js +918 -887
- package/main.js +2041 -1828
- package/package.json +50 -32
- package/.gitattributes +0 -2
- package/admin/admin.d.ts +0 -1
- package/docs/de/img/E-Mail.jpg +0 -0
- package/docs/de/img/Extraeinstellungen.jpg +0 -0
- package/docs/de/img/Pumpeneinstellung.jpg +0 -0
- package/docs/de/img/Pushover.jpg +0 -0
- package/docs/de/img/Select_ID.jpg +0 -0
- package/docs/de/img/Telegram.jpg +0 -0
- package/docs/de/img/Ventil-Haupteinstellung.jpg +0 -0
- package/docs/de/img/Ventil-Pumpeneinstellung.jpg +0 -0
- package/docs/de/img/WhatsApp.jpg +0 -0
- package/docs/de/img/Zeiteinstellung.jpg +0 -0
- package/docs/de/img/addTime.jpg +0 -0
- package/docs/de/img/analog.jpg +0 -0
- package/docs/de/img/ber-verdunstung.jpg +0 -0
- package/docs/de/img/bew-einstellung.jpg +0 -0
- package/docs/de/img/bew-feste-tage.jpg +0 -0
- package/docs/de/img/bistabil.jpg +0 -0
- package/docs/de/img/bodenf-analog.jpg +0 -0
- package/docs/de/img/bodenf-bistabil.jpg +0 -0
- package/docs/de/img/calculation.jpg +0 -0
- package/docs/de/img/control.jpg +0 -0
- package/docs/de/img/einschaltpunkt-giessen.jpg +0 -0
- package/docs/de/img/festeTage.jpg +0 -0
- package/docs/de/img/main.jpg +0 -0
- package/docs/de/img/main_tab.jpg +0 -0
- package/docs/de/img/max-bodenfeuchtigkeit.jpg +0 -0
- package/docs/de/img/schaltverhalten.jpg +0 -0
- package/docs/de/img/sprinklecontrol.png +0 -0
- package/docs/de/img/verdunstDiagra.jpg +0 -0
- package/docs/de/img/verdunstung.jpg +0 -0
- package/docs/de/img/zus-bew-einstellung.jpg +0 -0
- package/docs/de/sprinklecontrol.md +0 -656
- package/docs/en/img/schaltverhalten.jpg +0 -0
- package/docs/en/img/screenshot1.jpg +0 -0
- package/docs/en/img/screenshot2.jpg +0 -0
- package/docs/en/img/screenshot3.jpg +0 -0
- package/docs/en/img/screenshot4.jpg +0 -0
- package/docs/en/img/screenshot5.jpg +0 -0
- package/docs/en/img/screenshot6.jpg +0 -0
- package/docs/en/img/screenshot7.jpg +0 -0
- package/docs/en/img/screenshot8.jpg +0 -0
- package/docs/en/img/sprinklecontrol.png +0 -0
- package/docs/en/sprinklecontrol.md +0 -230
- package/main.test.js +0 -30
package/main.js
CHANGED
|
@@ -1,1828 +1,2041 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
// Load your modules here, e.g.: => // Laden Sie Ihre Module hier, z.B.
|
|
4
|
-
// const fs = require("fs");
|
|
5
|
-
|
|
6
|
-
const utils = require('@iobroker/adapter-core');
|
|
7
|
-
const schedule = require('node-schedule');
|
|
8
|
-
const SunCalc = require('
|
|
9
|
-
|
|
10
|
-
const sendMessageText = require('./lib/sendMessageText.js'); // sendMessageText
|
|
11
|
-
const valveControl = require('./lib/valveControl.js'); // Steuerung der einzelnen Ventile
|
|
12
|
-
const myConfig = require('./lib/myConfig.js'); // myConfig → Speichern und abrufen von Konfigurationsdaten der Ventile
|
|
13
|
-
const evaporation = require('./lib/evaporation.js');
|
|
14
|
-
const addTime = require('./lib/tools.js').addTime;
|
|
15
|
-
const formatTime = require('./lib/tools.js').formatTime;
|
|
16
|
-
//const trend = require('./lib/tools').trend;
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
let
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
let
|
|
28
|
-
|
|
29
|
-
let
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
let
|
|
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
|
-
if (
|
|
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
|
-
if (
|
|
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
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
}
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1083
|
-
|
|
1084
|
-
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
}
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
}
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
}
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
'
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
}
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
objMetConSM = {
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
|
|
1223
|
-
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
|
|
1269
|
-
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
|
|
1283
|
-
|
|
1284
|
-
|
|
1285
|
-
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
|
|
1298
|
-
|
|
1299
|
-
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
|
|
1312
|
-
|
|
1313
|
-
|
|
1314
|
-
|
|
1315
|
-
}
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
'
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
}
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1374
|
-
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1404
|
-
|
|
1405
|
-
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
'
|
|
1415
|
-
'
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1424
|
-
|
|
1425
|
-
|
|
1426
|
-
|
|
1427
|
-
'
|
|
1428
|
-
|
|
1429
|
-
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
'
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
'
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
|
|
1491
|
-
|
|
1492
|
-
|
|
1493
|
-
|
|
1494
|
-
|
|
1495
|
-
|
|
1496
|
-
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
|
|
1523
|
-
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
}
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
}
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
}
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Load your modules here, e.g.: => // Laden Sie Ihre Module hier, z.B.
|
|
4
|
+
// const fs = require("fs");
|
|
5
|
+
|
|
6
|
+
const utils = require('@iobroker/adapter-core');
|
|
7
|
+
const schedule = require('node-schedule');
|
|
8
|
+
const SunCalc = require('suncalc');
|
|
9
|
+
|
|
10
|
+
const sendMessageText = require('./lib/sendMessageText.js'); // sendMessageText
|
|
11
|
+
const valveControl = require('./lib/valveControl.js'); // Steuerung der einzelnen Ventile
|
|
12
|
+
const myConfig = require('./lib/myConfig.js'); // myConfig → Speichern und abrufen von Konfigurationsdaten der Ventile
|
|
13
|
+
const evaporation = require('./lib/evaporation.js');
|
|
14
|
+
const addTime = require('./lib/tools.js').addTime;
|
|
15
|
+
const formatTime = require('./lib/tools.js').formatTime;
|
|
16
|
+
//const trend = require('./lib/tools').trend;
|
|
17
|
+
|
|
18
|
+
let adapter;
|
|
19
|
+
const adapterName = require('./package.json').name.split('.').pop();
|
|
20
|
+
|
|
21
|
+
let publicHolidayStr = false; // Feiertag heute?
|
|
22
|
+
let publicHolidayTomorrowStr = false; // Feiertag morgen?
|
|
23
|
+
let weatherForecastTodayPfadStr = ''; // Pfad zur Regenvorhersage in mm
|
|
24
|
+
let weatherForecastTodayNum = 0; // heutige Regenvorhersage in mm
|
|
25
|
+
let weatherForecastTomorrowNum = 0; // morgige Regenvorhersage in mm
|
|
26
|
+
let addStartTimeSwitch = false; // Externer Schalter für Zusatzbewässerung
|
|
27
|
+
let startTimeStr = ''; // 06:00
|
|
28
|
+
let sunriseStr = '';
|
|
29
|
+
let sunsetStr = '';
|
|
30
|
+
let goldenHourEnd = '';
|
|
31
|
+
let holidayStr = false; // switch => sprinklecontrol.*.control.Holiday | (Holiday == true) => Wochenendprogramm
|
|
32
|
+
let autoOnOffStr = true;
|
|
33
|
+
let kwStr = ''; // akt. KW der Woche
|
|
34
|
+
let timer, timerSleep;
|
|
35
|
+
let today = 0; // heutige Tag 0:So;1:Mo...6:Sa
|
|
36
|
+
/* memo */
|
|
37
|
+
let ObjSprinkle = {};
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
/* +++++++++++++++++++++++++++ Starts the adapter instance ++++++++++++++++++++++++++++++++ */
|
|
41
|
+
|
|
42
|
+
function startAdapter(options) {
|
|
43
|
+
|
|
44
|
+
options = options || {};
|
|
45
|
+
Object.assign(options, { name: adapterName });
|
|
46
|
+
|
|
47
|
+
adapter = new utils.Adapter(options);
|
|
48
|
+
|
|
49
|
+
// start here!
|
|
50
|
+
adapter.on('ready', () => {
|
|
51
|
+
// init createConfig
|
|
52
|
+
myConfig.createConfig(adapter);
|
|
53
|
+
// Hauptpumpe zur Bewässerung setzen
|
|
54
|
+
valveControl.initValveControl(adapter);
|
|
55
|
+
main(adapter);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* +++++++++++++++++++++++++ is called when adapter shuts down +++++++++++++++++++++++++
|
|
60
|
+
*
|
|
61
|
+
* @param {() => void}callback
|
|
62
|
+
*/
|
|
63
|
+
adapter.on('unload', (callback) => {
|
|
64
|
+
/* Wird beim Stoppen nicht ausgeführt - Warum?
|
|
65
|
+
if(adapter.config.notificationEnabled){
|
|
66
|
+
sendMessageText.sendMessage('sprinklerControl is shutting down');
|
|
67
|
+
adapter.log.info('sprinklerControl is shutting down');
|
|
68
|
+
}
|
|
69
|
+
*/
|
|
70
|
+
try {
|
|
71
|
+
adapter.log.info('cleaned everything up...');
|
|
72
|
+
clearTimeout(timer);
|
|
73
|
+
clearTimeout(timerSleep);
|
|
74
|
+
/*Startzeiten der Timer löschen*/
|
|
75
|
+
schedule.cancelJob('calcPosTimer');
|
|
76
|
+
schedule.cancelJob('sprinkleStartTime');
|
|
77
|
+
schedule.cancelJob('sprinkleAddStartTime');
|
|
78
|
+
/* alle Ventile und Aktoren deaktivieren */
|
|
79
|
+
valveControl.clearEntireList();
|
|
80
|
+
callback();
|
|
81
|
+
} catch (err) {
|
|
82
|
+
callback(err);
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* ++++++++++++++++++ Answers when getTelegramUser calls from index_m ++++++++++++++++++
|
|
88
|
+
* -------------- Antwortet bei Aufrufen von getTelegramUser von index_m ---------------
|
|
89
|
+
*/
|
|
90
|
+
adapter.on ('message', (obj) => {
|
|
91
|
+
if (obj) {
|
|
92
|
+
switch (obj.command) {
|
|
93
|
+
case 'getTelegramUser':
|
|
94
|
+
adapter.getForeignState(`${adapter.config.telegramInstance }.communicate.users`, (err, state) => {
|
|
95
|
+
err && adapter.log.error(err);
|
|
96
|
+
if (state && state.val) {
|
|
97
|
+
try {
|
|
98
|
+
adapter.log.debug(`getTelegramUser: ${state.val}`);
|
|
99
|
+
adapter.sendTo(obj.from, obj.command, JSON.parse(state.val), obj.callback);
|
|
100
|
+
} catch (err) {
|
|
101
|
+
err && adapter.log.error(err);
|
|
102
|
+
adapter.log.error('Cannot parse stored user IDs from Telegram!');
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
});
|
|
106
|
+
break;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* ++++++++++++++++++ is called if a subscribed object changes ++++++++++++++++++
|
|
113
|
+
* ---------- wird aufgerufen, wenn sich ein abonniertes Objekt ändert ----------
|
|
114
|
+
*/
|
|
115
|
+
adapter.on('objectChange', (id, obj) => {
|
|
116
|
+
if (obj) {
|
|
117
|
+
adapter.log.info(`object ${id} changed: ${JSON.stringify(obj)}`);
|
|
118
|
+
} else {
|
|
119
|
+
// The object was deleted
|
|
120
|
+
adapter.log.info(`object ${id} deleted`);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* ++++++++++++++++++ is called if a subscribed state changes ++++++++++++++++++
|
|
126
|
+
* --------- wird aufgerufen, wenn sich ein abonnierter Status ändert ----------
|
|
127
|
+
*/
|
|
128
|
+
adapter.on('stateChange', (id, state) => {
|
|
129
|
+
// The state was changed → Der Zustand wurde geändert
|
|
130
|
+
adapter.log.debug(`state ${id} changed: ${state.val} (ack = ${state.ack})`);
|
|
131
|
+
|
|
132
|
+
// Signale zum bestätigen (ack = true) - signals for confirmation
|
|
133
|
+
if (state?.ack === false) {
|
|
134
|
+
// wenn (Holiday == true) ist, soll das Wochenendprogramm gefahren werden.
|
|
135
|
+
if (id === `${adapter.namespace }.control.Holiday`) {
|
|
136
|
+
// @ts-ignore
|
|
137
|
+
holidayStr = state.val;
|
|
138
|
+
adapter.setState(id, {
|
|
139
|
+
val: state.val,
|
|
140
|
+
ack: true
|
|
141
|
+
});
|
|
142
|
+
startTimeSprinkle();
|
|
143
|
+
}
|
|
144
|
+
// wenn (addStartTimeSwitch == true) wird die zusätzliche Bewässerung aktiviert
|
|
145
|
+
if (id === `${adapter.namespace}.control.addStartTimeSwitch` && typeof state.val === 'boolean') {
|
|
146
|
+
addStartTimeSwitch = state.val;
|
|
147
|
+
adapter.setState(id, {
|
|
148
|
+
val: state.val,
|
|
149
|
+
ack: true
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
// wenn (autoOnOff == false) so werden alle Sprenger nicht mehr automatisch gestartet.
|
|
153
|
+
if ((id === `${adapter.namespace }.control.autoOnOff`)) {
|
|
154
|
+
autoOnOffStr = state.val;
|
|
155
|
+
adapter.log.info(`startAdapter: control.autoOnOff: ${state.val}`);
|
|
156
|
+
adapter.setState(id, {
|
|
157
|
+
val: state.val,
|
|
158
|
+
ack: true
|
|
159
|
+
});
|
|
160
|
+
if (!state.val) {
|
|
161
|
+
valveControl.clearEntireList();
|
|
162
|
+
}
|
|
163
|
+
startTimeSprinkle();
|
|
164
|
+
}
|
|
165
|
+
// wenn (autoStart == true) so die automatische Bewässerung von Hand gestartet
|
|
166
|
+
if (id === `${adapter.namespace}.control.autoStart`) {
|
|
167
|
+
adapter.setState(id, {
|
|
168
|
+
val: false,
|
|
169
|
+
ack: true
|
|
170
|
+
});
|
|
171
|
+
if (state.val === true) {
|
|
172
|
+
// auto Start;
|
|
173
|
+
startOfIrrigation();
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// wenn (...sprinkleName.runningTime sich ändert) so wird der aktuelle Sprenger [sprinkleName]
|
|
177
|
+
// bei == 0 gestoppt, > 1 gestartet
|
|
178
|
+
if (myConfig.config) {
|
|
179
|
+
const found = myConfig.config.find(d => d.objectID === id);
|
|
180
|
+
if (found) {
|
|
181
|
+
if (id === myConfig.config[found.sprinkleID].objectID) {
|
|
182
|
+
if (!isNaN(state.val)) {
|
|
183
|
+
valveControl.addList(
|
|
184
|
+
[{
|
|
185
|
+
auto: false, // Handbetrieb
|
|
186
|
+
sprinkleID: found.sprinkleID,
|
|
187
|
+
wateringTime: (state.val <= 0) ? 0 : Math.round(60 * state.val)
|
|
188
|
+
}]);
|
|
189
|
+
adapter.setState(id, {
|
|
190
|
+
val: (state.val <= 0) ? 0 : addTime(Math.round(60 * state.val)),
|
|
191
|
+
ack: true
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
// wenn (...sprinkleName.autoOn == false[off]) so wird der aktuelle Sprenger [sprinkleName]
|
|
198
|
+
// bei false nicht automatisch gestartet
|
|
199
|
+
if (myConfig.config && (typeof state.val === 'boolean')) {
|
|
200
|
+
const found = myConfig.config.find(d => d.autoOnID === id);
|
|
201
|
+
if (found && id === myConfig.config[found.sprinkleID].autoOnID) {
|
|
202
|
+
myConfig.config[found.sprinkleID].autoOn = state.val;
|
|
203
|
+
adapter.setState(id, { // Bestätigung
|
|
204
|
+
val: state.val,
|
|
205
|
+
ack: true
|
|
206
|
+
});
|
|
207
|
+
adapter.log.info(`set ${found.objectName}.autoOn = ${state.val}, id: ${id}`);
|
|
208
|
+
if (state.val === false) {
|
|
209
|
+
valveControl.addList(
|
|
210
|
+
[{
|
|
211
|
+
auto: false,
|
|
212
|
+
sprinkleID: found.sprinkleID,
|
|
213
|
+
wateringTime: 0
|
|
214
|
+
}]
|
|
215
|
+
);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// postponeByOneDay → um einen Tag verschieben bei fixDay (twoNd & threeRd)
|
|
220
|
+
const idSplit = id.split('.', 5);
|
|
221
|
+
if (idSplit[4] === `postponeByOneDay`) {
|
|
222
|
+
const found = myConfig.config.find(d => d.objectName === idSplit[3]);
|
|
223
|
+
if (found) {
|
|
224
|
+
myConfig.postponeByOneDay(found.sprinkleID).catch((e) => {
|
|
225
|
+
adapter.log.warn(`postponeByOneDay: ${e}`);
|
|
226
|
+
});
|
|
227
|
+
adapter.setState(id, {
|
|
228
|
+
val: false,
|
|
229
|
+
ack: true
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
// Signale ohne Bestätigung - signals without confirmation
|
|
235
|
+
|
|
236
|
+
// wenn in der config unter methodControlSM!== 'analog' oder 'bistable' eingegeben wurde, dann Bodenfeuchte-Sensor auslesen
|
|
237
|
+
if (myConfig.config) {
|
|
238
|
+
function filterByID(obj){
|
|
239
|
+
return (((obj.methodControlSM === 'analog') || (obj.methodControlSM === 'bistable')) && (obj.triggerSM === id));
|
|
240
|
+
}
|
|
241
|
+
const filter = myConfig.config.filter(filterByID);
|
|
242
|
+
if (filter) {
|
|
243
|
+
for (const fil of filter) {
|
|
244
|
+
if (id === myConfig.config[fil.sprinkleID].triggerSM){
|
|
245
|
+
// analog
|
|
246
|
+
if (fil.methodControlSM === 'analog') {
|
|
247
|
+
myConfig.setSoilMoistPct(fil.sprinkleID, state.val);
|
|
248
|
+
} else if (fil.methodControlSM === 'bistable') { // bistable
|
|
249
|
+
myConfig.setSoilMoistBool(fil.sprinkleID, state.val);
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
// Change in outside temperature → Änderung der Außentemperatur
|
|
256
|
+
if (id === adapter.config.sensorOutsideTemperature) { /*Temperatur*/
|
|
257
|
+
if (!Number.isNaN(Number.parseFloat(state.val))) {
|
|
258
|
+
evaporation.setCurTemperature(parseFloat(state.val), state.ts);
|
|
259
|
+
} else {
|
|
260
|
+
adapter.log.warn(`sensorOutsideTemperature => Wrong value: ${state.val}, Type: ${typeof state.val}`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
// LuftFeuchtigkeit
|
|
264
|
+
if (id === adapter.config.sensorOutsideHumidity) {
|
|
265
|
+
if (!Number.isNaN(Number.parseFloat(state.val))) {
|
|
266
|
+
evaporation.setCurHumidity(parseFloat(state.val), state.lc);
|
|
267
|
+
} else {
|
|
268
|
+
adapter.log.warn(`sensorOutsideHumidity => Wrong value: ${state.val}, Type: ${typeof state.val}`);
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
// Helligkeit
|
|
272
|
+
if (id === adapter.config.sensorBrightness) {
|
|
273
|
+
if (!Number.isNaN(Number.parseFloat(state.val))) {
|
|
274
|
+
evaporation.setCurIllumination(parseFloat(state.val), state.lc);
|
|
275
|
+
} else {
|
|
276
|
+
adapter.log.warn(`sensorBrightness => Wrong value: ${state.val}, Type: ${typeof state.val}`);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
// Windgeschwindigkeit
|
|
280
|
+
if (id === adapter.config.sensorWindSpeed) {
|
|
281
|
+
if (!Number.isNaN(Number.parseFloat(state.val))) {
|
|
282
|
+
evaporation.setCurWindSpeed(parseFloat(state.val), state.lc);
|
|
283
|
+
} else {
|
|
284
|
+
adapter.log.warn(`sensorWindSpeed => Wrong value: ${state.val}, Type: ${typeof state.val}`);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
// Regencontainer
|
|
288
|
+
// If the amount of rain is over 20 mm, the 'lastRainCounter' is overwritten and no calculation is carried out. =>
|
|
289
|
+
// * Wenn die Regenmenge mehr als 20 mm beträgt, wird der 'lastRainCounter' überschrieben und es wird keine Berechnung durchgeführt.
|
|
290
|
+
if (id === adapter.config.sensorRainfall) {
|
|
291
|
+
if (!Number.isNaN(Number.parseFloat(state.val))) {
|
|
292
|
+
evaporation.setCurAmountOfRain(parseFloat(state.val));
|
|
293
|
+
} else {
|
|
294
|
+
adapter.log.warn(`sensorRainfall => Wrong value: ${state.val}, Type: ${typeof state.val}`);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
// Feiertagskalender
|
|
298
|
+
if (adapter.config.publicHolidays === true) {
|
|
299
|
+
if (id === `${adapter.config.publicHolInstance }.heute.boolean`) {
|
|
300
|
+
publicHolidayStr = state.val;
|
|
301
|
+
startTimeSprinkle();
|
|
302
|
+
}
|
|
303
|
+
if (id === `${adapter.config.publicHolInstance }.morgen.boolean`) {
|
|
304
|
+
// @ts-ignore
|
|
305
|
+
publicHolidayTomorrowStr = state.val;
|
|
306
|
+
startTimeSprinkle();
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
// Wettervorhersage
|
|
310
|
+
if (adapter.config.weatherForecast === true) {
|
|
311
|
+
if (id === weatherForecastTodayPfadStr) {
|
|
312
|
+
if (typeof state.val == 'string') {
|
|
313
|
+
weatherForecastTodayNum = parseFloat(state.val);
|
|
314
|
+
} else if (typeof state.val == 'number') {
|
|
315
|
+
weatherForecastTodayNum = state.val;
|
|
316
|
+
} else {
|
|
317
|
+
weatherForecastTodayNum = 0;
|
|
318
|
+
adapter.log.info(`StateChange => Wettervorhersage state.val ( ${state.val}; ${typeof state.val} ) kann nicht als Number verarbeitet werden`);
|
|
319
|
+
}
|
|
320
|
+
adapter.setState('info.rainToday', {
|
|
321
|
+
val: weatherForecastTodayNum,
|
|
322
|
+
ack: true
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
if (id === `${adapter.config.weatherForInstance }.NextDaysDetailed.Location_1.Day_2.rain_value`) {
|
|
326
|
+
weatherForecastTomorrowNum = parseFloat(state.val);
|
|
327
|
+
adapter.setState('info.rainTomorrow', {
|
|
328
|
+
val: weatherForecastTomorrowNum,
|
|
329
|
+
ack: true
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
// Füllstand der Zisterne bei Statusänderung
|
|
334
|
+
if (adapter.config.actualValueLevel && (id === adapter.config.actualValueLevel)) {
|
|
335
|
+
valveControl.setFillLevelCistern(parseFloat(state.val) || 0);
|
|
336
|
+
//fillLevelCistern = state.val || 0;
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// +++++++++++++++++ Get longitude an latitude from system config ++++++++++++++++++++
|
|
342
|
+
/**get longitude/latitude from system if not set or not valid
|
|
343
|
+
* do not change if we have already a valid value
|
|
344
|
+
* so we could use different settings compared to system if necessary
|
|
345
|
+
* >>>
|
|
346
|
+
* Längen- / Breitengrad vom System abrufen, falls nicht festgelegt oder ungültig
|
|
347
|
+
* wird nicht geändert, wenn bereits ein gültiger Wert vorhanden ist,
|
|
348
|
+
* daher können wir bei Bedarf andere Einstellungen als das System verwenden
|
|
349
|
+
*/
|
|
350
|
+
async function GetSystemData() {
|
|
351
|
+
if (typeof adapter.config.longitude === undefined || adapter.config.longitude == null || adapter.config.longitude.length === 0 || isNaN(adapter.config.longitude)
|
|
352
|
+
|| typeof adapter.config.latitude === undefined || adapter.config.latitude == null || adapter.config.latitude.length === 0 || isNaN(adapter.config.latitude)) {
|
|
353
|
+
|
|
354
|
+
try {
|
|
355
|
+
const obj = await adapter.getForeignObjectAsync('system.config');
|
|
356
|
+
|
|
357
|
+
if (obj && obj.common && obj.common.longitude && obj.common.latitude) {
|
|
358
|
+
adapter.config.longitude = obj.common.longitude;
|
|
359
|
+
adapter.config.latitude = obj.common.latitude;
|
|
360
|
+
|
|
361
|
+
adapter.log.debug(`longitude: ${adapter.config.longitude} | latitude: ${adapter.config.latitude}`);
|
|
362
|
+
} else {
|
|
363
|
+
adapter.log.error('system settings cannot be called up. Please check the geo data');
|
|
364
|
+
}
|
|
365
|
+
} catch (err) {
|
|
366
|
+
adapter.log.warn('system settings cannot be called up. Please check configuration!');
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* Schreiben des nächsten Starts in '.actualSoilMoisture'
|
|
374
|
+
* oder Rückgabe des DayName für den nächsten Start
|
|
375
|
+
*
|
|
376
|
+
* @param sprinkleID - Number of Array[0...]
|
|
377
|
+
* @param returnOn - true = Rückgabe des Wochentags; false = Schreiben in State /.actualSoilMoisture
|
|
378
|
+
* @returns nextStart ['Sun','Mon','Tue','Wed','Thur','Fri','Sat']
|
|
379
|
+
*/
|
|
380
|
+
function curNextFixDay (sprinkleID, returnOn) {
|
|
381
|
+
const weekDayArray = myConfig.config[sprinkleID].startFixDay;
|
|
382
|
+
const objPfad = `sprinkle.${myConfig.config[sprinkleID].objectName}`;
|
|
383
|
+
const weekday = ['Sun','Mon','Tue','Wed','Thur','Fri','Sat'];
|
|
384
|
+
let found = false;
|
|
385
|
+
let curDay = formatTime(adapter, '', 'day');
|
|
386
|
+
if (startTimeStr <= formatTime(adapter, '', 'hh:mm')) {
|
|
387
|
+
curDay++
|
|
388
|
+
}
|
|
389
|
+
for ( let i=0; i<7; i++ ) {
|
|
390
|
+
if (curDay > 6) {
|
|
391
|
+
curDay = curDay - 7;
|
|
392
|
+
}
|
|
393
|
+
if (weekDayArray[curDay] === true) {
|
|
394
|
+
found = true;
|
|
395
|
+
if (returnOn) {
|
|
396
|
+
return weekday[curDay];
|
|
397
|
+
} else {
|
|
398
|
+
adapter.setState(`${objPfad}.actualSoilMoisture`, {
|
|
399
|
+
val: curDay,
|
|
400
|
+
ack: true
|
|
401
|
+
});
|
|
402
|
+
}
|
|
403
|
+
break;
|
|
404
|
+
}
|
|
405
|
+
curDay++;
|
|
406
|
+
}
|
|
407
|
+
if (returnOn && found === false) {
|
|
408
|
+
return 'off';
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
//
|
|
413
|
+
/**
|
|
414
|
+
* Sets the status at start to a defined value
|
|
415
|
+
* → Setzt den Status beim Start auf einen definierten Wert
|
|
416
|
+
*/
|
|
417
|
+
function checkStates() {
|
|
418
|
+
/**
|
|
419
|
+
* control.Holiday
|
|
420
|
+
*
|
|
421
|
+
* @param {string|null} err
|
|
422
|
+
* @param {ioBroker.State|null|undefined} state
|
|
423
|
+
*/
|
|
424
|
+
adapter.getState('control.Holiday', (err, state) => {
|
|
425
|
+
if (state && (state.val == null)) {
|
|
426
|
+
adapter.setState('control.Holiday', {val: false, ack: true});
|
|
427
|
+
}
|
|
428
|
+
});
|
|
429
|
+
/**
|
|
430
|
+
* control.autoOnOff
|
|
431
|
+
*
|
|
432
|
+
* @param {string|null} err
|
|
433
|
+
* @param {ioBroker.State|null|undefined} state
|
|
434
|
+
*/
|
|
435
|
+
adapter.getState('control.autoOnOff', (err, state) => {
|
|
436
|
+
if (state && (typeof state.val === 'boolean')) {
|
|
437
|
+
autoOnOffStr = state.val;
|
|
438
|
+
} else {
|
|
439
|
+
autoOnOffStr = true;
|
|
440
|
+
adapter.setState('control.autoOnOff', {
|
|
441
|
+
val: autoOnOffStr,
|
|
442
|
+
ack: true
|
|
443
|
+
});
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
adapter.getState('evaporation.ETpToday', (err, state) => {
|
|
447
|
+
if (state && (state.val == null)) {
|
|
448
|
+
evaporation.setETpTodayNum(0);
|
|
449
|
+
adapter.setState('evaporation.ETpToday', {
|
|
450
|
+
val: 0,
|
|
451
|
+
ack: true
|
|
452
|
+
});
|
|
453
|
+
} else if (state) {
|
|
454
|
+
evaporation.setETpTodayNum(parseFloat(state.val));
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
adapter.getState('evaporation.ETpYesterday', (err, state) => {
|
|
458
|
+
if (state && (state.val == null || state.val === false)) {
|
|
459
|
+
adapter.setState('evaporation.ETpYesterday', {
|
|
460
|
+
val: 0,
|
|
461
|
+
ack: true
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
// akt. kW ermitteln für history last week
|
|
467
|
+
kwStr = formatTime(adapter, '','kW');
|
|
468
|
+
today = formatTime(adapter,'', 'day');
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
/**
|
|
472
|
+
* aktuelle States checken nach dem Start (2000 ms) wenn alle Sprenger-Kreise angelegt wurden
|
|
473
|
+
*/
|
|
474
|
+
async function checkActualStates () {
|
|
475
|
+
|
|
476
|
+
try {
|
|
477
|
+
/**
|
|
478
|
+
* switch Holiday
|
|
479
|
+
*
|
|
480
|
+
*/
|
|
481
|
+
const _holiday = await adapter.getStateAsync('control.Holiday');
|
|
482
|
+
if (_holiday && _holiday.val && typeof _holiday.val === 'boolean') {
|
|
483
|
+
holidayStr = _holiday.val;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* switch autoOnOff
|
|
488
|
+
*
|
|
489
|
+
*/
|
|
490
|
+
const _autoOnOff = await adapter.getStateAsync('control.autoOnOff');
|
|
491
|
+
if (_autoOnOff && _autoOnOff.val && typeof _autoOnOff.val === 'boolean') {
|
|
492
|
+
autoOnOffStr = _autoOnOff.val;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
if (adapter.config.publicHolidays === true && (adapter.config.publicHolInstance !== 'none' || adapter.config.publicHolInstance !== '')) {
|
|
496
|
+
/**
|
|
497
|
+
* Feiertag Heute
|
|
498
|
+
*
|
|
499
|
+
*/
|
|
500
|
+
const _publicHolInstanceHeute = await adapter.getForeignStateAsync(
|
|
501
|
+
`${adapter.config.publicHolInstance }.heute.boolean`
|
|
502
|
+
).catch((e) => adapter.log.warn(e));
|
|
503
|
+
if (_publicHolInstanceHeute && _publicHolInstanceHeute.val) {
|
|
504
|
+
publicHolidayStr = _publicHolInstanceHeute.val;
|
|
505
|
+
}
|
|
506
|
+
/**
|
|
507
|
+
* Feiertag MORGEN
|
|
508
|
+
*
|
|
509
|
+
*/
|
|
510
|
+
const _publicHolInstanceMorgen = await adapter.getForeignStateAsync(
|
|
511
|
+
`${adapter.config.publicHolInstance }.morgen.boolean`
|
|
512
|
+
).catch((e) => adapter.log.warn(e));
|
|
513
|
+
if (_publicHolInstanceMorgen && _publicHolInstanceMorgen.val) {
|
|
514
|
+
publicHolidayTomorrowStr = _publicHolInstanceMorgen.val;
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
if (adapter.config.weatherForecast === true && (adapter.config.weatherForInstance !== 'none' || adapter.config.weatherForInstance !== '')) {
|
|
519
|
+
/**
|
|
520
|
+
* Niederschlagsmenge HEUTE in mm
|
|
521
|
+
*
|
|
522
|
+
*/
|
|
523
|
+
const _weatherForInstanceToday = await adapter.getForeignStateAsync(
|
|
524
|
+
weatherForecastTodayPfadStr
|
|
525
|
+
).catch((e) => adapter.log.warn(e));
|
|
526
|
+
if (_weatherForInstanceToday && _weatherForInstanceToday.val) {
|
|
527
|
+
if (typeof _weatherForInstanceToday.val == 'string') {
|
|
528
|
+
weatherForecastTodayNum = parseFloat(_weatherForInstanceToday.val);
|
|
529
|
+
} else if (typeof _weatherForInstanceToday.val == 'number') {
|
|
530
|
+
weatherForecastTodayNum = _weatherForInstanceToday.val;
|
|
531
|
+
} else {
|
|
532
|
+
weatherForecastTodayNum = 0;
|
|
533
|
+
adapter.log.info(`checkActualStates => Wettervorhersage state.val ( ${_weatherForInstanceToday.val}); ${typeof _weatherForInstanceToday.val} kann nicht als Number verarbeitet werden`);
|
|
534
|
+
}
|
|
535
|
+
await adapter.setStateAsync('info.rainToday',
|
|
536
|
+
weatherForecastTodayNum,
|
|
537
|
+
true
|
|
538
|
+
);
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Niederschlagsmenge MORGEN in mm
|
|
543
|
+
*
|
|
544
|
+
*/
|
|
545
|
+
const _weatherForInstance = await adapter.getForeignStateAsync(
|
|
546
|
+
`${adapter.config.weatherForInstance }.NextDaysDetailed.Location_1.Day_2.rain_value`
|
|
547
|
+
).catch((e) => adapter.log.warn(e));
|
|
548
|
+
if (_weatherForInstance && _weatherForInstance.val) {
|
|
549
|
+
weatherForecastTomorrowNum = _weatherForInstance.val;
|
|
550
|
+
await adapter.setStateAsync(
|
|
551
|
+
'info.rainTomorrow',
|
|
552
|
+
weatherForecastTomorrowNum,
|
|
553
|
+
true
|
|
554
|
+
);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// wenn (...sprinkleName.autoOn == false[off]) so wird der aktuelle Sprenger [sprinkleName]
|
|
559
|
+
// bei false nicht automatisch gestartet
|
|
560
|
+
/**
|
|
561
|
+
* Abfrage von ...sprinkleName.autoOn
|
|
562
|
+
*
|
|
563
|
+
*/
|
|
564
|
+
const result = myConfig.config;
|
|
565
|
+
if (result) {
|
|
566
|
+
for (const res of result) {
|
|
567
|
+
/**
|
|
568
|
+
* Abfrage ... .autoOn beim Start
|
|
569
|
+
*
|
|
570
|
+
*/
|
|
571
|
+
const _autoOn = await adapter.getForeignStateAsync(
|
|
572
|
+
res.autoOnID
|
|
573
|
+
).catch((e) => adapter.log.warn(e));
|
|
574
|
+
if (_autoOn && typeof _autoOn.val === 'boolean') {
|
|
575
|
+
res.autoOn = _autoOn.val;
|
|
576
|
+
if (_autoOn.val === false) {
|
|
577
|
+
adapter.log.info(`get ${res.objectName}.autoOn = ${res.autoOn}`);
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
if (adapter.config.actualValueLevel){
|
|
584
|
+
/**
|
|
585
|
+
* Füllstand der Zisterne in % holen
|
|
586
|
+
*
|
|
587
|
+
*/
|
|
588
|
+
const _actualValueLevel = await adapter.getForeignStateAsync(
|
|
589
|
+
adapter.config.actualValueLevel
|
|
590
|
+
).catch((e) => adapter.log.warn(e));
|
|
591
|
+
if (_actualValueLevel && typeof parseFloat(_actualValueLevel.val) === 'number') {
|
|
592
|
+
valveControl.setFillLevelCistern(parseFloat(_actualValueLevel.val));
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
/**
|
|
596
|
+
* return the saved objects under sprinkle.*
|
|
597
|
+
* rückgabe der gespeicherten Objekte unter sprinkle.*
|
|
598
|
+
*
|
|
599
|
+
*/
|
|
600
|
+
const _list = await adapter.getForeignObjectsAsync(`${adapter.namespace }.sprinkle.*`, 'channel').catch((e) => adapter.log.warn(e));
|
|
601
|
+
if (_list) {
|
|
602
|
+
ObjSprinkle = _list;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
} catch (e) {
|
|
606
|
+
adapter.log.warn(`sprinkleControl cannot check actual States ... Please check your sprinkleControl states: ${e}`);
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
}
|
|
610
|
+
|
|
611
|
+
|
|
612
|
+
/**
|
|
613
|
+
* at 0:05 start of StartTimeSprinkle
|
|
614
|
+
* => um 0:05 start von StartTimeSprinkle
|
|
615
|
+
* (..., '(s )m h d m wd')
|
|
616
|
+
*/
|
|
617
|
+
const calcPos = schedule.scheduleJob('calcPosTimer', '5 0 * * *', function() {
|
|
618
|
+
// Berechnungen mittels SunCalc
|
|
619
|
+
sunPos();
|
|
620
|
+
today = formatTime(adapter,'', 'day');
|
|
621
|
+
|
|
622
|
+
// History Daten aktualisieren, wenn eine neue Woche beginnt
|
|
623
|
+
adapter.log.debug(`calcPos 0:05 old-KW: ${kwStr} new-KW: ${formatTime(adapter, '','kW')} if: ${(kwStr !== formatTime(adapter, '','kW'))}`);
|
|
624
|
+
if (kwStr !== formatTime(adapter, '','kW')) {
|
|
625
|
+
const result = myConfig.config;
|
|
626
|
+
if (result) {
|
|
627
|
+
for(const i in result) {
|
|
628
|
+
if (Object.hasOwn(result, i)) {
|
|
629
|
+
const objectName = result[i].objectName;
|
|
630
|
+
adapter.getState(`sprinkle.${objectName}.history.curCalWeekConsumed`, (err, state) => {
|
|
631
|
+
if (state) {
|
|
632
|
+
adapter.setState(`sprinkle.${objectName}.history.lastCalWeekConsumed`, { val: state.val, ack: true });
|
|
633
|
+
adapter.setState(`sprinkle.${objectName}.history.curCalWeekConsumed`, { val: 0, ack: true });
|
|
634
|
+
}
|
|
635
|
+
});
|
|
636
|
+
adapter.getState(`sprinkle.${objectName}.history.curCalWeekRunningTime`, (err, state) => {
|
|
637
|
+
if (state) {
|
|
638
|
+
adapter.setState(`sprinkle.${objectName}.history.lastCalWeekRunningTime`, { val: state.val, ack: true });
|
|
639
|
+
adapter.setState(`sprinkle.${objectName}.history.curCalWeekRunningTime`, { val: '00:00', ack: true });
|
|
640
|
+
}
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
kwStr = formatTime(adapter, '','kW');
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
// ETpToday und ETpYesterday in evaporation aktualisieren da ein neuer Tag
|
|
650
|
+
evaporation.setNewDay();
|
|
651
|
+
|
|
652
|
+
// Startzeit Festlegen → verzögert wegen Daten von SunCalc
|
|
653
|
+
setTimeout(() => {
|
|
654
|
+
startTimeSprinkle();
|
|
655
|
+
addStartTimeSprinkle();
|
|
656
|
+
},1000);
|
|
657
|
+
|
|
658
|
+
});
|
|
659
|
+
|
|
660
|
+
// Berechnung mittels sunCalc
|
|
661
|
+
function sunPos() {
|
|
662
|
+
// get today's sunlight times → Holen Sie sich die heutige Sonnenlichtzeit
|
|
663
|
+
const times = SunCalc.getTimes(new Date(), adapter.config.latitude, adapter.config.longitude);
|
|
664
|
+
|
|
665
|
+
// format sunrise time from the Date object → Formatieren Sie die Sonnenaufgangszeit aus dem Date-Objekt
|
|
666
|
+
sunriseStr = `${(`0${times.sunrise.getHours()}`).slice(-2)}:${(`0${times.sunrise.getMinutes()}`).slice(-2)}`;
|
|
667
|
+
|
|
668
|
+
// format golden hour end time from the Date object → Formatiere golden hour end time aus dem Date-Objekt
|
|
669
|
+
goldenHourEnd = `${(`0${times.goldenHourEnd.getHours()}`).slice(-2)}:${(`0${times.goldenHourEnd.getMinutes()}`).slice(-2)}`;
|
|
670
|
+
|
|
671
|
+
// format sunset time from the Date object → formatieren Sie die Sonnenuntergangszeit aus dem Date-Objekt
|
|
672
|
+
sunsetStr = sunsetStr = `${(`0${times.sunset.getHours()}`).slice(-2)}:${(`0${times.sunset.getMinutes()}`).slice(-2)}`;
|
|
673
|
+
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
function addStartTimeSprinkle() {
|
|
677
|
+
schedule.cancelJob('sprinkleAddStartTime');
|
|
678
|
+
if (adapter.config.selectAddStartTime === 'greaterETpCurrent' || adapter.config.selectAddStartTime === 'withExternalSignal') {
|
|
679
|
+
const addStartTimeSplit = adapter.config.addWateringStartTime.split(':');
|
|
680
|
+
const scheduleAddStartTime = schedule.scheduleJob('sprinkleAddStartTime', `${addStartTimeSplit[1]} ${addStartTimeSplit[0]} * * *`, function() {
|
|
681
|
+
// if (autoOnOff == false) => keine auto Start
|
|
682
|
+
if (!autoOnOffStr) {
|
|
683
|
+
schedule.cancelJob('sprinkleAddStartTime');
|
|
684
|
+
return;
|
|
685
|
+
}
|
|
686
|
+
if (((adapter.config.selectAddStartTime === 'greaterETpCurrent') && (adapter.config.triggerAddStartTimeETpCur < evaporation.getETpTodayNum()))
|
|
687
|
+
|| (adapter.config.selectAddStartTime === 'withExternalSignal' && addStartTimeSwitch)) {
|
|
688
|
+
let messageText = '';
|
|
689
|
+
|
|
690
|
+
// Filter enabled
|
|
691
|
+
const result = myConfig.config.filter(d => d.enabled === true);
|
|
692
|
+
if (result) {
|
|
693
|
+
/**
|
|
694
|
+
* Array zum flüchtigen Sammeln von Bewässerungsaufgaben
|
|
695
|
+
*
|
|
696
|
+
*/
|
|
697
|
+
const memAddList = [];
|
|
698
|
+
|
|
699
|
+
/**
|
|
700
|
+
* result Rain
|
|
701
|
+
* - (aktuelle Wettervorhersage - Schwellwert der Regenberücksichtigung) wenn Sensor sich im Freien befindet
|
|
702
|
+
* - (> 0) es regnet - Abbruch -
|
|
703
|
+
* - (≤ 0) Start der Bewässerung
|
|
704
|
+
*
|
|
705
|
+
* @param inGreenhouse - Sensor befindet sich im Gewächshaus
|
|
706
|
+
* @returns - resultierende Regenmenge
|
|
707
|
+
*/
|
|
708
|
+
function resRain (inGreenhouse) {
|
|
709
|
+
return (adapter.config.weatherForecast && !inGreenhouse) ? (((+ weatherForecastTodayNum) - parseFloat(adapter.config.thresholdRain)).toFixed(1)) : 0;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
for(const res of result) {
|
|
713
|
+
if (res.autoOn // Ventil aktiv
|
|
714
|
+
&& (res.addWateringTime > 0) // zusätzliche Bewässerung aktiv time > 0
|
|
715
|
+
&& (resRain(res.inGreenhouse) <= 0)) { // keine Regenvorhersage
|
|
716
|
+
|
|
717
|
+
switch (res.methodControlSM) {
|
|
718
|
+
case 'bistable': {
|
|
719
|
+
if (res.soilMoisture.bool) {
|
|
720
|
+
messageText += `<b>${res.objectName}</b> (${res.soilMoisture.bool})\n`
|
|
721
|
+
+ ` START => ${addTime(res.addWateringTime, '')}\n`;
|
|
722
|
+
memAddList.push({
|
|
723
|
+
auto: true,
|
|
724
|
+
sprinkleID: res.sprinkleID,
|
|
725
|
+
wateringTime: res.addWateringTime
|
|
726
|
+
});
|
|
727
|
+
}
|
|
728
|
+
break;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
case 'fixDay': {
|
|
732
|
+
messageText += `<b>${res.objectName}</b>\n`
|
|
733
|
+
+ ` START => ${addTime(Math.round(60 * res.addWateringTime), '')}\n`;
|
|
734
|
+
memAddList.push({
|
|
735
|
+
auto: true,
|
|
736
|
+
sprinkleID: res.sprinkleID,
|
|
737
|
+
wateringTime: Math.round(60 * res.addWateringTime)
|
|
738
|
+
});
|
|
739
|
+
break;
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
case 'calculation': {
|
|
743
|
+
const addCountdown = res.wateringTime * (res.soilMoisture.maxIrrigation - res.soilMoisture.val) / (res.soilMoisture.maxIrrigation - res.soilMoisture.triggersIrrigation) - res.wateringTime;
|
|
744
|
+
adapter.log.debug(`addCountdown: ${addCountdown}, addWateringTime: ${res.addWateringTime}, if(${(addCountdown - res.addWateringTime) > 0})`);
|
|
745
|
+
if ((addCountdown - res.addWateringTime) > 0) {
|
|
746
|
+
messageText += `<b>${res.objectName}</b> ${res.soilMoisture.pct}% (${res.soilMoisture.pctTriggerIrrigation}%)\n`
|
|
747
|
+
+ ` START => ${addTime(Math.round(60 * addCountdown), '')}\n`;
|
|
748
|
+
memAddList.push({
|
|
749
|
+
auto: true,
|
|
750
|
+
sprinkleID: res.sprinkleID,
|
|
751
|
+
wateringTime: Math.round(60 * addCountdown)
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
break;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
case 'analog': {
|
|
758
|
+
if (res.soilMoisture.pct < res.soilMoisture.pctAddTriggersIrrigation) {
|
|
759
|
+
messageText += `<b>${res.objectName}</b> ${res.soilMoisture.pct} %(${res.soilMoisture.pctAddTriggersIrrigation}%)\n`
|
|
760
|
+
+ ` START => ${addTime(Math.round(60 * res.addWateringTime), '')}\n`;
|
|
761
|
+
memAddList.push({
|
|
762
|
+
auto: true,
|
|
763
|
+
sprinkleID: res.sprinkleID,
|
|
764
|
+
wateringTime: Math.round(60 * res.addWateringTime)
|
|
765
|
+
});
|
|
766
|
+
}
|
|
767
|
+
break;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
}
|
|
771
|
+
} else {
|
|
772
|
+
adapter.log.debug(`${res.objectName}: autoOn (${res.autoOn}) && addWateringTime (${res.addWateringTime} > 0) && resRain (${resRain(res.inGreenhouse)}) <= 0, if(${res.autoOn && (res.addWateringTime > 0) && (resRain(res.inGreenhouse) <= 0)})`);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
valveControl.addList(memAddList);
|
|
776
|
+
}
|
|
777
|
+
if(!sendMessageText.onlySendError() && messageText.length > 0){
|
|
778
|
+
sendMessageText.sendMessage(messageText);
|
|
779
|
+
}
|
|
780
|
+
} else {
|
|
781
|
+
adapter.log.debug(`greaterETpCurrent: ${(adapter.config.selectAddStartTime === 'greaterETpCurrent')} & ${(adapter.config.triggerAddStartTimeETpCur < evaporation.getETpTodayNum())}, withExternalSignal; ${(adapter.config.selectAddStartTime === 'withExternalSignal')} & ${addStartTimeSwitch}`);
|
|
782
|
+
}
|
|
783
|
+
setTimeout(()=>{
|
|
784
|
+
schedule.cancelJob('sprinkleAddStartTime');
|
|
785
|
+
}, 200);
|
|
786
|
+
});
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
// Determination of the irrigation time => Bestimmung der Bewässerungszeit
|
|
791
|
+
function startTimeSprinkle() {
|
|
792
|
+
let startTimeSplit = [];
|
|
793
|
+
let infoMessage;
|
|
794
|
+
let messageText = '';
|
|
795
|
+
|
|
796
|
+
schedule.cancelJob('sprinkleStartTime');
|
|
797
|
+
|
|
798
|
+
// if (autoOnOff == false) => keine auto Start
|
|
799
|
+
if (!autoOnOffStr) {
|
|
800
|
+
adapter.log.info(`Sprinkle: autoOnOff == Aus ( ${autoOnOffStr} )`);
|
|
801
|
+
adapter.setState('info.nextAutoStart', {
|
|
802
|
+
val: 'autoOnOff = off(0)',
|
|
803
|
+
ack: true
|
|
804
|
+
});
|
|
805
|
+
return;
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
/**
|
|
809
|
+
* next start time (automatic)
|
|
810
|
+
* → Berechnung des nächsten Starts (Automatik)
|
|
811
|
+
*
|
|
812
|
+
* @returns
|
|
813
|
+
*/
|
|
814
|
+
function nextStartTime () {
|
|
815
|
+
let newStartTime;
|
|
816
|
+
let run = 0;
|
|
817
|
+
const curTime = new Date();
|
|
818
|
+
const myHours = checkTime(curTime.getHours());
|
|
819
|
+
const myMinutes = checkTime(curTime.getMinutes());
|
|
820
|
+
let myWeekday = curTime.getDay();
|
|
821
|
+
const myWeekdayStr = ['So','Mo','Di','Mi','Do','Fr','Sa'];
|
|
822
|
+
const myTime = `${myHours}:${myMinutes}`;
|
|
823
|
+
|
|
824
|
+
/**
|
|
825
|
+
* aus 0...9 wird String 00...09
|
|
826
|
+
*
|
|
827
|
+
* @param i
|
|
828
|
+
* @returns
|
|
829
|
+
*/
|
|
830
|
+
function checkTime(i) {
|
|
831
|
+
return (+i < 10) ? `0${i}` : i;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
do {
|
|
835
|
+
myWeekday += run;
|
|
836
|
+
run++;
|
|
837
|
+
if (myWeekday>6){
|
|
838
|
+
myWeekday=0;
|
|
839
|
+
}
|
|
840
|
+
// Start time variant according to configuration => Startzeitvariante gemäß Konfiguration
|
|
841
|
+
switch(adapter.config.wateringStartTime) {
|
|
842
|
+
case 'livingTime' : /*Startauswahl = festen Zeit*/
|
|
843
|
+
infoMessage = 'Start zur festen Zeit ';
|
|
844
|
+
newStartTime = adapter.config.weekLiving;
|
|
845
|
+
break;
|
|
846
|
+
case 'livingSunrise' : /*Startauswahl = Sonnenaufgang*/
|
|
847
|
+
infoMessage = 'Start mit Sonnenaufgang ';
|
|
848
|
+
// format sunrise time from the Date object
|
|
849
|
+
newStartTime = addTime(sunriseStr, parseInt(adapter.config.timeShift));
|
|
850
|
+
break;
|
|
851
|
+
case 'livingGoldenHourEnd' : /*Startauswahl = Ende der Golden Hour*/
|
|
852
|
+
infoMessage = 'Start zum Ende der Golden Hour ';
|
|
853
|
+
// format goldenHourEnd time from the Date object
|
|
854
|
+
newStartTime = goldenHourEnd;
|
|
855
|
+
break;
|
|
856
|
+
case 'livingSunset' : /*Startauswahl = Sonnenuntergang*/
|
|
857
|
+
infoMessage = 'Start mit Sonnenuntergang ';
|
|
858
|
+
// format sunset time from the Date object
|
|
859
|
+
newStartTime = addTime(sunsetStr, parseInt(adapter.config.timeShift));
|
|
860
|
+
break;
|
|
861
|
+
}
|
|
862
|
+
// Start am Wochenende →, wenn andere Zeiten verwendet werden soll
|
|
863
|
+
if((adapter.config.publicWeekend) && ((myWeekday === 6) || (myWeekday === 0))){
|
|
864
|
+
infoMessage = 'Start am Wochenende ';
|
|
865
|
+
newStartTime = adapter.config.weekEndLiving;
|
|
866
|
+
}
|
|
867
|
+
// Start an Feiertagen →, wenn Zeiten des Wochenendes verwendet werden soll
|
|
868
|
+
if((adapter.config.publicHolidays) && (adapter.config.publicWeekend)
|
|
869
|
+
&& (((publicHolidayStr === true) && (run === 1)) // heute Feiertag && erster Durchlauf
|
|
870
|
+
|| ((publicHolidayTomorrowStr === true) && (run === 2)) // morgen Feiertag && zweiter Durchlauf
|
|
871
|
+
|| (holidayStr === true))) { // Urlaub
|
|
872
|
+
infoMessage = 'Start am Feiertag ';
|
|
873
|
+
newStartTime = adapter.config.weekEndLiving;
|
|
874
|
+
}
|
|
875
|
+
} while ((newStartTime <= myTime) && (run === 1));
|
|
876
|
+
|
|
877
|
+
const newStartTimeLong = `${myWeekdayStr[myWeekday]} ${newStartTime}`;
|
|
878
|
+
/**
|
|
879
|
+
* next Auto-Start
|
|
880
|
+
*
|
|
881
|
+
* @param {string|null} err
|
|
882
|
+
* @param {ioBroker.State|null|undefined} state
|
|
883
|
+
*/
|
|
884
|
+
adapter.getState('info.nextAutoStart', (err, state) =>{
|
|
885
|
+
if (state) {
|
|
886
|
+
if (state.val !== newStartTimeLong) {
|
|
887
|
+
adapter.setState('info.nextAutoStart', {
|
|
888
|
+
val: newStartTimeLong,
|
|
889
|
+
ack: true
|
|
890
|
+
});
|
|
891
|
+
// next Start Message
|
|
892
|
+
if(!sendMessageText.onlySendError){
|
|
893
|
+
sendMessageText.sendMessage(`${infoMessage}(${myWeekdayStr[myWeekday]}) um ${newStartTime}`);
|
|
894
|
+
}
|
|
895
|
+
adapter.log.info(`${infoMessage} (${myWeekdayStr[myWeekday]}) um ${newStartTime}`);
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
});
|
|
899
|
+
return newStartTime;
|
|
900
|
+
}
|
|
901
|
+
//
|
|
902
|
+
startTimeStr = nextStartTime();
|
|
903
|
+
startTimeSplit = startTimeStr.split(':');
|
|
904
|
+
|
|
905
|
+
const scheduleStartTime = schedule.scheduleJob('sprinkleStartTime', `${startTimeSplit[1]} ${startTimeSplit[0]} * * *`, function() {
|
|
906
|
+
startOfIrrigation();
|
|
907
|
+
setTimeout (() => {
|
|
908
|
+
setTimeout(()=>{
|
|
909
|
+
nextStartTime();
|
|
910
|
+
}, 800);
|
|
911
|
+
schedule.cancelJob('sprinkleStartTime');
|
|
912
|
+
}, 200);
|
|
913
|
+
});
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
const startOfIrrigation = () => {
|
|
917
|
+
let messageText = '';
|
|
918
|
+
|
|
919
|
+
// Filter enabled
|
|
920
|
+
const result = myConfig.config.filter(d => d.enabled === true);
|
|
921
|
+
if (result) {
|
|
922
|
+
/**
|
|
923
|
+
* Array zum flüchtigen Sammeln von Bewässerungsaufgaben
|
|
924
|
+
*
|
|
925
|
+
*/
|
|
926
|
+
const memAddList = [];
|
|
927
|
+
|
|
928
|
+
/**
|
|
929
|
+
* result Rain
|
|
930
|
+
* - (aktuelle Wettervorhersage - Schwellwert der Regenberücksichtigung) wenn Sensor sich im Freien befindet
|
|
931
|
+
* - (> 0) es regnet - Abbruch -
|
|
932
|
+
* - (≤ 0) Start der Bewässerung
|
|
933
|
+
*
|
|
934
|
+
* @param inGreenhouse - Sensor befindet sich im Gewächshaus
|
|
935
|
+
* @returns - resultierende Regenmenge
|
|
936
|
+
*/
|
|
937
|
+
function resRain (inGreenhouse) {
|
|
938
|
+
return (adapter.config.weatherForecast && !inGreenhouse) ? (((+ weatherForecastTodayNum) - parseFloat(adapter.config.thresholdRain)).toFixed(1)) : 0;
|
|
939
|
+
}
|
|
940
|
+
// Bewässerung mit Zisterne? Füllstand anzeigen
|
|
941
|
+
if (adapter.config.cisternSettings === true) messageText += `${valveControl.getStatusCistern()}\n`;
|
|
942
|
+
|
|
943
|
+
for(const res of result) {
|
|
944
|
+
let messageTextZeile1 = '';
|
|
945
|
+
let messageTextZeile2 = '';
|
|
946
|
+
messageTextZeile1 = `<b>${res.objectName}</b>`;
|
|
947
|
+
switch (res.methodControlSM) {
|
|
948
|
+
case 'bistable':
|
|
949
|
+
messageTextZeile1 += ` (${res.soilMoisture.bool})`;
|
|
950
|
+
break;
|
|
951
|
+
case 'analog':
|
|
952
|
+
messageTextZeile1 += ` ${res.soilMoisture.pct}% (${res.soilMoisture.pctTriggerIrrigation}%)`;
|
|
953
|
+
break;
|
|
954
|
+
case 'fixDay':
|
|
955
|
+
//messageTextZeile1 += ` (${curNextFixDay(res.sprinkleID, true)})`;
|
|
956
|
+
break;
|
|
957
|
+
case 'calculation':
|
|
958
|
+
messageTextZeile1 += ` ${res.soilMoisture.pct}% (${res.soilMoisture.pctTriggerIrrigation}%)`;
|
|
959
|
+
break;
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
// Test Bodenfeuchte
|
|
963
|
+
adapter.log.debug(`Bodenfeuchte: ${res.soilMoisture.val} <= ${res.soilMoisture.triggersIrrigation} AutoOn: ${res.autoOn}`);
|
|
964
|
+
if (res.autoOn) {
|
|
965
|
+
switch (res.methodControlSM) {
|
|
966
|
+
// -- bistable -- Bodenfeuchte-Sensor mit 2-Punkt-Regler true und false -- //
|
|
967
|
+
case 'bistable':
|
|
968
|
+
if(res.soilMoisture.bool) {
|
|
969
|
+
/* Wenn in der Config Regenvorhersage aktiviert: Startvorgang abbrechen, wenn der Regen den eingegebenen Schwellwert überschreitet. */
|
|
970
|
+
if (resRain(res.inGreenhouse) <= 0) {
|
|
971
|
+
const curWateringTime = Math.round(60 * res.wateringTime * evaporation.timeExtension(res.wateringAdd));
|
|
972
|
+
memAddList.push({
|
|
973
|
+
auto: true,
|
|
974
|
+
sprinkleID: res.sprinkleID,
|
|
975
|
+
wateringTime: curWateringTime
|
|
976
|
+
});
|
|
977
|
+
messageTextZeile2 += `START => ${addTime(curWateringTime, '')}`;
|
|
978
|
+
} else if (adapter.config.weatherForecast) {
|
|
979
|
+
/* Bewässerung unterdrückt da ausreichende Regenvorhersage */
|
|
980
|
+
messageTextZeile2 += `<i>Start verschoben, da heute ${weatherForecastTodayNum}mm Niederschlag</i>`;
|
|
981
|
+
adapter.log.info(`${res.objectName}: Start verschoben, da Regenvorhersage für Heute ${weatherForecastTodayNum} mm [ ${resRain(res.inGreenhouse)} > 0 ]`);
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
break;
|
|
985
|
+
// --- analog -- Bodenfeuchte-Sensor im Wertebereich von 0 bis 100% --- //
|
|
986
|
+
// -- Prozentuale Bodenfeuchte zu gering -- //
|
|
987
|
+
case 'analog':
|
|
988
|
+
if(res.soilMoisture.pct <= res.soilMoisture.pctTriggerIrrigation) {
|
|
989
|
+
/* Wenn in der Config Regenvorhersage aktiviert: Startvorgang abbrechen, wenn der Regen den eingegebenen Schwellwert überschreitet. */
|
|
990
|
+
if (resRain(res.inGreenhouse) <= 0) {
|
|
991
|
+
let countdown = res.wateringTime * (100 - res.soilMoisture.pct) / (100 - res.soilMoisture.pctTriggerIrrigation); // in min
|
|
992
|
+
// Begrenzung der Bewässerungszeit auf dem in der Config eingestellten Überschreitung (in Prozent)
|
|
993
|
+
if (countdown > (res.wateringTime * res.wateringAdd / 100)) {
|
|
994
|
+
countdown = res.wateringTime * res.wateringAdd / 100;
|
|
995
|
+
}
|
|
996
|
+
memAddList.push({
|
|
997
|
+
auto: true,
|
|
998
|
+
sprinkleID: res.sprinkleID,
|
|
999
|
+
wateringTime: Math.round(60* countdown)
|
|
1000
|
+
});
|
|
1001
|
+
messageTextZeile2 += `START => ${addTime(Math.round(60*countdown), '')}`;
|
|
1002
|
+
} else if (adapter.config.weatherForecast) {
|
|
1003
|
+
/* Bewässerung unterdrückt da ausreichende Regenvorhersage */
|
|
1004
|
+
messageTextZeile2 += `<i>Start verschoben, da heute ${weatherForecastTodayNum}mm Niederschlag</i> `;
|
|
1005
|
+
adapter.log.info(`${res.objectName}: Start verschoben, da Regenvorhersage für Heute ${weatherForecastTodayNum} mm [ ${resRain(res.inGreenhouse)} > 0 ]`);
|
|
1006
|
+
}
|
|
1007
|
+
}
|
|
1008
|
+
break;
|
|
1009
|
+
// --- fixDay -- Start an festen Tagen ohne Sensoren --- //
|
|
1010
|
+
// -- Bewässerungstag erreicht //
|
|
1011
|
+
case 'fixDay':
|
|
1012
|
+
/* Wenn in der Config Regenvorhersage aktiviert: Startvorgang abbrechen, wenn der Regen den eingegebenen Schwellwert überschreitet. */
|
|
1013
|
+
if (resRain(res.inGreenhouse) <= 0) {
|
|
1014
|
+
// Bewässerungstag erreicht
|
|
1015
|
+
if (res.startFixDay[today]) {
|
|
1016
|
+
const curWateringTime = Math.round(60 * res.wateringTime * evaporation.timeExtension(res.wateringAdd));
|
|
1017
|
+
memAddList.push({
|
|
1018
|
+
auto: true,
|
|
1019
|
+
sprinkleID: res.sprinkleID,
|
|
1020
|
+
wateringTime: curWateringTime
|
|
1021
|
+
});
|
|
1022
|
+
messageTextZeile2 += `START => ${addTime(curWateringTime, '')}`;
|
|
1023
|
+
if (res.startDay === 'threeRd'){ // Next Start in 3 Tagen
|
|
1024
|
+
res.startFixDay[today] = false;
|
|
1025
|
+
res.startFixDay[(+ today + 3 > 6) ? (+ today-4) : (+ today+3)] = true;
|
|
1026
|
+
}else if (res.startDay === 'twoNd') { // Next Start in 2 Tagen
|
|
1027
|
+
res.startFixDay[today] = false;
|
|
1028
|
+
res.startFixDay[(+ today + 2 > 6) ? (+ today-5) : (+ today+2)] = true;
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
} else if (adapter.config.weatherForecast){
|
|
1032
|
+
messageTextZeile2 += `<i>Start verschoben, da heute ${weatherForecastTodayNum}mm Niederschlag</i>`;
|
|
1033
|
+
adapter.log.info(`${res.objectName}: Start verschoben, da Regenvorhersage für Heute ${weatherForecastTodayNum} mm [ ${resRain(false)} > 0 ]`);
|
|
1034
|
+
if ((res.startDay === 'threeRd') || (res.startDay === 'twoNd')) {
|
|
1035
|
+
let startDay = -1;
|
|
1036
|
+
res.startFixDay.forEach((item, index) => {
|
|
1037
|
+
if (item) {
|
|
1038
|
+
startDay = index;
|
|
1039
|
+
}
|
|
1040
|
+
});
|
|
1041
|
+
if (startDay !== -1) {
|
|
1042
|
+
res.startFixDay[startDay] = false;
|
|
1043
|
+
res.startFixDay[(+ startDay + 1 > 6) ? (+ startDay-6) : (+ startDay+1)] = true;
|
|
1044
|
+
} else {
|
|
1045
|
+
adapter.log.warn(`${res.objectName}: no start day found`);
|
|
1046
|
+
}
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
1049
|
+
curNextFixDay(res.sprinkleID, false);
|
|
1050
|
+
messageTextZeile1 += ` (${curNextFixDay(res.sprinkleID, true)})`;
|
|
1051
|
+
break;
|
|
1052
|
+
// --- calculation -- Berechnung der Bodenfeuchte --- //
|
|
1053
|
+
// -- Bodenfeuchte zu gering -- //
|
|
1054
|
+
case 'calculation':
|
|
1055
|
+
if (res.soilMoisture.val <= res.soilMoisture.triggersIrrigation) {
|
|
1056
|
+
/* Wenn in der Config Regenvorhersage aktiviert: Startvorgang abbrechen, wenn es heute ausreichend regnen sollte. */
|
|
1057
|
+
const resMoisture = (adapter.config.weatherForecast)?((+ res.soilMoisture.val) + (+ weatherForecastTodayNum) - parseFloat(adapter.config.thresholdRain)):(res.soilMoisture.val); // aktualisierte Bodenfeuchte mit Regenvorhersage
|
|
1058
|
+
if ((resMoisture <= res.soilMoisture.triggersIrrigation) || res.inGreenhouse) { // Kontrolle ob Regenvorhersage ausreicht || Bewässerung inGreenhouse
|
|
1059
|
+
let countdown = res.wateringTime * (res.soilMoisture.maxIrrigation - res.soilMoisture.val) / (res.soilMoisture.maxIrrigation - res.soilMoisture.triggersIrrigation); // in min
|
|
1060
|
+
// Begrenzung der Bewässerungszeit auf dem in der Config eingestellten Überschreitung (in Prozent)
|
|
1061
|
+
if (countdown > (res.wateringTime * res.wateringAdd / 100)) {
|
|
1062
|
+
countdown = res.wateringTime * res.wateringAdd / 100;
|
|
1063
|
+
}
|
|
1064
|
+
memAddList.push({
|
|
1065
|
+
auto: true,
|
|
1066
|
+
sprinkleID: res.sprinkleID,
|
|
1067
|
+
wateringTime: Math.round(60*countdown)
|
|
1068
|
+
});
|
|
1069
|
+
messageTextZeile2 += `START => ${addTime(Math.round(60*countdown), '')}`;
|
|
1070
|
+
} else if (adapter.config.weatherForecast) {
|
|
1071
|
+
/* Bewässerung unterdrückt da ausreichende Regenvorhersage */
|
|
1072
|
+
messageTextZeile2 += `<i>Start verschoben, da heute ${weatherForecastTodayNum}mm Niederschlag</i>`;
|
|
1073
|
+
adapter.log.info(`${res.objectName}: Start verschoben, da Regenvorhersage für Heute ${weatherForecastTodayNum} mm [ ${res.soilMoisture.val.toFixed(1)} (${resMoisture.toFixed(1)}) <= ${res.soilMoisture.triggersIrrigation} ]`);
|
|
1074
|
+
}
|
|
1075
|
+
}
|
|
1076
|
+
break;
|
|
1077
|
+
}
|
|
1078
|
+
} else {
|
|
1079
|
+
messageTextZeile2 += `<i>Ventil auf Handbetrieb</i> `;
|
|
1080
|
+
}
|
|
1081
|
+
messageText += (messageTextZeile2.length > 0) ? (`${messageTextZeile1}\n ${messageTextZeile2}\n`) : (`${messageTextZeile1}\n`);
|
|
1082
|
+
}
|
|
1083
|
+
valveControl.addList(memAddList);
|
|
1084
|
+
}
|
|
1085
|
+
if(!sendMessageText.onlySendError()){
|
|
1086
|
+
sendMessageText.sendMessage(messageText);
|
|
1087
|
+
}
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
//
|
|
1091
|
+
async function createSprinklers() {
|
|
1092
|
+
/**Creates an Object .control.addStartTimeSwitch, when additional watering has been activated via an external signal
|
|
1093
|
+
* - Erzeugt ein Object .control.addStartTimeSwitch, wenn die Zusatzbewässerung über ein externes Signal aktiviert wurde
|
|
1094
|
+
* @type {{id: string, name: string} | void}
|
|
1095
|
+
* @private
|
|
1096
|
+
*/
|
|
1097
|
+
const _addStartTimeSwitch = await adapter.findForeignObjectAsync(`${adapter.namespace}.control.addStartTimeSwitch`, 'boolean').catch((e) => adapter.log.warn(`.control.addStartTimeSwitch ${e}`));
|
|
1098
|
+
if (_addStartTimeSwitch.id !== `${adapter.namespace}.control.addStartTimeSwitch` && adapter.config.selectAddStartTime === 'withExternalSignal') {
|
|
1099
|
+
adapter.setObjectNotExistsAsync(`${adapter.namespace}.control.addStartTimeSwitch`, {
|
|
1100
|
+
type: 'state',
|
|
1101
|
+
common: {
|
|
1102
|
+
role: 'switch',
|
|
1103
|
+
name: {
|
|
1104
|
+
en: "additional irrigation enabled",
|
|
1105
|
+
de: "weitere Bewässerung aktiviert",
|
|
1106
|
+
ru: "включено дополнительное орошение",
|
|
1107
|
+
pt: "irrigação adicional ativada",
|
|
1108
|
+
nl: "extra irrigatie mogelijk",
|
|
1109
|
+
fr: "arrosage supplémentaire activé",
|
|
1110
|
+
it: "irrigazione extra abilitata",
|
|
1111
|
+
es: "riego adicional habilitado",
|
|
1112
|
+
pl: "włączone dodatkowe nawadnianie",
|
|
1113
|
+
uk: "додаткове зрошення включено",
|
|
1114
|
+
"zh-cn": "已启用额外灌溉"
|
|
1115
|
+
},
|
|
1116
|
+
type: 'boolean',
|
|
1117
|
+
read: true,
|
|
1118
|
+
write: true,
|
|
1119
|
+
def: false
|
|
1120
|
+
},
|
|
1121
|
+
native: {}
|
|
1122
|
+
}).catch((e) => adapter.log.warn(`.control.addStartTimeSwitch ${e}`));
|
|
1123
|
+
} else if (_addStartTimeSwitch.id === `${adapter.namespace}.control.addStartTimeSwitch`) {
|
|
1124
|
+
if (adapter.config.selectAddStartTime !== 'withExternalSignal') {
|
|
1125
|
+
adapter.delObjectAsync(`${adapter.namespace}.control.addStartTimeSwitch`).catch((e) => adapter.log.warn(`.control.addStartTimeSwitch ${e}`));
|
|
1126
|
+
addStartTimeSwitch = false;
|
|
1127
|
+
} else {
|
|
1128
|
+
/**
|
|
1129
|
+
* auslesen .control.addStartTimeSwitch.val
|
|
1130
|
+
*/
|
|
1131
|
+
const _state = await adapter.getStateAsync(`${adapter.namespace}.control.addStartTimeSwitch`).catch((e) => adapter.log.warn(`.control.addStartTimeSwitch ${e}`));
|
|
1132
|
+
if (typeof _state.val === 'boolean') {
|
|
1133
|
+
addStartTimeSwitch = _state.val;
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
|
|
1139
|
+
|
|
1140
|
+
const result = adapter.config.events;
|
|
1141
|
+
if (result) {
|
|
1142
|
+
for(const res of result) {
|
|
1143
|
+
let objectName;
|
|
1144
|
+
|
|
1145
|
+
if(res.sprinkleName !== '') {
|
|
1146
|
+
objectName = res.sprinkleName.replace(/[.;, ]/g, '_');
|
|
1147
|
+
} else if (res.sprinkleName === '') {
|
|
1148
|
+
objectName = res.name.replace(/[.;, ]/g, '_');
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1151
|
+
const objPfad = `sprinkle.${objectName}`;
|
|
1152
|
+
const j = myConfig.config.findIndex(d => d.objectName === objectName);
|
|
1153
|
+
|
|
1154
|
+
// Create bzw. update .actualSoilMoisture
|
|
1155
|
+
|
|
1156
|
+
let nameMetConSM, objMetConSM;
|
|
1157
|
+
await fillMetConSM(res);
|
|
1158
|
+
async function fillMetConSM(res) {
|
|
1159
|
+
//adapter.log.debug(JSON.stringify(res));
|
|
1160
|
+
switch (res.methodControlSM) {
|
|
1161
|
+
case 'calculation':
|
|
1162
|
+
nameMetConSM = {
|
|
1163
|
+
en: `${objectName} => Calculated soil moisture in %`,
|
|
1164
|
+
de: `${objectName} => Berechnete Bodenfeuchte in%`,
|
|
1165
|
+
ru: `${objectName} => Расчетная влажность почвы в%`,
|
|
1166
|
+
pt: `${objectName} => Umidade do solo calculada em%`,
|
|
1167
|
+
nl: `${objectName} => Berekend bodemvocht in%`,
|
|
1168
|
+
fr: `${objectName} => Humidité du sol calculée en %`,
|
|
1169
|
+
it: `${objectName} => Umidità del suolo in%`,
|
|
1170
|
+
es: `${objectName} => Humedad del suelo calculada en%`,
|
|
1171
|
+
pl: `${objectName} => Obliczona wilgotność gleby w%`,
|
|
1172
|
+
uk: `${objectName} => Розрахована вологість ґрунту в%`,
|
|
1173
|
+
"zh-cn": `${objectName} => 计算出的土壤湿度百分比`
|
|
1174
|
+
};
|
|
1175
|
+
objMetConSM = {
|
|
1176
|
+
type: 'state',
|
|
1177
|
+
common: {
|
|
1178
|
+
role: 'state',
|
|
1179
|
+
name: nameMetConSM,
|
|
1180
|
+
type: 'number',
|
|
1181
|
+
min: 0,
|
|
1182
|
+
max: 150,
|
|
1183
|
+
unit: '%',
|
|
1184
|
+
read: true,
|
|
1185
|
+
write: false,
|
|
1186
|
+
def: 50
|
|
1187
|
+
},
|
|
1188
|
+
native: {},
|
|
1189
|
+
};
|
|
1190
|
+
break;
|
|
1191
|
+
case 'bistable':
|
|
1192
|
+
nameMetConSM = {
|
|
1193
|
+
en: `${objectName} => bistable soil moisture sensor`,
|
|
1194
|
+
de: `${objectName} => Bistabiler Bodenfeuchtesensor`,
|
|
1195
|
+
ru: `${objectName} => бистабильный датчик влажности почвы`,
|
|
1196
|
+
pt: `${objectName} => sensor biestável de umidade`,
|
|
1197
|
+
nl: `${objectName} => bistabiele bodemvochtsensor`,
|
|
1198
|
+
fr: `${objectName} => capteur d'humidité du sol bistable`,
|
|
1199
|
+
it: `${objectName} => sensore di umidità bistabile`,
|
|
1200
|
+
es: `${objectName} => sensor biestable de humedad`,
|
|
1201
|
+
pl: `${objectName} => bistabilny czujnik wilgotności gleby`,
|
|
1202
|
+
uk: `${objectName} => бістабільний датчик вологості ґрунту`,
|
|
1203
|
+
"zh-cn": `${objectName} => 双稳态土壤湿度传感器`
|
|
1204
|
+
};
|
|
1205
|
+
objMetConSM = {
|
|
1206
|
+
type: 'state',
|
|
1207
|
+
common: {
|
|
1208
|
+
role: 'state',
|
|
1209
|
+
name: nameMetConSM,
|
|
1210
|
+
type: 'boolean',
|
|
1211
|
+
read: true,
|
|
1212
|
+
write: false,
|
|
1213
|
+
def: false
|
|
1214
|
+
},
|
|
1215
|
+
native: {},
|
|
1216
|
+
};
|
|
1217
|
+
break;
|
|
1218
|
+
case 'analog':
|
|
1219
|
+
nameMetConSM = {
|
|
1220
|
+
en: `${objectName} => analog soil moisture sensor in %`,
|
|
1221
|
+
de: `${objectName} => analoger Bodenfeuchtesensor in%`,
|
|
1222
|
+
ru: `${objectName} => аналоговый датчик влажности почвы в%`,
|
|
1223
|
+
pt: `${objectName} => sensor analógico de umidade em%`,
|
|
1224
|
+
nl: `${objectName} => analoge bodemvochtsensor in%`,
|
|
1225
|
+
fr: `${objectName} => capteur d'humidité du sol analogique en %`,
|
|
1226
|
+
it: `${objectName} => sensore umidità analogico in%`,
|
|
1227
|
+
es: `${objectName} => sensor analógico de humedad en%`,
|
|
1228
|
+
pl: `${objectName} => analogowy czujnik wilgotności gleby w%`,
|
|
1229
|
+
uk: `${objectName} => аналоговий датчик вологості ґрунту в%`,
|
|
1230
|
+
"zh-cn": `${objectName} => 模拟土壤湿度传感器,单位为%`
|
|
1231
|
+
};
|
|
1232
|
+
objMetConSM = {
|
|
1233
|
+
type: 'state',
|
|
1234
|
+
common: {
|
|
1235
|
+
role: 'state',
|
|
1236
|
+
name: nameMetConSM,
|
|
1237
|
+
type: 'number',
|
|
1238
|
+
min: 0,
|
|
1239
|
+
max: 150,
|
|
1240
|
+
unit: '%',
|
|
1241
|
+
read: true,
|
|
1242
|
+
write: false
|
|
1243
|
+
},
|
|
1244
|
+
native: {},
|
|
1245
|
+
};
|
|
1246
|
+
break;
|
|
1247
|
+
case 'fixDay':
|
|
1248
|
+
nameMetConSM = {
|
|
1249
|
+
en: `${objectName} => start on a fixed day`,
|
|
1250
|
+
de: `${objectName} => start an einem festen Tag`,
|
|
1251
|
+
ru: `${objectName} => начните в определенный день`,
|
|
1252
|
+
pt: `${objectName} => começa em dia fixo`,
|
|
1253
|
+
nl: `${objectName} => start op een vaste dag`,
|
|
1254
|
+
fr: `${objectName} => commence un jour fixe`,
|
|
1255
|
+
it: `${objectName} => inizio a un giorno`,
|
|
1256
|
+
es: `${objectName} => empezar un día fijo`,
|
|
1257
|
+
pl: `${objectName} => zacznij w ustalonym dniu`,
|
|
1258
|
+
uk: `${objectName} => початок у фіксований день`,
|
|
1259
|
+
"zh-cn": `${objectName} => 在固定的日期开始`
|
|
1260
|
+
};
|
|
1261
|
+
objMetConSM = {
|
|
1262
|
+
type: 'state',
|
|
1263
|
+
common: {
|
|
1264
|
+
role: 'state',
|
|
1265
|
+
name: nameMetConSM,
|
|
1266
|
+
type: 'number',
|
|
1267
|
+
min: 0,
|
|
1268
|
+
max: 7,
|
|
1269
|
+
states: {0:'Sun', 1:'Mon', 2:'Tue', 3:'Wed', 4:'Thur', 5:'Fri', 6:'Sat', 7:'off'},
|
|
1270
|
+
read: true,
|
|
1271
|
+
write: false,
|
|
1272
|
+
def: 7
|
|
1273
|
+
},
|
|
1274
|
+
native: {},
|
|
1275
|
+
};
|
|
1276
|
+
break;
|
|
1277
|
+
default:
|
|
1278
|
+
adapter.log.warn(`sprinkleControl cannot created ... Please check your sprinkleControl config ${objectName} methodControl`);
|
|
1279
|
+
nameMetConSM = {
|
|
1280
|
+
en: `${objectName} => Emergency program! start on a fixed day`,
|
|
1281
|
+
de: `${objectName} => Notfallprogramm! start an einem festen Tag`,
|
|
1282
|
+
ru: `${objectName} => Экстренная программа! начните в определенный день`,
|
|
1283
|
+
pt: `${objectName} => Programa urgente! comece em dia fixo`,
|
|
1284
|
+
nl: `${objectName} => Noodprogramma! op een vaste dag beginnen`,
|
|
1285
|
+
fr: `${objectName} => Programme d'urgence ! commencer un jour fixe`,
|
|
1286
|
+
it: `${objectName} => Emergenze! inizio a data fissa`,
|
|
1287
|
+
es: `${objectName} => ¡Programa de emergencia! empezar un día fijo`,
|
|
1288
|
+
pl: `${objectName} => Program awaryjny! zacznij w ustalonym dniu`,
|
|
1289
|
+
uk: `${objectName} => Екстрена програма! початок у визначений день`,
|
|
1290
|
+
"zh-cn": `${objectName} => 紧急计划!从固定的日子开始`
|
|
1291
|
+
};
|
|
1292
|
+
objMetConSM = {
|
|
1293
|
+
type: 'state',
|
|
1294
|
+
common: {
|
|
1295
|
+
role: 'state',
|
|
1296
|
+
name: nameMetConSM,
|
|
1297
|
+
type: 'number',
|
|
1298
|
+
min: 0,
|
|
1299
|
+
max: 7,
|
|
1300
|
+
states: {0:'Sun', 1:'Mon', 2:'Tue', 3:'Wed', 4:'Thur', 5:'Fri', 6:'Sat', 7:'off'},
|
|
1301
|
+
read: true,
|
|
1302
|
+
write: false,
|
|
1303
|
+
def: 7
|
|
1304
|
+
},
|
|
1305
|
+
native: {},
|
|
1306
|
+
};
|
|
1307
|
+
}
|
|
1308
|
+
}
|
|
1309
|
+
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
|
|
1310
|
+
// +++++ Objekte erstellen +++++ //
|
|
1311
|
+
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
|
|
1312
|
+
if (objectName && objectName !== '') {
|
|
1313
|
+
try {
|
|
1314
|
+
// Create Object for sprinkle. (ID)
|
|
1315
|
+
const _sprinkleNotExist = await adapter.setObjectNotExistsAsync(`sprinkle.${objectName}`, {
|
|
1316
|
+
type: 'channel',
|
|
1317
|
+
common: {
|
|
1318
|
+
name: res.sprinkleName
|
|
1319
|
+
},
|
|
1320
|
+
native: {},
|
|
1321
|
+
});
|
|
1322
|
+
// Create Object for .history
|
|
1323
|
+
const _historyNotExist = await adapter.setObjectNotExistsAsync(`sprinkle.${objectName}.history`, {
|
|
1324
|
+
type: 'channel',
|
|
1325
|
+
common: {
|
|
1326
|
+
name: {
|
|
1327
|
+
en: `${res.sprinkleName} => History`,
|
|
1328
|
+
de: `${res.sprinkleName} => Verlauf`,
|
|
1329
|
+
ru: `${res.sprinkleName} => История`,
|
|
1330
|
+
pt: `${res.sprinkleName} => História`,
|
|
1331
|
+
nl: `${res.sprinkleName} => Geschiedenis`,
|
|
1332
|
+
fr: `${res.sprinkleName} => Histoire`,
|
|
1333
|
+
it: `${res.sprinkleName} => Storia`,
|
|
1334
|
+
es: `${res.sprinkleName} => Historia`,
|
|
1335
|
+
pl: `${res.sprinkleName} => Historia`,
|
|
1336
|
+
uk: `${res.sprinkleName} => Історія`,
|
|
1337
|
+
"zh-cn": `${res.sprinkleName} => 历史`
|
|
1338
|
+
}
|
|
1339
|
+
},
|
|
1340
|
+
native: {},
|
|
1341
|
+
});
|
|
1342
|
+
// Create Object for .history.curCalWeekConsumed
|
|
1343
|
+
// Sprinkler consumption of the current calendar week => History - Sprinkler-Verbrauch der aktuellen Kalenderwoche (783 Liter)
|
|
1344
|
+
const _curCalWeekConsumedNotExist = adapter.setObjectNotExistsAsync(`${objPfad}.history.curCalWeekConsumed`, {
|
|
1345
|
+
type: 'state',
|
|
1346
|
+
common: {
|
|
1347
|
+
role: 'state',
|
|
1348
|
+
name: {
|
|
1349
|
+
en: `${objectName} => History - Sprinkler consumption of the current calendar week`,
|
|
1350
|
+
de: `${objectName} => Verlauf — Sprinklerverbrauch der aktuellen Woche`,
|
|
1351
|
+
ru: `${objectName} => История - потребление спринклеров за текущую календарную неделю`,
|
|
1352
|
+
pt: `${objectName} => Histórico - Consumo de sprinklers na semana atual`,
|
|
1353
|
+
nl: `${objectName} => Geschiedenis - Sprinklerverbruik van de huidige kalenderweek`,
|
|
1354
|
+
fr: `${objectName} => Historique - Consommation de gicleurs de la semaine en cours`,
|
|
1355
|
+
it: `${objectName} => Cronologia - Consumo di irrigatori nella settimana corrente`,
|
|
1356
|
+
es: `${objectName} => Historial: consumo de rociadores en la semana natural actual`,
|
|
1357
|
+
pl: `${objectName} => Historia - Zużycie tryskaczy w bieżącym tygodniu kalendarzowym`,
|
|
1358
|
+
uk: `${objectName} => Історія - Споживання спринклерів поточного календарного тижня`,
|
|
1359
|
+
"zh-cn": `${objectName} => 历史-当前日历周的洒水消耗量`
|
|
1360
|
+
},
|
|
1361
|
+
type: 'number',
|
|
1362
|
+
unit: 'Liter',
|
|
1363
|
+
read: true,
|
|
1364
|
+
write: false,
|
|
1365
|
+
def: 0
|
|
1366
|
+
},
|
|
1367
|
+
native: {},
|
|
1368
|
+
});
|
|
1369
|
+
// Create Object for .history.curCalWeekRunningTime
|
|
1370
|
+
// Sprinkler running time of the current calendar week => History - Sprinkler-Laufzeit der aktuellen Kalenderwoche (783 Liter)
|
|
1371
|
+
const _curCalWeekRunningTimeNotExist = adapter.setObjectNotExistsAsync(`${objPfad}.history.curCalWeekRunningTime`, {
|
|
1372
|
+
type: 'state',
|
|
1373
|
+
common: {
|
|
1374
|
+
role: 'state',
|
|
1375
|
+
name: {
|
|
1376
|
+
en: `${objectName} => History - Sprinkler running time of the current calendar week`,
|
|
1377
|
+
de: `${objectName} => Verlauf — Sprinklerlaufzeit der aktuellen Woche`,
|
|
1378
|
+
ru: `${objectName} => История - время работы спринклеров на текущей календарной неделе`,
|
|
1379
|
+
pt: `${objectName} => Histórico - Tempo de operação do sprinkler na semana atual`,
|
|
1380
|
+
nl: `${objectName} => Geschiedenis - De looptijd van de sprinkler in de huidige kalenderweek`,
|
|
1381
|
+
fr: `${objectName} => Historique - Durée du gicleur pour la semaine civile en cours`,
|
|
1382
|
+
it: `${objectName} => Cronologia - Durata dell'irrigatore nella settimana corrente`,
|
|
1383
|
+
es: `${objectName} => Historia: duración de los rociadores de la semana actual`,
|
|
1384
|
+
pl: `${objectName} => Historia - Czas pracy tryskacza bieżącego tygodnia kalendarzowego`,
|
|
1385
|
+
uk: `${objectName} => Історія - Час роботи спринклера поточного календарного тижня`,
|
|
1386
|
+
"zh-cn": `${objectName} => 历史-当前日历周的洒水器运行时间`
|
|
1387
|
+
},
|
|
1388
|
+
type: 'string',
|
|
1389
|
+
read: true,
|
|
1390
|
+
write: false,
|
|
1391
|
+
def: '00:00'
|
|
1392
|
+
},
|
|
1393
|
+
native: {},
|
|
1394
|
+
});
|
|
1395
|
+
// Create Object for .history.lastCalWeekConsumed
|
|
1396
|
+
// Sprinkler consumption of the last calendar week => History - Sprinkler-Verbrauch der letzten Kalenderwoche (783 Liter)
|
|
1397
|
+
const _lastCalWeekConsumedNotExist = adapter.setObjectNotExistsAsync(`${objPfad}.history.lastCalWeekConsumed`, {
|
|
1398
|
+
type: 'state',
|
|
1399
|
+
common: {
|
|
1400
|
+
role: 'state',
|
|
1401
|
+
name: {
|
|
1402
|
+
en: `${objectName} => History - Sprinkler consumption of the last calendar week`,
|
|
1403
|
+
de: `${objectName} => Verlauf — Sprinklerverbrauch der letzten Woche`,
|
|
1404
|
+
ru: `${objectName} => История - потребление спринклеров за последнюю календарную неделю`,
|
|
1405
|
+
pt: `${objectName} => Histórico - Consumo de sprinklers na última semana`,
|
|
1406
|
+
nl: `${objectName} => Geschiedenis - Sprinklerverbruik van de laatste kalenderweek`,
|
|
1407
|
+
fr: `${objectName} => Historique - Consommation de gicleurs la semaine dernière`,
|
|
1408
|
+
it: `${objectName} => Cronologia - Consumo di irrigatori nell'ultima settimana`,
|
|
1409
|
+
es: `${objectName} => Historia: consumo de rociadores de la última semana natural`,
|
|
1410
|
+
pl: `${objectName} => Historia - Zużycie tryskaczy w ostatnim tygodniu kalendarzowym`,
|
|
1411
|
+
uk: `${objectName} => Історія - Споживання спринклерів за останній календарний тиждень`,
|
|
1412
|
+
"zh-cn": `${objectName} => 历史-上个日历周的洒水消耗量`
|
|
1413
|
+
},
|
|
1414
|
+
type: 'number',
|
|
1415
|
+
unit: 'Liter',
|
|
1416
|
+
read: true,
|
|
1417
|
+
write: false,
|
|
1418
|
+
def: 0
|
|
1419
|
+
},
|
|
1420
|
+
native: {},
|
|
1421
|
+
});
|
|
1422
|
+
// Create Object for .history.lastCalWeekRunningTime
|
|
1423
|
+
// Sprinkler running time of the last calendar week => History - Sprinkler-Laufzeit der letzten Kalenderwoche (783 Liter)
|
|
1424
|
+
const _lastCalWeekRunningTimeNotExist = adapter.setObjectNotExistsAsync(`${objPfad}.history.lastCalWeekRunningTime`, {
|
|
1425
|
+
type: 'state',
|
|
1426
|
+
common: {
|
|
1427
|
+
role: 'state',
|
|
1428
|
+
name: {
|
|
1429
|
+
en: `${objectName} => History - Sprinkler running time of the last calendar week`,
|
|
1430
|
+
de: `${objectName} => Verlauf — Sprinklerlaufzeit der letzten Woche`,
|
|
1431
|
+
ru: `${objectName} => История - Время работы спринклеров за последнюю календарную неделю`,
|
|
1432
|
+
pt: `${objectName} => Histórico - Tempo de operação do sprinkler na última semana`,
|
|
1433
|
+
nl: `${objectName} => Geschiedenis - De looptijd van de sprinkler van de laatste kalenderweek`,
|
|
1434
|
+
fr: `${objectName} => Historique - Durée de fonctionnement du gicleur la semaine dernière`,
|
|
1435
|
+
it: `${objectName} => Storia - Durata dell'irrigatore nell'ultima settimana`,
|
|
1436
|
+
es: `${objectName} => Historia: funcionamiento de los rociadores de la última semana`,
|
|
1437
|
+
pl: `${objectName} => Historia - Czas pracy tryskacza w ostatnim tygodniu kalendarzowym`,
|
|
1438
|
+
uk: `${objectName} => Історія - Час роботи спринклерів за останній календарний тиждень`,
|
|
1439
|
+
"zh-cn": `${objectName} => 历史-上个日历周的洒水器运行时间`
|
|
1440
|
+
},
|
|
1441
|
+
type: 'string',
|
|
1442
|
+
read: true,
|
|
1443
|
+
write: false,
|
|
1444
|
+
def: '00:00'
|
|
1445
|
+
},
|
|
1446
|
+
native: {},
|
|
1447
|
+
});
|
|
1448
|
+
// Create Object for .history.lastConsumed
|
|
1449
|
+
// Last consumed of sprinkler => History - Letzte Verbrauchsmenge des Ventils (783 Liter)
|
|
1450
|
+
const _lastConsumedNotExist = adapter.setObjectNotExistsAsync(`${objPfad}.history.lastConsumed`, {
|
|
1451
|
+
type: 'state',
|
|
1452
|
+
common: {
|
|
1453
|
+
role: 'state',
|
|
1454
|
+
name: {
|
|
1455
|
+
en: `${objectName} => History - Last consumed of sprinkler`,
|
|
1456
|
+
de: `${objectName} => Historie — Letzter Sprinklerverbrauch`,
|
|
1457
|
+
ru: `${objectName} => История - Последнее потребление спринклера`,
|
|
1458
|
+
pt: `${objectName} => Histórico - Último consumo do aspersor`,
|
|
1459
|
+
nl: `${objectName} => Geschiedenis - Sprinkler voor het laatst verbruikt`,
|
|
1460
|
+
fr: `${objectName} => Historique - Dernier gicleur consommé`,
|
|
1461
|
+
it: `${objectName} => Storia - Ultimo uso di irrigatore`,
|
|
1462
|
+
es: `${objectName} => Historia: rociador consumido por última vez`,
|
|
1463
|
+
pl: `${objectName} => Historia - Ostatnie zużycie tryskacza`,
|
|
1464
|
+
uk: `${objectName} => Історія - Останнє споживання спринклера`,
|
|
1465
|
+
"zh-cn": `${objectName} => 历史-上次消耗的洒水器`
|
|
1466
|
+
},
|
|
1467
|
+
type: 'number',
|
|
1468
|
+
unit: 'Liter',
|
|
1469
|
+
read: true,
|
|
1470
|
+
write: false,
|
|
1471
|
+
def: 0
|
|
1472
|
+
},
|
|
1473
|
+
native: {},
|
|
1474
|
+
});
|
|
1475
|
+
// Create Object for .history.lastOn
|
|
1476
|
+
// Last On of sprinkler => History - Letzter Start des Ventils (30.03 06:30)
|
|
1477
|
+
const _lastOnNotExist = adapter.setObjectNotExistsAsync(`${objPfad}.history.lastOn`, {
|
|
1478
|
+
type: 'state',
|
|
1479
|
+
common: {
|
|
1480
|
+
role: 'state',
|
|
1481
|
+
name: {
|
|
1482
|
+
en: `${objectName} => History - Last On of sprinkler`,
|
|
1483
|
+
de: `${objectName} => Historie — Letzter Start des Sprinkler`,
|
|
1484
|
+
ru: `${objectName} => История - Последний включитель спринклера`,
|
|
1485
|
+
pt: `${objectName} => História - Último aspersor`,
|
|
1486
|
+
nl: `${objectName} => Geschiedenis - De laatste sprinkler`,
|
|
1487
|
+
fr: `${objectName} => Histoire - Dernier gicleur`,
|
|
1488
|
+
it: `${objectName} => Storia - Ultimo irrigatore`,
|
|
1489
|
+
es: `${objectName} => Historia: el último rociador`,
|
|
1490
|
+
pl: `${objectName} => Historia - Ostatnie włączenie tryskacza`,
|
|
1491
|
+
uk: `${objectName} => Історія - Остання увімкнення спринклера`,
|
|
1492
|
+
"zh-cn": `${objectName} => 历史-洒水器的最后一次`
|
|
1493
|
+
},
|
|
1494
|
+
type: 'string',
|
|
1495
|
+
read: true,
|
|
1496
|
+
write: false,
|
|
1497
|
+
def: '-'
|
|
1498
|
+
},
|
|
1499
|
+
native: {},
|
|
1500
|
+
});
|
|
1501
|
+
// Create Object for .history.lastRunningTime
|
|
1502
|
+
// Last running time of sprinkler => History - Letzte Laufzeit des Ventils (0 sek, 47:00 min, 1:03:45 )
|
|
1503
|
+
const _lastRunningTimeNotExist = adapter.setObjectNotExistsAsync(`${objPfad}.history.lastRunningTime`, {
|
|
1504
|
+
type: 'state',
|
|
1505
|
+
common: {
|
|
1506
|
+
role: 'state',
|
|
1507
|
+
name: {
|
|
1508
|
+
en: `${objectName} => History - Last running time`,
|
|
1509
|
+
de: `${objectName} => Verlauf — Letzte Laufzeit`,
|
|
1510
|
+
ru: `${objectName} => История - время последнего запуска`,
|
|
1511
|
+
pt: `${objectName} => Histórico - Última execução`,
|
|
1512
|
+
nl: `${objectName} => Geschiedenis - Laatste speeltijd`,
|
|
1513
|
+
fr: `${objectName} => Historique - Dernière diffusion`,
|
|
1514
|
+
it: `${objectName} => Storia - Ultima durata`,
|
|
1515
|
+
es: `${objectName} => Historia: última edición`,
|
|
1516
|
+
pl: `${objectName} => Historia - Ostatni czas trwania`,
|
|
1517
|
+
uk: `${objectName} => Історія - Останній час роботи`,
|
|
1518
|
+
"zh-cn": `${objectName} => 历史-上次运行时间`
|
|
1519
|
+
},
|
|
1520
|
+
type: 'string',
|
|
1521
|
+
read: true,
|
|
1522
|
+
write: false,
|
|
1523
|
+
def: '00:00'
|
|
1524
|
+
},
|
|
1525
|
+
native: {},
|
|
1526
|
+
});
|
|
1527
|
+
// Create Object for .autoOn
|
|
1528
|
+
const _autoOnNotExist = adapter.setObjectNotExistsAsync(`${objPfad}.autoOn`, {
|
|
1529
|
+
type: 'state',
|
|
1530
|
+
common: {
|
|
1531
|
+
role: 'Switch',
|
|
1532
|
+
name: {
|
|
1533
|
+
en: `${objectName} => Switch automatic mode on / off`,
|
|
1534
|
+
de: `${objectName} => Automatik ein-/ausschalten`,
|
|
1535
|
+
ru: `${objectName} => Включить/выключить автоматический режим`,
|
|
1536
|
+
pt: `${objectName} => Liga/desliga o modo automático`,
|
|
1537
|
+
nl: `${objectName} => Automatische modus in- en uitschakelen`,
|
|
1538
|
+
fr: `${objectName} => Activer/désactiver le mode automatique`,
|
|
1539
|
+
it: `${objectName} => Attiva/spegne automaticamente`,
|
|
1540
|
+
es: `${objectName} => Activar/desactivar el modo automático`,
|
|
1541
|
+
pl: `${objectName} => Włączanie/wyłączanie trybu automatycznego`,
|
|
1542
|
+
uk: `${objectName} => Увімкнути/вимкнути автоматичний режим`,
|
|
1543
|
+
"zh-cn": `${objectName} => 开启/关闭自动模式`
|
|
1544
|
+
},
|
|
1545
|
+
type: 'boolean',
|
|
1546
|
+
states: {
|
|
1547
|
+
false: 'off',
|
|
1548
|
+
true: 'on'
|
|
1549
|
+
},
|
|
1550
|
+
read: true,
|
|
1551
|
+
write: true,
|
|
1552
|
+
def: true
|
|
1553
|
+
},
|
|
1554
|
+
native: {},
|
|
1555
|
+
}).catch((e) => adapter.log.warn(`setObjectNotExistsAsync ${objectName}.autoOn ${e}`));
|
|
1556
|
+
// Create Object for .actualSoilMoisture
|
|
1557
|
+
const _actualSoilMoistureFind = await adapter.findForeignObjectAsync(`${adapter.namespace}.${objPfad}.actualSoilMoisture`, `${objMetConSM.common.type}`);
|
|
1558
|
+
if (_actualSoilMoistureFind.id !== `${adapter.namespace}.${objPfad}.actualSoilMoisture` || _actualSoilMoistureFind.name !== nameMetConSM) {
|
|
1559
|
+
await adapter.setObjectAsync(
|
|
1560
|
+
`${objPfad}.actualSoilMoisture`,
|
|
1561
|
+
objMetConSM
|
|
1562
|
+
).catch((e) => adapter.log.warn(e));
|
|
1563
|
+
adapter.log.info(`sprinkleControl [sprinkle.${objectName}.actualSoilMoisture] was updated`);
|
|
1564
|
+
}
|
|
1565
|
+
|
|
1566
|
+
// postponeByOneDay → um einen Tag verschieben bei fixDay (twoNd & threeRd)
|
|
1567
|
+
const _postponeByOneDay = await adapter.findForeignObjectAsync(`${adapter.namespace}.${objPfad}.postponeByOneDay`, `boolean`);
|
|
1568
|
+
if (_postponeByOneDay.id !== `${adapter.namespace}.${objPfad}.postponeByOneDay`
|
|
1569
|
+
&& res.methodControlSM === 'fixDay'
|
|
1570
|
+
&& (res.startDay === 'twoNd'
|
|
1571
|
+
|| res.startDay === 'threeRd')) {
|
|
1572
|
+
await adapter.setObjectNotExistsAsync(`${objPfad}.postponeByOneDay`, {
|
|
1573
|
+
type: 'state',
|
|
1574
|
+
common: {
|
|
1575
|
+
role: 'button',
|
|
1576
|
+
name: {
|
|
1577
|
+
en: `${objectName} Postpone start by one day`,
|
|
1578
|
+
de: `${objectName} Start um einen Tag verschieben`,
|
|
1579
|
+
ru: `${objectName} Отложите начало на один день`,
|
|
1580
|
+
pt: `${objectName} Adie o início em um dia`,
|
|
1581
|
+
nl: `${objectName} Start met een dag uitstellen`,
|
|
1582
|
+
fr: `${objectName} Reporter le début d'un jour`,
|
|
1583
|
+
it: `${objectName} Rinviare l'inizio di un giorno`,
|
|
1584
|
+
es: `${objectName} Posponer un día el inicio`,
|
|
1585
|
+
pl: `${objectName} Odłóż początek o jeden dzień`,
|
|
1586
|
+
uk: `${objectName} Відкладіть початок на один день`,
|
|
1587
|
+
"zh-cn": `${objectName} 推迟一天开始`
|
|
1588
|
+
},
|
|
1589
|
+
type: 'boolean',
|
|
1590
|
+
read: true,
|
|
1591
|
+
write: true,
|
|
1592
|
+
def: false
|
|
1593
|
+
},
|
|
1594
|
+
native: {
|
|
1595
|
+
UNIT: '',
|
|
1596
|
+
TAB_ORDER: 0,
|
|
1597
|
+
OPERATIONS: 6,
|
|
1598
|
+
FLAGS: 1,
|
|
1599
|
+
TYPE: 'ACTION',
|
|
1600
|
+
MIN: false,
|
|
1601
|
+
MAX: true,
|
|
1602
|
+
DEFAULT: false
|
|
1603
|
+
}
|
|
1604
|
+
});
|
|
1605
|
+
adapter.subscribeStates(`${adapter.namespace}.${objPfad}.postponeByOneDay`);
|
|
1606
|
+
} else if (res.methodControlSM === 'fixDay'
|
|
1607
|
+
&& (res.startDay === 'twoNd'
|
|
1608
|
+
|| res.startDay === 'threeRd')) {
|
|
1609
|
+
adapter.subscribeStates(`${adapter.namespace}.${objPfad}.postponeByOneDay`);
|
|
1610
|
+
} else {
|
|
1611
|
+
await adapter.delObjectAsync(`${adapter.namespace}.${objPfad}.postponeByOneDay`); // "sprinklecontrol.0.sprinkle.???.actualSoilMoisture"
|
|
1612
|
+
}
|
|
1613
|
+
|
|
1614
|
+
// Create Object for .countdown => Countdown des Ventils
|
|
1615
|
+
const _countdownNotExist = adapter.setObjectNotExistsAsync(`${objPfad}.countdown`, {
|
|
1616
|
+
type: 'state',
|
|
1617
|
+
common: {
|
|
1618
|
+
role: 'state',
|
|
1619
|
+
name: {
|
|
1620
|
+
en: `${objectName} => countdown of sprinkler`,
|
|
1621
|
+
de: `${objectName} => Sprinkler-Countdown`,
|
|
1622
|
+
ru: `${objectName} => обратный отсчет времени спринклера`,
|
|
1623
|
+
pt: `${objectName} => contagem do aspersor`,
|
|
1624
|
+
nl: `${objectName} => aftellen van de sprinkler`,
|
|
1625
|
+
fr: `${objectName} => compte à rebours`,
|
|
1626
|
+
it: `${objectName} => conto alla rovescia`,
|
|
1627
|
+
es: `${objectName} => cuenta atrás del aspersor`,
|
|
1628
|
+
pl: `${objectName} => odliczanie tryskacza`,
|
|
1629
|
+
uk: `${objectName} => зворотний відлік спринклера`,
|
|
1630
|
+
"zh-cn": `${objectName} => 洒水器倒计时`
|
|
1631
|
+
},
|
|
1632
|
+
type: 'string',
|
|
1633
|
+
read: true,
|
|
1634
|
+
write: false,
|
|
1635
|
+
def: '-'
|
|
1636
|
+
},
|
|
1637
|
+
native: {},
|
|
1638
|
+
});
|
|
1639
|
+
// Create Object for .runningTime => Laufzeit des Ventils
|
|
1640
|
+
const _runningTimeNotExist = await adapter.setObjectNotExistsAsync(`${objPfad}.runningTime`, {
|
|
1641
|
+
type: 'state',
|
|
1642
|
+
common: {
|
|
1643
|
+
role: 'state',
|
|
1644
|
+
name: {
|
|
1645
|
+
en: `${objectName} => running time of sprinkler`,
|
|
1646
|
+
de: `${objectName} => Laufzeit des Sprinklers`,
|
|
1647
|
+
ru: `${objectName} => время работы спринклера`,
|
|
1648
|
+
pt: `${objectName} => duração do aspersor`,
|
|
1649
|
+
nl: `${objectName} => looptijd van de sprinkler`,
|
|
1650
|
+
fr: `${objectName} => durée de fonctionnement du gicleur`,
|
|
1651
|
+
it: `${objectName} => durata dell'irrigatore`,
|
|
1652
|
+
es: `${objectName} => duración del rociador`,
|
|
1653
|
+
pl: `${objectName} => czas pracy zraszacza`,
|
|
1654
|
+
uk: `${objectName} => час роботи спринклера`,
|
|
1655
|
+
"zh-cn": `${objectName} => 洒水器的运行时间`
|
|
1656
|
+
},
|
|
1657
|
+
type: 'string',
|
|
1658
|
+
read: true,
|
|
1659
|
+
write: true,
|
|
1660
|
+
def: '-'
|
|
1661
|
+
},
|
|
1662
|
+
native: {},
|
|
1663
|
+
});
|
|
1664
|
+
// Create Object for .sprinklerState => Zustand des Ventils im Thread
|
|
1665
|
+
// <<< 1 = warten >>> ( 0:off; 1:wait; 2:on; 3:break; 4:Boost(on); 5:off(Boost) )
|
|
1666
|
+
// Create .sprinklerState
|
|
1667
|
+
const _sprinklerStateNotExists = await adapter.setObjectNotExistsAsync(`${objPfad}.sprinklerState`, {
|
|
1668
|
+
type: 'state',
|
|
1669
|
+
common: {
|
|
1670
|
+
role: 'state',
|
|
1671
|
+
name: {
|
|
1672
|
+
en: `${objectName} => actual state of sprinkler`,
|
|
1673
|
+
de: `${objectName} => Stand der Sprinkleranlage`,
|
|
1674
|
+
ru: `${objectName} => фактическое состояние спринклера`,
|
|
1675
|
+
pt: `${objectName} => estado real do aspersor`,
|
|
1676
|
+
nl: `${objectName} => werkelijke toestand van de sprinkler`,
|
|
1677
|
+
fr: `${objectName} => état actuel du gicleur`,
|
|
1678
|
+
it: `${objectName} => stato attuale dell'irrigatore`,
|
|
1679
|
+
es: `${objectName} => estado actual del rociador`,
|
|
1680
|
+
pl: `${objectName} => rzeczywisty stan tryskacza`,
|
|
1681
|
+
uk: `${objectName} => фактичний стан спринклера`,
|
|
1682
|
+
"zh-cn": `${objectName} => 洒水器的实际状态`
|
|
1683
|
+
},
|
|
1684
|
+
type: 'number',
|
|
1685
|
+
min: 0,
|
|
1686
|
+
max: 5,
|
|
1687
|
+
states: {
|
|
1688
|
+
0: 'off',
|
|
1689
|
+
1: 'wait',
|
|
1690
|
+
2: 'on',
|
|
1691
|
+
3: 'break',
|
|
1692
|
+
4: 'Boost(on)',
|
|
1693
|
+
5: 'off(Boost)'
|
|
1694
|
+
},
|
|
1695
|
+
read: true,
|
|
1696
|
+
write: false,
|
|
1697
|
+
def: 0
|
|
1698
|
+
},
|
|
1699
|
+
native: {},
|
|
1700
|
+
});
|
|
1701
|
+
// Create Object for triggerPoint → Schaltpunkt der Bodenfeuchte
|
|
1702
|
+
const _triggerPointNotExist = await adapter.setObjectNotExistsAsync(`${objPfad}.triggerPoint`, {
|
|
1703
|
+
type: 'state',
|
|
1704
|
+
common: {
|
|
1705
|
+
role: 'state',
|
|
1706
|
+
name: {
|
|
1707
|
+
en: `${objectName} => Trigger point of sprinkler`,
|
|
1708
|
+
de: `${objectName} => Schaltpunkt des Sprinklers`,
|
|
1709
|
+
ru: `${objectName} => Точка срабатывания спринклера`,
|
|
1710
|
+
pt: `${objectName} => Ponto de gatilho do aspersor`,
|
|
1711
|
+
nl: `${objectName} => Triggerpunt van de sprinkler`,
|
|
1712
|
+
fr: `${objectName} => Point de déclenchement du gicleur`,
|
|
1713
|
+
it: `${objectName} => Punto di innesco`,
|
|
1714
|
+
es: `${objectName} => Punto de activación del aspersor`,
|
|
1715
|
+
pl: `${objectName} => Punkt spustowy zraszacza`,
|
|
1716
|
+
uk: `${objectName} => Тригерна точка спринклера`,
|
|
1717
|
+
"zh-cn": `${objectName} => 洒水器的触发点`
|
|
1718
|
+
},
|
|
1719
|
+
type: 'string',
|
|
1720
|
+
read: true,
|
|
1721
|
+
write: false,
|
|
1722
|
+
def: '-'
|
|
1723
|
+
},
|
|
1724
|
+
native: {},
|
|
1725
|
+
});
|
|
1726
|
+
// Object created
|
|
1727
|
+
let value = true;
|
|
1728
|
+
(await Promise.all([
|
|
1729
|
+
_sprinkleNotExist,
|
|
1730
|
+
_historyNotExist,
|
|
1731
|
+
_curCalWeekConsumedNotExist,
|
|
1732
|
+
_curCalWeekRunningTimeNotExist,
|
|
1733
|
+
_lastCalWeekConsumedNotExist,
|
|
1734
|
+
_lastCalWeekRunningTimeNotExist,
|
|
1735
|
+
_lastConsumedNotExist,
|
|
1736
|
+
_lastOnNotExist,
|
|
1737
|
+
_lastRunningTimeNotExist,
|
|
1738
|
+
_autoOnNotExist,
|
|
1739
|
+
_countdownNotExist,
|
|
1740
|
+
_runningTimeNotExist,
|
|
1741
|
+
_sprinklerStateNotExists,
|
|
1742
|
+
_triggerPointNotExist
|
|
1743
|
+
])).forEach((val) => {
|
|
1744
|
+
value &= val;
|
|
1745
|
+
});
|
|
1746
|
+
if(value) {
|
|
1747
|
+
adapter.log.info(`sprinkleControl [sprinkle.${objectName}] was created`);
|
|
1748
|
+
}
|
|
1749
|
+
|
|
1750
|
+
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
|
|
1751
|
+
// +++++ zustände der States aktualisieren +++++ //
|
|
1752
|
+
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
|
|
1753
|
+
|
|
1754
|
+
//
|
|
1755
|
+
if(await _countdownNotExist){
|
|
1756
|
+
const _countdown = await adapter.getStateAsync(`${objPfad}.countdown`).catch((e) => adapter.log.warn(`${objectName}.countdown ${e}`));
|
|
1757
|
+
if (_countdown && _countdown.val !== '0') {
|
|
1758
|
+
adapter.setStateAsync(
|
|
1759
|
+
`${objPfad}.countdown`,
|
|
1760
|
+
'0',
|
|
1761
|
+
true
|
|
1762
|
+
).catch((e) => adapter.log.warn(e));
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
//
|
|
1766
|
+
if (_runningTimeNotExist) {
|
|
1767
|
+
const _runningTime = await adapter.getStateAsync(`${objPfad}.runningTime`).catch((e) => adapter.log.warn(`${objectName}.runningTime ${e}`));
|
|
1768
|
+
if (_runningTime && _runningTime.val !== '00:00') {
|
|
1769
|
+
adapter.setStateAsync(`${objPfad}.runningTime`,
|
|
1770
|
+
'00:00',
|
|
1771
|
+
true
|
|
1772
|
+
).catch((e) => adapter.log.warn(e));
|
|
1773
|
+
}
|
|
1774
|
+
}
|
|
1775
|
+
//
|
|
1776
|
+
if (_sprinklerStateNotExists){
|
|
1777
|
+
const _sprinklerState = await adapter.getStateAsync(`${objPfad}.sprinklerState`).catch((e) => adapter.log.warn(`${objectName}.sprinklerState ${e}`));
|
|
1778
|
+
if (_sprinklerState && _sprinklerState.val !== 0) {
|
|
1779
|
+
await adapter.setStateAsync(`${objPfad}.sprinklerState`,
|
|
1780
|
+
0,
|
|
1781
|
+
true
|
|
1782
|
+
).catch((e) => adapter.log.warn(`${objectName}.sprinklerState ${e}`));
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
// Festlegen des Schaltpunktes für den nächsten Start
|
|
1786
|
+
switch (myConfig.config[j].methodControlSM) {
|
|
1787
|
+
case 'bistable': {
|
|
1788
|
+
// Sensor soil moisture => Sensor Bodenfeuchte
|
|
1789
|
+
const _triggerSMBistabile = await adapter.getForeignStateAsync(myConfig.config[j].triggerSM).catch((e) => adapter.log.warn(`${objectName}.triggerSMBistabile ${e}`));
|
|
1790
|
+
if (_triggerSMBistabile && typeof _triggerSMBistabile.val === 'boolean') {
|
|
1791
|
+
myConfig.setSoilMoistBool(myConfig.config[j].sprinkleID, _triggerSMBistabile.val);
|
|
1792
|
+
} else {
|
|
1793
|
+
myConfig.setSoilMoistBool(myConfig.config[j].sprinkleID, true);
|
|
1794
|
+
adapter.log.warn(`The bistable sensor ${myConfig.config[j].triggerSM} in ${objectName} does not deliver correct values!`);
|
|
1795
|
+
}
|
|
1796
|
+
|
|
1797
|
+
adapter.setStateAsync(`${objPfad}.triggerPoint`,
|
|
1798
|
+
'-',
|
|
1799
|
+
true
|
|
1800
|
+
).catch((e) => adapter.log.warn(`${objectName}.triggerPoint ${e}`));
|
|
1801
|
+
break;
|
|
1802
|
+
}
|
|
1803
|
+
|
|
1804
|
+
case 'analog': {
|
|
1805
|
+
// Sensor soil moisture => Sensor Bodenfeuchte
|
|
1806
|
+
const _triggerSMAnalog = await adapter.getForeignStateAsync(myConfig.config[j].triggerSM).catch((e) => adapter.log.warn(`${objectName}.triggerSMAnalog ${e}`));
|
|
1807
|
+
if (_triggerSMAnalog && (typeof _triggerSMAnalog.val === 'number' || typeof _triggerSMAnalog.val === 'string')) {
|
|
1808
|
+
myConfig.setSoilMoistPct(myConfig.config[j].sprinkleID, _triggerSMAnalog.val);
|
|
1809
|
+
} else {
|
|
1810
|
+
await adapter.setStateAsync(`${objPfad}.actualSoilMoisture`,
|
|
1811
|
+
50,
|
|
1812
|
+
true
|
|
1813
|
+
);
|
|
1814
|
+
adapter.log.warn(`The analoge sensor ${myConfig.config[j].triggerSM} in ${objectName} does not deliver correct values!`);
|
|
1815
|
+
}
|
|
1816
|
+
adapter.setStateAsync(`${objPfad}.triggerPoint`,
|
|
1817
|
+
(myConfig.config[j].soilMoisture.pctTriggerIrrigation).toString(),
|
|
1818
|
+
true
|
|
1819
|
+
).catch((e) => adapter.log.warn(`${objectName}.triggerPoint setState ${e}`));
|
|
1820
|
+
break;
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
case 'fixDay': {
|
|
1824
|
+
const nextStartDay = ((today + 1) > 6 ? 0 : (today + 1));
|
|
1825
|
+
|
|
1826
|
+
/**
|
|
1827
|
+
* Neuen Start-Tag für Dreitage- und Zweitage-modus setzen
|
|
1828
|
+
*
|
|
1829
|
+
* @param threeRd - Dreitage-modus Ja/Nein
|
|
1830
|
+
* true → Dreitage-modus (treeRD)
|
|
1831
|
+
* false → Zweitage-modus (twoNd)
|
|
1832
|
+
*/
|
|
1833
|
+
async function setNewDay (threeRd) {
|
|
1834
|
+
const today = await formatTime(adapter,'', 'day');
|
|
1835
|
+
const _actualSoilMoisture = await adapter.getStateAsync(
|
|
1836
|
+
`${objPfad}.actualSoilMoisture`
|
|
1837
|
+
).catch((e) => adapter.log.warn(`${objectName}.actualSoilMoisture fixDay setState ${e}`));
|
|
1838
|
+
if (_actualSoilMoisture && (typeof _actualSoilMoisture.val === 'number')) {
|
|
1839
|
+
if ((_actualSoilMoisture.val >= 0) && (_actualSoilMoisture.val <= 6)) {
|
|
1840
|
+
if ((threeRd)
|
|
1841
|
+
&& (_actualSoilMoisture.val === (((today + 3) > 6) ? 2 : (today + 3)))
|
|
1842
|
+
|| (_actualSoilMoisture.val === (((today + 2) > 6) ? 1 : (today + 2)))
|
|
1843
|
+
|| (_actualSoilMoisture.val === (((today + 1) > 6) ? 0 : (today + 1)))
|
|
1844
|
+
|| (_actualSoilMoisture.val === today)) {
|
|
1845
|
+
myConfig.config[j].startFixDay[_actualSoilMoisture.val] = true;
|
|
1846
|
+
} else {
|
|
1847
|
+
myConfig.config[j].startFixDay[nextStartDay] = true;
|
|
1848
|
+
}
|
|
1849
|
+
} else {
|
|
1850
|
+
myConfig.config[j].startFixDay[nextStartDay] = true;
|
|
1851
|
+
}
|
|
1852
|
+
curNextFixDay(myConfig.config[j].sprinkleID, false);
|
|
1853
|
+
}
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1856
|
+
if (myConfig.config[j].startDay === 'threeRd') {
|
|
1857
|
+
await setNewDay(true);
|
|
1858
|
+
} else if (myConfig.config[j].startDay === 'twoNd') {
|
|
1859
|
+
await setNewDay(false);
|
|
1860
|
+
} else if (myConfig.config[j].startDay === 'fixDay') {
|
|
1861
|
+
curNextFixDay(myConfig.config[j].sprinkleID, false);
|
|
1862
|
+
}
|
|
1863
|
+
|
|
1864
|
+
adapter.setStateAsync(`${objPfad}.triggerPoint`,
|
|
1865
|
+
'-',
|
|
1866
|
+
true
|
|
1867
|
+
).catch((e) => adapter.log.warn(`${objectName}.triggerPoint fixDay setState ${e}`));
|
|
1868
|
+
break;
|
|
1869
|
+
}
|
|
1870
|
+
|
|
1871
|
+
case 'calculation': {
|
|
1872
|
+
const _actualSoilMoisture = await adapter.getStateAsync(`${objPfad}.actualSoilMoisture`).catch((e) => adapter.log.warn(e));
|
|
1873
|
+
if (_actualSoilMoisture) {
|
|
1874
|
+
if (await _actualSoilMoisture && typeof _actualSoilMoisture.val !== 'number' || _actualSoilMoisture.val === 0) {
|
|
1875
|
+
adapter.setStateAsync(`${objPfad}.actualSoilMoisture`,
|
|
1876
|
+
myConfig.config[j].soilMoisture.pct,
|
|
1877
|
+
true
|
|
1878
|
+
).catch((e) => adapter.log.warn(e));
|
|
1879
|
+
} else {
|
|
1880
|
+
// num Wert der Bodenfeuchte berechnen und in der config speichern, wenn Wert zwischen 0 und max liegt
|
|
1881
|
+
if ((0 < _actualSoilMoisture.val) && (_actualSoilMoisture.val <= (myConfig.config[j]).soilMoisture.maxRain*100/myConfig.config[j].soilMoisture.maxIrrigation)) {
|
|
1882
|
+
myConfig.config[j].soilMoisture.val = _actualSoilMoisture.val * myConfig.config[j].soilMoisture.maxIrrigation / 100;
|
|
1883
|
+
myConfig.config[j].soilMoisture.pct = _actualSoilMoisture.val;
|
|
1884
|
+
} else {
|
|
1885
|
+
// Wert aus config übernehmen
|
|
1886
|
+
adapter.setStateAsync(`${objPfad}.actualSoilMoisture`,
|
|
1887
|
+
myConfig.config[j].soilMoisture.pct,
|
|
1888
|
+
true
|
|
1889
|
+
).catch((e) => adapter.log.warn(e));
|
|
1890
|
+
}
|
|
1891
|
+
}
|
|
1892
|
+
}
|
|
1893
|
+
|
|
1894
|
+
adapter.setStateAsync(`${objPfad}.triggerPoint`,
|
|
1895
|
+
(myConfig.config[j].soilMoisture.pctTriggerIrrigation).toString(),
|
|
1896
|
+
true
|
|
1897
|
+
).catch((e) => adapter.log.warn(e));
|
|
1898
|
+
break;
|
|
1899
|
+
}
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
} catch (e) {
|
|
1903
|
+
adapter.log.warn(`sprinkleControl cannot created ... Please check your sprinkleControl config: ${e}`);
|
|
1904
|
+
}
|
|
1905
|
+
} else {
|
|
1906
|
+
adapter.log.warn('sprinkleControl cannot created ... Please check in your config the sprinkle Name');
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
|
|
1910
|
+
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
|
|
1911
|
+
// +++++ Objekte löschen +++++ //
|
|
1912
|
+
// ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ //
|
|
1913
|
+
for(const i in ObjSprinkle) {
|
|
1914
|
+
|
|
1915
|
+
const resID = ObjSprinkle[i]._id;
|
|
1916
|
+
const objectID = resID.split('.');
|
|
1917
|
+
const resultID = objectID[3];
|
|
1918
|
+
|
|
1919
|
+
const resultName = result.map(({ sprinkleName }) => ({ sprinkleName }));
|
|
1920
|
+
const fullRes = [];
|
|
1921
|
+
|
|
1922
|
+
for(const i in resultName) {
|
|
1923
|
+
// @ts-ignore
|
|
1924
|
+
if (Object.hasOwn(resultName,i)) {
|
|
1925
|
+
const res = resultName[i].sprinkleName.replace(/[.;, ]/g, '_');
|
|
1926
|
+
fullRes.push(res);
|
|
1927
|
+
}
|
|
1928
|
+
}
|
|
1929
|
+
|
|
1930
|
+
if (fullRes.indexOf(resultID) === -1) {
|
|
1931
|
+
try {
|
|
1932
|
+
// object deleted
|
|
1933
|
+
/* del when exist Object Async */
|
|
1934
|
+
const delWhenExistObjectAsync = async (id, type) => {
|
|
1935
|
+
const _find = await adapter.findForeignObjectAsync(`${id}`, `${type}`);
|
|
1936
|
+
if (_find && _find.id === `${id}`) {
|
|
1937
|
+
await adapter.delObjectAsync(`${id}`).catch((e) => adapter.log.warn(e)); // "sprinklecontrol.0.sprinkle.???.postponeByOneDay"
|
|
1938
|
+
}
|
|
1939
|
+
};
|
|
1940
|
+
|
|
1941
|
+
Promise.all([
|
|
1942
|
+
adapter.delObjectAsync(`${resID}.actualSoilMoisture`), // "sprinklecontrol.0.sprinkle.???.actualSoilMoisture"
|
|
1943
|
+
adapter.delObjectAsync(`${resID}.triggerPoint`), // "sprinklecontrol.0.sprinkle.???.triggerPoint"
|
|
1944
|
+
adapter.delObjectAsync(`${resID}.sprinklerState`), // "sprinklecontrol.0.sprinkle.???.sprinklerState"
|
|
1945
|
+
adapter.delObjectAsync(`${resID}.runningTime`), // "sprinklecontrol.0.sprinkle.???.runningTime"
|
|
1946
|
+
delWhenExistObjectAsync(`${resID}.postponeByOneDay`, `boolean`), // "sprinklecontrol.0.sprinkle.???.postponeByOneDay" wenn vorhanden löschen
|
|
1947
|
+
adapter.delObjectAsync(`${resID}.countdown`), // "sprinklecontrol.0.sprinkle.???.countdown"
|
|
1948
|
+
adapter.delObjectAsync(`${resID}.autoOn`), // "sprinklecontrol.0.sprinkle.???.autoOn"
|
|
1949
|
+
adapter.delObjectAsync(`${resID}.history.lastOn`), // "sprinklecontrol.0.sprinkle.???.history.lastOn"
|
|
1950
|
+
adapter.delObjectAsync(`${resID}.history.lastConsumed`), // "sprinklecontrol.0.sprinkle.???.history.lastConsumed"
|
|
1951
|
+
adapter.delObjectAsync(`${resID}.history.lastRunningTime`), // "sprinklecontrol.0.sprinkle.???.history.lastRunningTime"
|
|
1952
|
+
adapter.delObjectAsync(`${resID}.history.curCalWeekConsumed`), // "sprinklecontrol.0.sprinkle.???.history.curCalWeekConsumed"
|
|
1953
|
+
adapter.delObjectAsync(`${resID}.history.lastCalWeekConsumed`), // "sprinklecontrol.0.sprinkle.???.history.lastCalWeekConsumed"
|
|
1954
|
+
adapter.delObjectAsync(`${resID}.history.curCalWeekRunningTime`), // "sprinklecontrol.0.sprinkle.???.history.curCalWeekRunningTime"
|
|
1955
|
+
adapter.delObjectAsync(`${resID}.history.lastCalWeekRunningTime`) // "sprinklecontrol.0.sprinkle.???.history.lastCalWeekRunningTime"
|
|
1956
|
+
]
|
|
1957
|
+
).then(async ()=>{
|
|
1958
|
+
// History - Objekt(Ordner.history) löschen
|
|
1959
|
+
await adapter.delObjectAsync(`${resID}.history`);
|
|
1960
|
+
}).then(async ()=>{
|
|
1961
|
+
// Objekt(Ordner) löschen
|
|
1962
|
+
await adapter.delObjectAsync(resID);
|
|
1963
|
+
}).then(()=>{
|
|
1964
|
+
adapter.log.info(`sprinkleControl [${resID}] was deleted`);
|
|
1965
|
+
});
|
|
1966
|
+
} catch (e) {
|
|
1967
|
+
adapter.log.warn(e);
|
|
1968
|
+
}
|
|
1969
|
+
}
|
|
1970
|
+
}
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
1974
|
+
|
|
1975
|
+
function main(adapter) {
|
|
1976
|
+
|
|
1977
|
+
/* Auf die Adapterkonfiguration (im Instanz objekt alles unter dem Attribut "native") kann zugegriffen werden über adapter.config: */
|
|
1978
|
+
adapter.log.debug(`adapter.config.events: ${JSON.stringify(adapter.config.events)}`);
|
|
1979
|
+
/* Auf die Adapterkonfiguration (im Instanz objekt alles unter dem Attribut "native") kann zugegriffen werden über adapter.config */
|
|
1980
|
+
adapter.getForeignObject('system.config', (err, obj) => {
|
|
1981
|
+
if (obj) {
|
|
1982
|
+
checkStates();
|
|
1983
|
+
}
|
|
1984
|
+
});
|
|
1985
|
+
createSprinklers().catch((e) => adapter.log.warn(e));
|
|
1986
|
+
GetSystemData().catch((e) => adapter.log.warn(e));
|
|
1987
|
+
sendMessageText.initConfigMessage(adapter);
|
|
1988
|
+
evaporation.initEvaporation(adapter); // init evaporation
|
|
1989
|
+
checkActualStates().catch((e) => adapter.log.warn(e));
|
|
1990
|
+
sunPos();
|
|
1991
|
+
timer = setTimeout(() => {
|
|
1992
|
+
startTimeSprinkle();
|
|
1993
|
+
addStartTimeSprinkle();
|
|
1994
|
+
}, 2000);
|
|
1995
|
+
|
|
1996
|
+
/*
|
|
1997
|
+
* in this template all states changes inside the adapters namespace are subscribed
|
|
1998
|
+
* => In dieser Vorlage werden alle Statusänderungen im Namensraum des Adapters abonniert
|
|
1999
|
+
* adapter.subscribeStates('*');
|
|
2000
|
+
*/
|
|
2001
|
+
|
|
2002
|
+
adapter.subscribeStates('control.autoOnOff');
|
|
2003
|
+
adapter.subscribeStates('control.autoStart');
|
|
2004
|
+
adapter.subscribeStates('control.Holiday');
|
|
2005
|
+
|
|
2006
|
+
// Request a notification from a third-party adapter => Fordern Sie eine Benachrichtigung von einem Drittanbieter-Adapter an
|
|
2007
|
+
if (adapter.config.publicHolidays === true && (`${adapter.config.publicHolInstance}.heute.*`)) {
|
|
2008
|
+
adapter.subscribeForeignStates(`${adapter.config.publicHolInstance}.heute.*`);
|
|
2009
|
+
}
|
|
2010
|
+
if (adapter.config.publicHolidays === true && (`${adapter.config.publicHolInstance}.morgen.*`)) {
|
|
2011
|
+
adapter.subscribeForeignStates(`${adapter.config.publicHolInstance}.morgen.*`);
|
|
2012
|
+
}
|
|
2013
|
+
if (adapter.config.weatherForecast === true) {
|
|
2014
|
+
if (adapter.config.weatherForecastService === 'ownDataPoint') {
|
|
2015
|
+
weatherForecastTodayPfadStr = adapter.config.pathRainForecast;
|
|
2016
|
+
adapter.subscribeForeignStates(weatherForecastTodayPfadStr);
|
|
2017
|
+
} else if (adapter.config.weatherForecastService === 'dasWetter' && adapter.config.weatherForInstance) {
|
|
2018
|
+
weatherForecastTodayPfadStr = `${adapter.config.weatherForInstance}.NextDaysDetailed.Location_1.Day_1.rain_value`;
|
|
2019
|
+
adapter.subscribeForeignStates(weatherForecastTodayPfadStr);
|
|
2020
|
+
adapter.subscribeForeignStates(`${adapter.config.weatherForInstance}.NextDaysDetailed.Location_1.Day_2.rain_value`);
|
|
2021
|
+
} else {
|
|
2022
|
+
adapter.log.warn('There is no valid data record stored in the weather forecast, please correct it!');
|
|
2023
|
+
}
|
|
2024
|
+
}
|
|
2025
|
+
if (adapter.config.actualValueLevel !== '') {
|
|
2026
|
+
adapter.subscribeForeignStates(adapter.config.actualValueLevel);
|
|
2027
|
+
} else {
|
|
2028
|
+
adapter.setState('info.cisternState', { val: 'The level sensor of the water cistern is not specified', ack: true });
|
|
2029
|
+
}
|
|
2030
|
+
}
|
|
2031
|
+
|
|
2032
|
+
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
2033
|
+
|
|
2034
|
+
// ++++++++++++++++++ start option of Adapter ++++++++++++++++++++++
|
|
2035
|
+
// If started as allInOne/compact mode => return function to create instance
|
|
2036
|
+
if (module && module.parent) {
|
|
2037
|
+
module.exports = startAdapter;
|
|
2038
|
+
} else {
|
|
2039
|
+
// or start the instance directly
|
|
2040
|
+
startAdapter();
|
|
2041
|
+
}
|