Move all nodes into core subdirectory

This makes it easier to distinguish core nodes from those added later
This commit is contained in:
Nicholas O'Leary
2013-11-14 15:52:19 +00:00
parent affcc8ae65
commit 48dabffefc
70 changed files with 0 additions and 0 deletions

View File

@@ -0,0 +1,150 @@
<!--
Copyright 2013 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.
-->
<script type="text/x-red" data-template-name="arduino in">
<div class="form-row">
<label for="node-input-arduino"><i class="icon-tasks"></i> Arduino</label>
<input type="text" id="node-input-arduino">
</div>
<div class="form-row">
<label for="node-input-pin"><i class="icon-asterisk"></i> Pin</label>
<input type="text" id="node-input-pin" placeholder="2">
</div>
<div class="form-row">
<label for="node-input-state"><i class="icon-wrench"></i> Type</label>
<select type="text" id="node-input-state" style="width: 150px;">
<option value="INPUT">Digital pin</option>
<option value="ANALOG">Analogue pin</option>
</select>
</div>
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-tips"><b>Note:</b> You cannot use the same pin for both output and input.</div>
</script>
<script type="text/x-red" data-help-name="arduino in">
<p>Arduino input node. Connects to local Arduino and monitors the selected pin for changes. Uses <a href="http://firmata.org/" target="_new"><i>Firmata</i>.</a></p>
<p>You can select either Digital or Analogue input. Outputs the value read as <b>msg.payload</b> and the pin number as <b>msg.topic</b>.</p>
<p>It only outputs on a change of value - fine for digital inputs, but you can get a lot of data from analogue pins which you must then handle.</p>
<p>You can set the sample rate in ms from 20 to 65535.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('arduino in',{
category: 'advanced-input',
color:"#3fadb5",
defaults: {
name: {value:""},
pin: {value:"",required:true},
state: {value:"INPUT",required:true},
arduino: {type:"arduino-board",required:true}
},
inputs:0,
outputs:1,
icon: "arduino.png",
label: function() {
var a = "";
if (this.state == "ANALOG") a = "A";
return this.name||"Pin: "+a+this.pin;
},
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});
</script>
<script type="text/x-red" data-template-name="arduino out">
<div class="form-row">
<label for="node-input-arduino"><i class="icon-tasks"></i> Arduino</label>
<input type="text" id="node-input-arduino">
</div>
<div class="form-row">
<label for="node-input-pin"><i class="icon-asterisk"></i> Pin</label>
<input type="text" id="node-input-pin" placeholder="13">
</div>
<div class="form-row">
<label for="node-input-state"><i class="icon-wrench"></i> Type</label>
<select type="text" id="node-input-state" style="width: 150px;">
<option value="OUTPUT">Digital (0/1)</option>
<option value="PWM">Analogue (0-255)</option>
<option value="SERVO">Servo (0-180)</option>
</select>
</div>
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-tips"><b>Note:</b> You cannot use the same pin for both output and input.</div>
</script>
<script type="text/x-red" data-help-name="arduino out">
<p>Arduino output node. Connects to local Arduino and writes to the selected digital pin. Uses <a href="http://firmata.org/" target="_new"><i>Firmata</i>.</a></p>
<p>You can select Digital, Analogue (PWM) or Servo type outputs. Expects a numeric value in <b>msg.payload</b>. The pin number is set in the properties panel.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('arduino out',{
category: 'advanced-output',
color:"#3fadb5",
defaults: {
name: {value:""},
pin: {value:""},
state: {value:"",required:true},
arduino: {type:"arduino-board",required:true}
},
inputs:1,
outputs:0,
icon: "arduino.png",
align: "right",
label: function() {
return this.name||"Pin: "+this.pin;
},
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});
</script>
<script type="text/x-red" data-template-name="arduino-board">
<div class="form-row">
<label for="node-config-input-device"><i class="icon-bullhorn"></i> Arduino Port</label>
<input type="text" id="node-config-input-device" placeholder="/dev/ttyUSB0" style="width:50%;">
</div>
<div class="form-row">
<label for="node-config-input-repeat"><i class="icon-repeat"></i> Sample (ms)</label>
<input type="text" id="node-config-input-repeat" placeholder="25">
</div>
<!-- <div class="form-row">
<label for="node-config-input-baud"><i class="icon-bullhorn"></i> Baudrate</label>
<input type="text" id="node-config-input-baud" placeholder="115200" style="width:50%;">
</div> -->
</script>
<script type="text/javascript">
RED.nodes.registerType('arduino-board',{
category: 'config',
defaults: {
//baud: {baud:"57600",required:true},
repeat: {value:"50",required:true,validate:RED.validators.number()},
device: {value:"",required:true}
},
label: function() {
return this.device||"arduino";
}
});
</script>

