UNPKG

iobroker.lightcontrol

Version:

Light control of lamps from various manufacturers

947 lines (832 loc) 33 kB
"use strict"; const { clearAutoOffTimeouts, clearRampOnIntervals, clearRampOffIntervals, clearBlinkIntervals } = require("./timers"); const { setDeviceBri, SetWhiteSubstituteColor, PowerOnAftercare, SetBrightness, SetColor, AdaptiveBri, SetCt, } = require("./lightHandling"); const { SetValueToObject } = require("./helper"); /** * SimpleGroupPowerOnOff * @param {Object} adapter Adapter-Class * @param {string} Group Group of Lightgroups eg. LivingRoom, Children1,... * @param {boolean} OnOff true/false from power state */ async function SimpleGroupPowerOnOff(adapter, Group, OnOff) { const LightGroups = adapter.LightGroups; const operation = OnOff ? "on" : "off"; try { if (!LightGroups[Group].lights?.length) { adapter.writeLog( `[ SimpleGroupPowerOnOff ] Not able to switching Group = "${Group}". No lights are defined!!`, "warn", ); return; } const outlast = OutlastDevices(adapter, LightGroups[Group].lights, OnOff); const useSwitch = BrightnessDevicesSwitchPower(adapter, LightGroups[Group].lights, OnOff); const useBrightness = LightGroups[Group].lights .filter((Light) => Light?.bri?.oid && Light?.bri?.useBri) .map(async (Light) => { const brightness = LightGroups[Group].adaptiveBri ? await AdaptiveBri(adapter, Group) : adapter.LightGroups[Group].bri; await Promise.all([ setDeviceBri(adapter, Light, OnOff ? brightness : 0), adapter.writeLog( `[ SimpleGroupPowerOnOff ] Switching ${operation} ${Light.description} (${Light.bri.oid}) with brightness state`, ), ]); }); await Promise.all([useBrightness, useSwitch, outlast]); return true; } catch (error) { adapter.errorHandling(error, "SimpleGroupPowerOnOff"); } } /** * GroupPowerOnOff * @param {object} adapter Adapter-Class * @param {string} Group Group of Lightgroups eg. LivingRoom, Children1,... * @param {boolean} OnOff true/false from power state */ async function GroupPowerOnOff(adapter, Group, OnOff) { const LightGroups = adapter.LightGroups; try { adapter.writeLog( `[ GroupPowerOnOff ] Reaching for Group="${Group}", OnOff="${OnOff}" rampOn="${ LightGroups[Group].rampOn.enabled }" - ${JSON.stringify(LightGroups[Group].rampOn)} rampOff="${ LightGroups[Group].rampOff.enabled }" - ${JSON.stringify(LightGroups[Group].rampOff)}`, ); if (!LightGroups[Group].lights.some((Light) => Light.power?.oid || Light.bri?.oid)) { await adapter.writeLog( `[ SimpleGroupPowerOnOff ] Not able to switching ${OnOff} for Group = "${Group}". No lights defined or no power or brightness states are defined!!`, "warn", ); return; } if (OnOff) { LightGroups[Group].power = true; // // ******* Anschalten ohne ramping * // // if (!LightGroups[Group].rampOn.enabled) { await SimpleGroupPowerOnOff(adapter, Group, OnOff); if (LightGroups[Group].autoOffTimed.enabled) { //Wenn Zeitabschaltung aktiv und Anschaltung, AutoOff aktivieren await AutoOffTimed(adapter, Group); } } else { await TurnOnWithRamping(adapter, Group); } } else { // Ausschalten ohne Ramping */ if (!LightGroups[Group].rampOff.enabled) { if (LightGroups[Group].rampOn.enabled) { //Vor dem ausschalten Helligkeit auf 2 (0+1 wird bei manchchen Devices als aus gewertet) um bei rampon nicht mit voller Pulle zu starten await SetBrightness(adapter, Group, 2, "ramping"); } await SimpleGroupPowerOnOff(adapter, Group, OnOff); LightGroups[Group].power = false; } else { // Ausschalten mit Ramping */ await TurnOffWithRamping(adapter, Group); } } await Promise.all([ adapter.setStateAsync(Group + ".power", OnOff, true), adapter.SetLightState("GroupPowerOnOff"), ]); return true; } catch (error) { adapter.errorHandling(error, "GroupPowerOnOff"); } } /** * DeviceSwitch simple lights with no brightness state * @description Ausgelagert von GroupOnOff da im Interval kein await möglich * @param {object} adapter Adapter-Class * @param {string} Group Group of Lightgroups eg. LivingRoom, Children1,... * @param {boolean} OnOff true/false from power state */ async function DeviceSwitch(adapter, Group, OnOff) { try { adapter.writeLog(`[ DeviceSwitch ] Reaching for Group="${Group}, OnOff="${OnOff}"`); const LightGroups = adapter.LightGroups; const promises = LightGroups[Group].lights.map(async (Light) => { if (!Light?.bri?.oid && Light?.power?.oid) { await Promise.all([ adapter.setForeignStateAsync(Light.power.oid, OnOff ? Light.power.onVal : Light.power.offVal), adapter.writeLog( `[ DeviceSwitch ] Switching ${Light.description} (${Light.power.oid}) to: ${OnOff}`, ), ]); } }); await Promise.all(promises); } catch (error) { adapter.errorHandling(error, "DeviceSwitch"); } } /** * DeviceSwitch lights before ramping (if brightness state available and not use Bri for ramping) * @description Ausgelagert von GroupOnOff da im Interval kein await möglich * @param {object} adapter Adapter-Class * @param {string} Group Group of Lightgroups eg. LivingRoom, Children1,... * @param {boolean} OnOff true/false from power state */ async function DeviceSwitchForRamping(adapter, Group, OnOff) { try { adapter.writeLog(`[ DeviceSwitchForRamping ] Reaching for Group="${Group}, OnOff="${OnOff}"`); const LightGroups = adapter.LightGroups; const promises = LightGroups[Group].lights.map(async (Light) => { //prüfen ob Helligkeitsdatenpunkt vorhanden UND useBri = false if (Light?.bri?.oid && !Light?.bri?.useBri && Light?.power?.oid) { await adapter.setForeignStateAsync(Light.power.oid, OnOff ? Light.power.onVal : Light.power.offVal); } }); await Promise.all(promises); } catch (error) { adapter.errorHandling(error, "DeviceSwitchForRamping"); } } /** * OutlastDevices simple lights with no brightness state * @description Switch simple lights with no brightness state * @async * @function * @param {object} adapter Adapter-Class * @param {array} Lights Group of Lightgroups eg. LivingRoom, Children1,... * @param {boolean} OnOff true/false from power state */ async function OutlastDevices(adapter, Lights, OnOff) { try { return Lights.filter((Light) => Light.power?.oid && !Light.bri?.oid).map(async (Light) => { await Promise.all([ adapter.setForeignStateAsync(Light.power.oid, OnOff ? Light.power.onVal : Light.power.offVal), adapter.writeLog( `[ DOutlastDevices ] Switching ${Light.description} (${Light.power.oid}) to: ${OnOff}`, ), ]); }); } catch (error) { adapter.errorHandling(error, "OutlastDevices"); } } /** * BrightnessDevicesSwitchPower * @description Switch lights before ramping (if brightness state available and not use Bri for ramping) * @async * @function * @param {object} adapter Adapter-Class * @param {array} Lights Group of Lightgroups eg. LivingRoom, Children1,... * @param {boolean} OnOff true/false from power state */ async function BrightnessDevicesSwitchPower(adapter, Lights, OnOff) { try { return Lights.filter((Light) => Light.power?.oid && Light.bri?.oid && !Light.bri?.useBri).map(async (Light) => { await Promise.all([ adapter.setForeignStateAsync(Light.power.oid, OnOff ? Light.power.onVal : Light.power.offVal), adapter.writeLog( `[ BrightnessDevicesSwitchPower ] Switching ${Light.description} (${Light.bri.oid}) to: ${OnOff}`, ), ]); }); } catch (error) { adapter.errorHandling(error, "BrightnessDevicesSwitchPower"); } } /** * BrightnessDevicesWithoutRampTime * @description Switch lights before ramping (if brightness state available and not use Bri for ramping) * @async * @function * @param {object} adapter Adapter-Class * @param {array} Lights Group of Lightgroups eg. LivingRoom, Children1,... * @param {number} Brightness true/false from power state */ /* async function BrightnessDevicesWithoutRampTime(adapter, Lights, Brightness) { try { return Lights.filter((Light) => Light.bri?.oid && Light.bri?.useBri && !Light.tt?.useTt).map(async (Light) => { await Promise.all([ adapter.setForeignStateAsync(Light.bri.oid, Brightness), adapter.writeLog( `[ BrightnessDevicesWithoutRampTime ] Set ${Light.description} (${Light.bri.oid}) to: ${Brightness}`, ), ]); }); } catch (error) { adapter.errorHandling(error, "BrightnessDevicesWithoutRampTime"); } } */ /** * BrightnessDevicesWithRampTime * @description Set Brighness to Lights with Transmission time * @async * @function * @param {object} adapter Adapter-Class * @param {array} Lights Group of Lightgroups eg. LivingRoom, Children1,... * @param {boolean} Brightness true/false from power state * @param {number} RampTime Information about the RampTime */ /* async function BrightnessDevicesWithRampTime(adapter, Lights, Brightness, RampTime) { try { return Lights.filter((Light) => Light.bri?.oid && Light.bri?.useBri && Light.tt?.useTt).map(async (Light) => { await Promise.all([ adapter.setForeignStateAsync(Light.bri.oid, Brightness), adapter.writeLog( `[ BrightnessDevicesWithRampTime ] Set ${Light.description} (${Light.bri.oid}) to: ${Brightness} in: ${RampTime}`, ), ]); }); } catch (error) { adapter.errorHandling(error, "BrightnessDevicesWithRampTime"); } } */ /** * TurnOnWithRamping * @param {object} adapter Adapter-Class * @param {string} Group Group of Lightgroups eg. LivingRoom, Children1,... * @returns {Promise<Boolean>} Ein Promise-Objekt, das ein Boolean zurückgibt. */ async function TurnOnWithRamping(adapter, Group) { const LightGroups = adapter.LightGroups; const RampSteps = adapter.GlobalSettings.RampSteps; let LoopCount = 0; // // ******* Anschalten mit ramping * // // if (LightGroups[Group].rampOn.enabled && LightGroups[Group].rampOn.switchOutletsLast) { adapter.writeLog(`[ GroupPowerOnOff ] Switch off with ramping and simple lamps last for Group="${Group}"`); await clearRampOnIntervals(adapter, Group); await BrightnessDevicesSwitchPower(adapter, LightGroups[Group].lights, true); adapter.RampOnIntervalObject[Group] = setInterval(async function () { LoopCount++; // Helligkeit erhöhen await SetBrightness( adapter, Group, Math.round(RampSteps * LoopCount * (LightGroups[Group].bri / 100)), "ramping", ); //Interval stoppen und einfache Lampen schalten if (LoopCount >= RampSteps) { await DeviceSwitch(adapter, Group, true); // Einfache Lampen if (LightGroups[Group].autoOffTimed.enabled) { //Wenn Zeitabschaltung aktiv und Anschaltung, AutoOff aktivieren await AutoOffTimed(adapter, Group); } await clearRampOnIntervals(adapter, Group); } }, Math.round(LightGroups[Group].rampOn.time / RampSteps) * 1000); } else if (LightGroups[Group].rampOn.enabled && !LightGroups[Group].rampOn.switchOutletsLast) { //Anschalten mit Ramping und einfache Lampen zuerst adapter.writeLog(`[ GroupPowerOnOff ] Anschalten mit Ramping und einfache Lampen zuerst für Group="${Group}`); await clearRampOnIntervals(adapter, Group); await DeviceSwitch(adapter, Group, true); // Einfache Lampen await DeviceSwitchForRamping(adapter, Group, true); //Restliche Lampen // Interval starten adapter.RampOnIntervalObject[Group] = setInterval(async function () { // Helligkeit erhöhen await SetBrightness( adapter, Group, Math.round(RampSteps * LoopCount * (LightGroups[Group].bri / 100)), "ramping", ); LoopCount++; // Intervall stoppen if (LoopCount >= RampSteps) { if (LightGroups[Group].autoOffTimed.enabled) { //Wenn Zeitabschaltung aktiv und Anschaltung, AutoOff aktivieren await AutoOffTimed(adapter, Group); } await clearRampOnIntervals(adapter, Group); } }, Math.round(LightGroups[Group].rampOn.time / RampSteps) * 1000); } return true; } /** * TurnOffWithRamping * @param {object} adapter Adapter-Class * @param {string} Group Group of Lightgroups eg. LivingRoom, Children1,... */ async function TurnOffWithRamping(adapter, Group) { const LightGroups = adapter.LightGroups; const RampSteps = adapter.GlobalSettings.RampSteps; let LoopCount = 0; // //******* Ausschalten mit Ramping */ // if (LightGroups[Group].rampOff.enabled && LightGroups[Group].rampOff.switchOutletsLast) { ////Ausschalten mit Ramping und einfache Lampen zuletzt adapter.writeLog( `[ GroupPowerOnOff ] Ausschalten mit Ramping und einfache Lampen zuletzt für Group="${Group}"`, ); await clearRampOffIntervals(adapter, Group); // Interval starten adapter.RampOffIntervalObject[Group] = setInterval(async function () { // Helligkeit veringern await SetBrightness( adapter, Group, LightGroups[Group].bri - LightGroups[Group].bri / RampSteps - Math.round(RampSteps * LoopCount * (LightGroups[Group].bri / 100)), "ramping", ); LoopCount++; // Intervall stoppen if (LoopCount >= RampSteps) { await clearRampOffIntervals(adapter, Group); await DeviceSwitchForRamping(adapter, Group, false); //restliche Lampen await DeviceSwitch(adapter, Group, false); // einfache Lampen LightGroups[Group].power = false; adapter.writeLog(`Result of TurnOffWithRamping: ${LightGroups[Group].power}`); } }, Math.round(LightGroups[Group].rampOff.time / RampSteps) * 1000); } else if (LightGroups[Group].rampOff.enabled && !LightGroups[Group].rampOff.switchOutletsLast) { ////Ausschalten mit Ramping und einfache Lampen zuerst adapter.writeLog(`[ GroupPowerOnOff ] Ausschalten mit Ramping und einfache Lampen zuerst für Group="${Group}`); //Ausschalten von Lampen, welche keinen Brighness State haben await clearRampOffIntervals(adapter, Group); await DeviceSwitch(adapter, Group, false); // einfache Lampen // Intervall starten adapter.RampOffIntervalObject[Group] = setInterval(async function () { await SetBrightness( adapter, Group, LightGroups[Group].bri - LightGroups[Group].bri / RampSteps - Math.round(RampSteps * LoopCount * (LightGroups[Group].bri / 100)), "ramping", ); LoopCount++; // Intervall stoppen if (LoopCount >= RampSteps) { await DeviceSwitchForRamping(adapter, Group, false); // restliche Lampen await clearRampOffIntervals(adapter, Group); LightGroups[Group].power = false; adapter.writeLog(`Result of TurnOffWithRamping: ${LightGroups[Group].power}`); } }, Math.round(LightGroups[Group].rampOff.time / RampSteps) * 1000); } } /** * GroupPowerCleaningLightOnOff * @param {object} adapter Adapter-Class * @param {string} Group Group of Lightgroups eg. LivingRoom, Children1,... * @param {boolean} OnOff true/false from power state */ async function GroupPowerCleaningLightOnOff(adapter, Group, OnOff) { const LightGroups = adapter.LightGroups; const funcName = "GroupPowerCleaningLightOnOff"; try { adapter.writeLog(`[ ${funcName} ] Reaching GroupPowerCleaningLightOnOff for Group="${Group}, OnOff="${OnOff}"`); await clearAutoOffTimeouts(adapter, Group); if (OnOff) { if (LightGroups[Group].power) { await Promise.all([ SetBrightness(adapter, Group, 100), SetCt(adapter, Group, adapter.Settings.maxCt || 6500), ]); LightGroups[Group].lastPower = true; } else { adapter.LightGroups[Group].power = true; adapter.LightGroups[Group].lastPower = false; await SimpleGroupPowerOnOff(adapter, Group, true); await Promise.all([ SetBrightness(adapter, Group, 100), SetCt(adapter, Group, adapter.Settings.maxCt || 6500), adapter.setStateAsync(Group + ".power", true, true), ]); } } else { const brightness = LightGroups[Group].adaptiveBri ? await AdaptiveBri(adapter, Group) : LightGroups[Group].bri; await Promise.all([ SetBrightness(adapter, Group, brightness), SetCt(adapter, Group, LightGroups[Group].ct), ]); if (!LightGroups[Group].lastPower) { LightGroups[Group].power = false; await Promise.all([ SimpleGroupPowerOnOff(adapter, Group, false), adapter.setStateAsync(Group + ".power", false, true), ]); } } await adapter.setStateAsync(Group + ".powerCleaningLight", OnOff, true); } catch (error) { adapter.errorHandling(error, funcName, `Group="${Group}"`); } } /** * AutoOnLux * @param {object} adapter Adapter-Class * @param {string} Group Group of Lightgroups eg. LivingRoom, Children1,... */ async function AutoOnLux(adapter, Group) { const LightGroups = adapter.LightGroups; try { adapter.log.debug( `Reaching AutoOnLux for Group="${Group} enabled="${LightGroups[Group].autoOnLux?.enabled}", actuallux="${LightGroups[Group].actualLux}", minLux="${LightGroups[Group].autoOnLux?.minLux}" LightGroups[Group].autoOnLux.dailyLock="${LightGroups[Group].autoOnLux?.dailyLock}"`, ); let tempBri = 0; let tempColor = ""; let minLux = 500; if (LightGroups[Group].autoOnLux?.minLux === undefined) { minLux = 500; adapter.writeLog(`[ AutoOnLux ] No minLux defined for Group="${Group}". Use default minLux of 500lux`); } if (LightGroups[Group].autoOnLux?.operator == "<") { if ( LightGroups[Group].autoOnLux?.enabled && !LightGroups[Group].power && !LightGroups[Group].autoOnLux?.dailyLock && LightGroups[Group].actualLux <= minLux ) { adapter.log.info(`AutoOn_Lux() activated Group="${Group}"`); if ( (LightGroups[Group].autoOnLux?.switchOnlyWhenPresence && adapter.ActualPresence) || (LightGroups[Group].autoOnLux?.switchOnlyWhenNoPresence && !adapter.ActualPresence) ) { await GroupPowerOnOff(adapter, Group, true); tempBri = LightGroups[Group].autoOnLux?.bri !== 0 ? LightGroups[Group].autoOnLux?.bri : (tempBri = LightGroups[Group].bri); await SetWhiteSubstituteColor(adapter, Group); tempColor = LightGroups[Group].autoOnLux?.color !== "" ? LightGroups[Group].autoOnLux?.color : (tempColor = LightGroups[Group].color); await PowerOnAftercare(adapter, Group, tempBri, LightGroups[Group].ct, tempColor); } LightGroups[Group].autoOnLux.dailyLock = true; await adapter.setStateAsync(Group + ".autoOnLux.dailyLock", true, true); } else if (LightGroups[Group].autoOnLux.dailyLock && LightGroups[Group].actualLux > minLux) { //DailyLock zurücksetzen LightGroups[Group].autoOnLux.dailyLockCounter++; if (LightGroups[Group].autoOnLux.dailyLockCounter >= 5) { //5 Werte abwarten = Ausreisserschutz wenns am morgen kurz mal dunkler wird LightGroups[Group].autoOnLux.dailyLockCounter = 0; LightGroups[Group].autoOnLux.dailyLock = false; await adapter.setStateAsync(Group + ".autoOnLux.dailyLock", false, true); adapter.log.info(`AutoOn_Lux() setting DailyLock to ${LightGroups[Group].autoOnLux.dailyLock}`); } } } else if (LightGroups[Group].autoOnLux.operator == ">") { if ( LightGroups[Group].autoOnLux.enabled && !LightGroups[Group].power && !LightGroups[Group].autoOnLux.dailyLock && LightGroups[Group].actualLux >= minLux ) { adapter.log.info(`AutoOn_Lux() activated Group="${Group}"`); if ( (LightGroups[Group].autoOnLux.switchOnlyWhenPresence && adapter.ActualPresence) || (LightGroups[Group].autoOnLux.switchOnlyWhenNoPresence && !adapter.ActualPresence) ) { await GroupPowerOnOff(adapter, Group, true); tempBri = LightGroups[Group].autoOnLux.bri !== 0 ? LightGroups[Group].autoOnLux.bri : (tempBri = LightGroups[Group].bri); await SetWhiteSubstituteColor(adapter, Group); tempColor = LightGroups[Group].autoOnLux.color !== "" ? LightGroups[Group].autoOnLux.color : LightGroups[Group].color; await PowerOnAftercare(adapter, Group, tempBri, LightGroups[Group].ct, tempColor); } LightGroups[Group].autoOnLux.dailyLock = true; await adapter.setStateAsync(Group + ".autoOnLux.dailyLock", true, true); } else if (LightGroups[Group].autoOnLux.dailyLock && LightGroups[Group].actualLux < minLux) { //DailyLock zurücksetzen LightGroups[Group].autoOnLux.dailyLockCounter++; if (LightGroups[Group].autoOnLux.dailyLockCounter >= 5) { //5 Werte abwarten = Ausreisserschutz wenns am morgen kurz mal dunkler wird LightGroups[Group].autoOnLux.dailyLockCounter = 0; LightGroups[Group].autoOnLux.dailyLock = false; await adapter.setStateAsync(Group + ".autoOnLux.dailyLock", false, true); adapter.log.info(`AutoOn_Lux => setting DailyLock to ${LightGroups[Group].autoOnLux.dailyLock}`); } } } } catch (error) { adapter.errorHandling(error, "AutoOnLux", JSON.stringify(LightGroups[Group].autoOnLux)); } } /** * AutoOnMotion * @param {object} adapter Adapter-Class * @param {string} Group Group of Lightgroups eg. LivingRoom, Children1,... */ async function AutoOnMotion(adapter, Group) { const LightGroups = adapter.LightGroups; try { let tempBri = 0; let tempColor = ""; adapter.writeLog( `Reaching AutoOnMotion for Group:"${Group}, enabled="${LightGroups[Group].autoOnMotion?.enabled}", actuallux="${LightGroups[Group].actualLux}", minLux="${LightGroups[Group].autoOnMotion.minLux}"`, ); if ( LightGroups[Group].autoOnMotion?.enabled && LightGroups[Group].actualLux < LightGroups[Group].autoOnMotion?.minLux && LightGroups[Group].isMotion ) { adapter.writeLog(`Motion for Group="${Group} detected, switching on`, "info"); await GroupPowerOnOff(adapter, Group, true); tempBri = LightGroups[Group].autoOnMotion?.bri !== 0 ? LightGroups[Group].autoOnMotion?.bri : (tempBri = LightGroups[Group].bri); await SetWhiteSubstituteColor(adapter, Group); tempColor = LightGroups[Group].autoOnMotion?.color !== "" ? LightGroups[Group].autoOnMotion?.color : (tempColor = LightGroups[Group].color); await PowerOnAftercare(adapter, Group, tempBri, LightGroups[Group].ct, tempColor); } } catch (error) { adapter.errorHandling(error, "AutoOnMotion", JSON.stringify(LightGroups[Group].autoOnMotion)); } } /** * AutoOnPresenceIncrease * @param {object} adapter Adapter-Class */ async function AutoOnPresenceIncrease(adapter) { try { adapter.log.debug(`Reaching AutoOnPresenceIncrease`); const LightGroups = adapter.LightGroups; let tempBri = 0; let tempColor = ""; for (const Group in LightGroups) { if (Group === "All") continue; if ( LightGroups[Group].autoOnPresenceIncrease.enabled && LightGroups[Group].actualLux < LightGroups[Group].autoOnPresenceIncrease.minLux && !LightGroups[Group].power ) { await GroupPowerOnOff(adapter, Group, true); tempBri = LightGroups[Group].autoOnPresenceIncrease.bri !== 0 ? LightGroups[Group].autoOnPresenceIncrease.bri : LightGroups[Group].bri; await SetWhiteSubstituteColor(adapter, Group); tempColor = LightGroups[Group].autoOnPresenceIncrease.color !== "" ? LightGroups[Group].autoOnPresenceIncrease.color : (tempColor = LightGroups[Group].color); await PowerOnAftercare(adapter, Group, tempBri, LightGroups[Group].ct, tempColor); } } } catch (e) { adapter.writeLog(`AutoOnPresenceIncrease => ${e}`, "error"); } } /** * Blink * @param {object} adapter Adapter-Class * @param {string} Group Group of Lightgroups eg. LivingRoom, Children1,... */ async function blink(adapter, Group) { try { adapter.setStateAsync(Group + ".blink.enabled", true, true); const LightGroups = adapter.LightGroups; let loopcount = 0; //Save actual power state await SetValueToObject(LightGroups[Group], "blink.actual_power", LightGroups[Group].power); if (!LightGroups[Group].power) { //Wenn Gruppe aus, anschalten und ggfs. Helligkeit und Farbe setzen adapter.writeLog(`[ Blink ] on ${loopcount}`, "info"); for (const Light of LightGroups[Group].lights) { if (!Light?.power?.oid && !Light?.bri?.oid) { adapter.writeLog( `[ Blink ] Can't switch on. No power or brightness state defined for Light = "${Light.description}" in Group = "${Group}"`, "warn", ); } else if (Light?.bri?.useBri && Light?.bri?.oid) { await adapter.setForeignStateAsync(Light.bri.oid, LightGroups[Group].blink.bri, false); adapter.writeLog(`[ Blink ] Switching ${Light.description} ${Light.bri.oid} to: on`); } else if (Light?.power?.oid) { await adapter.setForeignStateAsync(Light.power.oid, Light.power.onVal, false); adapter.writeLog(`[ Blink ] Switching ${Light.description} ${Light.power.oid} to: on`); if (Light?.bri?.oid && LightGroups[Group].blink.bri !== 0) await setDeviceBri(adapter, Light, LightGroups[Group].blink.bri); } } LightGroups[Group].power = true; await adapter.setStateAsync(Group + ".power", true, true); await SetWhiteSubstituteColor(adapter, Group); if (LightGroups[Group].blink.color != "") await SetColor(adapter, Group, LightGroups[Group].blink.color); loopcount++; } await clearBlinkIntervals(adapter, Group); adapter.BlinkIntervalObj[Group] = setInterval(async function () { // Wenn loopcount++; adapter.writeLog(`[ Blink ] Is Infinite: ${LightGroups[Group].blink.infinite}`); adapter.writeLog(`[ Blink ] Stop: ${LightGroups[Group].blink.stop || false}`); if ( (loopcount <= LightGroups[Group].blink.blinks * 2 || LightGroups[Group].blink.infinite) && !LightGroups[Group].blink.stop ) { if (LightGroups[Group].power) { adapter.writeLog(`[ Blink ] off ${loopcount}`, "info"); for (const Light of LightGroups[Group].lights) { if (!Light?.power?.oid && !Light?.bri?.oid) { adapter.writeLog( `[ Blink ] Can't switch off. No power or brightness state defined for Light = "${Light.description}" in Group = "${Group}"`, "warn", ); } else if (Light?.bri?.useBri && Light?.bri?.oid) { await adapter.setForeignStateAsync(Light.bri.oid, 0, false); adapter.writeLog(`[ Blink ] Switching ${Light.description} ${Light.bri.oid} to: off`); } else if (Light?.power?.oid) { await adapter.setForeignStateAsync(Light.power.oid, Light.power.offVal, false); adapter.writeLog(`[ Blink ] Switching ${Light.description} ${Light.power.oid} to: on`); } } await SetWhiteSubstituteColor(adapter, Group); if (LightGroups[Group].blink.color != "") await SetColor(adapter, Group, LightGroups[Group].blink.color); LightGroups[Group].power = false; adapter.setStateAsync(Group + ".power", false, true); //adapter.SetLightState(); } else { adapter.writeLog(`Blink => on ${loopcount}`, "info"); for (const Light of LightGroups[Group].lights) { if (!Light?.power?.oid && !Light?.bri?.oid) { adapter.writeLog( `[ Blink ] Can't switch on. No power or brightness state defined for Light = "${Light.description}" in Group = "${Group}"`, "warn", ); } else if (Light?.bri?.useBri && Light?.bri?.oid) { await adapter.setForeignStateAsync(Light.bri.oid, LightGroups[Group].blink.bri, false); adapter.writeLog(`[ Blink ] Switching ${Light.description} ${Light.bri.oid} to: on`); } else if (Light?.power?.oid) { await adapter.setForeignStateAsync(Light.power.oid, Light.power.onVal, false); adapter.writeLog(`[ Blink ] Switching ${Light.description} ${Light.power.oid} to: on`); } } LightGroups[Group].power = true; adapter.setStateAsync(Group + ".power", true, true); //adapter.SetLightState(); } } else { await clearBlinkIntervals(adapter, Group); adapter.setStateAsync(Group + ".blink.enabled", false, true); if (LightGroups[Group].blink.infinite || LightGroups[Group].blink.actual_power) { await adapter.setStateAsync(Group + ".power", LightGroups[Group].blink.actual_power, false); await SetColor(adapter, Group, LightGroups[Group].color); } } }, LightGroups[Group].blink.frequency * 1000); } catch (error) { adapter.errorHandling(error, "blink"); } } /** * AutoOffLux * @param {object} adapter Adapter-Class * @param {string} Group Group of Lightgroups eg. LivingRoom, Children1,... */ async function AutoOffLux(adapter, Group) { //Handling für AutoOffLux try { const LightGroups = adapter.LightGroups; adapter.writeLog(`[ AutoOffLux ] Reaching for Group="${Group}"`); if ( LightGroups[Group].autoOffLux.operator == "<" && LightGroups[Group].actualLux < LightGroups[Group].autoOffLux.minLux && LightGroups[Group].autoOffLux.enabled && LightGroups[Group].power && !LightGroups[Group].autoOffLux.dailyLock ) { await GroupPowerOnOff(adapter, Group, false); LightGroups[Group].autoOffLux.dailyLock = true; await adapter.setStateAsync(Group + ".autoOffLux.dailyLock", true, true); } else if ( LightGroups[Group].autoOffLux.operator == ">" && LightGroups[Group].actualLux > LightGroups[Group].autoOffLux.minLux && LightGroups[Group].autoOffLux.enabled && LightGroups[Group].power && !LightGroups[Group].autoOffLux.dailyLock ) { await GroupPowerOnOff(adapter, Group, false); LightGroups[Group].autoOffLux.dailyLock = true; await adapter.setStateAsync(Group + ".autoOffLux.dailyLock", true, true); } if (LightGroups[Group].autoOffLux.operator == "<") { //DailyLock resetten if ( LightGroups[Group].actualLux > LightGroups[Group].autoOffLux.minLux && LightGroups[Group].autoOffLux.dailyLock ) { LightGroups[Group].autoOffLux.dailyLockCounter++; if (LightGroups[Group].autoOffLux.dailyLockCounter >= 5) { LightGroups[Group].autoOffLux.dailyLock = false; await adapter.setStateAsync(Group + ".autoOffLux.dailyLock", false, true); LightGroups[Group].autoOffLux.dailyLockCounter = 0; } } } else if (LightGroups[Group].autoOffLux.operator == ">") { if ( LightGroups[Group].actualLux < LightGroups[Group].autoOffLux.minLux && LightGroups[Group].autoOffLux.dailyLock ) { LightGroups[Group].autoOffLux.dailyLockCounter++; if (LightGroups[Group].autoOffLux.dailyLockCounter >= 5) { LightGroups[Group].autoOffLux.dailyLock = false; await adapter.setStateAsync(Group + ".autoOffLux.dailyLock", false, true); LightGroups[Group].autoOffLux.dailyLockCounter = 0; } } } } catch (error) { adapter.errorHandling(error, "AutoOffLux", "Group: " + Group); } } /** * AutoOffTimed * @param {object} adapter Adapter-Class * @param {string} Group Group of Lightgroups eg. LivingRoom, Children1,... */ async function AutoOffTimed(adapter, Group) { try { const LightGroups = adapter.LightGroups; adapter.writeLog( `[ AutoOffTimed ] Reaching for Group="${Group}" set time="${LightGroups[Group].autoOffTimed.autoOffTime}" LightGroups[${Group}].isMotion="${LightGroups[Group].isMotion}" LightGroups[${Group}].autoOffTimed.noAutoOffWhenMotion="${LightGroups[Group].autoOffTimed.noAutoOffWhenMotion}"`, ); await clearAutoOffTimeouts(adapter, Group); if (LightGroups[Group].autoOffTimed.enabled) { adapter.writeLog(`[ AutoOffTimed ] Start Timeout`); adapter.AutoOffTimeoutObject[Group] = setTimeout(async function () { // Interval starten if (LightGroups[Group].autoOffTimed.noAutoOffWhenMotion && LightGroups[Group].isMotion) { //Wenn noAutoOffWhenmotion aktiv und Bewegung erkannt adapter.writeLog( `[ AutoOffTimed ] Motion already detected, restarting Timeout for Group="${Group}" set time="${LightGroups[Group].autoOffTimed.autoOffTime}"`, ); adapter.writeLog(`[ AutoOffTimed ] Timer: ${JSON.stringify(adapter.AutoOffTimeoutObject[Group])}`); await AutoOffTimed(adapter, Group); } else { adapter.writeLog( `[ AutoOffTimed ] Group="${Group}" timed out, switching off. Motion="${LightGroups[Group].isMotion}"`, ); await GroupPowerOnOff(adapter, Group, false); } }, Math.round(LightGroups[Group].autoOffTimed.autoOffTime) * 1000); } } catch (error) { adapter.errorHandling(error, "AutoOffTimed", "Group: " + Group); } } /** * SetMasterPower * @param {object} adapter Adapter-Class * @param NewVal New Value of state */ async function SetMasterPower(adapter, NewVal) { const funcName = "SetMasterPower"; try { const LightGroups = adapter.LightGroups; adapter.writeLog(`[ ${funcName} ] Reaching SetMasterPower`); const promises = Object.keys(LightGroups) .filter((Group) => Group !== "All") .map((Group) => { adapter.writeLog(`[ ${funcName} ] Switching Group="${Group}" to ${NewVal}`); return adapter.setStateAsync(Group + ".power", NewVal, false); }); await Promise.all(promises); } catch (error) { adapter.errorHandling(error, "SetMasterPower"); } } module.exports = { SimpleGroupPowerOnOff, GroupPowerCleaningLightOnOff, GroupPowerOnOff, AutoOnLux, AutoOnMotion, AutoOnPresenceIncrease, blink, AutoOffLux, AutoOffTimed, SetMasterPower, };