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