mirror of
https://github.com/node-red/node-red-nodes.git
synced 2023-10-10 13:36:58 +02:00
Move Pi GPIO nodes to this repo
This commit is contained in:
parent
dcbe41bf83
commit
a172c8178d
544
hardware/PiGpio/36-rpi-gpio.html
Normal file
544
hardware/PiGpio/36-rpi-gpio.html
Normal file
@ -0,0 +1,544 @@
|
|||||||
|
<style>
|
||||||
|
.rpi-gpio-pinTable {
|
||||||
|
width: 340px;
|
||||||
|
display: inline-table;
|
||||||
|
font-size: 13px;
|
||||||
|
height: 380px;
|
||||||
|
min-height: 380px;
|
||||||
|
max-height: 380px;
|
||||||
|
}
|
||||||
|
.rpi-gpio-pinTable input[type="radio"] {
|
||||||
|
width: auto;
|
||||||
|
margin: 2px 2px;
|
||||||
|
}
|
||||||
|
.rpi-gpio-pinTable label {
|
||||||
|
width: auto;
|
||||||
|
margin: 0;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.rpi-gpio-pinTable .pinTableBody {
|
||||||
|
width: 340px;
|
||||||
|
display: table-row-group;
|
||||||
|
line-height: 12px;
|
||||||
|
}
|
||||||
|
.rpi-gpio-pinTable .pinTableRow {
|
||||||
|
width: 340px;
|
||||||
|
display: table-row;
|
||||||
|
height: 14px;
|
||||||
|
}
|
||||||
|
.rpi-gpio-pinTable .pinTableCellL {
|
||||||
|
width: 170px;
|
||||||
|
display: table-cell;
|
||||||
|
text-align: right;
|
||||||
|
padding-right: 4px;
|
||||||
|
vertical-align: top;
|
||||||
|
border: 1px solid #444;
|
||||||
|
}
|
||||||
|
.rpi-gpio-pinTable .pinTableCellR {
|
||||||
|
width: 170px;
|
||||||
|
display: table-cell;
|
||||||
|
text-align: left;
|
||||||
|
padding-left: 4px;
|
||||||
|
vertical-align: top;
|
||||||
|
border: 1px solid #000;
|
||||||
|
}
|
||||||
|
.rpi-gpio-pinTable .pinColorPower {
|
||||||
|
background-color:#FECBCE;
|
||||||
|
}
|
||||||
|
.rpi-gpio-pinTable .pinColorGround {
|
||||||
|
background-color:#DDDDDD;
|
||||||
|
}
|
||||||
|
.rpi-gpio-pinTable .pinColorGPIO {
|
||||||
|
background-color:#BFEBBF;
|
||||||
|
}
|
||||||
|
.rpi-gpio-pinTable .pinColorDual {
|
||||||
|
background-color:#D0E6F4;
|
||||||
|
}
|
||||||
|
.rpi-gpio-pinTable .pinColorSD {
|
||||||
|
background-color:#FFFDD0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<script type="text/x-red" data-template-name="rpi-gpio in">
|
||||||
|
|
||||||
|
<div class="form-row" style="min-width: 540px">
|
||||||
|
<label><i class="fa fa-circle"></i> <span data-i18n="rpi-gpio.pinname"></span></label>
|
||||||
|
<input type="text" id="node-input-pin" style="display:none;">
|
||||||
|
<div class="rpi-gpio-pinTable">
|
||||||
|
<div class="pinTableBody" id="pinform">
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorPower"><label>3.3V Power - 1 <input disabled type="radio" name="pins" value=""></label></div>
|
||||||
|
<div class="pinTableCellR pinColorPower"><label><input disabled type="radio" name="pins" value=""> 2 - 5V Power</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-3">SDA1 - GPIO02 - 3 <input id="pinTable-pin-3" type="radio" name="pins" value="3"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorPower"><label><input disabled type="radio" name="pins" value=""> 4 - 5V Power</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-5">SCL1 - GPIO03 - 5 <input id="pinTable-pin-5" type="radio" name="pins" value="5"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGround"><label><input disabled type="radio" name="pins" value=""> 6 - Ground</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-7">GPIO04 - 7 <input id="pinTable-pin-7" type="radio" name="pins" value="7"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-8"><input id="pinTable-pin-8" type="radio" name="pins" value="8"> 8 - GPIO14 - TxD</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGround"><label>Ground - 9 <input disabled type="radio" name="pins" value=""></label></div>
|
||||||
|
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-10"><input id="pinTable-pin-10" type="radio" name="pins" value="10"> 10 - GPIO15 - RxD</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-11">GPIO17 - 11 <input id="pinTable-pin-11" type="radio" name="pins" value="11"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-12"><input id="pinTable-pin-12" type="radio" name="pins" value="12"> 12 - GPIO18</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-13">GPIO27 - 13 <input id="pinTable-pin-13" type="radio" name="pins" value="13"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGround"><label><input disabled type="radio" name="pins" value=""> 14 - Ground</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-15">GPIO22 - 15 <input id="pinTable-pin-15" type="radio" name="pins" value="15"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-16"><input id="pinTable-pin-16" type="radio" name="pins" value="16"> 16 - GPIO23</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorPower"><label>3.3V Power - 17 <input disabled type="radio" name="pins" value=""></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-18"><input id="pinTable-pin-18" type="radio" name="pins" value="18"> 18 - GPIO24</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-19">MOSI - GPIO10 - 19 <input id="pinTable-pin-19" type="radio" name="pins" value="19"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGround"><label><input disabled type="radio" name="pins" value=""> 20 - Ground</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-21">MISO - GPIO09 - 21 <input id="pinTable-pin-21" type="radio" name="pins" value="21"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-22"><input id="pinTable-pin-22" type="radio" name="pins" value="22"> 22 - GPIO25</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-23">SCLK - GPIO11 - 23 <input id="pinTable-pin-23" type="radio" name="pins" value="23"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-24"><input id="pinTable-pin-24" type="radio" name="pins" value="24"> 24 - GPIO8 - CE0</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGround"><label>Ground - 25 <input disabled type="radio" name="pins" value=""></label></div>
|
||||||
|
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-26"><input id="pinTable-pin-26" type="radio" name="pins" value="26"> 26 - GPIO7 - CE1</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorSD"><label>SD - 27 <input disabled type="radio" name="pins" value=""></label></div>
|
||||||
|
<div class="pinTableCellR pinColorSD"><label><input disabled type="radio" name="pins" value=""> 28 - SC</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-29">GPIO05 - 29 <input id="pinTable-pin-29" type="radio" name="pins" value="29"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGround"><label><input disabled type="radio" name="pins" value=""> 30 - Ground</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-31">GPIO06 - 31 <input id="pinTable-pin-31" type="radio" name="pins" value="31"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-32"><input id="pinTable-pin-32" type="radio" name="pins" value="32"> 32 - GPIO12</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-33">GPIO13 - 33 <input id="pinTable-pin-33" type="radio" name="pins" value="33"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGround"><label><input disabled type="radio" name="pins" value=""> 34 - Ground</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-35">GPIO19 - 35 <input id="pinTable-pin-35" type="radio" name="pins" value="35"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-36"><input id="pinTable-pin-36" type="radio" name="pins" value="36"> 36 - GPIO16</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-37">GPIO26 - 37 <input id="pinTable-pin-37" type="radio" name="pins" value="37"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-38"><input id="pinTable-pin-38" type="radio" name="pins" value="38"> 38 - GPIO20</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGround"><label>Ground - 39 <input disabled type="radio" name="pins" value=""></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-40"><input id="pinTable-pin-40" type="radio" name="pins" value="40"> 40 - GPIO21</label></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-intype"><i class="fa fa-level-up"></i> <span data-i18n="rpi-gpio.label.resistor"></span></label>
|
||||||
|
<select type="text" id="node-input-intype" style="width:100px;">
|
||||||
|
<option value="tri" data-i18n="rpi-gpio.resistor.none"></option>
|
||||||
|
<option value="up" data-i18n="rpi-gpio.resistor.pullup"></option>
|
||||||
|
<option value="down" data-i18n="rpi-gpio.resistor.pulldown"></option>
|
||||||
|
</select>
|
||||||
|
<span data-i18n="rpi-gpio.label.debounce"></span>
|
||||||
|
<input type="text" id="node-input-debounce" style="width:47px; text-align:right"/> mS
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label> </label>
|
||||||
|
<input type="checkbox" id="node-input-read" style="display: inline-block; width: auto; vertical-align: top;">
|
||||||
|
<label for="node-input-read" style="width:70%;"><span data-i18n="rpi-gpio.label.readinitial"></span></label>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||||
|
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
|
||||||
|
</div>
|
||||||
|
<div class="form-tips" id="pin-tip"><span data-i18n="[html]rpi-gpio.tip.pin"></span></div>
|
||||||
|
<div class="form-tips"><span data-i18n="[html]rpi-gpio.tip.in"></span></div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var bcm2pin = {
|
||||||
|
"2":"3", "3":"5", "4":"7", "14":"8", "15":"10", "17":"11", "18":"12", "27":"13", "22":"15",
|
||||||
|
"23":"16", "24":"18", "10":"19", "9":"21", "25":"22", "11":"23", "8":"24", "7":"26",
|
||||||
|
"5":"29", "6":"31", "12":"32", "13":"33", "19":"35", "16":"36", "26":"37", "20":"38", "21":"40"
|
||||||
|
};
|
||||||
|
var pinsInUse = {};
|
||||||
|
RED.nodes.registerType('rpi-gpio in',{
|
||||||
|
category: 'Raspberry Pi',
|
||||||
|
color:"#c6dbef",
|
||||||
|
defaults: {
|
||||||
|
name: { value:"" },
|
||||||
|
pin: { value:"tri",required:true,validate:RED.validators.number() },
|
||||||
|
intype: { value:"tri" },
|
||||||
|
debounce: { value:"25" },
|
||||||
|
read: { value:false }
|
||||||
|
},
|
||||||
|
inputs:0,
|
||||||
|
outputs:1,
|
||||||
|
icon: "rpi.png",
|
||||||
|
info: function() {
|
||||||
|
if ( Object.keys(pinsInUse).length !== 0 ) {
|
||||||
|
return "**Pins in use** : "+Object.keys(pinsInUse);
|
||||||
|
}
|
||||||
|
else { return ""; }
|
||||||
|
},
|
||||||
|
label: function() {
|
||||||
|
var suf = "";
|
||||||
|
if (this.intype === "up") { suf = "↑ "}
|
||||||
|
if (this.intype === "down") { suf = "↓ "}
|
||||||
|
return this.name || "PIN: "+suf+this.pin ;
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
},
|
||||||
|
outputLabels: function() { return "GPIO"+this.pin; },
|
||||||
|
oneditprepare: function() {
|
||||||
|
var pinnow = this.pin;
|
||||||
|
var pintip = this._("rpi-gpio.tip.pin");
|
||||||
|
var pinname = this._("rpi-gpio.pinname");
|
||||||
|
var alreadyuse = this._("rpi-gpio.alreadyuse");
|
||||||
|
var alreadyset = this._("rpi-gpio.alreadyset");
|
||||||
|
|
||||||
|
$.getJSON('rpi-pins/'+this.id,function(data) {
|
||||||
|
pinsInUse = data || {};
|
||||||
|
$('#pin-tip').html(pintip + Object.keys(data));
|
||||||
|
});
|
||||||
|
$("#node-input-pin").on("change", function() {
|
||||||
|
if ($("#node-input-pin").val()) {
|
||||||
|
$("#pinform input[value="+$("#node-input-pin").val()+"]").prop('checked', true);
|
||||||
|
}
|
||||||
|
var pinnew = $("#node-input-pin").val();
|
||||||
|
if ((pinnew) && (pinnew !== pinnow)) {
|
||||||
|
if (pinsInUse.hasOwnProperty(pinnew)) {
|
||||||
|
RED.notify(pinname+" "+pinnew+" "+alreadyuse,"warn");
|
||||||
|
}
|
||||||
|
pinnow = pinnew;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$("#node-input-intype").on("change", function() {
|
||||||
|
var newtype = $("#node-input-intype").val();
|
||||||
|
if ((pinsInUse.hasOwnProperty(pinnow)) && (pinsInUse[pinnow] !== newtype)) {
|
||||||
|
RED.notify(pinname+" "+pinnow+" "+alreadyset+" "+pinsInUse[pinnow],"error");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$('#pinform input').on('change', function() {
|
||||||
|
this.pin = $("#pinform input[type='radio']:checked").val();
|
||||||
|
$("#node-input-pin").val(this.pin);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-template-name="rpi-gpio out">
|
||||||
|
<div class="form-row" style="min-width: 540px">
|
||||||
|
<label><i class="fa fa-circle"></i> <span data-i18n="rpi-gpio.pinname"></span></label>
|
||||||
|
<input type="text" id="node-input-pin" style="display:none;">
|
||||||
|
<div class="rpi-gpio-pinTable">
|
||||||
|
<div class="pinTableBody" id="pinform">
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorPower"><label>3.3V Power - 1 <input disabled type="radio" name="pins" value=""></label></div>
|
||||||
|
<div class="pinTableCellR pinColorPower"><label><input disabled type="radio" name="pins" value=""> 2 - 5V Power</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-3">SDA1 - GPIO02 - 3 <input id="pinTable-pin-3" type="radio" name="pins" value="3"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorPower"><label><input disabled type="radio" name="pins" value=""> 4 - 5V Power</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-5">SCL1 - GPIO03 - 5 <input id="pinTable-pin-5" type="radio" name="pins" value="5"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGround"><label><input disabled type="radio" name="pins" value=""> 6 - Ground</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-7">GPIO04 - 7 <input id="pinTable-pin-7" type="radio" name="pins" value="7"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-8"><input id="pinTable-pin-8" type="radio" name="pins" value="8"> 8 - GPIO14 - TxD</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGround"><label>Ground - 9 <input disabled type="radio" name="pins" value=""></label></div>
|
||||||
|
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-10"><input id="pinTable-pin-10" type="radio" name="pins" value="10"> 10 - GPIO15 - RxD</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-11">GPIO17 - 11 <input id="pinTable-pin-11" type="radio" name="pins" value="11"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-12"><input id="pinTable-pin-12" type="radio" name="pins" value="12"> 12 - GPIO18</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-13">GPIO27 - 13 <input id="pinTable-pin-13" type="radio" name="pins" value="13"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGround"><label><input disabled type="radio" name="pins" value=""> 14 - Ground</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-15">GPIO22 - 15 <input id="pinTable-pin-15" type="radio" name="pins" value="15"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-16"><input id="pinTable-pin-16" type="radio" name="pins" value="16"> 16 - GPIO23</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorPower"><label>3.3V Power - 17 <input disabled type="radio" name="pins" value=""></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-18"><input id="pinTable-pin-18" type="radio" name="pins" value="18"> 18 - GPIO24</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-19">MOSI - GPIO10 - 19 <input id="pinTable-pin-19" type="radio" name="pins" value="19"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGround"><label><input disabled type="radio" name="pins" value=""> 20 - Ground</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-21">MISO - GPIO09 - 21 <input id="pinTable-pin-21" type="radio" name="pins" value="21"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-22"><input id="pinTable-pin-22" type="radio" name="pins" value="22"> 22 - GPIO25</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-23">SCLK - GPIO11 - 23 <input id="pinTable-pin-23" type="radio" name="pins" value="23"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-24"><input id="pinTable-pin-24" type="radio" name="pins" value="24"> 24 - GPIO8 - CE0</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGround"><label>Ground - 25 <input disabled type="radio" name="pins" value=""></label></div>
|
||||||
|
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-26"><input id="pinTable-pin-26" type="radio" name="pins" value="26"> 26 - GPIO7 - CE1</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorSD"><label>SD - 27 <input disabled type="radio" name="pins" value=""></label></div>
|
||||||
|
<div class="pinTableCellR pinColorSD"><label><input disabled type="radio" name="pins" value=""> 28 - SC</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-29">GPIO05 - 29 <input id="pinTable-pin-29" type="radio" name="pins" value="29"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGround"><label><input disabled type="radio" name="pins" value=""> 30 - Ground</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-31">GPIO06 - 31 <input id="pinTable-pin-31" type="radio" name="pins" value="31"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-32"><input id="pinTable-pin-32" type="radio" name="pins" value="32"> 32 - GPIO12</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-33">GPIO13 - 33 <input id="pinTable-pin-33" type="radio" name="pins" value="33"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGround"><label><input disabled type="radio" name="pins" value=""> 34 - Ground</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-35">GPIO19 - 35 <input id="pinTable-pin-35" type="radio" name="pins" value="35"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-36"><input id="pinTable-pin-36" type="radio" name="pins" value="36"> 36 - GPIO16</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-37">GPIO26 - 37 <input id="pinTable-pin-37" type="radio" name="pins" value="37"></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-38"><input id="pinTable-pin-38" type="radio" name="pins" value="38"> 38 - GPIO20</label></div>
|
||||||
|
</div>
|
||||||
|
<div class="pinTableRow">
|
||||||
|
<div class="pinTableCellL pinColorGround"><label>Ground - 39 <input disabled type="radio" name="pins" value=""></label></div>
|
||||||
|
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-40"><input id="pinTable-pin-40" type="radio" name="pins" value="40"> 40 - GPIO21</label></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="form-row" id="node-set-pwm">
|
||||||
|
<label> <span data-i18n="rpi-gpio.label.type"></span></label>
|
||||||
|
<select id="node-input-out" style="width: 250px;">
|
||||||
|
<option value="out" data-i18n="rpi-gpio.digout"></option>
|
||||||
|
<option value="pwm" data-i18n="rpi-gpio.pwmout"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-row" id="node-set-tick">
|
||||||
|
<label> </label>
|
||||||
|
<input type="checkbox" id="node-input-set" style="display: inline-block; width: auto; vertical-align: top;">
|
||||||
|
<label for="node-input-set" style="width: 70%;"><span data-i18n="rpi-gpio.label.initpin"></span></label>
|
||||||
|
</div>
|
||||||
|
<div class="form-row" id="node-set-state">
|
||||||
|
<label for="node-input-level"> </label>
|
||||||
|
<select id="node-input-level" style="width: 250px;">
|
||||||
|
<option value="0" data-i18n="rpi-gpio.initpin0"></option>
|
||||||
|
<option value="1" data-i18n="rpi-gpio.initpin1"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-row" id="node-set-freq">
|
||||||
|
<label for="node-input-freq"> <span data-i18n="rpi-gpio.label.freq"></span></label>
|
||||||
|
<input type="text" id="node-input-freq" placeholder="100"> Hz
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||||
|
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
|
||||||
|
</div>
|
||||||
|
<div class="form-tips" id="pin-tip"><span data-i18n="[html]rpi-gpio.tip.pin"></span></div>
|
||||||
|
<div class="form-tips" id="dig-tip"><span data-i18n="[html]rpi-gpio.tip.dig"></span></div>
|
||||||
|
<div class="form-tips" id="pwm-tip"><span data-i18n="[html]rpi-gpio.tip.pwm"></span></div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var bcm2pin = {
|
||||||
|
"2":"3", "3":"5", "4":"7", "14":"8", "15":"10", "17":"11", "18":"12", "27":"13", "22":"15",
|
||||||
|
"23":"16", "24":"18", "10":"19", "9":"21", "25":"22", "11":"23", "8":"24", "7":"26",
|
||||||
|
"5":"29", "6":"31", "12":"32", "13":"33", "19":"35", "16":"36", "26":"37", "20":"38", "21":"40"
|
||||||
|
};
|
||||||
|
var pinsInUse = {};
|
||||||
|
RED.nodes.registerType('rpi-gpio out',{
|
||||||
|
category: 'Raspberry Pi',
|
||||||
|
color:"#c6dbef",
|
||||||
|
defaults: {
|
||||||
|
name: { value:"" },
|
||||||
|
pin: { value:"",required:true,validate:RED.validators.number() },
|
||||||
|
set: { value:"" },
|
||||||
|
level: { value:"0" },
|
||||||
|
freq: {value:""},
|
||||||
|
out: { value:"out" }
|
||||||
|
},
|
||||||
|
inputs:1,
|
||||||
|
outputs:0,
|
||||||
|
icon: "rpi.png",
|
||||||
|
info: function() {
|
||||||
|
if ( Object.keys(pinsInUse).length !== 0 ) {
|
||||||
|
return "**Pins in use** : "+Object.keys(pinsInUse);
|
||||||
|
}
|
||||||
|
else { return ""; }
|
||||||
|
},
|
||||||
|
align: "right",
|
||||||
|
label: function() {
|
||||||
|
if (this.out === "pwm") { return this.name || "PWM: "+this.pin; }
|
||||||
|
else if (this.out === "ser") { return this.name || "Servo: "+this.pin; }
|
||||||
|
else {
|
||||||
|
var suf = "";
|
||||||
|
if (this.set == true) { suf = (this.level === "1") ? " ¹" : " ₀"; }
|
||||||
|
return this.name||"PIN: "+ this.pin + suf ;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
},
|
||||||
|
inputLabels: function() { return "GPIO"+this.pin; },
|
||||||
|
oneditprepare: function() {
|
||||||
|
var pinnow = this.pin;
|
||||||
|
var pintip = this._("rpi-gpio.tip.pin");
|
||||||
|
var pinname = this._("rpi-gpio.pinname");
|
||||||
|
var alreadyuse = this._("rpi-gpio.alreadyuse");
|
||||||
|
var alreadyset = this._("rpi-gpio.alreadyset");
|
||||||
|
if (!$("#node-input-out").val()) { $("#node-input-out").val("out"); }
|
||||||
|
|
||||||
|
$.getJSON('rpi-pins/'+this.id,function(data) {
|
||||||
|
pinsInUse = data || {};
|
||||||
|
$('#pin-tip').html(pintip + Object.keys(data));
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#node-input-pin").on("change", function() {
|
||||||
|
if ($("#node-input-pin").val()) {
|
||||||
|
$("#pinform input[value="+$("#node-input-pin").val()+"]").prop('checked', true);
|
||||||
|
}
|
||||||
|
var pinnew = $("#node-input-pin").val();
|
||||||
|
if ((pinnew) && (pinnew !== pinnow)) {
|
||||||
|
if (pinsInUse.hasOwnProperty(pinnew)) {
|
||||||
|
RED.notify(pinname+" "+pinnew+" "+alreadyuse,"warn");
|
||||||
|
}
|
||||||
|
pinnow = pinnew;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#node-input-out").on("change", function() {
|
||||||
|
var newtype = $("#node-input-out").val();
|
||||||
|
if ((pinsInUse.hasOwnProperty(pinnow)) && (pinsInUse[pinnow] !== newtype)) {
|
||||||
|
RED.notify(pinname+" "+pinnow+" "+alreadyset+" "+pinsInUse[pinnow],"error");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var hidestate = function () {
|
||||||
|
if ($("#node-input-out").val() === "pwm") {
|
||||||
|
$('#node-set-tick').hide();
|
||||||
|
$('#node-set-state').hide();
|
||||||
|
$('#node-input-set').prop('checked', false);
|
||||||
|
$("#dig-tip").hide();
|
||||||
|
$("#pwm-tip").show();
|
||||||
|
$('#node-set-freq').show();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
$('#node-set-tick').show();
|
||||||
|
$("#dig-tip").show();
|
||||||
|
$("#pwm-tip").hide();
|
||||||
|
$('#node-set-freq').hide();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
$("#node-input-out").on("change", function () { hidestate(); });
|
||||||
|
hidestate();
|
||||||
|
|
||||||
|
var setstate = function () {
|
||||||
|
if ($('#node-input-set').is(":checked")) {
|
||||||
|
$("#node-set-state").show();
|
||||||
|
} else {
|
||||||
|
$("#node-set-state").hide();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
$("#node-input-set").on("change", function () { setstate(); });
|
||||||
|
setstate();
|
||||||
|
|
||||||
|
$('#pinform input').on('change', function() {
|
||||||
|
this.pin = $("#pinform input[type='radio']:checked").val();
|
||||||
|
$("#node-input-pin").val(this.pin);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-template-name="rpi-mouse">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-butt"><i class="fa fa-circle"></i> <span data-i18n="rpi-gpio.label.button"></span></label>
|
||||||
|
<select type="text" id="node-input-butt" style="width: 250px;">
|
||||||
|
<option value="1" data-i18n="rpi-gpio.left"></option>
|
||||||
|
<option value="2" data-i18n="rpi-gpio.right"></option>
|
||||||
|
<option value="4" data-i18n="rpi-gpio.middle"></option>
|
||||||
|
<option value="7" data-i18n="rpi-gpio.any"></option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<br/>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||||
|
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('rpi-mouse',{
|
||||||
|
category: 'Raspberry Pi',
|
||||||
|
color:"#c6dbef",
|
||||||
|
defaults: {
|
||||||
|
name: { value:"" },
|
||||||
|
butt: { value:"1",required:true }
|
||||||
|
},
|
||||||
|
inputs:0,
|
||||||
|
outputs:1,
|
||||||
|
icon: "rpi.png",
|
||||||
|
label: function() {
|
||||||
|
var na = this._("rpi-gpio.label.pimouse");
|
||||||
|
if (this.butt === "1") { na += " "+this._("rpi-gpio.label.left"); }
|
||||||
|
if (this.butt === "2") { na += " "+this._("rpi-gpio.label.right"); }
|
||||||
|
if (this.butt === "4") { na += " "+this._("rpi-gpio.label.middle"); }
|
||||||
|
return this.name||na;
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-template-name="rpi-keyboard">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
|
||||||
|
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('rpi-keyboard',{
|
||||||
|
category: 'Raspberry Pi',
|
||||||
|
color:"#c6dbef",
|
||||||
|
defaults: {
|
||||||
|
name: { value:"" }
|
||||||
|
},
|
||||||
|
inputs:0,
|
||||||
|
outputs:1,
|
||||||
|
icon: "rpi.png",
|
||||||
|
label: function() {
|
||||||
|
return this.name || this._("rpi-gpio.label.pikeyboard");
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
371
hardware/PiGpio/36-rpi-gpio.js
Normal file
371
hardware/PiGpio/36-rpi-gpio.js
Normal file
@ -0,0 +1,371 @@
|
|||||||
|
|
||||||
|
module.exports = function(RED) {
|
||||||
|
"use strict";
|
||||||
|
var exec = require('child_process').exec;
|
||||||
|
var spawn = require('child_process').spawn;
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
var gpioCommand = __dirname+'/nrgpio';
|
||||||
|
var allOK = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
var cpuinfo = fs.readFileSync("/proc/cpuinfo").toString();
|
||||||
|
if (cpuinfo.indexOf(": BCM") === -1) {
|
||||||
|
allOK = false;
|
||||||
|
RED.log.warn("rpi-gpio : "+RED._("rpi-gpio.errors.ignorenode"));
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
fs.statSync("/usr/share/doc/python-rpi.gpio"); // test on Raspbian
|
||||||
|
// /usr/lib/python2.7/dist-packages/RPi/GPIO
|
||||||
|
} catch(err) {
|
||||||
|
try {
|
||||||
|
fs.statSync("/usr/lib/python2.7/site-packages/RPi/GPIO"); // test on Arch
|
||||||
|
} catch(err) {
|
||||||
|
try {
|
||||||
|
fs.statSync("/usr/lib/python2.7/dist-packages/RPi/GPIO"); // test on Hypriot
|
||||||
|
} catch(err) {
|
||||||
|
try {
|
||||||
|
fs.statSync("/usr/local/lib/python2.7/dist-packages/RPi/GPIO"); // installed with pip
|
||||||
|
} catch(err) {
|
||||||
|
RED.log.warn("rpi-gpio : "+RED._("rpi-gpio.errors.libnotfound"));
|
||||||
|
allOK = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !(1 & parseInt((fs.statSync(gpioCommand).mode & parseInt("777", 8)).toString(8)[0]) )) {
|
||||||
|
RED.log.warn("rpi-gpio : "+RED._("rpi-gpio.errors.needtobeexecutable",{command:gpioCommand}));
|
||||||
|
allOK = false;
|
||||||
|
}
|
||||||
|
} catch(err) {
|
||||||
|
allOK = false;
|
||||||
|
RED.log.warn("rpi-gpio : "+RED._("rpi-gpio.errors.ignorenode"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// the magic to make python print stuff immediately
|
||||||
|
process.env.PYTHONUNBUFFERED = 1;
|
||||||
|
|
||||||
|
var pinsInUse = {};
|
||||||
|
var pinTypes = {"out":RED._("rpi-gpio.types.digout"), "tri":RED._("rpi-gpio.types.input"), "up":RED._("rpi-gpio.types.pullup"), "down":RED._("rpi-gpio.types.pulldown"), "pwm":RED._("rpi-gpio.types.pwmout")};
|
||||||
|
|
||||||
|
function GPIOInNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.buttonState = -1;
|
||||||
|
this.pin = n.pin;
|
||||||
|
this.intype = n.intype;
|
||||||
|
this.read = n.read || false;
|
||||||
|
this.debounce = Number(n.debounce || 25);
|
||||||
|
if (this.read) { this.buttonState = -2; }
|
||||||
|
var node = this;
|
||||||
|
if (!pinsInUse.hasOwnProperty(this.pin)) {
|
||||||
|
pinsInUse[this.pin] = this.intype;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ((pinsInUse[this.pin] !== this.intype)||(pinsInUse[this.pin] === "pwm")) {
|
||||||
|
node.warn(RED._("rpi-gpio.errors.alreadyset",{pin:this.pin,type:pinTypes[pinsInUse[this.pin]]}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allOK === true) {
|
||||||
|
if (node.pin !== undefined) {
|
||||||
|
node.child = spawn(gpioCommand, ["in",node.pin,node.intype,node.debounce]);
|
||||||
|
node.running = true;
|
||||||
|
node.status({fill:"green",shape:"dot",text:"common.status.ok"});
|
||||||
|
|
||||||
|
node.child.stdout.on('data', function (data) {
|
||||||
|
var d = data.toString().trim().split("\n");
|
||||||
|
for (var i = 0; i < d.length; i++) {
|
||||||
|
if (d[i] === '') { return; }
|
||||||
|
if (node.running && node.buttonState !== -1 && !isNaN(Number(d[i])) && node.buttonState !== d[i]) {
|
||||||
|
node.send({ topic:"pi/"+node.pin, payload:Number(d[i]) });
|
||||||
|
}
|
||||||
|
node.buttonState = d[i];
|
||||||
|
node.status({fill:"green",shape:"dot",text:d[i]});
|
||||||
|
if (RED.settings.verbose) { node.log("out: "+d[i]+" :"); }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
node.child.stderr.on('data', function (data) {
|
||||||
|
if (RED.settings.verbose) { node.log("err: "+data+" :"); }
|
||||||
|
});
|
||||||
|
|
||||||
|
node.child.on('close', function (code) {
|
||||||
|
node.running = false;
|
||||||
|
node.child = null;
|
||||||
|
if (RED.settings.verbose) { node.log(RED._("rpi-gpio.status.closed")); }
|
||||||
|
if (node.done) {
|
||||||
|
node.status({fill:"grey",shape:"ring",text:"rpi-gpio.status.closed"});
|
||||||
|
node.done();
|
||||||
|
}
|
||||||
|
else { node.status({fill:"red",shape:"ring",text:"rpi-gpio.status.stopped"}); }
|
||||||
|
});
|
||||||
|
|
||||||
|
node.child.on('error', function (err) {
|
||||||
|
if (err.errno === "ENOENT") { node.error(RED._("rpi-gpio.errors.commandnotfound")); }
|
||||||
|
else if (err.errno === "EACCES") { node.error(RED._("rpi-gpio.errors.commandnotexecutable")); }
|
||||||
|
else { node.error(RED._("rpi-gpio.errors.error",{error:err.errno})) }
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
node.warn(RED._("rpi-gpio.errors.invalidpin")+": "+node.pin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
node.status({fill:"grey",shape:"dot",text:"node-red:rpi-gpio.status.not-available"});
|
||||||
|
if (node.read === true) {
|
||||||
|
var val;
|
||||||
|
if (node.intype == "up") { val = 1; }
|
||||||
|
if (node.intype == "down") { val = 0; }
|
||||||
|
setTimeout(function(){
|
||||||
|
node.send({ topic:"pi/"+node.pin, payload:val });
|
||||||
|
node.status({fill:"grey",shape:"dot",text:RED._("rpi-gpio.status.na",{value:val})});
|
||||||
|
},250);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node.on("close", function(done) {
|
||||||
|
node.status({fill:"grey",shape:"ring",text:"rpi-gpio.status.closed"});
|
||||||
|
delete pinsInUse[node.pin];
|
||||||
|
if (node.child != null) {
|
||||||
|
node.done = done;
|
||||||
|
node.child.stdin.write("close "+node.pin);
|
||||||
|
node.child.kill('SIGKILL');
|
||||||
|
}
|
||||||
|
else { done(); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("rpi-gpio in",GPIOInNode);
|
||||||
|
|
||||||
|
function GPIOOutNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.pin = n.pin;
|
||||||
|
this.set = n.set || false;
|
||||||
|
this.level = n.level || 0;
|
||||||
|
this.freq = n.freq || 100;
|
||||||
|
this.out = n.out || "out";
|
||||||
|
var node = this;
|
||||||
|
if (!pinsInUse.hasOwnProperty(this.pin)) {
|
||||||
|
pinsInUse[this.pin] = this.out;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if ((pinsInUse[this.pin] !== this.out)||(pinsInUse[this.pin] === "pwm")) {
|
||||||
|
node.warn(RED._("rpi-gpio.errors.alreadyset",{pin:this.pin,type:pinTypes[pinsInUse[this.pin]]}));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function inputlistener(msg) {
|
||||||
|
if (msg.payload === "true") { msg.payload = true; }
|
||||||
|
if (msg.payload === "false") { msg.payload = false; }
|
||||||
|
var out = Number(msg.payload);
|
||||||
|
var limit = 1;
|
||||||
|
if (node.out === "pwm") { limit = 100; }
|
||||||
|
if ((out >= 0) && (out <= limit)) {
|
||||||
|
if (RED.settings.verbose) { node.log("out: "+out); }
|
||||||
|
if (node.child !== null) {
|
||||||
|
node.child.stdin.write(out+"\n");
|
||||||
|
node.status({fill:"green",shape:"dot",text:msg.payload.toString()});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
node.error(RED._("rpi-gpio.errors.pythoncommandnotfound"),msg);
|
||||||
|
node.status({fill:"red",shape:"ring",text:"rpi-gpio.status.not-running"});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { node.warn(RED._("rpi-gpio.errors.invalidinput")+": "+out); }
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allOK === true) {
|
||||||
|
if (node.pin !== undefined) {
|
||||||
|
if (node.set && (node.out === "out")) {
|
||||||
|
node.child = spawn(gpioCommand, [node.out,node.pin,node.level]);
|
||||||
|
node.status({fill:"green",shape:"dot",text:node.level});
|
||||||
|
} else {
|
||||||
|
node.child = spawn(gpioCommand, [node.out,node.pin,node.freq]);
|
||||||
|
node.status({fill:"green",shape:"dot",text:"common.status.ok"});
|
||||||
|
}
|
||||||
|
node.running = true;
|
||||||
|
|
||||||
|
node.on("input", inputlistener);
|
||||||
|
|
||||||
|
node.child.stdout.on('data', function (data) {
|
||||||
|
if (RED.settings.verbose) { node.log("out: "+data+" :"); }
|
||||||
|
});
|
||||||
|
|
||||||
|
node.child.stderr.on('data', function (data) {
|
||||||
|
if (RED.settings.verbose) { node.log("err: "+data+" :"); }
|
||||||
|
});
|
||||||
|
|
||||||
|
node.child.on('close', function (code) {
|
||||||
|
node.child = null;
|
||||||
|
node.running = false;
|
||||||
|
if (RED.settings.verbose) { node.log(RED._("rpi-gpio.status.closed")); }
|
||||||
|
if (node.done) {
|
||||||
|
node.status({fill:"grey",shape:"ring",text:"rpi-gpio.status.closed"});
|
||||||
|
node.done();
|
||||||
|
}
|
||||||
|
else { node.status({fill:"red",shape:"ring",text:"rpi-gpio.status.stopped"}); }
|
||||||
|
});
|
||||||
|
|
||||||
|
node.child.on('error', function (err) {
|
||||||
|
if (err.errno === "ENOENT") { node.error(RED._("rpi-gpio.errors.commandnotfound")); }
|
||||||
|
else if (err.errno === "EACCES") { node.error(RED._("rpi-gpio.errors.commandnotexecutable")); }
|
||||||
|
else { node.error(RED._("rpi-gpio.errors.error")+': ' + err.errno); }
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
node.warn(RED._("rpi-gpio.errors.invalidpin")+": "+node.pin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
node.status({fill:"grey",shape:"dot",text:"node-red:rpi-gpio.status.not-available"});
|
||||||
|
node.on("input", function(msg){
|
||||||
|
node.status({fill:"grey",shape:"dot",text:RED._("rpi-gpio.status.na",{value:msg.payload.toString()})});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
node.on("close", function(done) {
|
||||||
|
node.status({fill:"grey",shape:"ring",text:"rpi-gpio.status.closed"});
|
||||||
|
delete pinsInUse[node.pin];
|
||||||
|
if (node.child != null) {
|
||||||
|
node.done = done;
|
||||||
|
node.child.stdin.write("close "+node.pin);
|
||||||
|
node.child.kill('SIGKILL');
|
||||||
|
}
|
||||||
|
else { done(); }
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("rpi-gpio out",GPIOOutNode);
|
||||||
|
|
||||||
|
function PiMouseNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.butt = n.butt || 7;
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
if (allOK === true) {
|
||||||
|
node.child = spawn(gpioCommand+".py", ["mouse",node.butt]);
|
||||||
|
node.status({fill:"green",shape:"dot",text:"common.status.ok"});
|
||||||
|
|
||||||
|
node.child.stdout.on('data', function (data) {
|
||||||
|
data = Number(data);
|
||||||
|
if (data !== 0) { node.send({ topic:"pi/mouse", button:data, payload:1 }); }
|
||||||
|
else { node.send({ topic:"pi/mouse", button:data, payload:0 }); }
|
||||||
|
});
|
||||||
|
|
||||||
|
node.child.stderr.on('data', function (data) {
|
||||||
|
if (RED.settings.verbose) { node.log("err: "+data+" :"); }
|
||||||
|
});
|
||||||
|
|
||||||
|
node.child.on('close', function (code) {
|
||||||
|
node.child = null;
|
||||||
|
node.running = false;
|
||||||
|
if (RED.settings.verbose) { node.log(RED._("rpi-gpio.status.closed")); }
|
||||||
|
if (node.done) {
|
||||||
|
node.status({fill:"grey",shape:"ring",text:"rpi-gpio.status.closed"});
|
||||||
|
node.done();
|
||||||
|
}
|
||||||
|
else { node.status({fill:"red",shape:"ring",text:"rpi-gpio.status.stopped"}); }
|
||||||
|
});
|
||||||
|
|
||||||
|
node.child.on('error', function (err) {
|
||||||
|
if (err.errno === "ENOENT") { node.error(RED._("rpi-gpio.errors.commandnotfound")); }
|
||||||
|
else if (err.errno === "EACCES") { node.error(RED._("rpi-gpio.errors.commandnotexecutable")); }
|
||||||
|
else { node.error(RED._("rpi-gpio.errors.error")+': ' + err.errno); }
|
||||||
|
});
|
||||||
|
|
||||||
|
node.on("close", function(done) {
|
||||||
|
node.status({fill:"grey",shape:"ring",text:"rpi-gpio.status.closed"});
|
||||||
|
if (node.child != null) {
|
||||||
|
node.done = done;
|
||||||
|
node.child.kill('SIGINT');
|
||||||
|
node.child = null;
|
||||||
|
}
|
||||||
|
else { done(); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
node.status({fill:"grey",shape:"dot",text:"node-red:rpi-gpio.status.not-available"});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("rpi-mouse",PiMouseNode);
|
||||||
|
|
||||||
|
function PiKeyboardNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
if (allOK === true) {
|
||||||
|
node.child = spawn(gpioCommand+".py", ["kbd","0"]);
|
||||||
|
node.status({fill:"green",shape:"dot",text:"common.status.ok"});
|
||||||
|
|
||||||
|
node.child.stdout.on('data', function (data) {
|
||||||
|
var b = data.toString().trim().split(",");
|
||||||
|
var act = "up";
|
||||||
|
if (b[1] === "1") { act = "down"; }
|
||||||
|
if (b[1] === "2") { act = "repeat"; }
|
||||||
|
node.send({ topic:"pi/key", payload:Number(b[0]), action:act });
|
||||||
|
});
|
||||||
|
|
||||||
|
node.child.stderr.on('data', function (data) {
|
||||||
|
if (RED.settings.verbose) { node.log("err: "+data+" :"); }
|
||||||
|
});
|
||||||
|
|
||||||
|
node.child.on('close', function (code) {
|
||||||
|
node.running = false;
|
||||||
|
node.child = null;
|
||||||
|
if (RED.settings.verbose) { node.log(RED._("rpi-gpio.status.closed")); }
|
||||||
|
if (node.done) {
|
||||||
|
node.status({fill:"grey",shape:"ring",text:"rpi-gpio.status.closed"});
|
||||||
|
node.done();
|
||||||
|
}
|
||||||
|
else { node.status({fill:"red",shape:"ring",text:"rpi-gpio.status.stopped"}); }
|
||||||
|
});
|
||||||
|
|
||||||
|
node.child.on('error', function (err) {
|
||||||
|
if (err.errno === "ENOENT") { node.error(RED._("rpi-gpio.errors.commandnotfound")); }
|
||||||
|
else if (err.errno === "EACCES") { node.error(RED._("rpi-gpio.errors.commandnotexecutable")); }
|
||||||
|
else { node.error(RED._("rpi-gpio.errors.error")+': ' + err.errno); }
|
||||||
|
});
|
||||||
|
|
||||||
|
node.on("close", function(done) {
|
||||||
|
node.status({});
|
||||||
|
if (node.child != null) {
|
||||||
|
node.done = done;
|
||||||
|
node.child.kill('SIGINT');
|
||||||
|
node.child = null;
|
||||||
|
}
|
||||||
|
else { done(); }
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
node.status({fill:"grey",shape:"dot",text:"node-red:rpi-gpio.status.not-available"});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("rpi-keyboard",PiKeyboardNode);
|
||||||
|
|
||||||
|
var pitype = { type:"" };
|
||||||
|
if (allOK === true) {
|
||||||
|
exec(gpioCommand+" info", function(err,stdout,stderr) {
|
||||||
|
if (err) {
|
||||||
|
RED.log.info(RED._("rpi-gpio.errors.version"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
try {
|
||||||
|
var info = JSON.parse( stdout.trim().replace(/\'/g,"\"") );
|
||||||
|
pitype.type = info["TYPE"];
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
RED.log.info(RED._("rpi-gpio.errors.sawpitype"),stdout.trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.httpAdmin.get('/rpi-gpio/:id', RED.auth.needsPermission('rpi-gpio.read'), function(req,res) {
|
||||||
|
res.json(pitype);
|
||||||
|
});
|
||||||
|
|
||||||
|
RED.httpAdmin.get('/rpi-pins/:id', RED.auth.needsPermission('rpi-gpio.read'), function(req,res) {
|
||||||
|
res.json(pinsInUse);
|
||||||
|
});
|
||||||
|
}
|
177
hardware/PiGpio/LICENSE
Normal file
177
hardware/PiGpio/LICENSE
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
74
hardware/PiGpio/locales/de/36-rpi-gpio.html
Normal file
74
hardware/PiGpio/locales/de/36-rpi-gpio.html
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
<!--
|
||||||
|
Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
|
||||||
|
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-help-name="rpi-gpio in">
|
||||||
|
<p> Raspberry Pi-Empfangsknoten. Generiert eine <code>msg.payload</code> mit einem Wert von
|
||||||
|
0 oder 1 in Abhängigkeit vom Status des Eingabepins. </p>
|
||||||
|
<h3> Ausgaben </h3>
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt> payload <span class="property-type"> Zahl </span> </dt>
|
||||||
|
<dd> Die Nutzdaten sind 1 oder 0. </dd>
|
||||||
|
<dt> topic <span class="property-type"> Zeichenfolge </span> </dt>
|
||||||
|
<dd> Das Thema wird auf <code>pi/ { the pin number }</code> gesetzt. </dd>
|
||||||
|
</dl>
|
||||||
|
<h3> Details </h3>
|
||||||
|
<p> Sie können auch den Eingangs-Pullup-Widerstand oder den Pulldown-Widerstand aktivieren. </p>
|
||||||
|
<p> Erfordert die Python-Bibliothek RPi.GPIO in der Version 0.5.10 (oder besser). </p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="rpi-gpio out">
|
||||||
|
<p> Raspberry Pi-Ausgabeknoten. Kann im Digital- oder PWM-Modus verwendet werden. </p>
|
||||||
|
<h3> Eingaben </h3>
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt> payload <span class="property-type"> Zahl | Zeichen | Boolean </span> </dt>
|
||||||
|
</dl>
|
||||||
|
<h3> Details </h3>
|
||||||
|
<p> Der digitale Modus erwartet der Knoten eine <code>msg.payload</code> von entweder 0 oder 1 (oder false oder true)
|
||||||
|
und schaltet den ausgewählten physischen Pin in Abhängigkeit von dem übergebenen Wert entweder auf LOW oder HIGH. </p>
|
||||||
|
<p> Der Anfangswert für den Pin kann bei der Implementierung auf 0 oder 1 gesetzt werden. </p>
|
||||||
|
<p> Im PWM-Modus erwartet der Knoten einen Eingabewert mit der Zahl 0-100. Es kann ein Gleitkommazahl sein. </p>
|
||||||
|
<p> Der PWM-Modus kann verwendet werden, um einen Servo unter Verwendung von Eingabewerten nur zwischen 10 und 20 zu steuern,
|
||||||
|
akzeptiert aber auch Gleitkommawerte. Der GPIO2-Pin eignet sich am besten dafür, da er Hardware-PWM unterstützt. Für eine bessere Servounterstützung
|
||||||
|
sollten Sie den alternativen Knoten <pre>Node-red-node-pi-gpiod</pre> berücksichtigen. </p>
|
||||||
|
<p> Erfordert die Python-Bibliothek RPi.GPIO in der Version 0.5.10 (oder besser). </p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="rpi-mouse">
|
||||||
|
<p> Raspberry Pi-Maustastenknoten. Erfordert eine USB-Maus. </p>
|
||||||
|
<h3>Ausgaben </h3>
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt> payload <span class="property-type"> Zahl </span> </dt>
|
||||||
|
<dd> 1 oder 0, wenn die ausgewählte Maustaste gedrückt und losgelassen wird. </dd>
|
||||||
|
<dt> Schaltfläche <span class="property-type"> Zahl </span> </dt>
|
||||||
|
<dd> 1, 2, 4 entsprechend der linken, der rechten und der mittleren Taste, so dass Sie herausfinden können,
|
||||||
|
welche Schaltfläche oder Kombination gedrückt wurde. </dd>
|
||||||
|
<dt> topic <span class="property-type"> Zeichenfolge </span> </dt>
|
||||||
|
<dd>wird auf: <code>pi/mouse</code> gesetzt</dd>
|
||||||
|
</dl>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="rpi-keyboard">
|
||||||
|
<p>Raspberry Pi Tastaturknoten. Benötigt eine USB Tastatur.</p>
|
||||||
|
<h3>Ausgaben</h3>
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>payload <span class="property-type">Zahl</span></dt>
|
||||||
|
<dd>enthält den Tastaturcode value</dd>
|
||||||
|
<dt>action <span class="property-type">Zeichenfolge</span></dt>
|
||||||
|
<dd>wird auf "up", "down", oder "repeat" gesetzt</dd>
|
||||||
|
<dt>topic <span class="property-type">Zeichenfolge</span></dt>
|
||||||
|
<dd>wird auf <code>pi/key</code> gesetzt</dd>
|
||||||
|
</dl>
|
||||||
|
</script>
|
74
hardware/PiGpio/locales/en-US/36-rpi-gpio.json
Normal file
74
hardware/PiGpio/locales/en-US/36-rpi-gpio.json
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
{
|
||||||
|
"rpi-gpio": {
|
||||||
|
"label": {
|
||||||
|
"gpiopin": "GPIO",
|
||||||
|
"selectpin": "select pin",
|
||||||
|
"resistor": "Resistor?",
|
||||||
|
"readinitial": "Read initial state of pin on deploy/restart?",
|
||||||
|
"type": "Type",
|
||||||
|
"initpin": "Initialise pin state?",
|
||||||
|
"debounce": "Debounce",
|
||||||
|
"freq": "Frequency",
|
||||||
|
"button": "Button",
|
||||||
|
"pimouse": "Pi Mouse",
|
||||||
|
"pikeyboard": "Pi Keyboard",
|
||||||
|
"left": "Left",
|
||||||
|
"right": "Right",
|
||||||
|
"middle": "Middle"
|
||||||
|
},
|
||||||
|
"resistor": {
|
||||||
|
"none": "none",
|
||||||
|
"pullup": "pullup",
|
||||||
|
"pulldown": "pulldown"
|
||||||
|
},
|
||||||
|
"digout": "Digital output",
|
||||||
|
"pwmout": "PWM output",
|
||||||
|
"servo": "Servo output",
|
||||||
|
"initpin0": "initial level of pin - low (0)",
|
||||||
|
"initpin1": "initial level of pin - high (1)",
|
||||||
|
"left": "left",
|
||||||
|
"right": "right",
|
||||||
|
"middle": "middle",
|
||||||
|
"any": "any",
|
||||||
|
"pinname": "Pin",
|
||||||
|
"alreadyuse": "already in use",
|
||||||
|
"alreadyset": "already set as",
|
||||||
|
"tip": {
|
||||||
|
"pin": "<b>Pins in Use</b>: ",
|
||||||
|
"in": "Tip: Only Digital Input is supported - input must be 0 or 1.",
|
||||||
|
"dig": "Tip: For digital output - input must be 0 or 1.",
|
||||||
|
"pwm": "Tip: For PWM output - input must be between 0 to 100; setting high frequency might occupy more CPU than expected.",
|
||||||
|
"ser": "<b>Tip</b>: For Servo output - input must be between 0 to 100. 50 is centre."
|
||||||
|
},
|
||||||
|
"types": {
|
||||||
|
"digout": "digital output",
|
||||||
|
"input": "input",
|
||||||
|
"pullup": "input with pull up",
|
||||||
|
"pulldown": "input with pull down",
|
||||||
|
"pwmout": "PWM output",
|
||||||
|
"servo": "Servo output"
|
||||||
|
},
|
||||||
|
"status": {
|
||||||
|
"stopped": "stopped",
|
||||||
|
"closed": "closed",
|
||||||
|
"not-running": "not running",
|
||||||
|
"not-available": "not available",
|
||||||
|
"na": "N/A : __value__"
|
||||||
|
},
|
||||||
|
"errors": {
|
||||||
|
"ignorenode": "Raspberry Pi specific node set inactive",
|
||||||
|
"version": "Failed to get version from Pi",
|
||||||
|
"sawpitype": "Saw Pi Type",
|
||||||
|
"libnotfound": "Cannot find Pi RPi.GPIO python library",
|
||||||
|
"alreadyset": "GPIO pin __pin__ already set as type: __type__",
|
||||||
|
"invalidpin": "Invalid GPIO pin",
|
||||||
|
"invalidinput": "Invalid input",
|
||||||
|
"needtobeexecutable": "__command__ needs to be executable",
|
||||||
|
"mustbeexecutable": "nrgpio must to be executable",
|
||||||
|
"commandnotfound": "nrgpio command not found",
|
||||||
|
"commandnotexecutable": "nrgpio command not executable",
|
||||||
|
"error": "error: __error__",
|
||||||
|
"pythoncommandnotfound": "nrpgio python command not running"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
71
hardware/PiGpio/locales/ja/36-rpi-gpio.html
Normal file
71
hardware/PiGpio/locales/ja/36-rpi-gpio.html
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<!--
|
||||||
|
Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
|
||||||
|
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-help-name="rpi-gpio in">
|
||||||
|
<p>Raspberry Piの入力ノード。入力ピンの状態に応じて、0 または 1 の値を持つ<code>msg.payload</code>を生成します。</p>
|
||||||
|
<h3>出力</h3>
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>payload <span class="property-type">数値</span></dt>
|
||||||
|
<dd>ペイロードには、0 または 1 が設定されます。</dd>
|
||||||
|
<dt>topic <span class="property-type">文字列</span></dt>
|
||||||
|
<dd>トピックには、<code>pi/{ピン番号}</code>が設定されます。</dd>
|
||||||
|
</dl>
|
||||||
|
<h3>詳細</h3>
|
||||||
|
<p>入力のプルアップ抵抗またはプルダウン抵抗を有効にすることもできます。</p>
|
||||||
|
<p>動作にはRPi.GPIO pythonライブラリのバージョン 0.5.10 (またはそれ以上)が必要です。</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="rpi-gpio out">
|
||||||
|
<p>Raspberry Piの出力ノード。デジタルモードまたはPWMモードで利用できます。</p>
|
||||||
|
<h3>入力</h3>
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>payload <span class="property-type">数値 | 文字列 | 真偽値</span></dt>
|
||||||
|
</dl>
|
||||||
|
<h3>詳細</h3>
|
||||||
|
<p>デジタルモード - <code>msg.payload</code>に 0 または 1 (あるいは true または false ) を指定すると、入力値に応じて選択された物理ピンにハイまたはローを設定します。</p>
|
||||||
|
<p>デプロイ時にピンの初期値として 0 または 1 を設定することもできます。</p>
|
||||||
|
<p>PWMモード - 入力値に 0 から 100 の数値を指定でき。小数値の指定も可能です。</p>
|
||||||
|
<p>サーボの制御にPWMモードが利用でき、入力に小数値も含む 10 から 20 の値が指定可能です。
|
||||||
|
PWMを行うハードウェアを利用していることから、PWMモードの指定にはGPIO2ピンが最も適しています。
|
||||||
|
より良くサーボの制御を行いたい場合は、node-red-node-pi-gpiod ノードの利用も検討してください。</p>
|
||||||
|
<p>動作にはRPi.GPIO pythonライブラリのバージョン 0.5.10 (またはそれ以上)が必要です。</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="rpi-mouse">
|
||||||
|
<p>Raspberry Pi のマウスボタンノード。USBマウスが必要です。</p>
|
||||||
|
<h3>出力</h3>
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>payload <span class="property-type">数値</span></dt>
|
||||||
|
<dd>選択されたマウスのボタンが押された、または離された場合に 1 または 0 が設定されます。</dd>
|
||||||
|
<dt>button <span class="property-type">数値</span></dt>
|
||||||
|
<dd>左、右、真ん中のボタンに応じて 1, 2, 4 が設定され、ボタンあるいはボタンの組み合わせに応じた処理ができます。</dd>
|
||||||
|
<dt>topic <span class="property-type">文字列</span></dt>
|
||||||
|
<dd><code>pi/mouse</code>が設定されます。</dd>
|
||||||
|
</dl>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="rpi-keyboard">
|
||||||
|
<p>Raspberry Pi のキーボードを制御するノード。USBキーボードが必要です。</p>
|
||||||
|
<h3>出力</h3>
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>payload <span class="property-type">数値</span></dt>
|
||||||
|
<dd>キーコードを含みます。</dd>
|
||||||
|
<dt>action <span class="property-type">文字列</span></dt>
|
||||||
|
<dd>"up", "down", または "repeat" が設定されます。</dd>
|
||||||
|
<dt>topic <span class="property-type">文字列</span></dt>
|
||||||
|
<dd><code>pi/key</code>が設定されます。</dd>
|
||||||
|
</dl>
|
||||||
|
</script>
|
71
hardware/PiGpio/locales/ko/36-rpi-gpio.html
Normal file
71
hardware/PiGpio/locales/ko/36-rpi-gpio.html
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<!--
|
||||||
|
Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
|
||||||
|
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-help-name="rpi-gpio in">
|
||||||
|
<p>Raspberry Pi의 입력노드. 입력 핀의 상태에 따라, 0 또는 1의 값을 갖는 <code>msg.payload</code>을 생성합니다.</p>
|
||||||
|
<h3>출력</h3>
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>payload <span class="property-type">수치</span></dt>
|
||||||
|
<dd>페이로드에는, 0 또는 1이 설정됩니다.</dd>
|
||||||
|
<dt>topic <span class="property-type">문자열</span></dt>
|
||||||
|
<dd>토픽에는, <code>pi/{핀 번호}</code>가 설정됩니다.</dd>
|
||||||
|
</dl>
|
||||||
|
<h3>상세</h3>
|
||||||
|
<p>입력의 풀 업 저항 또는, 풀 다운 저항을 유효화 할 수도 있습니다.</p>
|
||||||
|
<p>작동하려면 RPi.GPIO python라이브러리 버젼0.5.10 (또는 그 이상)이 필요합니다.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="rpi-gpio out">
|
||||||
|
<p>Raspberry Pi의 출력노드. 디지털모드 또는 PWM모드에서 이용할 수 있습니다.</p>
|
||||||
|
<h3>입력</h3>
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>payload <span class="property-type">수치 | 문자열 | 진위값</span></dt>
|
||||||
|
</dl>
|
||||||
|
<h3>상세</h3>
|
||||||
|
<p>디지털모드 - <code>msg.payload</code>에 0 또는 1 (혹은 true 또는 false) 을 지정하면, 입력값에 따라 선택된 물리핀에 high 또는 low를 설정합니다.</p>
|
||||||
|
<p>배포시에 핀의 초기값으로 0 또는 1을 설정할 수도 있습니다.</p>
|
||||||
|
<p>PWM모드 - 입력값에 0에서 100의 수치를 지정할수 있고, 소수값도 지정할수 있습니다.</p>
|
||||||
|
<p>서보제어에 PWM모드를 이용할수 있으며, 입력에 소수값을 포함한 10에서 20의 값을 지정할 수 있습니다.
|
||||||
|
PWM를 실행하는 하드웨어를 이용하여, PWM모드의 지정에는 GPIO2핀이 가장 적합합니다.
|
||||||
|
보다 좋은 서보제어를 원하는 경우에는, node-red-node-pi-gpiod 노드를 이용할 것을 검토해 주십시오.</p>
|
||||||
|
<p>작동하려면 RPi.GPIO python라이브러리 버젼0.5.10 (또는 그 이상)이 필요합니다.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="rpi-mouse">
|
||||||
|
<p>Raspberry Pi 의 마우스버튼노드. USB마우스가 필요합니다.</p>
|
||||||
|
<h3>출력</h3>
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>payload <span class="property-type">수치</span></dt>
|
||||||
|
<dd>선택된 마우스의 버튼이 눌려지거나 떨어졌을 경우에 1 또는 0이 설정됩니다.</dd>
|
||||||
|
<dt>button <span class="property-type">수치</span></dt>
|
||||||
|
<dd>좌, 우, 중앙 버튼에 따라 1, 2, 4 가 설정되어, 버튼 혹은 버튼의 조합에 따른 처리를 할 수 있습니다.</dd>
|
||||||
|
<dt>topic <span class="property-type">문자열</span></dt>
|
||||||
|
<dd><code>pi/mouse</code>이 설정됩니다.</dd>
|
||||||
|
</dl>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="rpi-keyboard">
|
||||||
|
<p>Raspberry Pi 의 키보드를 제어하는 노드. USB키보드가 필요합니다.</p>
|
||||||
|
<h3>출력</h3>
|
||||||
|
<dl class="message-properties">
|
||||||
|
<dt>payload <span class="property-type">수치</span></dt>
|
||||||
|
<dd>키 코드를 포함합니다.</dd>
|
||||||
|
<dt>action <span class="property-type">문자열</span></dt>
|
||||||
|
<dd>"up", "down", 또는 "repeat" 이 설정됩니다.</dd>
|
||||||
|
<dt>topic <span class="property-type">문자열</span></dt>
|
||||||
|
<dd><code>pi/key</code>가 설정됩니다.</dd>
|
||||||
|
</dl>
|
||||||
|
</script>
|
17
hardware/PiGpio/nrgpio
Executable file
17
hardware/PiGpio/nrgpio
Executable file
@ -0,0 +1,17 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
#
|
||||||
|
# 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)
|
||||||
|
python -u $BASEDIR/nrgpio.py $@
|
239
hardware/PiGpio/nrgpio.py
Executable file
239
hardware/PiGpio/nrgpio.py
Executable file
@ -0,0 +1,239 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
#
|
||||||
|
# Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
#
|
||||||
|
# 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 struct
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import subprocess
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
try:
|
||||||
|
raw_input # Python 2
|
||||||
|
except NameError:
|
||||||
|
raw_input = input # Python 3
|
||||||
|
|
||||||
|
bounce = 25
|
||||||
|
|
||||||
|
if len(sys.argv) > 2:
|
||||||
|
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")
|
||||||
|
try:
|
||||||
|
freq = int(sys.argv[3])
|
||||||
|
except:
|
||||||
|
freq = 100
|
||||||
|
|
||||||
|
GPIO.setup(pin,GPIO.OUT)
|
||||||
|
p = GPIO.PWM(pin, freq)
|
||||||
|
p.start(0)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
data = raw_input()
|
||||||
|
if 'close' in data:
|
||||||
|
sys.exit(0)
|
||||||
|
p.ChangeDutyCycle(float(data))
|
||||||
|
except (EOFError, SystemExit): # 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 'close' in data:
|
||||||
|
sys.exit(0)
|
||||||
|
elif float(data) == 0:
|
||||||
|
p.stop()
|
||||||
|
else:
|
||||||
|
p.start(50)
|
||||||
|
p.ChangeFrequency(float(data))
|
||||||
|
except (EOFError, SystemExit): # 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 'close' in data:
|
||||||
|
sys.exit(0)
|
||||||
|
data = int(data)
|
||||||
|
except (EOFError, SystemExit): # hopefully always caused by us sigint'ing the program
|
||||||
|
GPIO.cleanup(pin)
|
||||||
|
sys.exit(0)
|
||||||
|
except:
|
||||||
|
if len(sys.argv) == 4:
|
||||||
|
data = int(sys.argv[3])
|
||||||
|
else:
|
||||||
|
data = 0
|
||||||
|
if data != 0:
|
||||||
|
data = 1
|
||||||
|
GPIO.output(pin,data)
|
||||||
|
|
||||||
|
elif cmd == "in":
|
||||||
|
#print("Initialised pin "+str(pin)+" to IN")
|
||||||
|
bounce = float(sys.argv[4])
|
||||||
|
def handle_callback(chan):
|
||||||
|
sleep(bounce/1000.0)
|
||||||
|
print(GPIO.input(chan))
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
print(GPIO.input(pin))
|
||||||
|
GPIO.add_event_detect(pin, GPIO.BOTH, callback=handle_callback, bouncetime=int(bounce))
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
data = raw_input()
|
||||||
|
if 'close' in data:
|
||||||
|
sys.exit(0)
|
||||||
|
except (EOFError, SystemExit): # 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 'close' in data:
|
||||||
|
sys.exit(0)
|
||||||
|
data = int(data)
|
||||||
|
except (EOFError, SystemExit): # 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 == "borg":
|
||||||
|
#print("Initialised BORG mode - "+str(pin)+)
|
||||||
|
GPIO.setup(11,GPIO.OUT)
|
||||||
|
GPIO.setup(13,GPIO.OUT)
|
||||||
|
GPIO.setup(15,GPIO.OUT)
|
||||||
|
r = GPIO.PWM(11, 100)
|
||||||
|
g = GPIO.PWM(13, 100)
|
||||||
|
b = GPIO.PWM(15, 100)
|
||||||
|
r.start(0)
|
||||||
|
g.start(0)
|
||||||
|
b.start(0)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
try:
|
||||||
|
data = raw_input()
|
||||||
|
if 'close' in data:
|
||||||
|
sys.exit(0)
|
||||||
|
c = data.split(",")
|
||||||
|
r.ChangeDutyCycle(float(c[0]))
|
||||||
|
g.ChangeDutyCycle(float(c[1]))
|
||||||
|
b.ChangeDutyCycle(float(c[2]))
|
||||||
|
except (EOFError, SystemExit): # hopefully always caused by us sigint'ing the program
|
||||||
|
GPIO.cleanup()
|
||||||
|
sys.exit(0)
|
||||||
|
except:
|
||||||
|
data = 0
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
elif cmd == "kbd": # catch keyboard button events
|
||||||
|
try:
|
||||||
|
while not os.path.isdir("/dev/input/by-path"):
|
||||||
|
sleep(10)
|
||||||
|
infile = subprocess.check_output("ls /dev/input/by-path/ | grep -m 1 'kbd'", shell=True).strip()
|
||||||
|
infile_path = "/dev/input/by-path/" + infile
|
||||||
|
EVENT_SIZE = struct.calcsize('llHHI')
|
||||||
|
file = open(infile_path, "rb")
|
||||||
|
event = file.read(EVENT_SIZE)
|
||||||
|
while event:
|
||||||
|
(tv_sec, tv_usec, type, code, value) = struct.unpack('llHHI', event)
|
||||||
|
#if type != 0 or code != 0 or value != 0:
|
||||||
|
if type == 1:
|
||||||
|
# type,code,value
|
||||||
|
print("%u,%u" % (code, value))
|
||||||
|
event = file.read(EVENT_SIZE)
|
||||||
|
print("0,0")
|
||||||
|
file.close()
|
||||||
|
sys.exit(0)
|
||||||
|
except:
|
||||||
|
file.close()
|
||||||
|
sys.exit(0)
|
||||||
|
|
||||||
|
elif len(sys.argv) > 1:
|
||||||
|
cmd = sys.argv[1].lower()
|
||||||
|
if cmd == "rev":
|
||||||
|
print(GPIO.RPI_REVISION)
|
||||||
|
elif cmd == "ver":
|
||||||
|
print(GPIO.VERSION)
|
||||||
|
elif cmd == "info":
|
||||||
|
print(GPIO.RPI_INFO)
|
||||||
|
else:
|
||||||
|
print("Bad parameters - in|out|pwm|buzz|byte|borg|mouse|kbd|ver|info {pin} {value|up|down}")
|
||||||
|
print(" only ver (gpio version) and info (board information) accept no pin parameter.")
|
||||||
|
|
||||||
|
else:
|
||||||
|
print("Bad parameters - in|out|pwm|buzz|byte|borg|mouse|kbd|ver|info {pin} {value|up|down}")
|
28
hardware/PiGpio/package.json
Normal file
28
hardware/PiGpio/package.json
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
"name": "node-red-node-pi-gpio",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "The basic Node-RED node for Pi GPIO",
|
||||||
|
"dependencies" : {
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/node-red/node-red-nodes/tree/master/hardware/PiGpio"
|
||||||
|
},
|
||||||
|
"keywords": [
|
||||||
|
"node-red", "Pi", "GPIO", "PiGpio"
|
||||||
|
],
|
||||||
|
"author": {
|
||||||
|
"name": "Dave Conway-Jones",
|
||||||
|
"email": "ceejay@vnet.ibm.com",
|
||||||
|
"url": "http://nodered.org"
|
||||||
|
},
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"node-red" : {
|
||||||
|
"nodes": {
|
||||||
|
"rpi-gpio": "36-rpi-gpio.js"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
157
test/hardware/PiGpio/36-rpi-gpio_spec.js
Normal file
157
test/hardware/PiGpio/36-rpi-gpio_spec.js
Normal file
@ -0,0 +1,157 @@
|
|||||||
|
/**
|
||||||
|
* Copyright JS Foundation and other contributors, http://js.foundation
|
||||||
|
*
|
||||||
|
* 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 should = require("should");
|
||||||
|
var helper = require("node-red-node-test-helper");
|
||||||
|
var rpiNode = require('../../../hardware/PiGpio/36-rpi-gpio.js');
|
||||||
|
|
||||||
|
//var rpiNode = require("nr-test-utils").require("@node-red/nodes/core/hardware/36-rpi-gpio.js");
|
||||||
|
//var statusNode = require("nr-test-utils").require("@node-red/nodes/core/core/25-status.js");
|
||||||
|
var helper = require("node-red-node-test-helper");
|
||||||
|
var fs = require("fs");
|
||||||
|
|
||||||
|
describe('RPI GPIO Node', function() {
|
||||||
|
|
||||||
|
before(function(done) {
|
||||||
|
helper.startServer(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
after(function(done) {
|
||||||
|
helper.stopServer(done);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(function() {
|
||||||
|
helper.unload();
|
||||||
|
});
|
||||||
|
|
||||||
|
var checkIgnore = function(done) {
|
||||||
|
setTimeout(function() {
|
||||||
|
try {
|
||||||
|
var logEvents = helper.log().args.filter(function(evt) {
|
||||||
|
return ((evt[0].level == 30) && (evt[0].msg.indexOf("rpi-gpio")===0));
|
||||||
|
});
|
||||||
|
logEvents[0][0].should.have.a.property('msg');
|
||||||
|
logEvents[0][0].msg.toString().should.startWith("rpi-gpio : rpi-gpio.errors.ignorenode");
|
||||||
|
done();
|
||||||
|
} catch(err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
},25);
|
||||||
|
}
|
||||||
|
|
||||||
|
it('should load Input node', function(done) {
|
||||||
|
var flow = [{id:"n1", type:"rpi-gpio in", name:"rpi-gpio in" }];
|
||||||
|
helper.load(rpiNode, flow, function() {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
n1.should.have.property('name', 'rpi-gpio in');
|
||||||
|
try {
|
||||||
|
var cpuinfo = fs.readFileSync("/proc/cpuinfo").toString();
|
||||||
|
if (cpuinfo.indexOf(": BCM") === 1) {
|
||||||
|
done(); // It's ON a PI ... should really do more tests !
|
||||||
|
} else {
|
||||||
|
checkIgnore(done);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
checkIgnore(done);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should load Output node', function(done) {
|
||||||
|
var flow = [{id:"n1", type:"rpi-gpio out", name:"rpi-gpio out" }];
|
||||||
|
helper.load(rpiNode, flow, function() {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
n1.should.have.property('name', 'rpi-gpio out');
|
||||||
|
try {
|
||||||
|
var cpuinfo = fs.readFileSync("/proc/cpuinfo").toString();
|
||||||
|
if (cpuinfo.indexOf(": BCM") === 1) {
|
||||||
|
done(); // It's ON a PI ... should really do more tests !
|
||||||
|
} else {
|
||||||
|
checkIgnore(done);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
checkIgnore(done);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
it('should read a dummy value high (not on Pi)', function(done) {
|
||||||
|
var flow = [{id:"n1", type:"rpi-gpio in", pin:"7", intype:"up", debounce:"25", read:true, wires:[["n2"]] },
|
||||||
|
{id:"n2", type:"helper"}];
|
||||||
|
helper.load(rpiNode, flow, function() {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
n2.on("input", function(msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property('topic', 'pi/7');
|
||||||
|
msg.should.have.property('payload', 1);
|
||||||
|
done();
|
||||||
|
} catch(err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should read a dummy value low (not on Pi)', function(done) {
|
||||||
|
var flow = [{id:"n1", type:"rpi-gpio in", pin:"11", intype:"down", debounce:"25", read:true, wires:[["n2"]] },
|
||||||
|
{id:"n2", type:"helper"}];
|
||||||
|
helper.load(rpiNode, flow, function() {
|
||||||
|
var n1 = helper.getNode("n1");
|
||||||
|
var n2 = helper.getNode("n2");
|
||||||
|
n2.on("input", function(msg) {
|
||||||
|
try {
|
||||||
|
msg.should.have.property('topic', 'pi/11');
|
||||||
|
msg.should.have.property('payload', 0);
|
||||||
|
done();
|
||||||
|
} catch(err) {
|
||||||
|
done(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// it('should be able preset out to a dummy value (not on Pi)', function(done) {
|
||||||
|
// var flow = [{id:"n1", type:"rpi-gpio out", pin:"7", out:"out", level:"0", set:true, freq:"", wires:[], z:"1"},
|
||||||
|
// {id:"n2", type:"status", scope:null, wires:[["n3"]], z:"1"},
|
||||||
|
// {id:"n3", type:"helper", z:"1"}];
|
||||||
|
// helper.load([rpiNode,statusNode], flow, function() {
|
||||||
|
// var n1 = helper.getNode("n1");
|
||||||
|
// var n2 = helper.getNode("n2");
|
||||||
|
// var n3 = helper.getNode("n3");
|
||||||
|
// var count = 0;
|
||||||
|
// n3.on("input", function(msg) {
|
||||||
|
// // Only check the first status message received as it may get a
|
||||||
|
// // 'closed' status as the test is tidied up.
|
||||||
|
// if (count === 0) {
|
||||||
|
// count++;
|
||||||
|
// try {
|
||||||
|
// msg.should.have.property('status');
|
||||||
|
// msg.status.should.have.property('text', "rpi-gpio.status.na");
|
||||||
|
// done();
|
||||||
|
// } catch(err) {
|
||||||
|
// done(err);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// n1.receive({payload:"1"});
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user