summaryrefslogtreecommitdiffstats
path: root/dgbuilder/core_nodes/hardware
diff options
context:
space:
mode:
Diffstat (limited to 'dgbuilder/core_nodes/hardware')
-rw-r--r--dgbuilder/core_nodes/hardware/35-arduino.html171
-rw-r--r--dgbuilder/core_nodes/hardware/35-arduino.js160
-rw-r--r--dgbuilder/core_nodes/hardware/36-rpi-gpio.html182
-rw-r--r--dgbuilder/core_nodes/hardware/36-rpi-gpio.js185
4 files changed, 698 insertions, 0 deletions
diff --git a/dgbuilder/core_nodes/hardware/35-arduino.html b/dgbuilder/core_nodes/hardware/35-arduino.html
new file mode 100644
index 00000000..17f02892
--- /dev/null
+++ b/dgbuilder/core_nodes/hardware/35-arduino.html
@@ -0,0 +1,171 @@
+<!--
+ Copyright 2013,2014 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="fa fa-tasks"></i> Arduino</label>
+ <input type="text" id="node-input-arduino">
+ </div>
+ <div class="form-row">
+ <label for="node-input-pin"><i class="fa fa-circle"></i> Pin</label>
+ <input type="text" id="node-input-pin" placeholder="2">
+ </div>
+ <div class="form-row">
+ <label for="node-input-state"><i class="fa fa-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="fa fa-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>The Arduino must be loaded with the Standard Firmata sketch available in the Arduino examples.</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: 'Arduino',
+ color:"#3fadb5",
+ defaults: {
+ name: {value:""},
+ pin: {value:"",required:true},
+ state: {value:"INPUT",required:true},
+ arduino: {type:"arduino-board"}
+ },
+ 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="fa fa-tasks"></i> Arduino</label>
+ <input type="text" id="node-input-arduino">
+ </div>
+ <div class="form-row">
+ <label for="node-input-pin"><i class="fa fa-circle"></i> Pin</label>
+ <input type="text" id="node-input-pin" placeholder="13">
+ </div>
+ <div class="form-row">
+ <label for="node-input-state"><i class="fa fa-wrench"></i> Type</label>
+ <select type="text" id="node-input-state" style="width: 200px;">
+ <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="fa fa-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>The Arduino must be loaded with the Standard Firmata sketch available in the Arduino examples.</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: 'Arduino',
+ color:"#3fadb5",
+ defaults: {
+ name: {value:""},
+ pin: {value:"",required:true},
+ state: {value:"",required:true},
+ arduino: {type:"arduino-board"}
+ },
+ 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="fa fa-random"></i> Port</label>
+ <input type="text" id="node-config-input-device" style="width:60%;" placeholder="e.g. /dev/ttyUSB0 COM1"/>
+ <a id="node-config-lookup-serial" class="btn"><i id="node-config-lookup-serial-icon" class="fa fa-search"></i></a>
+ </div>
+ <div class="form-tips"><b>Tip:</b> Use search to try to auto-detect serial port.</div>
+</script>
+
+<script type="text/javascript">
+ RED.nodes.registerType('arduino-board',{
+ category: 'config',
+ defaults: {
+ device: {value:"",required:true}
+ },
+ label: function() {
+ return this.device||"arduino";
+ },
+ oneditprepare: function() {
+ try {
+ $("#node-config-input-device").autocomplete( "destroy" );
+ } catch(err) { }
+ $("#node-config-lookup-serial").click(function() {
+ $("#node-config-lookup-serial-icon").removeClass('fa-search');
+ $("#node-config-lookup-serial-icon").addClass('spinner');
+ $("#node-config-lookup-serial").addClass('disabled');
+
+ $.getJSON('arduinoports',function(data) {
+ $("#node-config-lookup-serial-icon").addClass('fa-search');
+ $("#node-config-lookup-serial-icon").removeClass('spinner');
+ $("#node-config-lookup-serial").removeClass('disabled');
+ var ports = [];
+ $.each(data, function(i, port){
+ ports.push(port);
+ });
+ $("#node-config-input-device").autocomplete({
+ source:ports,
+ minLength:0,
+ close: function( event, ui ) {
+ $("#node-config-input-device").autocomplete( "destroy" );
+ }
+ }).autocomplete("search","");
+ });
+ });
+ }
+ });
+</script>
diff --git a/dgbuilder/core_nodes/hardware/35-arduino.js b/dgbuilder/core_nodes/hardware/35-arduino.js
new file mode 100644
index 00000000..795e9907
--- /dev/null
+++ b/dgbuilder/core_nodes/hardware/35-arduino.js
@@ -0,0 +1,160 @@
+/**
+ * Copyright 2013,2014 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.
+ **/
+
+module.exports = function(RED) {
+ "use strict";
+ var util = require("util");
+ var ArduinoFirmata = require('arduino-firmata');
+ var fs = require('fs');
+ var plat = require('os').platform();
+ var portlist = ArduinoFirmata.list(function (err, ports) {
+ portlist = ports;
+ });
+
+ // The Board Definition - this opens (and closes) the connection
+ function ArduinoNode(n) {
+ RED.nodes.createNode(this,n);
+ this.device = n.device || null;
+ this.repeat = n.repeat||25;
+ //node.log("opening connection "+this.device);
+ var node = this;
+ node.board = new ArduinoFirmata();
+ if (portlist.indexOf(node.device) === -1) {
+ node.warn("Device "+node.device+" not found");
+ }
+ else {
+ node.board.connect(node.device);
+ }
+
+ node.board.on('boardReady', function(){
+ node.log("version "+node.board.boardVersion);
+ });
+
+ node.on('close', function() {
+ if (node.board) {
+ try {
+ node.board.close(function() {
+ node.log("port closed");
+ });
+ } catch(e) { }
+ }
+ });
+ }
+ 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.status({fill:"red",shape:"ring",text:"connecting"});
+
+ node.board.on('connect', function() {
+ node.status({fill:"green",shape:"dot",text:"connected"});
+ //console.log("i",node.state,node.pin);
+ if (node.state == "ANALOG") {
+ node.board.on('analogChange', function(e) {
+ if (e.pin == node.pin) {
+ var msg = {payload:e.value, topic:"A"+e.pin};
+ node.send(msg);
+ }
+ });
+
+ }
+ else {
+ node.board.pinMode(node.pin, ArduinoFirmata.INPUT);
+ node.board.on('digitalChange', function(e) {
+ if (e.pin == node.pin) {
+ var msg = {payload:e.value, topic:e.pin};
+ node.send(msg);
+ }
+ });
+ }
+ });
+ }
+ else {
+ util.log("[Firmata-arduino] 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;
+ node.status({fill:"red",shape:"ring",text:"connecting"});
+
+ node.board.on('connect', function() {
+ node.status({fill:"green",shape:"dot",text:"connected"});
+ //console.log("o",node.state,node.pin);
+ node.board.pinMode(node.pin, node.state);
+ node.on("input", function(msg) {
+ if (node.state == "OUTPUT") {
+ if ((msg.payload == true)||(msg.payload == 1)||(msg.payload.toString().toLowerCase() == "on")) {
+ node.board.digitalWrite(node.pin, true);
+ }
+ if ((msg.payload == false)||(msg.payload == 0)||(msg.payload.toString().toLowerCase() == "off")) {
+ node.board.digitalWrite(node.pin, false);
+ }
+ }
+ 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 {
+ util.log("[Firmata-arduino] port not configured");
+ }
+ }
+ RED.nodes.registerType("arduino out",DuinoNodeOut);
+
+ RED.httpAdmin.get("/arduinoports",function(req,res) {
+ ArduinoFirmata.list(function (err, ports) {
+ //console.log(JSON.stringify(ports));
+ res.writeHead(200, {'Content-Type': 'text/plain'});
+ res.write(JSON.stringify(ports));
+ res.end();
+ });
+ });
+}
diff --git a/dgbuilder/core_nodes/hardware/36-rpi-gpio.html b/dgbuilder/core_nodes/hardware/36-rpi-gpio.html
new file mode 100644
index 00000000..9e705c2c
--- /dev/null
+++ b/dgbuilder/core_nodes/hardware/36-rpi-gpio.html
@@ -0,0 +1,182 @@
+<!--
+ Copyright 2013,2014 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="fa fa-circle"></i> GPIO Pin</label>
+ <select type="text" id="node-input-pin" style="width: 200px;">
+ <option value="-" disabled>select pin </option>
+ <option value="3">3 - SDA1 </option>
+ <option value="5">5 - SCL1 </option>
+ <option value="7">7 - GPIO7</option>
+ <option value="8">8 - TxD </option>
+ <option value="10">10 - RxD </option>
+ <option value="11">11 - GPIO0</option>
+ <option value="12">12 - GPIO1</option>
+ <option value="13">13 - GPIO2</option>
+ <option value="15">15 - GPIO3</option>
+ <option value="16">16 - GPIO4</option>
+ <option value="18">18 - GPIO5</option>
+ <option value="19">19 - MOSI </option>
+ <option value="21">21 - MISO </option>
+ <option value="22">22 - GPIO6</option>
+ <option value="23">23 - SCLK </option>
+ <option value="24">24 - CE0 </option>
+ <option value="26">26 - CE1 </option>
+ </select>
+ &nbsp;<span id="pitype"></span>
+ </div>
+ <div class="form-row">
+ <label for="node-input-intype"><i class="fa fa-long-arrow-up"></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="fa fa-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":"";
+ },
+ oneditprepare: function() {
+ $.getJSON('rpi-gpio/'+this.id,function(data) {
+ $('#pitype').text(data.type);
+ if (data.type === "Model B+") {
+ $('#node-input-pin').append($("<option></option>").attr("value",27).text("27 - SDA0"));
+ $('#node-input-pin').append($("<option></option>").attr("value",28).text("28 - SCL0"));
+ $('#node-input-pin').append($("<option></option>").attr("value",29).text("29 - GPIO21"));
+ $('#node-input-pin').append($("<option></option>").attr("value",31).text("31 - GPIO22"));
+ $('#node-input-pin').append($("<option></option>").attr("value",32).text("32 - GPIO26"));
+ $('#node-input-pin').append($("<option></option>").attr("value",33).text("33 - GPIO23"));
+ $('#node-input-pin').append($("<option></option>").attr("value",35).text("35 - GPIO24"));
+ $('#node-input-pin').append($("<option></option>").attr("value",36).text("36 - GPIO27"));
+ $('#node-input-pin').append($("<option></option>").attr("value",37).text("37 - GPIO25"));
+ $('#node-input-pin').append($("<option></option>").attr("value",38).text("38 - GPIO28"));
+ $('#node-input-pin').append($("<option></option>").attr("value",40).text("40 - GPIO29"));
+ }
+ });
+ }
+ });
+</script>
+
+
+<script type="text/x-red" data-template-name="rpi-gpio out">
+ <div class="form-row">
+ <label for="node-input-pin"><i class="fa fa-circle"></i> GPIO Pin</label>
+ <select type="text" id="node-input-pin" style="width: 200px;">
+ <option value="-">select pin </option>
+ <option value="3">3 - SDA1 </option>
+ <option value="5">5 - SCL1 </option>
+ <option value="7">7 - GPIO7</option>
+ <option value="8">8 - TxD </option>
+ <option value="10">10 - RxD </option>
+ <option value="11">11 - GPIO0</option>
+ <option value="12">12 - GPIO1</option>
+ <option value="13">13 - GPIO2</option>
+ <option value="15">15 - GPIO3</option>
+ <option value="16">16 - GPIO4</option>
+ <option value="18">18 - GPIO5</option>
+ <option value="19">19 - MOSI </option>
+ <option value="21">21 - MISO </option>
+ <option value="22">22 - GPIO6</option>
+ <option value="23">23 - SCLK </option>
+ <option value="24">24 - CE0 </option>
+ <option value="26">26 - CE1 </option>
+ </select>
+ &nbsp;<span id="pitype"></span>
+ </div>
+ <div class="form-row">
+ <label for="node-input-name"><i class="fa fa-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":"";
+ },
+ oneditprepare: function() {
+ $.getJSON('rpi-gpio/'+this.id,function(data) {
+ $('#pitype').text(data.type);
+ if (data.type === "Model B+") {
+ $('#node-input-pin').append($("<option></option>").attr("value",27).text("27 - SDA0"));
+ $('#node-input-pin').append($("<option></option>").attr("value",28).text("28 - SCL0"));
+ $('#node-input-pin').append($("<option></option>").attr("value",29).text("29 - GPIO21"));
+ $('#node-input-pin').append($("<option></option>").attr("value",31).text("31 - GPIO22"));
+ $('#node-input-pin').append($("<option></option>").attr("value",32).text("32 - GPIO26"));
+ $('#node-input-pin').append($("<option></option>").attr("value",33).text("33 - GPIO23"));
+ $('#node-input-pin').append($("<option></option>").attr("value",35).text("35 - GPIO24"));
+ $('#node-input-pin').append($("<option></option>").attr("value",36).text("36 - GPIO27"));
+ $('#node-input-pin').append($("<option></option>").attr("value",37).text("37 - GPIO25"));
+ $('#node-input-pin').append($("<option></option>").attr("value",38).text("38 - GPIO28"));
+ $('#node-input-pin').append($("<option></option>").attr("value",40).text("40 - GPIO29"));
+ }
+ });
+ }
+ });
+</script>
diff --git a/dgbuilder/core_nodes/hardware/36-rpi-gpio.js b/dgbuilder/core_nodes/hardware/36-rpi-gpio.js
new file mode 100644
index 00000000..93cbc4e0
--- /dev/null
+++ b/dgbuilder/core_nodes/hardware/36-rpi-gpio.js
@@ -0,0 +1,185 @@
+/**
+ * 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.
+ **/
+
+module.exports = function(RED) {
+ "use strict";
+ var util = require("util");
+ var exec = require('child_process').exec;
+ var fs = require('fs');
+
+ var gpioCommand = '/usr/local/bin/gpio';
+
+ if (!fs.existsSync("/dev/ttyAMA0")) { // unlikely if not on a Pi
+ throw "Info : Ignoring Raspberry Pi specific node.";
+ }
+
+ if (!fs.existsSync(gpioCommand)) { // gpio command not installed
+ throw "Info : Can't find Raspberry Pi wiringPi gpio command.";
+ }
+
+ // Map physical P1 pins to Gordon's Wiring-Pi Pins (as they should be V1/V2 tolerant)
+ var pintable = {
+ // Physical : WiringPi
+ "11":"0",
+ "12":"1",
+ "13":"2",
+ "15":"3",
+ "16":"4",
+ "18":"5",
+ "22":"6",
+ "7":"7",
+ "3":"8",
+ "5":"9",
+ "24":"10",
+ "26":"11",
+ "19":"12",
+ "21":"13",
+ "23":"14",
+ "8":"15",
+ "10":"16",
+ "27":"30",
+ "28":"31",
+ "29":"21",
+ "31":"22",
+ "32":"26",
+ "33":"23",
+ "35":"24",
+ "36":"27",
+ "37":"25",
+ "38":"28",
+ "40":"29"
+ }
+ var tablepin = {
+ // WiringPi : Physical
+ "0":"11",
+ "1":"12",
+ "2":"13",
+ "3":"15",
+ "4":"16",
+ "5":"18",
+ "6":"22",
+ "7":"7",
+ "8":"3",
+ "9":"5",
+ "10":"24",
+ "11":"26",
+ "12":"19",
+ "13":"21",
+ "14":"23",
+ "15":"8",
+ "16":"10",
+ "30":"27",
+ "31":"28",
+ "21":"29",
+ "22":"31",
+ "26":"32",
+ "23":"33",
+ "24":"35",
+ "27":"36",
+ "25":"37",
+ "28":"38",
+ "29":"40"
+ }
+
+ function GPIOInNode(n) {
+ RED.nodes.createNode(this,n);
+ this.buttonState = -1;
+ this.pin = pintable[n.pin];
+ this.intype = n.intype;
+ var node = this;
+
+ if (node.pin !== undefined) {
+ exec(gpioCommand+" mode "+node.pin+" "+node.intype, function(err,stdout,stderr) {
+ if (err) { node.error(err); }
+ else {
+ node._interval = setInterval( function() {
+ exec(gpioCommand+" 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 {
+ node.error("Invalid GPIO pin: "+node.pin);
+ }
+
+ node.on("close", function() {
+ clearInterval(node._interval);
+ });
+ }
+
+ function GPIOOutNode(n) {
+ RED.nodes.createNode(this,n);
+ this.pin = pintable[n.pin];
+ var node = this;
+
+ if (node.pin !== undefined) {
+ process.nextTick(function() {
+ exec(gpioCommand+" 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(gpioCommand+" write "+node.pin+" "+out, function(err,stdout,stderr) {
+ if (err) { node.error(err); }
+ });
+ }
+ else { node.warn("Invalid input - not 0 or 1"); }
+ });
+ }
+ });
+ });
+ }
+ else {
+ node.error("Invalid GPIO pin: "+node.pin);
+ }
+
+ node.on("close", function() {
+ exec(gpioCommand+" mode "+node.pin+" in");
+ });
+ }
+
+ var pitype = { type:"" };
+ exec(gpioCommand+" -v | grep Type", function(err,stdout,stderr) {
+ if (err) {
+ util.log('[36-rpi-gpio.js] Error: "'+gpioCommand+' -v" command failed for some reason.');
+ }
+ else {
+ pitype = { type:(stdout.split(","))[0].split(": ")[1], rev:(stdout.split(","))[1].split(": ")[1] };
+ }
+ });
+
+ RED.nodes.registerType("rpi-gpio in",GPIOInNode);
+ RED.nodes.registerType("rpi-gpio out",GPIOOutNode);
+
+ RED.httpAdmin.get('/rpi-gpio/:id',function(req,res) {
+ res.send( JSON.stringify(pitype) );
+ });
+}