1
0
mirror of https://github.com/node-red/node-red-nodes.git synced 2023-10-10 13:36:58 +02:00

Added PiFace Node and PiBorg LED Nodes for Raspberry Pi people

This commit is contained in:
Dave C-J 2013-10-04 08:22:35 +01:00
parent 790e9f6014
commit bf178b81ee
4 changed files with 367 additions and 0 deletions

130
hardware/37-rpi-piface.html Normal file
View File

@ -0,0 +1,130 @@
<!--
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-piface 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="Button S1">Button S1</option>
<option value="Button S2">Button S2</option>
<option value="Button S3">Button S3</option>
<option value="Button S4">Button S4</option>
<option value="Input 5">Input 5</option>
<option value="Input 6">Input 6</option>
<option value="Input 7">Input 7</option>
<option value="Input 8">Input 8</option>
<option value="Output0">Output 0</option>
<option value="Output1">Output 1</option>
<option value="Output2">Output 2</option>
<option value="Output3">Output 3</option>
<option value="Output4">Output 4</option>
<option value="Output5">Output 5</option>
<option value="Output6">Output 6</option>
<option value="Output7">Output 7</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="up">pullup</option>
<option value="tri">none</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-piface in">
<p>Raspberry Pi PiFace 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 if required.</p>
<p>The <b>msg.topic</b> is set to <i>pi/{the pin number}</i></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-piface in',{
category: 'advanced-input',
color:"#c6dbef",
defaults: {
name: { value:"" },
intype: { value: "up" },
pin: { value:"",required:true},
},
inputs:0,
outputs:1,
icon: "rpi.png",
label: function() {
return this.name||"PiFace: "+this.pin;
},
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});
</script>
<script type="text/x-red" data-template-name="rpi-piface 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="LED 0 / Relay 0">LED 0 / Relay 0</option>
<option value="LED 1 / Relay 1">LED 1 / Relay 1</option>
<option value="LED 2">LED 2</option>
<option value="LED 3">LED 3</option>
<option value="LED 4">LED 4</option>
<option value="LED 5">LED 5</option>
<option value="LED 6">LED 6</option>
<option value="LED 7">LED 7</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-piface out">
<p>Raspberry Pi PiFace output node. The PiFace board must be fitted. Requires the gpio command to work.</p>
<p>Expects a <b>msg.payload</b> with either a 0 or 1 (or true or false).</p>
<p>Will set the selected relay, LED, or pin on or off depending on the value passed in.</p>
</script>
<script type="text/javascript">
RED.nodes.registerType('rpi-piface out',{
category: 'advanced-output',
color:"#c6dbef",
defaults: {
name: { value:"" },
pin: { value:"",required:true},
},
inputs:1,
outputs:0,
icon: "rpi.png",
align: "right",
label: function() {
return this.name||"PiFace: "+this.pin;
},
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});
</script>

134
hardware/37-rpi-piface.js Normal file
View File