View File

@@ -0,0 +1,187 @@
/**
* Copyright 2013 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.
**/
var RED = require(process.env.NODE_RED_HOME+"/red/red");
var util = require("util");
var firmata = require("firmata");
var arduinoReady = false;
var thisboard = null;
// The Board Definition - this opens (and closes) the connection
function ArduinoNode(n) {
RED.nodes.createNode(this,n);
this.device = n.device;
this.repeat = n.repeat||25;
util.log("[firmata] Opening "+this.device);
var node = this;
node.toun = setInterval(function() {
if (!arduinoReady) {
if (thisboard == null) {
node.board = new firmata.Board(node.device, function(err) {
if (err) {
util.log("[firmata] error: "+err);
return;
}
arduinoReady = true;
thisboard = node.board;
clearInterval(node.toun);
util.log('[firmata] Arduino connected');
});
}
else {
node.board = thisboard;
node.board.removeAllListeners();
arduinoReady = true;
clearInterval(node.toun);
node.toun = false;
util.log("[firmata] Arduino already connected");
}
} else { util.log("[firmata] Waiting for Firmata"); }
}, 10000); // wait for firmata to connect to arduino
this.on('close', function() {
//this.board.sp.close(function() { console.log("[firmata] Serial port closed"); arduinoReady = false; });
arduinoReady = false;
if (node.toun) {
clearInterval(node.toun);
util.log("[firmata] arduino wait loop stopped");
}
util.log("[firmata] Stopped");
});
}
RED.nodes.registerType("arduino-board",ArduinoNode);
// The Input Node
function DuinoNodeIn(n) {
RED.nodes.createNode(this,n);
this.buttonState = -1;
this.pin = n.pin;
this.state = n.state;
this.arduino = n.arduino;
this.serverConfig = RED.nodes.getNode(this.arduino);
if (typeof this.serverConfig === "object") {
this.board = this.serverConfig.board;
this.repeat = this.serverConfig.repeat;
var node = this;
node.toui = setInterval(function() {
if (thisboard != null) {
node.board = thisboard;
clearInterval(node.toui);
node.toui = false;
//console.log("i",node.state,node.pin,node.board.MODES[node.state]);
node.board.pinMode(node.pin, node.board.MODES[node.state]);
node.board.setSamplingInterval(node.repeat);
var oldrdg = "";
if (node.state == "ANALOG") {
node.board.analogRead(node.pin, function(data) {
var msg = {payload:data, topic:"A"+node.pin};
if (data != oldrdg) {
node.send(msg);
oldrdg = data;
}
});
}
else {
node.board.digitalRead(node.pin, function(data) {
var msg = {payload:data, topic:node.pin};
node.send(msg);
});
}
}
else { node.log("Waiting for Arduino"); }
}, 5000); // loop to wait for firmata to connect to arduino
this.on('close', function() {
if (node.toui) {
clearInterval(node.toui);
util.log("[firmata] input wait loop stopped");
}
});
}
else {
util.log("[firmata] Serial Port not Configured");
}
}
RED.nodes.registerType("arduino in",DuinoNodeIn);
// The Output Node
function DuinoNodeOut(n) {
RED.nodes.createNode(this,n);
this.buttonState = -1;
this.pin = n.pin;
this.state = n.state;
this.arduino = n.arduino;
this.serverConfig = RED.nodes.getNode(this.arduino);
if (typeof this.serverConfig === "object") {
this.board = this.serverConfig.board;
var node = this;
this.on("input", function(msg) {
//console.log(msg);
if (node.board != null) {
if (node.state == "OUTPUT") {
if ((msg.payload == true)||(msg.payload == 1)||(msg.payload.toString().toLowerCase() == "on")) {
node.board.digitalWrite(node.pin, node.board.HIGH);
}
if ((msg.payload == false)||(msg.payload == 0)||(msg.payload.toString().toLowerCase() == "off")) {
node.board.digitalWrite(node.pin, node.board.LOW);
}
}
if (node.state == "PWM") {
msg.payload = msg.payload * 1;
if ((msg.payload >= 0) && (msg.payload <= 255)) {
//console.log(msg.payload, node.pin);
node.board.servoWrite(node.pin, msg.payload);
}
}
if (node.state == "SERVO") {
msg.payload = msg.payload * 1;
if ((msg.payload >= 0) && (msg.payload <= 180)) {
//console.log(msg.payload, node.pin);
node.board.servoWrite(node.pin, msg.payload);
}
}
}
//else { console.log("Arduino not ready"); }
});
node.touo = setInterval(function() {
if (thisboard != null) {
clearInterval(node.touo);
node.touo = false;
node.board = thisboard;
//console.log("o",node.state,node.pin,node.board.MODES[node.state]);
node.board.pinMode(node.pin, node.board.MODES[node.state]);
}
else { util.log("[firmata] waiting for arduino to connect"); }
}, 5000); // loop to wait for firmata to connect to arduino
this.on('close', function() {
if (node.touo) {
clearInterval(node.touo);
util.log("[firmata] output wait loop stopped");
}
});
}
else {
util.log("[firmata] Serial Port not Configured");
}
}
RED.nodes.registerType("arduino out",DuinoNodeOut);

