├── lib └── .gitignore ├── .nodemonignore ├── .gitignore ├── public ├── favicon.ico ├── icons │ ├── db.png │ ├── rpi.png │ ├── alert.png │ ├── debug.png │ ├── feed.png │ ├── file.png │ ├── hash.png │ ├── light.png │ ├── prowl.png │ ├── redis.png │ ├── watch.png │ ├── xmpp.png │ ├── arduino.png │ ├── arrow-in.png │ ├── bonjour.png │ ├── bridge.png │ ├── bullet.png │ ├── envelope.png │ ├── function.png │ ├── inject.png │ ├── leveldb.png │ ├── mongodb.png │ ├── serial.png │ ├── template.png │ ├── twitter.png │ ├── node-error.png │ ├── bridge-dash.png │ └── white-globe.png ├── node-red.png ├── pw_maze_white.png ├── bootstrap │ └── img │ │ ├── glyphicons-halflings.png │ │ └── glyphicons-halflings-white.png ├── jquery │ └── css │ │ └── smoothness │ │ └── images │ │ ├── animated-overlay.gif │ │ ├── ui-icons_222222_256x240.png │ │ ├── ui-icons_2e83ff_256x240.png │ │ ├── ui-icons_454545_256x240.png │ │ ├── ui-icons_888888_256x240.png │ │ ├── ui-icons_cd0a0a_256x240.png │ │ ├── ui-bg_flat_0_aaaaaa_40x100.png │ │ ├── ui-bg_flat_75_ffffff_40x100.png │ │ ├── ui-bg_glass_55_fbf9ee_1x400.png │ │ ├── ui-bg_glass_65_ffffff_1x400.png │ │ ├── ui-bg_glass_75_dadada_1x400.png │ │ ├── ui-bg_glass_75_e6e6e6_1x400.png │ │ ├── ui-bg_glass_95_fef1ec_1x400.png │ │ └── ui-bg_highlight-soft_75_cccccc_1x100.png └── red │ ├── validators.js │ ├── ui │ ├── state.js │ ├── keyboard.js │ ├── notifications.js │ ├── palette.js │ └── sidebar.js │ ├── history.js │ └── main.js ├── package.json ├── red ├── events.js ├── ui.js ├── red.js └── server.js ├── nodes ├── core │ ├── 90-comment.js │ ├── 80-template.js │ ├── 75-exec.js │ ├── 80-function.js │ ├── 75-exec.html │ ├── 20-inject.js │ ├── 90-comment.html │ ├── 58-debug.js │ ├── 80-template.html │ └── 80-function.html ├── analysis │ ├── 72-sentiment.js │ ├── 72-wordpos.js │ ├── 73-parsexml.js │ ├── 72-wordpos.html │ ├── 72-sentiment.html │ └── 73-parsexml.html ├── social │ ├── 57-notify.js │ ├── 61-email.js │ ├── 57-pushbullet.js │ ├── 57-prowl.js │ ├── 61-email.html │ ├── 32-feedparse.html │ ├── 57-notify.html │ ├── 61-imap.html │ ├── 57-pushbullet.html │ ├── 57-prowl.html │ ├── 91-irc.js │ ├── 32-feedparse.js │ ├── 61-imap.js │ ├── 92-xmpp.js │ └── 92-xmpp.html ├── io │ ├── 23-watch.js │ ├── 21-httpin.js │ ├── 90-httpget.js │ ├── 23-watch.html │ ├── 30-socketout.js │ ├── 90-httpget.html │ ├── 30-socketout.html │ ├── 10-mqtt.js │ ├── 30-socketin.html │ ├── 21-httpin.html │ ├── 31-tcpout.html │ ├── 32-multicast.js │ ├── 31-tcpout.js │ └── 30-socketin.js ├── storage │ ├── 28-tail.js │ ├── 50-file.js │ ├── 28-tail.html │ ├── 67-leveldb.js │ ├── 50-file.html │ ├── 65-redisout.js │ ├── 67-leveldb.html │ └── 66-mongodb.js ├── deprecated │ ├── 35-rpi-gpio-out.js │ ├── 35-rpi-gpio-out.html │ ├── 35-rpi-gpio-in.js │ └── 35-rpi-gpio-in.html ├── 99-sample.js.demo ├── hardware │ ├── 78-ledborg.js │ ├── 76-blinkstick.js │ ├── 77-blink1.html │ ├── 76-blinkstick.html │ ├── 78-ledborg.html │ ├── 77-blink1.js │ └── 36-rpi-gpio.js └── 99-sample.html.demo ├── INSTALL.md ├── red.js ├── settings.js └── README.md /lib/.gitignore: -------------------------------------------------------------------------------- 1 | * 2 | -------------------------------------------------------------------------------- /.nodemonignore: -------------------------------------------------------------------------------- 1 | .git/* 2 | *.json 3 | lib/* 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | credentials.json 3 | flows*.json 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/favicon.ico -------------------------------------------------------------------------------- /public/icons/db.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/db.png -------------------------------------------------------------------------------- /public/icons/rpi.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/rpi.png -------------------------------------------------------------------------------- /public/node-red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/node-red.png -------------------------------------------------------------------------------- /public/icons/alert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/alert.png -------------------------------------------------------------------------------- /public/icons/debug.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/debug.png -------------------------------------------------------------------------------- /public/icons/feed.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/feed.png -------------------------------------------------------------------------------- /public/icons/file.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/file.png -------------------------------------------------------------------------------- /public/icons/hash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/hash.png -------------------------------------------------------------------------------- /public/icons/light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/light.png -------------------------------------------------------------------------------- /public/icons/prowl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/prowl.png -------------------------------------------------------------------------------- /public/icons/redis.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/redis.png -------------------------------------------------------------------------------- /public/icons/watch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/watch.png -------------------------------------------------------------------------------- /public/icons/xmpp.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/xmpp.png -------------------------------------------------------------------------------- /public/icons/arduino.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/arduino.png -------------------------------------------------------------------------------- /public/icons/arrow-in.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/arrow-in.png -------------------------------------------------------------------------------- /public/icons/bonjour.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/bonjour.png -------------------------------------------------------------------------------- /public/icons/bridge.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/bridge.png -------------------------------------------------------------------------------- /public/icons/bullet.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/bullet.png -------------------------------------------------------------------------------- /public/icons/envelope.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/envelope.png -------------------------------------------------------------------------------- /public/icons/function.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/function.png -------------------------------------------------------------------------------- /public/icons/inject.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/inject.png -------------------------------------------------------------------------------- /public/icons/leveldb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/leveldb.png -------------------------------------------------------------------------------- /public/icons/mongodb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/mongodb.png -------------------------------------------------------------------------------- /public/icons/serial.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/serial.png -------------------------------------------------------------------------------- /public/icons/template.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/template.png -------------------------------------------------------------------------------- /public/icons/twitter.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/twitter.png -------------------------------------------------------------------------------- /public/pw_maze_white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/pw_maze_white.png -------------------------------------------------------------------------------- /public/icons/node-error.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/node-error.png -------------------------------------------------------------------------------- /public/icons/bridge-dash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/bridge-dash.png -------------------------------------------------------------------------------- /public/icons/white-globe.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/icons/white-globe.png -------------------------------------------------------------------------------- /public/bootstrap/img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/bootstrap/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /public/bootstrap/img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/bootstrap/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /public/jquery/css/smoothness/images/animated-overlay.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/jquery/css/smoothness/images/animated-overlay.gif -------------------------------------------------------------------------------- /public/jquery/css/smoothness/images/ui-icons_222222_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/jquery/css/smoothness/images/ui-icons_222222_256x240.png -------------------------------------------------------------------------------- /public/jquery/css/smoothness/images/ui-icons_2e83ff_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/jquery/css/smoothness/images/ui-icons_2e83ff_256x240.png -------------------------------------------------------------------------------- /public/jquery/css/smoothness/images/ui-icons_454545_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/jquery/css/smoothness/images/ui-icons_454545_256x240.png -------------------------------------------------------------------------------- /public/jquery/css/smoothness/images/ui-icons_888888_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/jquery/css/smoothness/images/ui-icons_888888_256x240.png -------------------------------------------------------------------------------- /public/jquery/css/smoothness/images/ui-icons_cd0a0a_256x240.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/jquery/css/smoothness/images/ui-icons_cd0a0a_256x240.png -------------------------------------------------------------------------------- /public/jquery/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/jquery/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png -------------------------------------------------------------------------------- /public/jquery/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/jquery/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png -------------------------------------------------------------------------------- /public/jquery/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/jquery/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png -------------------------------------------------------------------------------- /public/jquery/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/jquery/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png -------------------------------------------------------------------------------- /public/jquery/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/jquery/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png -------------------------------------------------------------------------------- /public/jquery/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/jquery/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png -------------------------------------------------------------------------------- /public/jquery/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/jquery/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png -------------------------------------------------------------------------------- /public/jquery/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Cougar/node-red/master/public/jquery/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-red", 3 | "version": "0.1.0", 4 | "description": "A visual tool for wiring the Internet of Things", 5 | "homepage": "http://nodered.org", 6 | "scripts": { 7 | "start": "node red.js" 8 | }, 9 | "main": "red/red.js", 10 | "author": "Nick O'Leary", 11 | "contributors": [ {"name": "Dave Conway-Jones"} ], 12 | "keywords": ["editor", "messaging", "iot", "m2m", "pi", "arduino", "beaglebone", "ibm"], 13 | "license": "Apache", 14 | "dependencies": { 15 | "express": "3.x", 16 | "mqtt": "*", 17 | "ws": "*", 18 | "mustache": "*", 19 | "cron":"*" 20 | }, 21 | "engines": { "node": ">=0.8" }, 22 | "repository": {"type":"git","url":"https://github.com/node-red/node-red.git"} 23 | } 24 | -------------------------------------------------------------------------------- /red/events.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var events = require("events"); 18 | 19 | module.exports = new events.EventEmitter(); 20 | -------------------------------------------------------------------------------- /nodes/core/90-comment.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | 19 | function CommentNode(n) { 20 | RED.nodes.createNode(this,n); 21 | } 22 | 23 | RED.nodes.registerType("comment",CommentNode); 24 | -------------------------------------------------------------------------------- /public/red/validators.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | RED.validators = { 17 | number: function(){return function(v) { return v!=='' && !isNaN(v);}}, 18 | regex: function(re){return function(v) { return re.test(v);}} 19 | }; 20 | -------------------------------------------------------------------------------- /public/red/ui/state.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | RED.state = { 17 | MOVING: 1, 18 | JOINING: 2, 19 | MOVING_ACTIVE: 3, 20 | ADDING: 4, 21 | EDITING: 5, 22 | EXPORT: 6, 23 | IMPORT: 7, 24 | IMPORT_DRAGGING: 8 25 | } 26 | -------------------------------------------------------------------------------- /nodes/analysis/72-sentiment.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var sentiment = require('sentiment'); 19 | 20 | function SentimentNode(n) { 21 | RED.nodes.createNode(this,n); 22 | 23 | this.on("input", function(msg) { 24 | var node = this; 25 | sentiment(msg.payload, function (err, result) { 26 | msg.sentiment = result; 27 | node.send(msg); 28 | }); 29 | }); 30 | } 31 | 32 | RED.nodes.registerType("sentiment",SentimentNode); 33 | -------------------------------------------------------------------------------- /nodes/analysis/72-wordpos.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var util = require("util"); 19 | var WordPos = require('wordpos'); 20 | 21 | var wordpos = new WordPos(); 22 | 23 | function WordPOSNode(n) { 24 | RED.nodes.createNode(this,n); 25 | this.on("input", function(msg) { 26 | var node = this; 27 | wordpos.getPOS(msg.payload, function (result) { 28 | msg.pos = result; 29 | node.send(msg); 30 | }); 31 | }); 32 | } 33 | 34 | RED.nodes.registerType("wordpos",WordPOSNode); 35 | -------------------------------------------------------------------------------- /red/ui.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | var express = require('express'); 17 | var util = require('util'); 18 | var crypto = require('crypto'); 19 | var fs = require("fs"); 20 | var app = express(); 21 | 22 | function setupUI(settings) { 23 | 24 | // Need to ensure the url ends with a '/' so the static serving works 25 | // with relative paths 26 | app.get("/",function(req,res) { 27 | if (req.originalUrl.slice(-1) != "/") { 28 | res.redirect(req.originalUrl+"/"); 29 | } else { 30 | req.next(); 31 | } 32 | }); 33 | 34 | app.use("/",express.static(__dirname + '/../public')); 35 | 36 | return app; 37 | } 38 | 39 | module.exports = setupUI; 40 | 41 | -------------------------------------------------------------------------------- /nodes/social/57-notify.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var growl = require('growl'); 19 | var imagefile = __dirname+"/../../public/mqtt-node-red.png"; 20 | 21 | function NotifyNode(n) { 22 | RED.nodes.createNode(this,n); 23 | this.title = n.title; 24 | var node = this; 25 | this.on("input",function(msg) { 26 | var titl = this.title||msg.topic; 27 | if (typeof(msg.payload) == 'object') { 28 | msg.payload = JSON.stringify(msg.payload); 29 | } 30 | if (typeof(titl) != 'undefined') { 31 | growl(msg.payload, { title: titl, image: imagefile }); 32 | } 33 | else { 34 | growl(msg.payload, { image: imagefile }); 35 | } 36 | }); 37 | } 38 | 39 | RED.nodes.registerType("notify",NotifyNode); 40 | -------------------------------------------------------------------------------- /nodes/core/80-template.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | 19 | var mustache = require("mustache"); 20 | var util = require("util"); 21 | var fs = require('fs'); 22 | 23 | function TemplateNode(n) { 24 | RED.nodes.createNode(this,n); 25 | this.name = n.name; 26 | this.template = n.template; 27 | this.on("input", function(msg) { 28 | if (msg != null) { 29 | try { 30 | msg.payload = mustache.render(this.template,msg) 31 | this.send(msg); 32 | } catch(err) { 33 | this.error(err.message); 34 | } 35 | } 36 | }); 37 | } 38 | 39 | RED.nodes.registerType("template",TemplateNode); 40 | 41 | RED.library.register("templates"); 42 | -------------------------------------------------------------------------------- /nodes/io/23-watch.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var notify = require("fs.notify"); 19 | 20 | function WatchNode(n) { 21 | RED.nodes.createNode(this,n); 22 | 23 | this.files = n.files.split(","); 24 | for (var f in this.files) { 25 | this.files[f] = this.files[f].trim(); 26 | } 27 | var node = this; 28 | var notifications = new notify(this.files); 29 | notifications.on('change', function (file) { 30 | node.log('file changed '+file); 31 | var msg = { payload: file, topic: JSON.stringify(node.files) }; 32 | node.send(msg); 33 | }); 34 | 35 | this._close = function() { 36 | notifications.close(); 37 | } 38 | } 39 | 40 | RED.nodes.registerType("watch",WatchNode); 41 | 42 | WatchNode.prototype.close = function() { 43 | this._close(); 44 | } 45 | 46 | -------------------------------------------------------------------------------- /nodes/storage/28-tail.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var fs = require("fs"); 19 | var spawn = require('child_process').spawn; 20 | 21 | function TailNode(n) { 22 | RED.nodes.createNode(this,n); 23 | 24 | this.filename = n.filename; 25 | this.split = n.split; 26 | var node = this; 27 | 28 | var tail = spawn("tail", ["-f", this.filename]); 29 | tail.stdout.on("data", function (data) { 30 | var msg = {topic:node.filename}; 31 | if (node.split) { 32 | var strings = data.toString().split("\n"); 33 | for (s in strings) { 34 | if (strings[s] != "") { 35 | msg.payload = strings[s]; 36 | node.send(msg); 37 | } 38 | } 39 | } 40 | else { 41 | msg.payload = data.toString(); 42 | node.send(msg); 43 | } 44 | }); 45 | } 46 | 47 | RED.nodes.registerType("tail",TailNode); 48 | -------------------------------------------------------------------------------- /nodes/analysis/73-parsexml.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var util = require("util"); 19 | var parseString = require('xml2js').parseString; 20 | var gotEyes = false; 21 | try { 22 | var eyes = require("eyes"); 23 | gotEyes = true; 24 | } catch(e) { 25 | util.log("[73-parsexml.js] Warning: Module 'eyes' not installed"); 26 | } 27 | 28 | function Xml2jsNode(n) { 29 | RED.nodes.createNode(this,n); 30 | this.useEyes = n.useEyes; 31 | var node = this; 32 | 33 | this.on("input", function(msg) { 34 | parseString(msg.payload, function (err, result) { 35 | msg.payload = result; 36 | node.send(msg); 37 | if (node.useEyes == true) { 38 | if (gotEyes == true) { eyes.inspect(msg); } 39 | else { node.log(JSON.stringify(msg)); } 40 | } 41 | }); 42 | }); 43 | } 44 | 45 | RED.nodes.registerType("xml2js",Xml2jsNode); 46 | -------------------------------------------------------------------------------- /red/red.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var events = require("./events"); 18 | var server = require("./server"); 19 | var nodes = require("./nodes"); 20 | var library = require("./library"); 21 | var settings = null; 22 | 23 | 24 | var events = require("events"); 25 | 26 | var RED = { 27 | 28 | init: function(httpServer,userSettings) { 29 | settings = userSettings; 30 | server.init(httpServer,settings); 31 | library.init(); 32 | return server.app; 33 | }, 34 | 35 | start: server.start, 36 | 37 | nodes: nodes, 38 | library: library, 39 | events: events 40 | }; 41 | 42 | RED.__defineGetter__("app", function() { return server.app }); 43 | RED.__defineGetter__("server", function() { return server.server }); 44 | RED.__defineGetter__("settings", function() { return settings }); 45 | 46 | module.exports = RED; 47 | -------------------------------------------------------------------------------- /nodes/deprecated/35-rpi-gpio-out.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var gpio = require("pi-gpio"); 19 | 20 | function GPIOOutNode(n) { 21 | RED.nodes.createNode(this,n); 22 | 23 | this.pin = n.pin; 24 | 25 | var node = this; 26 | 27 | if (this.pin) { 28 | gpio.open(this.pin,"output",function(err) { 29 | if (err) { 30 | node.error(err); 31 | } else { 32 | node.on("input",function(msg) { 33 | gpio.write(node.pin,msg.payload,function(err) { 34 | if (err) node.error(err); 35 | }); 36 | }); 37 | } 38 | }); 39 | } else { 40 | this.error("Invalid GPIO pin: "+this.pin); 41 | } 42 | } 43 | 44 | RED.nodes.registerType("rpi-gpio out",GPIOOutNode); 45 | 46 | GPIOOutNode.prototype.close = function() { 47 | gpio.close(this.pin); 48 | } 49 | 50 | 51 | 52 | -------------------------------------------------------------------------------- /nodes/io/21-httpin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var util = require("util"); 19 | 20 | function HTTPIn(n) { 21 | RED.nodes.createNode(this,n); 22 | this.url = n.url; 23 | this.method = n.method; 24 | 25 | var node = this; 26 | this.callback = function(req,res) { 27 | node.send({req:req,res:res}); 28 | } 29 | if (this.method == "get") { 30 | RED.app.get(this.url,this.callback); 31 | } else if (this.method == "post") { 32 | RED.app.post(this.url,this.callback); 33 | } else if (this.method == "put") { 34 | RED.app.put(this.url,this.callback); 35 | } else if (this.method == "delete") { 36 | RED.app.delete(this.url,this.callback); 37 | } 38 | } 39 | 40 | RED.nodes.registerType("http in",HTTPIn); 41 | 42 | HTTPIn.prototype.close = function() { 43 | var routes = RED.app.routes[this.method]; 44 | for (var i in routes) { 45 | if (routes[i].path == this.url) { 46 | routes.splice(i,1); 47 | break; 48 | } 49 | } 50 | } 51 | 52 | -------------------------------------------------------------------------------- /nodes/storage/50-file.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var fs = require("fs"); 19 | 20 | function FileNode(n) { 21 | RED.nodes.createNode(this,n); 22 | 23 | this.filename = n.filename; 24 | this.appendNewline = n.appendNewline; 25 | this.overwriteFile = n.overwriteFile; 26 | var node = this; 27 | this.on("input",function(msg) { 28 | var data = msg.payload; 29 | if (this.appendNewline) { 30 | data += "\n"; 31 | } 32 | if (this.overwriteFile) { 33 | fs.writeFile(this.filename, data, function (err) { 34 | if (err) node.warn('Failed to write to file : '+err); 35 | //console.log('Message written to file',this.filename); 36 | }); 37 | } 38 | else { 39 | fs.appendFile(this.filename, data, function (err) { 40 | if (err) node.warn('Failed to append to file : '+err); 41 | //console.log('Message appended to file',this.filename); 42 | }); 43 | } 44 | }); 45 | } 46 | 47 | RED.nodes.registerType("file",FileNode); 48 | -------------------------------------------------------------------------------- /nodes/social/61-email.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var nodemailer = require("nodemailer"); 19 | var emailkey = require("../../../emailkeys.js"); 20 | 21 | var smtpTransport = nodemailer.createTransport("SMTP",{ 22 | service: emailkey.service, 23 | auth: { 24 | user: emailkey.user, 25 | pass: emailkey.pass 26 | } 27 | }); 28 | 29 | function EmailNode(n) { 30 | RED.nodes.createNode(this,n); 31 | this.topic = n.topic; 32 | this.name = n.name; 33 | var node = this; 34 | this.on("input", function(msg) { 35 | //node.log("email :",this.id,this.topic," received",msg.payload); 36 | if (msg != null) { 37 | 38 | smtpTransport.sendMail({ 39 | from: emailkey.user, // sender address 40 | to: node.name, // comma separated list of receivers 41 | subject: msg.topic, // Subject line 42 | text: msg.payload // plaintext body 43 | }, function(error, response) { 44 | if (error) { 45 | node.error(error); 46 | } else { 47 | node.log("Message sent: " + response.message); 48 | } 49 | }); 50 | 51 | } 52 | }); 53 | } 54 | 55 | RED.nodes.registerType("email",EmailNode); 56 | -------------------------------------------------------------------------------- /nodes/io/90-httpget.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | 19 | function HttpGet(n) { 20 | RED.nodes.createNode(this,n); 21 | this.baseurl = n.baseurl || ""; 22 | this.append = n.append || ""; 23 | var node = this; 24 | if (this.baseurl.substring(0,5) === "https") { var http = require("https"); } 25 | else { var http = require("http"); } 26 | this.on("input", function(msg) { 27 | msg._payload = msg.payload; 28 | //util.log("[httpget] "+this.baseurl+msg.payload+this.append); 29 | http.get(this.baseurl+msg.payload+this.append, function(res) { 30 | node.log("Http response: " + res.statusCode); 31 | msg.rc = res.statusCode; 32 | msg.payload = ""; 33 | if ((msg.rc != 200) && (msg.rc != 404)) { 34 | node.send(msg); 35 | } 36 | res.setEncoding('utf8'); 37 | res.on('data', function(chunk) { 38 | msg.payload += chunk; 39 | }); 40 | res.on('end', function() { 41 | node.send(msg); 42 | }); 43 | }).on('error', function(e) { 44 | //node.error(e); 45 | msg.rc = 503; 46 | msg.payload = e; 47 | node.send(msg); 48 | }); 49 | }); 50 | } 51 | 52 | RED.nodes.registerType("httpget",HttpGet); 53 | -------------------------------------------------------------------------------- /public/red/ui/keyboard.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | RED.keyboard = function() { 17 | 18 | var active = true; 19 | var handlers = {}; 20 | 21 | d3.select(window).on("keydown",function() { 22 | if (!active) { return; } 23 | var handler = handlers[d3.event.keyCode]; 24 | if (handler) { 25 | if (!handler.modifiers || 26 | ((!handler.modifiers.shift || d3.event.shiftKey)&& 27 | (!handler.modifiers.ctrl || d3.event.ctrlKey))) { 28 | handler.callback(); 29 | } 30 | } 31 | }); 32 | 33 | function addHandler(key,modifiers,callback) { 34 | var mod = modifiers; 35 | var cb = callback; 36 | if (typeof modifiers == "function") { 37 | mod = {}; 38 | cb = modifiers; 39 | } 40 | handlers[key] = {modifiers:mod, callback:cb}; 41 | } 42 | function removeHandler(key) { 43 | delete handlers[key]; 44 | } 45 | 46 | return { 47 | add: addHandler, 48 | remove: removeHandler, 49 | disable: function(){ active = false;}, 50 | enable: function(){ active = true; } 51 | } 52 | 53 | }(); 54 | -------------------------------------------------------------------------------- /nodes/social/57-pushbullet.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var PushBullet = require('pushbullet'); 19 | 20 | // pushkey.js just needs to be like (with the quotes) 21 | // module.exports = {pushbullet:'My-API-KEY', deviceid:'12345'} 22 | 23 | try { 24 | var pushkey = require("../../settings").pushbullet || require("../../../pushkey.js"); 25 | } catch(err) { 26 | throw new Error("Failed to load PushBullet credentials"); 27 | } 28 | 29 | var pusher = new PushBullet(pushkey.pushbullet); 30 | var deviceId = pushkey.deviceid; 31 | 32 | function PushbulletNode(n) { 33 | RED.nodes.createNode(this,n); 34 | this.title = n.title; 35 | this.device 36 | var node = this; 37 | this.on("input",function(msg) { 38 | var titl = this.title||msg.topic||"Node-RED"; 39 | if (typeof(msg.payload) == 'object') { 40 | msg.payload = JSON.stringify(msg.payload); 41 | } 42 | try { 43 | pusher.note(deviceId, titl, msg.payload, function(err, response) { 44 | if ( err ) node.error(err); 45 | node.log( JSON.stringify(response) ); 46 | }); 47 | } 48 | catch (err) { 49 | node.error(err); 50 | } 51 | }); 52 | } 53 | 54 | RED.nodes.registerType("pushbullet",PushbulletNode); 55 | -------------------------------------------------------------------------------- /INSTALL.md: -------------------------------------------------------------------------------- 1 | Node-RED Install 2 | ================ 3 | 4 | ## Install node.js 5 | 6 | You can get the latest version from . 7 | 8 | Or, you may want to use a version from your operating system's package manager: 9 | 10 | 11 | ## Get Node-RED 12 | 13 | Clone the repository from GitHub: 14 | 15 | $ git clone git@github.com:node-red/node-red.git 16 | 17 | ## Install the pre-requisite modules 18 | 19 | From the top-level directory of Node-RED, run: 20 | 21 | $ npm install 22 | 23 | This will install the core pre-requisite modules. 24 | 25 | ## Run Node-RED 26 | 27 | From the top-level directory, run: 28 | 29 | $ node red.js 30 | 31 | You can then access Node-RED at . 32 | 33 | Online documentation is available at . 34 | 35 | ## Installing individual node dependencies 36 | 37 | When Node-RED starts, it attempts to load the nodes from the `nodes/` directory. 38 | Each will have its own set of dependencies that will need to be installed before 39 | the node is available in the palette. 40 | 41 | To help identify the dependencies, Node-RED logs any modules it fails to find 42 | for a particular node. You don't have to install these unless you want or need 43 | that node to appear. 44 | 45 | Alternatively, a node's `.js` file can be examined to identify the modules it 46 | explicitly requires. For example, the Twitter node is defined in 47 | `nodes/social/27-twitter.js` and contains: 48 | 49 | var RED = require("../../red/red"); 50 | var ntwitter = require('ntwitter'); 51 | var OAuth= require('oauth').OAuth; 52 | 53 | Of these, `ntwitter` and `oauth` are neither built-in modules nor ones provided 54 | by Node-RED itself. They can subsequently be installed by running: 55 | 56 | $ npm install ntwitter oauth 57 | 58 | -------------------------------------------------------------------------------- /nodes/99-sample.js.demo: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | // Sample Node-RED node file 18 | 19 | // Require main module 20 | var RED = require("../../red/red"); 21 | 22 | // The main node definition - most things happen in here 23 | function SampleNode(n) { 24 | // Create a RED node 25 | RED.nodes.createNode(this,n); 26 | 27 | // Store local copies of the node configuration (as defined in the .html) 28 | this.topic = n.topic; 29 | 30 | // Do whatever you need to do in here - declare callbacks etc 31 | // Note: this sample doesn't do anything much - it will only send 32 | // this message once at startup... 33 | // Look at other real nodes for some better ideas of what to do.... 34 | var msg = {}; 35 | msg.topic = node.topic; 36 | msg.payload = "Hello world !" 37 | 38 | // send out the message to the rest of the workspace. 39 | this.send(msg); 40 | } 41 | 42 | // Register the node by name. This must be called before overriding any of the 43 | // Node functions. 44 | RED.nodes.registerType("sample",SampleNode); 45 | 46 | 47 | SampleNode.prototype.close = function() { 48 | // Called when the node is shutdown - eg on redeploy. 49 | // Allows ports to be closed, connections dropped etc. 50 | // eg: this.client.disconnect(); 51 | } 52 | -------------------------------------------------------------------------------- /nodes/hardware/78-ledborg.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var util = require('util'); 19 | var fs = require('fs'); 20 | 21 | // check if /dev/ledborg exists - if not then don't even show the node. 22 | if (!fs.existsSync("/dev/ledborg")) { 23 | util.log("[78-ledborg.js] Error: PiBorg hardware : LedBorg not found"); 24 | return; 25 | } 26 | 27 | function LedBorgNode(n) { 28 | RED.nodes.createNode(this,n); 29 | var p1 = /[0-2][0-2][0-2]/ 30 | var p2 = /^\#[A-Fa-f0-9]{6}$/ 31 | var node = this; 32 | 33 | this.on("input", function(msg) { 34 | if (p1.test(msg.payload)) { 35 | fs.writeFile('/dev/ledborg', msg.payload, function (err) { 36 | if (err) node.warn(msg.payload+" : No LedBorg found"); 37 | }); 38 | } 39 | if (p2.test(msg.payload)) { 40 | var r = Math.floor(parseInt(msg.payload.slice(1,3),16)/88).toString(); 41 | var g = Math.floor(parseInt(msg.payload.slice(3,5),16)/88).toString(); 42 | var b = Math.floor(parseInt(msg.payload.slice(5),16)/88).toString(); 43 | fs.writeFile('/dev/ledborg', r+g+b, function (err) { 44 | if (err) node.warn(r+g+b+" : No LedBorg found"); 45 | }); 46 | } 47 | else { 48 | node.warn("Invalid LedBorg colour code"); 49 | } 50 | }); 51 | } 52 | 53 | RED.nodes.registerType("ledborg",LedBorgNode); 54 | -------------------------------------------------------------------------------- /nodes/social/57-prowl.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var Prowl = require('node-prowl'); 19 | 20 | // pushkey.js just needs to be like (with the quotes) 21 | // module.exports = {prowl:'My-API-KEY'} 22 | 23 | try { 24 | var pushkey = require("../../settings").prowl || require("../../../pushkey.js"); 25 | } catch(err) { 26 | throw new Error("Failed to load Prowl credentials"); 27 | } 28 | 29 | var prowl = new Prowl(pushkey.prowl); 30 | 31 | function ProwlNode(n) { 32 | RED.nodes.createNode(this,n); 33 | this.title = n.title; 34 | this.priority = n.priority * 1; 35 | if (this.priority > 2) this.priority = 2; 36 | if (this.priority < -2) this.priority = -2; 37 | var node = this; 38 | this.on("input",function(msg) { 39 | var titl = this.title||msg.topic||"Node-RED"; 40 | var pri = msg.priority||this.priority; 41 | if (typeof(msg.payload) == 'object') { 42 | msg.payload = JSON.stringify(msg.payload); 43 | } 44 | try { 45 | prowl.push(msg.payload, titl, { priority: pri }, function( err, remaining ){ 46 | if ( err ) node.error(err); 47 | node.log( remaining + ' calls to Prowl api during current hour.' ); 48 | }); 49 | } 50 | catch (err) { 51 | node.error(err); 52 | } 53 | }); 54 | } 55 | 56 | RED.nodes.registerType("prowl",ProwlNode); 57 | -------------------------------------------------------------------------------- /nodes/hardware/76-blinkstick.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var blinkstick = require("blinkstick"); 19 | 20 | Object.size = function(obj) { 21 | var size = 0, key; 22 | for (key in obj) { if (obj.hasOwnProperty(key)) size++; } 23 | return size; 24 | }; 25 | 26 | function BlinkStick(n) { 27 | RED.nodes.createNode(this,n); 28 | var p1 = /^\#[A-Fa-f0-9]{6}$/ 29 | var p2 = /[0-9]+,[0-9]+,[0-9]+/ 30 | this.led = blinkstick.findFirst(); // maybe try findAll() (one day) 31 | var node = this; 32 | 33 | this.on("input", function(msg) { 34 | if (msg != null) { 35 | if (Object.size(node.led) !== 0) { 36 | try { 37 | if (p2.test(msg.payload)) { 38 | var rgb = msg.payload.split(","); 39 | node.led.setColor(parseInt(rgb[0])&255, parseInt(rgb[1])&255, parseInt(rgb[2])&255); 40 | } 41 | else { 42 | node.led.setColor(msg.payload); 43 | } 44 | } 45 | catch (err) { 46 | node.warn("BlinkStick missing ?"); 47 | node.led = blinkstick.findFirst(); 48 | } 49 | } 50 | else { 51 | //node.warn("No BlinkStick found"); 52 | node.led = blinkstick.findFirst(); 53 | } 54 | } 55 | }); 56 | if (Object.size(node.led) === 0) { 57 | node.error("No BlinkStick found"); 58 | } 59 | 60 | } 61 | 62 | RED.nodes.registerType("blinkstick",BlinkStick); 63 | -------------------------------------------------------------------------------- /nodes/analysis/72-wordpos.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 25 | 26 | 38 | 39 | 58 | -------------------------------------------------------------------------------- /nodes/hardware/77-blink1.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 28 | 29 | 32 | 33 | 53 | -------------------------------------------------------------------------------- /red.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | var http = require('http'); 17 | var https = require('https'); 18 | var util = require("util"); 19 | var express = require("express"); 20 | var crypto = require("crypto"); 21 | var settings = require("./settings"); 22 | var RED = require("./red/red.js"); 23 | 24 | 25 | var server; 26 | var app = express(); 27 | 28 | if (settings.https) { 29 | server = https.createServer(settings.https,function(req,res){app(req,res);}); 30 | } else { 31 | server = http.createServer(function(req,res){app(req,res);}); 32 | } 33 | 34 | settings.httpRoot = settings.httpRoot||"/"; 35 | 36 | if (settings.httpRoot[0] != "/") { 37 | settings.httpRoot = "/"+settings.httpRoot; 38 | } 39 | if (settings.httpRoot.slice(-1) != "/") { 40 | settings.httpRoot = settings.httpRoot + "/"; 41 | } 42 | settings.uiPort = settings.uiPort||1880; 43 | 44 | if (settings.httpAuth) { 45 | app.use(settings.httpRoot, 46 | express.basicAuth(function(user, pass) { 47 | return user === settings.httpAuth.user && crypto.createHash('md5').update(pass,'utf8').digest('hex') === settings.httpAuth.pass; 48 | }) 49 | ); 50 | } 51 | 52 | var red = RED.init(server,settings); 53 | app.use(settings.httpRoot,red); 54 | 55 | 56 | server.listen(settings.uiPort); 57 | RED.start(); 58 | util.log('[red] Server now running at http'+(settings.https?'s':'')+'://127.0.0.1:'+settings.uiPort+settings.httpRoot); 59 | 60 | -------------------------------------------------------------------------------- /nodes/hardware/76-blinkstick.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 24 | 25 | 30 | 31 | 50 | -------------------------------------------------------------------------------- /settings.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | module.exports = { 17 | uiPort: 1880, 18 | mqttReconnectTime: 15000, 19 | serialReconnectTime: 15000, 20 | debugMaxLength: 1000, 21 | 22 | // You can protect the user interface with a userid and password by using the following property 23 | // the password must be an md5 hash eg.. 5f4dcc3b5aa765d61d8327deb882cf99 ('password') 24 | //httpAuth: {user:"user",pass:"5f4dcc3b5aa765d61d8327deb882cf99"}, 25 | 26 | // By default, the Node-RED UI is available at http://localhost:1880/ 27 | // The following property can be used to specifiy a different root path. 28 | //httpRoot: '/admin', 29 | 30 | // The following property can be used to enable HTTPS 31 | // See http://nodejs.org/api/https.html#https_https_createserver_options_requestlistener 32 | // for details on its contents. 33 | //https: { 34 | // key: fs.readFileSync('privatekey.pem'), 35 | // cert: fs.readFileSync('certificate.pem') 36 | //}, 37 | 38 | // Anything in this hash is globally available to all functions. 39 | // It is accessed as context.global. 40 | // eg: 41 | // functionGlobalContext: { os:require('os') } 42 | // can be accessed in a function block as: 43 | // context.global.os 44 | 45 | functionGlobalContext: { } 46 | //functionGlobalContext: { bonescript:require('bonescript') } 47 | //functionGlobalContext: { arduino:require('duino') } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /nodes/analysis/72-sentiment.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 25 | 26 | 32 | 33 | 52 | -------------------------------------------------------------------------------- /nodes/analysis/73-parsexml.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 29 | 30 | 34 | 35 | 54 | -------------------------------------------------------------------------------- /nodes/hardware/78-ledborg.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 24 | 25 | 31 | 32 | 51 | -------------------------------------------------------------------------------- /nodes/hardware/77-blink1.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var Blink1 = require("node-blink1"); 19 | 20 | function Blink1Node(n) { 21 | RED.nodes.createNode(this,n); 22 | this.fade = n.fade||0; 23 | var node = this; 24 | 25 | try { 26 | var p1 = /^\#[A-Fa-f0-9]{6}$/ 27 | var p2 = /[0-9]+,[0-9]+,[0-9]+/ 28 | this.on("input", function(msg) { 29 | if (blink1) { 30 | if (p1.test(msg.payload)) { 31 | // if it is a hex colour string 32 | var r = parseInt(msg.payload.slice(1,3),16); 33 | var g = parseInt(msg.payload.slice(3,5),16); 34 | var b = parseInt(msg.payload.slice(5),16); 35 | if (node.fade == 0) { blink1.setRGB( r, g, b ); } 36 | else { blink1.fadeToRGB(node.fade, r, g, b ); } 37 | } 38 | else if (p2.test(msg.payload)) { 39 | // if it is a r,g,b triple 40 | var rgb = msg.payload.split(','); 41 | if (node.fade == 0) { blink1.setRGB(parseInt(rgb[0])&255, parseInt(rgb[1])&255, parseInt(rgb[2])&255); } 42 | else { blink1.fadeToRGB(node.fade, parseInt(rgb[0])&255, parseInt(rgb[1])&255, parseInt(rgb[2])&255); } 43 | } 44 | else { 45 | // you can do fancy colours by name here if you want... 46 | node.warn("Blink1 : invalid msg : "+msg.payload); 47 | } 48 | } 49 | else { 50 | node.warn("No Blink1 found"); 51 | } 52 | }); 53 | var blink1 = new Blink1.Blink1(); 54 | } 55 | catch(e) { 56 | node.error("No Blink1 found"); 57 | } 58 | } 59 | 60 | RED.nodes.registerType("blink1",Blink1Node); 61 | -------------------------------------------------------------------------------- /nodes/social/61-email.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 23 | 24 | 31 | 32 | 51 | -------------------------------------------------------------------------------- /public/red/ui/notifications.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | RED.notify = function() { 17 | var currentNotifications = []; 18 | var c = 0; 19 | return function(msg,type,fixed) { 20 | if (currentNotifications.length > 4) { 21 | var ll = currentNotifications.length; 22 | for (var i = 0;ll > 4 && i 16 | 17 | 32 | 33 | 36 | 37 | 58 | -------------------------------------------------------------------------------- /nodes/io/23-watch.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 27 | 28 | 34 | 35 | 54 | -------------------------------------------------------------------------------- /nodes/io/30-socketout.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | 19 | function SocketOut(n) { 20 | RED.nodes.createNode(this,n); 21 | this.host = n.host; 22 | this.port = n.port * 1; 23 | this.name = n.name; 24 | this.trans = n.transport||n.trans||""; 25 | var node = this; 26 | this.on("input", function(msg) { 27 | if (msg != null) { 28 | if (this.trans == "http") { 29 | var http = require("http"); 30 | http.get(msg.payload, function(res) { 31 | node.log("http : response : " + res.statusCode); 32 | }).on('error', function(e) { 33 | node.error("http : error : " + e.message); 34 | }); 35 | } 36 | if (this.trans == "tcp") { 37 | var net = require('net'); 38 | var client = new net.Socket(); 39 | client.on('error', function (err) { 40 | node.error('tcp : '+err); 41 | }); 42 | client.connect(this.port, this.host, function() { 43 | try { client.end(msg.payload); } 44 | catch (e) { node.error(e); } 45 | }); 46 | } 47 | if (this.trans == "udp") { 48 | var dgram = require('dgram'); 49 | var sock = dgram.createSocket('udp4'); // only use ipv4 for now 50 | sock.bind(this.port); // have to bind before you can enable broadcast... 51 | sock.setBroadcast(true); // turn on broadcast 52 | var buf = new Buffer(msg.payload); 53 | sock.send(buf, 0, buf.length, this.port, this.host, function(err, bytes) { 54 | if (err) node.error("udp : "+err); 55 | //util.log('[socket out] udp :' +bytes); 56 | sock.close(); 57 | }); 58 | } 59 | } 60 | }); 61 | var node = this; 62 | } 63 | 64 | RED.nodes.registerType("socket out",SocketOut); 65 | -------------------------------------------------------------------------------- /nodes/deprecated/35-rpi-gpio-out.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 36 | 37 | 60 | -------------------------------------------------------------------------------- /nodes/social/57-notify.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 27 | 28 | 34 | 35 | 56 | -------------------------------------------------------------------------------- /nodes/social/61-imap.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 27 | 28 | 35 | 36 | 55 | -------------------------------------------------------------------------------- /nodes/storage/28-tail.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 33 | 34 | 38 | 39 | 59 | -------------------------------------------------------------------------------- /nodes/core/75-exec.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | 19 | var spawn = require('child_process').spawn; 20 | var exec = require('child_process').exec; 21 | 22 | function ExecNode(n) { 23 | RED.nodes.createNode(this,n); 24 | this.cmd = n.command; 25 | this.append = n.append || ""; 26 | this.useSpawn = n.useSpawn; 27 | 28 | var node = this; 29 | this.on("input", function(msg) { 30 | if (msg != null) { 31 | 32 | if (this.useSpawn == true) { 33 | // make the extra args into an array 34 | // then prepend with the msg.payload 35 | var arg = node.append.split(","); 36 | if (msg.payload != " ") { arg.unshift(msg.payload); } 37 | console.log(arg); 38 | var ex = spawn(node.cmd,arg); 39 | ex.stdout.on('data', function (data) { 40 | //console.log('[exec] stdout: ' + data); 41 | msg.payload = data; 42 | node.send([msg,null,null]); 43 | }); 44 | ex.stderr.on('data', function (data) { 45 | //console.log('[exec] stderr: ' + data); 46 | msg.payload = data; 47 | node.send([null,msg,null]); 48 | }); 49 | ex.on('close', function (code) { 50 | //console.log('[exec] result: ' + code); 51 | msg.payload = code; 52 | node.send([null,null,msg]); 53 | }); 54 | } 55 | 56 | else { 57 | var cl = node.cmd+" "+msg.payload+" "+node.append; 58 | node.log(cl); 59 | var child = exec(cl, function (error, stdout, stderr) { 60 | msg.payload = stdout; 61 | var msg2 = {payload:stderr}; 62 | //console.log('[exec] stdout: ' + stdout); 63 | //console.log('[exec] stderr: ' + stderr); 64 | if (error !== null) { 65 | var msg3 = {payload:error}; 66 | //console.log('[exec] error: ' + error); 67 | } 68 | node.send([msg,msg2,msg3]); 69 | }); 70 | } 71 | } 72 | 73 | }); 74 | } 75 | 76 | RED.nodes.registerType("exec",ExecNode); 77 | -------------------------------------------------------------------------------- /nodes/social/57-pushbullet.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 31 | 32 | 38 | 39 | 61 | -------------------------------------------------------------------------------- /nodes/deprecated/35-rpi-gpio-in.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var gpio = require("pi-gpio"); 19 | 20 | function GPIOInNode(n) { 21 | RED.nodes.createNode(this,n); 22 | 23 | this.buttonState = -1; 24 | this.pin = n.pin; 25 | this.resistor = n.resistor; 26 | 27 | var node = this; 28 | 29 | if (this.pin) { 30 | var setupPin = function(err) { 31 | if (err) { 32 | node.error(err); 33 | } else { 34 | node._interval = setInterval(function(){ 35 | gpio.read(node.pin, function(err, value) { 36 | if(err){ 37 | node.error(err); 38 | } else{ 39 | if(node.buttonState !== value){ 40 | var previousState = node.buttonState; 41 | node.buttonState = value; 42 | if (previousState !== -1) { 43 | var msg = {payload:node.buttonState}; 44 | node.send(msg); 45 | } 46 | } 47 | } 48 | }); 49 | }, 50); 50 | } 51 | }; 52 | if (this.resistor == "no") { 53 | gpio.open(this.pin,"input",setupPin()); 54 | } else { 55 | // Assume enabled externally via gpio-admin 56 | setupPin(); 57 | } 58 | } else { 59 | this.error("Invalid GPIO pin: "+this.pin); 60 | } 61 | } 62 | 63 | RED.nodes.registerType("rpi-gpio in",GPIOInNode); 64 | 65 | GPIOInNode.prototype.close = function() { 66 | clearInterval(this._interval); 67 | if (this.resistor == "no") { 68 | gpio.close(this.pin); 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /nodes/social/57-prowl.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 31 | 32 | 39 | 40 | 62 | -------------------------------------------------------------------------------- /nodes/social/91-irc.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var irc = require("irc"); 19 | 20 | // The Server Definition - this opens (and closes) the connection 21 | function IRCServerNode(n) { 22 | RED.nodes.createNode(this,n); 23 | this.server = n.server; 24 | this.channel = n.channel; 25 | this.nickname = n.nickname; 26 | this.ircclient = new irc.Client(this.server, this.nickname, { 27 | channels: [this.channel] 28 | }); 29 | this._close = function() { 30 | this.ircclient.disconnect(); 31 | } 32 | } 33 | 34 | RED.nodes.registerType("irc-server",IRCServerNode); 35 | 36 | IRCServerNode.prototype.close = function() { 37 | this._close(); 38 | } 39 | 40 | 41 | // The Input Node 42 | function IrcInNode(n) { 43 | RED.nodes.createNode(this,n); 44 | this.ircserver = n.ircserver; 45 | this.serverConfig = RED.nodes.getNode(this.ircserver); 46 | this.ircclient = this.serverConfig.ircclient; 47 | var node = this; 48 | 49 | 50 | this.ircclient.addListener('message', function (from, to, message) { 51 | console.log(from + ' => ' + to + ': ' + message); 52 | var msg = { "topic":from, "to":to, "payload":message }; 53 | node.send(msg); 54 | }); 55 | 56 | this.ircclient.addListener('error', function(message) { 57 | node.error(JSON.stringify(message)); 58 | }); 59 | 60 | } 61 | RED.nodes.registerType("irc in",IrcInNode); 62 | 63 | // The Output Node 64 | function IrcOutNode(n) { 65 | RED.nodes.createNode(this,n); 66 | this.sendAll = n.sendObject; 67 | this.ircserver = n.ircserver; 68 | this.serverConfig = RED.nodes.getNode(this.ircserver); 69 | this.ircclient = this.serverConfig.ircclient; 70 | this.channel = this.serverConfig.channel; 71 | var node = this; 72 | 73 | this.on("input", function(msg) { 74 | console.log(msg); 75 | if (node.sendAll) { 76 | node.ircclient.say(node.channel, JSON.stringify(msg)); 77 | } 78 | else { 79 | var to = msg.topic || node.channel; 80 | node.ircclient.say(to, msg.payload); 81 | } 82 | }); 83 | } 84 | RED.nodes.registerType("irc out",IrcOutNode); 85 | -------------------------------------------------------------------------------- /nodes/io/90-httpget.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 32 | 33 | 39 | 40 | 60 | -------------------------------------------------------------------------------- /public/red/history.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | RED.history = function() { 17 | var undo_history = []; 18 | 19 | return { 20 | //TODO: this function is a placeholder until there is a 'save' event that can be listened to 21 | markAllDirty: function() { 22 | for (var i in undo_history) { 23 | undo_history[i].dirty = true; 24 | } 25 | }, 26 | push: function(ev) { 27 | undo_history.push(ev); 28 | }, 29 | pop: function() { 30 | var ev = undo_history.pop(); 31 | if (ev) { 32 | if (ev.t == 'add') { 33 | for (var i in ev.nodes) { 34 | RED.nodes.remove(ev.nodes[i]); 35 | } 36 | for (var i in ev.links) { 37 | RED.nodes.removeLink(ev.links[i]); 38 | } 39 | } else if (ev.t == "delete") { 40 | for (var i in ev.nodes) { 41 | RED.nodes.add(ev.nodes[i]); 42 | } 43 | for (var i in ev.links) { 44 | RED.nodes.addLink(ev.links[i]); 45 | } 46 | } else if (ev.t == "move") { 47 | for (var i in ev.nodes) { 48 | var n = ev.nodes[i]; 49 | n.n.x = n.ox; 50 | n.n.y = n.oy; 51 | n.n.dirty = true; 52 | } 53 | } else if (ev.t == "edit") { 54 | for (var i in ev.changes) { 55 | ev.node[i] = ev.changes[i]; 56 | } 57 | RED.editor.updateNodeProperties(ev.node); 58 | for (var i in ev.links) { 59 | RED.nodes.addLink(ev.links[i]); 60 | } 61 | RED.editor.validateNode(ev.node); 62 | ev.node.dirty = true; 63 | } 64 | RED.view.dirty(ev.dirty); 65 | RED.view.redraw(); 66 | } 67 | } 68 | } 69 | 70 | }(); 71 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Node-RED 2 | 3 | A visual tool for wiring the Internet of Things. 4 | 5 | ## Quick Start 6 | 7 | Check out [INSTALL](INSTALL.md) for full instructions on getting started. 8 | 9 | 1. download the zip and unzip, or git clone 10 | 2. cd node-red 11 | 3. npm install 12 | 4. node red.js 13 | 5. Open 14 | 15 | ## Documentation 16 | 17 | More documentation can be found [here](http://nodered.org/docs). 18 | 19 | ## Browser Support 20 | 21 | The Node-RED editor runs in the browser. We routinely develop and test using 22 | Chrome and Firefox. We have anecdotal evidence that it works in IE9. 23 | 24 | We do not yet support mobile browsers, although that is high on our priority 25 | list. 26 | 27 | ## Contributing 28 | 29 | ### Reporting issues 30 | 31 | Please raise any bug reports or feature requests on the project's issue 32 | tracker. Be sure to search the list to see if your issue has already 33 | been raised. 34 | 35 | ### Creating new nodes 36 | 37 | The plugin nature of Node-RED means anyone can create a new node to extend 38 | its capabilities. 39 | 40 | We want to avoid duplication as that can lead to confusion. Many of our existing 41 | nodes offer a starting point of functionality. If they are missing features, 42 | we would rather extend them than add separate 'advanced' versions. But the key 43 | to that approach is getting the UX right to not lose the simplicity. 44 | 45 | We are also going to be quite selective over what nodes are included in the main 46 | repository - enough to be useful, but not so many that new user is overwhelmed. 47 | 48 | To contribute a new node, please raise a pull-request against the 49 | `node-red-nodes` repository. 50 | 51 | Eventually, the nodes will be npm-installable, but we're not there yet. We'll 52 | also have some sort of registry of nodes to help with discoverability. 53 | 54 | ### Pull-Requests 55 | 56 | In order for us to accept pull-requests, the contributor must first complete 57 | a Contributor License Agreement (CLA). This clarifies the intellectual 58 | property license granted with any contribution. It is for your protection as a 59 | Contributor as well as the protection of IBM and its customers; it does not 60 | change your rights to use your own Contributions for any other purpose. 61 | 62 | Once you have created a pull-request, we'll provide a link to the appropriate 63 | CLA document. 64 | 65 | If you are an IBMer, please contact us directly as the contribution process is 66 | slightly different. 67 | 68 | ## Authors 69 | 70 | Node-RED is a creation of the IBM Emerging Technology Services team. 71 | 72 | * Nick O'Leary [@knolleary](http://twitter.com/knolleary) 73 | * Dave Conway-Jones [@ceejay](http://twitter.com/ceejay) 74 | 75 | ## Copyright and license 76 | 77 | Copyright 2013 IBM Corp. under [the Apache 2.0 license](LICENSE). 78 | -------------------------------------------------------------------------------- /nodes/storage/67-leveldb.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var lvldb = require('level'); 19 | 20 | function LevelNode(n) { 21 | RED.nodes.createNode(this,n); 22 | this.dbname = n.db; 23 | var node = this; 24 | lvldb(this.dbname, function(err, db) { 25 | if (err) node.error(err); 26 | node.db = db; 27 | }); 28 | } 29 | RED.nodes.registerType("leveldbase",LevelNode); 30 | LevelNode.prototype.close = function() { 31 | this.db.close(); 32 | } 33 | 34 | function LevelDBNodeIn(n) { 35 | RED.nodes.createNode(this,n); 36 | this.level = n.level; 37 | this.levelConfig = RED.nodes.getNode(this.level); 38 | 39 | if (this.levelConfig) { 40 | var node = this; 41 | node.on("input", function(msg) { 42 | if (typeof msg.topic === 'string') { 43 | node.levelConfig.db.get(msg.topic, function(err, value) { 44 | if (err) { 45 | //node.warn(err); 46 | // for some reason they treat nothing found as an error... 47 | msg.payload = null; // so we should return null 48 | } 49 | else { msg.payload = value; } 50 | node.send(msg); 51 | }); 52 | } 53 | else { 54 | if (typeof msg.topic !== 'string') node.error("msg.topic (the key is not defined"); 55 | } 56 | }); 57 | } 58 | else { 59 | this.error("LevelDB database name not configured"); 60 | } 61 | } 62 | RED.nodes.registerType("leveldb in",LevelDBNodeIn); 63 | 64 | 65 | function LevelDBNodeOut(n) { 66 | RED.nodes.createNode(this,n); 67 | this.level = n.level; 68 | this.operation = n.operation; 69 | this.levelConfig = RED.nodes.getNode(this.level); 70 | 71 | if (this.levelConfig) { 72 | var node = this; 73 | node.on("input", function(msg) { 74 | if (typeof msg.topic === 'string') { 75 | if (node.operation === "delete") { 76 | node.levelConfig.db.del(msg.topic); 77 | } 78 | else { 79 | node.levelConfig.db.put(msg.topic, msg.payload, function(err) { 80 | if (err) node.error(err); 81 | }); 82 | } 83 | } 84 | else { 85 | if (typeof msg.topic !== 'string') node.error("msg.topic (the key is not defined"); 86 | } 87 | }); 88 | } 89 | else { 90 | this.error("LevelDB database name not configured"); 91 | } 92 | } 93 | RED.nodes.registerType("leveldb out",LevelDBNodeOut); 94 | -------------------------------------------------------------------------------- /nodes/core/80-function.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | 19 | var util = require("util"); 20 | var vm = require("vm"); 21 | var fs = require('fs'); 22 | var fspath = require('path'); 23 | 24 | function FunctionNode(n) { 25 | RED.nodes.createNode(this,n); 26 | this.name = n.name; 27 | this.func = n.func; 28 | var functionText = "var results = (function(msg){"+this.func+"})(msg);"; 29 | this.topic = n.topic; 30 | this.context = {global:RED.settings.functionGlobalContext || {}}; 31 | try { 32 | this.script = vm.createScript(functionText); 33 | this.on("input", function(msg) { 34 | if (msg != null) { 35 | var sandbox = {msg:msg,console:console,util:util,Buffer:Buffer,context:this.context}; 36 | try { 37 | this.script.runInNewContext(sandbox); 38 | var results = sandbox.results; 39 | 40 | if (results == null) { 41 | results = []; 42 | } else if (results.length == null) { 43 | results = [results]; 44 | } 45 | if (msg._topic) { 46 | for (var m in results) { 47 | if (results[m]) { 48 | if (util.isArray(results[m])) { 49 | for (var n in results[m]) { 50 | results[m][n]._topic = msg._topic; 51 | } 52 | } else { 53 | results[m]._topic = msg._topic; 54 | } 55 | } 56 | } 57 | } 58 | this.send(results); 59 | 60 | } catch(err) { 61 | this.error(err.message); 62 | } 63 | } 64 | }); 65 | } catch(err) { 66 | this.error(err.message); 67 | } 68 | } 69 | 70 | RED.nodes.registerType("function",FunctionNode); 71 | RED.library.register("functions"); 72 | -------------------------------------------------------------------------------- /nodes/io/30-socketout.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 38 | 39 | 44 | 45 | 67 | -------------------------------------------------------------------------------- /nodes/core/75-exec.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 36 | 37 | 44 | 45 | 64 | -------------------------------------------------------------------------------- /nodes/deprecated/35-rpi-gpio-in.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 47 | 48 | 70 | -------------------------------------------------------------------------------- /nodes/social/32-feedparse.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var FeedParser = require("feedparser"); 19 | var request = require("request"); 20 | 21 | function FeedParseNode(n) { 22 | RED.nodes.createNode(this,n); 23 | this.url = n.url; 24 | this.interval = (parseInt(n.interval)||15)*60000; 25 | var node = this; 26 | this.interval_id = null; 27 | this.seen = {}; 28 | if (this.url !== "") { 29 | var getFeed = function() { 30 | request(node.url,function(err) { 31 | if (err) node.error(err); 32 | }) 33 | .pipe(new FeedParser({feedurl:node.url})) 34 | .on('error', function(error) { 35 | node.error(error); 36 | }) 37 | .on('meta', function (meta) {}) 38 | .on('article', function (article) { 39 | if (!(article.guid in node.seen) || ( node.seen[article.guid] != 0 && node.seen[article.guid] != article.date.getTime())) { 40 | node.seen[article.guid] = article.date?article.date.getTime():0; 41 | var msg = { 42 | topic:article.origlink||article.link, 43 | payload: article.description, 44 | article: { 45 | summary:article.summary, 46 | link:article.link, 47 | date: article.date, 48 | pubdate: article.pubdate, 49 | author: article.author, 50 | guid: article.guid, 51 | } 52 | }; 53 | node.send(msg); 54 | } 55 | }) 56 | .on('end', function () { 57 | }); 58 | }; 59 | this.interval_id = setInterval(getFeed,node.interval); 60 | getFeed(); 61 | 62 | } else { 63 | this.error("Invalid url"); 64 | } 65 | } 66 | 67 | RED.nodes.registerType("feedparse",FeedParseNode); 68 | 69 | FeedParseNode.prototype.close = function() { 70 | if (this.interval_id != null) { 71 | clearInterval(this.interval_id); 72 | } 73 | } 74 | 75 | 76 | -------------------------------------------------------------------------------- /nodes/storage/50-file.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 37 | 38 | 43 | 44 | 67 | -------------------------------------------------------------------------------- /nodes/io/10-mqtt.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var connectionPool = require("./lib/mqttConnectionPool"); 19 | var util = require("util"); 20 | 21 | function MQTTBrokerNode(n) { 22 | RED.nodes.createNode(this,n); 23 | this.broker = n.broker; 24 | this.port = n.port; 25 | } 26 | RED.nodes.registerType("mqtt-broker",MQTTBrokerNode); 27 | 28 | 29 | function MQTTInNode(n) { 30 | RED.nodes.createNode(this,n); 31 | this.topic = n.topic; 32 | this.broker = n.broker; 33 | this.brokerConfig = RED.nodes.getNode(this.broker); 34 | if (this.brokerConfig) { 35 | this.client = connectionPool.get(this.brokerConfig.broker,this.brokerConfig.port); 36 | var node = this; 37 | this.client.subscribe(this.topic,2,function(topic,payload,qos,retain) { 38 | var msg = {topic:topic,payload:payload,qos:qos,retain:retain}; 39 | if ((node.brokerConfig.broker == "localhost")||(node.brokerConfig.broker == "127.0.0.1")) { 40 | msg._topic = topic; 41 | } 42 | node.send(msg); 43 | }); 44 | this.client.connect(); 45 | } else { 46 | this.error("missing broker configuration"); 47 | } 48 | } 49 | 50 | RED.nodes.registerType("mqtt in",MQTTInNode); 51 | 52 | MQTTInNode.prototype.close = function() { 53 | if (this.client) { 54 | this.client.disconnect(); 55 | } 56 | } 57 | 58 | 59 | function MQTTOutNode(n) { 60 | RED.nodes.createNode(this,n); 61 | 62 | this.topic = n.topic; 63 | this.broker = n.broker; 64 | 65 | this.brokerConfig = RED.nodes.getNode(this.broker); 66 | 67 | if (this.brokerConfig) { 68 | this.client = connectionPool.get(this.brokerConfig.broker,this.brokerConfig.port); 69 | this.on("input",function(msg) { 70 | if (msg != null) { 71 | if (this.topic) { 72 | msg.topic = this.topic; 73 | } 74 | this.client.publish(msg); 75 | } 76 | }); 77 | this.client.connect(); 78 | } else { 79 | this.error("missing broker configuration"); 80 | } 81 | } 82 | 83 | RED.nodes.registerType("mqtt out",MQTTOutNode); 84 | 85 | MQTTOutNode.prototype.close = function() { 86 | if (this.client) { 87 | this.client.disconnect(); 88 | } 89 | } 90 | 91 | -------------------------------------------------------------------------------- /nodes/core/20-inject.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | try { 19 | var cron = require("cron"); 20 | } catch(err) { 21 | require("util").log("[inject] Warning: cannot find module 'cron'"); 22 | } 23 | 24 | function InjectNode(n) { 25 | RED.nodes.createNode(this,n); 26 | this.topic = n.topic; 27 | this.payload = n.payload; 28 | this.repeat = n.repeat; 29 | this.crontab = n.crontab; 30 | this.once = n.once; 31 | var node = this; 32 | this.interval_id = null; 33 | this.cronjob = null; 34 | 35 | if (this.repeat && !isNaN(this.repeat) && this.repeat > 0) { 36 | this.repeat = this.repeat * 1000; 37 | this.log("repeat = "+this.repeat); 38 | this.interval_id = setInterval( function() { 39 | node.emit("input",{}); 40 | }, this.repeat ); 41 | } else if (this.crontab) { 42 | if (cron) { 43 | this.log("crontab = "+this.crontab); 44 | this.cronjob = new cron.CronJob(this.crontab, 45 | function() { 46 | node.emit("input",{}); 47 | }, 48 | null,true); 49 | } else { 50 | this.error("'cron' module not found"); 51 | } 52 | } 53 | 54 | if (this.once) { 55 | setTimeout( function(){ node.emit("input",{}); }, 50); 56 | } 57 | 58 | this.on("input",function(msg) { 59 | var msg = {topic:this.topic,payload:this.payload}; 60 | if (msg.payload == "") { msg.payload = Date.now(); } 61 | this.send(msg); 62 | msg = null; 63 | }); 64 | } 65 | 66 | RED.nodes.registerType("inject",InjectNode); 67 | 68 | InjectNode.prototype.close = function() { 69 | if (this.interval_id != null) { 70 | clearInterval(this.interval_id); 71 | this.log("inject: repeat stopped"); 72 | } else if (this.cronjob != null) { 73 | this.cronjob.stop(); 74 | this.log("inject: cronjob stopped"); 75 | delete this.cronjob; 76 | } 77 | } 78 | 79 | RED.app.post("/inject/:id", function(req,res) { 80 | var node = RED.nodes.getNode(req.params.id); 81 | if (node != null) { 82 | try { 83 | node.receive(); 84 | res.send(200); 85 | } catch(err) { 86 | res.send(500); 87 | node.error("Inject failed:"+err); 88 | console.log(err.stack); 89 | } 90 | } else { 91 | res.send(404); 92 | } 93 | }); 94 | -------------------------------------------------------------------------------- /nodes/io/30-socketin.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 41 | 42 | 47 | 48 | 70 | -------------------------------------------------------------------------------- /public/red/ui/palette.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | RED.palette = function() { 17 | 18 | function addNodeType(nt,def) { 19 | 20 | if (def.category != 'config') { 21 | var d = document.createElement("div"); 22 | d.id = "pn_"+nt; 23 | d.type = nt; 24 | 25 | var label = /^(.*?)( in| out)?$/.exec(nt)[1]; 26 | d.innerHTML = '
'+label+"
"; 27 | d.className="palette_node"; 28 | if (def.icon) { 29 | d.style.backgroundImage = "url(icons/"+def.icon+")"; 30 | if (def.align == "right") { 31 | d.style.backgroundPosition = "95% 50%"; 32 | } else if (def.inputs > 0) { 33 | d.style.backgroundPosition = "10% 50%"; 34 | } 35 | } 36 | 37 | d.style.backgroundColor = def.color; 38 | 39 | if (def.outputs > 0) { 40 | var port = document.createElement("div"); 41 | port.className = "palette_port palette_port_output"; 42 | d.appendChild(port); 43 | } 44 | 45 | if (def.inputs > 0) { 46 | var port = document.createElement("div"); 47 | port.className = "palette_port"; 48 | d.appendChild(port); 49 | } 50 | 51 | // TODO: add categories dynamically? 52 | $("#palette-"+def.category).append(d); 53 | 54 | d.onmousedown = function(e) { e.preventDefault(); } 55 | 56 | $(d).popover({ 57 | title:d.type, 58 | placement:"right", 59 | trigger: "hover", 60 | delay: { show: 750, hide: 50 }, 61 | html: true, 62 | title: nt, 63 | container:'body', 64 | content: $(($("script[data-help-name|='"+nt+"']").html()||"

no information available

").trim())[0] 65 | }); 66 | 67 | $(d).draggable({ 68 | helper: 'clone', 69 | appendTo: 'body', 70 | revert: true, 71 | revertDuration: 50 72 | }); 73 | } 74 | } 75 | 76 | $(".palette-header").click( 77 | function(e) { 78 | $(this).next().slideToggle(); 79 | $(this).children("i").toggleClass("expanded"); 80 | }); 81 | 82 | 83 | return { 84 | add:addNodeType 85 | }; 86 | }(); 87 | -------------------------------------------------------------------------------- /nodes/social/61-imap.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var Imap = require('imap'); 19 | var inspect = require('util').inspect; 20 | var oldmail = {}; 21 | 22 | try { 23 | var emailkey = require("../../settings").email || require("../../../emailkeys.js"); 24 | } catch(err) { 25 | throw new Error("Failed to load Email credentials"); 26 | } 27 | 28 | var imap = new Imap({ 29 | user: emailkey.user, 30 | password: emailkey.pass, 31 | host: emailkey.server||"imap.gmail.com", 32 | port: emailkey.port||"993", 33 | secure: true 34 | }); 35 | 36 | function show(obj) { 37 | return inspect(obj, false, Infinity); 38 | } 39 | 40 | function fail(err) { 41 | console.log('[imap] : ' + err); 42 | } 43 | 44 | function openInbox(cb) { 45 | imap.connect(function(err) { 46 | if (err) fail(err); 47 | imap.openBox('INBOX', true, cb); 48 | }); 49 | } 50 | 51 | function ImapNode(n) { 52 | RED.nodes.createNode(this,n); 53 | this.name = n.name; 54 | this.repeat = n.repeat * 1000; 55 | var node = this; 56 | this.interval_id = null; 57 | 58 | if (this.repeat && !isNaN(this.repeat) && this.repeat > 0) { 59 | this.log("repeat = "+this.repeat); 60 | this.interval_id = setInterval( function() { 61 | node.emit("input",{}); 62 | }, this.repeat ); 63 | } 64 | 65 | this.on("input", function(msg) { 66 | openInbox(function(err, mailbox) { 67 | if (err) fail(err); 68 | imap.seq.fetch(mailbox.messages.total + ':*', { struct: false }, 69 | { headers: ['from', 'subject'], 70 | body: true, 71 | cb: function(fetch) { 72 | fetch.on('message', function(msg) { 73 | //node.log('Saw message no. ' + msg.seqno); 74 | var pay = {}; 75 | var body = ''; 76 | msg.on('headers', function(hdrs) { 77 | pay.from = hdrs.from[0]; 78 | pay.topic = hdrs.subject[0]; 79 | }); 80 | msg.on('data', function(chunk) { 81 | body += chunk.toString('utf8'); 82 | }); 83 | msg.on('end', function() { 84 | pay.payload = body; 85 | if ((pay.topic !== oldmail.topic)|(pay.payload !== oldmail.payload)) { 86 | oldmail = pay; 87 | //node.log("From: "+pay.from); 88 | node.log("Subj: "+pay.topic); 89 | //node.log("Body: "+pay.payload); 90 | node.send(pay); 91 | } 92 | }); 93 | }); 94 | } 95 | }, function(err) { 96 | if (err) node.log("Err : "+err); 97 | //node.log("Done fetching messages."); 98 | imap.logout(); 99 | } 100 | ); 101 | }); 102 | 103 | }); 104 | } 105 | 106 | RED.nodes.registerType("imap",ImapNode); 107 | 108 | ImapNode.prototype.close = function() { 109 | if (this.interval_id != null) { 110 | clearInterval(this.interval_id); 111 | this.log("inject: repeat stopped"); 112 | } 113 | } 114 | 115 | -------------------------------------------------------------------------------- /nodes/core/90-comment.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 29 | 30 | 33 | 34 | 86 | -------------------------------------------------------------------------------- /nodes/io/21-httpin.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 36 | 37 | 64 | 65 | 86 | -------------------------------------------------------------------------------- /nodes/storage/65-redisout.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var util = require("util"); 19 | var redis = require("redis"); 20 | 21 | var hashFieldRE = /^([^=]+)=(.*)$/; 22 | 23 | var redisConnectionPool = function() { 24 | var connections = {}; 25 | var obj = { 26 | get: function(host,port) { 27 | var id = host+":"+port; 28 | if (!connections[id]) { 29 | connections[id] = redis.createClient(port,host); 30 | connections[id].on("error",function(err) { 31 | util.log("[redis] "+err); 32 | }); 33 | connections[id].on("connect",function() { 34 | util.log("[redis] connected to "+host+":"+port); 35 | }); 36 | connections[id]._id = id; 37 | connections[id]._nodeCount = 0; 38 | } 39 | connections[id]._nodeCount += 1; 40 | return connections[id]; 41 | }, 42 | close: function(connection) { 43 | connection._nodeCount -= 1; 44 | if (connection._nodeCount == 0) { 45 | if (connection) { 46 | clearTimeout(connection.retry_timer); 47 | connection.end(); 48 | } 49 | delete connections[connection._id]; 50 | } 51 | } 52 | }; 53 | return obj; 54 | }(); 55 | 56 | 57 | function RedisOutNode(n) { 58 | RED.nodes.createNode(this,n); 59 | this.port = n.port||"6379"; 60 | this.hostname = n.hostname||"127.0.0.1"; 61 | this.key = n.key; 62 | this.structtype = n.structtype; 63 | 64 | this.client = redisConnectionPool.get(this.hostname,this.port); 65 | 66 | this.on("input", function(msg) { 67 | if (msg != null) { 68 | var k = this.key || msg.topic; 69 | if (k) { 70 | if (this.structtype == "string") { 71 | this.client.set(k,msg.payload); 72 | } else if (this.structtype == "hash") { 73 | var r = hashFieldRE.exec(msg.payload); 74 | if (r) { 75 | this.client.hset(k,r[1],r[2]); 76 | } else { 77 | this.warn("Invalid payload for redis hash"); 78 | } 79 | } else if (this.structtype == "set") { 80 | this.client.sadd(k,msg.payload); 81 | } else if (this.structtype == "list") { 82 | this.client.rpush(k,msg.payload); 83 | } 84 | } else { 85 | this.warn("No key or topic set"); 86 | } 87 | } 88 | }); 89 | } 90 | 91 | RED.nodes.registerType("redis out",RedisOutNode); 92 | 93 | RedisOutNode.prototype.close = function() { 94 | redisConnectionPool.close(this.client); 95 | } 96 | 97 | -------------------------------------------------------------------------------- /nodes/io/31-tcpout.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 42 | 43 | 51 | 52 | 87 | -------------------------------------------------------------------------------- /nodes/core/58-debug.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | 19 | var util = require("util"); 20 | var ws = require('ws'); 21 | var events = require("events"); 22 | var debuglength = RED.settings.debugMaxLength||1000; 23 | 24 | function DebugNode(n) { 25 | RED.nodes.createNode(this,n); 26 | this.name = n.name; 27 | this.complete = n.complete; 28 | this.active = (n.active == null)||n.active; 29 | 30 | this.on("input",function(msg) { 31 | if (this.active) { 32 | if (msg.payload instanceof Buffer) { 33 | msg.payload = "(Buffer) "+msg.payload.toString(); 34 | } 35 | if (this.complete == "true") { 36 | DebugNode.send({id:this.id,name:this.name,topic:msg.topic,msg:msg,_path:msg._path}); 37 | } else { 38 | if (typeof msg.payload !== "undefined") { 39 | DebugNode.send({id:this.id,name:this.name,topic:msg.topic,msg:msg.payload,_path:msg._path}); 40 | } 41 | } 42 | } 43 | }); 44 | } 45 | 46 | RED.nodes.registerType("debug",DebugNode); 47 | 48 | DebugNode.send = function(msg) { 49 | if (msg.msg instanceof Error) { 50 | msg.msg = msg.msg.toString(); 51 | } 52 | else if (typeof msg.msg === 'object') { 53 | var seen = []; 54 | msg.msg = "(Object) " + JSON.stringify(msg.msg, function(key, value) { 55 | if (typeof value === 'object' && value !== null) { 56 | if (seen.indexOf(value) !== -1) { return "[circular]"; } 57 | seen.push(value); 58 | } 59 | return value; 60 | }," "); 61 | seen = null; 62 | } 63 | else if (typeof msg.msg === "boolean") msg.msg = "(boolean) "+msg.msg.toString(); 64 | else if (msg.msg === 0) msg.msg = "0"; 65 | 66 | if (msg.msg.length > debuglength) { 67 | msg.msg = msg.msg.substr(0,debuglength) +" ...."; 68 | } 69 | 70 | for (var i in DebugNode.activeConnections) { 71 | var ws = DebugNode.activeConnections[i]; 72 | try { 73 | var p = JSON.stringify(msg); 74 | ws.send(p); 75 | } catch(err) { 76 | util.log("[debug] ws error : "+err); 77 | } 78 | } 79 | } 80 | 81 | DebugNode.activeConnections = []; 82 | DebugNode.wsServer = new ws.Server({server:RED.server}); 83 | DebugNode.wsServer.on('connection',function(ws) { 84 | DebugNode.activeConnections.push(ws); 85 | ws.on('close',function() { 86 | for (var i in DebugNode.activeConnections) { 87 | if (DebugNode.activeConnections[i] === ws) { 88 | DebugNode.activeConnections.splice(i,1); 89 | break; 90 | } 91 | } 92 | }); 93 | }); 94 | 95 | DebugNode.logHandler = new events.EventEmitter(); 96 | DebugNode.logHandler.on("log",function(msg) { 97 | if (msg.level == "warn" || msg.level == "error") { 98 | DebugNode.send(msg); 99 | } 100 | }); 101 | RED.nodes.addLogHandler(DebugNode.logHandler); 102 | 103 | RED.app.post("/debug/:id", function(req,res) { 104 | var node = RED.nodes.getNode(req.params.id); 105 | if (node != null) { 106 | if (node.active) { 107 | node.active = false; 108 | res.send(201); 109 | } else { 110 | node.active = true; 111 | res.send(200); 112 | } 113 | } else { 114 | res.send(404); 115 | } 116 | }); 117 | -------------------------------------------------------------------------------- /nodes/core/80-template.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 30 | 31 | 36 | 37 | 92 | -------------------------------------------------------------------------------- /nodes/social/92-xmpp.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var xmpp = require('simple-xmpp'); 19 | 20 | try { 21 | var xmppkey = require("../../settings").xmpp || require("../../../xmppkeys.js"); 22 | } catch(err) { 23 | throw new Error("Failed to load XMPP credentials"); 24 | } 25 | 26 | function XmppNode(n) { 27 | RED.nodes.createNode(this,n); 28 | this.server = n.server; 29 | this.port = n.port; 30 | this.join = n.join || false; 31 | this.nick = n.nick || "Node-RED"; 32 | this.sendAll = n.sendObject; 33 | this.to = n.to || ""; 34 | var node = this; 35 | 36 | setTimeout(function() { 37 | xmpp.connect({ 38 | jid : xmppkey.jid, 39 | password : xmppkey.password, 40 | host : this.server, 41 | port : this.port, 42 | skipPresence : true, 43 | reconnect : false 44 | }); 45 | }, 5000); 46 | 47 | xmpp.on('online', function() { 48 | node.log('connected to '+node.server); 49 | xmpp.setPresence('online', node.nick+' online'); 50 | if (node.join) { 51 | xmpp.join(node.to+'/'+node.nick); 52 | } 53 | }); 54 | 55 | xmpp.on('chat', function(from, message) { 56 | var msg = { topic:from, payload:message }; 57 | node.send([msg,null]); 58 | }); 59 | 60 | xmpp.on('groupchat', function(conference, from, message, stamp) { 61 | var msg = { topic:from, payload:message, room:conference }; 62 | if (from != node.nick) { node.send([msg,null]); } 63 | }); 64 | 65 | //xmpp.on('chatstate', function(from, state) { 66 | //console.log('%s is currently %s', from, state); 67 | //var msg = { topic:from, payload:state }; 68 | //node.send([null,msg]); 69 | //}); 70 | 71 | xmpp.on('buddy', function(jid, state, statusText) { 72 | node.log(jid+" is "+state+" : "+statusText); 73 | var msg = { topic:jid, payload: { presence:state, status:statusText} }; 74 | node.send([null,msg]); 75 | }); 76 | 77 | xmpp.on('error', function(err) { 78 | console.error(err); 79 | }); 80 | 81 | xmpp.on('close', function(err) { 82 | node.log('connection closed'); 83 | }); 84 | 85 | xmpp.on('subscribe', function(from) { 86 | xmpp.acceptSubscription(from); 87 | }); 88 | 89 | this.on("input", function(msg) { 90 | var to = msg.topic; 91 | if (node.to != "") { to = node.to; } 92 | if (node.sendAll) { 93 | xmpp.send(to, JSON.stringify(msg), node.join); 94 | } 95 | else { 96 | xmpp.send(to, msg.payload, node.join); 97 | } 98 | }); 99 | 100 | this._close = function() { 101 | xmpp.setPresence('offline'); 102 | //xmpp.conn.end(); 103 | // TODO - DCJ NOTE... this is not good. It leaves the connection up over a restart - which will end up with bad things happening... 104 | // (but requires the underlying xmpp lib to be fixed (which does have an open bug request on fixing the close method)). 105 | 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."); 106 | } 107 | } 108 | 109 | RED.nodes.registerType("xmpp",XmppNode); 110 | 111 | XmppNode.prototype.close = function() { 112 | this._close(); 113 | } 114 | -------------------------------------------------------------------------------- /nodes/io/32-multicast.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var dgram = require('dgram'); 19 | 20 | // The Input Node 21 | function MCastIn(n) { 22 | RED.nodes.createNode(this,n); 23 | this.group = n.group; 24 | this.port = n.port; 25 | this.host = n.host || null; 26 | this.base64 = n.base64; 27 | this.iface = n.iface || null; 28 | this.multicast = n.multicast; 29 | var node = this; 30 | 31 | var server = dgram.createSocket('udp4'); 32 | 33 | server.on("error", function (err) { 34 | console.log("udp listener error:\n" + err.stack); 35 | server.close(); 36 | }); 37 | 38 | server.on('message', function (message, remote) { 39 | var msg; 40 | if (node.base64) { msg = { payload:message.toString('base64'), fromip:remote.address+':'+remote.port }; } 41 | else { msg = { payload:message, fromip:remote.address+':'+remote.port }; } 42 | node.send(msg); 43 | }); 44 | 45 | server.on('listening', function () { 46 | var address = server.address(); 47 | node.log('udp listener at ' + address.address + ":" + address.port); 48 | if (node.multicast) { 49 | server.setBroadcast(true) 50 | server.setMulticastTTL(128); 51 | server.addMembership(node.group,node.iface); 52 | node.log("udp multicast group "+node.group); 53 | } 54 | }); 55 | 56 | //server.bind(node.port,node.host); 57 | server.bind(node.port,node.host); 58 | 59 | this._close = function() { 60 | server.close(); 61 | node.log('udp listener stopped'); 62 | } 63 | 64 | } 65 | 66 | MCastIn.prototype.close = function() { 67 | this._close(); 68 | } 69 | RED.nodes.registerType("multicast in",MCastIn); 70 | 71 | // The Output Node 72 | function MCastOut(n) { 73 | RED.nodes.createNode(this,n); 74 | this.group = n.group; 75 | this.port = n.port; 76 | this.host = n.host || null; 77 | this.base64 = n.base64; 78 | this.iface = n.iface || null; 79 | this.multicast = n.multicast; 80 | var node = this; 81 | 82 | var sock = dgram.createSocket('udp4'); // only use ipv4 for now 83 | sock.bind(node.port); // have to bind before you can enable broadcast... 84 | sock.setBroadcast(true); // turn on broadcast 85 | sock.setMulticastTTL(128); 86 | sock.addMembership(node.group,node.iface); // Add to the multicast group 87 | node.log('udp multicaster ready on '+node.group+":"+node.port); 88 | 89 | node.on("input", function(msg) { 90 | if (msg.payload != null) { 91 | console.log("MCast:",msg.payload); 92 | var message; 93 | if (node.base64) { 94 | message = new Buffer(msg.payload,'base64'); 95 | } 96 | else { 97 | message = new Buffer(msg.payload); 98 | } 99 | sock.send(message, 0, message.length, node.port, node.group, function(err, bytes) { 100 | if (err) node.error("udp : "+err); 101 | //util.log('[socket out] udp :' +bytes); 102 | }); 103 | } 104 | }); 105 | 106 | this._close = function() { 107 | sock.close(); 108 | node.log('udp multicaster stopped'); 109 | } 110 | 111 | } 112 | 113 | RED.nodes.registerType("multicast out",MCastOut); 114 | 115 | MCastOut.prototype.close = function() { 116 | this._close(); 117 | } 118 | 119 | -------------------------------------------------------------------------------- /nodes/social/92-xmpp.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 48 | 49 | 56 | 57 | 81 | -------------------------------------------------------------------------------- /nodes/99-sample.html.demo: -------------------------------------------------------------------------------- 1 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 43 | 44 | 45 | 46 | 56 | 57 | 58 | 59 | 77 | -------------------------------------------------------------------------------- /public/red/ui/sidebar.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | RED.sidebar = function() { 17 | 18 | $('#sidebar').tabs(); 19 | 20 | $('#btn-sidebar').click(function() {toggleSidebar();}); 21 | RED.keyboard.add(/* SPACE */ 32,{ctrl:true},function(){toggleSidebar();d3.event.preventDefault();}); 22 | 23 | 24 | var sidebarSeparator = {}; 25 | $("#sidebar-separator").draggable({ 26 | axis: "x", 27 | start:function(event,ui) { 28 | var winWidth = $(window).width(); 29 | sidebarSeparator.start = ui.position.left; 30 | sidebarSeparator.width = $("#sidebar").width(); 31 | sidebarSeparator.chartWidth = $("#chart").width(); 32 | sidebarSeparator.chartRight = winWidth-$("#chart").width()-$("#chart").offset().left-2; 33 | sidebarSeparator.closing = false; 34 | }, 35 | drag: function(event,ui) { 36 | var d = ui.position.left-sidebarSeparator.start; 37 | var newSidebarWidth = sidebarSeparator.width-d; 38 | 39 | if (newSidebarWidth > 180 && sidebarSeparator.chartWidth+d > 200) { 40 | var newChartRight = sidebarSeparator.chartRight-d; 41 | $("#chart").css("right",newChartRight); 42 | $("#chart-zoom-controls").css("right",newChartRight+20); 43 | $("#sidebar").width(newSidebarWidth); 44 | } 45 | if (newSidebarWidth < 150 && !sidebarSeparator.closing) { 46 | $("#sidebar").addClass("closing"); 47 | sidebarSeparator.closing = true; 48 | } 49 | if (newSidebarWidth >= 150 && sidebarSeparator.closing) { 50 | sidebarSeparator.closing = false; 51 | $("#sidebar").removeClass("closing"); 52 | } 53 | 54 | }, 55 | stop:function(event,ui) { 56 | $("#sidebar-separator").css("left","auto"); 57 | $("#sidebar-separator").css("right",($("#sidebar").width()+15)+"px"); 58 | if (sidebarSeparator.closing) { 59 | $("#sidebar").removeClass("closing"); 60 | toggleSidebar(); 61 | } 62 | } 63 | }); 64 | 65 | function toggleSidebar() { 66 | if ($('#sidebar').tabs( "option", "active" ) === false) { 67 | $('#sidebar').tabs( "option", "active",0); 68 | } 69 | var btnSidebar = $("#btn-sidebar"); 70 | btnSidebar.toggleClass("active"); 71 | 72 | if (!btnSidebar.hasClass("active")) { 73 | $("#main-container").addClass("sidebar-closed"); 74 | } else { 75 | $("#main-container").removeClass("sidebar-closed"); 76 | } 77 | } 78 | toggleSidebar(); 79 | 80 | function addTab(title,content) { 81 | var tab = document.createElement("li"); 82 | tab.innerHTML = ''+title+''; 83 | $("#sidebar-tabs").append(tab); 84 | $("#sidebar-content").append(content); 85 | 86 | $('#sidebar').tabs("refresh"); 87 | 88 | } 89 | 90 | return { 91 | addTab: addTab 92 | } 93 | 94 | }(); 95 | -------------------------------------------------------------------------------- /nodes/io/31-tcpout.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var reconnectTime = RED.settings.socketReconnectTime||10000; 19 | var net = require('net'); 20 | 21 | function TcpOut(n) { 22 | RED.nodes.createNode(this,n); 23 | this.host = n.host; 24 | this.port = n.port * 1; 25 | this.base64 = n.base64; 26 | this.beserver = n.beserver; 27 | this.name = n.name; 28 | this.closing = false; 29 | var node = this; 30 | 31 | if (!node.beserver||node.beserver=="client") { 32 | var reconnectTimeout; 33 | var client = null; 34 | var connected = false; 35 | 36 | function setupTcpClient() { 37 | node.log("connecting to "+node.host+":"+node.port); 38 | client = net.connect(node.port, node.host, function() { 39 | connected = true; 40 | node.log("connected to "+node.host+":"+node.port); 41 | }); 42 | 43 | client.on('error', function (err) { 44 | node.log('error : '+err); 45 | }); 46 | 47 | client.on('end', function (err) { 48 | }); 49 | 50 | client.on('close', function() { 51 | node.log("connection lost to "+node.host+":"+node.port); 52 | connected = false; 53 | client.destroy(); 54 | if (!node.closing) { 55 | reconnectTimeout = setTimeout(setupTcpClient,reconnectTime); 56 | } 57 | }); 58 | } 59 | setupTcpClient(); 60 | 61 | 62 | node.on("input", function(msg) { 63 | if (connected && msg.payload != null) { 64 | if (Buffer.isBuffer(msg.payload)) { 65 | client.write(msg.payload); 66 | } else if (typeof msg.payload === "string" && node.base64) { 67 | client.write(new Buffer(msg.payload,'base64')); 68 | } else { 69 | client.write(new Buffer(""+msg.payload)); 70 | } 71 | } 72 | }); 73 | 74 | 75 | this._close = function() { 76 | this.closing = true; 77 | client.end(); 78 | clearTimeout(reconnectTimeout); 79 | } 80 | } 81 | 82 | else { 83 | var connectedSockets = []; 84 | var server = net.createServer(function (socket) { 85 | var remoteDetails = socket.remoteAddress+":"+socket.remotePort; 86 | node.log("connection from "+remoteDetails); 87 | connectedSockets.push(socket); 88 | socket.on('close',function() { 89 | node.log("connection closed from "+remoteDetails); 90 | connectedSockets.splice(connectedSockets.indexOf(socket),1); 91 | }); 92 | }); 93 | node.on("input", function(msg) { 94 | if (msg.payload != null) { 95 | var buffer; 96 | if (Buffer.isBuffer(msg.payload)) { 97 | buffer = msg.payload; 98 | } else if (typeof msg.payload === "string" && node.base64) { 99 | buffer = new Buffer(msg.payload,'base64'); 100 | } else { 101 | buffer = new Buffer(""+msg.payload); 102 | } 103 | for (var i = 0; iError: "+resp,"error"); 44 | } else { 45 | RED.notify("Error: no response from server","error"); 46 | } 47 | console.log(err,resp); 48 | } 49 | }); 50 | } 51 | } 52 | 53 | $('#btn-deploy').click(function() { save(); }); 54 | 55 | $( "#node-dialog-confirm-deploy" ).dialog({ 56 | title: "Confirm deploy", 57 | modal: true, 58 | autoOpen: false, 59 | width: 530, 60 | height: 230, 61 | buttons: [ 62 | { 63 | text: "Confirm deploy", 64 | click: function() { 65 | save(true); 66 | $( this ).dialog( "close" ); 67 | } 68 | }, 69 | { 70 | text: "Cancel", 71 | click: function() { 72 | $( this ).dialog( "close" ); 73 | } 74 | } 75 | ] 76 | }); 77 | 78 | function loadNodes() { 79 | $.get('nodes', function(data) { 80 | $("body").append(data); 81 | loadFlows(); 82 | }); 83 | } 84 | 85 | function loadFlows() { 86 | d3.json("flows",function(nodes) { 87 | RED.nodes.import(nodes); 88 | RED.view.dirty(false); 89 | RED.view.redraw(); 90 | }); 91 | } 92 | 93 | function showHelp() { 94 | 95 | var dialog = $('#node-help'); 96 | 97 | //$("#node-help").draggable({ 98 | // handle: ".modal-header" 99 | //}); 100 | 101 | dialog.on('show',function() { 102 | RED.keyboard.disable(); 103 | }); 104 | dialog.on('hidden',function() { 105 | RED.keyboard.enable(); 106 | }); 107 | 108 | dialog.modal(); 109 | } 110 | 111 | 112 | $(function() { 113 | RED.keyboard.add(/* ? */ 191,{shift:true},function(){showHelp();d3.event.preventDefault();}); 114 | loadNodes(); 115 | }); 116 | 117 | return { 118 | }; 119 | }(); 120 | 121 | -------------------------------------------------------------------------------- /nodes/hardware/36-rpi-gpio.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var util = require("util"); 19 | var exec = require('child_process').exec; 20 | var fs = require('fs'); 21 | 22 | if (!fs.existsSync("/usr/local/bin/gpio")) { 23 | exec("cat /proc/cpuinfo | grep BCM27",function(err,stdout,stderr) { 24 | if (stdout.indexOf('BCM27') > -1) { 25 | util.log('[36-rpi-gpio.js] Error: Cannot find Wiring-Pi "gpio" command'); 26 | } 27 | // else not on a Pi so don't worry anyone with needless messages. 28 | }); 29 | return; 30 | } 31 | 32 | // Map physical P1 pins to Gordon's Wiring-Pi Pins (as they should be V1/V2 tolerant) 33 | var pintable = { 34 | // Physical : WiringPi 35 | "7":"7", 36 | "11":"0", 37 | "12":"1", 38 | "13":"2", 39 | "15":"3", 40 | "16":"4", 41 | "18":"5", 42 | "22":"6" 43 | } 44 | var tablepin = { 45 | // WiringPi : Physical 46 | "7":"7", 47 | "0":"11", 48 | "1":"12", 49 | "2":"13", 50 | "3":"15", 51 | "4":"16", 52 | "5":"18", 53 | "6":"22" 54 | } 55 | 56 | function GPIOInNode(n) { 57 | RED.nodes.createNode(this,n); 58 | this.buttonState = -1; 59 | this.pin = pintable[n.pin]; 60 | this.intype = n.intype; 61 | var node = this; 62 | 63 | if (this.pin) { 64 | exec("gpio mode "+node.pin+" "+node.intype, function(err,stdout,stderr) { 65 | if (err) node.error(err); 66 | else { 67 | node._interval = setInterval( function() { 68 | exec("gpio read "+node.pin, function(err,stdout,stderr) { 69 | if (err) node.error(err); 70 | else { 71 | if (node.buttonState !== Number(stdout)) { 72 | var previousState = node.buttonState; 73 | node.buttonState = Number(stdout); 74 | if (previousState !== -1) { 75 | var msg = {topic:"pi/"+tablepin[node.pin], payload:node.buttonState}; 76 | node.send(msg); 77 | } 78 | } 79 | } 80 | }); 81 | }, 250); 82 | } 83 | }); 84 | } 85 | else { 86 | this.error("Invalid GPIO pin: "+this.pin); 87 | } 88 | } 89 | 90 | function GPIOOutNode(n) { 91 | RED.nodes.createNode(this,n); 92 | this.pin = pintable[n.pin]; 93 | var node = this; 94 | 95 | if (this.pin) { 96 | process.nextTick(function() { 97 | exec("gpio mode "+node.pin+" out", function(err,stdout,stderr) { 98 | if (err) node.error(err); 99 | else { 100 | node.on("input", function(msg) { 101 | if (msg.payload === "true") msg.payload = true; 102 | if (msg.payload === "false") msg.payload = false; 103 | var out = Number(msg.payload); 104 | if ((out == 0)|(out == 1)) { 105 | exec("gpio write "+node.pin+" "+out, function(err,stdout,stderr) { 106 | if (err) node.error(err); 107 | }); 108 | } 109 | else node.warn("Invalid input - not 0 or 1"); 110 | }); 111 | } 112 | }); 113 | }); 114 | } 115 | else { 116 | this.error("Invalid GPIO pin: "+this.pin); 117 | } 118 | } 119 | 120 | exec("gpio mode 0 in",function(err,stdout,stderr) { 121 | if (err) { 122 | util.log('[36-rpi-gpio.js] Error: "gpio" command failed for some reason.'); 123 | } 124 | exec("gpio mode 1 in"); 125 | exec("gpio mode 2 in"); 126 | exec("gpio mode 3 in"); 127 | exec("gpio mode 4 in"); 128 | exec("gpio mode 5 in"); 129 | exec("gpio mode 6 in"); 130 | exec("gpio mode 7 in",function(err,stdout,stderr) { 131 | RED.nodes.registerType("rpi-gpio in",GPIOInNode); 132 | RED.nodes.registerType("rpi-gpio out",GPIOOutNode); 133 | 134 | GPIOInNode.prototype.close = function() { 135 | clearInterval(this._interval); 136 | } 137 | 138 | GPIOOutNode.prototype.close = function() { 139 | exec("gpio mode "+this.pin+" in"); 140 | } 141 | 142 | }); 143 | }); 144 | -------------------------------------------------------------------------------- /nodes/core/80-function.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 32 | 33 | 39 | 40 | 97 | -------------------------------------------------------------------------------- /nodes/storage/67-leveldb.html: -------------------------------------------------------------------------------- 1 | 16 | 17 | 23 | 24 | 35 | 36 | 46 | 47 | 53 | 54 | 74 | 75 | 76 | 93 | 94 | 95 | 100 | 101 | 123 | -------------------------------------------------------------------------------- /nodes/storage/66-mongodb.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | var mongo = require('mongodb'); 19 | 20 | function MongoNode(n) { 21 | RED.nodes.createNode(this,n); 22 | this.hostname = n.hostname; 23 | this.port = n.port; 24 | this.db = n.db; 25 | this.name = n.name; 26 | } 27 | RED.nodes.registerType("mongodb",MongoNode); 28 | 29 | 30 | function MongoOutNode(n) { 31 | RED.nodes.createNode(this,n); 32 | this.collection = n.collection; 33 | this.mongodb = n.mongodb; 34 | this.payonly = n.payonly || false; 35 | this.operation = n.operation; 36 | this.mongoConfig = RED.nodes.getNode(this.mongodb); 37 | 38 | if (this.mongoConfig) { 39 | var node = this; 40 | this.clientDb = new mongo.Db(node.mongoConfig.db, new mongo.Server(node.mongoConfig.hostname, node.mongoConfig.port, {}), {w: 1}); 41 | this.clientDb.open(function(err,cli) { 42 | if (err) { node.error(err); } 43 | else { 44 | node.clientDb.collection(node.collection,function(err,coll) { 45 | if (err) { node.error(err); } 46 | else { 47 | node.on("input",function(msg) { 48 | if (node.operation == "store") { 49 | delete msg._topic; 50 | if (node.payonly) coll.save(msg.payload,function(err,item){ if (err){node.error(err);} }); 51 | else coll.save(msg,function(err,item){if (err){node.error(err);}}); 52 | } 53 | if (node.operation == "delete") { 54 | console.log(msg.payload); 55 | coll.remove(msg.payload, {w:1}, function(err, items){ if (err) node.error(err); }); 56 | } 57 | }); 58 | } 59 | }); 60 | } 61 | }); 62 | } else { 63 | this.error("missing mongodb configuration"); 64 | } 65 | } 66 | 67 | RED.nodes.registerType("mongodb out",MongoOutNode); 68 | 69 | MongoOutNode.prototype.close = function() { 70 | if (this.clientDb) { 71 | this.clientDb.close(); 72 | } 73 | } 74 | 75 | function MongoInNode(n) { 76 | RED.nodes.createNode(this,n); 77 | this.collection = n.collection; 78 | this.mongodb = n.mongodb; 79 | this.mongoConfig = RED.nodes.getNode(this.mongodb); 80 | 81 | if (this.mongoConfig) { 82 | var node = this; 83 | this.clientDb = new mongo.Db(node.mongoConfig.db, new mongo.Server(node.mongoConfig.hostname, node.mongoConfig.port, {}), {w: 1}); 84 | this.clientDb.open(function(err,cli) { 85 | if (err) { node.error(err); } 86 | else { 87 | node.clientDb.collection(node.collection,function(err,coll) { 88 | if (err) { node.error(err); } 89 | else { 90 | node.on("input",function(msg) { 91 | msg.projection = msg.projection || {}; 92 | coll.find(msg.payload,msg.projection).sort(msg.sort).limit(msg.limit).toArray(function(err, items) { 93 | if (err) { node.error(err); } 94 | msg.payload = items; 95 | delete msg.projection; 96 | delete msg.sort; 97 | delete msg.limit; 98 | node.send(msg); 99 | }); 100 | }); 101 | } 102 | }); 103 | } 104 | }); 105 | } else { 106 | this.error("missing mongodb configuration"); 107 | } 108 | } 109 | 110 | RED.nodes.registerType("mongodb in",MongoInNode); 111 | 112 | MongoInNode.prototype.close = function() { 113 | if (this.clientDb) { 114 | this.clientDb.close(); 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /nodes/io/30-socketin.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Copyright 2013 IBM Corp. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | **/ 16 | 17 | var RED = require("../../red/red"); 18 | 19 | function SocketIn(n) { 20 | RED.nodes.createNode(this,n); 21 | this.port = n.port; 22 | this.topic = n.topic; 23 | this.trans = (n.transport||n.trans||"").toLowerCase(); 24 | var node = this; 25 | if (this.trans == "http") { 26 | var http = require('http'); 27 | var server = http.createServer(function (req, res) { 28 | //node.log("http "+req.url); 29 | var msg = {topic:node.topic,payload:req.url.slice(1)}; 30 | node.send(msg); 31 | res.writeHead(304, {'Content-Type': 'text/plain'}); 32 | res.end('\n'); 33 | }).listen(node.port); 34 | server.on('error', function (e) { 35 | if (e.code == 'EADDRINUSE') { 36 | setTimeout(node.error('TCP port is already in use - please reconfigure socket.'),250); 37 | } 38 | else { console.log(e); } 39 | server = null; 40 | }); 41 | node.log('http listener at http://127.0.0.1:'+node.port+'/'); 42 | 43 | this._close = function() { 44 | if (server) server.close(); 45 | node.log('http listener stopped'); 46 | } 47 | } 48 | 49 | if (this.trans == "tcp") { 50 | var net = require('net'); 51 | var server = net.createServer(function (socket) { 52 | var buffer = null; 53 | socket.on('data', function (chunk) { 54 | if (buffer == null) { 55 | buffer = chunk; 56 | } else { 57 | buffer = Buffer.concat([buffer,chunk]); 58 | } 59 | }); 60 | socket.on('end', function() { 61 | var msg = {topic:node.topic, payload:buffer, fromip:socket.remoteAddress+':'+socket.remotePort}; 62 | node.send(msg); 63 | }); 64 | }); 65 | server.on('error', function (e) { 66 | if (e.code == 'EADDRINUSE') { 67 | setTimeout(node.error('TCP port is already in use - please reconfigure socket.'),250); 68 | } 69 | else { console.log(e); } 70 | server = null; 71 | }); 72 | server.listen(node.port); 73 | node.log('tcp listener on port :'+node.port); 74 | 75 | this._close = function() { 76 | if (server) server.close(); 77 | node.log('tcp listener stopped'); 78 | } 79 | } 80 | 81 | if (this.trans == "tcpc") { 82 | var net = require('net'); 83 | var client; 84 | var to; 85 | function setupTcpClient() { 86 | node.log('tcpc connecting to port :'+node.port); 87 | client = net.connect({port: node.port}, function() { 88 | node.log("tcpc connected"); 89 | }); 90 | 91 | client.on('data', function (data) { 92 | var msg = {topic:node.topic, payload:data}; 93 | node.send(msg); 94 | }); 95 | 96 | client.on('end', function() { 97 | node.log("tcpc socket ended"); 98 | }); 99 | 100 | client.on('close', function() { 101 | node.log('tcpc socket closed'); 102 | to = setTimeout(setupTcpClient, 10000); //Try to reconnect 103 | }); 104 | 105 | client.on('error', function() { 106 | node.log('tcpc socket error'); 107 | client = null; 108 | to = setTimeout(setupTcpClient, 10000); //Try to reconnect 109 | }); 110 | } 111 | setupTcpClient(); 112 | 113 | this._close = function() { 114 | if (client) client.end(); 115 | //client.destroy(); 116 | clearTimeout(to); 117 | node.log('tcpc stopped client'); 118 | } 119 | setupTcpClient(); 120 | } 121 | 122 | if (this.trans == "udp") { 123 | var dgram = require('dgram'); 124 | var server = dgram.createSocket('udp4'); 125 | server.on('listening', function () { 126 | var address = server.address(); 127 | node.log('udp listener at ' + address.address + ":" + address.port); 128 | }); 129 | server.on('message', function (message, remote) { 130 | var msg = {topic:node.topic,payload:message,fromip:remote.address+':'+remote.port}; 131 | node.send(msg); 132 | }); 133 | server.on('error', function (e) { 134 | console.log(e); 135 | server = null; 136 | }); 137 | server.bind(node.port); 138 | 139 | this._close = function() { 140 | if (server) server.close(); 141 | node.log('udp listener stopped'); 142 | } 143 | } 144 | 145 | } 146 | 147 | RED.nodes.registerType("socket in",SocketIn); 148 | 149 | SocketIn.prototype.close = function() { 150 | this._close(); 151 | } 152 | --------------------------------------------------------------------------------