module.exports = function (RED) { "use strict"; var SunCalc = require('suncalc'); const spacetime = require("spacetime") const SUNRISE_KEY = "sunrise"; const SUNSET_KEY = "sunset"; function TimeswitchNode(n) { RED.nodes.createNode(this, n); this.lat = n.lat; this.lon = n.lon; this.startt = n.starttime; this.endt = n.endtime; this.sunriseOffset = n.dawnoff; this.sunsetOffset = n.duskoff; this.mytopic = n.mytopic; this.timezone = n.timezone || "UTC"; this.sun = n.sun; this.mon = n.mon; this.tue = n.tue; this.wed = n.wed; this.thu = n.thu; this.fri = n.fri; this.sat = n.sat; this.jan = n.jan; this.feb = n.feb; this.mar = n.mar; this.apr = n.apr; this.may = n.may; this.jun = n.jun; this.jul = n.jul; this.aug = n.aug; this.sep = n.sep; this.oct = n.oct; this.nov = n.nov; this.dec = n.dec; var node = this; this.on("input", function () { // current global time const now = spacetime.now(); const nowNative = now.toNativeDate(); // all sun events for the given lat/long const sunEvents = SunCalc.getTimes(nowNative, node.lat, node.lon); const sunAlt = SunCalc.getPosition(nowNative, node.lat, node.lon).altitude; var sunriseDateTime = spacetime(sunEvents[SUNRISE_KEY]).nearest("minute"); var sunsetDateTime = spacetime(sunEvents[SUNSET_KEY]).nearest("minute"); if (sunEvents[SUNRISE_KEY] == "Invalid Date") { if (sunAlt >= 0) { sunriseDateTime = now.startOf("day"); } else { sunriseDateTime = now.endOf("day"); } } if (sunEvents[SUNSET_KEY] == "Invalid Date") { if (sunAlt >= 0) { sunsetDateTime = now.endOf("day"); } else { sunsetDateTime = now.startOf("day"); } } // add optional sun event offset, if specified sunriseDateTime = sunriseDateTime.add(Number(node.sunriseOffset), "minutes"); sunsetDateTime = sunsetDateTime.add(Number(node.sunsetOffset), "minutes"); // check if sun event has already occurred today if (now.isAfter(sunriseDateTime)) { // get tomorrow's sunrise, since it'll be different // sunriseDateTime = spacetime(SunCalc.getTimes(now.add(1, "day").toNativeDate(), node.lat, node.lon)[SUNRISE_KEY]).nearest("minute"); sunriseDateTime = sunriseDateTime.add(1, "day"); // add optional sun event offset, if specified (again) sunriseDateTime = sunriseDateTime.add(Number(node.sunriseOffset), "minutes"); } if (now.isAfter(sunsetDateTime)) { // get tomorrow's sunset, since it'll be different // sunsetDateTime = spacetime(SunCalc.getTimes(now.add(1, "day").toNativeDate(), node.lat, node.lon)[SUNSET_KEY]).nearest("minute"); sunsetDateTime = sunsetDateTime.add(1, "day"); // add optional sun event offset, if specified (again) sunsetDateTime = sunsetDateTime.add(Number(node.sunsetOffset), "minutes"); } // log sun events if (RED.settings.verbose) { node.log(`Sunrise ${sunriseDateTime.format("time")} - Sunset ${sunsetDateTime.format("time")} `); } // apply selected timezone to selected times (not to sunrise/sunset-- those are based on lat/long) const currentTimeZone = now.timezone(); const selectedTimeZone = spacetime(now.epoch, this.timezone.toLowerCase()).timezone(); // handler function to convert minute strings (from