New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

node-red-contrib-eztimer

Package Overview
Dependencies
Maintainers
1
Versions
25
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

node-red-contrib-eztimer - npm Package Compare versions

Comparing version 1.1.6 to 1.2.1

311

index.js

@@ -29,3 +29,2 @@ const util = require('util');

module.exports = function(RED) {
const debug = true;
const moment = require('moment');

@@ -94,10 +93,12 @@ const SunCalc = require('suncalc');

send(events.on, true);
if (events.off.type == '3') schedule(events.off, null, true); // If 'off' is of type duration, schedule 'off' event.
status(events.on, true);
} else if (msg.payload === 'off') {
if (events.off && events.off.type == '3') schedule(events.off, null, true); // If 'off' is of type duration, schedule 'off' event.
updateStatus();
} else if (msg.payload === 'off' && config.timerType == '1') {
// Sends the off event, then re-schedules it
handled = true;
clearTimeout(events.off.timeout);
events.off.moment = null;
send(events.off, true);
if (!isSuspended()) schedule(events.off);
status(events.off, true);
if (!isSuspended() && events.off.type != '3') schedule(events.off);
updateStatus();
} else if (msg.payload === 'trigger') {

@@ -107,2 +108,3 @@ // Sends the trigger/on event without impact the scheduled event

send(events.on);
updateStatus();
} else if (msg.payload === 'cancel' && config.timerType == '1') {

@@ -113,5 +115,7 @@ // Cancels the current timer without sending the off event

schedule(events.on);
schedule(events.off);
clearTimeout(events.off.timeout);
events.off.moment = null;
if (!isSuspended() && events.off.type != '3') schedule(events.off);
}
status(events.off);
updateStatus();
} else if (msg.payload === 'info') {

@@ -130,4 +134,4 @@ handled = true;

ret.on = {
property: 'msg.' + events.on.property,
value: events.on.value || "<none>",
property: (events.on.propertytype || 'msg') + '.' + events.on.property,
value: getValue(events.on) || "<none>",
nextEvent: function() {

@@ -141,4 +145,4 @@ if (isSuspended()) return 'suspended';

ret.off = {
property: 'msg.' + events.off.property,
value: events.off.value || "<none>",
property: (events.off.propertytype || 'msg') + '.' + events.off.property,
value: getValue(events.off) || "<none>",
nextEvent: function() {

@@ -154,4 +158,4 @@ if (config.timerType == '2') return undefined; // Trigger

ret.trigger = {
property: 'msg.' + events.on.property,
value: events.on.value || "<none>",
property: (events.on.propertytype || 'msg') + '.' + events.on.property,
value: getValue(events.on) || "<none>",
nextEvent: function() {

@@ -217,30 +221,50 @@ if (isSuspended()) return 'suspended';

function log(level, message) {
if (config.debug) level = Math.max(3, level); //Outputs everything in node warn or error.
switch (level) {
case 1: //verbose, ignore
break;
case 2:
node.log(message); // log to node console only
break;
case 3:
node.warn(message); // log to node debug window
break;
default:
node.error(message); //anything above 3.
}
}
function dynamicDuration(property, duration) {
// Return false if not a duration request
if (property != "duration") return true;
if (state) {
// Timer currently 'on' - parse time
var secs = getSeconds(duration);
var offTime = moment(events.on.last.moment).add(secs, 'seconds');
if (offTime.isBefore(node.now())) {
// New time is before now - need to turn off and schedule
node.log("Live duration change (" + duration + " => " + secs + "s) causes an off-time in the past, sending 'off' event.");
send(events.off);
schedule(events.off);
status(events.off);
if (property == "offtime" && state) {
schedule(events.off, null, true);
} else if (property == "duration") {
if (state) {
// Timer currently 'on' - parse time
var secs = getSeconds(duration);
var offTime = moment(events.on.last.moment).add(secs, 'seconds');
if (offTime.isBefore(node.now())) {
// New time is before now - need to turn off and schedule
log(2, "Live duration change (" + duration + " => " + secs + "s) causes an off-time in the past, sending 'off' event.");
send(events.off);
schedule(events.off);
} else {
// New time is after now - just update the scheduled off event (and status)
log(2, "Live duration change (" + duration + " => " + secs + "s), rescheduling 'off' time to " + offTime.toString());
schedule(events.off, null, true);
}
} else {
// New time is after now - just update the scheduled off event (and status)
node.log("Live duration change (" + duration + " => " + secs + "s), rescheduling 'off' time to " + offTime.toString());
schedule(events.off, null, true);
status(events.on);
// Timer currently 'off', just re-schedule of off event (if an on event is scheduled)
if (!isSuspended()) {
schedule(events.off);
}
}
} else {
// Timer currently 'off', just re-schedule of off event (if an on event is scheduled)
if (!isSuspended()) {
schedule(events.off);
status(events.off);
}
return true;
}
updateStatus();
// Return false to indicate no bootstrap required

@@ -288,3 +312,3 @@ return false;

send(event);
if (events.on.type != '9' && !isSuspended()) {
if (!isSuspended()) {
// Schedule the next event, if it's not a 'manual' timer

@@ -297,3 +321,3 @@ schedule(event, null, null);

// Update the status/icon
status(event);
updateStatus();
};

@@ -303,28 +327,57 @@ return event;

function getValue(event) {
// Parse value to selected format
var tgtValue = event.value;
switch (event.valuetype) {
case 'flow':
tgtValue = node.context().flow.get(tgtValue);
break;
case 'global':
tgtValue = node.context().global.get(tgtValue);
break;
case 'json':
tgtValue = JSON.parse(tgtValue);
break;
case 'bool':
tgtValue = (tgtValue == "true");
break;
case 'date':
tgtValue = (new Date()).getTime();
break;
}
return tgtValue;
}
function send(event, manual) {
//node.warn('sending \'' + event.name + '\'');
var msg = {};
msg.tag = config.tag || 'eztimer';
if (event.topic) msg.topic = event.topic;
//msg.topic = event.topic || (msg.tag + '.' + event.name.toLowerCase());
var currPart = msg;
var spl = event.property.split('.');
for (var i in spl) {
if (i < (spl.length - 1)) {
if (!currPart[spl[i]]) currPart[spl[i]] = {};
currPart = currPart[spl[i]];
} else {
if (event.valuetype == 'json') {
currPart[spl[i]] = JSON.parse(event.value);
} else if (event.valuetype == 'bool') {
currPart[spl[i]] = (event.value == "true");
} else if (event.valuetype == 'date') {
currPart[spl[i]] = (new Date()).getTime();
} else {
currPart[spl[i]] = event.value;
log(1, 'emitting \'' + event.name + '\' event');
event.last.moment = node.now();
if (!event.suppressrepeats || state != event.state) {
// Output value
switch (event.propertytype || 'msg') {
case "flow":
node.context().flow.set(event.property, getValue(event));
break;
case "global":
node.context().global.set(event.property, getValue(event));
break;
case "msg":
var msg = {};
msg.tag = config.tag || 'eztimer';
if (event.topic) msg.topic = event.topic;
var currPart = msg;
var spl = event.property.split('.');
for (var i in spl) {
if (i < (spl.length - 1)) {
if (!currPart[spl[i]]) currPart[spl[i]] = {};
currPart = currPart[spl[i]];
} else {
currPart[spl[i]] = getValue(event);
}
}
node.send(msg);
break;
}
}
}
event.last.moment = node.now();
if (!event.suppressrepeats || state != event.state) node.send(msg);
state = event.state;

@@ -336,5 +389,6 @@ }

var now = node.now();
switch (event.type) {
case '1': //Sun
event.typeName = 'sun';
var nextDate = new Date();

@@ -349,3 +403,3 @@ // Get tomorrow's sun data

if (event.timesun != sunTimes[t]) {
node.warn({ "message": 'Sun event (' + event.timesun + ') invalid for chosen lat/long (due to polar proximity). Sun event \'' + sunTimes[t] + '\' has been chosen as the closest valid candidate.', "events": sunCalcTimes});
log(4, { "message": 'Sun event (' + event.timesun + ') invalid for chosen lat/long (due to polar proximity). Sun event \'' + sunTimes[t] + '\' has been chosen as the closest valid candidate.', "events": sunCalcTimes});
}

@@ -359,4 +413,10 @@ // Use determined event time

}
break;
case '2': //Time of Day
if (event.timetod == '') {
event.moment = null;
return true;
}
event.typeName = 'time of day';
var m = node.now().millisecond(0);

@@ -386,10 +446,14 @@ var re = new RegExp(/\d+/g);

case '3': //Duration
event.typeName = 'duration';
var secs = getSeconds(event.duration);
if (manual) {
if (manual && event.inverse.last.moment) {
//event is manual - schedule based on last 'on' event
event.moment = moment(event.inverse.last.moment).add(secs, 'seconds');
} else {
} else if (event.inverse.moment) {
// event is auto - schedule based on current 'on' event
event.moment = moment(event.inverse.moment).add(secs, 'seconds');
} else {
event.moment = null;
return true;
}

@@ -401,3 +465,8 @@

}
break;
case '9': //Manual
event.typeName = 'manual';
event.moment = null;
return true;
}

@@ -432,2 +501,5 @@

// Log event
log(1, "Scheduled '" + event.name + "' (" + event.typeName + ") for " + event.moment.toString());
// Clear any pending event

@@ -442,21 +514,43 @@ if (event.timeout) clearTimeout(event.timeout);

function status(event, manual) {
manual = manual || (events.on.type == 9)
var data = {
fill: manual ? 'blue' : 'green',
shape: event.shape,
text: {}
function updateStatus() {
var message = null;
// Determine the next event
var nextEvent = null;
switch (config.timerType) {
case "1": // on/off
if (state) {
if (events.off && events.off.moment) nextEvent = events.off;
} else {
if (events.on.moment) nextEvent = events.on;
}
message = {
fill: 'green',
shape: state ? 'dot' : 'ring',
text: state ? events.on.name : events.off.name
};
if (nextEvent) message.text += ` until ${nextEvent.moment.format(fmt)}`;
break;
case "2": // trigger
if (events.on.moment) nextEvent = events.on;
message = {
fill: 'green',
shape: 'ring',
text: ''
};
if (nextEvent) message.text = `trigger @ ${nextEvent.moment.format(fmt)}`;
break;
}
if (event.inverse) {
if (event.inverse.moment && event.inverse.moment.isAfter(node.now())) {
//data.text = event.name + (manual ? ' manual' : ' auto') + (isSuspended() ? ' - scheduling suspended' : ` until ${event.inverse.moment.format(fmt)}`);
data.text = event.name + (manual ? ' manual' : ' auto') + ` until ${event.inverse.moment.format(fmt)}`;
if (!nextEvent) {
if (isSuspended()) {
if (!state) message.fill = 'grey';
message.shape = 'dot';
message.text += 'scheduling suspended';
} else {
data.text = event.name + (manual ? ' manual' : ' auto') + (isSuspended() ? ' - scheduling suspended' : ``);
message.text += ', no scheduled event';
}
} else {
data.text = `trigger @ ${event.moment.format(fmt)}`;
message.text += weekdays().indexOf(true) === -1 ? ' (no weekdays selected) ' : '';
}
node.status(data);
node.status(message);
}

@@ -473,32 +567,9 @@

events.on.moment = null;
node.status({
fill: 'grey',
shape: 'dot',
text: `Scheduling suspended ${
weekdays().indexOf(true) === -1 ? '(no weekdays selected) ' : ''
}`
});
updateStatus();
}
function resume() {
if (events.on.type == '9') return; // Don't do anything when resuming a manual timer
if (schedule(events.on, true) && (!events.off || (events.off && schedule(events.off, true)))) {
const firstEvent = events.off && events.off.moment.isBefore(events.on.moment) ? events.off : events.on;
var message;
if (events.off && events.off.moment) {
message = {
fill: 'yellow',
shape: 'dot',
text: `${firstEvent.name} @ ${firstEvent.moment.format(fmt)}, ${firstEvent.inverse.name} @ ${firstEvent.inverse.moment.format(fmt)}`
}
} else {
message = {
fill: 'green',
shape: 'ring',
text: `trigger @ ${firstEvent.moment.format(fmt)}`
}
}
node.status(message);
}
var on = events.on.type != '9' && schedule(events.on, true);
var off = (!events.off || (events.off && events.off.type != '9' && schedule(events.off, true)));
}

@@ -511,17 +582,29 @@

resume();
// Wait 2.5 for startup, then fire PREVIOUS event to ensure we're in the right state.
// Wait 1000ms for startup, then fire PREVIOUS event to ensure we're in the right state.
setTimeout(function() {
if (config.startupMessage && config.startupMessage == true && events.on && events.on.moment && events.off && events.off.moment) {
if (events.on && events.on.moment && events.off && events.off.moment) {
if (events.off.moment.isAfter(events.on.moment)) {
//Next event is ON, send OFF
send(events.off);
if (config.startupMessage && config.startupMessage == true) {
send(events.off);
} else {
state = false;
}
} else {
//Next event is OFF, send ON
if (config.startupMessage && config.startupMessage == true) {
send(events.on);
} else {
state = true;
}
}
} else if (events.on && (!events.off || events.off.type == '9')) {
//Trigger
if (config.startupMessage && config.startupMessage == true) {
send(events.on);
}
} else if (config.startupMessage && config.startupMessage == true && events.on && !events.off) {
//Trigger
send(events.on);
}
}, 2500);
updateStatus();
}, 1000);
}

@@ -528,0 +611,0 @@ }

{
"name": "node-red-contrib-eztimer",
"version": "1.1.6",
"version": "1.2.1",
"description": "A simple-yet-flexible timer/scheduler for node-red",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -119,2 +119,14 @@ # eztimer

# Change Log
## 1.2.0
* Fixed emitting of `flow` and `global` context values (node wouldn't pick them up as values previously)
* Fixed assignment of `flow` and `global` context values to store correct type. [credit @LorenzKahl](https://github.com/mrgadget/node-red-contrib-eztimer/issues/24).
* Renamed `Input Trigger` off-type to `Manual` to align with the on-type of the same name.
* Fixed status reports for `Manual` off time. [credit @moryoav](https://github.com/mrgadget/node-red-contrib-eztimer/issues/25).
* Permit blank on time - allows for full programmatic usage without errors being displayed. [credit @moryoav](https://github.com/mrgadget/node-red-contrib-eztimer/issues/25).
* Simplified node status, removed auto/manual concept (inherited from parent, didn't really make any sense with the way the node works now).
## 1.1.7
* Fixed `cancel` to actually work - the node no longer emits the `off` event after a `cancel` call. [credit @svwhisper](https://github.com/mrgadget/node-red-contrib-eztimer/issues/23).
* Added code to support `flow` and `global` contexts as assignment properties. When selected, these do not emit flow message. [credit @LorenzKahl](https://github.com/mrgadget/node-red-contrib-eztimer/issues/22).
## 1.1.6

@@ -121,0 +133,0 @@ Fixes driven by issue #21 [credit @jazzgil](https://github.com/mrgadget/node-red-contrib-eztimer/issues/21).

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc