Got to start somewhere
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
node_modules
|
||||||
|
credentials.json
|
||||||
|
flows*.json
|
3
.nodemonignore
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
.git/*
|
||||||
|
*.json
|
||||||
|
lib/*
|
51
INSTALL
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
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>
|
||||||
|
|
||||||
|
## 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://node-red.github.io/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
|
||||||
|
|
177
LICENSE
Normal file
@ -0,0 +1,177 @@
|
|||||||
|
|
||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
54
README.md
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# Node-RED
|
||||||
|
|
||||||
|
A visual tool for wiring the Internet of Things.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
Check out [INSTALL](INSTALL) for full instructions on getting started.
|
||||||
|
|
||||||
|
1. download the zip and unzip, or git clone
|
||||||
|
2. cd node-red
|
||||||
|
3. npm install
|
||||||
|
4. node red.js
|
||||||
|
5. Open [http://localhost:1880]
|
||||||
|
|
||||||
|
## Browser Support
|
||||||
|
|
||||||
|
The Node-RED editor runs in the browser. We routinely develop and test using
|
||||||
|
Chrome and Firefox. We have anecdotal evidence that it works in IE9.
|
||||||
|
|
||||||
|
We do not yet support mobile browsers, although that is high on our priority
|
||||||
|
list.
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
### Reporting issues
|
||||||
|
|
||||||
|
Please raise any bug reports or feature requests on the project's issue
|
||||||
|
tracker. Be sure to search the list to see if your issue has already
|
||||||
|
been raised.
|
||||||
|
|
||||||
|
### Creating new nodes
|
||||||
|
|
||||||
|
The plugin nature of Node-RED means anyone can create a new node to extend
|
||||||
|
its capabilities. Eventually, the nodes will be npm-installable, but we're not
|
||||||
|
there yet.
|
||||||
|
|
||||||
|
### Pull-Requests
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
## Authors
|
||||||
|
|
||||||
|
Node-RED is a creation of the IBM Emerging Technology Services team.
|
||||||
|
|
||||||
|
* Nick O'Leary [http://twitter.com/knolleary](@knolleary)
|
||||||
|
* Dave Conway-Jones [http://twitter.com/ceejay](@ceejay)
|
||||||
|
|
||||||
|
## Copyright and license
|
||||||
|
|
||||||
|
Copyright 2013 IBM Corp. under [the Apache 2.0 license](LICENSE).
|
76
nodes/99-sample.html.demo
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- Sample html file that corresponds to the 99-sample.js file -->
|
||||||
|
<!-- This creates and configures the onscreen elements of the node -->
|
||||||
|
|
||||||
|
<!-- First, the content of the edit dialog is defined. -->
|
||||||
|
|
||||||
|
<script type="text/x-red" data-template-name="sample">
|
||||||
|
<!-- data-template-name identifies the node type this is for -->
|
||||||
|
|
||||||
|
<!-- Each of the following divs creates a field in the edit dialog. -->
|
||||||
|
<!-- Generally, there should be an input for each property of the node. -->
|
||||||
|
<!-- The for and id attributes identify the corresponding property -->
|
||||||
|
<!-- (with the 'node-input-' prefix). -->
|
||||||
|
<!-- The available icon classes are defined in Twitter Bootstrap -->
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-topic"><i class="icon-tasks"></i> Topic</label>
|
||||||
|
<input type="text" id="node-input-topic" placeholder="Topic">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- By convention, most nodes have a 'name' property. The following div -->
|
||||||
|
<!-- provides the necessary field. -->
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<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="sample">
|
||||||
|
<!-- data-help-name identifies the node type this help is for -->
|
||||||
|
<!-- This content appears in the Info sidebar when a node is selected -->
|
||||||
|
<!-- The first <p> is used as the pop-up tool tip when hovering over a -->
|
||||||
|
<!-- node in the palette. -->
|
||||||
|
<p>Simple sample input node. Just sends a single message when it starts up.
|
||||||
|
This is not very useful.</p>
|
||||||
|
<p>Outputs an object called <b>msg</b> containing <b>msg.topic</b> and
|
||||||
|
<b>msg.payload</b>. msg.payload is a String.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- Finally, the node type is registered along with all of its properties -->
|
||||||
|
<!-- The example below shows a small subset of the properties that can be set-->
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('sample',{
|
||||||
|
category: 'input', // the palette category
|
||||||
|
defaults: { // defines the editable properties of the node
|
||||||
|
name: {value:""}, // along with default values.
|
||||||
|
topic: {value:"", required:true}
|
||||||
|
},
|
||||||
|
inputs:0, // set the number of inputs - only 0 or 1
|
||||||
|
outputs:1, // set the number of outputs - 0 to n
|
||||||
|
icon: "arrow-in.png", // set the icon (held in public/icons)
|
||||||
|
label: function() { // sets the default label contents
|
||||||
|
return this.name||this.topic||"sample";
|
||||||
|
},
|
||||||
|
labelStyle: function() { // sets the class to apply to the label
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
51
nodes/99-sample.js.demo
Normal file
@ -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.
|
||||||
|
**/
|
||||||
|
|
||||||
|
// Sample Node-RED node file
|
||||||
|
|
||||||
|
// Require main module
|
||||||
|
var RED = require("../../red/red");
|
||||||
|
|
||||||
|
// The main node definition - most things happen in here
|
||||||
|
function SampleNode(n) {
|
||||||
|
// Create a RED node
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
|
||||||
|
// Store local copies of the node configuration (as defined in the .html)
|
||||||
|
this.topic = n.topic;
|
||||||
|
|
||||||
|
// Do whatever you need to do in here - declare callbacks etc
|
||||||
|
// Note: this sample doesn't do anything much - it will only send
|
||||||
|
// this message once at startup...
|
||||||
|
// Look at other real nodes for some better ideas of what to do....
|
||||||
|
var msg = {};
|
||||||
|
msg.topic = node.topic;
|
||||||
|
msg.payload = "Hello world !"
|
||||||
|
|
||||||
|
// send out the message to the rest of the workspace.
|
||||||
|
this.send(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Register the node by name. This must be called before overriding any of the
|
||||||
|
// Node functions.
|
||||||
|
RED.nodes.registerType("sample",SampleNode);
|
||||||
|
|
||||||
|
|
||||||
|
SampleNode.prototype.close = function() {
|
||||||
|
// Called when the node is shutdown - eg on redeploy.
|
||||||
|
// Allows ports to be closed, connections dropped etc.
|
||||||
|
// eg: this.client.disconnect();
|
||||||
|
}
|
51
nodes/analysis/72-sentiment.html
Normal file
@ -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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script type="text/x-red" data-template-name="sentiment">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
<div class="form-tips">Adds <b>msg.sentiment.score</b> as the anaylsis result.
|
||||||
|
</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>Score can range from -5 to +5.</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>
|
32
nodes/analysis/72-sentiment.js
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
var sentiment = require('sentiment');
|
||||||
|
|
||||||
|
function SentimentNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
|
||||||
|
this.on("input", function(msg) {
|
||||||
|
var node = this;
|
||||||
|
sentiment(msg.payload, function (err, result) {
|
||||||
|
msg.sentiment = result;
|
||||||
|
node.send(msg);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("sentiment",SentimentNode);
|
57
nodes/analysis/72-wordpos.html
Normal file
@ -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="wordpos">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
<div class="form-tips">Adds <b>msg.pos</b> as the anaylsis result.
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="wordpos">
|
||||||
|
<p>Analyses <b>msg.payload</b> and classifies the part-of-speech of each word.</p>
|
||||||
|
<p>The resulting message has <b>msg.pos</b> added with the results:</p>
|
||||||
|
<pre>{
|
||||||
|
nouns:[],
|
||||||
|
verbs:[],
|
||||||
|
adjectives:[],
|
||||||
|
adverbs:[],
|
||||||
|
rest:[]
|
||||||
|
}</pre>
|
||||||
|
<p>Note: a word may appear in multiple POS (eg, 'great' is both a noun and an adjective)</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('wordpos',{
|
||||||
|
category: 'analysis-function',
|
||||||
|
color:"#E6E0F8",
|
||||||
|
defaults: {
|
||||||
|
name: {value:""},
|
||||||
|
},
|
||||||
|
inputs:1,
|
||||||
|
outputs:1,
|
||||||
|
icon: "arrow-in.png",
|
||||||
|
label: function() {
|
||||||
|
return this.name||"wordpos";
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
34
nodes/analysis/72-wordpos.js
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
var util = require("util");
|
||||||
|
var WordPos = require('wordpos');
|
||||||
|
|
||||||
|
var wordpos = new WordPos();
|
||||||
|
|
||||||
|
function WordPOSNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.on("input", function(msg) {
|
||||||
|
var node = this;
|
||||||
|
wordpos.getPOS(msg.payload, function (result) {
|
||||||
|
msg.pos = result;
|
||||||
|
node.send(msg);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("wordpos",WordPOSNode);
|
53
nodes/analysis/73-parsexml.html
Normal file
@ -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="icon-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: 'advanced-function',
|
||||||
|
color:"#E6E0F8",
|
||||||
|
defaults: {
|
||||||
|
useEyes: {value:"false"},
|
||||||
|
name: {value:""},
|
||||||
|
},
|
||||||
|
inputs:1,
|
||||||
|
outputs:1,
|
||||||
|
icon: "arrow-in.png",
|
||||||
|
label: function() {
|
||||||
|
return this.name||"xml2js";
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
45
nodes/analysis/73-parsexml.js
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
var util = require("util");
|
||||||
|
var parseString = require('xml2js').parseString;
|
||||||
|
var gotEyes = false;
|
||||||
|
try {
|
||||||
|
var eyes = require("eyes");
|
||||||
|
gotEyes = true;
|
||||||
|
} catch(e) {
|
||||||
|
util.log("[73-parsexml.js] Warning: Module 'eyes' not installed");
|
||||||
|
}
|
||||||
|
|
||||||
|
function Xml2jsNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.useEyes = n.useEyes;
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
this.on("input", function(msg) {
|
||||||
|
parseString(msg.payload, function (err, result) {
|
||||||
|
msg.payload = result;
|
||||||
|
node.send(msg);
|
||||||
|
if (node.useEyes == true) {
|
||||||
|
if (gotEyes == true) { eyes.inspect(msg); }
|
||||||
|
else { node.log(JSON.stringify(msg)); }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("xml2js",Xml2jsNode);
|
94
nodes/core/20-inject.html
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
<!--
|
||||||
|
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="inject">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-topic"><i class="icon-tasks"></i> Topic</label>
|
||||||
|
<input type="text" id="node-input-topic" placeholder="Topic">
|
||||||
|
</div>
|
||||||
|
<div class="form-row node-input-payload">
|
||||||
|
<label for="node-input-payload"><i class="icon-envelope"></i> Payload</label>
|
||||||
|
<input type="text" id="node-input-payload" placeholder="Payload">
|
||||||
|
</div>
|
||||||
|
<div class="form-row node-input-repeat">
|
||||||
|
<label for="node-input-repeat"><i class="icon-repeat"></i> Repeat (S)</label>
|
||||||
|
<input type="text" id="node-input-repeat" placeholder="0">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label> </label>
|
||||||
|
<input type="checkbox" id="node-input-once" placeholder="once" style="display: inline-block; width: auto; vertical-align: top;">
|
||||||
|
<label for="node-input-once" style="width: 70%;">Fire once at start ?</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
<div class="form-tips">Tip: Injects Date.now() if no payload set.<br/>Repeat interval blank or 0 means no repeat.</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="inject">
|
||||||
|
<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>
|
||||||
|
<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>
|
||||||
|
<p>The repeat function does what it says on the tin and continuously sends the payload every x seconds.</p>
|
||||||
|
<p>The Fire once at start option actually waits 50mS before firing to give other nodes a chance to instantiate properly.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('inject',{
|
||||||
|
category: 'input',
|
||||||
|
color:"#a6bbcf",
|
||||||
|
defaults: {
|
||||||
|
name: {value:""},
|
||||||
|
topic: {value:""},
|
||||||
|
payload: {value:""},
|
||||||
|
repeat: {value:""},
|
||||||
|
once: {value:false}
|
||||||
|
},
|
||||||
|
inputs:0,
|
||||||
|
outputs:1,
|
||||||
|
icon: "inject.png",
|
||||||
|
label: function() {
|
||||||
|
return this.name||this.topic||this.payload;
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
},
|
||||||
|
button: {
|
||||||
|
onclick: function() {
|
||||||
|
var label = this.name||this.payload;
|
||||||
|
d3.xhr("inject/"+this.id).post(function(err,resp) {
|
||||||
|
if (err) {
|
||||||
|
if (err.status == 404) {
|
||||||
|
RED.notify("<strong>Error</strong>: inject node not deployed","error");
|
||||||
|
} else {
|
||||||
|
RED.notify("<strong>Error</strong>: "+err.response,"error");
|
||||||
|
}
|
||||||
|
} else if (resp.status == 200) {
|
||||||
|
RED.notify("Successfully injected: "+label,"success");
|
||||||
|
} else {
|
||||||
|
if (resp) {
|
||||||
|
RED.notify("<strong>Error</strong>: "+resp,"error");
|
||||||
|
} else {
|
||||||
|
RED.notify("<strong>Error</strong>: no response from server","error");
|
||||||
|
}
|
||||||
|
console.log(err,resp);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
65
nodes/core/20-inject.js
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
/**
|
||||||
|
* Copyright 2013 IBM Corp.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
**/
|
||||||
|
|
||||||
|
var RED = require("../../red/red");
|
||||||
|
|
||||||
|
function InjectNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.topic = n.topic;
|
||||||
|
this.payload = n.payload;
|
||||||
|
this.repeat = n.repeat;
|
||||||
|
this.once = n.once;
|
||||||
|
var node = this;
|
||||||
|
this.interval_id = 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 );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.once) {
|
||||||
|
setTimeout( function(){ node.emit("input",{}); }, 50);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.on("input",function(msg) {
|
||||||
|
var msg = {topic:this.topic,payload:this.payload};
|
||||||
|
if (msg.payload == "") { msg.payload = Date.now(); }
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.app.post("/inject/:id", function(req,res) {
|
||||||
|
var node = RED.nodes.getNode(req.params.id);
|
||||||
|
if (node != null) {
|
||||||
|
node.receive();
|
||||||
|
res.send(200);
|
||||||
|
} else {
|
||||||
|
res.send(404);
|
||||||
|
}
|
||||||
|
});
|
238
nodes/core/58-debug.html
Normal file
@ -0,0 +1,238 @@
|
|||||||
|
<!--
|
||||||
|
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-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label> </label>
|
||||||
|
<input type="checkbox" id="node-input-complete" placeholder="Complete" style="display: inline-block; width: auto; vertical-align: top;">
|
||||||
|
<label for="node-input-complete" style="width: 70%;">Show complete msg object ?</label>
|
||||||
|
</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 under the Debug tab at the top of the sidebar.</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},
|
||||||
|
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: {
|
||||||
|
color: function() {
|
||||||
|
return (typeof this.active === 'undefined') ? ("#87a980" ) : (this.active ? "#87a980" : "#b9b9b9");
|
||||||
|
},
|
||||||
|
onclick: function() {
|
||||||
|
var label = this.name||"debug";
|
||||||
|
var node = this;
|
||||||
|
d3.xhr("debug/"+this.id).post(function(err,resp) {
|
||||||
|
if (err) {
|
||||||
|
if (err.status == 404) {
|
||||||
|
RED.notify("<strong>Error</strong>: debug node not deployed","error");
|
||||||
|
} else {
|
||||||
|
RED.notify("<strong>Error</strong>: "+err.response,"error");
|
||||||
|
}
|
||||||
|
} else if (resp.status == 200) {
|
||||||
|
RED.notify("Successfully activated: "+label,"success");
|
||||||
|
node.active = true;
|
||||||
|
node.dirty = true;
|
||||||
|
RED.view.redraw();
|
||||||
|
} else if (resp.status == 201) {
|
||||||
|
RED.notify("Successfully deactivated: "+label,"success");
|
||||||
|
node.active = false;
|
||||||
|
node.dirty = true;
|
||||||
|
RED.view.redraw();
|
||||||
|
} else {
|
||||||
|
if (resp) {
|
||||||
|
RED.notify("<strong>Error</strong>: "+resp,"error");
|
||||||
|
} else {
|
||||||
|
RED.notify("<strong>Error</strong>: no response from server","error");
|
||||||
|
}
|
||||||
|
console.log(err,resp);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
var a = 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="icon-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.toUTCString().substring(5,25)+"."+d.getMilliseconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
var sbc = document.getElementById("debug-content");
|
||||||
|
|
||||||
|
function debugConnect() {
|
||||||
|
//console.log("debug ws connecting");
|
||||||
|
var ws = new WebSocket("ws://"+location.hostname+":"+location.port+document.location.pathname+"/debug");
|
||||||
|
ws.onopen = function() {
|
||||||
|
//console.log("debug ws connected");
|
||||||
|
}
|
||||||
|
ws.onmessage = function(event) {
|
||||||
|
var o = JSON.parse(event.data);
|
||||||
|
//console.log(msg);
|
||||||
|
var msg = document.createElement("div");
|
||||||
|
msg.onmouseover = function() {
|
||||||
|
msg.style.borderRightColor = "#999";
|
||||||
|
RED.nodes.eachNode(function(node) {
|
||||||
|
if( node.id == o.id) {
|
||||||
|
node.highlighted = true;
|
||||||
|
node.dirty = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
RED.view.redraw();
|
||||||
|
};
|
||||||
|
msg.onmouseout = function() {
|
||||||
|
msg.style.borderRightColor = "";
|
||||||
|
RED.nodes.eachNode(function(node) {
|
||||||
|
if( node.id == o.id) {
|
||||||
|
node.highlighted = false;
|
||||||
|
node.dirty = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
RED.view.redraw();
|
||||||
|
};
|
||||||
|
var name = (o.name?o.name:o.id).toString().replace(/</g,"<").replace(/>/g,">");
|
||||||
|
var topic = (o.topic||"").toString().replace(/</g,"<").replace(/>/g,">");
|
||||||
|
var payload = (o.msg||"").toString().replace(/</g,"<").replace(/>/g,">");
|
||||||
|
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;
|
||||||
|
$(messages).append(msg);
|
||||||
|
if (atBottom) {
|
||||||
|
$(sbc).scrollTop(sbc.scrollHeight);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
ws.onclose = function() {
|
||||||
|
//console.log("debug ws closed");
|
||||||
|
setTimeout(debugConnect,1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
debugConnect();
|
||||||
|
|
||||||
|
$("#debug-tab-clear").click(function() {
|
||||||
|
$(".debug-message").remove();
|
||||||
|
RED.nodes.eachNode(function(node) {
|
||||||
|
node.highlighted = false;
|
||||||
|
node.dirty = true;
|
||||||
|
});
|
||||||
|
RED.view.redraw();
|
||||||
|
});
|
||||||
|
|
||||||
|
}();
|
||||||
|
</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: #caa;
|
||||||
|
}
|
||||||
|
.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>
|
97
nodes/core/58-debug.js
Normal file
@ -0,0 +1,97 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
|
||||||
|
var util = require("util");
|
||||||
|
var ws = require('ws');
|
||||||
|
var events = require("events");
|
||||||
|
|
||||||
|
function DebugNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.name = n.name;
|
||||||
|
this.complete = n.complete;
|
||||||
|
this.active = (n.active == null)||n.active;
|
||||||
|
this.on("input",function(msg) {
|
||||||
|
if (this.active) {
|
||||||
|
if (msg.payload instanceof Buffer) {
|
||||||
|
msg.payload = "(Buffer) "+msg.payload.toString();
|
||||||
|
}
|
||||||
|
if (this.complete) {
|
||||||
|
DebugNode.send({id:this.id,name:this.name,topic:msg.topic,msg:msg,_path:msg._path});
|
||||||
|
} else {
|
||||||
|
DebugNode.send({id:this.id,name:this.name,topic:msg.topic,msg:msg.payload,_path:msg._path});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("debug",DebugNode);
|
||||||
|
|
||||||
|
DebugNode.send = function(msg) {
|
||||||
|
if (msg.msg instanceof Error) {
|
||||||
|
msg.msg = msg.msg.toString();
|
||||||
|
} else if (typeof msg.msg === 'object') {
|
||||||
|
msg.msg = "(Object) "+JSON.stringify(msg.msg,null,1);
|
||||||
|
} else if (msg.msg == 0) msg.msg = "0";
|
||||||
|
|
||||||
|
for (var i in DebugNode.activeConnections) {
|
||||||
|
var ws = DebugNode.activeConnections[i];
|
||||||
|
try {
|
||||||
|
var p = JSON.stringify(msg);
|
||||||
|
ws.send(p);
|
||||||
|
} catch(err) {
|
||||||
|
util.log("[debug] ws error : "+err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugNode.activeConnections = [];
|
||||||
|
DebugNode.wsServer = new ws.Server({server:RED.server});
|
||||||
|
DebugNode.wsServer.on('connection',function(ws) {
|
||||||
|
DebugNode.activeConnections.push(ws);
|
||||||
|
ws.on('close',function() {
|
||||||
|
for (var i in DebugNode.activeConnections) {
|
||||||
|
if (DebugNode.activeConnections[i] === ws) {
|
||||||
|
DebugNode.activeConnections.splice(i,1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
DebugNode.logHandler = new events.EventEmitter();
|
||||||
|
DebugNode.logHandler.on("log",function(msg) {
|
||||||
|
if (msg.level == "warn" || msg.level == "error") {
|
||||||
|
DebugNode.send(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
RED.nodes.addLogHandler(DebugNode.logHandler);
|
||||||
|
|
||||||
|
RED.app.post("/debug/:id", function(req,res) {
|
||||||
|
var node = RED.nodes.getNode(req.params.id);
|
||||||
|
if (node != null) {
|
||||||
|
if (node.active) {
|
||||||
|
node.active = false;
|
||||||
|
res.send(201);
|
||||||
|
} else {
|
||||||
|
node.active = true;
|
||||||
|
res.send(200);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res.send(404);
|
||||||
|
}
|
||||||
|
});
|
63
nodes/core/75-exec.html
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<!--
|
||||||
|
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="icon-label"></i> Command</label>
|
||||||
|
<input type="text" id="node-input-command" placeholder="command">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-append"><i class="icon-label"></i> Append</label>
|
||||||
|
<input type="text" id="node-input-append" placeholder="extra input">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label> </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="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="exec">
|
||||||
|
<p>Call to a system command.<br/>This can be very dangerous...</p>
|
||||||
|
<p>Provides 3 outputs... stdout, stderr, and return code.</p>
|
||||||
|
<p>By default uses exec() which calls the command, waits 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 then returns a return code (on the 3rd output).</p>
|
||||||
|
<p>The optional append gets added to the command after the <b>msg.payload</b> (so you can do things like pipe etc.)</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;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
76
nodes/core/75-exec.js
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
|
||||||
|
var spawn = require('child_process').spawn;
|
||||||
|
var exec = require('child_process').exec;
|
||||||
|
|
||||||
|
function ExecNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.cmd = n.command;
|
||||||
|
this.append = n.append || "";
|
||||||
|
this.useSpawn = n.useSpawn;
|
||||||
|
|
||||||
|
var node = this;
|
||||||
|
this.on("input", function(msg) {
|
||||||
|
if (msg != null) {
|
||||||
|
|
||||||
|
if (this.useSpawn == true) {
|
||||||
|
// make the extra args into an array
|
||||||
|
// then prepend with the msg.payload
|
||||||
|
var arg = node.append.split(",");
|
||||||
|
if (msg.payload != " ") { arg.unshift(msg.payload); }
|
||||||
|
console.log(arg);
|
||||||
|
var ex = spawn(node.cmd,arg);
|
||||||
|
ex.stdout.on('data', function (data) {
|
||||||
|
//console.log('[exec] stdout: ' + data);
|
||||||
|
msg.payload = data;
|
||||||
|
node.send([msg,null,null]);
|
||||||
|
});
|
||||||
|
ex.stderr.on('data', function (data) {
|
||||||
|
//console.log('[exec] stderr: ' + data);
|
||||||
|
msg.payload = data;
|
||||||
|
node.send([null,msg,null]);
|
||||||
|
});
|
||||||
|
ex.on('close', function (code) {
|
||||||
|
//console.log('[exec] result: ' + code);
|
||||||
|
msg.payload = code;
|
||||||
|
node.send([null,null,msg]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
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};
|
||||||
|
//console.log('[exec] stdout: ' + stdout);
|
||||||
|
//console.log('[exec] stderr: ' + stderr);
|
||||||
|
if (error !== null) {
|
||||||
|
var msg3 = {payload:error};
|
||||||
|
//console.log('[exec] error: ' + error);
|
||||||
|
}
|
||||||
|
node.send([msg,msg2,msg3]);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("exec",ExecNode);
|
96
nodes/core/80-function.html
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
<!--
|
||||||
|
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="icon-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="icon-wrench"></i> Function</label>
|
||||||
|
<input type="hidden" id="node-input-func">
|
||||||
|
<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="icon-random"></i> Outputs</label>
|
||||||
|
<input id="node-input-outputs" style="width: 60px; height: 1.7em;" value="1">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="function">
|
||||||
|
<p>The generic function block where you can write code to do more interesting things.</p>
|
||||||
|
<p>You can have multiple outputs - in which case the function expects you to return an array of messages... <pre>return [msg,msg2,...];</pre></p>
|
||||||
|
<p>You may return null for any or all outputs if you want to.</p>
|
||||||
|
<p>You can save your functions to a library (button to right of name field) - and likewise pick from that library.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('function',{
|
||||||
|
color:"#fdd0a2",
|
||||||
|
category: 'function',
|
||||||
|
defaults: {
|
||||||
|
name: {value:""},
|
||||||
|
func: {value:"// The received message is stored in 'msg'\n// It will have at least a 'payload' property:\n// console.log(msg.payload);\n// The 'context' object is available to store state\n// between invocations of the function\n// context = {};\n\n\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-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-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']
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
},
|
||||||
|
oneditsave: function() {
|
||||||
|
$("#node-input-func").val(this.editor.getText())
|
||||||
|
delete this.editor;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
71
nodes/core/80-function.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
|
||||||
|
var util = require("util");
|
||||||
|
var vm = require("vm");
|
||||||
|
var fs = require('fs');
|
||||||
|
var fspath = require('path');
|
||||||
|
|
||||||
|
function FunctionNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.name = n.name;
|
||||||
|
this.func = n.func;
|
||||||
|
var functionText = "var results = (function(msg){"+this.func+"})(msg);";
|
||||||
|
this.topic = n.topic;
|
||||||
|
this.context = {global:RED.settings.functionGlobalContext || {}};
|
||||||
|
try {
|
||||||
|
this.script = vm.createScript(functionText);
|
||||||
|
this.on("input", function(msg) {
|
||||||
|
if (msg != null) {
|
||||||
|
var sandbox = {msg:msg,console:console,util:util,Buffer:Buffer,context:this.context};
|
||||||
|
try {
|
||||||
|
this.script.runInNewContext(sandbox);
|
||||||
|
var results = sandbox.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 in results[m]) {
|
||||||
|
results[m][n]._topic = msg._topic;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
results[m]._topic = msg._topic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.send(results);
|
||||||
|
|
||||||
|
} catch(err) {
|
||||||
|
this.error(err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch(err) {
|
||||||
|
this.error(err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("function",FunctionNode);
|
||||||
|
RED.library.register("functions");
|
91
nodes/core/80-template.html
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<!--
|
||||||
|
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="template">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-template"><i class="icon-wrench"></i> Template</label>
|
||||||
|
<input type="hidden" id="node-input-template">
|
||||||
|
<div style="height: 250px;" class="node-text-editor" id="node-input-template-editor" ></div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="template">
|
||||||
|
<p>Creates new messages based on a template.</p>
|
||||||
|
<p>Very useful for creating boilerplate web pages, emails, tweets and so on.</p>
|
||||||
|
<p>Uses the <i><a href="http://mustache.github.io/mustache.5.html" target="_new">Mustache</a></i> format.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('template',{
|
||||||
|
color:"rgb(243, 181, 103)",
|
||||||
|
category: 'function',
|
||||||
|
defaults: {
|
||||||
|
name: {value:""},
|
||||||
|
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']
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
},
|
||||||
|
oneditsave: function() {
|
||||||
|
$("#node-input-template").val(this.editor.getText())
|
||||||
|
delete this.editor;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
41
nodes/core/80-template.js
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
|
||||||
|
var mustache = require("mustache");
|
||||||
|
var util = require("util");
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
function TemplateNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.name = n.name;
|
||||||
|
this.template = n.template;
|
||||||
|
this.on("input", function(msg) {
|
||||||
|
if (msg != null) {
|
||||||
|
try {
|
||||||
|
msg.payload = mustache.render(this.template,msg)
|
||||||
|
this.send(msg);
|
||||||
|
} catch(err) {
|
||||||
|
this.error(err.message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("template",TemplateNode);
|
||||||
|
|
||||||
|
RED.library.register("templates");
|
45
nodes/core/90-comment.html
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
<!--
|
||||||
|
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="icon-tag"></i> Comment</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Comment">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="comment">
|
||||||
|
<p>Simple comment block. More of a label really...</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('comment',{
|
||||||
|
category: 'function',
|
||||||
|
color:"#ffffff",
|
||||||
|
defaults: {
|
||||||
|
name: {value:""}
|
||||||
|
},
|
||||||
|
inputs:0,
|
||||||
|
outputs:0,
|
||||||
|
icon: "file.png",
|
||||||
|
label: function() {
|
||||||
|
return this.name||"comment";
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
23
nodes/core/90-comment.js
Normal file
@ -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.
|
||||||
|
**/
|
||||||
|
|
||||||
|
var RED = require("../../red/red");
|
||||||
|
|
||||||
|
function CommentNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("comment",CommentNode);
|
148
nodes/hardware/35-arduino.html
Normal file
@ -0,0 +1,148 @@
|
|||||||
|
<!--
|
||||||
|
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="arduino in">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-arduino"><i class="icon-tasks"></i> Arduino</label>
|
||||||
|
<input type="text" id="node-input-arduino">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-pin"><i class="icon-asterisk"></i> Pin</label>
|
||||||
|
<input type="text" id="node-input-pin" placeholder="2">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-state"><i class="icon-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="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</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>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: 'advanced-input',
|
||||||
|
color:"#c6dbef",
|
||||||
|
defaults: {
|
||||||
|
name: {value:""},
|
||||||
|
pin: {value:"",required:true},
|
||||||
|
state: {value:"INPUT",required:true},
|
||||||
|
arduino: {type:"arduino-board",required:true}
|
||||||
|
},
|
||||||
|
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="icon-tasks"></i> Arduino</label>
|
||||||
|
<input type="text" id="node-input-arduino">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-pin"><i class="icon-asterisk"></i> Pin</label>
|
||||||
|
<input type="text" id="node-input-pin" placeholder="13">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-state"><i class="icon-wrench"></i> Type</label>
|
||||||
|
<select type="text" id="node-input-state" style="width: 150px;">
|
||||||
|
<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="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</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>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: 'advanced-output',
|
||||||
|
color:"#c6dbef",
|
||||||
|
defaults: {
|
||||||
|
name: {value:""},
|
||||||
|
pin: {value:""},
|
||||||
|
state: {value:"",required:true},
|
||||||
|
arduino: {type:"arduino-board",required:true}
|
||||||
|
},
|
||||||
|
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="icon-bullhorn"></i> Arduino Port</label>
|
||||||
|
<input type="text" id="node-config-input-device" placeholder="ttyU" style="width:50%;">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-config-input-repeat"><i class="icon-repeat"></i> Sample (ms)</label>
|
||||||
|
<input type="text" id="node-config-input-repeat" placeholder="25">
|
||||||
|
</div>
|
||||||
|
<!-- <div class="form-row">
|
||||||
|
<label for="node-config-input-baud"><i class="icon-bullhorn"></i> Baudrate</label>
|
||||||
|
<input type="text" id="node-config-input-baud" placeholder="115200" style="width:50%;">
|
||||||
|
</div> -->
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('arduino-board',{
|
||||||
|
category: 'config',
|
||||||
|
defaults: {
|
||||||
|
//baud: {baud:"57600",required:true},
|
||||||
|
repeat: {value:"25",required:true,validate:RED.validators.number()},
|
||||||
|
device: {value:"",required:true}
|
||||||
|
},
|
||||||
|
label: function() {
|
||||||
|
return this.device||"arduino";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
167
nodes/hardware/35-arduino.js
Normal file
@ -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.
|
||||||
|
**/
|
||||||
|
|
||||||
|
var RED = require("../../red/red");
|
||||||
|
var util = require("util");
|
||||||
|
var firmata = require("firmata");
|
||||||
|
var arduinoReady = false;
|
||||||
|
var thisboard = null;
|
||||||
|
|
||||||
|
// The Board Definition - this opens (and closes) the connection
|
||||||
|
function ArduinoNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.device = n.device;
|
||||||
|
this.repeat = n.repeat||25;
|
||||||
|
util.log("[firmata] Opening"+this.device);
|
||||||
|
|
||||||
|
// var tou = setInterval(function() {
|
||||||
|
// if (!arduinoReady) {
|
||||||
|
// clearInterval(tou);
|
||||||
|
|
||||||
|
arduinoReady = false;
|
||||||
|
if (thisboard == null) {
|
||||||
|
this.board = new firmata.Board(this.device, function(err) {
|
||||||
|
if (err) {
|
||||||
|
util.log("[firmata] "+err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
arduinoReady = true;
|
||||||
|
util.log('[firmata] Arduino connected');
|
||||||
|
});
|
||||||
|
thisboard = this.board;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
util.log("[firmata] Arduino already connected");
|
||||||
|
this.board = thisboard;
|
||||||
|
console.log(this.board._events);
|
||||||
|
this.board.removeAllListeners();
|
||||||
|
arduinoReady = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// } else { util.log("[firmata] Waiting for Firmata"); }
|
||||||
|
// }, 1000); // wait for firmata to disconnect from arduino
|
||||||
|
|
||||||
|
this._close = function() {
|
||||||
|
//this.board.sp.close(function() { console.log("[firmata] Serial port closed"); arduinoReady = false; });
|
||||||
|
util.log("[firmata] Stopped");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("arduino-board",ArduinoNode);
|
||||||
|
|
||||||
|
ArduinoNode.prototype.close = function() {
|
||||||
|
this._close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
this.board = this.serverConfig.board;
|
||||||
|
this.repeat = this.serverConfig.repeat;
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
var tout = setInterval(function() {
|
||||||
|
if (arduinoReady) {
|
||||||
|
clearInterval(tout);
|
||||||
|
console.log(node.state,node.pin,node.board.MODES[node.state]);
|
||||||
|
node.board.pinMode(node.pin, node.board.MODES[node.state]);
|
||||||
|
node.board.setSamplingInterval(node.repeat);
|
||||||
|
var oldrdg = "";
|
||||||
|
if (node.state == "ANALOG") {
|
||||||
|
node.board.analogRead(node.pin, function(data) {
|
||||||
|
var msg = {payload:data, topic:"A"+node.pin};
|
||||||
|
if (data != oldrdg) {
|
||||||
|
node.send(msg);
|
||||||
|
oldrdg = data;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
node.board.digitalRead(node.pin, function(data) {
|
||||||
|
var msg = {payload:data, topic:node.pin};
|
||||||
|
node.send(msg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { node.log("Waiting for Arduino"); }
|
||||||
|
}, 2000); // loop to wait for firmata to connect to arduino
|
||||||
|
|
||||||
|
this._close = function() {
|
||||||
|
clearInterval(this._interval);
|
||||||
|
util.log("[firmata] input eventlistener stopped");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("arduino in",DuinoNodeIn);
|
||||||
|
|
||||||
|
DuinoNodeIn.prototype.close = function() {
|
||||||
|
this._close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
this.board = this.serverConfig.board;
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
this.on("input", function(msg) {
|
||||||
|
//console.log(msg);
|
||||||
|
if (arduinoReady) {
|
||||||
|
if (node.state == "OUTPUT") {
|
||||||
|
if ((msg.payload == true)||(msg.payload == 1)||(msg.payload.toString().toLowerCase() == "on")) {
|
||||||
|
node.board.digitalWrite(node.pin, node.board.HIGH);
|
||||||
|
}
|
||||||
|
if ((msg.payload == false)||(msg.payload == 0)||(msg.payload.toString().toLowerCase() == "off")) {
|
||||||
|
node.board.digitalWrite(node.pin, node.board.LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 { console.log("Arduino not ready"); }
|
||||||
|
});
|
||||||
|
|
||||||
|
var touo = setInterval(function() {
|
||||||
|
if (arduinoReady) {
|
||||||
|
clearInterval(touo);
|
||||||
|
//console.log(node.state,node.pin,node.board.MODES[node.state]);
|
||||||
|
node.board.pinMode(node.pin, node.board.MODES[node.state]);
|
||||||
|
}
|
||||||
|
}, 5000); // loop to wait for firmata to connect to arduino
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("arduino out",DuinoNodeOut);
|
69
nodes/hardware/35-rpi-gpio-in.html
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<!--
|
||||||
|
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="rpi-gpio in">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-pin"><i class="icon-asterisk"></i> Pin</label>
|
||||||
|
<select type="text" id="node-input-pin" style="width: 150px;">
|
||||||
|
<option value="7">7</option>
|
||||||
|
<option value="11">11</option>
|
||||||
|
<option value="12">12</option>
|
||||||
|
<option value="13">13</option>
|
||||||
|
<option value="15">15</option>
|
||||||
|
<option value="16">16</option>
|
||||||
|
<option value="18">18</option>
|
||||||
|
<option value="22">22</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-resistor"><i class=" icon-resize-full"></i> Resistor?</label>
|
||||||
|
<select type="text" id="node-input-resistor" style="width: 150px;">
|
||||||
|
<option value="no">no</option>
|
||||||
|
<option value="pullup">pullup</option>
|
||||||
|
<option value="pulldown">pulldown</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-tips">Tip: if pull up/down resistor is selected, the <code>gpio-admin</code> command <em>must</em> be used
|
||||||
|
to do the actual enabling. If 'no' resistor is selected, nothing further needs to be done
|
||||||
|
to use this node. See <code>man gpio-admin</code> for more details.</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('rpi-gpio in',{
|
||||||
|
category: 'advanced-input',
|
||||||
|
color:"#c6dbef",
|
||||||
|
defaults: {
|
||||||
|
name: { value:""},
|
||||||
|
resistor: { value: "no"},
|
||||||
|
pin: {value:"",required:true},
|
||||||
|
},
|
||||||
|
inputs:0,
|
||||||
|
outputs:1,
|
||||||
|
icon: "rpi.png",
|
||||||
|
label: function() {
|
||||||
|
return this.name||"Pin: "+this.pin;
|
||||||
|
//+(this.resistor == "no"?"":" ("+(this.resistor=="pullup"?"":"↓")+")");
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
71
nodes/hardware/35-rpi-gpio-in.js
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
var gpio = require("pi-gpio");
|
||||||
|
|
||||||
|
function GPIOInNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
|
||||||
|
this.buttonState = -1;
|
||||||
|
this.pin = n.pin;
|
||||||
|
this.resistor = n.resistor;
|
||||||
|
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
if (this.pin) {
|
||||||
|
var setupPin = function(err) {
|
||||||
|
if (err) {
|
||||||
|
node.error(err);
|
||||||
|
} else {
|
||||||
|
node._interval = setInterval(function(){
|
||||||
|
gpio.read(node.pin, function(err, value) {
|
||||||
|
if(err){
|
||||||
|
node.error(err);
|
||||||
|
} else{
|
||||||
|
if(node.buttonState !== value){
|
||||||
|
var previousState = node.buttonState;
|
||||||
|
node.buttonState = value;
|
||||||
|
if (previousState !== -1) {
|
||||||
|
var msg = {payload:node.buttonState};
|
||||||
|
node.send(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}, 50);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if (this.resistor == "no") {
|
||||||
|
gpio.open(this.pin,"input",setupPin());
|
||||||
|
} else {
|
||||||
|
// Assume enabled externally via gpio-admin
|
||||||
|
setupPin();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.error("Invalid GPIO pin: "+this.pin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("rpi-gpio in",GPIOInNode);
|
||||||
|
|
||||||
|
GPIOInNode.prototype.close = function() {
|
||||||
|
clearInterval(this._interval);
|
||||||
|
if (this.resistor == "no") {
|
||||||
|
gpio.close(this.pin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
59
nodes/hardware/35-rpi-gpio-out.html
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<!--
|
||||||
|
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="rpi-gpio out">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-pin"><i class="icon-asterisk"></i> Pin</label>
|
||||||
|
<select type="text" id="node-input-pin" style="width: 150px;">
|
||||||
|
<option value="7">7</option>
|
||||||
|
<option value="11">11</option>
|
||||||
|
<option value="12">12</option>
|
||||||
|
<option value="13">13</option>
|
||||||
|
<option value="15">15</option>
|
||||||
|
<option value="16">16</option>
|
||||||
|
<option value="18">18</option>
|
||||||
|
<option value="22">22</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('rpi-gpio out',{
|
||||||
|
category: 'advanced-output',
|
||||||
|
color:"#c6dbef",
|
||||||
|
defaults: {
|
||||||
|
name: { value:""},
|
||||||
|
resistor: { value: "no"},
|
||||||
|
pin: {value:"",required:true},
|
||||||
|
},
|
||||||
|
inputs:1,
|
||||||
|
outputs:0,
|
||||||
|
icon: "rpi.png",
|
||||||
|
align: "right",
|
||||||
|
label: function() {
|
||||||
|
return this.name||"Pin: "+this.pin;
|
||||||
|
//+(this.resistor == "no"?"":" ("+(this.resistor=="pullup"?"":"↓")+")");
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
51
nodes/hardware/35-rpi-gpio-out.js
Normal file
@ -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.
|
||||||
|
**/
|
||||||
|
|
||||||
|
var RED = require("../../red/red");
|
||||||
|
var gpio = require("pi-gpio");
|
||||||
|
|
||||||
|
function GPIOOutNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
|
||||||
|
this.pin = n.pin;
|
||||||
|
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
if (this.pin) {
|
||||||
|
gpio.open(this.pin,"output",function(err) {
|
||||||
|
if (err) {
|
||||||
|
node.error(err);
|
||||||
|
} else {
|
||||||
|
node.on("input",function(msg) {
|
||||||
|
gpio.write(node.pin,msg.payload,function(err) {
|
||||||
|
if (err) node.error(err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.error("Invalid GPIO pin: "+this.pin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("rpi-gpio out",GPIOOutNode);
|
||||||
|
|
||||||
|
GPIOOutNode.prototype.close = function() {
|
||||||
|
gpio.close(this.pin);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
47
nodes/hardware/77-blink1.html
Normal file
@ -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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script type="text/x-red" data-template-name="blink">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
<div class="form-tips">Expects a msg.payload with three part csv string of r,g,b.</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="blink">
|
||||||
|
<p>Thingm Blink1 output node. Expects a msg.payload with a three part csv string of r,g,b.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('blink',{
|
||||||
|
category: 'output',
|
||||||
|
color:"cornsilk",
|
||||||
|
defaults: {
|
||||||
|
name: {value:""}
|
||||||
|
},
|
||||||
|
inputs:1,
|
||||||
|
outputs:0,
|
||||||
|
icon: "arrow-in.png",
|
||||||
|
align: "right",
|
||||||
|
label: function() {
|
||||||
|
return this.name||"blink1";
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return (this.name||!this.topic)?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
46
nodes/hardware/77-blink1.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
var Blink1 = require("node-blink1");
|
||||||
|
|
||||||
|
function Blink1Node(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
var node = this;
|
||||||
|
try {
|
||||||
|
var blink1 = new Blink1.Blink1();
|
||||||
|
node.log("started");
|
||||||
|
|
||||||
|
this.on("input", function(msg) {
|
||||||
|
if (msg != null) {
|
||||||
|
var rgb = msg.payload.split(',');
|
||||||
|
// only do it if three parameters...
|
||||||
|
if (rgb.length == 3) {
|
||||||
|
blink1.setRGB( (rgb[0]*1)&255, (rgb[1]*1)&255, (rgb[2]*1)&255 );
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
//let Andy do fancy colours by name here if he wants...
|
||||||
|
node.log("received "+msg.payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch(e) {
|
||||||
|
node.error(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("blink",Blink1Node);
|
121
nodes/io/10-mqtt.html
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
<!--
|
||||||
|
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="mqtt in">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-broker"><i class="icon-tag"></i> Broker</label>
|
||||||
|
<input type="text" id="node-input-broker">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-topic"><i class="icon-tasks"></i> Topic</label>
|
||||||
|
<input type="text" id="node-input-topic" placeholder="Topic">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<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 the specified 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>. <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:"#c6dbef",
|
||||||
|
inputs:0,
|
||||||
|
outputs:1,
|
||||||
|
icon: "bridge.png",
|
||||||
|
label: function() {
|
||||||
|
return this.name||this.topic;
|
||||||
|
},
|
||||||
|
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="icon-tag"></i> Broker</label>
|
||||||
|
<input type="text" id="node-input-broker">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-topic"><i class="icon-tasks"></i> Topic</label>
|
||||||
|
<input type="text" id="node-input-topic" placeholder="Topic">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</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><b>msg.qos</b> and <b>msg.retain</b> may also optionally have been set. If not set they are set to 0 and false respectively.</p>
|
||||||
|
<p>If <b>msg.payload</b> contains a buffer or 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:""},
|
||||||
|
broker: {type:"mqtt-broker", required:true}
|
||||||
|
},
|
||||||
|
color:"#c6dbef",
|
||||||
|
inputs:1,
|
||||||
|
outputs:0,
|
||||||
|
icon: "bridge.png",
|
||||||
|
align: "right",
|
||||||
|
label: function() {
|
||||||
|
return this.name||this.topic;
|
||||||
|
},
|
||||||
|
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="icon-bookmark"></i> Broker</label>
|
||||||
|
<input class="input-append-left" type="text" id="node-config-input-broker" placeholder="Broker" 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>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('mqtt-broker',{
|
||||||
|
category: 'config',
|
||||||
|
defaults: {
|
||||||
|
broker: {value:"localhost",required:true},
|
||||||
|
port: {value:1883,required:true,validate:RED.validators.number()}
|
||||||
|
},
|
||||||
|
label: function() {
|
||||||
|
return this.broker+":"+this.port;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
90
nodes/io/10-mqtt.js
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
var connectionPool = require("./lib/mqttConnectionPool");
|
||||||
|
var util = require("util");
|
||||||
|
|
||||||
|
function MQTTBrokerNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.broker = n.broker;
|
||||||
|
this.port = n.port;
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("mqtt-broker",MQTTBrokerNode);
|
||||||
|
|
||||||
|
|
||||||
|
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.client = connectionPool.get(this.brokerConfig.broker,this.brokerConfig.port);
|
||||||
|
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.connect();
|
||||||
|
} else {
|
||||||
|
this.error("missing broker configuration");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("mqtt in",MQTTInNode);
|
||||||
|
|
||||||
|
MQTTInNode.prototype.close = function() {
|
||||||
|
if (this.client) {
|
||||||
|
this.client.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function MQTTOutNode(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.client = connectionPool.get(this.brokerConfig.broker,this.brokerConfig.port);
|
||||||
|
this.on("input",function(msg) {
|
||||||
|
if (msg != null) {
|
||||||
|
if (this.topic) {
|
||||||
|
msg.topic = this.topic;
|
||||||
|
}
|
||||||
|
this.client.publish(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.client.connect();
|
||||||
|
} else {
|
||||||
|
this.error("missing broker configuration");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("mqtt out",MQTTOutNode);
|
||||||
|
|
||||||
|
MQTTOutNode.prototype.close = function() {
|
||||||
|
if (this.client) {
|
||||||
|
this.client.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
85
nodes/io/21-httpin.html
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
<!--
|
||||||
|
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="icon-tasks"></i> Method</label>
|
||||||
|
<select type="text" id="node-input-method" style="width: 150px;">
|
||||||
|
<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-topic"><i class="icon-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="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</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&this=that</pre>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
To send JSON encoded data, 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 must be done within
|
||||||
|
a subsequent Function node. The <a href="http://expressjs.com/api.html#res">Express response documentation</a>
|
||||||
|
describes how this should be done.
|
||||||
|
<pre>msg.res.send(200, 'Thanks for the request ');<br/>return msg;</pre>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
</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() {
|
||||||
|
return this.name||"["+this.method+"] "+this.url;
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
51
nodes/io/21-httpin.js
Normal file
@ -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.
|
||||||
|
**/
|
||||||
|
|
||||||
|
var RED = require("../../red/red");
|
||||||
|
var util = require("util");
|
||||||
|
|
||||||
|
function HTTPIn(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.url = n.url;
|
||||||
|
this.method = n.method;
|
||||||
|
|
||||||
|
var node = this;
|
||||||
|
this.callback = function(req,res) {
|
||||||
|
node.send({req:req,res:res});
|
||||||
|
}
|
||||||
|
if (this.method == "get") {
|
||||||
|
RED.app.get(this.url,this.callback);
|
||||||
|
} else if (this.method == "post") {
|
||||||
|
RED.app.post(this.url,this.callback);
|
||||||
|
} else if (this.method == "put") {
|
||||||
|
RED.app.put(this.url,this.callback);
|
||||||
|
} else if (this.method == "delete") {
|
||||||
|
RED.app.delete(this.url,this.callback);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
HTTPIn.prototype.close = function() {
|
||||||
|
var routes = redUI.app.routes[this.method];
|
||||||
|
for (var i in routes) {
|
||||||
|
if (routes[i].path == this.url) {
|
||||||
|
routes.splice(i,1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("http in",HTTPIn);
|
53
nodes/io/23-watch.html
Normal file
@ -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="watch">
|
||||||
|
<div class="form-row node-input-filename">
|
||||||
|
<label for="node-input-files"><i class="icon-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="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="watch">
|
||||||
|
<p>Watches a file or directory for any changes.</p>
|
||||||
|
<p>You can enter a list of comma separated files, or directories if you like. You will need to put " around any that have spaces in.</p>
|
||||||
|
<p>The 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>Of course in Linux, <i>everything</i> could be a file and thus watched...</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>
|
45
nodes/io/23-watch.js
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
var notify = require("fs.notify");
|
||||||
|
|
||||||
|
function WatchNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
|
||||||
|
this.files = n.files.split(",");
|
||||||
|
for (var f in this.files) {
|
||||||
|
this.files[f] = this.files[f].trim();
|
||||||
|
}
|
||||||
|
var node = this;
|
||||||
|
var notifications = new notify(this.files);
|
||||||
|
notifications.on('change', function (file) {
|
||||||
|
node.log('file changed '+file);
|
||||||
|
var msg = { payload: file, topic: JSON.stringify(node.files) };
|
||||||
|
node.send(msg);
|
||||||
|
});
|
||||||
|
|
||||||
|
this._close = function() {
|
||||||
|
notifications.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("watch",WatchNode);
|
||||||
|
|
||||||
|
WatchNode.prototype.close = function() {
|
||||||
|
this._close();
|
||||||
|
}
|
||||||
|
|
146
nodes/io/25-serial.html
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
<!--
|
||||||
|
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="serial in">
|
||||||
|
<div class="form-row node-input-serial">
|
||||||
|
<label for="node-input-serial"><i class="icon-bullhorn"></i> Serial Port</label>
|
||||||
|
<input type="text" id="node-input-serial">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="serial in">
|
||||||
|
<p>Reads data from a local serial port.</p>
|
||||||
|
<p>Keeps reading from the serial port until it sees \n (default) or the character(s) requested. Only sets <b>msg.payload</b>.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('serial in',{
|
||||||
|
category: 'input',
|
||||||
|
defaults: {
|
||||||
|
name: {name:""},
|
||||||
|
serial: {type:"serial-port",required:true}
|
||||||
|
},
|
||||||
|
color:"BurlyWood",
|
||||||
|
inputs:0,
|
||||||
|
outputs:1,
|
||||||
|
icon: "serial.png",
|
||||||
|
label: function() {
|
||||||
|
return this.name||(this.serial)?RED.nodes.node(this.serial).label():"serial";
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<script type="text/x-red" data-template-name="serial out">
|
||||||
|
<div class="form-row node-input-serial">
|
||||||
|
<label for="node-input-serial"><i class="icon-bullhorn"></i> Serial Port</label>
|
||||||
|
<input type="text" id="node-input-serial">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="serial out">
|
||||||
|
<p>Provides a connection to an outbound serial port.</p>
|
||||||
|
<p>Only the <b>msg.payload</b> is sent.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('serial out',{
|
||||||
|
category: 'output',
|
||||||
|
defaults: {
|
||||||
|
name: {name:""},
|
||||||
|
serial: {type:"serial-port",required:true}
|
||||||
|
},
|
||||||
|
color:"BurlyWood",
|
||||||
|
inputs:1,
|
||||||
|
outputs:0,
|
||||||
|
icon: "serial.png",
|
||||||
|
align: "right",
|
||||||
|
label: function() {
|
||||||
|
return this.name||((this.serial)?RED.nodes.node(this.serial).label():"serial");
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
<script type="text/x-red" data-template-name="serial-port">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-config-input-serialport"><i class="icon-bullhorn"></i> Serial Port</label>
|
||||||
|
<input type="text" id="node-config-input-serialport" placeholder="/dev/ttyUSB0" style="width:50%;">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-config-input-serialbaud"><i class="icon-wrench"></i> Baud Rate</label>
|
||||||
|
<select type="text" id="node-config-input-serialbaud" style="width: 150px;">
|
||||||
|
<option value="115200">115200</option>
|
||||||
|
<option value="57600">57600</option>
|
||||||
|
<option value="38400">38400</option>
|
||||||
|
<option value="19200">19200</option>
|
||||||
|
<option value="9600">9600</option>
|
||||||
|
<option value="4800">4800</option>
|
||||||
|
<option value="2400">2400</option>
|
||||||
|
<option value="1800">1800</option>
|
||||||
|
<option value="1200">1200</option>
|
||||||
|
<option value="600">600</option>
|
||||||
|
<option value="300">300</option>
|
||||||
|
<option value="200">200</option>
|
||||||
|
<option value="150">150</option>
|
||||||
|
<option value="134">134</option>
|
||||||
|
<option value="110">110</option>
|
||||||
|
<option value="75">75</option>
|
||||||
|
<option value="50">50</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-config-input-newline"><i class="icon-text-width"></i> New line</label>
|
||||||
|
<input type="text" id="node-config-input-newline">
|
||||||
|
</div>
|
||||||
|
<!--
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-config-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-config-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
-->
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('serial-port',{
|
||||||
|
category: 'config',
|
||||||
|
defaults: {
|
||||||
|
//name: {value:""},
|
||||||
|
serialport: {value:"",required:true},
|
||||||
|
serialbaud: {value:57600,required:true},
|
||||||
|
newline: {value:"\\n"}
|
||||||
|
},
|
||||||
|
label: function() {
|
||||||
|
//return this.name||this.serialport;
|
||||||
|
return this.serialport+":"+this.serialbaud;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
181
nodes/io/25-serial.js
Normal file
@ -0,0 +1,181 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
|
||||||
|
var events = require("events");
|
||||||
|
var util = require("util");
|
||||||
|
var serialp = require("serialport");
|
||||||
|
var settings = RED.settings;
|
||||||
|
|
||||||
|
// TODO: 'serialPool' should be encapsulated in SerialPortNode
|
||||||
|
|
||||||
|
function SerialPortNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.serialport = n.serialport;
|
||||||
|
this.serialbaud = n.serialbaud * 1;
|
||||||
|
this.newline = n.newline;
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("serial-port",SerialPortNode);
|
||||||
|
|
||||||
|
|
||||||
|
function SerialOutNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.serial = n.serial;
|
||||||
|
this.serialConfig = RED.nodes.getNode(this.serial);
|
||||||
|
|
||||||
|
if (this.serialConfig) {
|
||||||
|
var node = this;
|
||||||
|
try {
|
||||||
|
node.port = serialPool.get(this.serialConfig.serialport,this.serialConfig.serialbaud,this.serialConfig.newline);
|
||||||
|
} catch(err) {
|
||||||
|
this.error(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
node.port.on("ready",function() {
|
||||||
|
node.on("input",function(msg) {
|
||||||
|
//console.log("{",msg,"}");
|
||||||
|
node.port.write(msg.payload,function(err,res) {
|
||||||
|
if (err) {
|
||||||
|
node.error(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.error("missing serial config");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("serial out",SerialOutNode);
|
||||||
|
|
||||||
|
SerialOutNode.prototype.close = function() {
|
||||||
|
if (this.serialConfig) {
|
||||||
|
serialPool.close(this.serialConfig.serialport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function SerialInNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.serial = n.serial;
|
||||||
|
this.serialConfig = RED.nodes.getNode(this.serial);
|
||||||
|
|
||||||
|
if (this.serialConfig) {
|
||||||
|
var node = this;
|
||||||
|
try {
|
||||||
|
this.port = serialPool.get(this.serialConfig.serialport,this.serialConfig.serialbaud,this.serialConfig.newline);
|
||||||
|
} catch(err) {
|
||||||
|
this.error(err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.port.on('data', function(msg) {
|
||||||
|
// console.log("{",msg,"}");
|
||||||
|
var m = { "payload": msg };
|
||||||
|
node.send(m);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.error("missing serial config");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("serial in",SerialInNode);
|
||||||
|
|
||||||
|
SerialInNode.prototype.close = function() {
|
||||||
|
if (this.serialConfig) {
|
||||||
|
try {
|
||||||
|
serialPool.close(this.serialConfig.serialport);
|
||||||
|
} catch(err) {
|
||||||
|
}
|
||||||
|
this.warn("Deploying with serial-port nodes is known to occasionally cause Node-RED to hang. This is due to an open issue with the underlying module.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var serialPool = function() {
|
||||||
|
var connections = {};
|
||||||
|
return {
|
||||||
|
get:function(port,baud,newline,callback) {
|
||||||
|
var id = port;
|
||||||
|
if (!connections[id]) {
|
||||||
|
connections[id] = function() {
|
||||||
|
var obj = {
|
||||||
|
_emitter: new events.EventEmitter(),
|
||||||
|
serial: null,
|
||||||
|
_closing: false,
|
||||||
|
tout: null,
|
||||||
|
on: function(a,b) { this._emitter.on(a,b); },
|
||||||
|
close: function(cb) { this.serial.close(cb)},
|
||||||
|
write: function(m,cb) { this.serial.write(m,cb)},
|
||||||
|
}
|
||||||
|
newline = newline.replace("\\n","\n").replace("\\r","\r");
|
||||||
|
var setupSerial = function() {
|
||||||
|
obj.serial = new serialp.SerialPort(port,{
|
||||||
|
baudrate: baud,
|
||||||
|
parser: serialp.parsers.readline(newline)
|
||||||
|
});
|
||||||
|
obj.serial.on('error', function(err) {
|
||||||
|
util.log("[serial] serial port "+port+" error "+err);
|
||||||
|
obj.tout = setTimeout(function() {
|
||||||
|
setupSerial();
|
||||||
|
},settings.serialReconnectTime);
|
||||||
|
});
|
||||||
|
obj.serial.on('close', function() {
|
||||||
|
if (!obj._closing) {
|
||||||
|
util.log("[serial] serial port "+port+" closed unexpectedly");
|
||||||
|
obj.tout = setTimeout(function() {
|
||||||
|
setupSerial();
|
||||||
|
},settings.serialReconnectTime);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
obj.serial.on('open',function() {
|
||||||
|
util.log("[serial] serial port "+port+" opened at "+baud+" baud");
|
||||||
|
obj.serial.flush();
|
||||||
|
obj._emitter.emit('ready');
|
||||||
|
});
|
||||||
|
obj.serial.on('data',function(d) {
|
||||||
|
obj._emitter.emit('data',d);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setupSerial();
|
||||||
|
return obj;
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
return connections[id];
|
||||||
|
},
|
||||||
|
close: function(port) {
|
||||||
|
if (connections[port]) {
|
||||||
|
if (connections[port].tout != null) clearTimeout(connections[port].tout);
|
||||||
|
connections[port]._closing = true;
|
||||||
|
try {
|
||||||
|
connections[port].close(function() {
|
||||||
|
util.log("[serial] serial port closed");
|
||||||
|
});
|
||||||
|
} catch(err) {
|
||||||
|
};
|
||||||
|
}
|
||||||
|
delete connections[port];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}();
|
||||||
|
|
||||||
|
RED.app.get("/serialports",function(req,res) {
|
||||||
|
serialp.list(function (err, ports) {
|
||||||
|
res.writeHead(200, {'Content-Type': 'text/plain'});
|
||||||
|
res.write(JSON.stringify(ports));
|
||||||
|
res.end();
|
||||||
|
});
|
||||||
|
});
|
69
nodes/io/30-socketin.html
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
<!--
|
||||||
|
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="socket in">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-transport"><i class="icon-tasks"></i> Type</label>
|
||||||
|
<select type="text" id="node-input-transport" style="width: 150px;">
|
||||||
|
<option value="http">http listen</option>
|
||||||
|
<option value="tcp">tcp server</option>
|
||||||
|
<!-- <option value="tcpc">tcp client</option> -->
|
||||||
|
<option value="udp">udp socket</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-port"><i class="icon-random"></i> Port</label>
|
||||||
|
<input type="text" id="node-input-port" placeholder="Port">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-topic"><i class="icon-tasks"></i> Topic</label>
|
||||||
|
<input type="text" id="node-input-topic" placeholder="Topic">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
<div class="form-tips">Tip: sends the received data as a Buffer object.</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="socket in">
|
||||||
|
<p>Provides a input node for http, tcp or udp sockets. Topic is optional. These are server like sockets.</p>
|
||||||
|
<p>The TCP and UDP sockets produce a <i>BUFFER</i> object msg.payload and NOT a String. If you need a String then use .toString() on msg.payload in your next function block.</p>
|
||||||
|
<p>TCP and UDP sockets also provide <b>msg.fromip</b> of the form ipaddress:port</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('socket in',{
|
||||||
|
category: 'input',
|
||||||
|
color:"Silver",
|
||||||
|
defaults: {
|
||||||
|
name: {value:""},
|
||||||
|
topic: {value:""},
|
||||||
|
port: {value:"",required:true},
|
||||||
|
transport: {value:"tcp",required:true}
|
||||||
|
},
|
||||||
|
inputs:0,
|
||||||
|
outputs:1,
|
||||||
|
icon: "bridge-dash.png",
|
||||||
|
label: function() {
|
||||||
|
return this.name||this.topic||(this.transport+":"+this.port);
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
134
nodes/io/30-socketin.js
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
|
||||||
|
function SocketIn(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.port = n.port;
|
||||||
|
this.topic = n.topic;
|
||||||
|
this.trans = (n.transport||n.trans||"").toLowerCase();
|
||||||
|
var node = this;
|
||||||
|
if (this.trans == "http") {
|
||||||
|
var http = require('http');
|
||||||
|
var serv = http.createServer(function (req, res) {
|
||||||
|
//node.log("http "+req.url);
|
||||||
|
var msg = {topic:node.topic,payload:req.url.slice(1)};
|
||||||
|
node.send(msg);
|
||||||
|
res.writeHead(304, {'Content-Type': 'text/plain'});
|
||||||
|
res.end('\n');
|
||||||
|
}).listen(node.port);
|
||||||
|
node.log('http listener at http://127.0.0.1:'+node.port+'/');
|
||||||
|
|
||||||
|
this._close = function() {
|
||||||
|
serv.close();
|
||||||
|
node.log('http listener stopped');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.trans == "tcp") {
|
||||||
|
var net = require('net');
|
||||||
|
var server = net.createServer(function (socket) {
|
||||||
|
var buffer = null;
|
||||||
|
socket.on('data', function (chunk) {
|
||||||
|
if (buffer == null) {
|
||||||
|
buffer = chunk;
|
||||||
|
} else {
|
||||||
|
buffer = Buffer.concat([buffer,chunk]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
socket.on('end', function() {
|
||||||
|
var msg = {topic:node.topic, payload:buffer, fromip:socket.remoteAddress+':'+socket.remotePort};
|
||||||
|
node.send(msg);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
server.listen(node.port);
|
||||||
|
node.log('tcp listener on port :'+node.port+'/');
|
||||||
|
|
||||||
|
this._close = function() {
|
||||||
|
server.close();
|
||||||
|
node.log('tcp listener stopped');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.trans == "tcpc") {
|
||||||
|
var net = require('net');
|
||||||
|
var client;
|
||||||
|
var to;
|
||||||
|
function setupTcpClient() {
|
||||||
|
node.log('tcpc connecting to port :'+node.port);
|
||||||
|
client = net.connect({port: node.port}, function() {
|
||||||
|
node.log("tcpc connected");
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('data', function (data) {
|
||||||
|
var msg = {topic:node.topic, payload:data};
|
||||||
|
node.send(msg);
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('end', function() {
|
||||||
|
node.log("tcpc socket ended");
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('close', function() {
|
||||||
|
node.log('tcpc socket closed');
|
||||||
|
to = setTimeout(setupTcpClient, 10000); //Try to reconnect
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('error', function() {
|
||||||
|
node.log('tcpc socket error');
|
||||||
|
to = setTimeout(setupTcpClient, 10000); //Try to reconnect
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setupTcpClient();
|
||||||
|
|
||||||
|
this._close = function() {
|
||||||
|
client.end();
|
||||||
|
//client.destroy();
|
||||||
|
clearTimeout(to);
|
||||||
|
node.log('tcpc stopped client');
|
||||||
|
}
|
||||||
|
setupTcpClient();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.trans == "udp") {
|
||||||
|
var dgram = require('dgram');
|
||||||
|
var server = dgram.createSocket('udp4');
|
||||||
|
server.on('listening', function () {
|
||||||
|
var address = server.address();
|
||||||
|
node.log('udp listener at ' + address.address + ":" + address.port);
|
||||||
|
});
|
||||||
|
server.on('message', function (message, remote) {
|
||||||
|
var msg = {topic:node.topic,payload:message,fromip:remote.address+':'+remote.port};
|
||||||
|
node.send(msg);
|
||||||
|
});
|
||||||
|
server.bind(node.port);
|
||||||
|
|
||||||
|
this._close = function() {
|
||||||
|
server.close();
|
||||||
|
node.log('udp listener stopped');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("socket in",SocketIn);
|
||||||
|
|
||||||
|
SocketIn.prototype.close = function() {
|
||||||
|
this._close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
66
nodes/io/30-socketout.html
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<!--
|
||||||
|
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="socket out">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-host"><i class="icon-bookmark"></i> Host</label>
|
||||||
|
<input type="text" id="node-input-host" placeholder="localhost" style="width: 40%;" >
|
||||||
|
|
||||||
|
<label for="node-input-port" style="margin-left: 10px; width: 35px;"> Port</label>
|
||||||
|
<input type="text" id="node-input-port" placeholder="Port" style="width: 45px">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-transport"><i class="icon-tasks"></i> Type</label>
|
||||||
|
<select type="text" id="node-input-transport" style="width: 150px;">
|
||||||
|
<option value="http">http</option>
|
||||||
|
<option value="tcp">tcp</option>
|
||||||
|
<option value="udp">udp</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="socket out">
|
||||||
|
<p>Provides a choice of http, tcp or udp output connections. All connect, send their <b>msg.payload</b> and disconnect.</p>
|
||||||
|
<p>To use broadcast select udp and set the host to be either the subnet broadcast address required or 255.255.255.255</p>
|
||||||
|
<p>If you need a response from an http request use the httpget node instead.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('socket out',{
|
||||||
|
category: 'output',
|
||||||
|
color:"Silver",
|
||||||
|
defaults: {
|
||||||
|
host: {value:"127.0.0.1",required:true},
|
||||||
|
port: {value:"",required:true},
|
||||||
|
name: {value:""},
|
||||||
|
transport: {value:"tcp",required:true}
|
||||||
|
},
|
||||||
|
inputs:1,
|
||||||
|
outputs:0,
|
||||||
|
icon: "bridge-dash.png",
|
||||||
|
align: "right",
|
||||||
|
label: function() {
|
||||||
|
return this.name||this.topic||(this.transport+":"+this.port);
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return (this.name||!this.topic)?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
63
nodes/io/30-socketout.js
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
|
||||||
|
function SocketOut(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.host = n.host;
|
||||||
|
this.port = n.port * 1;
|
||||||
|
this.name = n.name;
|
||||||
|
this.trans = n.transport||n.trans||"";
|
||||||
|
var node = this;
|
||||||
|
this.on("input", function(msg) {
|
||||||
|
if (msg != null) {
|
||||||
|
if (this.trans == "http") {
|
||||||
|
var http = require("http");
|
||||||
|
http.get(msg.payload, function(res) {
|
||||||
|
node.log("http : response : " + res.statusCode);
|
||||||
|
}).on('error', function(e) {
|
||||||
|
node.error("http : error : " + e.message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.trans == "tcp") {
|
||||||
|
var net = require('net');
|
||||||
|
var client = new net.Socket();
|
||||||
|
client.on('error', function (err) {
|
||||||
|
node.error('tcp : '+err);
|
||||||
|
});
|
||||||
|
client.connect(this.port, this.host, function() {
|
||||||
|
client.end(msg.payload);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (this.trans == "udp") {
|
||||||
|
var dgram = require('dgram');
|
||||||
|
var sock = dgram.createSocket('udp4'); // only use ipv4 for now
|
||||||
|
sock.bind(this.port); // have to bind before you can enable broadcast...
|
||||||
|
sock.setBroadcast(true); // turn on broadcast
|
||||||
|
var buf = new Buffer(msg.payload);
|
||||||
|
sock.send(buf, 0, buf.length, this.port, this.host, function(err, bytes) {
|
||||||
|
if (err) node.error("udp : "+err);
|
||||||
|
//util.log('[socket out] udp :' +bytes);
|
||||||
|
sock.close();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var node = this;
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("socket out",SocketOut);
|
79
nodes/io/31-tcpin.html
Normal file
@ -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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<script type="text/x-red" data-template-name="tcp in">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-host"><i class="icon-bookmark"></i> Host</label>
|
||||||
|
<input type="text" id="node-input-host" placeholder="localhost" style="width: 40%;" >
|
||||||
|
|
||||||
|
<label for="node-input-port" style="margin-left: 10px; width: 35px;"> Port</label>
|
||||||
|
<input type="text" id="node-input-port" placeholder="Port" style="width: 45px">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label> </label>
|
||||||
|
<input type="checkbox" id="node-input-server" placeholder="server" style="display: inline-block; width: auto; vertical-align: top;">
|
||||||
|
<label for="node-input-server" style="width: 70%;">Be a server socket ?</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label> </label>
|
||||||
|
<input type="checkbox" id="node-input-base64" placeholder="base64" style="display: inline-block; width: auto; vertical-align: top;">
|
||||||
|
<label for="node-input-base64" style="width: 70%;">Base64 encode payload ?</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-topic"><i class="icon-tasks"></i> Topic</label>
|
||||||
|
<input type="text" id="node-input-topic" placeholder="Topic">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
<div class="form-tips">Tip: sends the received data as a Buffer object (not a String).<br/>If you select server socket the host defaults to localhost.</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="tcp in">
|
||||||
|
<p>Provides a choice of tcp input connections. Can either be a client - or provide a listening socket.</p>
|
||||||
|
<p>The TCP node produces a <i>BUFFER</i> object <b></b>msg.payload</b> and NOT a String. If you need a String then use <i>.toString()</i> on <b>msg.payload</b> in your next function block.</p>
|
||||||
|
<p>It also provides <b>msg.fromip</b> of the form ipaddress:port .</p>
|
||||||
|
<p>You can select Base64 encoding if you want to make it easy to preserve the complete message as a string.</p>
|
||||||
|
<p>In case of disconnection the client trys to reconnect every 10 secs. Topic is optional.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('tcp in',{
|
||||||
|
category: 'input',
|
||||||
|
color:"Silver",
|
||||||
|
defaults: {
|
||||||
|
host: {value:"127.0.0.1",required:true},
|
||||||
|
port: {value:"",required:true,validate:RED.validators.number()},
|
||||||
|
base64: {value:false,required:true},
|
||||||
|
server: {value:false,required:true},
|
||||||
|
topic: {value:""},
|
||||||
|
name: {value:""}
|
||||||
|
},
|
||||||
|
inputs:0,
|
||||||
|
outputs:1,
|
||||||
|
icon: "bridge-dash.png",
|
||||||
|
label: function() {
|
||||||
|
if ((this.host!="") & (this.port!="")) {
|
||||||
|
return this.name||(this.host+":"+this.port);
|
||||||
|
}
|
||||||
|
else { return "tcp in"; }
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
103
nodes/io/31-tcpin.js
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
var reConnect = RED.settings.socketReconnectTime||10000;
|
||||||
|
var net = require('net');
|
||||||
|
|
||||||
|
function TcpIn(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.host = n.host;
|
||||||
|
this.port = n.port * 1;
|
||||||
|
this.topic = n.topic;
|
||||||
|
this.base64 = n.base64;
|
||||||
|
this.server = n.server;
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
if (!node.server) {
|
||||||
|
var client;
|
||||||
|
var to;
|
||||||
|
|
||||||
|
function setupTcpClient() {
|
||||||
|
node.log('connecting to port '+node.port);
|
||||||
|
client = net.connect(node.port, node.host, function() {
|
||||||
|
node.log("input connected to "+node.host+":"+node.port);
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('data', function (data) {
|
||||||
|
var msg;
|
||||||
|
if (node.base64) { msg = { topic:node.topic, payload:new Buffer(data).toString('base64') }; }
|
||||||
|
else { msg = {topic:node.topic, payload:data}; }
|
||||||
|
node.send(msg);
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('end', function() {
|
||||||
|
node.log("ended");
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('close', function() {
|
||||||
|
client.destroy();
|
||||||
|
node.log('closed');
|
||||||
|
to = setTimeout(setupTcpClient, reConnect);
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('error', function(err) {
|
||||||
|
node.log('error : '+err);
|
||||||
|
//to = setTimeout(setupTcpClient, reConnect);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setupTcpClient();
|
||||||
|
|
||||||
|
this._close = function() {
|
||||||
|
client.end();
|
||||||
|
clearTimeout(to);
|
||||||
|
node.log('input stopped');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var server = net.createServer(function (socket) {
|
||||||
|
var buffer = null;
|
||||||
|
socket.on('data', function (chunk) {
|
||||||
|
//if (buffer == null) {
|
||||||
|
// buffer = chunk;
|
||||||
|
//} else {
|
||||||
|
//buffer = Buffer.concat([buffer,chunk]);
|
||||||
|
var msg = {topic:node.topic, payload:chunk, fromip:socket.remoteAddress+':'+socket.remotePort};
|
||||||
|
node.send(msg);
|
||||||
|
//}
|
||||||
|
});
|
||||||
|
socket.on('end', function() {
|
||||||
|
var msg = {topic:node.topic, payload:buffer, fromip:socket.remoteAddress+':'+socket.remotePort};
|
||||||
|
node.send(msg);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
server.listen(node.port);
|
||||||
|
node.log('socket input on port '+node.port);
|
||||||
|
|
||||||
|
this._close = function() {
|
||||||
|
server.close();
|
||||||
|
node.log('socket input stopped');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("tcp in",TcpIn);
|
||||||
|
|
||||||
|
TcpIn.prototype.close = function() {
|
||||||
|
this._close();
|
||||||
|
}
|
||||||
|
|
73
nodes/io/31-tcpout.html
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
<!--
|
||||||
|
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="tcp out">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-host"><i class="icon-bookmark"></i> Host</label>
|
||||||
|
<input type="text" id="node-input-host" placeholder="localhost" style="width: 40%;" >
|
||||||
|
|
||||||
|
<label for="node-input-port" style="margin-left: 10px; width: 35px;"> Port</label>
|
||||||
|
<input type="text" id="node-input-port" placeholder="Port" style="width: 45px">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label> </label>
|
||||||
|
<input type="checkbox" id="node-input-beserver" placeholder="server" style="display: inline-block; width: auto; vertical-align: top;">
|
||||||
|
<label for="node-input-beserver" style="width: 70%;">Be a server socket ?</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label> </label>
|
||||||
|
<input type="checkbox" id="node-input-base64" placeholder="base64" style="display: inline-block; width: auto; vertical-align: top;">
|
||||||
|
<label for="node-input-base64" style="width: 70%;">Decode Base64 message ?</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
<div class="form-tips">Tip: If you select server socket the host defaults to localhost.</div>
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="tcp out">
|
||||||
|
<p>Provides a choice of tcp output connections. Can either connect out - or provide a socket connection.</p>
|
||||||
|
<p>Only <b>msg.payload</b> is sent.</p>
|
||||||
|
<p>You can select Base64 decoding if you want to decode a message encoded by the input socket.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('tcp out',{
|
||||||
|
category: 'output',
|
||||||
|
color:"Silver",
|
||||||
|
defaults: {
|
||||||
|
host: {value:"127.0.0.1",required:true},
|
||||||
|
port: {value:"",required:true},
|
||||||
|
beserver: {value:false,required:true},
|
||||||
|
base64: {value:false,required:true},
|
||||||
|
name: {value:""}
|
||||||
|
},
|
||||||
|
inputs:1,
|
||||||
|
outputs:0,
|
||||||
|
icon: "bridge-dash.png",
|
||||||
|
align: "right",
|
||||||
|
label: function() {
|
||||||
|
var lab = this.host+":"+this.port;
|
||||||
|
if (this.server) lab = "tcp out:"+this.port;
|
||||||
|
return this.name||lab;
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return (this.name)?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
98
nodes/io/31-tcpout.js
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
var reConnect = RED.settings.socketReconnectTime||10000;
|
||||||
|
var net = require('net');
|
||||||
|
|
||||||
|
function TcpOut(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.host = n.host;
|
||||||
|
this.port = n.port * 1;
|
||||||
|
this.base64 = n.base64;
|
||||||
|
this.beserver = n.beserver;
|
||||||
|
this.name = n.name;
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
if (!node.beserver) {
|
||||||
|
var client = new net.Socket();
|
||||||
|
var to;
|
||||||
|
|
||||||
|
function setupTcpClient() {
|
||||||
|
client.connect(node.port, node.host, function() {
|
||||||
|
node.log("output connected to "+node.host+":"+node.port);
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('error', function (err) {
|
||||||
|
node.error('error : '+err);
|
||||||
|
to = setTimeout(setupTcpClient, reConnect);
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('end', function (err) {
|
||||||
|
node.log("output disconnected");
|
||||||
|
to = setTimeout(setupTcpClient, reConnect);
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('close', function() {
|
||||||
|
client.destroy();
|
||||||
|
node.log('closed');
|
||||||
|
to = setTimeout(setupTcpClient, reConnect);
|
||||||
|
});
|
||||||
|
|
||||||
|
node.on("input", function(msg) {
|
||||||
|
if (msg.payload != null) {
|
||||||
|
if (node.base64) { client.write(new Buffer(msg.payload,'base64')); }
|
||||||
|
else { client.write(msg.payload);}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
setupTcpClient();
|
||||||
|
|
||||||
|
this._close = function() {
|
||||||
|
client.end();
|
||||||
|
clearTimeout(to);
|
||||||
|
node.log('output stopped');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
var server = net.createServer(function (socket) {
|
||||||
|
socket.on("connect",function() {
|
||||||
|
node.log("Connection from "+socket.remoteAddress);
|
||||||
|
});
|
||||||
|
node.on("input", function(msg) {
|
||||||
|
if (msg.payload != null) {
|
||||||
|
if (node.base64) { socket.write(new Buffer(msg.payload,'base64')); }
|
||||||
|
else { socket.write(msg.payload);}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
server.listen(node.port);
|
||||||
|
node.log('socket output on port '+node.port);
|
||||||
|
|
||||||
|
this._close = function() {
|
||||||
|
server.close();
|
||||||
|
node.log('output stopped');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("tcp out",TcpOut);
|
||||||
|
|
||||||
|
TcpOut.prototype.close = function() {
|
||||||
|
this._close();
|
||||||
|
}
|
||||||
|
|
131
nodes/io/32-multicast.html
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
<!--
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- The Input Node -->
|
||||||
|
<script type="text/x-red" data-template-name="multicast in">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-group"><i class="icon-tasks"></i> Group</label>
|
||||||
|
<input type="text" id="node-input-group" placeholder="225.0.18.83" style="width: 40%;">
|
||||||
|
<label for="node-input-port" style="margin-left: 10px; width: 35px;"> Port</label>
|
||||||
|
<input type="text" id="node-input-port" placeholder="Port" style="width: 45px">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-iface"><i class="icon-globe"></i> Interface</label>
|
||||||
|
<input type="text" id="node-input-iface" placeholder="eth0">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label> </label>
|
||||||
|
<input type="checkbox" id="node-input-base64" placeholder="base64" style="display: inline-block; width: auto; vertical-align: top;">
|
||||||
|
<label for="node-input-base64" style="width: 70%;">Base64 encode payload ?</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
<div class="form-tips">Tip: sends the received data as a Buffer object (not a String).<br/>Make sure your firewall will allow the data in.</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="multicast in">
|
||||||
|
<p>A multicast udp input node, that produces a <b>msg.payload</b> containing a <i>BUFFER</i> object and NOT a String.</p>
|
||||||
|
<p>If you need a String then use <i>.toString()</i> on <b>msg.payload</b> in your next function block.</p>
|
||||||
|
<p>It also provides <b>msg.fromip</b> of the form ipaddress:port .</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('multicast in',{
|
||||||
|
category: 'input',
|
||||||
|
color:"Silver",
|
||||||
|
defaults: {
|
||||||
|
name: {value:""},
|
||||||
|
group: {value:"",required:true},
|
||||||
|
host: {value:""},
|
||||||
|
iface: {value:""},
|
||||||
|
port: {value:"",required:true,validate:RED.validators.number()},
|
||||||
|
base64: {value:false,required:true},
|
||||||
|
multicast: {value:"true"}
|
||||||
|
},
|
||||||
|
inputs:0,
|
||||||
|
outputs:1,
|
||||||
|
icon: "bridge-dash.png",
|
||||||
|
label: function() {
|
||||||
|
if ((this.group!="") & (this.port!="")) {
|
||||||
|
return this.name||(this.group+":"+this.port);
|
||||||
|
}
|
||||||
|
else { return "multicast in"; }
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<!-- The Output Node -->
|
||||||
|
<script type="text/x-red" data-template-name="multicast out">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-group"><i class="icon-tasks"></i> Group</label>
|
||||||
|
<input type="text" id="node-input-group" placeholder="225.0.18.83" style="width: 40%;">
|
||||||
|
<label for="node-input-port" style="margin-left: 10px; width: 35px;"> Port</label>
|
||||||
|
<input type="text" id="node-input-port" placeholder="Port" style="width: 45px">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-iface"><i class="icon-globe"></i> Interface</label>
|
||||||
|
<input type="text" id="node-input-iface" placeholder="eth0">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="form-row">
|
||||||
|
<label> </label>
|
||||||
|
<input type="checkbox" id="node-input-base64" placeholder="base64" style="display: inline-block; width: auto; vertical-align: top;">
|
||||||
|
<label for="node-input-base64" style="width: 70%;">Decode Base64 encoded payload ?</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="multicast out">
|
||||||
|
<p>This node sends <b>msg.payload</b> to the designated multicast group and port.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('multicast out',{
|
||||||
|
category: 'output',
|
||||||
|
color:"Silver",
|
||||||
|
defaults: {
|
||||||
|
name: {value:""},
|
||||||
|
group: {value:"",required:true},
|
||||||
|
host: {value:""},
|
||||||
|
iface: {value:""},
|
||||||
|
port: {value:"",required:true,validate:RED.validators.number()},
|
||||||
|
base64: {value:false,required:true},
|
||||||
|
multicast: {value:"true"}
|
||||||
|
},
|
||||||
|
inputs:1,
|
||||||
|
outputs:0,
|
||||||
|
icon: "bridge-dash.png",
|
||||||
|
align: "right",
|
||||||
|
label: function() {
|
||||||
|
if ((this.group!="") & (this.port!="")) {
|
||||||
|
return this.name||(this.group+":"+this.port);
|
||||||
|
}
|
||||||
|
else { return "multicast out"; }
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
118
nodes/io/32-multicast.js
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
var dgram = require('dgram');
|
||||||
|
|
||||||
|
// The Input Node
|
||||||
|
function MCastIn(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.group = n.group;
|
||||||
|
this.port = n.port;
|
||||||
|
this.host = n.host || null;
|
||||||
|
this.base64 = n.base64;
|
||||||
|
this.iface = n.iface || null;
|
||||||
|
this.multicast = n.multicast;
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
var server = dgram.createSocket('udp4');
|
||||||
|
|
||||||
|
server.on("error", function (err) {
|
||||||
|
console.log("udp listener error:\n" + err.stack);
|
||||||
|
server.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on('message', function (message, remote) {
|
||||||
|
var msg;
|
||||||
|
if (node.base64) { msg = { payload:message.toString('base64'), fromip:remote.address+':'+remote.port }; }
|
||||||
|
else { msg = { payload:message, fromip:remote.address+':'+remote.port }; }
|
||||||
|
node.send(msg);
|
||||||
|
});
|
||||||
|
|
||||||
|
server.on('listening', function () {
|
||||||
|
var address = server.address();
|
||||||
|
node.log('udp listener at ' + address.address + ":" + address.port);
|
||||||
|
if (node.multicast) {
|
||||||
|
server.setBroadcast(true)
|
||||||
|
server.setMulticastTTL(128);
|
||||||
|
server.addMembership(node.group,node.iface);
|
||||||
|
node.log("udp multicast group "+node.group);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//server.bind(node.port,node.host);
|
||||||
|
server.bind(node.port,node.host);
|
||||||
|
|
||||||
|
this._close = function() {
|
||||||
|
server.close();
|
||||||
|
node.log('udp listener stopped');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MCastIn.prototype.close = function() {
|
||||||
|
this._close();
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("multicast in",MCastIn);
|
||||||
|
|
||||||
|
// The Output Node
|
||||||
|
function MCastOut(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.group = n.group;
|
||||||
|
this.port = n.port;
|
||||||
|
this.host = n.host || null;
|
||||||
|
this.base64 = n.base64;
|
||||||
|
this.iface = n.iface || null;
|
||||||
|
this.multicast = n.multicast;
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
var sock = dgram.createSocket('udp4'); // only use ipv4 for now
|
||||||
|
sock.bind(node.port); // have to bind before you can enable broadcast...
|
||||||
|
sock.setBroadcast(true); // turn on broadcast
|
||||||
|
sock.setMulticastTTL(128);
|
||||||
|
sock.addMembership(node.group,node.iface); // Add to the multicast group
|
||||||
|
node.log('udp multicaster ready on '+node.group+":"+node.port);
|
||||||
|
|
||||||
|
node.on("input", function(msg) {
|
||||||
|
if (msg.payload != null) {
|
||||||
|
console.log("MCast:",msg.payload);
|
||||||
|
var message;
|
||||||
|
if (node.base64) {
|
||||||
|
message = new Buffer(msg.payload,'base64');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
message = new Buffer(msg.payload);
|
||||||
|
}
|
||||||
|
sock.send(message, 0, message.length, node.port, node.group, function(err, bytes) {
|
||||||
|
if (err) node.error("udp : "+err);
|
||||||
|
//util.log('[socket out] udp :' +bytes);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this._close = function() {
|
||||||
|
sock.close();
|
||||||
|
node.log('udp multicaster stopped');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("multicast out",MCastOut);
|
||||||
|
|
||||||
|
MCastOut.prototype.close = function() {
|
||||||
|
this._close();
|
||||||
|
}
|
||||||
|
|
59
nodes/io/90-httpget.html
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<!--
|
||||||
|
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-row">
|
||||||
|
<label for="node-input-baseurl"><i class="icon-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="icon-tasks"></i> Append</label>
|
||||||
|
<input type="text" id="node-input-append" placeholder="">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
<div class="form-tips">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: 'advanced-function',
|
||||||
|
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||"http(s) get";
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return (this.name||!this.baseurl)?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
52
nodes/io/90-httpget.js
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
|
||||||
|
function HttpGet(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
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);
|
225
nodes/io/lib/mqtt.js
Normal file
@ -0,0 +1,225 @@
|
|||||||
|
/**
|
||||||
|
* 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 util = require("util");
|
||||||
|
var mqtt = require("mqtt");
|
||||||
|
var events = require("events");
|
||||||
|
|
||||||
|
//var Client = module.exports.Client = function(
|
||||||
|
|
||||||
|
var port = 1883;
|
||||||
|
var host = "localhost";
|
||||||
|
|
||||||
|
function MQTTClient(port,host) {
|
||||||
|
this.port = port||1883;
|
||||||
|
this.host = host||"localhost";
|
||||||
|
this.messageId = 1;
|
||||||
|
this.pendingSubscriptions = {};
|
||||||
|
this.inboundMessages = {};
|
||||||
|
this.lastOutbound = (new Date()).getTime();
|
||||||
|
this.lastInbound = (new Date()).getTime();
|
||||||
|
this.connected = false;
|
||||||
|
|
||||||
|
this._nextMessageId = function() {
|
||||||
|
this.messageId += 1;
|
||||||
|
if (this.messageId > 0xFFFF) {
|
||||||
|
this.messageId = 1;
|
||||||
|
}
|
||||||
|
return this.messageId;
|
||||||
|
}
|
||||||
|
events.EventEmitter.call(this);
|
||||||
|
}
|
||||||
|
util.inherits(MQTTClient, events.EventEmitter);
|
||||||
|
|
||||||
|
MQTTClient.prototype.connect = function(options) {
|
||||||
|
var self = this;
|
||||||
|
options = options||{};
|
||||||
|
self.options = options;
|
||||||
|
self.options.keepalive = options.keepalive||15;
|
||||||
|
self.options.clean = self.options.clean||true;
|
||||||
|
self.options.protocolId = 'MQIsdp';
|
||||||
|
self.options.protocolVersion = 3;
|
||||||
|
|
||||||
|
self.client = mqtt.createConnection(this.port,this.host,function(err,client) {
|
||||||
|
if (err) {
|
||||||
|
self.emit('connectionlost',err);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
client.on('close',function(e) {
|
||||||
|
clearInterval(self.watchdog);
|
||||||
|
if (self.connected) {
|
||||||
|
self.connected = false;
|
||||||
|
self.emit('connectionlost',e);
|
||||||
|
} else {
|
||||||
|
self.emit('disconnect');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
client.on('error',function(e) {
|
||||||
|
clearInterval(self.watchdog);
|
||||||
|
if (self.connected) {
|
||||||
|
self.connected = false;
|
||||||
|
self.emit('connectionlost',e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
client.on('connack',function(packet) {
|
||||||
|
if (packet.returnCode == 0) {
|
||||||
|
self.watchdog = setInterval(function(self) {
|
||||||
|
var now = (new Date()).getTime();
|
||||||
|
if (now - self.lastOutbound > self.options.keepalive*500 || now - self.lastInbound > self.options.keepalive*500) {
|
||||||
|
if (self.pingOutstanding) {
|
||||||
|
// DO DISCONNECT
|
||||||
|
} else {
|
||||||
|
self.lastOutbound = (new Date()).getTime();
|
||||||
|
self.lastInbound = (new Date()).getTime();
|
||||||
|
self.pingOutstanding = true;
|
||||||
|
self.client.pingreq();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
},self.options.keepalive*500,self);
|
||||||
|
self.lastInbound = (new Date()).getTime()
|
||||||
|
self.connected = true;
|
||||||
|
self.emit('connect');
|
||||||
|
} else {
|
||||||
|
self.connected = false;
|
||||||
|
self.emit('connectionlost');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
client.on('suback',function(packet) {
|
||||||
|
self.lastInbound = (new Date()).getTime()
|
||||||
|
var topic = self.pendingSubscriptions[packet.messageId];
|
||||||
|
self.emit('subscribe',topic,packet.granted[0]);
|
||||||
|
delete self.pendingSubscriptions[packet.messageId];
|
||||||
|
});
|
||||||
|
client.on('unsuback',function(packet) {
|
||||||
|
self.lastInbound = (new Date()).getTime()
|
||||||
|
var topic = self.pendingSubscriptions[packet.messageId];
|
||||||
|
self.emit('unsubscribe',topic,packet.granted[0]);
|
||||||
|
delete self.pendingSubscriptions[packet.messageId];
|
||||||
|
});
|
||||||
|
client.on('publish',function(packet) {
|
||||||
|
self.lastInbound = (new Date()).getTime()
|
||||||
|
if (packet.qos < 2) {
|
||||||
|
var p = packet;
|
||||||
|
self.emit('message',p.topic,p.payload,p.qos,p.retain);
|
||||||
|
} else {
|
||||||
|
self.inboundMessages[packet.messageId] = packet;
|
||||||
|
this.lastOutbound = (new Date()).getTime()
|
||||||
|
self.client.pubrec(packet);
|
||||||
|
}
|
||||||
|
if (packet.qos == 1) {
|
||||||
|
this.lastOutbound = (new Date()).getTime()
|
||||||
|
self.client.puback(packet);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('pubrel',function(packet) {
|
||||||
|
self.lastInbound = (new Date()).getTime()
|
||||||
|
var p = self.inboundMessages[packet.messageId];
|
||||||
|
self.emit('message',p.topic,p.payload,p.qos,p.retain);
|
||||||
|
delete self.inboundMessages[packet.messageId];
|
||||||
|
self.lastOutbound = (new Date()).getTime()
|
||||||
|
self.client.pubcomp(packet);
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('puback',function(packet) {
|
||||||
|
self.lastInbound = (new Date()).getTime()
|
||||||
|
// outbound qos-1 complete
|
||||||
|
});
|
||||||
|
|
||||||
|
client.on('pubrec',function(packet) {
|
||||||
|
self.lastInbound = (new Date()).getTime()
|
||||||
|
self.lastOutbound = (new Date()).getTime()
|
||||||
|
self.client.pubrel(packet);
|
||||||
|
});
|
||||||
|
client.on('pubcomp',function(packet) {
|
||||||
|
self.lastInbound = (new Date()).getTime()
|
||||||
|
// outbound qos-2 complete
|
||||||
|
});
|
||||||
|
client.on('pingresp',function(packet) {
|
||||||
|
self.lastInbound = (new Date()).getTime()
|
||||||
|
self.pingOutstanding = false;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.lastOutbound = (new Date()).getTime()
|
||||||
|
client.connect(self.options);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
MQTTClient.prototype.subscribe = function(topic,qos) {
|
||||||
|
var self = this;
|
||||||
|
if (self.connected) {
|
||||||
|
var options = {
|
||||||
|
subscriptions:[{topic:topic,qos:qos}],
|
||||||
|
messageId: self._nextMessageId()
|
||||||
|
};
|
||||||
|
this.pendingSubscriptions[options.messageId] = topic;
|
||||||
|
this.lastOutbound = (new Date()).getTime()
|
||||||
|
self.client.subscribe(options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MQTTClient.prototype.unsubscribe = function(topic) {
|
||||||
|
var self = this;
|
||||||
|
if (self.connected) {
|
||||||
|
var options = {
|
||||||
|
topic:topic,
|
||||||
|
messageId: self._nextMessageId()
|
||||||
|
};
|
||||||
|
this.pendingSubscriptions[options.messageId] = topic;
|
||||||
|
this.lastOutbound = (new Date()).getTime()
|
||||||
|
self.client.unsubscribe(options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MQTTClient.prototype.publish = function(topic,payload,qos,retain) {
|
||||||
|
var self = this;
|
||||||
|
if (self.connected) {
|
||||||
|
|
||||||
|
if (Buffer.isBuffer(payload)) {
|
||||||
|
payload = payload.toString();
|
||||||
|
} else if (typeof payload === "object") {
|
||||||
|
payload = JSON.stringify(payload);
|
||||||
|
} else if (typeof payload !== "string") {
|
||||||
|
payload = ""+payload;
|
||||||
|
}
|
||||||
|
var options = {
|
||||||
|
topic: topic,
|
||||||
|
payload: payload,
|
||||||
|
qos: qos||0,
|
||||||
|
retain:retain||false
|
||||||
|
};
|
||||||
|
if (options.qos != 0) {
|
||||||
|
options.messageId = self._nextMessageId();
|
||||||
|
}
|
||||||
|
this.lastOutbound = (new Date()).getTime()
|
||||||
|
self.client.publish(options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MQTTClient.prototype.disconnect = function() {
|
||||||
|
var self = this;
|
||||||
|
if (this.connected) {
|
||||||
|
this.connected = false;
|
||||||
|
this.client.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MQTTClient.prototype.isConnected = function() {
|
||||||
|
return this.connected;
|
||||||
|
}
|
||||||
|
module.exports.createClient = function(port,host) {
|
||||||
|
var mqtt_client = new MQTTClient(port,host);
|
||||||
|
return mqtt_client;
|
||||||
|
}
|
||||||
|
|
119
nodes/io/lib/mqttConnectionPool.js
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
/**
|
||||||
|
* 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 util = require("util");
|
||||||
|
var mqtt = require("./mqtt");
|
||||||
|
var settings = require("../../../red/red").settings;
|
||||||
|
|
||||||
|
var connections = {};
|
||||||
|
|
||||||
|
function matchTopic(ts,t) {
|
||||||
|
var re = new RegExp("^"+ts.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g,"\\$1").replace(/\+/g,"[^/]+").replace(/#$/,".*"));
|
||||||
|
return re.test(t);
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
get: function(broker,port) {
|
||||||
|
var id = broker+":"+port;
|
||||||
|
if (!connections[id]) {
|
||||||
|
connections[id] = function() {
|
||||||
|
var client = mqtt.createClient(port,broker);
|
||||||
|
var options = {keepalive:15,clientId:'mqtt_' + (1+Math.random()*4294967295).toString(16)};
|
||||||
|
var queue = [];
|
||||||
|
var subscriptions = [];
|
||||||
|
var connecting = false;
|
||||||
|
var obj = {
|
||||||
|
_instances: 0,
|
||||||
|
publish: function(msg) {
|
||||||
|
if (client.isConnected()) {
|
||||||
|
client.publish(msg.topic,msg.payload,msg.qos,msg.retain);
|
||||||
|
} else {
|
||||||
|
if (!connecting) {
|
||||||
|
connecting = true;
|
||||||
|
client.connect(options);
|
||||||
|
}
|
||||||
|
queue.push(msg);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
subscribe: function(topic,qos,callback) {
|
||||||
|
subscriptions.push({topic:topic,qos:qos,callback:callback});
|
||||||
|
client.on('message',function(mtopic,mpayload,mqos,mretain) {
|
||||||
|
if (matchTopic(topic,mtopic)) {
|
||||||
|
callback(mtopic,mpayload,mqos,mretain);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (client.isConnected()) {
|
||||||
|
client.subscribe(topic,qos);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
on: function(a,b){
|
||||||
|
client.on(a,b);
|
||||||
|
},
|
||||||
|
once: function(a,b){
|
||||||
|
client.once(a,b);
|
||||||
|
},
|
||||||
|
connect: function() {
|
||||||
|
if (!client.isConnected() && !connecting) {
|
||||||
|
connecting = true;
|
||||||
|
client.connect(options);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
disconnect: function() {
|
||||||
|
this._instances -= 1;
|
||||||
|
if (this._instances == 0) {
|
||||||
|
client.disconnect();
|
||||||
|
client = null;
|
||||||
|
delete connections[id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
client.on('connect',function() {
|
||||||
|
|
||||||
|
util.log('[mqtt] connected to broker tcp://'+broker+':'+port);
|
||||||
|
|
||||||
|
connecting = false;
|
||||||
|
for (var s in subscriptions) {
|
||||||
|
var topic = subscriptions[s].topic;
|
||||||
|
var qos = subscriptions[s].qos;
|
||||||
|
var callback = subscriptions[s].callback;
|
||||||
|
client.subscribe(topic,qos);
|
||||||
|
}
|
||||||
|
//console.log("connected - publishing",queue.length,"messages");
|
||||||
|
while(queue.length) {
|
||||||
|
var msg = queue.shift();
|
||||||
|
//console.log(msg);
|
||||||
|
client.publish(msg.topic,msg.payload,msg.qos,msg.retain);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
client.on('connectionlost', function(err) {
|
||||||
|
util.log('[mqtt] connection lost to broker tcp://'+broker+':'+port);
|
||||||
|
setTimeout(function() {
|
||||||
|
if (client) {
|
||||||
|
client.connect(options);
|
||||||
|
}
|
||||||
|
}, settings.mqttReconnectTime||5000);
|
||||||
|
});
|
||||||
|
client.on('disconnect', function() {
|
||||||
|
util.log('[mqtt] disconnected from broker tcp://'+broker+':'+port);
|
||||||
|
});
|
||||||
|
|
||||||
|
return obj
|
||||||
|
}();
|
||||||
|
}
|
||||||
|
connections[id]._instances += 1;
|
||||||
|
return connections[id];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
192
nodes/social/27-twitter.html
Normal file
@ -0,0 +1,192 @@
|
|||||||
|
<!--
|
||||||
|
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="twitter-credentials">
|
||||||
|
<div class="form-row" id="node-config-twitter-row"></div>
|
||||||
|
<input type="hidden" id="node-config-input-screen_name">
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var twitterConfigNodeId = null;
|
||||||
|
var twitterConfigNodeIntervalId = null;
|
||||||
|
|
||||||
|
function showTwitterAuthStart() {
|
||||||
|
var pathname = document.location.pathname;
|
||||||
|
if (pathname.slice(-1) != "/") {
|
||||||
|
pathname += "/";
|
||||||
|
}
|
||||||
|
var callback = encodeURIComponent(location.protocol+"//"+location.hostname+":"+location.port+pathname+"twitter/"+twitterConfigNodeId+"/auth/callback");
|
||||||
|
|
||||||
|
$("#node-config-twitter-row").html('Click <a id="node-config-twitter-start" href="/twitter/'+twitterConfigNodeId+'/auth?callback='+callback+'" target="_blank">here</a> to authenticate with Twitter.');
|
||||||
|
$("#node-config-twitter-start").click(function() {
|
||||||
|
twitterConfigNodeIntervalId = window.setTimeout(pollTwitterCredentials,2000);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function updateTwitterScreenName(sn) {
|
||||||
|
$("#node-config-input-screen_name").val(sn);
|
||||||
|
$("#node-config-twitter-row").html('<label><i class="icon-user"></i> Twitter ID</label><span class="input-xlarge uneditable-input">'+sn+'</span>');
|
||||||
|
}
|
||||||
|
function pollTwitterCredentials(e) {
|
||||||
|
$.getJSON('twitter/'+twitterConfigNodeId,function(data) {
|
||||||
|
if (data.sn) {
|
||||||
|
updateTwitterScreenName(data.sn);
|
||||||
|
twitterConfigNodeIntervalId = null;
|
||||||
|
} else {
|
||||||
|
twitterConfigNodeIntervalId = window.setTimeout(pollTwitterCredentials,2000);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
RED.nodes.registerType('twitter-credentials',{
|
||||||
|
category: 'config',
|
||||||
|
defaults: {
|
||||||
|
screen_name: {value:""},
|
||||||
|
access_token: {value: ""},
|
||||||
|
access_token_secret: {value:""}
|
||||||
|
},
|
||||||
|
label: function() {
|
||||||
|
return this.screen_name;
|
||||||
|
},
|
||||||
|
exportable: false,
|
||||||
|
oneditprepare: function() {
|
||||||
|
twitterConfigNodeId = this.id;
|
||||||
|
if (!this.screen_name || this.screen_name == "") {
|
||||||
|
showTwitterAuthStart();
|
||||||
|
} else {
|
||||||
|
$.getJSON('twitter/'+twitterConfigNodeId,function(data) {
|
||||||
|
if (data.sn) {
|
||||||
|
updateTwitterScreenName(data.sn);
|
||||||
|
} else {
|
||||||
|
showTwitterAuthStart();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
oneditsave: function() {
|
||||||
|
if (twitterConfigNodeIntervalId) {
|
||||||
|
window.clearTimeout(twitterConfigNodeIntervalId);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
oneditcancel: function(adding) {
|
||||||
|
if (twitterConfigNodeIntervalId) {
|
||||||
|
window.clearTimeout(twitterConfigNodeIntervalId);
|
||||||
|
}
|
||||||
|
if (adding) {
|
||||||
|
$.ajax({
|
||||||
|
url: 'twitter/'+this.id,
|
||||||
|
type: 'DELETE',
|
||||||
|
success: function(result) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ondelete: function() {
|
||||||
|
$.ajax({
|
||||||
|
url: 'twitter/'+this.id,
|
||||||
|
type: 'DELETE',
|
||||||
|
success: function(result) {}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-template-name="twitter in">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-twitter"><i class="icon-user"></i> Twitter</label>
|
||||||
|
<input type="text" id="node-input-twitter">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-tags"><i class="icon-tag"></i> Tags</label>
|
||||||
|
<input type="text" id="node-input-tags" placeholder="comma-separated tags">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label> </label>
|
||||||
|
<input type="checkbox" id="node-input-user" placeholder="Name" style="display: inline-block; width: auto; vertical-align: top;">
|
||||||
|
<label for="node-input-user" style="width: 70%;">Tick to use user stream<br/>(rather than status/filter)</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-topic"><i class="icon-tasks"></i> Topic</label>
|
||||||
|
<input type="text" id="node-input-topic" placeholder="Topic">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
<div class="form-tips">Tip: the Senders name gets appended to the topic heirarchy
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="twitter in">
|
||||||
|
<p>Twitter input node. Watches the public stream for tweets containing the configured search term.</p>
|
||||||
|
<p>Sets the <b>msg.topic</b> to the configured topic and then appends the senders screen name.</p>
|
||||||
|
<p>Sets <b>msg.location</b> to the tweeters location if known.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('twitter in',{
|
||||||
|
category: 'social-input',
|
||||||
|
color:"#C0DEED",
|
||||||
|
defaults: {
|
||||||
|
twitter: {type:"twitter-credentials",required:true},
|
||||||
|
tags: {value:"",required:true},
|
||||||
|
user: {value:false},
|
||||||
|
name: {value:""},
|
||||||
|
topic: {value:"tweets"}
|
||||||
|
},
|
||||||
|
inputs:0,
|
||||||
|
outputs:1,
|
||||||
|
icon: "twitter.png",
|
||||||
|
label: function() {
|
||||||
|
return this.name||this.topic;
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script type="text/x-red" data-template-name="twitter out">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-twitter"><i class="icon-user"></i> Twitter</label>
|
||||||
|
<input type="text" id="node-input-twitter">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="twitter out">
|
||||||
|
<p>Twitter out node. Tweets the <b>msg.payload</b>.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('twitter out',{
|
||||||
|
category: 'social-output',
|
||||||
|
color:"#C0DEED",
|
||||||
|
defaults: {
|
||||||
|
twitter: {type:"twitter-credentials",required:true},
|
||||||
|
name: {value:"Tweet"}
|
||||||
|
},
|
||||||
|
inputs:1,
|
||||||
|
outputs:0,
|
||||||
|
icon: "twitter.png",
|
||||||
|
align: "right",
|
||||||
|
label: function() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
211
nodes/social/27-twitter.js
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
var ntwitter = require('ntwitter');
|
||||||
|
var OAuth= require('oauth').OAuth;
|
||||||
|
|
||||||
|
function TwitterNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.screen_name = n.screen_name;
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("twitter-credentials",TwitterNode);
|
||||||
|
|
||||||
|
|
||||||
|
function TwitterInNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.active = true;
|
||||||
|
this.user = n.user;
|
||||||
|
this.tags = n.tags.replace(/ /g,'');
|
||||||
|
this.twitter = n.twitter;
|
||||||
|
this.topic = n.topic;
|
||||||
|
this.twitterConfig = RED.nodes.getNode(this.twitter);
|
||||||
|
var credentials = RED.nodes.getCredentials(this.twitter);
|
||||||
|
|
||||||
|
if (credentials && credentials.screen_name == this.twitterConfig.screen_name) {
|
||||||
|
var twit = new ntwitter({
|
||||||
|
consumer_key: "OKjYEd1ef2bfFolV25G5nQ",
|
||||||
|
consumer_secret: "meRsltCktVMUI8gmggpXett7WBLd1k0qidYazoML6g",
|
||||||
|
access_token_key: credentials.access_token,
|
||||||
|
access_token_secret: credentials.access_token_secret
|
||||||
|
});
|
||||||
|
|
||||||
|
var node = this;
|
||||||
|
if (this.tags !== "") {
|
||||||
|
try {
|
||||||
|
var thing = 'statuses/filter';
|
||||||
|
if (this.user) { thing = 'user'; }
|
||||||
|
function setupStream() {
|
||||||
|
if (node.active) {
|
||||||
|
twit.stream(thing, { track: [node.tags] }, function(stream) {
|
||||||
|
//twit.stream('user', { track: [node.tags] }, function(stream) {
|
||||||
|
//twit.stream('statuses/filter', { track: [node.tags] }, function(stream) {
|
||||||
|
node.stream = stream;
|
||||||
|
stream.on('data', function(tweet) {
|
||||||
|
//console.log(tweet.user);
|
||||||
|
if (tweet.user !== undefined) {
|
||||||
|
var where = tweet.user.location||"";
|
||||||
|
var la = tweet.lang || tweet.user.lang;
|
||||||
|
//console.log(tweet.user.location,"=>",tweet.user.screen_name,"=>",pay);
|
||||||
|
var msg = { topic:node.topic+"/"+tweet.user.screen_name, payload:tweet.text, location:where, lang:la, tweet:tweet };
|
||||||
|
node.send(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
stream.on('error', function(tweet) {
|
||||||
|
node.warn(tweet);
|
||||||
|
setTimeout(setupStream,5000);
|
||||||
|
});
|
||||||
|
stream.on('destroy', function (response) {
|
||||||
|
if (this.active) {
|
||||||
|
node.warn("twitter ended unexpectedly");
|
||||||
|
setTimeout(setupStream,5000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setupStream();
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
node.error(err);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.error("Invalid tag property");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this.error("missing twitter credentials");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("twitter in",TwitterInNode);
|
||||||
|
|
||||||
|
TwitterInNode.prototype.close = function() {
|
||||||
|
if (this.stream) {
|
||||||
|
this.active = false;
|
||||||
|
this.stream.destroy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function TwitterOutNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.topic = n.topic;
|
||||||
|
this.twitter = n.twitter;
|
||||||
|
this.twitterConfig = RED.nodes.getNode(this.twitter);
|
||||||
|
var credentials = RED.nodes.getCredentials(this.twitter);
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
if (credentials && credentials.screen_name == this.twitterConfig.screen_name) {
|
||||||
|
var twit = new ntwitter({
|
||||||
|
consumer_key: "OKjYEd1ef2bfFolV25G5nQ",
|
||||||
|
consumer_secret: "meRsltCktVMUI8gmggpXett7WBLd1k0qidYazoML6g",
|
||||||
|
access_token_key: credentials.access_token,
|
||||||
|
access_token_secret: credentials.access_token_secret
|
||||||
|
}).verifyCredentials(function (err, data) {
|
||||||
|
if (err) {
|
||||||
|
node.error("Error verifying credentials: " + err);
|
||||||
|
} else {
|
||||||
|
node.on("input", function(msg) {
|
||||||
|
if (msg != null) {
|
||||||
|
if (msg.payload.length > 140) {
|
||||||
|
msg.payload = msg.payload.slice(0,139);
|
||||||
|
node.warn("Tweet greater than 140 : truncated");
|
||||||
|
}
|
||||||
|
twit.updateStatus(msg.payload, function (err, data) {
|
||||||
|
if (err) node.error(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("twitter out",TwitterOutNode);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var oa = new OAuth(
|
||||||
|
"https://api.twitter.com/oauth/request_token",
|
||||||
|
"https://api.twitter.com/oauth/access_token",
|
||||||
|
"OKjYEd1ef2bfFolV25G5nQ",
|
||||||
|
"meRsltCktVMUI8gmggpXett7WBLd1k0qidYazoML6g",
|
||||||
|
"1.0",
|
||||||
|
null,
|
||||||
|
"HMAC-SHA1"
|
||||||
|
);
|
||||||
|
|
||||||
|
var credentials = {};
|
||||||
|
|
||||||
|
RED.app.get('/twitter/:id', function(req,res) {
|
||||||
|
var credentials = RED.nodes.getCredentials(req.params.id);
|
||||||
|
if (credentials) {
|
||||||
|
res.send(JSON.stringify({sn:credentials.screen_name}));
|
||||||
|
} else {
|
||||||
|
res.send(JSON.stringify({}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RED.app.delete('/twitter/:id', function(req,res) {
|
||||||
|
RED.nodes.deleteCredentials(req.params.id);
|
||||||
|
res.send(200);
|
||||||
|
});
|
||||||
|
|
||||||
|
RED.app.get('/twitter/:id/auth', function(req, res){
|
||||||
|
var credentials = {};
|
||||||
|
oa.getOAuthRequestToken({
|
||||||
|
oauth_callback: req.query.callback
|
||||||
|
},function(error, oauth_token, oauth_token_secret, results){
|
||||||
|
if (error) {
|
||||||
|
console.log(error);
|
||||||
|
res.send("yeah no. didn't work.")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
credentials.oauth_token = oauth_token;
|
||||||
|
credentials.oauth_token_secret = oauth_token_secret;
|
||||||
|
res.redirect('https://twitter.com/oauth/authorize?oauth_token='+oauth_token)
|
||||||
|
RED.nodes.addCredentials(req.params.id,credentials);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
RED.app.get('/twitter/:id/auth/callback', function(req, res, next){
|
||||||
|
|
||||||
|
var credentials = RED.nodes.getCredentials(req.params.id);
|
||||||
|
credentials.oauth_verifier = req.query.oauth_verifier;
|
||||||
|
|
||||||
|
oa.getOAuthAccessToken(
|
||||||
|
credentials.oauth_token,
|
||||||
|
credentials.token_secret,
|
||||||
|
credentials.oauth_verifier,
|
||||||
|
function(error, oauth_access_token, oauth_access_token_secret, results){
|
||||||
|
if (error){
|
||||||
|
console.log(error);
|
||||||
|
res.send("yeah something broke.");
|
||||||
|
} else {
|
||||||
|
credentials = {};
|
||||||
|
credentials.access_token = oauth_access_token;
|
||||||
|
credentials.access_token_secret = oauth_access_token_secret;
|
||||||
|
credentials.screen_name = "@"+results.screen_name;
|
||||||
|
RED.nodes.addCredentials(req.params.id,credentials);
|
||||||
|
res.send("<html><head></head><body>Authorised - you can close this window and return to Node-RED</body></html>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
57
nodes/social/32-feedparse.html
Normal file
@ -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="feedparse">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-url"><i class="icon-globe"></i> Feed url</label>
|
||||||
|
<input type="text" id="node-input-url">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-interval"><i class="icon-repeat"></i> Repeat <span style="font-size: 0.9em;">(M)</span></label>
|
||||||
|
<input type="text" id="node-input-interval" placeholder="minutes">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
<!-- <div class="form-tips"></div> -->
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="feedparse">
|
||||||
|
<p>Monitors an RSS/atom feed for new entries.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('feedparse',{
|
||||||
|
category: 'advanced-input',
|
||||||
|
color:"#C0DEED",
|
||||||
|
defaults: {
|
||||||
|
name: {value:""},
|
||||||
|
url: {value:"", required:true},
|
||||||
|
interval: { value:15, required: true,validate:RED.validators.number()}
|
||||||
|
},
|
||||||
|
inputs:0,
|
||||||
|
outputs:1,
|
||||||
|
icon: "feed.png",
|
||||||
|
label: function() {
|
||||||
|
return this.name||this.url;
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
75
nodes/social/32-feedparse.js
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
var FeedParser = require("feedparser");
|
||||||
|
var request = require("request");
|
||||||
|
|
||||||
|
function FeedParseNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.url = n.url;
|
||||||
|
this.interval = (parseInt(n.interval)||15)*60000;
|
||||||
|
var node = this;
|
||||||
|
this.interval_id = null;
|
||||||
|
this.seen = {};
|
||||||
|
if (this.url !== "") {
|
||||||
|
var getFeed = function() {
|
||||||
|
request(node.url,function(err) {
|
||||||
|
if (err) node.error(err);
|
||||||
|
})
|
||||||
|
.pipe(new FeedParser({feedurl:node.url}))
|
||||||
|
.on('error', function(error) {
|
||||||
|
node.error(error);
|
||||||
|
})
|
||||||
|
.on('meta', function (meta) {})
|
||||||
|
.on('article', function (article) {
|
||||||
|
if (!(article.guid in node.seen) || ( node.seen[article.guid] != 0 && node.seen[article.guid] != article.date.getTime())) {
|
||||||
|
node.seen[article.guid] = article.date?article.date.getTime():0;
|
||||||
|
var msg = {
|
||||||
|
topic:article.origlink||article.link,
|
||||||
|
payload: article.description,
|
||||||
|
article: {
|
||||||
|
summary:article.summary,
|
||||||
|
link:article.link,
|
||||||
|
date: article.date,
|
||||||
|
pubdate: article.pubdate,
|
||||||
|
author: article.author,
|
||||||
|
guid: article.guid,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
node.send(msg);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.on('end', function () {
|
||||||
|
});
|
||||||
|
};
|
||||||
|
this.interval_id = setInterval(getFeed,node.interval);
|
||||||
|
getFeed();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this.error("Invalid url");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("feedparse",FeedParseNode);
|
||||||
|
|
||||||
|
FeedParseNode.prototype.close = function() {
|
||||||
|
if (this.interval_id != null) {
|
||||||
|
clearInterval(this.interval_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
55
nodes/social/57-notify.html
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<!--
|
||||||
|
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="notify">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-title"><i class="icon-tag"></i> Title</label>
|
||||||
|
<input type="text" id="node-input-title" placeholder="Node-RED">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="notify">
|
||||||
|
<p>Uses Growl to provide a desktop popup containing the <b>msg.payload</b>. Only useful on the local machine.</p>
|
||||||
|
<p>Optionally uses <b>msg.topic</b> as the title.</p>
|
||||||
|
<p>Uses Growl so should work cross platform but will need pre-reqs installed... see <i><a href="https://npmjs.org/package/growl" target="_new">this link.</a></i></p>
|
||||||
|
<p>If installing on Windows you MUST read the install instructions ... especially the bit about adding growlnotify to your path... or it WON'T work.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('notify',{
|
||||||
|
category: 'output',
|
||||||
|
defaults: {
|
||||||
|
title: {value:""},
|
||||||
|
name: {value:""}
|
||||||
|
},
|
||||||
|
color:"#a7c9a0",
|
||||||
|
inputs:1,
|
||||||
|
outputs:0,
|
||||||
|
icon: "alert.png",
|
||||||
|
align: "right",
|
||||||
|
label: function() {
|
||||||
|
return this.name||this.title||"notify";
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
39
nodes/social/57-notify.js
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
var growl = require('growl');
|
||||||
|
var imagefile = __dirname+"/../../public/mqtt-node-red.png";
|
||||||
|
|
||||||
|
function NotifyNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.title = n.title;
|
||||||
|
var node = this;
|
||||||
|
this.on("input",function(msg) {
|
||||||
|
var titl = this.title||msg.topic;
|
||||||
|
if (typeof(msg.payload) == 'object') {
|
||||||
|
msg.payload = JSON.stringify(msg.payload);
|
||||||
|
}
|
||||||
|
if (typeof(titl) != 'undefined') {
|
||||||
|
growl(msg.payload, { title: titl, image: imagefile });
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
growl(msg.payload, { image: imagefile });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("notify",NotifyNode);
|
61
nodes/social/57-prowl.html
Normal file
@ -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="prowl">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-title"><i class="icon-tag"></i> Title</label>
|
||||||
|
<input type="text" id="node-input-title" placeholder="Node-RED">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-priority"><i class="icon-tag"></i> Priority</label>
|
||||||
|
<input type="text" id="node-input-priority" placeholder="0">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="prowl">
|
||||||
|
<p>Uses Prowl to push the <b>msg.payload</b> to an Apple device that has the prowl app installed.</p>
|
||||||
|
<p>Optionally uses <b>msg.topic</b> to set the title. You can also set <b>msg.priority</b> to confgure the urgency from -2 (low), through 0 (normal) to 2 (urgent).</p>
|
||||||
|
<p>You MUST configure your prowl API key into the pushkey.js file in the directory above node-red.</p>
|
||||||
|
<p><pre>module.exports = { prowl:'My-API-KEY' }</pre></p>
|
||||||
|
<p>Uses Prowl so see <i><a href="https://www.prowlapp.com" target="_new">this link</a></i> for more details.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('prowl',{
|
||||||
|
category: 'output',
|
||||||
|
defaults: {
|
||||||
|
title: {value:""},
|
||||||
|
priority: {value:0,required:true,validate:RED.validators.number()},
|
||||||
|
name: {value:""}
|
||||||
|
},
|
||||||
|
color:"#a7c9a0",
|
||||||
|
inputs:1,
|
||||||
|
outputs:0,
|
||||||
|
icon: "prowl.png",
|
||||||
|
align: "right",
|
||||||
|
label: function() {
|
||||||
|
return this.name||this.title||"prowl";
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
56
nodes/social/57-prowl.js
Normal file
@ -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.
|
||||||
|
**/
|
||||||
|
|
||||||
|
var RED = require("../../red/red");
|
||||||
|
var Prowl = require('node-prowl');
|
||||||
|
|
||||||
|
// pushkey.js just needs to be like (with the quotes)
|
||||||
|
// module.exports = {prowl:'My-API-KEY'}
|
||||||
|
|
||||||
|
try {
|
||||||
|
var pushkey = require("../../settings").prowl || require("../../../pushkey.js");
|
||||||
|
} catch(err) {
|
||||||
|
throw new Error("Failed to load Prowl credentials");
|
||||||
|
}
|
||||||
|
|
||||||
|
var prowl = new Prowl(pushkey.prowl);
|
||||||
|
|
||||||
|
function ProwlNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.title = n.title;
|
||||||
|
this.priority = n.priority * 1;
|
||||||
|
if (this.priority > 2) this.priority = 2;
|
||||||
|
if (this.priority < -2) this.priority = -2;
|
||||||
|
var node = this;
|
||||||
|
this.on("input",function(msg) {
|
||||||
|
var titl = this.title||msg.topic||"Node-RED";
|
||||||
|
var pri = msg.priority||this.priority;
|
||||||
|
if (typeof(msg.payload) == 'object') {
|
||||||
|
msg.payload = JSON.stringify(msg.payload);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
prowl.push(msg.payload, titl, { priority: pri }, function( err, remaining ){
|
||||||
|
if ( err ) node.error(err);
|
||||||
|
node.log( remaining + ' calls to Prowl api during current hour.' );
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
node.error(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("prowl",ProwlNode);
|
60
nodes/social/57-pushbullet.html
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
<!--
|
||||||
|
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="pushbullet">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-title"><i class="icon-tag"></i> Title</label>
|
||||||
|
<input type="text" id="node-input-title" placeholder="Node-RED">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-priority"><i class="icon-tag"></i> Priority</label>
|
||||||
|
<input type="text" id="node-input-priority" placeholder="0">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="pushbullet">
|
||||||
|
<p>Uses PushBullet to push the <b>msg.payload</b> to an Android device that has PushBullet app installed.</p>
|
||||||
|
<p>Optionally uses <b>msg.topic</b> to set the title.</p>
|
||||||
|
<p>You MUST configure both your API key and the target device ID into the pushkey.js file in the directory above node-red.<p>
|
||||||
|
<p><pre>>module.exports = { pushbullet:'My-API-KEY', deviceid:'12345' }</pre</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('pushbullet',{
|
||||||
|
category: 'output',
|
||||||
|
defaults: {
|
||||||
|
title: {value:""},
|
||||||
|
priority: {value:0,required:true,validate:RED.validators.number()},
|
||||||
|
name: {value:""}
|
||||||
|
},
|
||||||
|
color:"#a7c9a0",
|
||||||
|
inputs:1,
|
||||||
|
outputs:0,
|
||||||
|
icon: "bullet.png",
|
||||||
|
align: "right",
|
||||||
|
label: function() {
|
||||||
|
return this.name||this.title||"pushbullet";
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
54
nodes/social/57-pushbullet.js
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
var PushBullet = require('pushbullet');
|
||||||
|
|
||||||
|
// pushkey.js just needs to be like (with the quotes)
|
||||||
|
// module.exports = {pushbullet:'My-API-KEY', deviceid:'12345'}
|
||||||
|
|
||||||
|
try {
|
||||||
|
var pushkey = require("../../settings").pushbullet || require("../../../pushkey.js");
|
||||||
|
} catch(err) {
|
||||||
|
throw new Error("Failed to load PushBullet credentials");
|
||||||
|
}
|
||||||
|
|
||||||
|
var pusher = new PushBullet(pushkey.pushbullet);
|
||||||
|
var deviceId = pushkey.deviceid;
|
||||||
|
|
||||||
|
function PushbulletNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.title = n.title;
|
||||||
|
this.device
|
||||||
|
var node = this;
|
||||||
|
this.on("input",function(msg) {
|
||||||
|
var titl = this.title||msg.topic||"Node-RED";
|
||||||
|
if (typeof(msg.payload) == 'object') {
|
||||||
|
msg.payload = JSON.stringify(msg.payload);
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
pusher.note(deviceId, titl, msg.payload, function(err, response) {
|
||||||
|
if ( err ) node.error(err);
|
||||||
|
node.log( JSON.stringify(response) );
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (err) {
|
||||||
|
node.error(err);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("pushbullet",PushbulletNode);
|
50
nodes/social/61-email.html
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<!--
|
||||||
|
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="email">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-envelope"></i> To</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="email@address.com">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="email">
|
||||||
|
<p>Sends the <b>msg.payload</b> as an email, with a subject of <b>msg.topic</b>.</p>
|
||||||
|
<p>It sends the message to the configured recipient <i>only</i>.</p>
|
||||||
|
<p><b>msg.topic</b> is used to set the subject of the email, and <b>msg.payload</b> is the body text.</p>
|
||||||
|
<p>Uses the nodemailer module - you also need to pre-configure your email SMTP settings in ../../emailkeys.js - see INSTALL file for details.</p>
|
||||||
|
<p><pre>module.exports = { service: "Gmail", user: "blahblah@gmail.com", pass: "password", server: "imap.gmail.com", port: "993" }</pre></p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('email',{
|
||||||
|
category: 'social-output',
|
||||||
|
color:"#c7e9c0",
|
||||||
|
defaults: {
|
||||||
|
name: {value:"",required:true}
|
||||||
|
},
|
||||||
|
inputs:1,
|
||||||
|
outputs:0,
|
||||||
|
icon: "envelope.png",
|
||||||
|
align: "right",
|
||||||
|
label: function() {
|
||||||
|
return this.name;
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return (this.name||!this.topic)?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
55
nodes/social/61-email.js
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
var nodemailer = require("nodemailer");
|
||||||
|
var emailkey = require("../../../emailkeys.js");
|
||||||
|
|
||||||
|
var smtpTransport = nodemailer.createTransport("SMTP",{
|
||||||
|
service: emailkey.service,
|
||||||
|
auth: {
|
||||||
|
user: emailkey.user,
|
||||||
|
pass: emailkey.pass
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function EmailNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.topic = n.topic;
|
||||||
|
this.name = n.name;
|
||||||
|
var node = this;
|
||||||
|
this.on("input", function(msg) {
|
||||||
|
//node.log("email :",this.id,this.topic," received",msg.payload);
|
||||||
|
if (msg != null) {
|
||||||
|
|
||||||
|
smtpTransport.sendMail({
|
||||||
|
from: emailkey.user, // sender address
|
||||||
|
to: node.name, // comma separated list of receivers
|
||||||
|
subject: msg.topic, // Subject line
|
||||||
|
text: msg.payload // plaintext body
|
||||||
|
}, function(error, response) {
|
||||||
|
if (error) {
|
||||||
|
node.error(error);
|
||||||
|
} else {
|
||||||
|
node.log("Message sent: " + response.message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("email",EmailNode);
|
54
nodes/social/61-imap.html
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<!--
|
||||||
|
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="icon-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="icon-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 body text. <b>msg.from</b> is also set if you need it.</p>
|
||||||
|
<p>Uses the imap module - you also need to pre-configure your email settings in ../../emailkeys.js - see INSTALL file for details.</p>
|
||||||
|
<p><pre>module.exports = { service: "Gmail", user: "blahblah@gmail.com", pass: "password", server: "imap.gmail.com", port: "993" }</pre></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: 'social-input',
|
||||||
|
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>
|
114
nodes/social/61-imap.js
Normal file
@ -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.
|
||||||
|
**/
|
||||||
|
|
||||||
|
var RED = require("../../red/red");
|
||||||
|
var Imap = require('imap');
|
||||||
|
var inspect = require('util').inspect;
|
||||||
|
var oldmail = {};
|
||||||
|
|
||||||
|
try {
|
||||||
|
var emailkey = require("../../settings").email || require("../../../emailkeys.js");
|
||||||
|
} catch(err) {
|
||||||
|
throw new Error("Failed to load Email credentials");
|
||||||
|
}
|
||||||
|
|
||||||
|
var imap = new Imap({
|
||||||
|
user: emailkey.user,
|
||||||
|
password: emailkey.pass,
|
||||||
|
host: emailkey.server||"imap.gmail.com",
|
||||||
|
port: emailkey.port||"993",
|
||||||
|
secure: true
|
||||||
|
});
|
||||||
|
|
||||||
|
function show(obj) {
|
||||||
|
return inspect(obj, false, Infinity);
|
||||||
|
}
|
||||||
|
|
||||||
|
function fail(err) {
|
||||||
|
console.log('[imap] : ' + err);
|
||||||
|
}
|
||||||
|
|
||||||
|
function openInbox(cb) {
|
||||||
|
imap.connect(function(err) {
|
||||||
|
if (err) fail(err);
|
||||||
|
imap.openBox('INBOX', true, cb);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function ImapNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.name = n.name;
|
||||||
|
this.repeat = n.repeat * 1000;
|
||||||
|
var node = this;
|
||||||
|
this.interval_id = null;
|
||||||
|
|
||||||
|
if (this.repeat && !isNaN(this.repeat) && this.repeat > 0) {
|
||||||
|
this.log("repeat = "+this.repeat);
|
||||||
|
this.interval_id = setInterval( function() {
|
||||||
|
node.emit("input",{});
|
||||||
|
}, this.repeat );
|
||||||
|
}
|
||||||
|
|
||||||
|
this.on("input", function(msg) {
|
||||||
|
openInbox(function(err, mailbox) {
|
||||||
|
if (err) fail(err);
|
||||||
|
imap.seq.fetch(mailbox.messages.total + ':*', { struct: false },
|
||||||
|
{ headers: ['from', 'subject'],
|
||||||
|
body: true,
|
||||||
|
cb: function(fetch) {
|
||||||
|
fetch.on('message', function(msg) {
|
||||||
|
//node.log('Saw message no. ' + msg.seqno);
|
||||||
|
var pay = {};
|
||||||
|
var body = '';
|
||||||
|
msg.on('headers', function(hdrs) {
|
||||||
|
pay.from = hdrs.from[0];
|
||||||
|
pay.topic = hdrs.subject[0];
|
||||||
|
});
|
||||||
|
msg.on('data', function(chunk) {
|
||||||
|
body += chunk.toString('utf8');
|
||||||
|
});
|
||||||
|
msg.on('end', function() {
|
||||||
|
pay.payload = body;
|
||||||
|
if ((pay.topic !== oldmail.topic)|(pay.payload !== oldmail.payload)) {
|
||||||
|
oldmail = pay;
|
||||||
|
//node.log("From: "+pay.from);
|
||||||
|
node.log("Subj: "+pay.topic);
|
||||||
|
//node.log("Body: "+pay.payload);
|
||||||
|
node.send(pay);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, function(err) {
|
||||||
|
if (err) node.log("Err : "+err);
|
||||||
|
//node.log("Done fetching messages.");
|
||||||
|
imap.logout();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("imap",ImapNode);
|
||||||
|
|
||||||
|
ImapNode.prototype.close = function() {
|
||||||
|
if (this.interval_id != null) {
|
||||||
|
clearInterval(this.interval_id);
|
||||||
|
this.log("inject: repeat stopped");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
126
nodes/social/91-irc.html
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
<!--
|
||||||
|
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="irc in">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-ircserver"><i class="icon-tasks"></i> IRC Server</label>
|
||||||
|
<input type="text" id="node-input-ircserver">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="irc in">
|
||||||
|
<p>Connects to a channel on an IRC server</p>
|
||||||
|
<p>Any messages on that channel will appear on the <b>msg.payload</b> at the output, while <b>msg.topic</b> will contain who it is from.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('irc in',{
|
||||||
|
category: 'social-input',
|
||||||
|
defaults: {
|
||||||
|
name: {value:""},
|
||||||
|
ircserver: {type:"irc-server", required:true}
|
||||||
|
},
|
||||||
|
color:"Silver",
|
||||||
|
inputs:0,
|
||||||
|
outputs:1,
|
||||||
|
icon: "hash.png",
|
||||||
|
label: function() {
|
||||||
|
return this.name||(this.ircserver)?RED.nodes.node(this.ircserver).label():"irc";
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-template-name="irc out">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-ircserver"><i class="icon-tasks"></i> IRC Server</label>
|
||||||
|
<input type="text" id="node-input-ircserver">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label> </label>
|
||||||
|
<input type="checkbox" id="node-input-sendObject" placeholder="" style="display: inline-block; width: auto; vertical-align: top;">
|
||||||
|
<label for="node-input-sendObject" style="width: 70%;">Send complete msg object ?</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
<div class="form-tips">Sending complete object will stringify the whole msg object before sending.</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="irc out">
|
||||||
|
<p>Connects to a channel on an IRC server</p>
|
||||||
|
<p>If you send something with NO msg.topic it will go to the channel - otherwise it will go to the id in the <b>msg.topic</b> field.</p>
|
||||||
|
<p>You can either just send the <b>msg.payload</b>, or you can send the complete <b>msg</b> object.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('irc out',{
|
||||||
|
category: 'social-output',
|
||||||
|
defaults: {
|
||||||
|
name: {value:""},
|
||||||
|
sendObject: {value:false},
|
||||||
|
ircserver: {type:"irc-server", required:true}
|
||||||
|
},
|
||||||
|
color:"Silver",
|
||||||
|
inputs:1,
|
||||||
|
outputs:0,
|
||||||
|
icon: "hash.png",
|
||||||
|
align: "right",
|
||||||
|
label: function() {
|
||||||
|
return this.name || (this.ircserver)?RED.nodes.node(this.ircserver).label():"irc";
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-template-name="irc-server">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-config-input-server"><i class="icon-tasks"></i> IRC Server</label>
|
||||||
|
<input type="text" id="node-config-input-server" placeholder="irc.UK-IRC.net">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-config-input-channel"><i class="icon-tasks"></i> Channel</label>
|
||||||
|
<input type="text" id="node-config-input-channel" placeholder="#testing1234">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-config-input-nickname"><i class="icon-tasks"></i> Nickname</label>
|
||||||
|
<input type="text" id="node-config-input-nickname" placeholder="joe123">
|
||||||
|
</div>
|
||||||
|
<div class="form-tips">The channel to join must start with a # (as per normal irc rules...)</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('irc-server',{
|
||||||
|
category: 'config',
|
||||||
|
defaults: {
|
||||||
|
channel: {value:"",required:true,validate:RED.validators.regex(/^#/)},
|
||||||
|
server: {value:"",required:true},
|
||||||
|
nickname: {value:"",required:true}
|
||||||
|
},
|
||||||
|
label: function() {
|
||||||
|
return this.server+":"+this.channel;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
84
nodes/social/91-irc.js
Normal file
@ -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.
|
||||||
|
**/
|
||||||
|
|
||||||
|
var RED = require("../../red/red");
|
||||||
|
var irc = require("irc");
|
||||||
|
|
||||||
|
// The Server Definition - this opens (and closes) the connection
|
||||||
|
function IRCServerNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.server = n.server;
|
||||||
|
this.channel = n.channel;
|
||||||
|
this.nickname = n.nickname;
|
||||||
|
this.ircclient = new irc.Client(this.server, this.nickname, {
|
||||||
|
channels: [this.channel]
|
||||||
|
});
|
||||||
|
this._close = function() {
|
||||||
|
this.ircclient.disconnect();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("irc-server",IRCServerNode);
|
||||||
|
|
||||||
|
IRCServerNode.prototype.close = function() {
|
||||||
|
this._close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// The Input Node
|
||||||
|
function IrcInNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.ircserver = n.ircserver;
|
||||||
|
this.serverConfig = RED.nodes.getNode(this.ircserver);
|
||||||
|
this.ircclient = this.serverConfig.ircclient;
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
|
||||||
|
this.ircclient.addListener('message', function (from, to, message) {
|
||||||
|
console.log(from + ' => ' + to + ': ' + message);
|
||||||
|
var msg = { "topic":from, "to":to, "payload":message };
|
||||||
|
node.send(msg);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.ircclient.addListener('error', function(message) {
|
||||||
|
node.error(JSON.stringify(message));
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("irc in",IrcInNode);
|
||||||
|
|
||||||
|
// The Output Node
|
||||||
|
function IrcOutNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.sendAll = n.sendObject;
|
||||||
|
this.ircserver = n.ircserver;
|
||||||
|
this.serverConfig = RED.nodes.getNode(this.ircserver);
|
||||||
|
this.ircclient = this.serverConfig.ircclient;
|
||||||
|
this.channel = this.serverConfig.channel;
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
this.on("input", function(msg) {
|
||||||
|
console.log(msg);
|
||||||
|
if (node.sendAll) {
|
||||||
|
node.ircclient.say(node.channel, JSON.stringify(msg));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
var to = msg.topic || node.channel;
|
||||||
|
node.ircclient.say(to, msg.payload);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("irc out",IrcOutNode);
|
80
nodes/social/92-xmpp.html
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
<!--
|
||||||
|
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="xmpp">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-server"><i class="icon-bookmark"></i> Server</label>
|
||||||
|
<input type="text" id="node-input-server" placeholder="talk.google.com" style="width: 40%;" >
|
||||||
|
<label for="node-input-port" style="margin-left: 10px; width: 35px; "> Port</label>
|
||||||
|
<input type="text" id="node-input-port" placeholder="Port" style="width:45px">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label> </label>
|
||||||
|
<input type="checkbox" id="node-input-sendObject" placeholder="" style="display: inline-block; width: auto; vertical-align: top;">
|
||||||
|
<label for="node-input-sendObject" style="width: 70%;">Send complete msg object ?</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-to"><i class="icon-envelope"></i> To</label>
|
||||||
|
<input type="text" id="node-input-to" placeholder="joe@gmail.com">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label> </label>
|
||||||
|
<input type="checkbox" id="node-input-join" placeholder="" style="display: inline-block; width: auto; vertical-align: top;">
|
||||||
|
<label for="node-input-join" style="width: 70%;">Is a Chat Room ?</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-nick"><i class="icon-user"></i> Nickname</label>
|
||||||
|
<input type="text" id="node-input-nick" placeholder="Joe">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
<div class="form-tips">The <b>To</b> field is optional. If not set uses the <b>msg.topic</b> property of the message.</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="xmpp">
|
||||||
|
<p>Connects to an XMPP server to send and receive messages.</p>
|
||||||
|
<p>Incoming messages will appear as <b>msg.payload</b> on the first output, while <b>msg.topic</b> will contain who it is from.</p>
|
||||||
|
<p>The second output will user presence and status in <b>msg.payload</b>.</p>
|
||||||
|
<p>The <b>To</b> field is optional. If not set uses the <b>msg.topic</b> property of the message.</p>
|
||||||
|
<p>If you are joining a room then the <b>To</b> field must be filled in.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('xmpp',{
|
||||||
|
category: 'advanced-function',
|
||||||
|
color:"Silver",
|
||||||
|
defaults: {
|
||||||
|
name: {value:""},
|
||||||
|
server: { value:"",required:true},
|
||||||
|
port: {value:5222,required:true},
|
||||||
|
to: {value:""},
|
||||||
|
join: {value:"false"},
|
||||||
|
sendObject: { value:false },
|
||||||
|
nick: {value:""}
|
||||||
|
},
|
||||||
|
inputs:1,
|
||||||
|
outputs:2,
|
||||||
|
icon: "xmpp.png",
|
||||||
|
label: function() {
|
||||||
|
return this.name||this.server||"xmpp";
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return (this.name||!this.server)?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
113
nodes/social/92-xmpp.js
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
var xmpp = require('simple-xmpp');
|
||||||
|
|
||||||
|
try {
|
||||||
|
var xmppkey = require("../../settings").xmpp || require("../../../xmppkeys.js");
|
||||||
|
} catch(err) {
|
||||||
|
throw new Error("Failed to load XMPP credentials");
|
||||||
|
}
|
||||||
|
|
||||||
|
function XmppNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.server = n.server;
|
||||||
|
this.port = n.port;
|
||||||
|
this.join = n.join || false;
|
||||||
|
this.nick = n.nick || "Node-RED";
|
||||||
|
this.sendAll = n.sendObject;
|
||||||
|
this.to = n.to || "";
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
xmpp.connect({
|
||||||
|
jid : xmppkey.jid,
|
||||||
|
password : xmppkey.password,
|
||||||
|
host : this.server,
|
||||||
|
port : this.port,
|
||||||
|
skipPresence : true,
|
||||||
|
reconnect : false
|
||||||
|
});
|
||||||
|
}, 5000);
|
||||||
|
|
||||||
|
xmpp.on('online', function() {
|
||||||
|
node.log('connected to '+node.server);
|
||||||
|
xmpp.setPresence('online', node.nick+' online');
|
||||||
|
if (node.join) {
|
||||||
|
xmpp.join(node.to+'/'+node.nick);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
xmpp.on('chat', function(from, message) {
|
||||||
|
var msg = { topic:from, payload:message };
|
||||||
|
node.send([msg,null]);
|
||||||
|
});
|
||||||
|
|
||||||
|
xmpp.on('groupchat', function(conference, from, message, stamp) {
|
||||||
|
var msg = { topic:from, payload:message, room:conference };
|
||||||
|
if (from != node.nick) { node.send([msg,null]); }
|
||||||
|
});
|
||||||
|
|
||||||
|
//xmpp.on('chatstate', function(from, state) {
|
||||||
|
//console.log('%s is currently %s', from, state);
|
||||||
|
//var msg = { topic:from, payload:state };
|
||||||
|
//node.send([null,msg]);
|
||||||
|
//});
|
||||||
|
|
||||||
|
xmpp.on('buddy', function(jid, state, statusText) {
|
||||||
|
node.log(jid+" is "+state+" : "+statusText);
|
||||||
|
var msg = { topic:jid, payload: { presence:state, status:statusText} };
|
||||||
|
node.send([null,msg]);
|
||||||
|
});
|
||||||
|
|
||||||
|
xmpp.on('error', function(err) {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
xmpp.on('close', function(err) {
|
||||||
|
node.log('connection closed');
|
||||||
|
});
|
||||||
|
|
||||||
|
xmpp.on('subscribe', function(from) {
|
||||||
|
xmpp.acceptSubscription(from);
|
||||||
|
});
|
||||||
|
|
||||||
|
this.on("input", function(msg) {
|
||||||
|
var to = msg.topic;
|
||||||
|
if (node.to != "") { to = node.to; }
|
||||||
|
if (node.sendAll) {
|
||||||
|
xmpp.send(to, JSON.stringify(msg), node.join);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
xmpp.send(to, msg.payload, node.join);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this._close = function() {
|
||||||
|
xmpp.setPresence('offline');
|
||||||
|
//xmpp.conn.end();
|
||||||
|
// TODO - DCJ NOTE... this is not good. It leaves the connection up over a restart - which will end up with bad things happening...
|
||||||
|
// (but requires the underlying xmpp lib to be fixed (which does have an open bug request on fixing the close method)).
|
||||||
|
this.warn("Due to an underlying bug in the xmpp library this does not disconnect old sessions. This is bad... A restart would be better.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("xmpp",XmppNode);
|
||||||
|
|
||||||
|
XmppNode.prototype.close = function() {
|
||||||
|
this._close();
|
||||||
|
}
|
58
nodes/storage/28-tail.html
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
<!--
|
||||||
|
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="tail">
|
||||||
|
<div class="form-row node-input-filename">
|
||||||
|
<label for="node-input-filename"><i class="icon-file"></i> Filename</label>
|
||||||
|
<input type="text" id="node-input-filename" placeholder="Filename">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label> </label>
|
||||||
|
<input type="checkbox" id="node-input-split" placeholder="Name" style="display: inline-block; width: auto; vertical-align: top;">
|
||||||
|
<label for="node-input-split" style="width: 70%;">Split lines if we see \n ?</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
<div class="form-tips">WON'T work on Windows.</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="tail">
|
||||||
|
<p>Tails (watches for things to be added) to the configured file. (Linux/Mac ONLY)</p>
|
||||||
|
<p>This won't work on Windows filesystems (as it relies on the tail -f command) so we will probably have to hide it in future.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('tail',{
|
||||||
|
category: 'storage-input',
|
||||||
|
defaults: {
|
||||||
|
name: {value:""},
|
||||||
|
split: {value:false},
|
||||||
|
filename: {value:"",required:true}
|
||||||
|
},
|
||||||
|
color:"BurlyWood",
|
||||||
|
inputs:0,
|
||||||
|
outputs:1,
|
||||||
|
icon: "file.png",
|
||||||
|
label: function() {
|
||||||
|
return this.name||this.filename;
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
47
nodes/storage/28-tail.js
Normal file
@ -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.
|
||||||
|
**/
|
||||||
|
|
||||||
|
var RED = require("../../red/red");
|
||||||
|
var fs = require("fs");
|
||||||
|
var spawn = require('child_process').spawn;
|
||||||
|
|
||||||
|
function TailNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
|
||||||
|
this.filename = n.filename;
|
||||||
|
this.split = n.split;
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
var tail = spawn("tail", ["-f", this.filename]);
|
||||||
|
tail.stdout.on("data", function (data) {
|
||||||
|
var msg = {topic:node.filename};
|
||||||
|
if (node.split) {
|
||||||
|
var strings = data.toString().split("\n");
|
||||||
|
for (s in strings) {
|
||||||
|
if (strings[s] != "") {
|
||||||
|
msg.payload = strings[s];
|
||||||
|
node.send(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
msg.payload = data.toString();
|
||||||
|
node.send(msg);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("tail",TailNode);
|
66
nodes/storage/50-file.html
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
<!--
|
||||||
|
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="file">
|
||||||
|
<div class="form-row node-input-filename">
|
||||||
|
<label for="node-input-filename"><i class="icon-file"></i> Filename</label>
|
||||||
|
<input type="text" id="node-input-filename" placeholder="Filename">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label> </label>
|
||||||
|
<input type="checkbox" id="node-input-appendNewline" placeholder="Name" style="display: inline-block; width: auto; vertical-align: top;">
|
||||||
|
<label for="node-input-appendNewline" style="width: 70%;">Append newline ?</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label> </label>
|
||||||
|
<input type="checkbox" id="node-input-overwriteFile" placeholder="Name" style="display: inline-block; width: auto; vertical-align: top;">
|
||||||
|
<label for="node-input-overwriteFile" style="width: 70%;">Overwrite complete file ?</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="file">
|
||||||
|
<p>Writes the <b>msg.payload</b> to the file specified, e.g. to create a log.</p>
|
||||||
|
<p>A newline is added to every message. But this can be turned off if required, for example, to allow binary files to be written.</p>
|
||||||
|
<p>The default behaviour is to append to the file. This can be changed to overwrite the file each time, for example if you want to output a "static" web page or report.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('file',{
|
||||||
|
category: 'storage-output',
|
||||||
|
defaults: {
|
||||||
|
name: {value:""},
|
||||||
|
filename: {value:"",required:true},
|
||||||
|
appendNewline: {value:true},
|
||||||
|
overwriteFile: {value:false}
|
||||||
|
},
|
||||||
|
color:"BurlyWood",
|
||||||
|
inputs:1,
|
||||||
|
outputs:0,
|
||||||
|
icon: "file.png",
|
||||||
|
align: "right",
|
||||||
|
label: function() {
|
||||||
|
return this.name||this.filename;
|
||||||
|
},
|
||||||
|
labelStyle: function() {
|
||||||
|
return this.name?"node_label_italic":"";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
</script>
|
47
nodes/storage/50-file.js
Normal file
@ -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.
|
||||||
|
**/
|
||||||
|
|
||||||
|
var RED = require("../../red/red");
|
||||||
|
var fs = require("fs");
|
||||||
|
|
||||||
|
function FileNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
|
||||||
|
this.filename = n.filename;
|
||||||
|
this.appendNewline = n.appendNewline;
|
||||||
|
this.overwriteFile = n.overwriteFile;
|
||||||
|
var node = this;
|
||||||
|
this.on("input",function(msg) {
|
||||||
|
var data = msg.payload;
|
||||||
|
if (this.appendNewline) {
|
||||||
|
data += "\n";
|
||||||
|
}
|
||||||
|
if (this.overwriteFile) {
|
||||||
|
fs.writeFile(this.filename, data, function (err) {
|
||||||
|
if (err) node.warn('Failed to write to file : '+err);
|
||||||
|
//console.log('Message written to file',this.filename);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
fs.appendFile(this.filename, data, function (err) {
|
||||||
|
if (err) node.warn('Failed to append to file : '+err);
|
||||||
|
//console.log('Message appended to file',this.filename);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("file",FileNode);
|
105
nodes/storage/65-redisout.html
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
<!--
|
||||||
|
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="redis out">
|
||||||
|
<div class="form-row node-input-hostname">
|
||||||
|
<label for="node-input-hostname"><i class="icon-bookmark"></i> Host</label>
|
||||||
|
<input class="input-append-left" type="text" id="node-input-hostname" placeholder="127.0.0.1" style="width: 40%;" ><button id="node-input-hostname-lookup" class="btn input-append-right"><span class="caret"></span></button>
|
||||||
|
<label for="node-input-port" style="margin-left: 10px; width: 35px; "> Port</label>
|
||||||
|
<input type="text" id="node-input-port" placeholder="6379" style="width:45px">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-key"><i class="icon-briefcase"></i> Key</label>
|
||||||
|
<input type="text" id="node-input-key" placeholder="Redis Key">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-type"><i class="icon-th"></i> Type</label>
|
||||||
|
<select type="text" id="node-input-structtype" style="width: 150px;">
|
||||||
|
<option value="string">String</option>
|
||||||
|
<option value="hash">Hash</option>
|
||||||
|
<option value="set">Set</option>
|
||||||
|
<option value="list">List</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
<div class="form-tips">
|
||||||
|
If key is blank, the topic will be used as the key.<br>
|
||||||
|
If type is hash, payload should be field=value.
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="redis out">
|
||||||
|
<p>A Redis output node. Options include Hash, Set, List and String.</p>
|
||||||
|
<p>To run this you need a local Redis server running. For details see <a href="http://redis.io/" target="_new">the Redis site</a>.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('redis out',{
|
||||||
|
category: 'storage-output',
|
||||||
|
color:"#ffaaaa",
|
||||||
|
defaults: {
|
||||||
|
hostname: { value:"127.0.0.1",required:true},
|
||||||
|
port: { value: 6379,required:true},
|
||||||
|
name: {value:""},
|
||||||
|
key: {value:""},
|
||||||
|
structtype: {value:"",required:true}
|
||||||
|
},
|
||||||
|
inputs:1,
|
||||||
|
outputs:0,
|
||||||
|
icon: "redis.png",
|
||||||
|
align: "right",
|
||||||
|
label: function() {
|
||||||
|
return this.name||this.key+" ("+this.structtype+")";
|
||||||
|
},
|
||||||
|
oneditprepare: function() {
|
||||||
|
var availableServers = [];
|
||||||
|
var matchedServers = {};
|
||||||
|
RED.nodes.eachNode(function(node) {
|
||||||
|
if (node.type == "redis out" && node.hostname && node.port && !matchedServers[node.hostname+":"+node.port]) {
|
||||||
|
var label = node.hostname+":"+node.port;
|
||||||
|
matchedServers[label] = true;
|
||||||
|
availableServers.push({
|
||||||
|
label:label,
|
||||||
|
value:node.hostname,
|
||||||
|
port:node.port
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$( "#node-input-hostname" ).autocomplete({
|
||||||
|
minLength: 0,
|
||||||
|
source: availableServers,
|
||||||
|
select: function( event, ui ) {
|
||||||
|
$("#node-input-port").val(ui.item.port);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
var tt = this;
|
||||||
|
tt._acOpen = false;
|
||||||
|
$( "#node-input-hostname" ).on( "autocompleteclose", function( event, ui ) { tt._acOpen = false;} );
|
||||||
|
$( "#node-input-hostname-lookup" ).click(function(e) {
|
||||||
|
if (tt._acOpen) {
|
||||||
|
$( "#node-input-hostname" ).autocomplete( "close");
|
||||||
|
} else {
|
||||||
|
$( "#node-input-hostname" ).autocomplete( "search", "" );
|
||||||
|
}
|
||||||
|
tt._acOpen = !tt._acOpen;
|
||||||
|
e.preventDefault();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
96
nodes/storage/65-redisout.js
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
var util = require("util");
|
||||||
|
var redis = require("redis");
|
||||||
|
|
||||||
|
var hashFieldRE = /^([^=]+)=(.*)$/;
|
||||||
|
|
||||||
|
var redisConnectionPool = function() {
|
||||||
|
var connections = {};
|
||||||
|
var obj = {
|
||||||
|
get: function(host,port) {
|
||||||
|
var id = host+":"+port;
|
||||||
|
if (!connections[id]) {
|
||||||
|
connections[id] = redis.createClient(port,host);
|
||||||
|
connections[id].on("error",function(err) {
|
||||||
|
util.log("[redis] "+err);
|
||||||
|
});
|
||||||
|
connections[id].on("connect",function() {
|
||||||
|
util.log("[redis] connected to "+host+":"+port);
|
||||||
|
});
|
||||||
|
connections[id]._id = id;
|
||||||
|
connections[id]._nodeCount = 0;
|
||||||
|
}
|
||||||
|
connections[id]._nodeCount += 1;
|
||||||
|
return connections[id];
|
||||||
|
},
|
||||||
|
close: function(connection) {
|
||||||
|
connection._nodeCount -= 1;
|
||||||
|
if (connection._nodeCount == 0) {
|
||||||
|
if (connection) {
|
||||||
|
clearTimeout(connection.retry_timer);
|
||||||
|
connection.end();
|
||||||
|
}
|
||||||
|
delete connections[connection._id];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
return obj;
|
||||||
|
}();
|
||||||
|
|
||||||
|
|
||||||
|
function RedisOutNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.port = n.port||"6379";
|
||||||
|
this.hostname = n.hostname||"127.0.0.1";
|
||||||
|
this.key = n.key;
|
||||||
|
this.structtype = n.structtype;
|
||||||
|
|
||||||
|
this.client = redisConnectionPool.get(this.hostname,this.port);
|
||||||
|
|
||||||
|
this.on("input", function(msg) {
|
||||||
|
if (msg != null) {
|
||||||
|
var k = this.key || msg.topic;
|
||||||
|
if (k) {
|
||||||
|
if (this.structtype == "string") {
|
||||||
|
this.client.set(k,msg.payload);
|
||||||
|
} else if (this.structtype == "hash") {
|
||||||
|
var r = hashFieldRE.exec(msg.payload);
|
||||||
|
if (r) {
|
||||||
|
this.client.hset(k,r[1],r[2]);
|
||||||
|
} else {
|
||||||
|
this.warn("Invalid payload for redis hash");
|
||||||
|
}
|
||||||
|
} else if (this.structtype == "set") {
|
||||||
|
this.client.sadd(k,msg.payload);
|
||||||
|
} else if (this.structtype == "list") {
|
||||||
|
this.client.rpush(k,msg.payload);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
this.warn("No key or topic set");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("redis out",RedisOutNode);
|
||||||
|
|
||||||
|
RedisOutNode.prototype.close = function() {
|
||||||
|
redisConnectionPool.close(this.client);
|
||||||
|
}
|
||||||
|
|
91
nodes/storage/66-mongodb.html
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
<!--
|
||||||
|
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="mongodb">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-config-input-hostname"><i class="icon-bookmark"></i> Host</label>
|
||||||
|
<input class="input-append-left" type="text" id="node-config-input-hostname" 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="27017" style="width:45px">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-config-input-db"><i class="icon-briefcase"></i> Database</label>
|
||||||
|
<input type="text" id="node-config-input-db" placeholder="test">
|
||||||
|
</div>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="mongodb out">
|
||||||
|
<p>A MongoDB output node.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('mongodb',{
|
||||||
|
category: 'config',
|
||||||
|
color:"rgb(218, 196, 180)",
|
||||||
|
defaults: {
|
||||||
|
hostname: { value:"127.0.0.1",required:true},
|
||||||
|
port: { value: 27017,required:true},
|
||||||
|
db: { value:"",required:true},
|
||||||
|
},
|
||||||
|
label: function() {
|
||||||
|
return this.hostname+":"+this.port+"//"+this.db;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<script type="text/x-red" data-template-name="mongodb out">
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-mongodb"><i class="icon-tag"></i> Server</label>
|
||||||
|
<input type="text" id="node-input-mongodb">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-collection"><i class="icon-briefcase"></i> Collection</label>
|
||||||
|
<input type="text" id="node-input-collection" placeholder="collection">
|
||||||
|
</div>
|
||||||
|
<div class="form-row">
|
||||||
|
<label for="node-input-name"><i class="icon-tag"></i> Name</label>
|
||||||
|
<input type="text" id="node-input-name" placeholder="Name">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/x-red" data-help-name="mongodb out">
|
||||||
|
<p>A MongoDB output node.</p>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
RED.nodes.registerType('mongodb out',{
|
||||||
|
category: 'storage-output',
|
||||||
|
color:"rgb(218, 196, 180)",
|
||||||
|
defaults: {
|
||||||
|
mongodb: { type:"mongodb",required:true},
|
||||||
|
name: {value:""},
|
||||||
|
collection: {value:"",required:true},
|
||||||
|
},
|
||||||
|
inputs:1,
|
||||||
|
outputs:0,
|
||||||
|
icon: "mongodb.png",
|
||||||
|
align: "right",
|
||||||
|
label: function() {
|
||||||
|
return this.name||this.collection||((this.mongodb)?RED.nodes.node(this.mongodb).label():"mongodb");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
</script>
|
66
nodes/storage/66-mongodb.js
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
/**
|
||||||
|
* 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("../../red/red");
|
||||||
|
var mongo = require('mongodb');
|
||||||
|
|
||||||
|
function MongoNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.hostname = n.hostname;
|
||||||
|
this.port = n.port;
|
||||||
|
this.db = n.db;
|
||||||
|
}
|
||||||
|
RED.nodes.registerType("mongodb",MongoNode);
|
||||||
|
|
||||||
|
|
||||||
|
function MongoOutNode(n) {
|
||||||
|
RED.nodes.createNode(this,n);
|
||||||
|
this.collection = n.collection;
|
||||||
|
this.mongodb = n.mongodb;
|
||||||
|
this.mongoConfig = RED.nodes.getNode(this.mongodb);
|
||||||
|
|
||||||
|
if (this.mongoConfig) {
|
||||||
|
var node = this;
|
||||||
|
|
||||||
|
this.clientDb = new mongo.Db(node.mongoConfig.db, new mongo.Server(node.mongoConfig.hostname, node.mongoConfig.port, {}), {w: 1});
|
||||||
|
this.clientDb.open(function(err,cli) {
|
||||||
|
if (err) { node.error(err); }
|
||||||
|
else {
|
||||||
|
node.clientDb.collection(node.collection,function(err,coll) {
|
||||||
|
if (err) { node.error(err); }
|
||||||
|
else {
|
||||||
|
node.on("input",function(msg) {
|
||||||
|
delete msg._topic;
|
||||||
|
coll.save(msg,function(err,item){if (err){node.error(err);}});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.error("missing mongodb configuration");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.registerType("mongodb out",MongoOutNode);
|
||||||
|
|
||||||
|
MongoOutNode.prototype.close = function() {
|
||||||
|
if (this.clientDb) {
|
||||||
|
this.clientDb.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
20
package.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "node-red",
|
||||||
|
"version": "0.1.0",
|
||||||
|
"description" : "A visual tool for wiring the Internet of Things",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node red.js"
|
||||||
|
},
|
||||||
|
"main": "lib/server.js",
|
||||||
|
"author": "Nicholas O'Leary",
|
||||||
|
"contributors": [ {"name": "Dave Conway-Jones"} ],
|
||||||
|
"keywords": ["editor", "messaging", "iot", "m2m", "pi", "arduino", "beaglebone", "ibm"],
|
||||||
|
"license": "Apache",
|
||||||
|
"dependencies": {
|
||||||
|
"express": "3.x",
|
||||||
|
"mqtt": "*",
|
||||||
|
"ws": "*",
|
||||||
|
"mustache": "*"
|
||||||
|
},
|
||||||
|
"engines": { "node": ">=0.8" }
|
||||||
|
}
|
9
public/bootstrap/css/bootstrap.min.css
vendored
Normal file
BIN
public/bootstrap/img/glyphicons-halflings-white.png
Normal file
After Width: | Height: | Size: 8.6 KiB |
BIN
public/bootstrap/img/glyphicons-halflings.png
Normal file
After Width: | Height: | Size: 12 KiB |
6
public/bootstrap/js/bootstrap.min.js
vendored
Normal file
4
public/d3.v3.min.js
vendored
Normal file
BIN
public/favicon.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
public/icons/alert.png
Normal file
After Width: | Height: | Size: 204 B |
BIN
public/icons/arduino.png
Normal file
After Width: | Height: | Size: 1010 B |
BIN
public/icons/arrow-in.png
Normal file
After Width: | Height: | Size: 310 B |
BIN
public/icons/bonjour.png
Normal file
After Width: | Height: | Size: 4.4 KiB |
BIN
public/icons/bridge-dash.png
Normal file
After Width: | Height: | Size: 811 B |
BIN
public/icons/bridge.png
Normal file
After Width: | Height: | Size: 832 B |
BIN
public/icons/bullet.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
public/icons/debug.png
Normal file
After Width: | Height: | Size: 257 B |
BIN
public/icons/envelope.png
Normal file
After Width: | Height: | Size: 1014 B |
BIN
public/icons/feed.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
public/icons/file.png
Normal file
After Width: | Height: | Size: 353 B |
BIN
public/icons/function.png
Normal file
After Width: | Height: | Size: 584 B |