@ -0,0 +1,134 @@
/**
* 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("../../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('[37-rpi-piface.js] Error: Cannot find Wiring-Pi "gpio" command');
}
// else not on a Pi so don't worry anyone with needless messages.
});
return;
}
// Map names of pins to Gordon's gpio PiFace pin numbers
var pintable = {
// Physical : WiringPi
"Button S1":"200",
"Button S2":"201",
"Button S3":"202",
"Button S4":"203",
"Input 5":"204",
"Input 6":"205",
"Input 7":"206",
"Input 8":"207",
"Output0":"208",
"Output1":"209",
"Output2":"210",
"Output3":"211",
"Output4":"212",
"Output5":"213",
"Output6":"214",
"Output7":"215",
"LED 0 / Relay 0":"200",
"LED 1 / Relay 1":"201",
"LED 2":"202",
"LED 3":"203",
"LED 4":"204",
"LED 5":"205",
"LED 6":"206",
"LED 7":"207"
}
function PiFACEInNode(n) {
RED.nodes.createNode(this,n);
this.buttonState = -1;
this.pin = pintable[n.pin];
this.intype = n.intype;
var node = this;
if (node.pin) {
exec("gpio -p mode "+node.pin+" "+node.intype, function(err,stdout,stderr) {
if (err) node.error(err);
else {
node._interval = setInterval( function() {
exec("gpio -p 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/"+node.pin, payload:node.buttonState};
node.send(msg);
}
}
}
});
}, 250);
}
});
}
else {
node.error("Invalid PiFACE pin: "+node.pin);
}
}
function PiFACEOutNode(n) {
RED.nodes.createNode(this,n);
this.pin = pintable[n.pin];
var node = this;
if (node.pin) {
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 -p 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 PiFACE pin: "+node.pin);
}
}
exec("gpio load spi",function(err,stdout,stderr) {
if (err) {
util.log('[37-rpi-piface.js] Error: "gpio load spi" command failed for some reason.');
}
exec("gpio -p reset",function(err,stdout,stderr) {
if (err) {
util.log('[37-rpi-piface.js] Error: "gpio -p reset" command failed for some reason.');
}
RED.nodes.registerType("rpi-piface in",PiFACEInNode);
RED.nodes.registerType("rpi-piface out",PiFACEOutNode);
PiFACEInNode.prototype.close = function() {
clearInterval(this._interval);
}
PiFACEOutNode.prototype.close = function() {
}
});
});

50
hardware/78-ledborg.html Normal file
View File

@ -0,0 +1,50 @@
<!--
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="ledborg">
<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">Expects a msg.payload with PiBorg three digit rgb colour string. 000 -> 222</div>
</script>
<script type="text/x-red" data-help-name="ledborg">
<p>PiBorg LedBorg LED output node. Expects a <b>msg.payload</b> with a three digit rgb triple, from <b>000</b> to <b>222</b>.</p>
<p>See <i><a href="http://www.piborg.com/ledborg/install" target="_new">the PiBorg site</a></i> for more information.</p>
<p>You can also now use a <b>msg.payload</b> in the standard hex format "#rrggbb". The clip levels are :</p>
<p><pre>0x00 - 0x57 = off<br/>0x58 - 0xA7 = 50%<br/>0xA8 - 0xFF = fully on</pre></p>
</script>
<script type="text/javascript">
RED.nodes.registerType('ledborg',{
category: 'output',
color:"GoldenRod",
defaults: {
name: {value:""}
},
inputs:1,
outputs:0,
icon: "light.png",
align: "right",
label: function() {
return this.name||"ledborg";
},
labelStyle: function() {
return this.name?"node_label_italic":"";
}
});
</script>

53
hardware/78-ledborg.js Normal file
View File

@ -0,0 +1,53 @@
/**
* 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("../../red/red");
var util = require('util');
var fs = require('fs');
// check if /dev/ledborg exists - if not then don't even show the node.
if (!fs.existsSync("/dev/ledborg")) {
util.log("[78-ledborg.js] Error: PiBorg hardware : LedBorg not found");
return;
}
function LedBorgNode(n) {
RED.nodes.createNode(this,n);
var p1 = /[0-2][0-2][0-2]/
var p2 = /^\#[A-Fa-f0-9]{6}$/
var node = this;
this.on("input", function(msg) {
if (p1.test(msg.payload)) {
fs.writeFile('/dev/ledborg', msg.payload, function (err) {
if (err) node.warn(msg.payload+" : No LedBorg found");
});
}
if (p2.test(msg.payload)) {
var r = Math.floor(parseInt(msg.payload.slice(1,3),16)/88).toString();
var g = Math.floor(parseInt(msg.payload.slice(3,5),16)/88).toString();
var b = Math.floor(parseInt(msg.payload.slice(5),16)/88).toString();
fs.writeFile('/dev/ledborg', r+g+b, function (err) {
if (err) node.warn(r+g+b+" : No LedBorg found");
});
}
else {
node.warn("Invalid LedBorg colour code");
}
});
}
RED.nodes.registerType("ledborg",LedBorgNode);