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

Update Piliter node to use python library.

This commit is contained in:
dceejay 2015-01-06 14:54:45 +00:00
parent c4ab9cd6bb
commit ac0aa40e24
6 changed files with 255 additions and 76 deletions

View File

@ -17,7 +17,7 @@
<script type="text/x-red" data-template-name="rpi-liter">
<div class="form-row">
<label for="node-input-pin"><i class="fa fa-cog"></i> Mode</label>
<select type="text" id="node-input-pin" style="width: 350px;">
<select type="text" id="node-input-pin" style="width: 300px;">
<option value='' disabled selected style='display:none;'>select mode</option>
<option value="pi-liter">0-255 : one bit per led</option>
<option value="meter">0-8 : turns on led indicated - needle</option>
@ -26,6 +26,11 @@
<option value="all">0/1 : turn off/on ALL leds</option>
</select>
</div>
<div class="form-row">
<label>&nbsp;</label>
<input type="checkbox" id="node-input-dir" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-dir" style="width: 70%;">Reverse bar direction ?</label>
</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">
@ -49,10 +54,11 @@
<script type="text/javascript">
RED.nodes.registerType('rpi-liter',{
category: 'Raspberry Pi',
color:"GoldenRod",
color:"#c6dbef",
defaults: {
name: { value:"" },
pin: { value:"",required:true }
name: {value:""},
pin: {value:"",required:true},
dir: {value:""}
},
inputs:1,
outputs:0,

View File

@ -16,104 +16,80 @@
module.exports = function(RED) {
"use strict";
var util = require("util");
var exec = require('child_process').exec;
var spawn = require('child_process').spawn;
var fs = require('fs');
var gpioCommand = __dirname+'/nrgpio';
if (!fs.existsSync("/dev/ttyAMA0")) { // unlikely if not on a Pi
//util.log("Info : Ignoring Raspberry Pi specific node.");
throw "Info : Ignoring Raspberry Pi specific node.";
}
if (!fs.existsSync("/usr/local/bin/gpio")) { // gpio command not installed
throw "Info : Can't find Raspberry Pi wiringPi gpio command.";
if (!fs.existsSync("/usr/share/doc/python-rpi.gpio")) {
util.log("[rpi-gpio] Info : Can't find Pi RPi.GPIO python library.");
throw "Warning : Can't find Pi RPi.GPIO python library.";
}
// Map physical P1 pins to Gordon's Wiring-Pi Pins (as they should be V1/V2 tolerant)
var pintable = {
// Physical : WiringPi
"LED1":"7",
"LED2":"0",
"LED3":"2",
"LED4":"1",
"LED5":"3",
"LED6":"4",
"LED7":"5",
"LED8":"6"
}
var tablepin = {
// WiringPi : Physical
"0":"LED2",
"1":"LED4",
"2":"LED3",
"3":"LED5",
"4":"LED6",
"5":"LED7",
"6":"LED8",
"7":"LED1"
}
var barpins = {
"1":"128",
"2":"129",
"3":"133",
"4":"135",
"5":"143",
"6":"159",
"7":"191",
"8":"255",
}
var meterpins = {
"1":"128",
"2":"1",
"3":"4",
"4":"2",
"5":"8",
"6":"16",
"7":"32",
"8":"64",
if ( !(1 & parseInt ((fs.statSync(gpioCommand).mode & parseInt ("777", 8)).toString (8)[0]) )) {
util.log("[rpi-gpio] Error : "+gpioCommand+" needs to be executable.");
throw "Error : nrgpio must to be executable.";
}
function PiLiter(n) {
RED.nodes.createNode(this,n);
this.pin = pintable[n.pin];
this.pinv = n.pin;
this.dir = (n.dir ? 1 : 0) || 0;
var node = this;
//Set all pins to outputs
for (var p = 0; p < 8; p++) {
exec("gpio mode "+p+" out");
}
if (this.pinv === "bar") {
node.child = spawn(gpioCommand, ["byte",node.dir]);
node.on("input", function(msg) {
var out = Number(msg.payload);
if ((out >= 1)&&(out <= 8)) { exec("gpio wb "+barpins[out]); }
else { exec("gpio wb 0"); }
if ((out >= 1) && (out <= 8)) { out = Math.pow(2, out) - 1; }
else { out = 0; }
if (node.child !== null) { node.child.stdin.write(out+"\n"); }
else { node.warn("Command not running"); }
});
}
else if (this.pinv === "meter") {
node.child = spawn(gpioCommand, ["byte",node.dir]);
node.on("input", function(msg) {
var out = Number(msg.payload);
if ((out >= 1)&&(out <= 8)) { exec("gpio wb "+meterpins[out]); }
else { exec("gpio wb 0"); }
if ((out >= 1) && (out <= 8)) { out = Math.pow(2, (out-1)); }
else { out = 0; }
if (node.child !== null) { node.child.stdin.write(out+"\n"); }
else { node.warn("Command not running"); }
});
}
else if (this.pinv === "all") {
node.child = spawn(gpioCommand, ["byte",node.dir]);
node.on("input", function(msg) {
var out = msg.payload;
if ((out === 1)|(out === true)|(out === "1")|(out === "on")) {
exec("gpio wb 255");
out = 255;
}
else { exec("gpio wb 0"); }
else { out = 0; }
if (node.child !== null) { node.child.stdin.write(out+"\n"); }
else { node.warn("Command not running"); }
});
}
else if (this.pinv === "pin") {
node.child = spawn(gpioCommand, ["byte",node.dir]);
var byte = 0;
node.on("input", function(msg) {
if (typeof msg.payload === "object") {
var out = Number(msg.payload.led);
var l = msg.payload.state;
if ((out >= 1)&&(out <= 8)) {
exec("gpio write "+pintable["LED"+out]+" "+l);
var l = Number(msg.payload.state);
if ((out >= 1) && (out <= 8)) {
out = (Math.pow(2, (out-1)));
if (l === 0) { out = ~ out; }
byte = byte & out & 255;
console.log("NOW",byte);
if (node.child !== null) { node.child.stdin.write(byte+"\n"); }
else { node.warn("Command not running"); }
}
else { node.warn("Not a valid object - see Info panel."); }
}
@ -121,21 +97,22 @@ module.exports = function(RED) {
});
}
else {
node.child = spawn(gpioCommand, ["byte",node.dir]);
node.on("input", function(msg) {
var out = Number(msg.payload);
if ((out >= 0)&&(out <= 255)) {
var val = 0;
for (var i = 0; i < 8; i ++) {
val += ((out & 0x01) << pintable["LED"+(i+1)]);
out = out >> 1;
}
exec("gpio wb "+val);
if ((out >= 0) && (out <= 255)) {
if (node.child !== null) { node.child.stdin.write(out+"\n"); }
else { node.warn("Command not running"); }
}
else { node.warn("Invalid input - not between 0 and 255"); }
});
}
node.on("close", function() {
exec("gpio wb 0");
if (node.child != null) {
node.child.kill('SIGKILL');
}
if (RED.settings.verbose) { node.log("end"); }
});
}
RED.nodes.registerType("rpi-liter",PiLiter);

View File

@ -14,8 +14,13 @@ Run the following command in the root directory of your Node-RED install
Pre-reqs
--------
Requires the WiringPi gpio command to be installed in order to work. See the <a href="http://wiringpi.com" target="new">WiringPi site</a> for details on how to do this.
Requires the python RPi.GPIO library v0.58 (or better) to be installed in order to work.
See the <a href="http://sourceforge.net/p/raspberry-gpio-python/wiki/install/" target="new">RPi.GPIO site</a> for details on how to do this.
This is built into most recent Raspbian versions so no install should be necessary - but if necessary
$ sudo apt-get update
$ sudo apt-get install python-rpi.gpio python3-rpi.gpio
Usage
-----
@ -30,4 +35,8 @@ Operates in one of 5 different modes :
- All LEDs Mode - expects a 1 or 0 - turns on and off ALL the LEDs
- Object Mode - expects a object specifying the LED and state eg. <code>{led:3,state:0}</code> to set LED3 off.
Requires the WiringPi gpio command in order to work.
Requires the RPi.GPIO library installed in order to work.
In order to access the GPIO the nrgpio.py command (installed as part of this package) must be run as root (sudo).
The default Pi user can do this so it "should just work" - however if you are running Node-RED as not the Pi user then
you may need to give your user sudo rights - or specifically sudo rights to python.

16
hardware/PiLiter/nrgpio Executable file
View File

@ -0,0 +1,16 @@
#
# Copyright 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.
#
BASEDIR=$(dirname $0)
sudo python -u $BASEDIR/nrgpio.py $@

171
hardware/PiLiter/nrgpio.py Executable file
View File

@ -0,0 +1,171 @@
#!/usr/bin/python
#
# Copyright 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.
#
# Import library functions we need
import RPi.GPIO as GPIO
import sys
bounce = 20 # bounce time in mS to apply
if len(sys.argv) > 1:
cmd = sys.argv[1].lower()
pin = int(sys.argv[2])
GPIO.setmode(GPIO.BOARD)
GPIO.setwarnings(False)
if cmd == "pwm":
#print "Initialised pin "+str(pin)+" to PWM"
GPIO.setup(pin,GPIO.OUT)
p = GPIO.PWM(pin, 100)
p.start(0)
while True:
try:
data = raw_input()
if data == "close":
GPIO.cleanup(pin)
sys.exit(0)
p.ChangeDutyCycle(float(data))
except EOFError: # hopefully always caused by us sigint'ing the program
GPIO.cleanup(pin)
sys.exit(0)
except Exception as ex:
print "bad data: "+data
elif cmd == "buzz":
#print "Initialised pin "+str(pin)+" to Buzz"
GPIO.setup(pin,GPIO.OUT)
p = GPIO.PWM(pin, 100)
p.stop()
while True:
try:
data = raw_input()
if data == "close":
GPIO.cleanup(pin)
sys.exit(0)
elif float(data) == 0:
p.stop()
else:
p.start(50)
p.ChangeFrequency(float(data))
except EOFError: # hopefully always caused by us sigint'ing the program
GPIO.cleanup(pin)
sys.exit(0)
except Exception as ex:
print "bad data: "+data
elif cmd == "out":
#print "Initialised pin "+str(pin)+" to OUT"
GPIO.setup(pin,GPIO.OUT)
if len(sys.argv) == 4:
GPIO.output(pin,int(sys.argv[3]))
while True:
try:
data = raw_input()
if data == "close":
GPIO.cleanup(pin)
sys.exit(0)
data = int(data)
except EOFError: # hopefully always caused by us sigint'ing the program
GPIO.cleanup(pin)
sys.exit(0)
except:
data = 0
if data != 0:
data = 1
GPIO.output(pin,data)
elif cmd == "in":
#print "Initialised pin "+str(pin)+" to IN"
def handle_callback(chan):
print GPIO.input(chan)
if len(sys.argv) == 4:
if sys.argv[3].lower() == "up":
GPIO.setup(pin,GPIO.IN,GPIO.PUD_UP)
elif sys.argv[3].lower() == "down":
GPIO.setup(pin,GPIO.IN,GPIO.PUD_DOWN)
else:
GPIO.setup(pin,GPIO.IN)
else:
GPIO.setup(pin,GPIO.IN)
print GPIO.input(pin)
GPIO.add_event_detect(pin, GPIO.BOTH, callback=handle_callback, bouncetime=bounce)
while True:
try:
data = raw_input()
if data == "close":
GPIO.cleanup(pin)
sys.exit(0)
except EOFError: # hopefully always caused by us sigint'ing the program
GPIO.cleanup(pin)
sys.exit(0)
elif cmd == "byte":
#print "Initialised BYTE mode - "+str(pin)+
list = [7,11,13,12,15,16,18,22]
GPIO.setup(list,GPIO.OUT)
while True:
try:
data = raw_input()
if data == "close":
GPIO.cleanup()
sys.exit(0)
data = int(data)
except EOFError: # hopefully always caused by us sigint'ing the program
GPIO.cleanup()
sys.exit(0)
except:
data = 0
for bit in range(8):
if pin == 1:
mask = 1 << (7 - bit)
else:
mask = 1 << bit
GPIO.output(list[bit], data & mask)
elif cmd == "rev":
print GPIO.RPI_REVISION
elif cmd == "ver":
print GPIO.VERSION
elif cmd == "mouse": # catch mice button events
file = open( "/dev/input/mice", "rb" )
oldbutt = 0
def getMouseEvent():
global oldbutt
global pin
buf = file.read(3)
pin = pin & 0x07
button = ord( buf[0] ) & pin # mask out just the required button(s)
if button != oldbutt: # only send if changed
oldbutt = button
print button
while True:
try:
getMouseEvent()
except:
file.close()
sys.exit(0)
else:
print "Bad parameters - {in|out|pwm} {pin} {value|up|down}"

View File

@ -1,6 +1,6 @@
{
"name" : "node-red-node-piliter",
"version" : "0.0.3",
"version" : "0.0.4",
"description" : "A Node-RED node to drive a Raspberry Pi Pi-LITEr 8 LED board.",
"dependencies" : {
},