From 5da9a0efcd4afbed177f1bb9c71ea6bf6c8c2e2b Mon Sep 17 00:00:00 2001 From: simatec Date: Tue, 18 Jul 2023 00:21:27 +0200 Subject: [PATCH 01/10] (simatec) Beta 1.6.1 --- README.md | 3 + lib/sunProtect.js | 2707 +++++++++++++++++++++++---------------------- 2 files changed, 1391 insertions(+), 1319 deletions(-) diff --git a/README.md b/README.md index 4bafa0b3..48d07099 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,9 @@ When the adapter crashes or an other Code error happens, this error message that ## Changelog +### __WORK IN PROGRESS__ +* (simatec) Fix Heat protection + ### 1.6.0 (2023-07-16) * (simatec) Manu mode block added * (simatec) Heat protection added diff --git a/lib/sunProtect.js b/lib/sunProtect.js index c3859606..c4bc1659 100644 --- a/lib/sunProtect.js +++ b/lib/sunProtect.js @@ -6,1359 +6,1428 @@ const setShutterState = require('./setShutter.js').setShutterState; let timerSleep = 0; async function sleep(ms) { - return new Promise(async (resolve) => { - // @ts-ignore - timerSleep = setTimeout(async () => resolve(), ms); - }); + return new Promise(async (resolve) => { + // @ts-ignore + timerSleep = setTimeout(async () => resolve(), ms); + }); } // @ts-ignore async function sunProtect(adapter, elevation, azimuth, shutterSettings) { - const driveDelayUpSleep = adapter.config.driveDelayUpAstro != 0 ? adapter.config.driveDelayUpAstro * 1000 : 20; - - await sleep(2000); - if (shutterSettings) { - const result = shutterSettings.filter((/** @type {{ enabled: boolean; }} */ d) => d.enabled === true); // Filter enabled - - if (elevation > adapter.config.sunProtEndElevation) { - for (const i in result) { - for (const s in shutterSettings) { - if (shutterSettings[s].shutterName == result[i].shutterName) { - let resultDirectionRangeMinus = 0; - let resultDirectionRangePlus = 0; - let convertShutter = false; - let heightDownSun = shutterSettings[s].heightDownSun; - - const nameDevice = shutterSettings[s].shutterName.replace(/[.;, ]/g, '_'); - - if (parseFloat(shutterSettings[s].heightDown) < parseFloat(shutterSettings[s].heightUp)) { - convertShutter = false; - } else if (parseFloat(shutterSettings[s].heightDown) > parseFloat(shutterSettings[s].heightUp)) { - convertShutter = true; + const driveDelayUpSleep = adapter.config.driveDelayUpAstro != 0 ? adapter.config.driveDelayUpAstro * 1000 : 20; + const vRound = adapter.config.shutterStateRound; + + await sleep(2000); + if (shutterSettings) { + const result = shutterSettings.filter((/** @type {{ enabled: boolean; }} */ d) => d.enabled === true); // Filter enabled + + if (elevation > adapter.config.sunProtEndElevation) { + for (const i in result) { + for (const s in shutterSettings) { + if (shutterSettings[s].shutterName == result[i].shutterName) { + let resultDirectionRangeMinus = 0; + let resultDirectionRangePlus = 0; + let convertShutter = false; + let heightDownSun = shutterSettings[s].heightDownSun; + + const nameDevice = shutterSettings[s].shutterName.replace(/[.;, ]/g, '_'); + + if (parseFloat(shutterSettings[s].heightDown) < parseFloat(shutterSettings[s].heightUp)) { + convertShutter = false; + } else if (parseFloat(shutterSettings[s].heightDown) > parseFloat(shutterSettings[s].heightUp)) { + convertShutter = true; + } + + const pendingAlarm = await checkPendingAlarm(adapter, shutterSettings[s]); + + const _autoSunState = await adapter.getStateAsync(`shutters.autoSun.${nameDevice}`).catch((e) => adapter.log.warn(e)); + + if (_autoSunState && _autoSunState.val === true) { + let currentValue = ''; + let _triggerState; + let mustValue = ''; + let mustValueTilted = ''; + + switch (shutterSettings[s].type) { + + // +++++++++++++++++ sunprotect with in/outside temperature and Lightsensor +++++++++++++++ + + case 'in- & outside temperature': // in- & outside temperature + _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; + mustValue = ('' + shutterSettings[s].triggerState); + mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); + + if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { + currentValue = ('' + _triggerState.val); + } + + if ((currentValue === mustValue || currentValue === mustValueTilted) && shutterSettings[s].tempSensor != '' || + (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off' && shutterSettings[s].tempSensor != '') || + (shutterSettings[s].triggerID == '' && shutterSettings[s].tempSensor != '')) { + + let insideTemp = 0; + let outsideTemp = 0; + let sunLight = 0; + + const _insideTempState = shutterSettings[s].tempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].tempSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _insideTempState != undefined && _insideTempState != null && _insideTempState.val != undefined) { + insideTemp = parseFloat(_insideTempState.val); + } + + const _outsideTempState = shutterSettings[s].outsideTempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].outsideTempSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _outsideTempState != undefined && _outsideTempState != null && _outsideTempState.val != undefined) { + outsideTemp = parseFloat(_outsideTempState.val); + } + + const _sunLight = shutterSettings[s].lightSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].lightSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _sunLight != undefined && _sunLight != null && _sunLight.val != undefined) { + sunLight = parseFloat(_sunLight.val); + } + + // heatProtection + if (shutterSettings[s].heatProtection == true && + shutterSettings[s].tempHeatProtection < outsideTemp && + shutterSettings[s].currentHeight != shutterSettings[s].heightDown) { + + shutterSettings[s].currentAction = shutterSettings[s].currentAction == 'sunProtect' ? '' : shutterSettings[s].currentAction; + heightDownSun = shutterSettings[s].heightDown; + adapter.log.debug(`Heat Protection for ${shutterSettings[s].shutterName} is active`); + adapter.log.debug(`currentAction ${shutterSettings[s].currentAction}`); + + } else { + heightDownSun = shutterSettings[s].heightDownSun; + } + + if (shutterSettings[s].sunProtectEndtimerid != '' && + shutterSettings[s].sunProtectEndtimerid != '0' && + shutterSettings[s].lightSensor != '' && + shutterSettings[s].valueLight < sunLight) { + + adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); + clearTimeout(shutterSettings[s].sunProtectEndtimerid); + shutterSettings[s].sunProtectEndtimerid = ''; + } + + if (currentValue === mustValue || currentValue === mustValueTilted || + (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || + (shutterSettings[s].triggerID == '')) { + + if (insideTemp > shutterSettings[s].tempInside) { + if (shutterSettings[s].tempOutside < outsideTemp && + (shutterSettings[s].lightSensor != '' && + shutterSettings[s].valueLight < sunLight || + shutterSettings[s].lightSensor == '') && + shutterSettings[s].currentAction != 'sunProtect' && + shutterSettings[s].currentAction != 'OpenInSunProtect' && + shutterSettings[s].currentAction != 'Manu_Mode') { + + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); + + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && + convertShutter == false) || + (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && + convertShutter == true)) && + Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && + (shutterSettings[s].currentHeight == shutterSettings[s].heightUp || + (shutterSettings[s].heatProtection == true && + shutterSettings[s].tempHeatProtection < outsideTemp))) { + + shutterSettings[s].currentAction = 'sunProtect'; + shutterSettings[s].lastAutoAction = 'down_Sunprotect'; + shutterSettings[s].currentHeight = heightDownSun; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #410'); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); + adapter.log.debug('Temperature inside: ' + insideTemp + ' > ' + shutterSettings[s].tempInside + ' AND ( Temperatur outside: ' + outsideTemp + ' > ' + shutterSettings[s].tempOutside + ' AND Light: ' + sunLight + ' > ' + shutterSettings[s].valueLight + ' )'); + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%'); + } + // Shutter closed. Set currentAction = sunProtect when sunProtect starts => + // If shutter is opened automatically it can be opened in height heightDownSun directly + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].heightDown) && + Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && + shutterSettings[s].currentHeight != shutterSettings[s].heightUp && + shutterSettings[s].currentAction != 'down' && + shutterSettings[s].currentAction != 'middle' && + shutterSettings[s].currentAction != 'Xmas' && + shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! + + shutterSettings[s].currentAction = 'OpenInSunProtect'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); + } + //Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> + // set sunProtect again + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) && + Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && + shutterSettings[s].currentHeight != shutterSettings[s].heightUp && + shutterSettings[s].currentHeight != shutterSettings[s].heightDown && + shutterSettings[s].currentAction == '') { + + shutterSettings[s].currentAction = 'sunProtect'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' HeightDownSun:' + heightDownSun); + } + } + } else { + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + } } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + if (insideTemp > shutterSettings[s].tempInside) { + if (shutterSettings[s].tempOutside < outsideTemp && + (shutterSettings[s].lightSensor != '' && + shutterSettings[s].valueLight < sunLight || + shutterSettings[s].lightSensor == '') && + shutterSettings[s].triggerAction != 'sunProtect' && + shutterSettings[s].triggerAction != 'OpenInSunProtect' && + shutterSettings[s].triggerAction != 'Manu_Mode') { + + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp + ' AND triggerAction:' + shutterSettings[s].triggerAction + ' != down '); + + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && + convertShutter == false) || + (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && + convertShutter == true)) && + Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && + shutterSettings[s].currentHeight == shutterSettings[s].heightUp && + shutterSettings[s].triggerAction != 'down' && + shutterSettings[s].currentAction != 'middle' && + shutterSettings[s].currentAction != 'Xmas') { + + shutterSettings[s].triggerHeight = parseFloat(heightDownSun); + shutterSettings[s].triggerAction = 'sunProtect'; + + adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + } - const pendingAlarm = await checkPendingAlarm(adapter, shutterSettings[s]); - - const _autoSunState = await adapter.getStateAsync(`shutters.autoSun.${nameDevice}`).catch((e) => adapter.log.warn(e)); - - if (_autoSunState && _autoSunState.val === true) { - let currentValue = ''; - let _triggerState; - let mustValue = ''; - let mustValueTilted = ''; - - switch (shutterSettings[s].type) { - - // +++++++++++++++++ sunprotect with in/outside temperature and Lightsensor +++++++++++++++ - - case 'in- & outside temperature': // in- & outside temperature - _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; - mustValue = ('' + shutterSettings[s].triggerState); - mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); - - if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { - currentValue = ('' + _triggerState.val); - } - - if ((currentValue === mustValue || currentValue === mustValueTilted) && shutterSettings[s].tempSensor != '' || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off' && shutterSettings[s].tempSensor != '') || (shutterSettings[s].triggerID == '' && shutterSettings[s].tempSensor != '')) { - let insideTemp = 0; - let outsideTemp = 0; - let sunLight = 0; - - const _insideTempState = shutterSettings[s].tempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].tempSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _insideTempState != undefined && _insideTempState != null && _insideTempState.val != undefined) { - insideTemp = parseFloat(_insideTempState.val); - } - - const _outsideTempState = shutterSettings[s].outsideTempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].outsideTempSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _outsideTempState != undefined && _outsideTempState != null && _outsideTempState.val != undefined) { - outsideTemp = parseFloat(_outsideTempState.val); - } - - const _sunLight = shutterSettings[s].lightSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].lightSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _sunLight != undefined && _sunLight != null && _sunLight.val != undefined) { - sunLight = parseFloat(_sunLight.val); - } - - // heatProtection - if (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown) { - shutterSettings[s].currentAction == 'sunProtect' ? '' : shutterSettings[s].currentAction; - heightDownSun = shutterSettings[s].heightDown; - adapter.log.debug(`Heat Protection for ${shutterSettings[s].shutterName} is active`); - } else { - heightDownSun = shutterSettings[s].heightDownSun; - } - - if (shutterSettings[s].sunProtectEndtimerid != '' && shutterSettings[s].sunProtectEndtimerid != '0' && shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight) { - adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); - clearTimeout(shutterSettings[s].sunProtectEndtimerid); - shutterSettings[s].sunProtectEndtimerid = ''; - } - - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || (shutterSettings[s].triggerID == '')) { - if (insideTemp > shutterSettings[s].tempInside) { - if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].currentAction != 'sunProtect' && shutterSettings[s].currentAction != 'OpenInSunProtect' && shutterSettings[s].currentAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); - - if ((( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound > parseFloat(heightDownSun) && convertShutter == false) || ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp) { - shutterSettings[s].currentAction = 'sunProtect'; - shutterSettings[s].lastAutoAction = 'down_Sunprotect'; - shutterSettings[s].currentHeight = heightDownSun; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #410'); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); - adapter.log.debug('Temperature inside: ' + insideTemp + ' > ' + shutterSettings[s].tempInside + ' AND ( Temperatur outside: ' + outsideTemp + ' > ' + shutterSettings[s].tempOutside + ' AND Light: ' + sunLight + ' > ' + shutterSettings[s].valueLight + ' )'); - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%'); - } - // Shutter closed. Set currentAction = sunProtect when sunProtect starts => - // If shutter is opened automatically it can be opened in height heightDownSun directly - else if ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].heightDown) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas' && shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! - shutterSettings[s].currentAction = 'OpenInSunProtect'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); - } - //Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> - // set sunProtect again - else if ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(heightDownSun) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown && shutterSettings[s].currentAction == '') { - shutterSettings[s].currentAction = 'sunProtect'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' HeightDownSun:' + heightDownSun); - } - } - } else { - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - } - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - if (insideTemp > shutterSettings[s].tempInside) { - if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].triggerAction != 'sunProtect' && shutterSettings[s].triggerAction != 'OpenInSunProtect' && shutterSettings[s].triggerAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp + ' AND triggerAction:' + shutterSettings[s].triggerAction + ' != down '); - if ((( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound > parseFloat(heightDownSun) && convertShutter == false) || ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp && shutterSettings[s].triggerAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas') { - shutterSettings[s].triggerHeight = parseFloat(heightDownSun); - shutterSettings[s].triggerAction = 'sunProtect'; - - adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - } - - } - } else { - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - } - } - } - } - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { - const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); - const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); - const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); - - if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { - adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); - shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { - shutterSettings[s].sunProtectEndtimerid = '0'; - }, shutterSettings[s].sunProtectEndDely * 60000, i); - } - - if (insideTemp < parseFloat(hysteresisInside) || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { - - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].currentAction = 'up'; - shutterSettings[s].currentHeight = shutterSettings[s].heightUp; - shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #411'); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); - adapter.log.debug('Temperature inside: ' + insideTemp + ' < ' + hysteresisInside + ' OR ( Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight + ' )'); - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%') - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].sunProtectEndtimerid = '' - shutterSettings[s].currentAction = 'none'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); - const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); - const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); - - if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { - adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); - shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { - shutterSettings[s].sunProtectEndtimerid = '0'; - }, shutterSettings[s].sunProtectEndDely * 60000, i); - } - - if (insideTemp < parseFloat(hysteresisInside) || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { - - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].triggerAction = 'up'; - - adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); - adapter.log.debug('Temperature inside: ' + insideTemp + ' < ' + hysteresisInside + ' OR ( Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight + ' )'); - adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].sunProtectEndtimerid = '' - shutterSettings[s].triggerAction = 'none'; - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - } - } - } - } - await sleep(driveDelayUpSleep); - break; - - ////////////////////////////////////////////////////////////////////////////////////////////////////// - - // +++++++++++++++++ sunprotect with in/outside temperature, Lightsensor and direction +++++++++++++++ - - case 'in- & outside temperature and direction': // in- & outside temperature and direction - resultDirectionRangeMinus = parseInt(shutterSettings[s].direction) - parseInt(shutterSettings[s].directionRange); - resultDirectionRangePlus = parseInt(shutterSettings[s].direction) + parseInt(shutterSettings[s].directionRange); - - _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; - mustValue = ('' + shutterSettings[s].triggerState); - mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); - - if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { - currentValue = ('' + _triggerState.val); - } - - if ((currentValue === mustValue || currentValue === mustValueTilted) && shutterSettings[s].tempSensor != '' || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off' && shutterSettings[s].tempSensor != '') || (shutterSettings[s].triggerID == '' && shutterSettings[s].tempSensor != '')) { - let insideTemp = 0; - let outsideTemp = 0; - let sunLight = 0; - - const _insideTempState = shutterSettings[s].tempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].tempSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _insideTempState != undefined && _insideTempState != null && _insideTempState.val != undefined) { - insideTemp = parseFloat(_insideTempState.val); - } - - const _outsideTempState = shutterSettings[s].outsideTempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].outsideTempSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _outsideTempState != undefined && _outsideTempState != null && _outsideTempState.val != undefined) { - outsideTemp = parseFloat(_outsideTempState.val); - } - - // heatProtection - if (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown) { - shutterSettings[s].currentAction == 'sunProtect' ? '' : shutterSettings[s].currentAction; - heightDownSun = shutterSettings[s].heightDown; - adapter.log.debug(`Heat Protection for ${shutterSettings[s].shutterName} is active`); - } else { - heightDownSun = shutterSettings[s].heightDownSun; - } - - const _sunLight = shutterSettings[s].lightSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].lightSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _sunLight != undefined && _sunLight != null && _sunLight.val != undefined) { - sunLight = parseFloat(_sunLight.val); - } - - if (shutterSettings[s].sunProtectEndtimerid != '' && shutterSettings[s].sunProtectEndtimerid != '0' && shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight) { - adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); - clearTimeout(shutterSettings[s].sunProtectEndtimerid); - shutterSettings[s].sunProtectEndtimerid = ''; - } - - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || (shutterSettings[s].triggerID == '')) { - if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth && insideTemp > shutterSettings[s].tempInside) { - if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].currentAction != 'sunProtect' && shutterSettings[s].currentAction != 'OpenInSunProtect' && shutterSettings[s].currentAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); - - if ((( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound > parseFloat(heightDownSun) && convertShutter == false) || ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp) { - shutterSettings[s].currentAction = 'sunProtect'; - shutterSettings[s].currentHeight = heightDownSun; - shutterSettings[s].lastAutoAction = 'down_Sunprotect'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #412'); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); - adapter.log.debug('Temperature inside: ' + insideTemp + ' > ' + shutterSettings[s].tempInside + ' AND ( Temperatur outside: ' + outsideTemp + ' > ' + shutterSettings[s].tempOutside + ' AND Light: ' + sunLight + ' > ' + shutterSettings[s].valueLight + ' )'); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%'); - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%') - } - // Shutter closed. Set currentAction = sunProtect when sunProtect starts => - // If shutter is opened automatically it can be opened in height heightDownSun directly - else if ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].heightDown) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas' && shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! - shutterSettings[s].currentAction = 'OpenInSunProtect'; - adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); - } - // Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> - // set sunProtect again - else if ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(heightDownSun) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown && shutterSettings[s].currentAction == '') { - shutterSettings[s].currentAction = 'sunProtect'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' HeightDownSun:' + heightDownSun); - } - } - } else { - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - } - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth && insideTemp > shutterSettings[s].tempInside) { - if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].triggerAction != 'sunProtect' && shutterSettings[s].triggerAction != 'OpenInSunProtect' && shutterSettings[s].triggerAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp + ' AND triggerAction:' + shutterSettings[s].triggerAction + ' != down '); - if ((( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound > parseFloat(heightDownSun) && convertShutter == false) || ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp && shutterSettings[s].triggerAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas') { - shutterSettings[s].triggerHeight = parseFloat(heightDownSun); - shutterSettings[s].triggerAction = 'sunProtect'; - - adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - } - } - } else { - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); - } - } - } - } - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { - const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); - const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); - const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); - - if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { - adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); - shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { - shutterSettings[s].sunProtectEndtimerid = '0'; - }, shutterSettings[s].sunProtectEndDely * 60000, i); - } - - - if (insideTemp < parseFloat(hysteresisInside) || (resultDirectionRangePlus) < azimuth || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { - - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].currentAction = 'up'; - shutterSettings[s].currentHeight = shutterSettings[s].heightUp; - shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #413'); - - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); - adapter.log.debug('Range: ' + resultDirectionRangePlus + ' < ' + azimuth + ' OR Temperature inside: ' + insideTemp + ' < ' + hysteresisInside + ' OR ( Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight + ')'); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + shutterSettings[s].heightUp + '%'); - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].sunProtectEndtimerid = '' - shutterSettings[s].currentAction = 'none'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); - const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); - const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); - - if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { - adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); - shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { - shutterSettings[s].sunProtectEndtimerid = '0'; - }, shutterSettings[s].sunProtectEndDely * 60000, i); - } - - if (insideTemp < parseFloat(hysteresisInside) || (resultDirectionRangePlus) < azimuth || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { - - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].triggerAction = 'up'; - - adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); - adapter.log.debug('Temperature inside: ' + insideTemp + ' < ' + hysteresisInside + ' OR ( Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight + ' )'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].triggerAction = 'none'; - - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } - } - } - } - await sleep(driveDelayUpSleep); - break; - - ////////////////////////////////////////////////////////////////////////////////////////////////////// - - // +++++++++++++++++ sunprotect with outside temperature, Lightsensor and direction +++++++++++++++ - - case 'outside temperature and direction': //outside temperature and direction - resultDirectionRangeMinus = parseInt(shutterSettings[s].direction) - parseInt(shutterSettings[s].directionRange); - resultDirectionRangePlus = parseInt(shutterSettings[s].direction) + parseInt(shutterSettings[s].directionRange); - - _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; - mustValue = ('' + shutterSettings[s].triggerState); - mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); - - if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { - currentValue = ('' + _triggerState.val); - } - - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off') || (shutterSettings[s].triggerID == '')) { - let outsideTemp = 0; - let sunLight = 0; - - const _outsideTempState = shutterSettings[s].outsideTempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].outsideTempSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _outsideTempState != undefined && _outsideTempState != null && _outsideTempState.val != undefined) { - outsideTemp = parseFloat(_outsideTempState.val); - } - - // heatProtection - if (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown) { - shutterSettings[s].currentAction == 'sunProtect' ? '' : shutterSettings[s].currentAction; - heightDownSun = shutterSettings[s].heightDown; - adapter.log.debug(`Heat Protection for ${shutterSettings[s].shutterName} is active`); - } else { - heightDownSun = shutterSettings[s].heightDownSun; - } - - const _sunLight = shutterSettings[s].lightSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].lightSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _sunLight != undefined && _sunLight != null && _sunLight.val != undefined) { - sunLight = parseFloat(_sunLight.val); - } - - if (shutterSettings[s].sunProtectEndtimerid != '' && shutterSettings[s].sunProtectEndtimerid != '0' && shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight) { - adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); - clearTimeout(shutterSettings[s].sunProtectEndtimerid); - shutterSettings[s].sunProtectEndtimerid = ''; - } - - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || (shutterSettings[s].triggerID == '')) { - if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth) { - if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].currentAction != 'sunProtect' && shutterSettings[s].currentAction != 'OpenInSunProtect' && shutterSettings[s].currentAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); - - if ((( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound > parseFloat(heightDownSun) && convertShutter == false) || ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp) { - shutterSettings[s].currentAction = 'sunProtect'; - shutterSettings[s].currentHeight = heightDownSun; - shutterSettings[s].lastAutoAction = 'down_Sunprotect'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #414'); - - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); - adapter.log.debug('Temperatur outside: ' + outsideTemp + ' > ' + shutterSettings[s].tempOutside + ' AND Light: ' + sunLight + ' > ' + shutterSettings[s].valueLight); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%') - } - // Shutter closed. Set currentAction = sunProtect when sunProtect starts => - // If shutter is opened automatically it can be opened in height heightDownSun directly - else if ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].heightDown) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas' && shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! - shutterSettings[s].currentAction = 'OpenInSunProtect'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); - } - // Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> - // set sunProtect again - else if ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(heightDownSun) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown && shutterSettings[s].currentAction == '') { - shutterSettings[s].currentAction = 'sunProtect'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' HeightDownSun:' + heightDownSun); - } - } - } else { - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); - } - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth) { - if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].triggerAction != 'sunProtect' && shutterSettings[s].triggerAction != 'OpenInSunProtect' && shutterSettings[s].triggerAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); - if ((( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound > parseFloat(heightDownSun) && convertShutter == false) || ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp && shutterSettings[s].triggerAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas') { - shutterSettings[s].triggerHeight = parseFloat(heightDownSun); - shutterSettings[s].triggerAction = 'sunProtect'; - - adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - } - - } - } else { - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); - } - } - } - } - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { - const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); - const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); - - if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { - adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); - shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { - shutterSettings[s].sunProtectEndtimerid = '0'; - }, shutterSettings[s].sunProtectEndDely * 60000, i); - } - - if ((resultDirectionRangePlus) < azimuth || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].currentAction = 'up'; - shutterSettings[s].currentHeight = shutterSettings[s].heightUp; - shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #415'); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); - adapter.log.debug('Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight); - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + shutterSettings[s].heightUp + '%') - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].currentAction = 'none'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); - const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); - - if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { - adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); - shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { - shutterSettings[s].sunProtectEndtimerid = '0'; - }, shutterSettings[s].sunProtectEndDely * 60000, i); - } - - if ((resultDirectionRangePlus) < azimuth || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].triggerAction = 'up'; - - adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].sunProtectEndtimerid = '' - shutterSettings[s].triggerAction = 'none'; - - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } - } - } - } - await sleep(driveDelayUpSleep); - break; - - ////////////////////////////////////////////////////////////////////////////////////////////////////// - - // ++++++++++++++++++++++++++++++ sunprotect with direction ++++++++++++++++++++++++++++++++++ - - case 'only direction': //only direction - resultDirectionRangeMinus = parseInt(shutterSettings[s].direction) - parseInt(shutterSettings[s].directionRange); - resultDirectionRangePlus = parseInt(shutterSettings[s].direction) + parseInt(shutterSettings[s].directionRange); - - _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; - mustValue = ('' + shutterSettings[s].triggerState); - mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); - - if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { - currentValue = ('' + _triggerState.val); - } - - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off') || (shutterSettings[s].triggerID == '')) { - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || (shutterSettings[s].triggerID == '')) { - if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth && shutterSettings[s].currentAction != 'sunProtect' && shutterSettings[s].currentAction != 'OpenInSunProtect' && shutterSettings[s].currentAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); - if ((( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound > parseFloat(heightDownSun) && convertShutter == false) || ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp) { - shutterSettings[s].currentAction = 'sunProtect'; - shutterSettings[s].currentHeight = heightDownSun; - shutterSettings[s].lastAutoAction = 'down_Sunprotect'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #416'); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); - adapter.log.debug('RangeMinus: ' + resultDirectionRangeMinus + ' < ' + azimuth + 'RangePlus: ' + resultDirectionRangePlus + ' > ' + azimuth); - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%'); - } - // Shutter closed. Set currentAction = sunProtect when sunProtect starts => - // If shutter is opened automatically it can be opened in height heightDownSun directly - else if ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].heightDown) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas' && shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! - shutterSettings[s].currentAction = 'OpenInSunProtect'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); - } - // Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> - // set sunProtect again - else if ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(heightDownSun) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown && shutterSettings[s].currentAction == '') { - shutterSettings[s].currentAction = 'sunProtect'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' HeightDownSun:' + heightDownSun); - } - } - } else { - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth && shutterSettings[s].triggerAction != 'sunProtect' && shutterSettings[s].triggerAction != 'OpenInSunProtect' && shutterSettings[s].triggerAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); - if ((( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound > parseFloat(heightDownSun) && convertShutter == false) || ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp && shutterSettings[s].triggerAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas') { - shutterSettings[s].triggerHeight = parseFloat(heightDownSun); - shutterSettings[s].triggerAction = 'sunProtect'; - - adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - } - } - } else { - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); - } - - } - } - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { - if ((resultDirectionRangePlus) < azimuth) { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].currentAction = 'up'; - shutterSettings[s].currentHeight = shutterSettings[s].heightUp; - shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #417'); - - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); - adapter.log.debug('Range: ' + resultDirectionRangePlus + ' < ' + azimuth); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + shutterSettings[s].heightUp + '%') - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].currentAction = 'none'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - if ((resultDirectionRangePlus) < azimuth) { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].triggerAction = 'up'; - - adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].triggerAction = 'none'; - - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } - } - } - } - await sleep(driveDelayUpSleep); - break; - - ////////////////////////////////////////////////////////////////////////////////////////////////////// - - // ++++++++++++++++++++++++ sunprotect with outside temperature and Lightsensor +++++++++++++++++++++++ - - case 'only outside temperature': //only outside temperature - _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; - mustValue = ('' + shutterSettings[s].triggerState); - mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); - - if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { - currentValue = ('' + _triggerState.val); - } - - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off') || (shutterSettings[s].triggerID == '')) { - let outsideTemp = 0; - let sunLight = 0; - - const _outsideTempState = shutterSettings[s].outsideTempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].outsideTempSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _outsideTempState != undefined && _outsideTempState != null && _outsideTempState.val != undefined) { - outsideTemp = parseFloat(_outsideTempState.val); - } - - // heatProtection - if (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown) { - shutterSettings[s].currentAction == 'sunProtect' ? '' : shutterSettings[s].currentAction; - heightDownSun = shutterSettings[s].heightDown; - adapter.log.debug(`Heat Protection for ${shutterSettings[s].shutterName} is active`); - } else { - heightDownSun = shutterSettings[s].heightDownSun; - } - - const _sunLight = shutterSettings[s].lightSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].lightSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _sunLight != undefined && _sunLight != null && _sunLight.val != undefined) { - sunLight = parseFloat(_sunLight.val); - } - - if (shutterSettings[s].sunProtectEndtimerid != '' && shutterSettings[s].sunProtectEndtimerid != '0' && shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight) { - adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); - clearTimeout(shutterSettings[s].sunProtectEndtimerid); - shutterSettings[s].sunProtectEndtimerid = ''; - } - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || (shutterSettings[s].triggerID == '')) { - if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].currentAction != 'sunProtect' && shutterSettings[s].currentAction != 'OpenInSunProtect' && shutterSettings[s].currentAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); - - if ((( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound > parseFloat(heightDownSun) && convertShutter == false) || ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp) { - shutterSettings[s].currentAction = 'sunProtect'; - shutterSettings[s].currentHeight = heightDownSun; - shutterSettings[s].lastAutoAction = 'down_Sunprotect'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #418'); - - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); - adapter.log.debug('Temperature outside: ' + outsideTemp + ' > ' + shutterSettings[s].tempOutside + ' AND Light: ' + sunLight + ' > ' + shutterSettings[s].valueLight); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%'); - } - // Shutter closed. Set currentAction = sunProtect when sunProtect starts => - // If shutter is opened automatically it can be opened in height heightDownSun directly - else if ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].heightDown) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas' && shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! - shutterSettings[s].currentAction = 'OpenInSunProtect'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); - } - // Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> - // set sunProtect again - else if ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(heightDownSun) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown && shutterSettings[s].currentAction == '') { - shutterSettings[s].currentAction = 'sunProtect'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' HeightDownSun:' + heightDownSun); - } - } - } else { - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].triggerAction != 'sunProtect' && shutterSettings[s].triggerAction != 'OpenInSunProtect' && shutterSettings[s].triggerAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); - - if ((( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound > parseFloat(heightDownSun) && convertShutter == false) || ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp && shutterSettings[s].triggerAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas') { - shutterSettings[s].triggerHeight = parseFloat(heightDownSun); - shutterSettings[s].triggerAction = 'sunProtect'; - - adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - } - } - } else { - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); - } - - } - } - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { - - const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); - const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); - - if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { - adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); - shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { - shutterSettings[s].sunProtectEndtimerid = '0'; - }, shutterSettings[s].sunProtectEndDely * 60000, i); - } - - if ((shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp)) { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].currentAction = 'up'; - shutterSettings[s].currentHeight = shutterSettings[s].heightUp; - shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #419'); - - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); - adapter.log.debug('Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + shutterSettings[s].heightUp + '%'); - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].sunProtectEndtimerid = '' - shutterSettings[s].currentAction = 'none'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); - const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); - - if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { - adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); - shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { - shutterSettings[s].sunProtectEndtimerid = '0'; - }, shutterSettings[s].sunProtectEndDely * 60000, i); - } - - if ((shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp)) { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].triggerAction = 'up'; - shutterSettings[s].sunProtectEndtimerid = ''; - - adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].sunProtectEndtimerid = '' - shutterSettings[s].triggerAction = 'none'; - shutterSettings[s].sunProtectEndtimerid = ''; - - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } - } - } - } - await sleep(driveDelayUpSleep); - break; - - ////////////////////////////////////////////////////////////////////////////////////////////////////// - - // ++++++++++++++++++++++++++++ sunprotect with inside temperature ++++++++++++++++++++++++++++++++++ - - case 'only inside temperature': //only inside temperature - _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; - mustValue = ('' + shutterSettings[s].triggerState); - mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); - - if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { - currentValue = ('' + _triggerState.val); - } - - if ((currentValue === mustValue || currentValue === mustValueTilted) && shutterSettings[s].tempSensor != '' || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off' && shutterSettings[s].tempSensor != '') || (shutterSettings[s].triggerID == '' && shutterSettings[s].tempSensor != '')) { - let insideTemp = 0; - - const _insideTempState = shutterSettings[s].tempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].tempSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _insideTempState != undefined && _insideTempState != null && _insideTempState.val != undefined) { - insideTemp = parseFloat(_insideTempState.val); - } - - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || (shutterSettings[s].triggerID == '')) { - if (insideTemp > shutterSettings[s].tempInside && shutterSettings[s].currentAction != 'sunProtect' && shutterSettings[s].currentAction != 'OpenInSunProtect' && shutterSettings[s].currentAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if ((( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound > parseFloat(heightDownSun) && convertShutter == false) || ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp) { - shutterSettings[s].currentAction = 'sunProtect'; - shutterSettings[s].currentHeight = heightDownSun; - shutterSettings[s].lastAutoAction = 'down_Sunprotect'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #420'); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%'); - } - // Shutter closed. Set currentAction = sunProtect when sunProtect starts => - // If shutter is opened automatically it can be opened in height heightDownSun directly - else if ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].heightDown) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas' && shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! - shutterSettings[s].currentAction = 'OpenInSunProtect'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); - } - // Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> - // set sunProtect again - else if ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(heightDownSun) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown && shutterSettings[s].currentAction == '') { - shutterSettings[s].currentAction = 'sunProtect'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' HeightDownSun:' + heightDownSun); - } - } - } else { - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - if (insideTemp > shutterSettings[s].tempInside && shutterSettings[s].triggerAction != 'sunProtect' && shutterSettings[s].triggerAction != 'OpenInSunProtect' && shutterSettings[s].triggerAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); - if ((( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound > parseFloat(heightDownSun) && convertShutter == false) || ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp && shutterSettings[s].triggerAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas') { - shutterSettings[s].triggerAction = 'sunProtect'; - shutterSettings[s].triggerHeight = parseFloat(heightDownSun); - - adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - } - } - } else { - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); - } - } - } - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { - const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); - - if (insideTemp < parseFloat(hysteresisInside)) { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].currentAction = 'up'; - shutterSettings[s].currentHeight = shutterSettings[s].heightUp; - shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #421'); - - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + shutterSettings[s].heightUp + '%'); - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].currentAction = 'none'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); - - if (insideTemp < parseFloat(hysteresisInside)) { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].triggerAction = 'up'; - - adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].triggerAction = 'none'; - - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } - } - } - } - await sleep(driveDelayUpSleep); - break; } + } else { + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + } } + } + } + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { + const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); + const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); + const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); + + if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { + adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); + shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { + shutterSettings[s].sunProtectEndtimerid = '0'; + }, shutterSettings[s].sunProtectEndDely * 60000, i); + } + + if (insideTemp < parseFloat(hysteresisInside) || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { + + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].currentAction = 'up'; + shutterSettings[s].currentHeight = shutterSettings[s].heightUp; + shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #411'); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); + adapter.log.debug('Temperature inside: ' + insideTemp + ' < ' + hysteresisInside + ' OR ( Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight + ' )'); + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%') + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].sunProtectEndtimerid = '' + shutterSettings[s].currentAction = 'none'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + } + } } - } - } - clearTimeout(timerSleep); - return (shutterSettings); - } - } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); + const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); + const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); + + if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { + adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); + shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { + shutterSettings[s].sunProtectEndtimerid = '0'; + }, shutterSettings[s].sunProtectEndDely * 60000, i); + } + + if (insideTemp < parseFloat(hysteresisInside) || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { + + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].triggerAction = 'up'; + + adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); + adapter.log.debug('Temperature inside: ' + insideTemp + ' < ' + hysteresisInside + ' OR ( Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight + ' )'); + adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].sunProtectEndtimerid = '' + shutterSettings[s].triggerAction = 'none'; + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + } + } + } + } + await sleep(driveDelayUpSleep); + break; + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + // +++++++++++++++++ sunprotect with in/outside temperature, Lightsensor and direction +++++++++++++++ + + case 'in- & outside temperature and direction': // in- & outside temperature and direction + resultDirectionRangeMinus = parseInt(shutterSettings[s].direction) - parseInt(shutterSettings[s].directionRange); + resultDirectionRangePlus = parseInt(shutterSettings[s].direction) + parseInt(shutterSettings[s].directionRange); + + _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; + mustValue = ('' + shutterSettings[s].triggerState); + mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); + + if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { + currentValue = ('' + _triggerState.val); + } + + if ((currentValue === mustValue || currentValue === mustValueTilted) && shutterSettings[s].tempSensor != '' || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off' && shutterSettings[s].tempSensor != '') || (shutterSettings[s].triggerID == '' && shutterSettings[s].tempSensor != '')) { + let insideTemp = 0; + let outsideTemp = 0; + let sunLight = 0; + + const _insideTempState = shutterSettings[s].tempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].tempSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _insideTempState != undefined && _insideTempState != null && _insideTempState.val != undefined) { + insideTemp = parseFloat(_insideTempState.val); + } + + const _outsideTempState = shutterSettings[s].outsideTempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].outsideTempSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _outsideTempState != undefined && _outsideTempState != null && _outsideTempState.val != undefined) { + outsideTemp = parseFloat(_outsideTempState.val); + } + + // heatProtection + if (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown) { + shutterSettings[s].currentAction = shutterSettings[s].currentAction == 'sunProtect' ? '' : shutterSettings[s].currentAction; + heightDownSun = shutterSettings[s].heightDown; + adapter.log.debug(`Heat Protection for ${shutterSettings[s].shutterName} is active`); + } else { + heightDownSun = shutterSettings[s].heightDownSun; + } + + const _sunLight = shutterSettings[s].lightSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].lightSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _sunLight != undefined && _sunLight != null && _sunLight.val != undefined) { + sunLight = parseFloat(_sunLight.val); + } + + if (shutterSettings[s].sunProtectEndtimerid != '' && shutterSettings[s].sunProtectEndtimerid != '0' && shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight) { + adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); + clearTimeout(shutterSettings[s].sunProtectEndtimerid); + shutterSettings[s].sunProtectEndtimerid = ''; + } + + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || (shutterSettings[s].triggerID == '')) { + if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth && insideTemp > shutterSettings[s].tempInside) { + if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].currentAction != 'sunProtect' && shutterSettings[s].currentAction != 'OpenInSunProtect' && shutterSettings[s].currentAction != 'Manu_Mode') { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); + + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || + (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && + (shutterSettings[s].currentHeight == shutterSettings[s].heightUp || (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp))) { + + shutterSettings[s].currentAction = 'sunProtect'; + shutterSettings[s].currentHeight = heightDownSun; + shutterSettings[s].lastAutoAction = 'down_Sunprotect'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #412'); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); + adapter.log.debug('Temperature inside: ' + insideTemp + ' > ' + shutterSettings[s].tempInside + ' AND ( Temperatur outside: ' + outsideTemp + ' > ' + shutterSettings[s].tempOutside + ' AND Light: ' + sunLight + ' > ' + shutterSettings[s].valueLight + ' )'); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%'); + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%') + } + // Shutter closed. Set currentAction = sunProtect when sunProtect starts => + // If shutter is opened automatically it can be opened in height heightDownSun directly + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].heightDown) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas' && shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! + shutterSettings[s].currentAction = 'OpenInSunProtect'; + adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); + } + // Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> + // set sunProtect again + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown && shutterSettings[s].currentAction == '') { + shutterSettings[s].currentAction = 'sunProtect'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' HeightDownSun:' + heightDownSun); + } + } + } else { + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + } + } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth && insideTemp > shutterSettings[s].tempInside) { + if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].triggerAction != 'sunProtect' && shutterSettings[s].triggerAction != 'OpenInSunProtect' && shutterSettings[s].triggerAction != 'Manu_Mode') { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp + ' AND triggerAction:' + shutterSettings[s].triggerAction + ' != down '); + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp && shutterSettings[s].triggerAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas') { + shutterSettings[s].triggerHeight = parseFloat(heightDownSun); + shutterSettings[s].triggerAction = 'sunProtect'; + + adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + } + } + } else { + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + } + } + } + } + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { + const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); + const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); + const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); + + if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { + adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); + shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { + shutterSettings[s].sunProtectEndtimerid = '0'; + }, shutterSettings[s].sunProtectEndDely * 60000, i); + } + + + if (insideTemp < parseFloat(hysteresisInside) || (resultDirectionRangePlus) < azimuth || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { + + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].currentAction = 'up'; + shutterSettings[s].currentHeight = shutterSettings[s].heightUp; + shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #413'); + + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); + adapter.log.debug('Range: ' + resultDirectionRangePlus + ' < ' + azimuth + ' OR Temperature inside: ' + insideTemp + ' < ' + hysteresisInside + ' OR ( Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight + ')'); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + shutterSettings[s].heightUp + '%'); + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].sunProtectEndtimerid = '' + shutterSettings[s].currentAction = 'none'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); + const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); + const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); + + if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { + adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); + shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { + shutterSettings[s].sunProtectEndtimerid = '0'; + }, shutterSettings[s].sunProtectEndDely * 60000, i); + } + + if (insideTemp < parseFloat(hysteresisInside) || (resultDirectionRangePlus) < azimuth || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { + + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].triggerAction = 'up'; + + adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); + adapter.log.debug('Temperature inside: ' + insideTemp + ' < ' + hysteresisInside + ' OR ( Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight + ' )'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].triggerAction = 'none'; + + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } + } + } + } + await sleep(driveDelayUpSleep); + break; + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + // +++++++++++++++++ sunprotect with outside temperature, Lightsensor and direction +++++++++++++++ + + case 'outside temperature and direction': //outside temperature and direction + resultDirectionRangeMinus = parseInt(shutterSettings[s].direction) - parseInt(shutterSettings[s].directionRange); + resultDirectionRangePlus = parseInt(shutterSettings[s].direction) + parseInt(shutterSettings[s].directionRange); + + _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; + mustValue = ('' + shutterSettings[s].triggerState); + mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); + + if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { + currentValue = ('' + _triggerState.val); + } + + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off') || (shutterSettings[s].triggerID == '')) { + let outsideTemp = 0; + let sunLight = 0; + + const _outsideTempState = shutterSettings[s].outsideTempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].outsideTempSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _outsideTempState != undefined && _outsideTempState != null && _outsideTempState.val != undefined) { + outsideTemp = parseFloat(_outsideTempState.val); + } + + // heatProtection + if (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown) { + shutterSettings[s].currentAction = shutterSettings[s].currentAction == 'sunProtect' ? '' : shutterSettings[s].currentAction; + heightDownSun = shutterSettings[s].heightDown; + adapter.log.debug(`Heat Protection for ${shutterSettings[s].shutterName} is active`); + } else { + heightDownSun = shutterSettings[s].heightDownSun; + } + + const _sunLight = shutterSettings[s].lightSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].lightSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _sunLight != undefined && _sunLight != null && _sunLight.val != undefined) { + sunLight = parseFloat(_sunLight.val); + } + + if (shutterSettings[s].sunProtectEndtimerid != '' && shutterSettings[s].sunProtectEndtimerid != '0' && shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight) { + adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); + clearTimeout(shutterSettings[s].sunProtectEndtimerid); + shutterSettings[s].sunProtectEndtimerid = ''; + } + + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || (shutterSettings[s].triggerID == '')) { + if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth) { + if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].currentAction != 'sunProtect' && shutterSettings[s].currentAction != 'OpenInSunProtect' && shutterSettings[s].currentAction != 'Manu_Mode') { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); + + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || + (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && + (shutterSettings[s].currentHeight == shutterSettings[s].heightUp || (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp))) { + + shutterSettings[s].currentAction = 'sunProtect'; + shutterSettings[s].currentHeight = heightDownSun; + shutterSettings[s].lastAutoAction = 'down_Sunprotect'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #414'); + + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); + adapter.log.debug('Temperatur outside: ' + outsideTemp + ' > ' + shutterSettings[s].tempOutside + ' AND Light: ' + sunLight + ' > ' + shutterSettings[s].valueLight); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%') + } + // Shutter closed. Set currentAction = sunProtect when sunProtect starts => + // If shutter is opened automatically it can be opened in height heightDownSun directly + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].heightDown) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas' && shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! + shutterSettings[s].currentAction = 'OpenInSunProtect'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); + } + // Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> + // set sunProtect again + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown && shutterSettings[s].currentAction == '') { + shutterSettings[s].currentAction = 'sunProtect'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' HeightDownSun:' + heightDownSun); + } + } + } else { + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + } + } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth) { + if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].triggerAction != 'sunProtect' && shutterSettings[s].triggerAction != 'OpenInSunProtect' && shutterSettings[s].triggerAction != 'Manu_Mode') { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp && shutterSettings[s].triggerAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas') { + shutterSettings[s].triggerHeight = parseFloat(heightDownSun); + shutterSettings[s].triggerAction = 'sunProtect'; + + adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + } + + } + } else { + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + } + } + } + } + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { + const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); + const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); + + if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { + adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); + shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { + shutterSettings[s].sunProtectEndtimerid = '0'; + }, shutterSettings[s].sunProtectEndDely * 60000, i); + } + + if ((resultDirectionRangePlus) < azimuth || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].currentAction = 'up'; + shutterSettings[s].currentHeight = shutterSettings[s].heightUp; + shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #415'); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); + adapter.log.debug('Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight); + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + shutterSettings[s].heightUp + '%') + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].currentAction = 'none'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); + const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); + + if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { + adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); + shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { + shutterSettings[s].sunProtectEndtimerid = '0'; + }, shutterSettings[s].sunProtectEndDely * 60000, i); + } + + if ((resultDirectionRangePlus) < azimuth || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].triggerAction = 'up'; + + adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].sunProtectEndtimerid = '' + shutterSettings[s].triggerAction = 'none'; + + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } + } + } + } + await sleep(driveDelayUpSleep); + break; + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + // ++++++++++++++++++++++++++++++ sunprotect with direction ++++++++++++++++++++++++++++++++++ + + case 'only direction': //only direction + resultDirectionRangeMinus = parseInt(shutterSettings[s].direction) - parseInt(shutterSettings[s].directionRange); + resultDirectionRangePlus = parseInt(shutterSettings[s].direction) + parseInt(shutterSettings[s].directionRange); + + _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; + mustValue = ('' + shutterSettings[s].triggerState); + mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); + + if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { + currentValue = ('' + _triggerState.val); + } + + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off') || (shutterSettings[s].triggerID == '')) { + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || (shutterSettings[s].triggerID == '')) { + if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth && shutterSettings[s].currentAction != 'sunProtect' && shutterSettings[s].currentAction != 'OpenInSunProtect' && shutterSettings[s].currentAction != 'Manu_Mode') { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp) { + shutterSettings[s].currentAction = 'sunProtect'; + shutterSettings[s].currentHeight = heightDownSun; + shutterSettings[s].lastAutoAction = 'down_Sunprotect'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #416'); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); + adapter.log.debug('RangeMinus: ' + resultDirectionRangeMinus + ' < ' + azimuth + 'RangePlus: ' + resultDirectionRangePlus + ' > ' + azimuth); + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%'); + } + // Shutter closed. Set currentAction = sunProtect when sunProtect starts => + // If shutter is opened automatically it can be opened in height heightDownSun directly + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].heightDown) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas' && shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! + shutterSettings[s].currentAction = 'OpenInSunProtect'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); + } + // Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> + // set sunProtect again + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown && shutterSettings[s].currentAction == '') { + shutterSettings[s].currentAction = 'sunProtect'; - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - // +++++++++++++++++ End of sunprotect with Elevationslimit +++++++++++++++ + adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' HeightDownSun:' + heightDownSun); + } + } + } else { + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth && shutterSettings[s].triggerAction != 'sunProtect' && shutterSettings[s].triggerAction != 'OpenInSunProtect' && shutterSettings[s].triggerAction != 'Manu_Mode') { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp && shutterSettings[s].triggerAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas') { + shutterSettings[s].triggerHeight = parseFloat(heightDownSun); + shutterSettings[s].triggerAction = 'sunProtect'; + + adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + } + } + } else { + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + } + + } + } + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { + if ((resultDirectionRangePlus) < azimuth) { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].currentAction = 'up'; + shutterSettings[s].currentHeight = shutterSettings[s].heightUp; + shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #417'); + + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); + adapter.log.debug('Range: ' + resultDirectionRangePlus + ' < ' + azimuth); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + shutterSettings[s].heightUp + '%') + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].currentAction = 'none'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + if ((resultDirectionRangePlus) < azimuth) { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].triggerAction = 'up'; + + adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].triggerAction = 'none'; + + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } + } + } + } + await sleep(driveDelayUpSleep); + break; + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + // ++++++++++++++++++++++++ sunprotect with outside temperature and Lightsensor +++++++++++++++++++++++ + + case 'only outside temperature': //only outside temperature + _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; + mustValue = ('' + shutterSettings[s].triggerState); + mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); + + if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { + currentValue = ('' + _triggerState.val); + } + + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off') || (shutterSettings[s].triggerID == '')) { + let outsideTemp = 0; + let sunLight = 0; + + const _outsideTempState = shutterSettings[s].outsideTempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].outsideTempSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _outsideTempState != undefined && _outsideTempState != null && _outsideTempState.val != undefined) { + outsideTemp = parseFloat(_outsideTempState.val); + } + + // heatProtection + if (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown) { + shutterSettings[s].currentAction = shutterSettings[s].currentAction == 'sunProtect' ? '' : shutterSettings[s].currentAction; + heightDownSun = shutterSettings[s].heightDown; + adapter.log.debug(`Heat Protection for ${shutterSettings[s].shutterName} is active`); + } else { + heightDownSun = shutterSettings[s].heightDownSun; + } + + const _sunLight = shutterSettings[s].lightSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].lightSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _sunLight != undefined && _sunLight != null && _sunLight.val != undefined) { + sunLight = parseFloat(_sunLight.val); + } + + if (shutterSettings[s].sunProtectEndtimerid != '' && shutterSettings[s].sunProtectEndtimerid != '0' && shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight) { + adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); + clearTimeout(shutterSettings[s].sunProtectEndtimerid); + shutterSettings[s].sunProtectEndtimerid = ''; + } + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || (shutterSettings[s].triggerID == '')) { + if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].currentAction != 'sunProtect' && shutterSettings[s].currentAction != 'OpenInSunProtect' && shutterSettings[s].currentAction != 'Manu_Mode') { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); + + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || + (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && + (shutterSettings[s].currentHeight == shutterSettings[s].heightUp || (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp))) { + + shutterSettings[s].currentAction = 'sunProtect'; + shutterSettings[s].currentHeight = heightDownSun; + shutterSettings[s].lastAutoAction = 'down_Sunprotect'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #418'); - if (shutterSettings) { - const result = shutterSettings.filter((/** @type {{ enabled: boolean; }} */ d) => d.enabled === true); + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); + adapter.log.debug('Temperature outside: ' + outsideTemp + ' > ' + shutterSettings[s].tempOutside + ' AND Light: ' + sunLight + ' > ' + shutterSettings[s].valueLight); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%'); + } + // Shutter closed. Set currentAction = sunProtect when sunProtect starts => + // If shutter is opened automatically it can be opened in height heightDownSun directly + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].heightDown) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas' && shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! + shutterSettings[s].currentAction = 'OpenInSunProtect'; - const sunProtEndStart = parseInt(adapter.config.sunProtEndElevation); - const sunProtEndStop = (adapter.config.sunProtEndElevation - 1); + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - for (const i in result) { - for (const s in shutterSettings) { - if (shutterSettings[s].shutterName == result[i].shutterName) { - if (elevation <= sunProtEndStart && elevation >= sunProtEndStop && (shutterSettings[s].currentAction == 'sunProtect' || shutterSettings[s].currentAction == 'manu_sunProtect')) { - const nameDevice = shutterSettings[s].shutterName.replace(/[.;, ]/g, '_'); - const heightDownSun = shutterSettings[s].heightDownSun; + adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); + } + // Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> + // set sunProtect again + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown && shutterSettings[s].currentAction == '') { + shutterSettings[s].currentAction = 'sunProtect'; - let convertShutter = false; + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - if (parseFloat(shutterSettings[s].heightDown) < parseFloat(shutterSettings[s].heightUp)) { - convertShutter = false; - adapter.log.debug(shutterSettings[s].shutterName + ' level conversion is disabled ...'); - } else if (parseFloat(shutterSettings[s].heightDown) > parseFloat(shutterSettings[s].heightUp)) { - convertShutter = true; - adapter.log.debug(shutterSettings[s].shutterName + ' level conversion is enabled'); + adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' HeightDownSun:' + heightDownSun); + } + } + } else { + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].triggerAction != 'sunProtect' && shutterSettings[s].triggerAction != 'OpenInSunProtect' && shutterSettings[s].triggerAction != 'Manu_Mode') { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - const pendingAlarm = await checkPendingAlarm(adapter, shutterSettings[s]); + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); - const _autoSunState = await adapter.getStateAsync(`shutters.autoSun.${nameDevice}`).catch((e) => adapter.log.warn(e)); + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp && shutterSettings[s].triggerAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas') { + shutterSettings[s].triggerHeight = parseFloat(heightDownSun); + shutterSettings[s].triggerAction = 'sunProtect'; - if (_autoSunState && _autoSunState.val === true) { - let currentValue = ''; + adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + } + } + } else { + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + } - const _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; + } + } + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { + + const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); + const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); + + if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { + adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); + shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { + shutterSettings[s].sunProtectEndtimerid = '0'; + }, shutterSettings[s].sunProtectEndDely * 60000, i); + } + + if ((shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp)) { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].currentAction = 'up'; + shutterSettings[s].currentHeight = shutterSettings[s].heightUp; + shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #419'); + + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); + adapter.log.debug('Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + shutterSettings[s].heightUp + '%'); + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].sunProtectEndtimerid = '' + shutterSettings[s].currentAction = 'none'; - const mustValue = ('' + shutterSettings[s].triggerState); - const mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { - currentValue = ('' + _triggerState.val); + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; - if ((currentValue === mustValue || currentValue === mustValueTilted) || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown' && shutterSettings[s].autoDrive != 'off') || (shutterSettings[s].triggerID == '')) { - if (shutterSettings[s].sunProtectEndtimerid != '' && shutterSettings[s].sunProtectEndtimerid != '0') { - adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); - clearTimeout(shutterSettings[s].sunProtectEndtimerid); - shutterSettings[s].sunProtectEndtimerid = ''; - } - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if ((shutterSettings[s].currentAction == 'sunProtect' || shutterSettings[s].currentAction == 'manu_sunProtect') && shutterSettings[s].KeepSunProtect === false && ( Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].sunProtectEndtimerid = '' - shutterSettings[s].currentAction = 'up'; - shutterSettings[s].currentHeight = shutterSettings[s].heightUp; - shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #422'); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is completed'); - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('save current height: ' + shutterSettings[s].currentHeight + '%' + ' from ' + shutterSettings[s].shutterName); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'none'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); + const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); + + if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { + adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); + shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { + shutterSettings[s].sunProtectEndtimerid = '0'; + }, shutterSettings[s].sunProtectEndDely * 60000, i); + } + + if ((shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp)) { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].triggerAction = 'up'; + shutterSettings[s].sunProtectEndtimerid = ''; + + adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - if (shutterSettings[s].sunProtectEndtimerid != '' && shutterSettings[s].sunProtectEndtimerid != '0') { - clearTimeout(shutterSettings[s].sunProtectEndtimerid); - shutterSettings[s].sunProtectEndtimerid = ''; - - adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); - - } - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if ((shutterSettings[s].triggerAction == 'sunProtect' || shutterSettings[s].triggerAction == 'manu_sunProtect') && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].triggerAction = 'up'; - shutterSettings[s].sunProtectEndtimerid = ''; - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); - adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); - - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - shutterSettings[s].sunProtectEndtimerid = '' - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'none'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].sunProtectEndtimerid = '' + shutterSettings[s].triggerAction = 'none'; + shutterSettings[s].sunProtectEndtimerid = ''; + + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); } - await sleep(driveDelayUpSleep); + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); } + } + } + } + await sleep(driveDelayUpSleep); + break; + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + // ++++++++++++++++++++++++++++ sunprotect with inside temperature ++++++++++++++++++++++++++++++++++ + + case 'only inside temperature': //only inside temperature + _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; + mustValue = ('' + shutterSettings[s].triggerState); + mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); + + if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { + currentValue = ('' + _triggerState.val); + } + + if ((currentValue === mustValue || currentValue === mustValueTilted) && shutterSettings[s].tempSensor != '' || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off' && shutterSettings[s].tempSensor != '') || (shutterSettings[s].triggerID == '' && shutterSettings[s].tempSensor != '')) { + let insideTemp = 0; + + const _insideTempState = shutterSettings[s].tempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].tempSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _insideTempState != undefined && _insideTempState != null && _insideTempState.val != undefined) { + insideTemp = parseFloat(_insideTempState.val); } + + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || (shutterSettings[s].triggerID == '')) { + if (insideTemp > shutterSettings[s].tempInside && shutterSettings[s].currentAction != 'sunProtect' && shutterSettings[s].currentAction != 'OpenInSunProtect' && shutterSettings[s].currentAction != 'Manu_Mode') { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp) { + shutterSettings[s].currentAction = 'sunProtect'; + shutterSettings[s].currentHeight = heightDownSun; + shutterSettings[s].lastAutoAction = 'down_Sunprotect'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #420'); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%'); + } + // Shutter closed. Set currentAction = sunProtect when sunProtect starts => + // If shutter is opened automatically it can be opened in height heightDownSun directly + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].heightDown) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas' && shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! + shutterSettings[s].currentAction = 'OpenInSunProtect'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); + } + // Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> + // set sunProtect again + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown && shutterSettings[s].currentAction == '') { + shutterSettings[s].currentAction = 'sunProtect'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' HeightDownSun:' + heightDownSun); + } + } + } else { + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + if (insideTemp > shutterSettings[s].tempInside && shutterSettings[s].triggerAction != 'sunProtect' && shutterSettings[s].triggerAction != 'OpenInSunProtect' && shutterSettings[s].triggerAction != 'Manu_Mode') { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp && shutterSettings[s].triggerAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas') { + shutterSettings[s].triggerAction = 'sunProtect'; + shutterSettings[s].triggerHeight = parseFloat(heightDownSun); + + adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + } + } + } else { + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + } + } + } + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { + const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); + + if (insideTemp < parseFloat(hysteresisInside)) { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].currentAction = 'up'; + shutterSettings[s].currentHeight = shutterSettings[s].heightUp; + shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #421'); + + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + shutterSettings[s].heightUp + '%'); + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].currentAction = 'none'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); + + if (insideTemp < parseFloat(hysteresisInside)) { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].triggerAction = 'up'; + + adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].triggerAction = 'none'; + + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } + } + } + } + await sleep(driveDelayUpSleep); + break; + } + } + + } + } + } + clearTimeout(timerSleep); + return (shutterSettings); + } + } + + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + + // +++++++++++++++++ End of sunprotect with Elevationslimit +++++++++++++++ + + if (shutterSettings) { + const result = shutterSettings.filter((/** @type {{ enabled: boolean; }} */ d) => d.enabled === true); + + const sunProtEndStart = parseInt(adapter.config.sunProtEndElevation); + const sunProtEndStop = (adapter.config.sunProtEndElevation - 1); + + for (const i in result) { + for (const s in shutterSettings) { + if (shutterSettings[s].shutterName == result[i].shutterName) { + if (elevation <= sunProtEndStart && elevation >= sunProtEndStop && (shutterSettings[s].currentAction == 'sunProtect' || shutterSettings[s].currentAction == 'manu_sunProtect')) { + const nameDevice = shutterSettings[s].shutterName.replace(/[.;, ]/g, '_'); + const heightDownSun = shutterSettings[s].heightDownSun; + + let convertShutter = false; + + if (parseFloat(shutterSettings[s].heightDown) < parseFloat(shutterSettings[s].heightUp)) { + convertShutter = false; + adapter.log.debug(shutterSettings[s].shutterName + ' level conversion is disabled ...'); + } else if (parseFloat(shutterSettings[s].heightDown) > parseFloat(shutterSettings[s].heightUp)) { + convertShutter = true; + adapter.log.debug(shutterSettings[s].shutterName + ' level conversion is enabled'); + } + + const pendingAlarm = await checkPendingAlarm(adapter, shutterSettings[s]); + + const _autoSunState = await adapter.getStateAsync(`shutters.autoSun.${nameDevice}`).catch((e) => adapter.log.warn(e)); + + if (_autoSunState && _autoSunState.val === true) { + let currentValue = ''; + + const _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; + + const mustValue = ('' + shutterSettings[s].triggerState); + const mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); + + if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { + currentValue = ('' + _triggerState.val); + } + + if ((currentValue === mustValue || currentValue === mustValueTilted) || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown' && shutterSettings[s].autoDrive != 'off') || (shutterSettings[s].triggerID == '')) { + if (shutterSettings[s].sunProtectEndtimerid != '' && shutterSettings[s].sunProtectEndtimerid != '0') { + adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); + clearTimeout(shutterSettings[s].sunProtectEndtimerid); + shutterSettings[s].sunProtectEndtimerid = ''; + } + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if ((shutterSettings[s].currentAction == 'sunProtect' || shutterSettings[s].currentAction == 'manu_sunProtect') && shutterSettings[s].KeepSunProtect === false && (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].sunProtectEndtimerid = '' + shutterSettings[s].currentAction = 'up'; + shutterSettings[s].currentHeight = shutterSettings[s].heightUp; + shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #422'); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is completed'); + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('save current height: ' + shutterSettings[s].currentHeight + '%' + ' from ' + shutterSettings[s].shutterName); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'none'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + if (shutterSettings[s].sunProtectEndtimerid != '' && shutterSettings[s].sunProtectEndtimerid != '0') { + clearTimeout(shutterSettings[s].sunProtectEndtimerid); + shutterSettings[s].sunProtectEndtimerid = ''; + + adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); + + } + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if ((shutterSettings[s].triggerAction == 'sunProtect' || shutterSettings[s].triggerAction == 'manu_sunProtect') && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].triggerAction = 'up'; + shutterSettings[s].sunProtectEndtimerid = ''; + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); + adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); + + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + shutterSettings[s].sunProtectEndtimerid = '' + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'none'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); } + } + await sleep(driveDelayUpSleep); } + } } - clearTimeout(timerSleep); - return (shutterSettings); + } } + clearTimeout(timerSleep); + return (shutterSettings); + } } module.exports = sunProtect; From c86e07d5c916f3dfc51725c512188fccf0ba9582 Mon Sep 17 00:00:00 2001 From: simatec Date: Tue, 18 Jul 2023 00:22:09 +0200 Subject: [PATCH 02/10] chore: release v1.6.1 * (simatec) Fix Heat protection --- README.md | 2 +- io-package.json | 28 ++++++++++++++-------------- package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 48d07099..db1ae8ff 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ When the adapter crashes or an other Code error happens, this error message that ## Changelog -### __WORK IN PROGRESS__ +### 1.6.1 (2023-07-17) * (simatec) Fix Heat protection ### 1.6.0 (2023-07-16) diff --git a/io-package.json b/io-package.json index 299c8a40..105a072b 100644 --- a/io-package.json +++ b/io-package.json @@ -1,8 +1,21 @@ { "common": { "name": "shuttercontrol", - "version": "1.6.0", + "version": "1.6.1", "news": { + "1.6.1": { + "en": "Fix Heat protection", + "de": "Wärmeschutz", + "ru": "Fix Защита тепла", + "pt": "Proteção contra calor", + "nl": "Fix Heat bescherming", + "fr": "Protection thermique", + "it": "Fissare la protezione del calore", + "es": "Protección de calor fijo", + "pl": "Fix Heat", + "uk": "Фіксований захист тепла", + "zh-cn": "Fix Heat保护" + }, "1.6.0": { "en": "Manu mode block added\nHeat protection added\nAdded rounding of incoming shutter states\nUkrainian language added\nsmall Bugfixes\nDependencies updated", "de": "Manu Mode Block hinzugefügt\nWärmeschutz hinzugefügt\nHinzugefügte Rundung der eintreffenden Verschlusszustände\nUkrainische Sprache hinzugefügt\nkleine Bugfixes\nAusgaben aktualisiert", @@ -80,19 +93,6 @@ "pl": "Fix Sunprotekt", "uk": "Виправлення Sunprotect", "zh-cn": "Fix Sunprotect" - }, - "1.4.25": { - "en": "small Fixes", - "de": "kleine Feste", - "ru": "небольшие исправления", - "pt": "pequenas correções", - "nl": "kleine Fixes", - "fr": "petits Fixes", - "it": "piccoli corredi", - "es": "pequeñas fijaciones", - "pl": "mały Fisz", - "uk": "маленькі Фікси", - "zh-cn": "小型固定" } }, "title": "shuttercontrol", diff --git a/package-lock.json b/package-lock.json index ccc8b5ed..9931ef2e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "iobroker.shuttercontrol", - "version": "1.6.0", + "version": "1.6.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "iobroker.shuttercontrol", - "version": "1.6.0", + "version": "1.6.1", "license": "MIT", "dependencies": { "@iobroker/adapter-core": "^2.6.8", diff --git a/package.json b/package.json index ecf55f7b..af4a8bd5 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iobroker.shuttercontrol", - "version": "1.6.0", + "version": "1.6.1", "description": "Automatic control for shutters", "author": { "name": "simatec", From a653e0aa2a4d6e6b63955b4dbb3490cd998eec1e Mon Sep 17 00:00:00 2001 From: simatec Date: Thu, 17 Aug 2023 11:31:05 +0200 Subject: [PATCH 03/10] (simatec) Beta 1.6.2 --- .github/workflows/test-and-release.yml | 6 +- README.md | 4 + package-lock.json | 197 ++++++++++++------------- package.json | 8 +- 4 files changed, 109 insertions(+), 106 deletions(-) diff --git a/.github/workflows/test-and-release.yml b/.github/workflows/test-and-release.yml index d76873e4..237bc53e 100644 --- a/.github/workflows/test-and-release.yml +++ b/.github/workflows/test-and-release.yml @@ -25,7 +25,7 @@ jobs: strategy: matrix: - node-version: [16.x] + node-version: [18.x] steps: - uses: actions/checkout@v3 @@ -56,7 +56,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - node-version: [16.x, 18.x] + node-version: [16.x, 18.x, 20.x] os: [ubuntu-latest, windows-latest, macos-latest] steps: @@ -92,7 +92,7 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - node-version: [16.x] + node-version: [18.x] steps: - name: Checkout code diff --git a/README.md b/README.md index db1ae8ff..c7d1f95e 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,10 @@ When the adapter crashes or an other Code error happens, this error message that ## Changelog +### __WORK IN PROGRESS__ +* (simatec) Dependencies updated +* (simatec) node 20 tests added + ### 1.6.1 (2023-07-17) * (simatec) Fix Heat protection diff --git a/package-lock.json b/package-lock.json index 9931ef2e..759e4d02 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.6.1", "license": "MIT", "dependencies": { - "@iobroker/adapter-core": "^2.6.8", + "@iobroker/adapter-core": "^3.0.3", "node-schedule": "^2.1.1", "suncalc": "^1.9.0" }, @@ -22,14 +22,14 @@ "@types/chai-as-promised": "^7.1.5", "@types/gulp": "^4.0.13", "@types/mocha": "^10.0.1", - "@types/node": "^20.4.2", + "@types/node": "^20.5.0", "@types/proxyquire": "^1.3.28", - "@types/sinon": "^10.0.15", + "@types/sinon": "^10.0.16", "@types/sinon-chai": "^3.2.9", "axios": "^1.4.0", "chai": "^4.3.7", "chai-as-promised": "^7.1.1", - "eslint": "^8.45.0", + "eslint": "^8.47.0", "gulp": "^4.0.2", "mocha": "^10.2.0", "proxyquire": "^2.1.3", @@ -557,18 +557,18 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", - "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", + "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", "dev": true, "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", - "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", "dev": true, "dependencies": { "ajv": "^6.12.4", @@ -612,9 +612,9 @@ "dev": true }, "node_modules/@eslint/js": { - "version": "8.44.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", - "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.47.0.tgz", + "integrity": "sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -677,11 +677,11 @@ "dev": true }, "node_modules/@iobroker/adapter-core": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/@iobroker/adapter-core/-/adapter-core-2.6.8.tgz", - "integrity": "sha512-xrqtH5RYZ6BvEcDyfuPkajd9el4R6p0VLRYKlnfMafAbxybIN+zfeHvjGI4l8OAHkyP2tcv6boX2Vu0KnMFOHw==", - "dependencies": { - "@types/iobroker": "^4.0.5" + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@iobroker/adapter-core/-/adapter-core-3.0.3.tgz", + "integrity": "sha512-SZmL69BtUXitnTbidNjlljQKB6CbkBLK9+Tqo/NMsOqHb1RmhPCNKhO4F5o8jc0dW0J6d4VArXryUkL7Ru0WpA==", + "peerDependencies": { + "@iobroker/types": "^5.0.11" } }, "node_modules/@iobroker/testing": { @@ -765,6 +765,15 @@ "node": ">=8" } }, + "node_modules/@iobroker/types": { + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@iobroker/types/-/types-5.0.11.tgz", + "integrity": "sha512-H96EQbum1mUVxO8gklWoW+G8R3sJLo2OOrGQHsjPrtKvmYU+UCLOjOMh9TjsYMvwGhPz86Bp8xlZSp5WifmbUA==", + "peer": true, + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -1034,14 +1043,6 @@ "node": ">=8.0" } }, - "node_modules/@types/iobroker": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/iobroker/-/iobroker-4.0.5.tgz", - "integrity": "sha512-D1tJwuDQEQQQ/cZVFjFjFUhUuMxJbfrz5U2UooiZwhgs69D/t8IowMvBI6Lk4ZR8HnCSxYwWHVRKyQnEMNgJPA==", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/minimatch": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", @@ -1055,9 +1056,10 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.4.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.2.tgz", - "integrity": "sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==" + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.0.tgz", + "integrity": "sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==", + "dev": true }, "node_modules/@types/proxyquire": { "version": "1.3.28", @@ -1066,9 +1068,9 @@ "dev": true }, "node_modules/@types/sinon": { - "version": "10.0.15", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.15.tgz", - "integrity": "sha512-3lrFNQG0Kr2LDzvjyjB6AMJk4ge+8iYhQfdnSwIwlG88FUOV43kPcQqDZkDa/h3WSZy6i8Fr0BSjfQtB1B3xuQ==", + "version": "10.0.16", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.16.tgz", + "integrity": "sha512-j2Du5SYpXZjJVJtXBokASpPRj+e2z+VUhCPHmM6WMfe3dpHu6iVKJMU6AiBcMp/XTAYnEj6Wc1trJUWwZ0QaAQ==", "dev": true, "dependencies": { "@types/sinonjs__fake-timers": "*" @@ -2438,27 +2440,27 @@ } }, "node_modules/eslint": { - "version": "8.45.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", - "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz", + "integrity": "sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.1.0", - "@eslint/js": "8.44.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "^8.47.0", "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.6.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -2492,9 +2494,9 @@ } }, "node_modules/eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "dependencies": { "esrecurse": "^4.3.0", @@ -2508,9 +2510,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -3367,9 +3369,9 @@ } }, "node_modules/globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", "dev": true, "dependencies": { "type-fest": "^0.20.2" @@ -7581,15 +7583,15 @@ } }, "@eslint-community/regexpp": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.4.0.tgz", - "integrity": "sha512-A9983Q0LnDGdLPjxyXQ00sbV+K+O+ko2Dr+CZigbHWtX9pNfxlaBkMR8X1CztI73zuEyEBXTVjx7CE+/VSwDiQ==", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.6.2.tgz", + "integrity": "sha512-pPTNuaAG3QMH+buKyBIGJs3g/S5y0caxw0ygM3YyE6yJFySwiGGSzA+mM3KJ8QQvzeLh3blwgSonkFjgQdxzMw==", "dev": true }, "@eslint/eslintrc": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.0.tgz", - "integrity": "sha512-Lj7DECXqIVCqnqjjHMPna4vn6GJcMgul/wuS0je9OZ9gsL0zzDpKPVtcG1HaDVc+9y+qgXneTeUMbCqXJNpH1A==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", + "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", "dev": true, "requires": { "ajv": "^6.12.4", @@ -7621,9 +7623,9 @@ } }, "@eslint/js": { - "version": "8.44.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.44.0.tgz", - "integrity": "sha512-Ag+9YM4ocKQx9AarydN0KY2j0ErMHNIocPDrVo8zAE44xLTjEtz81OdR68/cydGtk6m6jDb5Za3r2useMzYmSw==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.47.0.tgz", + "integrity": "sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==", "dev": true }, "@humanwhocodes/config-array": { @@ -7667,12 +7669,10 @@ "dev": true }, "@iobroker/adapter-core": { - "version": "2.6.8", - "resolved": "https://registry.npmjs.org/@iobroker/adapter-core/-/adapter-core-2.6.8.tgz", - "integrity": "sha512-xrqtH5RYZ6BvEcDyfuPkajd9el4R6p0VLRYKlnfMafAbxybIN+zfeHvjGI4l8OAHkyP2tcv6boX2Vu0KnMFOHw==", - "requires": { - "@types/iobroker": "^4.0.5" - } + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/@iobroker/adapter-core/-/adapter-core-3.0.3.tgz", + "integrity": "sha512-SZmL69BtUXitnTbidNjlljQKB6CbkBLK9+Tqo/NMsOqHb1RmhPCNKhO4F5o8jc0dW0J6d4VArXryUkL7Ru0WpA==", + "requires": {} }, "@iobroker/testing": { "version": "4.1.0", @@ -7739,6 +7739,12 @@ } } }, + "@iobroker/types": { + "version": "5.0.11", + "resolved": "https://registry.npmjs.org/@iobroker/types/-/types-5.0.11.tgz", + "integrity": "sha512-H96EQbum1mUVxO8gklWoW+G8R3sJLo2OOrGQHsjPrtKvmYU+UCLOjOMh9TjsYMvwGhPz86Bp8xlZSp5WifmbUA==", + "peer": true + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -7964,14 +7970,6 @@ } } }, - "@types/iobroker": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/@types/iobroker/-/iobroker-4.0.5.tgz", - "integrity": "sha512-D1tJwuDQEQQQ/cZVFjFjFUhUuMxJbfrz5U2UooiZwhgs69D/t8IowMvBI6Lk4ZR8HnCSxYwWHVRKyQnEMNgJPA==", - "requires": { - "@types/node": "*" - } - }, "@types/minimatch": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz", @@ -7985,9 +7983,10 @@ "dev": true }, "@types/node": { - "version": "20.4.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.2.tgz", - "integrity": "sha512-Dd0BYtWgnWJKwO1jkmTrzofjK2QXXcai0dmtzvIBhcA+RsG5h8R3xlyta0kGOZRNfL9GuRtb1knmPEhQrePCEw==" + "version": "20.5.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.0.tgz", + "integrity": "sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==", + "dev": true }, "@types/proxyquire": { "version": "1.3.28", @@ -7996,9 +7995,9 @@ "dev": true }, "@types/sinon": { - "version": "10.0.15", - "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.15.tgz", - "integrity": "sha512-3lrFNQG0Kr2LDzvjyjB6AMJk4ge+8iYhQfdnSwIwlG88FUOV43kPcQqDZkDa/h3WSZy6i8Fr0BSjfQtB1B3xuQ==", + "version": "10.0.16", + "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-10.0.16.tgz", + "integrity": "sha512-j2Du5SYpXZjJVJtXBokASpPRj+e2z+VUhCPHmM6WMfe3dpHu6iVKJMU6AiBcMp/XTAYnEj6Wc1trJUWwZ0QaAQ==", "dev": true, "requires": { "@types/sinonjs__fake-timers": "*" @@ -9112,27 +9111,27 @@ "dev": true }, "eslint": { - "version": "8.45.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.45.0.tgz", - "integrity": "sha512-pd8KSxiQpdYRfYa9Wufvdoct3ZPQQuVuU5O6scNgMuOMYuxvH0IGaYK0wUFjo4UYYQQCUndlXiMbnxopwvvTiw==", + "version": "8.47.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz", + "integrity": "sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.1.0", - "@eslint/js": "8.44.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.2", + "@eslint/js": "^8.47.0", "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", - "ajv": "^6.10.0", + "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", "debug": "^4.3.2", "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.1", - "espree": "^9.6.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -9225,9 +9224,9 @@ } }, "eslint-scope": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.0.tgz", - "integrity": "sha512-DYj5deGlHBfMt15J7rdtyKNq/Nqlv5KfU4iodrQ019XESsRnwXH9KAE0y3cwtUHDo2ob7CypAnCqefh6vioWRw==", + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, "requires": { "esrecurse": "^4.3.0", @@ -9235,9 +9234,9 @@ } }, "eslint-visitor-keys": { - "version": "3.4.1", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", - "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true }, "espree": { @@ -9831,9 +9830,9 @@ } }, "globals": { - "version": "13.20.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.20.0.tgz", - "integrity": "sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ==", + "version": "13.21.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", + "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", "dev": true, "requires": { "type-fest": "^0.20.2" diff --git a/package.json b/package.json index af4a8bd5..dcd88dc2 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,7 @@ "url": "https://github.com/simatec/ioBroker.shuttercontrol" }, "dependencies": { - "@iobroker/adapter-core": "^2.6.8", + "@iobroker/adapter-core": "^3.0.3", "node-schedule": "^2.1.1", "suncalc": "^1.9.0" }, @@ -34,14 +34,14 @@ "@types/chai-as-promised": "^7.1.5", "@types/gulp": "^4.0.13", "@types/mocha": "^10.0.1", - "@types/node": "^20.4.2", + "@types/node": "^20.5.0", "@types/proxyquire": "^1.3.28", - "@types/sinon": "^10.0.15", + "@types/sinon": "^10.0.16", "@types/sinon-chai": "^3.2.9", "axios": "^1.4.0", "chai": "^4.3.7", "chai-as-promised": "^7.1.1", - "eslint": "^8.45.0", + "eslint": "^8.47.0", "gulp": "^4.0.2", "mocha": "^10.2.0", "proxyquire": "^2.1.3", From a85d2f37360750df4c787f9abcfa72a9480a0fcb Mon Sep 17 00:00:00 2001 From: 5G7K <60315312+5G7K@users.noreply.github.com> Date: Mon, 21 Aug 2023 23:20:39 +0200 Subject: [PATCH 04/10] Update main.js Debug & fixes for sunProtect --- main.js | 62 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/main.js b/main.js index ad5eba96..ff909fbc 100644 --- a/main.js +++ b/main.js @@ -279,8 +279,41 @@ function startAdapter(options) { adapter.log.debug(shutterSettings[s].shutterName + ' Updated trigger action to ' + shutterSettings[s].triggerAction + ' to prevent moving after window close '); } } else { - shutterSettings[s].currentAction = 'Manu_Mode'; - shutterSettings[s].triggerAction = 'Manu_Mode'; + adapter.log.debug(shutterSettings[s].shutterName + ' AP C current Action ' + shutterSettings[s].currentAction); + if (shutterSettings[s].currentAction != 'none' && shutterSettings[s].currentAction != 'OpenInSunProtect') { + shutterSettings[s].currentAction = 'Manu_Mode'; + shutterSettings[s].triggerAction = 'Manu_Mode'; + adapter.log.debug('AP Sunprotect Test Manu_Mode A'); + } + else { + adapter.log.debug('AP Sunprotect Test Manu_Mode B'); + + //Shutter is closed -> open manually to heightUp (should be 100% or 0%) before it has been opened automatically -> enable possibility to activate sunprotect height if required --> if sunprotect is required: shutter is set to sunProtect height + adapter.log.debug(shutterSettings[s].shutterName + ' AP M firstCompleteUp ' + shutterSettings[s].firstCompleteUp + ' - ' + state.val + '=' + shutterSettings[s].heightUp + ' - ' + shutterSettings[s].currentAction); + if (shutterSettings[s].firstCompleteUp == true && state.val == shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'up' && shutterSettings[s].currentAction != 'triggered' && shutterSettings[s].currentAction != 'triggered_Tilted') { + shutterSettings[s].currentHeight = state.val; + shutterSettings[s].triggerHeight = state.val; + shutterSettings[s].currentAction = 'none'; //reset mode. e.g. mode can be set to sunProtect later if window is closed + shutterSettings[s].triggerAction = 'Manu_Mode'; + shutterSettings[s].firstCompleteUp = false; + adapter.log.debug(shutterSettings[s].shutterName + ' opened manually to ' + shutterSettings[s].heightUp + '. Old value = ' + shutterSettings[s].oldHeight + '. New value = ' + state.val + '. Possibility to activate sunprotect enabled.'); + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }) + .catch((e) => adapter.log.warn(e)); + await adapter.setStateAsync('shutters.autoLevel.' + nameDevice, { val: parseFloat(shutterSettings[s].currentHeight), ack: true }) + .catch((e) => adapter.log.warn(e)); + + } + else { + shutterSettings[s].currentAction = 'Manu_Mode'; + shutterSettings[s].triggerAction = 'Manu_Mode'; + adapter.log.debug('AP Sunprotect Test Manu_Mode A2'); + } + if (shutterSettings[s].firstCompleteUp == true && shutterSettings[s].currentAction != 'triggered' && shutterSettings[s].currentAction != 'triggered_Tilted' && shutterSettings[s].currentAction != 'none' && (state.val === shutterSettings[s].heightUp || state.val === shutterSettings[s].heightDownSun)) { + shutterSettings[s].firstCompleteUp = false; //reset firstCompleteUp if shutter has been moved up + adapter.log.debug('AP 1 Test Reset firstCompleteUp ' + shutterSettings[s].shutterName); + } + } adapter.log.debug(shutterSettings[s].shutterName + ' drived manually to ' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + '. Old value = ' + shutterSettings[s].oldHeight + '. New value = ' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound); adapter.log.debug(shutterSettings[s].shutterName + ' Updated trigger action to ' + shutterSettings[s].triggerAction + ' to prevent moving after window close '); @@ -302,28 +335,15 @@ function startAdapter(options) { shutterSettings = await shutterState(shutterSettings[s].name, adapter, shutterSettings, false); } else if (typeof _shutterState != undefined && _shutterState != null && Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound === shutterSettings[s].currentHeight) { adapter.log.debug(shutterSettings[s].shutterName + ' Old value = ' + shutterSettings[s].oldHeight + '. New value = ' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + '. automatic is active'); - shutterSettings = await shutterState(shutterSettings[s].name, adapter, shutterSettings, false); + shutterSettings[s].firstCompleteUp = false; + adapter.log.debug('AP 2 Test Reset firstCompleteUp ' + shutterSettings[s].shutterName); + shutterSettings = await shutterState(shutterSettings[s].name, adapter, shutterSettings, false); } await sleep(1000); saveCurrentStates(false); - //Shutter is closed -> opened manually to heightUp (should be 100% or 0%) before it has been opened automatically -> enable possibility to activate sunprotect height if required --> if sunprotect is required: shutter is set to sunProtect height - if (shutterSettings[s].firstCompleteUp === true && state.val === shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'up' && shutterSettings[s].currentAction != 'triggered' && shutterSettings[s].currentAction != 'triggered_Tilted') { - shutterSettings[s].currentHeight = state.val; - shutterSettings[s].currentAction = 'none'; //reset mode. e.g. mode can be set to sunProtect later if window is closed - shutterSettings[s].firstCompleteUp = false; - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }) - .catch((e) => adapter.log.warn(e)); - await adapter.setStateAsync('shutters.autoLevel.' + nameDevice, { val: parseFloat(shutterSettings[s].currentHeight), ack: true }) - .catch((e) => adapter.log.warn(e)); - - adapter.log.debug(shutterSettings[s].shutterName + ' opened manually to ' + shutterSettings[s].heightUp + '. Old value = ' + shutterSettings[s].oldHeight + '. New value = ' + state.val + '. Possibility to activate sunprotect enabled.'); - } - if (shutterSettings[s].firstCompleteUp === true && shutterSettings[s].currentAction != 'triggered' && shutterSettings[s].currentAction != 'triggered_Tilted' && shutterSettings[s].currentAction != 'none' && (state.val === shutterSettings[s].heightUp || state.val === shutterSettings[s].heightDownSun)) { - shutterSettings[s].firstCompleteUp = false; //reset firstCompleteUp if shutter has been moved up - } //save old height await sleep(60000 + waitTime4StateCheck); shutterSettings[s].oldHeight = state.val; //set old Height after 60 Sek - after 60 Sek end position should be reached @@ -687,10 +707,12 @@ const calc = schedule.scheduleJob('calcTimer', '30 2 * * *', async function () { const _shutterState = await adapter.getForeignStateAsync(resultStates[i].name).catch((e) => adapter.log.warn(e)); if (typeof _shutterState != undefined && _shutterState != null) { - // Case: Shutter in sunProtect mode. Auto-down in the evening before end of sunProtect. The sun is sill shining. Prevent that the shutter opens again with end of sunProtect. - // currentAction=sunprotect would be set in sunProtect(). But not if currentAction=down. So this is checked in sunProtect(). Reset here to enable possibility to set sunProtect in the morning -> + // Reset Actions every night resultStates[i].currentAction = 'none'; + resultStates[i].triggerAction = 'none'; resultStates[i].firstCompleteUp = true; + resultStates[i].lastAutoAction = 'none'; + resultStates[i].alarmTriggerAction = 'none'; await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: resultStates[i].currentAction, ack: true }) .catch((e) => adapter.log.warn(e)); From d7a18f1450ea23f9236f985e7b8970f288125cff Mon Sep 17 00:00:00 2001 From: 5G7K <60315312+5G7K@users.noreply.github.com> Date: Thu, 24 Aug 2023 17:45:30 +0200 Subject: [PATCH 05/10] Update main.js Fix Issue #623 Fix set oldHeight & firstCompleteUp Fix timing issues Update currentStates with current values --- main.js | 52 +++++++++++++++++++++++++--------------------------- 1 file changed, 25 insertions(+), 27 deletions(-) diff --git a/main.js b/main.js index ff909fbc..05765575 100644 --- a/main.js +++ b/main.js @@ -241,7 +241,7 @@ function startAdapter(options) { const nameDevice = shutterSettings[s].shutterName.replace(/[.;, ]/g, '_'); const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - if (typeof _shutterState != undefined && _shutterState != null && shutterSettings[s].oldHeight != Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound) { + if (typeof _shutterState != undefined && _shutterState != null && shutterSettings[s].oldHeight != Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound) { adapter.log.debug('Shutter state changed: ' + shutterSettings[s].shutterName + ' old value = ' + shutterSettings[s].oldHeight + ' new value = ' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound); } if (typeof _shutterState != undefined && _shutterState != null && Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound != shutterSettings[s].currentHeight && Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound != shutterSettings[s].oldHeight) { @@ -279,24 +279,21 @@ function startAdapter(options) { adapter.log.debug(shutterSettings[s].shutterName + ' Updated trigger action to ' + shutterSettings[s].triggerAction + ' to prevent moving after window close '); } } else { - adapter.log.debug(shutterSettings[s].shutterName + ' AP C current Action ' + shutterSettings[s].currentAction); - if (shutterSettings[s].currentAction != 'none' && shutterSettings[s].currentAction != 'OpenInSunProtect') { + if (shutterSettings[s].firstCompleteUp != true && shutterSettings[s].currentAction != 'none' && shutterSettings[s].currentAction != 'OpenInSunProtect') { shutterSettings[s].currentAction = 'Manu_Mode'; shutterSettings[s].triggerAction = 'Manu_Mode'; - adapter.log.debug('AP Sunprotect Test Manu_Mode A'); + adapter.log.debug('set Manu_Mode #1 ' + shutterSettings[s].shutterName); } else { - adapter.log.debug('AP Sunprotect Test Manu_Mode B'); - //Shutter is closed -> open manually to heightUp (should be 100% or 0%) before it has been opened automatically -> enable possibility to activate sunprotect height if required --> if sunprotect is required: shutter is set to sunProtect height - adapter.log.debug(shutterSettings[s].shutterName + ' AP M firstCompleteUp ' + shutterSettings[s].firstCompleteUp + ' - ' + state.val + '=' + shutterSettings[s].heightUp + ' - ' + shutterSettings[s].currentAction); - if (shutterSettings[s].firstCompleteUp == true && state.val == shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'up' && shutterSettings[s].currentAction != 'triggered' && shutterSettings[s].currentAction != 'triggered_Tilted') { - shutterSettings[s].currentHeight = state.val; - shutterSettings[s].triggerHeight = state.val; + if (shutterSettings[s].firstCompleteUp == true && Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'up' && shutterSettings[s].currentAction != 'triggered' && shutterSettings[s].currentAction != 'triggered_Tilted') { + shutterSettings[s].currentHeight = Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound; + shutterSettings[s].triggerHeight = Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound; shutterSettings[s].currentAction = 'none'; //reset mode. e.g. mode can be set to sunProtect later if window is closed shutterSettings[s].triggerAction = 'Manu_Mode'; shutterSettings[s].firstCompleteUp = false; - adapter.log.debug(shutterSettings[s].shutterName + ' opened manually to ' + shutterSettings[s].heightUp + '. Old value = ' + shutterSettings[s].oldHeight + '. New value = ' + state.val + '. Possibility to activate sunprotect enabled.'); + adapter.log.debug('Reset firstCompleteUp #1 for ' + shutterSettings[s].shutterName); + adapter.log.debug(shutterSettings[s].shutterName + ' opened manually to ' + shutterSettings[s].heightUp + '. Old value = ' + shutterSettings[s].oldHeight + '. New value = ' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + '. Possibility to activate sunprotect enabled.'); await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }) .catch((e) => adapter.log.warn(e)); @@ -307,12 +304,8 @@ function startAdapter(options) { else { shutterSettings[s].currentAction = 'Manu_Mode'; shutterSettings[s].triggerAction = 'Manu_Mode'; - adapter.log.debug('AP Sunprotect Test Manu_Mode A2'); - } - if (shutterSettings[s].firstCompleteUp == true && shutterSettings[s].currentAction != 'triggered' && shutterSettings[s].currentAction != 'triggered_Tilted' && shutterSettings[s].currentAction != 'none' && (state.val === shutterSettings[s].heightUp || state.val === shutterSettings[s].heightDownSun)) { - shutterSettings[s].firstCompleteUp = false; //reset firstCompleteUp if shutter has been moved up - adapter.log.debug('AP 1 Test Reset firstCompleteUp ' + shutterSettings[s].shutterName); - } + adapter.log.debug('set Manu_Mode #2 ' + shutterSettings[s].shutterName); + } } adapter.log.debug(shutterSettings[s].shutterName + ' drived manually to ' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + '. Old value = ' + shutterSettings[s].oldHeight + '. New value = ' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound); @@ -331,23 +324,26 @@ function startAdapter(options) { await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }) .catch((e) => adapter.log.warn(e)); - + await sleep(2000); shutterSettings = await shutterState(shutterSettings[s].name, adapter, shutterSettings, false); } else if (typeof _shutterState != undefined && _shutterState != null && Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound === shutterSettings[s].currentHeight) { adapter.log.debug(shutterSettings[s].shutterName + ' Old value = ' + shutterSettings[s].oldHeight + '. New value = ' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + '. automatic is active'); - shutterSettings[s].firstCompleteUp = false; - adapter.log.debug('AP 2 Test Reset firstCompleteUp ' + shutterSettings[s].shutterName); + await sleep(2000); shutterSettings = await shutterState(shutterSettings[s].name, adapter, shutterSettings, false); } - await sleep(1000); - saveCurrentStates(false); - - //save old height - await sleep(60000 + waitTime4StateCheck); - shutterSettings[s].oldHeight = state.val; //set old Height after 60 Sek - after 60 Sek end position should be reached - saveCurrentStates(false); + await sleep(2000); //already waited waitTime4StateCheck seconds. + var timeout_set_oldHeight; + timeout_set_oldHeight = setTimeout(async () => { //async set with timeout because e.g. Shelly submits several position by MQTT and not only the last one (0% 1% ... 97% - 98% - 100%). By this the value is set only after the final height state has been processed + timeout_set_oldHeight = null; + shutterSettings[s].oldHeight = shutterSettings[s].currentHeight; + if (shutterSettings[s].firstCompleteUp === true) { + shutterSettings[s].firstCompleteUp = false; + adapter.log.debug('Reset firstCompleteUp #2 for ' + shutterSettings[s].shutterName); + } + }, 5000 + waitTime4StateCheck); + saveCurrentStates(false); } } } @@ -720,6 +716,7 @@ const calc = schedule.scheduleJob('calcTimer', '30 2 * * *', async function () { if (typeof _shutterState.val != undefined && _shutterState.val != null) { resultStates[i].currentHeight = Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound; + resultStates[i].oldHeight = resultStates[i].currentHeight await adapter.setStateAsync('shutters.autoLevel.' + nameDevice, { val: parseFloat(resultStates[i].currentHeight), ack: true }) .catch((e) => adapter.log.warn(e)); @@ -729,6 +726,7 @@ const calc = schedule.scheduleJob('calcTimer', '30 2 * * *', async function () { adapter.log.debug(resultStates[i].shutterName + ' level conversion is enabled'); } } + saveCurrentStates(false); } } } From e382b047607369a4f2162d102d8b0df457aacdea Mon Sep 17 00:00:00 2001 From: 5G7K <60315312+5G7K@users.noreply.github.com> Date: Fri, 25 Aug 2023 08:12:58 +0200 Subject: [PATCH 06/10] shuttercontrol.md Optimized text for "Checking the current shutter status" --- docs/en/shuttercontrol.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/shuttercontrol.md b/docs/en/shuttercontrol.md index cfe853b9..1df4201d 100644 --- a/docs/en/shuttercontrol.md +++ b/docs/en/shuttercontrol.md @@ -245,7 +245,7 @@ These settings are actually self-explanatory: latitude and longitude of the plac ## Extra settings -**Checking the current shutter status:** For some users (among other shelly users) the problem arises that the level changes again. For this reason there is a checkbox here. Should the checkbox be active, shuttercontroll will check the current level 1 minute after the last trip of the shutter and save it temporarily. +**Checking the current shutter status:** For some users (among other shelly users) the problem arises that the level changes again or several times until the endposition is reached. As a result, the recognition of the last action may be incorrect and, for example, the "manu_mode" may be set incorrectly. For this reason there is a checkbox here. If the check box is activated, shuttercontrol checks the final level again after n seconds. Set the waiting time to the running time of your shutter that needs the longest. **Use of public holidays:** If the roller shutters are to be used on public holidays as well as on weekends, the checkbox is activated and an instance of the public holiday adapter is selected. You can create two instances of the holiday adapter if necessary; a to display all possible holidays and a working time relevant holidays, which then access shuttercontrol. @@ -317,4 +317,4 @@ This setting can be helpfull to prevent moving up and down while the weather is **Alarm Settings** With this setting the predefined alarm (Alarm setting in Main-Extra Menü) shall be acitvated for this -particular Rollo. \ No newline at end of file +particular Rollo. From ae272d49fdeae327cd3448a13c1e695b72690a54 Mon Sep 17 00:00:00 2001 From: 5G7K <60315312+5G7K@users.noreply.github.com> Date: Fri, 25 Aug 2023 08:21:22 +0200 Subject: [PATCH 07/10] shuttercontrol.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Optimierung des Textes zur "Überprüfung des aktuellen Rollladenstatus" --- docs/de/shuttercontrol.md | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/docs/de/shuttercontrol.md b/docs/de/shuttercontrol.md index baa49ad4..f49d6525 100644 --- a/docs/de/shuttercontrol.md +++ b/docs/de/shuttercontrol.md @@ -298,10 +298,8 @@ abgelaufen ist. ![extraSettingsExtra](img/ExtraSettingsExtra.png) **Überprüfen des aktuellen Rollladenstatus:** -Bei einigen Usern (unter anderen shelly User) tritt das Problem auf, dass sich das -Level noch einmal etwas verändert. Aus diesem Grund gibt es hier eine Checkbox. -Bei aktivierter Checkbox, prüft shuttercontrol 1 Minute nach der letzten Fahrt des -Rollladens das aktuelle Level und speichert es temporär. +Bei einigen Usern (unter anderen shelly User) tritt das Problem auf, dass sich das Level bis zum Erreichen der finalen Position fortlaufend oder zum Ende nochmal ändert. Dadurch kann die Erkennung der letzten Aktion fehlerhaft sein und z.B. der "manu_mode" fälschlicherweise gesetzt werden. Aus diesem Grund gibt es hier eine Checkbox. +Bei aktivierter Checkbox, prüft shuttercontrol die finale Position nochmal nach n Sekunden. Setze die Wartezeit auf die Laufzeit deines Rollladens, der am längsten benötigt. **Objekt ID des Auslösers für den Schlafbereich (Auto):** Mit diesem Auslöser wird der Automodus des Schlafbereichs aktiviert. From 19219b592aac189fff947be80067f247ca5fe58b Mon Sep 17 00:00:00 2001 From: simatec Date: Mon, 28 Aug 2023 11:48:02 +0200 Subject: [PATCH 08/10] (simatec) Beta 1.6.2 --- README.md | 2 + lib/sunProtect.js | 2809 +++++++++++++++++++++++---------------------- package-lock.json | 72 +- package.json | 8 +- 4 files changed, 1463 insertions(+), 1428 deletions(-) diff --git a/README.md b/README.md index c7d1f95e..efe72254 100644 --- a/README.md +++ b/README.md @@ -49,6 +49,8 @@ When the adapter crashes or an other Code error happens, this error message that ### __WORK IN PROGRESS__ * (simatec) Dependencies updated * (simatec) node 20 tests added +* (simatec) Fix ending Sunprotect with open door/window +* (5G7K) Fix timing & some states for sunprotect ### 1.6.1 (2023-07-17) * (simatec) Fix Heat protection diff --git a/lib/sunProtect.js b/lib/sunProtect.js index c4bc1659..379d391c 100644 --- a/lib/sunProtect.js +++ b/lib/sunProtect.js @@ -6,1428 +6,1461 @@ const setShutterState = require('./setShutter.js').setShutterState; let timerSleep = 0; async function sleep(ms) { - return new Promise(async (resolve) => { - // @ts-ignore - timerSleep = setTimeout(async () => resolve(), ms); - }); + return new Promise(async (resolve) => { + // @ts-ignore + timerSleep = setTimeout(async () => resolve(), ms); + }); } // @ts-ignore async function sunProtect(adapter, elevation, azimuth, shutterSettings) { - const driveDelayUpSleep = adapter.config.driveDelayUpAstro != 0 ? adapter.config.driveDelayUpAstro * 1000 : 20; - const vRound = adapter.config.shutterStateRound; - - await sleep(2000); - if (shutterSettings) { - const result = shutterSettings.filter((/** @type {{ enabled: boolean; }} */ d) => d.enabled === true); // Filter enabled - - if (elevation > adapter.config.sunProtEndElevation) { - for (const i in result) { - for (const s in shutterSettings) { - if (shutterSettings[s].shutterName == result[i].shutterName) { - let resultDirectionRangeMinus = 0; - let resultDirectionRangePlus = 0; - let convertShutter = false; - let heightDownSun = shutterSettings[s].heightDownSun; - - const nameDevice = shutterSettings[s].shutterName.replace(/[.;, ]/g, '_'); - - if (parseFloat(shutterSettings[s].heightDown) < parseFloat(shutterSettings[s].heightUp)) { - convertShutter = false; - } else if (parseFloat(shutterSettings[s].heightDown) > parseFloat(shutterSettings[s].heightUp)) { - convertShutter = true; - } - - const pendingAlarm = await checkPendingAlarm(adapter, shutterSettings[s]); - - const _autoSunState = await adapter.getStateAsync(`shutters.autoSun.${nameDevice}`).catch((e) => adapter.log.warn(e)); - - if (_autoSunState && _autoSunState.val === true) { - let currentValue = ''; - let _triggerState; - let mustValue = ''; - let mustValueTilted = ''; - - switch (shutterSettings[s].type) { - - // +++++++++++++++++ sunprotect with in/outside temperature and Lightsensor +++++++++++++++ - - case 'in- & outside temperature': // in- & outside temperature - _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; - mustValue = ('' + shutterSettings[s].triggerState); - mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); - - if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { - currentValue = ('' + _triggerState.val); - } - - if ((currentValue === mustValue || currentValue === mustValueTilted) && shutterSettings[s].tempSensor != '' || - (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off' && shutterSettings[s].tempSensor != '') || - (shutterSettings[s].triggerID == '' && shutterSettings[s].tempSensor != '')) { - - let insideTemp = 0; - let outsideTemp = 0; - let sunLight = 0; - - const _insideTempState = shutterSettings[s].tempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].tempSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _insideTempState != undefined && _insideTempState != null && _insideTempState.val != undefined) { - insideTemp = parseFloat(_insideTempState.val); - } - - const _outsideTempState = shutterSettings[s].outsideTempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].outsideTempSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _outsideTempState != undefined && _outsideTempState != null && _outsideTempState.val != undefined) { - outsideTemp = parseFloat(_outsideTempState.val); - } - - const _sunLight = shutterSettings[s].lightSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].lightSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _sunLight != undefined && _sunLight != null && _sunLight.val != undefined) { - sunLight = parseFloat(_sunLight.val); - } - - // heatProtection - if (shutterSettings[s].heatProtection == true && - shutterSettings[s].tempHeatProtection < outsideTemp && - shutterSettings[s].currentHeight != shutterSettings[s].heightDown) { - - shutterSettings[s].currentAction = shutterSettings[s].currentAction == 'sunProtect' ? '' : shutterSettings[s].currentAction; - heightDownSun = shutterSettings[s].heightDown; - adapter.log.debug(`Heat Protection for ${shutterSettings[s].shutterName} is active`); - adapter.log.debug(`currentAction ${shutterSettings[s].currentAction}`); - - } else { - heightDownSun = shutterSettings[s].heightDownSun; - } - - if (shutterSettings[s].sunProtectEndtimerid != '' && - shutterSettings[s].sunProtectEndtimerid != '0' && - shutterSettings[s].lightSensor != '' && - shutterSettings[s].valueLight < sunLight) { - - adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); - clearTimeout(shutterSettings[s].sunProtectEndtimerid); - shutterSettings[s].sunProtectEndtimerid = ''; - } - - if (currentValue === mustValue || currentValue === mustValueTilted || - (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || - (shutterSettings[s].triggerID == '')) { - - if (insideTemp > shutterSettings[s].tempInside) { - if (shutterSettings[s].tempOutside < outsideTemp && - (shutterSettings[s].lightSensor != '' && - shutterSettings[s].valueLight < sunLight || - shutterSettings[s].lightSensor == '') && - shutterSettings[s].currentAction != 'sunProtect' && - shutterSettings[s].currentAction != 'OpenInSunProtect' && - shutterSettings[s].currentAction != 'Manu_Mode') { - - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); - - if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && - convertShutter == false) || - (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && - convertShutter == true)) && - Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && - (shutterSettings[s].currentHeight == shutterSettings[s].heightUp || - (shutterSettings[s].heatProtection == true && - shutterSettings[s].tempHeatProtection < outsideTemp))) { - - shutterSettings[s].currentAction = 'sunProtect'; - shutterSettings[s].lastAutoAction = 'down_Sunprotect'; - shutterSettings[s].currentHeight = heightDownSun; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #410'); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); - adapter.log.debug('Temperature inside: ' + insideTemp + ' > ' + shutterSettings[s].tempInside + ' AND ( Temperatur outside: ' + outsideTemp + ' > ' + shutterSettings[s].tempOutside + ' AND Light: ' + sunLight + ' > ' + shutterSettings[s].valueLight + ' )'); - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%'); - } - // Shutter closed. Set currentAction = sunProtect when sunProtect starts => - // If shutter is opened automatically it can be opened in height heightDownSun directly - else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].heightDown) && - Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && - shutterSettings[s].currentHeight != shutterSettings[s].heightUp && - shutterSettings[s].currentAction != 'down' && - shutterSettings[s].currentAction != 'middle' && - shutterSettings[s].currentAction != 'Xmas' && - shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! - - shutterSettings[s].currentAction = 'OpenInSunProtect'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); - } - //Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> - // set sunProtect again - else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) && - Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && - shutterSettings[s].currentHeight != shutterSettings[s].heightUp && - shutterSettings[s].currentHeight != shutterSettings[s].heightDown && - shutterSettings[s].currentAction == '') { - - shutterSettings[s].currentAction = 'sunProtect'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' HeightDownSun:' + heightDownSun); - } - } - } else { - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - } - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - if (insideTemp > shutterSettings[s].tempInside) { - if (shutterSettings[s].tempOutside < outsideTemp && - (shutterSettings[s].lightSensor != '' && - shutterSettings[s].valueLight < sunLight || - shutterSettings[s].lightSensor == '') && - shutterSettings[s].triggerAction != 'sunProtect' && - shutterSettings[s].triggerAction != 'OpenInSunProtect' && - shutterSettings[s].triggerAction != 'Manu_Mode') { - - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp + ' AND triggerAction:' + shutterSettings[s].triggerAction + ' != down '); - - if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && - convertShutter == false) || - (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && - convertShutter == true)) && - Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && - shutterSettings[s].currentHeight == shutterSettings[s].heightUp && - shutterSettings[s].triggerAction != 'down' && - shutterSettings[s].currentAction != 'middle' && - shutterSettings[s].currentAction != 'Xmas') { - - shutterSettings[s].triggerHeight = parseFloat(heightDownSun); - shutterSettings[s].triggerAction = 'sunProtect'; - - adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - } - - } - } else { - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - } - } - } - } - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { - const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); - const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); - const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); - - if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { - adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); - shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { - shutterSettings[s].sunProtectEndtimerid = '0'; - }, shutterSettings[s].sunProtectEndDely * 60000, i); - } - - if (insideTemp < parseFloat(hysteresisInside) || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { - - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].currentAction = 'up'; - shutterSettings[s].currentHeight = shutterSettings[s].heightUp; - shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #411'); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); - adapter.log.debug('Temperature inside: ' + insideTemp + ' < ' + hysteresisInside + ' OR ( Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight + ' )'); - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%') - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].sunProtectEndtimerid = '' - shutterSettings[s].currentAction = 'none'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); - const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); - const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); - - if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { - adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); - shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { - shutterSettings[s].sunProtectEndtimerid = '0'; - }, shutterSettings[s].sunProtectEndDely * 60000, i); - } - - if (insideTemp < parseFloat(hysteresisInside) || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { - - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].triggerAction = 'up'; - - adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); - adapter.log.debug('Temperature inside: ' + insideTemp + ' < ' + hysteresisInside + ' OR ( Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight + ' )'); - adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].sunProtectEndtimerid = '' - shutterSettings[s].triggerAction = 'none'; - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - } - } - } - } - await sleep(driveDelayUpSleep); - break; - - ////////////////////////////////////////////////////////////////////////////////////////////////////// - - // +++++++++++++++++ sunprotect with in/outside temperature, Lightsensor and direction +++++++++++++++ - - case 'in- & outside temperature and direction': // in- & outside temperature and direction - resultDirectionRangeMinus = parseInt(shutterSettings[s].direction) - parseInt(shutterSettings[s].directionRange); - resultDirectionRangePlus = parseInt(shutterSettings[s].direction) + parseInt(shutterSettings[s].directionRange); - - _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; - mustValue = ('' + shutterSettings[s].triggerState); - mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); - - if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { - currentValue = ('' + _triggerState.val); - } - - if ((currentValue === mustValue || currentValue === mustValueTilted) && shutterSettings[s].tempSensor != '' || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off' && shutterSettings[s].tempSensor != '') || (shutterSettings[s].triggerID == '' && shutterSettings[s].tempSensor != '')) { - let insideTemp = 0; - let outsideTemp = 0; - let sunLight = 0; - - const _insideTempState = shutterSettings[s].tempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].tempSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _insideTempState != undefined && _insideTempState != null && _insideTempState.val != undefined) { - insideTemp = parseFloat(_insideTempState.val); - } - - const _outsideTempState = shutterSettings[s].outsideTempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].outsideTempSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _outsideTempState != undefined && _outsideTempState != null && _outsideTempState.val != undefined) { - outsideTemp = parseFloat(_outsideTempState.val); - } - - // heatProtection - if (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown) { - shutterSettings[s].currentAction = shutterSettings[s].currentAction == 'sunProtect' ? '' : shutterSettings[s].currentAction; - heightDownSun = shutterSettings[s].heightDown; - adapter.log.debug(`Heat Protection for ${shutterSettings[s].shutterName} is active`); - } else { - heightDownSun = shutterSettings[s].heightDownSun; - } - - const _sunLight = shutterSettings[s].lightSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].lightSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _sunLight != undefined && _sunLight != null && _sunLight.val != undefined) { - sunLight = parseFloat(_sunLight.val); - } - - if (shutterSettings[s].sunProtectEndtimerid != '' && shutterSettings[s].sunProtectEndtimerid != '0' && shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight) { - adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); - clearTimeout(shutterSettings[s].sunProtectEndtimerid); - shutterSettings[s].sunProtectEndtimerid = ''; - } - - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || (shutterSettings[s].triggerID == '')) { - if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth && insideTemp > shutterSettings[s].tempInside) { - if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].currentAction != 'sunProtect' && shutterSettings[s].currentAction != 'OpenInSunProtect' && shutterSettings[s].currentAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); - - if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || - (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && - (shutterSettings[s].currentHeight == shutterSettings[s].heightUp || (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp))) { - - shutterSettings[s].currentAction = 'sunProtect'; - shutterSettings[s].currentHeight = heightDownSun; - shutterSettings[s].lastAutoAction = 'down_Sunprotect'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #412'); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); - adapter.log.debug('Temperature inside: ' + insideTemp + ' > ' + shutterSettings[s].tempInside + ' AND ( Temperatur outside: ' + outsideTemp + ' > ' + shutterSettings[s].tempOutside + ' AND Light: ' + sunLight + ' > ' + shutterSettings[s].valueLight + ' )'); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%'); - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%') - } - // Shutter closed. Set currentAction = sunProtect when sunProtect starts => - // If shutter is opened automatically it can be opened in height heightDownSun directly - else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].heightDown) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas' && shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! - shutterSettings[s].currentAction = 'OpenInSunProtect'; - adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); - } - // Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> - // set sunProtect again - else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown && shutterSettings[s].currentAction == '') { - shutterSettings[s].currentAction = 'sunProtect'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' HeightDownSun:' + heightDownSun); - } - } - } else { - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - } - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth && insideTemp > shutterSettings[s].tempInside) { - if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].triggerAction != 'sunProtect' && shutterSettings[s].triggerAction != 'OpenInSunProtect' && shutterSettings[s].triggerAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp + ' AND triggerAction:' + shutterSettings[s].triggerAction + ' != down '); - if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp && shutterSettings[s].triggerAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas') { - shutterSettings[s].triggerHeight = parseFloat(heightDownSun); - shutterSettings[s].triggerAction = 'sunProtect'; - - adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - } - } - } else { - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); - } - } - } - } - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { - const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); - const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); - const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); - - if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { - adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); - shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { - shutterSettings[s].sunProtectEndtimerid = '0'; - }, shutterSettings[s].sunProtectEndDely * 60000, i); - } - - - if (insideTemp < parseFloat(hysteresisInside) || (resultDirectionRangePlus) < azimuth || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { - - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].currentAction = 'up'; - shutterSettings[s].currentHeight = shutterSettings[s].heightUp; - shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #413'); - - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); - adapter.log.debug('Range: ' + resultDirectionRangePlus + ' < ' + azimuth + ' OR Temperature inside: ' + insideTemp + ' < ' + hysteresisInside + ' OR ( Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight + ')'); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + shutterSettings[s].heightUp + '%'); - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].sunProtectEndtimerid = '' - shutterSettings[s].currentAction = 'none'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); - const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); - const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); - - if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { - adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); - shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { - shutterSettings[s].sunProtectEndtimerid = '0'; - }, shutterSettings[s].sunProtectEndDely * 60000, i); - } - - if (insideTemp < parseFloat(hysteresisInside) || (resultDirectionRangePlus) < azimuth || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { - - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].triggerAction = 'up'; - - adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); - adapter.log.debug('Temperature inside: ' + insideTemp + ' < ' + hysteresisInside + ' OR ( Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight + ' )'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].triggerAction = 'none'; - - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } - } - } - } - await sleep(driveDelayUpSleep); - break; - - ////////////////////////////////////////////////////////////////////////////////////////////////////// - - // +++++++++++++++++ sunprotect with outside temperature, Lightsensor and direction +++++++++++++++ - - case 'outside temperature and direction': //outside temperature and direction - resultDirectionRangeMinus = parseInt(shutterSettings[s].direction) - parseInt(shutterSettings[s].directionRange); - resultDirectionRangePlus = parseInt(shutterSettings[s].direction) + parseInt(shutterSettings[s].directionRange); - - _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; - mustValue = ('' + shutterSettings[s].triggerState); - mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); - - if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { - currentValue = ('' + _triggerState.val); - } - - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off') || (shutterSettings[s].triggerID == '')) { - let outsideTemp = 0; - let sunLight = 0; - - const _outsideTempState = shutterSettings[s].outsideTempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].outsideTempSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _outsideTempState != undefined && _outsideTempState != null && _outsideTempState.val != undefined) { - outsideTemp = parseFloat(_outsideTempState.val); - } - - // heatProtection - if (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown) { - shutterSettings[s].currentAction = shutterSettings[s].currentAction == 'sunProtect' ? '' : shutterSettings[s].currentAction; - heightDownSun = shutterSettings[s].heightDown; - adapter.log.debug(`Heat Protection for ${shutterSettings[s].shutterName} is active`); - } else { - heightDownSun = shutterSettings[s].heightDownSun; - } - - const _sunLight = shutterSettings[s].lightSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].lightSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _sunLight != undefined && _sunLight != null && _sunLight.val != undefined) { - sunLight = parseFloat(_sunLight.val); - } - - if (shutterSettings[s].sunProtectEndtimerid != '' && shutterSettings[s].sunProtectEndtimerid != '0' && shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight) { - adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); - clearTimeout(shutterSettings[s].sunProtectEndtimerid); - shutterSettings[s].sunProtectEndtimerid = ''; - } - - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || (shutterSettings[s].triggerID == '')) { - if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth) { - if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].currentAction != 'sunProtect' && shutterSettings[s].currentAction != 'OpenInSunProtect' && shutterSettings[s].currentAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); - - if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || - (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && - (shutterSettings[s].currentHeight == shutterSettings[s].heightUp || (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp))) { - - shutterSettings[s].currentAction = 'sunProtect'; - shutterSettings[s].currentHeight = heightDownSun; - shutterSettings[s].lastAutoAction = 'down_Sunprotect'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #414'); - - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); - adapter.log.debug('Temperatur outside: ' + outsideTemp + ' > ' + shutterSettings[s].tempOutside + ' AND Light: ' + sunLight + ' > ' + shutterSettings[s].valueLight); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%') - } - // Shutter closed. Set currentAction = sunProtect when sunProtect starts => - // If shutter is opened automatically it can be opened in height heightDownSun directly - else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].heightDown) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas' && shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! - shutterSettings[s].currentAction = 'OpenInSunProtect'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); - } - // Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> - // set sunProtect again - else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown && shutterSettings[s].currentAction == '') { - shutterSettings[s].currentAction = 'sunProtect'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' HeightDownSun:' + heightDownSun); - } - } - } else { - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); - } - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth) { - if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].triggerAction != 'sunProtect' && shutterSettings[s].triggerAction != 'OpenInSunProtect' && shutterSettings[s].triggerAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); - if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp && shutterSettings[s].triggerAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas') { - shutterSettings[s].triggerHeight = parseFloat(heightDownSun); - shutterSettings[s].triggerAction = 'sunProtect'; - - adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - } - - } - } else { - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); - } - } - } - } - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { - const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); - const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); - - if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { - adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); - shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { - shutterSettings[s].sunProtectEndtimerid = '0'; - }, shutterSettings[s].sunProtectEndDely * 60000, i); - } - - if ((resultDirectionRangePlus) < azimuth || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].currentAction = 'up'; - shutterSettings[s].currentHeight = shutterSettings[s].heightUp; - shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #415'); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); - adapter.log.debug('Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight); - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + shutterSettings[s].heightUp + '%') - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].currentAction = 'none'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); - const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); - - if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { - adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); - shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { - shutterSettings[s].sunProtectEndtimerid = '0'; - }, shutterSettings[s].sunProtectEndDely * 60000, i); - } - - if ((resultDirectionRangePlus) < azimuth || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].triggerAction = 'up'; - - adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].sunProtectEndtimerid = '' - shutterSettings[s].triggerAction = 'none'; - - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } - } - } - } - await sleep(driveDelayUpSleep); - break; - - ////////////////////////////////////////////////////////////////////////////////////////////////////// - - // ++++++++++++++++++++++++++++++ sunprotect with direction ++++++++++++++++++++++++++++++++++ - - case 'only direction': //only direction - resultDirectionRangeMinus = parseInt(shutterSettings[s].direction) - parseInt(shutterSettings[s].directionRange); - resultDirectionRangePlus = parseInt(shutterSettings[s].direction) + parseInt(shutterSettings[s].directionRange); - - _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; - mustValue = ('' + shutterSettings[s].triggerState); - mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); - - if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { - currentValue = ('' + _triggerState.val); - } - - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off') || (shutterSettings[s].triggerID == '')) { - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || (shutterSettings[s].triggerID == '')) { - if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth && shutterSettings[s].currentAction != 'sunProtect' && shutterSettings[s].currentAction != 'OpenInSunProtect' && shutterSettings[s].currentAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); - if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp) { - shutterSettings[s].currentAction = 'sunProtect'; - shutterSettings[s].currentHeight = heightDownSun; - shutterSettings[s].lastAutoAction = 'down_Sunprotect'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #416'); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); - adapter.log.debug('RangeMinus: ' + resultDirectionRangeMinus + ' < ' + azimuth + 'RangePlus: ' + resultDirectionRangePlus + ' > ' + azimuth); - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%'); - } - // Shutter closed. Set currentAction = sunProtect when sunProtect starts => - // If shutter is opened automatically it can be opened in height heightDownSun directly - else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].heightDown) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas' && shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! - shutterSettings[s].currentAction = 'OpenInSunProtect'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); - } - // Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> - // set sunProtect again - else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown && shutterSettings[s].currentAction == '') { - shutterSettings[s].currentAction = 'sunProtect'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' HeightDownSun:' + heightDownSun); - } - } - } else { - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth && shutterSettings[s].triggerAction != 'sunProtect' && shutterSettings[s].triggerAction != 'OpenInSunProtect' && shutterSettings[s].triggerAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); - if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp && shutterSettings[s].triggerAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas') { - shutterSettings[s].triggerHeight = parseFloat(heightDownSun); - shutterSettings[s].triggerAction = 'sunProtect'; - - adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - } - } - } else { - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); - } - - } - } - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { - if ((resultDirectionRangePlus) < azimuth) { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].currentAction = 'up'; - shutterSettings[s].currentHeight = shutterSettings[s].heightUp; - shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #417'); - - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); - adapter.log.debug('Range: ' + resultDirectionRangePlus + ' < ' + azimuth); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + shutterSettings[s].heightUp + '%') - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].currentAction = 'none'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - if ((resultDirectionRangePlus) < azimuth) { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].triggerAction = 'up'; - - adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].triggerAction = 'none'; - - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } - } - } - } - await sleep(driveDelayUpSleep); - break; - - ////////////////////////////////////////////////////////////////////////////////////////////////////// - - // ++++++++++++++++++++++++ sunprotect with outside temperature and Lightsensor +++++++++++++++++++++++ - - case 'only outside temperature': //only outside temperature - _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; - mustValue = ('' + shutterSettings[s].triggerState); - mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); - - if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { - currentValue = ('' + _triggerState.val); - } - - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off') || (shutterSettings[s].triggerID == '')) { - let outsideTemp = 0; - let sunLight = 0; - - const _outsideTempState = shutterSettings[s].outsideTempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].outsideTempSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _outsideTempState != undefined && _outsideTempState != null && _outsideTempState.val != undefined) { - outsideTemp = parseFloat(_outsideTempState.val); - } - - // heatProtection - if (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown) { - shutterSettings[s].currentAction = shutterSettings[s].currentAction == 'sunProtect' ? '' : shutterSettings[s].currentAction; - heightDownSun = shutterSettings[s].heightDown; - adapter.log.debug(`Heat Protection for ${shutterSettings[s].shutterName} is active`); - } else { - heightDownSun = shutterSettings[s].heightDownSun; - } - - const _sunLight = shutterSettings[s].lightSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].lightSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _sunLight != undefined && _sunLight != null && _sunLight.val != undefined) { - sunLight = parseFloat(_sunLight.val); - } - - if (shutterSettings[s].sunProtectEndtimerid != '' && shutterSettings[s].sunProtectEndtimerid != '0' && shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight) { - adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); - clearTimeout(shutterSettings[s].sunProtectEndtimerid); - shutterSettings[s].sunProtectEndtimerid = ''; - } - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || (shutterSettings[s].triggerID == '')) { - if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].currentAction != 'sunProtect' && shutterSettings[s].currentAction != 'OpenInSunProtect' && shutterSettings[s].currentAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); - - if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || - (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && - (shutterSettings[s].currentHeight == shutterSettings[s].heightUp || (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp))) { - - shutterSettings[s].currentAction = 'sunProtect'; - shutterSettings[s].currentHeight = heightDownSun; - shutterSettings[s].lastAutoAction = 'down_Sunprotect'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #418'); - - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); - adapter.log.debug('Temperature outside: ' + outsideTemp + ' > ' + shutterSettings[s].tempOutside + ' AND Light: ' + sunLight + ' > ' + shutterSettings[s].valueLight); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%'); - } - // Shutter closed. Set currentAction = sunProtect when sunProtect starts => - // If shutter is opened automatically it can be opened in height heightDownSun directly - else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].heightDown) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas' && shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! - shutterSettings[s].currentAction = 'OpenInSunProtect'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); - } - // Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> - // set sunProtect again - else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown && shutterSettings[s].currentAction == '') { - shutterSettings[s].currentAction = 'sunProtect'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' HeightDownSun:' + heightDownSun); - } - } - } else { - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + const driveDelayUpSleep = adapter.config.driveDelayUpAstro != 0 ? adapter.config.driveDelayUpAstro * 1000 : 20; + const vRound = adapter.config.shutterStateRound; + + await sleep(2000); + if (shutterSettings) { + const result = shutterSettings.filter((/** @type {{ enabled: boolean; }} */ d) => d.enabled === true); // Filter enabled + + if (elevation > adapter.config.sunProtEndElevation) { + for (const i in result) { + for (const s in shutterSettings) { + if (shutterSettings[s].shutterName == result[i].shutterName) { + let resultDirectionRangeMinus = 0; + let resultDirectionRangePlus = 0; + let convertShutter = false; + let heightDownSun = shutterSettings[s].heightDownSun; + + const nameDevice = shutterSettings[s].shutterName.replace(/[.;, ]/g, '_'); + + if (parseFloat(shutterSettings[s].heightDown) < parseFloat(shutterSettings[s].heightUp)) { + convertShutter = false; + } else if (parseFloat(shutterSettings[s].heightDown) > parseFloat(shutterSettings[s].heightUp)) { + convertShutter = true; } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].triggerAction != 'sunProtect' && shutterSettings[s].triggerAction != 'OpenInSunProtect' && shutterSettings[s].triggerAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); - - if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp && shutterSettings[s].triggerAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas') { - shutterSettings[s].triggerHeight = parseFloat(heightDownSun); - shutterSettings[s].triggerAction = 'sunProtect'; - - adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + const pendingAlarm = await checkPendingAlarm(adapter, shutterSettings[s]); + + const _autoSunState = await adapter.getStateAsync(`shutters.autoSun.${nameDevice}`).catch((e) => adapter.log.warn(e)); + + if (_autoSunState && _autoSunState.val === true) { + let currentValue = ''; + let _triggerState; + let mustValue = ''; + let mustValueTilted = ''; + + switch (shutterSettings[s].type) { + + // +++++++++++++++++ sunprotect with in/outside temperature and Lightsensor +++++++++++++++ + + case 'in- & outside temperature': // in- & outside temperature + _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; + mustValue = ('' + shutterSettings[s].triggerState); + mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); + + if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { + currentValue = ('' + _triggerState.val); + } + + if ((currentValue === mustValue || currentValue === mustValueTilted) && shutterSettings[s].tempSensor != '' || + (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off' && shutterSettings[s].tempSensor != '') || + (shutterSettings[s].triggerID == '' && shutterSettings[s].tempSensor != '')) { + + let insideTemp = 0; + let outsideTemp = 0; + let sunLight = 0; + + const _insideTempState = shutterSettings[s].tempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].tempSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _insideTempState != undefined && _insideTempState != null && _insideTempState.val != undefined) { + insideTemp = parseFloat(_insideTempState.val); + } + + const _outsideTempState = shutterSettings[s].outsideTempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].outsideTempSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _outsideTempState != undefined && _outsideTempState != null && _outsideTempState.val != undefined) { + outsideTemp = parseFloat(_outsideTempState.val); + } + + const _sunLight = shutterSettings[s].lightSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].lightSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _sunLight != undefined && _sunLight != null && _sunLight.val != undefined) { + sunLight = parseFloat(_sunLight.val); + } + + // heatProtection + if (shutterSettings[s].heatProtection == true && + shutterSettings[s].tempHeatProtection < outsideTemp && + shutterSettings[s].currentHeight != shutterSettings[s].heightDown) { + + shutterSettings[s].currentAction = shutterSettings[s].currentAction == 'sunProtect' ? '' : shutterSettings[s].currentAction; + heightDownSun = shutterSettings[s].heightDown; + adapter.log.debug(`Heat Protection for ${shutterSettings[s].shutterName} is active`); + adapter.log.debug(`currentAction ${shutterSettings[s].currentAction}`); + + } else { + heightDownSun = shutterSettings[s].heightDownSun; + } + + if (shutterSettings[s].sunProtectEndtimerid != '' && + shutterSettings[s].sunProtectEndtimerid != '0' && + shutterSettings[s].lightSensor != '' && + shutterSettings[s].valueLight < sunLight) { + + adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); + clearTimeout(shutterSettings[s].sunProtectEndtimerid); + shutterSettings[s].sunProtectEndtimerid = ''; + } + + if (currentValue === mustValue || currentValue === mustValueTilted || + (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || + (shutterSettings[s].triggerID == '')) { + + if (insideTemp > shutterSettings[s].tempInside) { + if (shutterSettings[s].tempOutside < outsideTemp && + (shutterSettings[s].lightSensor != '' && + shutterSettings[s].valueLight < sunLight || + shutterSettings[s].lightSensor == '') && + shutterSettings[s].currentAction != 'sunProtect' && + shutterSettings[s].currentAction != 'OpenInSunProtect' && + shutterSettings[s].currentAction != 'Manu_Mode') { + + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); + + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && + convertShutter == false) || + (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && + convertShutter == true)) && + Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && + (shutterSettings[s].currentHeight == shutterSettings[s].heightUp || + (shutterSettings[s].heatProtection == true && + shutterSettings[s].tempHeatProtection < outsideTemp))) { + + shutterSettings[s].currentAction = 'sunProtect'; + shutterSettings[s].lastAutoAction = 'down_Sunprotect'; + shutterSettings[s].currentHeight = heightDownSun; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #410'); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); + adapter.log.debug('Temperature inside: ' + insideTemp + ' > ' + shutterSettings[s].tempInside + ' AND ( Temperatur outside: ' + outsideTemp + ' > ' + shutterSettings[s].tempOutside + ' AND Light: ' + sunLight + ' > ' + shutterSettings[s].valueLight + ' )'); + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%'); + } + // Shutter closed. Set currentAction = sunProtect when sunProtect starts => + // If shutter is opened automatically it can be opened in height heightDownSun directly + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].heightDown) && + Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && + shutterSettings[s].currentHeight != shutterSettings[s].heightUp && + shutterSettings[s].currentAction != 'down' && + shutterSettings[s].currentAction != 'middle' && + shutterSettings[s].currentAction != 'Xmas' && + shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! + + shutterSettings[s].currentAction = 'OpenInSunProtect'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); + } + //Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> + // set sunProtect again + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) && + Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && + shutterSettings[s].currentHeight != shutterSettings[s].heightUp && + shutterSettings[s].currentHeight != shutterSettings[s].heightDown && + shutterSettings[s].currentAction == '') { + + shutterSettings[s].currentAction = 'sunProtect'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' HeightDownSun:' + heightDownSun); + } + } + } else { + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + } + } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + if (insideTemp > shutterSettings[s].tempInside) { + if (shutterSettings[s].tempOutside < outsideTemp && + (shutterSettings[s].lightSensor != '' && + shutterSettings[s].valueLight < sunLight || + shutterSettings[s].lightSensor == '') && + shutterSettings[s].triggerAction != 'sunProtect' && + shutterSettings[s].triggerAction != 'OpenInSunProtect' && + shutterSettings[s].triggerAction != 'Manu_Mode') { + + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp + ' AND triggerAction:' + shutterSettings[s].triggerAction + ' != down '); + + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && + convertShutter == false) || + (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && + convertShutter == true)) && + Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && + shutterSettings[s].currentHeight == shutterSettings[s].heightUp && + shutterSettings[s].triggerAction != 'down' && + shutterSettings[s].currentAction != 'middle' && + shutterSettings[s].currentAction != 'Xmas') { + + shutterSettings[s].triggerHeight = parseFloat(heightDownSun); + shutterSettings[s].triggerAction = 'sunProtect'; + + adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + } + + } + } else { + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + } + } + } + } + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { + const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); + const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); + const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); + + if (shutterSettings[s].sunProtectEndtimerid === '' && + shutterSettings[s].lightSensor != '' && + parseFloat(hysteresisLight) > sunLight && + (shutterSettings[s].currentAction == 'sunProtect' || (shutterSettings[s].currentAction == 'triggered' && shutterSettings[s].lastAutoAction == 'down_Sunprotect')) && + shutterSettings[s].KeepSunProtect === false) { + + adapter.log.debug('#1 Started sunprotect end delay for ' + shutterSettings[s].shutterName); + shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { + shutterSettings[s].sunProtectEndtimerid = '0'; + }, shutterSettings[s].sunProtectEndDely * 60000, i); + } + + if (insideTemp < parseFloat(hysteresisInside) || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { + + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].currentAction = 'up'; + shutterSettings[s].currentHeight = shutterSettings[s].heightUp; + shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #411'); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); + adapter.log.debug('Temperature inside: ' + insideTemp + ' < ' + hysteresisInside + ' OR ( Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight + ' )'); + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%') + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].sunProtectEndtimerid = '' + shutterSettings[s].currentAction = 'none'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); + const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); + const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); + + if (shutterSettings[s].sunProtectEndtimerid === '' && + shutterSettings[s].lightSensor != '' && + parseFloat(hysteresisLight) > sunLight && + (shutterSettings[s].currentAction == 'sunProtect' || (shutterSettings[s].currentAction == 'triggered' && shutterSettings[s].lastAutoAction == 'down_Sunprotect')) && + shutterSettings[s].KeepSunProtect === false) { + adapter.log.debug('#2 Started sunprotect end delay for ' + shutterSettings[s].shutterName); + shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { + shutterSettings[s].sunProtectEndtimerid = '0'; + }, shutterSettings[s].sunProtectEndDely * 60000, i); + } + + if (insideTemp < parseFloat(hysteresisInside) || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { + + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].triggerAction = 'up'; + + adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); + adapter.log.debug('Temperature inside: ' + insideTemp + ' < ' + hysteresisInside + ' OR ( Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight + ' )'); + adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].sunProtectEndtimerid = '' + shutterSettings[s].triggerAction = 'none'; + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + } + } + } + } + await sleep(driveDelayUpSleep); + break; + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + // +++++++++++++++++ sunprotect with in/outside temperature, Lightsensor and direction +++++++++++++++ + + case 'in- & outside temperature and direction': // in- & outside temperature and direction + resultDirectionRangeMinus = parseInt(shutterSettings[s].direction) - parseInt(shutterSettings[s].directionRange); + resultDirectionRangePlus = parseInt(shutterSettings[s].direction) + parseInt(shutterSettings[s].directionRange); + + _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; + mustValue = ('' + shutterSettings[s].triggerState); + mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); + + if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { + currentValue = ('' + _triggerState.val); + } + + if ((currentValue === mustValue || currentValue === mustValueTilted) && shutterSettings[s].tempSensor != '' || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off' && shutterSettings[s].tempSensor != '') || (shutterSettings[s].triggerID == '' && shutterSettings[s].tempSensor != '')) { + let insideTemp = 0; + let outsideTemp = 0; + let sunLight = 0; + + const _insideTempState = shutterSettings[s].tempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].tempSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _insideTempState != undefined && _insideTempState != null && _insideTempState.val != undefined) { + insideTemp = parseFloat(_insideTempState.val); + } + + const _outsideTempState = shutterSettings[s].outsideTempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].outsideTempSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _outsideTempState != undefined && _outsideTempState != null && _outsideTempState.val != undefined) { + outsideTemp = parseFloat(_outsideTempState.val); + } + + // heatProtection + if (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown) { + shutterSettings[s].currentAction = shutterSettings[s].currentAction == 'sunProtect' ? '' : shutterSettings[s].currentAction; + heightDownSun = shutterSettings[s].heightDown; + adapter.log.debug(`Heat Protection for ${shutterSettings[s].shutterName} is active`); + } else { + heightDownSun = shutterSettings[s].heightDownSun; + } + + const _sunLight = shutterSettings[s].lightSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].lightSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _sunLight != undefined && _sunLight != null && _sunLight.val != undefined) { + sunLight = parseFloat(_sunLight.val); + } + + if (shutterSettings[s].sunProtectEndtimerid != '' && shutterSettings[s].sunProtectEndtimerid != '0' && shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight) { + adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); + clearTimeout(shutterSettings[s].sunProtectEndtimerid); + shutterSettings[s].sunProtectEndtimerid = ''; + } + + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || (shutterSettings[s].triggerID == '')) { + if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth && insideTemp > shutterSettings[s].tempInside) { + if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].currentAction != 'sunProtect' && shutterSettings[s].currentAction != 'OpenInSunProtect' && shutterSettings[s].currentAction != 'Manu_Mode') { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); + + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || + (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && + (shutterSettings[s].currentHeight == shutterSettings[s].heightUp || (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp))) { + + shutterSettings[s].currentAction = 'sunProtect'; + shutterSettings[s].currentHeight = heightDownSun; + shutterSettings[s].lastAutoAction = 'down_Sunprotect'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #412'); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); + adapter.log.debug('Temperature inside: ' + insideTemp + ' > ' + shutterSettings[s].tempInside + ' AND ( Temperatur outside: ' + outsideTemp + ' > ' + shutterSettings[s].tempOutside + ' AND Light: ' + sunLight + ' > ' + shutterSettings[s].valueLight + ' )'); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%'); + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%') + } + // Shutter closed. Set currentAction = sunProtect when sunProtect starts => + // If shutter is opened automatically it can be opened in height heightDownSun directly + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].heightDown) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas' && shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! + shutterSettings[s].currentAction = 'OpenInSunProtect'; + adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); + } + // Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> + // set sunProtect again + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown && shutterSettings[s].currentAction == '') { + shutterSettings[s].currentAction = 'sunProtect'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' HeightDownSun:' + heightDownSun); + } + } + } else { + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + } + } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth && insideTemp > shutterSettings[s].tempInside) { + if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].triggerAction != 'sunProtect' && shutterSettings[s].triggerAction != 'OpenInSunProtect' && shutterSettings[s].triggerAction != 'Manu_Mode') { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp + ' AND triggerAction:' + shutterSettings[s].triggerAction + ' != down '); + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp && shutterSettings[s].triggerAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas') { + shutterSettings[s].triggerHeight = parseFloat(heightDownSun); + shutterSettings[s].triggerAction = 'sunProtect'; + + adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + } + } + } else { + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + } + } + } + } + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { + const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); + const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); + const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); + + if (shutterSettings[s].sunProtectEndtimerid === '' && + shutterSettings[s].lightSensor != '' && + parseFloat(hysteresisLight) > sunLight && + (shutterSettings[s].currentAction == 'sunProtect' || (shutterSettings[s].currentAction == 'triggered' && shutterSettings[s].lastAutoAction == 'down_Sunprotect')) && + shutterSettings[s].KeepSunProtect === false) { + adapter.log.debug('#3 Started sunprotect end delay for ' + shutterSettings[s].shutterName); + shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { + shutterSettings[s].sunProtectEndtimerid = '0'; + }, shutterSettings[s].sunProtectEndDely * 60000, i); + } + + + if (insideTemp < parseFloat(hysteresisInside) || (resultDirectionRangePlus) < azimuth || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { + + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].currentAction = 'up'; + shutterSettings[s].currentHeight = shutterSettings[s].heightUp; + shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #413'); + + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); + adapter.log.debug('Range: ' + resultDirectionRangePlus + ' < ' + azimuth + ' OR Temperature inside: ' + insideTemp + ' < ' + hysteresisInside + ' OR ( Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight + ')'); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + shutterSettings[s].heightUp + '%'); + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].sunProtectEndtimerid = '' + shutterSettings[s].currentAction = 'none'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); + const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); + const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); + + if (shutterSettings[s].sunProtectEndtimerid === '' && + shutterSettings[s].lightSensor != '' && + parseFloat(hysteresisLight) > sunLight && + (shutterSettings[s].currentAction == 'sunProtect' || (shutterSettings[s].currentAction == 'triggered' && shutterSettings[s].lastAutoAction == 'down_Sunprotect')) && + shutterSettings[s].KeepSunProtect === false) { + adapter.log.debug('#4 Started sunprotect end delay for ' + shutterSettings[s].shutterName); + shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { + shutterSettings[s].sunProtectEndtimerid = '0'; + }, shutterSettings[s].sunProtectEndDely * 60000, i); + } + + if (insideTemp < parseFloat(hysteresisInside) || (resultDirectionRangePlus) < azimuth || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { + + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].triggerAction = 'up'; + + adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); + adapter.log.debug('Temperature inside: ' + insideTemp + ' < ' + hysteresisInside + ' OR ( Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight + ' )'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].triggerAction = 'none'; + + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } + } + } + } + await sleep(driveDelayUpSleep); + break; + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + // +++++++++++++++++ sunprotect with outside temperature, Lightsensor and direction +++++++++++++++ + + case 'outside temperature and direction': //outside temperature and direction + resultDirectionRangeMinus = parseInt(shutterSettings[s].direction) - parseInt(shutterSettings[s].directionRange); + resultDirectionRangePlus = parseInt(shutterSettings[s].direction) + parseInt(shutterSettings[s].directionRange); + + _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; + mustValue = ('' + shutterSettings[s].triggerState); + mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); + + if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { + currentValue = ('' + _triggerState.val); + } + + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off') || (shutterSettings[s].triggerID == '')) { + let outsideTemp = 0; + let sunLight = 0; + + const _outsideTempState = shutterSettings[s].outsideTempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].outsideTempSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _outsideTempState != undefined && _outsideTempState != null && _outsideTempState.val != undefined) { + outsideTemp = parseFloat(_outsideTempState.val); + } + + // heatProtection + if (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown) { + shutterSettings[s].currentAction = shutterSettings[s].currentAction == 'sunProtect' ? '' : shutterSettings[s].currentAction; + heightDownSun = shutterSettings[s].heightDown; + adapter.log.debug(`Heat Protection for ${shutterSettings[s].shutterName} is active`); + } else { + heightDownSun = shutterSettings[s].heightDownSun; + } + + const _sunLight = shutterSettings[s].lightSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].lightSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _sunLight != undefined && _sunLight != null && _sunLight.val != undefined) { + sunLight = parseFloat(_sunLight.val); + } + + if (shutterSettings[s].sunProtectEndtimerid != '' && shutterSettings[s].sunProtectEndtimerid != '0' && shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight) { + adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); + clearTimeout(shutterSettings[s].sunProtectEndtimerid); + shutterSettings[s].sunProtectEndtimerid = ''; + } + + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || (shutterSettings[s].triggerID == '')) { + if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth) { + if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].currentAction != 'sunProtect' && shutterSettings[s].currentAction != 'OpenInSunProtect' && shutterSettings[s].currentAction != 'Manu_Mode') { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); + + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || + (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && + (shutterSettings[s].currentHeight == shutterSettings[s].heightUp || (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp))) { + + shutterSettings[s].currentAction = 'sunProtect'; + shutterSettings[s].currentHeight = heightDownSun; + shutterSettings[s].lastAutoAction = 'down_Sunprotect'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #414'); + + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); + adapter.log.debug('Temperatur outside: ' + outsideTemp + ' > ' + shutterSettings[s].tempOutside + ' AND Light: ' + sunLight + ' > ' + shutterSettings[s].valueLight); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%') + } + // Shutter closed. Set currentAction = sunProtect when sunProtect starts => + // If shutter is opened automatically it can be opened in height heightDownSun directly + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].heightDown) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas' && shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! + shutterSettings[s].currentAction = 'OpenInSunProtect'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); + } + // Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> + // set sunProtect again + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown && shutterSettings[s].currentAction == '') { + shutterSettings[s].currentAction = 'sunProtect'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' HeightDownSun:' + heightDownSun); + } + } + } else { + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + } + } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth) { + if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].triggerAction != 'sunProtect' && shutterSettings[s].triggerAction != 'OpenInSunProtect' && shutterSettings[s].triggerAction != 'Manu_Mode') { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp && shutterSettings[s].triggerAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas') { + shutterSettings[s].triggerHeight = parseFloat(heightDownSun); + shutterSettings[s].triggerAction = 'sunProtect'; + + adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + } + + } + } else { + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + } + } + } + } + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { + const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); + const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); + + if (shutterSettings[s].sunProtectEndtimerid === '' && + shutterSettings[s].lightSensor != '' && + parseFloat(hysteresisLight) > sunLight && + (shutterSettings[s].currentAction == 'sunProtect' || (shutterSettings[s].currentAction == 'triggered' && shutterSettings[s].lastAutoAction == 'down_Sunprotect')) && + shutterSettings[s].KeepSunProtect === false) { + adapter.log.debug('#5 Started sunprotect end delay for ' + shutterSettings[s].shutterName); + shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { + shutterSettings[s].sunProtectEndtimerid = '0'; + }, shutterSettings[s].sunProtectEndDely * 60000, i); + } + + if ((resultDirectionRangePlus) < azimuth || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].currentAction = 'up'; + shutterSettings[s].currentHeight = shutterSettings[s].heightUp; + shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #415'); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); + adapter.log.debug('Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight); + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + shutterSettings[s].heightUp + '%') + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].currentAction = 'none'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); + const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); + + if (shutterSettings[s].sunProtectEndtimerid === '' && + shutterSettings[s].lightSensor != '' && + parseFloat(hysteresisLight) > sunLight && + (shutterSettings[s].currentAction == 'sunProtect' || (shutterSettings[s].currentAction == 'triggered' && shutterSettings[s].lastAutoAction == 'down_Sunprotect')) && + shutterSettings[s].KeepSunProtect === false) { + adapter.log.debug('#6 Started sunprotect end delay for ' + shutterSettings[s].shutterName); + shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { + shutterSettings[s].sunProtectEndtimerid = '0'; + }, shutterSettings[s].sunProtectEndDely * 60000, i); + } + + if ((resultDirectionRangePlus) < azimuth || (parseFloat(hysteresisOutside) > outsideTemp || shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp && shutterSettings[s].lightSensor == '')) { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].triggerAction = 'up'; + + adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].sunProtectEndtimerid = '' + shutterSettings[s].triggerAction = 'none'; + + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } + } + } + } + await sleep(driveDelayUpSleep); + break; + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + // ++++++++++++++++++++++++++++++ sunprotect with direction ++++++++++++++++++++++++++++++++++ + + case 'only direction': //only direction + resultDirectionRangeMinus = parseInt(shutterSettings[s].direction) - parseInt(shutterSettings[s].directionRange); + resultDirectionRangePlus = parseInt(shutterSettings[s].direction) + parseInt(shutterSettings[s].directionRange); + + _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; + mustValue = ('' + shutterSettings[s].triggerState); + mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); + + if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { + currentValue = ('' + _triggerState.val); + } + + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off') || (shutterSettings[s].triggerID == '')) { + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || (shutterSettings[s].triggerID == '')) { + if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth && shutterSettings[s].currentAction != 'sunProtect' && shutterSettings[s].currentAction != 'OpenInSunProtect' && shutterSettings[s].currentAction != 'Manu_Mode') { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp) { + shutterSettings[s].currentAction = 'sunProtect'; + shutterSettings[s].currentHeight = heightDownSun; + shutterSettings[s].lastAutoAction = 'down_Sunprotect'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #416'); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); + adapter.log.debug('RangeMinus: ' + resultDirectionRangeMinus + ' < ' + azimuth + 'RangePlus: ' + resultDirectionRangePlus + ' > ' + azimuth); + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%'); + } + // Shutter closed. Set currentAction = sunProtect when sunProtect starts => + // If shutter is opened automatically it can be opened in height heightDownSun directly + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].heightDown) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas' && shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! + shutterSettings[s].currentAction = 'OpenInSunProtect'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); + } + // Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> + // set sunProtect again + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown && shutterSettings[s].currentAction == '') { + shutterSettings[s].currentAction = 'sunProtect'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' HeightDownSun:' + heightDownSun); + } + } + } else { + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + if ((resultDirectionRangeMinus) < azimuth && (resultDirectionRangePlus) > azimuth && shutterSettings[s].triggerAction != 'sunProtect' && shutterSettings[s].triggerAction != 'OpenInSunProtect' && shutterSettings[s].triggerAction != 'Manu_Mode') { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp && shutterSettings[s].triggerAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas') { + shutterSettings[s].triggerHeight = parseFloat(heightDownSun); + shutterSettings[s].triggerAction = 'sunProtect'; + + adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + } + } + } else { + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + } + + } + } + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { + if ((resultDirectionRangePlus) < azimuth) { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].currentAction = 'up'; + shutterSettings[s].currentHeight = shutterSettings[s].heightUp; + shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #417'); + + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); + adapter.log.debug('Range: ' + resultDirectionRangePlus + ' < ' + azimuth); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + shutterSettings[s].heightUp + '%') + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].currentAction = 'none'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + if ((resultDirectionRangePlus) < azimuth) { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].triggerAction = 'up'; + + adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].triggerAction = 'none'; + + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } + } + } + } + await sleep(driveDelayUpSleep); + break; + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + // ++++++++++++++++++++++++ sunprotect with outside temperature and Lightsensor +++++++++++++++++++++++ + + case 'only outside temperature': //only outside temperature + _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; + mustValue = ('' + shutterSettings[s].triggerState); + mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); + + if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { + currentValue = ('' + _triggerState.val); + } + + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off') || (shutterSettings[s].triggerID == '')) { + let outsideTemp = 0; + let sunLight = 0; + + const _outsideTempState = shutterSettings[s].outsideTempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].outsideTempSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _outsideTempState != undefined && _outsideTempState != null && _outsideTempState.val != undefined) { + outsideTemp = parseFloat(_outsideTempState.val); + } + + // heatProtection + if (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown) { + shutterSettings[s].currentAction = shutterSettings[s].currentAction == 'sunProtect' ? '' : shutterSettings[s].currentAction; + heightDownSun = shutterSettings[s].heightDown; + adapter.log.debug(`Heat Protection for ${shutterSettings[s].shutterName} is active`); + } else { + heightDownSun = shutterSettings[s].heightDownSun; + } + + const _sunLight = shutterSettings[s].lightSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].lightSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _sunLight != undefined && _sunLight != null && _sunLight.val != undefined) { + sunLight = parseFloat(_sunLight.val); + } + + if (shutterSettings[s].sunProtectEndtimerid != '' && shutterSettings[s].sunProtectEndtimerid != '0' && shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight) { + adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); + clearTimeout(shutterSettings[s].sunProtectEndtimerid); + shutterSettings[s].sunProtectEndtimerid = ''; + } + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || (shutterSettings[s].triggerID == '')) { + if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].currentAction != 'sunProtect' && shutterSettings[s].currentAction != 'OpenInSunProtect' && shutterSettings[s].currentAction != 'Manu_Mode') { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); + + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || + (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && + (shutterSettings[s].currentHeight == shutterSettings[s].heightUp || (shutterSettings[s].heatProtection == true && shutterSettings[s].tempHeatProtection < outsideTemp))) { + + shutterSettings[s].currentAction = 'sunProtect'; + shutterSettings[s].currentHeight = heightDownSun; + shutterSettings[s].lastAutoAction = 'down_Sunprotect'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #418'); + + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); + adapter.log.debug('Temperature outside: ' + outsideTemp + ' > ' + shutterSettings[s].tempOutside + ' AND Light: ' + sunLight + ' > ' + shutterSettings[s].valueLight); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%'); + } + // Shutter closed. Set currentAction = sunProtect when sunProtect starts => + // If shutter is opened automatically it can be opened in height heightDownSun directly + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].heightDown) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas' && shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! + shutterSettings[s].currentAction = 'OpenInSunProtect'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); + } + // Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> + // set sunProtect again + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown && shutterSettings[s].currentAction == '') { + shutterSettings[s].currentAction = 'sunProtect'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' HeightDownSun:' + heightDownSun); + } + } + } else { + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + if (shutterSettings[s].tempOutside < outsideTemp && (shutterSettings[s].lightSensor != '' && shutterSettings[s].valueLight < sunLight || shutterSettings[s].lightSensor == '') && shutterSettings[s].triggerAction != 'sunProtect' && shutterSettings[s].triggerAction != 'OpenInSunProtect' && shutterSettings[s].triggerAction != 'Manu_Mode') { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); + + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp && shutterSettings[s].triggerAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas') { + shutterSettings[s].triggerHeight = parseFloat(heightDownSun); + shutterSettings[s].triggerAction = 'sunProtect'; + + adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + } + } + } else { + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + } + + } + } + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { + + const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); + const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); + + if (shutterSettings[s].sunProtectEndtimerid === '' && + shutterSettings[s].lightSensor != '' && + parseFloat(hysteresisLight) > sunLight && + (shutterSettings[s].currentAction == 'sunProtect' || (shutterSettings[s].currentAction == 'triggered' && shutterSettings[s].lastAutoAction == 'down_Sunprotect')) && + shutterSettings[s].KeepSunProtect === false) { + adapter.log.debug('#7 Started sunprotect end delay for ' + shutterSettings[s].shutterName); + shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { + shutterSettings[s].sunProtectEndtimerid = '0'; + }, shutterSettings[s].sunProtectEndDely * 60000, i); + } + + if ((shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp)) { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].currentAction = 'up'; + shutterSettings[s].currentHeight = shutterSettings[s].heightUp; + shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #419'); + + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); + adapter.log.debug('Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + shutterSettings[s].heightUp + '%'); + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].sunProtectEndtimerid = '' + shutterSettings[s].currentAction = 'none'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); + const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); + + if (shutterSettings[s].sunProtectEndtimerid === '' && + shutterSettings[s].lightSensor != '' && + parseFloat(hysteresisLight) > sunLight && + (shutterSettings[s].currentAction == 'sunProtect' || (shutterSettings[s].currentAction == 'triggered' && shutterSettings[s].lastAutoAction == 'down_Sunprotect')) && + shutterSettings[s].KeepSunProtect === false) { + adapter.log.debug('#8 Started sunprotect end delay for ' + shutterSettings[s].shutterName); + shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { + shutterSettings[s].sunProtectEndtimerid = '0'; + }, shutterSettings[s].sunProtectEndDely * 60000, i); + } + + if ((shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp)) { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].triggerAction = 'up'; + shutterSettings[s].sunProtectEndtimerid = ''; + + adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].sunProtectEndtimerid = '' + shutterSettings[s].triggerAction = 'none'; + shutterSettings[s].sunProtectEndtimerid = ''; + + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } + } + } + } + await sleep(driveDelayUpSleep); + break; + + ////////////////////////////////////////////////////////////////////////////////////////////////////// + + // ++++++++++++++++++++++++++++ sunprotect with inside temperature ++++++++++++++++++++++++++++++++++ + + case 'only inside temperature': //only inside temperature + _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; + mustValue = ('' + shutterSettings[s].triggerState); + mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); + + if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { + currentValue = ('' + _triggerState.val); + } + + if ((currentValue === mustValue || currentValue === mustValueTilted) && shutterSettings[s].tempSensor != '' || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off' && shutterSettings[s].tempSensor != '') || (shutterSettings[s].triggerID == '' && shutterSettings[s].tempSensor != '')) { + let insideTemp = 0; + + const _insideTempState = shutterSettings[s].tempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].tempSensor).catch((e) => adapter.log.warn(e)) : null; + if (typeof _insideTempState != undefined && _insideTempState != null && _insideTempState.val != undefined) { + insideTemp = parseFloat(_insideTempState.val); + } + + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || (shutterSettings[s].triggerID == '')) { + if (insideTemp > shutterSettings[s].tempInside && shutterSettings[s].currentAction != 'sunProtect' && shutterSettings[s].currentAction != 'OpenInSunProtect' && shutterSettings[s].currentAction != 'Manu_Mode') { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp) { + shutterSettings[s].currentAction = 'sunProtect'; + shutterSettings[s].currentHeight = heightDownSun; + shutterSettings[s].lastAutoAction = 'down_Sunprotect'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #420'); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%'); + } + // Shutter closed. Set currentAction = sunProtect when sunProtect starts => + // If shutter is opened automatically it can be opened in height heightDownSun directly + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].heightDown) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas' && shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! + shutterSettings[s].currentAction = 'OpenInSunProtect'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); + } + // Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> + // set sunProtect again + else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown && shutterSettings[s].currentAction == '') { + shutterSettings[s].currentAction = 'sunProtect'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' HeightDownSun:' + heightDownSun); + } + } + } else { + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + if (insideTemp > shutterSettings[s].tempInside && shutterSettings[s].triggerAction != 'sunProtect' && shutterSettings[s].triggerAction != 'OpenInSunProtect' && shutterSettings[s].triggerAction != 'Manu_Mode') { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); + if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp && shutterSettings[s].triggerAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas') { + shutterSettings[s].triggerAction = 'sunProtect'; + shutterSettings[s].triggerHeight = parseFloat(heightDownSun); + + adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + } + } + } else { + shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); + shutterSettings[s].alarmTriggerAction = 'sunProtect'; + + adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + } + } + } + if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { + const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); + + if (insideTemp < parseFloat(hysteresisInside)) { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].currentAction = 'up'; + shutterSettings[s].currentHeight = shutterSettings[s].heightUp; + shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #421'); + + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); + adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + shutterSettings[s].heightUp + '%'); + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].currentAction = 'none'; + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } + } + } + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); + + if (insideTemp < parseFloat(hysteresisInside)) { + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].triggerAction = 'up'; + + adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + } + else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { + shutterSettings[s].triggerAction = 'none'; + + adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'up'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } + } + } + } + await sleep(driveDelayUpSleep); + break; } - } - } else { - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; - - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); } - } } - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { - - const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); - const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); - - if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { - adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); - shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { - shutterSettings[s].sunProtectEndtimerid = '0'; - }, shutterSettings[s].sunProtectEndDely * 60000, i); - } - - if ((shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp)) { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].currentAction = 'up'; - shutterSettings[s].currentHeight = shutterSettings[s].heightUp; - shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #419'); - - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); - adapter.log.debug('Temperature outside: ' + outsideTemp + ' < ' + hysteresisOutside + ' OR Light: ' + sunLight + ' < ' + hysteresisLight); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + shutterSettings[s].heightUp + '%'); - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].sunProtectEndtimerid = '' - shutterSettings[s].currentAction = 'none'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - const hysteresisOutside = (((100 - shutterSettings[s].hysteresisOutside) / 100) * shutterSettings[s].tempOutside).toFixed(2); - const hysteresisLight = (((100 - shutterSettings[s].hysteresisLight) / 100) * shutterSettings[s].valueLight).toFixed(2); - - if (shutterSettings[s].sunProtectEndtimerid === '' && shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false) { - adapter.log.debug('Started sunprotect end delay for ' + shutterSettings[s].shutterName); - shutterSettings[s].sunProtectEndtimerid = setTimeout(async function () { - shutterSettings[s].sunProtectEndtimerid = '0'; - }, shutterSettings[s].sunProtectEndDely * 60000, i); - } - - if ((shutterSettings[s].lightSensor != '' && parseFloat(hysteresisLight) > sunLight && shutterSettings[s].sunProtectEndtimerid === '0') || (parseFloat(hysteresisOutside) > outsideTemp)) { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].triggerAction = 'up'; - shutterSettings[s].sunProtectEndtimerid = ''; - - adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].sunProtectEndtimerid = '' - shutterSettings[s].triggerAction = 'none'; - shutterSettings[s].sunProtectEndtimerid = ''; - - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } - } - } - } - await sleep(driveDelayUpSleep); - break; - - ////////////////////////////////////////////////////////////////////////////////////////////////////// - - // ++++++++++++++++++++++++++++ sunprotect with inside temperature ++++++++++++++++++++++++++++++++++ - - case 'only inside temperature': //only inside temperature - _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; - mustValue = ('' + shutterSettings[s].triggerState); - mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); - - if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { - currentValue = ('' + _triggerState.val); - } - - if ((currentValue === mustValue || currentValue === mustValueTilted) && shutterSettings[s].tempSensor != '' || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'off' && shutterSettings[s].tempSensor != '') || (shutterSettings[s].triggerID == '' && shutterSettings[s].tempSensor != '')) { - let insideTemp = 0; - - const _insideTempState = shutterSettings[s].tempSensor != '' ? await adapter.getForeignStateAsync(shutterSettings[s].tempSensor).catch((e) => adapter.log.warn(e)) : null; - if (typeof _insideTempState != undefined && _insideTempState != null && _insideTempState.val != undefined) { - insideTemp = parseFloat(_insideTempState.val); - } - - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyUp') || (shutterSettings[s].triggerID == '')) { - if (insideTemp > shutterSettings[s].tempInside && shutterSettings[s].currentAction != 'sunProtect' && shutterSettings[s].currentAction != 'OpenInSunProtect' && shutterSettings[s].currentAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp) { - shutterSettings[s].currentAction = 'sunProtect'; - shutterSettings[s].currentHeight = heightDownSun; - shutterSettings[s].lastAutoAction = 'down_Sunprotect'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(heightDownSun), nameDevice, 'Sunprotect #420'); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is active'); - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + heightDownSun + '%'); - } - // Shutter closed. Set currentAction = sunProtect when sunProtect starts => - // If shutter is opened automatically it can be opened in height heightDownSun directly - else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].heightDown) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas' && shutterSettings[s].firstCompleteUp == true) { //check currentAction!=down here. If shutter is already closed sunProtect must not be set. Otherwise shutter will be opened again when sunProtect ends! - shutterSettings[s].currentAction = 'OpenInSunProtect'; - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); - - adapter.log.debug('Set sunprotect mode for ' + shutterSettings[s].shutterName + '. Currently closed. Set to sunprotect if shutter will be opened automatically'); - } - // Shutter is in position = sunProtect. Maybe restart of adapter. sunProtect not set -> - // set sunProtect again - else if (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight != shutterSettings[s].heightUp && shutterSettings[s].currentHeight != shutterSettings[s].heightDown && shutterSettings[s].currentAction == '') { - shutterSettings[s].currentAction = 'sunProtect'; + } + } + clearTimeout(timerSleep); + return (shutterSettings); + } + } - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - adapter.log.debug(shutterSettings[s].shutterName + ': Shutter is in position sunProtect. Reset mode sunProtect to cancel sunProtect automatically. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' HeightDownSun:' + heightDownSun); - } - } - } else { - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; + // +++++++++++++++++ End of sunprotect with Elevationslimit +++++++++++++++ - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - if (insideTemp > shutterSettings[s].tempInside && shutterSettings[s].triggerAction != 'sunProtect' && shutterSettings[s].triggerAction != 'OpenInSunProtect' && shutterSettings[s].triggerAction != 'Manu_Mode') { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + if (shutterSettings) { + const result = shutterSettings.filter((/** @type {{ enabled: boolean; }} */ d) => d.enabled === true); - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - adapter.log.debug(shutterSettings[s].shutterName + ': Check basis for sunprotect. Height:' + Math.round(_shutterState.val / vRound) * vRound + ' > HeightDownSun: ' + heightDownSun + ' AND Height:' + Math.round(_shutterState.val / vRound) * vRound + ' == currentHeight:' + shutterSettings[s].currentHeight + ' AND currentHeight:' + shutterSettings[s].currentHeight + ' == heightUp:' + shutterSettings[s].heightUp); - if (((Math.round(parseFloat(_shutterState.val) / vRound) * vRound > parseFloat(heightDownSun) && convertShutter == false) || (Math.round(parseFloat(_shutterState.val) / vRound) * vRound < parseFloat(heightDownSun) && convertShutter == true)) && Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight) && shutterSettings[s].currentHeight == shutterSettings[s].heightUp && shutterSettings[s].triggerAction != 'down' && shutterSettings[s].currentAction != 'middle' && shutterSettings[s].currentAction != 'Xmas') { - shutterSettings[s].triggerAction = 'sunProtect'; - shutterSettings[s].triggerHeight = parseFloat(heightDownSun); + const sunProtEndStart = parseInt(adapter.config.sunProtEndElevation); + const sunProtEndStop = (adapter.config.sunProtEndElevation - 1); - adapter.log.info(' Will sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + for (const i in result) { + for (const s in shutterSettings) { + if (shutterSettings[s].shutterName == result[i].shutterName) { + if (elevation <= sunProtEndStart && elevation >= sunProtEndStop && (shutterSettings[s].currentAction == 'sunProtect' || shutterSettings[s].currentAction == 'manu_sunProtect')) { + const nameDevice = shutterSettings[s].shutterName.replace(/[.;, ]/g, '_'); + const heightDownSun = shutterSettings[s].heightDownSun; - adapter.log.debug('save new trigger height: ' + heightDownSun + '%'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - } - } - } else { - shutterSettings[s].alarmTriggerLevel = parseFloat(heightDownSun); - shutterSettings[s].alarmTriggerAction = 'sunProtect'; + let convertShutter = false; - adapter.log.info('SunProtect not moving down now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%'); + if (parseFloat(shutterSettings[s].heightDown) < parseFloat(shutterSettings[s].heightUp)) { + convertShutter = false; + adapter.log.debug(shutterSettings[s].shutterName + ' level conversion is disabled ...'); + } else if (parseFloat(shutterSettings[s].heightDown) > parseFloat(shutterSettings[s].heightUp)) { + convertShutter = true; + adapter.log.debug(shutterSettings[s].shutterName + ' level conversion is enabled'); } - } - } - if (currentValue === mustValue || currentValue === mustValueTilted || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown') || (shutterSettings[s].triggerID == '')) { - const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); - if (insideTemp < parseFloat(hysteresisInside)) { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + const pendingAlarm = await checkPendingAlarm(adapter, shutterSettings[s]); - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].currentAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].currentAction = 'up'; - shutterSettings[s].currentHeight = shutterSettings[s].heightUp; - shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; + const _autoSunState = await adapter.getStateAsync(`shutters.autoSun.${nameDevice}`).catch((e) => adapter.log.warn(e)); - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #421'); + if (_autoSunState && _autoSunState.val === true) { + let currentValue = ''; - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active'); - adapter.log.debug('Sunprotect ' + shutterSettings[s].shutterName + ' old height: ' + shutterSettings[s].oldHeight + '% new height: ' + shutterSettings[s].heightUp + '%'); - } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].currentAction = 'none'; + const _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }).catch((e) => adapter.log.warn(e)); + const mustValue = ('' + shutterSettings[s].triggerState); + const mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { + currentValue = ('' + _triggerState.val); } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - const hysteresisInside = (((100 - shutterSettings[s].hysteresisInside) / 100) * shutterSettings[s].tempInside).toFixed(2); - if (insideTemp < parseFloat(hysteresisInside)) { - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if (shutterSettings[s].triggerAction == 'sunProtect' && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].triggerAction = 'up'; - - adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + if ((currentValue === mustValue || currentValue === mustValueTilted) || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown' && shutterSettings[s].autoDrive != 'off') || (shutterSettings[s].triggerID == '')) { + if (shutterSettings[s].sunProtectEndtimerid != '' && shutterSettings[s].sunProtectEndtimerid != '0') { + adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); + clearTimeout(shutterSettings[s].sunProtectEndtimerid); + shutterSettings[s].sunProtectEndtimerid = ''; + } + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if ((shutterSettings[s].currentAction == 'sunProtect' || shutterSettings[s].currentAction == 'manu_sunProtect') && shutterSettings[s].KeepSunProtect === false && (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].sunProtectEndtimerid = '' + shutterSettings[s].currentAction = 'up'; + shutterSettings[s].currentHeight = shutterSettings[s].heightUp; + shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; + + await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #422'); + + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is completed'); + adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); + adapter.log.debug('save current height: ' + shutterSettings[s].currentHeight + '%' + ' from ' + shutterSettings[s].shutterName); + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'none'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } } - else if (shutterSettings[s].currentAction == 'OpenInSunProtect') { - shutterSettings[s].triggerAction = 'none'; - - adapter.log.debug('OpenInSunProtect for ' + shutterSettings[s].shutterName + ' is not longer active'); + if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { + if (shutterSettings[s].sunProtectEndtimerid != '' && shutterSettings[s].sunProtectEndtimerid != '0') { + clearTimeout(shutterSettings[s].sunProtectEndtimerid); + shutterSettings[s].sunProtectEndtimerid = ''; + + adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); + + } + if (pendingAlarm == false) { + const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); + + if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { + if ((shutterSettings[s].triggerAction == 'sunProtect' || shutterSettings[s].triggerAction == 'manu_sunProtect') && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { + shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].triggerAction = 'up'; + shutterSettings[s].sunProtectEndtimerid = ''; + adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); + adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); + + adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); + + adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); + shutterSettings[s].sunProtectEndtimerid = '' + } + } + } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { + shutterSettings[s].sunProtectEndtimerid = ''; + shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); + shutterSettings[s].alarmTriggerAction = 'none'; + + adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + } } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'up'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); + await sleep(driveDelayUpSleep); } - } } - } - await sleep(driveDelayUpSleep); - break; - } - } - - } - } - } - clearTimeout(timerSleep); - return (shutterSettings); - } - } - - ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - - // +++++++++++++++++ End of sunprotect with Elevationslimit +++++++++++++++ - - if (shutterSettings) { - const result = shutterSettings.filter((/** @type {{ enabled: boolean; }} */ d) => d.enabled === true); - - const sunProtEndStart = parseInt(adapter.config.sunProtEndElevation); - const sunProtEndStop = (adapter.config.sunProtEndElevation - 1); - - for (const i in result) { - for (const s in shutterSettings) { - if (shutterSettings[s].shutterName == result[i].shutterName) { - if (elevation <= sunProtEndStart && elevation >= sunProtEndStop && (shutterSettings[s].currentAction == 'sunProtect' || shutterSettings[s].currentAction == 'manu_sunProtect')) { - const nameDevice = shutterSettings[s].shutterName.replace(/[.;, ]/g, '_'); - const heightDownSun = shutterSettings[s].heightDownSun; - - let convertShutter = false; - - if (parseFloat(shutterSettings[s].heightDown) < parseFloat(shutterSettings[s].heightUp)) { - convertShutter = false; - adapter.log.debug(shutterSettings[s].shutterName + ' level conversion is disabled ...'); - } else if (parseFloat(shutterSettings[s].heightDown) > parseFloat(shutterSettings[s].heightUp)) { - convertShutter = true; - adapter.log.debug(shutterSettings[s].shutterName + ' level conversion is enabled'); - } - - const pendingAlarm = await checkPendingAlarm(adapter, shutterSettings[s]); - - const _autoSunState = await adapter.getStateAsync(`shutters.autoSun.${nameDevice}`).catch((e) => adapter.log.warn(e)); - - if (_autoSunState && _autoSunState.val === true) { - let currentValue = ''; - - const _triggerState = shutterSettings[s].triggerID != '' ? await adapter.getForeignStateAsync(shutterSettings[s].triggerID).catch((e) => adapter.log.warn(e)) : null; - - const mustValue = ('' + shutterSettings[s].triggerState); - const mustValueTilted = shutterSettings[s].triggerStateTilted == 'none' ? ('' + shutterSettings[s].triggerState) : ('' + shutterSettings[s].triggerStateTilted); - - if (typeof _triggerState != undefined && _triggerState != null && _triggerState.val != undefined) { - currentValue = ('' + _triggerState.val); - } - - if ((currentValue === mustValue || currentValue === mustValueTilted) || (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].autoDrive != 'onlyDown' && shutterSettings[s].autoDrive != 'off') || (shutterSettings[s].triggerID == '')) { - if (shutterSettings[s].sunProtectEndtimerid != '' && shutterSettings[s].sunProtectEndtimerid != '0') { - adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); - clearTimeout(shutterSettings[s].sunProtectEndtimerid); - shutterSettings[s].sunProtectEndtimerid = ''; - } - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if ((shutterSettings[s].currentAction == 'sunProtect' || shutterSettings[s].currentAction == 'manu_sunProtect') && shutterSettings[s].KeepSunProtect === false && (Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].sunProtectEndtimerid = '' - shutterSettings[s].currentAction = 'up'; - shutterSettings[s].currentHeight = shutterSettings[s].heightUp; - shutterSettings[s].lastAutoAction = 'up_Sunprotect_end'; - - await setShutterState(adapter, shutterSettings, shutterSettings[s], parseFloat(shutterSettings[s].heightUp), nameDevice, 'Sunprotect #422'); - - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is completed'); - adapter.log.debug(`last automatic Action for ${shutterSettings[s].shutterName}: ${shutterSettings[s].lastAutoAction}`); - adapter.log.debug('save current height: ' + shutterSettings[s].currentHeight + '%' + ' from ' + shutterSettings[s].shutterName); - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'none'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); - } - } - if (currentValue != mustValue && currentValue != mustValueTilted && shutterSettings[s].driveAfterClose == true) { - if (shutterSettings[s].sunProtectEndtimerid != '' && shutterSettings[s].sunProtectEndtimerid != '0') { - clearTimeout(shutterSettings[s].sunProtectEndtimerid); - shutterSettings[s].sunProtectEndtimerid = ''; - - adapter.log.debug('Stopping sunprotect delay for ' + shutterSettings[s].shutterName); - - } - if (pendingAlarm == false) { - const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - - if (typeof _shutterState != undefined && _shutterState != null && _shutterState.val != undefined) { - if ((shutterSettings[s].triggerAction == 'sunProtect' || shutterSettings[s].triggerAction == 'manu_sunProtect') && shutterSettings[s].KeepSunProtect === false && (parseFloat(shutterSettings[s].triggerHeight) == parseFloat(heightDownSun) || Math.round(parseFloat(_shutterState.val) / vRound) * vRound == parseFloat(shutterSettings[s].currentHeight))) { - shutterSettings[s].triggerHeight = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].triggerAction = 'up'; - shutterSettings[s].sunProtectEndtimerid = ''; - adapter.log.debug('Sunprotect for ' + shutterSettings[s].shutterName + ' is not active anymore'); - adapter.log.info(' Will end sunprotect ID: ' + shutterSettings[s].shutterName + ' value: ' + heightDownSun + '%' + ' after the window has been closed '); - - adapter.log.debug('save new trigger height: ' + shutterSettings[s].triggerHeight + '%'); - - adapter.log.debug('save new trigger action: ' + shutterSettings[s].triggerAction); - shutterSettings[s].sunProtectEndtimerid = '' - } - } - } else if (shutterSettings[s].alarmTriggerAction == 'sunProtect') { - shutterSettings[s].sunProtectEndtimerid = ''; - shutterSettings[s].alarmTriggerLevel = parseFloat(shutterSettings[s].heightUp); - shutterSettings[s].alarmTriggerAction = 'none'; - - adapter.log.info('SunProtect not moving up now due to active alarm: ' + shutterSettings[s].shutterName + ' value: ' + shutterSettings[s].heightUp + '%'); } - } - await sleep(driveDelayUpSleep); } - } } - } + clearTimeout(timerSleep); + return (shutterSettings); } - clearTimeout(timerSleep); - return (shutterSettings); - } } module.exports = sunProtect; diff --git a/package-lock.json b/package-lock.json index 759e4d02..87335f94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,14 +22,14 @@ "@types/chai-as-promised": "^7.1.5", "@types/gulp": "^4.0.13", "@types/mocha": "^10.0.1", - "@types/node": "^20.5.0", + "@types/node": "^20.5.7", "@types/proxyquire": "^1.3.28", "@types/sinon": "^10.0.16", "@types/sinon-chai": "^3.2.9", - "axios": "^1.4.0", - "chai": "^4.3.7", + "axios": "^1.5.0", + "chai": "^4.3.8", "chai-as-promised": "^7.1.1", - "eslint": "^8.47.0", + "eslint": "^8.48.0", "gulp": "^4.0.2", "mocha": "^10.2.0", "proxyquire": "^2.1.3", @@ -612,9 +612,9 @@ "dev": true }, "node_modules/@eslint/js": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.47.0.tgz", - "integrity": "sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz", + "integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1056,9 +1056,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.0.tgz", - "integrity": "sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==", + "version": "20.5.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.7.tgz", + "integrity": "sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA==", "dev": true }, "node_modules/@types/proxyquire": { @@ -1519,9 +1519,9 @@ } }, "node_modules/axios": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", - "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.0.tgz", + "integrity": "sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==", "dev": true, "dependencies": { "follow-redirects": "^1.15.0", @@ -1767,9 +1767,9 @@ } }, "node_modules/chai": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", - "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.8.tgz", + "integrity": "sha512-vX4YvVVtxlfSZ2VecZgFUTU5qPCYsobVI2O9FmwEXBhDigYGQA6jRXCycIs1yJnnWbZ6/+a2zNIF5DfVCcJBFQ==", "dev": true, "dependencies": { "assertion-error": "^1.1.0", @@ -2440,15 +2440,15 @@ } }, "node_modules/eslint": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz", - "integrity": "sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz", + "integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "^8.47.0", + "@eslint/js": "8.48.0", "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -7623,9 +7623,9 @@ } }, "@eslint/js": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.47.0.tgz", - "integrity": "sha512-P6omY1zv5MItm93kLM8s2vr1HICJH8v0dvddDhysbIuZ+vcjOHg5Zbkf1mTkcmi2JA9oBG2anOkRnW8WJTS8Og==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz", + "integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==", "dev": true }, "@humanwhocodes/config-array": { @@ -7983,9 +7983,9 @@ "dev": true }, "@types/node": { - "version": "20.5.0", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.0.tgz", - "integrity": "sha512-Mgq7eCtoTjT89FqNoTzzXg2XvCi5VMhRV6+I2aYanc6kQCBImeNaAYRs/DyoVqk1YEUJK5gN9VO7HRIdz4Wo3Q==", + "version": "20.5.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.7.tgz", + "integrity": "sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA==", "dev": true }, "@types/proxyquire": { @@ -8349,9 +8349,9 @@ "dev": true }, "axios": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.4.0.tgz", - "integrity": "sha512-S4XCWMEmzvo64T9GfvQDOXgYRDJ/wsSZc7Jvdgx5u1sd0JwsuPLqb3SYmusag+edF6ziyMensPVqLTSc1PiSEA==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.5.0.tgz", + "integrity": "sha512-D4DdjDo5CY50Qms0qGQTTw6Q44jl7zRwY7bthds06pUGfChBCTcQs+N743eFWGEd6pRTMd6A+I87aWyFV5wiZQ==", "dev": true, "requires": { "follow-redirects": "^1.15.0", @@ -8556,9 +8556,9 @@ "dev": true }, "chai": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.7.tgz", - "integrity": "sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A==", + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/chai/-/chai-4.3.8.tgz", + "integrity": "sha512-vX4YvVVtxlfSZ2VecZgFUTU5qPCYsobVI2O9FmwEXBhDigYGQA6jRXCycIs1yJnnWbZ6/+a2zNIF5DfVCcJBFQ==", "dev": true, "requires": { "assertion-error": "^1.1.0", @@ -9111,15 +9111,15 @@ "dev": true }, "eslint": { - "version": "8.47.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.47.0.tgz", - "integrity": "sha512-spUQWrdPt+pRVP1TTJLmfRNJJHHZryFmptzcafwSvHsceV81djHOdnEeDmkdotZyLNjDhrOasNK8nikkoG1O8Q==", + "version": "8.48.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz", + "integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "^8.47.0", + "@eslint/js": "8.48.0", "@humanwhocodes/config-array": "^0.11.10", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", diff --git a/package.json b/package.json index dcd88dc2..e1f31f28 100644 --- a/package.json +++ b/package.json @@ -34,14 +34,14 @@ "@types/chai-as-promised": "^7.1.5", "@types/gulp": "^4.0.13", "@types/mocha": "^10.0.1", - "@types/node": "^20.5.0", + "@types/node": "^20.5.7", "@types/proxyquire": "^1.3.28", "@types/sinon": "^10.0.16", "@types/sinon-chai": "^3.2.9", - "axios": "^1.4.0", - "chai": "^4.3.7", + "axios": "^1.5.0", + "chai": "^4.3.8", "chai-as-promised": "^7.1.1", - "eslint": "^8.47.0", + "eslint": "^8.48.0", "gulp": "^4.0.2", "mocha": "^10.2.0", "proxyquire": "^2.1.3", From 9fc480cbbcf522cb046bc20cf1c6ac7999cf2542 Mon Sep 17 00:00:00 2001 From: simatec Date: Mon, 28 Aug 2023 11:59:13 +0200 Subject: [PATCH 09/10] (simatec) Beta 1.6.2 --- main.js | 86 +++++++++++++++++++++++++++++---------------------------- 1 file changed, 44 insertions(+), 42 deletions(-) diff --git a/main.js b/main.js index 05765575..6685032e 100644 --- a/main.js +++ b/main.js @@ -241,7 +241,7 @@ function startAdapter(options) { const nameDevice = shutterSettings[s].shutterName.replace(/[.;, ]/g, '_'); const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); - if (typeof _shutterState != undefined && _shutterState != null && shutterSettings[s].oldHeight != Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound) { + if (typeof _shutterState != undefined && _shutterState != null && shutterSettings[s].oldHeight != Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound) { adapter.log.debug('Shutter state changed: ' + shutterSettings[s].shutterName + ' old value = ' + shutterSettings[s].oldHeight + ' new value = ' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound); } if (typeof _shutterState != undefined && _shutterState != null && Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound != shutterSettings[s].currentHeight && Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound != shutterSettings[s].oldHeight) { @@ -280,33 +280,33 @@ function startAdapter(options) { } } else { if (shutterSettings[s].firstCompleteUp != true && shutterSettings[s].currentAction != 'none' && shutterSettings[s].currentAction != 'OpenInSunProtect') { - shutterSettings[s].currentAction = 'Manu_Mode'; - shutterSettings[s].triggerAction = 'Manu_Mode'; - adapter.log.debug('set Manu_Mode #1 ' + shutterSettings[s].shutterName); - } - else { - //Shutter is closed -> open manually to heightUp (should be 100% or 0%) before it has been opened automatically -> enable possibility to activate sunprotect height if required --> if sunprotect is required: shutter is set to sunProtect height - if (shutterSettings[s].firstCompleteUp == true && Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'up' && shutterSettings[s].currentAction != 'triggered' && shutterSettings[s].currentAction != 'triggered_Tilted') { - shutterSettings[s].currentHeight = Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound; - shutterSettings[s].triggerHeight = Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound; - shutterSettings[s].currentAction = 'none'; //reset mode. e.g. mode can be set to sunProtect later if window is closed - shutterSettings[s].triggerAction = 'Manu_Mode'; - shutterSettings[s].firstCompleteUp = false; - adapter.log.debug('Reset firstCompleteUp #1 for ' + shutterSettings[s].shutterName); - adapter.log.debug(shutterSettings[s].shutterName + ' opened manually to ' + shutterSettings[s].heightUp + '. Old value = ' + shutterSettings[s].oldHeight + '. New value = ' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + '. Possibility to activate sunprotect enabled.'); - - await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }) - .catch((e) => adapter.log.warn(e)); - await adapter.setStateAsync('shutters.autoLevel.' + nameDevice, { val: parseFloat(shutterSettings[s].currentHeight), ack: true }) - .catch((e) => adapter.log.warn(e)); - - } - else { - shutterSettings[s].currentAction = 'Manu_Mode'; - shutterSettings[s].triggerAction = 'Manu_Mode'; - adapter.log.debug('set Manu_Mode #2 ' + shutterSettings[s].shutterName); - } - } + shutterSettings[s].currentAction = 'Manu_Mode'; + shutterSettings[s].triggerAction = 'Manu_Mode'; + adapter.log.debug('set Manu_Mode #1 ' + shutterSettings[s].shutterName); + } + else { + //Shutter is closed -> open manually to heightUp (should be 100% or 0%) before it has been opened automatically -> enable possibility to activate sunprotect height if required --> if sunprotect is required: shutter is set to sunProtect height + if (shutterSettings[s].firstCompleteUp == true && Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound == shutterSettings[s].heightUp && shutterSettings[s].currentAction != 'up' && shutterSettings[s].currentAction != 'triggered' && shutterSettings[s].currentAction != 'triggered_Tilted') { + shutterSettings[s].currentHeight = Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound; + shutterSettings[s].triggerHeight = Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound; + shutterSettings[s].currentAction = 'none'; //reset mode. e.g. mode can be set to sunProtect later if window is closed + shutterSettings[s].triggerAction = 'Manu_Mode'; + shutterSettings[s].firstCompleteUp = false; + adapter.log.debug('Reset firstCompleteUp #1 for ' + shutterSettings[s].shutterName); + adapter.log.debug(shutterSettings[s].shutterName + ' opened manually to ' + shutterSettings[s].heightUp + '. Old value = ' + shutterSettings[s].oldHeight + '. New value = ' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + '. Possibility to activate sunprotect enabled.'); + + await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }) + .catch((e) => adapter.log.warn(e)); + await adapter.setStateAsync('shutters.autoLevel.' + nameDevice, { val: parseFloat(shutterSettings[s].currentHeight), ack: true }) + .catch((e) => adapter.log.warn(e)); + + } + else { + shutterSettings[s].currentAction = 'Manu_Mode'; + shutterSettings[s].triggerAction = 'Manu_Mode'; + adapter.log.debug('set Manu_Mode #2 ' + shutterSettings[s].shutterName); + } + } adapter.log.debug(shutterSettings[s].shutterName + ' drived manually to ' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + '. Old value = ' + shutterSettings[s].oldHeight + '. New value = ' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound); adapter.log.debug(shutterSettings[s].shutterName + ' Updated trigger action to ' + shutterSettings[s].triggerAction + ' to prevent moving after window close '); @@ -324,26 +324,28 @@ function startAdapter(options) { await adapter.setStateAsync('shutters.autoState.' + nameDevice, { val: shutterSettings[s].currentAction, ack: true }) .catch((e) => adapter.log.warn(e)); - await sleep(2000); + await sleep(2000); shutterSettings = await shutterState(shutterSettings[s].name, adapter, shutterSettings, false); } else if (typeof _shutterState != undefined && _shutterState != null && Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound === shutterSettings[s].currentHeight) { adapter.log.debug(shutterSettings[s].shutterName + ' Old value = ' + shutterSettings[s].oldHeight + '. New value = ' + Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound + '. automatic is active'); - await sleep(2000); - shutterSettings = await shutterState(shutterSettings[s].name, adapter, shutterSettings, false); + await sleep(2000); + shutterSettings = await shutterState(shutterSettings[s].name, adapter, shutterSettings, false); } //save old height await sleep(2000); //already waited waitTime4StateCheck seconds. - var timeout_set_oldHeight; - timeout_set_oldHeight = setTimeout(async () => { //async set with timeout because e.g. Shelly submits several position by MQTT and not only the last one (0% 1% ... 97% - 98% - 100%). By this the value is set only after the final height state has been processed - timeout_set_oldHeight = null; - shutterSettings[s].oldHeight = shutterSettings[s].currentHeight; - if (shutterSettings[s].firstCompleteUp === true) { - shutterSettings[s].firstCompleteUp = false; - adapter.log.debug('Reset firstCompleteUp #2 for ' + shutterSettings[s].shutterName); - } - }, 5000 + waitTime4StateCheck); - saveCurrentStates(false); + + let timeout_set_oldHeight; + + timeout_set_oldHeight = setTimeout(async () => { //async set with timeout because e.g. Shelly submits several position by MQTT and not only the last one (0% 1% ... 97% - 98% - 100%). By this the value is set only after the final height state has been processed + timeout_set_oldHeight = null; + shutterSettings[s].oldHeight = shutterSettings[s].currentHeight; + if (shutterSettings[s].firstCompleteUp === true) { + shutterSettings[s].firstCompleteUp = false; + adapter.log.debug('Reset firstCompleteUp #2 for ' + shutterSettings[s].shutterName); + } + }, 5000 + waitTime4StateCheck); + saveCurrentStates(false); } } } @@ -726,7 +728,7 @@ const calc = schedule.scheduleJob('calcTimer', '30 2 * * *', async function () { adapter.log.debug(resultStates[i].shutterName + ' level conversion is enabled'); } } - saveCurrentStates(false); + saveCurrentStates(false); } } } From ef32e90d1335ecbf27dc6a312b54a3816fe33403 Mon Sep 17 00:00:00 2001 From: simatec Date: Mon, 28 Aug 2023 12:07:22 +0200 Subject: [PATCH 10/10] chore: release v1.6.2 * (simatec) Dependencies updated * (simatec) node 20 tests added * (simatec) Fix ending Sunprotect with open door/window * (5G7K) Fix timing & some states for sunprotect --- README.md | 2 +- io-package.json | 28 ++++++++++++++-------------- package-lock.json | 4 ++-- package.json | 2 +- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index efe72254..17075f9a 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ When the adapter crashes or an other Code error happens, this error message that ## Changelog -### __WORK IN PROGRESS__ +### 1.6.2 (2023-08-28) * (simatec) Dependencies updated * (simatec) node 20 tests added * (simatec) Fix ending Sunprotect with open door/window diff --git a/io-package.json b/io-package.json index 105a072b..db0425db 100644 --- a/io-package.json +++ b/io-package.json @@ -1,8 +1,21 @@ { "common": { "name": "shuttercontrol", - "version": "1.6.1", + "version": "1.6.2", "news": { + "1.6.2": { + "en": "Dependencies updated\nnode 20 tests added\nFix ending Sunprotect with open door/window\nFix timing & some states for sunprotect", + "de": "Ausgaben aktualisiert\nknoten 20 tests hinzugefügt\nFix End Sunprotect mit offener Tür/Fenster\nFix Timing und einige Zustände für Sonnenschutz", + "ru": "Обновленные зависимости\nвсего 20 тестов добавлено\nFix ending Sunprotect с открытой дверью/окно\nИсправление сроков и некоторых государств для sunprotect", + "pt": "Dependências atualizadas\nnode 20 testes adicionados\nFix final Sunprotect com porta aberta / janela\nFix timing & alguns estados para proteção solar", + "nl": "Afhankelijkheid geüpdateerd\n20 testen toegevoegd\nVertaling:\nVertaling:", + "fr": "Dépendances mises à jour\nnode 20 tests ajoutés\nFixe fin Sunprotect avec porte ouverte/fenêtre\nFixer le timing & certains états pour sunprotect", + "it": "Dipendenze aggiornate\nnodo 20 test aggiunti\nFissare la protezione solare con la porta aperta/finestra\nFissare i tempi e alcuni stati per protezione solare", + "es": "Actualización de las dependencias\nnodo 20 pruebas agregadas\nAcabado fijo protector solar con puerta abierta / ventana\nTiempo de fijación \" algunos estados para protección solar", + "pl": "Zależności\n20 testów\nFix kończy Sunprotect z otwartym drzwiem/wysokiem\nFix i niektóre stany na słońce", + "uk": "Залежність оновлено\nдодано набір 20 тестів\nФіксація затримки Sunprotect з відкритими дверима/вікно\nВиправлення часу та деяких станів для захисту від сонця", + "zh-cn": "B. 更新的属地\n无20次试验增加\nFix 关闭Sunprotect,开门/日。\n固定时间和某些州" + }, "1.6.1": { "en": "Fix Heat protection", "de": "Wärmeschutz", @@ -80,19 +93,6 @@ "pl": "mały Fisz", "uk": "маленькі Фікси", "zh-cn": "小型固定" - }, - "1.4.26": { - "en": "Fix Sunprotect", - "de": "Sunprotekt reparieren", - "ru": "Исправление Sunprotect", - "pt": "Fix Sunprotect", - "nl": "Vertaling:", - "fr": "Fix Sunprotect", - "it": "Fissare la protezione solare", - "es": "Protección solar", - "pl": "Fix Sunprotekt", - "uk": "Виправлення Sunprotect", - "zh-cn": "Fix Sunprotect" } }, "title": "shuttercontrol", diff --git a/package-lock.json b/package-lock.json index 87335f94..5108a07a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "iobroker.shuttercontrol", - "version": "1.6.1", + "version": "1.6.2", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "iobroker.shuttercontrol", - "version": "1.6.1", + "version": "1.6.2", "license": "MIT", "dependencies": { "@iobroker/adapter-core": "^3.0.3", diff --git a/package.json b/package.json index e1f31f28..5c3cfe81 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iobroker.shuttercontrol", - "version": "1.6.1", + "version": "1.6.2", "description": "Automatic control for shutters", "author": { "name": "simatec",