UNPKG

iobroker.shuttercontrol

Version:
791 lines (694 loc) 106 kB
/* jshint -W097 */ /* jshint strict: false */ /*jslint node: true */ 'use strict'; // @ts-ignore const utils = require('@iobroker/adapter-core'); // @ts-ignore const schedule = require('node-schedule'); // @ts-ignore const SunCalc = require('suncalc'); const sunProtect = require('./lib/sunProtect.js'); // SunProtect const triggerChange = require('./lib/triggerChange.js'); // triggerChange const elevationDown = require('./lib/elevationDown.js'); // elevationDown const shutterGoldenHour = require('./lib/shutterGoldenHour.js'); // shutterGoldenHour const shutterUpLiving = require('./lib/shutterUpLiving.js'); // shutterUpLiving const shutterSunriseSunset = require('./lib/shutterSunriseSunset.js'); // shutterSunriseSunset const shutterDownLiving = require('./lib/shutterDownLiving.js'); // shutterDownLiving const shutterUpSleep = require('./lib/shutterUpSleep.js'); // shutterUpSleep const shutterDownLate = require('./lib/shutterDownLate.js'); // shutterDownLate const shutterDownChildren = require('./lib/shutterDownChildren.js'); // shutterDownChildren const shutterUpChildren = require('./lib/shutterUpChildren.js'); // shutterUpChildren const shutterDownSleep = require('./lib/shutterDownSleep.js'); // shutterDownSleep const buttonAction = require('./lib/buttonAction.js'); // buttonAction const shutterState = require('./lib/shutterState.js'); // shutterState const shutterDownComplete = require('./lib/shutterDownComplete.js'); // shutterDownComplete const shutterBrightnessSensor = require('./lib/shutterBrightnessSensor.js').shutterBrightnessSensor; // shutterBrightnessSensor const brightnessState = require('./lib/shutterBrightnessSensor.js').brightnessState; // brightnessState const shutterAlarm = require('./lib/shutterAlarm.js').shutterAlarm; // ShutterAlarm let adapter; const adapterName = require('./package.json').name.split('.').pop(); let autoLivingStr, autoSleepStr, autoChildrenStr, delayUp, delayUpChildren, delayDown, delayDownChildren, resTriggerChange, shutterSettings; let astroTimeLivingUp, astroTimeLivingDown, astroTimeSleepUp, astroTimeSleepDown, astroTimeChildrenUp, astroTimeChildrenDown; let timer, timerSleep; let resTrigger = []; let resSunInsideTemp = []; let resSunOutsideTemp = []; let resSunLight = []; let ObjautoUp = []; let ObjautoDown = []; let ObjautoSun = []; let ObjautoState = []; let ObjautoLevel = []; let resShutterState = []; const lastLigthSensorValue = {}; let waitTime4StateCheck = 10; let brightnessDown = false; // +++++++++++++++++++++++++++ Starts the adapter instance ++++++++++++++++++++++++++++++++ function startAdapter(options) { options = options || {}; Object.assign(options, { name: adapterName }); adapter = new utils.Adapter(options); // start here! adapter.on('ready', () => main(adapter)); // +++++++++++++++++++++++++ is called when adapter shuts down +++++++++++++++++++++++++ adapter.on('unload', (callback) => { try { adapter.log.info('cleaned everything up...'); clearTimeout(timer); clearTimeout(timerSleep); schedule.cancelJob('shutterUpGoldenHourEnd'); schedule.cancelJob('calcTimer'); schedule.cancelJob('shutterDownGoldenHour'); schedule.cancelJob('shutterUpSunrise'); schedule.cancelJob('shutterDownSunset'); schedule.cancelJob('shutterUpLiving'); schedule.cancelJob('shutterDownLiving'); schedule.cancelJob('shutterUpSleep'); schedule.cancelJob('shutterDownLate'); schedule.cancelJob('shutterDownComplete'); schedule.cancelJob('shutterDownSleep'); schedule.cancelJob('calcPosTimer'); schedule.cancelJob('shutterUpChildren'); schedule.cancelJob('shutterDownChildren'); callback(); } catch (err) { // @ts-ignore callback(err); } }); // ++++++++++++++++++ is called if a subscribed state changes ++++++++++++++++++ adapter.on('stateChange', async (id, state) => { if (state) { if (adapter.config.HolidayDP !== '') { if (id.includes(adapter.config.HolidayDP)) { adapter.log.debug(`HolidayDP changed to: ${state.val}`); await adapter.setStateAsync('control.Holiday', { val: state.val, ack: true }) .catch((e) => adapter.log.warn(e)); } } if (adapter.config.schoolfreeDP !== '') { if (id.includes(adapter.config.schoolfreeDP)) { adapter.log.debug(`schoolfreeDP changed to: ${state.val}`); await adapter.setStateAsync('control.schoolfree', { val: state.val, ack: true }) .catch((e) => adapter.log.warn(e)); } } if (id === `${adapter.namespace}.control.Holiday`) { HolidayStr = state.val; shutterDriveCalc(); } if (id === `${adapter.namespace}.control.schoolfree`) { SchoolfreeStr = state.val; shutterDriveCalc(); } if (id === `${adapter.namespace}.control.autoLiving`) { autoLivingStr = state.val; shutterDriveCalc(); } if (id === `${adapter.namespace}.control.autoSleep`) { autoSleepStr = state.val; shutterDriveCalc(); } if (id === `${adapter.namespace}.control.autoChildren`) { autoChildrenStr = state.val; shutterDriveCalc(); } if (adapter.config.publicHolidays === true) { if (id === `${adapter.config.publicHolInstance}.heute.boolean`) { publicHolidayStr = state.val; shutterDriveCalc(); } if (id === `${adapter.config.publicHolInstance}.morgen.boolean`) { publicHolidayTomorowStr = state.val; shutterDriveCalc(); } } if (adapter.config.schoolfree === true) { if (id === `${adapter.config.schoolfreeInstance}.info.today`) { schoolfreeStr = state.val; shutterDriveCalc(); } if (id === `${adapter.config.schoolfreeInstance}.info.tomorrow`) { schoolfreeTomorowStr = state.val; shutterDriveCalc(); } } if (id === adapter.config.triggerAutoLiving) { await adapter.setStateAsync('control.autoLiving', { val: state.val, ack: true }) .catch((e) => adapter.log.warn(e)); adapter.log.debug(`Auto Living is: ${state.val}`); } if (id === adapter.config.triggerAutoSleep) { await adapter.setStateAsync('control.autoSleep', { val: state.val, ack: true }) .catch((e) => adapter.log.warn(e)); adapter.log.debug(`Auto Sleep is: ${state.val}`); } if (id === adapter.config.triggerAutoChildren) { await adapter.setStateAsync('control.autoChildren', { val: state.val, ack: true }) .catch((e) => adapter.log.warn(e)); adapter.log.debug(`Auto Children is: ${state.val}`); } if (id === adapter.config.lightsensorUpDown) { shutterBrightnessSensor(adapter, state.val, shutterSettings, brightnessDown); adapter.log.debug(`Brightness sensor value: ${state.val}`); if (state.val === 0 && brightnessDown === false) { const shutterDownBrightnessTime = adapter.config.lightsensorDownTime; const downTime = shutterDownBrightnessTime.split(':'); schedule.cancelJob('shutterDownBrightness'); const downBrightness = schedule.scheduleJob('shutterDownBrightness', `${downTime[1]} ${downTime[0]} * * *`, async function () { adapter.log.debug(`Brightness State Down is: ${brightnessDown}`); adapter.log.debug(`Brightness sensor value: ${state.val}`); shutterBrightnessSensor(adapter, state.val, shutterSettings, brightnessDown); await sleep(10000); brightnessDown = brightnessState(adapter, state.val, brightnessDown); adapter.log.debug(`Brightness State Down is: ${brightnessDown}`); }); // @ts-ignore } else if (state.val > 0) { schedule.cancelJob('shutterDownBrightness'); } await sleep(10000); brightnessDown = brightnessState(adapter, state.val, brightnessDown); adapter.log.debug(`Brightness State Down is: ${brightnessDown}`); } if (id === adapter.config.alarmWind1) { adapter.log.debug(`Alarm Wind 1 changed: ${state.val}`); shutterAlarm(adapter, 'alarmWind1', shutterSettings); } if (id === adapter.config.alarmWind2) { adapter.log.debug(`Alarm Wind 2 changed: ${state.val}`); shutterAlarm(adapter, 'alarmWind2', shutterSettings); } if (id === adapter.config.alarmRain) { adapter.log.debug(`Alarm Rain changed: ${state.val}`); shutterAlarm(adapter, 'alarmRain', shutterSettings); } if (id === adapter.config.alarmFrost) { adapter.log.debug(`Alarm Frost changed: ${state.val}`); shutterAlarm(adapter, 'alarmFrost', shutterSettings); } if (id === adapter.config.alarmFire) { adapter.log.debug(`Alarm Fire changed: ${state.val}`); shutterAlarm(adapter, 'alarmFire', shutterSettings); } resTrigger.forEach(async function (resultTriggerID) { if (id === resultTriggerID && state.ts === state.lc) { resTriggerChange = resultTriggerID; adapter.log.debug(`TriggerID changed: ${resultTriggerID} | Value: ${state.val}`); triggerChange(resTriggerChange, adapter, shutterSettings); } }); resSunInsideTemp.forEach(async function (resSunInsideTempID) { if (id === resSunInsideTempID && state.ts === state.lc) { adapter.log.debug(`insidetemperature changed: ${resSunInsideTempID} | Value: ${state.val}°C`); sunProtect(adapter, elevation, azimuth, shutterSettings); } }); resSunOutsideTemp.forEach(async function (resSunOutsideTempID) { if (id === resSunOutsideTempID && state.ts === state.lc && state.val !== null) { adapter.log.debug(`outsidetemperature changed: ${resSunOutsideTempID} | Value: ${state.val}°C`); sunProtect(adapter, elevation, azimuth, shutterSettings); } }); resSunLight.forEach(async function (resSunLightID) { if (id === resSunLightID && state.ts === state.lc) { // @ts-ignore if (Math.round((new Date(state.lc) - new Date(lastLigthSensorValue[`${resSunLightID}`].ts)) / 1000 / 60) > 2) { adapter.log.debug(`Lightsensor changed: ${resSunLightID} | Value: ${state.val}lux`); sunProtect(adapter, elevation, azimuth, shutterSettings); lastLigthSensorValue[`${resSunLightID}`].ts = state.lc; } } }); resShutterState.forEach(async function (resShutterID) { if (id === resShutterID && state.ts === state.lc) { const result = shutterSettings.filter((d) => d.name === resShutterID); if (adapter.config.currentShutterState === true && adapter.config.currentShutterStateTime) { waitTime4StateCheck = (adapter.config.currentShutterStateTime ? adapter.config.currentShutterStateTime * 1000 : 60000); } adapter.log.debug('#0 wait for shutter check started'); await sleep(waitTime4StateCheck); adapter.log.debug('#0 wait for shutter check end'); for (const i in result) { for (const s in shutterSettings) { if (shutterSettings[s].shutterName === result[i].shutterName) { const nameDevice = shutterSettings[s].shutterName.replace(/[.;, ]/g, '_'); const _shutterState = await adapter.getForeignStateAsync(shutterSettings[s].name).catch((e) => adapter.log.warn(e)); if (_shutterState?.val !== null && _shutterState?.val !== undefined && 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 (_shutterState?.val !== null && _shutterState?.val !== undefined && 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) { if (adapter.config.blockManuMode === true) { switch (Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound) { case parseFloat(shutterSettings[s].heightUp): shutterSettings[s].currentAction = 'up'; shutterSettings[s].triggerAction = 'up'; shutterSettings[s].currentHeight = Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound; shutterSettings[s].triggerHeight = 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`); break; case parseFloat(shutterSettings[s].heightDown): shutterSettings[s].currentAction = 'down'; shutterSettings[s].triggerAction = 'down'; shutterSettings[s].currentHeight = Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound; shutterSettings[s].triggerHeight = 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`); break; case parseFloat(shutterSettings[s].heightDownSun): shutterSettings[s].currentAction = 'sunProtect'; shutterSettings[s].triggerAction = 'sunProtect'; shutterSettings[s].currentHeight = Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound; shutterSettings[s].triggerHeight = 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`); break; default: shutterSettings[s].currentAction = 'Manu_Mode'; shutterSettings[s].triggerAction = 'Manu_Mode'; 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`); } } 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}`); } } 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`); } adapter.log.debug(`#1 shutterName: ${shutterSettings[s].shutterName}`); adapter.log.debug(`#1 shutterState: ${Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound}%`); adapter.log.debug(`#1 currentAction: ${shutterSettings[s].currentAction}`); adapter.log.debug(`#1 triggerAction: ${shutterSettings[s].triggerAction}`); adapter.log.debug(`#1 currentHeight: ${shutterSettings[s].currentHeight}%`); adapter.log.debug(`#1 oldHeight: ${shutterSettings[s].oldHeight}%`); adapter.log.debug(`#1 currentShutterState: ${adapter.config.currentShutterState === true ? 'activated' : 'disabled'}`); adapter.log.debug(`#1 currentShutterStateTime: ${adapter.config.currentShutterStateTime} seconds`); 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 (_shutterState?.val !== null && _shutterState?.val !== undefined && 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); } //save old height await sleep(2000); //already waited waitTime4StateCheck seconds. saveCurrentStates(false); /* await sleep 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 */ await sleep(5000 + waitTime4StateCheck); 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}`); } saveCurrentStates(false); } } } } }); if (id === `${adapter.namespace}.info.Azimut`) { sunProtect(adapter, elevation, azimuth, shutterSettings); } if (id === `${adapter.namespace}.info.Elevation`) { elevationDown(adapter, elevation, azimuth, shutterSettings); } if (id === `${adapter.namespace}.control.closeAll`) { buttonAction(adapter, 'closeAll', shutterSettings); } if (id === `${adapter.namespace}.control.openAll`) { buttonAction(adapter, 'openAll', shutterSettings); } if (id === `${adapter.namespace}.control.closeLiving`) { buttonAction(adapter, 'closeLiving', shutterSettings); } if (id === `${adapter.namespace}.control.openLiving`) { buttonAction(adapter, 'openLiving', shutterSettings); } if (id === `${adapter.namespace}.control.closeSleep`) { buttonAction(adapter, 'closeSleep', shutterSettings); } if (id === `${adapter.namespace}.control.openSleep`) { buttonAction(adapter, 'openSleep', shutterSettings); } if (id === `${adapter.namespace}.control.closeChildren`) { buttonAction(adapter, 'closeChildren', shutterSettings); } if (id === `${adapter.namespace}.control.openChildren`) { buttonAction(adapter, 'openChildren', shutterSettings); } if (id === `${adapter.namespace}.control.sunProtect`) { buttonAction(adapter, 'sunProtect', shutterSettings); } if (id === `${adapter.namespace}.control.sunProtectSleep`) { buttonAction(adapter, 'sunProtectSleep', shutterSettings); } if (id === `${adapter.namespace}.control.sunProtectChildren`) { buttonAction(adapter, 'sunProtectChildren', shutterSettings); } if (id === `${adapter.namespace}.control.sunProtectLiving`) { buttonAction(adapter, 'sunProtectLiving', shutterSettings); } if (id === `${adapter.namespace}.control.autoAll`) { buttonAction(adapter, 'autoAll', shutterSettings); } } }); adapter.on('message', (obj) => { if (obj?.command === 'tab' && obj.callback) { const shutterSettings = adapter.config.events; for (const s in shutterSettings) { const nameDevice = shutterSettings[s].shutterName.replace(/[.;, ]/g, '_'); shutterSettings[s].autoDown = `shutters.autoDown.${nameDevice}`; shutterSettings[s].autoUp = `shutters.autoUp.${nameDevice}`; shutterSettings[s].autoSun = `shutters.autoSun.${nameDevice}`; shutterSettings[s].autoState = `shutters.autoState.${nameDevice}`; } try { adapter.sendTo(obj.from, obj.command, { data: { events: shutterSettings } }, obj.callback); } catch (e) { adapter.log.error('Tab-Menu is not loaded'); } } }); } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// /* ************************ Check all shutter values​and set default values ​​if values ​are not available ********************************* */ async function shutterConfigCheck() { return new Promise(async (resolve) => { let num = 0; if (shutterSettings) { adapter.log.debug('shutter Config Check started'); try { for (const s in shutterSettings) { shutterSettings[s].triggerState = shutterSettings[s].triggerState ? shutterSettings[s].triggerState : 'none'; shutterSettings[s].triggerStateTilted = shutterSettings[s].triggerStateTilted ? shutterSettings[s].triggerStateTilted : 'none'; shutterSettings[s].typeUp = shutterSettings[s].typeUp ? shutterSettings[s].typeUp : 'sunrise'; shutterSettings[s].typeDown = shutterSettings[s].typeDown ? shutterSettings[s].typeDown : 'sunset'; shutterSettings[s].heightUp = shutterSettings[s].heightUp ? shutterSettings[s].heightUp : '100'; shutterSettings[s].heightDown = shutterSettings[s].heightDown ? shutterSettings[s].heightDown : '0'; shutterSettings[s].triggerDrive = shutterSettings[s].triggerDrive ? shutterSettings[s].triggerDrive : '100'; shutterSettings[s].triggerDriveTildet = shutterSettings[s].triggerDriveTildet ? shutterSettings[s].triggerDriveTildet : shutterSettings[s].triggerDrive; shutterSettings[s].triggerChange = shutterSettings[s].triggerChange ? shutterSettings[s].triggerChange : 'off'; shutterSettings[s].elevation = shutterSettings[s].elevation ? shutterSettings[s].elevation : '8'; shutterSettings[s].type = shutterSettings[s].type ? shutterSettings[s].type : 'in- & outside temperature and direction'; shutterSettings[s].heightDownSun = shutterSettings[s].heightDownSun ? shutterSettings[s].heightDownSun : '30'; shutterSettings[s].direction = shutterSettings[s].direction ? shutterSettings[s].direction : '120'; shutterSettings[s].directionRange = shutterSettings[s].directionRange ? shutterSettings[s].directionRange : '50'; shutterSettings[s].tempInside = shutterSettings[s].tempInside ? shutterSettings[s].tempInside : '23'; shutterSettings[s].tempOutside = shutterSettings[s].tempOutside ? shutterSettings[s].tempOutside : '23'; shutterSettings[s].valueLight = shutterSettings[s].valueLight ? shutterSettings[s].valueLight : '15'; shutterSettings[s].autoDrive = shutterSettings[s].autoDrive ? shutterSettings[s].autoDrive : 'off'; shutterSettings[s].hysteresisOutside = shutterSettings[s].hysteresisOutside ? shutterSettings[s].hysteresisOutside : '5'; shutterSettings[s].hysteresisInside = shutterSettings[s].hysteresisInside ? shutterSettings[s].hysteresisInside : '5'; shutterSettings[s].hysteresisLight = shutterSettings[s].hysteresisLight ? shutterSettings[s].hysteresisLight : '5'; shutterSettings[s].XmasLevel = shutterSettings[s].XmasLevel ? shutterSettings[s].XmasLevel : '0'; shutterSettings[s].betweenPositionLevel = shutterSettings[s].betweenPositionLevel ? shutterSettings[s].betweenPositionLevel : '50'; shutterSettings[s].trigDelyUp = shutterSettings[s].trigDelyUp ? shutterSettings[s].trigDelyUp : '0'; shutterSettings[s].trigDelyDown = shutterSettings[s].trigDelyDown ? shutterSettings[s].trigDelyDown : '0'; shutterSettings[s].sunProtectEndDely = shutterSettings[s].sunProtectEndDely ? shutterSettings[s].sunProtectEndDely : '0'; shutterSettings[s].LateDown = shutterSettings[s].LateDown != null ? shutterSettings[s].LateDown : false; shutterSettings[s].inSummerNotDown = shutterSettings[s].inSummerNotDown != null ? shutterSettings[s].inSummerNotDown : false; shutterSettings[s].KeepSunProtect = shutterSettings[s].KeepSunProtect != null ? shutterSettings[s].KeepSunProtect : false; shutterSettings[s].driveAfterClose = shutterSettings[s].driveAfterClose != null ? shutterSettings[s].driveAfterClose : false; shutterSettings[s].useXmasLevel = shutterSettings[s].useXmasLevel != null ? shutterSettings[s].useXmasLevel : false; shutterSettings[s].betweenPosition = shutterSettings[s].betweenPosition != null ? shutterSettings[s].betweenPosition : false; shutterSettings[s].enableAlarmWind1 = shutterSettings[s].enableAlarmWind1 != null ? shutterSettings[s].enableAlarmWind1 : false; shutterSettings[s].enableAlarmWind2 = shutterSettings[s].enableAlarmWind2 != null ? shutterSettings[s].enableAlarmWind2 : false; shutterSettings[s].enableAlarmRain = shutterSettings[s].enableAlarmRain != null ? shutterSettings[s].enableAlarmRain : false; shutterSettings[s].enableAlarmFrost = shutterSettings[s].enableAlarmFrost != null ? shutterSettings[s].enableAlarmFrost : false; shutterSettings[s].enableAlarmFire = shutterSettings[s].enableAlarmFire != null ? shutterSettings[s].enableAlarmFire : false; if (num === parseFloat(s)) { adapter.log.debug('shutter Config Check successfully completed'); // @ts-ignore resolve(); } else { num++; } } } catch (e) { adapter.log.warn(`It is not possible to check the shutter configuration: ${e}`); // @ts-ignore resolve(); } } }); } // +++++++++++++++++ save states on start and shutter change ++++++++++++++++++++++++++++ async function saveCurrentStates(onStart) { if (onStart) { await shutterConfigCheck(); } let currentStates = {}; let shutterName = []; let num = 0; const _currentStates = await adapter.getStateAsync('shutters.currentStates').catch((e) => adapter.log.warn(e)); if (_currentStates && _currentStates.val && _currentStates.val !== null) { try { currentStates = JSON.parse(_currentStates.val); } catch (err) { adapter.log.debug('settings cannot be read from the state'); currentStates = {}; } } for (const s in shutterSettings) { const nameDevice = shutterSettings[s].shutterName.replace(/[.;, ]/g, '_'); shutterName.push(shutterSettings[s].shutterName); num++; if (currentStates && currentStates[`${nameDevice}`] && !onStart) { currentStates[`${nameDevice}`].currentAction = shutterSettings[s].currentAction; currentStates[`${nameDevice}`].currentHeight = shutterSettings[s].currentHeight; currentStates[`${nameDevice}`].triggerAction = shutterSettings[s].triggerAction; currentStates[`${nameDevice}`].triggerHeight = shutterSettings[s].triggerHeight; currentStates[`${nameDevice}`].oldHeight = shutterSettings[s].oldHeight; currentStates[`${nameDevice}`].firstCompleteUp = shutterSettings[s].firstCompleteUp; currentStates[`${nameDevice}`].alarmTriggerAction = shutterSettings[s].alarmTriggerAction; currentStates[`${nameDevice}`].alarmTriggerLevel = shutterSettings[s].alarmTriggerLevel; currentStates[`${nameDevice}`].lastAutoAction = shutterSettings[s].lastAutoAction; } else if (currentStates && currentStates[`${nameDevice}`] && onStart) { adapter.log.debug(`${nameDevice}: save settings`); shutterSettings[s].currentAction = currentStates[`${nameDevice}`].currentAction; shutterSettings[s].currentHeight = currentStates[`${nameDevice}`].currentHeight; shutterSettings[s].triggerAction = currentStates[`${nameDevice}`].triggerAction; shutterSettings[s].triggerHeight = currentStates[`${nameDevice}`].triggerHeight; shutterSettings[s].oldHeight = currentStates[`${nameDevice}`].oldHeight; shutterSettings[s].firstCompleteUp = currentStates[`${nameDevice}`].firstCompleteUp; shutterSettings[s].alarmTriggerAction = currentStates[`${nameDevice}`].alarmTriggerAction; shutterSettings[s].alarmTriggerLevel = currentStates[`${nameDevice}`].alarmTriggerLevel; shutterSettings[s].lastAutoAction = currentStates[`${nameDevice}`].lastAutoAction; } else if (currentStates && !currentStates[`${nameDevice}`] && onStart) { adapter.log.debug(`${nameDevice}: settings added`); currentStates[`${nameDevice}`] = null; const states = ({ shutterName: shutterSettings[s].shutterName, currentAction: shutterSettings[s].currentAction, currentHeight: shutterSettings[s].currentHeight, triggerAction: shutterSettings[s].triggerAction, triggerHeight: shutterSettings[s].triggerHeight, oldHeight: shutterSettings[s].oldHeight, firstCompleteUp: shutterSettings[s].firstCompleteUp, alarmTriggerLevel: shutterSettings[s].alarmTriggerLevel, alarmTriggerAction: shutterSettings[s].alarmTriggerAction, lastAutoAction: shutterSettings[s].lastAutoAction }); currentStates[`${nameDevice}`] = states; } if (num === shutterSettings.length && onStart) { for (const i in currentStates) { if (shutterName.indexOf(currentStates[i].shutterName) === -1) { const name = currentStates[i].shutterName.replace(/[.;, ]/g, '_') adapter.log.debug(`${name}: settings deleted`); delete currentStates[`${name}`]; } await sleep(2000); await adapter.setStateAsync('shutters.currentStates', { val: JSON.stringify(currentStates), ack: true }) .catch((e) => adapter.log.warn(e)); } } else if (num === shutterSettings.length && !onStart) { await adapter.setStateAsync('shutters.currentStates', { val: JSON.stringify(currentStates), ack: true }) .catch((e) => adapter.log.warn(e)); } await sleep(100); } } // +++++++++++++++++ Check States of Trigger after start ++++++++++++++++++++++++++++ async function checkStates() { const _holidayStates = await adapter.getStateAsync('control.Holiday').catch((e) => adapter.log.warn(e)); if ((_holidayStates && _holidayStates === null) || (_holidayStates && _holidayStates.val === null)) { await adapter.setStateAsync('control.Holiday', { val: false, ack: true }) .catch((e) => adapter.log.warn(e)); } const _schoolfreeStates = await adapter.getStateAsync('control.schoolfree').catch((e) => adapter.log.warn(e)); if ((_schoolfreeStates && _schoolfreeStates === null) || (_schoolfreeStates && _schoolfreeStates.val === null)) { await adapter.setStateAsync('control.schoolfree', { val: false, ack: true }) .catch((e) => adapter.log.warn(e)); } const _autoLivingStates = await adapter.getStateAsync('control.autoLiving').catch((e) => adapter.log.warn(e)); if ((_autoLivingStates && _autoLivingStates === null) || (_autoLivingStates && _autoLivingStates.val === null)) { await adapter.setStateAsync('control.autoLiving', { val: false, ack: true }) .catch((e) => adapter.log.warn(e)); } const _autoSleepStates = await adapter.getStateAsync('control.autoSleep').catch((e) => adapter.log.warn(e)); if ((_autoSleepStates && _autoSleepStates === null) || (_autoSleepStates && _autoSleepStates.val === null)) { await adapter.setStateAsync('control.autoSleep', { val: false, ack: true }) .catch((e) => adapter.log.warn(e)); } const _autoChildrenStates = await adapter.getStateAsync('control.autoChildren').catch((e) => adapter.log.warn(e)); if ((_autoChildrenStates && _autoChildrenStates === null) || (_autoChildrenStates && _autoChildrenStates.val === null)) { await adapter.setStateAsync('control.autoChildren', { val: false, ack: true }) .catch((e) => adapter.log.warn(e)); } } ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // +++++++++++++++++++ check all current States an changes +++++++++++++++++++++++++ async function checkActualStates() { const _holidayStates = await adapter.getStateAsync('control.Holiday').catch((e) => adapter.log.warn(e)); if (_holidayStates?.val !== null && _holidayStates?.val !== undefined) { HolidayStr = _holidayStates.val; } const _schoolfreeStates = await adapter.getStateAsync('control.schoolfree').catch((e) => adapter.log.warn(e)); if (_schoolfreeStates?.val !== null && _schoolfreeStates?.val !== undefined) { SchoolfreeStr = _schoolfreeStates.val; } const _autoLivingStates = await adapter.getStateAsync('control.autoLiving').catch((e) => adapter.log.warn(e)); if (_autoLivingStates?.val !== null && _autoLivingStates?.val !== undefined) { autoLivingStr = _autoLivingStates.val; } const _autoSleepStates = await adapter.getStateAsync('control.autoSleep').catch((e) => adapter.log.warn(e)); if (_autoSleepStates?.val !== null && _autoSleepStates?.val !== undefined) { autoSleepStr = _autoSleepStates.val; } const _autoChildrenStates = await adapter.getStateAsync('control.autoChildren').catch((e) => adapter.log.warn(e)); if (_autoChildrenStates?.val !== null && _autoChildrenStates?.val !== undefined) { autoChildrenStr = _autoChildrenStates.val; } if (adapter.config.publicHolidays === true && (adapter.config.publicHolInstance != 'none' || adapter.config.publicHolInstance != '')) { const _publicHolidayStr = await adapter.getForeignStateAsync(`${adapter.config.publicHolInstance}.heute.boolean`).catch((e) => adapter.log.warn(e)); if (_publicHolidayStr?.val !== null && _publicHolidayStr?.val !== undefined) { publicHolidayStr = _publicHolidayStr.val; } const _publicHolidayTomorowStr = await adapter.getForeignStateAsync(`${adapter.config.publicHolInstance}.morgen.boolean`).catch((e) => adapter.log.warn(e)); if (_publicHolidayTomorowStr?.val !== null && _publicHolidayTomorowStr?.val !== undefined) { publicHolidayTomorowStr = _publicHolidayTomorowStr.val; } } if (adapter.config.schoolfree === true && (adapter.config.schoolfreeInstance != 'none' || adapter.config.schoolfreeInstance != '')) { const _schoolfreeStr = await adapter.getForeignStateAsync(`${adapter.config.schoolfreeInstance}.info.today`).catch((e) => adapter.log.warn(e)); if (_schoolfreeStr?.val !== null && _schoolfreeStr?.val !== undefined) { schoolfreeStr = _schoolfreeStr.val; } const _schoolfreeTomorowStr = await adapter.getForeignStateAsync(`${adapter.config.schoolfreeInstance}.info.tomorrow`).catch((e) => adapter.log.warn(e)); if (_schoolfreeTomorowStr?.val !== null && _schoolfreeTomorowStr?.val !== undefined) { schoolfreeTomorowStr = _schoolfreeTomorowStr.val; } } if (adapter.config.HolidayDP !== '') { adapter.log.debug('checking HolidayDP'); const _HolidayDP = await adapter.getForeignStateAsync(adapter.config.HolidayDP).catch((e) => adapter.log.warn(e)); if (_HolidayDP?.val !== null && _HolidayDP?.val !== undefined) { adapter.log.debug(`got HolidayDP: ${_HolidayDP.val}`); await adapter.setStateAsync('control.Holiday', { val: _HolidayDP.val, ack: true }) .catch((e) => adapter.log.warn(e)); } } if (adapter.config.schoolfreeDP !== '') { adapter.log.debug('checking schoolfreeDP'); const _schoolfreeDP = await adapter.getForeignStateAsync(adapter.config.schoolfreeDP).catch((e) => adapter.log.warn(e)); if (_schoolfreeDP?.val !== null && _schoolfreeDP?.val !== undefined) { adapter.log.debug(`got schoolfreeDP: ${_schoolfreeDP.val}`); await adapter.setStateAsync('control.schoolfree', { val: _schoolfreeDP.val, ack: true }) .catch((e) => adapter.log.warn(e)); } } const _ObjautoUp = await adapter.getForeignObjectsAsync(`${adapter.namespace}.shutters.autoUp.*`, 'state').catch((e) => adapter.log.warn(e)); if (_ObjautoUp) { ObjautoUp = _ObjautoUp; } const _ObjautoDown = await adapter.getForeignObjectsAsync(`${adapter.namespace}.shutters.autoDown.*`, 'state').catch((e) => adapter.log.warn(e)); if (_ObjautoDown) { ObjautoDown = _ObjautoDown; } const _ObjautoSun = await adapter.getForeignObjectsAsync(`${adapter.namespace}.shutters.autoSun.*`, 'state').catch((e) => adapter.log.warn(e)); if (_ObjautoSun) { ObjautoSun = _ObjautoSun; } const _ObjautoState = await adapter.getForeignObjectsAsync(`${adapter.namespace}.shutters.autoState.*`, 'state').catch((e) => adapter.log.warn(e)); if (_ObjautoState) { ObjautoState = _ObjautoState; } const _ObjautoLevel = await adapter.getForeignObjectsAsync(`${adapter.namespace}.shutters.autoLevel.*`, 'state').catch((e) => adapter.log.warn(e)); if (_ObjautoLevel) { ObjautoLevel = _ObjautoLevel; } await sleep(1000); shutterDriveCalc(); createShutter(); } ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ++++++++++++++++++ reset current Action in the night at 02:30 +++++++++++++++++++++++ const calc = schedule.scheduleJob('calcTimer', '30 2 * * *', async function () { shutterDriveCalc(); const resultStates = shutterSettings; if (resultStates) { for (const i in resultStates) { const nameDevice = resultStates[i].shutterName.replace(/[.;, ]/g, '_'); const _shutterState = await adapter.getForeignStateAsync(resultStates[i].name).catch((e) => adapter.log.warn(e)); if (_shutterState?.val !== null && _shutterState?.val !== undefined) { // 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)); adapter.log.debug(`${resultStates[i].shutterName} set currentHeight to ${Math.round(_shutterState.val / adapter.config.shutterStateRound) * adapter.config.shutterStateRound}%`); if (_shutterState?.val !== null && _shutterState?.val !== undefined) { 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)); if (parseFloat(resultStates[i].heightDown) < parseFloat(resultStates[i].heightUp)) { adapter.log.d