node-red-nodes/time/timeswitch/timeswitch.js

160 lines
6.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

module.exports = function(RED) {
"use strict";
var SunCalc = require('suncalc');
function TimeswitchNode(n) {
RED.nodes.createNode(this, n);
this.lat = n.lat;
this.lon = n.lon;
this.start = n.start || "sunrise";
this.end = n.end || "sunset";
this.startt = n.starttime;
this.endt = n.endtime;
this.duskoff = n.duskoff;
this.dawnoff = n.dawnoff;
this.mytopic = n.mytopic;
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;
var ison = 0;
var newendtime = 0;
this.on("input", function(msg2) {
if (msg2.payload === "reset") { ison = 0; }
var now = new Date();
var nowoff = -now.getTimezoneOffset() * 60000;
var nowMillis = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes(), 0);
nowMillis += nowoff;
var midnightMillis = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), 0, 0);
var today = Math.round((nowMillis - midnightMillis) / 60000) % 1440;
var starttime = Number(node.startt);
var endtime = Number(node.endt);
if ((starttime >= 5000) || (endtime == 5000) || (endtime == 6000)) {
var times = SunCalc.getTimes(now, node.lat, node.lon);
var startMillis = Date.UTC(times[node.start].getUTCFullYear(), times[node.start].getUTCMonth(), times[node.start].getUTCDate(), times[node.start].getUTCHours(), times[node.start].getUTCMinutes());
var endMillis = Date.UTC(times[node.end].getUTCFullYear(), times[node.end].getUTCMonth(), times[node.end].getUTCDate(), times[node.end].getUTCHours(), times[node.end].getUTCMinutes());
startMillis += nowoff;
endMillis += nowoff;
var dawn = ((startMillis - midnightMillis) / 60000) + Number(node.dawnoff);
var dusk = ((endMillis - midnightMillis) / 60000) + Number(node.duskoff);
if (starttime == 5000) { starttime = dawn; }
if (starttime == 6000) { starttime = dusk; }
if (endtime == 5000) { endtime = dawn; }
if (endtime == 6000) { endtime = dusk; }
if (RED.settings.verbose) { node.log("Dawn " + parseInt(dawn / 60) + ":" + dawn % 60 + " - Dusk " + parseInt(dusk / 60) + ":" + dusk % 60); }
}
var proceed = 0;
switch (now.getDay()) {
case 0 : { if (node.sun) { proceed++; } break; }
case 1 : { if (node.mon) { proceed++; } break; }
case 2 : { if (node.tue) { proceed++; } break; }
case 3 : { if (node.wed) { proceed++; } break; }
case 4 : { if (node.thu) { proceed++; } break; }
case 5 : { if (node.fri) { proceed++; } break; }
case 6 : { if (node.sat) { proceed++; } break; }
}
if (proceed) {
switch (now.getMonth()) {
case 0 : { if (node.jan) { proceed++; } break; }
case 1 : { if (node.feb) { proceed++; } break; }
case 2 : { if (node.mar) { proceed++; } break; }
case 3 : { if (node.apr) { proceed++; } break; }
case 4 : { if (node.may) { proceed++; } break; }
case 5 : { if (node.jun) { proceed++; } break; }
case 6 : { if (node.jul) { proceed++; } break; }
case 7 : { if (node.aug) { proceed++; } break; }
case 8 : { if (node.sep) { proceed++; } break; }
case 9 : { if (node.oct) { proceed++; } break; }
case 10: { if (node.nov) { proceed++; } break; }
case 11: { if (node.dec) { proceed++; } break; }
}
}
if (proceed >= 2) { proceed = 1; }
else { proceed = 0; }
newendtime = endtime;
if (endtime > 10000) { newendtime = starttime + (endtime - 10000); }
if (proceed) { // have to handle midnight wrap
if (starttime <= newendtime) {
if ((today >= starttime) && (today <= newendtime)) { proceed++; }
}
else {
if ((today >= starttime) || (today <= newendtime)) { proceed++; }
}
}
if (proceed >= 2) {
var duration = newendtime - today;
if (today > newendtime) { duration += 1440; }
//node.status({fill:"yellow",shape:"dot",text:"on for " + duration + " mins"});
node.status({fill:"yellow", shape:"dot", text:"on until " + parseInt(newendtime / 60) + ":" + ("0" + newendtime % 60).substr(-2)});
}
//else { node.status({fill:"blue",shape:"dot",text:"off"}); }
else { node.status({fill:"blue", shape:"dot", text:"off until " + parseInt(starttime / 60) + ":" + ("0" + starttime % 60).substr(-2)}); }
var msg = {};
if (node.mytopic) { msg.topic = node.mytopic; }
msg.payload = (proceed >= 2) ? 1 : 0;
node.send(msg);
});
var tock = setTimeout(function() {
node.emit("input", {});
}, 2000); // wait 2 secs before starting to let things settle down e.g. UI connect
var tick = setInterval(function() {
node.emit("input", {});
}, 60000); // trigger every 60 secs
this.on("close", function() {
if (tock) { clearTimeout(tock); }
if (tick) { clearInterval(tick); }
});
}
RED.httpAdmin.post("/timeswitch/:id", RED.auth.needsPermission("timeswitch.write"), function(req, res) {
var node = RED.nodes.getNode(req.params.id);
if (node != null) {
try {
node.emit("input", {payload:"reset"});
res.sendStatus(200);
}
catch (err) {
res.sendStatus(500);
node.error("Inject failed:" + err);
}
}
else {
res.sendStatus(404);
}
});
RED.nodes.registerType("timeswitch", TimeswitchNode);
};