[CCSDK-28] populated the seed code for dgbuilder 31/8931/1
authorChinthakayala, Sheshashailavas (sc2914) <sc2914@us.att.com>
Mon, 28 Aug 2017 14:25:46 +0000 (05:25 -0900)
committerChinthakayala, Sheshashailavas (sc2914) <sc2914@att.com>
Mon, 28 Aug 2017 14:36:52 +0000 (05:36 -0900)
updated the code to point to the new package name for sli

Change-Id: I3b5a1d05dc5193664fd4a667afdcd0b2354010a4
Issue-ID:{CCSDK-28}
Signed-off-by: Chinthakayala, Sheshashailavas (sc2914) <sc2914@att.com>
Signed-off-by: Chinthakayala, Sheshashailavas (sc2914) <sc2914@att.com>
379 files changed:
dgbuilder/.gitignore [new file with mode: 0644]
dgbuilder/CONTRIBUTING.md [new file with mode: 0644]
dgbuilder/Gruntfile.js [new file with mode: 0644]
dgbuilder/INSTALL.md [new file with mode: 0644]
dgbuilder/LICENSE [new file with mode: 0644]
dgbuilder/build_pom_for_yang_compile [new file with mode: 0755]
dgbuilder/core_nodes/analysis/72-sentiment.html [new file with mode: 0644]
dgbuilder/core_nodes/analysis/72-sentiment.js [new file with mode: 0644]
dgbuilder/core_nodes/core/20-inject.html [new file with mode: 0644]
dgbuilder/core_nodes/core/20-inject.js [new file with mode: 0644]
dgbuilder/core_nodes/core/58-debug.html [new file with mode: 0644]
dgbuilder/core_nodes/core/58-debug.js [new file with mode: 0644]
dgbuilder/core_nodes/core/75-exec.html [new file with mode: 0644]
dgbuilder/core_nodes/core/75-exec.js [new file with mode: 0644]
dgbuilder/core_nodes/core/80-function.html [new file with mode: 0644]
dgbuilder/core_nodes/core/80-function.js [new file with mode: 0644]
dgbuilder/core_nodes/core/80-template.html [new file with mode: 0644]
dgbuilder/core_nodes/core/80-template.js [new file with mode: 0644]
dgbuilder/core_nodes/core/89-delay.html [new file with mode: 0644]
dgbuilder/core_nodes/core/89-delay.js [new file with mode: 0644]
dgbuilder/core_nodes/core/89-trigger.html [new file with mode: 0644]
dgbuilder/core_nodes/core/89-trigger.js [new file with mode: 0644]
dgbuilder/core_nodes/core/90-comment.html [new file with mode: 0644]
dgbuilder/core_nodes/core/90-comment.js [new file with mode: 0644]
dgbuilder/core_nodes/core/98-unknown.html [new file with mode: 0644]
dgbuilder/core_nodes/core/98-unknown.js [new file with mode: 0644]
dgbuilder/core_nodes/deprecated/61-imap.html [new file with mode: 0644]
dgbuilder/core_nodes/deprecated/61-imap.js [new file with mode: 0644]
dgbuilder/core_nodes/deprecated/73-parsexml.html [new file with mode: 0644]
dgbuilder/core_nodes/deprecated/73-parsexml.js [new file with mode: 0644]
dgbuilder/core_nodes/deprecated/74-js2xml.html [new file with mode: 0644]
dgbuilder/core_nodes/deprecated/74-js2xml.js [new file with mode: 0644]
dgbuilder/core_nodes/deprecated/90-httpget.html [new file with mode: 0644]
dgbuilder/core_nodes/deprecated/90-httpget.js [new file with mode: 0644]
dgbuilder/core_nodes/hardware/35-arduino.html [new file with mode: 0644]
dgbuilder/core_nodes/hardware/35-arduino.js [new file with mode: 0644]
dgbuilder/core_nodes/hardware/36-rpi-gpio.html [new file with mode: 0644]
dgbuilder/core_nodes/hardware/36-rpi-gpio.js [new file with mode: 0644]
dgbuilder/core_nodes/io/10-mqtt.html [new file with mode: 0644]
dgbuilder/core_nodes/io/10-mqtt.js [new file with mode: 0644]
dgbuilder/core_nodes/io/21-httpin.html [new file with mode: 0644]
dgbuilder/core_nodes/io/21-httpin.js [new file with mode: 0644]
dgbuilder/core_nodes/io/22-websocket.html [new file with mode: 0644]
dgbuilder/core_nodes/io/22-websocket.js [new file with mode: 0644]
dgbuilder/core_nodes/io/23-watch.html [new file with mode: 0644]
dgbuilder/core_nodes/io/23-watch.js [new file with mode: 0644]
dgbuilder/core_nodes/io/25-serial.html [new file with mode: 0644]
dgbuilder/core_nodes/io/25-serial.js [new file with mode: 0644]
dgbuilder/core_nodes/io/31-tcpin.html [new file with mode: 0644]
dgbuilder/core_nodes/io/31-tcpin.js [new file with mode: 0644]
dgbuilder/core_nodes/io/32-udp.html [new file with mode: 0644]
dgbuilder/core_nodes/io/32-udp.js [new file with mode: 0644]
dgbuilder/core_nodes/io/lib/mqtt.js [new file with mode: 0644]
dgbuilder/core_nodes/io/lib/mqttConnectionPool.js [new file with mode: 0644]
dgbuilder/core_nodes/logic/10-switch.html [new file with mode: 0644]
dgbuilder/core_nodes/logic/10-switch.js [new file with mode: 0644]
dgbuilder/core_nodes/logic/15-change.html [new file with mode: 0644]
dgbuilder/core_nodes/logic/15-change.js [new file with mode: 0644]
dgbuilder/core_nodes/logic/16-range.html [new file with mode: 0644]
dgbuilder/core_nodes/logic/16-range.js [new file with mode: 0644]
dgbuilder/core_nodes/parsers/70-CSV.html [new file with mode: 0644]
dgbuilder/core_nodes/parsers/70-CSV.js [new file with mode: 0644]
dgbuilder/core_nodes/parsers/70-HTML.html [new file with mode: 0644]
dgbuilder/core_nodes/parsers/70-HTML.js [new file with mode: 0644]
dgbuilder/core_nodes/parsers/70-JSON.html [new file with mode: 0644]
dgbuilder/core_nodes/parsers/70-JSON.js [new file with mode: 0644]
dgbuilder/core_nodes/parsers/70-XML.html [new file with mode: 0644]
dgbuilder/core_nodes/parsers/70-XML.js [new file with mode: 0644]
dgbuilder/core_nodes/social/27-twitter.html [new file with mode: 0644]
dgbuilder/core_nodes/social/27-twitter.js [new file with mode: 0644]
dgbuilder/core_nodes/social/32-feedparse.html [new file with mode: 0644]
dgbuilder/core_nodes/social/32-feedparse.js [new file with mode: 0644]
dgbuilder/core_nodes/social/61-email.html [new file with mode: 0644]
dgbuilder/core_nodes/social/61-email.js [new file with mode: 0644]
dgbuilder/core_nodes/social/91-irc.html [new file with mode: 0644]
dgbuilder/core_nodes/social/91-irc.js [new file with mode: 0644]
dgbuilder/core_nodes/storage/28-tail.html [new file with mode: 0644]
dgbuilder/core_nodes/storage/28-tail.js [new file with mode: 0644]
dgbuilder/core_nodes/storage/50-file.html [new file with mode: 0644]
dgbuilder/core_nodes/storage/50-file.js [new file with mode: 0644]
dgbuilder/core_nodes/storage/65-redisout.html [new file with mode: 0644]
dgbuilder/core_nodes/storage/65-redisout.js [new file with mode: 0644]
dgbuilder/core_nodes/storage/66-mongodb.html [new file with mode: 0644]
dgbuilder/core_nodes/storage/66-mongodb.js [new file with mode: 0644]
dgbuilder/createReleaseDir.sh [new file with mode: 0755]
dgbuilder/flowShareUsers.js [new file with mode: 0644]
dgbuilder/generatedJS/.gitignore [new file with mode: 0644]
dgbuilder/git_scripts/gitcheckout [new file with mode: 0755]
dgbuilder/git_scripts/gitckout [new file with mode: 0755]
dgbuilder/git_scripts/gitcurbranch [new file with mode: 0755]
dgbuilder/git_scripts/gitlog [new file with mode: 0755]
dgbuilder/git_scripts/gitpull [new file with mode: 0755]
dgbuilder/git_scripts/gitstatus [new file with mode: 0755]
dgbuilder/nodes/99-sample.html.demo [new file with mode: 0644]
dgbuilder/nodes/99-sample.js.demo [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/block.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/block.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/breakNode.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/breakNode.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/call.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/call.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/configure.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/configure.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/delete.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/delete.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/execute.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/execute.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/exists.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/exists.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/forNode.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/forNode.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/get-resource.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/get-resource.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/is-available.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/is-available.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/notify.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/notify.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/record.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/record.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/release.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/release.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/reserve.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/reserve.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/save.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/save.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/set.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/set.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/switchNode.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/switchNode.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/update.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgelogic/update.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgemain/GenericXML.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgemain/GenericXML.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgemain/comment.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgemain/comment.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgemain/dgstart.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgemain/dgstart.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgemain/method.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgemain/method.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgemain/serviceLogic.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgemain/serviceLogic.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgeoutcome/already-active.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgeoutcome/already-active.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgeoutcome/failure.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgeoutcome/failure.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgeoutcome/not-found.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgeoutcome/not-found.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgeoutcome/other.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgeoutcome/other.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgeoutcome/outcome.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgeoutcome/outcome.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgeoutcome/outcomeFalse.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgeoutcome/outcomeFalse.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgeoutcome/outcomeTrue.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgeoutcome/outcomeTrue.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgeoutcome/success.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgeoutcome/success.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgereturn/returnFailure.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgereturn/returnFailure.js [new file with mode: 0644]
dgbuilder/nodes/dge/dgereturn/returnSuccess.html [new file with mode: 0644]
dgbuilder/nodes/dge/dgereturn/returnSuccess.js [new file with mode: 0644]
dgbuilder/package.json [new file with mode: 0644]
dgbuilder/pom.xml [new file with mode: 0644]
dgbuilder/public/bootstrap/css/bootstrap.min.css [new file with mode: 0644]
dgbuilder/public/bootstrap/img/glyphicons-halflings-white.png [new file with mode: 0644]
dgbuilder/public/bootstrap/img/glyphicons-halflings.png [new file with mode: 0644]
dgbuilder/public/bootstrap/js/bootstrap.min.js [new file with mode: 0644]
dgbuilder/public/d3.v3.min.js [new file with mode: 0644]
dgbuilder/public/favicon.ico [new file with mode: 0644]
dgbuilder/public/font-awesome/css/font-awesome.min.css [new file with mode: 0644]
dgbuilder/public/font-awesome/fonts/FontAwesome.otf [new file with mode: 0644]
dgbuilder/public/font-awesome/fonts/fontawesome-webfont.eot [new file with mode: 0755]
dgbuilder/public/font-awesome/fonts/fontawesome-webfont.svg [new file with mode: 0755]
dgbuilder/public/font-awesome/fonts/fontawesome-webfont.ttf [new file with mode: 0755]
dgbuilder/public/font-awesome/fonts/fontawesome-webfont.woff [new file with mode: 0755]
dgbuilder/public/grip.png [new file with mode: 0644]
dgbuilder/public/icons/alert.png [new file with mode: 0644]
dgbuilder/public/icons/arduino.png [new file with mode: 0644]
dgbuilder/public/icons/arrow-in.png [new file with mode: 0644]
dgbuilder/public/icons/bridge-dash.png [new file with mode: 0644]
dgbuilder/public/icons/bridge.png [new file with mode: 0644]
dgbuilder/public/icons/comment.png [new file with mode: 0644]
dgbuilder/public/icons/db.png [new file with mode: 0644]
dgbuilder/public/icons/debug.png [new file with mode: 0644]
dgbuilder/public/icons/envelope.png [new file with mode: 0644]
dgbuilder/public/icons/feed.png [new file with mode: 0644]
dgbuilder/public/icons/file.png [new file with mode: 0644]
dgbuilder/public/icons/function.png [new file with mode: 0644]
dgbuilder/public/icons/hash.png [new file with mode: 0644]
dgbuilder/public/icons/inject.png [new file with mode: 0644]
dgbuilder/public/icons/leveldb.png [new file with mode: 0644]
dgbuilder/public/icons/light.png [new file with mode: 0644]
dgbuilder/public/icons/mongodb.png [new file with mode: 0644]
dgbuilder/public/icons/node-changed.png [new file with mode: 0644]
dgbuilder/public/icons/node-error.png [new file with mode: 0644]
dgbuilder/public/icons/range.png [new file with mode: 0644]
dgbuilder/public/icons/redis.png [new file with mode: 0644]
dgbuilder/public/icons/rpi.png [new file with mode: 0644]
dgbuilder/public/icons/serial.png [new file with mode: 0644]
dgbuilder/public/icons/swap.png [new file with mode: 0644]
dgbuilder/public/icons/switch.png [new file with mode: 0644]
dgbuilder/public/icons/template.png [new file with mode: 0644]
dgbuilder/public/icons/timer.png [new file with mode: 0644]
dgbuilder/public/icons/trigger.png [new file with mode: 0644]
dgbuilder/public/icons/twitter.png [new file with mode: 0644]
dgbuilder/public/icons/watch.png [new file with mode: 0644]
dgbuilder/public/icons/white-globe.png [new file with mode: 0644]
dgbuilder/public/images/dgstart.png [new file with mode: 0644]
dgbuilder/public/images/page-loading.gif [new file with mode: 0644]
dgbuilder/public/index.html [new file with mode: 0644]
dgbuilder/public/index.html.orig [new file with mode: 0644]
dgbuilder/public/jquery/css/smoothness/images/animated-overlay.gif [new file with mode: 0644]
dgbuilder/public/jquery/css/smoothness/images/ui-bg_flat_0_aaaaaa_40x100.png [new file with mode: 0644]
dgbuilder/public/jquery/css/smoothness/images/ui-bg_flat_75_ffffff_40x100.png [new file with mode: 0644]
dgbuilder/public/jquery/css/smoothness/images/ui-bg_glass_55_fbf9ee_1x400.png [new file with mode: 0644]
dgbuilder/public/jquery/css/smoothness/images/ui-bg_glass_65_ffffff_1x400.png [new file with mode: 0644]
dgbuilder/public/jquery/css/smoothness/images/ui-bg_glass_75_dadada_1x400.png [new file with mode: 0644]
dgbuilder/public/jquery/css/smoothness/images/ui-bg_glass_75_e6e6e6_1x400.png [new file with mode: 0644]
dgbuilder/public/jquery/css/smoothness/images/ui-bg_glass_95_fef1ec_1x400.png [new file with mode: 0644]
dgbuilder/public/jquery/css/smoothness/images/ui-bg_highlight-soft_75_cccccc_1x100.png [new file with mode: 0644]
dgbuilder/public/jquery/css/smoothness/images/ui-icons_222222_256x240.png [new file with mode: 0644]
dgbuilder/public/jquery/css/smoothness/images/ui-icons_2e83ff_256x240.png [new file with mode: 0644]
dgbuilder/public/jquery/css/smoothness/images/ui-icons_454545_256x240.png [new file with mode: 0644]
dgbuilder/public/jquery/css/smoothness/images/ui-icons_888888_256x240.png [new file with mode: 0644]
dgbuilder/public/jquery/css/smoothness/images/ui-icons_cd0a0a_256x240.png [new file with mode: 0644]
dgbuilder/public/jquery/css/smoothness/jquery-ui-1.10.3.custom.min.css [new file with mode: 0644]
dgbuilder/public/jquery/js/jquery-1.11.1.min.js [new file with mode: 0644]
dgbuilder/public/jquery/js/jquery-ui-1.10.3.custom.min.js [new file with mode: 0644]
dgbuilder/public/jquery/js/jquery.ui.touch-punch.min.js [new file with mode: 0644]
dgbuilder/public/node-red.png [new file with mode: 0644]
dgbuilder/public/orion/built-editor.css [new file with mode: 0644]
dgbuilder/public/orion/built-editor.min.js [new file with mode: 0644]
dgbuilder/public/pw_maze_white.png [new file with mode: 0644]
dgbuilder/public/red/comms.js [new file with mode: 0644]
dgbuilder/public/red/history.js [new file with mode: 0644]
dgbuilder/public/red/main.js [new file with mode: 0644]
dgbuilder/public/red/main.js.orig [new file with mode: 0644]
dgbuilder/public/red/nodes.js [new file with mode: 0644]
dgbuilder/public/red/ui/editor.js [new file with mode: 0644]
dgbuilder/public/red/ui/keyboard.js [new file with mode: 0644]
dgbuilder/public/red/ui/library.js [new file with mode: 0644]
dgbuilder/public/red/ui/menu.js [new file with mode: 0644]
dgbuilder/public/red/ui/notifications.js [new file with mode: 0644]
dgbuilder/public/red/ui/palette.js [new file with mode: 0644]
dgbuilder/public/red/ui/sidebar.js [new file with mode: 0644]
dgbuilder/public/red/ui/state.js [new file with mode: 0644]
dgbuilder/public/red/ui/tab-config.js [new file with mode: 0644]
dgbuilder/public/red/ui/tab-info.js [new file with mode: 0644]
dgbuilder/public/red/ui/tabs.js [new file with mode: 0644]
dgbuilder/public/red/ui/touch/radialMenu.js [new file with mode: 0644]
dgbuilder/public/red/ui/view.js [new file with mode: 0644]
dgbuilder/public/red/ui/view.js.orig [new file with mode: 0644]
dgbuilder/public/red/validators.js [new file with mode: 0644]
dgbuilder/public/spin.svg [new file with mode: 0644]
dgbuilder/public/style.css [new file with mode: 0644]
dgbuilder/public/style.css.orig [new file with mode: 0644]
dgbuilder/public/util/css/validateNodeXml.css [new file with mode: 0644]
dgbuilder/public/util/js/dgeToXml.js [new file with mode: 0644]
dgbuilder/public/util/js/dgeToXml.js.imp [new file with mode: 0644]
dgbuilder/public/util/js/jsonTool.js [new file with mode: 0644]
dgbuilder/public/util/js/migrateFlow.js [new file with mode: 0644]
dgbuilder/public/util/js/sliValues.js [new file with mode: 0644]
dgbuilder/public/util/js/validateNodeXml.js [new file with mode: 0644]
dgbuilder/public/util/js/vkbeautify.0.99.00.beta.js [new file with mode: 0644]
dgbuilder/red.js [new file with mode: 0644]
dgbuilder/red/cli/lib/config.js [new file with mode: 0644]
dgbuilder/red/cli/lib/request.js [new file with mode: 0644]
dgbuilder/red/cli/nr-cli.js [new file with mode: 0755]
dgbuilder/red/comms.js [new file with mode: 0644]
dgbuilder/red/events.js [new file with mode: 0644]
dgbuilder/red/library.js [new file with mode: 0644]
dgbuilder/red/log.js [new file with mode: 0644]
dgbuilder/red/nodes/Node.js [new file with mode: 0644]
dgbuilder/red/nodes/credentials.js [new file with mode: 0644]
dgbuilder/red/nodes/flows.js [new file with mode: 0644]
dgbuilder/red/nodes/index.js [new file with mode: 0644]
dgbuilder/red/nodes/registry.js [new file with mode: 0644]
dgbuilder/red/red.js [new file with mode: 0644]
dgbuilder/red/server.js [new file with mode: 0644]
dgbuilder/red/settings.js [new file with mode: 0644]
dgbuilder/red/sla.js [new file with mode: 0644]
dgbuilder/red/storage/index.js [new file with mode: 0644]
dgbuilder/red/storage/localfilesystem.js [new file with mode: 0644]
dgbuilder/red/ui.js [new file with mode: 0644]
dgbuilder/red/util.js [new file with mode: 0644]
dgbuilder/releases/sdnc1.0/.config.json [new file with mode: 0644]
dgbuilder/releases/sdnc1.0/codecloud/.gitignore [new file with mode: 0644]
dgbuilder/releases/sdnc1.0/conf/svclogic.properties [new file with mode: 0644]
dgbuilder/releases/sdnc1.0/customSettings.js [new file with mode: 0644]
dgbuilder/releases/sdnc1.0/flows/shared/.gitignore [new file with mode: 0644]
dgbuilder/releases/sdnc1.0/flows/shared/backups/.gitignore [new file with mode: 0644]
dgbuilder/releases/sdnc1.0/html/.gitignore [new file with mode: 0644]
dgbuilder/releases/sdnc1.0/lib/flows/.gitignore [new file with mode: 0644]
dgbuilder/releases/sdnc1.0/logs/.gitignore [new file with mode: 0644]
dgbuilder/releases/sdnc1.0/logs/process_pid [new file with mode: 0644]
dgbuilder/releases/sdnc1.0/xml/.gitignore [new file with mode: 0644]
dgbuilder/show_status.sh [new file with mode: 0755]
dgbuilder/src/assembly/assemble_zip.xml [new file with mode: 0644]
dgbuilder/start.sh [new file with mode: 0755]
dgbuilder/stop.sh [new file with mode: 0755]
dgbuilder/svclogic/copy_xml.sh [new file with mode: 0755]
dgbuilder/svclogic/dg.xml [new file with mode: 0644]
dgbuilder/svclogic/lib/.gitignore [new file with mode: 0644]
dgbuilder/svclogic/load_dg [new file with mode: 0755]
dgbuilder/svclogic/svclogic.properties [new file with mode: 0644]
dgbuilder/svclogic/svclogic.sh [new file with mode: 0755]
dgbuilder/test/_spec.js [new file with mode: 0644]
dgbuilder/test/nodes/core/core/20-inject_spec.js [new file with mode: 0644]
dgbuilder/test/nodes/core/core/58-debug_spec.js [new file with mode: 0644]
dgbuilder/test/nodes/core/core/80-function_spec.js [new file with mode: 0644]
dgbuilder/test/nodes/core/core/80-template_spec.js [new file with mode: 0644]
dgbuilder/test/nodes/core/core/89-delay_spec.js [new file with mode: 0644]
dgbuilder/test/nodes/core/core/90-comment_spec.js [new file with mode: 0644]
dgbuilder/test/nodes/core/logic/10-switch_spec.js [new file with mode: 0644]
dgbuilder/test/nodes/core/logic/15-change_spec.js [new file with mode: 0644]
dgbuilder/test/nodes/core/logic/16-range_spec.js [new file with mode: 0644]
dgbuilder/test/nodes/core/parsers/70-HTML_spec.js [new file with mode: 0644]
dgbuilder/test/nodes/core/parsers/70-JSON_spec.js [new file with mode: 0644]
dgbuilder/test/nodes/core/parsers/70-XML_spec.js [new file with mode: 0644]
dgbuilder/test/nodes/core/storage/28-tail_spec.js [new file with mode: 0644]
dgbuilder/test/nodes/helper.js [new file with mode: 0644]
dgbuilder/test/red/cli/lib/config_spec.js [new file with mode: 0644]
dgbuilder/test/red/cli/lib/request_spec.js [new file with mode: 0644]
dgbuilder/test/red/cli/nr-cli_spec.js [new file with mode: 0644]
dgbuilder/test/red/comms_spec.js [new file with mode: 0644]
dgbuilder/test/red/events_spec.js [new file with mode: 0644]
dgbuilder/test/red/library_spec.js [new file with mode: 0644]
dgbuilder/test/red/log_spec.js [new file with mode: 0644]
dgbuilder/test/red/nodes/Node_spec.js [new file with mode: 0644]
dgbuilder/test/red/nodes/credentials_spec.js [new file with mode: 0644]
dgbuilder/test/red/nodes/flows_spec.js [new file with mode: 0644]
dgbuilder/test/red/nodes/index_spec.js [new file with mode: 0644]
dgbuilder/test/red/nodes/registry_spec.js [new file with mode: 0644]
dgbuilder/test/red/nodes/resources/DuplicateTestNode/TestNode1.html [new file with mode: 0644]
dgbuilder/test/red/nodes/resources/DuplicateTestNode/TestNode1.js [new file with mode: 0644]
dgbuilder/test/red/nodes/resources/MultipleNodes1/MultipleNodes1.html [new file with mode: 0644]
dgbuilder/test/red/nodes/resources/MultipleNodes1/MultipleNodes1.js [new file with mode: 0644]
dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/NestedNode.html [new file with mode: 0644]
dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/NestedNode.js [new file with mode: 0644]
dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/icons/file.txt [new file with mode: 0644]
dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.html [new file with mode: 0644]
dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/lib/ShouldNotLoad.js [new file with mode: 0644]
dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.html [new file with mode: 0644]
dgbuilder/test/red/nodes/resources/NestedDirectoryNode/NestedNode/test/ShouldNotLoad.js [new file with mode: 0644]
dgbuilder/test/red/nodes/resources/TestNode1/TestNode1.html [new file with mode: 0644]
dgbuilder/test/red/nodes/resources/TestNode1/TestNode1.js [new file with mode: 0644]
dgbuilder/test/red/nodes/resources/TestNode2/TestNode2.html [new file with mode: 0644]
dgbuilder/test/red/nodes/resources/TestNode2/TestNode2.js [new file with mode: 0644]
dgbuilder/test/red/nodes/resources/TestNode3/TestNode3.html [new file with mode: 0644]
dgbuilder/test/red/nodes/resources/TestNode3/TestNode3.js [new file with mode: 0644]
dgbuilder/test/red/red_spec.js [new file with mode: 0644]
dgbuilder/test/red/server_spec.js [new file with mode: 0644]
dgbuilder/test/red/settings_spec.js [new file with mode: 0644]
dgbuilder/test/red/storage/index_spec.js [new file with mode: 0644]
dgbuilder/test/red/storage/localfilesystem_spec.js [new file with mode: 0644]
dgbuilder/test/red/ui_spec.js [new file with mode: 0644]
dgbuilder/test/red/util_spec.js [new file with mode: 0644]
dgbuilder/test/resources/70-HTML-test-file.html [new file with mode: 0644]
dgbuilder/tools/FormatXml.java [new file with mode: 0644]
dgbuilder/tools/PrintYangToProp.java [new file with mode: 0644]
dgbuilder/tools/dot_to_json.js [new file with mode: 0644]
dgbuilder/tools/formatXml.py [new file with mode: 0644]
dgbuilder/tools/format_json.sh [new file with mode: 0755]
dgbuilder/tools/format_xml.sh [new file with mode: 0755]
dgbuilder/tools/generate_props_from_yang.sh [new file with mode: 0755]
dgbuilder/tools/getModuleName.sh [new file with mode: 0755]
dgbuilder/tools/getRpcsClassFromYang.sh [new file with mode: 0755]
dgbuilder/tools/jsonTool.js [new file with mode: 0644]
dgbuilder/tools/json_to_html [new file with mode: 0644]
dgbuilder/tools/json_to_html_table [new file with mode: 0755]
dgbuilder/tools/json_to_prop [new file with mode: 0755]
dgbuilder/tools/output_js/.gitignore [new file with mode: 0644]
dgbuilder/tools/pom.xml_base [new file with mode: 0644]
dgbuilder/tools/printYangProps.sh [new file with mode: 0755]
dgbuilder/tools/printYangToProp.jar [new file with mode: 0644]
dgbuilder/tools/rs [new file with mode: 0755]
dgbuilder/tools/setClasspath [new file with mode: 0755]
dgbuilder/yangFiles/.gitignore [new file with mode: 0644]
pom.xml

diff --git a/dgbuilder/.gitignore b/dgbuilder/.gitignore
new file mode 100644 (file)
index 0000000..1b8a6ba
--- /dev/null
@@ -0,0 +1,12 @@
+org.eclipse.core.resources.prefs
+.classpath\r
+.project\r
+.settings\r
+.idea\r
+.externalToolBuilders\r
+maven-eclipse.xml\r
+*.class\r
+target/\r
+MANIFEST.MF\r
+.DS_STORE\r
+.metadata\r
diff --git a/dgbuilder/CONTRIBUTING.md b/dgbuilder/CONTRIBUTING.md
new file mode 100644 (file)
index 0000000..52fe891
--- /dev/null
@@ -0,0 +1,82 @@
+# Contributing to Node-RED
+
+We welcome contributions, but request you follow these guidelines.
+
+## Raising issues
+
+Please raise any bug reports on the project's 
+[issue tracker](https://github.com/node-red/node-red/issues?state=open). Be sure to
+search the list to see if your issue has already been raised.
+
+A good bug report is one that make it easy for us to understand what you were
+trying to do and what went wrong.
+
+Provide as much context as possible so we can try to recreate the issue.
+If possible, include the relevant part of your flow. To do this, select the
+relevant nodes, press Ctrl-E and copy the flow data from the Export dialog.
+
+At a minimum, please include:
+
+ - Version of Node-RED - either release number if you downloaded a zip, or the first few lines of `git log` if you are cloning the repository directly.
+ - Version of node.js - what does `node -v` say?
+
+
+## New features
+
+For feature requests, please raise them on the [mailing list](https://groups.google.com/forum/#!forum/node-red).
+
+## Pull-Requests
+
+### Changes to existing code
+if you want to raise a pull-request with a new feature, or a refactoring
+of existing code, it may well get rejected if you haven't discussed it on 
+the [mailing list](https://groups.google.com/forum/#!forum/node-red) first.
+
+### New nodes
+
+The plugin nature of Node-RED means anyone can create a new node to extend
+its capabilities.
+
+We want to avoid duplication as that can lead to confusion. Many of our existing
+nodes offer a starting point of functionality. If they are missing features,
+we would rather extend them than add separate 'advanced' versions. But the key
+to that approach is getting the UX right to not lose the simplicity.
+
+To contribute a new node, please raise a pull-request against the 
+`node-red-nodes` repository.
+
+Eventually, the nodes will be npm-installable, but we're not there yet. We'll
+also have some sort of registry of nodes to help with discoverability.
+
+### Coding standards
+
+Please ensure you follow the coding standards used through-out the existing
+code base. Some basic rules include:
+
+ - all files must have the Apache license in the header.
+ - indent with 4-spaces, no tabs. No arguments.
+ - opening brace on same line as `if`/`for`/`function`/etc, closing brace on its
+   own line.
+
+### Contributor License Aggreement
+
+In order for us to accept pull-requests, the contributor must first complete
+a Contributor License Agreement (CLA). This clarifies the intellectual 
+property license granted with any contribution. It is for your protection as a 
+Contributor as well as the protection of IBM and its customers; it does not 
+change your rights to use your own Contributions for any other purpose.
+
+You can download the CLAs here:
+
+ - [individual](http://nodered.org/cla/node-red-cla-individual.pdf)
+ - [corporate](http://nodered.org/cla/node-red-cla-corporate.pdf)
+
+If you are an IBMer, please contact us directly as the contribution process is
+slightly different.
+
+
+
+
+
+
+
diff --git a/dgbuilder/Gruntfile.js b/dgbuilder/Gruntfile.js
new file mode 100644 (file)
index 0000000..62a553f
--- /dev/null
@@ -0,0 +1,91 @@
+/**
+ * Copyright 2013, 2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+module.exports = function(grunt) {
+    
+    // Project configuration.
+    grunt.initConfig({
+            pkg: grunt.file.readJSON('package.json'),
+            simplemocha: {
+                options: {
+                    globals: ['expect'],
+                    timeout: 3000,
+                    ignoreLeaks: false,
+                    ui: 'bdd',
+                    reporter: 'spec'
+                },
+                all: { src: ['test/**/*_spec.js'] },
+                core: { src: ["test/_spec.js","test/red/**/*_spec.js"]},
+                nodes: { src: ["test/nodes/**/*_spec.js"]}
+            },
+            jshint: {
+                options: {
+                    // http://www.jshint.com/docs/options/
+                    "asi": true,      // allow missing semicolons
+                    "curly": true,    // require braces
+                    "eqnull": true,   // ignore ==null
+                    "forin": true,    // require property filtering in "for in" loops
+                    "immed": true,    // require immediate functions to be wrapped in ( )
+                    "nonbsp": true,   // warn on unexpected whitespace breaking chars
+                    //"strict": true, // commented out for now as it causes 100s of warnings, but want to get there eventually
+                    "loopfunc": true, // allow functions to be defined in loops
+                    "sub": true       // don't warn that foo['bar'] should be written as foo.bar
+                },
+                all: [
+                    'Gruntfile.js',
+                    'red.js',
+                    'red/**/*.js',
+                    'nodes/**/*.js',
+                    'public/red/**/*.js'
+                ],
+                
+                core: {
+                    files: {
+                        src: [
+                            'Gruntfile.js',
+                            'red.js',
+                            'red/**/*.js'
+                        ]
+                    }
+                },
+                nodes: {
+                    files: {
+                        src: [ 'nodes/**/*.js' ]
+                    }
+                },
+                editor: {
+                    files: {
+                        src: [ 'public/red/**/*.js' ]
+                    }
+                },
+                tests: {
+                    files: {
+                        src: ['test/**/*.js']
+                    },
+                    options: {
+                        "expr": true
+                    }
+                }
+                
+            }
+    });
+    
+    grunt.loadNpmTasks('grunt-simple-mocha');
+    grunt.loadNpmTasks('grunt-contrib-jshint');
+    
+    grunt.registerTask('default', ['jshint:core','jshint:tests','jshint:editor','simplemocha:core','simplemocha:nodes']);
+    
+};
diff --git a/dgbuilder/INSTALL.md b/dgbuilder/INSTALL.md
new file mode 100644 (file)
index 0000000..90922e6
--- /dev/null
@@ -0,0 +1,57 @@
+Node-RED Install
+================
+
+## Install node.js
+
+You can get the latest version from <http://nodejs.org/download/>.
+
+Or, you may want to use a version from your operating system's package manager:
+ <https://github.com/joyent/node/wiki/Installing-Node.js-via-package-manager>
+
+## Get Node-RED
+
+Clone the repository from GitHub:
+
+    $ git clone git@github.com:node-red/node-red.git
+
+## Install the pre-requisite modules
+
+From the top-level directory of Node-RED, run:
+
+    $ npm install
+
+This will install the core pre-requisite modules.
+
+## Run Node-RED
+
+From the top-level directory, run:
+
+    $ node red.js
+
+You can then access Node-RED at <http://localhost:1880>.
+
+Online documentation is available at <http://nodered.org/docs>.
+
+## Installing individual node dependencies
+
+When Node-RED starts, it attempts to load the nodes from the `nodes/` directory.
+Each will have its own set of dependencies that will need to be installed before
+the node is available in the palette.
+
+To help identify the dependencies, Node-RED logs any modules it fails to find
+for a particular node. You don't have to install these unless you want or need
+that node to appear.
+
+Alternatively, a node's `.js` file can be examined to identify the modules it
+explicitly requires. For example, the Twitter node is defined in
+`nodes/social/27-twitter.js` and contains:
+
+       var RED = require("../../red/red");
+       var ntwitter = require('ntwitter');
+       var OAuth= require('oauth').OAuth;
+
+Of these, `ntwitter` and `oauth` are neither built-in modules nor ones provided
+by Node-RED itself. They can subsequently be installed by running:
+
+    $ npm install ntwitter oauth
+
diff --git a/dgbuilder/LICENSE b/dgbuilder/LICENSE
new file mode 100644 (file)
index 0000000..f433b1a
--- /dev/null
@@ -0,0 +1,177 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
diff --git a/dgbuilder/build_pom_for_yang_compile b/dgbuilder/build_pom_for_yang_compile
new file mode 100755 (executable)
index 0000000..c9aa38a
--- /dev/null
@@ -0,0 +1,86 @@
+echo "Version of dgbuilder pom is : $4"
+echo "Building pom.xml_base for compiling yang"
+
+model_pom_content=$(cat <<EOF
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+       <modelVersion>4.0.0</modelVersion>
+       <parent>
+               <groupId>org.onap.ccsdk.distribution</groupId>
+               <artifactId>distribution-root</artifactId>      
+                <version>${1}</version>
+       </parent>
+       <artifactId>yangApp-model</artifactId>
+       <packaging>bundle</packaging>
+        <version>1.0.0-SNAPSHOT</version>
+
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <extensions>true</extensions>
+                               <configuration>
+                                       <instructions>
+                                               <Import-Package>*</Import-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.opendaylight.yangtools</groupId>
+                               <artifactId>yang-maven-plugin</artifactId>
+                               <version>\${odl.yangtools.yang.maven.plugin.version}</version>
+                               <dependencies>
+                                       <dependency>
+                                               <groupId>org.opendaylight.mdsal</groupId>
+                                               <artifactId>maven-sal-api-gen-plugin</artifactId>
+                                               <version>\${odl.sal.api.gen.plugin.version}</version>
+                                               <type>jar</type>
+                                       </dependency>
+                               </dependencies>
+                               <executions>
+                                       <execution>
+                                               <goals>
+                                                       <goal>generate-sources</goal>
+                                               </goals>
+                                               <configuration>
+                                                       <yangFilesRootDir>\${yang.file.directory}</yangFilesRootDir>
+                                                       <codeGenerators>
+                                                               <generator>
+                                                                       <codeGeneratorClass>org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl</codeGeneratorClass>
+                                                                       <outputBaseDir>\${salGeneratorPath}</outputBaseDir>
+                                                               </generator>
+                                                       </codeGenerators>
+                                                       <inspectDependencies>true</inspectDependencies>
+                                               </configuration>
+                                       </execution>
+                               </executions>
+                       </plugin>
+               </plugins>
+       </build>
+       <dependencies>
+               <dependency>
+                       <groupId>org.opendaylight.mdsal</groupId>
+                       <artifactId>yang-binding</artifactId>
+                       <version>\${odl.mdsal.yang.binding.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.opendaylight.yangtools</groupId>
+                       <artifactId>yang-common</artifactId>
+                       <version>\${odl.yangtools.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.opendaylight.mdsal.model</groupId>
+                       <artifactId>ietf-inet-types</artifactId>
+                       <version>\${odl.ietf-inet-types.version}</version>
+               </dependency>
+               <dependency>
+                       <groupId>org.opendaylight.mdsal.model</groupId>
+                       <artifactId>ietf-yang-types</artifactId>
+                       <version>\${odl.ietf-yang-types.version}</version>
+               </dependency>
+       </dependencies>
+</project>
+EOF
+)
+echo "$model_pom_content" >tools/pom.xml_base
diff --git a/dgbuilder/core_nodes/analysis/72-sentiment.html b/dgbuilder/core_nodes/analysis/72-sentiment.html
new file mode 100644 (file)
index 0000000..c33b873
--- /dev/null
@@ -0,0 +1,49 @@
+<!--
+  Copyright 2013 IBM Corp.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<script type="text/x-red" data-template-name="sentiment">
+    <div class="form-row">
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+        <input type="text" id="node-input-name" placeholder="Name">
+    </div>
+</script>
+
+<script type="text/x-red" data-help-name="sentiment">
+    <p>Analyses the <b>msg.payload</b> and adds a <b>msg.sentiment</b> object that contains the resulting AFINN-111 sentiment score as <b>msg.sentiment.score</b>.</p>
+    <p>A score greater than zero is positive and less than zero is negative.</p>
+    <p>The score typically ranges from -5 to +5, but can go higher and lower.</p>
+    <p>An object of word score overrides can be supplied as <b>msg.overrides</b>.</p>
+    <p>See <a href="https://github.com/thisandagain/sentiment/blob/master/README.md" target="_new">the Sentiment docs here</a>.</p>
+</script>
+
+<script type="text/javascript">
+    RED.nodes.registerType('sentiment',{
+        category: 'analysis-function',
+        color:"#E6E0F8",
+        defaults: {
+            name: {value:""},
+        },
+        inputs:1,
+        outputs:1,
+        icon: "arrow-in.png",
+        label: function() {
+            return this.name||"sentiment";
+        },
+        labelStyle: function() {
+            return this.name?"node_label_italic":"";
+        }
+    });
+</script>
diff --git a/dgbuilder/core_nodes/analysis/72-sentiment.js b/dgbuilder/core_nodes/analysis/72-sentiment.js
new file mode 100644 (file)
index 0000000..747e079
--- /dev/null
@@ -0,0 +1,33 @@
+/**
+ * Copyright 2013 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+module.exports = function(RED) {
+    "use strict";
+    var sentiment = require('sentiment');
+
+    function SentimentNode(n) {
+        RED.nodes.createNode(this,n);
+        var node = this;
+
+        this.on("input", function(msg) {
+            sentiment(msg.payload, msg.overrides || null, function (err, result) {
+                msg.sentiment = result;
+                node.send(msg);
+            });
+        });
+    }
+    RED.nodes.registerType("sentiment",SentimentNode);
+}
diff --git a/dgbuilder/core_nodes/core/20-inject.html b/dgbuilder/core_nodes/core/20-inject.html
new file mode 100644 (file)
index 0000000..38aa6ef
--- /dev/null
@@ -0,0 +1,437 @@
+<!--\r
+  Copyright 2013 IBM Corp.\r
+\r
+  Licensed under the Apache License, Version 2.0 (the "License");\r
+  you may not use this file except in compliance with the License.\r
+  You may obtain a copy of the License at\r
+\r
+  http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+  Unless required by applicable law or agreed to in writing, software\r
+  distributed under the License is distributed on an "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+  See the License for the specific language governing permissions and\r
+  limitations under the License.\r
+-->\r
+\r
+<script type="text/x-red" data-template-name="inject">\r
+    <div class="form-row node-input-payload">\r
+        <label for="node-input-payloadType"><i class="fa fa-envelope"></i> Payload</label>\r
+        <select id="node-input-payloadType" style="width:125px !important">\r
+          <option value="date">timestamp</option>\r
+          <option value="none">blank</option>\r
+          <option value="string">string</option>\r
+        </select>\r
+    </div>\r
+\r
+    <div class="form-row" id="node-input-row-payload">\r
+        <label for="node-input-payload"></label>\r
+        <input type="text" id="node-input-payload" placeholder="payload">\r
+    </div>\r
+\r
+    <div class="form-row">\r
+        <label for="node-input-topic"><i class="fa fa-tasks"></i> Topic</label>\r
+        <input type="text" id="node-input-topic" placeholder="topic">\r
+    </div>\r
+\r
+    <div class="form-row">\r
+        <label for=""><i class="fa fa-repeat"></i> Repeat</label>\r
+        <select id="inject-time-type-select"  style="width: 288px"><option value="none">none</option><option value="interval">interval</option><option value="interval-time">interval between times</option><option value="time">at a specific time</option></select>\r
+        <input type="hidden" id="node-input-repeat" placeholder="payload">\r
+        <input type="hidden" id="node-input-crontab" placeholder="payload">\r
+    </div>\r
+\r
+    <div class="form-row inject-time-row hidden" id="inject-time-row-interval">\r
+        every <input id="inject-time-interval-count" class="inject-time-count" value="1"></input>\r
+              <select style="width: 100px" id="inject-time-interval-units"><option value="s">seconds</option><option value="m">minutes</option><option value="h">hours</option></select><br/>\r
+        <!-- on <select disabled id="inject-time-interval-days" class="inject-time-days"></select> -->\r
+    </div>\r
+\r
+    <div class="form-row inject-time-row hidden" id="inject-time-row-interval-time">\r
+        at every <select style="width: 90px" id="inject-time-interval-time-units" class="inject-time-int-count" value="1">\r
+            <option value="1">1</option>\r
+            <option value="2">2</option>\r
+            <option value="3">3</option>\r
+            <option value="4">4</option>\r
+            <option value="5">5</option>\r
+            <option value="6">6</option>\r
+            <option value="10">10</option>\r
+            <option value="12">12</option>\r
+            <option value="15">15</option>\r
+            <option value="20">20</option>\r
+            <option value="30">30</option>\r
+            <option value="0">60</option>\r
+        </select> minutes<br/>\r
+        between <select id="inject-time-interval-time-start" class="inject-time-times"></select>\r
+        and <select id="inject-time-interval-time-end" class="inject-time-times"></select><br/>\r
+        on <select id="inject-time-interval-time-days" class="inject-time-days"></select>\r
+    </div>\r
+\r
+    <div class="form-row inject-time-row hidden" id="inject-time-row-time">\r
+        at <input id="inject-time-time" value="12:00"></input><br/>\r
+        on <select id="inject-time-time-days" class="inject-time-days"></select>\r
+    </div>\r
+\r
+    <div class="form-row" id="node-once">\r
+        <label>&nbsp;</label>\r
+        <input type="checkbox" id="node-input-once" style="display: inline-block; width: auto; vertical-align: top;">\r
+        <label for="node-input-once" style="width: 70%;">Fire once at start ?</label>\r
+    </div>\r
+\r
+    <div class="form-row">\r
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>\r
+        <input type="text" id="node-input-name" placeholder="name">\r
+    </div>\r
+\r
+    <div class="form-tips"><b>Note:</b> "interval between times" and "at a specific time" will use cron.<br/>See info box for details.</div>\r
+</script>\r
+<style>\r
+    .inject-time-row {\r
+        padding-left: 110px;\r
+    }\r
+    .inject-time-row select {\r
+        margin: 3px 0;\r
+    }\r
+    .inject-time-days {\r
+        width: 262px;\r
+    }\r
+    .inject-time-times {\r
+        width: 90px;\r
+    }\r
+    .inject-time-row > .ui-spinner {\r
+        height: 28px;\r
+        margin: 3px 0;\r
+        border-color: rgb(204, 204, 204);\r
+    }\r
+    #inject-time-time {\r
+        margin-top: 3px;\r
+        width: 75px;\r
+    }\r
+    .inject-time-count {\r
+        width: 40px !important;\r
+    }\r
+</style>\r
+<script type="text/x-red" data-help-name="inject">\r
+    <p>Pressing the button on the left side of the node allows a message on a topic to be injected into the flow. This is mainly for test purposes.</p>\r
+    <p>If no payload is specified the payload is set to the current time in millisecs since 1970. This allows subsequent functions to perform time based actions.</p>\r
+    <p>The repeat function does what it says on the tin and continuously sends the payload every x seconds.</p>\r
+    <p>The Fire once at start option actually waits 50mS before firing to give other nodes a chance to instantiate properly.</p>\r
+    <p><b>Note: </b>"Interval between times" and "at a specific time" will use cron. This means that 20 minutes will be at the next hour, 20 minutes past and 40 minutes past - not in 20 minutes time.\r
+    If you want every 20 minutes from now - use the basic "interval" option.</p>\r
+</script>\r
+\r
+<script type="text/javascript">\r
+    RED.nodes.registerType('inject',{\r
+        category: 'input',\r
+        color:"#a6bbcf",\r
+        defaults: {\r
+            name: {value:""},\r
+            topic: {value:""},\r
+            payload: {value:""},\r
+            payloadType: {value:"date"},\r
+            repeat: {value:""},\r
+            crontab: {value:""},\r
+            once: {value:false}\r
+        },\r
+        inputs:0,\r
+        outputs:1,\r
+        icon: "inject.png",\r
+        label: function() {\r
+            if (this.payloadType === "string") {\r
+                return this.name||this.topic||this.payload||"inject";\r
+            }\r
+            else { return this.name||this.topic||"inject"; }\r
+        },\r
+        labelStyle: function() {\r
+            return this.name?"node_label_italic":"";\r
+        },\r
+        oneditprepare: function() {\r
+            $("#inject-time-type-select").change(function() {\r
+                $("#node-input-crontab").val('');\r
+                var id = $("#inject-time-type-select option:selected").val();\r
+                $(".inject-time-row").hide();\r
+                $("#inject-time-row-"+id).show();\r
+                if ((id == "none") || (id == "interval")) {\r
+                    $("#node-once").show();\r
+                }\r
+                else {\r
+                    $("#node-once").hide();\r
+                    $("#node-input-once").prop('checked', false);\r
+                }\r
+            });\r
+\r
+            var days = [\r
+                {v:"*",t:"every day"},\r
+                {v:"1-5",t:"Mondays to Fridays"},\r
+                {v:"0,6",t:"Saturdays and Sundays"},\r
+                {v:"1",t:"Mondays"},\r
+                {v:"2",t:"Tuesdays"},\r
+                {v:"3",t:"Wednesdays"},\r
+                {v:"4",t:"Thursdays"},\r
+                {v:"5",t:"Fridays"},\r
+                {v:"6",t:"Saturdays"},\r
+                {v:"0",t:"Sundays"}\r
+            ];\r
+\r
+            $(".inject-time-days").each(function() {\r
+                for (var d in days) {\r
+                    $(this).append($("<option></option>").val(days[d].v).text(days[d].t));\r
+                }\r
+            });\r
+\r
+            $(".inject-time-times").each(function() {\r
+                for (var i=0;i<24;i++) {\r
+                    var l = (i<10?"0":"")+i+":00";\r
+                    $(this).append($("<option></option>").val(i).text(l));\r
+                }\r
+            });\r
+\r
+            $(".inject-time-count").spinner({\r
+                //max:60,\r
+                min:1\r
+            });\r
+\r
+            $("#inject-time-interval-units").change(function() {\r
+                var units = $("#inject-time-interval-units option:selected").val();\r
+                //$("#inject-time-interval-days").prop("disabled",(units == "s")?"disabled":false);\r
+                //$(".inject-time-count").spinner("option","max",(units == "h")?24:60);\r
+            });\r
+\r
+            $.widget( "ui.injecttimespinner", $.ui.spinner, {\r
+                options: {\r
+                    // seconds\r
+                    step: 60 * 1000,\r
+                    // hours\r
+                    page: 60\r
+                },\r
+                _parse: function( value ) {\r
+                    if ( typeof value === "string" ) {\r
+                        // already a timestamp\r
+                        if ( Number( value ) == value ) {\r
+                            return Number( value );\r
+                        }\r
+                        var p = value.split(":");\r
+                        var offset = new Date().getTimezoneOffset();\r
+                        return (((Number(p[0])+1)*60)+Number(p[1])+offset)*60*1000;\r
+                    }\r
+                    return value;\r
+                },\r
+                _format: function( value ) {\r
+                    var d = new Date(value);\r
+                    var h = d.getHours();\r
+                    var m = d.getMinutes();\r
+                    return ((h < 10)?"0":"")+h+":"+((m < 10)?"0":"")+m;\r
+                }\r
+            });\r
+\r
+            $("#inject-time-time").injecttimespinner();\r
+\r
+            var repeattype = "none";\r
+            if (this.repeat != "" && this.repeat != 0) {\r
+                repeattype = "interval";\r
+                var r = "s";\r
+                var c = this.repeat;\r
+                if (this.repeat % 60 === 0) { r = "m"; c = c/60; }\r
+                if (this.repeat % 1440 === 0) { r = "h"; c = c/24; }\r
+                $("#inject-time-interval-count").val(c);\r
+                $("#inject-time-interval-units").val(r);\r
+                //$("#inject-time-interval-units option").filter(function() {return $(this).val() == "s";}).attr('selected',true);\r
+                $("#inject-time-interval-days").prop("disabled","disabled");\r
+            } else if (this.crontab) {\r
+                var cronparts = this.crontab.split(" ");\r
+                var days = cronparts[4];\r
+                if (!isNaN(cronparts[0]) && !isNaN(cronparts[1])) {\r
+                    repeattype = "time";\r
+                    // Fixed time\r
+                    var time = cronparts[1]+":"+cronparts[0];\r
+                    $("#inject-time-time").val(time);\r
+                    $("#inject-time-type-select option").filter(function() {return $(this).val() == "s";}).attr('selected',true);\r
+                    $("#inject-time-time-days option").filter(function() {return $(this).val() == days;}).attr('selected',true);\r
+                }\r
+                //else if (cronparts[0] == "0") {\r
+                //    // interval - hours\r
+                //    var hours = cronparts[1].slice(2);\r
+                //    repeattype = "interval";\r
+                //    $("#inject-time-interval-days").prop("disabled",false);\r
+                //    $("#inject-time-interval-days option").filter(function() {return $(this).val() == days;}).attr('selected',true);\r
+                //    $("#inject-time-interval-count").val(hours)\r
+                //    $("#inject-time-interval-units option").filter(function() {return $(this).val() == "h";}).attr('selected',true);\r
+                //} else if (cronparts[1] == "*") {\r
+                //    // interval - minutes\r
+                //    var minutes = cronparts[0].slice(2);\r
+                //    repeattype = "interval";\r
+                //    $("#inject-time-interval-days").prop("disabled",false);\r
+                //    $("#inject-time-interval-days option").filter(function() {return $(this).val() == days;}).attr('selected',true);\r
+                //    $("#inject-time-interval-count").val(minutes)\r
+                //    $("#inject-time-interval-units option").filter(function() {return $(this).val() == "m";}).attr('selected',true);\r
+                //}\r
+                else {\r
+                    repeattype = "interval-time";\r
+                    // interval - time period\r
+                    var minutes = cronparts[0].slice(2);\r
+                    if (minutes === "") { minutes = "0"; }\r
+                    $("#inject-time-interval-time-units").val(minutes);\r
+                    $("#inject-time-interval-time-days option").filter(function() {return $(this).val() == days;}).attr('selected',true);\r
+                    var time = cronparts[1];\r
+                    var timeparts = time.split(",");\r
+                    var start;\r
+                    var end;\r
+                    if (timeparts.length == 1) {\r
+                        // 0 or 0-10\r
+                        var hours = timeparts[0].split("-");\r
+                        if (hours.length == 1) {\r
+                            if (hours[0] === "") {\r
+                                start = "0";\r
+                                end = "0";\r
+                            }\r
+                            else {\r
+                                start = hours[0];\r
+                                end = Number(hours[0])+1;\r
+                            }\r
+                        } else {\r
+                            start = hours[0];\r
+                            end = (Number(hours[1])+1)%24;\r
+                        }\r
+                    } else {\r
+                        // 23,0 or 17-23,0-10 or 23,0-2 or 17-23,0\r
+                        var startparts = timeparts[0].split("-");\r
+                        start = startparts[0];\r
+\r
+                        var endparts = timeparts[1].split("-");\r
+                        if (endparts.length == 1) {\r
+                            end = Number(endparts[0])+1;\r
+                        } else {\r
+                            end = Number(endparts[1])+1;\r
+                        }\r
+                    }\r
+                    $("#inject-time-interval-time-start option").filter(function() {return $(this).val() == start;}).attr('selected',true);\r
+                    $("#inject-time-interval-time-end option").filter(function() {return $(this).val() == end;}).attr('selected',true);\r
+\r
+                }\r
+            } else {\r
+                $("#inject-time-type-select option").filter(function() {return $(this).val() == "none";}).attr('selected',true);\r
+            }\r
+\r
+            $(".inject-time-row").hide();\r
+            $("#inject-time-type-select option").filter(function() {return $(this).val() == repeattype;}).attr('selected',true);\r
+            $("#inject-time-row-"+repeattype).show();\r
+\r
+            if (this.payloadType == null) {\r
+                if (this.payload == "") {\r
+                    this.payloadType = "date";\r
+                } else {\r
+                    this.payloadType = "string";\r
+                }\r
+            }\r
+\r
+            $("#node-input-payloadType").change(function() {\r
+                var id = $("#node-input-payloadType option:selected").val();\r
+                if (id == "string") {\r
+                    $("#node-input-row-payload").show();\r
+                } else {\r
+                    $("#node-input-row-payload").hide();\r
+                }\r
+            });\r
+            $("#node-input-payloadType").val(this.payloadType);\r
+            $("#node-input-payloadType").change();\r
+            $("#inject-time-type-select").change();\r
+\r
+        },\r
+        oneditsave: function() {\r
+            var repeat = "";\r
+            var crontab = "";\r
+            var type = $("#inject-time-type-select option:selected").val();\r
+            if (type == "none") {\r
+                // nothing\r
+            } else if (type == "interval") {\r
+                var count = $("#inject-time-interval-count").val();\r
+                var units = $("#inject-time-interval-units option:selected").val();\r
+                var days = $("#inject-time-interval-days option:selected").val();\r
+                if (units == "s") {\r
+                    repeat = count;\r
+                } else {\r
+                    if (units == "m") {\r
+                        //crontab = "*/"+count+" * * * "+days;\r
+                        repeat = count * 60;\r
+                    } else if (units == "h") {\r
+                        //crontab = "0 */"+count+" * * "+days;\r
+                        repeat = count * 60 * 24;\r
+                    }\r
+                }\r
+            } else if (type == "interval-time") {\r
+                var count = $("#inject-time-interval-time-units").val();\r
+                var startTime = Number($("#inject-time-interval-time-start option:selected").val());\r
+                var endTime = Number($("#inject-time-interval-time-end option:selected").val());\r
+                var days = $("#inject-time-interval-time-days option:selected").val();\r
+                var timerange = "*";\r
+                if (startTime == endTime) {\r
+                    //TODO: invalid\r
+                    repeat = "";\r
+                    crontab = "";\r
+                } else if (endTime == 0) {\r
+                    timerange = startTime+"-23";\r
+                } else if (startTime+1 < endTime) {\r
+                    timerange = startTime+"-"+(endTime-1);\r
+                } else if (startTime+1 == endTime) {\r
+                    timerange = startTime;\r
+                } else {\r
+                    var startpart = "";\r
+                    var endpart = "";\r
+                    if (startTime == 23) {\r
+                        startpart = "23";\r
+                    } else {\r
+                        startpart = startTime+"-23";\r
+                    }\r
+                    if (endTime == 1) {\r
+                        endpart = "0";\r
+                    } else {\r
+                        endpart = "0-"+(endTime-1);\r
+                    }\r
+                    timerange = startpart+","+endpart;\r
+                }\r
+                repeat = "";\r
+                if (count === "0") {\r
+                    crontab = count+" "+timerange+" * * "+days;\r
+                }\r
+                else {\r
+                    crontab = "*/"+count+" "+timerange+" * * "+days;\r
+                }\r
+            } else if (type == "time") {\r
+                var time = $("#inject-time-time").val();\r
+                var days = $("#inject-time-time-days option:selected").val();\r
+                var parts = time.split(":");\r
+                repeat = "";\r
+                crontab = parts[1]+" "+parts[0]+" * * "+days;\r
+            }\r
+\r
+            $("#node-input-repeat").val(repeat);\r
+            $("#node-input-crontab").val(crontab);\r
+\r
+        },\r
+        button: {\r
+            onclick: function() {\r
+                var label = (this.name||this.payload).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");\r
+                if (this.payloadType === "date") { label = "timestamp"; }\r
+                if (this.payloadType === "none") { label = "blank"; }\r
+                d3.xhr("inject/"+this.id).post(function(err,resp) {\r
+                        if (err) {\r
+                            if (err.status == 404) {\r
+                                RED.notify("<strong>Error</strong>: inject node not deployed","error");\r
+                            } else if (err.status == 500) {\r
+                                RED.notify("<strong>Error</strong>: inject failed, see log for details.","error");\r
+                            } else if (err.status == 0) {\r
+                                RED.notify("<strong>Error</strong>: no response from server","error");\r
+                            } else {\r
+                                RED.notify("<strong>Error</strong>: unexpected error: ("+err.status+")"+err.response,"error");\r
+                            }\r
+                        } else if (resp.status == 200) {\r
+                            RED.notify("Successfully injected: "+label,"success");\r
+                        } else {\r
+                            RED.notify("<strong>Error</strong>: unexpected response: ("+resp.status+") "+resp.response,"error");\r
+                        }\r
+                });\r
+            }\r
+        }\r
+    });\r
+\r
+</script>\r
diff --git a/dgbuilder/core_nodes/core/20-inject.js b/dgbuilder/core_nodes/core/20-inject.js
new file mode 100644 (file)
index 0000000..dff0fb6
--- /dev/null
@@ -0,0 +1,97 @@
+/**
+ * Copyright 2013, 2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+module.exports = function(RED) {
+    var cron = require("cron");
+    
+    function InjectNode(n) {
+        RED.nodes.createNode(this,n);
+        this.topic = n.topic;
+        this.payload = n.payload;
+        this.payloadType = n.payloadType;
+        this.repeat = n.repeat;
+        this.crontab = n.crontab;
+        this.once = n.once;
+        var node = this;
+        this.interval_id = null;
+        this.cronjob = null;
+    
+        if (this.repeat && !isNaN(this.repeat) && this.repeat > 0) {
+            this.repeat = this.repeat * 1000;
+            this.log("repeat = "+this.repeat);
+            this.interval_id = setInterval( function() {
+                node.emit("input",{});
+            }, this.repeat );
+        } else if (this.crontab) {
+            if (cron) {
+                this.log("crontab = "+this.crontab);
+                this.cronjob = new cron.CronJob(this.crontab,
+                    function() {
+                        node.emit("input",{});
+                    },
+                    null,true);
+            } else {
+                this.error("'cron' module not found");
+            }
+        }
+    
+        if (this.once) {
+            setTimeout( function(){ node.emit("input",{}); }, 100);
+        }
+    
+        this.on("input",function(msg) {
+            var msg = {topic:this.topic};
+            if ( (this.payloadType == null && this.payload == "") || this.payloadType == "date") {
+                msg.payload = Date.now();
+            } else if (this.payloadType == null || this.payloadType == "string") {
+                msg.payload = this.payload;
+            } else {
+                msg.payload = "";
+            }
+            this.send(msg);
+            msg = null;
+        });
+    }
+    
+    RED.nodes.registerType("inject",InjectNode);
+    
+    InjectNode.prototype.close = function() {
+        if (this.interval_id != null) {
+            clearInterval(this.interval_id);
+            this.log("inject: repeat stopped");
+        } else if (this.cronjob != null) {
+            this.cronjob.stop();
+            this.log("inject: cronjob stopped");
+            delete this.cronjob;
+        }
+    }
+    
+    RED.httpAdmin.post("/inject/:id", function(req,res) {
+            var node = RED.nodes.getNode(req.params.id);
+            if (node != null) {
+                try {
+                    node.receive();
+                    res.send(200);
+                } catch(err) {
+                    res.send(500);
+                    node.error("Inject failed:"+err);
+                    console.log(err.stack);
+                }
+            } else {
+                res.send(404);
+            }
+    });
+}
diff --git a/dgbuilder/core_nodes/core/58-debug.html b/dgbuilder/core_nodes/core/58-debug.html
new file mode 100644 (file)
index 0000000..04aa507
--- /dev/null
@@ -0,0 +1,248 @@
+<!--
+  Copyright 2013 IBM Corp.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<script type="text/x-red" data-template-name="debug">
+    <div class="form-row">
+        <label for="node-input-complete"><i class="fa fa-list"></i> Output</label>
+        <select type="text" id="node-input-complete" style="display: inline-block; width: 250px; vertical-align: top;">
+            <option value="false">payload only</option>
+            <option value="true">complete msg object</option>
+        </select>
+    </div>
+    <div class="form-row">
+        <label for="node-input-console"><i class="fa fa-random"></i> to</label>
+        <select type="text" id="node-input-console" style="display: inline-block; width: 250px; vertical-align: top;">
+            <option value="false">debug tab</option>
+            <option value="true">debug tab and console</option>
+        </select>
+    </div>
+    <div class="form-row">
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+        <input type="text" id="node-input-name" placeholder="Name">
+    </div>
+</script>
+
+<script type="text/x-red" data-help-name="debug">
+    <p>The Debug node can be connected to the output of any node. It will display the timestamp, <b>msg.topic</b> and <b>msg.payload</b> fields of any messages it receives in the debug tab of the sidebar.
+    <br/>The sidebar can be accessed under the options drop-down in the top right corner.</p>
+    <p>The button to the right of the node will toggle it's output on and off so you can de-clutter the debug window.</p>
+    <p>If the payload is an object it will be stringified first for display and indicate that by saying "(Object) ".</p>
+    <p>If the payload is a buffer it will be stringified first for display and indicate that by saying "(Buffer) ".</p>
+    <p>Selecting any particular message will highlight (in red) the debug node that reported it. This is useful if you wire up multiple debug nodes.</p>
+    <p>Optionally can show the complete msg object - but the screen can get messy.</p>
+    <p>In addition any calls to node.warn or node.error will appear here.</p>
+</script>
+
+<script type="text/javascript">
+    RED.nodes.registerType('debug',{
+        category: 'output',
+        defaults: {
+            name: {value:""},
+            active: {value:true},
+            console: {value:"false"},
+            complete: {value:"false"}
+        },
+        label: function() {
+            return this.name||"debug";
+        },
+        labelStyle: function() {
+            return this.name?"node_label_italic":"";
+        },
+        color:"#87a980",
+        inputs:1,
+        outputs:0,
+        icon: "debug.png",
+        align: "right",
+        button: {
+            toggle: "active",
+            onclick: function() {
+                var label = this.name||"debug";
+                d3.xhr("debug/"+this.id+"/"+(this.active?"enable":"disable")).post(function(err,resp) {
+                    if (err) {
+                        if (err.status == 404) {
+                            RED.notify("<strong>Error</strong>: debug node not deployed","error");
+                        } else if (err.status == 0) {
+                            RED.notify("<strong>Error</strong>: no response from server","error");
+                        } else {
+                            RED.notify("<strong>Error</strong>: unexpected error: ("+err.status+")"+err.response,"error");
+                        }
+                    } else if (resp.status == 200) {
+                        RED.notify("Successfully activated: "+label,"success");
+                    } else if (resp.status == 201) {
+                        RED.notify("Successfully deactivated: "+label,"success");
+                    } else {
+                        RED.notify("<strong>Error</strong>: unexpected response: ("+resp.status+") "+resp.response,"error");
+                    }
+                });
+            }
+        },
+        onpaletteadd: function() {
+            var content = document.createElement("div");
+            content.id = "tab-debug";
+    
+            var toolbar = document.createElement("div");
+            toolbar.id = "debug-toolbar";
+            content.appendChild(toolbar);
+    
+            toolbar.innerHTML = '<div class="btn-group pull-right"><a id="debug-tab-clear" title="clear log" class="btn btn-mini" href="#"><i class="fa fa-trash"></i></a></div> ';
+    
+            var messages = document.createElement("div");
+            messages.id = "debug-content";
+            content.appendChild(messages);
+    
+            RED.sidebar.addTab("debug",content);
+    
+            function getTimestamp() {
+                var d = new Date();
+                return d.toLocaleString();
+            }
+    
+            var sbc = document.getElementById("debug-content");
+    
+            var messageCount = 0;
+            var that = this;
+            RED._debug = function(msg) {
+                that.handleDebugMessage("",{
+                    name:"debug",
+                    msg:msg
+                });
+            }
+    
+            this.handleDebugMessage = function(t,o) {
+                var msg = document.createElement("div");
+                msg.onmouseover = function() {
+                    msg.style.borderRightColor = "#999";
+                    var n = RED.nodes.node(o.id);
+                    if (n) {
+                        n.highlighted = true;
+                        n.dirty = true;
+                    }
+                    RED.view.redraw();
+                };
+                msg.onmouseout = function() {
+                    msg.style.borderRightColor = "";
+                    var n = RED.nodes.node(o.id);
+                    if (n) {
+                        n.highlighted = false;
+                        n.dirty = true;
+                    }
+                    RED.view.redraw();
+                };
+                msg.onclick = function() {
+                    var node = RED.nodes.node(o.id);
+                    if (node) {
+                        RED.view.showWorkspace(node.z);
+                    }
+    
+                };
+                var name = (o.name?o.name:o.id).toString().replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");
+                var topic = (o.topic||"").toString().replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");
+                var payload = (o.msg||"").toString().replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;");
+                msg.className = 'debug-message'+(o.level?(' debug-message-level-'+o.level):'');
+                msg.innerHTML = '<span class="debug-message-date">'+getTimestamp()+'</span>'+
+                                '<span class="debug-message-name">['+name+']</span>'+
+                                (o.topic?'<span class="debug-message-topic">'+topic+'</span>':'')+
+                                '<span class="debug-message-payload">'+payload+'</span>';
+                var atBottom = (sbc.scrollHeight-messages.offsetHeight-sbc.scrollTop) < 5;
+                messageCount++;
+                $(messages).append(msg);
+    
+                if (messageCount > 200) {
+                    $("#debug-content .debug-message:first").remove();
+                    messageCount--;
+                }
+                if (atBottom) {
+                    $(sbc).scrollTop(sbc.scrollHeight);
+                }
+            };
+            RED.comms.subscribe("debug",this.handleDebugMessage);
+    
+            $("#debug-tab-clear").click(function() {
+                $(".debug-message").remove();
+                messageCount = 0;
+                RED.nodes.eachNode(function(node) {
+                    node.highlighted = false;
+                    node.dirty = true;
+                });
+                RED.view.redraw();
+            });
+        },
+        onpaletteremove: function() {
+            RED.comms.unsubscribe("debug",this.handleDebugMessage);
+            RED.sidebar.removeTab("debug");
+            delete RED._debug;
+        }
+    });
+</script>
+
+<style>
+    #debug-content {
+        position: absolute;
+        top: 30px;
+        bottom: 0px;
+        left:0px;
+        right: 0px;
+        overflow-y: scroll;
+    }
+    #debug-toolbar {
+        padding: 3px 10px;
+        height: 24px;
+        background: #f3f3f3;
+    }
+    .debug-message {
+        cursor: pointer;
+        border-bottom: 1px solid #eee;
+        border-left: 8px solid #eee;
+        border-right: 8px solid #eee;
+        padding: 2px;
+    }
+    .debug-message-date {
+        background: #fff;
+        font-size: 9px;
+        color: #aaa;
+        padding: 1px 5px 1px 1px;
+    }
+    .debug-message-topic {
+        display: block;
+        background: #fff;
+        padding: 1px 5px;
+        font-size: 9px;
+        color: #a66;
+    }
+    .debug-message-name {
+        background: #fff;
+        padding: 1px 5px;
+        font-size: 9px;
+        color: #aac;
+    }
+    .debug-message-payload {
+        display: block;
+        padding: 2px;
+        background: #fff;
+    }
+    .debug-message-level-log {
+        border-left-color: #eee;
+        border-right-color: #eee;
+    }
+    .debug-message-level-warn {
+        border-left-color: #ffdf9d;
+        border-right-color: #ffdf9d;
+    }
+    .debug-message-level-error {
+        border-left-color: #f99;
+        border-right-color: #f99;
+    }
+</style>
diff --git a/dgbuilder/core_nodes/core/58-debug.js b/dgbuilder/core_nodes/core/58-debug.js
new file mode 100644 (file)
index 0000000..7436bf2
--- /dev/null
@@ -0,0 +1,114 @@
+/**
+ * Copyright 2013 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+module.exports = function(RED) {
+    var util = require("util");
+    var events = require("events");
+    var debuglength = RED.settings.debugMaxLength||1000;
+    var useColors = false;
+    // util.inspect.styles.boolean = "red";
+    
+    function DebugNode(n) {
+        RED.nodes.createNode(this,n);
+        this.name = n.name;
+        this.complete = n.complete;
+        this.console = n.console;
+        this.active = (n.active == null)||n.active;
+        var node = this;
+    
+        this.on("input",function(msg) {
+            if (this.complete == "true") { // debug complete msg object
+                if (this.console == "true") {
+                    node.log("\n"+util.inspect(msg, {colors:useColors, depth:10}));
+                }
+                if (this.active) {
+                    sendDebug({id:this.id,name:this.name,topic:msg.topic,msg:msg,_path:msg._path});
+                }
+            } else { // debug just the msg.payload
+                if (this.console == "true") {
+                    if (typeof msg.payload === "string") {
+                        node.log((msg.payload.indexOf("\n") != -1 ? "\n" : "") + msg.payload);
+                    }
+                    else if (typeof msg.payload === "object") { node.log("\n"+util.inspect(msg.payload, {colors:useColors, depth:10})); }
+                    else { node.log(util.inspect(msg.payload, {colors:useColors})); }
+                }
+                if (this.active) {
+                    sendDebug({id:this.id,name:this.name,topic:msg.topic,msg:msg.payload,_path:msg._path});
+                }
+            }
+        });
+    }
+   
+    RED.nodes.registerType("debug",DebugNode);
+    
+    function sendDebug(msg) {
+        if (msg.msg instanceof Error) {
+            msg.msg = msg.msg.toString();
+        } else if (msg.msg instanceof Buffer) {
+            msg.msg = "(Buffer) "+msg.msg.toString('hex');
+        } else if (typeof msg.msg === 'object') {
+            var seen = [];
+            var ty = "(Object) ";
+            if (util.isArray(msg.msg)) { ty = "(Array) "; }
+            msg.msg = ty + JSON.stringify(msg.msg, function(key, value) {
+                if (typeof value === 'object' && value !== null) {
+                    if (seen.indexOf(value) !== -1) { return "[circular]"; }
+                    seen.push(value);
+                }
+                return value;
+            }," ");
+            seen = null;
+        } else if (typeof msg.msg === "boolean") {
+            msg.msg = "(boolean) "+msg.msg.toString();
+        } else if (msg.msg === 0) {
+            msg.msg = "0";
+        } else if (msg.msg == null) {
+            msg.msg = "(undefined)";
+        }
+    
+        if (msg.msg.length > debuglength) {
+            msg.msg = msg.msg.substr(0,debuglength) +" ....";
+        }
+        
+        RED.comms.publish("debug",msg);
+    }
+    
+    DebugNode.logHandler = new events.EventEmitter();
+    DebugNode.logHandler.on("log",function(msg) {
+        if (msg.level == "warn" || msg.level == "error") {
+            sendDebug(msg);
+        }
+    });
+    RED.log.addHandler(DebugNode.logHandler);
+    
+    RED.httpAdmin.post("/debug/:id/:state", function(req,res) {
+        var node = RED.nodes.getNode(req.params.id);
+        var state = req.params.state;
+        if (node != null) {
+            if (state === "enable") {
+                node.active = true;
+                res.send(200);
+            } else if (state === "disable") {
+                node.active = false;
+                res.send(201);
+            } else {
+                res.send(404);
+            }
+        } else {
+            res.send(404);
+        }
+    });
+}
diff --git a/dgbuilder/core_nodes/core/75-exec.html b/dgbuilder/core_nodes/core/75-exec.html
new file mode 100644 (file)
index 0000000..567a34c
--- /dev/null
@@ -0,0 +1,68 @@
+<!--
+  Copyright 2013 IBM Corp.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<script type="text/x-red" data-template-name="exec">
+    <div class="form-row">
+        <label for="node-input-command"><i class="fa fa-file"></i> Command</label>
+        <input type="text" id="node-input-command" placeholder="command">
+    </div>
+    <div class="form-row">
+        <label for="node-input-append"><i class="fa fa-list"></i> Append</label>
+        <input type="text" id="node-input-append" placeholder="extra input">
+    </div>
+    <div class="form-row">
+        <label>&nbsp;</label>
+        <input type="checkbox" id="node-input-useSpawn" placeholder="spawn" style="display: inline-block; width: auto; vertical-align: top;">
+        <label for="node-input-useSpawn" style="width: 70%;">Use spawn() instead of exec() ?</label>
+    </div>
+    <div class="form-row">
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+        <input type="text" id="node-input-name" placeholder="Name">
+    </div>
+    <div class="form-tips">Tip: <i>spawn</i> expects only one command word - and appended args to be comma separated.</div>
+</script>
+
+<script type="text/x-red" data-help-name="exec">
+    <p>Calls out to a system command.<br/></p>
+    <p>Provides 3 outputs... stdout, stderr, and return code.</p>
+    <p>By default uses exec() which calls the command, blocks while waiting for completion, and then returns the complete result in one go, along with any errors.</p>
+    <p>Optionally can use spawn() instead, which returns output from stdout and stderr as the command runs (ie one line at a time). On completion it then returns a return code (on the 3rd output).</p>
+    <p>Spawn only expect one command word, with all extra parameters to be comma separated and passed as the append.</p>
+    <p>The optional append gets added to the command after the <b>msg.payload</b> - so you can do things like pipe the result to another command.</p>
+</script>
+
+<script type="text/javascript">
+    RED.nodes.registerType('exec',{
+        category: 'advanced-function',
+        color:"darksalmon",
+        defaults: {
+            command: {value:"",required:true},
+            append: {value:""},
+            useSpawn: {value:""},
+            name: {value:""}
+        },
+        inputs:1,
+        outputs:3,
+        icon: "arrow-in.png",
+        align: "right",
+        label: function() {
+            return this.name||this.command;
+        },
+        labelStyle: function() {
+            return this.name?"node_label_italic":"";
+        }
+    });
+</script>
diff --git a/dgbuilder/core_nodes/core/75-exec.js b/dgbuilder/core_nodes/core/75-exec.js
new file mode 100644 (file)
index 0000000..a07b140
--- /dev/null
@@ -0,0 +1,84 @@
+/**
+ * Copyright 2013 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+module.exports = function(RED) {
+    "use strict";
+    var spawn = require('child_process').spawn;
+    var exec = require('child_process').exec;
+
+    function ExecNode(n) {
+        RED.nodes.createNode(this,n);
+        this.cmd = n.command.trim();
+        this.append = n.append.trim() || "";
+        this.useSpawn = n.useSpawn;
+
+        var node = this;
+        this.on("input", function(msg) {
+            node.status({fill:"blue",shape:"dot"});
+            if (this.useSpawn === true) {
+                // make the extra args into an array
+                // then prepend with the msg.payload
+                if (typeof(msg.payload !== "string")) { msg.payload = msg.payload.toString(); }
+                var arg = [];
+                if (node.append.length > 0) { arg = node.append.split(","); }
+                if (msg.payload.trim() !== "") { arg.unshift(msg.payload); }
+                node.log(node.cmd+" ["+arg+"]");
+                if (node.cmd.indexOf(" ") == -1) {
+                    var ex = spawn(node.cmd,arg);
+                    ex.stdout.on('data', function (data) {
+                        //console.log('[exec] stdout: ' + data);
+                        msg.payload = data.toString();
+                        node.send([msg,null,null]);
+                    });
+                    ex.stderr.on('data', function (data) {
+                        //console.log('[exec] stderr: ' + data);
+                        msg.payload = data.toString();
+                        node.send([null,msg,null]);
+                    });
+                    ex.on('close', function (code) {
+                        //console.log('[exec] result: ' + code);
+                        msg.payload = code;
+                        node.status({});
+                        node.send([null,null,msg]);
+                    });
+                    ex.on('error', function (code) {
+                        node.warn(code);
+                    });
+                }
+                else { node.error("Spawn command must be just the command - no spaces or extra parameters"); }
+            }
+            else {
+                var cl = node.cmd+" "+msg.payload+" "+node.append;
+                node.log(cl);
+                var child = exec(cl, function (error, stdout, stderr) {
+                    msg.payload = stdout;
+                    var msg2 = {payload:stderr};
+                    var msg3 = null;
+                    //console.log('[exec] stdout: ' + stdout);
+                    //console.log('[exec] stderr: ' + stderr);
+                    if (error !== null) {
+                        msg3 = {payload:error};
+                        //console.log('[exec] error: ' + error);
+                    }
+                    node.status({});
+                    node.send([msg,msg2,msg3]);
+                });
+            }
+        });
+    }
+
+    RED.nodes.registerType("exec",ExecNode);
+}
diff --git a/dgbuilder/core_nodes/core/80-function.html b/dgbuilder/core_nodes/core/80-function.html
new file mode 100644 (file)
index 0000000..442c391
--- /dev/null
@@ -0,0 +1,110 @@
+<!--
+  Copyright 2013 IBM Corp.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<script type="text/x-red" data-template-name="function">
+    <div class="form-row">
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+        <input type="text" id="node-input-name" placeholder="Name">
+    </div>
+    <div class="form-row">
+        <label for="node-input-func"><i class="fa fa-wrench"></i> Function</label>
+        <input type="hidden" id="node-input-func" autofocus="autofocus">
+        <div style="height: 250px;" class="node-text-editor" id="node-input-func-editor" ></div>
+    </div>
+    <div class="form-row">
+        <label for="node-input-outputs"><i class="fa fa-random"></i> Outputs</label>
+        <input id="node-input-outputs" style="width: 60px; height: 1.7em;" value="1">
+    </div>
+    <div class="form-tips">See the Info tab for help writing functions.</div>
+</script>
+
+<script type="text/x-red" data-help-name="function">
+       <p>A function block where you can write code to do more interesting things.</p>
+       <p>The message is passed in as a JavaScript object called <code>msg</code>.</p>
+       <p>By convention it will have a <code>msg.payload</code> property containing
+          the body of the message.</p>
+       <p>The function should return the messages it wants to pass on to the next nodes
+       in the flow. It can return:</p>
+       <ul>
+         <li>a single message object - passed to nodes connected to the first output</li>
+         <li>an array of message objects - passed to nodes connected to the corresponding outputs</li>
+    </ul>
+    <p>If any element of the array is itself an array of messages, multiple
+             messages are sent to the corresponding output.</p>
+       <p>If null is returned, either by itself or as an element of the array, no
+             message is passed on.</p>
+       <p>See the <a target="_new" href="http://nodered.org/docs/writing-functions.html">online documentation</a> for more help.</p>
+             
+</script>
+
+<script type="text/javascript">
+    RED.nodes.registerType('function',{
+        color:"#fdd0a2",
+        category: 'function',
+        defaults: {
+            name: {value:""},
+            func: {value:"\nreturn msg;"},
+            outputs: {value:1}
+        },
+        inputs:1,
+        outputs:1,
+        icon: "function.png",
+        label: function() {
+            return this.name;
+        },
+        oneditprepare: function() {
+            $( "#node-input-outputs" ).spinner({
+                min:1
+            });
+
+            function functionDialogResize(ev,ui) {
+                $("#node-input-func-editor").css("height",(ui.size.height-275)+"px");
+            };
+
+            $( "#dialog" ).on("dialogresize", functionDialogResize);
+            $( "#dialog" ).one("dialogopen", function(ev) {
+                var size = $( "#dialog" ).dialog('option','sizeCache-function');
+                if (size) {
+                    functionDialogResize(null,{size:size});
+                }
+            });
+            $( "#dialog" ).one("dialogclose", function(ev,ui) {
+                var height = $( "#dialog" ).dialog('option','height');
+                $( "#dialog" ).off("dialogresize",functionDialogResize);
+            });
+            var that = this;
+            require(["orion/editor/edit"], function(edit) {
+                that.editor = edit({
+                    parent:document.getElementById('node-input-func-editor'),
+                    lang:"js",
+                    contents: $("#node-input-func").val()
+                });
+                RED.library.create({
+                    url:"functions", // where to get the data from
+                    type:"function", // the type of object the library is for
+                    editor:that.editor, // the field name the main text body goes to
+                    fields:['name','outputs']
+                });
+                $("#node-input-name").focus();
+
+            });
+        },
+        oneditsave: function() {
+            $("#node-input-func").val(this.editor.getText())
+            delete this.editor;
+        }
+    });
+</script>
diff --git a/dgbuilder/core_nodes/core/80-function.js b/dgbuilder/core_nodes/core/80-function.js
new file mode 100644 (file)
index 0000000..e1413a7
--- /dev/null
@@ -0,0 +1,79 @@
+/**
+ * Copyright 2013 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+module.exports = function(RED) {
+    "use strict";
+    var util = require("util");
+    var vm = require("vm");
+
+    function FunctionNode(n) {
+        RED.nodes.createNode(this,n);
+        this.name = n.name;
+        this.func = n.func;
+        var functionText = "var results = null; results = (function(msg){"+this.func+"\n})(msg);";
+        this.topic = n.topic;
+        var sandbox = {
+            console:console,
+            util:util,
+            Buffer:Buffer,
+            context: {
+                global:RED.settings.functionGlobalContext || {}
+            }
+        };
+        var context = vm.createContext(sandbox);
+        try {
+            this.script = vm.createScript(functionText);
+            this.on("input", function(msg) {
+                try {
+                    var start = process.hrtime();
+                    context.msg = msg;
+                    this.script.runInContext(context);
+                    var results = context.results;
+                    if (results == null) {
+                        results = [];
+                    } else if (results.length == null) {
+                        results = [results];
+                    }
+                    if (msg._topic) {
+                        for (var m in results) {
+                            if (results[m]) {
+                                if (util.isArray(results[m])) {
+                                    for (var n=0; n < results[m].length; n++) {
+                                        results[m][n]._topic = msg._topic;
+                                    }
+                                } else {
+                                    results[m]._topic = msg._topic;
+                                }
+                            }
+                        }
+                    }
+                    this.send(results);
+                    var duration = process.hrtime(start);
+                    if (process.env.NODE_RED_FUNCTION_TIME) {
+                        this.status({fill:"yellow",shape:"dot",text:""+Math.floor((duration[0]* 1e9 +  duration[1])/10000)/100});
+                    }
+                } catch(err) {
+                    this.error(err.toString());
+                }
+            });
+        } catch(err) {
+            this.error(err);
+        }
+    }
+
+    RED.nodes.registerType("function",FunctionNode);
+    RED.library.register("functions");
+}
diff --git a/dgbuilder/core_nodes/core/80-template.html b/dgbuilder/core_nodes/core/80-template.html
new file mode 100644 (file)
index 0000000..dc014d3
--- /dev/null
@@ -0,0 +1,102 @@
+<!--
+  Copyright 2013,2014 IBM Corp.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<script type="text/x-red" data-template-name="template">
+    <div class="form-row">
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+        <input type="text" id="node-input-name" placeholder="Name">
+    </div>
+    <div class="form-row">
+        <label for="node-input-template"><i class="fa fa-file-code-o"></i> Template</label>
+        <input type="hidden" id="node-input-template" autofocus="autofocus">
+        <div style="height: 250px;" class="node-text-editor" id="node-input-template-editor" ></div>
+    </div>
+    <div class="form-row">
+        <label for="node-input-field"><i class="fa fa-edit"></i> Property</label>
+        msg.<input type="text" id="node-input-field" placeholder="payload" style="width: 64%;">
+    </div>
+</script>
+
+<script type="text/x-red" data-help-name="template">
+    <p>Creates a new message based on the provided template.</p>
+    <p>This uses the <i><a href="http://mustache.github.io/mustache.5.html" target="_new">mustache</a></i> format.</p>
+    <p>For example, when a template of:
+    <pre>Hello {{name}}. Today is {{date}}</pre>
+    <p>receives a message containing:
+    <pre>{
+  name: "Fred",
+  date: "Monday"
+  payload: ...
+}</pre>
+    <p>The resulting payload will be:
+    <pre>Hello Fred. Today is Monday</pre>
+</script>
+
+<script type="text/javascript">
+    RED.nodes.registerType('template',{
+        color:"rgb(243, 181, 103)",
+        category: 'function',
+        defaults: {
+            name: {value:""},
+            field: {value:"payload"},
+            template: {value:"This is the payload: {{payload}}!"},
+        },
+        inputs:1,
+        outputs:1,
+        icon: "template.png",
+        label: function() {
+            return this.name;
+        },
+        oneditprepare: function() {
+
+            function templateDialogResize(ev,ui) {
+                $("#node-input-template-editor").css("height",(ui.size.height-200)+"px");
+            };
+
+            $( "#dialog" ).on("dialogresize", templateDialogResize);
+            $( "#dialog" ).one("dialogopen", function(ev) {
+                var size = $( "#dialog" ).dialog('option','sizeCache-template');
+                if (size) {
+                    templateDialogResize(null,{size:size});
+                }
+            });
+            $( "#dialog" ).one("dialogclose", function(ev,ui) {
+                var height = $( "#dialog" ).dialog('option','height');
+                $( "#dialog" ).off("dialogresize",templateDialogResize);
+            });
+
+            var that = this;
+            require(["orion/editor/edit"], function(edit) {
+                that.editor = edit({
+                    parent:document.getElementById('node-input-template-editor'),
+                    lang:"html",
+                    contents: $("#node-input-template").val()
+                });
+                RED.library.create({
+                    url:"templates", // where to get the data from
+                    type:"template", // the type of object the library is for
+                    editor:that.editor, // the field name the main text body goes to
+                    fields:['name','field']
+                });
+                $("#node-input-name").focus();
+            });
+        },
+        oneditsave: function() {
+            $("#node-input-template").val(this.editor.getText())
+            delete this.editor;
+        }
+    });
+</script>
diff --git a/dgbuilder/core_nodes/core/80-template.js b/dgbuilder/core_nodes/core/80-template.js
new file mode 100644 (file)
index 0000000..7c84142
--- /dev/null
@@ -0,0 +1,61 @@
+/**
+ * Copyright 2013 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+module.exports = function(RED) {
+    "use strict";
+    var mustache = require("mustache");
+
+    function TemplateNode(n) {
+        RED.nodes.createNode(this,n);
+        this.name = n.name;
+        this.field = n.field || "payload";
+        this.template = n.template;
+        var node = this;
+
+        var b = node.field.split(".");
+        var i = 0;
+        var m = null;
+        var rec = function(obj) {
+            i += 1;
+            if ((i < b.length) && (typeof obj[b[i-1]] === "object")) {
+                rec(obj[b[i-1]]); // not there yet - carry on digging
+            }
+            else {
+                 if (i === b.length) { // we've finished so assign the value
+                     obj[b[i-1]] = mustache.render(node.template,m);
+                     node.send(m);
+                 }
+                 else {
+                     obj[b[i-1]] = {}; // needs to be a new object so create it
+                     rec(obj[b[i-1]]); // and carry on digging
+                 }
+            }
+        }
+
+        node.on("input", function(msg) {
+            try {
+                m = msg;
+                i = 0;
+                rec(msg);
+            } catch(err) {
+                node.error(err.message);
+            }
+        });
+    }
+
+    RED.nodes.registerType("template",TemplateNode);
+    RED.library.register("templates");
+}
diff --git a/dgbuilder/core_nodes/core/89-delay.html b/dgbuilder/core_nodes/core/89-delay.html
new file mode 100644 (file)
index 0000000..dcb0a5b
--- /dev/null
@@ -0,0 +1,167 @@
+<!--
+  Copyright 2013 IBM Corp.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<!-- First, the content of the edit dialog is defined.                       -->
+<script type="text/x-red" data-template-name="delay">
+
+    <div class="form-row">
+        <label for="node-input-pauseType"><i class="fa fa-tasks"></i> Action</label>
+        <select id="node-input-pauseType" style="width:270px !important">
+          <option value="delay">Delay message</option>
+          <option value="rate">Limit rate to</option>
+          <option value="random">Random delay</option>
+        </select>
+    </div>
+    <div id="delay-details" class="form-row">
+        <label for="node-input-timeout"><i class="fa fa-clock-o"></i> For</label>
+        <input type="text" id="node-input-timeout" placeholder="Time" style="direction:rtl; width:50px !important">
+        <select id="node-input-timeoutUnits" style="width:200px !important">
+          <option value="milliseconds">Milliseconds</option>
+          <option value="seconds">Seconds</option>
+          <option value="minutes">Minutes</option>
+          <option value="hours">Hours</option>
+          <option value="days">Days</option>
+        </select>
+    </div>
+
+    <div id="rate-details" class="form-row">
+        <label for="node-input-rate"><i class="fa fa-clock-o"></i> To</label>
+        <input type="text" id="node-input-rate" placeholder="1" style="direction:rtl; width:30px !important">
+        <label for="node-input-reateUnits">msg(s) per</label>
+        <select id="node-input-rateUnits" style="width:140px !important">
+          <option value="second">Second</option>
+          <option value="minute">Minute</option>
+          <option value="hour">Hour</option>
+          <option value="day">Day</option>
+        </select>
+        <br/>
+        <input style="margin: 20px 0 20px 100px; width: 30px;" type="checkbox" id="node-input-drop"><label style="width: 250px;" for="node-input-drop">drop intermediate messages</label>
+    </div>
+
+    <div id="random-details" class="form-row">
+        <label for="node-input-randomFirst"><i class="fa fa-clock-o"></i> Between</label>
+        <input type="text" id="node-input-randomFirst" placeholder="" style="directon:rtl; width:30px !important">
+        <label for="node-input-randomLast" style="width:20px"> &amp; </label>
+        <input type="text" id="node-input-randomLast" placeholder="" style="directon:rtl; width:30px !important">
+        <select id="node-input-randomUnits" style="width:140px !important">
+          <option value="milliseconds">Milliseconds</option>
+          <option value="seconds">Seconds</option>
+          <option value="minutes">Minutes</option>
+          <option value="hours">Hours</option>
+          <option value="days">Days</option>
+        </select>
+    </div>
+
+    <div class="form-row">
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+        <input type="text" id="node-input-name" placeholder="Name">
+    </div>
+
+</script>
+
+<!-- Next, some simple help text is provided for the node.                   -->
+<script type="text/x-red" data-help-name="delay">
+    <p>Introduces a delay into a flow or rate limts messges</p>
+    <p>Default delay is 5 seconds and rate limit of 1 msg/second, but both can be configured</p>
+</script>
+
+<!-- Finally, the node type is registered along with all of its properties   -->
+<script type="text/javascript">
+    RED.nodes.registerType('delay',{
+        category: 'function',      // the palette category
+        color:"#E6E0F8",
+        defaults: {             // defines the editable properties of the node
+            name: {value:""},   //  along with default values.
+            pauseType: {value:"delay", required:true},
+            timeout: {value:"5", required:true, validate:RED.validators.number()},
+            timeoutUnits: {value:"seconds"},
+            rate: {value:"1", required:true, validate:RED.validators.number()},
+            rateUnits: {value: "second"},
+            randomFirst: {value:"1", required:true, validate:RED.validators.number()},
+            randomLast: {value:"5", required:true, validate:RED.validators.number()},
+            randomUnits: {value: "seconds"},
+            drop: {value:false}
+        },
+        inputs:1,                // set the number of inputs - only 0 or 1
+        outputs:1,               // set the number of outputs - 0 to n
+        icon: "timer.png",    // set the icon (held in public/icons)
+        label: function() {      // sets the default label contents
+            if (this.pauseType == "delay") {
+              var units = this.timeoutUnits ? this.timeoutUnits.charAt(0) : "s";
+              if (this.timeoutUnits == "milliseconds") { units = "ms"; }
+              return this.name||"delay "+this.timeout+" " + units;
+            } else if (this.pauseType == "rate") {
+              var units = this.rateUnits ? this.rateUnits.charAt(0) : "s";
+              return this.name||"limit "+this.rate+" msg/"+ units;
+            } else if (this.pauseType == "random") {
+              return this.name || "random";
+            }
+            return "foo";
+        },
+        labelStyle: function() { // sets the class to apply to the label
+            return this.name?"node_label_italic":"";
+        },
+        oneditprepare: function() {
+          $( "#node-input-timeout" ).spinner({min:1,max:60});
+          $( "#node-input-rate" ).spinner({min:1});
+
+          $( "#node-input-randomFirst" ).spinner({min:0});
+          $( "#node-input-randomLast" ).spinner({min:1});
+
+          if (this.pauseType == "delay") {
+            $("#delay-details").show();
+            $("#rate-details").hide();
+            $("#random-details").hide();
+          } else if (this.pauseType == "rate") {
+            $("#delay-details").hide();
+            $("#rate-details").show();
+            $("#random-details").hide();
+          } else if (this.pauseType == "random") {
+            $("#delay-details").hide();
+            $("#rate-details").hide();
+            $("#random-details").show();
+          }
+
+          if (!this.timeoutUnits) {
+            $("#node-input-timeoutUnits option").filter(function() {
+              return $(this).val() == 'seconds';
+            }).attr('selected', true);
+          }
+
+          if (!this.randomUnits) {
+            $("#node-input-randomUnits option").filter(function() {
+               return $(this).val() == 'seconds';
+            }).attr('selected', true);
+          }
+
+          $("#node-input-pauseType").on("change",function() {
+            if (this.value == "delay") {
+              $("#delay-details").show();
+              $("#rate-details").hide();
+              $("#random-details").hide();
+            } else if (this.value == "rate") {
+              $("#delay-details").hide();
+              $("#rate-details").show();
+              $("#random-details").hide();
+            } else if (this.value == "random") {
+              $("#delay-details").hide();
+              $("#rate-details").hide();
+              $("#random-details").show();
+            }
+          });
+        }
+    });
+</script>
diff --git a/dgbuilder/core_nodes/core/89-delay.js b/dgbuilder/core_nodes/core/89-delay.js
new file mode 100644 (file)
index 0000000..3c4e1c0
--- /dev/null
@@ -0,0 +1,171 @@
+/**
+ * Copyright 2013, 2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+//Simple node to introduce a pause into a flow
+module.exports = function(RED) {
+    "use strict";
+    
+    var MILLIS_TO_NANOS = 1000000;
+    var SECONDS_TO_NANOS = 1000000000;
+    
+    function random(n) {
+        var wait = n.randomFirst + (n.diff * Math.random());
+        if (n.buffer.length > 0) {
+            n.send(n.buffer.pop());
+            n.randomID = setTimeout(function() {random(n);},wait);
+        } else {
+            n.randomID = -1;
+        }
+    }
+
+    function DelayNode(n) {
+        RED.nodes.createNode(this,n);
+
+        this.pauseType = n.pauseType;
+        this.timeoutUnits = n.timeoutUnits;
+        this.randomUnits = n.randomUnits;
+        this.rateUnits = n.rateUnits;
+
+        if (n.timeoutUnits === "milliseconds") {
+            this.timeout = n.timeout;
+        } else if (n.timeoutUnits === "seconds") {
+            this.timeout = n.timeout * 1000;
+        } else if (n.timeoutUnits === "minutes") {
+            this.timeout = n.timeout * (60 * 1000);
+        } else if (n.timeoutUnits === "hours") {
+            this.timeout = n.timeout * (60 * 60 * 1000);
+        } else if (n.timeoutUnits === "days") {
+            this.timeout = n.timeout * (24 * 60 * 60 * 1000);
+        }
+
+        if (n.rateUnits === "second") {
+            this.rate = 1000/n.rate;
+        } else if (n.rateUnits === "minute") {
+            this.rate = (60 * 1000)/n.rate;
+        } else if (n.rateUnits === "hour") {
+            this.rate = (60 * 60 * 1000)/n.rate;
+        } else if (n.rateUnits === "day") {
+            this.rate = (24 * 60 * 60 * 1000)/n.rate;
+        }
+
+        if (n.randomUnits === "milliseconds") {
+            this.randomFirst = n.randomFirst;
+            this.randomLast = n.randomLast;
+        } else if (n.randomUnits === "seconds") {
+            this.randomFirst = n.randomFirst * 1000;
+            this.randomLast = n.randomLast * 1000;
+        } else if (n.randomUnits === "minutes") {
+            this.randomFirst = n.randomFirst * (60 * 1000);
+            this.randomLast = n.randomLast * (60 * 1000);
+        } else if (n.randomUnits === "hours") {
+            this.randomFirst = n.randomFirst * (60 * 60 * 1000);
+            this.randomLast = n.randomLast * (60 * 60 * 1000);
+        } else if (n.randomUnits === "days") {
+            this.randomFirst = n.randomFirst * (24 * 60 * 60 * 1000);
+            this.randomLast = n.randomLast * (24 * 60 * 60 * 1000);
+        }
+
+        this.diff = this.randomLast - this.randomFirst;
+        this.name = n.name;
+        this.idList = [];
+        this.buffer = [];
+        this.intervalID = -1;
+        this.randomID = -1;
+        this.lastSent;
+        this.drop = n.drop;
+        var node = this;
+
+        if (this.pauseType === "delay") {
+            this.on("input", function(msg) {
+                var id;
+                id = setTimeout(function(){
+                    node.idList.splice(node.idList.indexOf(id),1);
+                    node.send(msg);
+                }, node.timeout);
+                this.idList.push(id);
+            });
+
+            this.on("close", function() {
+                for (var i=0; i<this.idList.length; i++ ) {
+                    clearTimeout(this.idList[i]);
+                }
+                this.idList = [];
+            });
+
+        } else if (this.pauseType === "rate") {
+            this.on("input", function(msg) {
+                if (!node.drop) {
+                    if ( node.intervalID !== -1) {
+                        node.buffer.push(msg);
+                        if (node.buffer.length > 0) {
+                            node.status({text:node.buffer.length});
+                        }
+                        if (node.buffer.length > 1000) {
+                            node.warn(this.name + " buffer exceeded 1000 messages");
+                        }
+                    } else {
+                        node.send(msg);
+                        node.intervalID = setInterval(function() {
+                            if (node.buffer.length === 0) {
+                                clearInterval(node.intervalID);
+                                node.intervalID = -1;
+                                node.status({text:""});
+                            }
+
+                            if (node.buffer.length > 0) {
+                                node.send(node.buffer.shift());
+                                node.status({text:node.buffer.length});
+                            }
+                        },node.rate);
+                    }
+                } else {
+                    var timeSinceLast;
+                    if (node.lastSent) {
+                        timeSinceLast = process.hrtime(node.lastSent);
+                    }
+                    if (!node.lastSent) { // ensuring that we always send the first message 
+                        node.lastSent = process.hrtime();
+                        node.send(msg);
+                    } else if ( ( (timeSinceLast[0] * SECONDS_TO_NANOS) + timeSinceLast[1] ) > (node.rate * MILLIS_TO_NANOS) ) {
+                        node.lastSent = process.hrtime();
+                        node.send(msg);
+                    }
+                }
+            });
+
+            this.on("close", function() {
+                clearInterval(this.intervalID);
+                this.buffer = [];
+            });
+
+        } else if (this.pauseType === "random") {
+            this.on("input",function(msg){
+                node.buffer.push(msg);
+                if (node.randomID === -1) {
+                    var wait = node.randomFirst + (node.diff * Math.random());
+                    node.randomID = setTimeout(function() {random(node);},wait);
+                }
+            });
+
+            this.on("close", function (){
+                if (this.randomID !== -1) {
+                    clearTimeout(this.randomID);
+                }
+            });
+        }
+    }
+    RED.nodes.registerType("delay",DelayNode);
+}
diff --git a/dgbuilder/core_nodes/core/89-trigger.html b/dgbuilder/core_nodes/core/89-trigger.html
new file mode 100644 (file)
index 0000000..f3ec530
--- /dev/null
@@ -0,0 +1,130 @@
+<!--
+  Copyright 2014 IBM Corp.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<script type="text/x-red" data-template-name="trigger">
+    <div class="form-row">
+        <label for="node-input-op1type"><i class="fa fa-arrow-up"></i> Output</label>
+        <select id="node-input-op1type" style="width:73% !important">
+            <option value="val">the value below</option>
+            <option value="pay">the existing payload</option>
+            <option value="nul">nothing (no output)</option>
+        </select>
+    </div>
+    <div class="form-row" id="node-op1">
+        <label for="node-input-op1">&nbsp;</label>
+        <input type="text" id="node-input-op1">
+    </div>
+    <div class="form-row">
+        <label for="node-input-duration"><i class="fa fa-clock-o"></i> then wait</label>
+        <input type="text" id="node-input-duration" placeholder="250" style="direction:rtl; width:70px !important">
+        <select id="node-input-units" style="width:140px !important">
+            <option value="ms">Milliseconds</option>
+            <option value="s">Seconds</option>
+            <option value="min">Minutes</option>
+            <option value="hr">Hours</option>
+        </select>
+    </div>
+    <div class="form-row">
+        <label for="node-input-op2type"><i class="fa fa-arrow-down"></i> output</label>
+        <select id="node-input-op2type" style="width:73% !important">
+            <option value="val">the value below</option>
+            <option value="pay">the existing payload</option>
+            <option value="nul">nothing (no output)</option>
+        </select>
+    </div>
+    <div class="form-row" id="node-op2">
+        <label for="node-input-op2">&nbsp;</label>
+        <input type="text" id="node-input-op2">
+    </div>
+    <div class="form-row">
+        <label for="node-input-extend"><i class="fa fa-repeat"></i> and</label>
+        <select id="node-input-extend" style="width:73% !important">
+            <option value="false">don't extend the timer if retriggered</option>
+            <option value="true">extend the timer if retriggered</option>
+        </select>
+    </div>
+    <div class="form-row">
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+        <input type="text" id="node-input-name" placeholder="Name">
+    </div>
+    <!-- <div class="form-tips">Tip: Outputs can be values, null, {{templated}} or msg.payload<br/> -->
+    <div class="form-tips">Setting the timeout to 0 sets an infinite timeout = single shot.</div>
+    <script>
+    {
+        $("#node-input-op1type").change(function() {
+            if ($("#node-input-op1type").val() == "val") { $("#node-op1").show(); }
+            else { $("#node-op1").hide(); }
+        });
+        $("#node-input-op2type").change(function() {
+            if ($("#node-input-op2type").val() == "val") { $("#node-op2").show(); }
+            else { $("#node-op2").hide(); }
+        });
+    }
+    </script>
+</script>
+
+<script type="text/x-red" data-help-name="trigger">
+    <p>Creates two messages on the output separated by a timeout whenever ANY <b>msg</b> arrives on the input.</p>
+    <p>For example, this can be used to toggle a Raspberry PI GPIO pin on and off.</p>
+    <p>The two output states can be specified as can the duration of the timer.
+    Either output can be set to a value, or templated from the inbound
+    <b>msg</b> using mustache syntax. <pre>The payload is {{payload}}</pre></p>
+    <p>If the payload is an object then setting the output to <i>existing payload</i> will pass the complete payload object through.</p>
+    <p>Optionally the timer can be extended by being retriggered... or not.</p>
+    <p>By setting the first output to <i>nothing</i>, and selecting extend timer - a watchdog timer can be created.
+    No output will happen as long as repeated inputs occur within the timeout period.</p>
+    <p>Setting the timer to 0 creates an "infinite" timeout - the first output will happen but the second
+    never will, and neither can the first be retriggered - so a true one shot.</p>
+    <p>If a <b>msg.reset</b> property is present any timeout currently in progress
+    will be cleared and the second output will not happen.</p>
+</script>
+
+<script type="text/javascript">
+    RED.nodes.registerType('trigger',{
+        category: 'function',
+        color:"#E6E0F8",
+        defaults: {
+            op1: {value:"1"},
+            op2: {value:"0"},
+            op1type: {value:""},
+            op2type: {value:""},
+            duration: {value:"250",required:true,validate:RED.validators.number()},
+            extend: {value:"false"},
+            units: {value: "ms"},
+            name: {value:""}
+        },
+        inputs:1,
+        outputs:1,
+        icon: "trigger.png",
+        label: function() {
+            if (this.duration > 0) {
+                return this.name||"trigger "+this.duration+this.units;
+            }
+            else {
+                return this.name||"trigger once &infin;";
+            }
+        },
+        labelStyle: function() {
+            return this.name?"node_label_italic":"";
+        },
+        oneditprepare: function() {
+            $( "#node-input-duration" ).spinner({
+                min:1,
+                increment:25
+            });
+        }
+    });
+</script>
diff --git a/dgbuilder/core_nodes/core/89-trigger.js b/dgbuilder/core_nodes/core/89-trigger.js
new file mode 100644 (file)
index 0000000..d86a213
--- /dev/null
@@ -0,0 +1,91 @@
+/**
+ * Copyright 2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+module.exports = function(RED) {
+    "use strict";
+    var mustache = require("mustache");
+    function TriggerNode(n) {
+        RED.nodes.createNode(this,n);
+        this.op1 = n.op1 || "1";
+        this.op2 = n.op2 || "0";
+        this.op1type = n.op1type || "val";
+        this.op2type = n.op2type || "val";
+        this.extend = n.extend || false;
+        this.units = n.units || "ms";
+        this.duration = n.duration || 250;
+        if (this.duration <= 0) { this.duration = 0; }
+        else {
+            if (this.units == "s") { this.duration = this.duration * 1000; }
+            if (this.units == "min") { this.duration = this.duration * 1000 * 60; }
+            if (this.units == "hr") { this.duration = this.duration * 1000 *60 * 60; }
+        }
+        this.op1Templated = this.op1.indexOf("{{") != -1;
+        this.op2Templated = this.op2.indexOf("{{") != -1;
+        if (!isNaN(this.op1)) { this.op1 = Number(this.op1); }
+        if (!isNaN(this.op2)) { this.op2 = Number(this.op2); }
+        if (this.op1 == "true") { this.op1 = true; }
+        if (this.op2 == "true") { this.op1 = true; }
+        if (this.op1 == "false") { this.op2 = false; }
+        if (this.op2 == "false") { this.op2 = false; }
+        if (this.op1 == "null") { this.op1 = null; }
+        if (this.op2 == "null") { this.op1 = null; }
+        try { this.op1 = JSON.parse(this.op1); }
+        catch(e) { this.op1 = this.op1; }
+        try { this.op2 = JSON.parse(this.op2); }
+        catch(e) { this.op2 = this.op2; }
+
+        var node = this;
+        var tout = null;
+        var m2;
+        this.on("input", function(msg) {
+            if (msg.hasOwnProperty("reset")) {
+                clearTimeout(tout);
+                tout = null;
+            }
+            else {
+                if (!tout) {
+                    if (node.op2type === "pay") { m2 = msg.payload; }
+                    else if (node.op2Templated) { m2 = mustache.render(node.op2,msg); }
+                    else { m2 = node.op2; }
+                    if (node.op1type === "pay") { }
+                    else if (node.op1Templated) { msg.payload = mustache.render(node.op1,msg); }
+                    else { msg.payload = node.op1; }
+                    if (node.op1type !== "nul") { node.send(msg); }
+                    if (node.duration === 0) { tout = "infinite"; }
+                    else {
+                        tout = setTimeout(function() {
+                            msg.payload = m2;
+                            if (node.op2type !== "nul") { node.send(msg); }
+                            tout = null;
+                        },node.duration);
+                    }
+                }
+                else if ((node.extend == "true") && (node.duration > 0)) {
+                    clearTimeout(tout);
+                    tout = setTimeout(function() {
+                        msg.payload = m2;
+                        if (node.op2type !== "nul") { node.send(msg); }
+                        tout = null;
+                    },node.duration);
+                }
+            }
+        });
+        this.on("close", function() {
+            if (tout) { clearTimeout(tout); }
+        });
+    }
+    RED.nodes.registerType("trigger",TriggerNode);
+}
diff --git a/dgbuilder/core_nodes/core/90-comment.html b/dgbuilder/core_nodes/core/90-comment.html
new file mode 100644 (file)
index 0000000..3638fda
--- /dev/null
@@ -0,0 +1,86 @@
+<!--
+  Copyright 2013 IBM Corp.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<script type="text/x-red" data-template-name="comment">
+    <div class="form-row">
+        <label for="node-input-name"><i class="fa fa-comment"></i> Comment</label>
+        <input type="text" id="node-input-name" placeholder="Comment">
+    </div>
+    <div class="form-row">
+        <label for="node-input-info" style="width: 100% !important;"><i class="fa fa-comments"></i> More</label>
+        <input type="hidden" id="node-input-info" autofocus="autofocus">
+        <div style="height: 250px;" class="node-text-editor" id="node-input-info-editor" ></div>
+    </div>
+    <div class="form-tips">Tip: this isn't meant for "War and Peace" - but useful notes can be kept here.</div>
+</script>
+
+<script type="text/x-red" data-help-name="comment">
+    <p>Simple comment block.</p>
+</script>
+
+<script type="text/javascript">
+    RED.nodes.registerType('comment',{
+        category: 'function',
+        color:"#ffffff",
+        defaults: {
+            name: {value:""},
+            info: {value:""}
+        },
+        inputs:0,
+        outputs:0,
+        icon: "comment.png",
+        label: function() {
+            return this.name||"";
+        },
+        labelStyle: function() {
+            return this.name?"node_label_italic":"";
+        },
+        oneditprepare: function() {
+            $( "#node-input-outputs" ).spinner({
+                min:1
+            });
+            function functionDialogResize(ev,ui) {
+                $("#node-input-info-editor").css("height",(ui.size.height-235)+"px");
+            };
+            $( "#dialog" ).on("dialogresize", functionDialogResize);
+            $( "#dialog" ).one("dialogopen", function(ev) {
+                var size = $( "#dialog" ).dialog('option','sizeCache-function');
+                if (size) {
+                    functionDialogResize(null,{size:size});
+                }
+            });
+            $( "#dialog" ).one("dialogclose", function(ev,ui) {
+                var height = $( "#dialog" ).dialog('option','height');
+                $( "#dialog" ).off("dialogresize",functionDialogResize);
+            });
+            var that = this;
+            require(["orion/editor/edit"], function(edit) {
+                that.editor = edit({
+                    parent:document.getElementById('node-input-info-editor'),
+                    lang:"text",
+                    showLinesRuler:false,
+                    showFoldingRuler:false,
+                    contents: $("#node-input-info").val()
+                });
+                $("#node-input-name").focus();
+            });
+        },
+        oneditsave: function() {
+            $("#node-input-info").val(this.editor.getText());
+            delete this.editor;
+        }
+    });
+</script>
diff --git a/dgbuilder/core_nodes/core/90-comment.js b/dgbuilder/core_nodes/core/90-comment.js
new file mode 100644 (file)
index 0000000..ef5f080
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * Copyright 2013 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+module.exports = function(RED) {
+    "use strict";
+    function CommentNode(n) {
+        RED.nodes.createNode(this,n);
+    }
+    RED.nodes.registerType("comment",CommentNode);
+}
diff --git a/dgbuilder/core_nodes/core/98-unknown.html b/dgbuilder/core_nodes/core/98-unknown.html
new file mode 100644 (file)
index 0000000..19a4ad5
--- /dev/null
@@ -0,0 +1,49 @@
+<!--
+  Copyright 2013 IBM Corp.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<script type="text/x-red" data-template-name="unknown">
+    <div class="form-tips"><p>This node is a type unknown to your installation of Node-RED.</p>
+    <p><i>If you deploy with the node in this state, it will lose all of its configuration.</i></p>
+    <p>See the Info side bar for more help</p></div>
+</script>
+
+<script type="text/x-red" data-help-name="unknown">
+    <p>This node is a type unknown to your installation of Node-RED.</p>
+    <p><i>If you deploy with the node in this state, it will lose all of its configuration.</i></p>
+    <p>It is possible this node type is already installed, but is missing a dependency. Check the Node-RED start-up log for
+       any error messages associated with the missing node type. Use <b>npm install &lt;module&gt;</b> to install any missing modules
+       and restart Node-RED and reimport the nodes.</p>
+    <p>Otherwise, you should contact the author of the flow to obtain a copy of the missing node type.</p>
+</script>
+
+<script type="text/javascript">
+    RED.nodes.registerType('unknown',{
+        category: 'unknown',
+        color:"#fff0f0",
+        defaults: {
+            name: {value:""}
+        },
+        inputs:1,
+        outputs:1,
+        icon: "",
+        label: function() {
+            return "("+this.name+")"||"unknown";
+        },
+        labelStyle: function() {
+            return "node_label_unknown";
+        }
+    });
+</script>
diff --git a/dgbuilder/core_nodes/core/98-unknown.js b/dgbuilder/core_nodes/core/98-unknown.js
new file mode 100644 (file)
index 0000000..ed4716b
--- /dev/null
@@ -0,0 +1,23 @@
+/**
+ * Copyright 2013 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+module.exports = function(RED) {
+    "use strict";
+    function UnknownNode(n) {
+        RED.nodes.createNode(this,n);
+    }
+    RED.nodes.registerType("unknown",UnknownNode);
+}
diff --git a/dgbuilder/core_nodes/deprecated/61-imap.html b/dgbuilder/core_nodes/deprecated/61-imap.html
new file mode 100644 (file)
index 0000000..9702cd6
--- /dev/null
@@ -0,0 +1,56 @@
+<!--
+  Copyright 2013 IBM Corp.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<script type="text/x-red" data-template-name="imap">
+    <div class="form-row node-input-repeat">
+        <label for="node-input-repeat"><i class="fa fa-repeat"></i>Repeat (S)</label>
+        <input type="text" id="node-input-repeat" placeholder="300">
+    </div>
+    <div class="form-row">
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+        <input type="text" id="node-input-name" placeholder="Name">
+    </div>
+</script>
+
+<script type="text/x-red" data-help-name="imap">
+    <p>Repeatedly gets a <b>single email</b> from an IMAP server and forwards on as a msg if not already seen.</p>
+    <p>The subject is loaded into <b>msg.topic</b> and <b>msg.payload</b> is the plain text body.
+       If there is text/html then that is returned in <b>msg.html</b>. <b>msg.from</b> and <b>msg.date</b> are also set if you need them.</p>
+    <p>Uses the imap module - you also need to pre-configure your email settings in a file emailkeys.js as per below.</p>
+    <p><pre>module.exports = { service: "Gmail", user: "blahblah@gmail.com", pass: "password", server: "imap.gmail.com", port: "993" }</pre></p>
+    <p>This <b>must</b> be located in the directory <b>above</b> node-red.</p>
+    <p><b>Note:</b> this node <i>only</i> gets the most recent single email from the inbox, so set the repeat (polling) time appropriately.</p>
+</script>
+
+<script type="text/javascript">
+    RED.nodes.registerType('imap',{
+        category: 'deprecated',
+        color:"#c7e9c0",
+        defaults: {
+            repeat: {value:"300",required:true},
+            name: {value:""}
+        },
+        inputs:0,
+        outputs:1,
+        icon: "envelope.png",
+        label: function() {
+            return this.name||"IMAP";
+        },
+        labelStyle: function() {
+            return (this.name||!this.topic)?"node_label_italic":"";
+        }
+    });
+</script>
diff --git a/dgbuilder/core_nodes/deprecated/61-imap.js b/dgbuilder/core_nodes/deprecated/61-imap.js
new file mode 100644 (file)
index 0000000..aa2b4be
--- /dev/null
@@ -0,0 +1,139 @@
+/**
+ * Copyright 2013 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+var RED = require(process.env.NODE_RED_HOME+"/red/red");
+var Imap = require('imap');
+var util = require('util');
+
+try {
+    var emailkey = RED.settings.email || require(process.env.NODE_RED_HOME+"/../emailkeys.js");
+} catch (err) {
+    //util.log("[61-imap.js] Info : No Email credentials found.");
+}
+
+if (emailkey) {
+    var imap = new Imap({
+        user: emailkey.user,
+        password: emailkey.pass,
+        host: emailkey.server||"imap.gmail.com",
+        port: emailkey.port||"993",
+        tls: true,
+        tlsOptions: { rejectUnauthorized: false }
+    });
+
+    function openInbox(cb) {
+        imap.openBox('INBOX', true, cb);
+    }
+}
+
+function ImapNode(n) {
+    RED.nodes.createNode(this,n);
+    this.warn("This node has been deprecated and will be deleted in a future release. Please update your flow to use the 'e-mail in' node.");
+    this.name = n.name;
+    this.repeat = n.repeat * 1000 || 300000;
+    var node = this;
+    this.interval_id = null;
+    var oldmail = {};
+
+    if (!isNaN(this.repeat) && this.repeat > 0) {
+        node.log("repeat = "+this.repeat);
+        this.interval_id = setInterval( function() {
+            node.emit("input",{});
+        }, this.repeat );
+    }
+
+    this.on("input", function(msg) {
+        if (imap) {
+            imap.once('ready', function() {
+                var pay = {};
+                openInbox(function(err, box) {
+                    if (box.messages.total > 0) {
+                        var f = imap.seq.fetch(box.messages.total + ':*', { bodies: ['HEADER.FIELDS (FROM SUBJECT DATE)','TEXT'] });
+                        f.on('message', function(msg, seqno) {
+                            node.log('message: #'+ seqno);
+                            var prefix = '(#' + seqno + ') ';
+                            msg.on('body', function(stream, info) {
+                                var buffer = '';
+                                stream.on('data', function(chunk) {
+                                    buffer += chunk.toString('utf8');
+                                });
+                                stream.on('end', function() {
+                                    if (info.which !== 'TEXT') {
+                                        pay.from = Imap.parseHeader(buffer).from[0];
+                                        pay.topic = Imap.parseHeader(buffer).subject[0];
+                                        pay.date = Imap.parseHeader(buffer).date[0];
+                                    } else {
+                                        var parts = buffer.split("Content-Type");
+                                        for (var p in parts) {
+                                            if (parts[p].indexOf("text/plain") >= 0) {
+                                                pay.payload = parts[p].split("\n").slice(1,-2).join("\n").trim();
+                                            }
+                                            if (parts[p].indexOf("text/html") >= 0) {
+                                                pay.html = parts[p].split("\n").slice(1,-2).join("\n").trim();
+                                            }
+                                        }
+                                        //pay.body = buffer;
+                                    }
+                                });
+                            });
+                            msg.on('end', function() {
+                                //node.log('Finished: '+prefix);
+                            });
+                        });
+                        f.on('error', function(err) {
+                            node.warn('fetch error: ' + err);
+                        });
+                        f.on('end', function() {
+                            if (JSON.stringify(pay) !== oldmail) {
+                                node.send(pay);
+                                oldmail = JSON.stringify(pay);
+                                node.log('sent new message: '+pay.topic);
+                            }
+                            else { node.log('duplicate not sent: '+pay.topic); }
+                            imap.end();
+                        });
+                    }
+                    else {
+                        // node.log("you have achieved inbox zero");
+                        imap.end();
+                    }
+                });
+            });
+            imap.connect();
+        }
+        else { node.warn("No Email credentials found. See info panel."); }
+    });
+
+    if (imap) {
+        imap.on('error', function(err) {
+            util.log(err);
+        });
+    }
+
+    this.on("error", function(err) {
+        node.log("error: ",err);
+    });
+
+    this.on("close", function() {
+        if (this.interval_id != null) {
+            clearInterval(this.interval_id);
+        }
+        if (imap) { imap.destroy(); }
+    });
+
+    node.emit("input",{});
+}
+RED.nodes.registerType("imap",ImapNode);
diff --git a/dgbuilder/core_nodes/deprecated/73-parsexml.html b/dgbuilder/core_nodes/deprecated/73-parsexml.html
new file mode 100644 (file)
index 0000000..b6fc16f
--- /dev/null
@@ -0,0 +1,53 @@
+<!--
+  Copyright 2013 IBM Corp.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<script type="text/x-red" data-template-name="xml2js">
+    <!-- <div class="form-row">
+        <label>Use Console</label>
+        <input type="checkbox" id="node-input-useEyes" placeholder="Name" style="display: inline-block; width: auto; vertical-align: top;">
+        <label for="node-input-useEyes" style="width: 70%;">Debug output in console ?</label>
+    </div> -->
+    <div class="form-row">
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+        <input type="text" id="node-input-name" placeholder="Name">
+    </div>
+    <!-- <div class="form-tips">Uses xml2js to process xml into javascript object.</div> -->
+</script>
+
+<script type="text/x-red" data-help-name="xml2js">
+    <p>A function that parses the <b>msg.payload</b> using the xml2js library. Places the result in the payload.</p>
+    <p>See <a href="https://github.com/Leonidas-from-XIV/node-xml2js/blob/master/README.md" target="_new">the xml2js docs <i>here</i></a> for more information.</p>
+</script>
+
+<script type="text/javascript">
+    RED.nodes.registerType('xml2js',{
+        category: 'deprecated',
+        color:"#E6E0F8",
+        defaults: {
+        //useEyes: {value:false},
+        name: {value:""}
+        },
+        inputs:1,
+        outputs:1,
+        icon: "arrow-in.png",
+        label: function() {
+            return this.name||"xml2json";
+        },
+        labelStyle: function() {
+            return this.name?"node_label_italic":"";
+        }
+    });
+</script>
diff --git a/dgbuilder/core_nodes/deprecated/73-parsexml.js b/dgbuilder/core_nodes/deprecated/73-parsexml.js
new file mode 100644 (file)
index 0000000..92850cb
--- /dev/null
@@ -0,0 +1,47 @@
+/**
+ * Copyright 2013 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+module.exports = function(RED) {
+    "use strict";
+    var util = require("util");
+    var parseString = require('xml2js').parseString;
+    var useColors = true;
+    //util.inspect.styles.boolean = "red";
+
+    function Xml2jsNode(n) {
+        RED.nodes.createNode(this,n);
+        this.warn("This node has been deprecated and will be deleted in a future release. Please update your flow to use the 'xml' node.");
+        this.useEyes = n.useEyes||false;
+        var node = this;
+        this.on("input", function(msg) {
+            try {
+                parseString(msg.payload, {strict:true,async:true}, function (err, result) {
+                //parseString(msg.payload, {strict:false,async:true}, function (err, result) {
+                    if (err) { node.error(err); }
+                    else {
+                        msg.payload = result;
+                        node.send(msg);
+                        if (node.useEyes == true) {
+                            node.log("\n"+util.inspect(msg, {colors:useColors, depth:10}));
+                        }
+                    }
+                });
+            }
+            catch(e) { util.log("[73-parsexml.js] "+e); }
+        });
+    }
+    RED.nodes.registerType("xml2js",Xml2jsNode);
+}
diff --git a/dgbuilder/core_nodes/deprecated/74-js2xml.html b/dgbuilder/core_nodes/deprecated/74-js2xml.html
new file mode 100644 (file)
index 0000000..f614579
--- /dev/null
@@ -0,0 +1,51 @@
+<!--\r
+  Copyright 2013 IBM Corp.\r
+\r
+  Licensed under the Apache License, Version 2.0 (the "License");\r
+  you may not use this file except in compliance with the License.\r
+  You may obtain a copy of the License at\r
+\r
+  http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+  Unless required by applicable law or agreed to in writing, software\r
+  distributed under the License is distributed on an "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+  See the License for the specific language governing permissions and\r
+  limitations under the License.\r
+-->\r
+\r
+<script type="text/x-red" data-template-name="json2xml">\r
+    <div class="form-row">\r
+        <label for="node-input-name"><i class="fa fa-list"></i> XML Root</label>\r
+        <input type="text" id="node-input-root" placeholder="object"></input>\r
+    </div>\r
+    <div class="form-row">\r
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>\r
+        <input type="text" id="node-input-name" placeholder="Name"></input>\r
+    </div>\r
+</script>\r
+\r
+<script type="text/x-red" data-help-name="json2xml">\r
+    <p>A function that parses the <b>msg.payload</b> using the js2xmlparser library. Places the result back in <b>msg.payload</b>.</p>\r
+    <p>See the <a href="https://github.com/michaelkourlas/node-js2xmlparser" target="_new">js2xmlparser docs</a> for more information.</p>\r
+</script>\r
+\r
+<script type="text/javascript">\r
+    RED.nodes.registerType('json2xml',{\r
+        category: 'deprecated',\r
+        color:"#E6E0F8",\r
+        defaults: {\r
+            name: {value:""},\r
+            root: {value:"object"},\r
+        },\r
+        inputs:1,\r
+        outputs:1,\r
+        icon: "arrow-in.png",\r
+        label: function() {\r
+            return this.name||"json2xml";\r
+        },\r
+        labelStyle: function() {\r
+            return this.name?"node_label_italic":"";\r
+        }\r
+    });\r
+</script>\r
diff --git a/dgbuilder/core_nodes/deprecated/74-js2xml.js b/dgbuilder/core_nodes/deprecated/74-js2xml.js
new file mode 100644 (file)
index 0000000..164bafa
--- /dev/null
@@ -0,0 +1,39 @@
+/**\r
+ * Copyright 2013 IBM Corp.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ **/\r
+\r
+module.exports = function(RED) {\r
+    "use strict";\r
+    var js2xmlparser = require("js2xmlparser");\r
+\r
+    function Js2XmlNode(n) {\r
+        RED.nodes.createNode(this,n);\r
+        this.warn("This node has been deprecated and will be deleted in a future release. Please update your flow to use the 'xml' node.");\r
+        this.root = n.root;\r
+        var node = this;\r
+\r
+        this.on("input", function(msg) {\r
+            try {\r
+                var root = node.root || typeof msg.payload;\r
+                if (typeof msg.payload !== "object") { msg.payload = '"'+msg.payload+'"'; }\r
+                console.log(root, typeof msg.payload,msg.payload);\r
+                msg.payload = js2xmlparser(root, msg.payload);\r
+                node.send(msg);\r
+            }\r
+            catch(e) { console.log(e); }\r
+        });\r
+    }\r
+    RED.nodes.registerType("json2xml",Js2XmlNode);\r
+}\r
diff --git a/dgbuilder/core_nodes/deprecated/90-httpget.html b/dgbuilder/core_nodes/deprecated/90-httpget.html
new file mode 100644 (file)
index 0000000..b1f2e08
--- /dev/null
@@ -0,0 +1,61 @@
+<!--
+  Copyright 2013 IBM Corp.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<script type="text/x-red" data-template-name="httpget">
+    <div class="form-tips"><b>Deprecated</b>: please use the <i>http request</i> node.</div>
+    <br>
+    <div class="form-row">
+        <label for="node-input-baseurl"><i class="fa fa-tasks"></i> Base URL</label>
+        <input type="text" id="node-input-baseurl" placeholder="http(s)://url">
+    </div>
+    <div class="form-row">
+        <label for="node-input-append"><i class="fa fa-tasks"></i> Append</label>
+        <input type="text" id="node-input-append" placeholder="">
+    </div>
+    <div class="form-row">
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+        <input type="text" id="node-input-name" placeholder="Name">
+    </div>
+    <div class="form-tips">The <b>Base URL</b> gets prepended to whatever payload is passed in. Leave blank if you pass in a full url.<br/>The append gets added to the end after any payload.<br/>The output Topic is the same as the input Topic.</div>
+</script>
+
+<script type="text/x-red" data-help-name="httpget">
+       <p>Performs an HTTP or HTTPS GET and returns the fetched page.</p>
+       <p>The return code is placed in <b>msg.rc</b>, and the full text of the result is in <b>msg.payload</b>.</p>
+       <p>The <b>msg.payload</b> is added to the base url, and then the optional append is added after.</p>
+       <p>This is mostly suitable for small pages as large results will need a lot of parsing....</p>
+</script>
+
+<script type="text/javascript">
+    RED.nodes.registerType('httpget',{
+        category: 'deprecated',
+        color:"rgb(231, 231, 174)",
+        defaults: {
+            name: {value:""},
+            baseurl: {value:""},
+            append: {value:""}
+        },
+        inputs:1,
+        outputs:1,
+        icon: "white-globe.png",
+        label: function() {
+            return this.name||this.baseurl;
+        },
+        labelStyle: function() {
+            return this.name?"node_label_italic":"";
+        }
+    });
+</script>
diff --git a/dgbuilder/core_nodes/deprecated/90-httpget.js b/dgbuilder/core_nodes/deprecated/90-httpget.js
new file mode 100644 (file)
index 0000000..63e16b9
--- /dev/null
@@ -0,0 +1,53 @@
+/**
+ * Copyright 2013 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+var RED = require(process.env.NODE_RED_HOME+"/red/red");
+
+function HttpGet(n) {
+    RED.nodes.createNode(this,n);
+    this.warn("This node has been deprecated and will be deleted in a future release. Please update your flow to use the 'http request' node.");
+    this.baseurl = n.baseurl || "";
+    this.append = n.append || "";
+    var node = this;
+    if (this.baseurl.substring(0,5) === "https") { var http = require("https"); }
+    else { var http = require("http"); }
+    this.on("input", function(msg) {
+        msg._payload = msg.payload;
+        //util.log("[httpget] "+this.baseurl+msg.payload+this.append);
+        http.get(this.baseurl+msg.payload+this.append, function(res) {
+            node.log("Http response: " + res.statusCode);
+            msg.rc = res.statusCode;
+            msg.payload = "";
+            if ((msg.rc != 200) && (msg.rc != 404)) {
+                node.send(msg);
+            }
+            res.setEncoding('utf8');
+            res.on('data', function(chunk) {
+                msg.payload += chunk;
+            });
+            res.on('end', function() {
+                node.send(msg);
+            });
+        }).on('error', function(e) {
+            //node.error(e);
+            msg.rc = 503;
+            msg.payload = e;
+            node.send(msg);
+        });
+    });
+}
+
+RED.nodes.registerType("httpget",HttpGet);
diff --git a/dgbuilder/core_nodes/hardware/35-arduino.html b/dgbuilder/core_nodes/hardware/35-arduino.html
new file mode 100644 (file)
index 0000000..17f0289
--- /dev/null
@@ -0,0 +1,171 @@
+<!--
+  Copyright 2013,2014 IBM Corp.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+<script type="text/x-red" data-template-name="arduino in">
+    <div class="form-row">
+        <label for="node-input-arduino"><i class="fa fa-tasks"></i> Arduino</label>
+        <input type="text" id="node-input-arduino">
+    </div>
+    <div class="form-row">
+        <label for="node-input-pin"><i class="fa fa-circle"></i> Pin</label>
+        <input type="text" id="node-input-pin" placeholder="2">
+    </div>
+    <div class="form-row">
+        <label for="node-input-state"><i class="fa fa-wrench"></i> Type</label>
+        <select type="text" id="node-input-state" style="width: 150px;">
+            <option value="INPUT">Digital pin</option>
+            <option value="ANALOG">Analogue pin</option>
+        </select>
+    </div>
+    <div class="form-row">
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+        <input type="text" id="node-input-name" placeholder="Name">
+    </div>
+    <div class="form-tips"><b>Note:</b> You cannot use the same pin for both output and input.</div>
+</script>
+
+<script type="text/x-red" data-help-name="arduino in">
+    <p>Arduino input node. Connects to local Arduino and monitors the selected pin for changes. Uses <a href="http://firmata.org/" target="_new"><i>Firmata</i>.</a></p>
+    <p>The Arduino must be loaded with the Standard Firmata sketch available in the Arduino examples.</p>
+    <p>You can select either Digital or Analogue input. Outputs the value read as <b>msg.payload</b> and the pin number as <b>msg.topic</b>.</p>
+    <p>It only outputs on a change of value - fine for digital inputs, but you can get a lot of data from analogue pins which you must then handle.</p>
+    <p>You can set the sample rate in ms from 20 to 65535.</p>
+</script>
+
+<script type="text/javascript">
+    RED.nodes.registerType('arduino in',{
+        category: 'Arduino',
+        color:"#3fadb5",
+        defaults: {
+            name: {value:""},
+            pin: {value:"",required:true},
+            state: {value:"INPUT",required:true},
+            arduino: {type:"arduino-board"}
+        },
+        inputs:0,
+        outputs:1,
+        icon: "arduino.png",
+        label: function() {
+            var a = "";
+            if (this.state == "ANALOG") a = "A";
+            return this.name||"Pin: "+a+this.pin;
+        },
+        labelStyle: function() {
+            return this.name?"node_label_italic":"";
+        }
+    });
+</script>
+
+<script type="text/x-red" data-template-name="arduino out">
+    <div class="form-row">
+        <label for="node-input-arduino"><i class="fa fa-tasks"></i> Arduino</label>
+        <input type="text" id="node-input-arduino">
+    </div>
+    <div class="form-row">
+        <label for="node-input-pin"><i class="fa fa-circle"></i> Pin</label>
+        <input type="text" id="node-input-pin" placeholder="13">
+    </div>
+    <div class="form-row">
+        <label for="node-input-state"><i class="fa fa-wrench"></i> Type</label>
+        <select type="text" id="node-input-state" style="width: 200px;">
+            <option value="OUTPUT">Digital (0/1)</option>
+            <option value="PWM">Analogue (0-255)</option>
+            <option value="SERVO">Servo (0-180)</option>
+        </select>
+    </div>
+    <div class="form-row">
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+        <input type="text" id="node-input-name" placeholder="Name">
+    </div>
+    <div class="form-tips"><b>Note:</b> You cannot use the same pin for both output and input.</div>
+</script>
+
+<script type="text/x-red" data-help-name="arduino out">
+    <p>Arduino output node. Connects to local Arduino and writes to the selected digital pin. Uses <a href="http://firmata.org/" target="_new"><i>Firmata</i>.</a></p>
+    <p>The Arduino must be loaded with the Standard Firmata sketch available in the Arduino examples.</p>
+    <p>You can select Digital, Analogue (PWM) or Servo type outputs. Expects a numeric value in <b>msg.payload</b>. The pin number is set in the properties panel.</p>
+</script>
+
+<script type="text/javascript">
+    RED.nodes.registerType('arduino out',{
+        category: 'Arduino',
+        color:"#3fadb5",
+        defaults: {
+            name: {value:""},
+            pin: {value:"",required:true},
+            state: {value:"",required:true},
+            arduino: {type:"arduino-board"}
+        },
+        inputs:1,
+        outputs:0,
+        icon: "arduino.png",
+        align: "right",
+        label: function() {
+            return this.name||"Pin: "+this.pin;
+        },
+        labelStyle: function() {
+            return this.name?"node_label_italic":"";
+        }
+    });
+</script>
+
+
+<script type="text/x-red" data-template-name="arduino-board">
+    <div class="form-row">
+        <label for="node-config-input-device"><i class="fa fa-random"></i> Port</label>
+        <input type="text" id="node-config-input-device" style="width:60%;" placeholder="e.g. /dev/ttyUSB0  COM1"/>
+        <a id="node-config-lookup-serial" class="btn"><i id="node-config-lookup-serial-icon" class="fa fa-search"></i></a>
+    </div>
+    <div class="form-tips"><b>Tip:</b> Use search to try to auto-detect serial port.</div>
+</script>
+
+<script type="text/javascript">
+    RED.nodes.registerType('arduino-board',{
+        category: 'config',
+        defaults: {
+            device: {value:"",required:true}
+        },
+        label: function() {
+            return this.device||"arduino";
+        },
+        oneditprepare: function() {
+            try {
+                $("#node-config-input-device").autocomplete( "destroy" );
+            } catch(err) { }
+            $("#node-config-lookup-serial").click(function() {
+                $("#node-config-lookup-serial-icon").removeClass('fa-search');
+                $("#node-config-lookup-serial-icon").addClass('spinner');
+                $("#node-config-lookup-serial").addClass('disabled');
+
+                $.getJSON('arduinoports',function(data) {
+                    $("#node-config-lookup-serial-icon").addClass('fa-search');
+                    $("#node-config-lookup-serial-icon").removeClass('spinner');
+                    $("#node-config-lookup-serial").removeClass('disabled');
+                    var ports = [];
+                    $.each(data, function(i, port){
+                        ports.push(port);
+                    });
+                    $("#node-config-input-device").autocomplete({
+                        source:ports,
+                        minLength:0,
+                        close: function( event, ui ) {
+                            $("#node-config-input-device").autocomplete( "destroy" );
+                        }
+                    }).autocomplete("search","");
+                });
+            });
+        }
+    });
+</script>
diff --git a/dgbuilder/core_nodes/hardware/35-arduino.js b/dgbuilder/core_nodes/hardware/35-arduino.js
new file mode 100644 (file)
index 0000000..795e990
--- /dev/null
@@ -0,0 +1,160 @@
+/**
+ * Copyright 2013,2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+module.exports = function(RED) {
+    "use strict";
+    var util = require("util");
+    var ArduinoFirmata = require('arduino-firmata');
+    var fs = require('fs');
+    var plat = require('os').platform();
+    var portlist = ArduinoFirmata.list(function (err, ports) {
+        portlist = ports;
+    });
+
+    // The Board Definition - this opens (and closes) the connection
+    function ArduinoNode(n) {
+        RED.nodes.createNode(this,n);
+        this.device = n.device || null;
+        this.repeat = n.repeat||25;
+        //node.log("opening connection "+this.device);
+        var node = this;
+        node.board = new ArduinoFirmata();
+        if (portlist.indexOf(node.device) === -1) {
+            node.warn("Device "+node.device+" not found");
+        }
+        else {
+            node.board.connect(node.device);
+        }
+
+        node.board.on('boardReady', function(){
+            node.log("version "+node.board.boardVersion);
+        });
+
+        node.on('close', function() {
+            if (node.board) {
+                try {
+                    node.board.close(function() {
+                        node.log("port closed");
+                    });
+                } catch(e) { }
+            }
+        });
+    }
+    RED.nodes.registerType("arduino-board",ArduinoNode);
+
+
+    // The Input Node
+    function DuinoNodeIn(n) {
+        RED.nodes.createNode(this,n);
+        this.buttonState = -1;
+        this.pin = n.pin;
+        this.state = n.state;
+        this.arduino = n.arduino;
+        this.serverConfig = RED.nodes.getNode(this.arduino);
+        if (typeof this.serverConfig === "object") {
+            this.board = this.serverConfig.board;
+            //this.repeat = this.serverConfig.repeat;
+            var node = this;
+            node.status({fill:"red",shape:"ring",text:"connecting"});
+
+            node.board.on('connect', function() {
+                node.status({fill:"green",shape:"dot",text:"connected"});
+                //console.log("i",node.state,node.pin);
+                if (node.state == "ANALOG") {
+                    node.board.on('analogChange', function(e) {
+                        if (e.pin == node.pin) {
+                            var msg = {payload:e.value, topic:"A"+e.pin};
+                            node.send(msg);
+                        }
+                    });
+
+                }
+                else {
+                    node.board.pinMode(node.pin, ArduinoFirmata.INPUT);
+                    node.board.on('digitalChange', function(e) {
+                        if (e.pin == node.pin) {
+                            var msg = {payload:e.value, topic:e.pin};
+                            node.send(msg);
+                        }
+                    });
+                }
+            });
+        }
+        else {
+            util.log("[Firmata-arduino] port not configured");
+        }
+    }
+    RED.nodes.registerType("arduino in",DuinoNodeIn);
+
+
+    // The Output Node
+    function DuinoNodeOut(n) {
+        RED.nodes.createNode(this,n);
+        this.buttonState = -1;
+        this.pin = n.pin;
+        this.state = n.state;
+        this.arduino = n.arduino;
+        this.serverConfig = RED.nodes.getNode(this.arduino);
+        if (typeof this.serverConfig === "object") {
+            this.board = this.serverConfig.board;
+            var node = this;
+            node.status({fill:"red",shape:"ring",text:"connecting"});
+
+            node.board.on('connect', function() {
+                node.status({fill:"green",shape:"dot",text:"connected"});
+                //console.log("o",node.state,node.pin);
+                node.board.pinMode(node.pin, node.state);
+                node.on("input", function(msg) {
+                    if (node.state == "OUTPUT") {
+                        if ((msg.payload == true)||(msg.payload == 1)||(msg.payload.toString().toLowerCase() == "on")) {
+                            node.board.digitalWrite(node.pin, true);
+                        }
+                        if ((msg.payload == false)||(msg.payload == 0)||(msg.payload.toString().toLowerCase() == "off")) {
+                            node.board.digitalWrite(node.pin, false);
+                        }
+                    }
+                    if (node.state == "PWM") {
+                        msg.payload = msg.payload * 1;
+                        if ((msg.payload >= 0) && (msg.payload <= 255)) {
+                            //console.log(msg.payload, node.pin);
+                            node.board.servoWrite(node.pin, msg.payload);
+                        }
+                    }
+                    if (node.state == "SERVO") {
+                        msg.payload = msg.payload * 1;
+                        if ((msg.payload >= 0) && (msg.payload <= 180)) {
+                            //console.log(msg.payload, node.pin);
+                            node.board.servoWrite(node.pin, msg.payload);
+                        }
+                    }
+                });
+            });
+        }
+        else {
+            util.log("[Firmata-arduino] port not configured");
+        }
+    }
+    RED.nodes.registerType("arduino out",DuinoNodeOut);
+
+    RED.httpAdmin.get("/arduinoports",function(req,res) {
+        ArduinoFirmata.list(function (err, ports) {
+            //console.log(JSON.stringify(ports));
+            res.writeHead(200, {'Content-Type': 'text/plain'});
+            res.write(JSON.stringify(ports));
+            res.end();
+        });
+    });
+}
diff --git a/dgbuilder/core_nodes/hardware/36-rpi-gpio.html b/dgbuilder/core_nodes/hardware/36-rpi-gpio.html
new file mode 100644 (file)
index 0000000..9e705c2
--- /dev/null
@@ -0,0 +1,182 @@
+<!--
+  Copyright 2013,2014 IBM Corp.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<script type="text/x-red" data-template-name="rpi-gpio in">
+    <div class="form-row">
+        <label for="node-input-pin"><i class="fa fa-circle"></i> GPIO Pin</label>
+        <select type="text" id="node-input-pin" style="width: 200px;">
+            <option value="-" disabled>select pin </option>
+            <option value="3">3 - SDA1 </option>
+            <option value="5">5 - SCL1 </option>
+            <option value="7">7 - GPIO7</option>
+            <option value="8">8 - TxD </option>
+            <option value="10">10 - RxD </option>
+            <option value="11">11 - GPIO0</option>
+            <option value="12">12 - GPIO1</option>
+            <option value="13">13 - GPIO2</option>
+            <option value="15">15 - GPIO3</option>
+            <option value="16">16 - GPIO4</option>
+            <option value="18">18 - GPIO5</option>
+            <option value="19">19 - MOSI </option>
+            <option value="21">21 - MISO </option>
+            <option value="22">22 - GPIO6</option>
+            <option value="23">23 - SCLK </option>
+            <option value="24">24 - CE0 </option>
+            <option value="26">26 - CE1 </option>
+         </select>
+         &nbsp;<span id="pitype"></span>
+    </div>
+    <div class="form-row">
+        <label for="node-input-intype"><i class="fa fa-long-arrow-up"></i> Resistor?</label>
+        <select type="text" id="node-input-intype" style="width: 150px;">
+        <option value="tri">none</option>
+        <option value="up">pullup</option>
+        <option value="down">pulldown</option>
+        <!--<option value="tri">tristate</option>-->
+        </select>
+    </div>
+    <div class="form-row">
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+        <input type="text" id="node-input-name" placeholder="Name">
+    </div>
+    <div class="form-tips">Tip: Only Digital I/O is supported - input must be 0 or 1.</div>
+</script>
+
+<script type="text/x-red" data-help-name="rpi-gpio in">
+    <p>Raspberry Pi input node. Generates a <b>msg.payload</b> with either a 0 or 1 depending on the state of the input pin. Requires the gpio command to work.</p>
+    <p>You may also enable the input pullup resitor or the pulldown resistor.</p>
+    <p>The <b>msg.topic</b> is set to <i>pi/{the pin number}</i></p>
+    <p><b>Note:</b> we are using the actual physical pin numbers on connector P1 as they are easier to locate.</p>
+    <p><b>Note:</b> This node currently polls the pin every 250mS. This is not ideal as it loads the cpu, and will be rewritten shortly to try to use interrupts.</p>
+
+</script>
+
+<script type="text/javascript">
+    RED.nodes.registerType('rpi-gpio in',{
+        category: 'advanced-input',
+        color:"#c6dbef",
+        defaults: {
+            name: { value:"" },
+            intype: { value: "in" },
+            pin: { value:"",required:true,validate:RED.validators.number() },
+        },
+        inputs:0,
+        outputs:1,
+        icon: "rpi.png",
+        label: function() {
+            return this.name||"Pin: "+this.pin ;
+        },
+        labelStyle: function() {
+            return this.name?"node_label_italic":"";
+        },
+        oneditprepare: function() {
+            $.getJSON('rpi-gpio/'+this.id,function(data) {
+                $('#pitype').text(data.type);
+                if (data.type === "Model B+") {
+                    $('#node-input-pin').append($("<option></option>").attr("value",27).text("27 - SDA0"));
+                    $('#node-input-pin').append($("<option></option>").attr("value",28).text("28 - SCL0"));
+                    $('#node-input-pin').append($("<option></option>").attr("value",29).text("29 - GPIO21"));
+                    $('#node-input-pin').append($("<option></option>").attr("value",31).text("31 - GPIO22"));
+                    $('#node-input-pin').append($("<option></option>").attr("value",32).text("32 - GPIO26"));
+                    $('#node-input-pin').append($("<option></option>").attr("value",33).text("33 - GPIO23"));
+                    $('#node-input-pin').append($("<option></option>").attr("value",35).text("35 - GPIO24"));
+                    $('#node-input-pin').append($("<option></option>").attr("value",36).text("36 - GPIO27"));
+                    $('#node-input-pin').append($("<option></option>").attr("value",37).text("37 - GPIO25"));
+                    $('#node-input-pin').append($("<option></option>").attr("value",38).text("38 - GPIO28"));
+                    $('#node-input-pin').append($("<option></option>").attr("value",40).text("40 - GPIO29"));
+                }
+            });
+        }
+    });
+</script>
+
+
+<script type="text/x-red" data-template-name="rpi-gpio out">
+    <div class="form-row">
+        <label for="node-input-pin"><i class="fa fa-circle"></i> GPIO Pin</label>
+        <select type="text" id="node-input-pin" style="width: 200px;">
+            <option value="-">select pin </option>
+            <option value="3">3 - SDA1 </option>
+            <option value="5">5 - SCL1 </option>
+            <option value="7">7 - GPIO7</option>
+            <option value="8">8 - TxD </option>
+            <option value="10">10 - RxD </option>
+            <option value="11">11 - GPIO0</option>
+            <option value="12">12 - GPIO1</option>
+            <option value="13">13 - GPIO2</option>
+            <option value="15">15 - GPIO3</option>
+            <option value="16">16 - GPIO4</option>
+            <option value="18">18 - GPIO5</option>
+            <option value="19">19 - MOSI </option>
+            <option value="21">21 - MISO </option>
+            <option value="22">22 - GPIO6</option>
+            <option value="23">23 - SCLK </option>
+            <option value="24">24 - CE0 </option>
+            <option value="26">26 - CE1 </option>
+         </select>
+         &nbsp;<span id="pitype"></span>
+    </div>
+    <div class="form-row">
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+        <input type="text" id="node-input-name" placeholder="Name">
+    </div>
+    <div class="form-tips">Tip: Only Digital I/O is supported - input must be 0 or 1.</div>
+</script>
+
+<script type="text/x-red" data-help-name="rpi-gpio out">
+    <p>Raspberry Pi output node. Expects a <b>msg.payload</b> with either a 0 or 1 (or true or false). Requires the gpio command to work.</p>
+    <p>Will set the selected physical pin high or low depending on the value passed in.</p>
+    <p><b>Note:</b> we are using the actual physical pin numbers on connector P1 as they are easier to locate.</p>
+</script>
+
+<script type="text/javascript">
+    RED.nodes.registerType('rpi-gpio out',{
+        category: 'advanced-output',
+        color:"#c6dbef",
+        defaults: {
+            name: { value:"" },
+            pin: { value:"",required:true,validate:RED.validators.number() },
+        },
+        inputs:1,
+        outputs:0,
+        icon: "rpi.png",
+        align: "right",
+        label: function() {
+            return this.name||"Pin: "+this.pin;
+        },
+        labelStyle: function() {
+            return this.name?"node_label_italic":"";
+        },
+        oneditprepare: function() {
+            $.getJSON('rpi-gpio/'+this.id,function(data) {
+                $('#pitype').text(data.type);
+                if (data.type === "Model B+") {
+                    $('#node-input-pin').append($("<option></option>").attr("value",27).text("27 - SDA0"));
+                    $('#node-input-pin').append($("<option></option>").attr("value",28).text("28 - SCL0"));
+                    $('#node-input-pin').append($("<option></option>").attr("value",29).text("29 - GPIO21"));
+                    $('#node-input-pin').append($("<option></option>").attr("value",31).text("31 - GPIO22"));
+                    $('#node-input-pin').append($("<option></option>").attr("value",32).text("32 - GPIO26"));
+                    $('#node-input-pin').append($("<option></option>").attr("value",33).text("33 - GPIO23"));
+                    $('#node-input-pin').append($("<option></option>").attr("value",35).text("35 - GPIO24"));
+                    $('#node-input-pin').append($("<option></option>").attr("value",36).text("36 - GPIO27"));
+                    $('#node-input-pin').append($("<option></option>").attr("value",37).text("37 - GPIO25"));
+                    $('#node-input-pin').append($("<option></option>").attr("value",38).text("38 - GPIO28"));
+                    $('#node-input-pin').append($("<option></option>").attr("value",40).text("40 - GPIO29"));
+                }
+            });
+        }
+    });
+</script>
diff --git a/dgbuilder/core_nodes/hardware/36-rpi-gpio.js b/dgbuilder/core_nodes/hardware/36-rpi-gpio.js
new file mode 100644 (file)
index 0000000..93cbc4e
--- /dev/null
@@ -0,0 +1,185 @@
+/**
+ * Copyright 2013 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+module.exports = function(RED) {
+    "use strict";
+    var util = require("util");
+    var exec = require('child_process').exec;
+    var fs =  require('fs');
+
+    var gpioCommand = '/usr/local/bin/gpio';
+
+    if (!fs.existsSync("/dev/ttyAMA0")) { // unlikely if not on a Pi
+        throw "Info : Ignoring Raspberry Pi specific node.";
+    }
+
+    if (!fs.existsSync(gpioCommand)) { // gpio command not installed
+        throw "Info : Can't find Raspberry Pi wiringPi gpio command.";
+    }
+
+    // Map physical P1 pins to Gordon's Wiring-Pi Pins (as they should be V1/V2 tolerant)
+    var pintable = {
+    // Physical : WiringPi
+            "11":"0",
+            "12":"1",
+            "13":"2",
+            "15":"3",
+            "16":"4",
+            "18":"5",
+            "22":"6",
+             "7":"7",
+             "3":"8",
+             "5":"9",
+            "24":"10",
+            "26":"11",
+            "19":"12",
+            "21":"13",
+            "23":"14",
+             "8":"15",
+            "10":"16",
+            "27":"30",
+            "28":"31",
+            "29":"21",
+            "31":"22",
+            "32":"26",
+            "33":"23",
+            "35":"24",
+            "36":"27",
+            "37":"25",
+            "38":"28",
+            "40":"29"
+    }
+    var tablepin = {
+    // WiringPi : Physical
+            "0":"11",
+            "1":"12",
+            "2":"13",
+            "3":"15",
+            "4":"16",
+            "5":"18",
+            "6":"22",
+            "7":"7",
+            "8":"3",
+            "9":"5",
+           "10":"24",
+           "11":"26",
+           "12":"19",
+           "13":"21",
+           "14":"23",
+           "15":"8",
+           "16":"10",
+           "30":"27",
+           "31":"28",
+           "21":"29",
+           "22":"31",
+           "26":"32",
+           "23":"33",
+           "24":"35",
+           "27":"36",
+           "25":"37",
+           "28":"38",
+           "29":"40"
+    }
+
+    function GPIOInNode(n) {
+        RED.nodes.createNode(this,n);
+        this.buttonState = -1;
+        this.pin = pintable[n.pin];
+        this.intype = n.intype;
+        var node = this;
+
+        if (node.pin !== undefined) {
+            exec(gpioCommand+" mode "+node.pin+" "+node.intype, function(err,stdout,stderr) {
+                if (err) { node.error(err); }
+                else {
+                    node._interval = setInterval( function() {
+                        exec(gpioCommand+" read "+node.pin, function(err,stdout,stderr) {
+                            if (err) { node.error(err); }
+                            else {
+                                if (node.buttonState !== Number(stdout)) {
+                                    var previousState = node.buttonState;
+                                    node.buttonState = Number(stdout);
+                                    if (previousState !== -1) {
+                                        var msg = {topic:"pi/"+tablepin[node.pin], payload:node.buttonState};
+                                        node.send(msg);
+                                    }
+                                }
+                            }
+                        });
+                    }, 250);
+                }
+            });
+        }
+        else {
+            node.error("Invalid GPIO pin: "+node.pin);
+        }
+
+        node.on("close", function() {
+            clearInterval(node._interval);
+        });
+    }
+
+    function GPIOOutNode(n) {
+        RED.nodes.createNode(this,n);
+        this.pin = pintable[n.pin];
+        var node = this;
+
+        if (node.pin !== undefined) {
+            process.nextTick(function() {
+                exec(gpioCommand+" mode "+node.pin+" out", function(err,stdout,stderr) {
+                    if (err) { node.error(err); }
+                    else {
+                        node.on("input", function(msg) {
+                            if (msg.payload === "true") { msg.payload = true; }
+                            if (msg.payload === "false") { msg.payload = false; }
+                            var out = Number(msg.payload);
+                            if ((out === 0)|(out === 1)) {
+                                exec(gpioCommand+" write "+node.pin+" "+out, function(err,stdout,stderr) {
+                                    if (err) { node.error(err); }
+                                });
+                            }
+                            else { node.warn("Invalid input - not 0 or 1"); }
+                        });
+                    }
+                });
+            });
+        }
+        else {
+            node.error("Invalid GPIO pin: "+node.pin);
+        }
+
+        node.on("close", function() {
+            exec(gpioCommand+" mode "+node.pin+" in");
+        });
+    }
+
+    var pitype = { type:"" };
+    exec(gpioCommand+" -v | grep Type", function(err,stdout,stderr) {
+        if (err) {
+            util.log('[36-rpi-gpio.js] Error: "'+gpioCommand+' -v" command failed for some reason.');
+        }
+        else {
+            pitype = { type:(stdout.split(","))[0].split(": ")[1], rev:(stdout.split(","))[1].split(": ")[1] };
+        }
+    });
+
+    RED.nodes.registerType("rpi-gpio in",GPIOInNode);
+    RED.nodes.registerType("rpi-gpio out",GPIOOutNode);
+
+    RED.httpAdmin.get('/rpi-gpio/:id',function(req,res) {
+        res.send( JSON.stringify(pitype) );
+    });
+}
diff --git a/dgbuilder/core_nodes/io/10-mqtt.html b/dgbuilder/core_nodes/io/10-mqtt.html
new file mode 100644 (file)
index 0000000..2ff5eb2
--- /dev/null
@@ -0,0 +1,157 @@
+<!--
+  Copyright 2013,2014 IBM Corp.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<script type="text/x-red" data-template-name="mqtt in">
+    <div class="form-row">
+        <label for="node-input-broker"><i class="fa fa-globe"></i> Broker</label>
+        <input type="text" id="node-input-broker">
+    </div>
+    <div class="form-row">
+        <label for="node-input-topic"><i class="fa fa-tasks"></i> Topic</label>
+        <input type="text" id="node-input-topic" placeholder="Topic">
+    </div>
+    <div class="form-row">
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+        <input type="text" id="node-input-name" placeholder="Name">
+    </div>
+</script>
+
+<script type="text/x-red" data-help-name="mqtt in">
+    <p>MQTT input node. Connects to a broker and subscribes to the specified topic. The topic may contain MQTT wildcards.</p>
+    <p>Outputs an object called <b>msg</b> containing <b>msg.topic, msg.payload, msg.qos</b> and <b>msg.retain</b>.</p>
+    <p><b>msg.payload</b> is a String.</p>
+</script>
+
+<script type="text/javascript">
+    RED.nodes.registerType('mqtt in',{
+        category: 'input',
+        defaults: {
+            name: {value:""},
+            topic: {value:"",required:true},
+            broker: {type:"mqtt-broker", required:true}
+        },
+        color:"#d8bfd8",
+        inputs:0,
+        outputs:1,
+        icon: "bridge.png",
+        label: function() {
+            return this.name||this.topic||"mqtt";
+        },
+        labelStyle: function() {
+            return this.name?"node_label_italic":"";
+        }
+    });
+</script>
+
+<script type="text/x-red" data-template-name="mqtt out">
+    <div class="form-row">
+        <label for="node-input-broker"><i class="fa fa-globe"></i> Broker</label>
+        <input type="text" id="node-input-broker">
+    </div>
+    <div class="form-row">
+        <label for="node-input-topic"><i class="fa fa-tasks"></i> Topic</label>
+        <input type="text" id="node-input-topic" placeholder="Topic">
+    </div>
+    <div class="form-row">
+        <label for="node-input-qos"><i class="fa fa-empire"></i> QoS</label>
+        <select id="node-input-qos" style="width:125px !important">
+            <option value=""></option>
+            <option value="0">0</option>
+            <option value="1">1</option>
+            <option value="2">2</option>
+        </select>
+        &nbsp;&nbsp;<i class="fa fa-history"></i>&nbsp;Retain &nbsp;<select id="node-input-retain" style="width:125px !important">
+            <option value=""></option>
+            <option value="false">false</option>
+            <option value="true">true</option>
+        </select>
+    </div>
+    <div class="form-row">
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+        <input type="text" id="node-input-name" placeholder="Name">
+    </div>
+    <div class="form-tips">Tip: Leave topic, qos or retain blank if you want to set them via msg properties.</div>
+</script>
+
+<script type="text/x-red" data-help-name="mqtt out">
+    <p>Connects to a MQTT broker and publishes <b>msg.payload</b> either to the <b>msg.topic</b> or to the topic specified in the edit window. The value in the edit window has precedence.</p>
+    <p>Likewise QoS and/or retain values in the edit panel will overwrite any <b>msg.qos</b> and <b>msg.retain</b> properties. If nothing is set they default to <i>0</i> and <i>false</i> respectively.</p>
+    <p>If <b>msg.payload</b> contains an object it will be stringified before being sent.</p>
+</script>
+
+<script type="text/javascript">
+    RED.nodes.registerType('mqtt out',{
+        category: 'output',
+        defaults: {
+            name: {value:""},
+            topic: {value:""},
+            qos: {value:""},
+            retain: {value:""},
+            broker: {type:"mqtt-broker", required:true}
+        },
+        color:"#d8bfd8",
+        inputs:1,
+        outputs:0,
+        icon: "bridge.png",
+        align: "right",
+        label: function() {
+            return this.name||this.topic||"mqtt";
+        },
+        labelStyle: function() {
+            return this.name?"node_label_italic":"";
+        }
+    });
+</script>
+
+<script type="text/x-red" data-template-name="mqtt-broker">
+    <div class="form-row node-input-broker">
+        <label for="node-config-input-broker"><i class="fa fa-globe"></i> Broker</label>
+        <input class="input-append-left" type="text" id="node-config-input-broker" placeholder="localhost" style="width: 40%;" >
+        <label for="node-config-input-port" style="margin-left: 10px; width: 35px; "> Port</label>
+        <input type="text" id="node-config-input-port" placeholder="Port" style="width:45px">
+    </div>
+    <div class="form-row">
+        <label for="node-config-input-clientid"><i class="fa fa-tag"></i> Client ID</label>
+        <input type="text" id="node-config-input-clientid" placeholder="Leave blank for auto generated">
+    </div>
+    <div class="form-row">
+        <label for="node-config-input-user"><i class="fa fa-user"></i> Username</label>
+        <input type="text" id="node-config-input-user">
+    </div>
+    <div class="form-row">
+        <label for="node-config-input-password"><i class="fa fa-lock"></i> Password</label>
+        <input type="password" id="node-config-input-password">
+    </div>
+</script>
+
+<script type="text/javascript">
+    RED.nodes.registerType('mqtt-broker',{
+        category: 'config',
+        defaults: {
+            broker: {value:"",required:true},
+            port: {value:1883,required:true,validate:RED.validators.number()},
+            clientid: { value:"" }
+        },
+        credentials: {
+            user: {type:"text"},
+            password: {type: "password"}
+        },
+        label: function() {
+            if (this.broker == "") { this.broker = "localhost"; }
+            return (this.clientid?this.clientid+"@":"")+this.broker+":"+this.port;
+        }
+    });
+</script>
diff --git a/dgbuilder/core_nodes/io/10-mqtt.js b/dgbuilder/core_nodes/io/10-mqtt.js
new file mode 100644 (file)
index 0000000..c8bc490
--- /dev/null
@@ -0,0 +1,119 @@
+/**
+ * Copyright 2013,2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+module.exports = function(RED) {
+    "use strict";
+    var connectionPool = require("./lib/mqttConnectionPool");
+
+    function MQTTBrokerNode(n) {
+        RED.nodes.createNode(this,n);
+        this.broker = n.broker;
+        this.port = n.port;
+        this.clientid = n.clientid;
+        if (this.credentials) {
+            this.username = this.credentials.user;
+            this.password = this.credentials.password;
+        }
+    }
+    RED.nodes.registerType("mqtt-broker",MQTTBrokerNode,{
+        credentials: {
+            user: {type:"text"},
+            password: {type: "password"}
+        }
+    });
+
+    function MQTTInNode(n) {
+        RED.nodes.createNode(this,n);
+        this.topic = n.topic;
+        this.broker = n.broker;
+        this.brokerConfig = RED.nodes.getNode(this.broker);
+        if (this.brokerConfig) {
+            this.status({fill:"red",shape:"ring",text:"disconnected"});
+            this.client = connectionPool.get(this.brokerConfig.broker,this.brokerConfig.port,this.brokerConfig.clientid,this.brokerConfig.username,this.brokerConfig.password);
+            var node = this;
+            this.client.subscribe(this.topic,2,function(topic,payload,qos,retain) {
+                    var msg = {topic:topic,payload:payload,qos:qos,retain:retain};
+                    if ((node.brokerConfig.broker == "localhost")||(node.brokerConfig.broker == "127.0.0.1")) {
+                        msg._topic = topic;
+                    }
+                    node.send(msg);
+            });
+            this.client.on("connectionlost",function() {
+                node.status({fill:"red",shape:"ring",text:"disconnected"});
+            });
+            this.client.on("connect",function() {
+                node.status({fill:"green",shape:"dot",text:"connected"});
+            });
+            this.client.connect();
+        } else {
+            this.error("missing broker configuration");
+        }
+        this.on('close', function() {
+            if (this.client) {
+                this.client.disconnect();
+            }
+        });
+    }
+    RED.nodes.registerType("mqtt in",MQTTInNode);
+
+    function MQTTOutNode(n) {
+        RED.nodes.createNode(this,n);
+        this.topic = n.topic;
+        this.qos = n.qos || null;
+        this.retain = n.retain;
+        this.broker = n.broker;
+        this.brokerConfig = RED.nodes.getNode(this.broker);
+
+        if (this.brokerConfig) {
+            this.status({fill:"red",shape:"ring",text:"disconnected"},true);
+            this.client = connectionPool.get(this.brokerConfig.broker,this.brokerConfig.port,this.brokerConfig.clientid,this.brokerConfig.username,this.brokerConfig.password);
+            var node = this;
+            this.on("input",function(msg) {
+                if (msg.qos) {
+                    msg.qos = parseInt(msg.qos);
+                    if ((msg.qos !== 0) && (msg.qos !== 1) && (msg.qos !== 2)) {
+                        msg.qos = null;
+                    }
+                }
+                msg.qos = Number(node.qos || msg.qos || 0);
+                msg.retain = node.retain || msg.retain || false;
+                msg.retain = ((msg.retain === true) || (msg.retain === "true")) || false;
+                if (node.topic) {
+                    msg.topic = node.topic;
+                }
+                if ((msg.hasOwnProperty("topic")) && (typeof msg.topic === "string") && (msg.topic !== "")) { // topic must exist
+                    this.client.publish(msg);  // send the message
+                }
+                else { node.warn("Invalid topic specified"); }
+            });
+            this.client.on("connectionlost",function() {
+                node.status({fill:"red",shape:"ring",text:"disconnected"});
+            });
+            this.client.on("connect",function() {
+                node.status({fill:"green",shape:"dot",text:"connected"});
+            });
+            this.client.connect();
+        } else {
+            this.error("missing broker configuration");
+        }
+        this.on('close', function() {
+            if (this.client) {
+                this.client.disconnect();
+            }
+        });
+    }
+    RED.nodes.registerType("mqtt out",MQTTOutNode);
+}
diff --git a/dgbuilder/core_nodes/io/21-httpin.html b/dgbuilder/core_nodes/io/21-httpin.html
new file mode 100644 (file)
index 0000000..059b859
--- /dev/null
@@ -0,0 +1,254 @@
+<!--
+  Copyright 2013 IBM Corp.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<script type="text/x-red" data-template-name="http in">
+    <div class="form-row">
+        <label for="node-input-method"><i class="fa fa-tasks"></i> Method</label>
+        <select type="text" id="node-input-method" style="width:72%;">
+        <option value="get">GET</option>
+        <option value="post">POST</option>
+        <option value="put">PUT</option>
+        <option value="delete">DELETE</option>
+        </select>
+    </div>
+    <div class="form-row">
+        <label for="node-input-url"><i class="fa fa-globe"></i> url</label>
+        <input type="text" id="node-input-url" placeholder="/url">
+    </div>
+    <div class="form-row">
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+        <input type="text" id="node-input-name" placeholder="Name">
+    </div>
+    <div id="node-input-tip" class="form-tips">The url will be relative to <code><span id="node-input-path"></span></code>.</div>
+</script>
+
+<script type="text/x-red" data-help-name="http in">
+    <p>Provides an input node for http requests, allowing the creation of simple web services.</p>
+    <p>The resulting message has the following properties:
+        <ul>
+            <li>msg.req : <a href="http://expressjs.com/api.html#req">http request</a></li>
+            <li>msg.res : <a href="http://expressjs.com/api.html#res">http response</a></li>
+        </ul>
+    </p>
+    <p>For POST/PUT requests, the body is available under <code>msg.req.body</code>. This
+       uses the <a href="http://expressjs.com/api.html#bodyParser">Express bodyParser middleware</a> to parse the content to a JSON object.
+    </p>
+    <p>
+       By default, this expects the body of the request to be url encoded:
+       <pre>foo=bar&amp;this=that</pre>
+    </p>
+    <p>
+       To send JSON encoded data to the node, the content-type header of the request must be set to
+       <code>application/json</code>.
+    </p>
+    <p>
+       <b>Note: </b>This node does not send any response to the http request. This should be done with
+       a subsequent HTTP Response node, or Function node.
+       In the case of a Function node, the <a href="http://expressjs.com/api.html#res">Express response documentation</a>
+       describes how this should be done. For example:
+       <pre>msg.res.send(200, 'Thanks for the request ');<br/>return msg;</pre>
+    </p>
+
+</script>
+
+<script type="text/x-red" data-template-name="http response">
+    <div class="form-row">
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+        <input type="text" id="node-input-name" placeholder="Name">
+    </div>
+    <div class="form-tips">The messages sent to this node <b>must</b> originate from an <i>http input</i> node</div>
+</script>
+
+<script type="text/x-red" data-help-name="http response">
+    <p>Sends responses back to http requests received from an HTTP Input node.</p>
+    <p>The response can be customised using the following message properties:</p>
+    <ul>
+        <li><code>payload</code> is sent as the body of the response</li>
+        <li><code>statusCode</code>, if set, is used as the response status code (default: 200)</li>
+        <li><code>headers</code>, if set, should be an object containing field/value
+        pairs to be added as response headers.</li>
+    </ul>
+</script>
+
+<script type="text/x-red" data-template-name="http request">
+    <div class="form-row">
+        <label for="node-input-method"><i class="fa fa-tasks"></i> Method</label>
+        <select type="text" id="node-input-method" style="width:72%;">
+        <option value="GET">GET</option>
+        <option value="POST">POST</option>
+        <option value="PUT">PUT</option>
+        <option value="DELETE">DELETE</option>
+        </select>
+    </div>
+    <div class="form-row">
+        <label for="node-input-url"><i class="fa fa-globe"></i> URL</label>
+        <input type="text" id="node-input-url" placeholder="http://">
+    </div>
+    <div class="form-row">
+        <label>&nbsp;</label>
+        <input type="checkbox" id="node-input-useAuth" style="display: inline-block; width: auto; vertical-align: top;">
+        <label for="node-input-useAuth" style="width: 70%;">Use basic authentication?</label>
+    </div>
+    <div class="form-row node-input-useAuth-row">
+        <label for="node-input-user"><i class="fa fa-user"></i> Username</label>
+        <input type="text" id="node-input-user">
+    </div>
+    <div class="form-row node-input-useAuth-row">
+        <label for="node-input-password"><i class="fa fa-lock"></i> Password</label>
+        <input type="password" id="node-input-password">
+    </div>
+    <div class="form-row">
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+        <input type="text" id="node-input-name" placeholder="Name">
+    </div>
+</script>
+
+<script type="text/x-red" data-help-name="http request">
+    <p>Provides a node for making http requests.</p>
+    <p>The URL and HTTP method can be configured in the node, but also
+       overridden by the incoming message:
+    <ul>
+        <li><code>url</code>, if set, is used as the url of the request. Must start with http: or https:</li>
+        <li><code>method</code>, if set, is used as the HTTP method of the request.
+        Must be one of <code>GET</code>, <code>PUT</code>, <code>POST</code> or <code>DELETE</code> (default: GET)</li>
+        <li><code>headers</code>, if set, should be an object containing field/value
+        pairs to be added as request headers</li>
+        <li><code>payload</code> is sent as the body of the request</li>
+    </ul>
+    <p>When configured within the node, the URL property can contain <a href="http://mustache.github.io/mustache.5.html" target="_new">mustache-style</a> tags. These allow the
+    url to be constructed using values of the incoming message. For example, if the url is set to
+    <code>example.com/{{topic}}</code>, it will have the value of <code>msg.topic</code> automatically inserted.</p>
+    <p>
+    The output message contains the following properties:
+    <ul>
+        <li><code>payload</code> is the body of the response</li>
+        <li><code>statusCode</code> is the status code of the response, or the error code if the request could not be completed</li>
+        <li><code>headers</code> is an object containing the response headers</li>
+    </ul>
+</script>
+
+<script type="text/javascript">
+    RED.nodes.registerType('http in',{
+        category: 'input',
+        color:"rgb(231, 231, 174)",
+        defaults: {
+            name: {value:""},
+            url: {value:"",required:true},
+            method: {value:"get",required:true}
+        },
+        inputs:0,
+        outputs:1,
+        icon: "white-globe.png",
+        label: function() {
+            if (this.name) {
+                return this.name;
+            } else if (this.url) {
+                var root = RED.settings.httpNodeRoot;
+                if (root.slice(-1) != "/") { 
+                    root = root+"/";
+                }
+                if (this.url.charAt(0) == "/") {
+                    root += this.url.slice(1);
+                } else {
+                    root += this.url;
+                }
+                return "["+this.method+"] "+root;
+            } else {
+                return "http";
+            }
+        },
+        labelStyle: function() {
+            return this.name?"node_label_italic":"";
+        },
+        oneditprepare: function() {
+            var root = RED.settings.httpNodeRoot;
+            if (root.slice(-1) == "/") { 
+                root = root.slice(0,-1);
+            }
+            if (root == "") {
+                $("#node-input-tip").hide();
+            } else {
+                $("#node-input-path").html(root);
+                $("#node-input-tip").show();
+            }
+            //document.getElementById("node-config-wsdocpath").innerHTML=
+        }
+
+    });
+
+    RED.nodes.registerType('http response',{
+        category: 'output',
+        color:"rgb(231, 231, 174)",
+        defaults: {
+            name: {value:""}
+        },
+        inputs:1,
+        outputs:0,
+        align: "right",
+        icon: "white-globe.png",
+        label: function() {
+            return this.name||"http";
+        },
+        labelStyle: function() {
+            return this.name?"node_label_italic":"";
+        }
+    });
+
+    RED.nodes.registerType('http request',{
+        category: 'function',
+        color:"rgb(231, 231, 174)",
+        defaults: {
+            name: {value:""},
+            method:{value:"GET"},
+            url:{value:""},
+            //user -> credentials
+            //pass -> credentials
+        },
+        credentials: {
+            user: {type:"text"},
+            password: {type: "password"}
+        },
+        inputs:1,
+        outputs:1,
+        align: "right",
+        icon: "white-globe.png",
+        label: function() {
+            return this.name||"http request";
+        },
+        labelStyle: function() {
+            return this.name?"node_label_italic":"";
+        },
+        oneditprepare: function() {
+            if (this.credentials.user || this.credentials.has_password) {
+                $('#node-input-useAuth').prop('checked', true);
+                $(".node-input-useAuth-row").show();
+            } else {
+                $('#node-input-useAuth').prop('checked', false);
+                $(".node-input-useAuth-row").hide();
+            }
+
+            $("#node-input-useAuth").change(function() {
+                if ($(this).is(":checked")) {
+                    $(".node-input-useAuth-row").show();
+                } else {
+                    $(".node-input-useAuth-row").hide();
+                    $('#node-input-user').val('');
+                    $('#node-input-password').val('');
+                }
+            });
+        },
+    });
+</script>
diff --git a/dgbuilder/core_nodes/io/21-httpin.js b/dgbuilder/core_nodes/io/21-httpin.js
new file mode 100644 (file)
index 0000000..877ccc0
--- /dev/null
@@ -0,0 +1,241 @@
+/**
+ * Copyright 2013,2014 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+module.exports = function(RED) {
+    "use strict";
+    var http = require("follow-redirects").http;
+    var https = require("follow-redirects").https;
+    var urllib = require("url");
+    var express = require("express");
+    var getBody = require('raw-body');
+    var mustache = require("mustache");
+    var querystring = require("querystring");
+
+    var cors = require('cors');
+    var jsonParser = express.json();
+    var urlencParser = express.urlencoded();
+
+    function rawBodyParser(req, res, next) {
+        if (req._body) { return next(); }
+        req.body = "";
+        req._body = true;
+        getBody(req, {
+            limit: '1mb',
+            length: req.headers['content-length'],
+            encoding: 'utf8'
+        }, function (err, buf) {
+            if (err) { return next(err); }
+            req.body = buf;
+            next();
+        });
+    }
+
+
+    function HTTPIn(n) {
+        RED.nodes.createNode(this,n);
+        if (RED.settings.httpNodeRoot !== false) {
+
+            this.url = n.url;
+            this.method = n.method;
+
+            var node = this;
+
+            this.errorHandler = function(err,req,res,next) {
+                node.warn(err);
+                res.send(500);
+            };
+
+            this.callback = function(req,res) {
+                if (node.method == "post") {
+                    node.send({req:req,res:res,payload:req.body});
+                } else if (node.method == "get") {
+                    node.send({req:req,res:res,payload:req.query});
+                } else {
+                    node.send({req:req,res:res});
+                }
+            }
+
+            var corsHandler = function(req,res,next) { next(); }
+
+            if (RED.settings.httpNodeCors) {
+                corsHandler = cors(RED.settings.httpNodeCors);
+                RED.httpNode.options(this.url,corsHandler);
+            }
+
+            if (this.method == "get") {
+                RED.httpNode.get(this.url,corsHandler,this.callback,this.errorHandler);
+            } else if (this.method == "post") {
+                RED.httpNode.post(this.url,corsHandler,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler);
+            } else if (this.method == "put") {
+                RED.httpNode.put(this.url,corsHandler,jsonParser,urlencParser,rawBodyParser,this.callback,this.errorHandler);
+            } else if (this.method == "delete") {
+                RED.httpNode.delete(this.url,corsHandler,this.callback,this.errorHandler);
+            }
+
+            this.on("close",function() {
+                var routes = RED.httpNode.routes[this.method];
+                for (var i = 0; i<routes.length; i++) {
+                    if (routes[i].path == this.url) {
+                        routes.splice(i,1);
+                        //break;
+                    }
+                }
+                if (RED.settings.httpNodeCors) {
+                    var route = RED.httpNode.route['options'];
+                    for (var j = 0; j<route.length; j++) {
+                        if (route[j].path == this.url) {
+                            route.splice(j,1);
+                            //break;
+                        }
+                    }
+                }
+            });
+        } else {
+            this.warn("Cannot create http-in node when httpNodeRoot set to false");
+        }
+    }
+    RED.nodes.registerType("http in",HTTPIn);
+
+
+    function HTTPOut(n) {
+        RED.nodes.createNode(this,n);
+        var node = this;
+        this.on("input",function(msg) {
+            if (msg.res) {
+                if (msg.headers) {
+                    msg.res.set(msg.headers);
+                }
+                var statusCode = msg.statusCode || 200;
+                if (typeof msg.payload == "object" && !Buffer.isBuffer(msg.payload)) {
+                    msg.res.jsonp(statusCode,msg.payload);
+                } else {
+                    if (msg.res.get('content-length') == null) {
+                        var len;
+                        if (msg.payload == null) {
+                            len = 0;
+                        } else if (typeof msg.payload == "number") {
+                            len = Buffer.byteLength(""+msg.payload);
+                        } else {
+                            len = Buffer.byteLength(msg.payload);
+                        }
+                        msg.res.set('content-length', len);
+                    }
+                    msg.res.send(statusCode,msg.payload);
+                }
+            } else {
+                node.warn("No response object");
+            }
+        });
+    }
+    RED.nodes.registerType("http response",HTTPOut);
+
+    function HTTPRequest(n) {
+        RED.nodes.createNode(this,n);
+        var nodeUrl = n.url;
+        var isTemplatedUrl = (nodeUrl||"").indexOf("{{") != -1;
+        var nodeMethod = n.method || "GET";
+        var node = this;
+        this.on("input",function(msg) {
+            node.status({fill:"blue",shape:"dot",text:"requesting"});
+            var url;
+            if (msg.url) {
+                url = msg.url;
+            } else if (isTemplatedUrl) {
+                url = mustache.render(nodeUrl,msg);
+            } else {
+                url = nodeUrl;
+            }
+            // url must start http:// or https:// so assume http:// if not set
+            if (!((url.indexOf("http://")===0) || (url.indexOf("https://")===0))) {
+                url = "http://"+url;
+            }
+
+            var method = (msg.method||nodeMethod).toUpperCase();
+            //node.log(method+" : "+url);
+            var opts = urllib.parse(url);
+            opts.method = method;
+            opts.headers = {};
+            if (msg.headers) {
+                for (var v in msg.headers) {
+                    if (msg.headers.hasOwnProperty(v)) {
+                        var name = v.toLowerCase();
+                        if (name !== "content-type" && name !== "content-length") {
+                            // only normalise the known headers used later in this
+                            // function. Otherwise leave them alone.
+                            name = v;
+                        }
+                        opts.headers[name] = msg.headers[v];
+                    }
+                }
+            }
+            if (this.credentials && this.credentials.user) {
+                opts.auth = this.credentials.user+":"+(this.credentials.password||"");
+            }
+            var payload = null;
+
+            if (msg.payload && (method == "POST" || method == "PUT") ) {
+                if (typeof msg.payload === "string" || Buffer.isBuffer(msg.payload)) {
+                    payload = msg.payload;
+                } else if (typeof msg.payload == "number") {
+                    payload = msg.payload+"";
+                } else {
+                    if (opts.headers['content-type'] == 'application/x-www-form-urlencoded') {
+                        payload = querystring.stringify(msg.payload);
+                    } else {
+                        payload = JSON.stringify(msg.payload);
+                        if (opts.headers['content-type'] == null) {
+                            opts.headers['content-type'] = "application/json";
+                        }
+                    }
+                }
+                if (opts.headers['content-length'] == null) {
+                    opts.headers['content-length'] = Buffer.byteLength(payload);
+                }
+            }
+
+            var req = ((/^https/.test(url))?https:http).request(opts,function(res) {
+                res.setEncoding('utf8');
+                msg.statusCode = res.statusCode;
+                msg.headers = res.headers;
+                msg.payload = "";
+                res.on('data',function(chunk) {
+                    msg.payload += chunk;
+                });
+                res.on('end',function() {
+                    node.send(msg);
+                    node.status({});
+                });
+            });
+            req.on('error',function(err) {
+                msg.payload = err.toString() + " : " + url;
+                msg.statusCode = err.code;
+                node.send(msg);
+                node.status({fill:"red",shape:"ring",text:err.code});
+            });
+            if (payload) {
+                req.write(payload);
+            }
+            req.end();
+        });
+    }
+
+    RED.nodes.registerType("http request",HTTPRequest,{
+        credentials: {
+            user: {type:"text"},
+            password: {type: "password"}
+        }
+    });
+}
diff --git a/dgbuilder/core_nodes/io/22-websocket.html b/dgbuilder/core_nodes/io/22-websocket.html
new file mode 100644 (file)
index 0000000..ff6ed74
--- /dev/null
@@ -0,0 +1,163 @@
+<!--\r
+  Copyright 2013 IBM Corp.\r
+\r
+  Licensed under the Apache License, Version 2.0 (the "License");\r
+  you may not use this file except in compliance with the License.\r
+  You may obtain a copy of the License at\r
+\r
+  http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+  Unless required by applicable law or agreed to in writing, software\r
+  distributed under the License is distributed on an "AS IS" BASIS,\r
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+  See the License for the specific language governing permissions and\r
+  limitations under the License.\r
+-->\r
+\r
+<!-- WebSocket Input Node -->\r
+<script type="text/x-red" data-template-name="websocket in">\r
+    <div class="form-row">\r
+        <label for="node-input-server"><i class="fa fa-bookmark"></i> Path</label>\r
+        <input type="text" id="node-input-server">\r
+    </div>\r
+    <div class="form-row">\r
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>\r
+        <input type="text" id="node-input-name" placeholder="Name">\r
+    </div>\r
+</script>\r
+\r
+<script type="text/x-red" data-help-name="websocket in">\r
+    <p>WebSocket input node.</p>\r
+    <p>By default, the data received from the WebSocket will be in <b>msg.payload</b>.\r
+    The listener can be configured to expect a properly formed JSON string, in which\r
+    case it will parse the JSON and send on the resulting object as the entire message.</p>\r
+</script>\r
+\r
+<script type="text/javascript">\r
+    RED.nodes.registerType('websocket in',{\r
+        category: 'input',\r
+        defaults: {\r
+            name: {value:""},\r
+            server: {type:"websocket-listener"}\r
+        },\r
+        color:"rgb(215, 215, 160)",\r
+        inputs:0,\r
+        outputs:1,\r
+        icon: "white-globe.png",\r
+        label: function() {\r
+            var wsNode = RED.nodes.node(this.server);\r
+            return this.name||(wsNode?"[ws] "+wsNode.label():"websocket");\r
+        },\r
+        labelStyle: function() {\r
+            return this.name?"node_label_italic":"";\r
+        }\r
+    });\r
+</script>\r
+\r
+<!-- WebSocket out Node -->\r
+<script type="text/x-red" data-template-name="websocket out">\r
+    <div class="form-row">\r
+        <label for="node-input-server"><i class="fa fa-bookmark"></i> Path</label>\r
+        <input type="text" id="node-input-server">\r
+    </div>\r
+    <div class="form-row">\r
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>\r
+        <input type="text" id="node-input-name" placeholder="Name">\r
+    </div>\r
+</script>\r
+\r
+<script type="text/x-red" data-help-name="websocket out">\r
+    <p>WebSocket out node.</p>\r
+    <p>By default, <b>msg.payload</b> will be sent over the WebSocket. The listener\r
+    can be configured to encode the entire message object as a JSON string and send that\r
+    over the WebSocket.</p>\r
+\r
+    <p>If the message arriving at this node started at a WebSocket In node, the message\r
+    will be sent back to the client that triggered the flow. Otherwise, the message\r
+    will be broadcast to all connected clients.</p>\r
+    <p>If you want to broadcast a message that started at a WebSocket In node, you\r
+    should delete the <b>msg._session</b> property within the flow</p>.\r
+</script>\r
+\r
+<script type="text/javascript">\r
+    RED.nodes.registerType('websocket out',{\r
+        category: 'output',\r
+        defaults: {\r
+            name: {value:""},\r
+            server: {type:"websocket-listener", required:true}\r
+        },\r
+        color:"rgb(215, 215, 160)",\r
+        inputs:1,\r
+        outputs:0,\r
+        icon: "white-globe.png",\r
+        align: "right",\r
+        label: function() {\r
+            var wsNode = RED.nodes.node(this.server);\r
+            return this.name||(wsNode?"[ws] "+wsNode.label():"websocket");\r
+        },\r
+        labelStyle: function() {\r
+            return this.name?"node_label_italic":"";\r
+        }\r
+    });\r
+</script>\r
+\r
+<!-- WebSocket Server configuration node -->\r
+<script type="text/x-red" data-template-name="websocket-listener">\r
+    <div class="form-row">\r
+        <label for="node-config-input-path"><i class="fa fa-bookmark"></i> Path</label>\r
+        <input type="text" id="node-config-input-path" placeholder="/ws/example">\r
+    </div>\r
+    <div class="form-row">\r
+        <label for="node-config-input-wholemsg">&nbsp;</label>\r
+        <select type="text" id="node-config-input-wholemsg" style="width: 70%;">\r
+            <option value="false">Send/Receive payload</option>\r
+            <option value="true">Send/Receive entire message</option>\r
+        </select>\r
+    </div>\r
+    <div class="form-tips">\r
+    Be default, <code>payload</code> will contain the data to be sent over, or received from a websocket.\r
+    The listener can be configured to send or receive the entire message object as a JSON formatted string.\r
+    <p id="node-config-ws-tip">This path will be relative to <code><span id="node-config-ws-path"></span></code>.</p>\r
+    </div>\r
+</script>\r
+\r
+<script type="text/x-red" data-help-name="websocket-listener">\r
+   <p>This configuration node creates a WebSocket Server using the specified path</p>\r
+</script>\r
+\r
+<script type="text/javascript">\r
+    RED.nodes.registerType('websocket-listener',{\r
+        category: 'config',\r
+        defaults: {\r
+            path: {value:"",required:true,validate:RED.validators.regex(/^((?!\/debug\/ws).)*$/) },\r
+            wholemsg: {value:"false"}\r
+        },\r
+        inputs:0,\r
+        outputs:0,\r
+        label: function() {\r
+            var root = RED.settings.httpNodeRoot;\r
+            if (root.slice(-1) != "/") { \r
+                root = root+"/";\r
+            }\r
+            if (this.path.charAt(0) == "/") {\r
+                root += this.path.slice(1);\r
+            } else {\r
+                root += this.path;\r
+            }\r
+            return root;\r
+        },\r
+        oneditprepare: function() {\r
+            var root = RED.settings.httpNodeRoot;\r
+            if (root.slice(-1) == "/") { \r
+                root = root.slice(0,-1);\r
+            }\r
+            if (root == "") {\r
+                $("#node-config-ws-tip").hide();\r
+            } else {\r
+                $("#node-config-ws-path").html(root);\r
+                $("#node-config-ws-tip").show();\r
+            }\r
+            //document.getElementById("node-config-wsdocpath").innerHTML=\r
+        }\r
+    });\r
+</script>\r
diff --git a/dgbuilder/core_nodes/io/22-websocket.js b/dgbuilder/core_nodes/io/22-websocket.js
new file mode 100644 (file)
index 0000000..72eda50
--- /dev/null
@@ -0,0 +1,185 @@
+/**\r
+ * Copyright 2013 IBM Corp.\r
+ *\r
+ * Licensed under the Apache License, Version 2.0 (the "License");\r
+ * you may not use this file except in compliance with the License.\r
+ * You may obtain a copy of the License at\r
+ *\r
+ * http://www.apache.org/licenses/LICENSE-2.0\r
+ *\r
+ * Unless required by applicable law or agreed to in writing, software\r
+ * distributed under the License is distributed on an "AS IS" BASIS,\r
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ * See the License for the specific language governing permissions and\r
+ * limitations under the License.\r
+ **/\r
+\r
+module.exports = function(RED) {\r
+    "use strict";\r
+    var ws = require("ws"),\r
+        inspect = require("sys").inspect;\r
+\r
+    // A node red node that sets up a local websocket server\r
+    function WebSocketListenerNode(n) {\r
+        // Create a RED node\r
+        RED.nodes.createNode(this,n);\r
+\r
+        var node = this;\r
+\r
+        // Store local copies of the node configuration (as defined in the .html)\r
+        node.path = n.path;\r
+        node.wholemsg = (n.wholemsg === "true");\r
+\r
+        node._inputNodes = [];    // collection of nodes that want to receive events\r
+\r
+        var path = RED.settings.httpNodeRoot || "/";\r
+        path = path + (path.slice(-1) == "/" ? "":"/") + (node.path.charAt(0) == "/" ? node.path.substring(1) : node.path);\r
+\r
+        // Workaround https://github.com/einaros/ws/pull/253\r
+        // Listen for 'newListener' events from RED.server\r
+        node._serverListeners = {};\r
+\r
+        var storeListener = function(/*String*/event,/*function*/listener){\r
+            if(event == "error" || event == "upgrade" || event == "listening"){\r
+                node._serverListeners[event] = listener;\r
+            }\r
+        }\r
+\r
+        node._clients = {};\r
+\r
+        RED.server.addListener('newListener',storeListener);\r
+\r
+        // Create a WebSocket Server\r
+        node.server = new ws.Server({server:RED.server,path:path});\r
+\r
+        // Workaround https://github.com/einaros/ws/pull/253\r
+        // Stop listening for new listener events\r
+        RED.server.removeListener('newListener',storeListener);\r
+\r
+        node.server.on('connection', function(socket){\r
+            var id = (1+Math.random()*4294967295).toString(16);\r
+            node._clients[id] = socket;\r
+            socket.on('close',function() {\r
+                delete node._clients[id];\r
+            });\r
+            socket.on('message',function(data,flags){\r
+                node.handleEvent(id,socket,'message',data,flags);\r
+            });\r
+            socket.on('error', function(err) {\r
+                node.warn("An error occured on the ws connection: "+inspect(err));\r
+            });\r
+        });\r
+\r
+        node.on("close", function() {\r
+            // Workaround https://github.com/einaros/ws/pull/253\r
+            // Remove listeners from RED.server\r
+            var listener = null;\r
+            for(var event in node._serverListeners) {\r
+                if (node._serverListeners.hasOwnProperty(event)) {\r
+                    listener = node._serverListeners[event];\r
+                    if(typeof listener === "function"){\r
+                        RED.server.removeListener(event,listener);\r
+                    }\r
+                }\r
+            }\r
+            node._serverListeners = {};\r
+            node.server.close();\r
+            node._inputNodes = [];\r
+        });\r
+    }\r
+    RED.nodes.registerType("websocket-listener",WebSocketListenerNode);\r
+\r
+    WebSocketListenerNode.prototype.registerInputNode = function(/*Node*/handler){\r
+        this._inputNodes.push(handler);\r
+    }\r
+\r
+    WebSocketListenerNode.prototype.handleEvent = function(id,/*socket*/socket,/*String*/event,/*Object*/data,/*Object*/flags){\r
+        var msg;\r
+        if (this.wholemsg) {\r
+            try {\r
+                msg = JSON.parse(data);\r
+            }\r
+            catch(err) {\r
+                msg = { payload:data };\r
+            }\r
+        } else {\r
+            msg = {\r
+                payload:data\r
+            };\r
+        }\r
+        msg._session = {type:"websocket",id:id};\r
+\r
+        for (var i = 0; i < this._inputNodes.length; i++) {\r
+            this._inputNodes[i].send(msg);\r
+        }\r
+    }\r
+\r
+    WebSocketListenerNode.prototype.broadcast = function(data){\r
+        try {\r
+            for (var i = 0; i < this.server.clients.length; i++) {\r
+                this.server.clients[i].send(data);\r
+            }\r
+        }\r
+        catch(e) { // swallow any errors\r
+            this.warn("ws:"+i+" : "+e);\r
+        }\r
+    }\r
+\r
+    WebSocketListenerNode.prototype.send = function(id,data) {\r
+        var session = this._clients[id];\r
+        if (session) {\r
+            try {\r
+                session.send(data);\r
+            }\r
+            catch(e) { // swallow any errors\r
+            }\r
+        }\r
+    }\r
+\r
+    function WebSocketInNode(n) {\r
+        RED.nodes.createNode(this,n);\r
+        this.server = n.server;\r
+        var node = this;\r
+        this.serverConfig = RED.nodes.getNode(this.server);\r
+        if (this.serverConfig) {\r
+            this.serverConfig.registerInputNode(this);\r
+        } else {\r
+            this.error("Missing server configuration");\r
+        }\r
+    }\r
+    RED.nodes.registerType("websocket in",WebSocketInNode);\r
+\r
+    function WebSocketOutNode(n) {\r
+        RED.nodes.createNode(this,n);\r
+        var node = this;\r
+        this.server = n.server;\r
+        this.serverConfig = RED.nodes.getNode(this.server);\r
+        if (!this.serverConfig) {\r
+            this.error("Missing server configuration");\r
+        }\r
+        this.on("input", function(msg) {\r
+            var payload;\r
+            if (this.serverConfig.wholemsg) {\r
+                delete msg._session;\r
+                payload = JSON.stringify(msg);\r
+            } else {\r
+                if (!Buffer.isBuffer(msg.payload)) { // if it's not a buffer make sure it's a string.\r
+                    payload = RED.util.ensureString(msg.payload);\r
+                }\r
+                else {\r
+                    payload = msg.payload;\r
+                }\r
+            }\r
+            if (msg._session && msg._session.type == "websocket") {\r
+                node.serverConfig.send(msg._session.id,payload);\r
+            } else {\r
+                node.serverConfig.broadcast(payload,function(error){\r
+                    if (!!error) {\r
+                        node.warn("An error occurred while sending:" + inspect(error));\r
+                    }\r
+                });\r
+            }\r
+        });\r
+    }\r
+    RED.nodes.registerType("websocket out",WebSocketOutNode);\r
+}\r
diff --git a/dgbuilder/core_nodes/io/23-watch.html b/dgbuilder/core_nodes/io/23-watch.html
new file mode 100644 (file)
index 0000000..8bf22be
--- /dev/null
@@ -0,0 +1,57 @@
+<!--
+  Copyright 2013 IBM Corp.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+-->
+
+<script type="text/x-red" data-template-name="watch">
+    <div class="form-row node-input-filename">
+         <label for="node-input-files"><i class="fa fa-file"></i> File(s)</label>
+         <input type="text" id="node-input-files" placeholder="File(s) or Directory">
+    </div>
+    <div class="form-row">
+        <label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
+        <input type="text" id="node-input-name" placeholder="Name">
+    </div>
+     <div id="node-input-tip" class="form-tips">On Windows you must use double slashes \\ in any directory names.</div>
+</script>
+
+<script type="text/x-red" data-help-name="watch">
+    <p>Watches a directory or file for any changes.</p>
+    <p>You can enter a list of comma separated directories or files if you like. You will need to put " around any that have spaces in.</p>
+    <p>On Windows you must use double slashes \\ in any directory names.</p>
+    <p>The full filename of the file that actually changed is put into <b>msg.payload</b>, while a stringified version of the watched criteria is returned in <b>msg.topic</b>.</p>
+    <p><b>msg.file</b> contains just the short filename of the file that changed.</p>
+    <p>Of course in Linux, <i>everything</i> could be a file and thus watched...</p>
+    <p><b>Note: </b>The directory or file must exist in order to be watched. If the file or directory gets deleted it may no longer be monitored even if it gets re-created.</p>
+</script>
+
+<script type="text/javascript">
+    RED.nodes.registerType('watch',{
+        category: 'advanced-input',
+        defaults: {
+            name: {value:""},
+            files: {value:"",required:true}
+        },
+        color:"BurlyWood",
+        inputs:0,
+        outputs:1,
+        icon: "watch.png",
+        label: function() {
+            return this.name||this.files;
+        },
+        labelStyle: function() {
+            return this.name?"node_label_italic":"";
+        }
+    });
+</script>
diff --git a/dgbuilder/core_nodes/io/23-watch.js b/dgbuilder/core_nodes/io/23-watch.js
new file mode 100644 (file)
index 0000000..8a17f5a
--- /dev/null
@@ -0,0 +1,51 @@
+/**
+ * Copyright 2013 IBM Corp.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ **/
+
+module.exports = function(RED) {
+    "use strict";
+    var Notify = require("fs.notify");
+    var fs = require("fs");
+    var sep = require("path").sep;
+
+    function WatchNode(n) {
+        RED.nodes.createNode(this,n);
+
+        this.files = n.files.split(",");
+        for (var f =0; f < this.files.length; f++) {
+            this.files[f] = this.files[f].trim();
+        }
+        this.p = (this.files.length == 1) ? this.files[0] : JSON.stringify(this.files);
+        var node = this;
+
+        var notifications = new Notify(node.files);
+        notifications.on('change', function (file, event, path) {
+            try {
+                if (fs.statSync(path).isDirectory()) { path = path + sep + file; }
+            } catch(e) { }
+            var msg = { payload: path, topic: node.p, file: file };
+            node.send(msg);
+        });
+
+        notifications.on('error', function (error, path) {
+            node.warn(error);
+        });
+
+        this.close = function() {
+            notifications.close();
+        }
+    }
+    RED.nodes.registerType("watch",WatchNode);
+}
diff --git a/dgbuilder/core_nodes/io/25-serial.html