View File

@@ -0,0 +1,126 @@
<!--
Copyright 2013 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.
-->
<script type="text/x-red" data-template-name="rpi-gpio in">
<div class="form-row">
<label for="node-input-pin"><i class="icon-asterisk"></i> GPIO Pin</label>
<select type="text" id="node-input-pin" style="width: 150px;">
<option value="-">select pin</option>
<option value="7">7</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="18">18</option>
<option value="22">22</option>
</select>
</div>
<div class="form-row">
<label for="node-input-intype"><i class=" icon-resize-full"></i> Resistor?</label>
<select type="text" id="node-input-intype" style="width: 150px;">
<option value="tri">none</option>
<option value="up">pullup</option>
<option value="down">pulldown</option>
<!--<option value="tri">tristate</option>-->
</select>
</div>
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-tips">Tip: Only Digital I/O is supported - input must be 0 or 1.</div>
</script>
<script type="text/x-red" data-help-name="rpi-gpio in">
<p>Raspberry Pi input node. Generates a <b>msg.payload</b> with either a 0 or 1 depending on the state of the input pin. Requires the gpio command to work.</p>
<p>You may also enable the input pullup resitor or the pulldown resistor.</p>
<p>The <b>msg.topic</b> is set to <i>pi/{the pin number}</i></p>
<p><b>Note:</b> we are using the actual physical pin numbers on connector P1 as they are easier to locate.</p>
<p><b>Note:</b> This node currently polls the pin every 250mS. This is not ideal as it loads the cpu, and will be rewritten shortly to try to use interrupts.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('rpi-gpio in',{
category: 'advanced-input',
color:"#c6dbef",
defaults: {
name: { value:"" },
intype: { value: "in" },
pin: { value:"",required:true,validate:RED.validators.number() },
},
inputs:0,
outputs:1,
icon: "rpi.png",
label: function() {
return this.name||"Pin: "+this.pin ;
},
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});
</script>
<script type="text/x-red" data-template-name="rpi-gpio out">
<div class="form-row">
<label for="node-input-pin"><i class="icon-asterisk"></i> GPIO Pin</label>
<select type="text" id="node-input-pin" style="width: 150px;">
<option value="-">select pin</option>
<option value="7">7</option>
<option value="11">11</option>
<option value="12">12</option>
<option value="13">13</option>
<option value="15">15</option>
<option value="16">16</option>
<option value="18">18</option>
<option value="22">22</option>
</select>
</div>
<div class="form-row">
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Name">
</div>
<div class="form-tips">Tip: Only Digital I/O is supported - input must be 0 or 1.</div>
</script>
<script type="text/x-red" data-help-name="rpi-gpio out">
<p>Raspberry Pi output node. Expects a <b>msg.payload</b> with either a 0 or 1 (or true or false). Requires the gpio command to work.</p>
<p>Will set the selected physical pin high or low depending on the value passed in.</p>
<p><b>Note:</b> we are using the actual physical pin numbers on connector P1 as they are easier to locate.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('rpi-gpio out',{
category: 'advanced-output',
color:"#c6dbef",
defaults: {
name: { value:"" },
pin: { value:"",required:true,validate:RED.validators.number() },
},
inputs:1,
outputs:0,
icon: "rpi.png",
align: "right",
label: function() {
return this.name||"Pin: "+this.pin;
},
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});
</script>

