diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..c8f50f7c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +npm-debug.log diff --git a/99-sample.html.demo b/99-sample.html.demo index e26197aa..06092b03 100644 --- a/99-sample.html.demo +++ b/99-sample.html.demo @@ -1,5 +1,5 @@ - +
- +
+
- +
- +
@@ -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 diff --git a/99-sample.js.demo b/99-sample.js.demo index c591185a..5147e092 100644 --- a/99-sample.js.demo +++ b/99-sample.js.demo @@ -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); diff --git a/README.md b/README.md index c695027d..1823e4d4 100644 --- a/README.md +++ b/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... diff --git a/analysis/swearfilter/74-swearfilter.html b/analysis/swearfilter/74-swearfilter.html index 34379f9b..e67933eb 100644 --- a/analysis/swearfilter/74-swearfilter.html +++ b/analysis/swearfilter/74-swearfilter.html @@ -16,7 +16,7 @@ diff --git a/analysis/swearfilter/74-swearfilter.js b/analysis/swearfilter/74-swearfilter.js index 394bca40..670f8a93 100644 --- a/analysis/swearfilter/74-swearfilter.js +++ b/analysis/swearfilter/74-swearfilter.js @@ -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); diff --git a/analysis/swearfilter/LICENSE b/analysis/swearfilter/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/analysis/swearfilter/LICENSE @@ -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 diff --git a/analysis/swearfilter/README.md b/analysis/swearfilter/README.md new file mode 100644 index 00000000..1bda6198 --- /dev/null +++ b/analysis/swearfilter/README.md @@ -0,0 +1,21 @@ +node-red-node-badwords +====================== + +A Node-RED 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 string. Everything else is blocked. diff --git a/analysis/swearfilter/package.json b/analysis/swearfilter/package.json new file mode 100644 index 00000000..88e3e473 --- /dev/null +++ b/analysis/swearfilter/package.json @@ -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" + } +} diff --git a/analysis/wordpos/72-wordpos.html b/analysis/wordpos/72-wordpos.html index 6b098990..7e940aff 100644 --- a/analysis/wordpos/72-wordpos.html +++ b/analysis/wordpos/72-wordpos.html @@ -16,7 +16,7 @@ + + + + diff --git a/function/random/random.js b/function/random/random.js new file mode 100644 index 00000000..ed732058 --- /dev/null +++ b/function/random/random.js @@ -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); +} diff --git a/function/smooth/17-smooth.html b/function/smooth/17-smooth.html new file mode 100644 index 00000000..66b2af90 --- /dev/null +++ b/function/smooth/17-smooth.html @@ -0,0 +1,91 @@ + + + + + + + diff --git a/function/smooth/17-smooth.js b/function/smooth/17-smooth.js new file mode 100644 index 00000000..dd8e39c2 --- /dev/null +++ b/function/smooth/17-smooth.js @@ -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); diff --git a/function/smooth/LICENSE b/function/smooth/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/function/smooth/LICENSE @@ -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 diff --git a/function/smooth/README.md b/function/smooth/README.md new file mode 100644 index 00000000..a4ebaa09 --- /dev/null +++ b/function/smooth/README.md @@ -0,0 +1,24 @@ +node-red-node-smooth +==================== + +A Node-RED 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. diff --git a/function/smooth/icons/smooth.png b/function/smooth/icons/smooth.png new file mode 100644 index 00000000..7118e0db Binary files /dev/null and b/function/smooth/icons/smooth.png differ diff --git a/function/smooth/package.json b/function/smooth/package.json new file mode 100644 index 00000000..e0adea7a --- /dev/null +++ b/function/smooth/package.json @@ -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" + } +} diff --git a/hardware/BBB/145-BBB-hardware.html b/hardware/BBB/145-BBB-hardware.html index 2af86449..7fa89ad1 100644 --- a/hardware/BBB/145-BBB-hardware.html +++ b/hardware/BBB/145-BBB-hardware.html @@ -17,7 +17,7 @@ @@ -78,7 +78,7 @@ voltage ten times in rapid succession for each input message and output the mean @@ -279,7 +279,7 @@ press. When using buttons or switches, enable debouncing to improve reliability. @@ -390,7 +390,7 @@ any other input message will reset it to zero. @@ -501,7 +501,7 @@ the Inverting property is not applied to this value. @@ -614,7 +614,7 @@ the pin changes state: its payload is the new state (0 or 1). - diff --git a/hardware/BBB/145-BBB-hardware.js b/hardware/BBB/145-BBB-hardware.js index 78ba7151..af5a70df 100644 --- a/hardware/BBB/145-BBB-hardware.js +++ b/hardware/BBB/145-BBB-hardware.js @@ -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); - } -}; diff --git a/hardware/BBB/LICENSE b/hardware/BBB/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/hardware/BBB/LICENSE @@ -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 diff --git a/hardware/BBB/README.md b/hardware/BBB/README.md new file mode 100644 index 00000000..e6c93002 --- /dev/null +++ b/hardware/BBB/README.md @@ -0,0 +1,96 @@ +node-red-node-beaglebone +======================== +A set of Node-RED nodes to interface with the GPIO pins of a Beaglebone Black. + +Pre-requisites +-------------- + +Only of use on a BeagleboneBlack board. Should ideally be running the latest Debian image - as that has node.js v0.10.x and the bonescript npm preinstalled. +it does also need bonescript - 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). diff --git a/hardware/BBB/icons/BBB.png b/hardware/BBB/icons/BBB.png index 0f228774..18c2ca9f 100644 Binary files a/hardware/BBB/icons/BBB.png and b/hardware/BBB/icons/BBB.png differ diff --git a/hardware/BBB/package.json b/hardware/BBB/package.json new file mode 100644 index 00000000..56a63e2a --- /dev/null +++ b/hardware/BBB/package.json @@ -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"} + ] +} diff --git a/hardware/HummingboardGPIO/LICENSE b/hardware/HummingboardGPIO/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/hardware/HummingboardGPIO/LICENSE @@ -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 diff --git a/hardware/HummingboardGPIO/README.md b/hardware/HummingboardGPIO/README.md new file mode 100644 index 00000000..b4b0ccab --- /dev/null +++ b/hardware/HummingboardGPIO/README.md @@ -0,0 +1,45 @@ +node-red-node-hbgpio +==================== + +A Node-RED 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 msg.payload 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. diff --git a/hardware/HummingboardGPIO/fixup.sh b/hardware/HummingboardGPIO/fixup.sh new file mode 100755 index 00000000..bdd4a38f --- /dev/null +++ b/hardware/HummingboardGPIO/fixup.sh @@ -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 diff --git a/hardware/HummingboardGPIO/gpiohb b/hardware/HummingboardGPIO/gpiohb new file mode 100755 index 00000000..1537a9bf --- /dev/null +++ b/hardware/HummingboardGPIO/gpiohb @@ -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 diff --git a/hardware/HummingboardGPIO/hb-gpio.html b/hardware/HummingboardGPIO/hb-gpio.html new file mode 100644 index 00000000..6c4aa762 --- /dev/null +++ b/hardware/HummingboardGPIO/hb-gpio.html @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + diff --git a/hardware/HummingboardGPIO/hb-gpio.js b/hardware/HummingboardGPIO/hb-gpio.js new file mode 100644 index 00000000..88cc61db --- /dev/null +++ b/hardware/HummingboardGPIO/hb-gpio.js @@ -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); +} diff --git a/hardware/HummingboardGPIO/package.json b/hardware/HummingboardGPIO/package.json new file mode 100644 index 00000000..93471010 --- /dev/null +++ b/hardware/HummingboardGPIO/package.json @@ -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" + } +} diff --git a/hardware/Pi/78-ledborg.html b/hardware/LEDborg/78-ledborg.html similarity index 81% rename from hardware/Pi/78-ledborg.html rename to hardware/LEDborg/78-ledborg.html index 55d128fe..d7f809b8 100644 --- a/hardware/Pi/78-ledborg.html +++ b/hardware/LEDborg/78-ledborg.html @@ -16,24 +16,24 @@ + + + + diff --git a/hardware/PiLiter/39-rpi-piliter.js b/hardware/PiLiter/39-rpi-piliter.js new file mode 100644 index 00000000..22e94f5c --- /dev/null +++ b/hardware/PiLiter/39-rpi-piliter.js @@ -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); +} diff --git a/hardware/PiLiter/LICENSE b/hardware/PiLiter/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/hardware/PiLiter/LICENSE @@ -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 diff --git a/hardware/PiLiter/README.md b/hardware/PiLiter/README.md new file mode 100644 index 00000000..242fb550 --- /dev/null +++ b/hardware/PiLiter/README.md @@ -0,0 +1,33 @@ +node-red-node-piliter +===================== + +A Node-RED 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 WiringPi site 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. {led:3,state:0} to set LED3 off. + +Requires the WiringPi gpio command in order to work. diff --git a/hardware/PiLiter/package.json b/hardware/PiLiter/package.json new file mode 100644 index 00000000..d30df82d --- /dev/null +++ b/hardware/PiLiter/package.json @@ -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" + } +} diff --git a/hardware/Pi/38-rpi-pibrella.html b/hardware/Pibrella/38-rpi-pibrella.html similarity index 60% rename from hardware/Pi/38-rpi-pibrella.html rename to hardware/Pibrella/38-rpi-pibrella.html index ffbe3ac8..c5ea4adf 100644 --- a/hardware/Pi/38-rpi-pibrella.html +++ b/hardware/Pibrella/38-rpi-pibrella.html @@ -16,9 +16,9 @@ @@ -41,11 +47,12 @@ diff --git a/hardware/Pibrella/38-rpi-pibrella.js b/hardware/Pibrella/38-rpi-pibrella.js new file mode 100644 index 00000000..1ee55643 --- /dev/null +++ b/hardware/Pibrella/38-rpi-pibrella.js @@ -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); +} diff --git a/hardware/Pibrella/LICENSE b/hardware/Pibrella/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/hardware/Pibrella/LICENSE @@ -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 diff --git a/hardware/Pibrella/README.md b/hardware/Pibrella/README.md new file mode 100644 index 00000000..2004ef96 --- /dev/null +++ b/hardware/Pibrella/README.md @@ -0,0 +1,38 @@ +node-red-node-pibrella +====================== +A Node-RED node to control a Pibrella 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 WiringPi site 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 msg.payload 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 msg.payload with either a 0 or 1 depending on the state of the input pin. + +The msg.topic is set to pibrella/{the pin id} - which will be A, B, C, D or R. + +Note: This node currently polls the pin every 250mS. This is not ideal as it loads the cpu. diff --git a/hardware/Pibrella/package.json b/hardware/Pibrella/package.json new file mode 100644 index 00000000..0345e00f --- /dev/null +++ b/hardware/Pibrella/package.json @@ -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" + } +} diff --git a/hardware/blink/76-blinkstick.html b/hardware/blink/76-blinkstick.html deleted file mode 100644 index 1bef4306..00000000 --- a/hardware/blink/76-blinkstick.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - - diff --git a/hardware/blink/76-blinkstick.js b/hardware/blink/76-blinkstick.js deleted file mode 100644 index ebbdacc7..00000000 --- a/hardware/blink/76-blinkstick.js +++ /dev/null @@ -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); diff --git a/hardware/blink/77-blink1.js b/hardware/blink/77-blink1.js deleted file mode 100644 index 474164d9..00000000 --- a/hardware/blink/77-blink1.js +++ /dev/null @@ -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); diff --git a/hardware/blink/77-blink1.html b/hardware/blink1/77-blink1.html similarity index 88% rename from hardware/blink/77-blink1.html rename to hardware/blink1/77-blink1.html index 14efa87a..48a40b6a 100644 --- a/hardware/blink/77-blink1.html +++ b/hardware/blink1/77-blink1.html @@ -16,11 +16,11 @@ @@ -28,6 +28,7 @@ + + + + diff --git a/hardware/blinkstick/76-blinkstick.js b/hardware/blinkstick/76-blinkstick.js new file mode 100644 index 00000000..54c1485e --- /dev/null +++ b/hardware/blinkstick/76-blinkstick.js @@ -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(); + }); + }); +}; diff --git a/hardware/blinkstick/LICENSE b/hardware/blinkstick/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/hardware/blinkstick/LICENSE @@ -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 diff --git a/hardware/blinkstick/README.md b/hardware/blinkstick/README.md new file mode 100644 index 00000000..e47fd168 --- /dev/null +++ b/hardware/blinkstick/README.md @@ -0,0 +1,32 @@ +node-red-node-blinkstick +======================== + +A Node-RED node to control a BlinkStick. + +Install +------- + +Run the following command in the root directory of your Node-RED install: + + npm install node-red-node-blinkstick + + +Usage +----- + +BlinkStick output node. Expects a msg.payload with one of: + +* A hex string "#rrggbb" triple +* "red,green,blue" three 0-255 values as a string +* "random" will generate a random color +* Standard HTML color name +* object 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 BlinkStick tutorials or the node module documentation. diff --git a/hardware/blinkstick/package.json b/hardware/blinkstick/package.json new file mode 100644 index 00000000..7bc2b1ad --- /dev/null +++ b/hardware/blinkstick/package.json @@ -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" + } + ] +} diff --git a/hardware/digiRGB/78-digiRGB.html b/hardware/digiRGB/78-digiRGB.html index bbb2a128..2f811d90 100644 --- a/hardware/digiRGB/78-digiRGB.html +++ b/hardware/digiRGB/78-digiRGB.html @@ -16,7 +16,7 @@ + + + + diff --git a/hardware/heatmiser/100-heatmiser-in.js b/hardware/heatmiser/100-heatmiser-in.js new file mode 100644 index 00000000..44eb1396 --- /dev/null +++ b/hardware/heatmiser/100-heatmiser-in.js @@ -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); diff --git a/hardware/heatmiser/101-heatmiser-out.html b/hardware/heatmiser/101-heatmiser-out.html new file mode 100644 index 00000000..fea925c2 --- /dev/null +++ b/hardware/heatmiser/101-heatmiser-out.html @@ -0,0 +1,62 @@ + + + + + + + diff --git a/hardware/heatmiser/101-heatmiser-out.js b/hardware/heatmiser/101-heatmiser-out.js new file mode 100644 index 00000000..a7ec6b07 --- /dev/null +++ b/hardware/heatmiser/101-heatmiser-out.js @@ -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); diff --git a/hardware/hue/103-hue_discover.html b/hardware/hue/103-hue_discover.html index ac6c1d39..4d375d8a 100644 --- a/hardware/hue/103-hue_discover.html +++ b/hardware/hue/103-hue_discover.html @@ -18,11 +18,11 @@ diff --git a/hardware/hue/104-hue_manage.html b/hardware/hue/104-hue_manage.html index d23f3973..99950970 100644 --- a/hardware/hue/104-hue_manage.html +++ b/hardware/hue/104-hue_manage.html @@ -18,17 +18,17 @@ diff --git a/hardware/makey/42-makey.html b/hardware/makey/42-makey.html new file mode 100644 index 00000000..57949c14 --- /dev/null +++ b/hardware/makey/42-makey.html @@ -0,0 +1,53 @@ + + + + + + + diff --git a/hardware/makey/42-makey.js b/hardware/makey/42-makey.js new file mode 100644 index 00000000..e2125e81 --- /dev/null +++ b/hardware/makey/42-makey.js @@ -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); +} diff --git a/hardware/makey/42-makey.rules b/hardware/makey/42-makey.rules new file mode 100644 index 00000000..1269f8a9 --- /dev/null +++ b/hardware/makey/42-makey.rules @@ -0,0 +1 @@ +SUBSYSTEM=="usb", ATTR{idVendor}=="1b4f", ATTR{idProduct}=="2b75", MODE="0666" diff --git a/hardware/makey/LICENSE b/hardware/makey/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/hardware/makey/LICENSE @@ -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 diff --git a/hardware/makey/README.md b/hardware/makey/README.md new file mode 100644 index 00000000..20bbd99e --- /dev/null +++ b/hardware/makey/README.md @@ -0,0 +1,37 @@ +node-red-node-makeymakey +======================== +A Node-RED 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 Node-hid npm 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 42-makey.rules to the /etc/udev/rules.d/ folder - this should let anyone then access the MakeyMakey. To restart udev use
sudo udevadm control --reload-rules
diff --git a/hardware/makey/package.json b/hardware/makey/package.json new file mode 100644 index 00000000..e4e573b1 --- /dev/null +++ b/hardware/makey/package.json @@ -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" + } +} diff --git a/hardware/scanBLE/101-scanBLE.html b/hardware/scanBLE/101-scanBLE.html index 329d142c..8a718460 100644 --- a/hardware/scanBLE/101-scanBLE.html +++ b/hardware/scanBLE/101-scanBLE.html @@ -18,17 +18,17 @@ diff --git a/hardware/scanBLE/101-scanBLE.js b/hardware/scanBLE/101-scanBLE.js index 24532e37..bf07e549 100644 --- a/hardware/scanBLE/101-scanBLE.js +++ b/hardware/scanBLE/101-scanBLE.js @@ -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(); } diff --git a/hardware/sensorTag/79-sensorTag.html b/hardware/sensorTag/79-sensorTag.html index 6e065d94..6f5db727 100644 --- a/hardware/sensorTag/79-sensorTag.html +++ b/hardware/sensorTag/79-sensorTag.html @@ -29,43 +29,43 @@
- +
- +
- +
- +
- +
- +
- +
- +
- +
- +
diff --git a/hardware/sensorTag/LICENSE b/hardware/sensorTag/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/hardware/sensorTag/LICENSE @@ -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 diff --git a/hardware/sensorTag/README b/hardware/sensorTag/README deleted file mode 100644 index 2d6657ab..00000000 --- a/hardware/sensorTag/README +++ /dev/null @@ -1,5 +0,0 @@ -This currently requires the sensortag library - -To install use the following command in the Node-Red directory - -npm install sensortag diff --git a/hardware/sensorTag/README.md b/hardware/sensorTag/README.md new file mode 100644 index 00000000..f443f893 --- /dev/null +++ b/hardware/sensorTag/README.md @@ -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 \ No newline at end of file diff --git a/hardware/sensorTag/package.json b/hardware/sensorTag/package.json new file mode 100644 index 00000000..a1ab6961 --- /dev/null +++ b/hardware/sensorTag/package.json @@ -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" + } +} diff --git a/hardware/wemo/60-wemo.html b/hardware/wemo/60-wemo.html index b282ea73..b75c3ab1 100644 --- a/hardware/wemo/60-wemo.html +++ b/hardware/wemo/60-wemo.html @@ -16,11 +16,11 @@ + + + + + + + + + + + + + + diff --git a/io/mqlight/mqlight.js b/io/mqlight/mqlight.js new file mode 100644 index 00000000..4049a1ed --- /dev/null +++ b/io/mqlight/mqlight.js @@ -0,0 +1,140 @@ +/** + * 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 mqlight = require('mqlight'); + var util = require("util"); + + function MQLightServiceNode(n) { + RED.nodes.createNode(this,n); + + var id = "mqlight_" + (n.clientid ? n.clientid : (1+Math.random()*4294967295).toString(16)); + + var opts = { + service: n.service, + id: id + }; + + if (this.credentials) { + opts.user = this.credentials.user; + opts.password = this.credentials.password; + } + + this.client = mqlight.createClient(opts, function(err) { + if (err) { + util.log('[mqlight] ['+id+'] not connected to service '+n.service); + } else { + util.log('[mqlight] ['+id+'] connected to service '+n.service); + } + }); + } + RED.nodes.registerType("mqlight service",MQLightServiceNode,{ + credentials: { + user: {type:"text"}, + password: {type: "password"} + } + }); + + function MQLightIn(n) { + RED.nodes.createNode(this, n); + this.topic = n.topic || ""; + this.share = n.share || null; + this.service = n.service; + this.serviceConfig = RED.nodes.getNode(this.service); + var node = this; + + if (node.serviceConfig) { + if (node.serviceConfig.client) { + var recvClient = node.serviceConfig.client; + recvClient.on("started", function() { + recvClient.on("message", function(data, delivery) { + var msg = { + topic: delivery.message.topic, + payload: data, + _session: { + type: "mqlight", + id: recvClient.id + } + }; + if (delivery.destination.share) { + msg.share = delivery.destination.share; + } + node.send(msg); + }); + var subscribeCallback = function(err) { + if (err) { + node.error("Failed to subscribe: " + err); + } else { + node.log("Subscribed to "+node.topic+(node.share?" ["+node.share+"]":"")); + } + }; + + if (node.share) { + recvClient.subscribe(node.topic, node.share, subscribeCallback); + } else { + recvClient.subscribe(node.topic, subscribeCallback); + } + }); + recvClient.start(); + + node.on("close", function (done) { + recvClient.stop(done); + }); + } + + } + } + RED.nodes.registerType("mqlight in", MQLightIn); + + function MQLightOut(n) { + RED.nodes.createNode(this, n); + this.topic = n.topic || ""; + this.service = n.service; + this.serviceConfig = RED.nodes.getNode(this.service); + var node = this; + + if (node.serviceConfig) { + if (node.serviceConfig.client) { + var sendClient = node.serviceConfig.client; + + sendClient.on("started", function () { + node.on("input", function(msg) { + if (node.topic === "") { + if (msg.topic) { + node.topic = msg.topic; + } else { + node.warn("No topic set in MQ Light out node"); + return; + } + } + sendClient.send(node.topic, msg.payload, function(err) { + if (err) { + node.error(err); + } + }); + }); + }); + sendClient.start(); + + node.on("close", function (done) { + sendClient.stop(done); + }); + } + } + } + RED.nodes.registerType("mqlight out", MQLightOut); +}; diff --git a/io/ping/88-ping.html b/io/ping/88-ping.html index 06e3028f..5415302d 100644 --- a/io/ping/88-ping.html +++ b/io/ping/88-ping.html @@ -16,22 +16,22 @@ diff --git a/io/ping/88-ping.js b/io/ping/88-ping.js index c2b98de5..c7496cf8 100644 --- a/io/ping/88-ping.js +++ b/io/ping/88-ping.js @@ -14,42 +14,48 @@ * limitations under the License. **/ -var RED = require(process.env.NODE_RED_HOME+"/red/red"); -var spawn = require('child_process').spawn; -var plat = require('os').platform(); +module.exports = function(RED) { + "use strict"; + var spawn = require('child_process').spawn; + var plat = require('os').platform(); -function PingNode(n) { - RED.nodes.createNode(this,n); - this.host = n.host; - this.timer = n.timer * 1000; - var node = this; + function PingNode(n) { + RED.nodes.createNode(this,n); + this.host = n.host; + this.timer = n.timer * 1000; + var node = this; - node.tout = setInterval(function() { - var ex; - if (plat == "linux") ex = spawn('ping', ['-n', '-w', '5', '-c', '1', node.host]); - else if (plat.match(/^win/)) ex = spawn('ping', ['-n', '1', '-w', '5000', node.host]); - else if (plat == "darwin") ex = spawn('ping', ['-n', '-t', '5', '-c', '1', node.host]); - else node.error("Sorry - your platform - "+plat+" - is not recognised."); - var res = false; - ex.stdout.on('data', function (data) { - //console.log('[ping] stdout: ' + data.toString()); - var regex = /from.*time.(.*)ms/; - var m = regex.exec(data.toString())||""; - if (m != '') { res = Number(m[1]); } - }); - ex.stderr.on('data', function (data) { - //console.log('[ping] stderr: ' + data); - }); - ex.on('close', function (code) { - //console.log('[ping] result: ' + code); - var msg = { payload:false, topic:node.host }; - if (code == 0) msg = { payload:res, topic:node.host }; - node.send(msg); - }); - }, node.timer); + node.tout = setInterval(function() { + var ex; + if (plat == "linux") { ex = spawn('ping', ['-n', '-w', '5', '-c', '1', node.host]); } + else if (plat.match(/^win/)) { ex = spawn('ping', ['-n', '1', '-w', '5000', node.host]); } + else if (plat == "darwin") { ex = spawn('ping', ['-n', '-t', '5', '-c', '1', node.host]); } + else { node.error("Sorry - your platform - "+plat+" - is not recognised."); } + var res = false; + var line = ""; + //var regex = /from.*time.(.*)ms/; + var regex = /=.*[<|=]([0-9]*).*TTL|ttl..*=([0-9\.]*)/; + ex.stdout.on('data', function (data) { + line += data.toString(); + }); + ex.stderr.on('data', function (data) { + //console.log('[ping] stderr: ' + data); + }); + ex.on('close', function (code) { + var m = regex.exec(line)||""; + if (m !== '') { + if (m[1]) { res = Number(m[1]); } + if (m[2]) { res = Number(m[2]); } + } + var msg = { payload:false, topic:node.host }; + if (code === 0) { msg = { payload:res, topic:node.host }; } + node.send(msg); + }); + }, node.timer); - this.on("close", function() { - clearInterval(this.tout); - }); + this.on("close", function() { + clearInterval(this.tout); + }); + } + RED.nodes.registerType("ping",PingNode); } -RED.nodes.registerType("ping",PingNode); diff --git a/io/ping/LICENSE b/io/ping/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/io/ping/LICENSE @@ -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 diff --git a/io/ping/README.md b/io/ping/README.md new file mode 100644 index 00000000..e10b690c --- /dev/null +++ b/io/ping/README.md @@ -0,0 +1,21 @@ +node-red-node-ping +================== + +A Node-RED node to ping a remote server, for use as a keep-alive check. + +Install +------- + +Run the following command in the root directory of your Node-RED install + + npm install node-red-node-ping + + +Usage +----- + +Pings a machine and returns the trip time in mS. + +Returns boolean **false** if no response received within 5 seconds, or if the host is unresolveable. + +Default ping is every 20 seconds but can be configured. diff --git a/io/ping/package.json b/io/ping/package.json new file mode 100644 index 00000000..ca5b23a0 --- /dev/null +++ b/io/ping/package.json @@ -0,0 +1,23 @@ +{ + "name" : "node-red-node-ping", + "version" : "0.0.3", + "description" : "A Node-RED node to ping a remote server, for use as a keep-alive check.", + "dependencies" : { + }, + "repository" : { + "type":"git", + "url":"https://github.com/node-red/node-red-nodes/tree/master/io/ping" + }, + "license": "Apache", + "keywords": [ "node-red", "ping", "keepalive" ], + "node-red" : { + "nodes" : { + "ping": "88-ping.js" + } + }, + "author": { + "name": "Dave Conway-Jones", + "email": "ceejay@vnet.ibm.com", + "url": "http://nodered.org" + } +} diff --git a/io/rawserial/26-rawserial.html b/io/rawserial/26-rawserial.html index c7b7c362..5bf3a7e3 100644 --- a/io/rawserial/26-rawserial.html +++ b/io/rawserial/26-rawserial.html @@ -16,17 +16,43 @@ diff --git a/io/rawserial/26-rawserial.js b/io/rawserial/26-rawserial.js index da53dfe8..c0913296 100644 --- a/io/rawserial/26-rawserial.js +++ b/io/rawserial/26-rawserial.js @@ -14,100 +14,136 @@ * limitations under the License. **/ -var RED = require(process.env.NODE_RED_HOME+"/red/red"); -var settings = RED.settings; -var util = require("util"); -var fs = require('fs'); -var plat = require('os').platform(); -var pre = "\\\\.\\"; +module.exports = function(RED) { + "use strict"; + var settings = RED.settings; + var util = require("util"); + var fs = require('fs'); + var plat = require('os').platform(); + var pre = "\\\\.\\"; -if (!plat.match(/^win/)) { - util.log("[26-rawserial.js] Info : only really needed for Windows boxes without serialport npm module installed."); - pre = ""; -} + if (!plat.match(/^win/)) { + throw "Info : only really needed for Windows boxes without serialport npm module installed."; + //util.log("[26-rawserial.js] Info : only really needed for Windows boxes without serialport npm module installed."); + pre = ""; + } -function RawSerialInNode(n) { - RED.nodes.createNode(this,n); - this.port = n.port; - this.split = n.split||null; - if (this.split == '\\n') this.split = "\n"; - if (this.split == '\\r') this.split = "\r"; - var node = this; + function RawSerialInNode(n) { + RED.nodes.createNode(this,n); + this.port = n.port; + this.splitc = n.splitc||null; + this.out = n.out||"char"; + this.bin = n.bin||false; + if (this.splitc == '\\n') { this.splitc = "\n"; } + if (this.splitc == '\\r') { this.splitc = "\r"; } + if (!isNaN(parseInt(this.splitc))) { this.splitc = parseInt(this.splitc); } + var node = this; - var setupSerial = function() { - node.inp = fs.createReadStream(pre+node.port); - node.log("opened "+pre+node.port); - node.inp.setEncoding('utf8'); - var line = ""; - node.inp.on('data', function (data) { - if (node.split != null) { - if (data == node.split) { - node.send({payload:line}); - line = ""; + var setupSerial = function() { + node.inp = fs.createReadStream(pre+node.port); + node.log("open "+pre+node.port); + node.tout = null; + var line = ""; + var buf = new Buffer(32768); + var i = 0; + node.inp.on('data', function (data) { + for (var z = 0; z < data.length; z++) { + if ((node.out === "time") && (node.splitc !== 0)) { + if (node.tout) { + i += 1; + buf[i] = data[z]; + } + else { + node.tout = setTimeout(function () { + node.tout = null; + var m = new Buffer(i+1); + buf.copy(m,0,0,i+1); + if (node.bin !== "true") { m = m.toString(); } + node.send({"payload": m}); + m = null; + }, node.splitc); + i = 0; + buf[0] = data[z]; + } + } + else if ((node.out == "char") && (node.splitc != null)) { + buf[i] = data[z]; + i += 1; + if ((data[z] === node.splitc.charCodeAt(0)) || (i === 32768)) { + var m = new Buffer(i); + buf.copy(m,0,0,i); + if (node.bin !== "true") { m = m.toString(); } + node.send({"payload":m}); + m = null; + i = 0; + } + } + else { + if (node.bin !== "true") { node.send({"payload": String.fromCharCode(data[z])}); } + else { node.send({"payload": new Buffer([data[z]])});} + } } - else { line += data; } - } - else { node.send({payload:data}); } + }); + //node.inp.on('end', function (error) {console.log("End", error);}); + node.inp.on('close', function (error) { + node.log(node.port+" closed"); + node.tout = setTimeout(function() { + setupSerial(); + },settings.serialReconnectTime); + }); + node.inp.on('error', function(error) { + if (error.code == "ENOENT") { node.log(node.port+" not found"); } + else { node.log(node.port+" error "+error); } + node.tout = setTimeout(function() { + setupSerial(); + },settings.serialReconnectTime); + }); + } + setupSerial(); + + node.on('close', function() { + if (node.tout) { clearTimeout(node.tout); } + if (node.inp) { node.inp.pause(); } }); - //node.inp.on('end', function (error) {console.log("End", error);}); - node.inp.on('close', function (error) { - util.log("[rawserial] "+node.port+" closed"); - node.tout = setTimeout(function() { - setupSerial(); - },settings.serialReconnectTime); - }); - node.inp.on('error', function(error) { - if (error.code == "ENOENT") { util.log("[rawserial] port "+node.port+" not found"); } - else { util.log("[rawserial] "+node.port+" error "+error); } - node.tout = setTimeout(function() { - setupSerial(); - },settings.serialReconnectTime); + + } + RED.nodes.registerType("rawserial in",RawSerialInNode); + + + function RawSerialOutNode(n) { + RED.nodes.createNode(this,n); + this.port = n.port; + var node = this; + + var setupSerial = function() { + node.oup = fs.createWriteStream(pre+node.port,{ flags:'w', encoding:'utf8', mode:'0666' }); + node.on("input", function(msg) { + if (msg.payload != null) { + node.oup.write(msg.payload); + } + }); + node.oup.on('open', function (error) { node.log("opened "+node.port); }); + node.oup.on('end', function (error) { node.log("end :"+error); }); + node.oup.on('close', function (error) { + node.log(node.port+" closed"); + node.tout = setTimeout(function() { + setupSerial(); + },settings.serialReconnectTime); + }); + node.oup.on('error', function(error) { + if (error.code == "EACCES") { node.log("can't access port "+node.port); } + else if (error.code == "EIO") { node.log("can't write to port "+node.port); } + else { node.log(node.port+" error "+error); } + node.tout = setTimeout(function() { + setupSerial(); + },settings.serialReconnectTime); + }); + } + setupSerial(); + + node.on('close', function() { + if (node.tout) { clearTimeout(node.tout); } }); } - setupSerial(); - - node.on('close', function() { - if (node.tout) { clearTimeout(node.tout); } - if (node.inp) { node.inp.pause(); } - }); - + RED.nodes.registerType("rawserial out",RawSerialOutNode); } -RED.nodes.registerType("rawserial in",RawSerialInNode); - - -function RawSerialOutNode(n) { - RED.nodes.createNode(this,n); - this.port = n.port; - var node = this; - - var setupSerial = function() { - node.oup = fs.createWriteStream(pre+node.port,{ flags:'w', encoding:'utf8', mode:0666 }); - node.on("input", function(msg) { - if (msg.payload != null) { - node.oup.write(msg.payload); - } - }); - node.oup.on('open', function (error) { util.log("[rawserial] opened "+node.port); }); - node.oup.on('end', function (error) { console.log("End",error); }); - node.oup.on('close', function (error) { - util.log("[rawserial] "+node.port+" closed"); - node.tout = setTimeout(function() { - setupSerial(); - },settings.serialReconnectTime); - }); - node.oup.on('error', function(error) { - if (error.code == "EACCES") { util.log("[rawserial] can't access port "+node.port); } - else if (error.code == "EIO") { util.log("[rawserial] can't write to port "+node.port); } - else { util.log("[rawserial] "+node.port+" error "+error); } - node.tout = setTimeout(function() { - setupSerial(); - },settings.serialReconnectTime); - }); - } - setupSerial(); - - node.on('close', function() { - if (node.tout) { clearTimeout(node.tout); } - }); -} -RED.nodes.registerType("rawserial out",RawSerialOutNode); diff --git a/io/stomp/18-stomp.html b/io/stomp/18-stomp.html new file mode 100644 index 00000000..8a99a143 --- /dev/null +++ b/io/stomp/18-stomp.html @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + + diff --git a/io/stomp/18-stomp.js b/io/stomp/18-stomp.js new file mode 100644 index 00000000..6f9ce3ff --- /dev/null +++ b/io/stomp/18-stomp.js @@ -0,0 +1,180 @@ +/** + * 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 StompClient = require('stomp-client'); + var querystring = require('querystring'); + + function StompServerNode(n) { + RED.nodes.createNode(this,n); + this.server = n.server; + this.port = n.port; + this.name = n.name; + var credentials = RED.nodes.getCredentials(n.id); + if (credentials) { + this.username = credentials.user; + this.password = credentials.password; + } + } + RED.nodes.registerType("stomp-server",StompServerNode); + + RED.httpAdmin.get('/stomp-server/:id',function(req,res) { + var credentials = RED.nodes.getCredentials(req.params.id); + if (credentials) { + res.send(JSON.stringify({user:credentials.user,hasPassword:(credentials.password&&credentials.password!=="")})); + } else { + res.send(JSON.stringify({})); + } + }); + + RED.httpAdmin.delete('/stomp-server/:id',function(req,res) { + RED.nodes.deleteCredentials(req.params.id); + res.send(200); + }); + + RED.httpAdmin.post('/stomp-server/:id',function(req,res) { + var body = ""; + req.on('data', function(chunk) { + body+=chunk; + }); + req.on('end', function(){ + var newCreds = querystring.parse(body); + var credentials = RED.nodes.getCredentials(req.params.id)||{}; + if (newCreds.user == null || newCreds.user === "") { + delete credentials.user; + } else { + credentials.user = newCreds.user; + } + if (newCreds.password === "") { + delete credentials.password; + } else { + credentials.password = newCreds.password||credentials.password; + } + RED.nodes.addCredentials(req.params.id,credentials); + res.send(200); + }); + }); + + + function StompInNode(n) { + RED.nodes.createNode(this,n); + this.server = n.server; + this.topic = n.topic; + + this.serverConfig = RED.nodes.getNode(this.server); + this.host = this.serverConfig.server; + this.port = this.serverConfig.port; + this.userid = this.serverConfig.username; + this.password = this.serverConfig.password; + + var node = this; + var msg = {topic:this.topic}; + var closing = false; + + node.client = new StompClient(node.host, node.port, node.userid, node.password, '1.0'); + node.status({fill:"grey",shape:"ring",text:"connecting"}); + + var doConnect = function() { + node.client.connect(function(sessionId) { + node.status({fill:"green",shape:"dot",text:"connected"}); + node.log('subscribed to: '+node.topic); + node.client.subscribe(node.topic, function(body, headers) { + msg.payload = JSON.parse(body); + node.send(msg); + }); + }, function(error) { + node.status({fill:"grey",shape:"dot",text:"error"}); + node.warn(error); + }); + } + + node.client.on("disconnect", function() { + node.status({fill:"red",shape:"ring",text:"disconnected"}); + if (!closing) { + setTimeout( function () { doConnect(); }, 15000); + } + }); + + node.client.on("error", function(error) { + node.status({fill:"grey",shape:"dot",text:"error"}); + node.log(error); + }); + + doConnect(); + + node.on("close", function(done) { + closing = true; + if (node.client) { + node.client.on("disconnect", function() { + done(); + }); + //node.client.unsubscribe(node.topic); + node.client.disconnect(); + } else { done(); } + }); + } + RED.nodes.registerType("stomp in",StompInNode); + + + function StompOutNode(n) { + RED.nodes.createNode(this,n); + this.server = n.server; + this.topic = n.topic; + + this.serverConfig = RED.nodes.getNode(this.server); + this.host = this.serverConfig.server; + this.port = this.serverConfig.port; + this.userid = this.serverConfig.username; + this.password = this.serverConfig.password; + + var node = this; + var msg = {topic:this.topic}; + var closing = false; + + node.client = new StompClient(node.host, node.port, node.userid, node.password, '1.0'); + node.status({fill:"grey",shape:"ring",text:"connecting"}); + + node.client.connect( function(sessionId) { + node.status({fill:"green",shape:"dot",text:"connected"}); + }, function(error) { + node.status({fill:"grey",shape:"dot",text:"error"}); + node.warn(error); + }); + + node.client.on("disconnect", function() { + node.status({fill:"red",shape:"ring",text:"disconnected"}); + if (!closing) { + setTimeout( function () { node.client.connect(); }, 15000); + } + }); + + node.client.on("error", function(error) { + node.log(error); + }); + + node.on("input", function(msg) { + node.client.publish(node.topic || msg.topic, msg.payload); + }); + + node.on("close", function(done) { + closing = true; + if (client) { client.disconnect(); } + }); + } + RED.nodes.registerType("stomp out",StompOutNode); + +} diff --git a/io/stomp/LICENSE b/io/stomp/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/io/stomp/LICENSE @@ -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 diff --git a/io/stomp/README.md b/io/stomp/README.md new file mode 100644 index 00000000..94e4ceb4 --- /dev/null +++ b/io/stomp/README.md @@ -0,0 +1,21 @@ +node-red-node-stomp +=================== + +A Node-RED node to publish and subscribe to and from a Stomp server. + +Install +------- + +Run the following command in the root directory of your Node-RED install + + npm install node-red-node-stomp + + +Usage +----- + +Connects to a Stomp capable server to send and receive messages. + +The **destination** field is optional. If set it overrides the **msg.topic** property of the message. + +This node only uses the simple security version of the stomp-client. diff --git a/io/stomp/package.json b/io/stomp/package.json new file mode 100644 index 00000000..7eec8101 --- /dev/null +++ b/io/stomp/package.json @@ -0,0 +1,24 @@ +{ + "name" : "node-red-node-stomp", + "version" : "0.0.1", + "description" : "A Node-RED node to publish and subscribe to/from a Stomp server", + "dependencies" : { + "stomp-client" : "0.5.0" + }, + "repository" : { + "type":"git", + "url":"https://github.com/node-red/node-red-nodes/tree/master/io/stomp" + }, + "license": "Apache", + "keywords": [ "node-red", "stomp", "stomp-client" ], + "node-red" : { + "nodes" : { + "stomp": "18-stomp.js" + } + }, + "author": { + "name": "Dave Conway-Jones", + "email": "ceejay@vnet.ibm.com", + "url": "http://nodered.org" + } +} diff --git a/io/wol/39-wol.html b/io/wol/39-wol.html index ffcdfb7b..93ce1e68 100644 --- a/io/wol/39-wol.html +++ b/io/wol/39-wol.html @@ -16,11 +16,11 @@ + + + + diff --git a/parsers/base64/70-base64.js b/parsers/base64/70-base64.js new file mode 100644 index 00000000..d28da040 --- /dev/null +++ b/parsers/base64/70-base64.js @@ -0,0 +1,48 @@ +/** + * 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 Base64Node(n) { + RED.nodes.createNode(this,n); + var node = this; + this.on("input", function(msg) { + if (Buffer.isBuffer(msg.payload)) { + // Take binary buffer and make into a base64 string + msg.payload = msg.payload.toString('base64'); + node.send(msg); + } + else if (typeof msg.payload === "string") { + // Take base64 string and make into binary buffer + var regexp = new RegExp('^[A-Za-z0-9+\/=]*$'); + if ( regexp.test(msg.payload) && (msg.payload.length % 4 === 0) ) { + msg.payload = new Buffer(msg.payload,'base64'); + node.send(msg); + } + else { + node.log("Not a Base64 string - maybe we should encode it..."); + msg.payload = (new Buffer(msg.payload,"binary")).toString('base64'); + node.send(msg); + } + } + else { + node.warn("This node only handles strings or buffers."); + } + }); + } + RED.nodes.registerType("base64",Base64Node); +} diff --git a/parsers/base64/LICENSE b/parsers/base64/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/parsers/base64/LICENSE @@ -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 diff --git a/parsers/base64/README.md b/parsers/base64/README.md new file mode 100644 index 00000000..f13fa837 --- /dev/null +++ b/parsers/base64/README.md @@ -0,0 +1,27 @@ +node-red-node-base64 +==================== + +A Node-RED node to endcode and decode base64 format messages. + + +Install +------- + +Run the following command in the root directory of your Node-RED install + + npm install node-red-node-base64 + +Usage +----- + +A function that converts the **msg.payload** to and from base64 format. + +If the input is a binary buffer it converts it to a Base64 encoded string. + +If the input is a Base64 string it converts it back to a binary buffer. + +Sample Flow +----------- + +
[{"id":"d2ccae00.2d335","type":"inject","name":"","topic":"","payload":"","payloadType":"none","repeat":"","crontab":"","once":false,"x":136,"y":99,"z":"385bdf8b.c7a42","wires":[["e03cae10.1fc35"]]},{"id":"b778ef09.48871","type":"base64","name":"","x":411.5,"y":160,"z":"385bdf8b.c7a42","wires":[["6295d1b1.9d6a3","46b597ba.b94a68"]]},{"id":"6295d1b1.9d6a3","type":"debug","name":"","active":true,"console":"false","complete":"false","x":610,"y":160,"z":"385bdf8b.c7a42","wires":[]},{"id":"ead9e7c9.152618","type":"debug","name":"","active":true,"console":"false","complete":"false","x":610,"y":240,"z":"385bdf8b.c7a42","wires":[]},{"id":"46b597ba.b94a68","type":"base64","name":"","x":411.5,"y":240,"z":"385bdf8b.c7a42","wires":[["ead9e7c9.152618"]]},{"id":"1c9124e9.e36edb","type":"inject","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":1775,"y":113,"z":"385bdf8b.c7a42","wires":[[]]},{"id":"48a892ea.b7576c","type":"debug","name":"","active":true,"console":"false","complete":"false","x":2171,"y":210,"z":"385bdf8b.c7a42","wires":[]},{"id":"e03cae10.1fc35","type":"function","name":"","func":"msg.payload = new Buffer(\"12345\");\nreturn msg;","outputs":1,"x":250,"y":160,"z":"385bdf8b.c7a42","wires":[["b778ef09.48871"]]}]
+
diff --git a/parsers/base64/package.json b/parsers/base64/package.json new file mode 100644 index 00000000..ad7dbcdb --- /dev/null +++ b/parsers/base64/package.json @@ -0,0 +1,24 @@ +{ + "name" : "node-red-node-base64", + "version" : "0.0.1", + "description" : "A Node-RED node to pack and unpack objects to base64 format", + "dependencies" : { + }, + "repository" : { + "type":"git", + "url":"https://github.com/node-red/node-red-nodes.git", + "path": "/tree/master/parsers/base64" + }, + "license": "Apache-2.0", + "keywords": [ "node-red", "base64" ], + "node-red" : { + "nodes" : { + "base64": "70-base64.js" + } + }, + "author": { + "name": "Dave Conway-Jones", + "email": "ceejay@vnet.ibm.com", + "url": "http://nodered.org" + } +} diff --git a/parsers/geohash/70-geohash.html b/parsers/geohash/70-geohash.html new file mode 100644 index 00000000..a1e483cc --- /dev/null +++ b/parsers/geohash/70-geohash.html @@ -0,0 +1,52 @@ + + + + + + + diff --git a/parsers/geohash/70-geohash.js b/parsers/geohash/70-geohash.js new file mode 100644 index 00000000..24fd95da --- /dev/null +++ b/parsers/geohash/70-geohash.js @@ -0,0 +1,93 @@ +/** + * 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 geohash = require('ngeohash'); + + function GeohashNode(n) { + RED.nodes.createNode(this,n); + var node = this; + + var round = function(value, decimals) { + return Number(Math.round(value+'e'+decimals)+'e-'+decimals); + } + + this.on("input", function(msg) { + if (msg.hasOwnProperty("location")) { + if (msg.location.hasOwnProperty("geohash")) { + var pos = geohash.decode(msg.location.geohash); + msg.location.lat = round(pos.latitude,5); + msg.location.lon = round(pos.longitude,5); + msg.location.error = { lat:round(pos.error.latitude,5), lon:round(pos.error.longitude,5) }; + node.send(msg); + } + else { + var lat = msg.location.lat; + var lon = msg.location.lon; + var len = parseInt(msg.location.precision || msg.location.payload || 9); + if (len < 1) { len = 1; } + if (len > 9) { len = 9; } + if (lat && lon) { + msg.location.geohash = geohash.encode(lat, lon, len); + node.send(msg); + } + } + } + else if (typeof msg.payload === "string") { + // try to decode it... + var regexp = new RegExp('^[a-z0-9]{1,9}$'); // can only contain a-z or 0-9 and length 1-9 + if (regexp.test(msg.payload)) { + var pos = geohash.decode(msg.payload); + msg.payload = { lat:round(pos.latitude,5), lon:round(pos.longitude,5) }; + msg.payload.error = { lat:round(pos.error.latitude,5), lon:round(pos.error.longitude,5) }; + node.send(msg); + } + else if (msg.payload.indexOf(",") !== -1) { + // has a comma so assume it's lat,lon(,precision) + var bits = msg.payload.split(","); + if (bits.length === 2) { + var la = Number(bits[0]); + if (la < -90) { la = -90; } + if (la > 90) { la = 90; } + var lo = Number(bits[1]); + if (lo < -180) { lo = -180; } + if (lo > 180) { la = 180; } + msg.payload = geohash.encode(la, lo); + node.send(msg); + } + else { node.warn("Unexpected string format - should be lat,lon"); } + } + else { node.warn("Unexpected string format - should either be lat,lon or geohash"); } + } + else if (typeof msg.payload === "object") { + var lat = msg.payload.lat || msg.payload.latitude; + var lon = msg.payload.lon || msg.payload.longitude; + var len = parseInt(msg.payload.precision || 9); + if (len < 1) { len = 1; } + if (len > 9) { len = 9; } + if (lat && lon) { + msg.payload.geohash = geohash.encode(lat, lon, len); + node.send(msg); + } + } + else { + node.warn("This node only expects strings or objects."); + } + }); + } + RED.nodes.registerType("geohash",GeohashNode); +} diff --git a/parsers/geohash/LICENSE b/parsers/geohash/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/parsers/geohash/LICENSE @@ -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 diff --git a/parsers/geohash/README.md b/parsers/geohash/README.md new file mode 100644 index 00000000..76fc67f2 --- /dev/null +++ b/parsers/geohash/README.md @@ -0,0 +1,35 @@ +node-red-node-geohash +===================== + +A Node-RED node to encode and decode lat,lon pairs to a geohash string. + +Install +------- + +Run the following command in the root directory of your Node-RED install + + npm install node-red-node-geohash + + +Usage +----- + +This function encodes a lat,lon string to and from a geohash. + +If the **msg.payload** is a string it tries to see if it's a geohash - + if so it tries to decode it and outputs a payload object containing + + - latitude + - longitude + - errorlatitude + - error.longitude + +If the **msg.payload** is an object with properties **lat** or **latitude** and **lon** or **longitude** - it will add a geohash property to the payload. + +The precision can be set by **msg.payload.precision** from 1 to 9. + + +Example flow +------------ + +
[{"id":"60ebfc45.9f1404","type":"function","name":"","func":"msg.payload = {lat:51,lon:-1,precision:5};\nreturn msg;","outputs":1,"x":281,"y":485,"z":"385bdf8b.c7a42","wires":[["6f1c5357.90e3ac"]]},{"id":"6f1c5357.90e3ac","type":"geohash","name":"","x":415.5,"y":420,"z":"385bdf8b.c7a42","wires":[["71a94378.8e56bc"]]},{"id":"52763c46.ad89c4","type":"inject","name":"","topic":"","payload":"51.05,-1.05","payloadType":"string","repeat":"","crontab":"","once":false,"x":165.5,"y":337,"z":"385bdf8b.c7a42","wires":[["7b08247.f84f7dc"]]},{"id":"7b08247.f84f7dc","type":"geohash","name":"","x":360.5,"y":337,"z":"385bdf8b.c7a42","wires":[["6f1c5357.90e3ac","893e37b7.76c1c8"]]},{"id":"6fec77c4.901388","type":"inject","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":155,"y":397,"z":"385bdf8b.c7a42","wires":[["60ebfc45.9f1404"]]},{"id":"893e37b7.76c1c8","type":"debug","name":"","active":true,"console":"false","complete":"false","x":535,"y":337,"z":"385bdf8b.c7a42","wires":[]},{"id":"71a94378.8e56bc","type":"debug","name":"","active":true,"console":"false","complete":"false","x":590,"y":420,"z":"385bdf8b.c7a42","wires":[]}]
diff --git a/parsers/geohash/package.json b/parsers/geohash/package.json new file mode 100644 index 00000000..94ccc4a5 --- /dev/null +++ b/parsers/geohash/package.json @@ -0,0 +1,24 @@ +{ + "name" : "node-red-node-geohash", + "version" : "0.0.2", + "description" : "A Node-RED node to encode and decode lat,lon pairs to a geohash.", + "dependencies" : { + "ngeohash" : "0.6.0" + }, + "repository" : { + "type":"git", + "url":"https://github.com/node-red/node-red-nodes/tree/master/parsers/geohash" + }, + "license": "Apache-2.0", + "keywords": [ "node-red", "geohash" ], + "node-red" : { + "nodes" : { + "geohash": "70-geohash.js" + } + }, + "author": { + "name": "Dave Conway-Jones", + "email": "ceejay@vnet.ibm.com", + "url": "http://nodered.org" + } +} diff --git a/parsers/msgpack/70-msgpack.html b/parsers/msgpack/70-msgpack.html new file mode 100644 index 00000000..7a754d14 --- /dev/null +++ b/parsers/msgpack/70-msgpack.html @@ -0,0 +1,48 @@ + + + + + + + diff --git a/parsers/msgpack/70-msgpack.js b/parsers/msgpack/70-msgpack.js new file mode 100644 index 00000000..f50d276b --- /dev/null +++ b/parsers/msgpack/70-msgpack.js @@ -0,0 +1,46 @@ +/** + * 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 msgpack = require('msgpack-js'); + + function MsgPackNode(n) { + RED.nodes.createNode(this,n); + var node = this; + this.on("input", function(msg) { + if (Buffer.isBuffer(msg.payload)) { + var l = msg.payload.length; + try { + msg.payload = msgpack.decode(msg.payload); + node.send(msg); + node.status({text:l +" b->o "+ JSON.stringify(msg.payload).length}); + } + catch (e) { + node.warn("Bad decode: "+e); + node.status({text:"not a msgpack buffer"}); + } + } + else { + var l = JSON.stringify(msg.payload).length; + msg.payload = msgpack.encode(msg.payload); + node.send(msg); + node.status({text:l +" o->b "+ msg.payload.length}); + } + }); + } + RED.nodes.registerType("msgpack",MsgPackNode); +} diff --git a/parsers/msgpack/LICENSE b/parsers/msgpack/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/parsers/msgpack/LICENSE @@ -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 diff --git a/parsers/msgpack/README.md b/parsers/msgpack/README.md new file mode 100644 index 00000000..49549236 --- /dev/null +++ b/parsers/msgpack/README.md @@ -0,0 +1,23 @@ +node-red-node-msgpack +===================== + +A Node-RED node to pack and unpack objects to msgpack format buffers. + +Install +------- + +Run the following command in the root directory of your Node-RED install + + npm install node-red-node-msgpack + + +Usage +----- + +Uses the msgpack npm to pack and unpack msg.payload objects to msgpack format buffers. + +If the input is an object it converts it to a msgpack buffer. + +If the input is a msgpack buffer it converts it back to an object. + +Current only supports msg.payloads of type object. diff --git a/parsers/msgpack/package.json b/parsers/msgpack/package.json new file mode 100644 index 00000000..23a675b8 --- /dev/null +++ b/parsers/msgpack/package.json @@ -0,0 +1,24 @@ +{ + "name" : "node-red-node-msgpack", + "version" : "0.0.3", + "description" : "A Node-RED node to pack and unpack objects to msgpack format", + "dependencies" : { + "msgpack-js" : "0.3.0" + }, + "repository" : { + "type":"git", + "url":"https://github.com/node-red/node-red-nodes/tree/master/parsers/msgpack" + }, + "license": "Apache-2.0", + "keywords": [ "node-red", "msgpack" ], + "node-red" : { + "nodes" : { + "msgpack": "70-msgpack.js" + } + }, + "author": { + "name": "Dave Conway-Jones", + "email": "ceejay@vnet.ibm.com", + "url": "http://nodered.org" + } +} diff --git a/social/dweetio/55-dweetio.html b/social/dweetio/55-dweetio.html new file mode 100644 index 00000000..a70fd841 --- /dev/null +++ b/social/dweetio/55-dweetio.html @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + diff --git a/social/dweetio/55-dweetio.js b/social/dweetio/55-dweetio.js new file mode 100644 index 00000000..4ef8c88b --- /dev/null +++ b/social/dweetio/55-dweetio.js @@ -0,0 +1,70 @@ +/** + * 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 DweetClient = require("node-dweetio"); + var dweetio = null; + + function DweetioOutNode(n) { + RED.nodes.createNode(this,n); + this.thing = n.thing; + if (dweetio == null) { dweetio = new DweetClient(); } + var node = this; + + this.on("input",function(msg) { + //if (typeof(msg.payload) === 'object') { + var thing = node.thing || msg.thing; + try { + dweetio.dweet_for(thing, {payload:msg.payload}, function(err, dweet) { + //console.log(dweet.thing); // "my-thing" + //console.log(dweet.content); // The content of the dweet + //console.log(dweet.created); // The create date of the dweet + }); + } + catch (err) { + node.log(err); + } + //} else { node.warn("Dweetio only sends payload objects."); } + }); + + } + RED.nodes.registerType("dweetio out",DweetioOutNode); + + function DweetioInNode(n) { + RED.nodes.createNode(this,n); + this.thing = n.thing; + if (dweetio == null) { dweetio = new DweetClient(); } + var node = this; + + dweetio.listen_for(node.thing, function(dweet){ + // This will be called anytime there is a new dweet for my-thing + if (dweet.content.hasOwnProperty("payload")) { + dweet.payload=dweet.content.payload; + } else { + dweet.payload = dweet.content; + } + delete dweet.content; + node.send(dweet); + }); + + this.on("close", function() { + dweetio.stop_listening_for(node.thing); + }); + + } + RED.nodes.registerType("dweetio in",DweetioInNode); +} diff --git a/social/dweetio/LICENSE b/social/dweetio/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/social/dweetio/LICENSE @@ -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 diff --git a/social/dweetio/README.md b/social/dweetio/README.md new file mode 100644 index 00000000..657803a5 --- /dev/null +++ b/social/dweetio/README.md @@ -0,0 +1,44 @@ +node-red-node-dweetio +===================== + +A Node-RED node to send and receive simple dweets. + +This node does **NOT** support private or "locked" dweets. + +Install +------- + +Run the following command in the root directory of your Node-RED install + + npm install node-red-node-dweetio + + +Usage +----- + +###Output + +Sends the **msg.payload** to Dweet.io + + +Optionally uses **msg.thing** to set the thing id, if not already set in the properties. + +You need to make the thing id unique - you are recommended to use a GUID. + +###Input + +Listens for messages from Dweet.io + +The thing id should be globally unique as they are all public - you are recommended to use a GUID. + +The Thing ID is set into **msg.dweet**, and the timesamp into **msg.created**. + + +For further info see the Dweet.io website + + +###Sample Flow + +Cut the text below - then in Node-RED use Ctrl-I (Import) - Ctrl-V (Paste) to insert into your workspace. + + [{"id":"58bfbfe.fa7404","type":"debug","name":"","active":true,"console":"false","complete":"false","x":401,"y":211,"z":"8f1399c1.70ec68","wires":[]},{"id":"bc69a077.43966","type":"dweetio out","thing":"not-very-random-big-string","name":"","x":409,"y":135,"z":"8f1399c1.70ec68","wires":[]},{"id":"aaad178a.5552e8","type":"dweetio in","thing":"not-very-random-big-string","name":"","x":153,"y":211,"z":"8f1399c1.70ec68","wires":[["58bfbfe.fa7404"]]},{"id":"db15a21f.24ea6","type":"inject","name":"","topic":"Ticktock","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":160,"y":136,"z":"8f1399c1.70ec68","wires":[["bc69a077.43966"]]}] diff --git a/social/dweetio/package.json b/social/dweetio/package.json new file mode 100644 index 00000000..ad23c5cf --- /dev/null +++ b/social/dweetio/package.json @@ -0,0 +1,24 @@ +{ + "name" : "node-red-node-dweetio", + "version" : "0.0.5", + "description" : "A Node-RED node to send and receive simple dweets", + "dependencies" : { + "node-dweetio" : "0.0.11" + }, + "repository" : { + "type":"git", + "url":"https://github.com/node-red/node-red-nodes/tree/master/social/dweetio" + }, + "license": "Apache-2.0", + "keywords": [ "node-red", "dweetio" ], + "node-red" : { + "nodes" : { + "dweetio": "55-dweetio.js" + } + }, + "author": { + "name": "Dave Conway-Jones", + "email": "ceejay@vnet.ibm.com", + "url": "http://nodered.org" + } +} diff --git a/social/music/69-mpd.html b/social/music/69-mpd.html index acfc07be..bfa11854 100644 --- a/social/music/69-mpd.html +++ b/social/music/69-mpd.html @@ -16,7 +16,7 @@ + + + + diff --git a/social/nma/57-nma.js b/social/nma/57-nma.js new file mode 100644 index 00000000..3870a05b --- /dev/null +++ b/social/nma/57-nma.js @@ -0,0 +1,88 @@ +/** + * 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 nma = require('nma'); + + function NMANode(n) { + RED.nodes.createNode(this,n); + this.title = n.title; + var credentials = RED.nodes.getCredentials(n.id); + if ((credentials) && (credentials.hasOwnProperty("pushkey"))) { this.pushkey = credentials.pushkey; } + else { this.error("No NMA API key set"); } + var node = this; + this.on("input",function(msg) { + var titl = this.title||msg.topic||"Node-RED"; + if (typeof(msg.payload) === 'object') { + msg.payload = JSON.stringify(msg.payload); + } + else { msg.payload = msg.payload.toString(); } + if (node.pushkey) { + nma({ + "apikey": node.pushkey, + "application": "Node-RED", + "event": titl, + "description": msg.payload, + "priority": 0 + }, function (error) { + if (error) { + node.warn("NMA error: " + error); + } + }); + } + else { + node.warn("NMA credentials not set."); + } + }); + } + + RED.nodes.registerType("nma",NMANode); + + var querystring = require('querystring'); + + RED.httpAdmin.get('/nma/:id',function(req,res) { + var credentials = RED.nodes.getCredentials(req.params.id); + if (credentials) { + res.send(JSON.stringify({hasPassword:(credentials.pushkey&&credentials.pushkey!=="")})); + } else { + res.send(JSON.stringify({})); + } + }); + + RED.httpAdmin.delete('/nma/:id',function(req,res) { + RED.nodes.deleteCredentials(req.params.id); + res.send(200); + }); + + RED.httpAdmin.post('/nma/:id',function(req,res) { + var body = ""; + req.on('data', function(chunk) { + body+=chunk; + }); + req.on('end', function(){ + var newCreds = querystring.parse(body); + var credentials = RED.nodes.getCredentials(req.params.id)||{}; + if (newCreds.pushkey === "") { + delete credentials.pushkey; + } else { + credentials.pushkey = newCreds.pushkey||credentials.pushkey; + } + RED.nodes.addCredentials(req.params.id,credentials); + res.send(200); + }); + }); +} diff --git a/social/nma/LICENSE b/social/nma/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/social/nma/LICENSE @@ -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 diff --git a/social/nma/README.md b/social/nma/README.md new file mode 100644 index 00000000..2ae013cf --- /dev/null +++ b/social/nma/README.md @@ -0,0 +1,23 @@ +node-red-node-nma +================= + +A Node-RED node to send alerts via Notify-My-Android. + +Install +------- + +Run the following command in the root directory of your Node-RED install + + npm install node-red-node-nma + + +Usage +----- + +Uses Notify-My-Android (NMA) to push the **msg.payload** to an Android device that has Notify-My-Android app installed. + +Optionally uses **msg.topic** to set the title, if not already set in the properties. + +The API-key is stored in a separate credentials file. + +Uses Notify-My-Android. See this link for more details.

diff --git a/social/nma/icons/nma.png b/social/nma/icons/nma.png new file mode 100644 index 00000000..902f90f4 Binary files /dev/null and b/social/nma/icons/nma.png differ diff --git a/social/nma/package.json b/social/nma/package.json new file mode 100644 index 00000000..07932d16 --- /dev/null +++ b/social/nma/package.json @@ -0,0 +1,28 @@ +{ + "name" : "node-red-node-nma", + "version" : "0.0.2", + "description" : "A Node-RED node to send alerts via Notify-My-Android", + "dependencies" : { + "nma" : "0.2.2" + }, + "repository" : { + "type":"git", + "url":"https://github.com/node-red/node-red-nodes/tree/master/social/nma" + }, + "license": "Apache", + "keywords": [ "node-red", "nma", "notify my android" ], + "node-red" : { + "nodes" : { + "nma": "57-nma.js" + } + }, + "author": { + "name": "Dave Conway-Jones", + "email": "ceejay@vnet.ibm.com", + "url": "http://nodered.org" + }, + "contributors": [{ + "name": "Edwin Hermans", + "email": "edwin@madtech.cx" + }] +} diff --git a/social/notify/57-notify.html b/social/notify/57-notify.html index fa820d31..96859100 100644 --- a/social/notify/57-notify.html +++ b/social/notify/57-notify.html @@ -16,11 +16,11 @@ diff --git a/social/notify/57-notify.js b/social/notify/57-notify.js index b36d6b82..764effb7 100644 --- a/social/notify/57-notify.js +++ b/social/notify/57-notify.js @@ -14,26 +14,28 @@ * limitations under the License. **/ -var RED = require(process.env.NODE_RED_HOME+"/red/red"); -var growl = require('growl'); -var imagefile = process.env.NODE_RED_HOME+"/public/node-red.png"; +module.exports = function(RED) { + "use strict"; + var growl = require('growl'); + var imagefile = process.env.NODE_RED_HOME+"/public/node-red.png"; -function NotifyNode(n) { - RED.nodes.createNode(this,n); - this.title = n.title; - var node = this; - this.on("input",function(msg) { - var titl = this.title || msg.topic; - if (typeof(msg.payload) == 'object') { - msg.payload = JSON.stringify(msg.payload); - } - if (typeof(titl) != 'undefined') { - growl(msg.payload, { title: titl, image: imagefile }); - } - else { - growl(msg.payload, { image: imagefile }); - } - }); + function NotifyNode(n) { + RED.nodes.createNode(this,n); + this.title = n.title; + var node = this; + this.on("input",function(msg) { + var titl = this.title || msg.topic; + if (typeof(msg.payload) == 'object') { + msg.payload = JSON.stringify(msg.payload); + } + if (typeof(titl) != 'undefined') { + growl(msg.payload, { title: titl, image: imagefile }); + } + else { + growl(msg.payload, { image: imagefile }); + } + }); + } + + RED.nodes.registerType("notify",NotifyNode); } - -RED.nodes.registerType("notify",NotifyNode); diff --git a/social/prowl/57-prowl.html b/social/prowl/57-prowl.html index 6a897f79..bc90e6df 100644 --- a/social/prowl/57-prowl.html +++ b/social/prowl/57-prowl.html @@ -16,27 +16,32 @@ diff --git a/social/prowl/57-prowl.js b/social/prowl/57-prowl.js index ee1791c2..a0f42f6e 100644 --- a/social/prowl/57-prowl.js +++ b/social/prowl/57-prowl.js @@ -14,54 +14,98 @@ * limitations under the License. **/ -var RED = require(process.env.NODE_RED_HOME+"/red/red"); -var Prowl = require('node-prowl'); -var util = require('util'); +module.exports = function(RED) { + "use strict"; + var Prowl = require('node-prowl'); -// Either add a line like this to settings.js -// prowl: {prowlkey:'My-API-KEY'}, -// or create pushkey.js in dir ABOVE node-red, it just needs to be like -// module.exports = {prowlkey:'My-API-KEY'} + // Either add a line like this to settings.js + // prowl: {prowlkey:'My-API-KEY'}, + // or create pushkey.js in dir ABOVE node-red, it just needs to be like + // module.exports = {prowlkey:'My-API-KEY'} -try { - var pushkey = RED.settings.prowl || require(process.env.NODE_RED_HOME+"/../pushkey.js"); -} -catch(err) { - util.log("[57-prowl.js] Error: Failed to load Prowl credentials"); -} + try { + var pushkeys = RED.settings.prowl || require(process.env.NODE_RED_HOME+"/../pushkey.js"); + } + catch(err) { } -if (pushkey) { - if (pushkey.prowlkey) { var prowl = new Prowl(pushkey.prowlkey); } -} - -function ProwlNode(n) { - RED.nodes.createNode(this,n); - this.title = n.title; - this.priority = parseInt(n.priority); - if (this.priority > 2) this.priority = 2; - if (this.priority < -2) this.priority = -2; - var node = this; - this.on("input",function(msg) { - var titl = this.title||msg.topic||"Node-RED"; - var pri = msg.priority||this.priority; - if (typeof(msg.payload) === 'object') { - msg.payload = JSON.stringify(msg.payload); + function ProwlNode(n) { + RED.nodes.createNode(this,n); + this.title = n.title; + this.priority = parseInt(n.priority); + if (this.priority > 2) { this.priority = 2; } + if (this.priority < -2) { this.priority = -2; } + var credentials = RED.nodes.getCredentials(n.id); + if ((credentials) && (credentials.hasOwnProperty("pushkey"))) { this.pushkey = credentials.pushkey; } + else { + if (pushkeys) { this.pushkey = pushkeys.prowlkey; } + else { this.error("No Prowl credentials set."); } } - else { msg.payload = msg.payload.toString(); } - if (pushkey.prowlkey) { - try { - prowl.push(msg.payload, titl, { priority: pri }, function(err, remaining) { - if (err) node.error(err); - node.log( remaining + ' calls to Prowl api during current hour.' ); - }); + this.prowl = false; + if (this.pushkey) { this.prowl = new Prowl(this.pushkey); } + var node = this; + + this.on("input",function(msg) { + var titl = this.title||msg.topic||"Node-RED"; + var pri = msg.priority||this.priority; + if (typeof(msg.payload) === 'object') { + msg.payload = JSON.stringify(msg.payload); } - catch (err) { - node.error(err); + else { msg.payload = msg.payload.toString(); } + if (node.pushkey) { + try { + node.prowl.push(msg.payload, titl, { priority: pri }, function(err, remaining) { + if (err) { node.error(err); } + node.log( remaining + ' calls to Prowl api during current hour.' ); + }); + } + catch (err) { + node.error(err); + } } + else { + node.warn("Prowl credentials not set."); + } + }); + } + RED.nodes.registerType("prowl",ProwlNode); + + var querystring = require('querystring'); + + RED.httpAdmin.get('/prowl/:id',function(req,res) { + var credentials = RED.nodes.getCredentials(req.params.id); + if (credentials) { + res.send(JSON.stringify({hasPassword:(credentials.pushkey&&credentials.pushkey!=="")})); + } + else if (pushkeys && pushkeys.prowlkey) { + RED.nodes.addCredentials(req.params.id,{pushkey:pushkeys.prowlkey,global:true}); + credentials = RED.nodes.getCredentials(req.params.id); + res.send(JSON.stringify({hasPassword:(credentials.pushkey&&credentials.pushkey!==""),global:credentials.global})); } else { - node.warn("Prowl credentials not set/found. See node info."); + res.send(JSON.stringify({})); } }); + + RED.httpAdmin.delete('/prowl/:id',function(req,res) { + RED.nodes.deleteCredentials(req.params.id); + res.send(200); + }); + + RED.httpAdmin.post('/prowl/:id',function(req,res) { + var body = ""; + req.on('data', function(chunk) { + body+=chunk; + }); + req.on('end', function(){ + var newCreds = querystring.parse(body); + var credentials = RED.nodes.getCredentials(req.params.id)||{}; + if (newCreds.pushkey === "") { + delete credentials.pushkey; + } else { + credentials.pushkey = newCreds.pushkey||credentials.pushkey; + } + RED.nodes.addCredentials(req.params.id,credentials); + res.send(200); + }); + }); } -RED.nodes.registerType("prowl",ProwlNode); diff --git a/social/prowl/LICENSE b/social/prowl/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/social/prowl/LICENSE @@ -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 diff --git a/social/prowl/README.md b/social/prowl/README.md new file mode 100644 index 00000000..4736bbd5 --- /dev/null +++ b/social/prowl/README.md @@ -0,0 +1,23 @@ +node-red-node-prowl +=================== + +A Node-RED node to send alerts via Prowl. + +Install +------- + +Run the following command in the root directory of your Node-RED install + + npm install node-red-node-prowl + + +Usage +----- + +Uses Prowl to push the **msg.payload** to an Apple device that has the prowl app installed. + +Optionally uses **msg.topic** to set the title. You can also set **msg.priority** to confgure the urgency from -2 (low), through 0 (normal) to 2 (urgent). + +The API Key is stored in a separate credentials file. + +Uses Prowl. See this link for more details. diff --git a/social/prowl/package.json b/social/prowl/package.json new file mode 100644 index 00000000..5df611e1 --- /dev/null +++ b/social/prowl/package.json @@ -0,0 +1,24 @@ +{ + "name" : "node-red-node-prowl", + "version" : "0.0.1", + "description" : "A Node-RED node to send alerts via Prowl", + "dependencies" : { + "node-prowl" : "0.1.7" + }, + "repository" : { + "type":"git", + "url":"https://github.com/node-red/node-red-nodes/tree/master/social/prowl" + }, + "license": "Apache", + "keywords": [ "node-red", "prowl"], + "node-red" : { + "nodes" : { + "prowl": "57-prowl.js" + } + }, + "author": { + "name": "Dave Conway-Jones", + "email": "ceejay@vnet.ibm.com", + "url": "http://nodered.org" + } +} diff --git a/social/pushbullet/57-pushbullet.html b/social/pushbullet/57-pushbullet.html index 4008321f..396b7e98 100644 --- a/social/pushbullet/57-pushbullet.html +++ b/social/pushbullet/57-pushbullet.html @@ -16,23 +16,37 @@ diff --git a/social/pushbullet/57-pushbullet.js b/social/pushbullet/57-pushbullet.js index a172490d..86a69fd3 100644 --- a/social/pushbullet/57-pushbullet.js +++ b/social/pushbullet/57-pushbullet.js @@ -14,53 +14,112 @@ * limitations under the License. **/ -var RED = require(process.env.NODE_RED_HOME+"/red/red"); -var PushBullet = require('pushbullet'); -var util = require('util'); +module.exports = function(RED) { + "use strict"; + var PushBullet = require('pushbullet'); + var util = require('util'); -// Either add a line like this to settings.js -// pushbullet: {pushbullet:'My-API-KEY', deviceid:'12345'}, -// or create pushkey.js in dir ABOVE node-red, it just needs to be like -// module.exports = {pushbullet:'My-API-KEY', deviceid:'12345'} + // Either create pushkey.js in dir ABOVE node-red, it just needs to be like + // module.exports = {pushbullet:'My-API-KEY', deviceid:'12345'} + // or set them per node in the edit dialog -try { - var pushkey = RED.settings.pushbullet || require(process.env.NODE_RED_HOME+"/../pushkey.js"); -} -catch(err) { - util.log("[57-pushbullet.js] Error: Failed to load PushBullet credentials"); -} + try { + var pushkeys = RED.settings.pushbullet || require(process.env.NODE_RED_HOME+"/../pushkey.js"); + } + catch(err) { + //util.log("[57-pushbullet.js] Warning: Failed to load global PushBullet credentials"); + } -if (pushkey) { - if (pushkey.pushbullet) { var pusher = new PushBullet(pushkey.pushbullet); } - if (pushkey.deviceid) { var deviceId = pushkey.deviceid; } -} - -function PushbulletNode(n) { - RED.nodes.createNode(this,n); - this.title = n.title; - var node = this; - this.on("input",function(msg) { - var titl = this.title||msg.topic||"Node-RED"; - if (typeof(msg.payload) === 'object') { - msg.payload = JSON.stringify(msg.payload); + function PushbulletNode(n) { + RED.nodes.createNode(this,n); + this.title = n.title; + this.chan = n.chan; + var credentials = RED.nodes.getCredentials(n.id); + if ((credentials) && (credentials.hasOwnProperty("pushkey"))) { this.pushkey = credentials.pushkey; } + else { + if (pushkeys) { this.pushkey = pushkeys.pushbullet; } + else { this.error("No Pushbullet API key set"); } } - else { msg.payload = msg.payload.toString(); } - if (pushkey.pushbullet && pushkey.deviceid) { - try { - if (!isNaN(deviceId)) { deviceId = Number(deviceId); } - pusher.note(deviceId, titl, msg.payload, function(err, response) { - if (err) node.error("Pushbullet error: "+err); - //console.log(response); - }); + if ((credentials) && (credentials.hasOwnProperty("deviceid"))) { this.deviceid = credentials.deviceid; } + else { + if (pushkeys) { this.deviceid = pushkeys.deviceid; } + else { this.warn("No deviceid set"); } + } + this.pusher = new PushBullet(this.pushkey); + var node = this; + + this.on("input",function(msg) { + var titl = node.title || msg.topic || "Node-RED"; + var dev = node.deviceid || msg.deviceid; + var channel = node.chan || msg.chan; + if (channel != undefined) { + dev = { channel_tag : channel }; + } else { + if (!isNaN(dev)) { dev = Number(dev); } } - catch (err) { - node.error(err); + if (typeof(msg.payload) === 'object') { + msg.payload = JSON.stringify(msg.payload); } + else { msg.payload = msg.payload.toString(); } + if (node.pushkey && dev) { + try { + node.pusher.note(dev, titl, msg.payload, function(err, response) { + if (err) { node.error("Pushbullet error"); } + }); + } + catch (err) { + node.error(err); + } + } + else { + node.warn("Pushbullet credentials not set/found. See node info."); + } + }); + } + RED.nodes.registerType("pushbullet",PushbulletNode); + + var querystring = require('querystring'); + + RED.httpAdmin.get('/pushbullet/:id',function(req,res) { + var credentials = RED.nodes.getCredentials(req.params.id); + if (credentials) { + res.send(JSON.stringify({deviceid:credentials.deviceid,hasPassword:(credentials.pushkey&&credentials.pushkey!=="")})); + } + else if (pushkeys && pushkeys.pushbullet && pushkeys.deviceid) { + RED.nodes.addCredentials(req.params.id,{pushkey:pushkeys.pushbullet,deviceid:pushkeys.deviceid,global:true}); + credentials = RED.nodes.getCredentials(req.params.id); + res.send(JSON.stringify({deviceid:credentials.deviceid,global:credentials.global,hasPassword:(credentials.pushkey&&credentials.pushkey!=="")})); } else { - node.warn("Pushbullet credentials not set/found. See node info."); + res.send(JSON.stringify({})); } }); -} -RED.nodes.registerType("pushbullet",PushbulletNode); + RED.httpAdmin.delete('/pushbullet/:id',function(req,res) { + RED.nodes.deleteCredentials(req.params.id); + res.send(200); + }); + + RED.httpAdmin.post('/pushbullet/:id',function(req,res) { + var body = ""; + req.on('data', function(chunk) { + body+=chunk; + }); + req.on('end', function(){ + var newCreds = querystring.parse(body); + var credentials = RED.nodes.getCredentials(req.params.id)||{}; + if (newCreds.deviceid === null || newCreds.deviceid === "") { + delete credentials.deviceid; + } else { + credentials.deviceid = newCreds.deviceid; + } + if (newCreds.pushkey === "") { + delete credentials.pushkey; + } else { + credentials.pushkey = newCreds.pushkey||credentials.pushkey; + } + RED.nodes.addCredentials(req.params.id,credentials); + res.send(200); + }); + }); +} diff --git a/social/pushbullet/LICENSE b/social/pushbullet/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/social/pushbullet/LICENSE @@ -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 diff --git a/social/pushbullet/README.md b/social/pushbullet/README.md new file mode 100644 index 00000000..4084eea1 --- /dev/null +++ b/social/pushbullet/README.md @@ -0,0 +1,21 @@ +node-red-node-pushbullet +======================== + +A Node-RED node to send alerts via Pushbullet. + +Install +------- + +Run the following command in the root directory of your Node-RED install + + npm install node-red-node-pushbullet + + +Usage +----- + +Uses PushBullet to push the msg.payload to a device that has the PushBullet app installed. + +Optionally uses msg.topic to set the title, if not already set in the properties. + +You need to configure both your API key and the target device ID. The device ID may be passed in as msg.deviceid. You can set these per node in the edit dialog. diff --git a/social/pushbullet/package.json b/social/pushbullet/package.json new file mode 100644 index 00000000..de4ed94d --- /dev/null +++ b/social/pushbullet/package.json @@ -0,0 +1,24 @@ +{ + "name" : "node-red-node-pushbullet", + "version" : "0.0.2", + "description" : "A Node-RED node to send alerts via Pushbullet", + "dependencies" : { + "pushbullet" : "1.4.*" + }, + "repository" : { + "type":"git", + "url":"https://github.com/node-red/node-red-nodes/tree/master/hardware/pushbullet" + }, + "license": "Apache", + "keywords": [ "node-red", "pushbullet" ], + "node-red" : { + "nodes" : { + "pushbullet": "57-pushbullet.js" + } + }, + "author": { + "name": "Dave Conway-Jones", + "email": "ceejay@vnet.ibm.com", + "url": "http://nodered.org" + } +} diff --git a/social/pusher/114-pusher.html b/social/pusher/114-pusher.html new file mode 100644 index 00000000..086a681d --- /dev/null +++ b/social/pusher/114-pusher.html @@ -0,0 +1,184 @@ + + + + + + + + + + + + + + + + + diff --git a/social/pusher/114-pusher.js b/social/pusher/114-pusher.js new file mode 100644 index 00000000..13bf5268 --- /dev/null +++ b/social/pusher/114-pusher.js @@ -0,0 +1,157 @@ +/** +* pusher.js +* Subscription module for the Pusher service (www.pusher.com) +* Requires 'pusher' and 'pusher-client' modules. +* +* Copyright 2014 Charalampos Doukas, @BuildingIoT +* +* 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 Pusher = require('pusher'); + var PusherClient = require('pusher-client'); + + //node for subscribing to an event/channel + function PusherNode(n) { + // Create a RED node + RED.nodes.createNode(this,n); + + var node = this; + var credentials = RED.nodes.getCredentials(n.id); + + if ((credentials) && (credentials.hasOwnProperty("pusherappkey_sub"))) { this.appkey = credentials.pusherappkey_sub; } + else { this.error("No Pusher app key set for input node"); } + + //get parameters from user + this.channel = n.channel; + this.eventname = n.eventname; + + //create a subscription to the channel and event defined by user + var socket = new PusherClient(''+this.appkey); + var my_channel = socket.subscribe(''+this.channel); + socket.bind(''+this.eventname, + function(data) { + var msg = {}; + if (data.hasOwnProperty("payload")) { msg.payload = data.payload; } + else { msg.payload = data; } + node.send(msg); + } + ); + + this.on("close", function() { + socket.disconnect(); + }); + } + + //Node for sending Pusher events + function PusherNodeSend(n) { + // Create a RED node + RED.nodes.createNode(this,n); + + var node = this; + + var credentials = RED.nodes.getCredentials(n.id); + + if ((credentials) && (credentials.hasOwnProperty("pusherappid"))) { this.appid = credentials.pusherappid; } + else { this.error("No Pusher api token set"); } + if ((credentials) && (credentials.hasOwnProperty("pusherappsecret"))) { this.appsecret = credentials.pusherappsecret; } + else { this.error("No Pusher user secret set"); } + if ((credentials) && (credentials.hasOwnProperty("pusherappkey"))) { this.appkey = credentials.pusherappkey; } + else { this.error("No Pusher user key set"); } + + //get parameters from user + this.channel = n.channel; + this.eventname = n.eventname; + + var pusher = new Pusher({ + appId: this.appid, + key: this.appkey, + secret: this.appsecret + }); + + this.on("input", function(msg){ + pusher.trigger(this.channel, this.eventname, { + "payload": msg.payload + }); + }); + + this.on("close", function() { + }); + } + + //debugging on the output: + var displayResult = function(result) { + node.log(result); + }; + + var displayError = function(err) { + node.log("Error: "+err); + }; + + RED.nodes.registerType("pusher in",PusherNode); + RED.nodes.registerType("pusher out",PusherNodeSend); + + var querystring = require('querystring'); + + RED.httpAdmin.get('/pusher/:id',function(req,res) { + var credentials = RED.nodes.getCredentials(req.params.id); + if (credentials) { + res.send(JSON.stringify({pusherappid:credentials.pusherappid,pusherappsecret:credentials.pusherappsecret, pusherappkey:credentials.pusherappkey, pusherappkey_sub:credentials.pusherappkey_sub})); + } else { + res.send(JSON.stringify({})); + } + }); + + RED.httpAdmin.delete('/pusher/:id',function(req,res) { + RED.nodes.deleteCredentials(req.params.id); + res.send(200); + }); + + RED.httpAdmin.post('/pusher/:id',function(req,res) { + var body = ""; + req.on('data', function(chunk) { + body+=chunk; + }); + req.on('end', function(){ + var newCreds = querystring.parse(body); + var credentials = RED.nodes.getCredentials(req.params.id)||{}; + + if (newCreds.pusherappid === null || newCreds.pusherappid === "") { + delete credentials.pusherappid; + } else { + credentials.pusherappid = newCreds.pusherappid; + } + if (newCreds.pusherappkey === "") { + delete credentials.pusherappkey; + } else { + credentials.pusherappkey = newCreds.pusherappkey||credentials.pusherappkey; + } + + if (newCreds.pusherappsecret === "") { + delete credentials.pusherappsecret; + } else { + credentials.pusherappsecret = newCreds.pusherappsecret||credentials.pusherappsecret; + } + + if (newCreds.pusherappkey_sub === "") { + delete credentials.pusherappkey_sub; + } else { + credentials.pusherappkey_sub = newCreds.pusherappkey_sub||credentials.pusherappkey_sub; + } + + RED.nodes.addCredentials(req.params.id,credentials); + res.send(200); + }); + }); +} diff --git a/social/pusher/icons/pusher.png b/social/pusher/icons/pusher.png new file mode 100644 index 00000000..04bc1635 Binary files /dev/null and b/social/pusher/icons/pusher.png differ diff --git a/social/pushover/57-pushover.html b/social/pushover/57-pushover.html new file mode 100644 index 00000000..02329b7c --- /dev/null +++ b/social/pushover/57-pushover.html @@ -0,0 +1,109 @@ + + + + + + + diff --git a/social/pushover/57-pushover.js b/social/pushover/57-pushover.js new file mode 100644 index 00000000..d309260f --- /dev/null +++ b/social/pushover/57-pushover.js @@ -0,0 +1,112 @@ +/** + * 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 PushOver = require('pushover-notifications'); + var util = require('util'); + + function PushoverNode(n) { + RED.nodes.createNode(this,n); + this.title = n.title; + this.priority = n.priority; + var credentials = RED.nodes.getCredentials(n.id); + if ((credentials) && (credentials.hasOwnProperty("pushkey"))) { this.pushkey = credentials.pushkey; } + else { this.error("No Pushover api token set"); } + if ((credentials) && (credentials.hasOwnProperty("deviceid"))) { this.deviceid = credentials.deviceid; } + else { this.error("No Pushover user key set"); } + var pusher = false; + if (this.pushkey && this.deviceid) { + pusher = new PushOver({ + user: this.deviceid, + token: this.pushkey, + onerror: function(err) { + util.log('[57-pushover.js] Error: '+err); + } + }); + } + var node = this; + + this.on("input",function(msg) { + var titl = this.title || msg.topic || "Node-RED"; + var pri = this.priority || msg.priority || 0; + if (isNaN(pri)) {pri=0;} + if (pri > 2) {pri = 2;} + if (pri < -1) {pri = -1;} + if (typeof(msg.payload) === 'object') { + msg.payload = JSON.stringify(msg.payload); + } + else { msg.payload = msg.payload.toString(); } + if (pusher) { + var pushmsg = { + message: msg.payload, + title: titl, + priority: pri, + retry: 30, + expire: 600 + }; + //console.log("Sending",pushmsg); + pusher.send( pushmsg, function(err, response) { + if (err) { node.error("Pushover Error: "+err); } + //console.log(response); + }); + } + else { + node.warn("Pushover credentials not set."); + } + }); + } + RED.nodes.registerType("pushover",PushoverNode); + + var querystring = require('querystring'); + + RED.httpAdmin.get('/pushover/:id',function(req,res) { + var credentials = RED.nodes.getCredentials(req.params.id); + if (credentials) { + res.send(JSON.stringify({deviceid:credentials.deviceid,hasPassword:(credentials.pushkey&&credentials.pushkey!=="")})); + } else { + res.send(JSON.stringify({})); + } + }); + + RED.httpAdmin.delete('/pushover/:id',function(req,res) { + RED.nodes.deleteCredentials(req.params.id); + res.send(200); + }); + + RED.httpAdmin.post('/pushover/:id',function(req,res) { + var body = ""; + req.on('data', function(chunk) { + body+=chunk; + }); + req.on('end', function(){ + var newCreds = querystring.parse(body); + var credentials = RED.nodes.getCredentials(req.params.id)||{}; + if (newCreds.deviceid === null || newCreds.deviceid === "") { + delete credentials.deviceid; + } else { + credentials.deviceid = newCreds.deviceid; + } + if (newCreds.pushkey === "") { + delete credentials.pushkey; + } else { + credentials.pushkey = newCreds.pushkey||credentials.pushkey; + } + RED.nodes.addCredentials(req.params.id,credentials); + res.send(200); + }); + }); +} diff --git a/social/pushover/LICENSE b/social/pushover/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/social/pushover/LICENSE @@ -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 diff --git a/social/pushover/README.md b/social/pushover/README.md new file mode 100644 index 00000000..3ff18ebc --- /dev/null +++ b/social/pushover/README.md @@ -0,0 +1,23 @@ +node-red-node-pushover +====================== + +A Node-RED node to send alerts via Pushover. + +Install +------- + +Run the following command in the root directory of your Node-RED install + + npm install node-red-node-pushover + + +Usage +----- + +Uses Pushover to push the msg.payload to a device that has the Pushover app installed. + +Optionally uses **msg.topic** to set the title, and **msg.priority** to set the priority, if not already set in the properties. + +The User-key and API-token are stored in a separate credentials file. + +Uses Pushover. See Pushover.net for more details. diff --git a/social/pushover/icons/pushover.png b/social/pushover/icons/pushover.png new file mode 100644 index 00000000..faeb8be6 Binary files /dev/null and b/social/pushover/icons/pushover.png differ diff --git a/social/pushover/package.json b/social/pushover/package.json new file mode 100644 index 00000000..c33c8418 --- /dev/null +++ b/social/pushover/package.json @@ -0,0 +1,24 @@ +{ + "name" : "node-red-node-pushover", + "version" : "0.0.1", + "description" : "A Node-RED node to send alerts via Pushover", + "dependencies" : { + "pushover-notifications" : "0.2.0" + }, + "repository" : { + "type":"git", + "url":"https://github.com/node-red/node-red-nodes/tree/master/social/pushover" + }, + "license": "Apache", + "keywords": [ "node-red", "pushover" ], + "node-red" : { + "nodes" : { + "pushover": "57-pushover.js" + } + }, + "author": { + "name": "Dave Conway-Jones", + "email": "ceejay@vnet.ibm.com", + "url": "http://nodered.org" + } +} diff --git a/social/snapchat/79-snapchat.html b/social/snapchat/79-snapchat.html index f1fb9a74..62ba94a9 100644 --- a/social/snapchat/79-snapchat.html +++ b/social/snapchat/79-snapchat.html @@ -1,12 +1,12 @@ + + + + + + - + + + + diff --git a/social/xmpp/92-xmpp.js b/social/xmpp/92-xmpp.js index f7755bc3..06373a6e 100644 --- a/social/xmpp/92-xmpp.js +++ b/social/xmpp/92-xmpp.js @@ -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. @@ -14,48 +14,92 @@ * limitations under the License. **/ -var orig=console.warn; -console.warn=(function() { // suppress warning from stringprep when not needed) - var orig=console.warn; - return function() { - //orig.apply(console, arguments); - }; -})(); +module.exports = function(RED) { +"use strict"; +var XMPP = require('simple-xmpp'); -var RED = require(process.env.NODE_RED_HOME+"/red/red"); -var xmpp = require('simple-xmpp'); -console.warn = orig; +try { var xmppkey = RED.settings.xmpp || require(process.env.NODE_RED_HOME+"/../xmppkeys.js"); } +catch(err) { } -try { - var xmppkey = RED.settings.xmpp || require(process.env.NODE_RED_HOME+"/../xmppkeys.js"); -} catch(err) { - throw new Error("Failed to load XMPP credentials"); -} - -function XmppNode(n) { +function XMPPServerNode(n) { RED.nodes.createNode(this,n); this.server = n.server; this.port = n.port; + this.nickname = n.nickname; + var credentials = RED.nodes.getCredentials(n.id); + if (credentials) { + this.username = credentials.user; + this.password = credentials.password; + } +} +RED.nodes.registerType("xmpp-server",XMPPServerNode); + +var querystring = require('querystring'); + +RED.httpAdmin.get('/xmpp-server/:id',function(req,res) { + var credentials = RED.nodes.getCredentials(req.params.id); + if (credentials) { + res.send(JSON.stringify({user:credentials.user,hasPassword:(credentials.password&&credentials.password!=="")})); + } else if (xmppkey && xmppkey.jid && xmppkey.password) { + RED.nodes.addCredentials(req.params.id,{user:xmppkey.jid, password:xmppkey.password, global:true}); + credentials = RED.nodes.getCredentials(req.params.id); + res.send(JSON.stringify({user:credentials.user,global:credentials.global,hasPassword:(credentials.password&&credentials.password!=="")})); + } else { + res.send(JSON.stringify({})); + } +}); + +RED.httpAdmin.delete('/xmpp-server/:id',function(req,res) { + RED.nodes.deleteCredentials(req.params.id); + res.send(200); +}); + +RED.httpAdmin.post('/xmpp-server/:id',function(req,res) { + var body = ""; + req.on('data', function(chunk) { + body+=chunk; + }); + req.on('end', function(){ + var newCreds = querystring.parse(body); + var credentials = RED.nodes.getCredentials(req.params.id)||{}; + if (newCreds.user == null || newCreds.user === "") { + delete credentials.user; + } else { + credentials.user = newCreds.user; + } + if (newCreds.password === "") { + delete credentials.password; + } else { + credentials.password = newCreds.password||credentials.password; + } + RED.nodes.addCredentials(req.params.id,credentials); + res.send(200); + }); +}); + + +function XmppInNode(n) { + RED.nodes.createNode(this,n); + this.server = n.server; + + this.serverConfig = RED.nodes.getNode(this.server); + this.host = this.serverConfig.server; + this.port = this.serverConfig.port; + this.nick = this.serverConfig.nickname || "Node-RED"; + this.userid = this.serverConfig.username; + this.password = this.serverConfig.password; + this.join = n.join || false; - this.nick = n.nick || "Node-RED"; this.sendAll = n.sendObject; this.to = n.to || ""; var node = this; - setTimeout(function() { - xmpp.connect({ - jid : xmppkey.jid, - password : xmppkey.password, - host : this.server, - port : this.port, - skipPresence : true, - reconnect : false - }); - }, 5000); + var xmpp = new XMPP.SimpleXMPP(); xmpp.on('online', function() { - node.log('connected to '+node.server); - xmpp.setPresence('online', node.nick+' online'); + node.log('connected to '+node.host+":"+node.port); + node.status({fill:"green",shape:"dot",text:"connected"}); + //xmpp.setPresence('online', node.nick+' online'); if (node.join) { xmpp.join(node.to+'/'+node.nick); } @@ -84,39 +128,126 @@ function XmppNode(n) { }); xmpp.on('error', function(err) { - console.error(err); + console.error("error",err); }); xmpp.on('close', function(err) { node.log('connection closed'); + node.status({fill:"red",shape:"ring",text:"not connected"}); }); xmpp.on('subscribe', function(from) { xmpp.acceptSubscription(from); }); - this.on("input", function(msg) { - var to = msg.topic; - if (node.to != "") { to = node.to; } - if (node.sendAll) { - xmpp.send(to, JSON.stringify(msg), node.join); - } - else { - xmpp.send(to, msg.payload, node.join); - } - }); + // Now actually make the connection + try { + xmpp.connect({ + jid : node.userid, + password : node.password, + host : node.host, + port : node.port, + skipPresence : true, + reconnect : false + }); + } catch(e) { + node.error("Bad xmpp configuration"); + node.status({fill:"red",shape:"ring",text:"not connected"}); + } - this.on("close", function() { - xmpp.setPresence('offline'); - try { - xmpp.disconnect(); - // TODO - DCJ NOTE... this is not good. It leaves the connection up over a restart - which will end up with bad things happening... - // (but requires the underlying xmpp lib to be fixed, which does have an open bug request on fixing the close method - and a work around. - // see - https://github.com/simple-xmpp/node-simple-xmpp/issues/12 for the fix - } catch(e) { - this.warn("Due to an underlying bug in the xmpp library this does not disconnect old sessions. This is bad... A restart would be better."); - } + node.on("close", function(done) { + //xmpp.setPresence('offline'); + if (xmpp.conn) { xmpp.conn.end(); } + xmpp = null; + done(); }); } +RED.nodes.registerType("xmpp in",XmppInNode); -RED.nodes.registerType("xmpp",XmppNode); +function XmppOutNode(n) { + RED.nodes.createNode(this,n); + this.server = n.server; + + this.serverConfig = RED.nodes.getNode(this.server); + this.host = this.serverConfig.server; + this.port = this.serverConfig.port; + this.nick = this.serverConfig.nickname || "Node-RED"; + this.userid = this.serverConfig.username; + this.password = this.serverConfig.password; + + this.join = n.join || false; + this.sendAll = n.sendObject; + this.to = n.to || ""; + var node = this; + + var xmpp = new XMPP.SimpleXMPP(); + + xmpp.on('online', function() { + node.log('connected to '+node.host+":"+node.port); + node.status({fill:"green",shape:"dot",text:"connected"}); + xmpp.setPresence('online', node.nick+' online'); + if (node.join) { + xmpp.join(node.to+'/'+node.nick); + } + }); + + xmpp.on('error', function(err) { + console.error("error",err); + }); + + xmpp.on('close', function(err) { + node.log('connection closed'); + node.status({fill:"red",shape:"ring",text:"not connected"}); + }); + + xmpp.on('subscribe', function(from) { + xmpp.acceptSubscription(from); + }); + + // Now actually make the connection + try { + xmpp.connect({ + jid : node.userid, + password : node.password, + host : node.host, + port : node.port, + skipPresence : true, + reconnect : false + }); + } catch(e) { + node.error("Bad xmpp configuration"); + node.status({fill:"red",shape:"ring",text:"not connected"}); + } + + node.on("input", function(msg) { + if (msg.presence) { + if (['away', 'dnd', 'xa','chat'].indexOf(msg.presence) > -1 ) { + xmpp.setPresence(msg.presence, msg.payload); + } + else { node.warn("Can't set presence - invalid value"); } + } + else { + var to = msg.topic; + if (node.to !== "") { to = node.to; } + if (node.sendAll) { + xmpp.send(to, JSON.stringify(msg), node.join); + } + else if (msg.payload) { + if (typeof(msg.payload) === "object") { + xmpp.send(to, JSON.stringify(msg.payload), node.join); + } else { + xmpp.send(to, msg.payload.toString(), node.join); + } + } + } + }); + + node.on("close", function() { + xmpp.setPresence('offline'); + if (xmpp.conn) { xmpp.conn.end(); } + xmpp = null; + }); +} +RED.nodes.registerType("xmpp out",XmppOutNode); + +} diff --git a/social/xmpp/LICENSE b/social/xmpp/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/social/xmpp/LICENSE @@ -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 diff --git a/social/xmpp/README.md b/social/xmpp/README.md new file mode 100644 index 00000000..e9aed75e --- /dev/null +++ b/social/xmpp/README.md @@ -0,0 +1,44 @@ +node-red-node-xmpp +================== + +A Node-RED node to talk to an XMPP server. + +Install +------- + +Run the following command in the root directory of your Node-RED install + + npm install node-red-node-xmpp + + +Usage +----- + +Provides two nodes - one to send messages, and one to receive. + +###Receive + +Connects to an XMPP server to receive messages.

+ +The Buddy field is the id of the buddy or room you want to receive messages from. + +Incoming messages will appear as msg.payload on the first output, while msg.topic will contain who it is from. + +The second output will show the presence and status of a user in msg.payload. Again msg.topic will hold the user. + +###Send + +Connects to an XMPP server to send messages. + +The To field is optional. If not set the msg.topic property of the message is used to set that value. + +If you are joining a chat room then the To field must be filled in with the room name. + +You may also send a msg with msg.presence to set your presence to one of + + 1. chat + 2. away + 3. dnd + 4. xa + +If you do so then the msg.payload is used to set your status message.

diff --git a/social/xmpp/icons/xmpp.png b/social/xmpp/icons/xmpp.png index 57e43fc4..636847e3 100644 Binary files a/social/xmpp/icons/xmpp.png and b/social/xmpp/icons/xmpp.png differ diff --git a/social/xmpp/package.json b/social/xmpp/package.json new file mode 100644 index 00000000..0da9298d --- /dev/null +++ b/social/xmpp/package.json @@ -0,0 +1,24 @@ +{ + "name" : "node-red-node-xmpp", + "version" : "0.0.2", + "description" : "A Node-RED node to talk to an XMPP server", + "dependencies" : { + "simple-xmpp" : "0.1.19" + }, + "repository" : { + "type":"git", + "url":"https://github.com/node-red/node-red-nodes/tree/master/social/xmpp" + }, + "license": "Apache-2.0", + "keywords": [ "node-red", "xmpp" ], + "node-red" : { + "nodes" : { + "xmpp": "92-xmpp.js" + } + }, + "author": { + "name": "Dave Conway-Jones", + "email": "ceejay@vnet.ibm.com", + "url": "http://nodered.org" + } +} diff --git a/storage/ddb/69-ddbout.html b/storage/ddb/69-ddbout.html index 3f0859bd..e8db2edd 100644 --- a/storage/ddb/69-ddbout.html +++ b/storage/ddb/69-ddbout.html @@ -16,19 +16,19 @@ diff --git a/storage/ddb/69-ddbout.js b/storage/ddb/69-ddbout.js index 939d7d23..1d803bb9 100644 --- a/storage/ddb/69-ddbout.js +++ b/storage/ddb/69-ddbout.js @@ -21,6 +21,7 @@ var attrWrapper = require("dynamodb-data-types").AttributeValue; function DDBOutNode(n) { RED.nodes.createNode(this, n); + this.warn("This node has been deprecated and will be deleted in a future release. Please update your flow to use the version from npm. Note: you cannot have both this and the npm version installed at the same time."); this.credentials = RED.nodes.getNode(n.credentials); this.region = n.region || "us-east-1"; this.table = n.table; @@ -32,13 +33,11 @@ function DDBOutNode(n) { var ddb = new aws.DynamoDB(); this.on("input", function(msg) { - if (msg != null) { - ddb.putItem({ "TableName": this.table, - "Item": attrWrapper.wrap(msg.payload) }, + ddb.putItem({ "TableName": this.table, + "Item": attrWrapper.wrap(msg.payload) }, function(err, data) { - err && util.log(err); - }); - } + if (err) { util.log(err); } + }); }); } RED.nodes.registerType("ddb out", DDBOutNode); diff --git a/storage/ddb/aws.html b/storage/ddb/aws.html index 5c26c904..8d6aeb87 100644 --- a/storage/ddb/aws.html +++ b/storage/ddb/aws.html @@ -16,11 +16,11 @@ diff --git a/storage/leveldb/67-leveldb.html b/storage/leveldb/67-leveldb.html index 72ead707..e889a15a 100644 --- a/storage/leveldb/67-leveldb.html +++ b/storage/leveldb/67-leveldb.html @@ -16,7 +16,7 @@ @@ -35,11 +35,11 @@ @@ -75,18 +75,18 @@ diff --git a/storage/leveldb/67-leveldb.js b/storage/leveldb/67-leveldb.js index f4a91db6..9e1d56bf 100644 --- a/storage/leveldb/67-leveldb.js +++ b/storage/leveldb/67-leveldb.js @@ -14,81 +14,83 @@ * limitations under the License. **/ -var RED = require(process.env.NODE_RED_HOME+"/red/red"); -var lvldb = require('level'); +module.exports = function(RED) { + "use strict"; + var lvldb = require('level'); -function LevelNode(n) { - RED.nodes.createNode(this,n); - this.dbname = n.db; - var node = this; - lvldb(this.dbname, function(err, db) { - if (err) node.error(err); - node.db = db; - }); - this.on('close', function() { - if (node.db) { node.db.close(); } - }); -} -RED.nodes.registerType("leveldbase",LevelNode); - - -function LevelDBNodeIn(n) { - RED.nodes.createNode(this,n); - this.level = n.level; - this.levelConfig = RED.nodes.getNode(this.level); - - if (this.levelConfig) { + function LevelNode(n) { + RED.nodes.createNode(this,n); + this.dbname = n.db; var node = this; - node.on("input", function(msg) { - if (typeof msg.topic === 'string') { - node.levelConfig.db.get(msg.topic, function(err, value) { - if (err) { - //node.warn(err); - // for some reason they treat nothing found as an error... - msg.payload = null; // so we should return null - } - else { msg.payload = value; } - node.send(msg); - }); - } - else { - if (typeof msg.topic !== 'string') node.error("msg.topic (the key is not defined"); - } + lvldb(this.dbname, function(err, db) { + if (err) { node.error(err); } + node.db = db; + }); + this.on('close', function() { + if (node.db) { node.db.close(); } }); } - else { - this.error("LevelDB database name not configured"); - } -} -RED.nodes.registerType("leveldb in",LevelDBNodeIn); + RED.nodes.registerType("leveldbase",LevelNode); -function LevelDBNodeOut(n) { - RED.nodes.createNode(this,n); - this.level = n.level; - this.operation = n.operation; - this.levelConfig = RED.nodes.getNode(this.level); + function LevelDBNodeIn(n) { + RED.nodes.createNode(this,n); + this.level = n.level; + this.levelConfig = RED.nodes.getNode(this.level); - if (this.levelConfig) { - var node = this; - node.on("input", function(msg) { - if (typeof msg.topic === 'string') { - if (node.operation === "delete") { - node.levelConfig.db.del(msg.topic); - } - else { - node.levelConfig.db.put(msg.topic, msg.payload, function(err) { - if (err) node.error(err); + if (this.levelConfig) { + var node = this; + node.on("input", function(msg) { + if (typeof msg.topic === 'string') { + node.levelConfig.db.get(msg.topic, function(err, value) { + if (err) { + //node.warn(err); + // for some reason they treat nothing found as an error... + msg.payload = null; // so we should return null + } + else { msg.payload = value; } + node.send(msg); }); } - } - else { - if (typeof msg.topic !== 'string') node.error("msg.topic (the key is not defined"); - } - }); + else { + if (typeof msg.topic !== 'string') { node.error("msg.topic (the key is not defined"); } + } + }); + } + else { + this.error("LevelDB database name not configured"); + } } - else { - this.error("LevelDB database name not configured"); + RED.nodes.registerType("leveldb in",LevelDBNodeIn); + + + function LevelDBNodeOut(n) { + RED.nodes.createNode(this,n); + this.level = n.level; + this.operation = n.operation; + this.levelConfig = RED.nodes.getNode(this.level); + + if (this.levelConfig) { + var node = this; + node.on("input", function(msg) { + if (typeof msg.topic === 'string') { + if (node.operation === "delete") { + node.levelConfig.db.del(msg.topic); + } + else { + node.levelConfig.db.put(msg.topic, msg.payload, function(err) { + if (err) { node.error(err); } + }); + } + } + else { + if (typeof msg.topic !== 'string') { node.error("msg.topic (the key is not defined"); } + } + }); + } + else { + this.error("LevelDB database name not configured"); + } } + RED.nodes.registerType("leveldb out",LevelDBNodeOut); } -RED.nodes.registerType("leveldb out",LevelDBNodeOut); diff --git a/storage/leveldb/LICENSE b/storage/leveldb/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/storage/leveldb/LICENSE @@ -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 diff --git a/storage/leveldb/README.md b/storage/leveldb/README.md new file mode 100644 index 00000000..7dbc770d --- /dev/null +++ b/storage/leveldb/README.md @@ -0,0 +1,26 @@ +node-red-node-leveldb +===================== +A Node-RED node to read and write to a LevelDB database. + +Install +------- + +Run the following command in the root directory of your Node-RED install + + npm install node-red-node-leveldb + + +Usage +----- + +Allows basic access to a LevelDB database. + +Uses LevelDB for a simple key value pair database. + +There are two node to choose from... + +Use one node to either put (store) the msg.payload to the named database file, using msg.topic as the key, or to delete information select delete in the properties dialogue and again use msg.topic as the key.. + +Use the other node to get, or retrieve the data already saved in the database. + +Again use msg.topic to hold the key for the database, and the result is returned in msg.payload. If nothing is found for the key then null is returned. diff --git a/storage/leveldb/icons/leveldb.png b/storage/leveldb/icons/leveldb.png new file mode 100644 index 00000000..55760c7d Binary files /dev/null and b/storage/leveldb/icons/leveldb.png differ diff --git a/storage/leveldb/package.json b/storage/leveldb/package.json new file mode 100644 index 00000000..066c9362 --- /dev/null +++ b/storage/leveldb/package.json @@ -0,0 +1,24 @@ +{ + "name" : "node-red-node-leveldb", + "version" : "0.0.1", + "description" : "A Node-RED node to read and write to a LevelDB database", + "dependencies" : { + "level" : "0.18.0" + }, + "repository" : { + "type":"git", + "url":"https://github.com/node-red/node-red-nodes/tree/master/storage/leveldb" + }, + "license": "Apache", + "keywords": [ "node-red", "leveldb" ], + "node-red" : { + "nodes" : { + "leveldb": "67-leveldb.js" + } + }, + "author": { + "name": "Dave Conway-Jones", + "email": "ceejay@vnet.ibm.com", + "url": "http://nodered.org" + } +} diff --git a/storage/mysql/68-mysql.html b/storage/mysql/68-mysql.html index a68e642b..aa66dc57 100644 --- a/storage/mysql/68-mysql.html +++ b/storage/mysql/68-mysql.html @@ -16,25 +16,29 @@ diff --git a/storage/mysql/68-mysql.js b/storage/mysql/68-mysql.js index d4141130..c4f889ed 100644 --- a/storage/mysql/68-mysql.js +++ b/storage/mysql/68-mysql.js @@ -14,182 +14,155 @@ * limitations under the License. **/ -var RED = require(process.env.NODE_RED_HOME+"/red/red"); -var reconnect = RED.settings.mysqlReconnectTime || 30000; -var mysqldb = require('mysql'); -var querystring = require('querystring'); +module.exports = function(RED) { + "use strict"; + var reconnect = RED.settings.mysqlReconnectTime || 30000; + var mysqldb = require('mysql'); + var querystring = require('querystring'); -RED.httpAdmin.get('/MySQLdatabase/:id',function(req,res) { - var credentials = RED.nodes.getCredentials(req.params.id); - if (credentials) { - res.send(JSON.stringify({user:credentials.user,hasPassword:(credentials.password&&credentials.password!="")})); - } else { - res.send(JSON.stringify({})); - } -}); - -RED.httpAdmin.delete('/MySQLdatabase/:id',function(req,res) { - RED.nodes.deleteCredentials(req.params.id); - res.send(200); -}); - -RED.httpAdmin.post('/MySQLdatabase/:id',function(req,res) { - var body = ""; - req.on('data', function(chunk) { - body+=chunk; + RED.httpAdmin.get('/MySQLdatabase/:id',function(req,res) { + var credentials = RED.nodes.getCredentials(req.params.id); + if (credentials) { + res.send(JSON.stringify({user:credentials.user,hasPassword:(credentials.password&&credentials.password!=="")})); + } else { + res.send(JSON.stringify({})); + } }); - req.on('end', function(){ - var newCreds = querystring.parse(body); - var credentials = RED.nodes.getCredentials(req.params.id)||{}; - if (newCreds.user == null || newCreds.user == "") { - delete credentials.user; - } else { - credentials.user = newCreds.user; - } - if (newCreds.password == "") { - delete credentials.password; - } else { - credentials.password = newCreds.password||credentials.password; - } - RED.nodes.addCredentials(req.params.id,credentials); + + RED.httpAdmin.delete('/MySQLdatabase/:id',function(req,res) { + RED.nodes.deleteCredentials(req.params.id); res.send(200); }); -}); + + RED.httpAdmin.post('/MySQLdatabase/:id',function(req,res) { + var body = ""; + req.on('data', function(chunk) { + body+=chunk; + }); + req.on('end', function(){ + var newCreds = querystring.parse(body); + var credentials = RED.nodes.getCredentials(req.params.id)||{}; + if (newCreds.user == null || newCreds.user === "") { + delete credentials.user; + } else { + credentials.user = newCreds.user; + } + if (newCreds.password === "") { + delete credentials.password; + } else { + credentials.password = newCreds.password||credentials.password; + } + RED.nodes.addCredentials(req.params.id,credentials); + res.send(200); + }); + }); -function MySQLNode(n) { - RED.nodes.createNode(this,n); - this.host = n.host; - this.port = n.port; + function MySQLNode(n) { + RED.nodes.createNode(this,n); + this.host = n.host; + this.port = n.port; + this.tz = n.tz || "local"; - this.connected = false; - this.connecting = false; + this.connected = false; + this.connecting = false; - if (n.user) { var credentials = {}; - credentials.user = n.user; - credentials.password = n.pass; - RED.nodes.addCredentials(n.id,credentials); - this.user = n.user; - this.password = n.pass; - } else { - var credentials = RED.nodes.getCredentials(n.id); - if (credentials) { - this.user = credentials.user; - this.password = credentials.password; - } - } - - this.dbname = n.db; - var node = this; - - function doConnect() { - node.connecting = true; - node.connection = mysqldb.createConnection({ - host : node.host, - port : node.port, - user : node.user, - password : node.password, - database : node.dbname, - insecureAuth: true - }); - - node.connection.connect(function(err) { - node.connecting = false; - if (err) { - node.warn(err); - node.tick = setTimeout(doConnect, reconnect); - } else { - node.connected = true; + if (n.user) { + credentials.user = n.user; + credentials.password = n.pass; + RED.nodes.addCredentials(n.id,credentials); + this.user = n.user; + this.password = n.pass; + } else { + credentials = RED.nodes.getCredentials(n.id); + if (credentials) { + this.user = credentials.user; + this.password = credentials.password; } - }); - - node.connection.on('error', function(err) { - node.connected = false; - if (err.code === 'PROTOCOL_CONNECTION_LOST') { - doConnect(); // silently reconnect... - } else { - node.error(err); - doConnect(); - } - }); - } - - this.connect = function() { - if (!this.connected && !this.connecting) { - doConnect(); } - } - this.on('close', function () { - if (this.tick) { clearTimeout(this.tick); } - if (this.connection) { - node.connection.end(function(err) { - if (err) node.error(err); + this.dbname = n.db; + var node = this; + + function doConnect() { + node.connecting = true; + node.connection = mysqldb.createConnection({ + host : node.host, + port : node.port, + user : node.user, + password : node.password, + database : node.dbname, + timezone : node.tz, + insecureAuth: true + }); + + node.connection.connect(function(err) { + node.connecting = false; + if (err) { + node.warn(err); + node.tick = setTimeout(doConnect, reconnect); + } else { + node.connected = true; + } + }); + + node.connection.on('error', function(err) { + node.connected = false; + if (err.code === 'PROTOCOL_CONNECTION_LOST') { + doConnect(); // silently reconnect... + } else { + node.error(err); + doConnect(); + } }); } - }); -} -RED.nodes.registerType("MySQLdatabase",MySQLNode); - -function MysqlDBNodeIn(n) { - RED.nodes.createNode(this,n); - this.mydb = n.mydb; - this.mydbConfig = RED.nodes.getNode(this.mydb); - - if (this.mydbConfig) { - this.mydbConfig.connect(); - var node = this; - node.on("input", function(msg) { - if (typeof msg.topic === 'string') { - //console.log("query:",msg.topic); - node.mydbConfig.connection.query(msg.topic, function(err, rows) { - if (err) { node.warn(err); } - else { - msg.payload = rows; - node.send(msg); - } - }); + this.connect = function() { + if (!this.connected && !this.connecting) { + doConnect(); } - else { - if (typeof msg.topic !== 'string') node.error("msg.topic : the query is not defined as a string"); + } + + this.on('close', function () { + if (this.tick) { clearTimeout(this.tick); } + if (this.connection) { + node.connection.end(function(err) { + if (err) { node.error(err); } + }); } }); } - else { - this.error("MySQL database not configured"); + RED.nodes.registerType("MySQLdatabase",MySQLNode); + + + function MysqlDBNodeIn(n) { + RED.nodes.createNode(this,n); + this.mydb = n.mydb; + this.mydbConfig = RED.nodes.getNode(this.mydb); + + if (this.mydbConfig) { + this.mydbConfig.connect(); + var node = this; + node.on("input", function(msg) { + if (typeof msg.topic === 'string') { + //console.log("query:",msg.topic); + node.mydbConfig.connection.query(msg.topic, function(err, rows) { + if (err) { node.warn(err); } + else { + msg.payload = rows; + node.send(msg); + } + }); + } + else { + if (typeof msg.topic !== 'string') { node.error("msg.topic : the query is not defined as a string"); } + } + }); + } + else { + this.error("MySQL database not configured"); + } } + RED.nodes.registerType("mysql",MysqlDBNodeIn); } -RED.nodes.registerType("mysql",MysqlDBNodeIn); - - -//function MysqlDBNodeOut(n) { - //RED.nodes.createNode(this,n); - //this.level = n.level; - //this.operation = n.operation; - //this.levelConfig = RED.nodes.getNode(this.level); - - //if (this.levelConfig) { - //var node = this; - //node.on("input", function(msg) { - //if (typeof msg.topic === 'string') { - //if (node.operation === "delete") { - //node.levelConfig.db.del(msg.topic); - //} - //else { - //node.levelConfig.db.put(msg.topic, msg.payload, function(err) { - //if (err) node.error(err); - //}); - //} - //} - //else { - //if (typeof msg.topic !== 'string') node.error("msg.topic : the key is not defined"); - //} - //}); - //} - //else { - //this.error("MySQL database not configured"); - //} -//} -//RED.nodes.registerType("mysql out",MysqlDBNodeOut); diff --git a/storage/mysql/LICENSE b/storage/mysql/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/storage/mysql/LICENSE @@ -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 diff --git a/storage/mysql/README.md b/storage/mysql/README.md new file mode 100644 index 00000000..a2be5cb0 --- /dev/null +++ b/storage/mysql/README.md @@ -0,0 +1,29 @@ +node-red-node-mysql +======================== +A Node-RED node to read and write to a MySQL database. + +Install +------- + +Run the following command in the root directory of your Node-RED install + + npm install node-red-node-mysql + + +Usage +----- + +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... + +The msg.topic must hold the query for the database, and the result is returned in msg.payload. + +Typically the returned payload will be an array of the result rows. + +If nothing is found for the key then null is returned. + +The reconnect retry timeout in milliseconds can be changed by adding a line to settings.js +
mysqlReconnectTime: 30000,

diff --git a/storage/mysql/package.json b/storage/mysql/package.json new file mode 100644 index 00000000..3bd6818e --- /dev/null +++ b/storage/mysql/package.json @@ -0,0 +1,24 @@ +{ + "name" : "node-red-node-mysql", + "version" : "0.0.4", + "description" : "A Node-RED node to read and write to a MySQL database", + "dependencies" : { + "mysql" : "2.3.*" + }, + "repository" : { + "type":"git", + "url":"https://github.com/node-red/node-red-nodes/tree/master/storage/mysql" + }, + "license": "Apache", + "keywords": [ "node-red", "mysql" ], + "node-red" : { + "nodes" : { + "mysql": "68-mysql.js" + } + }, + "author": { + "name": "Dave Conway-Jones", + "email": "ceejay@vnet.ibm.com", + "url": "http://nodered.org" + } +} diff --git a/storage/postgres/110-postgres.html b/storage/postgres/110-postgres.html index 6fae6ac1..399a574d 100644 --- a/storage/postgres/110-postgres.html +++ b/storage/postgres/110-postgres.html @@ -16,19 +16,19 @@ @@ -86,11 +86,11 @@ + + + + + + + + + diff --git a/storage/sqlite/sqlite.js b/storage/sqlite/sqlite.js new file mode 100644 index 00000000..9a7e3b34 --- /dev/null +++ b/storage/sqlite/sqlite.js @@ -0,0 +1,80 @@ +/** + * 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 reconnect = RED.settings.sqliteReconnectTime || 20000; + var sqlite3 = require('sqlite3'); + + function SqliteNodeDB(n) { + RED.nodes.createNode(this,n); + + this.dbname = n.db; + var node = this; + + node.doConnect = function() { + node.db = new sqlite3.Database(node.dbname); + node.db.on('open',function(err) { + if (node.tick) { clearTimeout(node.tick); } + node.log("opened "+node.dbname+" ok"); + }); + node.db.on('error', function(err) { + node.warn(err); + node.log("failed to open "+node.dbname); + node.tick = setTimeout(doConnect, reconnect); + }); + } + + node.on('close', function () { + if (node.tick) { clearTimeout(node.tick); } + if (node.db) { node.db.close(); } + }); + } + RED.nodes.registerType("sqlitedb",SqliteNodeDB); + + + function SqliteNodeIn(n) { + RED.nodes.createNode(this,n); + this.mydb = n.mydb; + this.mydbConfig = RED.nodes.getNode(this.mydb); + + if (this.mydbConfig) { + this.mydbConfig.doConnect(); + var node = this; + node.on("input", function(msg) { + if (typeof msg.topic === 'string') { + //console.log("query:",msg.topic); + node.mydbConfig.db.all(msg.topic, function(err, row) { + if (err) { node.warn(err); } + else { + msg.payload = row; + node.send(msg); + } + }); + } + else { + if (typeof msg.topic !== 'string') { + node.error("msg.topic : the query is not defined as a string"); + } + } + }); + } + else { + this.error("Sqlite database not configured"); + } + } + RED.nodes.registerType("sqlite",SqliteNodeIn); +} diff --git a/test/utility/exif/94-exif_spec.js b/test/utility/exif/94-exif_spec.js new file mode 100644 index 00000000..30087415 --- /dev/null +++ b/test/utility/exif/94-exif_spec.js @@ -0,0 +1,76 @@ +/** + * 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 should = require("should"); +var sinon = require('sinon'); +var fs = require("fs"); + +var exifNode = require("../../../utility/exif/94-exif.js"); + +var helper = require('../../../../node-red/test/nodes/helper.js'); + +describe('exif node', function() { + + beforeEach(function(done) { + helper.startServer(done); + }); + + afterEach(function(done) { + helper.unload(); + helper.stopServer(done); + }); + + it('extracts location data from Exif data of JPEG', function(done) { + + var exif = require('exif'); + var ExifImage = exif.ExifImage; + + // the jpg file is a single black dot but it was originally a photo taken at IBM Hursley + var data = fs.readFileSync("./exif_test_image.jpg", null); // extracting genuine exif data to be fed back as the result of the stubbed ExifImage constructor + + var eD; + + new ExifImage({ image : data }, function (error, exifData) { + if(error) { + done(error); + } else { + eD = exifData; + } + + var flow = [{id:"exifNode1", type:"exif", wires:[["helperNode1"]]}, + {id:"helperNode1", type:"helper"}]; + + helper.load(exifNode, flow, function() { + var exifNode1 = helper.getNode("exifNode1"); + var helperNode1 = helper.getNode("helperNode1"); + + helperNode1.on("input", function(msg) { + msg.location.lat.should.equal(50.95624); // this data is stored in the jpg file + msg.location.lon.should.equal(-1.36701); + done(); + }); + + var stub = sinon.stub(ExifImage.prototype, 'loadImage', function(error, callback) { + stub.restore(); + callback(null, eD); + }); + + exifNode1.receive({payload:data}); + }); + }); + + }); +}); diff --git a/test/utility/exif/Gruntfile.js b/test/utility/exif/Gruntfile.js new file mode 100644 index 00000000..80a4296e --- /dev/null +++ b/test/utility/exif/Gruntfile.js @@ -0,0 +1,57 @@ +/** + * 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(grunt) { + + // Project configuration. + grunt.initConfig({ + simplemocha: { + options: { + globals: ['expect'], + timeout: 3000, + ignoreLeaks: false, + ui: 'bdd', + reporter: 'spec' + }, + all: { src: ['./*_spec.js'] }, + }, + jshint: { + options: { + // http://www.jshint.com/docs/options/ + "asi": true, // allow missing semicolons + "curly": true, // require braces + "eqnull": true, // ignore ==null + "forin": true, // require property filtering in "for in" loops + "immed": true, // require immediate functions to be wrapped in ( ) + "nonbsp": true, // warn on unexpected whitespace breaking chars + //"strict": true, // commented out for now as it causes 100s of warnings, but want to get there eventually + "loopfunc": true, // allow functions to be defined in loops + "sub": true // don't warn that foo['bar'] should be written as foo.bar + }, + all: { + src: ['../../../utility/exif/*.js'] + }, + } + }); + + grunt.loadNpmTasks('grunt-simple-mocha'); + grunt.loadNpmTasks('grunt-contrib-jshint'); + grunt.loadNpmTasks('grunt-lint-inline'); + + grunt.registerTask('default', + ['jshint:all', 'simplemocha:all']); + +}; diff --git a/test/utility/exif/exif_test_image.jpg b/test/utility/exif/exif_test_image.jpg new file mode 100644 index 00000000..4ce96b3c Binary files /dev/null and b/test/utility/exif/exif_test_image.jpg differ diff --git a/time/79-suncalc.html b/time/79-suncalc.html index 7e595f86..191057cc 100644 --- a/time/79-suncalc.html +++ b/time/79-suncalc.html @@ -1,5 +1,5 @@ + + + + + + diff --git a/utility/daemon/daemon.js b/utility/daemon/daemon.js new file mode 100644 index 00000000..704d7f5e --- /dev/null +++ b/utility/daemon/daemon.js @@ -0,0 +1,106 @@ +/** + * 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 spawn = require('child_process').spawn; + + function DaemonNode(n) { + RED.nodes.createNode(this,n); + this.cmd = n.command; + this.args = n.args.split(" ") || []; + this.cr = n.cr; + this.op = n.op; + this.redo = n.redo; + this.running = false; + var node = this; + + function inputlistener(msg) { + if (msg != null) { + if (!Buffer.isBuffer(msg.payload)) { + if (typeof msg.payload === "object") { msg.payload = JSON.stringify(msg.payload); } + if (typeof msg.payload !== "string") { msg.payload = msg.payload.toString(); } + if (node.cr === true) { msg.payload += "\n"; } + } + if (RED.settings.verbose) { node.log("inp: "+msg.payload); } + if (node.child !== null) { node.child.stdin.write(msg.payload); } + else { node.warn("Command not running"); } + } + } + + function runit() { + node.child = spawn(node.cmd, node.args); + if (RED.settings.verbose) { node.log(node.cmd+" "+JSON.stringify(node.args)); } + node.status({fill:"green",shape:"dot",text:"running"}); + node.running = true; + + node.on("input", inputlistener); + + node.child.stdout.on('data', function (data) { + if (node.op == "string") { data = data.toString(); } + if (node.op == "number") { data = Number(data); } + if (RED.settings.verbose) { node.log("out: "+data); } + if (data && data.trim() !== "") { + var msg = {payload:data}; + node.send([msg,null,null]); + } + }); + + node.child.stderr.on('data', function (data) { + if (node.op == "string") { data = data.toString(); } + if (node.op == "number") { data = Number(data); } + if (RED.settings.verbose) { node.log("err: "+data); } + var msg = {payload:data}; + node.send([null,msg,null]); + }); + + node.child.on('close', function (code) { + if (RED.settings.verbose) { node.log("ret: "+code); } + var msg = {payload:code}; + node.send([null,null,msg]); + node.child = null; + node.running = false; + node.status({fill:"red",shape:"ring",text:"stopped"}); + }); + + node.child.on('error', function (err) { + if (err.errno === "ENOENT") { node.warn('Command not found'); } + else if (err.errno === "EACCES") { node.warn('Command not executable'); } + else { node.log('error: ' + err); } + node.status({fill:"grey",shape:"dot",text:"error"}); + }); + } + + if (node.redo === true) { + var loop = setInterval( function() { + if (!node.running) { + node.removeListener('input', inputlistener); + node.warn("Restarting : " + node.cmd); + runit(); + } + }, 10000); // Restart after 10 secs if required + } + + node.on("close", function() { + if (node.child != null) { node.child.kill('SIGKILL'); } + if (RED.settings.verbose) { node.log(node.cmd+" stopped"); } + clearInterval(loop); + }); + + runit(); + } + RED.nodes.registerType("daemon",DaemonNode); +} diff --git a/utility/daemon/package.json b/utility/daemon/package.json new file mode 100644 index 00000000..8c5dbc84 --- /dev/null +++ b/utility/daemon/package.json @@ -0,0 +1,23 @@ +{ + "name" : "node-red-node-daemon", + "version" : "0.0.1", + "description" : "A Node-RED node that runs and monitors a long running system command.", + "dependencies" : { + }, + "repository" : { + "type":"git", + "url":"https://github.com/node-red/node-red-nodes/tree/master/utility/daemon" + }, + "license": "Apache-v2.0", + "keywords": [ "node-red", "daemon", "shell", "exec" ], + "node-red" : { + "nodes" : { + "daemon": "daemon.js" + } + }, + "author": { + "name": "Dave Conway-Jones", + "email": "ceejay@vnet.ibm.com", + "url": "http://nodered.org" + } +} diff --git a/utility/exif/94-exif.html b/utility/exif/94-exif.html new file mode 100644 index 00000000..689c290c --- /dev/null +++ b/utility/exif/94-exif.html @@ -0,0 +1,49 @@ + + + + + + + diff --git a/utility/exif/94-exif.js b/utility/exif/94-exif.js new file mode 100644 index 00000000..eb7140c7 --- /dev/null +++ b/utility/exif/94-exif.js @@ -0,0 +1,124 @@ +/** + * 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 ExifImage = require('exif').ExifImage; + + function convertDegreesMinutesSecondsToDecimals(degrees, minutes, seconds) { + var result; + result = degrees + (minutes / 60) + (seconds / 3600); + return result; + } + + /*** + * Extracts GPS location information from Exif data. If enough information is + * provided, convert the Exif data into a pair of single floating point number + * latitude/longitude data pairs. Populates msg.location with these. + * Assumes that the msg object will always have exifData available as msg.exif. + * Assume that the GPS data saved into Exif provides a valid value + */ + function addMsgLocationDataFromExifGPSData(msg) { + if(msg.exif.gps) { + var gpsData = msg.exif.gps; // declaring variable purely to make checks more readable + if(gpsData.GPSAltitude) { + if(!msg.location) { + msg.location = {}; + } + msg.location.alt = gpsData.GPSAltitude; + } + if(gpsData.GPSLatitudeRef && gpsData.GPSLatitude && gpsData.GPSLongitudeRef && gpsData.GPSLongitude) { // location can be determined, OK + // The data provided in Exif is in degrees, minutes, seconds, this is to be converted into a single floating point degree + if(gpsData.GPSLatitude.length === 3) { // OK to convert latitude + if(gpsData.GPSLongitude.length === 3) { // OK to convert longitude + var latitude = convertDegreesMinutesSecondsToDecimals(gpsData.GPSLatitude[0], gpsData.GPSLatitude[1], gpsData.GPSLatitude[2]); + latitude = Math.round(latitude * 100000)/100000; + + // (N)orth means positive latitude + // (S)outh means negative latitude + // (E)ast means positive longitude + // (W)est means negative longitude + if(gpsData.GPSLatitudeRef.toString() === 'S' || gpsData.GPSLatitudeRef.toString() === 's') { + latitude = latitude * -1; + } + + var longitude = convertDegreesMinutesSecondsToDecimals(gpsData.GPSLongitude[0], gpsData.GPSLongitude[1], gpsData.GPSLongitude[2]); + longitude = Math.round(longitude * 100000)/100000; + + if(gpsData.GPSLongitudeRef.toString() === 'W' || gpsData.GPSLongitudeRef.toString() === 'w') { + longitude = longitude * -1; + } + if(!msg.location) { + msg.location = {}; + } + msg.location.lat = latitude; + msg.location.lon = longitude; + return; + } else { + node.log("Invalid longitude data, no location information has been added to the message."); + } + } else { + node.log("Invalid latitude data, no location information has been added to the message."); + } + } else { + node.log("The location of this image cannot be determined safely so no location information has been added to the message."); + } + } else { + node.log("No location info found in this image."); + } + } + + function ExifNode(n) { + RED.nodes.createNode(this,n); + var node = this; + this.on("input", function(msg) { + try { + + if(msg.payload) { + var isBuffer = Buffer.isBuffer(msg.payload); + if(isBuffer === true) { + new ExifImage({ image : msg.payload }, function (error, exifData) { + if (error) { + node.error('Failed to extract Exif data from image.'); + node.log('Failed to extract Exif data from image. '+ error); + } else { + //msg.payload remains the same buffer + if(exifData) { + msg.exif = exifData; + addMsgLocationDataFromExifGPSData(msg); + } else { + node.warn("The incoming buffer did not contain Exif data, nothing to do. "); + } + } + node.send(msg); + }); + } else { + node.error("Invalid payload received, the Exif node cannot proceed, no messages sent."); + return; + } + } else { + node.error("No payload received, the Exif node cannot proceed, no messages sent."); + return; + } + } catch (error) { + node.error("An error occurred while extracting Exif information. Please check the log for details."); + node.log('Error: '+error.message); + return; + } + }); + } + RED.nodes.registerType("exif",ExifNode); +} diff --git a/utility/exif/LICENSE b/utility/exif/LICENSE new file mode 100644 index 00000000..f433b1a5 --- /dev/null +++ b/utility/exif/LICENSE @@ -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 diff --git a/utility/exif/README.md b/utility/exif/README.md new file mode 100644 index 00000000..47d14f7a --- /dev/null +++ b/utility/exif/README.md @@ -0,0 +1,23 @@ +node-red-node-exif +================== + +A Node-RED node to extract Exif information from JPEG images. + +Install +------- + +Run the following command in the root directory of your Node-RED install + + npm install node-red-node-exif + + +Usage +----- + +Extracts Exif information from JPEG images. + +This node expects an incoming JPEG image as a buffer. If Exif data is present, it extracts the data into a **msg.exif** object. + +If the Exif data also contains location information this is extracted as **msg.location**. + +**msg.payload** retains the original, unmodified image buffer. diff --git a/utility/exif/package.json b/utility/exif/package.json new file mode 100644 index 00000000..ba12c7d0 --- /dev/null +++ b/utility/exif/package.json @@ -0,0 +1,23 @@ +{ + "name" : "node-red-node-exif", + "version" : "0.0.1", + "description" : "A Node-RED node that extracts Exif information from JPEG image buffers.", + "dependencies" : { + "exif": "0.4.0" + }, + "repository" : { + "type":"git", + "url":"https://github.com/node-red/node-red-nodes/tree/master/utility/exif" + }, + "license": "Apache-v2.0", + "keywords": [ "node-red", "exif"], + "node-red" : { + "nodes" : { + "exif": "94-exif.js" + } + }, + "contributors": [ + {"name": "Dave Conway-Jones"}, + {"name": "Zoltan Balogh"} + ] +}