2015-11-02 18:24:27 +01:00
|
|
|
|
/**
|
|
|
|
|
* Copyright 2015 IBM Corp.
|
|
|
|
|
*
|
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
|
*
|
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
*
|
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
|
* limitations under the License.
|
|
|
|
|
*
|
|
|
|
|
* Based on work by P.Scargill and D.Conway-Jones
|
|
|
|
|
*
|
|
|
|
|
**/
|
|
|
|
|
|
|
|
|
|
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());
|
2016-02-15 12:12:29 +01:00
|
|
|
|
var endMillis = Date.UTC(times[node.end].getUTCFullYear(), times[node.end].getUTCMonth(), times[node.end].getUTCDate(), times[node.end].getUTCHours(), times[node.end].getUTCMinutes());
|
2015-11-02 18:24:27 +01:00
|
|
|
|
startMillis += nowoff;
|
2016-02-15 12:12:29 +01:00
|
|
|
|
endMillis += nowoff;
|
2015-11-02 18:24:27 +01:00
|
|
|
|
var dawn = ((startMillis - midnightMillis) / 60000) + Number(node.dawnoff);
|
2016-02-15 12:12:29 +01:00
|
|
|
|
var dusk = ((endMillis - midnightMillis) / 60000) + Number(node.duskoff);
|
2015-11-02 18:24:27 +01:00
|
|
|
|
if (starttime == 5000) { starttime = dawn; }
|
|
|
|
|
if (starttime == 6000) { starttime = dusk; }
|
2016-02-15 12:12:29 +01:00
|
|
|
|
if (endtime == 5000) { endtime = dawn; }
|
|
|
|
|
if (endtime == 6000) { endtime = dusk; }
|
2015-11-02 18:24:27 +01:00
|
|
|
|
if (RED.settings.verbose) { node.log("Dawn " + parseInt(dawn / 60) + ":" + dawn % 60 + " - Dusk " + parseInt(dusk / 60) + ":" + dusk % 60); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var proceed = 0;
|
|
|
|
|
switch (now.getDay()) {
|
2016-02-15 12:12:29 +01:00
|
|
|
|
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; }
|
2015-11-02 18:24:27 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (proceed) {
|
|
|
|
|
switch (now.getMonth()) {
|
2016-02-15 12:12:29 +01:00
|
|
|
|
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; }
|
2015-11-02 18:24:27 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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"}); }
|
2016-02-15 12:12:29 +01:00
|
|
|
|
else { node.status({fill:"blue", shape:"dot", text:"off until " + parseInt(starttime / 60) + ":" + ("0" + starttime % 60).substr(-2)}); }
|
2015-11-02 18:24:27 +01:00
|
|
|
|
|
|
|
|
|
var msg = {};
|
|
|
|
|
if (node.mytopic) { msg.topic = node.mytopic; }
|
2016-02-15 12:12:29 +01:00
|
|
|
|
msg.payload = (proceed >= 2) ? 1 : 0;
|
2015-11-02 18:24:27 +01:00
|
|
|
|
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"});
|
2016-02-15 12:12:29 +01:00
|
|
|
|
res.sendStatus(200);
|
2015-11-02 18:24:27 +01:00
|
|
|
|
} catch (err) {
|
2016-02-15 12:12:29 +01:00
|
|
|
|
res.sendStatus(500);
|
2015-11-02 18:24:27 +01:00
|
|
|
|
node.error("Inject failed:" + err);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
2016-02-15 12:12:29 +01:00
|
|
|
|
res.sendStatus(404);
|
2015-11-02 18:24:27 +01:00
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
RED.nodes.registerType("timeswitch", TimeswitchNode);
|
2016-02-15 12:12:29 +01:00
|
|
|
|
};
|