mirror of
https://github.com/node-red/node-red-nodes.git
synced 2023-10-10 13:36:58 +02:00
jsHint passing versions of BBB, scanBLE and wemo nodes.
Also fixe and in vs out issue on wemo... no way it could have been working previously..
This commit is contained in:
parent
c14364d752
commit
999874f2b5
@ -14,489 +14,492 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
// Require main module
|
module.exports = function(RED) {
|
||||||
var RED = require(process.env.NODE_RED_HOME + "/red/red");
|
"use strict";
|
||||||
var bonescript = require("bonescript");
|
var bonescript = require("bonescript");
|
||||||
|
|
||||||
// Node constructor for bbb-analogue-in
|
// Node constructor for bbb-analogue-in
|
||||||
function AnalogueInputNode(n) {
|
function AnalogueInputNode(n) {
|
||||||
// Create a RED node
|
// Create a RED node
|
||||||
RED.nodes.createNode(this, n);
|
RED.nodes.createNode(this, n);
|
||||||
|
|
||||||
// Store local copies of the node configuration (as defined in the .html)
|
// Store local copies of the node configuration (as defined in the .html)
|
||||||
this.topic = n.topic;
|
this.topic = n.topic;
|
||||||
this.pin = n.pin;
|
this.pin = n.pin;
|
||||||
this.breakpoints = n.breakpoints;
|
this.breakpoints = n.breakpoints;
|
||||||
this.averaging = n.averaging;
|
this.averaging = n.averaging;
|
||||||
if (this.averaging) {
|
if (this.averaging) {
|
||||||
this.averages = 10;
|
this.averages = 10;
|
||||||
} else {
|
} else {
|
||||||
this.averages = 1;
|
this.averages = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define 'node' to allow us to access 'this' from within callbacks
|
// Define 'node' to allow us to access 'this' from within callbacks
|
||||||
var node = this;
|
var node = this;
|
||||||
|
|
||||||
// Variables used for input averaging
|
// Variables used for input averaging
|
||||||
var sum; // accumulates the input readings to be averaged
|
var sum; // accumulates the input readings to be averaged
|
||||||
var count; // keep track of the number of measurements made
|
var count; // keep track of the number of measurements made
|
||||||
|
|
||||||
// The callback function for analogRead. Accumulates the required number of
|
// The callback function for analogRead. Accumulates the required number of
|
||||||
// measurements, then divides the total number, applies output scaling and
|
// measurements, then divides the total number, applies output scaling and
|
||||||
// sends the result
|
// sends the result
|
||||||
var analogReadCallback = function (x) {
|
var analogReadCallback = function (x) {
|
||||||
sum = sum + x.value;
|
sum = sum + x.value;
|
||||||
count = count - 1;
|
count = count - 1;
|
||||||
if (count > 0) {
|
if (count > 0) {
|
||||||
bonescript.analogRead(node.pin, analogReadCallback);
|
bonescript.analogRead(node.pin, analogReadCallback);
|
||||||
} else {
|
|
||||||
var msg = {};
|
|
||||||
msg.topic = node.topic;
|
|
||||||
sum = sum/node.averages;
|
|
||||||
// i is the index of the first breakpoint where the 'input' value is strictly
|
|
||||||
// greater than the measurement (note: a measurement can never be == 1)
|
|
||||||
var i = node.breakpoints.map(function (breakpoint) { return sum >= breakpoint.input; }).indexOf(false);
|
|
||||||
msg.payload = node.breakpoints[i-1].output + (node.breakpoints[i].output - node.breakpoints[i-1].output) *
|
|
||||||
(sum - node.breakpoints[i-1].input)/(node.breakpoints[i].input - node.breakpoints[i-1].input);
|
|
||||||
node.send(msg);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// If we have a valid pin, set the input event handler to Bonescript's analogRead
|
|
||||||
if (["P9_39", "P9_40", "P9_37", "P9_38", "P9_33", "P9_36", "P9_35"].indexOf(node.pin) >= 0) {
|
|
||||||
node.on("input", function (msg) {
|
|
||||||
sum = 0;
|
|
||||||
count = node.averages;
|
|
||||||
bonescript.analogRead(node.pin, analogReadCallback);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
node.error("Unconfigured input pin");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Node constructor for bbb-discrete-in
|
|
||||||
function DiscreteInputNode(n) {
|
|
||||||
RED.nodes.createNode(this, n);
|
|
||||||
|
|
||||||
// Store local copies of the node configuration (as defined in the .html)
|
|
||||||
this.topic = n.topic; // the topic is not currently used
|
|
||||||
this.pin = n.pin; // The Beaglebone Black pin identifying string
|
|
||||||
if (n.activeLow) // Set the 'active' state 0 or 1 as appropriate
|
|
||||||
this.activeState = 0;
|
|
||||||
else
|
|
||||||
this.activeState = 1;
|
|
||||||
this.updateInterval = n.updateInterval * 1000; // How often to send totalActiveTime messages
|
|
||||||
this.debounce = n.debounce; // Enable switch contact debouncing algorithm
|
|
||||||
if (n.outputOn === "rising") {
|
|
||||||
this.activeEdges = [false, true];
|
|
||||||
} else if (n.outputOn === "falling") {
|
|
||||||
this.activeEdges = [true, false];
|
|
||||||
} else if (n.outputOn === "both") {
|
|
||||||
this.activeEdges = [true, true];
|
|
||||||
} else {
|
|
||||||
node.error("Invalid edge type: " + n.outputOn);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Working variables
|
|
||||||
this.interruptAttached = false; // Flag: should we detach interrupt when we are closed?
|
|
||||||
this.intervalId = null; // Remember the timer ID so we can delete it when we are closed
|
|
||||||
this.currentState = 0; // The pin input state "1" or "0"
|
|
||||||
this.lastActiveTime = NaN; // The date (in ms since epoch) when the pin last went high
|
|
||||||
// switch to process.hrtime()
|
|
||||||
this.totalActiveTime = 0; // The total time in ms that the pin has been high (since reset)
|
|
||||||
this.starting = true;
|
|
||||||
this.debouncing = false; // True after a change of state while waiting for the 7ms debounce time to elapse
|
|
||||||
this.debounceTimer = null;
|
|
||||||
|
|
||||||
// Define 'node' to allow us to access 'this' from within callbacks
|
|
||||||
var node = this;
|
|
||||||
|
|
||||||
// This function is called by the input pin change-of-state interrupt. If
|
|
||||||
// debounce is disabled, send the output message. Otherwise, if we are
|
|
||||||
// currently debouncing, ignore this interrupt. If we are not debouncing,
|
|
||||||
// schedule a re-read of the input pin in 7ms time, and set the debouncing flag
|
|
||||||
// Note: this function gets called spuriously when the interrupt is first enabled:
|
|
||||||
// in this case x.value is undefined - we must test for this
|
|
||||||
var interruptCallback = function (x) {
|
|
||||||
if (x.value !== undefined && node.currentState !== Number(x.value)) {
|
|
||||||
if (node.debounce) {
|
|
||||||
if (node.debouncing === false) {
|
|
||||||
node.debouncing = true;
|
|
||||||
node.debounceTimer = setTimeout(function () { bonescript.digitalRead(node.pin, debounceCallback); }, 7);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
var msg = {};
|
||||||
|
msg.topic = node.topic;
|
||||||
|
sum = sum/node.averages;
|
||||||
|
// i is the index of the first breakpoint where the 'input' value is strictly
|
||||||
|
// greater than the measurement (note: a measurement can never be == 1)
|
||||||
|
var i = node.breakpoints.map(function (breakpoint) { return sum >= breakpoint.input; }).indexOf(false);
|
||||||
|
msg.payload = node.breakpoints[i-1].output + (node.breakpoints[i].output - node.breakpoints[i-1].output) *
|
||||||
|
(sum - node.breakpoints[i-1].input)/(node.breakpoints[i].input - node.breakpoints[i-1].input);
|
||||||
|
node.send(msg);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// If we have a valid pin, set the input event handler to Bonescript's analogRead
|
||||||
|
if (["P9_39", "P9_40", "P9_37", "P9_38", "P9_33", "P9_36", "P9_35"].indexOf(node.pin) >= 0) {
|
||||||
|
node.on("input", function (msg) {
|
||||||
|
sum = 0;
|
||||||
|
count = node.averages;
|
||||||
|
bonescript.analogRead(node.pin, analogReadCallback);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
node.error("Unconfigured input pin");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node constructor for bbb-discrete-in
|
||||||
|
function DiscreteInputNode(n) {
|
||||||
|
RED.nodes.createNode(this, n);
|
||||||
|
|
||||||
|
// Store local copies of the node configuration (as defined in the .html)
|
||||||
|
this.topic = n.topic; // the topic is not currently used
|
||||||
|
this.pin = n.pin; // The Beaglebone Black pin identifying string
|
||||||
|
if (n.activeLow) { // Set the 'active' state 0 or 1 as appropriate
|
||||||
|
this.activeState = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.activeState = 1;
|
||||||
|
}
|
||||||
|
this.updateInterval = n.updateInterval * 1000; // How often to send totalActiveTime messages
|
||||||
|
this.debounce = n.debounce; // Enable switch contact debouncing algorithm
|
||||||
|
if (n.outputOn === "rising") {
|
||||||
|
this.activeEdges = [false, true];
|
||||||
|
} else if (n.outputOn === "falling") {
|
||||||
|
this.activeEdges = [true, false];
|
||||||
|
} else if (n.outputOn === "both") {
|
||||||
|
this.activeEdges = [true, true];
|
||||||
|
} else {
|
||||||
|
node.error("Invalid edge type: " + n.outputOn);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Working variables
|
||||||
|
this.interruptAttached = false; // Flag: should we detach interrupt when we are closed?
|
||||||
|
this.intervalId = null; // Remember the timer ID so we can delete it when we are closed
|
||||||
|
this.currentState = 0; // The pin input state "1" or "0"
|
||||||
|
this.lastActiveTime = NaN; // The date (in ms since epoch) when the pin last went high
|
||||||
|
// switch to process.hrtime()
|
||||||
|
this.totalActiveTime = 0; // The total time in ms that the pin has been high (since reset)
|
||||||
|
this.starting = true;
|
||||||
|
this.debouncing = false; // True after a change of state while waiting for the 7ms debounce time to elapse
|
||||||
|
this.debounceTimer = null;
|
||||||
|
|
||||||
|
// Define 'node' to allow us to access 'this' from within callbacks
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
// This function is called by the input pin change-of-state interrupt. If
|
||||||
|
// debounce is disabled, send the output message. Otherwise, if we are
|
||||||
|
// currently debouncing, ignore this interrupt. If we are not debouncing,
|
||||||
|
// schedule a re-read of the input pin in 7ms time, and set the debouncing flag
|
||||||
|
// Note: this function gets called spuriously when the interrupt is first enabled:
|
||||||
|
// in this case x.value is undefined - we must test for this
|
||||||
|
var interruptCallback = function (x) {
|
||||||
|
if (x.value !== undefined && node.currentState !== Number(x.value)) {
|
||||||
|
if (node.debounce) {
|
||||||
|
if (node.debouncing === false) {
|
||||||
|
node.debouncing = true;
|
||||||
|
node.debounceTimer = setTimeout(function () { bonescript.digitalRead(node.pin, debounceCallback); }, 7);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sendStateMessage(x);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// This function is called approx 7ms after a potential change-of-state which is
|
||||||
|
// being debounced. Terminate the debounce, and send a message if the state has
|
||||||
|
// actually changed
|
||||||
|
var debounceCallback = function (x) {
|
||||||
|
node.debounceTimer = null;
|
||||||
|
node.debouncing = false;
|
||||||
|
if (x.value !== undefined && node.currentState !== Number(x.value)) {
|
||||||
sendStateMessage(x);
|
sendStateMessage(x);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
// This function is called approx 7ms after a potential change-of-state which is
|
// This function is called when either the interruptCallback or the debounceCallback
|
||||||
// being debounced. Terminate the debounce, and send a message if the state has
|
// have determined we have a 'genuine' change of state. Update the currentState and
|
||||||
// actually changed
|
// ActiveTime variables, and send a message on the first output with the new state
|
||||||
var debounceCallback = function (x) {
|
var sendStateMessage = function (x) {
|
||||||
node.debounceTimer = null;
|
node.currentState = Number(x.value);
|
||||||
node.debouncing = false;
|
var now = Date.now();
|
||||||
if (x.value !== undefined && node.currentState !== Number(x.value)) {
|
if (node.currentState === node.activeState) {
|
||||||
sendStateMessage(x);
|
node.lastActiveTime = now;
|
||||||
}
|
} else if (!isNaN(node.lastActiveTime)) {
|
||||||
};
|
node.totalActiveTime += now - node.lastActiveTime;
|
||||||
|
}
|
||||||
|
if (node.activeEdges[node.currentState]) {
|
||||||
|
var msg = {};
|
||||||
|
msg.topic = node.topic;
|
||||||
|
msg.payload = node.currentState;
|
||||||
|
node.send([msg, null]);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// This function is called when either the interruptCallback or the debounceCallback
|
// This function is called by the timer. It updates the ActiveTime variables, and sends a
|
||||||
// have determined we have a 'genuine' change of state. Update the currentState and
|
// message on the second output with the latest value of the total active time, in seconds
|
||||||
// ActiveTime variables, and send a message on the first output with the new state
|
var timerCallback = function () {
|
||||||
var sendStateMessage = function (x) {
|
if (node.currentState === node.activeState) {
|
||||||
node.currentState = Number(x.value);
|
var now = Date.now();
|
||||||
var now = Date.now();
|
node.totalActiveTime += now - node.lastActiveTime;
|
||||||
if (node.currentState === node.activeState) {
|
node.lastActiveTime = now;
|
||||||
node.lastActiveTime = now;
|
}
|
||||||
} else if (!isNaN(node.lastActiveTime)) {
|
|
||||||
node.totalActiveTime += now - node.lastActiveTime;
|
|
||||||
}
|
|
||||||
if (node.activeEdges[node.currentState]) {
|
|
||||||
var msg = {};
|
var msg = {};
|
||||||
msg.topic = node.topic;
|
msg.topic = node.topic;
|
||||||
msg.payload = node.currentState;
|
msg.payload = node.totalActiveTime / 1000;
|
||||||
node.send([msg, null]);
|
node.send([null, msg]);
|
||||||
}
|
// Re-synchronise the pin state if we have missed a state change interrupt for some
|
||||||
};
|
// reason, and we are not in the process of debouncing one
|
||||||
|
if (node.debouncing === false) {
|
||||||
// This function is called by the timer. It updates the ActiveTime variables, and sends a
|
bonescript.digitalRead(node.pin, interruptCallback);
|
||||||
// message on the second output with the latest value of the total active time, in seconds
|
|
||||||
var timerCallback = function () {
|
|
||||||
if (node.currentState === node.activeState) {
|
|
||||||
var now = Date.now();
|
|
||||||
node.totalActiveTime += now - node.lastActiveTime;
|
|
||||||
node.lastActiveTime = now;
|
|
||||||
}
|
|
||||||
var msg = {};
|
|
||||||
msg.topic = node.topic;
|
|
||||||
msg.payload = node.totalActiveTime / 1000;
|
|
||||||
node.send([null, msg]);
|
|
||||||
// Re-synchronise the pin state if we have missed a state change interrupt for some
|
|
||||||
// reason, and we are not in the process of debouncing one
|
|
||||||
if (node.debouncing === false) {
|
|
||||||
bonescript.digitalRead(node.pin, interruptCallback);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// This function is called when we receive an input message. If the topic contains
|
|
||||||
// 'load' (case insensitive) set the totalActiveTime to the numeric value of the
|
|
||||||
// payload, if possible. Otherwise clear the totalActiveTime (so we start counting
|
|
||||||
// from zero again)
|
|
||||||
var inputCallback = function (ipMsg) {
|
|
||||||
if (String(ipMsg.topic).search(/load/i) < 0 || isFinite(ipMsg.payload) == false) {
|
|
||||||
node.totalActiveTime = 0;
|
|
||||||
} else {
|
|
||||||
node.totalActiveTime = Number(ipMsg.payload);
|
|
||||||
}
|
|
||||||
if (node.currentState === node.activeState) {
|
|
||||||
node.lastActiveTime = Date.now();
|
|
||||||
}
|
|
||||||
// On startup, send an initial activeTime message, but only send an
|
|
||||||
// initial currentState message if we are in both edges active mode
|
|
||||||
if (node.starting) {
|
|
||||||
node.starting = false;
|
|
||||||
var msg;
|
|
||||||
if (node.activeEdges[0] && node.activeEdges[1]) {
|
|
||||||
msg = [{topic:node.topic}, {topic:node.topic}];
|
|
||||||
msg[0].payload = node.currentState;
|
|
||||||
} else {
|
|
||||||
msg = [null, {topic:node.topic}];
|
|
||||||
}
|
}
|
||||||
msg[1].payload = node.totalActiveTime;
|
};
|
||||||
node.send(msg);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// If we have a valid pin, set it as an input and read the (digital) state
|
// This function is called when we receive an input message. If the topic contains
|
||||||
if (["P8_7", "P8_8", "P8_9", "P8_10", "P8_11", "P8_12", "P8_13", "P8_14", "P8_15",
|
// 'load' (case insensitive) set the totalActiveTime to the numeric value of the
|
||||||
"P8_16", "P8_17", "P8_18", "P8_19", "P8_26", "P9_11", "P9_12", "P9_13", "P9_14",
|
// payload, if possible. Otherwise clear the totalActiveTime (so we start counting
|
||||||
"P9_15", "P9_16", "P9_17", "P9_18", "P9_21", "P9_22", "P9_23", "P9_24", "P9_26",
|
// from zero again)
|
||||||
"P9_27", "P9_30", "P9_41", "P9_42"].indexOf(node.pin) >= 0) {
|
var inputCallback = function (ipMsg) {
|
||||||
// Don't set up interrupts & intervals until after the close event handler has been installed
|
if (String(ipMsg.topic).search(/load/i) < 0 || isFinite(ipMsg.payload) === false) {
|
||||||
bonescript.detachInterrupt(node.pin);
|
node.totalActiveTime = 0;
|
||||||
process.nextTick(function () {
|
} else {
|
||||||
bonescript.pinMode(node.pin, bonescript.INPUT);
|
node.totalActiveTime = Number(ipMsg.payload);
|
||||||
bonescript.digitalRead(node.pin, function (x) {
|
}
|
||||||
// Initialise the currentState and lastActveTime variables based on the value read
|
if (node.currentState === node.activeState) {
|
||||||
node.currentState = Number(x.value);
|
node.lastActiveTime = Date.now();
|
||||||
if (node.currentState === node.activeState) {
|
}
|
||||||
node.lastActiveTime = Date.now();
|
// On startup, send an initial activeTime message, but only send an
|
||||||
// switch to process.hrtime()
|
// initial currentState message if we are in both edges active mode
|
||||||
}
|
if (node.starting) {
|
||||||
// Attempt to attach a change-of-state interrupt handler to the pin. If we succeed,
|
node.starting = false;
|
||||||
// set the input event and interval handlers, then send an initial message with the
|
var msg;
|
||||||
// pin state on the first output
|
if (node.activeEdges[0] && node.activeEdges[1]) {
|
||||||
if (bonescript.attachInterrupt(node.pin, true, bonescript.CHANGE, interruptCallback)) {
|
msg = [{topic:node.topic}, {topic:node.topic}];
|
||||||
node.interruptAttached = true;
|
msg[0].payload = node.currentState;
|
||||||
node.on("input", inputCallback);
|
} else {
|
||||||
node.intervalId = setInterval(timerCallback, node.updateInterval);
|
msg = [null, {topic:node.topic}];
|
||||||
} else {
|
}
|
||||||
node.error("Failed to attach interrupt");
|
msg[1].payload = node.totalActiveTime;
|
||||||
}
|
node.send(msg);
|
||||||
setTimeout(function () { node.emit("input", {}); }, 50);
|
}
|
||||||
});
|
};
|
||||||
});
|
|
||||||
} else {
|
|
||||||
node.error("Unconfigured input pin");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Node constructor for bbb-pulse-in
|
// If we have a valid pin, set it as an input and read the (digital) state
|
||||||
function PulseInputNode(n) {
|
if (["P8_7", "P8_8", "P8_9", "P8_10", "P8_11", "P8_12", "P8_13", "P8_14", "P8_15",
|
||||||
RED.nodes.createNode(this, n);
|
"P8_16", "P8_17", "P8_18", "P8_19", "P8_26", "P9_11", "P9_12", "P9_13", "P9_14",
|
||||||
|
"P9_15", "P9_16", "P9_17", "P9_18", "P9_21", "P9_22", "P9_23", "P9_24", "P9_26",
|
||||||
// Store local copies of the node configuration (as defined in the .html)
|
"P9_27", "P9_30", "P9_41", "P9_42"].indexOf(node.pin) >= 0) {
|
||||||
this.topic = n.topic; // the topic is not currently used
|
// Don't set up interrupts & intervals until after the close event handler has been installed
|
||||||
this.pin = n.pin; // The Beaglebone Black pin identifying string
|
bonescript.detachInterrupt(node.pin);
|
||||||
this.updateInterval = n.updateInterval * 1000; // How often to send output messages
|
process.nextTick(function () {
|
||||||
this.countType = n.countType; // Sets either 'edge' or 'pulse' counting
|
|
||||||
this.countUnit = n.countUnit; // Scaling appling to count output
|
|
||||||
this.countRate = n.countRate; // Scaling applied to rate output
|
|
||||||
|
|
||||||
// Working variables
|
|
||||||
this.interruptAttached = false; // Flag: should we detach interrupt when we are closed?
|
|
||||||
this.intervalId = null; // Remember the timer ID so we can delete it when we are closed
|
|
||||||
this.pulseCount = 0; // (Unscaled) total pulse count
|
|
||||||
// Hold the hrtime of the last two pulses (with ns resolution)
|
|
||||||
this.pulseTime = [[NaN, NaN], [NaN, NaN]];
|
|
||||||
|
|
||||||
// Define 'node' to allow us to access 'this' from within callbacks
|
|
||||||
var node = this;
|
|
||||||
|
|
||||||
// Called by the edge or pulse interrupt. If this is a valid interrupt, record the
|
|
||||||
// pulse time and count the pulse
|
|
||||||
var interruptCallback = function (x) {
|
|
||||||
if (x.value !== undefined) {
|
|
||||||
node.pulseTime = [node.pulseTime[1], process.hrtime()];
|
|
||||||
node.pulseCount = node.pulseCount + 1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Called when an input message arrives. If the topic contains 'load' (case
|
|
||||||
// insensitive) and the payload is a valid number, set the count to that
|
|
||||||
// number, otherwise set it to zero
|
|
||||||
var inputCallback = function (msg) {
|
|
||||||
if (String(msg.topic).search(/load/i) < 0 || isFinite(msg.payload) == false) {
|
|
||||||
node.pulseCount = 0;
|
|
||||||
} else {
|
|
||||||
node.pulseCount = Number(msg.payload);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Called by the message timer. Send two messages: the scaled pulse count on
|
|
||||||
// the first output and the scaled instantaneous pulse rate on the second.
|
|
||||||
// The instantaneous pulse rate is the reciprocal of the larger of either the
|
|
||||||
// time interval between the last two pulses, or the time interval since the last pulse.
|
|
||||||
var timerCallback = function () {
|
|
||||||
var now = process.hrtime();
|
|
||||||
var lastTime = node.pulseTime[1][0] - node.pulseTime[0][0] + (node.pulseTime[1][1] - node.pulseTime[0][1]) / 1e9;
|
|
||||||
var thisTime = now[0] - node.pulseTime[1][0] + (now[1] - node.pulseTime[1][1]) / 1e9;
|
|
||||||
var msg = [{ topic:node.topic }, { topic:node.topic }];
|
|
||||||
msg[0].payload = node.countUnit * node.pulseCount;
|
|
||||||
// At startup, pulseTime contains NaN's: force the rate output to 0
|
|
||||||
msg[1].payload = node.countRate / Math.max(thisTime, lastTime) || 0;
|
|
||||||
node.send(msg);
|
|
||||||
};
|
|
||||||
|
|
||||||
// If we have a valid pin, set it as an input and read the (digital) state
|
|
||||||
if (["P8_7", "P8_8", "P8_9", "P8_10", "P8_11", "P8_12", "P8_13", "P8_14", "P8_15",
|
|
||||||
"P8_16", "P8_17", "P8_18", "P8_19", "P8_26", "P9_11", "P9_12", "P9_13", "P9_14",
|
|
||||||
"P9_15", "P9_16", "P9_17", "P9_18", "P9_21", "P9_22", "P9_23", "P9_24", "P9_26",
|
|
||||||
"P9_27", "P9_30", "P9_41", "P9_42"].indexOf(node.pin) >= 0) {
|
|
||||||
// Don't set up interrupts & intervals until after the close event handler has been installed
|
|
||||||
bonescript.detachInterrupt(node.pin);
|
|
||||||
process.nextTick(function () {
|
|
||||||
bonescript.pinMode(node.pin, bonescript.INPUT);
|
bonescript.pinMode(node.pin, bonescript.INPUT);
|
||||||
bonescript.digitalRead(node.pin, function (x) {
|
bonescript.digitalRead(node.pin, function (x) {
|
||||||
// Initialise the currentState based on the value read
|
// Initialise the currentState and lastActveTime variables based on the value read
|
||||||
node.currentState = Number(x.value);
|
node.currentState = Number(x.value);
|
||||||
// Attempt to attach an interrupt handler to the pin. If we succeed,
|
if (node.currentState === node.activeState) {
|
||||||
// set the input event and interval handlers
|
node.lastActiveTime = Date.now();
|
||||||
var interruptType;
|
// switch to process.hrtime()
|
||||||
if (node.countType === "pulse") {
|
}
|
||||||
// interruptType = bonescript.FALLING; <- doesn't work in v0.2.4
|
// Attempt to attach a change-of-state interrupt handler to the pin. If we succeed,
|
||||||
interruptType = bonescript.RISING;
|
// set the input event and interval handlers, then send an initial message with the
|
||||||
} else {
|
// pin state on the first output
|
||||||
interruptType = bonescript.CHANGE;
|
if (bonescript.attachInterrupt(node.pin, true, bonescript.CHANGE, interruptCallback)) {
|
||||||
}
|
node.interruptAttached = true;
|
||||||
if (bonescript.attachInterrupt(node.pin, true, interruptType, interruptCallback)) {
|
node.on("input", inputCallback);
|
||||||
node.interruptAttached = true;
|
node.intervalId = setInterval(timerCallback, node.updateInterval);
|
||||||
node.on("input", inputCallback);
|
} else {
|
||||||
node.intervalId = setInterval(timerCallback, node.updateInterval);
|
node.error("Failed to attach interrupt");
|
||||||
} else {
|
}
|
||||||
node.error("Failed to attach interrupt");
|
setTimeout(function () { node.emit("input", {}); }, 50);
|
||||||
}
|
});
|
||||||
});
|
});
|
||||||
});
|
} else {
|
||||||
} else {
|
node.error("Unconfigured input pin");
|
||||||
node.error("Unconfigured input pin");
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Node constructor for bbb-discrete-out
|
// Node constructor for bbb-pulse-in
|
||||||
function DiscreteOutputNode(n) {
|
function PulseInputNode(n) {
|
||||||
RED.nodes.createNode(this, n);
|
RED.nodes.createNode(this, n);
|
||||||
|
|
||||||
// Store local copies of the node configuration (as defined in the .html)
|
// Store local copies of the node configuration (as defined in the .html)
|
||||||
this.topic = n.topic; // the topic is not currently used
|
this.topic = n.topic; // the topic is not currently used
|
||||||
this.pin = n.pin; // The Beaglebone Black pin identifying string
|
this.pin = n.pin; // The Beaglebone Black pin identifying string
|
||||||
this.defaultState = Number(n.defaultState); // What state to set up as
|
this.updateInterval = n.updateInterval * 1000; // How often to send output messages
|
||||||
this.inverting = n.inverting;
|
this.countType = n.countType; // Sets either 'edge' or 'pulse' counting
|
||||||
this.toggle = n.toggle;
|
this.countUnit = n.countUnit; // Scaling appling to count output
|
||||||
|
this.countRate = n.countRate; // Scaling applied to rate output
|
||||||
|
|
||||||
// Working variables
|
// Working variables
|
||||||
this.currentState = this.defaultState;
|
this.interruptAttached = false; // Flag: should we detach interrupt when we are closed?
|
||||||
|
this.intervalId = null; // Remember the timer ID so we can delete it when we are closed
|
||||||
|
this.pulseCount = 0; // (Unscaled) total pulse count
|
||||||
|
// Hold the hrtime of the last two pulses (with ns resolution)
|
||||||
|
this.pulseTime = [[NaN, NaN], [NaN, NaN]];
|
||||||
|
|
||||||
var node = this;
|
// Define 'node' to allow us to access 'this' from within callbacks
|
||||||
|
var node = this;
|
||||||
|
|
||||||
// If the input message paylod is numeric, values > 0.5 are 'true', otherwise use
|
// Called by the edge or pulse interrupt. If this is a valid interrupt, record the
|
||||||
// the truthiness of the payload. Apply the inversion flag before setting the output
|
// pulse time and count the pulse
|
||||||
var inputCallback = function (msg) {
|
var interruptCallback = function (x) {
|
||||||
var newState;
|
if (x.value !== undefined) {
|
||||||
if (node.toggle) {
|
node.pulseTime = [node.pulseTime[1], process.hrtime()];
|
||||||
newState = node.currentState === 0 ? 1 : 0;
|
node.pulseCount = node.pulseCount + 1;
|
||||||
} else {
|
}
|
||||||
if (isFinite(Number(msg.payload))) {
|
};
|
||||||
newState = Number(msg.payload) > 0.5 ? true : false;
|
|
||||||
} else if (msg.payload) {
|
// Called when an input message arrives. If the topic contains 'load' (case
|
||||||
newState = true;
|
// insensitive) and the payload is a valid number, set the count to that
|
||||||
|
// number, otherwise set it to zero
|
||||||
|
var inputCallback = function (msg) {
|
||||||
|
if (String(msg.topic).search(/load/i) < 0 || isFinite(msg.payload) === false) {
|
||||||
|
node.pulseCount = 0;
|
||||||
} else {
|
} else {
|
||||||
newState = false;
|
node.pulseCount = Number(msg.payload);
|
||||||
}
|
}
|
||||||
if (node.inverting) {
|
};
|
||||||
newState = !newState;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bonescript.digitalWrite(node.pin, newState ? 1 : 0);
|
|
||||||
node.send({ topic:node.topic, payload:newState });
|
|
||||||
node.currentState = newState;
|
|
||||||
};
|
|
||||||
|
|
||||||
// If we have a valid pin, set it as an output and set the default state
|
// Called by the message timer. Send two messages: the scaled pulse count on
|
||||||
if (["P8_7", "P8_8", "P8_9", "P8_10", "P8_11", "P8_12", "P8_13", "P8_14", "P8_15",
|
// the first output and the scaled instantaneous pulse rate on the second.
|
||||||
"P8_16", "P8_17", "P8_18", "P8_19", "P8_26", "P9_11", "P9_12", "P9_13", "P9_14",
|
// The instantaneous pulse rate is the reciprocal of the larger of either the
|
||||||
"P9_15", "P9_16", "P9_17", "P9_18", "P9_21", "P9_22", "P9_23", "P9_24", "P9_26",
|
// time interval between the last two pulses, or the time interval since the last pulse.
|
||||||
"P9_27", "P9_30", "P9_41", "P9_42", "USR0", "USR1", "USR2", "USR3"].indexOf(node.pin) >= 0) {
|
var timerCallback = function () {
|
||||||
// Don't set up interrupts & intervals until after the close event handler has been installed
|
var now = process.hrtime();
|
||||||
bonescript.detachInterrupt(node.pin);
|
var lastTime = node.pulseTime[1][0] - node.pulseTime[0][0] + (node.pulseTime[1][1] - node.pulseTime[0][1]) / 1e9;
|
||||||
process.nextTick(function () {
|
var thisTime = now[0] - node.pulseTime[1][0] + (now[1] - node.pulseTime[1][1]) / 1e9;
|
||||||
bonescript.pinMode(node.pin, bonescript.OUTPUT);
|
var msg = [{ topic:node.topic }, { topic:node.topic }];
|
||||||
node.on("input", inputCallback);
|
msg[0].payload = node.countUnit * node.pulseCount;
|
||||||
setTimeout(function () { bonescript.digitalWrite(node.pin, node.defaultState); }, 50);
|
// At startup, pulseTime contains NaN's: force the rate output to 0
|
||||||
});
|
msg[1].payload = node.countRate / Math.max(thisTime, lastTime) || 0;
|
||||||
} else {
|
node.send(msg);
|
||||||
node.error("Unconfigured output pin");
|
};
|
||||||
|
|
||||||
|
// If we have a valid pin, set it as an input and read the (digital) state
|
||||||
|
if (["P8_7", "P8_8", "P8_9", "P8_10", "P8_11", "P8_12", "P8_13", "P8_14", "P8_15",
|
||||||
|
"P8_16", "P8_17", "P8_18", "P8_19", "P8_26", "P9_11", "P9_12", "P9_13", "P9_14",
|
||||||
|
"P9_15", "P9_16", "P9_17", "P9_18", "P9_21", "P9_22", "P9_23", "P9_24", "P9_26",
|
||||||
|
"P9_27", "P9_30", "P9_41", "P9_42"].indexOf(node.pin) >= 0) {
|
||||||
|
// Don't set up interrupts & intervals until after the close event handler has been installed
|
||||||
|
bonescript.detachInterrupt(node.pin);
|
||||||
|
process.nextTick(function () {
|
||||||
|
bonescript.pinMode(node.pin, bonescript.INPUT);
|
||||||
|
bonescript.digitalRead(node.pin, function (x) {
|
||||||
|
// Initialise the currentState based on the value read
|
||||||
|
node.currentState = Number(x.value);
|
||||||
|
// Attempt to attach an interrupt handler to the pin. If we succeed,
|
||||||
|
// set the input event and interval handlers
|
||||||
|
var interruptType;
|
||||||
|
if (node.countType === "pulse") {
|
||||||
|
// interruptType = bonescript.FALLING; <- doesn't work in v0.2.4
|
||||||
|
interruptType = bonescript.RISING;
|
||||||
|
} else {
|
||||||
|
interruptType = bonescript.CHANGE;
|
||||||
|
}
|
||||||
|
if (bonescript.attachInterrupt(node.pin, true, interruptType, interruptCallback)) {
|
||||||
|
node.interruptAttached = true;
|
||||||
|
node.on("input", inputCallback);
|
||||||
|
node.intervalId = setInterval(timerCallback, node.updateInterval);
|
||||||
|
} else {
|
||||||
|
node.error("Failed to attach interrupt");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
node.error("Unconfigured input pin");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Node constructor for bbb-pulse-out
|
// Node constructor for bbb-discrete-out
|
||||||
function PulseOutputNode(n) {
|
function DiscreteOutputNode(n) {
|
||||||
RED.nodes.createNode(this, n);
|
RED.nodes.createNode(this, n);
|
||||||
|
|
||||||
// Store local copies of the node configuration (as defined in the .html)
|
// Store local copies of the node configuration (as defined in the .html)
|
||||||
this.topic = n.topic; // the topic is not currently used
|
this.topic = n.topic; // the topic is not currently used
|
||||||
this.pin = n.pin; // The Beaglebone Black pin identifying string
|
this.pin = n.pin; // The Beaglebone Black pin identifying string
|
||||||
this.pulseState = Number(n.pulseState); // What state the pulse will be..
|
this.defaultState = Number(n.defaultState); // What state to set up as
|
||||||
this.defaultState = this.pulseState === 1 ? 0 : 1;
|
this.inverting = n.inverting;
|
||||||
this.retriggerable = n.retriggerable;
|
this.toggle = n.toggle;
|
||||||
this.pulseTime = n.pulseTime * 1000; // Pulse width in milliseconds
|
|
||||||
|
|
||||||
// Working variables
|
// Working variables
|
||||||
this.pulseTimer = null; // Non-null while a pulse is being generated
|
this.currentState = this.defaultState;
|
||||||
|
|
||||||
var node = this;
|
var node = this;
|
||||||
|
|
||||||
// Generate a pulse in response to an input message. If the topic includes the text
|
// If the input message paylod is numeric, values > 0.5 are 'true', otherwise use
|
||||||
// 'time' (case insensitive) and the payload is numeric, use this value as the
|
// the truthiness of the payload. Apply the inversion flag before setting the output
|
||||||
// pulse time. Otherwise use the value from the properties dialog.
|
var inputCallback = function (msg) {
|
||||||
// If the resulting pulse time is < 1ms, do nothing.
|
var newState;
|
||||||
// If the pulse mode is not retriggerable, then if no pulseTimer is active, generate
|
if (node.toggle) {
|
||||||
// a pulse. If the pulse mode is retriggerable, and a pulseTimer is active, cancel it.
|
newState = node.currentState === 0 ? 1 : 0;
|
||||||
// If no timer is active, set the pulse output. In both cases schedule a new pulse
|
|
||||||
// timer.
|
|
||||||
var inputCallback = function (msg) {
|
|
||||||
var time = node.pulseTime;
|
|
||||||
if (String(msg.topic).search(/time/i) >= 0 && isFinite(msg.payload)) {
|
|
||||||
time = msg.payload * 1000;
|
|
||||||
}
|
|
||||||
if (time >= 1) {
|
|
||||||
if (node.retriggerable === false) {
|
|
||||||
if (node.pulseTimer === null) {
|
|
||||||
node.pulseTimer = setTimeout(endPulseCallback, time);
|
|
||||||
bonescript.digitalWrite(node.pin, node.pulseState);
|
|
||||||
node.send({ topic:node.topic, payload:node.pulseState });
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (node.pulseTimer !== null) {
|
if (isFinite(Number(msg.payload))) {
|
||||||
clearTimeout(node.pulseTimer);
|
newState = Number(msg.payload) > 0.5 ? true : false;
|
||||||
|
} else if (msg.payload) {
|
||||||
|
newState = true;
|
||||||
} else {
|
} else {
|
||||||
bonescript.digitalWrite(node.pin, node.pulseState);
|
newState = false;
|
||||||
node.send({ topic:node.topic, payload:node.pulseState });
|
}
|
||||||
|
if (node.inverting) {
|
||||||
|
newState = !newState;
|
||||||
}
|
}
|
||||||
node.pulseTimer = setTimeout(endPulseCallback, time);
|
|
||||||
}
|
}
|
||||||
}
|
bonescript.digitalWrite(node.pin, newState ? 1 : 0);
|
||||||
};
|
node.send({ topic:node.topic, payload:newState });
|
||||||
|
node.currentState = newState;
|
||||||
|
};
|
||||||
|
|
||||||
// At the end of the pulse, restore the default state and set the timer to null
|
// If we have a valid pin, set it as an output and set the default state
|
||||||
var endPulseCallback = function () {
|
if (["P8_7", "P8_8", "P8_9", "P8_10", "P8_11", "P8_12", "P8_13", "P8_14", "P8_15",
|
||||||
node.pulseTimer = null;
|
"P8_16", "P8_17", "P8_18", "P8_19", "P8_26", "P9_11", "P9_12", "P9_13", "P9_14",
|
||||||
bonescript.digitalWrite(node.pin, node.defaultState);
|
"P9_15", "P9_16", "P9_17", "P9_18", "P9_21", "P9_22", "P9_23", "P9_24", "P9_26",
|
||||||
node.send({ topic:node.topic, payload:node.defaultState });
|
"P9_27", "P9_30", "P9_41", "P9_42", "USR0", "USR1", "USR2", "USR3"].indexOf(node.pin) >= 0) {
|
||||||
};
|
// Don't set up interrupts & intervals until after the close event handler has been installed
|
||||||
|
bonescript.detachInterrupt(node.pin);
|
||||||
// If we have a valid pin, set it as an output and set the default state
|
process.nextTick(function () {
|
||||||
if (["P8_7", "P8_8", "P8_9", "P8_10", "P8_11", "P8_12", "P8_13", "P8_14", "P8_15",
|
bonescript.pinMode(node.pin, bonescript.OUTPUT);
|
||||||
"P8_16", "P8_17", "P8_18", "P8_19", "P8_26", "P9_11", "P9_12", "P9_13", "P9_14",
|
node.on("input", inputCallback);
|
||||||
"P9_15", "P9_16", "P9_17", "P9_18", "P9_21", "P9_22", "P9_23", "P9_24", "P9_26",
|
setTimeout(function () { bonescript.digitalWrite(node.pin, node.defaultState); }, 50);
|
||||||
"P9_27", "P9_30", "P9_41", "P9_42", "USR0", "USR1", "USR2", "USR3"].indexOf(node.pin) >= 0) {
|
});
|
||||||
// Don't set up interrupts & intervals until after the close event handler has been installed
|
} else {
|
||||||
bonescript.detachInterrupt(node.pin);
|
node.error("Unconfigured output pin");
|
||||||
process.nextTick(function () {
|
}
|
||||||
bonescript.pinMode(node.pin, bonescript.OUTPUT);
|
|
||||||
node.on("input", inputCallback);
|
|
||||||
// Set the pin to the default stte once the dust settles
|
|
||||||
setTimeout(endPulseCallback, 50);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
node.error("Unconfigured output pin");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Node constructor for bbb-pulse-out
|
||||||
|
function PulseOutputNode(n) {
|
||||||
|
RED.nodes.createNode(this, n);
|
||||||
|
|
||||||
|
// Store local copies of the node configuration (as defined in the .html)
|
||||||
|
this.topic = n.topic; // the topic is not currently used
|
||||||
|
this.pin = n.pin; // The Beaglebone Black pin identifying string
|
||||||
|
this.pulseState = Number(n.pulseState); // What state the pulse will be..
|
||||||
|
this.defaultState = this.pulseState === 1 ? 0 : 1;
|
||||||
|
this.retriggerable = n.retriggerable;
|
||||||
|
this.pulseTime = n.pulseTime * 1000; // Pulse width in milliseconds
|
||||||
|
|
||||||
|
// Working variables
|
||||||
|
this.pulseTimer = null; // Non-null while a pulse is being generated
|
||||||
|
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
// Generate a pulse in response to an input message. If the topic includes the text
|
||||||
|
// 'time' (case insensitive) and the payload is numeric, use this value as the
|
||||||
|
// pulse time. Otherwise use the value from the properties dialog.
|
||||||
|
// If the resulting pulse time is < 1ms, do nothing.
|
||||||
|
// If the pulse mode is not retriggerable, then if no pulseTimer is active, generate
|
||||||
|
// a pulse. If the pulse mode is retriggerable, and a pulseTimer is active, cancel it.
|
||||||
|
// If no timer is active, set the pulse output. In both cases schedule a new pulse
|
||||||
|
// timer.
|
||||||
|
var inputCallback = function (msg) {
|
||||||
|
var time = node.pulseTime;
|
||||||
|
if (String(msg.topic).search(/time/i) >= 0 && isFinite(msg.payload)) {
|
||||||
|
time = msg.payload * 1000;
|
||||||
|
}
|
||||||
|
if (time >= 1) {
|
||||||
|
if (node.retriggerable === false) {
|
||||||
|
if (node.pulseTimer === null) {
|
||||||
|
node.pulseTimer = setTimeout(endPulseCallback, time);
|
||||||
|
bonescript.digitalWrite(node.pin, node.pulseState);
|
||||||
|
node.send({ topic:node.topic, payload:node.pulseState });
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (node.pulseTimer !== null) {
|
||||||
|
clearTimeout(node.pulseTimer);
|
||||||
|
} else {
|
||||||
|
bonescript.digitalWrite(node.pin, node.pulseState);
|
||||||
|
node.send({ topic:node.topic, payload:node.pulseState });
|
||||||
|
}
|
||||||
|
node.pulseTimer = setTimeout(endPulseCallback, time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// At the end of the pulse, restore the default state and set the timer to null
|
||||||
|
var endPulseCallback = function () {
|
||||||
|
node.pulseTimer = null;
|
||||||
|
bonescript.digitalWrite(node.pin, node.defaultState);
|
||||||
|
node.send({ topic:node.topic, payload:node.defaultState });
|
||||||
|
};
|
||||||
|
|
||||||
|
// If we have a valid pin, set it as an output and set the default state
|
||||||
|
if (["P8_7", "P8_8", "P8_9", "P8_10", "P8_11", "P8_12", "P8_13", "P8_14", "P8_15",
|
||||||
|
"P8_16", "P8_17", "P8_18", "P8_19", "P8_26", "P9_11", "P9_12", "P9_13", "P9_14",
|
||||||
|
"P9_15", "P9_16", "P9_17", "P9_18", "P9_21", "P9_22", "P9_23", "P9_24", "P9_26",
|
||||||
|
"P9_27", "P9_30", "P9_41", "P9_42", "USR0", "USR1", "USR2", "USR3"].indexOf(node.pin) >= 0) {
|
||||||
|
// Don't set up interrupts & intervals until after the close event handler has been installed
|
||||||
|
bonescript.detachInterrupt(node.pin);
|
||||||
|
process.nextTick(function () {
|
||||||
|
bonescript.pinMode(node.pin, bonescript.OUTPUT);
|
||||||
|
node.on("input", inputCallback);
|
||||||
|
// Set the pin to the default stte once the dust settles
|
||||||
|
setTimeout(endPulseCallback, 50);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
node.error("Unconfigured output pin");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register the nodes by name. This must be called before overriding any of the Node functions.
|
||||||
|
RED.nodes.registerType("bbb-analogue-in", AnalogueInputNode);
|
||||||
|
RED.nodes.registerType("bbb-discrete-in", DiscreteInputNode);
|
||||||
|
RED.nodes.registerType("bbb-pulse-in", PulseInputNode);
|
||||||
|
RED.nodes.registerType("bbb-discrete-out", DiscreteOutputNode);
|
||||||
|
RED.nodes.registerType("bbb-pulse-out", PulseOutputNode);
|
||||||
|
|
||||||
|
// On close, detach the interrupt (if we attached one) and clear any active timers
|
||||||
|
DiscreteInputNode.prototype.close = function () {
|
||||||
|
if (this.interruptAttached) {
|
||||||
|
bonescript.detachInterrupt(this.pin);
|
||||||
|
}
|
||||||
|
if (this.intervalId !== null) {
|
||||||
|
clearInterval(this.intervalId);
|
||||||
|
}
|
||||||
|
if (this.debounceTimer !== null) {
|
||||||
|
clearTimeout(this.debounceTimer);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// On close, detach the interrupt (if we attached one) and clear the interval (if we set one)
|
||||||
|
PulseInputNode.prototype.close = function () {
|
||||||
|
if (this.interruptAttached) {
|
||||||
|
bonescript.detachInterrupt(this.pin);
|
||||||
|
}
|
||||||
|
if (this.intervalId !== null) {
|
||||||
|
clearInterval(this.intervalId);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// On close, clear an active pulse timer
|
||||||
|
PulseOutputNode.prototype.close = function () {
|
||||||
|
if (this.pulseTimer !== null) {
|
||||||
|
clearTimeout(this.pulseTimer);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the nodes by name. This must be called before overriding any of the Node functions.
|
|
||||||
RED.nodes.registerType("bbb-analogue-in", AnalogueInputNode);
|
|
||||||
RED.nodes.registerType("bbb-discrete-in", DiscreteInputNode);
|
|
||||||
RED.nodes.registerType("bbb-pulse-in", PulseInputNode);
|
|
||||||
RED.nodes.registerType("bbb-discrete-out", DiscreteOutputNode);
|
|
||||||
RED.nodes.registerType("bbb-pulse-out", PulseOutputNode);
|
|
||||||
|
|
||||||
// On close, detach the interrupt (if we attached one) and clear any active timers
|
|
||||||
DiscreteInputNode.prototype.close = function () {
|
|
||||||
if (this.interruptAttached) {
|
|
||||||
bonescript.detachInterrupt(this.pin);
|
|
||||||
}
|
|
||||||
if (this.intervalId !== null) {
|
|
||||||
clearInterval(this.intervalId);
|
|
||||||
}
|
|
||||||
if (this.debounceTimer !== null) {
|
|
||||||
clearTimeout(this.debounceTimer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// On close, detach the interrupt (if we attached one) and clear the interval (if we set one)
|
|
||||||
PulseInputNode.prototype.close = function () {
|
|
||||||
if (this.interruptAttached) {
|
|
||||||
bonescript.detachInterrupt(this.pin);
|
|
||||||
}
|
|
||||||
if (this.intervalId !== null) {
|
|
||||||
clearInterval(this.intervalId);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// On close, clear an active pulse timer
|
|
||||||
PulseOutputNode.prototype.close = function () {
|
|
||||||
if (this.pulseTimer !== null) {
|
|
||||||
clearTimeout(this.pulseTimer);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
@ -37,29 +37,30 @@ function BleScan(n) {
|
|||||||
this.ble_name = n.ble_name;
|
this.ble_name = n.ble_name;
|
||||||
this.ble_uuid = n.ble_uuid;
|
this.ble_uuid = n.ble_uuid;
|
||||||
|
|
||||||
this.on("input", function(msg){
|
this.on("input", function(msg){
|
||||||
noble.startScanning();
|
noble.startScanning();
|
||||||
});
|
});
|
||||||
noble.on('scanStart', function(msg) {
|
|
||||||
var msg = {};
|
noble.on('scanStart', function(msg) {
|
||||||
|
msg = {};
|
||||||
msg.topic = node.topic;
|
msg.topic = node.topic;
|
||||||
msg.payload = "Scanning initiated..." //debugging
|
msg.payload = "Scanning initiated..." //debugging
|
||||||
//console.log('scanning initiated...');
|
//console.log('scanning initiated...');
|
||||||
node.send(msg);
|
node.send(msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
noble.on('discover', function(peripheral) {
|
|
||||||
|
|
||||||
|
noble.on('discover', function(peripheral) {
|
||||||
var msg = {};
|
var msg = {};
|
||||||
msg.topic = node.topic;
|
msg.topic = node.topic;
|
||||||
msg.payload = "not found";
|
msg.payload = "not found";
|
||||||
|
|
||||||
//check for the device name and the UUID (first one from the UUID list)
|
//check for the device name and the UUID (first one from the UUID list)
|
||||||
if(peripheral.advertisement.localName==node.ble_name && peripheral.advertisement.serviceUuids[0]==node.ble_uuid) {
|
if(peripheral.advertisement.localName==node.ble_name && peripheral.advertisement.serviceUuids[0]==node.ble_uuid) {
|
||||||
msg.payload=peripheral.advertisement.localName;
|
msg.payload=peripheral.advertisement.localName;
|
||||||
noble.stopScanning(); }
|
noble.stopScanning();
|
||||||
|
}
|
||||||
node.send(msg);
|
node.send(msg);
|
||||||
});
|
});
|
||||||
|
|
||||||
this.on("close", function() {
|
this.on("close", function() {
|
||||||
try { noble.stopScanning(); }
|
try { noble.stopScanning(); }
|
||||||
|
@ -16,12 +16,12 @@
|
|||||||
|
|
||||||
module.exports = function(RED) {
|
module.exports = function(RED) {
|
||||||
"use strict";
|
"use strict";
|
||||||
var WeMo = new require('wemo');
|
var Wemo = require('wemo');
|
||||||
|
|
||||||
function WeMoOut(n) {
|
function WemoOut(n) {
|
||||||
RED.nodes.createNode(this,n);
|
RED.nodes.createNode(this,n);
|
||||||
this.ipaddr = n.ipaddr;
|
this.ipaddr = n.ipaddr;
|
||||||
this.wemoSwitch = new WeMo(n.ipaddr);
|
this.wemoSwitch = new Wemo(n.ipaddr);
|
||||||
var node = this;
|
var node = this;
|
||||||
|
|
||||||
this.on("input", function(msg) {
|
this.on("input", function(msg) {
|
||||||
@ -35,9 +35,9 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
RED.nodes.registerType("wemo out",WeMoOut);
|
RED.nodes.registerType("wemo out",WemoOut);
|
||||||
|
|
||||||
function WeMoIn(n) {
|
function WemoIn(n) {
|
||||||
RED.nodes.createNode(this,n);
|
RED.nodes.createNode(this,n);
|
||||||
this.ipaddr = n.ipaddr;
|
this.ipaddr = n.ipaddr;
|
||||||
this.wemoSwitch = new WeMo(n.ipaddr);
|
this.wemoSwitch = new WeMo(n.ipaddr);
|
||||||
@ -58,5 +58,5 @@ module.exports = function(RED) {
|
|||||||
clearInterval(tick);
|
clearInterval(tick);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
RED.nodes.registerType("wemo in",WeMoOut);
|
RED.nodes.registerType("wemo in",WemoIn);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user