@tbowmo/node-red-small-timer
Version:
Small timer node for Node-RED with support for sunrise, sunset etc. timers
122 lines (121 loc) • 4.76 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.TimeCalc = void 0;
const sun_and_moon_1 = require("./sun-and-moon");
const utils_1 = require("./utils");
const wholeDay = 1440;
class TimeCalc extends sun_and_moon_1.SunAndMoon {
constructor(latitude, longitude, wrapMidnight, startTime, endTime, startOffset, endOffset, minimumOnTime) {
super(latitude, longitude);
this.wrapMidnight = wrapMidnight;
this.startTime = startTime;
this.endTime = endTime;
this.startOffset = startOffset;
this.endOffset = endOffset;
this.minimumOnTime = minimumOnTime;
this.actualStart = 0;
this.actualEnd = 0;
this.lastRecalcTime = -1;
this.eventCalculation();
}
convertDateToTime(times) {
return Object.fromEntries(Object.values(this.sunLookup)
.map((key) => {
if (times && (key in times)) {
const t = times[key];
return t === undefined ? undefined : [key, this.getTime(t)];
}
})
.filter(utils_1.isNotUndefinedOrNull));
}
debug() {
const sunTimes = this.convertDateToTime(this.sunTimes);
const moonTimes = this.convertDateToTime(this.moonTimes);
return {
sunTimes,
moonTimes,
now: this.getTime(new Date()),
actualStart: this.actualStart,
actualEnd: this.actualEnd,
nextStart: this.getTimeToNextStartEvent(),
nextEnd: this.getTimeToNextEndEvent(),
onState: this.getOnState(),
operationToday: this.operationToday(),
};
}
setStartEndTime(startTime = this.startTime, endTime = this.endTime, startOffset = this.startOffset, endOffset = this.endOffset) {
const changedProp = !(startTime === this.startTime
&& endTime === this.endTime
&& startOffset === this.startOffset
&& endOffset === this.endOffset);
this.startTime = startTime;
this.endTime = endTime;
this.startOffset = startOffset;
this.endOffset = endOffset;
this.eventCalculation(changedProp);
}
getTimeToNextStartEvent(date = new Date()) {
const currentTime = this.getTime(date);
const nextEvent = this.actualStart - currentTime;
return nextEvent >= 0 ? nextEvent : (nextEvent + wholeDay);
}
getTimeToNextEndEvent(date = new Date()) {
const currentTime = this.getTime(date);
const nextEvent = this.actualEnd - currentTime;
return nextEvent >= 0 ? nextEvent : (nextEvent + wholeDay);
}
onTime() {
const onTime = this.actualEnd - this.actualStart;
if (this.wrapMidnight && onTime < 0) {
return onTime + wholeDay;
}
return onTime;
}
getOnState(date = new Date()) {
const currentTime = this.getTime(date);
this.eventCalculation(false, date);
if (this.onTime() < this.minimumOnTime) {
return false;
}
if (this.actualEnd < this.actualStart) {
return this.wrapMidnight && ((currentTime < this.actualEnd) || (currentTime > this.actualStart));
}
return (currentTime > this.actualStart) && (currentTime < this.actualEnd);
}
operationToday() {
const onTime = this.onTime();
if (onTime >= 0 && onTime < this.minimumOnTime) {
return 'minimumOnTimeNotMet';
}
return !this.wrapMidnight && (this.actualEnd < this.actualStart) ? 'noMidnightWrap' : 'normal';
}
eventCalculation(forceUpdate = false, now = new Date()) {
this.updateSunCalc(now);
if (!forceUpdate && this.lastRecalcTime === now.getDate()) {
return;
}
this.lastRecalcTime = now.getDate();
this.actualStart = this.lookupEventTime(this.startTime) + this.startOffset;
this.actualEnd = this.lookupEventTime(this.endTime, this.actualStart) + this.endOffset;
}
getTime(date) {
return date.getHours() * 60 + date.getMinutes();
}
lookupEventTime(time, startTime = 0) {
if (time <= wholeDay) {
return time;
}
if (this.latitude === undefined && this.longitude === undefined) {
throw new Error('Something went wrong, latitude and longitude not specified');
}
if (time > 10000) {
return (startTime + (time - 10000)) % wholeDay;
}
const lookedUptime = this.getSunOrMoonTime(time);
if (!lookedUptime) {
throw new Error(`Can't look up the correct time '${time}' '${startTime}'`);
}
return this.getTime(lookedUptime);
}
}
exports.TimeCalc = TimeCalc;