mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Compare commits
31 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
c6ad2c9ad2 | ||
|
3b44d9972e | ||
|
af736c98f2 | ||
|
f1377fa217 | ||
|
2ba146b9ff | ||
|
2361607aa3 | ||
|
86ffc80098 | ||
|
7f6915eb59 | ||
|
d69bcad028 | ||
|
4cb45e2712 | ||
|
b7a0ad703a | ||
|
7610b9a975 | ||
|
7d95f621df | ||
|
bba210e112 | ||
|
3a97e20bde | ||
|
4fe7ea00b0 | ||
|
3ec8ecd4de | ||
|
401e65e852 | ||
|
e7c5b691a0 | ||
|
9f3ea8da67 | ||
|
4d84d624b1 | ||
|
633a6a0ee6 | ||
|
c7bcd3f438 | ||
|
d3a29a6f16 | ||
|
827711ca89 | ||
|
76e98f74fa | ||
|
fb09f4b22d | ||
|
bb06585748 | ||
|
c76ba1dcc7 | ||
|
a115301b04 | ||
|
72917117a9 |
@@ -66,4 +66,4 @@ For more open-source projects from IBM, head over [here](http://ibm.github.io).
|
||||
|
||||
## Copyright and license
|
||||
|
||||
Copyright 2013, 2015 IBM Corp. under [the Apache 2.0 license](LICENSE).
|
||||
Copyright 2013, 2016 IBM Corp. under [the Apache 2.0 license](LICENSE).
|
||||
|
@@ -951,20 +951,20 @@ RED.editor = (function() {
|
||||
RED.nodes.add(editing_config_node);
|
||||
}
|
||||
|
||||
updateConfigNodeSelect(configProperty,configType,editing_config_node.id);
|
||||
|
||||
if (configTypeDef.credentials) {
|
||||
updateNodeCredentials(editing_config_node,configTypeDef.credentials,"node-config-input");
|
||||
}
|
||||
if (configTypeDef.oneditsave) {
|
||||
configTypeDef.oneditsave.call(editing_config_node);
|
||||
}
|
||||
if (configTypeDef.credentials) {
|
||||
updateNodeCredentials(editing_config_node,configTypeDef.credentials,"node-config-input");
|
||||
}
|
||||
validateNode(editing_config_node);
|
||||
for (var i=0;i<editing_config_node.users.length;i++) {
|
||||
var user = editing_config_node.users[i];
|
||||
validateNode(user);
|
||||
}
|
||||
|
||||
updateConfigNodeSelect(configProperty,configType,editing_config_node.id);
|
||||
|
||||
RED.nodes.dirty(true);
|
||||
RED.view.redraw(true);
|
||||
$(this).dialog("close");
|
||||
|
@@ -20,8 +20,8 @@ RED.sidebar.config = (function() {
|
||||
content.className = "sidebar-node-config"
|
||||
|
||||
$('<div class="button-group sidebar-header">'+
|
||||
'<a class="sidebar-header-button selected" id="workspace-config-node-filter-all" href="#"><span data-i18n="sidebar.config.filterAll"></span></a>'+
|
||||
'<a class="sidebar-header-button" id="workspace-config-node-filter-unused" href="#"><span data-i18n="sidebar.config.filterUnused"></span></a> '+
|
||||
'<a class="sidebar-header-button-toggle selected" id="workspace-config-node-filter-all" href="#"><span data-i18n="sidebar.config.filterAll"></span></a>'+
|
||||
'<a class="sidebar-header-button-toggle" id="workspace-config-node-filter-unused" href="#"><span data-i18n="sidebar.config.filterUnused"></span></a> '+
|
||||
'</div>'
|
||||
).appendTo(content);
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2015 IBM Corp.
|
||||
* Copyright 2015, 2016 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -76,3 +76,23 @@
|
||||
.ui-dialog .ui-dialog-buttonpane {
|
||||
padding: .3em 1em .5em 1em;
|
||||
}
|
||||
|
||||
.ui-spinner {
|
||||
border-radius: 4px;
|
||||
padding: 0;
|
||||
border: 1px solid $form-input-border-color;
|
||||
}
|
||||
.ui-spinner input {
|
||||
margin: 0 17px 0 0;
|
||||
padding: 6px;
|
||||
border: none;
|
||||
border-top-right-radius: 0px;
|
||||
border-bottom-right-radius: 0px;
|
||||
|
||||
-webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
-moz-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||
&:focus {
|
||||
outline: none;
|
||||
}
|
||||
}
|
||||
|
@@ -30,9 +30,9 @@
|
||||
|
||||
@mixin workspace-button {
|
||||
@include disable-selection;
|
||||
color: $workspace-button-color;
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
color: $workspace-button-color;
|
||||
background: $workspace-button-background;
|
||||
border: 1px solid $secondary-border-color;
|
||||
text-align: center;
|
||||
@@ -67,6 +67,17 @@
|
||||
border-left: none;
|
||||
}
|
||||
}
|
||||
@mixin workspace-button-toggle {
|
||||
@include workspace-button;
|
||||
color: $workspace-button-color-selected;
|
||||
background: $workspace-button-background-active;
|
||||
|
||||
&.selected:not(.disabled) {
|
||||
color: $workspace-button-color;
|
||||
background: $workspace-button-background;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@mixin component-footer {
|
||||
border-top: 1px solid $primary-border-color;
|
||||
|
@@ -83,6 +83,12 @@
|
||||
line-height: 13px;
|
||||
padding: 5px 8px;
|
||||
}
|
||||
.sidebar-header-button-toggle {
|
||||
@include workspace-button-toggle;
|
||||
font-size: 13px;
|
||||
line-height: 13px;
|
||||
padding: 5px 8px;
|
||||
}
|
||||
.sidebar-header-button:not(:first-child) {
|
||||
border-left: none;
|
||||
}
|
||||
|
@@ -22,10 +22,11 @@
|
||||
</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>Analyses the <code>msg.payload</code> and adds a <code>msg.sentiment</code> object
|
||||
that contains the resulting AFINN-111 sentiment score as <code>msg.sentiment.score</code>.</p>
|
||||
<p>A score greater than zero is positive and less than zero is negative.</p>
|
||||
<p>The score typically ranges from -5 to +5, but can go higher and lower.</p>
|
||||
<p>An object of word score overrides can be supplied as <b>msg.overrides</b>.</p>
|
||||
<p>An object of word score overrides can be supplied as <code>msg.overrides</code>.</p>
|
||||
<p>See <a href="https://github.com/thisandagain/sentiment/blob/master/README.md" target="_new">the Sentiment docs here</a>.</p>
|
||||
</script>
|
||||
|
||||
|
@@ -142,13 +142,7 @@
|
||||
.inject-time-times {
|
||||
width: 90px;
|
||||
}
|
||||
.inject-time-row > .ui-spinner {
|
||||
height: 28px;
|
||||
margin: 3px 0;
|
||||
border-color: rgb(204, 204, 204);
|
||||
}
|
||||
#inject-time-time {
|
||||
margin-top: 3px;
|
||||
width: 75px;
|
||||
}
|
||||
.inject-time-count {
|
||||
@@ -157,11 +151,11 @@
|
||||
</style>
|
||||
<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>
|
||||
to be injected into the flow.</p>
|
||||
<p>The payload defaults to the current time in millisecs since 1970, but can
|
||||
also be set to a String or left blank.</p>
|
||||
also be set to various other javascript types.</p>
|
||||
<p>The repeat function allows the payload to be sent on the required schedule.</p>
|
||||
<p>The <i>Fire once at start</i> option actually waits a short interval before firing
|
||||
<p>The <i>Inject once at start</i> option actually waits a short interval before firing
|
||||
to give other nodes a chance to instantiate properly.</p>
|
||||
<p><b>Note: </b>"Interval between times" and "at a specific time" uses cron.
|
||||
This means that 20 minutes will be at the next hour, 20 minutes past and
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2013, 2015 IBM Corp.
|
||||
* Copyright 2013, 2016 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -58,7 +58,7 @@ module.exports = function(RED) {
|
||||
} else if (this.payloadType == 'none') {
|
||||
msg.payload = "";
|
||||
} else {
|
||||
msg.payload = RED.util.evaluateNodeProperty(this.payload,this.payloadType,this,msg)||"";
|
||||
msg.payload = RED.util.evaluateNodeProperty(this.payload,this.payloadType,this,msg);
|
||||
}
|
||||
this.send(msg);
|
||||
msg = null;
|
||||
|
@@ -39,13 +39,14 @@
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="debug">
|
||||
<p>The Debug node can be connected to the output of any node. It can be used to display the output of any message property in the debug tab of the sidebar. The default is to display <b>msg.payload</b>.</p>
|
||||
<p>Each message will also display the timestamp, <b>msg.topic</b> and the property chosen to output.</p>
|
||||
<p>The Debug node can be connected to the output of any node. It can be used to display the output of any message
|
||||
property in the debug tab of the sidebar. The default is to display <code>msg.payload</code>.</p>
|
||||
<p>Each message will also display the timestamp, <code>msg.topic</code> and the type of property chosen to output.</p>
|
||||
<p>The sidebar can be accessed under the options drop-down in the top right corner.</p>
|
||||
<p>The button to the right of the node will toggle its output on and off so you can de-clutter the debug window.</p>
|
||||
<p>If the payload is an object or buffer it will be stringified first for display and indicate that by saying "(Object)" or "(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 <b>msg</b> object.</p>
|
||||
<p>Optionally can show the complete <code>msg</code> object, and send messages to the console log.</p>
|
||||
<p>In addition any calls to node.warn or node.error will appear here.</p>
|
||||
</script>
|
||||
|
||||
|
@@ -44,7 +44,7 @@
|
||||
<p>Provides 3 outputs... stdout, stderr, and return code.</p>
|
||||
<p>By default uses exec() which calls the command, then gets a callback on completion, returning the complete result in one message, along with any errors.</p>
|
||||
<p>Optionally can use spawn() instead, which returns the output from stdout and stderr as the command runs (usually one line at a time). On completion it 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 the result to another command.</p>
|
||||
<p>The optional append gets added to the command after the <code>msg.payload</code> - so you can do things like pipe the result to another command.</p>
|
||||
<p>Parameters with spaces should be enclosed in quotes - <i>"This is a single parameter"</i></p>
|
||||
<p>If stdout is binary a <i>buffer</i> is returned - otherwise returns a <i>string</i>.</p>
|
||||
<p>The blue status icon will be visible while the node is active.</p>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<!--
|
||||
Copyright 2013, 2015 IBM Corp.
|
||||
Copyright 2013, 2016 IBM Corp.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -29,7 +29,7 @@
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-outputs"><i class="fa fa-random"></i> <span data-i18n="function.label.outputs"></span></label>
|
||||
<input id="node-input-outputs" style="width: 60px; height: 1.7em;" value="1">
|
||||
<input id="node-input-outputs" style="width: 60px;" value="1">
|
||||
</div>
|
||||
<div class="form-tips"><span data-i18n="function.tip"></span></div>
|
||||
</script>
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<!--
|
||||
Copyright 2013, 2015 IBM Corp.
|
||||
Copyright 2013, 2016 IBM Corp.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -24,12 +24,12 @@
|
||||
<input type="text" id="node-input-field" placeholder="payload" style="width:250px;">
|
||||
<input type="hidden" id="node-input-fieldType">
|
||||
</div>
|
||||
<div class="form-row" style="margin-bottom: 0px;">
|
||||
<div class="form-row" style="position: relative; margin-bottom: 0px;">
|
||||
<label for="node-input-template"><i class="fa fa-file-code-o"></i> <span data-i18n="template.label.template"></span></label>
|
||||
<input type="hidden" id="node-input-template" autofocus="autofocus">
|
||||
<div style="float:right;margin-bottom: 3px; font-size: 0.8em;">
|
||||
<div style="position: absolute; right:0;display:inline-block; text-align: right; font-size: 0.8em;">
|
||||
<span data-i18n="template.label.format"></span>:
|
||||
<select id="node-input-format" style=" height: 20px; font-size: 1em !important; width:110px;">
|
||||
<select id="node-input-format" style="width:110px; font-size: 10px !important; height: 24px; padding:0;">
|
||||
<option value="handlebars">mustache</option>
|
||||
<option value="html">HTML</option>
|
||||
<option value="json">JSON</option>
|
||||
@@ -41,11 +41,19 @@
|
||||
<div class="form-row node-text-editor-row">
|
||||
<div style="height: 250px;" class="node-text-editor" id="node-input-template-editor" ></div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-syntax"><i class="fa fa-code"></i> <span data-i18n="template.label.syntax"></span></label>
|
||||
<select id="node-input-syntax" style="width:180px;">
|
||||
<option value="mustache" data-i18n="template.label.mustache"></option>
|
||||
<option value="plain" data-i18n="template.label.plain"></option>
|
||||
</select>
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="template">
|
||||
<p>Sets a property based on the provided template.</p>
|
||||
<p>This uses the <i><a href="http://mustache.github.io/mustache.5.html" target="_new">mustache</a></i> format.</p>
|
||||
<p>By default this uses the <i><a href="http://mustache.github.io/mustache.5.html" target="_new">mustache</a></i>
|
||||
format, but this can be switched off if required.</p>
|
||||
<p>For example, when a template of:
|
||||
<pre>Hello {{name}}. Today is {{date}}</pre>
|
||||
<p>receives a message containing:
|
||||
@@ -69,6 +77,7 @@
|
||||
field: {value:"payload"},
|
||||
fieldType: {value:"msg"},
|
||||
format: {value:"handlebars"},
|
||||
syntax: {value:"mustache"},
|
||||
template: {value:"This is the payload: {{payload}} !"},
|
||||
},
|
||||
inputs:1,
|
||||
@@ -82,6 +91,10 @@
|
||||
if (!this.fieldType) {
|
||||
this.fieldType = 'msg';
|
||||
}
|
||||
if (!this.syntax) {
|
||||
this.syntax = 'mustache';
|
||||
$("#node-input-syntax").val(this.syntax);
|
||||
}
|
||||
$("#node-input-field").typedInput({
|
||||
default: 'msg',
|
||||
types: ['msg','flow','global'],
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2013 IBM Corp.
|
||||
* Copyright 2013, 2016 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,12 +23,18 @@ module.exports = function(RED) {
|
||||
this.name = n.name;
|
||||
this.field = n.field || "payload";
|
||||
this.template = n.template;
|
||||
this.syntax = n.syntax || "mustache";
|
||||
this.fieldType = n.fieldType || "msg";
|
||||
|
||||
var node = this;
|
||||
node.on("input", function(msg) {
|
||||
try {
|
||||
var value = mustache.render(node.template,msg);
|
||||
var value;
|
||||
if (node.syntax === "mustache") {
|
||||
value = mustache.render(node.template,msg);
|
||||
} else {
|
||||
value = node.template;
|
||||
}
|
||||
if (node.fieldType === 'msg') {
|
||||
RED.util.setMessageProperty(msg,node.field,value);
|
||||
} else if (node.fieldType === 'flow') {
|
||||
|
@@ -14,14 +14,13 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<!-- First, the content of the edit dialog is defined. -->
|
||||
<script type="text/x-red" data-template-name="delay">
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-pauseType"><i class="fa fa-tasks"></i> <span data-i18n="delay.action"></span></label>
|
||||
<select id="node-input-pauseType" style="width:270px !important">
|
||||
<option value="delay" data-i18n="delay.delaymsg"></option>
|
||||
<option value="random" data-i18n="delay.ramdomdelay"></option>
|
||||
<option value="random" data-i18n="delay.randomdelay"></option>
|
||||
<option value="rate" data-i18n="delay.limitrate"></option>
|
||||
<option value="queue" data-i18n="delay.fairqueue"></option>
|
||||
</select>
|
||||
@@ -74,25 +73,23 @@
|
||||
|
||||
</script>
|
||||
|
||||
<!-- Next, some simple help text is provided for the node. -->
|
||||
<script type="text/x-red" data-help-name="delay">
|
||||
<p>Introduces a delay into a flow or rate limits messages.</p>
|
||||
<p>The default delay is 5 seconds and rate limit of 1 msg/second, but both can be configured.</p>
|
||||
<p>When set to rate limit messages, they are spread across the configured time period. It can
|
||||
also be set to discard any intermediate messages that arrive.</p>
|
||||
<p>The "topic based fair queue" adds messages to a release queue tagged by their <b>msg.topic</b> property.
|
||||
<p>The "topic based fair queue" adds messages to a release queue tagged by their <code>msg.topic</code> property.
|
||||
At each "tick", derived from the rate, the next "topic" is released.
|
||||
Any messages arriving on the same topic before release replace those in that position in the queue.
|
||||
So each "topic" gets a turn - but the most recent value is always the one sent.</p>
|
||||
</script>
|
||||
|
||||
<!-- Finally, the node type is registered along with all of its properties -->
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('delay',{
|
||||
category: 'function', // the palette category
|
||||
category: 'function',
|
||||
color:"#E6E0F8",
|
||||
defaults: { // defines the editable properties of the node
|
||||
name: {value:""}, // along with default values.
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
pauseType: {value:"delay", required:true},
|
||||
timeout: {value:"5", required:true, validate:RED.validators.number()},
|
||||
timeoutUnits: {value:"seconds"},
|
||||
@@ -103,10 +100,10 @@
|
||||
randomUnits: {value: "seconds"},
|
||||
drop: {value:false}
|
||||
},
|
||||
inputs:1, // set the number of inputs - only 0 or 1
|
||||
outputs:1, // set the number of outputs - 0 to n
|
||||
icon: "timer.png", // set the icon (held in public/icons)
|
||||
label: function() { // sets the default label contents
|
||||
inputs:1,
|
||||
outputs:1,
|
||||
icon: "timer.png",
|
||||
label: function() {
|
||||
if (this.pauseType == "delay") {
|
||||
var units = this.timeoutUnits ? this.timeoutUnits.charAt(0) : "s";
|
||||
if (this.timeoutUnits == "milliseconds") { units = "ms"; }
|
||||
@@ -122,7 +119,7 @@
|
||||
return this.name || this._("delay.label.queue")+" "+this.rate+" msg/"+units;
|
||||
}
|
||||
},
|
||||
labelStyle: function() { // sets the class to apply to the label
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
oneditprepare: function() {
|
||||
|
@@ -19,6 +19,7 @@
|
||||
<span data-i18n="trigger.send"></span>
|
||||
<select id="node-input-op1type" style="width:200px !important">
|
||||
<option value="val" data-i18n="trigger.output.string"></option>
|
||||
<option value="num" data-i18n="trigger.output.number"></option>
|
||||
<option value="pay" data-i18n="trigger.output.existing"></option>
|
||||
<option value="nul" data-i18n="trigger.output.nothing"></option>
|
||||
</select>
|
||||
@@ -44,13 +45,17 @@
|
||||
<span data-i18n="trigger.then-send"></span>
|
||||
<select id="node-input-op2type" style="width:200px !important">
|
||||
<option value="val" data-i18n="trigger.output.string"></option>
|
||||
<option value="num" data-i18n="trigger.output.number"></option>
|
||||
<option value="pay" data-i18n="trigger.output.existing"></option>
|
||||
<option value="nul" data-i18n="trigger.output.nothing"></option>
|
||||
</select>
|
||||
<input style="width: 145px !important" type="text" id="node-input-op2">
|
||||
</div>
|
||||
<div class="form-row node-type-wait">
|
||||
<input type="checkbox" id="node-input-extend" style="margin-left: 5px; vertical-align: top; width: auto !important;"> <label style="width:auto !important;" for="node-input-extend" data-i18n="trigger.extend"></label>
|
||||
<input type="checkbox" id="node-input-extend" style="margin-left: 0px; vertical-align: top; width: auto !important;"> <label style="width:auto !important;" for="node-input-extend" data-i18n="trigger.extend"></label>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<span data-i18n="trigger.label.reset"></span><input type="text" id="node-input-reset" style="width:240px" data-i18n="[placeholder]trigger.label.resetprompt">
|
||||
</div>
|
||||
<br/>
|
||||
<div class="form-row">
|
||||
@@ -61,18 +66,20 @@
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="trigger">
|
||||
<p>Creates two messages on the output separated by a timeout whenever ANY <b>msg</b> arrives on the input.</p>
|
||||
<p>Creates two messages on the output separated by a timeout whenever <i>any</i> <code>msg</code> arrives on the input.</p>
|
||||
<p>For example, this can be used to toggle a Raspberry PI GPIO pin on and off.</p>
|
||||
<p>The two output states can be specified as can the duration of the timer.
|
||||
Either output can be set to a value, or templated from the inbound
|
||||
<b>msg</b> using mustache syntax. <pre>The payload is {{payload}}</pre></p>
|
||||
<p>If the payload is an object then setting the output to <i>existing payload</i> will pass the complete payload object through.</p>
|
||||
<code>msg</code> using mustache syntax. <pre>The payload is {{payload}}</pre></p>
|
||||
<p>If the <code>msg.payload</code> is an object then setting the output to
|
||||
<i>existing payload</i> will pass the complete payload object through.</p>
|
||||
<p>Optionally the timer can be extended by being retriggered... or not.</p>
|
||||
<p>By setting the first output to <i>nothing</i>, and selecting extend timer - a watchdog timer can be created.
|
||||
No output will happen as long as repeated inputs occur within the timeout period.</p>
|
||||
<p>Setting the timer to 0 creates an "infinite" timeout - the first output will happen but the second
|
||||
never will, and neither can the first be retriggered - so a true one shot.</p>
|
||||
<p>If a <b>msg.reset</b> property is present any timeout currently in progress
|
||||
<p>If a <code>msg.reset</code> property is present, or the <code>msg.payload</code>
|
||||
matches the optional reset value, any timeout currently in progress
|
||||
will be cleared and the second output will not happen.</p>
|
||||
<p>The blue status icon will be visible while the node is active.</p>
|
||||
</script>
|
||||
@@ -88,7 +95,8 @@
|
||||
op2type: {value:"val"},
|
||||
duration: {value:"250",required:true,validate:RED.validators.number()},
|
||||
extend: {value:"false"},
|
||||
units: {value: "ms"},
|
||||
units: {value:"ms"},
|
||||
reset: {value:""},
|
||||
name: {value:""}
|
||||
},
|
||||
inputs:1,
|
||||
@@ -116,14 +124,14 @@
|
||||
}
|
||||
});
|
||||
$("#node-input-op1type").change(function() {
|
||||
if ($(this).val() == "val") {
|
||||
if (($(this).val() == "val")||($(this).val() == "num")) {
|
||||
$("#node-input-op1").show();
|
||||
} else {
|
||||
$("#node-input-op1").hide();
|
||||
}
|
||||
});
|
||||
$("#node-input-op2type").change(function() {
|
||||
if ($(this).val() == "val") {
|
||||
if (($(this).val() == "val")||($(this).val() == "num")) {
|
||||
$("#node-input-op2").show();
|
||||
} else {
|
||||
$("#node-input-op2").hide();
|
||||
|
@@ -25,6 +25,7 @@ module.exports = function(RED) {
|
||||
this.op2type = n.op2type || "val";
|
||||
this.extend = n.extend || "false";
|
||||
this.units = n.units || "ms";
|
||||
this.reset = n.reset || '';
|
||||
this.duration = n.duration || 250;
|
||||
if (this.duration <= 0) { this.duration = 0; }
|
||||
else {
|
||||
@@ -34,24 +35,24 @@ module.exports = function(RED) {
|
||||
}
|
||||
this.op1Templated = this.op1.indexOf("{{") != -1;
|
||||
this.op2Templated = this.op2.indexOf("{{") != -1;
|
||||
if (!isNaN(this.op1)) { this.op1 = Number(this.op1); }
|
||||
if (!isNaN(this.op2)) { this.op2 = Number(this.op2); }
|
||||
if ((this.op1type === "num") && (!isNaN(this.op1))) { this.op1 = Number(this.op1); }
|
||||
if ((this.op2type === "num") && (!isNaN(this.op2))) { this.op2 = Number(this.op2); }
|
||||
if (this.op1 == "true") { this.op1 = true; }
|
||||
if (this.op2 == "true") { this.op2 = true; }
|
||||
if (this.op1 == "false") { this.op1 = false; }
|
||||
if (this.op2 == "false") { this.op2 = false; }
|
||||
if (this.op1 == "null") { this.op1 = null; }
|
||||
if (this.op2 == "null") { this.op2 = null; }
|
||||
try { this.op1 = JSON.parse(this.op1); }
|
||||
catch(e) { this.op1 = this.op1; }
|
||||
try { this.op2 = JSON.parse(this.op2); }
|
||||
catch(e) { this.op2 = this.op2; }
|
||||
//try { this.op1 = JSON.parse(this.op1); }
|
||||
//catch(e) { this.op1 = this.op1; }
|
||||
//try { this.op2 = JSON.parse(this.op2); }
|
||||
//catch(e) { this.op2 = this.op2; }
|
||||
|
||||
var node = this;
|
||||
var tout = null;
|
||||
var m2;
|
||||
this.on("input", function(msg) {
|
||||
if (msg.hasOwnProperty("reset")) {
|
||||
if (msg.hasOwnProperty("reset") || ((node.reset !== '')&&(msg.payload == node.reset)) ) {
|
||||
clearTimeout(tout);
|
||||
tout = null;
|
||||
node.status({});
|
||||
@@ -90,8 +91,8 @@ module.exports = function(RED) {
|
||||
this.on("close", function() {
|
||||
if (tout) {
|
||||
clearTimeout(tout);
|
||||
node.status({});
|
||||
}
|
||||
node.status({});
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("trigger",TriggerNode);
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<!--
|
||||
Copyright 2013, 2015 IBM Corp.
|
||||
Copyright 2013, 2016 IBM Corp.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -55,9 +55,6 @@
|
||||
},
|
||||
oneditprepare: function() {
|
||||
var that = this;
|
||||
$( "#node-input-outputs" ).spinner({
|
||||
min:1
|
||||
});
|
||||
this.editor = RED.editor.createEditor({
|
||||
id: 'node-input-info-editor',
|
||||
mode: 'ace/mode/markdown',
|
||||
|
@@ -41,16 +41,18 @@
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-intype"><i class="fa fa-level-up"></i> <span data-i18n="rpi-gpio.label.resistor"></span></label>
|
||||
<select type="text" id="node-input-intype" style="width: 150px;">
|
||||
<select type="text" id="node-input-intype" style="width:100px;">
|
||||
<option value="tri" data-i18n="rpi-gpio.resistor.none"></option>
|
||||
<option value="up" data-i18n="rpi-gpio.resistor.pullup"></option>
|
||||
<option value="down" data-i18n="rpi-gpio.resistor.pulldown"></option>
|
||||
</select>
|
||||
<span data-i18n="rpi-gpio.label.debounce"></span>
|
||||
<input type="text" id="node-input-debounce" style="width:47px; text-align:right"/> mS
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-input-read" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-input-read" style="width: 70%;"><span data-i18n="rpi-gpio.label.readinitial"></span></label>
|
||||
<label for="node-input-read" style="width:70%;"><span data-i18n="rpi-gpio.label.readinitial"></span></label>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="form-row">
|
||||
@@ -62,10 +64,11 @@
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-gpio in">
|
||||
<p>Raspberry Pi input node. Generates a <b>msg.payload</b> with either a 0 or 1 depending on the state of the input pin. Requires the gpio command to work.</p>
|
||||
<p>Raspberry Pi input node. Generates a <code>msg.payload</code> with either a
|
||||
0 or 1 depending on the state of the input pin.</p>
|
||||
<p>You may also enable the input pullup resistor or the pulldown resistor.</p>
|
||||
<p>The <b>msg.topic</b> is set to <i>pi/{the pin number}</i></p>
|
||||
<p>Requires the RPi.GPIO python library version 0.5.8 (or better) in order to work.</p>
|
||||
<p>The <code>msg.topic</code> is set to <i>pi/{the pin number}</i></p>
|
||||
<p>Requires the RPi.GPIO python library version 0.5.10 (or better) in order to work.</p>
|
||||
<p><b>Note:</b> we are using the actual physical pin numbers on connector P1 as they are easier to locate.</p>
|
||||
</script>
|
||||
|
||||
@@ -77,8 +80,9 @@
|
||||
color:"#c6dbef",
|
||||
defaults: {
|
||||
name: { value:"" },
|
||||
pin: { value:"",required:true,validate:RED.validators.number() },
|
||||
intype: { value: "in" },
|
||||
pin: { value:"tri",required:true,validate:RED.validators.number() },
|
||||
intype: { value:"in" },
|
||||
debounce: { value:"25" },
|
||||
read: { value:false }
|
||||
},
|
||||
inputs:0,
|
||||
@@ -104,7 +108,7 @@
|
||||
var alreadyset = this._("rpi-gpio.alreadyset");
|
||||
$.getJSON('rpi-gpio/'+this.id,function(data) {
|
||||
$('#pitype').text(data.type);
|
||||
if ((data.type === "Model B+") || (data.type === "Model A+")) {
|
||||
if ((data.type !== "Model B") && (data.type !== "Model A")) {
|
||||
$('#node-input-pin').append($("<option></option>").attr("value",27).text("27 - SDA0 - BCM0"));
|
||||
$('#node-input-pin').append($("<option></option>").attr("value",28).text("28 - SCL0 - BCM1"));
|
||||
$('#node-input-pin').append($("<option></option>").attr("value",29).text("29 - GPIO21 - BCM5"));
|
||||
@@ -200,13 +204,14 @@
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-gpio out">
|
||||
<p>Raspberry Pi output node. Expects a <b>msg.payload</b> with either a 0 or 1 (or true or false). Requires the gpio command to work.</p>
|
||||
<p>Will set the selected physical pin high or low depending on the value passed in.</p>
|
||||
<p>Raspberry Pi output node. Can be used in Digital, PWM or Servo modes.
|
||||
<p>Digital mode expects a <code>msg.payload</code> with either a 0 or 1 (or true or false),
|
||||
and will set the selected physical pin high or low depending on the value passed in.</p>
|
||||
<p>The initial value of the pin at deploy time can also be set to 0 or 1.</p>
|
||||
<p>When using PWM mode - expects an input value of a number 0 - 100. It can be floating point.</p>
|
||||
<p>PWM mode can be used to drive a servo using input values between 10 and 20 only.
|
||||
The GPIO2 pin is best for this as it uses hardware to do the PWM.</p>
|
||||
<p>Requires the RPi.GPIO python library version 0.5.8 (or better) in order to work.</p>
|
||||
<p>Requires the RPi.GPIO python library version 0.5.10 (or better) in order to work.</p>
|
||||
<p><b>Note:</b> we are using the actual physical pin numbers on connector P1 as they are easier to locate.</p>
|
||||
</script>
|
||||
|
||||
@@ -249,7 +254,7 @@
|
||||
if (!$("#node-input-out").val()) { $("#node-input-out").val("out"); }
|
||||
$.getJSON('rpi-gpio/'+this.id,function(data) {
|
||||
$('#pitype').text(data.type);
|
||||
if ((data.type === "Model B+") || (data.type === "Model A+")) {
|
||||
if ((data.type !== "Model B") && (data.type !== "Model A")) {
|
||||
$('#node-input-pin').append($("<option></option>").attr("value",27).text("27 - SDA0 - BCM0"));
|
||||
$('#node-input-pin').append($("<option></option>").attr("value",28).text("28 - SCL0 - BCM1"));
|
||||
$('#node-input-pin').append($("<option></option>").attr("value",29).text("29 - GPIO21 - BCM5"));
|
||||
@@ -336,12 +341,12 @@
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-mouse">
|
||||
<p>Raspberry Pi mouse button node. Requires a USB mouse.</p>
|
||||
<p>Generates a <b>msg.payload</b> with
|
||||
<p>Generates a <code>msg.payload</code> with
|
||||
either a 1 or 0 when the selected mouse button is pressed and released</p>
|
||||
<p>Also sets <b>msg.button</b> to the code value
|
||||
<p>Also sets <code>msg.button</code> to the code value
|
||||
<ul><li>1 = left</li><li>2 = right</li><li>4 = middle</li></ul>
|
||||
so you can work out which button or combination was pressed.</p>
|
||||
<p>And sets <b>msg.topic</b> to <i>pi/mouse</i>.</p>
|
||||
<p>And sets <code>msg.topic</code> to <i>pi/mouse</i>.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
@@ -378,9 +383,9 @@
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-keyboard">
|
||||
<p>Raspberry Pi keyboard handling node. Requires a USB keyboard.</p>
|
||||
<p>Generates a <b>msg.payload</b> with a keycode, and <b>msg.action</b> set to
|
||||
<p>Generates a <code>msg.payload</code> with a keycode, and <code>msg.action</code> set to
|
||||
<i>up, down</i> or <i>repeat</i> whenever a key is pressed or released.</p>
|
||||
<p>It also sets <b>msg.topic</b> to <i>pi/key</i>.</p>
|
||||
<p>It also sets <code>msg.topic</code> to <i>pi/key</i>.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2013,2015 IBM Corp.
|
||||
* Copyright 2013,2016 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,9 +18,9 @@ module.exports = function(RED) {
|
||||
"use strict";
|
||||
var exec = require('child_process').exec;
|
||||
var spawn = require('child_process').spawn;
|
||||
var fs = require('fs');
|
||||
var fs = require('fs');
|
||||
|
||||
var gpioCommand = __dirname+'/nrgpio.py';
|
||||
var gpioCommand = __dirname+'/nrgpio';
|
||||
|
||||
try {
|
||||
fs.statSync("/dev/ttyAMA0"); // unlikely if not on a Pi
|
||||
@@ -53,6 +53,7 @@ module.exports = function(RED) {
|
||||
this.pin = n.pin;
|
||||
this.intype = n.intype;
|
||||
this.read = n.read || false;
|
||||
this.debounce = Number(n.debounce || 25);
|
||||
if (this.read) { this.buttonState = -2; }
|
||||
var node = this;
|
||||
if (!pinsInUse.hasOwnProperty(this.pin)) {
|
||||
@@ -65,11 +66,7 @@ module.exports = function(RED) {
|
||||
}
|
||||
|
||||
if (node.pin !== undefined) {
|
||||
if (node.intype === "tri") {
|
||||
node.child = spawn(gpioCommand, ["in",node.pin]);
|
||||
} else {
|
||||
node.child = spawn(gpioCommand, ["in",node.pin,node.intype]);
|
||||
}
|
||||
node.child = spawn(gpioCommand, ["in",node.pin,node.intype,node.debounce]);
|
||||
node.running = true;
|
||||
node.status({fill:"green",shape:"dot",text:"common.status.ok"});
|
||||
|
||||
@@ -124,7 +121,6 @@ module.exports = function(RED) {
|
||||
}
|
||||
RED.nodes.registerType("rpi-gpio in",GPIOInNode);
|
||||
|
||||
|
||||
function GPIOOutNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.pin = n.pin;
|
||||
@@ -164,7 +160,7 @@ module.exports = function(RED) {
|
||||
if (node.pin !== undefined) {
|
||||
if (node.set && (node.out === "out")) {
|
||||
node.child = spawn(gpioCommand, [node.out,node.pin,node.level]);
|
||||
} else {
|
||||
} else {
|
||||
node.child = spawn(gpioCommand, [node.out,node.pin]);
|
||||
}
|
||||
node.running = true;
|
||||
@@ -214,20 +210,6 @@ module.exports = function(RED) {
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
var pitype = { type:"" };
|
||||
exec(gpioCommand+" rev 0", function(err,stdout,stderr) {
|
||||
if (err) {
|
||||
RED.log.info(RED._("rpi-gpio.errors.version"));
|
||||
}
|
||||
else {
|
||||
if (stdout.trim() == "0") { pitype = { type:"Compute" }; }
|
||||
else if (stdout.trim() == "1") { pitype = { type:"A/B v1" }; }
|
||||
else if (stdout.trim() == "2") { pitype = { type:"A/B v2" }; }
|
||||
else if (stdout.trim() == "3") { pitype = { type:"Model B+" }; }
|
||||
else { RED.log.info(RED._("rpi-gpio.errors.sawpitype"),stdout.trim()); }
|
||||
}
|
||||
});
|
||||
RED.nodes.registerType("rpi-gpio out",GPIOOutNode);
|
||||
|
||||
function PiMouseNode(n) {
|
||||
@@ -235,7 +217,7 @@ module.exports = function(RED) {
|
||||
this.butt = n.butt || 7;
|
||||
var node = this;
|
||||
|
||||
node.child = spawn(gpioCommand, ["mouse",node.butt]);
|
||||
node.child = spawn(gpioCommand+".py", ["mouse",node.butt]);
|
||||
node.status({fill:"green",shape:"dot",text:"common.status.ok"});
|
||||
|
||||
node.child.stdout.on('data', function (data) {
|
||||
@@ -281,7 +263,7 @@ module.exports = function(RED) {
|
||||
RED.nodes.createNode(this,n);
|
||||
var node = this;
|
||||
|
||||
node.child = spawn(gpioCommand, ["kbd","0"]);
|
||||
node.child = spawn(gpioCommand+".py", ["kbd","0"]);
|
||||
node.status({fill:"green",shape:"dot",text:"common.status.ok"});
|
||||
|
||||
node.child.stdout.on('data', function (data) {
|
||||
@@ -325,6 +307,22 @@ module.exports = function(RED) {
|
||||
}
|
||||
RED.nodes.registerType("rpi-keyboard",PiKeyboardNode);
|
||||
|
||||
var pitype = { type:"" };
|
||||
exec(gpioCommand+" info", function(err,stdout,stderr) {
|
||||
if (err) {
|
||||
RED.log.info(RED._("rpi-gpio.errors.version"));
|
||||
}
|
||||
else {
|
||||
try {
|
||||
var info = JSON.parse( stdout.trim().replace(/\'/g,"\"") );
|
||||
pitype.type = info["TYPE"];
|
||||
}
|
||||
catch(e) {
|
||||
RED.log.info(RED._("rpi-gpio.errors.sawpitype"),stdout.trim());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
RED.httpAdmin.get('/rpi-gpio/:id', RED.auth.needsPermission('rpi-gpio.read'), function(req,res) {
|
||||
res.json(pitype);
|
||||
});
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright 2014 IBM Corp.
|
||||
# Copyright 2014,2016 IBM Corp.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -19,8 +19,9 @@ import struct
|
||||
import sys
|
||||
import os
|
||||
import subprocess
|
||||
from time import sleep
|
||||
|
||||
bounce = 20 # bounce time in mS to apply
|
||||
bounce = 25;
|
||||
|
||||
if sys.version_info >= (3,0):
|
||||
print("Sorry - currently only configured to work with python 2.x")
|
||||
@@ -95,18 +96,18 @@ if len(sys.argv) > 2:
|
||||
|
||||
elif cmd == "in":
|
||||
#print "Initialised pin "+str(pin)+" to IN"
|
||||
bounce = int(sys.argv[4])
|
||||
def handle_callback(chan):
|
||||
sleep(bounce/1000)
|
||||
print GPIO.input(chan)
|
||||
|
||||
if len(sys.argv) == 4:
|
||||
if sys.argv[3].lower() == "up":
|
||||
GPIO.setup(pin,GPIO.IN,GPIO.PUD_UP)
|
||||
elif sys.argv[3].lower() == "down":
|
||||
GPIO.setup(pin,GPIO.IN,GPIO.PUD_DOWN)
|
||||
else:
|
||||
GPIO.setup(pin,GPIO.IN)
|
||||
if sys.argv[3].lower() == "up":
|
||||
GPIO.setup(pin,GPIO.IN,GPIO.PUD_UP)
|
||||
elif sys.argv[3].lower() == "down":
|
||||
GPIO.setup(pin,GPIO.IN,GPIO.PUD_DOWN)
|
||||
else:
|
||||
GPIO.setup(pin,GPIO.IN)
|
||||
|
||||
print GPIO.input(pin)
|
||||
GPIO.add_event_detect(pin, GPIO.BOTH, callback=handle_callback, bouncetime=bounce)
|
||||
|
||||
@@ -169,12 +170,6 @@ if len(sys.argv) > 2:
|
||||
except:
|
||||
data = 0
|
||||
|
||||
elif cmd == "rev":
|
||||
print GPIO.RPI_REVISION
|
||||
|
||||
elif cmd == "ver":
|
||||
print GPIO.VERSION
|
||||
|
||||
elif cmd == "mouse": # catch mice button events
|
||||
file = open( "/dev/input/mice", "rb" )
|
||||
oldbutt = 0
|
||||
@@ -225,9 +220,11 @@ elif len(sys.argv) > 1:
|
||||
print GPIO.RPI_REVISION
|
||||
elif cmd == "ver":
|
||||
print GPIO.VERSION
|
||||
elif cmd == "info":
|
||||
print GPIO.RPI_INFO
|
||||
else:
|
||||
print "Bad parameters - in|out|pwm|buzz|byte|borg|mouse|kbd|ver {pin} {value|up|down}"
|
||||
print " only ver (gpio version) and rev (board revision) accept no pin parameter."
|
||||
print "Bad parameters - in|out|pwm|buzz|byte|borg|mouse|kbd|ver|info {pin} {value|up|down}"
|
||||
print " only ver (gpio version) and info (board information) accept no pin parameter."
|
||||
|
||||
else:
|
||||
print "Bad parameters - in|out|pwm|buzz|byte|borg|mouse|kbd|ver {pin} {value|up|down}"
|
||||
print "Bad parameters - in|out|pwm|buzz|byte|borg|mouse|kbd|ver|info {pin} {value|up|down}"
|
||||
|
@@ -1,5 +1,5 @@
|
||||
<!--
|
||||
Copyright 2013,2015 IBM Corp.
|
||||
Copyright 2013, 2016 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
|
||||
@@ -27,9 +27,15 @@
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="mqtt in">
|
||||
<p>MQTT input node. Connects to a broker and subscribes to the specified topic. The topic may contain MQTT wildcards.</p>
|
||||
<p>Outputs an object called <b>msg</b> containing <b>msg.topic, msg.payload, msg.qos</b> and <b>msg.retain</b>.</p>
|
||||
<p><b>msg.payload</b> is usually a string, but can also be a binary buffer.</p>
|
||||
<p>Connects to a broker and subscribes to the specified topic.</p>
|
||||
<p>Outputs a message with the properties:</p>
|
||||
<ul>
|
||||
<li><code>msg.topic</code></li>
|
||||
<li><code>msg.payload</code></li>
|
||||
<li><code>msg.qos</code></li>
|
||||
<li><code>msg.retain</code></li>
|
||||
</ul>
|
||||
<p><code>msg.payload</code> will be a String, unless it is detected as a binary buffer.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
@@ -37,7 +43,7 @@
|
||||
category: 'input',
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
topic: {value:"",required:true},
|
||||
topic: {value:"",required:true,validate: RED.validators.regex(/^(#$|(\+|[^+#]*)(\/(\+|[^+#]*))*(\/(\+|#|[^+#]*))?$)/)},
|
||||
broker: {type:"mqtt-broker", required:true}
|
||||
},
|
||||
color:"#d8bfd8",
|
||||
@@ -84,9 +90,14 @@
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="mqtt out">
|
||||
<p>Connects to a MQTT broker and publishes <b>msg.payload</b> either to the <b>msg.topic</b> or to the topic specified in the edit window. The value in the edit window has precedence.</p>
|
||||
<p>Likewise QoS and/or retain values in the edit panel will overwrite any <b>msg.qos</b> and <b>msg.retain</b> properties. If nothing is set they default to <i>0</i> and <i>false</i> respectively.</p>
|
||||
<p>If <b>msg.payload</b> contains an object it will be stringified before being sent.</p>
|
||||
<p>Connects to a MQTT broker and publishes messages.</p>
|
||||
<p>The topic used can be configured in the node or, if left blank, can be set
|
||||
by <code>msg.topic</code>.</p>
|
||||
<p>Likewise the QoS and retain values can be configured in the node or, if left
|
||||
blank, set by <code>msg.qos</code> and <code>msg.retain</code> respectively.
|
||||
By default, messages are published at QoS 0 with the retain flag set to false.</p>
|
||||
<p>If <code>msg.payload</code> contains an object it will be converted to JSON
|
||||
before being sent.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
@@ -226,7 +237,7 @@
|
||||
usetls: {value: false},
|
||||
verifyservercert: { value: false},
|
||||
compatmode: { value: true},
|
||||
keepalive: {value:15,validate:RED.validators.number()},
|
||||
keepalive: {value:60,validate:RED.validators.number()},
|
||||
cleansession: {value: true},
|
||||
willTopic: {value:""},
|
||||
willQos: {value:"0"},
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2013,2015 IBM Corp.
|
||||
* Copyright 2013, 2016 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -76,7 +76,7 @@ module.exports = function(RED) {
|
||||
this.verifyservercert = false;
|
||||
}
|
||||
if (typeof this.keepalive === 'undefined'){
|
||||
this.keepalive = 15;
|
||||
this.keepalive = 60;
|
||||
} else if (typeof this.keepalive === 'string') {
|
||||
this.keepalive = Number(this.keepalive);
|
||||
}
|
||||
@@ -184,15 +184,14 @@ module.exports = function(RED) {
|
||||
if (node.birthMessage) {
|
||||
node.publish(node.birthMessage);
|
||||
}
|
||||
|
||||
// Send any queued messages
|
||||
while(node.queue.length) {
|
||||
var msg = node.queue.shift();
|
||||
//console.log(msg);
|
||||
node.publish(msg);
|
||||
}
|
||||
});
|
||||
|
||||
node.client.on("reconnect", function() {
|
||||
for (var id in node.users) {
|
||||
if (node.users.hasOwnProperty(id)) {
|
||||
node.users[id].status({fill:"yellow",shape:"ring",text:"common.status.connecting"});
|
||||
}
|
||||
}
|
||||
})
|
||||
// Register disconnect handlers
|
||||
node.client.on('close', function () {
|
||||
if (node.connected) {
|
||||
@@ -272,11 +271,6 @@ module.exports = function(RED) {
|
||||
retain: msg.retain || false
|
||||
};
|
||||
node.client.publish(msg.topic, msg.payload, options, function (err){return});
|
||||
} else {
|
||||
if (!node.connecting) {
|
||||
node.connect();
|
||||
}
|
||||
node.queue.push(msg);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -306,6 +300,9 @@ module.exports = function(RED) {
|
||||
this.topic = n.topic;
|
||||
this.broker = n.broker;
|
||||
this.brokerConn = RED.nodes.getNode(this.broker);
|
||||
if (!/^(#$|(\+|[^+#]*)(\/(\+|[^+#]*))*(\/(\+|#|[^+#]*))?$)/.test(this.topic)) {
|
||||
return this.warn(RED._("mqtt.errors.invalid-topic"));
|
||||
}
|
||||
var node = this;
|
||||
if (this.brokerConn) {
|
||||
this.status({fill:"red",shape:"ring",text:"common.status.disconnected"});
|
||||
|
@@ -28,6 +28,8 @@ module.exports = function(RED) {
|
||||
var isTemplatedUrl = (nodeUrl||"").indexOf("{{") != -1;
|
||||
var nodeMethod = n.method || "GET";
|
||||
this.ret = n.ret || "txt";
|
||||
if (RED.settings.httpRequestTimeout) { this.reqTimeout = parseInt(RED.settings.httpRequestTimeout) || 120000; }
|
||||
else { this.reqTimeout = 120000; }
|
||||
var node = this;
|
||||
|
||||
var prox, noprox;
|
||||
@@ -162,6 +164,13 @@ module.exports = function(RED) {
|
||||
node.status({});
|
||||
});
|
||||
});
|
||||
req.setTimeout(node.reqTimeout, function() {
|
||||
node.error(RED._("common.notification.errors.no-response"),msg);
|
||||
setTimeout(function() {
|
||||
node.status({fill:"red",shape:"ring",text:"common.notification.errors.no-response"});
|
||||
},10);
|
||||
req.abort();
|
||||
});
|
||||
req.on('error',function(err) {
|
||||
msg.payload = err.toString() + " : " + url;
|
||||
msg.statusCode = err.code;
|
||||
|
@@ -38,7 +38,7 @@
|
||||
|
||||
<script type="text/x-red" data-help-name="websocket in">
|
||||
<p>WebSocket input node.</p>
|
||||
<p>By default, the data received from the WebSocket will be in <b>msg.payload</b>.
|
||||
<p>By default, the data received from the WebSocket will be in <code>msg.payload</code>.
|
||||
The socket can be configured to expect a properly formed JSON string, in which
|
||||
case it will parse the JSON and send on the resulting object as the entire message.</p>
|
||||
</script>
|
||||
@@ -48,7 +48,7 @@
|
||||
(function() {
|
||||
|
||||
function ws_oneditprepare() {
|
||||
$("#websocket-client-row").hide();
|
||||
$("#websocket-client-row").hide();
|
||||
$("#node-input-mode").change(function(){
|
||||
if( $("#node-input-mode").val() === 'client') {
|
||||
$("#websocket-server-row").hide();
|
||||
@@ -59,7 +59,7 @@
|
||||
$("#websocket-client-row").hide();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
if(this.client) {
|
||||
$("#node-input-mode").val('client').change();
|
||||
}
|
||||
@@ -67,24 +67,24 @@
|
||||
$("#node-input-mode").val('server').change();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function ws_oneditsave() {
|
||||
if($("#node-input-mode").val() === 'client') {
|
||||
$("#node-input-server").append('<option value="">Dummy</option>');
|
||||
$("#node-input-server").val('');
|
||||
$("#node-input-server").val('');
|
||||
}
|
||||
else {
|
||||
$("#node-input-client").append('<option value="">Dummy</option>');
|
||||
$("#node-input-client").val('');
|
||||
$("#node-input-client").val('');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function ws_label() {
|
||||
var nodeid = (this.client)?this.client:this.server;
|
||||
var wsNode = RED.nodes.node(nodeid);
|
||||
return this.name||(wsNode?"[ws] "+wsNode.label():"websocket");
|
||||
}
|
||||
|
||||
|
||||
function ws_validateserver() {
|
||||
if($("#node-input-mode").val() === 'client' || (this.client && !this.server)) {
|
||||
return true;
|
||||
@@ -93,7 +93,7 @@
|
||||
return RED.nodes.node(this.server) != null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function ws_validateclient() {
|
||||
if($("#node-input-mode").val() === 'client' || (this.client && !this.server)) {
|
||||
return RED.nodes.node(this.client) != null;
|
||||
@@ -121,7 +121,7 @@
|
||||
oneditsave: ws_oneditsave,
|
||||
oneditprepare: ws_oneditprepare
|
||||
});
|
||||
|
||||
|
||||
RED.nodes.registerType('websocket out',{
|
||||
category: 'output',
|
||||
defaults: {
|
||||
@@ -141,7 +141,7 @@
|
||||
oneditsave: ws_oneditsave,
|
||||
oneditprepare: ws_oneditprepare
|
||||
});
|
||||
|
||||
|
||||
RED.nodes.registerType('websocket-listener',{
|
||||
category: 'config',
|
||||
defaults: {
|
||||
@@ -152,7 +152,7 @@
|
||||
outputs:0,
|
||||
label: function() {
|
||||
var root = RED.settings.httpNodeRoot;
|
||||
if (root.slice(-1) != "/") {
|
||||
if (root.slice(-1) != "/") {
|
||||
root = root+"/";
|
||||
}
|
||||
if (this.path.charAt(0) == "/") {
|
||||
@@ -164,7 +164,7 @@
|
||||
},
|
||||
oneditprepare: function() {
|
||||
var root = RED.settings.httpNodeRoot;
|
||||
if (root.slice(-1) == "/") {
|
||||
if (root.slice(-1) == "/") {
|
||||
root = root.slice(0,-1);
|
||||
}
|
||||
if (root == "") {
|
||||
@@ -188,7 +188,7 @@
|
||||
return this.path;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
})();
|
||||
</script>
|
||||
|
||||
@@ -217,15 +217,15 @@
|
||||
|
||||
<script type="text/x-red" data-help-name="websocket out">
|
||||
<p>WebSocket out node.</p>
|
||||
<p>By default, <b>msg.payload</b> will be sent over the WebSocket. The socket
|
||||
can be configured to encode the entire message object as a JSON string and send that
|
||||
<p>By default, <code>msg.payload</code> will be sent over the WebSocket. The socket
|
||||
can be configured to encode the entire <code>msg</code> object as a JSON string and send that
|
||||
over the WebSocket.</p>
|
||||
|
||||
<p>If the message arriving at this node started at a WebSocket In node, the message
|
||||
will be sent back to the client that triggered the flow. Otherwise, the message
|
||||
will be broadcast to all connected clients.</p>
|
||||
<p>If you want to broadcast a message that started at a WebSocket In node, you
|
||||
should delete the <b>msg._session</b> property within the flow</p>.
|
||||
should delete the <code>msg._session</code> property within the flow.</p>
|
||||
</script>
|
||||
|
||||
<!-- WebSocket Server configuration node -->
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2013,2015 IBM Corp.
|
||||
* Copyright 2013, 2016 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -82,7 +82,15 @@ module.exports = function(RED) {
|
||||
RED.server.addListener('newListener',storeListener);
|
||||
|
||||
// Create a WebSocket Server
|
||||
node.server = new ws.Server({server:RED.server,path:path});
|
||||
node.server = new ws.Server({
|
||||
server:RED.server,
|
||||
path:path,
|
||||
// Disable the deflate option due to this issue
|
||||
// https://github.com/websockets/ws/pull/632
|
||||
// that is fixed in the 1.x release of the ws module
|
||||
// that we cannot currently pickup as it drops node 0.10 support
|
||||
perMessageDeflate: false
|
||||
});
|
||||
|
||||
// Workaround https://github.com/einaros/ws/pull/253
|
||||
// Stop listening for new listener events
|
||||
|
@@ -31,11 +31,11 @@
|
||||
<p>You can enter a list of comma separated directories and/or files. You will
|
||||
need to put quotes "..." around any that have spaces in.</p>
|
||||
<p>On Windows you must use double back-slashes \\ in any directory names.</p>
|
||||
<p>The full filename of the file that actually changed is put into <b>msg.payload</b>,
|
||||
while a stringified version of the watch list is returned in <b>msg.topic</b>.</p>
|
||||
<p><b>msg.file</b> contains just the short filename of the file that changed.
|
||||
<b>msg.type</b> has the type of thing changed, usually <i>file</i> or <i>directory</i>,
|
||||
while <b>msg.size</b> holds the file size in bytes.</p>
|
||||
<p>The full filename of the file that actually changed is put into <code>msg.payload</code>,
|
||||
while a stringified version of the watch list is returned in <code>msg.topic</code>.</p>
|
||||
<p><code>msg.file</code> contains just the short filename of the file that changed.
|
||||
<code>msg.type</code> has the type of thing changed, usually <i>file</i> or <i>directory</i>,
|
||||
while <code>msg.size</code> holds the file size in bytes.</p>
|
||||
<p>Of course in Linux, <i>everything</i> is a file and thus can be watched...</p>
|
||||
<p><b>Note: </b>The directory or file must exist in order to be watched. If the file
|
||||
or directory gets deleted it may no longer be monitored even if it gets re-created.</p>
|
||||
|
@@ -56,7 +56,7 @@
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="tcp in">
|
||||
<p>Provides a choice of tcp inputs. Can either connect to a remote tcp port,
|
||||
<p>Provides a choice of TCP inputs. Can either connect to a remote TCP port,
|
||||
or accept incoming connections.</p>
|
||||
</script>
|
||||
|
||||
@@ -147,12 +147,14 @@
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="tcp out">
|
||||
<p>Provides a choice of tcp outputs. Can either connect to a remote tcp port,
|
||||
<p>Provides a choice of TCP outputs. Can either connect to a remote TCP port,
|
||||
accept incoming connections, or reply to messages received from a TCP In node.</p>
|
||||
<p>Only <b>msg.payload</b> is sent.</p>
|
||||
<p>If <b>msg.payload</b> is a string containing a Base64 encoding of binary
|
||||
<p>Only <code>msg.payload</code> is sent.</p>
|
||||
<p>If <code>msg.payload</code> is a string containing a Base64 encoding of binary
|
||||
data, the Base64 decoding option will cause it to be converted back to binary
|
||||
before being sent.</p>
|
||||
<p>If <code>msg._session</code> is not present the payload is
|
||||
sent to <b>all</b> connected clients.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
@@ -247,12 +249,12 @@
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="tcp request">
|
||||
<p>A simple TCP request node - sends the <b>msg.payload</b> to a server tcp port and expects a response.</p>
|
||||
<p>Connects, sends the "request", reads the "response". It can either count a number of
|
||||
<p>A simple TCP request node - sends the <code>msg.payload</code> to a server tcp port and expects a response.</p>
|
||||
<p>Connects, sends the "request", and reads the "response". It can either count a number of
|
||||
returned characters into a fixed buffer, match a specified character before returning,
|
||||
wait a fixed timeout from first reply and then return, or just sit and wait for data.</p>
|
||||
<p>The response will be output in <b>msg.payload</b> as a buffer, so you may want to .toString() it.</p>
|
||||
<p>If you leave tcp host or port blank they must be set by using the <b>msg.host</b> and <b>msg.port</b> properties.</p>
|
||||
<p>The response will be output in <code>msg.payload</code> as a buffer, so you may want to .toString() it.</p>
|
||||
<p>If you leave tcp host or port blank they must be set by using the <code>msg.host</code> and <code>msg.port</code> properties.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
@@ -303,6 +303,17 @@ module.exports = function(RED) {
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (var i in connectionPool) {
|
||||
if (Buffer.isBuffer(msg.payload)) {
|
||||
connectionPool[i].write(msg.payload);
|
||||
} else if (typeof msg.payload === "string" && node.base64) {
|
||||
connectionPool[i].write(new Buffer(msg.payload,'base64'));
|
||||
} else {
|
||||
connectionPool[i].write(new Buffer(""+msg.payload));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
} else {
|
||||
var connectedSockets = [];
|
||||
|
@@ -29,7 +29,7 @@
|
||||
</div>
|
||||
<div class="form-row node-input-iface">
|
||||
<label for="node-input-iface"><i class="fa fa-random"></i> <span data-i18n="udp.label.interface"></span></label>
|
||||
<input type="text" id="node-input-iface" data-i18n="[placeholder]udp.label.interface">
|
||||
<input type="text" id="node-input-iface" data-i18n="[placeholder]udp.label.interfaceprompt">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-port"><i class="fa fa-sign-in"></i> <span data-i18n="udp.label.onport"></span></label>
|
||||
@@ -56,9 +56,11 @@
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="udp in">
|
||||
<p>A udp input node, that produces a <b>msg.payload</b> containing a <i>BUFFER</i>, string, or base64 encoded string. Supports multicast.</p>
|
||||
<p>It also provides <b>msg.ip</b> and <b>msg.port</b> to the ip address and port from which the message was received.</p>
|
||||
<p>On some systems you may need to be root to use ports below 1024 and/or broadcast.</p>
|
||||
<p>A UDP input node, that produces a <code>msg.payload</code> containing a
|
||||
Buffer, string, or base64 encoded string. Supports multicast.</p>
|
||||
<p>It also provides <code>msg.ip</code> and <code>msg.port</code> set to the
|
||||
ip address and port from which the message was received.</p>
|
||||
<p><b>Note</b>: On some systems you may need to be root to use ports below 1024 and/or broadcast.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
@@ -163,10 +165,10 @@
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="udp out">
|
||||
<p>This node sends <b>msg.payload</b> to the designated udp host and port. Supports multicast.</p>
|
||||
<p>You may also use <b>msg.ip</b> and <b>msg.port</b> to set the destination values.<br/><b>Note</b>: the statically configured values have precedence.</p>
|
||||
<p>This node sends <code>msg.payload</code> to the designated UDP host and port. Supports multicast.</p>
|
||||
<p>You may also use <code>msg.ip</code> and <code>msg.port</code> to set the destination values, but the statically configured values have precedence.</p>
|
||||
<p>If you select broadcast either set the address to the local broadcast ip address, or maybe try 255.255.255.255, which is the global broadcast address.</p>
|
||||
<p>On some systems you may need to be root to use ports below 1024 and/or broadcast.</p>
|
||||
<p><b>Note</b>: On some systems you may need to be root to use ports below 1024 and/or broadcast.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
@@ -137,8 +137,11 @@
|
||||
"template": {
|
||||
"label": {
|
||||
"template": "Template",
|
||||
"property": "Property",
|
||||
"format": "Syntax Highlight"
|
||||
"property": "Set property",
|
||||
"format": "Syntax Highlight",
|
||||
"syntax": "Format",
|
||||
"mustache": "Mustache template",
|
||||
"plain": "Plain text"
|
||||
},
|
||||
"templatevalue": "This is the payload: {{payload}} !"
|
||||
},
|
||||
@@ -146,7 +149,7 @@
|
||||
"action": "Action",
|
||||
"for": "For",
|
||||
"delaymsg": "Delay message",
|
||||
"ramdomdelay": "Random delay",
|
||||
"randomdelay": "Random delay",
|
||||
"limitrate": "Limit rate to",
|
||||
"fairqueue": "Topic based fair queue",
|
||||
"milisecs": "Miliseconds",
|
||||
@@ -165,7 +168,7 @@
|
||||
"label": {
|
||||
"delay": "delay",
|
||||
"limit": "limit",
|
||||
"random": "ramdom",
|
||||
"random": "random",
|
||||
"queue": "queue"
|
||||
},
|
||||
"error": {
|
||||
@@ -177,8 +180,9 @@
|
||||
"then": "then",
|
||||
"then-send": "then send",
|
||||
"output": {
|
||||
"string": "the string payload",
|
||||
"existing": "the existing message",
|
||||
"string": "the string",
|
||||
"number": "the number",
|
||||
"existing": "the existing msg.payload",
|
||||
"nothing": "nothing"
|
||||
},
|
||||
"wait-reset": "wait to be reset",
|
||||
@@ -189,11 +193,13 @@
|
||||
"m": "Minutes",
|
||||
"h": "Hours"
|
||||
},
|
||||
"extend": "extend delay if new message arrives",
|
||||
"tip": "The node can be reset by sending a message with the <b>msg.reset</b> property set",
|
||||
"extend": " extend delay if new message arrives",
|
||||
"tip": "The node can also be reset by sending a message with the <b>msg.reset</b> property set to any value.",
|
||||
"label": {
|
||||
"trigger": "trigger",
|
||||
"trigger-block": "trigger & block"
|
||||
"trigger-block": "trigger & block",
|
||||
"reset": "and reset if msg.payload == ",
|
||||
"resetprompt": "(optional reset value)"
|
||||
}
|
||||
},
|
||||
"comment": {
|
||||
@@ -371,7 +377,8 @@
|
||||
"using": "using",
|
||||
"output": "Output",
|
||||
"group": "Group",
|
||||
"interface": "Interface",
|
||||
"interface": "Local IP",
|
||||
"interfaceprompt": "(optional) local ip address to bind to",
|
||||
"send": "Send a",
|
||||
"toport": "to port",
|
||||
"address": "Address",
|
||||
@@ -569,6 +576,7 @@
|
||||
"readinitial": "Read initial state of pin on deploy/restart?",
|
||||
"type": "Type",
|
||||
"initpin": "Initialise pin state?",
|
||||
"debounce": "Debounce",
|
||||
"button": "Button",
|
||||
"pimouse": "Pi Mouse",
|
||||
"pikeyboard": "Pi Keyboard",
|
||||
|
@@ -43,7 +43,7 @@
|
||||
<p>When a message arrives, the selected property is evaluated against each
|
||||
of the defined rules. The message is then sent to the output of <i>all</i>
|
||||
rules that pass.</p>
|
||||
<p>Note: the <i>otherwise</i> rule applies as a "not any of" the rules preceding it.</p>
|
||||
<p><b>Note</b>: the <i>otherwise</i> rule applies as a "not any of" the rules preceding it.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
@@ -68,12 +68,12 @@
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="csv">
|
||||
<p>A function that parses the <b>msg.payload</b> to convert CSV to/from a javascript object.
|
||||
<p>A function that parses the <code>msg.payload</code> to convert CSV to/from a javascript object.
|
||||
Places the result in the payload.</p>
|
||||
<p>If the input is a string it tries to parse it as CSV and creates a javascript object.</p>
|
||||
<p>If the input is a javascript object it tries to build a CSV string.</p>
|
||||
<p>If the input is a simple array the output is just a CSV generated from that array.</p>
|
||||
<p>If the input is an array of arrays or an array of objects a multiple-line CSV is created.</p>
|
||||
<p>If the input is an array of arrays, or an array of objects, a multiple-line CSV is created.</p>
|
||||
<p>The columns template should contain an ordered list of column headers. For CSV input these become the property names.
|
||||
For CSV output these specify the properties to extract from the object and the order for the CSV.</p>
|
||||
<p>If the input is an array then the columns template does not matter, but can be used to generate a row of column titles.</p>
|
||||
|
@@ -44,7 +44,7 @@
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="html">
|
||||
<p>Extracts elements from an html document held in <b>msg.payload</b> using a selector.</p>
|
||||
<p>Extracts elements from an html document held in <code>msg.payload</code> using a selector.</p>
|
||||
<p>The selector uses <a href=="https://github.com/cheeriojs/cheerio/blob/master/Readme.md" target="_new">Cheerio</a>
|
||||
which uses the <a href="https://github.com/fb55/CSSselect#user-content-supported-selectors" target="_new">CSS selector</a> syntax.</p>
|
||||
<p>The result can be either a single message with a payload containing an array of the matched elements, or multiple
|
||||
|
@@ -22,7 +22,7 @@
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="json">
|
||||
<p>A function that parses the <b>msg.payload</b> to convert a JSON string to/from a javascript object. Places the result back into the payload.</p>
|
||||
<p>A function that parses the <code>msg.payload</code> to convert a JSON string to/from a javascript object. Places the result back into the payload.</p>
|
||||
<p>If the input is a JSON string it tries to parse it to a javascript object.</p>
|
||||
<p>If the input is a javascript object it creates a JSON string.</p>
|
||||
</script>
|
||||
|
@@ -33,11 +33,11 @@
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="xml">
|
||||
<p>A function that parses the <b>msg.payload</b> to convert xml to/from a javascript object. Places the result in the payload.</p>
|
||||
<p>A function that parses the <code>msg.payload</code> to convert xml to/from a javascript object. Places the result in the payload.</p>
|
||||
<p>If the input is a string it tries to parse it as XML and creates a javascript object.</p>
|
||||
<p>If the input is a javascript object it tries to build an XML string.</p>
|
||||
<p>You can also pass in a <b>msg.options</b> object to overide all the multitude of parameters. See
|
||||
<a href="https://github.com/Leonidas-from-XIV/node-xml2js/blob/master/README.md" target="_new">the xml2js docs <i>here</i></a>
|
||||
<p>You can also pass in a <code>msg.options</code> object to overide all the multitude of parameters. See
|
||||
<a href="https://github.com/Leonidas-from-XIV/node-xml2js/blob/master/README.md#options" target="_new">the xml2js docs</a>
|
||||
for more information.</p>
|
||||
<p>If set, options in the edit dialogue override those passed in on the msg.options object.</p>
|
||||
</script>
|
||||
|
@@ -33,7 +33,7 @@
|
||||
|
||||
<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.</p>
|
||||
<p>This won't work on Windows filesystems, as it relies on the <b>tail -F</b> command.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
@@ -44,11 +44,12 @@
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="file">
|
||||
<p>Writes <b>msg.payload</b> to the file specified, e.g. to create a log.</p>
|
||||
<p>The filename can be configured in the node, if left blank it should be set in an incoming message on <b>msg.filename</b>.</p>
|
||||
<p>Writes <code>msg.payload</code> to the file specified, for example to create a log.</p>
|
||||
<p>The filename can be configured in the node. If left blank it should be
|
||||
set by <code>msg.filename</code> on the incoming message.</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>
|
||||
<p>This node can also be configured to delete a file if required. <i>Note:</i> Using msg.delete is now deprecated.</p>
|
||||
<p>This node can also be configured to delete a file if required.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="file in">
|
||||
@@ -70,8 +71,10 @@
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="file in">
|
||||
<p>Reads the specified file and sends the content as <b>msg.payload</b>, and the filename as <b>msg.filename</b>.</p>
|
||||
<p>The filename can be configured in the node, if left blank it should be set in an incoming message on <b>msg.filename</b>.</p>
|
||||
<p>Reads the specified file and sends the content as <code>msg.payload</code>,
|
||||
and the filename as <code>msg.filename</code>.</p>
|
||||
<p>The filename can be configured in the node. If left blank it should be
|
||||
set by <code>msg.filename</code> on the incoming message.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
26
package.json
26
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name" : "node-red",
|
||||
"version" : "0.13.1",
|
||||
"version" : "0.13.2",
|
||||
"description" : "A visual tool for wiring the Internet of Things",
|
||||
"homepage" : "http://nodered.org",
|
||||
"license" : "Apache-2.0",
|
||||
@@ -27,29 +27,29 @@
|
||||
"dependencies": {
|
||||
"basic-auth": "1.0.3",
|
||||
"bcryptjs": "2.3.0",
|
||||
"body-parser": "1.14.2",
|
||||
"cheerio":"0.19.0",
|
||||
"body-parser": "1.15.0",
|
||||
"cheerio":"0.20.0",
|
||||
"clone": "1.0.2",
|
||||
"cors":"2.7.1",
|
||||
"cron":"1.1.0",
|
||||
"express": "4.13.3",
|
||||
"express": "4.13.4",
|
||||
"follow-redirects":"0.0.7",
|
||||
"fs-extra": "0.26.4",
|
||||
"fs-extra": "0.26.5",
|
||||
"fs.notify":"0.0.4",
|
||||
"i18next":"1.10.6",
|
||||
"is-utf8":"0.2.1",
|
||||
"media-typer": "0.3.0",
|
||||
"mqtt": "1.6.3",
|
||||
"mqtt": "1.7.2",
|
||||
"mustache": "2.2.1",
|
||||
"nopt": "3.0.6",
|
||||
"oauth2orize":"1.2.0",
|
||||
"oauth2orize":"1.2.2",
|
||||
"on-headers":"1.0.1",
|
||||
"passport":"0.3.2",
|
||||
"passport-http-bearer":"1.0.1",
|
||||
"passport-oauth2-client-password":"0.1.2",
|
||||
"raw-body":"2.1.5",
|
||||
"semver": "5.1.0",
|
||||
"sentiment":"1.0.5",
|
||||
"sentiment":"1.0.6",
|
||||
"uglify-js":"2.6.1",
|
||||
"when": "3.7.7",
|
||||
"ws": "0.8.1",
|
||||
@@ -67,22 +67,22 @@
|
||||
"grunt": "0.4.5",
|
||||
"grunt-chmod": "1.1.1",
|
||||
"grunt-cli": "0.1.13",
|
||||
"grunt-concurrent":"2.1.0",
|
||||
"grunt-concurrent":"2.2.1",
|
||||
"grunt-contrib-clean":"0.7.0",
|
||||
"grunt-contrib-compress": "0.14.0",
|
||||
"grunt-contrib-concat":"0.5.1",
|
||||
"grunt-contrib-copy": "0.8.2",
|
||||
"grunt-contrib-jshint": "0.12.0",
|
||||
"grunt-contrib-uglify": "0.11.0",
|
||||
"grunt-contrib-uglify": "0.11.1",
|
||||
"grunt-contrib-watch":"0.6.1",
|
||||
"grunt-jsonlint":"1.0.7",
|
||||
"grunt-nodemon":"0.4.1",
|
||||
"grunt-sass":"1.1.0",
|
||||
"grunt-simple-mocha": "0.4.1",
|
||||
"mocha": "2.3.4",
|
||||
"mocha": "2.4.5",
|
||||
"should": "6.0.3",
|
||||
"sinon": "1.17.2",
|
||||
"supertest": "1.1.0"
|
||||
"sinon": "1.17.3",
|
||||
"supertest": "1.2.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10"
|
||||
|
13
red.js
13
red.js
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
/**
|
||||
* Copyright 2013, 2015 IBM Corp.
|
||||
* Copyright 2013, 2016 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -35,12 +35,14 @@ var flowFile;
|
||||
var knownOpts = {
|
||||
"settings":[path],
|
||||
"userDir":[path],
|
||||
"port": Number,
|
||||
"v": Boolean,
|
||||
"help": Boolean
|
||||
};
|
||||
var shortHands = {
|
||||
"s":["--settings"],
|
||||
"u":["--userDir"],
|
||||
"p":["--port"],
|
||||
"?":["--help"]
|
||||
};
|
||||
nopt.invalidHandler = function(k,v,t) {
|
||||
@@ -51,11 +53,13 @@ var parsedArgs = nopt(knownOpts,shortHands,process.argv,2)
|
||||
|
||||
if (parsedArgs.help) {
|
||||
console.log("Node-RED v"+RED.version());
|
||||
console.log("Usage: node-red [-v] [-?] [--settings settings.js] [--userDir DIR] [flows.json]");
|
||||
console.log("Usage: node-red [-v] [-?] [--settings settings.js] [--userDir DIR]");
|
||||
console.log(" [--port PORT] [flows.json]");
|
||||
console.log("");
|
||||
console.log("Options:");
|
||||
console.log(" -s, --settings FILE use specified settings file");
|
||||
console.log(" -u, --userDir DIR use specified user directory");
|
||||
console.log(" -p, --port PORT port to listen on");
|
||||
console.log(" -v enable verbose output");
|
||||
console.log(" -?, --help show usage");
|
||||
console.log("");
|
||||
@@ -153,7 +157,7 @@ if (settings.httpNodeRoot !== false) {
|
||||
settings.httpNodeAuth = settings.httpNodeAuth || settings.httpAuth;
|
||||
}
|
||||
|
||||
settings.uiPort = settings.uiPort||1880;
|
||||
settings.uiPort = parsedArgs.port||settings.uiPort||1880;
|
||||
settings.uiHost = settings.uiHost||"0.0.0.0";
|
||||
|
||||
if (flowFile) {
|
||||
@@ -194,6 +198,9 @@ function basicAuthMiddleware(user,pass) {
|
||||
}
|
||||
|
||||
return function(req,res,next) {
|
||||
if (req.method === 'OPTIONS') {
|
||||
return next();
|
||||
}
|
||||
var requestUser = basicAuth(req);
|
||||
if (!requestUser || requestUser.name !== user || !checkPassword(requestUser.pass)) {
|
||||
res.set('WWW-Authenticate', 'Basic realm=Authorization Required');
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2014, 2015 IBM Corp.
|
||||
* Copyright 2014, 2016 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -51,7 +51,15 @@ function start() {
|
||||
var webSocketKeepAliveTime = settings.webSocketKeepAliveTime || 15000;
|
||||
var path = settings.httpAdminRoot || "/";
|
||||
path = (path.slice(0,1) != "/" ? "/":"") + path + (path.slice(-1) == "/" ? "":"/") + "comms";
|
||||
wsServer = new ws.Server({server:server,path:path});
|
||||
wsServer = new ws.Server({
|
||||
server:server,
|
||||
path:path,
|
||||
// Disable the deflate option due to this issue
|
||||
// https://github.com/websockets/ws/pull/632
|
||||
// that is fixed in the 1.x release of the ws module
|
||||
// that we cannot currently pickup as it drops node 0.10 support
|
||||
perMessageDeflate: false
|
||||
});
|
||||
|
||||
wsServer.on('connection',function(ws) {
|
||||
log.audit({event: "comms.open"});
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2014 IBM Corp.
|
||||
* Copyright 2014, 2016 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,7 +28,8 @@ var persistentSettings = {
|
||||
userSettings = settings;
|
||||
for (var i in settings) {
|
||||
/* istanbul ignore else */
|
||||
if (settings.hasOwnProperty(i) && typeof settings[i] !== "function") {
|
||||
if (settings.hasOwnProperty(i) && i !== 'load' && i !== 'get' && i !== 'set' && i !== 'available' && i !== 'reset') {
|
||||
// Don't allow any of the core functions get replaced via settings
|
||||
(function() {
|
||||
var j = i;
|
||||
persistentSettings.__defineGetter__(j,function() { return userSettings[j]; });
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2014, 2015 IBM Corp.
|
||||
* Copyright 2014, 2016 IBM Corp.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -165,7 +165,7 @@ function evaluateNodeProperty(value, type, node, msg) {
|
||||
} else if (type === 'global' && node) {
|
||||
return node.context().global.get(value);
|
||||
} else if (type === 'bool') {
|
||||
return /^true$/i.test(value)
|
||||
return /^true$/i.test(value);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
@@ -40,6 +40,10 @@ module.exports = {
|
||||
// defaults to no timeout
|
||||
//socketTimeout: 120000,
|
||||
|
||||
// Timeout in milliseconds for HTTP request connections
|
||||
// defaults to 120 seconds
|
||||
//httpRequestTimeout: 120000,
|
||||
|
||||
// The maximum length, in characters, of any message sent to the debug sidebar tab
|
||||
debugMaxLength: 1000,
|
||||
|
||||
|
@@ -23,7 +23,7 @@ describe('inject node', function() {
|
||||
before(function(done) {
|
||||
helper.startServer(done);
|
||||
});
|
||||
|
||||
|
||||
afterEach(function() {
|
||||
helper.unload();
|
||||
});
|
||||
@@ -87,13 +87,13 @@ describe('inject node', function() {
|
||||
it('should inject message', function(done) {
|
||||
helper.load(injectNode,
|
||||
[{id:"n1", type:"inject",
|
||||
payloadType:"some type", topic: "t4",
|
||||
payloadType:"str", topic: "t4",payload:"hello",
|
||||
wires:[["n4"]] },
|
||||
{ id:"n4", type:"helper"}], function() {
|
||||
var n4 = helper.getNode("n4");
|
||||
n4.on("input", function(msg) {
|
||||
msg.should.have.property('topic', 't4');
|
||||
msg.should.have.property('payload', '');
|
||||
msg.should.have.property('payload', 'hello');
|
||||
helper.clearFlows().then(function() {
|
||||
done();
|
||||
});
|
||||
|
@@ -35,8 +35,8 @@ describe('trigger Node', function() {
|
||||
helper.load(triggerNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
n1.should.have.property('name', 'triggerNode');
|
||||
n1.should.have.property('op1', 1);
|
||||
n1.should.have.property('op2', 0);
|
||||
n1.should.have.property('op1', '1');
|
||||
n1.should.have.property('op2', '0');
|
||||
n1.should.have.property('op1type', 'val');
|
||||
n1.should.have.property('op2type', 'val');
|
||||
n1.should.have.property('extend', "false");
|
||||
@@ -82,11 +82,11 @@ describe('trigger Node', function() {
|
||||
var c = 0;
|
||||
n2.on("input", function(msg) {
|
||||
if (c === 0) {
|
||||
msg.should.have.a.property("payload", 1);
|
||||
msg.should.have.a.property("payload", '1');
|
||||
c+=1;
|
||||
}
|
||||
else {
|
||||
msg.should.have.a.property("payload", 0);
|
||||
msg.should.have.a.property("payload", '0');
|
||||
done();
|
||||
}
|
||||
});
|
||||
@@ -103,11 +103,11 @@ describe('trigger Node', function() {
|
||||
var c = 0;
|
||||
n2.on("input", function(msg) {
|
||||
if (c === 0) {
|
||||
msg.should.have.a.property("payload", 1);
|
||||
msg.should.have.a.property("payload", '1');
|
||||
c+=1;
|
||||
}
|
||||
else {
|
||||
msg.should.have.a.property("payload", 0);
|
||||
msg.should.have.a.property("payload", '0');
|
||||
}
|
||||
});
|
||||
setTimeout( function() {
|
||||
|
Reference in New Issue
Block a user