View File

@@ -0,0 +1,143 @@
/**
* Copyright 2013 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.
**/
var RED = require(process.env.NODE_RED_HOME+"/red/red");
var util = require("util");
var exec = require('child_process').exec;
var fs = require('fs');
if (!fs.existsSync("/usr/local/bin/gpio")) {
exec("cat /proc/cpuinfo | grep BCM27",function(err,stdout,stderr) {
if (stdout.indexOf('BCM27') > -1) {
util.log('[36-rpi-gpio.js] Error: Cannot find Wiring-Pi "gpio" command. http://wiringpi.com/download-and-install/');
}
// else not on a Pi so don't worry anyone with needless messages.
});
return;
}
// Map physical P1 pins to Gordon's Wiring-Pi Pins (as they should be V1/V2 tolerant)
var pintable = {
// Physical : WiringPi
"7":"7",
"11":"0",
"12":"1",
"13":"2",
"15":"3",
"16":"4",
"18":"5",
"22":"6"
}
var tablepin = {
// WiringPi : Physical
"7":"7",
"0":"11",
"1":"12",
"2":"13",
"3":"15",
"4":"16",
"5":"18",
"6":"22"
}
function GPIOInNode(n) {
RED.nodes.createNode(this,n);
this.buttonState = -1;
this.pin = pintable[n.pin];
this.intype = n.intype;
var node = this;
if (this.pin) {
exec("gpio mode "+node.pin+" "+node.intype, function(err,stdout,stderr) {
if (err) node.error(err);
else {
node._interval = setInterval( function() {
exec("gpio read "+node.pin, function(err,stdout,stderr) {
if (err) node.error(err);
else {
if (node.buttonState !== Number(stdout)) {
var previousState = node.buttonState;
node.buttonState = Number(stdout);
if (previousState !== -1) {
var msg = {topic:"pi/"+tablepin[node.pin], payload:node.buttonState};
node.send(msg);
}
}
}
});
}, 250);
}
});
}
else {
this.error("Invalid GPIO pin: "+this.pin);
}
}
function GPIOOutNode(n) {
RED.nodes.createNode(this,n);
this.pin = pintable[n.pin];
var node = this;
if (this.pin) {
process.nextTick(function() {
exec("gpio mode "+node.pin+" out", function(err,stdout,stderr) {
if (err) node.error(err);
else {
node.on("input", function(msg) {
if (msg.payload === "true") msg.payload = true;
if (msg.payload === "false") msg.payload = false;
var out = Number(msg.payload);
if ((out == 0)|(out == 1)) {
exec("gpio write "+node.pin+" "+out, function(err,stdout,stderr) {
if (err) node.error(err);
});
}
else node.warn("Invalid input - not 0 or 1");
});
}
});
});
}
else {
this.error("Invalid GPIO pin: "+this.pin);
}
}
exec("gpio mode 0 in",function(err,stdout,stderr) {
if (err) {
util.log('[36-rpi-gpio.js] Error: "gpio" command failed for some reason.');
}
exec("gpio mode 1 in");
exec("gpio mode 2 in");
exec("gpio mode 3 in");
exec("gpio mode 4 in");
exec("gpio mode 5 in");
exec("gpio mode 6 in");
exec("gpio mode 7 in",function(err,stdout,stderr) {
RED.nodes.registerType("rpi-gpio in",GPIOInNode);
RED.nodes.registerType("rpi-gpio out",GPIOOutNode);
GPIOInNode.prototype.close = function() {
clearInterval(this._interval);
}
GPIOOutNode.prototype.close = function() {
exec("gpio mode "+this.pin+" in");
}
});
});