iobroker.sprinklecontrol 1.0.5 → 1.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +7 -31
- package/admin/i18n/de/translations.json +9 -1
- package/admin/i18n/en/translations.json +9 -1
- package/admin/i18n/es/translations.json +8 -0
- package/admin/i18n/fr/translations.json +8 -0
- package/admin/i18n/it/translations.json +8 -0
- package/admin/i18n/nl/translations.json +8 -0
- package/admin/i18n/pl/translations.json +8 -0
- package/admin/i18n/pt/translations.json +8 -0
- package/admin/i18n/ru/translations.json +8 -0
- package/admin/i18n/uk/translations.json +8 -0
- package/admin/i18n/zh-cn/translations.json +8 -0
- package/admin/index_m.html +34 -3
- package/admin/index_m.js +12 -2
- package/admin/words.js +11 -3
- package/io-package.json +32 -29
- package/lib/evaporation.js +5 -5
- package/lib/tools.js +9 -2
- package/lib/valveControl.js +341 -103
- package/main.js +99 -52
- package/package.json +6 -6
package/lib/valveControl.js
CHANGED
|
@@ -23,7 +23,19 @@ const threadList = [];
|
|
|
23
23
|
* Ventil mit dem größten Durchfluss (pipeFlow) für die Steuerung des Druckentlastungsventils
|
|
24
24
|
* - wird in der Funktion updateList() ermittelt
|
|
25
25
|
*/
|
|
26
|
-
const pressureReliefValve = {
|
|
26
|
+
const pressureReliefValve = {
|
|
27
|
+
enable: false,
|
|
28
|
+
name: '',
|
|
29
|
+
wateringTime: 10,
|
|
30
|
+
ac: {},
|
|
31
|
+
controller: {},
|
|
32
|
+
control: {
|
|
33
|
+
idState: undefined,
|
|
34
|
+
idON_TIME: undefined,
|
|
35
|
+
idACK: undefined,
|
|
36
|
+
maker: undefined
|
|
37
|
+
}
|
|
38
|
+
};
|
|
27
39
|
|
|
28
40
|
/**
|
|
29
41
|
* - bereit zum Boost (true: kein Boostventil aktive; false: BoostVentil aktive)
|
|
@@ -46,7 +58,12 @@ let boostReady = true,
|
|
|
46
58
|
*/
|
|
47
59
|
timeBasedRestrictionEn = false;
|
|
48
60
|
|
|
49
|
-
const updateListMarker = {
|
|
61
|
+
const updateListMarker = {
|
|
62
|
+
funcActive: false,
|
|
63
|
+
newStart: false,
|
|
64
|
+
switchingDistance: 5000,
|
|
65
|
+
cancelSwitchingDistance: {}
|
|
66
|
+
};
|
|
50
67
|
|
|
51
68
|
/**
|
|
52
69
|
* aktive Pumpendaten
|
|
@@ -64,9 +81,38 @@ const updateListMarker = {funcActive: false, newStart: false, switchingDistance:
|
|
|
64
81
|
* - ac: AbortController
|
|
65
82
|
*/
|
|
66
83
|
|
|
67
|
-
const currentPumpUse = {
|
|
68
|
-
|
|
69
|
-
|
|
84
|
+
const currentPumpUse = {
|
|
85
|
+
enable: false,
|
|
86
|
+
name: '',
|
|
87
|
+
wateringTime: 0,
|
|
88
|
+
id: '',
|
|
89
|
+
pumpCistern: false,
|
|
90
|
+
intBreak: false,
|
|
91
|
+
leadTime: 0,
|
|
92
|
+
cancelLeadTime: {},
|
|
93
|
+
pumpPower: 0,
|
|
94
|
+
restFlow: 0,
|
|
95
|
+
ac: {},
|
|
96
|
+
controller: {},
|
|
97
|
+
control: {
|
|
98
|
+
idState: undefined,
|
|
99
|
+
idON_TIME: undefined,
|
|
100
|
+
idACK: undefined,
|
|
101
|
+
maker: undefined
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
let mainPumpControl = {
|
|
105
|
+
idState: undefined,
|
|
106
|
+
idON_TIME: undefined,
|
|
107
|
+
idACK: undefined,
|
|
108
|
+
maker: undefined
|
|
109
|
+
};
|
|
110
|
+
let cisternPumpControl = {
|
|
111
|
+
idState: undefined,
|
|
112
|
+
idON_TIME: undefined,
|
|
113
|
+
idACK: undefined,
|
|
114
|
+
maker: undefined
|
|
115
|
+
};
|
|
70
116
|
|
|
71
117
|
/**
|
|
72
118
|
* Steuerspannung 24V
|
|
@@ -75,7 +121,27 @@ let cisternPumpControl = {idState: undefined, idON_TIME: undefined, idACK: undef
|
|
|
75
121
|
* - idState: Aktorerkennung "hm-rpc.0.MEQ1810129.1.STATE"
|
|
76
122
|
* - controller: controlle von Zeiten und Abbruchsignalen
|
|
77
123
|
*/
|
|
78
|
-
const controlVoltage = {
|
|
124
|
+
const controlVoltage = {
|
|
125
|
+
enable: false,
|
|
126
|
+
name: '24V',
|
|
127
|
+
wateringTime: 0,
|
|
128
|
+
ac: {},
|
|
129
|
+
controller: {},
|
|
130
|
+
control: {
|
|
131
|
+
idState: undefined,
|
|
132
|
+
idON_TIME: undefined,
|
|
133
|
+
idACK: undefined,
|
|
134
|
+
maker: undefined
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
const sensorPressure = {
|
|
139
|
+
inadequatePressure: false, // true = Nicht ausreichender Druck, false = ausreichender Druck
|
|
140
|
+
name: 'Sensor Pressure',
|
|
141
|
+
value: 0,
|
|
142
|
+
state: 0,
|
|
143
|
+
ac: null
|
|
144
|
+
};
|
|
79
145
|
|
|
80
146
|
/**
|
|
81
147
|
* Schaltabstand in ms
|
|
@@ -154,7 +220,7 @@ const setValve = async (thread, val) => {
|
|
|
154
220
|
|
|
155
221
|
//adapter.log.info(`Set Valve (async () => {...}`);
|
|
156
222
|
try {
|
|
157
|
-
// Ventil
|
|
223
|
+
// ON_Time setzen wenn angegeben, damit das Ventil nach der angegebenen Zeit automatisch ausgeschaltet wird (z.B. wenn der Ausschaltbefehl nicht ausgeführt werden kann, z.B Funkstörung)
|
|
158
224
|
if (thread.control.idON_TIME !== null) {
|
|
159
225
|
await adapter.setForeignStateAsync(thread.control.idON_TIME, {
|
|
160
226
|
val: val ? Math.ceil(thread.wateringTime + 5) : 0,
|
|
@@ -162,7 +228,7 @@ const setValve = async (thread, val) => {
|
|
|
162
228
|
});
|
|
163
229
|
await asyncTime.setTimeout(200, undefined, undefined);
|
|
164
230
|
}
|
|
165
|
-
|
|
231
|
+
// Ventil ansteuern
|
|
166
232
|
const _setValve = await adapter.setForeignStateAsync(thread.control.idState, {
|
|
167
233
|
val: val,
|
|
168
234
|
ack: false
|
|
@@ -205,16 +271,21 @@ const setValve = async (thread, val) => {
|
|
|
205
271
|
if (thread.ac.acSetValveCancelTimeout.aborted === false) thread.ac.acSetValveCancelTimeout.abort();
|
|
206
272
|
}
|
|
207
273
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
274
|
+
try {
|
|
275
|
+
if (thread.name !== 'Cistern pump' && thread.name !== 'Main pump' && thread.name !== '24V' && thread.name !== 'no Pump') {
|
|
276
|
+
await adapter.setStateAsync(`sprinkle.${thread.name}.sprinklerState`, {
|
|
277
|
+
val: thread.state,
|
|
278
|
+
ack: true
|
|
279
|
+
});
|
|
280
|
+
adapter.setStateAsync(`sprinkle.${thread.name}.valveOn`, {
|
|
281
|
+
val: thread.enable,
|
|
282
|
+
ack: true
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
} catch (error) {
|
|
286
|
+
adapter.log.error(`setValve ${thread.name} => Error setting sprinklerState or valveOn: ${error}`);
|
|
217
287
|
}
|
|
288
|
+
|
|
218
289
|
return result;
|
|
219
290
|
};
|
|
220
291
|
|
|
@@ -258,6 +329,9 @@ const delList = async (killList) => {
|
|
|
258
329
|
|
|
259
330
|
/**
|
|
260
331
|
* currentConsumption aktueller Verbrauch ermitteln
|
|
332
|
+
* - curFlow: aktuelle Restfördertleistung der Pumpe
|
|
333
|
+
* - parallel: aktuelle Anzahl der eingeschalteten Ventile
|
|
334
|
+
* - pumpRequired: Pumpe erforderlich (true/false)
|
|
261
335
|
*
|
|
262
336
|
* @param {boolean} write
|
|
263
337
|
* @returns {Promise<{curFlow:number, parallel:number, pumpRequired:boolean}>}
|
|
@@ -269,13 +343,15 @@ const currentConsumption = async (write) => {
|
|
|
269
343
|
parallel = 0,
|
|
270
344
|
pumpRequired = false;
|
|
271
345
|
adapter.log.debug(`currentConsumption curFlow: ${curFlow}, ${currentPumpUse.intBreak} => ${currentPumpUse.intBreak ? 0 : currentPumpUse.pumpPower}`);
|
|
272
|
-
if (!currentPumpUse.intBreak
|
|
346
|
+
if (!currentPumpUse.intBreak
|
|
347
|
+
&& !sensorPressure.inadequatePressure
|
|
348
|
+
) {
|
|
273
349
|
// ermitteln von curPipe und der Anzahl der parallelen Stränge
|
|
274
350
|
for (const entry of threadList){
|
|
275
351
|
if (entry.state === 'wait') pumpRequired = true; // state => wait
|
|
276
|
-
if (entry.enable === true
|
|
277
|
-
&& entry.extBreak === false
|
|
278
|
-
&& timeBasedRestrictionEn === false
|
|
352
|
+
if (entry.enable === true // Ventil eingeschaltet
|
|
353
|
+
&& entry.extBreak === false // && nicht in der externen Pause (extBreak)
|
|
354
|
+
&& timeBasedRestrictionEn === false // && nicht in der zeitlichen Bewässerungspause
|
|
279
355
|
) {
|
|
280
356
|
curFlow -= entry.pipeFlow; // // ermitteln der RestFörderkapazität
|
|
281
357
|
parallel ++; // Anzahl der Bewässerungsstellen um 1 erhöhen
|
|
@@ -451,7 +527,7 @@ const countSprinkleTime = async (entry) => {
|
|
|
451
527
|
/**
|
|
452
528
|
* Timer zum ausschalten des Boost
|
|
453
529
|
*
|
|
454
|
-
* @param {
|
|
530
|
+
* @param {object} entry
|
|
455
531
|
*/
|
|
456
532
|
const boostOnTimer = async (entry) => {
|
|
457
533
|
entry.ac.acBoostOnTimer = new AbortController;
|
|
@@ -533,7 +609,7 @@ const updateList = async () => {
|
|
|
533
609
|
: false;
|
|
534
610
|
|
|
535
611
|
/**
|
|
536
|
-
*
|
|
612
|
+
* Find das Ventil mit dem größten Durchfluss (pipeFlow) für die Steuerung des Druckentlastungsventils
|
|
537
613
|
* - Wenn die Bewässerung beendet wird, soll der Druck in den Leitungen durch kurzes Öffnen eines Druckentlastungsventils abgebaut werden,
|
|
538
614
|
* um die Lebensdauer des Systems zu erhöhen. Hierzu wird das Ventil mit dem Größten Durchfluss (pipeFlow) für 10 Sekunden angesteuert.
|
|
539
615
|
*/
|
|
@@ -546,9 +622,22 @@ const updateList = async () => {
|
|
|
546
622
|
}, myConfig.config[0]
|
|
547
623
|
);
|
|
548
624
|
}
|
|
549
|
-
|
|
550
|
-
|
|
625
|
+
/**
|
|
626
|
+
* Druckentlastungsventil ein wenn alle Ventile ihre Laufzeit beendet haben
|
|
627
|
+
* .killSprinkle = true
|
|
628
|
+
*/
|
|
629
|
+
function pressureReliefIO() {
|
|
630
|
+
return threadList.reduce((count, entry) => {
|
|
631
|
+
return (entry.myBreak === true // Intervall-Beregnung on
|
|
632
|
+
&& entry.killSprinkle === false // && Aufgabe noch nicht erledigt
|
|
633
|
+
) ? (count + 1) : count;
|
|
634
|
+
}, 0
|
|
635
|
+
);
|
|
636
|
+
}
|
|
551
637
|
|
|
638
|
+
/**
|
|
639
|
+
* Start der Steuerung der Pumpen und Ventile
|
|
640
|
+
*/
|
|
552
641
|
consumption = await currentConsumption(true);
|
|
553
642
|
if (consumption.pumpRequired === true) { // Pumpe erforderlich
|
|
554
643
|
|
|
@@ -556,7 +645,7 @@ const updateList = async () => {
|
|
|
556
645
|
try {
|
|
557
646
|
if (adapter.config.triggerControlVoltage
|
|
558
647
|
&& controlVoltage.enable === false
|
|
559
|
-
|| adjustment === true
|
|
648
|
+
|| adjustment === true // Anpassung ON_Time wenn Laufzeit zu kurz, damit die 24V Versorgung während der Laufzeit nicht ausgeschaltet wird
|
|
560
649
|
) {
|
|
561
650
|
controlVoltage.wateringTime = sumOfWateringTime > controlVoltage.wateringTime ? sumOfWateringTime + 5 : controlVoltage.wateringTime; // Schaltzeit der 24V Versorgung entsprechend der maximalen Laufzeit aller Ventile in der threadList anpassen
|
|
562
651
|
const _controlVoltage = await setValve(controlVoltage, true);
|
|
@@ -576,7 +665,7 @@ const updateList = async () => {
|
|
|
576
665
|
try {
|
|
577
666
|
if (adapter.config.pumpSelection !== 'noPump'
|
|
578
667
|
&& currentPumpUse.enable === false
|
|
579
|
-
|| adjustment === true
|
|
668
|
+
|| adjustment === true // Anpassung ON_Time wenn Laufzeit zu kurz, damit die Pumpe während der Laufzeit nicht ausgeschaltet wird
|
|
580
669
|
) {
|
|
581
670
|
currentPumpUse.wateringTime = sumOfWateringTime > currentPumpUse.wateringTime ? sumOfWateringTime : currentPumpUse.wateringTime; // Schaltzeit der Pumpe entsprechend der maximalen Laufzeit aller Ventile in der threadList anpassen
|
|
582
671
|
const _currentPumpUse = await setValve(currentPumpUse, true);
|
|
@@ -725,7 +814,8 @@ const updateList = async () => {
|
|
|
725
814
|
) {
|
|
726
815
|
try {
|
|
727
816
|
const empty = await findPressureReliefValve();
|
|
728
|
-
|
|
817
|
+
const _pressureReliefIO = await pressureReliefIO();
|
|
818
|
+
if (empty && _pressureReliefIO === 0) { // Ventil gefunden und alle Ventile haben ihre Laufzeit beendet
|
|
729
819
|
pressureReliefValve.name = empty.objectName;
|
|
730
820
|
pressureReliefValve.wateringTime = 10;
|
|
731
821
|
pressureReliefValve.pipeFlow = empty.pipeFlow;
|
|
@@ -796,8 +886,8 @@ const setActualPump = async () => {
|
|
|
796
886
|
case 'mainPump': {
|
|
797
887
|
/* Pumpe AUS => Zisternen-Bewässerung nicht aktiviert */
|
|
798
888
|
if (adapter.config.triggerCisternPump) {
|
|
799
|
-
adapter.
|
|
800
|
-
val: `Cistern settings are not active! ${(fillLevelCistern > 0) ? (`
|
|
889
|
+
await adapter.setStateAsync('info.cisternState', {
|
|
890
|
+
val: `Cistern settings are not active! ${(fillLevelCistern > 0) ? (` ${fillLevelCistern}% ${(adapter.config.triggerMinCisternLevel !== '') ? (` ${adapter.config.triggerMinCisternLevel}%`) : ('')}`):('')}`,
|
|
801
891
|
ack: true
|
|
802
892
|
});
|
|
803
893
|
}
|
|
@@ -805,48 +895,37 @@ const setActualPump = async () => {
|
|
|
805
895
|
}
|
|
806
896
|
|
|
807
897
|
case 'cistern': {
|
|
808
|
-
|
|
898
|
+
// Zisterne unter Minimum
|
|
899
|
+
if (fillLevelCistern < parseFloat(adapter.config.triggerMinCisternLevel)) {
|
|
809
900
|
if (!currentPumpUse.intBreak) {
|
|
810
901
|
currentPumpUse.intBreak = true;
|
|
811
|
-
adapter.log.
|
|
902
|
+
adapter.log.info('Cistern empty => irrigation no longer possible');
|
|
812
903
|
if(!sendMessageText.onlySendError()){
|
|
813
904
|
sendMessageText.sendMessage('Cistern empty => irrigation no longer possible'); // Zisterne leer => Bewässerung nicht mehr möglich
|
|
814
905
|
}
|
|
815
906
|
}
|
|
816
|
-
adapter.setState('info.cisternState', {
|
|
817
|
-
val: `Cistern empty: ${fillLevelCistern} % (${adapter.config.triggerMinCisternLevel} %)`,
|
|
818
|
-
ack: true
|
|
819
|
-
});
|
|
820
907
|
// Pumpe ist eingeschaltet => ausschalten
|
|
821
908
|
if (currentPumpUse.enable) {
|
|
822
909
|
await setValve(currentPumpUse, false);
|
|
823
910
|
updateList(); // Wasserverbrauch an Pumpenleistung anpassen
|
|
824
911
|
}
|
|
912
|
+
// Zisterne über Minimum
|
|
825
913
|
} else if (fillLevelCistern > parseFloat(adapter.config.triggerOnCisternLevel)) {
|
|
826
914
|
if (currentPumpUse.intBreak) {
|
|
827
915
|
currentPumpUse.intBreak = false;
|
|
828
|
-
adapter.log.
|
|
916
|
+
adapter.log.info('Cistern filled => irrigation can begin again'); // Zisterne gefüllt => Bewässerung kann wieder beginnen
|
|
829
917
|
if(!sendMessageText.onlySendError()){
|
|
830
918
|
sendMessageText.sendMessage('Cistern filled => irrigation can begin again');
|
|
831
919
|
}
|
|
832
920
|
}
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
val: `Cistern filled: ${fillLevelCistern} % (${adapter.config.triggerMinCisternLevel} %)`,
|
|
836
|
-
ack: true
|
|
837
|
-
});
|
|
838
|
-
updateList(); // Wasserverbrauch an Pumpenleistung anpassen
|
|
839
|
-
} else if (currentPumpUse.intBreak === true) {
|
|
840
|
-
adapter.setState('info.cisternState', {
|
|
841
|
-
val: `Cistern empty: ${fillLevelCistern} % (${adapter.config.triggerMinCisternLevel} %)`,
|
|
842
|
-
ack: true
|
|
843
|
-
});
|
|
844
|
-
} else {
|
|
845
|
-
adapter.setState('info.cisternState', {
|
|
846
|
-
val: `Cistern filled: ${fillLevelCistern} % (${adapter.config.triggerMinCisternLevel} %)`,
|
|
847
|
-
ack: true
|
|
848
|
-
});
|
|
921
|
+
// Wasserverbrauch an Pumpenleistung anpassen
|
|
922
|
+
updateList();
|
|
849
923
|
}
|
|
924
|
+
/* Info aktualisieren */
|
|
925
|
+
await adapter.setStateAsync('info.cisternState', {
|
|
926
|
+
val: `${ (currentPumpUse.intBreak === true) ? 'Cistern empty: ' : 'Cistern filled: ' } ${ fillLevelCistern } % (${ adapter.config.triggerMinCisternLevel } %)`,
|
|
927
|
+
ack: true
|
|
928
|
+
});
|
|
850
929
|
break;
|
|
851
930
|
}
|
|
852
931
|
|
|
@@ -861,6 +940,8 @@ const setActualPump = async () => {
|
|
|
861
940
|
val: currentPumpUse.enable,
|
|
862
941
|
ack: true
|
|
863
942
|
});
|
|
943
|
+
} else {
|
|
944
|
+
throw new Error(`Error trigger cistern Pump off [${currentPumpUse.control.idState}]`);
|
|
864
945
|
}
|
|
865
946
|
currentPumpUse.pumpCistern = false;
|
|
866
947
|
currentPumpUse.name = 'Main pump';
|
|
@@ -874,6 +955,8 @@ const setActualPump = async () => {
|
|
|
874
955
|
val: currentPumpUse.enable,
|
|
875
956
|
ack: true
|
|
876
957
|
});
|
|
958
|
+
} else {
|
|
959
|
+
throw new Error(`Error trigger main Pump on [${currentPumpUse.control.idState}]`);
|
|
877
960
|
}
|
|
878
961
|
adapter.log.info('Pump change (cistern empty) Cistern pump off => main pump on');
|
|
879
962
|
if(!sendMessageText.onlySendError()){
|
|
@@ -883,45 +966,39 @@ const setActualPump = async () => {
|
|
|
883
966
|
}
|
|
884
967
|
} else {
|
|
885
968
|
/* Bewässerungspumpen inaktiv */
|
|
886
|
-
if (
|
|
887
|
-
/* Zisterne voll
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
969
|
+
if (fillLevelCistern > parseFloat(adapter.config.triggerOnCisternLevel)) {
|
|
970
|
+
/* Zisterne voll */
|
|
971
|
+
if (currentPumpUse.pumpCistern === false) {
|
|
972
|
+
currentPumpUse.pumpCistern = true;
|
|
973
|
+
currentPumpUse.name = 'Cistern pump';
|
|
974
|
+
currentPumpUse.id = 'info.cisternPump';
|
|
975
|
+
currentPumpUse.control = { ...cisternPumpControl };
|
|
976
|
+
currentPumpUse.pumpPower = parseInt(adapter.config.triggerCisternPumpPower);
|
|
977
|
+
await adapter.setStateAsync('control.restFlow', {
|
|
978
|
+
val: `${currentPumpUse.pumpPower} (${currentPumpUse.pumpPower} | ${currentPumpUse.name})`,
|
|
979
|
+
ack: true
|
|
980
|
+
});
|
|
981
|
+
}
|
|
982
|
+
} else if (fillLevelCistern < parseFloat(adapter.config.triggerMinCisternLevel)) {
|
|
983
|
+
/* Zisterne leer */
|
|
984
|
+
if (currentPumpUse.pumpCistern === true) {
|
|
985
|
+
currentPumpUse.pumpCistern = false;
|
|
986
|
+
currentPumpUse.name = 'Main pump';
|
|
987
|
+
currentPumpUse.id = 'info.mainPump';
|
|
988
|
+
currentPumpUse.control = { ...mainPumpControl };
|
|
989
|
+
currentPumpUse.pumpPower = parseInt(adapter.config.triggerMainPumpPower);
|
|
990
|
+
await adapter.setStateAsync('control.restFlow', {
|
|
991
|
+
val: `${currentPumpUse.pumpPower} (${currentPumpUse.pumpPower} | ${currentPumpUse.name})`,
|
|
992
|
+
ack: true
|
|
993
|
+
});
|
|
994
|
+
}
|
|
908
995
|
}
|
|
909
|
-
adapter.setState('control.restFlow', {
|
|
910
|
-
val: `${currentPumpUse.pumpPower} (${currentPumpUse.pumpPower} | ${currentPumpUse.name})`,
|
|
911
|
-
ack: true
|
|
912
|
-
});
|
|
913
|
-
}
|
|
914
|
-
if (currentPumpUse.pumpCistern) {
|
|
915
|
-
adapter.setState('info.cisternState', {
|
|
916
|
-
val: `Cistern filled: ${fillLevelCistern} % (${adapter.config.triggerMinCisternLevel} %)`,
|
|
917
|
-
ack: true
|
|
918
|
-
});
|
|
919
|
-
} else {
|
|
920
|
-
adapter.setState('info.cisternState', {
|
|
921
|
-
val: `Cistern empty: ${fillLevelCistern} % (${adapter.config.triggerMinCisternLevel} %)`,
|
|
922
|
-
ack: true
|
|
923
|
-
});
|
|
924
996
|
}
|
|
997
|
+
/* Info aktualisieren */
|
|
998
|
+
await adapter.setStateAsync('info.cisternState', {
|
|
999
|
+
val: `${ (currentPumpUse.pumpCistern === false) ? 'Cistern empty: ' : 'Cistern filled: ' } ${ fillLevelCistern } % (${ adapter.config.triggerMinCisternLevel } %)`,
|
|
1000
|
+
ack: true
|
|
1001
|
+
});
|
|
925
1002
|
break;
|
|
926
1003
|
}
|
|
927
1004
|
}
|
|
@@ -1135,8 +1212,8 @@ const valveControl = {
|
|
|
1135
1212
|
const _actualValueLevel = await adapter.getForeignStateAsync(adapter.config.actualValueLevel);
|
|
1136
1213
|
if (_actualValueLevel && _actualValueLevel.val) {
|
|
1137
1214
|
if (typeof _actualValueLevel.val === 'number') {
|
|
1138
|
-
fillLevelCistern = _actualValueLevel.val;
|
|
1139
|
-
(
|
|
1215
|
+
fillLevelCistern = parseInt(_actualValueLevel.val);
|
|
1216
|
+
(fillLevelCistern > parseInt(adapter.config.triggerMinCisternLevel)) ? currentPumpUse.intBreak = false : currentPumpUse.intBreak = true;
|
|
1140
1217
|
} else if (typeof _actualValueLevel.val === 'boolean') {
|
|
1141
1218
|
if (_actualValueLevel.val) {
|
|
1142
1219
|
currentPumpUse.intBreak = false;
|
|
@@ -1163,6 +1240,19 @@ const valveControl = {
|
|
|
1163
1240
|
currentPumpUse.leadTime = (parseInt(adapter.config.cisternPumpLeadTime) || 5) * 1000;
|
|
1164
1241
|
currentPumpUse.pumpPower = parseInt(adapter.config.triggerCisternPumpPower) || 0;
|
|
1165
1242
|
currentPumpUse.restFlow = parseInt(adapter.config.triggerCisternPumpPower) || 0;
|
|
1243
|
+
if (isNaN(parseInt(adapter.config.triggerMinCisternLevel))
|
|
1244
|
+
|| (parseInt(adapter.config.triggerMinCisternLevel) <= 1)
|
|
1245
|
+
|| (parseInt(adapter.config.triggerMinCisternLevel) > 100)
|
|
1246
|
+
) {
|
|
1247
|
+
adapter.log.error(`Pump selection "cistern" is selected, but the minimum cistern level is set to ${adapter.config.triggerMinCisternLevel}%. Please set the minimum cistern level to 1...100% or select another pump selection!`);
|
|
1248
|
+
}
|
|
1249
|
+
if (isNaN(parseInt(adapter.config.triggerOnCisternLevel))
|
|
1250
|
+
|| (parseInt(adapter.config.triggerOnCisternLevel) <= parseInt(adapter.config.triggerMinCisternLevel))
|
|
1251
|
+
|| (parseInt(adapter.config.triggerOnCisternLevel) > 100)
|
|
1252
|
+
|| (parseInt(adapter.config.triggerOnCisternLevel) < 5)
|
|
1253
|
+
) {
|
|
1254
|
+
adapter.log.error(`Pump selection "cistern" is selected, but the trigger on cistern level is set to ${adapter.config.triggerOnCisternLevel}%. Please set the trigger on cistern level to ${parseInt(adapter.config.triggerMinCisternLevel) + 5}...100% or select another pump selection!`);
|
|
1255
|
+
}
|
|
1166
1256
|
// @ts-ignore
|
|
1167
1257
|
await adapter.setObjectNotExistsAsync(`info.cisternPump`, objCisternPump);
|
|
1168
1258
|
const _mainPump = await adapter.getObjectAsync(`info.mainPump`);
|
|
@@ -1176,12 +1266,26 @@ const valveControl = {
|
|
|
1176
1266
|
cisternPumpControl = await tools.idStateControl(adapter, adapter.config.triggerCisternPump);
|
|
1177
1267
|
if (mainPumpControl?.idACK) adapter.subscribeForeignStates(mainPumpControl.idACK);
|
|
1178
1268
|
if (cisternPumpControl?.idACK) adapter.subscribeForeignStates(cisternPumpControl.idACK);
|
|
1269
|
+
/* Kontrolle der Konfiguration CisternLevel */
|
|
1270
|
+
if (isNaN(parseInt(adapter.config.triggerMinCisternLevel))
|
|
1271
|
+
|| (parseInt(adapter.config.triggerMinCisternLevel) <= 1)
|
|
1272
|
+
|| (parseInt(adapter.config.triggerMinCisternLevel) > 100)
|
|
1273
|
+
) {
|
|
1274
|
+
adapter.log.error(`Pump selection "mainpump & cistern" is selected, but the minimum cistern level is set to ${adapter.config.triggerMinCisternLevel}%. Please set the minimum cistern level to 1...100% or select another pump selection!`);
|
|
1275
|
+
}
|
|
1276
|
+
if (isNaN(parseInt(adapter.config.triggerOnCisternLevel))
|
|
1277
|
+
|| (parseInt(adapter.config.triggerOnCisternLevel) <= parseInt(adapter.config.triggerMinCisternLevel))
|
|
1278
|
+
|| (parseInt(adapter.config.triggerOnCisternLevel) > 100)
|
|
1279
|
+
|| (parseInt(adapter.config.triggerOnCisternLevel) < 5)
|
|
1280
|
+
) {
|
|
1281
|
+
adapter.log.error(`Pump selection "cistern" is selected, but the trigger on cistern level is set to ${adapter.config.triggerOnCisternLevel}%. Please set the trigger on cistern level to ${parseInt(adapter.config.triggerMinCisternLevel) + 5}...100% or select another pump selection!`);
|
|
1282
|
+
}
|
|
1179
1283
|
if (adapter.config.actualValueLevel) {
|
|
1180
1284
|
/* Füllstand der Zisterne in % holen */
|
|
1181
1285
|
const _actualValueLevel = await adapter.getForeignStateAsync(adapter.config.actualValueLevel);
|
|
1182
|
-
if (_actualValueLevel
|
|
1286
|
+
if (_actualValueLevel?.val) {
|
|
1183
1287
|
if (typeof _actualValueLevel.val === 'number') {
|
|
1184
|
-
fillLevelCistern = _actualValueLevel.val;
|
|
1288
|
+
fillLevelCistern = parseInt(_actualValueLevel.val);
|
|
1185
1289
|
} else if (typeof _actualValueLevel.val === 'boolean') {
|
|
1186
1290
|
_actualValueLevel.val ? fillLevelCistern = 100 : fillLevelCistern = 0;
|
|
1187
1291
|
} else {
|
|
@@ -1229,7 +1333,7 @@ const valveControl = {
|
|
|
1229
1333
|
}
|
|
1230
1334
|
}
|
|
1231
1335
|
/* Objekt control.restFlow befüllen */
|
|
1232
|
-
adapter.setStateAsync('control.restFlow', {
|
|
1336
|
+
await adapter.setStateAsync('control.restFlow', {
|
|
1233
1337
|
val: `${currentPumpUse.pumpPower} (${currentPumpUse.pumpPower} | ${currentPumpUse.name})`,
|
|
1234
1338
|
ack: true
|
|
1235
1339
|
});
|
|
@@ -1291,6 +1395,63 @@ const valveControl = {
|
|
|
1291
1395
|
}
|
|
1292
1396
|
}
|
|
1293
1397
|
}
|
|
1398
|
+
|
|
1399
|
+
/**
|
|
1400
|
+
* Objekt sensorPressure anlegen und abonnieren, wenn benötigt
|
|
1401
|
+
*/
|
|
1402
|
+
|
|
1403
|
+
if (typeof adapter.config.sensorPressure === 'string'
|
|
1404
|
+
&& adapter.config.sensorPressure.length > 5
|
|
1405
|
+
&& adapter.config.pumpSelection !== 'noPump'
|
|
1406
|
+
) {
|
|
1407
|
+
const _sensorPressure = await adapter.getForeignStateAsync(adapter.config.sensorPressure);
|
|
1408
|
+
if (_sensorPressure) {
|
|
1409
|
+
adapter.subscribeForeignStates(adapter.config.sensorPressure);
|
|
1410
|
+
const _waterPressure = await adapter.getObjectAsync(`info.waterPressure`);
|
|
1411
|
+
if (_waterPressure) {
|
|
1412
|
+
await adapter.setStateAsync(`info.waterPressure`, {
|
|
1413
|
+
val: `${ _sensorPressure.val }`,
|
|
1414
|
+
ack: true
|
|
1415
|
+
});
|
|
1416
|
+
} else {
|
|
1417
|
+
await adapter.setObjectNotExistsAsync(`info.waterPressure`, {
|
|
1418
|
+
type: 'state',
|
|
1419
|
+
common: {
|
|
1420
|
+
role: 'state',
|
|
1421
|
+
name: 'Water pressure',
|
|
1422
|
+
desc: {
|
|
1423
|
+
en: 'Water pressure',
|
|
1424
|
+
de: 'Wasserdruck',
|
|
1425
|
+
ru: 'Давление воды',
|
|
1426
|
+
pt: 'Pressão da água',
|
|
1427
|
+
nl: 'Waterdruk',
|
|
1428
|
+
fr: "Pression de l'eau",
|
|
1429
|
+
it: "Pressione dell'acqua",
|
|
1430
|
+
es: 'Presión del agua',
|
|
1431
|
+
pl: 'Ciśnienie wody',
|
|
1432
|
+
uk: 'Тиск води',
|
|
1433
|
+
'zh-cn': '水压'
|
|
1434
|
+
},
|
|
1435
|
+
type: 'string',
|
|
1436
|
+
read: true,
|
|
1437
|
+
write: false,
|
|
1438
|
+
def: ' --- ',
|
|
1439
|
+
unit: 'bar'
|
|
1440
|
+
},
|
|
1441
|
+
native: {},
|
|
1442
|
+
});
|
|
1443
|
+
await adapter.setStateAsync(`info.waterPressure`, {
|
|
1444
|
+
val: `${ _sensorPressure.val }`,
|
|
1445
|
+
ack: true
|
|
1446
|
+
});
|
|
1447
|
+
}
|
|
1448
|
+
} else {
|
|
1449
|
+
adapter.log.warn(`The configured pressure sensor "${ adapter.config.sensorPressure }" could not be found. Please check the configuration of the pressure sensor!`);
|
|
1450
|
+
}
|
|
1451
|
+
} else {
|
|
1452
|
+
const _waterPressure = await adapter.getObjectAsync(`info.waterPressure`);
|
|
1453
|
+
if (_waterPressure) await adapter.delObjectAsync(`info.waterPressure`);
|
|
1454
|
+
}
|
|
1294
1455
|
} catch (error) {
|
|
1295
1456
|
adapter.log.error(`initValveControl ERROR: ${error}`);
|
|
1296
1457
|
}
|
|
@@ -1308,6 +1469,7 @@ const valveControl = {
|
|
|
1308
1469
|
*/
|
|
1309
1470
|
addList: async function (sprinkleList) {
|
|
1310
1471
|
try {
|
|
1472
|
+
sensorPressure.inadequatePressure = false; // Kontrolle Drucksensorwert zurücksetzen, damit die Bewässerungsbeschränkung korrekt funktioniert, wenn der Drucksensorwert während der Bewässerungsbeschränkung unter dem Minimum lag
|
|
1311
1473
|
// kontrolle bei ausgeschalteter Pumpe, ob die Zisterne zur Bewässerung genutzt werden kann
|
|
1312
1474
|
if (adapter.config.pumpSelection === 'pumpAndCistern'
|
|
1313
1475
|
&& currentPumpUse.enable === false
|
|
@@ -1377,7 +1539,7 @@ const valveControl = {
|
|
|
1377
1539
|
/** 0:"off", 1:"wait", 2:"on", 3:"break", 4:"Boost(on)", 5:"off(Boost)", 6:"Cistern empty", 7:"extBreak" */
|
|
1378
1540
|
newThread.state = 'wait'; // zustand des Ventils Softwaremäßig
|
|
1379
1541
|
newThread.enable = false; // zustand des Ventil softwaremäßig
|
|
1380
|
-
newThread.myBreak = false; // meine interne Pause
|
|
1542
|
+
newThread.myBreak = false; // meine interne Pause Intervallberegnung
|
|
1381
1543
|
newThread.extBreak = myConfig.config[res.sprinkleID].extBreak; // extBreak wird über .sprinkle.*.extBreak geschaltet
|
|
1382
1544
|
newThread.killSprinkle = false; // Löschauftrag ausführen am Ende in threadList
|
|
1383
1545
|
newThread.litersPerSecond = myConfig.config[res.sprinkleID].pipeFlow / 3600; // Wasserverbrauchsmenge pro Sekunde
|
|
@@ -1410,7 +1572,8 @@ const valveControl = {
|
|
|
1410
1572
|
}, // End addList
|
|
1411
1573
|
|
|
1412
1574
|
timeBasedRestriction: async function (enable) { //Irrigation ban => zeitliche Bewässerungsbeschränkung noch zu bearbeiten ! ! !
|
|
1413
|
-
try {
|
|
1575
|
+
try {
|
|
1576
|
+
sensorPressure.inadequatePressure = false; // Kontrolle Drucksensorwert zurücksetzen, damit die Bewässerungsbeschränkung korrekt funktioniert, wenn der Drucksensorwert während der Bewässerungsbeschränkung unter dem Minimum lag
|
|
1414
1577
|
timeBasedRestrictionEn = enable;
|
|
1415
1578
|
if (threadList) {
|
|
1416
1579
|
if (timeBasedRestrictionEn === true) { // zeitliche Bewässerungsbeschränkung aktiv
|
|
@@ -1591,15 +1754,26 @@ const valveControl = {
|
|
|
1591
1754
|
* @param {number|string|boolean} levelCistern
|
|
1592
1755
|
*/
|
|
1593
1756
|
setFillLevelCistern: function (levelCistern) {
|
|
1594
|
-
|
|
1757
|
+
let myFillLevelCistern = 0;
|
|
1758
|
+
adapter.log.debug(`setFillLevelCistern: ${ levelCistern }`);
|
|
1595
1759
|
if(typeof levelCistern === 'number') {
|
|
1596
|
-
|
|
1760
|
+
myFillLevelCistern = parseInt(levelCistern);
|
|
1597
1761
|
}else if(typeof levelCistern === 'string') {
|
|
1598
|
-
|
|
1762
|
+
myFillLevelCistern = parseInt(levelCistern);
|
|
1599
1763
|
}else if(typeof levelCistern === 'boolean') {
|
|
1600
|
-
(levelCistern === true) ?
|
|
1764
|
+
(levelCistern === true) ? myFillLevelCistern = 100 : myFillLevelCistern = 0;
|
|
1765
|
+
}
|
|
1766
|
+
if(typeof myFillLevelCistern !== "number"
|
|
1767
|
+
|| myFillLevelCistern < 0
|
|
1768
|
+
|| myFillLevelCistern > 100
|
|
1769
|
+
) {
|
|
1770
|
+
adapter.log.warn(`setFillLevelCistern (0...100% || true/false) => Wrong value: ${ levelCistern }, Type: ${ typeof levelCistern }`);
|
|
1771
|
+
return;
|
|
1772
|
+
}
|
|
1773
|
+
if (myFillLevelCistern != fillLevelCistern) {
|
|
1774
|
+
fillLevelCistern = myFillLevelCistern;
|
|
1775
|
+
setActualPump();
|
|
1601
1776
|
}
|
|
1602
|
-
setActualPump();
|
|
1603
1777
|
}, // End setFillLevelCistern
|
|
1604
1778
|
|
|
1605
1779
|
/**
|
|
@@ -1609,8 +1783,72 @@ const valveControl = {
|
|
|
1609
1783
|
*/
|
|
1610
1784
|
getIntBreakCisternPump: function () {
|
|
1611
1785
|
return (adapter.config.pumpSelection === 'cistern') ? currentPumpUse.intBreak : false;
|
|
1612
|
-
}
|
|
1786
|
+
},
|
|
1613
1787
|
|
|
1788
|
+
/**
|
|
1789
|
+
* Setzt den Drucksensorwert
|
|
1790
|
+
* https://blog.logrocket.com/complete-guide-abortcontroller/
|
|
1791
|
+
*
|
|
1792
|
+
* @param {number} pressure
|
|
1793
|
+
*/
|
|
1794
|
+
setSensorPressure: async function (pressure) {
|
|
1795
|
+
let alteredPressure = false; // Veränderter Druck => updateList starten um Verbrauch anzupassen / Ventile ausschalten
|
|
1796
|
+
let reviews = '';
|
|
1797
|
+
try {
|
|
1798
|
+
sensorPressure.value = parseFloat(pressure).toFixed(1);
|
|
1799
|
+
if (currentPumpUse.enable === true && adapter.config.minimumPressure > pressure) {
|
|
1800
|
+
if (sensorPressure.ac === null) {
|
|
1801
|
+
sensorPressure.ac = new AbortController();
|
|
1802
|
+
await asyncTime.setTimeout(60000, undefined, { signal: sensorPressure.ac.signal }); // max. 60s warten und Drucksensorwert erneut prüfen, bevor die Pumpe ausgeschaltet wird
|
|
1803
|
+
const _currentPressure = await adapter.getForeignStateAsync(adapter.config.sensorPressure);
|
|
1804
|
+
if (_currentPressure?.val
|
|
1805
|
+
&& currentPumpUse.enable === true
|
|
1806
|
+
&& adapter.config.minimumPressure > parseFloat(_currentPressure.val)
|
|
1807
|
+
) {
|
|
1808
|
+
reviews = 'Not Okay'
|
|
1809
|
+
if (sensorPressure.inadequatePressure === false) {
|
|
1810
|
+
alteredPressure = true;
|
|
1811
|
+
sensorPressure.inadequatePressure = true;
|
|
1812
|
+
}
|
|
1813
|
+
sensorPressure.value = parseFloat(_currentPressure.val).toFixed(1);
|
|
1814
|
+
adapter.log.warn(`Pressure sensor value ${ pressure } bar is below the minimum pressure ${ adapter.config.minimumPressure } bar. The pump will be turned off to prevent damage. Please check the pressure sensor and the configuration of the minimum pressure!`);
|
|
1815
|
+
if (adapter.config.notificationEnabled) {
|
|
1816
|
+
sendMessageText.sendMessage(`Pressure sensor value ${ pressure } bar is below the minimum pressure ${ adapter.config.minimumPressure } bar. The pump will be turned off to prevent damage. Please check the pressure sensor and the configuration of the minimum pressure!`);
|
|
1817
|
+
}
|
|
1818
|
+
sensorPressure.ac.abort(); // setTimeout abbrechen, da die Pumpe bereits ausgeschaltet wird
|
|
1819
|
+
sensorPressure.ac = null; // AbortController zurücksetzen
|
|
1820
|
+
} else if (_currentPressure?.val) {
|
|
1821
|
+
reviews = 'Okay';
|
|
1822
|
+
}
|
|
1823
|
+
sensorPressure.ac = null; // AbortController zurücksetzen
|
|
1824
|
+
} else {
|
|
1825
|
+
reviews = 'I don\'t know';
|
|
1826
|
+
}
|
|
1827
|
+
} else if (currentPumpUse.enable === false || adapter.config.minimumPressure <= pressure) {
|
|
1828
|
+
reviews = 'Okay'
|
|
1829
|
+
if (sensorPressure?.ac !== null) {
|
|
1830
|
+
await sensorPressure.ac.abort(); // AbortController zurücksetzen
|
|
1831
|
+
sensorPressure.ac = null;
|
|
1832
|
+
}
|
|
1833
|
+
} else {
|
|
1834
|
+
reviews = 'Okay'
|
|
1835
|
+
}
|
|
1836
|
+
} catch (error) {
|
|
1837
|
+
if (error.name === 'AbortError') {
|
|
1838
|
+
adapter.log.debug(`setSensorPressure(${pressure}): The shutdown process was aborted because the operating pressure was restored.`);
|
|
1839
|
+
if (sensorPressure?.ac !== null) {
|
|
1840
|
+
sensorPressure.ac.abort(); // AbortController zurücksetzen
|
|
1841
|
+
sensorPressure.ac = null;
|
|
1842
|
+
}
|
|
1843
|
+
}
|
|
1844
|
+
} finally {
|
|
1845
|
+
await adapter.setStateAsync(`info.waterPressure`, {
|
|
1846
|
+
val: `${ reviews } ( ${ sensorPressure.value } bar )`,
|
|
1847
|
+
ack: true
|
|
1848
|
+
});
|
|
1849
|
+
if (alteredPressure) updateList();
|
|
1850
|
+
}
|
|
1851
|
+
}
|
|
1614
1852
|
}; // End valveControl
|
|
1615
1853
|
|
|
1616
1854
|
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
|