Socket
Socket
Sign inDemoInstall

node-red-contrib-schedex

Package Overview
Dependencies
3
Maintainers
1
Versions
41
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.8.1 to 1.0.0

124

index.js

@@ -36,6 +36,17 @@ /**

var node = this,
events = {on: setupEvent('on', 'dot'), off: setupEvent('off', 'ring')};
events = { on: setupEvent('on', 'dot'), off: setupEvent('off', 'ring') };
events.on.inverse = events.off;
events.off.inverse = events.on;
// migration code : if new values are undefined, set all to true
if (config.sun === undefined && config.mon === undefined && config.tue === undefined &&
config.wed === undefined && config.thu === undefined && config.fri === undefined &&
config.sat === undefined) {
const name = config.name || config.ontime + ' - ' + config.offtime;
node.warn('Schedex [' + name + ']: New weekday configuration attributes are not defined, please edit the node. Defaulting to true.');
config.sun = config.mon = config.tue = config.wed = config.thu = config.fri = config.sat = true;
}
var weekdays = [config.mon, config.tue, config.wed, config.thu, config.fri, config.sat, config.sun];
node.on('input', function (msg) {

@@ -59,10 +70,10 @@ var handled = false, requiresBootstrap = false;

}
eachProp(function (eventName, msgProperty, typeConstructor) {
var prop = eventName + msgProperty;
enumerateOnOffEvents(function (eventType, eventName, eventNameTypeConverter) {
var prop = eventType + eventName;
var match = new RegExp('.*' + prop + '\\s+(\\S+)').exec(msg.payload);
if (match) {
handled = true;
var previous = events[eventName][msgProperty];
events[eventName][msgProperty] = typeConstructor(match[1]);
requiresBootstrap = requiresBootstrap || previous !== events[eventName][msgProperty];
var previous = events[eventType][eventName];
events[eventType][eventName] = eventNameTypeConverter(match[1]);
requiresBootstrap = requiresBootstrap || previous !== events[eventType][eventName];
}

@@ -78,9 +89,9 @@ });

}
eachProp(function (eventName, msgProperty, typeConstructor) {
var prop = eventName + msgProperty;
enumerateOnOffEvents(function (eventType, eventName, eventNameTypeConverter) {
var prop = eventType + eventName;
if (msg.payload.hasOwnProperty(prop)) {
handled = true;
var previous = events[eventName][msgProperty];
events[eventName][msgProperty] = typeConstructor(msg.payload[prop]);
requiresBootstrap = requiresBootstrap || previous !== events[eventName][msgProperty];
var previous = events[eventType][eventName];
events[eventType][eventName] = eventNameTypeConverter(msg.payload[prop]);
requiresBootstrap = requiresBootstrap || previous !== events[eventType][eventName];
}

@@ -90,3 +101,3 @@ });

if (!handled) {
node.status({fill: 'red', shape: 'dot', text: 'Unsupported input'});
node.status({ fill: 'red', shape: 'dot', text: 'Unsupported input' });
} else if (requiresBootstrap) {

@@ -116,3 +127,3 @@ bootstrap();

function send(event, manual) {
node.send({topic: event.topic, payload: event.payload});
node.send({ topic: event.topic, payload: event.payload });
node.status({

@@ -129,4 +140,4 @@ fill: manual ? 'blue' : 'green',

if (matches && matches.length) {
// Don't use 'now' here as hour and minute mutate the moment.
event.moment = moment().hour(matches[1]).minute(matches[2]);
// Don't use existing 'now' moment here as hour and minute mutate the moment.
event.moment = moment().hour(+matches[1]).minute(+matches[2]);
} else {

@@ -139,24 +150,30 @@ var sunCalcTimes = SunCalc.getTimes(new Date(), config.lat, config.lon);

}
if (event.moment) {
event.moment.seconds(0);
if (event.offset) {
var adjustment = event.offset;
if (event.randomoffset) {
adjustment = event.offset * Math.random();
}
event.moment.add(adjustment, 'minutes');
}
if (!event.moment) {
node.status({ fill: 'red', shape: 'dot', text: 'Invalid time: ' + event.time });
return false;
}
event.moment.seconds(0);
if (!isInitial || isInitial && now.isAfter(event.moment)) {
event.moment.add(1, 'day');
}
if (!isInitial || isInitial && now.isAfter(event.moment)) {
event.moment.add(1, 'day');
if (event.offset) {
var adjustment = event.offset;
if (event.randomoffset) {
adjustment = event.offset * Math.random();
}
event.moment.add(adjustment, 'minutes');
}
var delay = event.moment.diff(now);
if (event.timeout) {
clearTimeout(event.timeout);
}
event.timeout = setTimeout(event.callback, delay);
} else {
node.status({fill: 'red', shape: 'dot', text: 'Invalid time: ' + event.time});
// Adjust weekday if not selected
while (!weekdays[event.moment.isoWeekday() - 1]) {
event.moment.add(1, 'day');
}
var delay = event.moment.diff(now);
if (event.timeout) {
clearTimeout(event.timeout);
}
event.timeout = setTimeout(event.callback, delay);
return true;
}

@@ -167,16 +184,20 @@

clearTimeout(events.off.timeout);
node.status({fill: 'grey', shape: 'dot', text: 'Scheduling suspended - manual mode only'});
node.status({
fill: 'grey',
shape: 'dot',
text: 'Scheduling suspended ' + (weekdays.indexOf(true) === -1 ? '(no weekdays selected) ' : '') + '- manual mode only'
});
}
function resume() {
schedule(events.on, true);
schedule(events.off, true);
var firstEvent = events.on.moment.isBefore(events.off.moment) ? events.on : events.off;
var message = firstEvent.name + ' ' + firstEvent.moment.format(fmt) + ', ' +
firstEvent.inverse.name + ' ' + firstEvent.inverse.moment.format(fmt);
node.status({fill: 'yellow', shape: 'dot', text: message});
if (schedule(events.on, true) && schedule(events.off, true)) {
var firstEvent = events.on.moment.isBefore(events.off.moment) ? events.on : events.off;
var message = firstEvent.name + ' ' + firstEvent.moment.format(fmt) + ', ' +
firstEvent.inverse.name + ' ' + firstEvent.inverse.moment.format(fmt);
node.status({ fill: 'yellow', shape: 'dot', text: message });
}
}
function bootstrap() {
if (config.suspended) {
if (config.suspended || weekdays.indexOf(true) === -1) {
suspend();

@@ -188,9 +209,10 @@ } else {

function eachProp(callback) {
Object.keys(events).forEach(function (eventName) {
callback(eventName, 'time', String);
callback(eventName, 'topic', String);
callback(eventName, 'payload', String);
callback(eventName, 'offset', Number);
callback(eventName, 'randomoffset', toBoolean);
function enumerateOnOffEvents(callback) {
// The keys here will be ['on', 'off']
Object.keys(events).forEach(function (eventType) {
callback(eventType, 'time', String);
callback(eventType, 'topic', String);
callback(eventType, 'payload', String);
callback(eventType, 'offset', Number);
callback(eventType, 'randomoffset', toBoolean);
});

@@ -203,4 +225,8 @@ }

node.schedexEvents = function () {
return events;
};
bootstrap();
});
};
};
{
"name": "node-red-contrib-schedex",
"version": "0.8.1",
"version": "1.0.0",
"description": "",

@@ -14,3 +14,3 @@ "main": "index.js",

"scripts": {
"test": "node_modules/.bin/mocha -R spec ./tests/test.js",
"test": "nyc --reporter=html node_modules/.bin/mocha -R spec ./tests/test.js",
"readme2html": "node_modules/.bin/markdown README.md -f gfm"

@@ -33,6 +33,9 @@ },

"devDependencies": {
"chai": "^3.5.0",
"chai": "^4.0.1",
"eslint": "^3.19.0",
"eslint-config-biddster": "^0.3.0",
"markdown-to-html": "0.0.13",
"mocha": "^3.1.2",
"node-red-contrib-mock-node": "^0.2.0"
"mocha": "^3.4.2",
"node-red-contrib-mock-node": "^0.3.0",
"nyc": "^11.0.2"
},

@@ -43,3 +46,11 @@ "node-red": {

}
},
"eslintConfig": {
"env": {
"es6": true,
"node": true,
"mocha": true
},
"extends": "eslint-config-biddster/es6-node"
}
}

@@ -8,7 +8,8 @@ # Schedex

__NOTE: When upgrading from versions prior to 1.0.0, you will see a message for each Schedex node in the Node-RED debug window. This message is to advise that the Schedex configuration changed slightly in version 1.0.0
in order to accomodate days of the week when scheduling. To remedy, simply edit each Schedex node, tick the days of the week you want Schedex enabled and re-deploy.__
# Installation
Change directory to your node red installation:
$ cd ~/.node-red
$ npm install node-red-contrib-schedex

@@ -18,2 +19,7 @@

## Schedule
The scheduling days allow you to choose which days of the week to schedule events. Unticking all days
will suspend scheduling.
## Suspending scheduling

@@ -20,0 +26,0 @@

@@ -26,2 +26,3 @@ /**

"use strict";
var assert = require('chai').assert;

@@ -36,18 +37,121 @@ var _ = require('lodash');

it('should schedule initially', function () {
var node = mock(nodeRedModule, {
onTime: '11:45',
onTopic: 'on',
onPayload: 'on payload',
offTime: '11:48',
offTopic: 'off',
offPayload: 'off payload',
lat: 51.33411,
lon: -0.83716,
unitTest: true
});
var node = newNode();
assert.strictEqual(node.schedexEvents().on.time, '11:45');
assert.strictEqual(node.schedexEvents().off.time, 'dawn');
// TODO - actually do something here.
node.emit('input', { payload: 'on' });
assert.strictEqual(node.sent(0).payload, 'on payload');
assert.strictEqual(node.sent(0).topic, 'on topic');
// assert.strictEqual(2881, node.messages().length);
node.emit('input', { payload: 'off' });
assert.strictEqual(node.sent(1).payload, 'off payload');
assert.strictEqual(node.sent(1).topic, 'off topic');
});
it('should handle programmatic scheduling', function () {
var node = newNode();
node.emit('input', { payload: 'ontime 11:12' });
assert.strictEqual(node.schedexEvents().on.time, '11:12');
node.emit('input', { payload: { ontime: '23:12' } });
assert.strictEqual(node.schedexEvents().on.time, '23:12');
node.emit('input', { payload: 'offtime 10:12' });
assert.strictEqual(node.schedexEvents().off.time, '10:12');
node.emit('input', { payload: { offtime: '22:12' } });
assert.strictEqual(node.schedexEvents().off.time, '22:12');
});
it('should indicate bad programmatic input', function () {
var node = newNode();
node.emit('input', { payload: 'wibble' });
assert.strictEqual(node.status().text, 'Unsupported input');
node.status().text = '';
node.emit('input', { payload: '4412' });
assert.strictEqual(node.status().text, 'Unsupported input');
});
it('should indicate bad configuration', function () {
var node = newNode({ ontime: '5555' });
assert.strictEqual(node.status().text, 'Invalid time: 5555');
});
it('should suspend initially', function () {
var node = newNode({ suspended: true });
assert(node.status().text.indexOf('Scheduling suspended') === 0);
});
it('should suspend if all weekdays are unticked and disabled', function () {
var config = _.zipObject(['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'], _.times(7, () => false));
var node = newNode(config);
assert(node.status().text.indexOf('Scheduling suspended') === 0);
});
it('should suspend programtically', function () {
var node = newNode();
node.emit('input', { payload: { suspended: true } });
assert(node.status().text.indexOf('Scheduling suspended') === 0);
node = newNode();
node.emit('input', { payload: 'suspended true' });
assert(node.status().text.indexOf('Scheduling suspended') === 0);
});
it('should handle day configuration', function () {
var now = moment();
// Start by disabling today in the configuration.
var config = _.zipObject(['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'], _.times(7, index => now.isoWeekday() !== (index + 1)));
// Make sure we schedule 'on' for today by making the time after now. That way, disabling
// today in the config will force the 'on' to be tomorrow and we can assert it.
config.ontime = moment().add(1, 'minute').format('HH:mm');
var node = newNode(config);
assert.strictEqual(node.schedexEvents().on.moment.isoWeekday(), now.add(1, 'day').isoWeekday());
});
it('should send something when tiggered', function (done) {
this.timeout(60000 * 5);
console.log('This test will take 3 minutes, please wait...');
var ontime = moment().add(1, 'minute').format('HH:mm');
var offtime = moment().add(2, 'minute').format('HH:mm');
var node = newNode({ ontime: ontime, offtime: offtime, offoffset: 0, offrandomoffset: '0' });
setTimeout(function () {
assert.strictEqual(node.sent(0).payload, 'on payload');
assert.strictEqual(node.sent(0).topic, 'on topic');
assert.strictEqual(node.sent(1).payload, 'off payload');
assert.strictEqual(node.sent(1).topic, 'off topic');
done();
}, 60000 * 3);
});
it('should send something after programmatic configuration when tiggered', function (done) {
this.timeout(60000 * 5);
console.log('This test will take 3 minutes, please wait...');
var ontime = moment().add(1, 'minute').format('HH:mm');
var offtime = moment().add(2, 'minute').format('HH:mm');
var node = newNode({ offoffset: 0, offrandomoffset: '0' });
node.emit('input', { payload: 'ontime ' + ontime });
node.emit('input', { payload: 'offtime ' + offtime });
setTimeout(function () {
assert.strictEqual(node.sent(0).payload, 'on payload');
assert.strictEqual(node.sent(0).topic, 'on topic');
assert.strictEqual(node.sent(1).payload, 'off payload');
assert.strictEqual(node.sent(1).topic, 'off topic');
done();
}, 60000 * 3);
});
});
function newNode(configOverrides) {
var config = {
suspended: false,
ontime: '11:45',
ontopic: 'on topic',
onpayload: 'on payload',
onoffset: '',
onrandomoffset: 0,
offtime: 'dawn',
offtopic: 'off topic',
offpayload: 'off payload',
offoffset: '5',
offrandomoffset: 1,
lat: 51.33411,
lon: -0.83716,
unittest: true
};
if (configOverrides) {
_.assign(config, configOverrides);
}
return mock(nodeRedModule, config);
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc