mirror of
https://github.com/node-red/node-red-nodes.git
synced 2023-10-10 13:36:58 +02:00
commit
7d541c38a7
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
npm-debug.log
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
Copyright 2013 IBM Corp.
|
||||
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.
|
||||
@ -28,16 +28,17 @@
|
||||
<!-- Generally, there should be an input for each property of the node. -->
|
||||
<!-- The for and id attributes identify the corresponding property -->
|
||||
<!-- (with the 'node-input-' prefix). -->
|
||||
<!-- The available icon classes are defined in Twitter Bootstrap -->
|
||||
<!-- The available icon classes are defined Twitter Bootstrap glyphicons -->
|
||||
<div class="form-row">
|
||||
<label for="node-input-topic"><i class="icon-tasks"></i> Topic</label>
|
||||
<label for="node-input-topic"><i class="fa fa-tasks"></i> Topic</label>
|
||||
<input type="text" id="node-input-topic" placeholder="Topic">
|
||||
</div>
|
||||
|
||||
<br/>
|
||||
<!-- By convention, most nodes have a 'name' property. The following div -->
|
||||
<!-- provides the necessary field. -->
|
||||
<!-- provides the necessary field. Should always be the last option -->
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
@ -64,10 +65,11 @@
|
||||
name: {value:""}, // along with default values.
|
||||
topic: {value:"", required:true}
|
||||
},
|
||||
inputs:0, // set the number of inputs - only 0 or 1
|
||||
outputs:1, // set the number of outputs - 0 to n
|
||||
icon: "arrow-in.png", // set the icon (held in public/icons)
|
||||
label: function() { // sets the default label contents
|
||||
inputs:1, // set the number of inputs - only 0 or 1
|
||||
outputs:1, // set the number of outputs - 0 to n
|
||||
// set the icon (held in icons dir below where you save the node)
|
||||
icon: "myicon.png", // saved in icons/myicon.png
|
||||
label: function() { // sets the default label contents
|
||||
return this.name||this.topic||"sample";
|
||||
},
|
||||
labelStyle: function() { // sets the class to apply to the label
|
||||
|
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2013 IBM Corp.
|
||||
* 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.
|
||||
@ -19,34 +19,45 @@
|
||||
// Sample Node-RED node file
|
||||
|
||||
// Require main module
|
||||
var RED = require(process.env.NODE_RED_HOME+"/red/red");
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
// require any external libraries we may need....
|
||||
//var foo = require("foo-library");
|
||||
|
||||
// The main node definition - most things happen in here
|
||||
function SampleNode(n) {
|
||||
// Create a RED node
|
||||
RED.nodes.createNode(this,n);
|
||||
// The main node definition - most things happen in here
|
||||
function SampleNode(n) {
|
||||
// Create a RED node
|
||||
RED.nodes.createNode(this,n);
|
||||
|
||||
// Store local copies of the node configuration (as defined in the .html)
|
||||
this.topic = n.topic;
|
||||
// Store local copies of the node configuration (as defined in the .html)
|
||||
this.topic = n.topic;
|
||||
|
||||
// Do whatever you need to do in here - declare callbacks etc
|
||||
// Note: this sample doesn't do anything much - it will only send
|
||||
// this message once at startup...
|
||||
// Look at other real nodes for some better ideas of what to do....
|
||||
var msg = {};
|
||||
msg.topic = this.topic;
|
||||
msg.payload = "Hello world !"
|
||||
// Do whatever you need to do in here - declare callbacks etc
|
||||
// Note: this sample doesn't do anything much - it will only send
|
||||
// this message once at startup...
|
||||
// Look at other real nodes for some better ideas of what to do....
|
||||
var msg = {};
|
||||
msg.topic = this.topic;
|
||||
msg.payload = "Hello world !"
|
||||
|
||||
// send out the message to the rest of the workspace.
|
||||
this.send(msg);
|
||||
// send out the message to the rest of the workspace.
|
||||
this.send(msg);
|
||||
|
||||
this.on("close", function() {
|
||||
// Called when the node is shutdown - eg on redeploy.
|
||||
// Allows ports to be closed, connections dropped etc.
|
||||
// eg: this.client.disconnect();
|
||||
});
|
||||
// respond to inputs....
|
||||
this.on('input', function (msg) {
|
||||
node.warn("I saw a payload: "+msg.payload);
|
||||
// in this example just send it straight on... should process it here really
|
||||
this.send(msg);
|
||||
}
|
||||
|
||||
this.on("close", function() {
|
||||
// Called when the node is shutdown - eg on redeploy.
|
||||
// Allows ports to be closed, connections dropped etc.
|
||||
// eg: this.client.disconnect();
|
||||
});
|
||||
}
|
||||
|
||||
// Register the node by name. This must be called before overriding any of the
|
||||
// Node functions.
|
||||
RED.nodes.registerType("sample",SampleNode);
|
||||
}
|
||||
|
||||
// Register the node by name. This must be called before overriding any of the
|
||||
// Node functions.
|
||||
RED.nodes.registerType("sample",SampleNode);
|
||||
|
131
README.md
131
README.md
@ -4,106 +4,135 @@ A collection of nodes for [Node-RED](http://nodered.org). See below for a list.
|
||||
|
||||
## Installation
|
||||
|
||||
Eventually, the nodes will be npm-installable, but we're not there yet. Until then:
|
||||
Most of these nodes are available as npm packages. See the list below for the npm package names, or [search npm](https://www.npmjs.org/search?q=node-red-node).
|
||||
|
||||
To install
|
||||
|
||||
cd node-red
|
||||
npm install node-red-node-{*filename*}
|
||||
|
||||
This repository acts as an overall store for these nodes - and is no longer intended as a way to install them - unless you really do want some bloat.
|
||||
|
||||
To manually install using this repo:
|
||||
|
||||
1. cd into the `nodes` directory of Node-RED
|
||||
2. Either:
|
||||
- download the zip of the repository and extract it
|
||||
- run `git clone https://github.com/node-red/node-red-nodes.git`
|
||||
3. npm install any of the individual node dependencies
|
||||
|
||||
This is all too manual, so the sooner we npm-enable this stuff the better
|
||||
3. npm install in any of the node subfolders to install individual node's dependencies
|
||||
|
||||
## Contributing
|
||||
|
||||
Please read the Contributing section of the main project [README](https://github.com/node-red/node-red/blob/master/README.md)
|
||||
Now that we support npm installaton of nodes we recommend people post their own via [npm](https://www.npmjs.org/). Please read the [packaging guide notes](http://nodered.org/docs/creating-nodes/packaging.html).
|
||||
|
||||
The key points are:
|
||||
- try to follow the conventions we use (all undocumented at the moment just to make it interesting)
|
||||
- focus on the UX of the node - make it simple to do simple things and simple to do advanced things. Don't
|
||||
force a user wanting to do simple things have to wade through the advanced things.
|
||||
- avoid duplication
|
||||
|
||||
### Contributor License Agreement
|
||||
|
||||
In order for us to accept pull-requests, the contributor must first complete
|
||||
a Contributor License Agreement (CLA). This clarifies the intellectual
|
||||
property license granted with any contribution. It is for your protection as a
|
||||
Contributor as well as the protection of IBM and its customers; it does not
|
||||
change your rights to use your own Contributions for any other purpose.
|
||||
|
||||
Once you have created a pull-request, we'll provide a link to the appropriate
|
||||
CLA document.
|
||||
|
||||
If you are an IBMer, please contact us directly as the contribution process is
|
||||
slightly different.
|
||||
If you are an IBMer, please contact us directly as the contribution process is slightly different.
|
||||
|
||||
|
||||
## Copyright and license
|
||||
|
||||
Copyright 2013 IBM Corp. under [the Apache 2.0 license](LICENSE).
|
||||
Copyright 2013,2014 IBM Corp. under [the Apache 2.0 license](LICENSE).
|
||||
|
||||
# Extra Node Information
|
||||
|
||||
NPM name - File-link - Description
|
||||
|
||||
### Analysis
|
||||
|
||||
**72-wordpos** - Analyses the payload and classifies the part-of-speech of each word. The resulting message has msg.pos added with the results. A word may appear in multiple categories (eg, 'great' is both a noun and an adjective).
|
||||
**node-red-node-wordpos** - *[72-wordpos](analysis/wordpos)* - Analyses the payload and classifies the part-of-speech of each word. The resulting message has msg.pos added with the results. A word may appear in multiple categories (eg, 'great' is both a noun and an adjective).
|
||||
|
||||
**74-swearfilter** - Analyses the payload and tries to filter out any messages containing bad swear words. This only operates on payloads of type string. Everything else is blocked.
|
||||
**node-red-node-wordpos** - *[74-swearfilter](analysis/swearfilter)* - Analyses the payload and tries to filter out any messages containing bad swear words. This only operates on payloads of type string. Everything else is blocked.
|
||||
|
||||
### Function
|
||||
|
||||
**node-red-node-smooth** - *[17-smooth](analysis/smooth)* - A simple node to provide various functions across several previous values, including max, min, mean, high and low pass filters.
|
||||
|
||||
### Hardware
|
||||
|
||||
**37-rpi-piface** - Adds support for the PiFace interface module for Raspberry Pi.
|
||||
**node-red-node-beaglebone** - *[145-BBB-hardware](hardware/BBB)* - A collection of analogue & digital input & output nodes for the [Beaglebone Black](http://beagleboard.org/black).
|
||||
|
||||
**78-ledborg** - A simple driver for the LEDborg plug on module for Raspberry Pi.
|
||||
**node-red-node-piface** - *[37-rpi-piface](hardware/PiFace)* - Adds support for the [PiFace](http://www.piface.org.uk/) interface module for Raspberry Pi.
|
||||
|
||||
**60-wemo** - Basic node to drive a WeMo socket and switch. Does not use discovery.
|
||||
**node-red-node-pibrella** - *[38-rpi-pibrella](hardware/Pibrella)* - Controls a [Pibrella](http://pibrella.com/) add-on board for a Raspberry-Pi.
|
||||
|
||||
**76-blinkstick** - Provides support for the BlinkStick USB LED device.
|
||||
**node-red-node-piliter** - *[39-rpi-piliter](hardware/PiLiter)* - Controls a Pimorini Pi-LITEr 8 LED add-on board for a Raspberry-Pi.
|
||||
|
||||
**77-blink1** - Provides support for the Blink1 USB LED from ThingM.
|
||||
**node-red-node-blinkstick** - *[76-blinkstick](hardware/blinkstick)* - Provides support for the [BlinkStick](http://www.blinkstick.com/) USB LED device.
|
||||
|
||||
**78-digiRGB** - Provides support for the DigiSpark RGB USB LED.
|
||||
**node-red-node-blink1** - *[77-blink1](hardware/blink1)* - Provides support for the [Blink1](http://blink1.thingm.com/) USB LED from ThingM.
|
||||
|
||||
**79-sensorTag** - Reads data from the Ti BLE SensorTag device.
|
||||
**node-red-node-ledborg** - *[78-ledborg](hardware/LEDborg)* - A simple driver for the [LEDborg](https://www.piborg.org/ledborg) plug on module for Raspberry Pi.
|
||||
|
||||
**101-scanBLE** - Scans for a particular Bluetooth Low Energy (BLE) device.
|
||||
**node-red-node-digirgb** - *[78-digiRGB](hardware/digiRGB)* - Provides support for the DigiSpark RGB USB LED.
|
||||
|
||||
**145-BBB-hardware** - A collection of analogue & digital input & output nodes for the Beaglebone Black
|
||||
**node-red-node-wemo** - *[60-wemo](hardware/wemo)* - Basic node to drive a [WeMo](http://www.belkin.com/us/Products/home-automation/c/wemo-home-automation/) socket and switch. Does not use discovery.
|
||||
|
||||
**N/A** - *[42-makey](hardware/makey)* - A Node-RED node to read from a [MakeyMakey](http://www.makeymakey.com/) input device.
|
||||
|
||||
**N/A** - *[79-sensorTag](hardware/sensorTag)* - Reads data from the Ti Bluetooh Low Energy (BLE) SensorTag device.
|
||||
|
||||
**N/A** - *[100-heatmiser-in](hardware/heatmiser)* - Writes settings for temperature and frost protection to Heatmiser thermostats.
|
||||
|
||||
**N/A** - *[101-heatmiser-out](hardware/heatmiser)* - Reads settings from Heatmiser thermostats at a polling interval.
|
||||
|
||||
**N/A** - *[101-scanBLE](hardware/scanBLE)* - Scans for a particular Bluetooth Low Energy (BLE) device.
|
||||
|
||||
**N/A** - *[103-hue_discover](hardware/hue)* - Looks for a Philips Hue Bridge in the local network.
|
||||
|
||||
**N/A** - *[104-hue_manage](hardware/hue)* - Implements some basic functionality for managing a Philips Hue wireless Lamp system.
|
||||
|
||||
### IO
|
||||
|
||||
**26-rawserial** - Only really needed for Windows boxes without serialport npm module installed.
|
||||
**node-red-node-stomp** - *[18-stomp](io/stomp)* - A Node-RED node to publish and subscribe to and from a [STOMP server](https://stomp.github.io/implementations.html#STOMP_Servers).
|
||||
|
||||
**node-red-node-wol** - *[39-wol](io/wol)* - Sends a Wake-On-LAN magic packet to the mac address specified. You may instead set msg.mac to dynamically set the target device mac to wake up.
|
||||
|
||||
**node-red-node-ping** - *[88-ping](io/ping)* - Pings a machine and returns the trip time in mS. Returns false if no response received within 3 seconds, or if the host is unresolveable. Default ping is every 20 seconds but can be configured.
|
||||
|
||||
**N/A** - *[88-emoncms](io/emoncms)* - Adds node to post to an [Emoncms](http://emoncms.org/) server.
|
||||
|
||||
**N/A** - *[26-rawserial](io/rawserial)* - Only really needed for Windows boxes without serialport npm module installed.
|
||||
Uses a simple read of the serial port as a file to input data. You **must** set the baud rate etc externally *before* starting Node-RED. This node does not implement pooling of connections so only one instance of each port may be used - so in **or** out but **not** both.
|
||||
|
||||
**39-wol** - Sends a Wake-On-LAN magic packet to the mac address specified. You may instead set msg.mac to dynamically set the target device mac to wake up.
|
||||
|
||||
**88-ping** - Pings a machine and returns the trip time in mS. Returns false if no response received within 3 seconds, or if the host is unresolveable. Default ping is every 20 seconds but can be configured.
|
||||
|
||||
### Social
|
||||
|
||||
**69-mpd** - MPD music control nodes. Output node expects payload to be a valid mpc command. Currently only simple commands that expect no reply are supported. Input node creates a payload object with Artist, Album, Title, Genre and Date.
|
||||
**node-red-node-twilio** - *[56-twilio](social/twilio)* - Uses [Twilio](https://www.twilio.com/) service to send/receive text messages.
|
||||
|
||||
**57-notify** - Uses Growl to provide a desktop popup containing the payload. Only useful on the local machine.
|
||||
**node-red-node-dweetio** - *[55-dweetio](social/dweetio)* - Uses [dweetio](https://dweet.io/) to send/receive messages.
|
||||
|
||||
**57-prowl** - Uses Prowl to push the payload to an Apple device that has the Prowl app installed.
|
||||
**node-red-node-nma** - *[57-nma](social/nma)* - Sends alerts to Android devices via the [Notify-My-Android](http://www.notifymyandroid.com/) app.
|
||||
|
||||
**57-pushbullet** - Uses PushBullet to push the payload to an Android device that has the PushBullet app installed.
|
||||
**node-red-node-notify** - *[57-notify](social/notify)* - Uses [Growl](http://growl.info/) to provide a desktop popup containing the payload. Only useful on the local Apple machine.
|
||||
|
||||
**92-xmpp** - Connects to an XMPP server to send and receive messages.
|
||||
**node-red-node-prowl** - *[57-prowl](social/prowl)* - Uses [Prowl](http://www.prowlapp.com/) to push the payload to an Apple device that has the Prowl app installed.
|
||||
|
||||
**node-red-node-pushbullet** - *[57-pushbullet](social/pushbullet)* - Uses [PushBullet](https://www.pushbullet.com/) to push the payload to an Android device that has the [PushBullet](https://www.pushbullet.com/) app installed.
|
||||
|
||||
**node-red-node-pushover** - *[57-pushover](social/pushover)* - Sends alerts via [Pushover](https://pushover.net/).
|
||||
|
||||
**node-red-node-xmpp** - *[92-xmpp](social/xmpp)* - Connects to an XMPP server to send and receive messages.
|
||||
|
||||
**N/A** - *[69-mpd](social/music)* - MPD music control nodes. Output node expects payload to be a valid mpc command. Currently only simple commands that expect no reply are supported. Input node creates a payload object with Artist, Album, Title, Genre and Date.
|
||||
|
||||
**N/A** - *[79-snapchat](social/snapchat)* - Downloads [SnapChat](https://www.snapchat.com/) images from the account specified.
|
||||
|
||||
**N/A** - *[114-pusher](social/pusher)* - Publish-Subscribe to a [Pusher](http://pusher.com/) channel/event.
|
||||
|
||||
### Storage
|
||||
|
||||
**67-leveldb** - Uses LevelDB for a simple key value pair database.
|
||||
**node-red-node-leveldb** - *[67-leveldb](storage/leveldb)* - Uses LevelDB for a simple key value pair database.
|
||||
|
||||
**68-mysql** - Allows basic access to a MySQL database. This node uses the **query** operation against the configured database. This does allow both INSERTS and DELETES. By it's very nature it allows SQL injection... *so be careful out there...*
|
||||
**node-red-node-mysql** - *[68-mysql](storage/mysql)* - Allows basic access to a MySQL database. This node uses the **query** operation against the configured database. This does allow both INSERTS and DELETES. By it's very nature it allows SQL injection... *so be careful out there...*
|
||||
|
||||
**69-ddbout** - Support output to Amazon DynamoDB.
|
||||
**node-red-node-sqlite** - *[sqlite](storage/sqlite)* - Supports read and write to a local sqlite database.
|
||||
|
||||
**node-red-node-ddb** - *[69-ddbout](https://github.com/wnagele/node-red-node-ddb)* - Support output to Amazon DynamoDB. This version deprecated - now moved to it's own npm. **Note:** you cannot have both version installed - if you do install from npm then please manually delete the version from your node-red-nodes/storage/ddb directory.
|
||||
|
||||
**N/A** - *[110-postgres](storage/postgres)* - PostgreSql I/O node.
|
||||
|
||||
### Time
|
||||
|
||||
**79-suncalc** - Uses the suncalc module to generate an output at sunrise and sunset based on a specified location. Several choices of definition of sunrise and sunset are available,
|
||||
**node-red-node-suncalc** - *[79-suncalc](time)* - Uses the suncalc module to generate an output at sunrise and sunset based on a specified location. Several choices of definition of sunrise and sunset are available,
|
||||
|
||||
### Misc
|
||||
|
||||
**99-sample** - A sample node with more comments than most to try to help you get started without any other docs...
|
||||
**N/A** - *[99-sample](./)* - A sample node with more comments than most to try to help you get started without any other docs...
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="badwords">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
|
@ -14,18 +14,20 @@
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var RED = require(process.env.NODE_RED_HOME+"/red/red");
|
||||
var badwords = require('badwords');
|
||||
if (badwords.length == 0 ) { return; }
|
||||
var badwordsRegExp = require('badwords/regexp');
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var badwords = require('badwords');
|
||||
if (badwords.length === 0 ) { return; }
|
||||
var badwordsRegExp = require('badwords/regexp');
|
||||
|
||||
function BadwordsNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
var node = this;
|
||||
this.on("input", function(msg) {
|
||||
if (typeof msg.payload === "string") {
|
||||
if ( !badwordsRegExp.test(msg.payload) ) { node.send(msg); }
|
||||
}
|
||||
});
|
||||
function BadwordsNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
var node = this;
|
||||
this.on("input", function(msg) {
|
||||
if (typeof msg.payload === "string") {
|
||||
if ( !badwordsRegExp.test(msg.payload) ) { node.send(msg); }
|
||||
}
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("badwords",BadwordsNode);
|
||||
}
|
||||
RED.nodes.registerType("badwords",BadwordsNode);
|
||||
|
177
analysis/swearfilter/LICENSE
Normal file
177
analysis/swearfilter/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
|
21
analysis/swearfilter/README.md
Normal file
21
analysis/swearfilter/README.md
Normal file
@ -0,0 +1,21 @@
|
||||
node-red-node-badwords
|
||||
======================
|
||||
|
||||
A <a href="http://nodered.org" target="_new">Node-RED</a> node that attempts to filter out messages containing swearwords.
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
Run the following command in the root directory of your Node-RED install
|
||||
|
||||
npm install node-red-node-badwords
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Uses the badwords npm to attempt to filter out messages containing swearwords.
|
||||
|
||||
Analyses the **msg.payload** and tries to filter out any messages containing bad swear words. If the payload contains a bad word then the whole message is blocked.
|
||||
|
||||
**Note** : this only operates on payloads of type <b>string</b>. Everything else is blocked.
|
24
analysis/swearfilter/package.json
Normal file
24
analysis/swearfilter/package.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name" : "node-red-node-badwords",
|
||||
"version" : "0.0.1",
|
||||
"description" : "A Node-RED node that attempts to filter out messages containing swearwords.",
|
||||
"dependencies" : {
|
||||
"badwords" : "0.0.1"
|
||||
},
|
||||
"repository" : {
|
||||
"type":"git",
|
||||
"url":"https://github.com/node-red/node-red-nodes/tree/master/analysis/swearfilter"
|
||||
},
|
||||
"license": "Apache",
|
||||
"keywords": [ "node-red", "badwords", "swearfilter" ],
|
||||
"node-red" : {
|
||||
"nodes" : {
|
||||
"badwords": "74-swearfilter.js"
|
||||
}
|
||||
},
|
||||
"author": {
|
||||
"name": "Dave Conway-Jones",
|
||||
"email": "ceejay@vnet.ibm.com",
|
||||
"url": "http://nodered.org"
|
||||
}
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="wordpos">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<div class="form-tips">Adds <b>msg.pos</b> as the anaylsis result.
|
||||
|
@ -14,18 +14,20 @@
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var RED = require(process.env.NODE_RED_HOME+"/red/red");
|
||||
var WordPos = require('wordpos');
|
||||
var wordpos = new WordPos();
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var WordPos = require('wordpos');
|
||||
var wordpos = new WordPos();
|
||||
|
||||
function WordPOSNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.on("input", function(msg) {
|
||||
var node = this;
|
||||
wordpos.getPOS(msg.payload, function (result) {
|
||||
msg.pos = result;
|
||||
node.send(msg);
|
||||
function WordPOSNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.on("input", function(msg) {
|
||||
var node = this;
|
||||
wordpos.getPOS(msg.payload, function (result) {
|
||||
msg.pos = result;
|
||||
node.send(msg);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("wordpos",WordPOSNode);
|
||||
}
|
||||
RED.nodes.registerType("wordpos",WordPOSNode);
|
||||
|
177
analysis/wordpos/LICENSE
Normal file
177
analysis/wordpos/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
|
27
analysis/wordpos/README.md
Normal file
27
analysis/wordpos/README.md
Normal file
@ -0,0 +1,27 @@
|
||||
node-red-node-wordpos
|
||||
=====================
|
||||
|
||||
A <a href="http://nodered.org" target="_new">Node-RED</a> node that breaks a sentance into the various parts of (English) speech.
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
Run the following command in the root directory of your Node-RED install
|
||||
|
||||
npm install node-red-node-wordpos
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Uses the wordpos npm to analyse the **msg.payload** and classify the part-of-speech of each word.
|
||||
|
||||
The resulting message has a **msg.pos** object added with the results split into the following:
|
||||
|
||||
nouns:[],
|
||||
verbs:[],
|
||||
adjectives:[],
|
||||
adverbs:[],
|
||||
rest:[]
|
||||
|
||||
**Note:** a word may appear in multiple POS (eg, 'great' is both a noun and an adjective).
|
24
analysis/wordpos/package.json
Normal file
24
analysis/wordpos/package.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name" : "node-red-node-wordpos",
|
||||
"version" : "0.0.1",
|
||||
"description" : "A Node-RED node that breaks a sentence into the various parts of (English) speech.",
|
||||
"dependencies" : {
|
||||
"wordpos" : "0.1.*"
|
||||
},
|
||||
"repository" : {
|
||||
"type":"git",
|
||||
"url":"https://github.com/node-red/node-red-nodes/tree/master/analysis/wordpos"
|
||||
},
|
||||
"license": "Apache",
|
||||
"keywords": [ "node-red", "wordpos" ],
|
||||
"node-red" : {
|
||||
"nodes" : {
|
||||
"wordpos": "72-wordpos.js"
|
||||
}
|
||||
},
|
||||
"author": {
|
||||
"name": "Dave Conway-Jones",
|
||||
"email": "ceejay@vnet.ibm.com",
|
||||
"url": "http://nodered.org"
|
||||
}
|
||||
}
|
177
function/random/LICENSE
Normal file
177
function/random/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
|
23
function/random/README.md
Normal file
23
function/random/README.md
Normal file
@ -0,0 +1,23 @@
|
||||
node-red-node-random
|
||||
====================
|
||||
|
||||
A <a href="http://nodered.org" target="_new">Node-RED</a> node that when triggered generates a random number between two values.
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
Run the following command in the root directory of your Node-RED install
|
||||
|
||||
npm install node-red-node-random
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
A simple node to generate a random number when triggered.
|
||||
|
||||
If integer mode is selected (default) it will return an integer **between and including** the two values given - so selecting 1 to 6 will return values 1,2,3,4,5 or 6.
|
||||
|
||||
If floating point mode is selected then it will return a number **between** the two values given - so selecting 1 to 6 will return values 1 < x < 6 .
|
||||
|
||||
**Note:** This generates **numbers**.
|
23
function/random/package.json
Normal file
23
function/random/package.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"name" : "node-red-node-random",
|
||||
"version" : "0.0.1",
|
||||
"description" : "A Node-RED node that that when triggered generates a random number between two values.",
|
||||
"dependencies" : {
|
||||
},
|
||||
"repository" : {
|
||||
"type":"git",
|
||||
"url":"https://github.com/node-red/node-red-nodes/tree/master/function/random"
|
||||
},
|
||||
"license": "Apache",
|
||||
"keywords": [ "node-red", "random" ],
|
||||
"node-red" : {
|
||||
"nodes" : {
|
||||
"random": "random.js"
|
||||
}
|
||||
},
|
||||
"author": {
|
||||
"name": "Dave Conway-Jones",
|
||||
"email": "ceejay@vnet.ibm.com",
|
||||
"url": "http://nodered.org"
|
||||
}
|
||||
}
|
66
function/random/random.html
Normal file
66
function/random/random.html
Normal file
@ -0,0 +1,66 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-template-name="random">
|
||||
<div class="form-row">
|
||||
<label for="node-input-inte"><i class="fa fa-random"></i> Generate</label>
|
||||
<select type="text" id="node-input-inte" style="width: 300px;">
|
||||
<option value="true">a whole number - integer</option>
|
||||
<option value="false">a real number - floating point</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-low"><i class="fa fa-arrow-down"></i> From</label>
|
||||
<input type="text" id="node-input-low" placeholder="lowest number" style="width: 300px;">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-high"><i class="fa fa-arrow-up"></i> To</label>
|
||||
<input type="text" id="node-input-high" placeholder="highest number" style="width: 300px;">
|
||||
</div>
|
||||
<br/>
|
||||
<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" style="width: 300px;">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="random">
|
||||
<p>Generates a random number between a low and high value.</p>
|
||||
<p>If you return an integer it can <i>include</i> both the low and high values.</p>
|
||||
<p>If you return a floating point value it will be <i>between</i> the low and high values.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('random',{
|
||||
category: 'function',
|
||||
color:"#E2D96E",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
low: {value:"1"},
|
||||
high: {value:"6"},
|
||||
inte: {value:"true"}
|
||||
},
|
||||
inputs:1,
|
||||
outputs:1,
|
||||
icon: "debug.png",
|
||||
label: function() {
|
||||
return this.name||"random";
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
35
function/random/random.js
Normal file
35
function/random/random.js
Normal file
@ -0,0 +1,35 @@
|
||||
/**
|
||||
* 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.
|
||||
**/
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
function RandomNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.low = Number(n.low);
|
||||
this.high = Number(n.high);
|
||||
this.inte = n.inte;
|
||||
var node = this;
|
||||
this.on("input", function(msg) {
|
||||
if (node.inte === "true") {
|
||||
msg.payload = Math.round(Number(Math.random()) * (node.high - node.low + 1) + node.low - 0.5);
|
||||
} else {
|
||||
msg.payload = Number(Math.random()) * (node.high - node.low) + node.low;
|
||||
}
|
||||
node.send(msg);
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("random",RandomNode);
|
||||
}
|
91
function/smooth/17-smooth.html
Normal file
91
function/smooth/17-smooth.html
Normal file
@ -0,0 +1,91 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-template-name="smooth">
|
||||
<div class="form-row">
|
||||
<label for="node-input-action"><i class="fa fa-bolt"></i> Action</label>
|
||||
<select id="node-input-action" style="width:60%; margin-right:5px;">
|
||||
<option value="max">Return the maximum value seen</option>
|
||||
<option value="min">Return the minimum value seen</option>
|
||||
<option value="mean">Return the mean value seen</option>
|
||||
<option value="low">Perform low pass filter</option>
|
||||
<option value="high">Perform high pass filter</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-count"> </label>
|
||||
<span id="node-over">over the most recent </span>
|
||||
<input type="text" id="node-input-count" placeholder="10" style="width:80px;"/>
|
||||
<span id="node-over2"> values.</span>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-round"> </label>
|
||||
<input type="checkbox" id="node-input-round" style="display: inline-block; width: auto; vertical-align: top;"> Round to the nearest integer ?
|
||||
</div>
|
||||
<br/>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<div class="form-tips" id="node-tip">Tip: This node ONLY works with numbers.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="smooth">
|
||||
<p>A simple node to provide various functions across several previous values, including max, min, mean, high and low pass filters.</p>
|
||||
<p>Max, Min and Mean work over a specified number of previous values.</p>
|
||||
<p>The High and Low pass filters use a smoothing factor. The higher the number the more the smoothing. E.g. a value of 10 is similar to an α of 0.1. It is analagous to an RC time constant - but there is no time component to this as the time is based on events arriving.</p>
|
||||
<p><b>Note:</b> This only operates on <b>numbers</b>. Anything else will try to be made into a number and rejected if that fails.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('smooth', {
|
||||
color: "#E2D96E",
|
||||
category: 'function',
|
||||
defaults: {
|
||||
count: {value:"10",required:true,validate:RED.validators.number()},
|
||||
action: {value:"mean"},
|
||||
round: {value:false},
|
||||
name: {value:""}
|
||||
},
|
||||
inputs: 1,
|
||||
outputs: 1,
|
||||
icon: "smooth.png",
|
||||
label: function() {
|
||||
return this.name || "smooth";
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name ? "node_label_italic" : "";
|
||||
},
|
||||
oneditprepare: function() {
|
||||
$("#node-input-count").spinner({
|
||||
min:1,
|
||||
width:80
|
||||
});
|
||||
$("#node-input-action").change( function() {
|
||||
var a = $("#node-input-action").val();
|
||||
if ((a === "high") || ( a === "low" )) {
|
||||
$("#node-over").html("with a smoothing factor of ");
|
||||
$("#node-over2").html("");
|
||||
}
|
||||
else {
|
||||
$("#node-over").html("over the most recent ");
|
||||
$("#node-over2").html(" values.");
|
||||
}
|
||||
});
|
||||
$("#node-input-action").change();
|
||||
}
|
||||
});
|
||||
</script>
|
59
function/smooth/17-smooth.js
Normal file
59
function/smooth/17-smooth.js
Normal file
@ -0,0 +1,59 @@
|
||||
/**
|
||||
* 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.
|
||||
**/
|
||||
|
||||
var RED = require(process.env.NODE_RED_HOME + "/red/red");
|
||||
|
||||
function SmoothNode(n) {
|
||||
RED.nodes.createNode(this, n);
|
||||
this.action = n.action;
|
||||
this.round = n.round || false;
|
||||
this.count = Number(n.count);
|
||||
var node = this;
|
||||
var a = [];
|
||||
var tot = 0;
|
||||
var pop = 0;
|
||||
var old = null;
|
||||
|
||||
this.on('input', function (msg) {
|
||||
var n = Number(msg.payload);
|
||||
if (!isNaN(n)) {
|
||||
if ((node.action === "low") || (node.action === "high")) {
|
||||
if (old == null) { old = n; }
|
||||
old = old + (n - old) / node.count;
|
||||
if (node.action === "low") { msg.payload = old; }
|
||||
else { msg.payload = n - old; }
|
||||
}
|
||||
else {
|
||||
a.push(n);
|
||||
if (a.length > node.count) { pop = a.shift(); }
|
||||
if (node.action === "max") {
|
||||
msg.payload = Math.max.apply(Math, a);
|
||||
}
|
||||
if (node.action === "min") {
|
||||
msg.payload = Math.min.apply(Math, a);
|
||||
}
|
||||
if (node.action === "mean") {
|
||||
tot = tot + n - pop;
|
||||
msg.payload = tot / a.length;
|
||||
}
|
||||
}
|
||||
if (node.round) { msg.payload = Math.round(msg.payload); }
|
||||
node.send(msg);
|
||||
}
|
||||
else { node.log("Not a number: "+msg.payload); }
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("smooth", SmoothNode);
|
177
function/smooth/LICENSE
Normal file
177
function/smooth/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
|
24
function/smooth/README.md
Normal file
24
function/smooth/README.md
Normal file
@ -0,0 +1,24 @@
|
||||
node-red-node-smooth
|
||||
====================
|
||||
|
||||
A <a href="http://nodered.org" target="_new">Node-RED</a> node that provides several simple smoothing algorithms for incoming data values.
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
Run the following command in the root directory of your Node-RED install
|
||||
|
||||
npm install node-red-node-smooth
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
A simple node to provide various functions across several previous values, including max, min, mean, high and low pass filters.
|
||||
|
||||
Max, Min and Mean work over a specified number of previous values.
|
||||
|
||||
The High and Low pass filters use a smoothing factor. The higher the number the more the smoothing. E.g. a value of 10 is similar to an α of 0.1. It is analogous to an RC time constant - but there is no time component to this as the code is based on events arriving.
|
||||
|
||||
|
||||
**Note:** This only operates on **numbers**. Anything else will try to be made into a number and rejected if that fails.
|
BIN
function/smooth/icons/smooth.png
Normal file
BIN
function/smooth/icons/smooth.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 725 B |
23
function/smooth/package.json
Normal file
23
function/smooth/package.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"name" : "node-red-node-smooth",
|
||||
"version" : "0.0.2",
|
||||
"description" : "A Node-RED node that provides several simple smoothing algorithms for incoming data values.",
|
||||
"dependencies" : {
|
||||
},
|
||||
"repository" : {
|
||||
"type":"git",
|
||||
"url":"https://github.com/node-red/node-red-nodes/tree/master/analysis/smooth"
|
||||
},
|
||||
"license": "Apache",
|
||||
"keywords": [ "node-red", "smooth", "average" ],
|
||||
"node-red" : {
|
||||
"nodes" : {
|
||||
"smooth": "17-smooth.js"
|
||||
}
|
||||
},
|
||||
"author": {
|
||||
"name": "Dave Conway-Jones",
|
||||
"email": "ceejay@vnet.ibm.com",
|
||||
"url": "http://nodered.org"
|
||||
}
|
||||
}
|
@ -17,7 +17,7 @@
|
||||
<!-- Edit dialog for bbb-analogue-in -->
|
||||
<script type="text/x-red" data-template-name="bbb-analogue-in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-pin"><i class="icon-asterisk"></i>Input pin</label>
|
||||
<label for="node-input-pin"><i class="fa fa-asterisk"></i>Input pin</label>
|
||||
<select type="text" id="node-input-pin" style="width: 150px;">
|
||||
<option value="">select pin</option>
|
||||
<option value="P9_39">AIN0 (P9 pin 39)</option>
|
||||
@ -30,7 +30,7 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-topic"><i class="icon-tasks"></i> Topic</label>
|
||||
<label for="node-input-topic"><i class="fa fa-tasks"></i> Topic</label>
|
||||
<input type="text" id="node-input-topic" placeholder="Topic">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
@ -43,13 +43,13 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<a href="#" class="btn btn-mini" id="node-input-add-breakpoint" style="margin-top: 4px;"><i class="icon-plus"></i> Add Breakpoint</a>
|
||||
<a href="#" class="btn btn-mini" id="node-input-add-breakpoint" style="margin-top: 4px;"><i class="fa fa-plus"></i> Add Breakpoint</a>
|
||||
<span style="float:right; margin-top:4px">
|
||||
<input type="checkbox" id="node-input-averaging" style="display:inline-block; width:auto; vertical-align:top;"> Averaging
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
@ -78,7 +78,7 @@ voltage ten times in rapid succession for each input message and output the mean
|
||||
<!-- Register bbb-analogue-in node -->
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('bbb-analogue-in', {
|
||||
category: 'advanced-input', // the palette category
|
||||
category: 'Beaglebone', // the palette category
|
||||
color:"#de7224",
|
||||
defaults: { // defines the editable properties of the node
|
||||
pin: { value:"", required:true },
|
||||
@ -124,11 +124,11 @@ voltage ten times in rapid succession for each input message and output the mean
|
||||
});
|
||||
} else {
|
||||
mutableFlag.attr("mutable", "false");
|
||||
}
|
||||
}
|
||||
if (insert === true) {
|
||||
var last = $("#node-input-breakpoint-container").children().last();
|
||||
var prev = last.prev();
|
||||
inputValueField.val((Number(last.find(".node-input-breakpoint-input-value").val()) +
|
||||
inputValueField.val((Number(last.find(".node-input-breakpoint-input-value").val()) +
|
||||
Number(prev.find(".node-input-breakpoint-input-value").val()))/2);
|
||||
outputValueField.val((Number(last.find(".node-input-breakpoint-output-value").val()) +
|
||||
Number(prev.find(".node-input-breakpoint-output-value").val()))/2);
|
||||
@ -139,17 +139,17 @@ voltage ten times in rapid succession for each input message and output the mean
|
||||
$("#node-input-breakpoint-container").append(container);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$("#node-input-add-breakpoint").click(function () {
|
||||
generateBreakpoint({input:0, output:0, mutable:true}, true);
|
||||
$("#node-input-breakpoint-container-div").scrollTop($("#node-input-breakpoint-container-div").get(0).scrollHeight);
|
||||
});
|
||||
|
||||
|
||||
for (var i = 0; i < this.breakpoints.length; i++) {
|
||||
var breakpoint = this.breakpoints[i];
|
||||
generateBreakpoint(breakpoint, false);
|
||||
}
|
||||
|
||||
|
||||
// Handle resizing the Input Scaling div when the dialog is resized - this isn't quite right!
|
||||
function switchDialogResize(ev, ui) {
|
||||
$("#node-input-breakpoint-container-div").css("height", (ui.size.height - 299) + "px");
|
||||
@ -186,7 +186,7 @@ voltage ten times in rapid succession for each input message and output the mean
|
||||
<!-- Edit dialog for bbb-discrete-in -->
|
||||
<script type="text/x-red" data-template-name="bbb-discrete-in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-pin"><i class="icon-asterisk"></i>Input pin</label>
|
||||
<label for="node-input-pin"><i class="fa fa-asterisk"></i>Input pin</label>
|
||||
<select type="text" id="node-input-pin" style="width: 200px;">
|
||||
<option value="">select pin</option>
|
||||
<option value="P8_7">GPIO2_2 (P8 pin 7)</option>
|
||||
@ -239,16 +239,16 @@ voltage ten times in rapid succession for each input message and output the mean
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-updateInterval"><i class="icon-repeat"></i> Update at</label>
|
||||
<label for="node-input-updateInterval"><i class="fa fa-repeat"></i> Update at</label>
|
||||
<input id="node-input-updateInterval" type="text" style="width: 65px">
|
||||
<label>sec intervals</label>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-topic"><i class="icon-tasks"></i> Topic</label>
|
||||
<label for="node-input-topic"><i class="fa fa-tasks"></i> Topic</label>
|
||||
<input type="text" id="node-input-topic" placeholder="Topic">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
@ -279,7 +279,7 @@ press. When using buttons or switches, enable debouncing to improve reliability.
|
||||
<!-- Register bbb-discrete-in node -->
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('bbb-discrete-in', {
|
||||
category: 'advanced-input', // the palette category
|
||||
category: 'Beaglebone', // the palette category
|
||||
color:"#de7224",
|
||||
defaults: { // defines the editable properties of the node
|
||||
pin: { value:"", required:true },
|
||||
@ -305,7 +305,7 @@ press. When using buttons or switches, enable debouncing to improve reliability.
|
||||
<!-- Edit dialog for bbb-pulse-in -->
|
||||
<script type="text/x-red" data-template-name="bbb-pulse-in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-pin"><i class="icon-asterisk"></i>Input pin</label>
|
||||
<label for="node-input-pin"><i class="fa fa-asterisk"></i>Input pin</label>
|
||||
<select type="text" id="node-input-pin" style="width: 200px;">
|
||||
<option value="">select pin</option>
|
||||
<option value="P8_7">GPIO2_2 (P8 pin 7)</option>
|
||||
@ -359,16 +359,16 @@ press. When using buttons or switches, enable debouncing to improve reliability.
|
||||
<label style="width: 60%"> units per count/second</label>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-updateInterval"><i class="icon-repeat"></i> Update at</label>
|
||||
<label for="node-input-updateInterval"><i class="fa fa-repeat"></i> Update at</label>
|
||||
<input id="node-input-updateInterval" type="text" style="width: 65px">
|
||||
<label>sec intervals</label>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-topic"><i class="icon-tasks"></i> Topic</label>
|
||||
<label for="node-input-topic"><i class="fa fa-tasks"></i> Topic</label>
|
||||
<input type="text" id="node-input-topic" placeholder="Topic">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
@ -390,7 +390,7 @@ any other input message will reset it to zero.
|
||||
<!-- Register bbb-pulse-in node -->
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('bbb-pulse-in', {
|
||||
category: 'advanced-input', // the palette category
|
||||
category: 'Beaglebone', // the palette category
|
||||
color:"#de7224",
|
||||
defaults: { // defines the editable properties of the node
|
||||
pin: { value:"", required:true },
|
||||
@ -416,7 +416,7 @@ any other input message will reset it to zero.
|
||||
<!-- Edit dialog for bbb-discrete-out -->
|
||||
<script type="text/x-red" data-template-name="bbb-discrete-out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-pin"><i class="icon-asterisk"></i>Output pin</label>
|
||||
<label for="node-input-pin"><i class="fa fa-asterisk"></i>Output pin</label>
|
||||
<select type="text" id="node-input-pin" style="width: 200px;">
|
||||
<option value="">select pin</option>
|
||||
<option value="P8_7">GPIO2_2 (P8 pin 7)</option>
|
||||
@ -472,7 +472,7 @@ any other input message will reset it to zero.
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
@ -501,7 +501,7 @@ the Inverting property is not applied to this value.
|
||||
<!-- Register bbb-discrete-out node -->
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('bbb-discrete-out', {
|
||||
category: 'advanced-input', // the palette category
|
||||
category: 'Beaglebone', // the palette category
|
||||
color:"#de7224",
|
||||
defaults: { // defines the editable properties of the node
|
||||
pin: { value:"", required:true },
|
||||
@ -526,7 +526,7 @@ the Inverting property is not applied to this value.
|
||||
<!-- Edit dialog for bbb-pulse-out -->
|
||||
<script type="text/x-red" data-template-name="bbb-pulse-out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-pin"><i class="icon-asterisk"></i>Output pin</label>
|
||||
<label for="node-input-pin"><i class="fa fa-asterisk"></i>Output pin</label>
|
||||
<select type="text" id="node-input-pin" style="width: 200px;">
|
||||
<option value="">select pin</option>
|
||||
<option value="P8_7">GPIO2_2 (P8 pin 7)</option>
|
||||
@ -567,7 +567,7 @@ the Inverting property is not applied to this value.
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-pulseTime"><i class="icon-repeat"></i> Pulse time</label>
|
||||
<label for="node-input-pulseTime"><i class="fa fa-repeat"></i> Pulse time</label>
|
||||
<input id="node-input-pulseTime" type="text" style="width: 65px">
|
||||
<label> seconds</label>
|
||||
</div>
|
||||
@ -583,7 +583,7 @@ the Inverting property is not applied to this value.
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
@ -614,7 +614,7 @@ the pin changes state: its payload is the new state (0 or 1).
|
||||
<!-- Register bbb-pulse-out node -->
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('bbb-pulse-out', {
|
||||
category: 'advanced-input', // the palette category
|
||||
category: 'Beaglebone', // the palette category
|
||||
color:"#de7224",
|
||||
defaults: { // defines the editable properties of the node
|
||||
pin: { value:"", required:true },
|
||||
@ -635,4 +635,3 @@ the pin changes state: its payload is the new state (0 or 1).
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
@ -14,489 +14,492 @@
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
// Require main module
|
||||
var RED = require(process.env.NODE_RED_HOME + "/red/red");
|
||||
var bonescript = require("bonescript");
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var bonescript = require("bonescript");
|
||||
|
||||
// Node constructor for bbb-analogue-in
|
||||
function AnalogueInputNode(n) {
|
||||
// Create a RED node
|
||||
RED.nodes.createNode(this, n);
|
||||
// Node constructor for bbb-analogue-in
|
||||
function AnalogueInputNode(n) {
|
||||
// Create a RED node
|
||||
RED.nodes.createNode(this, n);
|
||||
|
||||
// Store local copies of the node configuration (as defined in the .html)
|
||||
this.topic = n.topic;
|
||||
this.pin = n.pin;
|
||||
this.breakpoints = n.breakpoints;
|
||||
this.averaging = n.averaging;
|
||||
if (this.averaging) {
|
||||
this.averages = 10;
|
||||
} else {
|
||||
this.averages = 1;
|
||||
}
|
||||
// Store local copies of the node configuration (as defined in the .html)
|
||||
this.topic = n.topic;
|
||||
this.pin = n.pin;
|
||||
this.breakpoints = n.breakpoints;
|
||||
this.averaging = n.averaging;
|
||||
if (this.averaging) {
|
||||
this.averages = 10;
|
||||
} else {
|
||||
this.averages = 1;
|
||||
}
|
||||
|
||||
// Define 'node' to allow us to access 'this' from within callbacks
|
||||
var node = this;
|
||||
// Define 'node' to allow us to access 'this' from within callbacks
|
||||
var node = this;
|
||||
|
||||
// Variables used for input averaging
|
||||
var sum; // accumulates the input readings to be averaged
|
||||
var count; // keep track of the number of measurements made
|
||||
// Variables used for input averaging
|
||||
var sum; // accumulates the input readings to be averaged
|
||||
var count; // keep track of the number of measurements made
|
||||
|
||||
// The callback function for analogRead. Accumulates the required number of
|
||||
// measurements, then divides the total number, applies output scaling and
|
||||
// sends the result
|
||||
var analogReadCallback = function (x) {
|
||||
sum = sum + x.value;
|
||||
count = count - 1;
|
||||
if (count > 0) {
|
||||
bonescript.analogRead(node.pin, analogReadCallback);
|
||||
} else {
|
||||
var msg = {};
|
||||
msg.topic = node.topic;
|
||||
sum = sum/node.averages;
|
||||
// i is the index of the first breakpoint where the 'input' value is strictly
|
||||
// greater than the measurement (note: a measurement can never be == 1)
|
||||
var i = node.breakpoints.map(function (breakpoint) { return sum >= breakpoint.input; }).indexOf(false);
|
||||
msg.payload = node.breakpoints[i-1].output + (node.breakpoints[i].output - node.breakpoints[i-1].output) *
|
||||
(sum - node.breakpoints[i-1].input)/(node.breakpoints[i].input - node.breakpoints[i-1].input);
|
||||
node.send(msg);
|
||||
}
|
||||
};
|
||||
|
||||
// If we have a valid pin, set the input event handler to Bonescript's analogRead
|
||||
if (["P9_39", "P9_40", "P9_37", "P9_38", "P9_33", "P9_36", "P9_35"].indexOf(node.pin) >= 0) {
|
||||
node.on("input", function (msg) {
|
||||
sum = 0;
|
||||
count = node.averages;
|
||||
bonescript.analogRead(node.pin, analogReadCallback);
|
||||
});
|
||||
} else {
|
||||
node.error("Unconfigured input pin");
|
||||
}
|
||||
}
|
||||
|
||||
// Node constructor for bbb-discrete-in
|
||||
function DiscreteInputNode(n) {
|
||||
RED.nodes.createNode(this, n);
|
||||
|
||||
// Store local copies of the node configuration (as defined in the .html)
|
||||
this.topic = n.topic; // the topic is not currently used
|
||||
this.pin = n.pin; // The Beaglebone Black pin identifying string
|
||||
if (n.activeLow) // Set the 'active' state 0 or 1 as appropriate
|
||||
this.activeState = 0;
|
||||
else
|
||||
this.activeState = 1;
|
||||
this.updateInterval = n.updateInterval * 1000; // How often to send totalActiveTime messages
|
||||
this.debounce = n.debounce; // Enable switch contact debouncing algorithm
|
||||
if (n.outputOn === "rising") {
|
||||
this.activeEdges = [false, true];
|
||||
} else if (n.outputOn === "falling") {
|
||||
this.activeEdges = [true, false];
|
||||
} else if (n.outputOn === "both") {
|
||||
this.activeEdges = [true, true];
|
||||
} else {
|
||||
node.error("Invalid edge type: " + n.outputOn);
|
||||
}
|
||||
|
||||
// Working variables
|
||||
this.interruptAttached = false; // Flag: should we detach interrupt when we are closed?
|
||||
this.intervalId = null; // Remember the timer ID so we can delete it when we are closed
|
||||
this.currentState = 0; // The pin input state "1" or "0"
|
||||
this.lastActiveTime = NaN; // The date (in ms since epoch) when the pin last went high
|
||||
// switch to process.hrtime()
|
||||
this.totalActiveTime = 0; // The total time in ms that the pin has been high (since reset)
|
||||
this.starting = true;
|
||||
this.debouncing = false; // True after a change of state while waiting for the 7ms debounce time to elapse
|
||||
this.debounceTimer = null;
|
||||
|
||||
// Define 'node' to allow us to access 'this' from within callbacks
|
||||
var node = this;
|
||||
|
||||
// This function is called by the input pin change-of-state interrupt. If
|
||||
// debounce is disabled, send the output message. Otherwise, if we are
|
||||
// currently debouncing, ignore this interrupt. If we are not debouncing,
|
||||
// schedule a re-read of the input pin in 7ms time, and set the debouncing flag
|
||||
// Note: this function gets called spuriously when the interrupt is first enabled:
|
||||
// in this case x.value is undefined - we must test for this
|
||||
var interruptCallback = function (x) {
|
||||
if (x.value !== undefined && node.currentState !== Number(x.value)) {
|
||||
if (node.debounce) {
|
||||
if (node.debouncing === false) {
|
||||
node.debouncing = true;
|
||||
node.debounceTimer = setTimeout(function () { bonescript.digitalRead(node.pin, debounceCallback); }, 7);
|
||||
}
|
||||
// The callback function for analogRead. Accumulates the required number of
|
||||
// measurements, then divides the total number, applies output scaling and
|
||||
// sends the result
|
||||
var analogReadCallback = function (x) {
|
||||
sum = sum + x.value;
|
||||
count = count - 1;
|
||||
if (count > 0) {
|
||||
bonescript.analogRead(node.pin, analogReadCallback);
|
||||
} else {
|
||||
var msg = {};
|
||||
msg.topic = node.topic;
|
||||
sum = sum/node.averages;
|
||||
// i is the index of the first breakpoint where the 'input' value is strictly
|
||||
// greater than the measurement (note: a measurement can never be == 1)
|
||||
var i = node.breakpoints.map(function (breakpoint) { return sum >= breakpoint.input; }).indexOf(false);
|
||||
msg.payload = node.breakpoints[i-1].output + (node.breakpoints[i].output - node.breakpoints[i-1].output) *
|
||||
(sum - node.breakpoints[i-1].input)/(node.breakpoints[i].input - node.breakpoints[i-1].input);
|
||||
node.send(msg);
|
||||
}
|
||||
};
|
||||
|
||||
// If we have a valid pin, set the input event handler to Bonescript's analogRead
|
||||
if (["P9_39", "P9_40", "P9_37", "P9_38", "P9_33", "P9_36", "P9_35"].indexOf(node.pin) >= 0) {
|
||||
node.on("input", function (msg) {
|
||||
sum = 0;
|
||||
count = node.averages;
|
||||
bonescript.analogRead(node.pin, analogReadCallback);
|
||||
});
|
||||
} else {
|
||||
node.error("Unconfigured input pin");
|
||||
}
|
||||
}
|
||||
|
||||
// Node constructor for bbb-discrete-in
|
||||
function DiscreteInputNode(n) {
|
||||
RED.nodes.createNode(this, n);
|
||||
|
||||
// Store local copies of the node configuration (as defined in the .html)
|
||||
this.topic = n.topic; // the topic is not currently used
|
||||
this.pin = n.pin; // The Beaglebone Black pin identifying string
|
||||
if (n.activeLow) { // Set the 'active' state 0 or 1 as appropriate
|
||||
this.activeState = 0;
|
||||
}
|
||||
else {
|
||||
this.activeState = 1;
|
||||
}
|
||||
this.updateInterval = n.updateInterval * 1000; // How often to send totalActiveTime messages
|
||||
this.debounce = n.debounce; // Enable switch contact debouncing algorithm
|
||||
if (n.outputOn === "rising") {
|
||||
this.activeEdges = [false, true];
|
||||
} else if (n.outputOn === "falling") {
|
||||
this.activeEdges = [true, false];
|
||||
} else if (n.outputOn === "both") {
|
||||
this.activeEdges = [true, true];
|
||||
} else {
|
||||
node.error("Invalid edge type: " + n.outputOn);
|
||||
}
|
||||
|
||||
// Working variables
|
||||
this.interruptAttached = false; // Flag: should we detach interrupt when we are closed?
|
||||
this.intervalId = null; // Remember the timer ID so we can delete it when we are closed
|
||||
this.currentState = 0; // The pin input state "1" or "0"
|
||||
this.lastActiveTime = NaN; // The date (in ms since epoch) when the pin last went high
|
||||
// switch to process.hrtime()
|
||||
this.totalActiveTime = 0; // The total time in ms that the pin has been high (since reset)
|
||||
this.starting = true;
|
||||
this.debouncing = false; // True after a change of state while waiting for the 7ms debounce time to elapse
|
||||
this.debounceTimer = null;
|
||||
|
||||
// Define 'node' to allow us to access 'this' from within callbacks
|
||||
var node = this;
|
||||
|
||||
// This function is called by the input pin change-of-state interrupt. If
|
||||
// debounce is disabled, send the output message. Otherwise, if we are
|
||||
// currently debouncing, ignore this interrupt. If we are not debouncing,
|
||||
// schedule a re-read of the input pin in 7ms time, and set the debouncing flag
|
||||
// Note: this function gets called spuriously when the interrupt is first enabled:
|
||||
// in this case x.value is undefined - we must test for this
|
||||
var interruptCallback = function (x) {
|
||||
if (x.value !== undefined && node.currentState !== Number(x.value)) {
|
||||
if (node.debounce) {
|
||||
if (node.debouncing === false) {
|
||||
node.debouncing = true;
|
||||
node.debounceTimer = setTimeout(function () { bonescript.digitalRead(node.pin, debounceCallback); }, 7);
|
||||
}
|
||||
} else {
|
||||
sendStateMessage(x);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// This function is called approx 7ms after a potential change-of-state which is
|
||||
// being debounced. Terminate the debounce, and send a message if the state has
|
||||
// actually changed
|
||||
var debounceCallback = function (x) {
|
||||
node.debounceTimer = null;
|
||||
node.debouncing = false;
|
||||
if (x.value !== undefined && node.currentState !== Number(x.value)) {
|
||||
sendStateMessage(x);
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// This function is called approx 7ms after a potential change-of-state which is
|
||||
// being debounced. Terminate the debounce, and send a message if the state has
|
||||
// actually changed
|
||||
var debounceCallback = function (x) {
|
||||
node.debounceTimer = null;
|
||||
node.debouncing = false;
|
||||
if (x.value !== undefined && node.currentState !== Number(x.value)) {
|
||||
sendStateMessage(x);
|
||||
}
|
||||
};
|
||||
// This function is called when either the interruptCallback or the debounceCallback
|
||||
// have determined we have a 'genuine' change of state. Update the currentState and
|
||||
// ActiveTime variables, and send a message on the first output with the new state
|
||||
var sendStateMessage = function (x) {
|
||||
node.currentState = Number(x.value);
|
||||
var now = Date.now();
|
||||
if (node.currentState === node.activeState) {
|
||||
node.lastActiveTime = now;
|
||||
} else if (!isNaN(node.lastActiveTime)) {
|
||||
node.totalActiveTime += now - node.lastActiveTime;
|
||||
}
|
||||
if (node.activeEdges[node.currentState]) {
|
||||
var msg = {};
|
||||
msg.topic = node.topic;
|
||||
msg.payload = node.currentState;
|
||||
node.send([msg, null]);
|
||||
}
|
||||
};
|
||||
|
||||
// This function is called when either the interruptCallback or the debounceCallback
|
||||
// have determined we have a 'genuine' change of state. Update the currentState and
|
||||
// ActiveTime variables, and send a message on the first output with the new state
|
||||
var sendStateMessage = function (x) {
|
||||
node.currentState = Number(x.value);
|
||||
var now = Date.now();
|
||||
if (node.currentState === node.activeState) {
|
||||
node.lastActiveTime = now;
|
||||
} else if (!isNaN(node.lastActiveTime)) {
|
||||
node.totalActiveTime += now - node.lastActiveTime;
|
||||
}
|
||||
if (node.activeEdges[node.currentState]) {
|
||||
// This function is called by the timer. It updates the ActiveTime variables, and sends a
|
||||
// message on the second output with the latest value of the total active time, in seconds
|
||||
var timerCallback = function () {
|
||||
if (node.currentState === node.activeState) {
|
||||
var now = Date.now();
|
||||
node.totalActiveTime += now - node.lastActiveTime;
|
||||
node.lastActiveTime = now;
|
||||
}
|
||||
var msg = {};
|
||||
msg.topic = node.topic;
|
||||
msg.payload = node.currentState;
|
||||
node.send([msg, null]);
|
||||
}
|
||||
};
|
||||
|
||||
// This function is called by the timer. It updates the ActiveTime variables, and sends a
|
||||
// message on the second output with the latest value of the total active time, in seconds
|
||||
var timerCallback = function () {
|
||||
if (node.currentState === node.activeState) {
|
||||
var now = Date.now();
|
||||
node.totalActiveTime += now - node.lastActiveTime;
|
||||
node.lastActiveTime = now;
|
||||
}
|
||||
var msg = {};
|
||||
msg.topic = node.topic;
|
||||
msg.payload = node.totalActiveTime / 1000;
|
||||
node.send([null, msg]);
|
||||
// Re-synchronise the pin state if we have missed a state change interrupt for some
|
||||
// reason, and we are not in the process of debouncing one
|
||||
if (node.debouncing === false) {
|
||||
bonescript.digitalRead(node.pin, interruptCallback);
|
||||
}
|
||||
};
|
||||
|
||||
// This function is called when we receive an input message. If the topic contains
|
||||
// 'load' (case insensitive) set the totalActiveTime to the numeric value of the
|
||||
// payload, if possible. Otherwise clear the totalActiveTime (so we start counting
|
||||
// from zero again)
|
||||
var inputCallback = function (ipMsg) {
|
||||
if (String(ipMsg.topic).search(/load/i) < 0 || isFinite(ipMsg.payload) == false) {
|
||||
node.totalActiveTime = 0;
|
||||
} else {
|
||||
node.totalActiveTime = Number(ipMsg.payload);
|
||||
}
|
||||
if (node.currentState === node.activeState) {
|
||||
node.lastActiveTime = Date.now();
|
||||
}
|
||||
// On startup, send an initial activeTime message, but only send an
|
||||
// initial currentState message if we are in both edges active mode
|
||||
if (node.starting) {
|
||||
node.starting = false;
|
||||
var msg;
|
||||
if (node.activeEdges[0] && node.activeEdges[1]) {
|
||||
msg = [{topic:node.topic}, {topic:node.topic}];
|
||||
msg[0].payload = node.currentState;
|
||||
} else {
|
||||
msg = [null, {topic:node.topic}];
|
||||
msg.payload = node.totalActiveTime / 1000;
|
||||
node.send([null, msg]);
|
||||
// Re-synchronise the pin state if we have missed a state change interrupt for some
|
||||
// reason, and we are not in the process of debouncing one
|
||||
if (node.debouncing === false) {
|
||||
bonescript.digitalRead(node.pin, interruptCallback);
|
||||
}
|
||||
msg[1].payload = node.totalActiveTime;
|
||||
node.send(msg);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
// If we have a valid pin, set it as an input and read the (digital) state
|
||||
if (["P8_7", "P8_8", "P8_9", "P8_10", "P8_11", "P8_12", "P8_13", "P8_14", "P8_15",
|
||||
"P8_16", "P8_17", "P8_18", "P8_19", "P8_26", "P9_11", "P9_12", "P9_13", "P9_14",
|
||||
"P9_15", "P9_16", "P9_17", "P9_18", "P9_21", "P9_22", "P9_23", "P9_24", "P9_26",
|
||||
"P9_27", "P9_30", "P9_41", "P9_42"].indexOf(node.pin) >= 0) {
|
||||
// Don't set up interrupts & intervals until after the close event handler has been installed
|
||||
bonescript.detachInterrupt(node.pin);
|
||||
process.nextTick(function () {
|
||||
bonescript.pinMode(node.pin, bonescript.INPUT);
|
||||
bonescript.digitalRead(node.pin, function (x) {
|
||||
// Initialise the currentState and lastActveTime variables based on the value read
|
||||
node.currentState = Number(x.value);
|
||||
if (node.currentState === node.activeState) {
|
||||
node.lastActiveTime = Date.now();
|
||||
// switch to process.hrtime()
|
||||
}
|
||||
// Attempt to attach a change-of-state interrupt handler to the pin. If we succeed,
|
||||
// set the input event and interval handlers, then send an initial message with the
|
||||
// pin state on the first output
|
||||
if (bonescript.attachInterrupt(node.pin, true, bonescript.CHANGE, interruptCallback)) {
|
||||
node.interruptAttached = true;
|
||||
node.on("input", inputCallback);
|
||||
node.intervalId = setInterval(timerCallback, node.updateInterval);
|
||||
} else {
|
||||
node.error("Failed to attach interrupt");
|
||||
}
|
||||
setTimeout(function () { node.emit("input", {}); }, 50);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
node.error("Unconfigured input pin");
|
||||
}
|
||||
}
|
||||
// This function is called when we receive an input message. If the topic contains
|
||||
// 'load' (case insensitive) set the totalActiveTime to the numeric value of the
|
||||
// payload, if possible. Otherwise clear the totalActiveTime (so we start counting
|
||||
// from zero again)
|
||||
var inputCallback = function (ipMsg) {
|
||||
if (String(ipMsg.topic).search(/load/i) < 0 || isFinite(ipMsg.payload) === false) {
|
||||
node.totalActiveTime = 0;
|
||||
} else {
|
||||
node.totalActiveTime = Number(ipMsg.payload);
|
||||
}
|
||||
if (node.currentState === node.activeState) {
|
||||
node.lastActiveTime = Date.now();
|
||||
}
|
||||
// On startup, send an initial activeTime message, but only send an
|
||||
// initial currentState message if we are in both edges active mode
|
||||
if (node.starting) {
|
||||
node.starting = false;
|
||||
var msg;
|
||||
if (node.activeEdges[0] && node.activeEdges[1]) {
|
||||
msg = [{topic:node.topic}, {topic:node.topic}];
|
||||
msg[0].payload = node.currentState;
|
||||
} else {
|
||||
msg = [null, {topic:node.topic}];
|
||||
}
|
||||
msg[1].payload = node.totalActiveTime;
|
||||
node.send(msg);
|
||||
}
|
||||
};
|
||||
|
||||
// Node constructor for bbb-pulse-in
|
||||
function PulseInputNode(n) {
|
||||
RED.nodes.createNode(this, n);
|
||||
|
||||
// Store local copies of the node configuration (as defined in the .html)
|
||||
this.topic = n.topic; // the topic is not currently used
|
||||
this.pin = n.pin; // The Beaglebone Black pin identifying string
|
||||
this.updateInterval = n.updateInterval * 1000; // How often to send output messages
|
||||
this.countType = n.countType; // Sets either 'edge' or 'pulse' counting
|
||||
this.countUnit = n.countUnit; // Scaling appling to count output
|
||||
this.countRate = n.countRate; // Scaling applied to rate output
|
||||
|
||||
// Working variables
|
||||
this.interruptAttached = false; // Flag: should we detach interrupt when we are closed?
|
||||
this.intervalId = null; // Remember the timer ID so we can delete it when we are closed
|
||||
this.pulseCount = 0; // (Unscaled) total pulse count
|
||||
// Hold the hrtime of the last two pulses (with ns resolution)
|
||||
this.pulseTime = [[NaN, NaN], [NaN, NaN]];
|
||||
|
||||
// Define 'node' to allow us to access 'this' from within callbacks
|
||||
var node = this;
|
||||
|
||||
// Called by the edge or pulse interrupt. If this is a valid interrupt, record the
|
||||
// pulse time and count the pulse
|
||||
var interruptCallback = function (x) {
|
||||
if (x.value !== undefined) {
|
||||
node.pulseTime = [node.pulseTime[1], process.hrtime()];
|
||||
node.pulseCount = node.pulseCount + 1;
|
||||
}
|
||||
};
|
||||
|
||||
// Called when an input message arrives. If the topic contains 'load' (case
|
||||
// insensitive) and the payload is a valid number, set the count to that
|
||||
// number, otherwise set it to zero
|
||||
var inputCallback = function (msg) {
|
||||
if (String(msg.topic).search(/load/i) < 0 || isFinite(msg.payload) == false) {
|
||||
node.pulseCount = 0;
|
||||
} else {
|
||||
node.pulseCount = Number(msg.payload);
|
||||
}
|
||||
};
|
||||
|
||||
// Called by the message timer. Send two messages: the scaled pulse count on
|
||||
// the first output and the scaled instantaneous pulse rate on the second.
|
||||
// The instantaneous pulse rate is the reciprocal of the larger of either the
|
||||
// time interval between the last two pulses, or the time interval since the last pulse.
|
||||
var timerCallback = function () {
|
||||
var now = process.hrtime();
|
||||
var lastTime = node.pulseTime[1][0] - node.pulseTime[0][0] + (node.pulseTime[1][1] - node.pulseTime[0][1]) / 1e9;
|
||||
var thisTime = now[0] - node.pulseTime[1][0] + (now[1] - node.pulseTime[1][1]) / 1e9;
|
||||
var msg = [{ topic:node.topic }, { topic:node.topic }];
|
||||
msg[0].payload = node.countUnit * node.pulseCount;
|
||||
// At startup, pulseTime contains NaN's: force the rate output to 0
|
||||
msg[1].payload = node.countRate / Math.max(thisTime, lastTime) || 0;
|
||||
node.send(msg);
|
||||
};
|
||||
|
||||
// If we have a valid pin, set it as an input and read the (digital) state
|
||||
if (["P8_7", "P8_8", "P8_9", "P8_10", "P8_11", "P8_12", "P8_13", "P8_14", "P8_15",
|
||||
"P8_16", "P8_17", "P8_18", "P8_19", "P8_26", "P9_11", "P9_12", "P9_13", "P9_14",
|
||||
"P9_15", "P9_16", "P9_17", "P9_18", "P9_21", "P9_22", "P9_23", "P9_24", "P9_26",
|
||||
"P9_27", "P9_30", "P9_41", "P9_42"].indexOf(node.pin) >= 0) {
|
||||
// Don't set up interrupts & intervals until after the close event handler has been installed
|
||||
bonescript.detachInterrupt(node.pin);
|
||||
process.nextTick(function () {
|
||||
// If we have a valid pin, set it as an input and read the (digital) state
|
||||
if (["P8_7", "P8_8", "P8_9", "P8_10", "P8_11", "P8_12", "P8_13", "P8_14", "P8_15",
|
||||
"P8_16", "P8_17", "P8_18", "P8_19", "P8_26", "P9_11", "P9_12", "P9_13", "P9_14",
|
||||
"P9_15", "P9_16", "P9_17", "P9_18", "P9_21", "P9_22", "P9_23", "P9_24", "P9_26",
|
||||
"P9_27", "P9_30", "P9_41", "P9_42"].indexOf(node.pin) >= 0) {
|
||||
// Don't set up interrupts & intervals until after the close event handler has been installed
|
||||
bonescript.detachInterrupt(node.pin);
|
||||
process.nextTick(function () {
|
||||
bonescript.pinMode(node.pin, bonescript.INPUT);
|
||||
bonescript.digitalRead(node.pin, function (x) {
|
||||
// Initialise the currentState based on the value read
|
||||
node.currentState = Number(x.value);
|
||||
// Attempt to attach an interrupt handler to the pin. If we succeed,
|
||||
// set the input event and interval handlers
|
||||
var interruptType;
|
||||
if (node.countType === "pulse") {
|
||||
// interruptType = bonescript.FALLING; <- doesn't work in v0.2.4
|
||||
interruptType = bonescript.RISING;
|
||||
} else {
|
||||
interruptType = bonescript.CHANGE;
|
||||
}
|
||||
if (bonescript.attachInterrupt(node.pin, true, interruptType, interruptCallback)) {
|
||||
node.interruptAttached = true;
|
||||
node.on("input", inputCallback);
|
||||
node.intervalId = setInterval(timerCallback, node.updateInterval);
|
||||
} else {
|
||||
node.error("Failed to attach interrupt");
|
||||
}
|
||||
// Initialise the currentState and lastActveTime variables based on the value read
|
||||
node.currentState = Number(x.value);
|
||||
if (node.currentState === node.activeState) {
|
||||
node.lastActiveTime = Date.now();
|
||||
// switch to process.hrtime()
|
||||
}
|
||||
// Attempt to attach a change-of-state interrupt handler to the pin. If we succeed,
|
||||
// set the input event and interval handlers, then send an initial message with the
|
||||
// pin state on the first output
|
||||
if (bonescript.attachInterrupt(node.pin, true, bonescript.CHANGE, interruptCallback)) {
|
||||
node.interruptAttached = true;
|
||||
node.on("input", inputCallback);
|
||||
node.intervalId = setInterval(timerCallback, node.updateInterval);
|
||||
} else {
|
||||
node.error("Failed to attach interrupt");
|
||||
}
|
||||
setTimeout(function () { node.emit("input", {}); }, 50);
|
||||
});
|
||||
});
|
||||
});
|
||||
} else {
|
||||
node.error("Unconfigured input pin");
|
||||
} else {
|
||||
node.error("Unconfigured input pin");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Node constructor for bbb-discrete-out
|
||||
function DiscreteOutputNode(n) {
|
||||
RED.nodes.createNode(this, n);
|
||||
// Node constructor for bbb-pulse-in
|
||||
function PulseInputNode(n) {
|
||||
RED.nodes.createNode(this, n);
|
||||
|
||||
// Store local copies of the node configuration (as defined in the .html)
|
||||
this.topic = n.topic; // the topic is not currently used
|
||||
this.pin = n.pin; // The Beaglebone Black pin identifying string
|
||||
this.defaultState = Number(n.defaultState); // What state to set up as
|
||||
this.inverting = n.inverting;
|
||||
this.toggle = n.toggle;
|
||||
// Store local copies of the node configuration (as defined in the .html)
|
||||
this.topic = n.topic; // the topic is not currently used
|
||||
this.pin = n.pin; // The Beaglebone Black pin identifying string
|
||||
this.updateInterval = n.updateInterval * 1000; // How often to send output messages
|
||||
this.countType = n.countType; // Sets either 'edge' or 'pulse' counting
|
||||
this.countUnit = n.countUnit; // Scaling appling to count output
|
||||
this.countRate = n.countRate; // Scaling applied to rate output
|
||||
|
||||
// Working variables
|
||||
this.currentState = this.defaultState;
|
||||
// Working variables
|
||||
this.interruptAttached = false; // Flag: should we detach interrupt when we are closed?
|
||||
this.intervalId = null; // Remember the timer ID so we can delete it when we are closed
|
||||
this.pulseCount = 0; // (Unscaled) total pulse count
|
||||
// Hold the hrtime of the last two pulses (with ns resolution)
|
||||
this.pulseTime = [[NaN, NaN], [NaN, NaN]];
|
||||
|
||||
var node = this;
|
||||
// Define 'node' to allow us to access 'this' from within callbacks
|
||||
var node = this;
|
||||
|
||||
// If the input message paylod is numeric, values > 0.5 are 'true', otherwise use
|
||||
// the truthiness of the payload. Apply the inversion flag before setting the output
|
||||
var inputCallback = function (msg) {
|
||||
var newState;
|
||||
if (node.toggle) {
|
||||
newState = node.currentState === 0 ? 1 : 0;
|
||||
} else {
|
||||
if (isFinite(Number(msg.payload))) {
|
||||
newState = Number(msg.payload) > 0.5 ? true : false;
|
||||
} else if (msg.payload) {
|
||||
newState = true;
|
||||
// Called by the edge or pulse interrupt. If this is a valid interrupt, record the
|
||||
// pulse time and count the pulse
|
||||
var interruptCallback = function (x) {
|
||||
if (x.value !== undefined) {
|
||||
node.pulseTime = [node.pulseTime[1], process.hrtime()];
|
||||
node.pulseCount = node.pulseCount + 1;
|
||||
}
|
||||
};
|
||||
|
||||
// Called when an input message arrives. If the topic contains 'load' (case
|
||||
// insensitive) and the payload is a valid number, set the count to that
|
||||
// number, otherwise set it to zero
|
||||
var inputCallback = function (msg) {
|
||||
if (String(msg.topic).search(/load/i) < 0 || isFinite(msg.payload) === false) {
|
||||
node.pulseCount = 0;
|
||||
} else {
|
||||
newState = false;
|
||||
node.pulseCount = Number(msg.payload);
|
||||
}
|
||||
if (node.inverting) {
|
||||
newState = !newState;
|
||||
}
|
||||
}
|
||||
bonescript.digitalWrite(node.pin, newState ? 1 : 0);
|
||||
node.send({ topic:node.topic, payload:newState });
|
||||
node.currentState = newState;
|
||||
};
|
||||
};
|
||||
|
||||
// If we have a valid pin, set it as an output and set the default state
|
||||
if (["P8_7", "P8_8", "P8_9", "P8_10", "P8_11", "P8_12", "P8_13", "P8_14", "P8_15",
|
||||
"P8_16", "P8_17", "P8_18", "P8_19", "P8_26", "P9_11", "P9_12", "P9_13", "P9_14",
|
||||
"P9_15", "P9_16", "P9_17", "P9_18", "P9_21", "P9_22", "P9_23", "P9_24", "P9_26",
|
||||
"P9_27", "P9_30", "P9_41", "P9_42", "USR0", "USR1", "USR2", "USR3"].indexOf(node.pin) >= 0) {
|
||||
// Don't set up interrupts & intervals until after the close event handler has been installed
|
||||
bonescript.detachInterrupt(node.pin);
|
||||
process.nextTick(function () {
|
||||
bonescript.pinMode(node.pin, bonescript.OUTPUT);
|
||||
node.on("input", inputCallback);
|
||||
setTimeout(function () { bonescript.digitalWrite(node.pin, node.defaultState); }, 50);
|
||||
});
|
||||
} else {
|
||||
node.error("Unconfigured output pin");
|
||||
// Called by the message timer. Send two messages: the scaled pulse count on
|
||||
// the first output and the scaled instantaneous pulse rate on the second.
|
||||
// The instantaneous pulse rate is the reciprocal of the larger of either the
|
||||
// time interval between the last two pulses, or the time interval since the last pulse.
|
||||
var timerCallback = function () {
|
||||
var now = process.hrtime();
|
||||
var lastTime = node.pulseTime[1][0] - node.pulseTime[0][0] + (node.pulseTime[1][1] - node.pulseTime[0][1]) / 1e9;
|
||||
var thisTime = now[0] - node.pulseTime[1][0] + (now[1] - node.pulseTime[1][1]) / 1e9;
|
||||
var msg = [{ topic:node.topic }, { topic:node.topic }];
|
||||
msg[0].payload = node.countUnit * node.pulseCount;
|
||||
// At startup, pulseTime contains NaN's: force the rate output to 0
|
||||
msg[1].payload = node.countRate / Math.max(thisTime, lastTime) || 0;
|
||||
node.send(msg);
|
||||
};
|
||||
|
||||
// If we have a valid pin, set it as an input and read the (digital) state
|
||||
if (["P8_7", "P8_8", "P8_9", "P8_10", "P8_11", "P8_12", "P8_13", "P8_14", "P8_15",
|
||||
"P8_16", "P8_17", "P8_18", "P8_19", "P8_26", "P9_11", "P9_12", "P9_13", "P9_14",
|
||||
"P9_15", "P9_16", "P9_17", "P9_18", "P9_21", "P9_22", "P9_23", "P9_24", "P9_26",
|
||||
"P9_27", "P9_30", "P9_41", "P9_42"].indexOf(node.pin) >= 0) {
|
||||
// Don't set up interrupts & intervals until after the close event handler has been installed
|
||||
bonescript.detachInterrupt(node.pin);
|
||||
process.nextTick(function () {
|
||||
bonescript.pinMode(node.pin, bonescript.INPUT);
|
||||
bonescript.digitalRead(node.pin, function (x) {
|
||||
// Initialise the currentState based on the value read
|
||||
node.currentState = Number(x.value);
|
||||
// Attempt to attach an interrupt handler to the pin. If we succeed,
|
||||
// set the input event and interval handlers
|
||||
var interruptType;
|
||||
if (node.countType === "pulse") {
|
||||
// interruptType = bonescript.FALLING; <- doesn't work in v0.2.4
|
||||
interruptType = bonescript.RISING;
|
||||
} else {
|
||||
interruptType = bonescript.CHANGE;
|
||||
}
|
||||
if (bonescript.attachInterrupt(node.pin, true, interruptType, interruptCallback)) {
|
||||
node.interruptAttached = true;
|
||||
node.on("input", inputCallback);
|
||||
node.intervalId = setInterval(timerCallback, node.updateInterval);
|
||||
} else {
|
||||
node.error("Failed to attach interrupt");
|
||||
}
|
||||
});
|
||||
});
|
||||
} else {
|
||||
node.error("Unconfigured input pin");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Node constructor for bbb-pulse-out
|
||||
function PulseOutputNode(n) {
|
||||
RED.nodes.createNode(this, n);
|
||||
// Node constructor for bbb-discrete-out
|
||||
function DiscreteOutputNode(n) {
|
||||
RED.nodes.createNode(this, n);
|
||||
|
||||
// Store local copies of the node configuration (as defined in the .html)
|
||||
this.topic = n.topic; // the topic is not currently used
|
||||
this.pin = n.pin; // The Beaglebone Black pin identifying string
|
||||
this.pulseState = Number(n.pulseState); // What state the pulse will be..
|
||||
this.defaultState = this.pulseState === 1 ? 0 : 1;
|
||||
this.retriggerable = n.retriggerable;
|
||||
this.pulseTime = n.pulseTime * 1000; // Pulse width in milliseconds
|
||||
// Store local copies of the node configuration (as defined in the .html)
|
||||
this.topic = n.topic; // the topic is not currently used
|
||||
this.pin = n.pin; // The Beaglebone Black pin identifying string
|
||||
this.defaultState = Number(n.defaultState); // What state to set up as
|
||||
this.inverting = n.inverting;
|
||||
this.toggle = n.toggle;
|
||||
|
||||
// Working variables
|
||||
this.pulseTimer = null; // Non-null while a pulse is being generated
|
||||
// Working variables
|
||||
this.currentState = this.defaultState;
|
||||
|
||||
var node = this;
|
||||
var node = this;
|
||||
|
||||
// Generate a pulse in response to an input message. If the topic includes the text
|
||||
// 'time' (case insensitive) and the payload is numeric, use this value as the
|
||||
// pulse time. Otherwise use the value from the properties dialog.
|
||||
// If the resulting pulse time is < 1ms, do nothing.
|
||||
// If the pulse mode is not retriggerable, then if no pulseTimer is active, generate
|
||||
// a pulse. If the pulse mode is retriggerable, and a pulseTimer is active, cancel it.
|
||||
// If no timer is active, set the pulse output. In both cases schedule a new pulse
|
||||
// timer.
|
||||
var inputCallback = function (msg) {
|
||||
var time = node.pulseTime;
|
||||
if (String(msg.topic).search(/time/i) >= 0 && isFinite(msg.payload)) {
|
||||
time = msg.payload * 1000;
|
||||
}
|
||||
if (time >= 1) {
|
||||
if (node.retriggerable === false) {
|
||||
if (node.pulseTimer === null) {
|
||||
node.pulseTimer = setTimeout(endPulseCallback, time);
|
||||
bonescript.digitalWrite(node.pin, node.pulseState);
|
||||
node.send({ topic:node.topic, payload:node.pulseState });
|
||||
}
|
||||
// If the input message paylod is numeric, values > 0.5 are 'true', otherwise use
|
||||
// the truthiness of the payload. Apply the inversion flag before setting the output
|
||||
var inputCallback = function (msg) {
|
||||
var newState;
|
||||
if (node.toggle) {
|
||||
newState = node.currentState === 0 ? 1 : 0;
|
||||
} else {
|
||||
if (node.pulseTimer !== null) {
|
||||
clearTimeout(node.pulseTimer);
|
||||
if (isFinite(Number(msg.payload))) {
|
||||
newState = Number(msg.payload) > 0.5 ? true : false;
|
||||
} else if (msg.payload) {
|
||||
newState = true;
|
||||
} else {
|
||||
bonescript.digitalWrite(node.pin, node.pulseState);
|
||||
node.send({ topic:node.topic, payload:node.pulseState });
|
||||
newState = false;
|
||||
}
|
||||
if (node.inverting) {
|
||||
newState = !newState;
|
||||
}
|
||||
node.pulseTimer = setTimeout(endPulseCallback, time);
|
||||
}
|
||||
}
|
||||
};
|
||||
bonescript.digitalWrite(node.pin, newState ? 1 : 0);
|
||||
node.send({ topic:node.topic, payload:newState });
|
||||
node.currentState = newState;
|
||||
};
|
||||
|
||||
// At the end of the pulse, restore the default state and set the timer to null
|
||||
var endPulseCallback = function () {
|
||||
node.pulseTimer = null;
|
||||
bonescript.digitalWrite(node.pin, node.defaultState);
|
||||
node.send({ topic:node.topic, payload:node.defaultState });
|
||||
};
|
||||
|
||||
// If we have a valid pin, set it as an output and set the default state
|
||||
if (["P8_7", "P8_8", "P8_9", "P8_10", "P8_11", "P8_12", "P8_13", "P8_14", "P8_15",
|
||||
"P8_16", "P8_17", "P8_18", "P8_19", "P8_26", "P9_11", "P9_12", "P9_13", "P9_14",
|
||||
"P9_15", "P9_16", "P9_17", "P9_18", "P9_21", "P9_22", "P9_23", "P9_24", "P9_26",
|
||||
"P9_27", "P9_30", "P9_41", "P9_42", "USR0", "USR1", "USR2", "USR3"].indexOf(node.pin) >= 0) {
|
||||
// Don't set up interrupts & intervals until after the close event handler has been installed
|
||||
bonescript.detachInterrupt(node.pin);
|
||||
process.nextTick(function () {
|
||||
bonescript.pinMode(node.pin, bonescript.OUTPUT);
|
||||
node.on("input", inputCallback);
|
||||
// Set the pin to the default stte once the dust settles
|
||||
setTimeout(endPulseCallback, 50);
|
||||
});
|
||||
} else {
|
||||
node.error("Unconfigured output pin");
|
||||
// If we have a valid pin, set it as an output and set the default state
|
||||
if (["P8_7", "P8_8", "P8_9", "P8_10", "P8_11", "P8_12", "P8_13", "P8_14", "P8_15",
|
||||
"P8_16", "P8_17", "P8_18", "P8_19", "P8_26", "P9_11", "P9_12", "P9_13", "P9_14",
|
||||
"P9_15", "P9_16", "P9_17", "P9_18", "P9_21", "P9_22", "P9_23", "P9_24", "P9_26",
|
||||
"P9_27", "P9_30", "P9_41", "P9_42", "USR0", "USR1", "USR2", "USR3"].indexOf(node.pin) >= 0) {
|
||||
// Don't set up interrupts & intervals until after the close event handler has been installed
|
||||
bonescript.detachInterrupt(node.pin);
|
||||
process.nextTick(function () {
|
||||
bonescript.pinMode(node.pin, bonescript.OUTPUT);
|
||||
node.on("input", inputCallback);
|
||||
setTimeout(function () { bonescript.digitalWrite(node.pin, node.defaultState); }, 50);
|
||||
});
|
||||
} else {
|
||||
node.error("Unconfigured output pin");
|
||||
}
|
||||
}
|
||||
|
||||
// Node constructor for bbb-pulse-out
|
||||
function PulseOutputNode(n) {
|
||||
RED.nodes.createNode(this, n);
|
||||
|
||||
// Store local copies of the node configuration (as defined in the .html)
|
||||
this.topic = n.topic; // the topic is not currently used
|
||||
this.pin = n.pin; // The Beaglebone Black pin identifying string
|
||||
this.pulseState = Number(n.pulseState); // What state the pulse will be..
|
||||
this.defaultState = this.pulseState === 1 ? 0 : 1;
|
||||
this.retriggerable = n.retriggerable;
|
||||
this.pulseTime = n.pulseTime * 1000; // Pulse width in milliseconds
|
||||
|
||||
// Working variables
|
||||
this.pulseTimer = null; // Non-null while a pulse is being generated
|
||||
|
||||
var node = this;
|
||||
|
||||
// Generate a pulse in response to an input message. If the topic includes the text
|
||||
// 'time' (case insensitive) and the payload is numeric, use this value as the
|
||||
// pulse time. Otherwise use the value from the properties dialog.
|
||||
// If the resulting pulse time is < 1ms, do nothing.
|
||||
// If the pulse mode is not retriggerable, then if no pulseTimer is active, generate
|
||||
// a pulse. If the pulse mode is retriggerable, and a pulseTimer is active, cancel it.
|
||||
// If no timer is active, set the pulse output. In both cases schedule a new pulse
|
||||
// timer.
|
||||
var inputCallback = function (msg) {
|
||||
var time = node.pulseTime;
|
||||
if (String(msg.topic).search(/time/i) >= 0 && isFinite(msg.payload)) {
|
||||
time = msg.payload * 1000;
|
||||
}
|
||||
if (time >= 1) {
|
||||
if (node.retriggerable === false) {
|
||||
if (node.pulseTimer === null) {
|
||||
node.pulseTimer = setTimeout(endPulseCallback, time);
|
||||
bonescript.digitalWrite(node.pin, node.pulseState);
|
||||
node.send({ topic:node.topic, payload:node.pulseState });
|
||||
}
|
||||
} else {
|
||||
if (node.pulseTimer !== null) {
|
||||
clearTimeout(node.pulseTimer);
|
||||
} else {
|
||||
bonescript.digitalWrite(node.pin, node.pulseState);
|
||||
node.send({ topic:node.topic, payload:node.pulseState });
|
||||
}
|
||||
node.pulseTimer = setTimeout(endPulseCallback, time);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// At the end of the pulse, restore the default state and set the timer to null
|
||||
var endPulseCallback = function () {
|
||||
node.pulseTimer = null;
|
||||
bonescript.digitalWrite(node.pin, node.defaultState);
|
||||
node.send({ topic:node.topic, payload:node.defaultState });
|
||||
};
|
||||
|
||||
// If we have a valid pin, set it as an output and set the default state
|
||||
if (["P8_7", "P8_8", "P8_9", "P8_10", "P8_11", "P8_12", "P8_13", "P8_14", "P8_15",
|
||||
"P8_16", "P8_17", "P8_18", "P8_19", "P8_26", "P9_11", "P9_12", "P9_13", "P9_14",
|
||||
"P9_15", "P9_16", "P9_17", "P9_18", "P9_21", "P9_22", "P9_23", "P9_24", "P9_26",
|
||||
"P9_27", "P9_30", "P9_41", "P9_42", "USR0", "USR1", "USR2", "USR3"].indexOf(node.pin) >= 0) {
|
||||
// Don't set up interrupts & intervals until after the close event handler has been installed
|
||||
bonescript.detachInterrupt(node.pin);
|
||||
process.nextTick(function () {
|
||||
bonescript.pinMode(node.pin, bonescript.OUTPUT);
|
||||
node.on("input", inputCallback);
|
||||
// Set the pin to the default stte once the dust settles
|
||||
setTimeout(endPulseCallback, 50);
|
||||
});
|
||||
} else {
|
||||
node.error("Unconfigured output pin");
|
||||
}
|
||||
}
|
||||
|
||||
// Register the nodes by name. This must be called before overriding any of the Node functions.
|
||||
RED.nodes.registerType("bbb-analogue-in", AnalogueInputNode);
|
||||
RED.nodes.registerType("bbb-discrete-in", DiscreteInputNode);
|
||||
RED.nodes.registerType("bbb-pulse-in", PulseInputNode);
|
||||
RED.nodes.registerType("bbb-discrete-out", DiscreteOutputNode);
|
||||
RED.nodes.registerType("bbb-pulse-out", PulseOutputNode);
|
||||
|
||||
// On close, detach the interrupt (if we attached one) and clear any active timers
|
||||
DiscreteInputNode.prototype.close = function () {
|
||||
if (this.interruptAttached) {
|
||||
bonescript.detachInterrupt(this.pin);
|
||||
}
|
||||
if (this.intervalId !== null) {
|
||||
clearInterval(this.intervalId);
|
||||
}
|
||||
if (this.debounceTimer !== null) {
|
||||
clearTimeout(this.debounceTimer);
|
||||
}
|
||||
};
|
||||
|
||||
// On close, detach the interrupt (if we attached one) and clear the interval (if we set one)
|
||||
PulseInputNode.prototype.close = function () {
|
||||
if (this.interruptAttached) {
|
||||
bonescript.detachInterrupt(this.pin);
|
||||
}
|
||||
if (this.intervalId !== null) {
|
||||
clearInterval(this.intervalId);
|
||||
}
|
||||
};
|
||||
|
||||
// On close, clear an active pulse timer
|
||||
PulseOutputNode.prototype.close = function () {
|
||||
if (this.pulseTimer !== null) {
|
||||
clearTimeout(this.pulseTimer);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// Register the nodes by name. This must be called before overriding any of the Node functions.
|
||||
RED.nodes.registerType("bbb-analogue-in", AnalogueInputNode);
|
||||
RED.nodes.registerType("bbb-discrete-in", DiscreteInputNode);
|
||||
RED.nodes.registerType("bbb-pulse-in", PulseInputNode);
|
||||
RED.nodes.registerType("bbb-discrete-out", DiscreteOutputNode);
|
||||
RED.nodes.registerType("bbb-pulse-out", PulseOutputNode);
|
||||
|
||||
// On close, detach the interrupt (if we attached one) and clear any active timers
|
||||
DiscreteInputNode.prototype.close = function () {
|
||||
if (this.interruptAttached) {
|
||||
bonescript.detachInterrupt(this.pin);
|
||||
}
|
||||
if (this.intervalId !== null) {
|
||||
clearInterval(this.intervalId);
|
||||
}
|
||||
if (this.debounceTimer !== null) {
|
||||
clearTimeout(this.debounceTimer);
|
||||
}
|
||||
};
|
||||
|
||||
// On close, detach the interrupt (if we attached one) and clear the interval (if we set one)
|
||||
PulseInputNode.prototype.close = function () {
|
||||
if (this.interruptAttached) {
|
||||
bonescript.detachInterrupt(this.pin);
|
||||
}
|
||||
if (this.intervalId !== null) {
|
||||
clearInterval(this.intervalId);
|
||||
}
|
||||
};
|
||||
|
||||
// On close, clear an active pulse timer
|
||||
PulseOutputNode.prototype.close = function () {
|
||||
if (this.pulseTimer !== null) {
|
||||
clearTimeout(this.pulseTimer);
|
||||
}
|
||||
};
|
||||
|
177
hardware/BBB/LICENSE
Normal file
177
hardware/BBB/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
|
96
hardware/BBB/README.md
Normal file
96
hardware/BBB/README.md
Normal file
@ -0,0 +1,96 @@
|
||||
node-red-node-beaglebone
|
||||
========================
|
||||
A set of <a href="http://nodered.org" target="_new">Node-RED</a> nodes to interface with the GPIO pins of a <a href="http://http://beagleboard.org/black/" target="_new">Beaglebone Black</a>.
|
||||
|
||||
Pre-requisites
|
||||
--------------
|
||||
|
||||
Only of use on a BeagleboneBlack board. Should ideally be running the <a href="http://beagleboard.org/latest-images/" target="_new"> latest Debian</a> image - as that has node.js v0.10.x and the bonescript npm preinstalled.
|
||||
it does also need <b>bonescript</b> - but this is also pre-installed so no need to mark as a dependency...
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
Run the following command in the root directory of your Node-RED install
|
||||
|
||||
npm install node-red-node-beaglebone
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
This package provides 5 nodes for use with the BeagleboneBlack board.
|
||||
|
||||
###Analogue Input
|
||||
|
||||
Reads an analogue pin when triggered by
|
||||
a message.
|
||||
|
||||
The output message topic is the node topic: the output message value is the
|
||||
scaled analogue input or NaN if a read error occurs.
|
||||
|
||||
|
||||
Simple linear scaling is defined by setting the output values required for input
|
||||
values of 0 and 1. You can apply more complicated scaling, e.g. for sensor linearisation,
|
||||
by defining breakpoints at intermediate input values, with the desired output for
|
||||
each. Values between breakpoints are linearly interpolated.
|
||||
|
||||
|
||||
To reduce the effect of noise, enable averaging. This will read the input pin
|
||||
voltage ten times in rapid succession for each input message and output the mean value.
|
||||
|
||||
###Digital Input
|
||||
|
||||
Sends a message with payload 0 or 1 on the first output when the pin changes state, and logs the total time in the active state.
|
||||
|
||||
Sends a message with a payload of the current total active time
|
||||
(in seconds) on the second output at selectable intervals. An input message with topic 'load'
|
||||
and a numeric payload will set the total active time to that value: any other input message
|
||||
will reset it to zero.
|
||||
|
||||
The active state may be set to be high or low: this only affects the calculation
|
||||
of the active time, not the pin state value sent on the first output.
|
||||
|
||||
The pin state messages may be generated for both directions of change, or for just 0 to 1
|
||||
or just 1 to 0 changes. This is useful to generate a single message from a button
|
||||
press. When using buttons or switches, enable debouncing to improve reliability.
|
||||
|
||||
###Pulse Input
|
||||
|
||||
Pulse input for the Beaglebone Black. Counts input pulses or pulse edges: outputs
|
||||
total counts and the rate of counts/sec, with scaling.
|
||||
|
||||
Sends the total count message on the first output, and the current count
|
||||
rate message on the second output, at the chosen interval. An input message with topic 'load'
|
||||
and a numeric payload will set the total count to that value (no scaling is applied):
|
||||
any other input message will reset it to zero.
|
||||
|
||||
###Digital Output
|
||||
|
||||
Sets the output pin high or low depending on the payload of the input message. Numeric
|
||||
payloads > 0.5 are 'high' (1), payloads <= 0.5 are 'low' (0). Other payloads which
|
||||
evaluate to true are 'high', if not then 'low'. Selecting the Inverting checkbox will
|
||||
switch the sense of the pin output.
|
||||
|
||||
|
||||
If the Toggle state checkbox is checked, the message content is ignored: successive
|
||||
messages cause the pin to toggle between 0 and 1.
|
||||
|
||||
|
||||
The pin will be initially set to the given Startup state until the first message arrives:
|
||||
the Inverting property is not applied to this value.
|
||||
|
||||
###Pulse Output
|
||||
|
||||
Pulses the output pin for the set time after receiving an input message, unless the
|
||||
message has a topic including the text 'time' and a numeric payload. In this case, the
|
||||
the pulse time will be the value of the payload in seconds. If the time from either
|
||||
source is < 0.001 seconds, no pulse is generated.
|
||||
|
||||
In retriggerable mode, a second message within the pulse period will extend the duration
|
||||
of the pulse by the time value: in non-retriggerable mode, input messages arriving during
|
||||
the duration of the pulse are ignored.
|
||||
|
||||
The pin state of the pulse may be set to either 0 or 1: the output pin will switch
|
||||
back to the other state after the pulse time. An output message is generated each time
|
||||
the pin changes state: its payload is the new state (0 or 1).
|
Binary file not shown.
Before Width: | Height: | Size: 719 B After Width: | Height: | Size: 1.3 KiB |
22
hardware/BBB/package.json
Normal file
22
hardware/BBB/package.json
Normal file
@ -0,0 +1,22 @@
|
||||
{
|
||||
"name" : "node-red-node-beaglebone",
|
||||
"version" : "0.0.3",
|
||||
"description" : "A set of Node-RED nodes to interface to the GPIO pins of a Beaglebone Black board",
|
||||
"dependencies" : {
|
||||
},
|
||||
"repository" : {
|
||||
"type":"git",
|
||||
"url":"https://github.com/node-red/node-red-nodes/tree/master/hardware/BBB"
|
||||
},
|
||||
"license": "Apache-v2.0",
|
||||
"keywords": [ "node-red", "beagleboneblack", "beaglebone", "bbb" ],
|
||||
"node-red" : {
|
||||
"nodes" : {
|
||||
"bbb": "145-BBB-hardware.js"
|
||||
}
|
||||
},
|
||||
"contributors": [
|
||||
{"name": "Max Hadley"},
|
||||
{"name": "Dave Conway-Jones"}
|
||||
]
|
||||
}
|
177
hardware/HummingboardGPIO/LICENSE
Normal file
177
hardware/HummingboardGPIO/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
|
45
hardware/HummingboardGPIO/README.md
Normal file
45
hardware/HummingboardGPIO/README.md
Normal file
@ -0,0 +1,45 @@
|
||||
node-red-node-hbgpio
|
||||
====================
|
||||
|
||||
A <a href="http://nodered.org" target="_new">Node-RED</a> node to read and write the digital IO of a SolidRun HummingBoard.
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
**This install is for Debian based OS on Hummingboard.**
|
||||
|
||||
Run the following command in the root directory of your Node-RED install:
|
||||
|
||||
npm install node-red-node-hpgpio
|
||||
|
||||
**Note :** This **should** be run as root in order to move and set SUID permissions on a script to talk to the gpio pins. Alternatively you can run as a normal user and then move the file and change permissions manually.
|
||||
|
||||
sudo cp node_modules/node-red-node-hpgpio/gpiohb /usr/local/bin/
|
||||
sudo chmod 4755 /usr/lcoal/bin/gpiohb
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Hummingboard GPIO input and output nodes.
|
||||
|
||||
This requires a small script (gpiohb) to run as root in order to work. It should be placed in /usr/local/bin/ and have SUID permissions 4755.
|
||||
|
||||
**Note:** We are using the actual physical pin numbers as they are easier to locate.
|
||||
|
||||
###Output node
|
||||
|
||||
Expects a <b>msg.payload</b> with either a 0 or 1 (or true or false).
|
||||
|
||||
Will set the selected physical pin high or low depending on the value passed in.
|
||||
|
||||
The initial value of the pin at deploy time can also be set to 0 or 1.
|
||||
|
||||
|
||||
###Input node
|
||||
|
||||
Generates a **msg.payload** with either a 0 or 1 depending on the state of the input pin.
|
||||
|
||||
The **msg.topic** is set to **pin/{the pin number}**
|
||||
|
||||
**Note:** The input node waits for a change on the level of the pin before reading the value - and then resets to wait for the next interrupt - so it is possible to miss very fast changes as we may still be reading the value when the second edge occurs.
|
18
hardware/HummingboardGPIO/fixup.sh
Executable file
18
hardware/HummingboardGPIO/fixup.sh
Executable file
@ -0,0 +1,18 @@
|
||||
#!/bin/bash
|
||||
|
||||
echo "*********************************************"
|
||||
echo "Moving gpiohb to /usr/local/bin/"
|
||||
if [[ $EUID -ne 0 ]]; then
|
||||
echo "Not running as user root" 2>&1
|
||||
echo "please run the following commands manually"
|
||||
echo " sudo cp $PWD/gpiohb /usr/local/bin/gpiohb"
|
||||
echo " sudo chmod 4755 /usr/local/bin/gpiohb"
|
||||
echo "or re-run npm install as root / sudo"
|
||||
echo "*********************************************"
|
||||
exit 1
|
||||
else
|
||||
cp gpiohb /usr/local/bin/
|
||||
chmod 4755 /usr/local/bin/gpiohb
|
||||
echo "OK - gpiohb moved to /usr/local/bin"
|
||||
echo "*********************************************"
|
||||
fi
|
74
hardware/HummingboardGPIO/gpiohb
Executable file
74
hardware/HummingboardGPIO/gpiohb
Executable file
@ -0,0 +1,74 @@
|
||||
#!/bin/bash
|
||||
|
||||
# There is NO error checking in this program - you can mess up pins big time if you want.
|
||||
|
||||
# gpio mode pin inputtype
|
||||
# gpio read pin
|
||||
# gpio write pin level
|
||||
# gpio pwm pin level
|
||||
# gpio close pin
|
||||
|
||||
declare -A pins
|
||||
# Map the GPIO names to actual underlying IO numbers
|
||||
pins=(["0"]="73" ["1"]="72" ["2"]="71" ["3"]="70" ["4"]="194" ["5"]="195" ["6"]="67" ["7"]="1")
|
||||
|
||||
usage() {
|
||||
echo ""
|
||||
echo " gpiohb mode {pin} {in|out}"
|
||||
echo " gpiohb read {pin}"
|
||||
echo " gpiohb write {pin} {0|1}"
|
||||
echo " gpiohb wfi {pin} {rising|falling|both|none}"
|
||||
#echo " gpiohb pwm {pin} {0-1023}"
|
||||
echo " gpiohb close {pin}"
|
||||
echo ""
|
||||
}
|
||||
|
||||
while [ "$1" != "" ]; do
|
||||
case $1 in
|
||||
-h | --help | -?)
|
||||
usage
|
||||
exit
|
||||
;;
|
||||
mode)
|
||||
echo $1 $2 $3
|
||||
if [ "$3" != "out" ] ; then
|
||||
$3="in"
|
||||
fi
|
||||
pin=${pins[$2]}
|
||||
echo $pin > /sys/class/gpio/export
|
||||
echo $3 > /sys/class/gpio/gpio$pin/direction
|
||||
exit
|
||||
;;
|
||||
read)
|
||||
pin=${pins[$2]}
|
||||
cat /sys/class/gpio/gpio$pin/value
|
||||
exit
|
||||
;;
|
||||
write)
|
||||
pin=${pins[$2]}
|
||||
echo $3 > /sys/class/gpio/gpio$pin/value
|
||||
exit
|
||||
;;
|
||||
wfi)
|
||||
pin=${pins[$2]}
|
||||
echo $3 > /sys/class/gpio/gpio$pin/edge
|
||||
exit
|
||||
;;
|
||||
pwm)
|
||||
# Not implemented yet....
|
||||
pin=${pins[$2]}
|
||||
exit
|
||||
;;
|
||||
close)
|
||||
pin=${pins[$2]}
|
||||
echo $pin > /sys/class/gpio/unexport
|
||||
exit
|
||||
;;
|
||||
*)
|
||||
echo "ERROR: unknown parameter \"$PARAM\""
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
shift
|
||||
done
|
162
hardware/HummingboardGPIO/hb-gpio.html
Normal file
162
hardware/HummingboardGPIO/hb-gpio.html
Normal file
@ -0,0 +1,162 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-template-name="hb-gpio in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-pin"><i class="fa fa-circle"></i> GPIO Pin</label>
|
||||
<select type="text" id="node-input-pin" style="width: 250px;">
|
||||
<option value='' disabled selected style='display:none;'>select pin</option>
|
||||
<option value="7">7 - GPIO 1</option>
|
||||
<option value="11">11 - GPIO 73</option>
|
||||
<option value="12">12 - GPIO 72</option>
|
||||
<option value="13">13 - GPIO 71</option>
|
||||
<option value="15">15 - GPIO 10</option>
|
||||
<option value="16">16 - GPIO 194</option>
|
||||
<option value="18">18 - GPIO 195</option>
|
||||
<option value="22">22 - GPIO 87</option>
|
||||
</select>
|
||||
<span id="pitype"></span>
|
||||
</div>
|
||||
<!-- <div class="form-row">
|
||||
<label for="node-input-intype"><i class="fa fa-level-up"></i> Resistor ?</label>
|
||||
<select type="text" id="node-input-intype" style="width: 150px;">
|
||||
<option value="tri">none</option>
|
||||
<option value="up">pullup</option>
|
||||
<option value="down">pulldown</option>
|
||||
</select>
|
||||
</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%;">Read initial state of pin on deploy/restart ?</label>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<div class="form-tips">Tip: Only Digital Input is supported - input must be 0 or 1.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="hb-gpio in">
|
||||
<p>Hummingboard GPIO input pin node. Generates a <b>msg.payload</b> with either a 0 or 1 depending on the state of the input pin.</p>
|
||||
<p>You may also enable the input pullup resitor or the pulldown resistor.</p>
|
||||
<p>The <b>msg.topic</b> is set to <i>pi/{the pin number}</i></p>
|
||||
<p><b>Note:</b> we are using the actual physical pin numbers on connector P1 as they are easier to locate.</p>
|
||||
<p><b>Note:</b> requires the gpiohb command to be executeable as root in order to work.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('hb-gpio in',{
|
||||
category: 'Hummingboard',
|
||||
color:"#c6dbef",
|
||||
defaults: {
|
||||
name: { value:"" },
|
||||
pin: { value:"",required:true,validate:RED.validators.number() },
|
||||
intype: { value: "in" },
|
||||
read: { value:false }
|
||||
},
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
icon: "arrow.png",
|
||||
label: function() {
|
||||
return this.name||"Pin: "+this.pin ;
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/x-red" data-template-name="hb-gpio out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-pin"><i class="fa fa-circle"></i> GPIO Pin</label>
|
||||
<select type="text" id="node-input-pin" style="width: 250px;">
|
||||
<option value='' disabled selected style='display:none;'>select pin</option>
|
||||
<option value="7">7 - GPIO 1</option>
|
||||
<option value="11">11 - GPIO 73</option>
|
||||
<option value="12">12 - GPIO 72</option>
|
||||
<option value="13">13 - GPIO 71</option>
|
||||
<option value="15">15 - GPIO 10</option>
|
||||
<option value="16">16 - GPIO 194</option>
|
||||
<option value="18">18 - GPIO 195</option>
|
||||
<option value="22">22 - GPIO 87</option>
|
||||
</select>
|
||||
<span id="pitype"></span>
|
||||
</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%;">Initialise pin state ?</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">initial level of pin - low (0)</option>
|
||||
<option value="1">initial level of pin - high (1)</option>
|
||||
</select>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<div class="form-tips" id="dig-tip"><b>Tip</b>: For digital output - input must be 0 or 1.</div>
|
||||
<!-- <div class="form-tips" id="pwm-tip"><b>Tip</b>: For PWM output - input must be between 0 to 1023.</div> -->
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="hb-gpio out">
|
||||
<p>Hummingboard GPIO output pin node. Expects a <b>msg.payload</b> with either a 0 or 1 (or true or false).</p>
|
||||
<p>Will set the selected physical pin high or low depending on the value passed in.</p>
|
||||
<p>The initial value of the pin at deploy time can also be set to 0 or 1.</p>
|
||||
<p><b>Note:</b> we are using the actual physical pin numbers as they are easier to locate.</p>
|
||||
<p><b>Note:</b> requires the gpiohb command to be executeable as root in order to work.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('hb-gpio out',{
|
||||
category: 'Hummingboard',
|
||||
color:"#c6dbef",
|
||||
defaults: {
|
||||
name: { value:"" },
|
||||
pin: { value:"",required:true,validate:RED.validators.number() },
|
||||
set: { value:"" },
|
||||
level: { value:"0" }
|
||||
},
|
||||
inputs:1,
|
||||
outputs:0,
|
||||
icon: "arrow.png",
|
||||
align: "right",
|
||||
label: function() {
|
||||
return this.name||"Pin: "+this.pin ;
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
oneditprepare: function() {
|
||||
var setstate = function () {
|
||||
if ($('#node-input-set').is(":checked")) {
|
||||
$("#node-set-state").show();
|
||||
} else {
|
||||
$("#node-set-state").hide();
|
||||
}
|
||||
};
|
||||
$("#node-input-set").change(function () { setstate(); });
|
||||
setstate();
|
||||
}
|
||||
});
|
||||
</script>
|
188
hardware/HummingboardGPIO/hb-gpio.js
Normal file
188
hardware/HummingboardGPIO/hb-gpio.js
Normal file
@ -0,0 +1,188 @@
|
||||
/**
|
||||
* 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.
|
||||
**/
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var exec = require('child_process').exec;
|
||||
var fs = require('fs');
|
||||
|
||||
var gpioCommand = '/usr/local/bin/gpiohb';
|
||||
|
||||
//if (!fs.existsSync("/sys/devices/soc0/machine")) { // unlikely if not on a Hummingboard
|
||||
//throw "Info : Ignoring Hummingboard specific node.";
|
||||
//}
|
||||
|
||||
if (!fs.existsSync(gpioCommand)) { // gpio command not installed
|
||||
throw "Error : Can't find "+gpioCommand+" command for Hummingboard.";
|
||||
}
|
||||
|
||||
// Map physical P1 pins to Gordon's Wiring-Pi Pins (as they should be V1/V2 tolerant)
|
||||
var pintable = {
|
||||
// Physical : WiringPi
|
||||
"11":"0",
|
||||
"12":"1",
|
||||
"13":"2",
|
||||
"15":"3",
|
||||
"16":"4",
|
||||
"18":"5",
|
||||
"22":"6",
|
||||
"7":"7",
|
||||
"3":"8",
|
||||
"5":"9",
|
||||
"24":"10",
|
||||
"26":"11",
|
||||
"19":"12",
|
||||
"21":"13",
|
||||
"23":"14",
|
||||
"8":"15",
|
||||
"10":"16",
|
||||
"27":"30",
|
||||
"28":"31",
|
||||
"29":"21",
|
||||
"31":"22",
|
||||
"32":"26",
|
||||
"33":"23",
|
||||
"35":"24",
|
||||
"36":"27",
|
||||
"37":"25",
|
||||
"38":"28",
|
||||
"40":"29"
|
||||
}
|
||||
var tablepin = {
|
||||
// WiringPi : Physical
|
||||
"0":"11",
|
||||
"1":"12",
|
||||
"2":"13",
|
||||
"3":"15",
|
||||
"4":"16",
|
||||
"5":"18",
|
||||
"6":"22",
|
||||
"7":"7",
|
||||
"8":"3",
|
||||
"9":"5",
|
||||
"10":"24",
|
||||
"11":"26",
|
||||
"12":"19",
|
||||
"13":"21",
|
||||
"14":"23",
|
||||
"15":"8",
|
||||
"16":"10",
|
||||
"30":"27",
|
||||
"31":"28",
|
||||
"21":"29",
|
||||
"22":"31",
|
||||
"26":"32",
|
||||
"23":"33",
|
||||
"24":"35",
|
||||
"27":"36",
|
||||
"25":"37",
|
||||
"28":"38",
|
||||
"29":"40"
|
||||
}
|
||||
|
||||
function GPIOHBInNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.buttonState = -1;
|
||||
this.pin = pintable[n.pin];
|
||||
this.intype = n.intype;
|
||||
this.read = n.read || false;
|
||||
if (this.read) { this.buttonState = -2; }
|
||||
var node = this;
|
||||
|
||||
var readit = function() {
|
||||
exec(gpioCommand+" read "+node.pin, function(err,stdout,stderr) {
|
||||
if (err) { node.error(err); }
|
||||
else {
|
||||
exec(gpioCommand+" wfi "+node.pin + " both", function(err,stdo,stde) {
|
||||
if (err) { node.error(err); }
|
||||
else { readit(); }
|
||||
});
|
||||
if (node.buttonState !== Number(stdout)) {
|
||||
var previousState = node.buttonState;
|
||||
node.buttonState = Number(stdout);
|
||||
if (previousState !== -1) {
|
||||
var msg = {topic:"pi/"+tablepin[node.pin], payload:(node.buttonState === 0 ? 0 : 1)};
|
||||
node.send(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (node.pin !== undefined) {
|
||||
exec(gpioCommand+" mode "+node.pin+" "+node.intype, function(err,stdout,stderr) {
|
||||
if (err) { node.error(err); }
|
||||
else {
|
||||
readit();
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
node.error("Invalid GPIO pin: "+node.pin);
|
||||
}
|
||||
|
||||
node.on("close", function() {
|
||||
clearInterval(node._interval);
|
||||
exec(gpioCommand+" close "+node.pin);
|
||||
});
|
||||
}
|
||||
|
||||
function GPIOHBOutNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.pin = pintable[n.pin];
|
||||
this.set = n.set || false;
|
||||
this.level = n.level || 0;
|
||||
this.out = n.out || "out";
|
||||
var node = this;
|
||||
(node.out === "pwm") ? (node.op = "pwm") : (node.op = "write");
|
||||
|
||||
if (node.pin !== undefined) {
|
||||
exec(gpioCommand+" mode "+node.pin+" "+node.out, function(err,stdout,stderr) {
|
||||
if (err) { node.error(err); }
|
||||
else {
|
||||
if (node.set && (node.out === "out")) {
|
||||
exec(gpioCommand+" write "+node.pin+" "+node.level, function(err,stdout,stderr) {
|
||||
if (err) { node.error(err); }
|
||||
});
|
||||
}
|
||||
node.on("input", function(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 = 1023; }
|
||||
if ((out >= 0) && (out <= limit)) {
|
||||
exec(gpioCommand+" "+node.op+" "+node.pin+" "+out, function(err,stdout,stderr) {
|
||||
if (err) { node.error(err); }
|
||||
});
|
||||
}
|
||||
else { node.warn("Invalid input: "+out); }
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
node.error("Invalid GPIO pin: "+node.pin);
|
||||
}
|
||||
|
||||
node.on("close", function() {
|
||||
exec(gpioCommand+" close "+node.pin);
|
||||
});
|
||||
}
|
||||
|
||||
RED.nodes.registerType("hb-gpio in",GPIOHBInNode);
|
||||
RED.nodes.registerType("hb-gpio out",GPIOHBOutNode);
|
||||
}
|
26
hardware/HummingboardGPIO/package.json
Normal file
26
hardware/HummingboardGPIO/package.json
Normal file
@ -0,0 +1,26 @@
|
||||
{
|
||||
"name" : "node-red-node-hbgpio",
|
||||
"version" : "0.0.3",
|
||||
"description" : "A Node-RED node for the GPIO of the Hummingboard",
|
||||
"dependencies": {
|
||||
},
|
||||
"repository" : {
|
||||
"type":"tgz",
|
||||
"url":"https://github.com/node-red/node-red-nodes/tree/master/hardware/HummingboardGPIO"
|
||||
},
|
||||
"license": "Apache-2.0",
|
||||
"keywords": [ "node-red", "hummingboard", "gpio" ],
|
||||
"node-red" : {
|
||||
"nodes": {
|
||||
"hb-gpio": "hb-gpio.js"
|
||||
}
|
||||
},
|
||||
"scripts": {
|
||||
"postinstall": "./fixup.sh"
|
||||
},
|
||||
"author": {
|
||||
"name": "Dave Conway-Jones",
|
||||
"email": "ceejay@vnet.ibm.com",
|
||||
"url": "http://nodered.org"
|
||||
}
|
||||
}
|
@ -16,24 +16,24 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="ledborg">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<div class="form-tips">Expects a msg.payload with PiBorg three digit rgb colour string. 000 -> 222</div>
|
||||
<div class="form-tips">See info panel for the various input options.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="ledborg">
|
||||
<p>PiBorg LedBorg LED output node. Expects a <b>msg.payload</b> with a three digit rgb triple, from <b>000</b> to <b>222</b>.</p>
|
||||
<p>See <i><a href="http://www.piborg.com/ledborg/install" target="_new">the PiBorg site</a></i> for more information.</p>
|
||||
<p>You can also now use a <b>msg.payload</b> in the standard hex format "#rrggbb". The clip levels are :</p>
|
||||
<p>You can also use a <b>msg.payload</b> in the standard hex format "#rrggbb". The clip levels are :</p>
|
||||
<p><pre>0x00 - 0x57 = off<br/>0x58 - 0xA7 = 50%<br/>0xA8 - 0xFF = fully on</pre></p>
|
||||
<p>You can also use the @cheerlight colour names - red, amber, green, blue, cyan, magenta, yeloow, orange, pink, purple,
|
||||
<p>You can also use the @cheerlight colour names - red, amber, green, blue, cyan, magenta, yellow, orange, pink, purple,
|
||||
white, warmwhite, black</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('ledborg',{
|
||||
category: 'output',
|
||||
category: 'Rapsberry Pi',
|
||||
color:"GoldenRod",
|
||||
defaults: {
|
||||
name: {value:""}
|
65
hardware/LEDborg/78-ledborg.js
Normal file
65
hardware/LEDborg/78-ledborg.js
Normal file
@ -0,0 +1,65 @@
|
||||
/**
|
||||
* Copyright 2013 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var util = require('util');
|
||||
var fs = require('fs');
|
||||
|
||||
// check if /dev/ledborg exists - if not then don't even show the node.
|
||||
if (!fs.existsSync("/dev/ledborg")) {
|
||||
throw "Info : PiBorg hardware : LedBorg not found";
|
||||
}
|
||||
|
||||
function LedBorgNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
var p1 = /^[0-2][0-2][0-2]$/
|
||||
var p2 = /^\#[A-Fa-f0-9]{6}$/
|
||||
var node = this;
|
||||
|
||||
this.on("input", function(msg) {
|
||||
if (p1.test(msg.payload)) {
|
||||
fs.writeFile('/dev/ledborg', msg.payload, function (err) {
|
||||
if (err) { node.warn(msg.payload+" : No LedBorg found"); }
|
||||
});
|
||||
}
|
||||
else if (p2.test(msg.payload)) {
|
||||
var r = Math.floor(parseInt(msg.payload.slice(1,3),16)/88).toString();
|
||||
var g = Math.floor(parseInt(msg.payload.slice(3,5),16)/88).toString();
|
||||
var b = Math.floor(parseInt(msg.payload.slice(5),16)/88).toString();
|
||||
fs.writeFile('/dev/ledborg', r+g+b, function (err) {
|
||||
if (err) { node.warn(r+g+b+" : No LedBorg found"); }
|
||||
});
|
||||
}
|
||||
else {
|
||||
// you can add fancy colours by name here if you want...
|
||||
// these are the @cheerlight ones.
|
||||
var colors = {"red":"200","green":"020","blue":"002","cyan":"022","white":"222","pink":"201",
|
||||
"warmwhite":"221","purple":"101","magenta":"202","yellow":"220","amber":"220","orange":"210","black":"000"}
|
||||
if (msg.payload.toLowerCase() in colors) {
|
||||
var c = colors[msg.payload.toLowerCase()];
|
||||
fs.writeFile('/dev/ledborg', c, function (err) {
|
||||
if (err) { node.warn(msg.payload+" : No LedBorg found"); }
|
||||
});
|
||||
}
|
||||
else {
|
||||
node.warn("Invalid LedBorg colour code");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("ledborg",LedBorgNode);
|
||||
}
|
177
hardware/LEDborg/LICENSE
Normal file
177
hardware/LEDborg/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
|
25
hardware/LEDborg/README.md
Normal file
25
hardware/LEDborg/README.md
Normal file
@ -0,0 +1,25 @@
|
||||
node-red-node-ledborg
|
||||
=====================
|
||||
|
||||
A <a href="http://nodered.org" target="_new">Node-RED</a> node to control a <a href="https://www.piborg.org/ledborg" target="_new">PiBorg LedBorg</a> baord for a Raspberry Pi.
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
Run the following command in the root directory of your Node-RED install
|
||||
|
||||
npm install node-red-node-ledborg
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
A PiBorg LedBorg LED output node that expects a <b>msg.payload</b> with a three digit rgb triple, from <b>000</b> to <b>222</b>. I.E. there are only 27 possible colours.
|
||||
|
||||
See <i><a href="http://www.piborg.com/ledborg/install" target="_new">the PiBorg site</a></i> for more information.
|
||||
|
||||
You can also now use a <b>msg.payload</b> in the standard hex format "#rrggbb". The clip levels are :
|
||||
|
||||
><pre>0x00 - 0x57 = off<br/>0x58 - 0xA7 = 50%<br/>0xA8 - 0xFF = fully on</pre>
|
||||
|
||||
You can also use the @cheerlight colour names - red, amber, green, blue, cyan, magenta, yellow, orange, pink, purple, white, warmwhite, black
|
23
hardware/LEDborg/package.json
Normal file
23
hardware/LEDborg/package.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"name" : "node-red-node-ledborg",
|
||||
"version" : "0.0.2",
|
||||
"description" : "A Node-RED node to control a PiBorg LedBorg board for a Raspberry Pi.",
|
||||
"dependencies" : {
|
||||
},
|
||||
"repository" : {
|
||||
"type":"git",
|
||||
"url":"https://github.com/node-red/node-red-nodes/tree/master/hardware/ledborg"
|
||||
},
|
||||
"license": "Apache",
|
||||
"keywords": [ "node-red", "ledborg" ],
|
||||
"node-red" : {
|
||||
"nodes" : {
|
||||
"ledborg": "78-ledborg.js"
|
||||
}
|
||||
},
|
||||
"author": {
|
||||
"name": "Dave Conway-Jones",
|
||||
"email": "ceejay@vnet.ibm.com",
|
||||
"url": "http://nodered.org"
|
||||
}
|
||||
}
|
@ -1,161 +0,0 @@
|
||||
/**
|
||||
* Copyright 2013 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var RED = require(process.env.NODE_RED_HOME+"/red/red");
|
||||
var util = require("util");
|
||||
var exec = require('child_process').exec;
|
||||
var fs = require('fs');
|
||||
|
||||
if (!fs.existsSync("/usr/local/bin/gpio")) {
|
||||
exec("cat /proc/cpuinfo | grep BCM27",function(err,stdout,stderr) {
|
||||
if (stdout.indexOf('BCM27') > -1) {
|
||||
util.log('[37-rpi-piface.js] Error: Cannot find Wiring-Pi "gpio" command');
|
||||
}
|
||||
// else not on a Pi so don't worry anyone with needless messages.
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Map names of pins to Gordon's gpio PiFace pin numbers
|
||||
var pintable = {
|
||||
// Physical : WiringPi
|
||||
"Button S1":"200",
|
||||
"Button S2":"201",
|
||||
"Button S3":"202",
|
||||
"Button S4":"203",
|
||||
"Input 5":"204",
|
||||
"Input 6":"205",
|
||||
"Input 7":"206",
|
||||
"Input 8":"207",
|
||||
"Output0":"208",
|
||||
"Output1":"209",
|
||||
"Output2":"210",
|
||||
"Output3":"211",
|
||||
"Output4":"212",
|
||||
"Output5":"213",
|
||||
"Output6":"214",
|
||||
"Output7":"215",
|
||||
"LED 0 / Relay 0":"200",
|
||||
"LED 1 / Relay 1":"201",
|
||||
"LED 2":"202",
|
||||
"LED 3":"203",
|
||||
"LED 4":"204",
|
||||
"LED 5":"205",
|
||||
"LED 6":"206",
|
||||
"LED 7":"207"
|
||||
}
|
||||
var tablepin = {
|
||||
// WiringPi : Physical
|
||||
"200":"S1",
|
||||
"201":"S2",
|
||||
"202":"S3",
|
||||
"203":"S4",
|
||||
"204":"I5",
|
||||
"205":"I6",
|
||||
"206":"I7",
|
||||
"207":"I8",
|
||||
"208":"O0",
|
||||
"209":"O1",
|
||||
"210":"O2",
|
||||
"211":"O3",
|
||||
"212":"O4",
|
||||
"213":"O5",
|
||||
"214":"O6",
|
||||
"215":"O7",
|
||||
"200":"L0",
|
||||
"201":"L1",
|
||||
"202":"L2",
|
||||
"203":"L3",
|
||||
"204":"L4",
|
||||
"205":"L5",
|
||||
"206":"L6",
|
||||
"207":"L7"
|
||||
}
|
||||
|
||||
function PiFACEInNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.buttonState = -1;
|
||||
this.pin = pintable[n.pin];
|
||||
this.intype = n.intype;
|
||||
var node = this;
|
||||
if (node.pin) {
|
||||
exec("gpio -p mode "+node.pin+" "+node.intype, function(err,stdout,stderr) {
|
||||
if (err) node.error(err);
|
||||
else {
|
||||
node._interval = setInterval( function() {
|
||||
exec("gpio -p read "+node.pin, function(err,stdout,stderr) {
|
||||
if (err) node.error(err);
|
||||
else {
|
||||
if (node.buttonState !== Number(stdout)) {
|
||||
var previousState = node.buttonState;
|
||||
node.buttonState = Number(stdout);
|
||||
if (previousState !== -1) {
|
||||
var msg = {topic:"piface/"+tablepin[node.pin], payload:node.buttonState};
|
||||
node.send(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 250);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
node.error("Invalid PiFACE pin: "+node.pin);
|
||||
}
|
||||
}
|
||||
|
||||
function PiFACEOutNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.pin = pintable[n.pin];
|
||||
var node = this;
|
||||
if (node.pin) {
|
||||
node.on("input", function(msg) {
|
||||
if (msg.payload === "true") msg.payload = true;
|
||||
if (msg.payload === "false") msg.payload = false;
|
||||
var out = Number(msg.payload);
|
||||
if ((out == 0)|(out == 1)) {
|
||||
exec("gpio -p write "+node.pin+" "+out, function(err,stdout,stderr) {
|
||||
if (err) node.error(err);
|
||||
});
|
||||
}
|
||||
else node.warn("Invalid input - not 0 or 1");
|
||||
});
|
||||
}
|
||||
else {
|
||||
node.error("Invalid PiFACE pin: "+node.pin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
exec("gpio load spi",function(err,stdout,stderr) {
|
||||
if (err) {
|
||||
util.log('[37-rpi-piface.js] Error: "gpio load spi" command failed for some reason.');
|
||||
}
|
||||
exec("gpio -p reset",function(err,stdout,stderr) {
|
||||
if (err) {
|
||||
util.log('[37-rpi-piface.js] Error: "gpio -p reset" command failed for some reason.');
|
||||
}
|
||||
RED.nodes.registerType("rpi-piface in",PiFACEInNode);
|
||||
RED.nodes.registerType("rpi-piface out",PiFACEOutNode);
|
||||
PiFACEInNode.prototype.close = function() {
|
||||
clearInterval(this._interval);
|
||||
}
|
||||
PiFACEOutNode.prototype.close = function() {
|
||||
}
|
||||
});
|
||||
});
|
@ -1,172 +0,0 @@
|
||||
/**
|
||||
* 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.
|
||||
**/
|
||||
|
||||
var RED = require(process.env.NODE_RED_HOME+"/red/red");
|
||||
var util = require("util");
|
||||
var exec = require('child_process').exec;
|
||||
var fs = require('fs');
|
||||
|
||||
if (!fs.existsSync("/dev/ttyAMA0")) { // unlikely if not on a Pi
|
||||
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.";
|
||||
}
|
||||
|
||||
// Map physical P1 pins to Gordon's Wiring-Pi Pins (as they should be V1/V2 tolerant)
|
||||
var pintable = {
|
||||
// Physical : WiringPi
|
||||
"Amber LED":"0",
|
||||
"Buzzer ":"1",
|
||||
"Red LED":"2",
|
||||
"Out E":"3",
|
||||
"Out F":"4",
|
||||
"Out G":"5",
|
||||
"Out H":"6",
|
||||
"Green LED":"7",
|
||||
"In C":"10",
|
||||
"In B":"11",
|
||||
"In D":"12",
|
||||
"In A":"13",
|
||||
"Red Button":"14",
|
||||
}
|
||||
var tablepin = {
|
||||
// WiringPi : Physical
|
||||
"0":"Amber",
|
||||
"1":"Buzzer",
|
||||
"2":"Red",
|
||||
"3":"E",
|
||||
"4":"F",
|
||||
"5":"G",
|
||||
"6":"H",
|
||||
"7":"Green",
|
||||
"10":"C",
|
||||
"11":"B",
|
||||
"12":"D",
|
||||
"13":"A",
|
||||
"14":"R",
|
||||
}
|
||||
|
||||
function PibrellaIn(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.buttonState = -1;
|
||||
this.pin = pintable[n.pin];
|
||||
var node = this;
|
||||
|
||||
if (this.pin) {
|
||||
exec("gpio mode "+node.pin+" in", function(err,stdout,stderr) {
|
||||
if (err) node.error(err);
|
||||
else {
|
||||
node._interval = setInterval( function() {
|
||||
exec("gpio read "+node.pin, function(err,stdout,stderr) {
|
||||
if (err) node.error(err);
|
||||
else {
|
||||
if (node.buttonState !== Number(stdout)) {
|
||||
var previousState = node.buttonState;
|
||||
node.buttonState = Number(stdout);
|
||||
if (previousState !== -1) {
|
||||
var msg = {topic:"pibrella/"+tablepin[node.pin], payload:node.buttonState};
|
||||
node.send(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 200);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.error("Invalid GPIO pin: "+this.pin);
|
||||
}
|
||||
|
||||
this.on("close", function() {
|
||||
clearInterval(this._interval);
|
||||
});
|
||||
}
|
||||
|
||||
function PibrellaOut(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.pin = pintable[n.pin];
|
||||
var node = this;
|
||||
|
||||
if (this.pin == "1") {
|
||||
exec("gpio mode 1 pwm");
|
||||
process.nextTick(function() {
|
||||
exec("gpio pwm-ms");
|
||||
node.on("input", function(msg) {
|
||||
var out = Number(msg.payload);
|
||||
if (out == 1) { // fixed buzz
|
||||
exec("gpio pwm 1 511");
|
||||
exec("gpio pwmc 100");
|
||||
}
|
||||
else if ((out >= 2) && (out <= 9999)) { // set buzz to a value
|
||||
exec("gpio pwm 1 511");
|
||||
exec("gpio pwmc "+out);
|
||||
}
|
||||
else { exec("gpio pwm 1 0"); } // turn it off
|
||||
});
|
||||
});
|
||||
}
|
||||
else if (this.pin) {
|
||||
process.nextTick(function() {
|
||||
exec("gpio mode "+node.pin+" out", function(err,stdout,stderr) {
|
||||
if (err) node.error(err);
|
||||
else {
|
||||
node.on("input", function(msg) {
|
||||
if (msg.payload === "true") msg.payload = true;
|
||||
if (msg.payload === "false") msg.payload = false;
|
||||
var out = Number(msg.payload);
|
||||
if ((out == 0)|(out == 1)) {
|
||||
exec("gpio write "+node.pin+" "+out, function(err,stdout,stderr) {
|
||||
if (err) node.error(err);
|
||||
});
|
||||
}
|
||||
else node.warn("Invalid input - not 0 or 1");
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.error("Invalid GPIO pin: "+this.pin);
|
||||
}
|
||||
|
||||
this.on("close", function() {
|
||||
exec("gpio mode "+this.pin+" in");
|
||||
});
|
||||
}
|
||||
|
||||
exec("gpio mode 0 out",function(err,stdout,stderr) {
|
||||
if (err) {
|
||||
util.log('[36-rpi-gpio.js] Error: "gpio" command failed for some reason.');
|
||||
}
|
||||
exec("gpio mode 1 out");
|
||||
exec("gpio mode 2 out");
|
||||
exec("gpio mode 3 out");
|
||||
exec("gpio mode 4 out");
|
||||
exec("gpio mode 5 out");
|
||||
exec("gpio mode 6 out");
|
||||
exec("gpio mode 7 out");
|
||||
exec("gpio mode 10 in");
|
||||
exec("gpio mode 11 in");
|
||||
exec("gpio mode 12 in");
|
||||
exec("gpio mode 13 in");
|
||||
exec("gpio mode 14 in");
|
||||
});
|
||||
|
||||
RED.nodes.registerType("rpi-pibrella in",PibrellaIn);
|
||||
RED.nodes.registerType("rpi-pibrella out",PibrellaOut);
|
@ -1,63 +0,0 @@
|
||||
/**
|
||||
* Copyright 2013 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var RED = require(process.env.NODE_RED_HOME+"/red/red");
|
||||
var util = require('util');
|
||||
var fs = require('fs');
|
||||
|
||||
// check if /dev/ledborg exists - if not then don't even show the node.
|
||||
if (!fs.existsSync("/dev/ledborg")) {
|
||||
throw "Info : PiBorg hardware : LedBorg not found";
|
||||
}
|
||||
|
||||
function LedBorgNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
var p1 = /^[0-2][0-2][0-2]$/
|
||||
var p2 = /^\#[A-Fa-f0-9]{6}$/
|
||||
var node = this;
|
||||
|
||||
this.on("input", function(msg) {
|
||||
if (p1.test(msg.payload)) {
|
||||
fs.writeFile('/dev/ledborg', msg.payload, function (err) {
|
||||
if (err) node.warn(msg.payload+" : No LedBorg found");
|
||||
});
|
||||
}
|
||||
else if (p2.test(msg.payload)) {
|
||||
var r = Math.floor(parseInt(msg.payload.slice(1,3),16)/88).toString();
|
||||
var g = Math.floor(parseInt(msg.payload.slice(3,5),16)/88).toString();
|
||||
var b = Math.floor(parseInt(msg.payload.slice(5),16)/88).toString();
|
||||
fs.writeFile('/dev/ledborg', r+g+b, function (err) {
|
||||
if (err) node.warn(r+g+b+" : No LedBorg found");
|
||||
});
|
||||
}
|
||||
else {
|
||||
// you can add fancy colours by name here if you want...
|
||||
// these are the @cheerlight ones.
|
||||
var colors = {"red":"200","green":"020","blue":"002","cyan":"022","white":"222","pink":"201",
|
||||
"warmwhite":"221","purple":"101","magenta":"202","yellow":"220","amber":"220","orange":"210","black":"000"}
|
||||
if (msg.payload.toLowerCase() in colors) {
|
||||
var c = colors[msg.payload.toLowerCase()];
|
||||
fs.writeFile('/dev/ledborg', c, function (err) {
|
||||
if (err) node.warn(msg.payload+" : No LedBorg found");
|
||||
});
|
||||
}
|
||||
else {
|
||||
node.warn("Invalid LedBorg colour code");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("ledborg",LedBorgNode);
|
@ -1,5 +1,5 @@
|
||||
<!--
|
||||
Copyright 2013 IBM Corp.
|
||||
Copyright 2013,2014 IBM Corp.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -16,9 +16,9 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="rpi-piface in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-pin"><i class="icon-asterisk"></i> GPIO Pin</label>
|
||||
<label for="node-input-pin"><i class="fa fa-circle"></i> GPIO Pin</label>
|
||||
<select type="text" id="node-input-pin" style="width: 150px;">
|
||||
<option value="-">select pin</option>
|
||||
<option value='' disabled selected style='display:none;'>select input</option>
|
||||
<option value="Button S1">Button S1</option>
|
||||
<option value="Button S2">Button S2</option>
|
||||
<option value="Button S3">Button S3</option>
|
||||
@ -38,14 +38,20 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-intype"><i class=" icon-resize-full"></i> Resistor?</label>
|
||||
<label for="node-input-intype"><i class="fa fa-level-up"></i> Resistor ?</label>
|
||||
<select type="text" id="node-input-intype" style="width: 150px;">
|
||||
<option value="up">pullup</option>
|
||||
<option value="tri">none</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<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%;">Read initial state of pin on deploy/restart ?</label>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<div class="form-tips">Tip: Only Digital I/O is supported - input must be 0 or 1.</div>
|
||||
@ -61,12 +67,13 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('rpi-piface in',{
|
||||
category: 'advanced-input',
|
||||
category: 'Raspberry Pi',
|
||||
color:"#c6dbef",
|
||||
defaults: {
|
||||
name: { value:"" },
|
||||
intype: { value: "up" },
|
||||
pin: { value:"",required:true},
|
||||
intype: { value: "up" },
|
||||
read: { value:false }
|
||||
},
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
@ -83,9 +90,9 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="rpi-piface out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-pin"><i class="icon-asterisk"></i> GPIO Pin</label>
|
||||
<label for="node-input-pin"><i class="fa fa-circle"></i> GPIO Pin</label>
|
||||
<select type="text" id="node-input-pin" style="width: 150px;">
|
||||
<option value="-">select pin</option>
|
||||
<option value='' disabled selected style='display:none;'>select output</option>
|
||||
<option value="LED 0 / Relay 0">LED 0 / Relay 0</option>
|
||||
<option value="LED 1 / Relay 1">LED 1 / Relay 1</option>
|
||||
<option value="LED 2">LED 2</option>
|
||||
@ -97,7 +104,20 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<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%;">Initialise output state ?</label>
|
||||
</div>
|
||||
<div class="form-row" id="node-set-state">
|
||||
<label for="node-input-level"> </label>
|
||||
<select id="node-input-level" style="width: 300px;">
|
||||
<option value="0">initial level of output - off - low - 0</option>
|
||||
<option value="1">initial level of output - on - high - 1</option>
|
||||
</select>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<div class="form-tips">Tip: Only Digital I/O is supported - input must be 0 or 1.</div>
|
||||
@ -111,11 +131,13 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('rpi-piface out',{
|
||||
category: 'advanced-output',
|
||||
category: 'Raspberry Pi',
|
||||
color:"#c6dbef",
|
||||
defaults: {
|
||||
name: { value:"" },
|
||||
pin: { value:"",required:true},
|
||||
set: { value:false },
|
||||
level: { value:"0" }
|
||||
},
|
||||
inputs:1,
|
||||
outputs:0,
|
||||
@ -126,6 +148,15 @@
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
oneditprepare: function() {
|
||||
$("#node-input-set").change(function() {
|
||||
if ($('#node-input-set').is(":checked")) {
|
||||
$("#node-set-state").show();
|
||||
} else {
|
||||
$("#node-set-state").hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
134
hardware/PiFace/37-rpi-piface.js
Normal file
134
hardware/PiFace/37-rpi-piface.js
Normal file
@ -0,0 +1,134 @@
|
||||
/**
|
||||
* Copyright 2013,2014 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var util = require("util");
|
||||
var exec = require('child_process').exec;
|
||||
var fs = require('fs');
|
||||
|
||||
if (!fs.existsSync("/dev/ttyAMA0")) { // unlikely if not on a Pi
|
||||
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.";
|
||||
}
|
||||
|
||||
// Map names of pins to Gordon's gpio PiFace pin numbers
|
||||
var pintable = {
|
||||
// Physical : WiringPi
|
||||
"Button S1":"200",
|
||||
"Button S2":"201",
|
||||
"Button S3":"202",
|
||||
"Button S4":"203",
|
||||
"Input 5":"204",
|
||||
"Input 6":"205",
|
||||
"Input 7":"206",
|
||||
"Input 8":"207",
|
||||
"Output0":"208",
|
||||
"Output1":"209",
|
||||
"Output2":"210",
|
||||
"Output3":"211",
|
||||
"Output4":"212",
|
||||
"Output5":"213",
|
||||
"Output6":"214",
|
||||
"Output7":"215",
|
||||
"LED 0 / Relay 0":"200",
|
||||
"LED 1 / Relay 1":"201",
|
||||
"LED 2":"202",
|
||||
"LED 3":"203",
|
||||
"LED 4":"204",
|
||||
"LED 5":"205",
|
||||
"LED 6":"206",
|
||||
"LED 7":"207"
|
||||
}
|
||||
|
||||
function PiFACEInNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.buttonState = -1;
|
||||
this.npin = n.pin;
|
||||
this.pin = pintable[n.pin];
|
||||
this.intype = n.intype;
|
||||
this.read = n.read || false;
|
||||
if (this.read) { this.buttonState = -2; }
|
||||
var node = this;
|
||||
if (node.pin) {
|
||||
exec("gpio -p mode "+node.pin+" "+node.intype, function(err,stdout,stderr) {
|
||||
if (err) { node.error(err); }
|
||||
else {
|
||||
node._interval = setInterval( function() {
|
||||
exec("gpio -p read "+node.pin, function(err,stdout,stderr) {
|
||||
if (err) { node.error(err); }
|
||||
else {
|
||||
if (node.buttonState !== Number(stdout)) {
|
||||
var previousState = node.buttonState;
|
||||
node.buttonState = Number(stdout);
|
||||
if (previousState !== -1) {
|
||||
var msg = {topic:"piface/"+node.npin, payload:node.buttonState};
|
||||
node.send(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 200);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
node.error("Invalid PiFACE pin: "+node.pin);
|
||||
}
|
||||
node.on("close", function() {
|
||||
clearInterval(node._interval);
|
||||
});
|
||||
}
|
||||
|
||||
function PiFACEOutNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.pin = pintable[n.pin];
|
||||
var node = this;
|
||||
if (node.pin) {
|
||||
if (node.set) {
|
||||
exec("gpio -p write "+node.pin+" "+node.level, function(err,stdout,stderr) {
|
||||
if (err) { node.error(err); }
|
||||
});
|
||||
}
|
||||
node.on("input", function(msg) {
|
||||
if (msg.payload === "true") { msg.payload = true; }
|
||||
if (msg.payload === "false") { msg.payload = false; }
|
||||
var out = Number(msg.payload);
|
||||
if ((out === 0)|(out === 1)) {
|
||||
exec("gpio -p write "+node.pin+" "+out, function(err,stdout,stderr) {
|
||||
if (err) { node.error(err); }
|
||||
});
|
||||
}
|
||||
else { node.warn("Invalid input - not 0 or 1"); }
|
||||
});
|
||||
}
|
||||
else {
|
||||
node.error("Invalid PiFACE pin: "+node.pin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
exec("gpio load spi",function(err,stdout,stderr) {
|
||||
if (err) {
|
||||
util.log('[37-rpi-piface.js] Error: "gpio load spi" command failed for some reason.');
|
||||
}
|
||||
RED.nodes.registerType("rpi-piface in",PiFACEInNode);
|
||||
RED.nodes.registerType("rpi-piface out",PiFACEOutNode);
|
||||
});
|
||||
}
|
177
hardware/PiFace/LICENSE
Normal file
177
hardware/PiFace/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
|
41
hardware/PiFace/README.md
Normal file
41
hardware/PiFace/README.md
Normal file
@ -0,0 +1,41 @@
|
||||
node-red-node-piface
|
||||
====================
|
||||
|
||||
<a href="http://nodered.org" target="_new">Node-RED</a> nodes to control a <a href="http://www.piface.org.uk/products/piface_digital/" target="_new">PiFace Digital</a> add-on board for a Raspberry-Pi.
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
Run the following command in the root directory of your Node-RED install
|
||||
|
||||
npm install node-red-node-piface
|
||||
|
||||
|
||||
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.
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
A pair of input and output Node-RED nodes for the Raspberry Pi PiFace Digital add-on board.
|
||||
|
||||
###Output
|
||||
|
||||
The PiFace output node will set the selected relay, LED, or pin on or off depending on the value passed in. Expects a <b>msg.payload</b> with either a 1 or 0 (or true or false).
|
||||
|
||||
Requires the WiringPi gpio command in order to work (see pre-reqs).
|
||||
|
||||
###Input
|
||||
|
||||
The PiFace input node generates a <b>msg.payload</b> with either a 0 or 1 depending on the state of the input pin.
|
||||
|
||||
You may also enable the input pullup resistor if required.
|
||||
|
||||
The <b>msg.topic</b> is set to <i>piface/{the pin number}</i>
|
||||
|
||||
Requires the WiringPi gpio command in order to work (see pre-reqs).
|
||||
|
||||
<b>Note:</b> This node currently polls the pin every 250mS. This is not ideal as it loads the cpu.
|
23
hardware/PiFace/package.json
Normal file
23
hardware/PiFace/package.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"name" : "node-red-node-piface",
|
||||
"version" : "0.0.2",
|
||||
"description" : "Node-RED nodes to read from and write to a PiFace Digital Raspberry Pi add-on board",
|
||||
"dependencies" : {
|
||||
},
|
||||
"repository" : {
|
||||
"type":"git",
|
||||
"url":"https://github.com/node-red/node-red-nodes/tree/master/hardware/PiFace"
|
||||
},
|
||||
"license": "Apache",
|
||||
"keywords": [ "node-red", "piface" ],
|
||||
"node-red" : {
|
||||
"nodes" : {
|
||||
"piface": "37-rpi-piface.js"
|
||||
}
|
||||
},
|
||||
"author": {
|
||||
"name": "Dave Conway-Jones",
|
||||
"email": "ceejay@vnet.ibm.com",
|
||||
"url": "http://nodered.org"
|
||||
}
|
||||
}
|
68
hardware/PiLiter/39-rpi-piliter.html
Normal file
68
hardware/PiLiter/39-rpi-piliter.html
Normal file
@ -0,0 +1,68 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<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;">
|
||||
<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>
|
||||
<option value="bar">0-8 : turns on leds up to value - bar</option>
|
||||
<option value="pin">object : select led and set state</option>
|
||||
<option value="all">0/1 : turn off/on ALL leds</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<div class="form-tips">See the Info panel for descriptions of the different modes.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-liter">
|
||||
<p>Raspberry Pi-LITEr output node. The Pi-LITEr must be fitted.</p>
|
||||
<p>Operates in one of 5 different modes :</p>
|
||||
<ul>
|
||||
<li><b>Byte Mode</b> - expects a value between 0 and 255, and each of the LEDs represent 1 bit.</li>
|
||||
<li><b>Meter Mode</b> - expects a value between 0 and 8, the led lit corresponds to the input value - like a meter needle.</li>
|
||||
<li><b>Bar Mode</b> - expects a value between 0 and 8, similar to meter - but all the leds up to the value are turned on - like a mini bar chart.</li>
|
||||
<li><b>Object Mode</b> - expects a object specifying the LED and state eg. <code>{led:3,state:0}</code> to set LED3 off.</li>
|
||||
<li><b>All LEDs Mode</b> - expects a 1 or 0 - turns on and off ALL the LEDs.</li>
|
||||
</ul>
|
||||
<p>Requires the WiringPi gpio command in order to work.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('rpi-liter',{
|
||||
category: 'Raspberry Pi',
|
||||
color:"GoldenRod",
|
||||
defaults: {
|
||||
name: { value:"" },
|
||||
pin: { value:"",required:true }
|
||||
},
|
||||
inputs:1,
|
||||
outputs:0,
|
||||
icon: "light.png",
|
||||
align: "right",
|
||||
label: function() {
|
||||
return this.name||"Pi-LITEr";
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
142
hardware/PiLiter/39-rpi-piliter.js
Normal file
142
hardware/PiLiter/39-rpi-piliter.js
Normal file
@ -0,0 +1,142 @@
|
||||
/**
|
||||
* 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.
|
||||
**/
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var exec = require('child_process').exec;
|
||||
var fs = require('fs');
|
||||
|
||||
if (!fs.existsSync("/dev/ttyAMA0")) { // unlikely if not on a Pi
|
||||
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.";
|
||||
}
|
||||
|
||||
// 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",
|
||||
}
|
||||
|
||||
function PiLiter(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.pin = pintable[n.pin];
|
||||
this.pinv = n.pin;
|
||||
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.on("input", function(msg) {
|
||||
var out = Number(msg.payload);
|
||||
if ((out >= 1)&&(out <= 8)) { exec("gpio wb "+barpins[out]); }
|
||||
else { exec("gpio wb 0"); }
|
||||
});
|
||||
}
|
||||
else if (this.pinv === "meter") {
|
||||
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"); }
|
||||
});
|
||||
}
|
||||
else if (this.pinv === "all") {
|
||||
node.on("input", function(msg) {
|
||||
var out = msg.payload;
|
||||
if ((out === 1)|(out === true)|(out === "1")|(out === "on")) {
|
||||
exec("gpio wb 255");
|
||||
}
|
||||
else { exec("gpio wb 0"); }
|
||||
});
|
||||
}
|
||||
else if (this.pinv === "pin") {
|
||||
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);
|
||||
}
|
||||
else { node.warn("Not a valid object - see Info panel."); }
|
||||
}
|
||||
else { node.warn("Not a valid object - see Info panel."); }
|
||||
});
|
||||
}
|
||||
else {
|
||||
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);
|
||||
}
|
||||
else { node.warn("Invalid input - not between 0 and 255"); }
|
||||
});
|
||||
}
|
||||
node.on("close", function() {
|
||||
exec("gpio wb 0");
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("rpi-liter",PiLiter);
|
||||
}
|
177
hardware/PiLiter/LICENSE
Normal file
177
hardware/PiLiter/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
|
33
hardware/PiLiter/README.md
Normal file
33
hardware/PiLiter/README.md
Normal file
@ -0,0 +1,33 @@
|
||||
node-red-node-piliter
|
||||
=====================
|
||||
|
||||
A <a href="http://nodered.org" target="_new">Node-RED</a> node to control a Pimorini Pi-LITEr 8 LED add-on board for a Raspberry-Pi.
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
Run the following command in the root directory of your Node-RED install
|
||||
|
||||
npm install node-red-node-piliter
|
||||
|
||||
|
||||
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.
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Raspberry Pi-LITEr output node. The Pi-LITEr must be fitted.
|
||||
|
||||
Operates in one of 5 different modes :
|
||||
|
||||
- Byte Mode - expects a value between 0 and 255, and each of the LEDs represent 1 bit.
|
||||
- Meter Mode - expects a value between 0 and 8, the led lit corresponds to the input value - like a meter needle.
|
||||
- Bar Mode - expects a value between 0 and 8, similar to meter - but all the leds up to the value are turned on - like a mini bar chart.
|
||||
- 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.
|
23
hardware/PiLiter/package.json
Normal file
23
hardware/PiLiter/package.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"name" : "node-red-node-piliter",
|
||||
"version" : "0.0.3",
|
||||
"description" : "A Node-RED node to drive a Raspberry Pi Pi-LITEr 8 LED board.",
|
||||
"dependencies" : {
|
||||
},
|
||||
"repository" : {
|
||||
"type":"git",
|
||||
"url":"https://github.com/node-red/node-red-nodes/tree/master/hardware/PiLiter"
|
||||
},
|
||||
"license": "Apache",
|
||||
"keywords": [ "node-red", "piliter" ],
|
||||
"node-red" : {
|
||||
"nodes" : {
|
||||
"rpi-piliter": "39-rpi-piliter.js"
|
||||
}
|
||||
},
|
||||
"author": {
|
||||
"name": "Dave Conway-Jones",
|
||||
"email": "ceejay@vnet.ibm.com",
|
||||
"url": "http://nodered.org"
|
||||
}
|
||||
}
|
@ -16,9 +16,9 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="rpi-pibrella in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-pin"><i class="icon-asterisk"></i> Input</label>
|
||||
<label for="node-input-pin"><i class="fa fa-circle"></i> Input</label>
|
||||
<select type="text" id="node-input-pin" style="width: 150px;">
|
||||
<option value="-">select input</option>
|
||||
<option value='' disabled selected style='display:none;'>select input</option>
|
||||
<option value="Red Button">Red Button</option>
|
||||
<option value="In A">In A</option>
|
||||
<option value="In B">In B</option>
|
||||
@ -27,7 +27,13 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<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%;">Read initial state of pin on deploy/restart ?</label>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
@ -41,11 +47,12 @@
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('rpi-pibrella in',{
|
||||
category: 'advanced-input',
|
||||
category: 'Raspberry Pi',
|
||||
color:"#c6dbef",
|
||||
defaults: {
|
||||
name: { value:"" },
|
||||
pin: { value:"",required:true,validate:RED.validators.regex(/ /) }
|
||||
pin: { value:"",required:true,validate:RED.validators.regex(/ /) },
|
||||
read: { value:false }
|
||||
},
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
@ -62,9 +69,9 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="rpi-pibrella out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-pin"><i class="icon-asterisk"></i> Output</label>
|
||||
<label for="node-input-pin"><i class="fa fa-circle"></i> Output</label>
|
||||
<select type="text" id="node-input-pin" style="width: 150px;">
|
||||
<option value="-">select output</option>
|
||||
<option value='' disabled selected style='display:none;'>select output</option>
|
||||
<option value="Red LED">Red LED</option>
|
||||
<option value="Amber LED">Amber LED</option>
|
||||
<option value="Green LED">Green LED</option>
|
||||
@ -75,27 +82,43 @@
|
||||
<option value="Buzzer ">Buzzer</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row" id="node-set-check">
|
||||
<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%;">Initialise output state ?</label>
|
||||
</div>
|
||||
<div class="form-row" id="node-set-state" hidden>
|
||||
<label for="node-input-level"> </label>
|
||||
<select id="node-input-level" style="width: 300px;">
|
||||
<option value="0">initial level of output - off - low - 0</option>
|
||||
<option value="1">initial level of output - on - high - 1</option>
|
||||
</select>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<div class="form-tips">Buzzer takes <b>msg.payload</b> between 2 (high) and 512 (low), or 0 for off.</div>
|
||||
<div class="form-tips" id="node-buzz-tip">Buzzer takes <b>msg.payload</b> between 2 (high) and 512 (low), or 0 for off.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-pibrella out">
|
||||
<p>Raspberry Pi Pibrella output node. The Pibrella board must be fitted.</p>
|
||||
<p>Will set the selected output high (on) or low (off) depending on the value passed in. Expects a <b>msg.payload</b> with either a 0 or 1 (or true or false).</p>
|
||||
<p>The Buzzer is a divider so low numbers are high notes. 0 is off, and the sensible lowest note is around 250-300. 2 is the highest note. 1 is just a buzz (so you can use 0/1 type inputs).</p>
|
||||
<p><b>Note:</b> Using the buzzer is known to "kill" audio output via the 3.5mm socket.</p>
|
||||
<p>Requires the WiringPi gpio command in order to work.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('rpi-pibrella out',{
|
||||
category: 'advanced-output',
|
||||
category: 'Raspberry Pi',
|
||||
color:"#c6dbef",
|
||||
defaults: {
|
||||
name: { value:"" },
|
||||
pin: { value:"",required:true,validate:RED.validators.regex(/ /) }
|
||||
pin: { value:"",required:true,validate:RED.validators.regex(/ /) },
|
||||
set: { value:false },
|
||||
level: { value:"0" }
|
||||
},
|
||||
inputs:1,
|
||||
outputs:0,
|
||||
@ -106,6 +129,25 @@
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
oneditprepare: function() {
|
||||
$("#node-input-set").change(function() {
|
||||
if ($('#node-input-set').is(":checked")) {
|
||||
$("#node-set-state").show();
|
||||
} else {
|
||||
$("#node-set-state").hide();
|
||||
}
|
||||
});
|
||||
$("#node-input-pin").change(function() {
|
||||
if ($('#node-input-pin').val() !== "Buzzer ") {
|
||||
$("#node-set-check").show();
|
||||
$("#node-buzz-tip").hide();
|
||||
} else {
|
||||
$("#node-set-check").hide();
|
||||
$("#node-buzz-tip").show();
|
||||
}
|
||||
$("#node-input-set").change();
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
181
hardware/Pibrella/38-rpi-pibrella.js
Normal file
181
hardware/Pibrella/38-rpi-pibrella.js
Normal file
@ -0,0 +1,181 @@
|
||||
/**
|
||||
* 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.
|
||||
**/
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var util = require("util");
|
||||
var exec = require('child_process').exec;
|
||||
var fs = require('fs');
|
||||
|
||||
if (!fs.existsSync("/dev/ttyAMA0")) { // unlikely if not on a Pi
|
||||
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.";
|
||||
}
|
||||
|
||||
// Map physical P1 pins to Gordon's Wiring-Pi Pins (as they should be V1/V2 tolerant)
|
||||
var pintable = {
|
||||
// Physical : WiringPi
|
||||
"Amber LED":"0",
|
||||
"Buzzer ":"1",
|
||||
"Red LED":"2",
|
||||
"Out E":"3",
|
||||
"Out F":"4",
|
||||
"Out G":"5",
|
||||
"Out H":"6",
|
||||
"Green LED":"7",
|
||||
"In C":"10",
|
||||
"In B":"11",
|
||||
"In D":"12",
|
||||
"In A":"13",
|
||||
"Red Button":"14",
|
||||
}
|
||||
var tablepin = {
|
||||
// WiringPi : Physical
|
||||
"0":"Amber",
|
||||
"1":"Buzzer",
|
||||
"2":"Red",
|
||||
"3":"E",
|
||||
"4":"F",
|
||||
"5":"G",
|
||||
"6":"H",
|
||||
"7":"Green",
|
||||
"10":"C",
|
||||
"11":"B",
|
||||
"12":"D",
|
||||
"13":"A",
|
||||
"14":"R",
|
||||
}
|
||||
|
||||
function PibrellaIn(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.buttonState = -1;
|
||||
this.pin = pintable[n.pin];
|
||||
this.read = n.read || false;
|
||||
if (this.read) { this.buttonState = -2; }
|
||||
var node = this;
|
||||
|
||||
if (node.pin) {
|
||||
exec("gpio mode "+node.pin+" in", function(err,stdout,stderr) {
|
||||
if (err) { node.error(err); }
|
||||
else {
|
||||
node._interval = setInterval( function() {
|
||||
exec("gpio read "+node.pin, function(err,stdout,stderr) {
|
||||
if (err) { node.error(err); }
|
||||
else {
|
||||
if (node.buttonState !== Number(stdout)) {
|
||||
var previousState = node.buttonState;
|
||||
node.buttonState = Number(stdout);
|
||||
if (previousState !== -1) {
|
||||
var msg = {topic:"pibrella/"+tablepin[node.pin], payload:node.buttonState};
|
||||
node.send(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}, 200);
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
node.error("Invalid GPIO pin: "+node.pin);
|
||||
}
|
||||
|
||||
node.on("close", function() {
|
||||
clearInterval(node._interval);
|
||||
});
|
||||
}
|
||||
|
||||
function PibrellaOut(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.pin = pintable[n.pin];
|
||||
this.set = n.set || false;
|
||||
this.level = n.level || 0;
|
||||
var node = this;
|
||||
|
||||
if (node.pin == "1") {
|
||||
exec("gpio mode 1 pwm");
|
||||
process.nextTick(function() {
|
||||
exec("gpio pwm-ms");
|
||||
node.on("input", function(msg) {
|
||||
var out = Number(msg.payload);
|
||||
if (out == 1) { // fixed buzz
|
||||
exec("gpio pwm 1 511");
|
||||
exec("gpio pwmc 100");
|
||||
}
|
||||
else if ((out >= 2) && (out <= 9999)) { // set buzz to a value
|
||||
exec("gpio pwm 1 511");
|
||||
exec("gpio pwmc "+out);
|
||||
}
|
||||
else { exec("gpio pwm 1 0"); } // turn it off
|
||||
});
|
||||
});
|
||||
}
|
||||
else if (node.pin) {
|
||||
exec("gpio mode "+node.pin+" out", function(err,stdout,stderr) {
|
||||
if (err) { node.error(err); }
|
||||
else {
|
||||
if (node.set) {
|
||||
exec("gpio write "+node.pin+" "+node.level, function(err,stdout,stderr) {
|
||||
if (err) { node.error(err); }
|
||||
});
|
||||
}
|
||||
node.on("input", function(msg) {
|
||||
if (msg.payload === "true") { msg.payload = true; }
|
||||
if (msg.payload === "false") { msg.payload = false; }
|
||||
var out = Number(msg.payload);
|
||||
if ((out === 0)|(out === 1)) {
|
||||
exec("gpio write "+node.pin+" "+out, function(err,stdout,stderr) {
|
||||
if (err) { node.error(err); }
|
||||
});
|
||||
}
|
||||
else { node.warn("Invalid input - not 0 or 1"); }
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
node.error("Invalid GPIO pin: "+node.pin);
|
||||
}
|
||||
|
||||
node.on("close", function() {
|
||||
exec("gpio mode "+node.pin+" in");
|
||||
});
|
||||
}
|
||||
|
||||
//exec("gpio mode 0 out",function(err,stdout,stderr) {
|
||||
//if (err) {
|
||||
//util.log('[36-rpi-gpio.js] Error: "gpio" command failed for some reason.');
|
||||
//}
|
||||
//exec("gpio mode 1 out");
|
||||
//exec("gpio mode 2 out");
|
||||
//exec("gpio mode 3 out");
|
||||
//exec("gpio mode 4 out");
|
||||
//exec("gpio mode 5 out");
|
||||
//exec("gpio mode 6 out");
|
||||
//exec("gpio mode 7 out");
|
||||
//exec("gpio mode 10 in");
|
||||
//exec("gpio mode 11 in");
|
||||
//exec("gpio mode 12 in");
|
||||
//exec("gpio mode 13 in");
|
||||
//exec("gpio mode 14 in");
|
||||
//});
|
||||
|
||||
RED.nodes.registerType("rpi-pibrella in",PibrellaIn);
|
||||
RED.nodes.registerType("rpi-pibrella out",PibrellaOut);
|
||||
}
|
177
hardware/Pibrella/LICENSE
Normal file
177
hardware/Pibrella/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
|
38
hardware/Pibrella/README.md
Normal file
38
hardware/Pibrella/README.md
Normal file
@ -0,0 +1,38 @@
|
||||
node-red-node-pibrella
|
||||
======================
|
||||
A <a href="http://nodered.org" target="_new">Node-RED</a> node to control a <a href="http://pibrealla.com/" target="_new">Pibrella</a> add-on board for a Raspberry-Pi.
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
Run the following command in the root directory of your Node-RED install
|
||||
|
||||
npm install node-red-node-pibrella
|
||||
|
||||
|
||||
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.
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
A pair of input and output Node-RED nodes for the Raspberry Pi Pibrella from Pimoroni.
|
||||
|
||||
###Output
|
||||
|
||||
The output node will set the selected output high (on) or low (off) depending on the value passed in. Expects a <b>msg.payload</b> with either a 0 or 1 (or true or false).
|
||||
|
||||
The Buzzer is a divider so low numbers are high notes. 0 is off, and the sensible lowest note is around 250-300. 2 is the highest note. 1 is just a buzz - so you can use 0/1 type inputs.
|
||||
|
||||
**Note:** Using the buzzer is known to "kill" audio output via the 3.5mm socket.
|
||||
|
||||
###Input
|
||||
|
||||
The input node generates a <b>msg.payload</b> with either a 0 or 1 depending on the state of the input pin.
|
||||
|
||||
The <b>msg.topic</b> is set to <i>pibrella/{the pin id}</i> - which will be A, B, C, D or R.
|
||||
|
||||
<b>Note:</b> This node currently polls the pin every 250mS. This is not ideal as it loads the cpu.
|
23
hardware/Pibrella/package.json
Normal file
23
hardware/Pibrella/package.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"name" : "node-red-node-pibrella",
|
||||
"version" : "0.0.4",
|
||||
"description" : "A Node-RED node to read from and write to a Pibrella Raspberry Pi add-on board",
|
||||
"dependencies" : {
|
||||
},
|
||||
"repository" : {
|
||||
"type":"git",
|
||||
"url":"https://github.com/node-red/node-red-nodes/tree/master/hardware/Pibrella"
|
||||
},
|
||||
"license": "Apache",
|
||||
"keywords": [ "node-red", "pibrella" ],
|
||||
"node-red" : {
|
||||
"nodes" : {
|
||||
"pibrella": "38-rpi-pibrella.js"
|
||||
}
|
||||
},
|
||||
"author": {
|
||||
"name": "Dave Conway-Jones",
|
||||
"email": "ceejay@vnet.ibm.com",
|
||||
"url": "http://nodered.org"
|
||||
}
|
||||
}
|
@ -1,50 +0,0 @@
|
||||
<!--
|
||||
Copyright 2013 IBM Corp.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-template-name="blinkstick">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<div class="form-tips">Expects a msg.payload with either hex #rrggbb or decimal red,green,blue.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="blinkstick">
|
||||
<p>BlinkStick output node. Expects a <b>msg.payload</b> with either a hex string #rrggbb triple or red,green,blue as three 0-255 values.
|
||||
It can also accept <i><a href="http://www.w3schools.com/html/html_colornames.asp" target="_new">standard HTML colour</a></i> names</p>
|
||||
<p><b>NOTE:</b> currently only works with a single BlinkStick. (As it uses the findFirst() function to attach).</p>
|
||||
<p>For more info see the <i><a href="http://blinkstick.com/" target="_new">BlinkStick website</a></i> or the <i><a href="https://github.com/arvydas/blinkstick-node" target="_new">node module</a></i> documentation.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('blinkstick',{
|
||||
category: 'output',
|
||||
color:"GoldenRod",
|
||||
defaults: {
|
||||
name: {value:""}
|
||||
},
|
||||
inputs:1,
|
||||
outputs:0,
|
||||
icon: "light.png",
|
||||
align: "right",
|
||||
label: function() {
|
||||
return this.name||"blinkstick";
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
@ -1,62 +0,0 @@
|
||||
/**
|
||||
* Copyright 2013 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var RED = require(process.env.NODE_RED_HOME+"/red/red");
|
||||
var blinkstick = require("blinkstick");
|
||||
|
||||
Object.size = function(obj) {
|
||||
var size = 0, key;
|
||||
for (key in obj) { if (obj.hasOwnProperty(key)) size++; }
|
||||
return size;
|
||||
};
|
||||
|
||||
function BlinkStick(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
var p1 = /^\#[A-Fa-f0-9]{6}$/
|
||||
var p2 = /[0-9]+,[0-9]+,[0-9]+/
|
||||
this.led = blinkstick.findFirst(); // maybe try findAll() (one day)
|
||||
var node = this;
|
||||
|
||||
this.on("input", function(msg) {
|
||||
if (msg != null) {
|
||||
if (Object.size(node.led) !== 0) {
|
||||
try {
|
||||
if (p2.test(msg.payload)) {
|
||||
var rgb = msg.payload.split(",");
|
||||
node.led.setColor(parseInt(rgb[0])&255, parseInt(rgb[1])&255, parseInt(rgb[2])&255);
|
||||
}
|
||||
else {
|
||||
node.led.setColor(msg.payload.toLowerCase().replace(/\s+/g,''));
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
node.warn("BlinkStick missing ?");
|
||||
node.led = blinkstick.findFirst();
|
||||
}
|
||||
}
|
||||
else {
|
||||
//node.warn("No BlinkStick found");
|
||||
node.led = blinkstick.findFirst();
|
||||
}
|
||||
}
|
||||
});
|
||||
if (Object.size(node.led) === 0) {
|
||||
node.error("No BlinkStick found");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
RED.nodes.registerType("blinkstick",BlinkStick);
|
@ -1,83 +0,0 @@
|
||||
/**
|
||||
* Copyright 2013 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var RED = require(process.env.NODE_RED_HOME+"/red/red");
|
||||
var Blink1 = require("node-blink1");
|
||||
// create a single global blink1 object
|
||||
// all blink1 nodes affect the same (single) led
|
||||
var blink1 = null;
|
||||
|
||||
function Blink1Node(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.fade = Number(n.fade) || 0;
|
||||
var node = this;
|
||||
|
||||
try {
|
||||
var p1 = /^\#[A-Fa-f0-9]{6}$/
|
||||
var p2 = /[0-9]+,[0-9]+,[0-9]+/
|
||||
this.on("input", function(msg) {
|
||||
blink1 = blink1 || new Blink1.Blink1();
|
||||
if (blink1) {
|
||||
try {
|
||||
if (p1.test(msg.payload)) {
|
||||
// if it is a hex colour string
|
||||
var r = parseInt(msg.payload.slice(1,3),16);
|
||||
var g = parseInt(msg.payload.slice(3,5),16);
|
||||
var b = parseInt(msg.payload.slice(5),16);
|
||||
if (node.fade == 0) { blink1.setRGB( r, g, b ); }
|
||||
else { blink1.fadeToRGB(node.fade, r, g, b ); }
|
||||
}
|
||||
else if (p2.test(msg.payload)) {
|
||||
// if it is a r,g,b triple
|
||||
var rgb = msg.payload.split(',');
|
||||
if (node.fade == 0) { blink1.setRGB(parseInt(rgb[0])&255, parseInt(rgb[1])&255, parseInt(rgb[2])&255); }
|
||||
else { blink1.fadeToRGB(node.fade, parseInt(rgb[0])&255, parseInt(rgb[1])&255, parseInt(rgb[2])&255); }
|
||||
}
|
||||
else {
|
||||
// you can add fancy colours by name here if you want...
|
||||
// these are the @cheerlight ones.
|
||||
var colors = {"red":"#FF0000","green":"#008000","blue":"#0000FF","cyan":"#00FFFF","white":"#FFFFFF","warmwhite":"#FDF5E6",
|
||||
"purple":"#800080","magenta":"#FF00FF","yellow":"#FFFF00","amber":"#FFD200","orange":"#FFA500","black":"#000000"}
|
||||
if (msg.payload.toLowerCase() in colors) {
|
||||
var c = colors[msg.payload.toLowerCase()];
|
||||
var r = parseInt(c.slice(1,3),16);
|
||||
var g = parseInt(c.slice(3,5),16);
|
||||
var b = parseInt(c.slice(5),16);
|
||||
if (node.fade == 0) { blink1.setRGB( r, g, b ); }
|
||||
else { blink1.fadeToRGB(node.fade, r, g, b ); }
|
||||
}
|
||||
else {
|
||||
node.warn("Blink1 : invalid msg : "+msg.payload);
|
||||
}
|
||||
}
|
||||
} catch (e) { node.warn("Blink1 : error"); blink1 = null; }
|
||||
}
|
||||
else {
|
||||
node.warn("Blink1 : not found");
|
||||
}
|
||||
});
|
||||
this.on("close", function() {
|
||||
if (blink1 && typeof blink1.close == "function") {
|
||||
//blink1.close(); //This ought to work but seems to cause more hangs on closing than not...
|
||||
}
|
||||
blink1 = null;
|
||||
});
|
||||
}
|
||||
catch(e) {
|
||||
node.error("No Blink1 found (" + e + ")");
|
||||
}
|
||||
}
|
||||
RED.nodes.registerType("blink1",Blink1Node);
|
@ -16,11 +16,11 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="blink1">
|
||||
<div class="form-row">
|
||||
<label for="node-input-fade"><i class="icon-signal"></i> Fade (mS)</label>
|
||||
<label for="node-input-fade"><i class="fa fa-signal"></i> Fade (mS)</label>
|
||||
<input type="text" id="node-input-fade" placeholder="0">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
@ -28,6 +28,7 @@
|
||||
<script type="text/x-red" data-help-name="blink1">
|
||||
<p>ThingM Blink1 output node.</p>
|
||||
<p>Expects a msg.payload with either a three part csv string of r,g,b or a hex colour #rrggbb</p>
|
||||
<p>Also accepts cheerlight colour names.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
86
hardware/blink1/77-blink1.js
Normal file
86
hardware/blink1/77-blink1.js
Normal file
@ -0,0 +1,86 @@
|
||||
/**
|
||||
* Copyright 2013 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var Blink1 = require("node-blink1");
|
||||
// create a single global blink1 object
|
||||
// all blink1 nodes affect the same (single) led
|
||||
var blink1 = null;
|
||||
|
||||
function Blink1Node(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.fade = Number(n.fade) || 0;
|
||||
var node = this;
|
||||
|
||||
try {
|
||||
var p1 = /^\#[A-Fa-f0-9]{6}$/
|
||||
var p2 = /[0-9]+,[0-9]+,[0-9]+/
|
||||
this.on("input", function(msg) {
|
||||
blink1 = blink1 || new Blink1.Blink1();
|
||||
if (blink1) {
|
||||
var r,g,b;
|
||||
try {
|
||||
if (p1.test(msg.payload)) {
|
||||
// if it is a hex colour string
|
||||
r = parseInt(msg.payload.slice(1,3),16);
|
||||
g = parseInt(msg.payload.slice(3,5),16);
|
||||
b = parseInt(msg.payload.slice(5),16);
|
||||
if (node.fade === 0) { blink1.setRGB( r, g, b ); }
|
||||
else { blink1.fadeToRGB(node.fade, r, g, b ); }
|
||||
}
|
||||
else if (p2.test(msg.payload)) {
|
||||
// if it is a r,g,b triple
|
||||
var rgb = msg.payload.split(',');
|
||||
if (node.fade === 0) { blink1.setRGB(parseInt(rgb[0])&255, parseInt(rgb[1])&255, parseInt(rgb[2])&255); }
|
||||
else { blink1.fadeToRGB(node.fade, parseInt(rgb[0])&255, parseInt(rgb[1])&255, parseInt(rgb[2])&255); }
|
||||
}
|
||||
else {
|
||||
// you can add fancy colours by name here if you want...
|
||||
// these are the @cheerlight ones.
|
||||
var colors = {"red":"#FF0000","green":"#00FF00","blue":"#0000FF","cyan":"#00FFFF","white":"#FFFFFF","warmwhite":"#FDF5E6",
|
||||
"purple":"#800080","magenta":"#FF00FF","yellow":"#FFFF00","amber":"#FFD200","orange":"#FFA500","black":"#000000"}
|
||||
if (msg.payload.toLowerCase() in colors) {
|
||||
var c = colors[msg.payload.toLowerCase()];
|
||||
r = parseInt(c.slice(1,3),16);
|
||||
g = parseInt(c.slice(3,5),16);
|
||||
b = parseInt(c.slice(5),16);
|
||||
if (node.fade === 0) { blink1.setRGB( r, g, b ); }
|
||||
else { blink1.fadeToRGB(node.fade, r, g, b ); }
|
||||
}
|
||||
else {
|
||||
node.warn("Blink1 : invalid msg : "+msg.payload);
|
||||
}
|
||||
}
|
||||
} catch (e) { node.warn("Blink1 : error"); blink1 = null; }
|
||||
}
|
||||
else {
|
||||
node.warn("Blink1 : not found");
|
||||
}
|
||||
});
|
||||
this.on("close", function() {
|
||||
if (blink1 && typeof blink1.close == "function") {
|
||||
//blink1.close(); //This ought to work but seems to cause more hangs on closing than not...
|
||||
}
|
||||
blink1 = null;
|
||||
});
|
||||
}
|
||||
catch(e) {
|
||||
node.error("No Blink1 found (" + e + ")");
|
||||
}
|
||||
}
|
||||
RED.nodes.registerType("blink1",Blink1Node);
|
||||
}
|
177
hardware/blink1/LICENSE
Normal file
177
hardware/blink1/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
|
23
hardware/blink1/README.md
Normal file
23
hardware/blink1/README.md
Normal file
@ -0,0 +1,23 @@
|
||||
node-red-node-blink1
|
||||
====================
|
||||
|
||||
A <a href="http://nodered.org" target="_new">Node-RED</a> node to control a <a href="http://thingm.com/products/blink-1/" target="_new">Thingm Blink(1)</a> LED.
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
Run the following command in the root directory of your Node-RED install
|
||||
|
||||
npm install node-red-node-blink1
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Sends the <b>msg.payload</b> to a Thingm Blink(1) LED device. The payload can be any of the following:
|
||||
|
||||
- a three part csv string of r,g,b - e.g. red is 255,0,0
|
||||
- a hex colour #rrggbb - e.g. green is #00FF00
|
||||
- a <a href="http://www.cheerlights.com/control-cheerlights">@cheerlights</a> colour name - e.g. blue
|
||||
|
||||
The @cheerlights colours are - red, amber, green, blue, cyan, magenta, yellow, orange, pink, purple, white, warmwhite, black
|
24
hardware/blink1/package.json
Normal file
24
hardware/blink1/package.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name" : "node-red-node-blink1",
|
||||
"version" : "0.0.2",
|
||||
"description" : "A Node-RED node to control a Thingm Blink(1)",
|
||||
"dependencies" : {
|
||||
"node-blink1" : "0.1.2"
|
||||
},
|
||||
"repository" : {
|
||||
"type":"git",
|
||||
"url":"https://github.com/node-red/node-red-nodes/tree/master/hardware/blink1"
|
||||
},
|
||||
"license": "Apache",
|
||||
"keywords": [ "node-red", "blink1" ],
|
||||
"node-red" : {
|
||||
"nodes" : {
|
||||
"blink1": "77-blink1.js"
|
||||
}
|
||||
},
|
||||
"author": {
|
||||
"name": "Dave Conway-Jones",
|
||||
"email": "ceejay@vnet.ibm.com",
|
||||
"url": "http://nodered.org"
|
||||
}
|
||||
}
|
2
hardware/blinkstick/.gitignore
vendored
Normal file
2
hardware/blinkstick/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
.DS_Store
|
||||
node_modules/
|
189
hardware/blinkstick/76-blinkstick.html
Normal file
189
hardware/blinkstick/76-blinkstick.html
Normal file
@ -0,0 +1,189 @@
|
||||
<!--
|
||||
Copyright 2013-2014 Agile Innovative Ltd.
|
||||
Based on code written by Dave Conway-Jones, IBM Corp.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-template-name="blinkstick">
|
||||
<div class="form-row">
|
||||
<div class="form-row" id="node-input-row-payload">
|
||||
<label for="node-input-serial">Serial</label>
|
||||
<input type="text" id="node-input-serial" placeholder="defaults to first found" style="width:60%">
|
||||
<a id="node-lookup-serial" class="btn"><i id="node-lookup-serial-icon" class="fa fa-search"></i></a>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-task"><i class="fa fa-empire"></i> Task</label>
|
||||
<select id="node-input-task" style="width:125px !important">
|
||||
<option value="set_color">Set Color</option>
|
||||
<option value="blink">Blink</option>
|
||||
<option value="morph">Morph</option>
|
||||
<option value="pulse">Pulse</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div id="delay-details" class="form-row">
|
||||
<label for="node-input-delay"><i class="fa fa-clock-o"></i> Delay</label>
|
||||
<input type="text" id="node-input-delay" placeholder="Delay" style="direction:rtl; width:50px !important">
|
||||
milliseconds
|
||||
</div>
|
||||
<div id="repeats-details" class="form-row">
|
||||
<label for="node-input-repeats"><i class="fa fa-history"></i> Repeats</label>
|
||||
<input type="text" id="node-input-repeats" placeholder="Times" style="direction:rtl; width:50px !important">
|
||||
</div>
|
||||
|
||||
<div id="duration-details" class="form-row">
|
||||
<label for="node-input-duration"><i class="fa fa-clock-o"></i> Duration</label>
|
||||
<input type="text" id="node-input-duration" placeholder="Duration" style="direction:rtl; width:50px !important">
|
||||
milliseconds
|
||||
</div>
|
||||
<div id="steps-details" class="form-row">
|
||||
<label for="node-input-steps"><i class="fa fa-history"></i> Steps</label>
|
||||
<input type="text" id="node-input-steps" placeholder="Steps" style="direction:rtl; width:50px !important">
|
||||
</div>
|
||||
<div id="repeat-details" class="form-row">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-input-repeat" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-input-repeat" style="width: 70%;">Repeat ∞ until next payload received?</label>
|
||||
</div>
|
||||
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<div class="form-tips">Expects a msg.payload with either hex "#rrggbb" or decimal "red,green,blue" string, or HTML color name.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="blinkstick">
|
||||
<p><i><a href="http://www.blinkstick.com" target="_new">BlinkStick</a></i> output node. Expects a <b>msg.payload</b> with one of:</p>
|
||||
<ul>
|
||||
<li>A hex string <b>"#rrggbb"</b> triple</li>
|
||||
<li><b>"red,green,blue"</b> three 0-255 values as a string</li>
|
||||
<li><b>"random"</b> will generate a random color</li>
|
||||
<li><i><a href="http://www.w3schools.com/html/html_colornames.asp" target="_new">Standard HTML color</a></i> name</li>
|
||||
<li><b>object</b> can override any of the parameters</li>
|
||||
</ul>
|
||||
<p>An object payload can override any of the settings on the node. Omitted parameters are left intact. For example:</p>
|
||||
<pre>
|
||||
{ 'color': 'blue' }
|
||||
{ 'task': 'blink', 'color': 'red' }
|
||||
{ 'task': 'pulse', 'color': 'gree', 'duration': 500 }
|
||||
{ 'task': 'morph', 'color': 'orange', 'duration': 500, 'steps': 20 }
|
||||
</pre>
|
||||
<p>For more info see <i><a href="http://www.blinkstick.com/help/tutorials" target="_new">BlinkStick tutorials</a></i>
|
||||
or the <i><a href="https://github.com/arvydas/blinkstick-node" target="_new">node module</a></i> documentation.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
function updateView(task) {
|
||||
if (task == "set_color") {
|
||||
$("#delay-details").hide();
|
||||
$("#repeats-details").hide();
|
||||
$("#duration-details").hide();
|
||||
$("#steps-details").hide();
|
||||
$("#repeat-details").hide();
|
||||
} else if (task == "blink") {
|
||||
$("#delay-details").show();
|
||||
$("#repeats-details").show();
|
||||
$("#duration-details").hide();
|
||||
$("#steps-details").hide();
|
||||
$("#repeat-details").show();
|
||||
} else if (task == "morph") {
|
||||
$("#delay-details").hide();
|
||||
$("#repeats-details").hide();
|
||||
$("#duration-details").show();
|
||||
$("#steps-details").show();
|
||||
$("#repeat-details").hide();
|
||||
} else if (task == "pulse") {
|
||||
$("#delay-details").hide();
|
||||
$("#repeats-details").hide();
|
||||
$("#duration-details").show();
|
||||
$("#steps-details").show();
|
||||
$("#repeat-details").show();
|
||||
}
|
||||
}
|
||||
|
||||
RED.nodes.registerType('blinkstick',{
|
||||
category: 'output',
|
||||
color:"GoldenRod",
|
||||
defaults: { // defines the default editable properties of the node
|
||||
name: {value:""}, // along with default values.
|
||||
serial: {value:""},
|
||||
task: {value:"set_color", validate:function(v) {return ((v === undefined)||v=="set_color"||v=="blink"||v=="morph"||v=="pulse"); }},
|
||||
delay: {value:"500", validate:function(v) {return ((v === undefined)||(/^\d+$/).test(v)); }},
|
||||
repeats: {value:"1", validate:function(v) {return ((v === undefined)||(/^\d+$/).test(v)); }},
|
||||
duration: {value:"1000", validate:function(v) {return ((v === undefined)||(/^\d+$/).test(v)); }},
|
||||
steps: {value:"50", validate:function(v) {return ((v === undefined)||(/^\d+$/).test(v)); }},
|
||||
repeat: {value:false}
|
||||
},
|
||||
inputs:1,
|
||||
outputs:0,
|
||||
icon: "light.png",
|
||||
align: "right",
|
||||
label: function() {
|
||||
return this.name||"blinkstick";
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
oneditprepare: function() {
|
||||
if (!$("#node-input-task").val()) {
|
||||
$("#node-input-task").val("set_color");
|
||||
}
|
||||
|
||||
if (!$("#node-input-delay").val()) {
|
||||
$("#node-input-delay").val(500);
|
||||
}
|
||||
|
||||
if (!$("#node-input-repeats").val()) {
|
||||
$("#node-input-repeats").val(1);
|
||||
}
|
||||
|
||||
if (!$("#node-input-duration").val()) {
|
||||
$("#node-input-duration").val(1000);
|
||||
}
|
||||
|
||||
if (!$("#node-input-steps").val()) {
|
||||
$("#node-input-steps").val(50);
|
||||
}
|
||||
|
||||
$( "#node-input-repeats" ).spinner({min:1,max:100});
|
||||
$( "#node-input-delay" ).spinner({min:10,max:5000});
|
||||
$( "#node-input-duration" ).spinner({min:10,max:5000});
|
||||
$( "#node-input-steps" ).spinner({min:10,max:255});
|
||||
|
||||
$("#node-input-task").on("change",function() {
|
||||
updateView(this.value);
|
||||
});
|
||||
|
||||
updateView(this.task);
|
||||
|
||||
$("#node-lookup-serial").click(function() {
|
||||
$("#node-lookup-serial").addClass('disabled');
|
||||
$.getJSON('blinksticklist',function(data) {
|
||||
$("#node-lookup-serial").removeClass('disabled');
|
||||
var sticks = [];
|
||||
$.each(data, function(i, stick){
|
||||
sticks.push(stick);
|
||||
});
|
||||
$("#node-input-serial").autocomplete({
|
||||
source:sticks,
|
||||
minLength:0,
|
||||
close: function( event, ui ) {
|
||||
$("#node-input-serial").autocomplete( "destroy" );
|
||||
}
|
||||
}).autocomplete("search","");
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
258
hardware/blinkstick/76-blinkstick.js
Normal file
258
hardware/blinkstick/76-blinkstick.js
Normal file
@ -0,0 +1,258 @@
|
||||
/**
|
||||
* Copyright 2013-2014 Agile Innovative Ltd.
|
||||
* Based on code written by Dave Conway-Jones, IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var blinkstick = require("blinkstick");
|
||||
|
||||
var availableTasks = ["set_color", "blink", "pulse", "morph"];
|
||||
|
||||
Object.size = function(obj) {
|
||||
var size = 0;
|
||||
for (var key in obj) { if (obj.hasOwnProperty(key)) { size++; } }
|
||||
return size;
|
||||
};
|
||||
|
||||
//Helper function to convert decimal number to hex with padding
|
||||
function decimalToHex(d, padding) {
|
||||
var hex = Number(d).toString(16);
|
||||
padding = typeof (padding) === "undefined" || padding === null ? padding = 2 : padding;
|
||||
|
||||
while (hex.length < padding) {
|
||||
hex = "0" + hex;
|
||||
}
|
||||
|
||||
return hex;
|
||||
}
|
||||
|
||||
function validateInt(value, defaultValue) {
|
||||
return typeof (value) === "undefined" || value === null ? value = defaultValue : parseInt(value);
|
||||
}
|
||||
|
||||
function validate(value, defaultValue) {
|
||||
return typeof (value) === "undefined" || value === null ? value = defaultValue : value;
|
||||
}
|
||||
|
||||
function validatePayloadObject (obj) {
|
||||
var
|
||||
task = validate(obj.task),
|
||||
delay = validateInt(obj.delay),
|
||||
repeats = validateInt(obj.repeats),
|
||||
duration = validateInt(obj.duration),
|
||||
steps = validateInt(obj.steps),
|
||||
repeat = validate(obj.repeat),
|
||||
color = validate(obj.color);
|
||||
|
||||
if (typeof(task) !== 'undefined' && availableTasks.indexOf(task) === -1) {
|
||||
return "Task is invalid";
|
||||
}
|
||||
|
||||
if (typeof(color) === 'undefined') {
|
||||
return "Color parameter is not set";
|
||||
}
|
||||
|
||||
return { 'task': task, 'delay': delay, 'repeats': repeats, 'duration': duration, 'steps': steps,
|
||||
'repeat': repeat, 'color': color };
|
||||
}
|
||||
|
||||
function BlinkStick(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
|
||||
this.name = n.name;
|
||||
this.serial = n.serial;
|
||||
this.task = n.task || "set_color";
|
||||
this.delay = n.delay || 500;
|
||||
this.repeats = n.repeats || 1;
|
||||
this.duration = n.duration || 1000;
|
||||
this.steps = n.steps || 50;
|
||||
this.repeat = n.repeat;
|
||||
this.closing = false;
|
||||
this.color = '';
|
||||
this.previousColor = '';
|
||||
|
||||
var p1 = /[0-9]+,[0-9]+,[0-9]+/;
|
||||
var node = this;
|
||||
//Keeps track for active animations
|
||||
var animationComplete = true;
|
||||
|
||||
//Find BlinkStick based on serial number if supplied, otherwise look for first
|
||||
//Blinkstick in the USB device list
|
||||
var findBlinkStick = function (callback) {
|
||||
if (typeof(node.serial) == 'string' && node.serial.replace(/\s+/g,'') !== '') {
|
||||
blinkstick.findBySerial(node.serial, function (device) {
|
||||
node.led = device;
|
||||
|
||||
if (Object.size(node.led) === 0) {
|
||||
node.status({fill:"red",shape:"ring",text:"disconnected"});
|
||||
node.error("BlinkStick with serial number " + node.serial + " not found");
|
||||
} else {
|
||||
node.status({fill:"green",shape:"dot",text:"connected"});
|
||||
if (callback) callback();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
node.led = blinkstick.findFirst();
|
||||
|
||||
if (Object.size(node.led) === 0) {
|
||||
node.status({fill:"red",shape:"ring",text:"disconnected"});
|
||||
node.error("No BlinkStick found");
|
||||
} else {
|
||||
node.status({fill:"green",shape:"dot",text:"connected"});
|
||||
if (callback) callback();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//Check if repeat is enabled. Works only for pulse and blink tasks
|
||||
var canRepeat = function () {
|
||||
return node.task == "pulse" || node.task == "blink";
|
||||
};
|
||||
|
||||
//Event handler for all animation complete events
|
||||
var blinkstickAnimationComplete = function (err) {
|
||||
if (typeof(err) !== 'undefined') {
|
||||
node.warn(err);
|
||||
|
||||
if (typeof(err.name) === 'undefined' || err.name !== 'ReferenceError') {
|
||||
//USB error occurred when BlinkStick was animating
|
||||
node.led.close(function (err) {
|
||||
node.led = undefined;
|
||||
findBlinkStick();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
animationComplete = true;
|
||||
|
||||
//Apply queued color animation
|
||||
if (!node.closing && node.color !== '') {
|
||||
//Apply new color only if there was no error or queued color is different from the previous color
|
||||
if (typeof(err) === 'undefined' || typeof(err) !== 'undefined' && node.color != node.previousColor) {
|
||||
applyColor();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var applyColor = function () {
|
||||
animationComplete = false;
|
||||
|
||||
//Store the value of color to check if it has changed
|
||||
node.previousColor = node.color;
|
||||
|
||||
try {
|
||||
//Select animation to perform
|
||||
if (node.task == "pulse") {
|
||||
node.led.pulse(node.color, {'duration': node.duration, 'steps': node.steps }, blinkstickAnimationComplete);
|
||||
} else if (node.task == "morph") {
|
||||
node.led.morph(node.color, {'duration': node.duration, 'steps': node.steps }, blinkstickAnimationComplete);
|
||||
} else if (node.task == "blink") {
|
||||
node.led.blink(node.color,{'repeats': node.repeats, 'delay': node.delay }, blinkstickAnimationComplete);
|
||||
} else {
|
||||
node.led.setColor(node.color, blinkstickAnimationComplete);
|
||||
}
|
||||
} catch (err) {
|
||||
if (err.toString().indexOf("setColor") !== -1) {
|
||||
node.led.setColour(node.color, blinkstickAnimationComplete);
|
||||
node.warn("Old version - please upgrade Blinkstick npm");
|
||||
}
|
||||
else {
|
||||
node.warn("BlinkStick missing ? " + err);
|
||||
}
|
||||
console.log(err);
|
||||
//Reset animation
|
||||
animationComplete = true;
|
||||
//Clear color
|
||||
node.color = '';
|
||||
//Look for a BlinkStick
|
||||
findBlinkStick();
|
||||
return;
|
||||
}
|
||||
|
||||
//Clear color value until next one is received, unless repeat option is set to true
|
||||
if (!node.repeat || !canRepeat()) {
|
||||
node.color = '';
|
||||
}
|
||||
};
|
||||
|
||||
findBlinkStick();
|
||||
|
||||
this.on("input", function(msg) {
|
||||
if (typeof(msg.payload) === 'object' ) {
|
||||
var data = validatePayloadObject(msg.payload);
|
||||
|
||||
if (typeof(data) === 'object') {
|
||||
node.task = data.task ? data.task : node.task;
|
||||
node.delay = data.delay ? data.delay : node.delay;
|
||||
node.repeats = data.repeats ? data.repeats : node.repeats;
|
||||
node.duration = data.duration ? data.duration : node.duration;
|
||||
node.steps = data.steps ? data.steps : node.steps;
|
||||
node.repeat = data.repeat ? data.repeat : node.repeat;
|
||||
node.color = data.color ? data.color : node.color;
|
||||
} else {
|
||||
node.error(data);
|
||||
return;
|
||||
}
|
||||
|
||||
} else if (p1.test(msg.payload)) {
|
||||
//Color value is represented as "red,green,blue" string of bytes
|
||||
var rgb = msg.payload.split(",");
|
||||
|
||||
//Convert color value back to HEX string for easier implementation
|
||||
node.color = "#" + decimalToHex(parseInt(rgb[0])&255) +
|
||||
decimalToHex(parseInt(rgb[1])&255) + decimalToHex(parseInt(rgb[2])&255);
|
||||
} else {
|
||||
//Sanitize color value
|
||||
node.color = msg.payload.toLowerCase().replace(/\s+/g,'');
|
||||
}
|
||||
|
||||
if (Object.size(node.led) !== 0) {
|
||||
//Start color animation, otherwise the color is queued until current animation completes
|
||||
if (animationComplete) {
|
||||
applyColor();
|
||||
}
|
||||
} else {
|
||||
//Attempt to find BlinkStick and start animation if it's found
|
||||
findBlinkStick(function() {
|
||||
if (animationComplete) {
|
||||
applyColor();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
this.on("close", function() {
|
||||
//Set the flag to finish all animations
|
||||
this.closing = true;
|
||||
|
||||
if (Object.size(node.led) !== 0) {
|
||||
//Close device and stop animations
|
||||
if (typeof this.led.close === "function") { this.led.close(); }
|
||||
else { node.warn("Please upgrade blinkstick npm"); }
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
RED.nodes.registerType("blinkstick",BlinkStick);
|
||||
|
||||
RED.httpAdmin.get("/blinksticklist",function(req,res) {
|
||||
blinkstick.findAllSerials(function(serials) {
|
||||
res.writeHead(200, {'Content-Type': 'application/json'});
|
||||
res.write(JSON.stringify(serials));
|
||||
res.end();
|
||||
});
|
||||
});
|
||||
};
|
177
hardware/blinkstick/LICENSE
Normal file
177
hardware/blinkstick/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
|
32
hardware/blinkstick/README.md
Normal file
32
hardware/blinkstick/README.md
Normal file
@ -0,0 +1,32 @@
|
||||
node-red-node-blinkstick
|
||||
========================
|
||||
|
||||
A <a href="http://nodered.org" target="_new">Node-RED</a> node to control a <a href="http://www.blinkstick.com/" target="_new">BlinkStick</a>.
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
Run the following command in the root directory of your Node-RED install:
|
||||
|
||||
npm install node-red-node-blinkstick
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
<i><a href="http://www.blinkstick.com" target="_new">BlinkStick</a></i> output node. Expects a <b>msg.payload</b> with one of:
|
||||
|
||||
* A hex string <b>"#rrggbb"</b> triple
|
||||
* <b>"red,green,blue"</b> three 0-255 values as a string
|
||||
* <b>"random"</b> will generate a random color
|
||||
* <i><a href="http://www.w3schools.com/html/html_colornames.asp" target="_new">Standard HTML color</a></i> name
|
||||
* <b>object</b> can override any of the parameters
|
||||
|
||||
An object payload can override any of the settings on the node. Omitted parameters are left intact. For example:
|
||||
|
||||
{ 'color': 'blue' }
|
||||
{ 'task': 'blink', 'color': 'red' }
|
||||
{ 'task': 'pulse', 'color': 'gree', 'duration': 500 }
|
||||
{ 'task': 'morph', 'color': 'orange', 'duration': 500, 'steps': 20 }
|
||||
|
||||
For more information see <i><a href="http://www.blinkstick.com/help/tutorials" target="_new">BlinkStick tutorials</a></i> or the <i><a href="https://github.com/arvydas/blinkstick-node" target="_new">node module</a></i> documentation.
|
31
hardware/blinkstick/package.json
Normal file
31
hardware/blinkstick/package.json
Normal file
@ -0,0 +1,31 @@
|
||||
{
|
||||
"name" : "node-red-node-blinkstick",
|
||||
"version" : "0.1.1",
|
||||
"description" : "A Node-RED node to control a Blinkstick",
|
||||
"dependencies" : {
|
||||
"blinkstick" : "1.1.*"
|
||||
},
|
||||
"repository" : {
|
||||
"type":"git",
|
||||
"url":"https://github.com/node-red/node-red-nodes/tree/master/hardware/blinkstick"
|
||||
},
|
||||
"license": "Apache",
|
||||
"keywords": [ "node-red", "blinkstick" ],
|
||||
"node-red" : {
|
||||
"nodes" : {
|
||||
"blinkstick": "76-blinkstick.js"
|
||||
}
|
||||
},
|
||||
"author": {
|
||||
"name": "Arvydas Juskevicius",
|
||||
"email": "arvydas@agileinnovative.co.uk",
|
||||
"url": "http://www.blinkstick.com"
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Dave Conway-Jones",
|
||||
"email": "ceejay@vnet.ibm.com",
|
||||
"url": "http://nodered.org"
|
||||
}
|
||||
]
|
||||
}
|
@ -16,7 +16,7 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="digiRGB">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="DigiSpark">
|
||||
</div>
|
||||
<div class="form-tips">Expects a msg.payload with three part csv string of r,g,b.</div>
|
||||
|
@ -14,56 +14,56 @@
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var RED = require(process.env.NODE_RED_HOME+"/red/red");
|
||||
var HID = require('node-hid');
|
||||
var device;
|
||||
var node;
|
||||
module.exports = function(RED) {
|
||||
//"use strict";
|
||||
var HID = require('node-hid');
|
||||
var device;
|
||||
var node;
|
||||
|
||||
function DigiRGBNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
node=this;
|
||||
function DigiRGBNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
node=this;
|
||||
|
||||
var devices = HID.devices(0x16c0,0x05df);
|
||||
for (var i=0; i< devices.length; i++) {
|
||||
if (devices[i].product == 'DigiUSB') {
|
||||
path = devices[i].path;
|
||||
node.log("found: " + path);
|
||||
try {
|
||||
device = new HID.HID(devices[i].path);
|
||||
break;
|
||||
} catch (e) {
|
||||
node.log(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var p1 = /^\#[A-Fa-f0-9]{6}$/
|
||||
var p2 = /[0-9]+,[0-9]+,[0-9]+/
|
||||
|
||||
if (device) {
|
||||
this.on("input", function(msg) {
|
||||
if (msg != null) {
|
||||
if (p1.test(msg.payload)) {
|
||||
var r = parseInt(msg.payload.slice(1,3),16);
|
||||
var g = parseInt(msg.payload.slice(3,5),16);
|
||||
var b = parseInt(msg.payload.slice(5),16);
|
||||
device.sendFeatureReport([115,r,g,b]);
|
||||
} else if (p2.test(msg.payload)) {
|
||||
var args = msg.payload.split(',');
|
||||
if (args.length == 3) {
|
||||
device.sendFeatureReport([115,parseInt(args[0]),parseInt(args[1]),parseInt(args[2])]);
|
||||
var devices = HID.devices(0x16c0,0x05df);
|
||||
for (var i=0; i< devices.length; i++) {
|
||||
if (devices[i].product == 'DigiUSB') {
|
||||
path = devices[i].path;
|
||||
node.log("found: " + path);
|
||||
try {
|
||||
device = new HID.HID(devices[i].path);
|
||||
break;
|
||||
} catch (e) {
|
||||
node.log(e)
|
||||
}
|
||||
} else {
|
||||
node.warn("incompatable input - " + msg.payload);
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
node.warn("no digispark RGB found");
|
||||
}
|
||||
|
||||
this.on('close', function() {
|
||||
if (device) { device.close(); }
|
||||
});
|
||||
var p1 = /^\#[A-Fa-f0-9]{6}$/
|
||||
var p2 = /[0-9]+,[0-9]+,[0-9]+/
|
||||
|
||||
if (device) {
|
||||
this.on("input", function(msg) {
|
||||
if (p1.test(msg.payload)) {
|
||||
var r = parseInt(msg.payload.slice(1,3),16);
|
||||
var g = parseInt(msg.payload.slice(3,5),16);
|
||||
var b = parseInt(msg.payload.slice(5),16);
|
||||
device.sendFeatureReport([115,r,g,b]);
|
||||
} else if (p2.test(msg.payload)) {
|
||||
var args = msg.payload.split(',');
|
||||
if (args.length == 3) {
|
||||
device.sendFeatureReport([115,parseInt(args[0]),parseInt(args[1]),parseInt(args[2])]);
|
||||
}
|
||||
} else {
|
||||
node.warn("incompatable input - " + msg.payload);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
node.warn("no digispark RGB found");
|
||||
}
|
||||
|
||||
this.on('close', function() {
|
||||
if (device) { device.close(); }
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("digiRGB",DigiRGBNode);
|
||||
}
|
||||
RED.nodes.registerType("digiRGB",DigiRGBNode);
|
||||
|
177
hardware/digiRGB/LICENSE
Normal file
177
hardware/digiRGB/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
|
19
hardware/digiRGB/README.md
Normal file
19
hardware/digiRGB/README.md
Normal file
@ -0,0 +1,19 @@
|
||||
node-red-node-digirgb
|
||||
=====================
|
||||
|
||||
A <a href="http://nodered.org" target="_new">Node-RED</a> node to control a <a href="http://digistump.com/products/3" target="_new">Digispark RGB</a> LED.
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
Run the following command in the root directory of your Node-RED install
|
||||
|
||||
npm install node-red-node-digirgb
|
||||
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Simple output node to drive a Digispark RGB LED.
|
||||
|
||||
Requires a <b>msg.payload</b> to be of the form 'r,g,b' - for example 255,0,0 for red.
|
32
hardware/digiRGB/package.json
Normal file
32
hardware/digiRGB/package.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"name" : "node-red-node-digirgb",
|
||||
"version" : "0.0.2",
|
||||
"description" : "A Node-RED node to control a Digispark RGB LED",
|
||||
"dependencies" : {
|
||||
"node-hid" : "0.3.1"
|
||||
},
|
||||
"homepage": "http://www.hardill.me.uk/wordpress/2013/02/06/budget-blink1/",
|
||||
"repository" : {
|
||||
"type":"git",
|
||||
"url":"https://github.com/node-red/node-red-nodes/tree/master/hardware/digiRGB"
|
||||
},
|
||||
"license": "Apache",
|
||||
"keywords": [ "node-red", "digiRGB" ],
|
||||
"node-red" : {
|
||||
"nodes" : {
|
||||
"digiRGB": "78-digiRGB.js"
|
||||
}
|
||||
},
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Dave Conway-Jones",
|
||||
"email": "ceejay@vnet.ibm.com",
|
||||
"url": "http://nodered.org"
|
||||
},
|
||||
{
|
||||
"name": "Ben Hardill",
|
||||
"email": "hardillb@gmail.com",
|
||||
"url": "http://www.hardill.me.uk/wordpress/"
|
||||
}
|
||||
]
|
||||
}
|
62
hardware/heatmiser/100-heatmiser-in.html
Normal file
62
hardware/heatmiser/100-heatmiser-in.html
Normal file
@ -0,0 +1,62 @@
|
||||
<!--
|
||||
Copyright 2014 Sean Bedford
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-template-name="heatmiser-in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-uuid"><i class="fa fa-tag"></i> IP Address</label>
|
||||
<input type="text" id="node-input-ip" placeholder="192.168.0.1">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> PIN</label>
|
||||
<input type="text" id="node-input-pin" placeholder="1234">
|
||||
</div>
|
||||
<div class="form-tips">Expects a msg.payload with a JSON object that contains settings for the Heatmiser thermostat</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="heatmiser-in">
|
||||
<p>Heatmiser Input node.</p>
|
||||
<p>Expects a msg.payload with a JSON object that contains settings for the Heatmiser thermostat</p>
|
||||
<p>msg.payload can currently be either a heating boost option, or a run mode, as below:</p>
|
||||
<h3>Heating boost</h3>
|
||||
<p><pre>{heating: {target: TARGET_TEMPERATURE, hold: MINUTES_TO_STAY_ON_FOR}}</pre></p>
|
||||
<h3>Run mode</h3>
|
||||
<p><pre>{runmode:"frost" OR "heating"}</pre></p
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('heatmiser-in',{
|
||||
category: 'advanced-function',
|
||||
color:"GoldenRod",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
ip: {value:""},
|
||||
pin: {value:""}
|
||||
},
|
||||
inputs:1,
|
||||
outputs:0,
|
||||
icon: "timer.png",
|
||||
label: function() {
|
||||
return this.name||"heatmiser-in";
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
191
hardware/heatmiser/100-heatmiser-in.js
Normal file
191
hardware/heatmiser/100-heatmiser-in.js
Normal file
@ -0,0 +1,191 @@
|
||||
/**
|
||||
* Copyright 2014 Sean Bedford
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var RED = require(process.env.NODE_RED_HOME+"/red/red");
|
||||
|
||||
var Heatmiser = require("heatmiser");
|
||||
var util = require('util');
|
||||
|
||||
function HeatmiserInputNode(n) {
|
||||
// TODO - holiday and hot water cases when confirmed working
|
||||
var DEBUG = false;
|
||||
RED.nodes.createNode(this,n);
|
||||
this.ip = n.ip || "192.168.0.1";
|
||||
this.pin = n.pin || "1234";
|
||||
this.multiWriteFunc = undefined;
|
||||
hminnode = this;
|
||||
this.pollIntervalRef = undefined;
|
||||
|
||||
this.hm = new Heatmiser(this.ip, this.pin);
|
||||
|
||||
this.hm.on('success', function(data) {
|
||||
if (DEBUG) {
|
||||
util.log("[100-heatmiser-in.js] - Successfully wrote data. Response : " + JSON.stringify(data));
|
||||
}
|
||||
hminnode.currentStatus = data.dcb;
|
||||
if (hminnode.multiWriteFunc) {
|
||||
hminnode.multiWriteFunc();
|
||||
hminnode.multiWriteFunc = undefined;
|
||||
return;
|
||||
}
|
||||
hminnode.send({topic: "", payload:JSON.stringify(data.dcb)});
|
||||
});
|
||||
this.hm.on('error', function(data) {
|
||||
if (DEBUG) {
|
||||
util.log("[100-heatmiser-in.js] - Error during data setting : " + JSON.stringify(data));
|
||||
}
|
||||
hminnode.send(data);
|
||||
});
|
||||
|
||||
this.on("close", function() {
|
||||
if (this.pollIntervalRef) {
|
||||
clearInterval(this.pollIntervalRef);
|
||||
this.pollIntervalRef = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
this.read = function() {
|
||||
if (hminnode.hm) {
|
||||
hminnode.hm.read_device();
|
||||
}
|
||||
};
|
||||
|
||||
if (!this.currentStatus) {
|
||||
this.read();
|
||||
this.pollIntervalRef = setInterval(this.read, 30*60*1000);
|
||||
}
|
||||
|
||||
this.write = function(dcb) {
|
||||
if (hminnode.hm) {
|
||||
hminnode.hm.write_device(dcb);
|
||||
}
|
||||
};
|
||||
|
||||
this.validateAndWrite = function(message) {
|
||||
for (var key in message.payload) {
|
||||
// Ensure our valid keys contain valid values
|
||||
switch(key) {
|
||||
case "runmode" :
|
||||
if (DEBUG) {
|
||||
util.log("[100-heatmiser-in.js] Hit the runmode case");
|
||||
}
|
||||
if (message.payload[key] !== "frost" && message.payload[key] !== "heating") {
|
||||
util.log("[100-heatmiser-in.js] Warning: Unsupported 'runmode' value passed!");
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
// case "holiday" :
|
||||
// if (DEBUG) {
|
||||
// util.log("[100-heatmiser-in.js] Hit the holiday case");
|
||||
// }
|
||||
// if (!('enabled' in message.payload[key]) && !('time' in message.payload[key])) {
|
||||
// util.log("[100-heatmiser-in.js] Warning: Unsupported 'holiday' value passed!");
|
||||
// return;
|
||||
// }
|
||||
// var time = message.payload[key].time;
|
||||
// // Ensure hminnode time is a date
|
||||
// if (typeof(time) == "string") {
|
||||
// util.log("Typeof time was " +typeof(message.payload[key].time));
|
||||
// // message.payload[key].time = new Date(message.payload[key].time);
|
||||
// message.payload[key].time = new Date(2014, 02, 15, 12, 0, 0);
|
||||
// util.log("Typeof time is now " +typeof(message.payload[key].time));
|
||||
// }
|
||||
// // Also add in away mode (for hot water) if we're on hols
|
||||
// if (message.payload[key].time) {
|
||||
// message.payload.away_mode = 1;
|
||||
// }
|
||||
// else {
|
||||
// message.payload.away_mode = 0;
|
||||
// }
|
||||
// break;
|
||||
|
||||
// case "hotwater" :
|
||||
// if (DEBUG) {
|
||||
// util.log("[100-heatmiser-in.js] Hit the hotwater case");
|
||||
// }
|
||||
// if (message.payload[key] !== "on" && message.payload[key] !== "boost" && message.payload[key] !== "off") {
|
||||
// util.log("[100-heatmiser-in.js] Warning: Unsupported 'hotwater' value passed!");
|
||||
// return;
|
||||
// }
|
||||
// break;
|
||||
|
||||
case "heating" :
|
||||
// Ensure heating stays last! It's got a multi write scenario
|
||||
if (DEBUG) {
|
||||
util.log("[100-heatmiser-in.js] Hit the heating case");
|
||||
}
|
||||
if (!('target' in message.payload[key]) && !('hold' in message.payload[key])) {
|
||||
util.log("[100-heatmiser-in.js] Warning: Unsupported 'heating' value passed!");
|
||||
return;
|
||||
}
|
||||
// Set sane temp and time ranges and sanitise to float/int
|
||||
var target = parseFloat(message.payload[key].target);
|
||||
var hold = parseInt(message.payload[key].hold);
|
||||
(target > 30.0) ? message.payload[key].target = 30.0 : message.payload[key].target = target;
|
||||
(hold > 1440) ? message.payload[key].hold = 1440 : message.payload[key].hold = hold;
|
||||
(target <= 10.0) ? message.payload[key].target = 10.0 : message.payload[key].target = target;
|
||||
(hold <= 0) ? message.payload[key].hold = 0 : message.payload[key].hold = hold;
|
||||
|
||||
// Ensure hminnode runmode == heating first
|
||||
if (hminnode.currentStatus.run_mode === "frost_protection") {
|
||||
// Use the multiWriteFunc as a callback in our success case
|
||||
hminnode.multiWriteFunc = function() {
|
||||
hminnode.write(message.payload);
|
||||
}
|
||||
hminnode.write({"runmode" : "heating"});
|
||||
// End the flow here to ensure no double-writing
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
default :
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Valid set of key messages, construct DCB and write
|
||||
var dcb = message.payload;
|
||||
if (DEBUG) {
|
||||
util.log("[100-heatmiser-in.js] Injecting " + JSON.stringify(dcb));
|
||||
}
|
||||
hminnode.write(dcb);
|
||||
};
|
||||
|
||||
this.on("input", function(message) {
|
||||
// Valid inputs are heating:{target:, hold:}, read:, runmode:frost/heating, holiday:{enabled:, time:}, hotwater:{'on':1/0 / 'boost':1/0}
|
||||
if (message.payload) {
|
||||
if (typeof(message.payload) === "string") {
|
||||
message.payload = JSON.parse(message.payload);
|
||||
}
|
||||
// Compare message.payload data to confirm valid and send to thermostat
|
||||
var validInputs = ["heating", "runmode"];
|
||||
for (var key in message.payload) {
|
||||
if (message.payload.hasOwnProperty(key)) {
|
||||
if (validInputs.indexOf(key) < 0) {
|
||||
util.log("[100-heatmiser-in.js] Warning: Unsupported key ("+key+") passed!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
hminnode.validateAndWrite(message);
|
||||
}
|
||||
else {
|
||||
util.log("[100-heatmiser-in.js] Warning: Invalid input passed!");
|
||||
return;
|
||||
}
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("heatmiser-in",HeatmiserInputNode);
|
62
hardware/heatmiser/101-heatmiser-out.html
Normal file
62
hardware/heatmiser/101-heatmiser-out.html
Normal file
@ -0,0 +1,62 @@
|
||||
<!--
|
||||
Copyright 2014 Sean Bedford
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-template-name="heatmiser-out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-uuid"><i class="fa fa-tag"></i> IP Address</label>
|
||||
<input type="text" id="node-input-ip" placeholder="192.168.0.1">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> PIN</label>
|
||||
<input type="text" id="node-input-pin" placeholder="1234">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Poll time (in minutes)</label>
|
||||
<input type="text" id="node-input-pollTime" placeholder="30">
|
||||
</div>
|
||||
<div class="form-tips">Expects a msg.payload with a JSON object that contains settings for the Heatmiser thermostat</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="heatmiser-out">
|
||||
<p>Heatmiser Output node.</p>
|
||||
<p>Will read and send a status update at a configurable time interval. This is set to every 30 minutes by default</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('heatmiser-out',{
|
||||
category: 'advanced-function',
|
||||
color:"GoldenRod",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
ip: {value:""},
|
||||
pin: {value:""},
|
||||
pollTime : {value:""}
|
||||
},
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
icon: "timer.png",
|
||||
label: function() {
|
||||
return this.name||"heatmiser-out";
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
91
hardware/heatmiser/101-heatmiser-out.js
Normal file
91
hardware/heatmiser/101-heatmiser-out.js
Normal file
@ -0,0 +1,91 @@
|
||||
/**
|
||||
* Copyright 2014 Sean Bedford
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
var RED = require(process.env.NODE_RED_HOME+"/red/red");
|
||||
|
||||
var Heatmiser = require("heatmiser");
|
||||
var util = require('util');
|
||||
|
||||
function HeatmiserOutputNode(n) {
|
||||
// TODO - holiday and hot water cases when confirmed working
|
||||
var DEBUG = false;
|
||||
RED.nodes.createNode(this,n);
|
||||
this.ip = n.ip || "192.168.0.1";
|
||||
this.pin = n.pin || "1234";
|
||||
this.pollTime = n.pollTime*60*1000 || 30*60*1000;
|
||||
this.pollIntervalRef = undefined;
|
||||
hmoutnode = this;
|
||||
|
||||
this.hm = new Heatmiser(this.ip, this.pin);
|
||||
|
||||
this.hm.on('success', function(data) {
|
||||
if (DEBUG) {
|
||||
util.log("[100-heatmiser-in.js] - Successfully wrote data. Response : " + JSON.stringify(data));
|
||||
}
|
||||
hmoutnode.send({topic: "", payload:JSON.stringify(data.dcb)});
|
||||
});
|
||||
this.hm.on('error', function(data) {
|
||||
if (DEBUG) {
|
||||
util.log("[100-heatmiser-in.js] - Error during data setting : " + JSON.stringify(data));
|
||||
}
|
||||
hmoutnode.send(data);
|
||||
});
|
||||
|
||||
this.read = function() {
|
||||
if (hmoutnode.hm) {
|
||||
hmoutnode.hm.read_device();
|
||||
}
|
||||
};
|
||||
|
||||
if (!this.currentStatus) {
|
||||
this.read();
|
||||
this.pollIntervalRef = setInterval(this.read, this.pollTime);
|
||||
}
|
||||
|
||||
this.on("close", function() {
|
||||
if (this.pollIntervalRef) {
|
||||
clearInterval(this.pollIntervalRef);
|
||||
this.pollIntervalRef = undefined;
|
||||
}
|
||||
});
|
||||
|
||||
this.on("input", function(message) {
|
||||
// Valid inputs are heating:{target:, hold:}, read:, runmode:frost/heating, holiday:{enabled:, time:}, hotwater:{'on':1/0 / 'boost':1/0}
|
||||
if (message.payload == "undefined" || !message.payload) {
|
||||
message.payload = {read : true};
|
||||
}
|
||||
if (typeof(message.payload) == "string") {
|
||||
message.payload = JSON.parse(message.payload);
|
||||
}
|
||||
if (message.payload.read) {
|
||||
hmoutnode.read();
|
||||
}
|
||||
else if (message.payload) {
|
||||
// Compare message.payload data to confirm valid and send to thermostat
|
||||
var validInputs = ["heating", "runmode"];
|
||||
for (var key in message.payload) {
|
||||
if (message.payload.hasOwnProperty(key)) {
|
||||
if (validInputs.indexOf(key) < 0) {
|
||||
util.log("[100-heatmiser.js] Warning: Unsupported key ("+key+") passed!");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
hmoutnode.validateAndWrite(message);
|
||||
}
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("heatmiser-out",HeatmiserOutputNode);
|
@ -18,11 +18,11 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="Discover">
|
||||
<div class="form-row">
|
||||
<label for="node-input-username"><i class="icon-tag"></i> Username:</label>
|
||||
<label for="node-input-username"><i class="fa fa-tag"></i> Username:</label>
|
||||
<input type="text" id="node-input-username" placeholder="username">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
|
@ -18,17 +18,17 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="HueNode">
|
||||
<div class="form-row">
|
||||
<label for="node-input-topic"><i class="icon-tasks"></i>Hue App Username:</label>
|
||||
<label for="node-input-topic"><i class="fa fa-tasks"></i>Hue App Username:</label>
|
||||
<input type="text" id="node-input-username" placeholder="username">
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i>Lamp ID:</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i>Lamp ID:</label>
|
||||
<input type="text" id="node-input-lamp_id" placeholder="lamp_id">
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i>Lamp Status:</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i>Lamp Status:</label>
|
||||
<select id="node-input-lamp_status" placeholder="lamp_status">
|
||||
<option value="AUTO">AUTO</option>
|
||||
<option value="ON">ON</option>
|
||||
@ -37,17 +37,17 @@
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-brightness"><i class="icon-tag"></i>Change Brightness (0->100):</label>
|
||||
<label for="node-input-brightness"><i class="fa fa-tag"></i>Change Brightness (0->100):</label>
|
||||
<input type="text" id="node-input-brightness" placeholder="brightness">
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-color"><i class="icon-tag"></i>Select color:</label>
|
||||
<label for="node-input-color"><i class="fa fa-tag"></i>Select color:</label>
|
||||
<input type="text" id="node-input-color" placeholder="color">
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
|
53
hardware/makey/42-makey.html
Normal file
53
hardware/makey/42-makey.html
Normal file
@ -0,0 +1,53 @@
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<script type="text/x-red" data-template-name="makeymakey">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="makeymakey">
|
||||
<p>Provides "keyboard" like input from a MakeyMakey device.</p>
|
||||
<p><b>Note:</b> this uses the hidstream npm module that by default only
|
||||
supports the basic keyboard keys and NOT the mouse inputs, fn keys,
|
||||
keypad keys, cursor keys etc. This means that the extra mouse emulation jumpers
|
||||
won't work.</p>
|
||||
<p>The MakeyMakey can of course be re-programmed to re-assign the keys.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('makeymakey',{
|
||||
category: 'advanced-input',
|
||||
color:"#f6e686",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
vid: {value:"0x1b4f",required:true},
|
||||
pid: {value:"0x2b75",required:true},
|
||||
cr: {value:false}
|
||||
},
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
icon: "usb.png",
|
||||
label: function() {
|
||||
return this.name||"makeymakey";
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
}
|
||||
});
|
||||
</script>
|
86
hardware/makey/42-makey.js
Normal file
86
hardware/makey/42-makey.js
Normal file
@ -0,0 +1,86 @@
|
||||
/**
|
||||
* 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.
|
||||
**/
|
||||
|
||||
module.exports = function(RED) {
|
||||
"use strict";
|
||||
var hids = require('hidstream');
|
||||
|
||||
function MakeyNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.vid = 0x1b4f; // MakeyMakey vendor ID
|
||||
this.pid = 0x2b75; // MakeyMakey product ID
|
||||
var node = this;
|
||||
var path = null;
|
||||
var tout;
|
||||
var click = false;
|
||||
var keylookup = { "44":"space", "82":"up", "81":"down", "79":"right", "80":"left",
|
||||
"26":"w", "4":"a", "22":"s", "7":"d", "9":"f", "10":"g" };
|
||||
|
||||
var findmakey = function() {
|
||||
node.log("looking for MakeyMakey");
|
||||
var devices = hids.getDevices();
|
||||
for (var dev = 0; dev < devices.length; dev++) {
|
||||
//node.log("Find:"+devices[dev].vendorId.toString(16)+":"+devices[dev].productId.toString(16));
|
||||
if ((devices[dev].vendorId == node.vid) && (devices[dev].productId == node.pid)) {
|
||||
path = devices[dev].path;
|
||||
node.log("found MakeyMakey at: "+path); //path = "0003:0004:00";
|
||||
break; // stop on first match
|
||||
}
|
||||
}
|
||||
if (path === null) {
|
||||
tout = setTimeout( function () {
|
||||
findmakey();
|
||||
},15000);
|
||||
}
|
||||
}
|
||||
findmakey();
|
||||
|
||||
if (path != null) {
|
||||
try {
|
||||
node.makey = new hids.device(path);
|
||||
node.makey.on("data", function(key) {
|
||||
var msg = {payload:[]};
|
||||
//console.log(key);
|
||||
if (key.modKeys[0] === "shift") {
|
||||
for (var keys = 0; keys < key.keyCodes.length; keys++) {
|
||||
node.log(key.keyCodes[keys]+" : "+keylookup[key.keyCodes[keys].toString()]);
|
||||
msg.payload.push(keylookup[key.keyCodes[keys].toString()]);
|
||||
}
|
||||
msg.payload = msg.payload.join();
|
||||
node.send(msg);
|
||||
}
|
||||
else if (key.modKeys[0] === "ctrl") {
|
||||
if (key.charCodes.length === 0) {
|
||||
click = !click;
|
||||
msg.payload = (click) ? "click" : "clock";
|
||||
node.send(msg);
|
||||
}
|
||||
}
|
||||
else { console.log(key); }
|
||||
});
|
||||
} catch(err) { node.warn("can't open MakeyMakey: Do you need root access ?"); }
|
||||
}
|
||||
else {
|
||||
findmakey();
|
||||
}
|
||||
|
||||
this.on("close", function() {
|
||||
if (tout) { clearTimeout(tout); }
|
||||
if (node.makey) { node.makey.device.close(); }
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("makeymakey",MakeyNode);
|
||||
}
|
1
hardware/makey/42-makey.rules
Normal file
1
hardware/makey/42-makey.rules
Normal file
@ -0,0 +1 @@
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="1b4f", ATTR{idProduct}=="2b75", MODE="0666"
|
177
hardware/makey/LICENSE
Normal file
177
hardware/makey/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
|
37
hardware/makey/README.md
Normal file
37
hardware/makey/README.md
Normal file
@ -0,0 +1,37 @@
|
||||
node-red-node-makeymakey
|
||||
========================
|
||||
A <a href="http://nodered.org" target="_new">Node-RED</a> node to read from a MakeyMakey input device.
|
||||
|
||||
Install
|
||||
-------
|
||||
|
||||
Run the following command in the root directory of your Node-RED install
|
||||
|
||||
npm install node-red-node-makeymakey
|
||||
|
||||
|
||||
Pre-reqs
|
||||
--------
|
||||
|
||||
As this requires an underlying npm this also requires it's pre-reqs, see <a href="https://www.npmjs.org/package/node-hid" target="_new">Node-hid npm</a> for more details.
|
||||
|
||||
- libudev-dev (Linux only)
|
||||
- libusb-1.0-0-dev (Ubuntu versions missing libusb.h only)
|
||||
|
||||
As this uses the raw HID strea mit often requires you to run Node-RED as root, unless you have correct priviliges.
|
||||
|
||||
Usage
|
||||
-----
|
||||
|
||||
Provides "keyboard" like input from a MakeyMakey device.
|
||||
|
||||
This uses the hidstream npm module that by default only supports the basic keyboard keys and **NOT** the mouse inputs, fn keys, keypad keys, cursor keys etc. This means that the extra mouse emulation jumpers won't work.
|
||||
|
||||
The MakeyMakey can of course be re-programmed to re-assign the keys - but this node doesn't know about that...
|
||||
|
||||
Known Issues
|
||||
------------
|
||||
|
||||
1) Every now and then something causes the MakeyMakey HID to become detached (lose focus) from this app and re-attach to another (the in focus) app... whereupon the emulated keys will end up in the wrong window... - Any ideas on how to stop this would be greatly appreciated - but I suspect it's a fundamental issue with the MakeyMakey pretending to be a HID.
|
||||
|
||||
2) Default usage is such that you have to run as root. On Debian based systems you can copy the file <i>42-makey.rules</i> to the <code>/etc/udev/rules.d/</code> folder - this should let anyone then access the MakeyMakey. To restart udev use <pre>sudo udevadm control --reload-rules</pre>
|
24
hardware/makey/package.json
Normal file
24
hardware/makey/package.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name" : "node-red-node-makeymakey",
|
||||
"version" : "0.0.1",
|
||||
"description" : "A Node-RED node to read from a MakeyMakey input device.",
|
||||
"dependencies" : {
|
||||
"hidstream": "0.0.3"
|
||||
},
|
||||
"repository" : {
|
||||
"type":"git",
|
||||
"url":"https://github.com/node-red/node-red-nodes/tree/master/hardware/makey"
|
||||
},
|
||||
"license": "Apache",
|
||||
"keywords": [ "node-red", "makeymakey" ],
|
||||
"node-red" : {
|
||||
"nodes" : {
|
||||
"makeymakey": "42-makey.js"
|
||||
}
|
||||
},
|
||||
"author": {
|
||||
"name": "Dave Conway-Jones",
|
||||
"email": "ceejay@vnet.ibm.com",
|
||||
"url": "http://nodered.org"
|
||||
}
|
||||
}
|
@ -18,17 +18,17 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="scanBLE">
|
||||
<div class="form-row">
|
||||
<label for="node-input-topic"><i class="icon-tasks"></i> BLE Device name</label>
|
||||
<label for="node-input-topic"><i class="fa fa-tasks"></i> BLE Device name</label>
|
||||
<input type="text" id="node-input-ble_name" placeholder="XXX">
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-topic"><i class="icon-tasks"></i> UUID</label>
|
||||
<label for="node-input-topic"><i class="fa fa-tasks"></i> UUID</label>
|
||||
<input type="text" id="node-input-ble_uuid" placeholder="UUID">
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
|
@ -37,29 +37,30 @@ function BleScan(n) {
|
||||
this.ble_name = n.ble_name;
|
||||
this.ble_uuid = n.ble_uuid;
|
||||
|
||||
this.on("input", function(msg){
|
||||
noble.startScanning();
|
||||
});
|
||||
noble.on('scanStart', function(msg) {
|
||||
var msg = {};
|
||||
this.on("input", function(msg){
|
||||
noble.startScanning();
|
||||
});
|
||||
|
||||
noble.on('scanStart', function(msg) {
|
||||
msg = {};
|
||||
msg.topic = node.topic;
|
||||
msg.payload = "Scanning initiated..." //debugging
|
||||
//console.log('scanning initiated...');
|
||||
node.send(msg);
|
||||
});
|
||||
|
||||
noble.on('discover', function(peripheral) {
|
||||
//console.log('scanning initiated...');
|
||||
node.send(msg);
|
||||
});
|
||||
|
||||
noble.on('discover', function(peripheral) {
|
||||
var msg = {};
|
||||
msg.topic = node.topic;
|
||||
msg.topic = node.topic;
|
||||
msg.payload = "not found";
|
||||
|
||||
//check for the device name and the UUID (first one from the UUID list)
|
||||
if(peripheral.advertisement.localName==node.ble_name && peripheral.advertisement.serviceUuids[0]==node.ble_uuid) {
|
||||
msg.payload=peripheral.advertisement.localName;
|
||||
noble.stopScanning(); }
|
||||
noble.stopScanning();
|
||||
}
|
||||
node.send(msg);
|
||||
});
|
||||
});
|
||||
|
||||
this.on("close", function() {
|
||||
try { noble.stopScanning(); }
|
||||
|
@ -29,43 +29,43 @@
|
||||
<!-- By convention, most nodes have a 'name' property. The following div -->
|
||||
<!-- provides the necessary field. -->
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-topic"><i class="icon-tag"></i> Topic</label>
|
||||
<label for="node-input-topic"><i class="fa fa-tag"></i> Topic</label>
|
||||
<input type="text" id="node-input-topic" >
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-uuid"><i class="icon-tag"></i> UUID</label>
|
||||
<label for="node-input-uuid"><i class="fa fa-tag"></i> UUID</label>
|
||||
<input type="text" id="node-input-uuid" >
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Temperature</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Temperature</label>
|
||||
<input type="checkbox" id="node-input-temperature" placeholder="">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Humidity</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Humidity</label>
|
||||
<input type="checkbox" id="node-input-humidity" >
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Pressure</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Pressure</label>
|
||||
<input type="checkbox" id="node-input-pressure" >
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Magnetometer</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Magnetometer</label>
|
||||
<input type="checkbox" id="node-input-magnetometer" >
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Accelerometer</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Accelerometer</label>
|
||||
<input type="checkbox" id="node-input-accelerometer" >
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Gyroscope</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Gyroscope</label>
|
||||
<input type="checkbox" id="node-input-gyroscope" >
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Keys</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Keys</label>
|
||||
<input type="checkbox" id="node-input-keys" >
|
||||
</div>
|
||||
</script>
|
||||
|
177
hardware/sensorTag/LICENSE
Normal file
177
hardware/sensorTag/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
|
@ -1,5 +0,0 @@
|
||||
This currently requires the sensortag library
|
||||
|
||||
To install use the following command in the Node-Red directory
|
||||
|
||||
npm install sensortag
|
26
hardware/sensorTag/README.md
Normal file
26
hardware/sensorTag/README.md
Normal file
@ -0,0 +1,26 @@
|
||||
node-red-node-sensortag
|
||||
=======================
|
||||
|
||||
This node adds support to Node-RED to read from the Texas Instruments SensorTag.
|
||||
|
||||
The SensorTag is a Bluetooth LE device hosting the following sensors:
|
||||
* Ambient & ir Temperature
|
||||
* Barometric Pressure
|
||||
* Humidity
|
||||
* 3 axis Accelerometer
|
||||
* 3 axis Magnetometer
|
||||
* 3 axis Gyroscope
|
||||
* 2 push Buttons
|
||||
|
||||
The config node allows the user to enable/disable any of the sensors listed above. The readings from
|
||||
these sensors will be sent as a JSON object payload with the sensor name appended to the topic provided:
|
||||
|
||||
* Temperature - { topic: [topic_prefix]/temperature, payload: { ambient: 21.2, object: 33.0 } }
|
||||
* Barometric Pressure - { topic: [topic_prefix]/pressure, payload: { pres: 1000.1 } }
|
||||
* Humidity - { topic: [topic_prefix]/humidity , payload: { temp: 21.2, humidity: 88} }
|
||||
* Accelerometer - { topic: [topic_prefix]/ , payload: { x:0.0, y:9.8, z:0.0 } }
|
||||
* Magnetometer - { topic: [topic_prefix]/ , payload: { x:0.0, y:0.0, z:0.0 } }
|
||||
* Gyroscope - { topic: [topic_prefix]/ , payload: { x:0.0, y:0.0, z:0.0 } }
|
||||
* Buttons - { topic: [topic_prefix]/ , payload: { left: "down", right: "up"} }
|
||||
|
||||
**NOTE:** Node-RED needs to be run as root inorder or access the Linux Bluetooth 4.0 system calls
|
24
hardware/sensorTag/package.json
Normal file
24
hardware/sensorTag/package.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"name": "node-red-node-sensortag",
|
||||
"description": "A Node-RED node to read data from a TI SensorTag",
|
||||
"version": "0.0.1",
|
||||
"keywords" : ["node-red","sensortag"],
|
||||
"dependencies": {
|
||||
"sensortag" : "0.1.9"
|
||||
},
|
||||
"license": "Apache",
|
||||
"repository" : {
|
||||
"type":"git",
|
||||
"url":"https://github.com/node-red/node-red-nodes/tree/master/hardware/sensorTag"
|
||||
},
|
||||
"node-red" : {
|
||||
"nodes" : {
|
||||
"sensortTag": "79-sensorTag.js"
|
||||
}
|
||||
},
|
||||
"author": {
|
||||
"name": "Ben Hardill",
|
||||
"email":"hardillb@gmail.com",
|
||||
"url": "http://www.hardill.me.uk/wordpress"
|
||||
}
|
||||
}
|
@ -16,11 +16,11 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="wemo out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-ipaddr"><i class="icon-globe"></i> IP Address</label>
|
||||
<label for="node-input-ipaddr"><i class="fa fa-globe"></i> IP Address</label>
|
||||
<input type="text" id="node-input-ipaddr" placeholder="192.168.1.100">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<div class="form-tips">Expects a msg.payload with either 1/0, on/off, or true/false</div>
|
||||
@ -54,11 +54,11 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="wemo in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-ipaddr"><i class="icon-globe"></i> IP Address</label>
|
||||
<label for="node-input-ipaddr"><i class="fa fa-globe"></i> IP Address</label>
|
||||
<input type="text" id="node-input-ipaddr" placeholder="192.168.1.100">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<div class="form-tips">Creates a msg.payload with either 1, 0, nc or na.</div>
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user