mirror of
https://github.com/node-red/node-red-nodes.git
synced 2025-03-01 10:37:43 +00:00
Merge branch 'master' of https://github.com/node-red/node-red-nodes
This commit is contained in:
commit
60fcbc351d
8
analysis/mlsentiment/locales/de/mlsentiment.json
Normal file
8
analysis/mlsentiment/locales/de/mlsentiment.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"mlsentiment": {
|
||||
"sentiment": "sentiment",
|
||||
"label": {
|
||||
"language": "Sprache"
|
||||
}
|
||||
}
|
||||
}
|
29
analysis/mlsentiment/locales/en-US/mlsentiment.html
Normal file
29
analysis/mlsentiment/locales/en-US/mlsentiment.html
Normal file
@ -0,0 +1,29 @@
|
||||
|
||||
<script type="text/html" data-help-name="mlsentiment">
|
||||
<p>Analyses the chosen property, default <code>payload</code>, and adds a <code>sentiment</code> object.</p>
|
||||
<h3>Outputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>sentiment <span class="property-type">object</span></dt>
|
||||
<dd>contains the resulting AFINN-111 sentiment.</dd>
|
||||
<dt>sentiment.score <span class="property-type">number</span></dt>
|
||||
<dd>the sentiment score.</dd>
|
||||
</dl>
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>words <span class="property-type">object</span></dt>
|
||||
<dd>an object of words and scores to override or add words can be supplied - <code>{ word:score,... }</code>.</dd>
|
||||
</dl>
|
||||
<dl class="message-properties">
|
||||
<dt>lang <span class="property-type">string</span></dt>
|
||||
<dd>Two letter cldr code to specify the language to use - from the list below</dd>
|
||||
</dl>
|
||||
<h3>Details</h3>
|
||||
<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>See <a href="https://github.com/marcellobarile/multilang-sentiment/blob/develop/README.md" target="_blank">the Sentiment docs here</a>.</p>
|
||||
<p>The node can also be configured to let the language be specified by setting <code>msg.lang</code> to one of the codes below</p>
|
||||
<p>The language codes supported are - af, am, ar, az, be, bg, bn, bs, ca, ceb, co, cs, cy, da, de, el, en, eo, es, et, eu, fa, fi,
|
||||
fr, fy, ga, gd, gl, gu, ha, haw, hi, hmn, hr, ht, hu, hy, id, ig, is, it, iw, ja, jw, ka, kk, km, kn, ko, ku, ky, la, lb, lo, lt,
|
||||
lv, mg, mi, mk, ml, mn, mr, ms, mt, my, ne, nl, no, ny, pa, pl, ps, pt, ro, ru, sd, si, sk, sl, sm, sn, so, sq, sr, st, su, sv,
|
||||
sw, ta, te, tg, th, tl, tr, uk, ur, uz, vi, xh, yi, yo, zh, zh-tw, zu</p>
|
||||
</script>
|
@ -1,5 +1,5 @@
|
||||
|
||||
<script type="text/x-red" data-help-name="mlsentiment">
|
||||
<script type="text/html" data-help-name="mlsentiment">
|
||||
<p>指定したプロパティ(デフォルトは<code>payload</code>)を分析し、<code>sentiment</code>オブジェクトを追加します。</p>
|
||||
<h3>出力</h3>
|
||||
<dl class="message-properties">
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="mlsentiment">
|
||||
<script type="text/html" data-template-name="mlsentiment">
|
||||
<div class="form-row">
|
||||
<label for="node-input-lang"><i class="fa fa-language"></i> <span data-i18n="mlsentiment.label.language"></span></label>
|
||||
<select type="text" id="node-input-lang" style="width:70%;">
|
||||
@ -118,35 +118,6 @@
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="mlsentiment">
|
||||
<p>Analyses the chosen property, default <code>payload</code>, and adds a <code>sentiment</code> object.</p>
|
||||
<h3>Outputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>sentiment <span class="property-type">object</span></dt>
|
||||
<dd>contains the resulting AFINN-111 sentiment.</dd>
|
||||
<dt>sentiment.score <span class="property-type">number</span></dt>
|
||||
<dd>the sentiment score.</dd>
|
||||
</dl>
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>words <span class="property-type">object</span></dt>
|
||||
<dd>an object of words and scores to override or add words can be supplied - <code>{ word:score,... }</code>.</dd>
|
||||
</dl>
|
||||
<dl class="message-properties">
|
||||
<dt>lang <span class="property-type">string</span></dt>
|
||||
<dd>Two letter cldr code to specify the language to use - from the list below</dd>
|
||||
</dl>
|
||||
<h3>Details</h3>
|
||||
<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>See <a href="https://github.com/marcellobarile/multilang-sentiment/blob/develop/README.md" target="_blank">the Sentiment docs here</a>.</p>
|
||||
<p>The node can also be configured to let the language be specified by setting <code>msg.lang</code> to one of the codes below</p>
|
||||
<p>The language codes supported are - af, am, ar, az, be, bg, bn, bs, ca, ceb, co, cs, cy, da, de, el, en, eo, es, et, eu, fa, fi,
|
||||
fr, fy, ga, gd, gl, gu, ha, haw, hi, hmn, hr, ht, hu, hy, id, ig, is, it, iw, ja, jw, ka, kk, km, kn, ko, ku, ky, la, lb, lo, lt,
|
||||
lv, mg, mi, mk, ml, mn, mr, ms, mt, my, ne, nl, no, ny, pa, pl, ps, pt, ro, ru, sd, si, sk, sl, sm, sn, so, sq, sr, st, su, sv,
|
||||
sw, ta, te, tg, th, tl, tr, uk, ur, uz, vi, xh, yi, yo, zh, zh-tw, zu</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('mlsentiment',{
|
||||
category: 'analysis-function',
|
||||
|
@ -1,4 +1,4 @@
|
||||
<script type="text/x-red" data-template-name="sentiment">
|
||||
<script type="text/html" data-template-name="sentiment">
|
||||
<div class="form-row">
|
||||
<label for="node-input-property"><i class="fa fa-ellipsis-h"></i> <span data-i18n="node-red:common.label.property"></span></label>
|
||||
<input type="text" id="node-input-property" style="width:70%;"/>
|
||||
|
8
analysis/sentiment/locales/de/72-sentiment.json
Normal file
8
analysis/sentiment/locales/de/72-sentiment.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"sentiment": {
|
||||
"sentiment": "sentiment",
|
||||
"label": {
|
||||
"language": "Sprache"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,12 +1,12 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="badwords">
|
||||
<script type="text/html" data-template-name="badwords">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="badwords">
|
||||
<script type="text/html" data-help-name="badwords">
|
||||
<p>Analyses the <code>msg.payload</code> and tries to filter out any messages containing bad swear words...</p>
|
||||
<p><b>Note:</b> this only operates on payloads of type <b>string</b>. Everything else is blocked.</p>
|
||||
</script>
|
||||
|
8
function/PID/locales/en-US/pidcontrol.html
Normal file
8
function/PID/locales/en-US/pidcontrol.html
Normal file
@ -0,0 +1,8 @@
|
||||
|
||||
<script type="text/html" data-help-name="PID control">
|
||||
<p>A PID controller node.</p>
|
||||
<p>This node ONLY expects a numeric <code>msg.payload</code> containing the current reading.
|
||||
It will output the correction that needs to be applied in order to move to the preset <i>set point</i> value.</p>
|
||||
<p>See <a href="https://en.wikipedia.org/wiki/PID_controller" target="_new">Wikipedia</a> for more details.</p>
|
||||
<p>The <i>set point</i> may be overridden by <code>msg.setpoint</code>. If you do so the edit box value can be used as the initial value.</p>
|
||||
</script>
|
@ -1,5 +1,5 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="PID control">
|
||||
<script type="text/html" data-template-name="PID control">
|
||||
<div class="form-row">
|
||||
<label for="node-input-target" style="width:120px;"><i class="fa fa-dot-circle-o"></i> Set Point</label>
|
||||
<input type="text" id="node-input-target" placeholder="target value" style="width:60%;">
|
||||
@ -24,14 +24,6 @@
|
||||
The damping factors are typically in the range 0 - 1.<br></div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="PID control">
|
||||
<p>A PID controller node.</p>
|
||||
<p>This node ONLY expects a numeric <code>msg.payload</code> containing the current reading.
|
||||
It will output the correction that needs to be applied in order to move to the preset <i>set point</i> value.</p>
|
||||
<p>See <a href="https://en.wikipedia.org/wiki/PID_controller" target="_new">Wikipedia</a> for more details.</p>
|
||||
<p>The <i>set point</i> may be overridden by <code>msg.setpoint</code>. If you do so the edit box value can be used as the initial value.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('PID control',{
|
||||
color:"#d6ba48",
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="data-generator">
|
||||
<script type="text/html" data-template-name="data-generator">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
|
||||
@ -25,17 +25,6 @@
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="data-generator">
|
||||
<p>Creates dummy data strings based on a handlebars-style template.</p>
|
||||
<p>Uses the <i><a href="https://github.com/webroo/dummy-json/blob/master/README.md" target="_new">dummy-json</a></i>
|
||||
module, which can create rich sets of dummy data for testing or other uses.</p>
|
||||
<p>Will build a string or a parsed JSON object, creating values based on the helper names below:
|
||||
<pre style="word-break:normal">title, firstName, lastName, company, domain, tld, email, street, city, country, countryCode, zipcode, postcode, lat, long, phone, color, hexColor, guid, ipv4, ipv6, lorem [nn], date, time, lowercase, uppercase, int, float, boolean</pre>
|
||||
<p>Multiple values can be generated by use of the <i>repeat</i> syntax.</p>
|
||||
<p>In addition any properties passed in on <code>msg</code> can also be used - for example <code>{{payload}}</code>.</p>
|
||||
<p>Finally <code>msg.seed</code> can be used to preset the pseudo-random seed to ensure repeatability across calls.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('data-generator',{
|
||||
color:"rgb(243, 181, 103)",
|
||||
|
13
function/datagenerator/locales/de/datagenerator.json
Normal file
13
function/datagenerator/locales/de/datagenerator.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"datagen": {
|
||||
"datagen": "data generator",
|
||||
"label": {
|
||||
"syntax": "Rückgabe",
|
||||
"text": "ein Text-String",
|
||||
"json": "ein analysiertes (parsed) JSON-Objekt"
|
||||
},
|
||||
"errors": {
|
||||
"json-error": "Fehler beim Versuch, String zu JSON zu analysieren (parsen)"
|
||||
}
|
||||
}
|
||||
}
|
11
function/datagenerator/locales/en-US/datagenerator.html
Normal file
11
function/datagenerator/locales/en-US/datagenerator.html
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
<script type="text/html" data-help-name="data-generator">
|
||||
<p>Creates dummy data strings based on a handlebars-style template.</p>
|
||||
<p>Uses the <i><a href="https://github.com/webroo/dummy-json/blob/master/README.md" target="_new">dummy-json</a></i>
|
||||
module, which can create rich sets of dummy data for testing or other uses.</p>
|
||||
<p>Will build a string or a parsed JSON object, creating values based on the helper names below:
|
||||
<pre style="word-break:normal">title, firstName, lastName, company, domain, tld, email, street, city, country, countryCode, zipcode, postcode, lat, long, phone, color, hexColor, guid, ipv4, ipv6, lorem [nn], date, time, lowercase, uppercase, int, float, boolean</pre>
|
||||
<p>Multiple values can be generated by use of the <i>repeat</i> syntax.</p>
|
||||
<p>In addition any properties passed in on <code>msg</code> can also be used - for example <code>{{payload}}</code>.</p>
|
||||
<p>Finally <code>msg.seed</code> can be used to preset the pseudo-random seed to ensure repeatability across calls.</p>
|
||||
</script>
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name" : "node-red-node-data-generator",
|
||||
"version" : "0.1.1",
|
||||
"version" : "0.2.0",
|
||||
"description" : "A Node-RED node to create a string of dummy data values from a template. Useful for test-cases.",
|
||||
"dependencies" : {
|
||||
"dummy-json": "^2.0.0"
|
||||
|
13
function/random/locales/de/random.json
Normal file
13
function/random/locales/de/random.json
Normal file
@ -0,0 +1,13 @@
|
||||
{
|
||||
"random": {
|
||||
"label": {
|
||||
"generate": "Generiere",
|
||||
"wholeNumber": "eine Ganzzahl (integer)",
|
||||
"realNumber": "eine reelle Zahl (floating point)",
|
||||
"from": "Von",
|
||||
"lowestNumber": "kleinste Zahl",
|
||||
"to": "Bis",
|
||||
"highestNumber": "größte Zahl"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name" : "node-red-node-random",
|
||||
"version" : "0.3.1",
|
||||
"version" : "0.4.0",
|
||||
"description" : "A Node-RED node that when triggered generates a random number between two values.",
|
||||
"dependencies" : {
|
||||
},
|
||||
|
40
function/rbe/locales/de/rbe.html
Normal file
40
function/rbe/locales/de/rbe.html
Normal file
@ -0,0 +1,40 @@
|
||||
<script type="text/html" data-help-name="rbe">
|
||||
<p>Report by Exception (RBE) - Daten-Weiterleitung nur bei Änderung der Nutzdaten (Payload).
|
||||
Der Node kann auch blockieren oder weiterleiten, wenn die Wertänderung eine Grenze überschreitet (Totband- und Nahband-Modus).</p>
|
||||
<h3>Eingangsdaten</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload
|
||||
<span class="property-type">number | string | (object)</span>
|
||||
</dt>
|
||||
<dd>Der RBE-Modus mit Prüfung auf Wertänderung akzeptiert Zahlen (numbers), Zeichenfolgen (string) und einfache Objekte (object).
|
||||
Bei den anderen wertvergleichenden Modies müssen analysierbare (parseable) Zahlenwerte übergeben werden.</dd>
|
||||
<dt class="optional">topic <span class="property-type">string</span>
|
||||
</dt>
|
||||
<dd>Wenn vorgegeben erfolgt die Auswertung separat für jedes Topic</dd>
|
||||
<dt class="optional">reset<span class="property-type">any</span></dt>
|
||||
<dd>Wenn gesetzt wird/werden der/die gespeicherte(n) Wert(e) rückgesetzt</dd>
|
||||
</dl>
|
||||
<h3>Ausgangsdaten</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload
|
||||
<span class="property-type">wie Eingangsdaten</span>
|
||||
</dt>
|
||||
<dd>Wenn Bedingung erfüllt, sind die Ausgangsdaten gleich den Eingangsdaten</dd>
|
||||
</dl>
|
||||
<h3>Details</h3>
|
||||
<p>Im <i>RBE</i>-Modus mit Prüfung auf Wertänderung blockiert dieser Node die Datenweitergabe bis
|
||||
<code>msg.payload</code> (oder die eingestellte Eigenschaft) verändert ist gegenüber dessen vorherigen Wert.
|
||||
Wenn benötigt, wird der Anfangswert ignoriert, sodass beim Start nichts gesendet wird.</p>
|
||||
<p>In den <i>Totband</i>-Modies werden die Eingangswerte geblockt,
|
||||
<i>bis</i> die Wertänderung größer oder größer-gleich ist als ± des Bandes um den voherigen Wert.</p>
|
||||
<p>In den <i>Nahband</i>-Modies werden die Eingangswerte geblockt,
|
||||
<i>wenn</i> die Wertänderung größer oder größer-gleich ist als ± des Bandes um den voherigen Wert.
|
||||
Dies ist beispielsweise nützlich, um Ausreißer eines fehlerhaften Sensors zu ignorieren.</p>
|
||||
<p>In den Totband und Nahband-Modies müssen die Eingangswerte analysierbare (parseable) Zahlenwerte sein und
|
||||
beide unterstützen auch % (prozentuale Angabe), d.h. der Node sendet nur, wenn der Eingangswert mehr als x% vom vorherigen Wert abweicht.</p>
|
||||
<p>Die Totband- und Nahband-Modies erlauben den Vergleich entweder gegen den letzten gültigen Ausgangswert,
|
||||
dieses zum Ignorieren von Werten außerhalb des gültigen Bereichs, oder gegen den des vorherigen Eingangswertes,
|
||||
welches den Sollwert rücksetzt, was einen allmähligen Drift (Totband) oder einen eine schrittweise Veränderung (Nahband) ermöglicht.</p>
|
||||
<p><b>Hinweis</b>: Dieser Node arbeitet auf per-<code>msg.topic</code>-Basis.
|
||||
Dies bedeutet, dass ein einzelner rbe-Node mehrere verschiedene Topics parallel bearbeiten kann.</p>
|
||||
</script>
|
29
function/rbe/locales/de/rbe.json
Normal file
29
function/rbe/locales/de/rbe.json
Normal file
@ -0,0 +1,29 @@
|
||||
{
|
||||
"rbe": {
|
||||
"rbe": "rbe",
|
||||
"label": {
|
||||
"func": "Modus",
|
||||
"init": "Sende Anfangswert",
|
||||
"start": "Startwert",
|
||||
"name": "Name",
|
||||
"septopics": "Modus für jedes msg.topic separat anwenden"
|
||||
},
|
||||
"placeholder":{
|
||||
"bandgap": "z.B. 10 oder 5%",
|
||||
"start": "Leer lassen, um erste empfangenen Daten zu nutzen"
|
||||
},
|
||||
"opts": {
|
||||
"rbe": "Blockieren bis Wertänderung",
|
||||
"rbei": "Blockieren bis Wertänderung (Anfangswert ignorieren)",
|
||||
"deadband": "Blockieren bis Wertänderung ist größer als",
|
||||
"deadbandEq": "Blockieren bis Wertänderung ist größer-gleich",
|
||||
"narrowband": "Blockieren wenn Wertänderung ist größer als",
|
||||
"narrowbandEq": "Blockieren wenn Wertänderung ist größer-gleich",
|
||||
"in": "verglichen mit letzten Eingangswert",
|
||||
"out": "verglichen mit letzten gültigen Ausgangswert"
|
||||
},
|
||||
"warn": {
|
||||
"nonumber": "Keine Zahl gefunden in den Nutzdaten (Payload)"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,18 +1,19 @@
|
||||
<script type="text/html" data-help-name="rbe">
|
||||
<p>Report by Exception node - only passes on data if the payload has changed.</p>
|
||||
<p>It can also block unless, or ignore if the value changes by a specified amount.</p>
|
||||
<p>Report by Exception (RBE) node - only passes on data if the payload has changed.
|
||||
It can also block unless, or ignore if the value changes by a specified amount (Dead- and Narrowband mode).</p>
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload
|
||||
<span class="property-type">number | string | (object)</span>
|
||||
</dt>
|
||||
<dd>RBE mode will accept numbers, strings, and simple objects. Other modes must provide a parseable number.</dd>
|
||||
<dd>RBE mode will accept numbers, strings, and simple objects.
|
||||
Other modes must provide a parseable number.</dd>
|
||||
<dt class="optional">topic <span class="property-type">string</span>
|
||||
</dt>
|
||||
<dd>if specified the function will work on a per topic basis.</dd>
|
||||
<dt class="optional">reset<span class="property-type">any</span></dt>
|
||||
<dd>if set clears the stored value for the specified msg.topic, or
|
||||
all topics if msg.topic is not specified.</dd>
|
||||
all topics if msg.topic is not specified.</dd>
|
||||
</dl>
|
||||
<h3>Outputs</h3>
|
||||
<dl class="message-properties">
|
||||
@ -23,16 +24,18 @@
|
||||
</dl>
|
||||
<h3>Details</h3>
|
||||
<p>In RBE mode this node will block until the <code>msg.payload</code>,
|
||||
(or selected property) value is different to the previous one. If required
|
||||
it can ignore the intial value, so as not to send anything at start.</p>
|
||||
<p>In the Deadband modes the incoming value must contain a parseable number and will block
|
||||
unless the change is greater than + or - the band gap away from a previous value.</p>
|
||||
<p>Deadband also supports % - only sends if the input differs by more than x% of the original value.</p>
|
||||
<p>The Narrowband modes will block if the incoming value change is greater than + or - the band gap
|
||||
away from the previous value. Useful for ignoring outliers from a faulty sensor for example.</p>
|
||||
(or selected property) value is different to the previous one.
|
||||
If required it can ignore the intial value, so as not to send anything at start.</p>
|
||||
<p>The <a href="https://en.wikipedia.org/wiki/Deadband" target="_blank">Deadband</a> modes will block the incoming value
|
||||
<i>unless</i> its change is greater or greater-equal than ± the band gap away from a previous value.</p>
|
||||
<p>The Narrowband modes will block the incoming value,
|
||||
<i>if</i> its change is greater or greater-equal than ± the band gap away from the previous value.
|
||||
It is useful for ignoring outliers from a faulty sensor for example.</p>
|
||||
<p>Both in Deadband and Narrowband modes the incoming value must contain a parseable number and
|
||||
both also supports % - only sends if/unless the input differs by more than x% of the original value.</p>
|
||||
<p>Both Deadband and Narrowband allow comparison against either the previous valid output value, thus
|
||||
ignoring any values out of range; or the previous input value, which resets the set point, thus allowing
|
||||
ignoring any values out of range, or the previous input value, which resets the set point, thus allowing
|
||||
gradual drift (deadband), or a step change (narrowband).</p>
|
||||
<p><b>Note:</b> This works on a per <code>msg.topic</code> basis. This means that a single rbe node can
|
||||
handle multiple different topics at the same time.</p>
|
||||
<p><b>Note:</b> This works on a per <code>msg.topic</code> basis.
|
||||
This means that a single rbe node can handle multiple different topics at the same time.</p>
|
||||
</script>
|
||||
|
@ -5,7 +5,8 @@
|
||||
"func": "Mode",
|
||||
"init": "Send initial value",
|
||||
"start": "Start value",
|
||||
"name": "Name"
|
||||
"name": "Name",
|
||||
"septopics": "Apply mode for each msg.topic separately"
|
||||
},
|
||||
"placeholder":{
|
||||
"bandgap": "e.g. 10 or 5%",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name" : "node-red-node-rbe",
|
||||
"version" : "0.2.9",
|
||||
"version" : "0.5.0",
|
||||
"description" : "A Node-RED node that provides report-by-exception (RBE) and deadband capabilities.",
|
||||
"dependencies" : {
|
||||
},
|
||||
|
@ -27,6 +27,11 @@
|
||||
<label for="node-input-property"><i class="fa fa-ellipsis-h"></i> <span data-i18n="node-red:common.label.property"></span></label>
|
||||
<input type="text" id="node-input-property" style="width:70%;"/>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label> </label>
|
||||
<input type="checkbox" id="node-input-septopics" style="display:inline-block; width:20px; vertical-align:baseline;">
|
||||
<span data-i18n="rbe.label.septopics"></span>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="rbe.label.name"></span></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]rbe.label.name" style="width:70%;">
|
||||
@ -43,6 +48,7 @@
|
||||
gap: {value:"",validate:RED.validators.regex(/^(\d*[.]*\d*|)(%|)$/)},
|
||||
start: {value:""},
|
||||
inout: {value:"out"},
|
||||
septopics: {value:true},
|
||||
property: {value:"payload",required:true}
|
||||
},
|
||||
inputs:1,
|
||||
@ -59,6 +65,9 @@
|
||||
if (this.property === undefined) {
|
||||
$("#node-input-property").val("payload");
|
||||
}
|
||||
if (this.septopics === undefined) {
|
||||
$("#node-input-septopics").prop('checked', true);
|
||||
}
|
||||
$("#node-input-property").typedInput({default:'msg',types:['msg']});
|
||||
//$( "#node-input-gap" ).spinner({min:0});
|
||||
if ($("#node-input-inout").val() === null) {
|
||||
|
@ -14,20 +14,25 @@ module.exports = function(RED) {
|
||||
}
|
||||
this.g = this.gap;
|
||||
this.property = n.property||"payload";
|
||||
this.septopics = true;
|
||||
if (n.septopics !== undefined && n.septopics === false) {
|
||||
this.septopics = false;
|
||||
}
|
||||
|
||||
var node = this;
|
||||
|
||||
node.previous = {};
|
||||
this.on("input",function(msg) {
|
||||
if (msg.hasOwnProperty("reset")) {
|
||||
if (msg.hasOwnProperty("topic") && (typeof msg.topic === "string") && (msg.topic !== "")) {
|
||||
if (node.septopics && msg.hasOwnProperty("topic") && (typeof msg.topic === "string") && (msg.topic !== "")) {
|
||||
delete node.previous[msg.topic];
|
||||
}
|
||||
else { node.previous = {}; }
|
||||
}
|
||||
var value = RED.util.getMessageProperty(msg,node.property);
|
||||
if (value !== undefined) {
|
||||
var t = msg.topic || "_no_topic";
|
||||
var t = "_no_topic";
|
||||
if (node.septopics) { t = msg.topic || t; }
|
||||
if ((this.func === "rbe") || (this.func === "rbei")) {
|
||||
var doSend = (this.func !== "rbei") || (node.previous.hasOwnProperty(t)) || false;
|
||||
if (typeof(value) === "object") {
|
||||
|
@ -45,16 +45,6 @@
|
||||
<div class="form-tips" id="node-tip">Tip: This node ONLY works with numbers.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="smooth">
|
||||
<p>A simple node to provide various functions across several previous values, including max, min, mean, high and low pass filters.</p>
|
||||
<p>Messages arriving with different <code>msg.topic</code> can be treated as separate streams if so configured.</p>
|
||||
<p>Max, Min and Mean work over a specified number of previous values.</p>
|
||||
<p>The High and Low pass filters use a smoothing factor. The higher the number the more the smoothing. E.g. a value of 10 is similar to an α of 0.1. It is analagous to an RC time constant - but there is no time component to this as the time is based on events arriving.</p>
|
||||
<p>Enabling the Reduce option causes the node to only emit one message per N values (available for the Max, Min and Mean functions). E.g. if set to Mean over 10 values, there will only be one outgoing message per 10 incoming ones.</p>
|
||||
<p>If <code>msg.reset</code> is received (with any value), all the counters and intermediate values are reset to an initial state.</p>
|
||||
<p><b>Note:</b> This only operates on <b>numbers</b>. Anything else will try to be made into a number and rejected if that fails.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('smooth', {
|
||||
color: "#E2D96E",
|
||||
|
10
function/smooth/locales/en-US/17-smooth.html
Normal file
10
function/smooth/locales/en-US/17-smooth.html
Normal file
@ -0,0 +1,10 @@
|
||||
|
||||
<script type="text/html" data-help-name="smooth">
|
||||
<p>A simple node to provide various functions across several previous values, including max, min, mean, high and low pass filters.</p>
|
||||
<p>Messages arriving with different <code>msg.topic</code> can be treated as separate streams if so configured.</p>
|
||||
<p>Max, Min and Mean work over a specified number of previous values.</p>
|
||||
<p>The High and Low pass filters use a smoothing factor. The higher the number the more the smoothing. E.g. a value of 10 is similar to an α of 0.1. It is analagous to an RC time constant - but there is no time component to this as the time is based on events arriving.</p>
|
||||
<p>Enabling the Reduce option causes the node to only emit one message per N values (available for the Max, Min and Mean functions). E.g. if set to Mean over 10 values, there will only be one outgoing message per 10 incoming ones.</p>
|
||||
<p>If <code>msg.reset</code> is received (with any value), all the counters and intermediate values are reset to an initial state.</p>
|
||||
<p><b>Note:</b> This only operates on <b>numbers</b>. Anything else will try to be made into a number and rejected if that fails.</p>
|
||||
</script>
|
@ -24,14 +24,6 @@
|
||||
<div class="form-tips"><span data-i18n="[html]arduino.tip.io"></span></div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="arduino in">
|
||||
<p>Arduino input node. Connects to a local Arduino and monitors the selected pin for changes. Uses <a href="http://firmata.org/" target="_new"><i>Firmata</i>.</a></p>
|
||||
<p>The Arduino must be loaded with the Standard Firmata sketch available in the Arduino examples.</p>
|
||||
<p>You can select either Digital or Analogue input. Outputs the value read as <code>msg.payload</code> and the pin number as <code>msg.topic</code>.</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>For example you could use a <code>delay</code> node set to rate limit and drop intermediate values, or an <code>rbe</code> node to only report when it changes by a certain amount.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('arduino in',{
|
||||
category: 'Arduino',
|
||||
@ -85,14 +77,6 @@
|
||||
<div class="form-tips"><span data-i18n="[html]arduino.tip.io"></span></div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="arduino out">
|
||||
<p>Arduino output node. Connects to local Arduino and writes to the selected digital
|
||||
pin. Uses <a href="http://firmata.org/" target="_new"><i>Firmata</i>.</a></p>
|
||||
<p>The Arduino must be loaded with the Standard Firmata sketch available in the Arduino examples.</p>
|
||||
<p>You can select Digital, Analogue (PWM) or Servo type outputs. Expects an integer numeric
|
||||
value in <code>msg.payload</code>. The pin number is set in the properties panel.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('arduino out', {
|
||||
category: 'Arduino',
|
||||
|
42
hardware/Arduino/locales/de/35-arduino.json
Normal file
42
hardware/Arduino/locales/de/35-arduino.json
Normal file
@ -0,0 +1,42 @@
|
||||
{
|
||||
"arduino": {
|
||||
"label": {
|
||||
"pin": "Pin",
|
||||
"type": "Typ",
|
||||
"port": "Port"
|
||||
},
|
||||
"placeholder": {
|
||||
"port": "z. B. /dev/ttyUSB0 COM1"
|
||||
},
|
||||
"status": {
|
||||
"connectfirst": "Verbinde mit zuerst gefundenen Board",
|
||||
"connect": "Verbinde mit __device__",
|
||||
"connected": "Verbunden mit __device__",
|
||||
"version": "Version: __version__",
|
||||
"portclosed": "Serieller Arduino-Port geschlossen"
|
||||
},
|
||||
"state": {
|
||||
"in": {
|
||||
"digital": "Digitaler Pin",
|
||||
"pullup": "Digitaler Pin mit Pullup",
|
||||
"analogue": "Analoger Pin",
|
||||
"string": "String"
|
||||
},
|
||||
"out": {
|
||||
"digital": "Digital (0/1)",
|
||||
"analogue": "Analog (0-255)",
|
||||
"servo": "Servo (0-180)",
|
||||
"string": "String"
|
||||
}
|
||||
},
|
||||
"tip": {
|
||||
"io": "<b>Hinweis:</b> Derselbe Pin kann nicht gleichzeitig als Ausgang und Eingang verwendet werden",
|
||||
"conf": "<b>Tipp:</b> Zur automatischen Erkennung des seriellen Ports die Suche verwenden"
|
||||
},
|
||||
"errors": {
|
||||
"portnotconf": "Port nicht konfiguriert",
|
||||
"portnotfound": "Port nicht gefunden: __device__",
|
||||
"devnotfound": "Device __dev__ nicht gefunden. Versuche Board zu finden."
|
||||
}
|
||||
}
|
||||
}
|
16
hardware/Arduino/locales/en-US/35-arduino.html
Normal file
16
hardware/Arduino/locales/en-US/35-arduino.html
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
<script type="text/html" data-help-name="arduino in">
|
||||
<p>Arduino input node. Connects to a local Arduino and monitors the selected pin for changes. Uses <a href="http://firmata.org/" target="_new"><i>Firmata</i>.</a></p>
|
||||
<p>The Arduino must be loaded with the Standard Firmata sketch available in the Arduino examples.</p>
|
||||
<p>You can select either Digital or Analogue input. Outputs the value read as <code>msg.payload</code> and the pin number as <code>msg.topic</code>.</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>For example you could use a <code>delay</code> node set to rate limit and drop intermediate values, or an <code>rbe</code> node to only report when it changes by a certain amount.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="arduino out">
|
||||
<p>Arduino output node. Connects to local Arduino and writes to the selected digital
|
||||
pin. Uses <a href="http://firmata.org/" target="_new"><i>Firmata</i>.</a></p>
|
||||
<p>The Arduino must be loaded with the Standard Firmata sketch available in the Arduino examples.</p>
|
||||
<p>You can select Digital, Analogue (PWM) or Servo type outputs. Expects an integer numeric
|
||||
value in <code>msg.payload</code>. The pin number is set in the properties panel.</p>
|
||||
</script>
|
@ -1,5 +1,5 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="rpi-piface in">
|
||||
<script type="text/html" data-template-name="rpi-piface in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-pin"><i class="fa fa-circle"></i> GPIO Pin</label>
|
||||
<select type="text" id="node-input-pin" style="width: 150px;">
|
||||
@ -42,7 +42,7 @@
|
||||
<div class="form-tips">Tip: Only Digital I/O is supported - input must be 0 or 1.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-piface in">
|
||||
<script type="text/html" data-help-name="rpi-piface in">
|
||||
<p>Raspberry Pi PiFace 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 if required.</p>
|
||||
@ -76,7 +76,7 @@
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/x-red" data-template-name="rpi-piface out">
|
||||
<script type="text/html" data-template-name="rpi-piface out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-pin"><i class="fa fa-circle"></i> GPIO Pin</label>
|
||||
<select type="text" id="node-input-pin" style="width: 150px;">
|
||||
@ -111,7 +111,7 @@
|
||||
<div class="form-tips">Tip: Only Digital I/O is supported - input must be 0 or 1.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-piface out">
|
||||
<script type="text/html" data-help-name="rpi-piface out">
|
||||
<p>Raspberry Pi PiFace output node. The PiFace board must be fitted.</p>
|
||||
<p>Will set the selected relay, LED, or pin on or off depending on the value passed in. Expects a <code>msg.payload</code> with either a 1 or 0 (or true or false).</p>
|
||||
<p>Requires the WiringPi gpio command in order to work.</p>
|
||||
|
@ -78,86 +78,86 @@
|
||||
<div class="pinTableCellR pinColorPower"><label><input disabled type="radio" name="pins" value=""> 2 - 5V Power</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-3">SDA1 - GPIO02 - 3 <input id="pinTable-pin-3" type="radio" name="pins" value="3"></label></div>
|
||||
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-3">SDA1 - GPIO02 - 3 <input id="pinTable-pin-3" type="radio" name="pins" value="2"></label></div>
|
||||
<div class="pinTableCellR pinColorPower"><label><input disabled type="radio" name="pins" value=""> 4 - 5V Power</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-5">SCL1 - GPIO03 - 5 <input id="pinTable-pin-5" type="radio" name="pins" value="5"></label></div>
|
||||
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-5">SCL1 - GPIO03 - 5 <input id="pinTable-pin-5" type="radio" name="pins" value="3"></label></div>
|
||||
<div class="pinTableCellR pinColorGround"><label><input disabled type="radio" name="pins" value=""> 6 - Ground</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-7">GPIO04 - 7 <input id="pinTable-pin-7" type="radio" name="pins" value="7"></label></div>
|
||||
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-8"><input id="pinTable-pin-8" type="radio" name="pins" value="8"> 8 - GPIO14 - TxD</label></div>
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-7">GPIO04 - 7 <input id="pinTable-pin-7" type="radio" name="pins" value="4"></label></div>
|
||||
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-8"><input id="pinTable-pin-8" type="radio" name="pins" value="14"> 8 - GPIO14 - TxD</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGround"><label>Ground - 9 <input disabled type="radio" name="pins" value=""></label></div>
|
||||
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-10"><input id="pinTable-pin-10" type="radio" name="pins" value="10"> 10 - GPIO15 - RxD</label></div>
|
||||
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-10"><input id="pinTable-pin-10" type="radio" name="pins" value="15"> 10 - GPIO15 - RxD</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-11">GPIO17 - 11 <input id="pinTable-pin-11" type="radio" name="pins" value="11"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-12"><input id="pinTable-pin-12" type="radio" name="pins" value="12"> 12 - GPIO18</label></div>
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-11">GPIO17 - 11 <input id="pinTable-pin-11" type="radio" name="pins" value="17"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-12"><input id="pinTable-pin-12" type="radio" name="pins" value="18"> 12 - GPIO18</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-13">GPIO27 - 13 <input id="pinTable-pin-13" type="radio" name="pins" value="13"></label></div>
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-13">GPIO27 - 13 <input id="pinTable-pin-13" type="radio" name="pins" value="27"></label></div>
|
||||
<div class="pinTableCellR pinColorGround"><label><input disabled type="radio" name="pins" value=""> 14 - Ground</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-15">GPIO22 - 15 <input id="pinTable-pin-15" type="radio" name="pins" value="15"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-16"><input id="pinTable-pin-16" type="radio" name="pins" value="16"> 16 - GPIO23</label></div>
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-15">GPIO22 - 15 <input id="pinTable-pin-15" type="radio" name="pins" value="22"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-16"><input id="pinTable-pin-16" type="radio" name="pins" value="23"> 16 - GPIO23</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorPower"><label>3.3V Power - 17 <input disabled type="radio" name="pins" value=""></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-18"><input id="pinTable-pin-18" type="radio" name="pins" value="18"> 18 - GPIO24</label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-18"><input id="pinTable-pin-18" type="radio" name="pins" value="24"> 18 - GPIO24</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-19">MOSI - GPIO10 - 19 <input id="pinTable-pin-19" type="radio" name="pins" value="19"></label></div>
|
||||
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-19">MOSI - GPIO10 - 19 <input id="pinTable-pin-19" type="radio" name="pins" value="10"></label></div>
|
||||
<div class="pinTableCellR pinColorGround"><label><input disabled type="radio" name="pins" value=""> 20 - Ground</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-21">MISO - GPIO09 - 21 <input id="pinTable-pin-21" type="radio" name="pins" value="21"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-22"><input id="pinTable-pin-22" type="radio" name="pins" value="22"> 22 - GPIO25</label></div>
|
||||
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-21">MISO - GPIO09 - 21 <input id="pinTable-pin-21" type="radio" name="pins" value="9"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-22"><input id="pinTable-pin-22" type="radio" name="pins" value="25"> 22 - GPIO25</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-23">SCLK - GPIO11 - 23 <input id="pinTable-pin-23" type="radio" name="pins" value="23"></label></div>
|
||||
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-24"><input id="pinTable-pin-24" type="radio" name="pins" value="24"> 24 - GPIO8 - CE0</label></div>
|
||||
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-23">SCLK - GPIO11 - 23 <input id="pinTable-pin-23" type="radio" name="pins" value="11"></label></div>
|
||||
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-24"><input id="pinTable-pin-24" type="radio" name="pins" value="8"> 24 - GPIO8 - CE0</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGround"><label>Ground - 25 <input disabled type="radio" name="pins" value=""></label></div>
|
||||
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-26"><input id="pinTable-pin-26" type="radio" name="pins" value="26"> 26 - GPIO7 - CE1</label></div>
|
||||
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-26"><input id="pinTable-pin-26" type="radio" name="pins" value="7"> 26 - GPIO7 - CE1</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorSD"><label>SD - 27 <input disabled type="radio" name="pins" value=""></label></div>
|
||||
<div class="pinTableCellR pinColorSD"><label><input disabled type="radio" name="pins" value=""> 28 - SC</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-29">GPIO05 - 29 <input id="pinTable-pin-29" type="radio" name="pins" value="29"></label></div>
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-29">GPIO05 - 29 <input id="pinTable-pin-29" type="radio" name="pins" value="5"></label></div>
|
||||
<div class="pinTableCellR pinColorGround"><label><input disabled type="radio" name="pins" value=""> 30 - Ground</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-31">GPIO06 - 31 <input id="pinTable-pin-31" type="radio" name="pins" value="31"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-32"><input id="pinTable-pin-32" type="radio" name="pins" value="32"> 32 - GPIO12</label></div>
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-31">GPIO06 - 31 <input id="pinTable-pin-31" type="radio" name="pins" value="6"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-32"><input id="pinTable-pin-32" type="radio" name="pins" value="12"> 32 - GPIO12</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-33">GPIO13 - 33 <input id="pinTable-pin-33" type="radio" name="pins" value="33"></label></div>
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-33">GPIO13 - 33 <input id="pinTable-pin-33" type="radio" name="pins" value="13"></label></div>
|
||||
<div class="pinTableCellR pinColorGround"><label><input disabled type="radio" name="pins" value=""> 34 - Ground</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-35">GPIO19 - 35 <input id="pinTable-pin-35" type="radio" name="pins" value="35"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-36"><input id="pinTable-pin-36" type="radio" name="pins" value="36"> 36 - GPIO16</label></div>
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-35">GPIO19 - 35 <input id="pinTable-pin-35" type="radio" name="pins" value="19"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-36"><input id="pinTable-pin-36" type="radio" name="pins" value="16"> 36 - GPIO16</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-37">GPIO26 - 37 <input id="pinTable-pin-37" type="radio" name="pins" value="37"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-38"><input id="pinTable-pin-38" type="radio" name="pins" value="38"> 38 - GPIO20</label></div>
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-37">GPIO26 - 37 <input id="pinTable-pin-37" type="radio" name="pins" value="26"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-38"><input id="pinTable-pin-38" type="radio" name="pins" value="20"> 38 - GPIO20</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGround"><label>Ground - 39 <input disabled type="radio" name="pins" value=""></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-40"><input id="pinTable-pin-40" type="radio" name="pins" value="40"> 40 - GPIO21</label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-40"><input id="pinTable-pin-40" type="radio" name="pins" value="21"> 40 - GPIO21</label></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label> </label>
|
||||
<label> BCM GPIO</label>
|
||||
<input type="text" id="node-input-pin" style="width: 352px">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
@ -189,8 +189,12 @@
|
||||
"23":"16", "24":"18", "10":"19", "9":"21", "25":"22", "11":"23", "8":"24", "7":"26",
|
||||
"5":"29", "6":"31", "12":"32", "13":"33", "19":"35", "16":"36", "26":"37", "20":"38", "21":"40"
|
||||
};
|
||||
var pin2bcm = { '3':'2', '5':'3', '7':'4', '8':'14', '10':'15', '11':'17', '12':'18', '13':'27',
|
||||
'15':'22', '16':'23', '18':'24', '19':'10', '21':'9', '22':'25', '23':'11', '24':'8', '26':'7',
|
||||
'29':'5', '31':'6', '32':'12', '33':'13', '35':'19', '36':'16', '37':'26', '38':'20', '40':'21'
|
||||
}
|
||||
var pinsInUse = {};
|
||||
var validPinValues = Object.values(bcm2pin);
|
||||
|
||||
var isEnvVar = function (value) {
|
||||
var re = /^\${([0-9a-zA-Z_]+)}$/;
|
||||
var match = value.match(re);
|
||||
@ -205,17 +209,18 @@
|
||||
}
|
||||
}
|
||||
var validatePin = function (value) {
|
||||
return isEnvVar(value) || (isInt(value) && validPinValues.includes(value));
|
||||
return isEnvVar(value) || (isInt(value) && value>=0 && value<=45);
|
||||
};
|
||||
RED.nodes.registerType('rpi-gpio in',{
|
||||
category: 'Raspberry Pi',
|
||||
color:"#c6dbef",
|
||||
defaults: {
|
||||
name: { value:"" },
|
||||
pin: { value:"tri",required:true,validate:validatePin },
|
||||
pin: { value:"",required:true,validate:validatePin },
|
||||
intype: { value:"tri" },
|
||||
debounce: { value:"25" },
|
||||
read: { value:false }
|
||||
read: { value:false },
|
||||
bcm: { value:true }
|
||||
},
|
||||
inputs:0,
|
||||
outputs:1,
|
||||
@ -227,10 +232,12 @@
|
||||
else { return ""; }
|
||||
},
|
||||
label: function() {
|
||||
if (!this.bcm) { this.pin = pin2bcm[this.pin]; this.bcm = true; }
|
||||
var p = bcm2pin[this.pin];
|
||||
var suf = "";
|
||||
if (this.intype === "up") { suf = "↑ "}
|
||||
if (this.intype === "down") { suf = "↓ "}
|
||||
return this.name || "PIN: "+suf+this.pin ;
|
||||
if (this.intype === "up") { suf = " ↑"}
|
||||
if (this.intype === "down") { suf = " ↓"}
|
||||
return this.name || (p ? "PIN: "+p+suf : "GPIO: "+this.pin+suf) ;
|
||||
},
|
||||
labelStyle: function() {
|
||||
return this.name?"node_label_italic":"";
|
||||
@ -292,86 +299,86 @@
|
||||
<div class="pinTableCellR pinColorPower"><label><input disabled type="radio" name="pins" value=""> 2 - 5V Power</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-3">SDA1 - GPIO02 - 3 <input id="pinTable-pin-3" type="radio" name="pins" value="3"></label></div>
|
||||
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-3">SDA1 - GPIO02 - 3 <input id="pinTable-pin-3" type="radio" name="pins" value="2"></label></div>
|
||||
<div class="pinTableCellR pinColorPower"><label><input disabled type="radio" name="pins" value=""> 4 - 5V Power</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-5">SCL1 - GPIO03 - 5 <input id="pinTable-pin-5" type="radio" name="pins" value="5"></label></div>
|
||||
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-5">SCL1 - GPIO03 - 5 <input id="pinTable-pin-5" type="radio" name="pins" value="3"></label></div>
|
||||
<div class="pinTableCellR pinColorGround"><label><input disabled type="radio" name="pins" value=""> 6 - Ground</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-7">GPIO04 - 7 <input id="pinTable-pin-7" type="radio" name="pins" value="7"></label></div>
|
||||
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-8"><input id="pinTable-pin-8" type="radio" name="pins" value="8"> 8 - GPIO14 - TxD</label></div>
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-7">GPIO04 - 7 <input id="pinTable-pin-7" type="radio" name="pins" value="4"></label></div>
|
||||
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-8"><input id="pinTable-pin-8" type="radio" name="pins" value="14"> 8 - GPIO14 - TxD</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGround"><label>Ground - 9 <input disabled type="radio" name="pins" value=""></label></div>
|
||||
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-10"><input id="pinTable-pin-10" type="radio" name="pins" value="10"> 10 - GPIO15 - RxD</label></div>
|
||||
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-10"><input id="pinTable-pin-10" type="radio" name="pins" value="15"> 10 - GPIO15 - RxD</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-11">GPIO17 - 11 <input id="pinTable-pin-11" type="radio" name="pins" value="11"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-12"><input id="pinTable-pin-12" type="radio" name="pins" value="12"> 12 - GPIO18</label></div>
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-11">GPIO17 - 11 <input id="pinTable-pin-11" type="radio" name="pins" value="17"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-12"><input id="pinTable-pin-12" type="radio" name="pins" value="18"> 12 - GPIO18</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-13">GPIO27 - 13 <input id="pinTable-pin-13" type="radio" name="pins" value="13"></label></div>
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-13">GPIO27 - 13 <input id="pinTable-pin-13" type="radio" name="pins" value="27"></label></div>
|
||||
<div class="pinTableCellR pinColorGround"><label><input disabled type="radio" name="pins" value=""> 14 - Ground</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-15">GPIO22 - 15 <input id="pinTable-pin-15" type="radio" name="pins" value="15"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-16"><input id="pinTable-pin-16" type="radio" name="pins" value="16"> 16 - GPIO23</label></div>
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-15">GPIO22 - 15 <input id="pinTable-pin-15" type="radio" name="pins" value="22"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-16"><input id="pinTable-pin-16" type="radio" name="pins" value="23"> 16 - GPIO23</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorPower"><label>3.3V Power - 17 <input disabled type="radio" name="pins" value=""></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-18"><input id="pinTable-pin-18" type="radio" name="pins" value="18"> 18 - GPIO24</label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-18"><input id="pinTable-pin-18" type="radio" name="pins" value="24"> 18 - GPIO24</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-19">MOSI - GPIO10 - 19 <input id="pinTable-pin-19" type="radio" name="pins" value="19"></label></div>
|
||||
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-19">MOSI - GPIO10 - 19 <input id="pinTable-pin-19" type="radio" name="pins" value="10"></label></div>
|
||||
<div class="pinTableCellR pinColorGround"><label><input disabled type="radio" name="pins" value=""> 20 - Ground</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-21">MISO - GPIO09 - 21 <input id="pinTable-pin-21" type="radio" name="pins" value="21"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-22"><input id="pinTable-pin-22" type="radio" name="pins" value="22"> 22 - GPIO25</label></div>
|
||||
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-21">MISO - GPIO09 - 21 <input id="pinTable-pin-21" type="radio" name="pins" value="9"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-22"><input id="pinTable-pin-22" type="radio" name="pins" value="25"> 22 - GPIO25</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-23">SCLK - GPIO11 - 23 <input id="pinTable-pin-23" type="radio" name="pins" value="23"></label></div>
|
||||
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-24"><input id="pinTable-pin-24" type="radio" name="pins" value="24"> 24 - GPIO8 - CE0</label></div>
|
||||
<div class="pinTableCellL pinColorDual"><label for="pinTable-pin-23">SCLK - GPIO11 - 23 <input id="pinTable-pin-23" type="radio" name="pins" value="11"></label></div>
|
||||
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-24"><input id="pinTable-pin-24" type="radio" name="pins" value="8"> 24 - GPIO8 - CE0</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGround"><label>Ground - 25 <input disabled type="radio" name="pins" value=""></label></div>
|
||||
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-26"><input id="pinTable-pin-26" type="radio" name="pins" value="26"> 26 - GPIO7 - CE1</label></div>
|
||||
<div class="pinTableCellR pinColorDual"><label for="pinTable-pin-26"><input id="pinTable-pin-26" type="radio" name="pins" value="7"> 26 - GPIO7 - CE1</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorSD"><label>SD - 27 <input disabled type="radio" name="pins" value=""></label></div>
|
||||
<div class="pinTableCellR pinColorSD"><label><input disabled type="radio" name="pins" value=""> 28 - SC</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-29">GPIO05 - 29 <input id="pinTable-pin-29" type="radio" name="pins" value="29"></label></div>
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-29">GPIO05 - 29 <input id="pinTable-pin-29" type="radio" name="pins" value="5"></label></div>
|
||||
<div class="pinTableCellR pinColorGround"><label><input disabled type="radio" name="pins" value=""> 30 - Ground</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-31">GPIO06 - 31 <input id="pinTable-pin-31" type="radio" name="pins" value="31"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-32"><input id="pinTable-pin-32" type="radio" name="pins" value="32"> 32 - GPIO12</label></div>
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-31">GPIO06 - 31 <input id="pinTable-pin-31" type="radio" name="pins" value="6"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-32"><input id="pinTable-pin-32" type="radio" name="pins" value="12"> 32 - GPIO12</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-33">GPIO13 - 33 <input id="pinTable-pin-33" type="radio" name="pins" value="33"></label></div>
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-33">GPIO13 - 33 <input id="pinTable-pin-33" type="radio" name="pins" value="13"></label></div>
|
||||
<div class="pinTableCellR pinColorGround"><label><input disabled type="radio" name="pins" value=""> 34 - Ground</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-35">GPIO19 - 35 <input id="pinTable-pin-35" type="radio" name="pins" value="35"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-36"><input id="pinTable-pin-36" type="radio" name="pins" value="36"> 36 - GPIO16</label></div>
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-35">GPIO19 - 35 <input id="pinTable-pin-35" type="radio" name="pins" value="19"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-36"><input id="pinTable-pin-36" type="radio" name="pins" value="16"> 36 - GPIO16</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-37">GPIO26 - 37 <input id="pinTable-pin-37" type="radio" name="pins" value="37"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-38"><input id="pinTable-pin-38" type="radio" name="pins" value="38"> 38 - GPIO20</label></div>
|
||||
<div class="pinTableCellL pinColorGPIO"><label for="pinTable-pin-37">GPIO26 - 37 <input id="pinTable-pin-37" type="radio" name="pins" value="26"></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-38"><input id="pinTable-pin-38" type="radio" name="pins" value="20"> 38 - GPIO20</label></div>
|
||||
</div>
|
||||
<div class="pinTableRow">
|
||||
<div class="pinTableCellL pinColorGround"><label>Ground - 39 <input disabled type="radio" name="pins" value=""></label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-40"><input id="pinTable-pin-40" type="radio" name="pins" value="40"> 40 - GPIO21</label></div>
|
||||
<div class="pinTableCellR pinColorGPIO"><label for="pinTable-pin-40"><input id="pinTable-pin-40" type="radio" name="pins" value="21"> 40 - GPIO21</label></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label> </label>
|
||||
<label> BCM GPIO</label>
|
||||
<input type="text" id="node-input-pin" style="width: 352px">
|
||||
</div>
|
||||
<div class="form-row" id="node-set-pwm">
|
||||
@ -412,6 +419,10 @@
|
||||
"23":"16", "24":"18", "10":"19", "9":"21", "25":"22", "11":"23", "8":"24", "7":"26",
|
||||
"5":"29", "6":"31", "12":"32", "13":"33", "19":"35", "16":"36", "26":"37", "20":"38", "21":"40"
|
||||
};
|
||||
var pin2bcm = { '3':'2', '5':'3', '7':'4', '8':'14', '10':'15', '11':'17', '12':'18', '13':'27',
|
||||
'15':'22', '16':'23', '18':'24', '19':'10', '21':'9', '22':'25', '23':'11', '24':'8', '26':'7',
|
||||
'29':'5', '31':'6', '32':'12', '33':'13', '35':'19', '36':'16', '37':'26', '38':'20', '40':'21'
|
||||
}
|
||||
var pinsInUse = {};
|
||||
var validPinValues = Object.values(bcm2pin);
|
||||
var isEnvVar = function (value) {
|
||||
@ -428,7 +439,7 @@
|
||||
}
|
||||
}
|
||||
var validatePin = function (value) {
|
||||
return isEnvVar(value) || (isInt(value) && validPinValues.includes(value));
|
||||
return isEnvVar(value) || (isInt(value) && value>=0 && value<=45);
|
||||
};
|
||||
RED.nodes.registerType('rpi-gpio out',{
|
||||
category: 'Raspberry Pi',
|
||||
@ -438,8 +449,9 @@
|
||||
pin: { value:"",required:true,validate:validatePin },
|
||||
set: { value:"" },
|
||||
level: { value:"0" },
|
||||
freq: {value:""},
|
||||
out: { value:"out" }
|
||||
freq: { value:""},
|
||||
out: { value:"out" },
|
||||
bcm: { value:true }
|
||||
},
|
||||
inputs:1,
|
||||
outputs:0,
|
||||
@ -452,12 +464,15 @@
|
||||
},
|
||||
align: "right",
|
||||
label: function() {
|
||||
if (this.out === "pwm") { return this.name || "PWM: "+this.pin; }
|
||||
else if (this.out === "ser") { return this.name || "Servo: "+this.pin; }
|
||||
if (!this.bcm) { this.pin = pin2bcm[this.pin]; this.bcm = true; }
|
||||
var p = bcm2pin[this.pin];
|
||||
var t = p ? "PIN: "+p : "GPIO: "+this.pin;
|
||||
if (this.out === "pwm") { return this.name || "PWM: "+p; }
|
||||
else if (this.out === "ser") { return this.name || "Servo: "+p; }
|
||||
else {
|
||||
var suf = "";
|
||||
if (this.set == true) { suf = (this.level === "1") ? " ¹" : " ₀"; }
|
||||
return this.name||"PIN: "+ this.pin + suf ;
|
||||
return this.name|| t + suf ;
|
||||
}
|
||||
},
|
||||
labelStyle: function() {
|
||||
|
@ -22,10 +22,15 @@ module.exports = function(RED) {
|
||||
var pinsInUse = {};
|
||||
var pinTypes = {"out":RED._("rpi-gpio.types.digout"), "tri":RED._("rpi-gpio.types.input"), "up":RED._("rpi-gpio.types.pullup"), "down":RED._("rpi-gpio.types.pulldown"), "pwm":RED._("rpi-gpio.types.pwmout")};
|
||||
|
||||
var pin2bcm = { '3':'2', '5':'3', '7':'4', '8':'14', '10':'15', '11':'17', '12':'18', '13':'27',
|
||||
'15':'22', '16':'23', '18':'24', '19':'10', '21':'9', '22':'25', '23':'11', '24':'8', '26':'7',
|
||||
'29':'5', '31':'6', '32':'12', '33':'13', '35':'19', '36':'16', '37':'26', '38':'20', '40':'21'
|
||||
}
|
||||
|
||||
function GPIOInNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.buttonState = -1;
|
||||
this.pin = n.pin;
|
||||
this.pin = (n.bcm === true) ? n.pin : pin2bcm[n.pin];
|
||||
this.intype = n.intype;
|
||||
this.read = n.read || false;
|
||||
this.debounce = Number(n.debounce || 25);
|
||||
@ -51,7 +56,7 @@ module.exports = function(RED) {
|
||||
for (var i = 0; i < d.length; i++) {
|
||||
if (d[i] === '') { return; }
|
||||
if (node.running && node.buttonState !== -1 && !isNaN(Number(d[i])) && node.buttonState !== d[i]) {
|
||||
node.send({ topic:"pi/"+node.pin, payload:Number(d[i]) });
|
||||
node.send({ topic:"gpio/"+node.pin, payload:Number(d[i]) });
|
||||
}
|
||||
node.buttonState = d[i];
|
||||
node.status({fill:"green",shape:"dot",text:d[i]});
|
||||
@ -92,7 +97,7 @@ module.exports = function(RED) {
|
||||
if (node.intype == "up") { val = 1; }
|
||||
if (node.intype == "down") { val = 0; }
|
||||
setTimeout(function() {
|
||||
node.send({ topic:"pi/"+node.pin, payload:val });
|
||||
node.send({ topic:"gpio/"+node.pin, payload:val });
|
||||
node.status({fill:"grey",shape:"dot",text:RED._("rpi-gpio.status.na",{value:val})});
|
||||
},250);
|
||||
}
|
||||
@ -113,7 +118,7 @@ module.exports = function(RED) {
|
||||
|
||||
function GPIOOutNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.pin = n.pin;
|
||||
this.pin = (n.bcm === true) ? n.pin : pin2bcm[n.pin];
|
||||
this.set = n.set || false;
|
||||
this.level = n.level || 0;
|
||||
this.freq = n.freq || 100;
|
||||
|
@ -21,7 +21,7 @@ command in your Node-RED user directory - typically `~/.node-red`
|
||||
The python library may also work with other distros running on a Pi (like Ubuntu or Debian) - you will need to install the PIGPIO package and run the following commands in order to gain full access to the GPIO pins as this ability is not part of the default distro. This is NOT necessary on Raspbian.
|
||||
|
||||
sudo apt-get install python-pip python-dev
|
||||
sudo pip install RPi.GPIO
|
||||
sudo pip install RPi.GPIO
|
||||
sudo addgroup gpio
|
||||
sudo chown root:gpio /dev/gpiomem
|
||||
sudo adduser $USER gpio
|
||||
@ -30,7 +30,7 @@ The python library may also work with other distros running on a Pi (like Ubuntu
|
||||
|
||||
## Usage
|
||||
|
||||
**Note:** the pin numbers refer the physical pin numbers on connector P1 as they are easier to locate.
|
||||
**Note:** the diagram in the configuration shows pin numbers - the BCM GPIO field allows you to enter the GPIO number directly (this allows you to use the node for other devices that have other BCM GPIO like the Pi Compute modules.)
|
||||
|
||||
### Input node
|
||||
|
||||
|
@ -1,73 +1,75 @@
|
||||
"rpi-gpio" : {
|
||||
"label" : {
|
||||
"gpiopin" : "GPIO",
|
||||
"selectpin" : "Auswahlstift",
|
||||
"resistor" : "Widerstand?",
|
||||
"readinitial" : "Anfangsstatus des Pins bei Implementierung/Neustart lesen?",
|
||||
"type" : "Typ",
|
||||
"initpin" : "Pin-Status initialisieren?",
|
||||
"debounce" : "Debounce",
|
||||
"freq" : "Frequenz",
|
||||
"button" : "Knopf",
|
||||
"pimouse" : "Pi-Maus",
|
||||
"pikeyboard" : "Pi-Tastatur",
|
||||
"left" : "Links",
|
||||
"right" : "Rechts",
|
||||
"middle" : "Mitte"
|
||||
},
|
||||
"resistor" : {
|
||||
"none" : "keine",
|
||||
"pullup" : "pullup",
|
||||
"pulldown" : "Pulldown"
|
||||
},
|
||||
"digout" : "Digitale Ausgabe",
|
||||
"pwmout" : "PWM-Ausgabe",
|
||||
"servo" : "Servo-Ausgabe",
|
||||
"initpin0" : "Anfangsstand des Pin-Niedrig (0)",
|
||||
"initpin1" : "Anfangsebene von Pin-High (1)",
|
||||
"left" : "links",
|
||||
"right" : "rechts",
|
||||
"middle" : "Mitte",
|
||||
"any" : "beliebig",
|
||||
"pinname" : "Pin",
|
||||
"alreadyuse" : "bereits im Gebrauch",
|
||||
"alreadyset" : "bereits festgelegt als",
|
||||
"tip" : {
|
||||
"pin" : "<b> Verwender Pins </b>: ",
|
||||
"in" : "Tipp: Es wird nur die digitale Eingabe unterstützt. Die Eingabe muss 0 oder 1 sein.",
|
||||
"dig" : "Tipp: Für die digitale Ausgabe muss der Wert 0 oder 1 sein.",
|
||||
"pwm" : "Tipp: Für die PWM-Ausgabe muss der Wert zwischen 0 und 100 liegen; die Einstellung der Hochfrequenz kann mehr CPU beanspruchen als erwartet.",
|
||||
"ser" : "<b> Tipp </b>: Für die Servo-Ausgabe muss ein Wert zwischen 0 und 100 eingegeben werden. 50 ist das Zentrum."
|
||||
},
|
||||
"types" : {
|
||||
"digout" : "digitale Ausgabe",
|
||||
"input" : "Eingabe",
|
||||
"pullup" : "Eingabe mit Pull-up",
|
||||
"pulldown" : "Eingabe mit Pull-down",
|
||||
"pwmout" : "PWM-Ausgabe",
|
||||
"servo" : "Servo-Ausgabe"
|
||||
},
|
||||
"status" : {
|
||||
"stopped" : "Gestoppt",
|
||||
"closed" : "geschlossen",
|
||||
"not-running" : "nicht aktiv",
|
||||
"not-available" : "nicht verfügbar",
|
||||
"na" : "N/A: __Wert__",
|
||||
"ok": "OK"
|
||||
},
|
||||
"errors" : {
|
||||
"ignorenode" : "Raspberry Pi-spezifische Nodes inaktiv",
|
||||
"version" : "Abrufen der Version von Pi fehlgeschlagen",
|
||||
"sawpitype" : "Saw-Pi-Typ",
|
||||
"libnotfound" : "Pi RPi.GPIO-Python-Bibliothek nicht gefunden",
|
||||
"alreadyset" : "GPIO-Stift __pin__ ist bereits als Typ festgelegt: __type__",
|
||||
"invalidpin" : "Ungültiger GPIO-Pin",
|
||||
"invalidinput" : "Ungültige Eingabe",
|
||||
"needtobeexecutable" : "__command__ muss ausführbar sein",
|
||||
"mustbeexecutable" : "nrgpio muss ausführbar sein",
|
||||
"commandnotfound" : "Befehl 'nrgpio' nicht gefunden",
|
||||
"commandnotexecutable" : "nrgpio-Befehl nicht ausführbar",
|
||||
"error" : "Fehler: __error__",
|
||||
"pythoncommandnotfound" : "Befehl 'nrgpio python' nicht aktiv"
|
||||
{
|
||||
"rpi-gpio": {
|
||||
"label": {
|
||||
"gpiopin": "GPIO",
|
||||
"selectpin": "Pinauswahl",
|
||||
"resistor": "Widerstand",
|
||||
"readinitial": "Initalzustand des Pins bei Übernahme/Neustart lesen",
|
||||
"type": "Typ",
|
||||
"initpin": "Pin-Zustand initialisieren",
|
||||
"debounce": "Entprellung",
|
||||
"freq": "Frequenz",
|
||||
"button": "Taste",
|
||||
"pimouse": "Pi-Maus",
|
||||
"pikeyboard": "Pi-Tastatur",
|
||||
"left": "Links",
|
||||
"right": "Rechts",
|
||||
"middle": "Mitte"
|
||||
},
|
||||
"resistor": {
|
||||
"none": "Kein",
|
||||
"pullup": "Pull-Up",
|
||||
"pulldown": "Pull-Down"
|
||||
},
|
||||
"digout": "Digitaler Ausgang",
|
||||
"pwmout": "PWM-Ausgang",
|
||||
"servo": "Servo-Ausgang",
|
||||
"initpin0": "Pin-Initalzustand low (0)",
|
||||
"initpin1": "Pin-Initalzustand high (1)",
|
||||
"left": "Links",
|
||||
"right": "Rechts",
|
||||
"middle": "Mitte",
|
||||
"any": "Beliebig",
|
||||
"pinname": "Pin",
|
||||
"alreadyuse": "bereits im Gebrauch",
|
||||
"alreadyset": "bereits festgelegt als",
|
||||
"tip": {
|
||||
"pin": "<b>Verwendete Pins:</b> ",
|
||||
"in": "<b>Tipp:</b> Es werden nur die digitale Eingänge unterstützt. Der Eingang muss 0 oder 1 sein",
|
||||
"dig": "<b>Tipp:</b> Für den digitalen Ausgang muss der Node-Eingangswert 0 oder 1 sein",
|
||||
"pwm": "<b>Tipp:</b> Für die PWM-Ausgabe muss der Node-Eingangswert zwischen 0 und 100 liegen. Hohen Frequenzen können die CPU mehr beanspruchen als erwartet.",
|
||||
"ser": "<b>Tipp:</b> Für die Servo-Ausgabe muss der Node-Eingangswert zwischen 0 und 100 eingegeben werden. 50 ist die Mitte."
|
||||
},
|
||||
"types": {
|
||||
"digout": "Digitaler Ausgang",
|
||||
"input": "Eingang",
|
||||
"pullup": "Eingang mit Pull-Up",
|
||||
"pulldown": "Eingabe mit Pull-Down",
|
||||
"pwmout": "PWM-Ausgang",
|
||||
"servo": "Servo-Ausgang"
|
||||
},
|
||||
"status": {
|
||||
"stopped": "Gestoppt",
|
||||
"closed": "Geschlossen",
|
||||
"not-running": "Nicht aktiv",
|
||||
"not-available": "Nicht verfügbar",
|
||||
"na": "Nicht anwendbar: __Wert__",
|
||||
"ok": "OK"
|
||||
},
|
||||
"errors": {
|
||||
"ignorenode": "Raspberry-Pi-spezifische Nodes inaktiv gesetzt",
|
||||
"version": "Abrufen der Version vom Pi fehlgeschlagen",
|
||||
"sawpitype": "Saw-Pi-Typ",
|
||||
"libnotfound": "RPi.GPIO-Python-Bibliothek nicht gefunden",
|
||||
"alreadyset": "GPIO-Pin __pin__ ist bereits festgelegt als Typ: __type__",
|
||||
"invalidpin": "Ungültiger GPIO-Pin",
|
||||
"invalidinput": "Ungültige Eingabe",
|
||||
"needtobeexecutable": "__command__ muss ausführbar sein",
|
||||
"mustbeexecutable": "nrgpio muss ausführbar sein",
|
||||
"commandnotfound": "nrgpio-Befehl nicht gefunden",
|
||||
"commandnotexecutable": "nrgpio-Befehl nicht ausführbar",
|
||||
"error": "Fehler: __error__",
|
||||
"pythoncommandnotfound": "nrgpio-Python-Befehl nicht aktiv"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,18 +1,3 @@
|
||||
<!--
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
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/html" data-help-name="rpi-gpio in">
|
||||
<p>Raspberry Pi input node. Generates a <code>msg.payload</code> with either a
|
||||
@ -22,7 +7,7 @@
|
||||
<dt>payload <span class="property-type">number</span></dt>
|
||||
<dd>the payload will be a 1 or a 0.</dd>
|
||||
<dt>topic <span class="property-type">string</span></dt>
|
||||
<dd>the topic will be set to <code>pi/{the pin number}</code>.</dd>
|
||||
<dd>the topic will be set to <code>gpio/{the bcm spio number}</code>.</dd>
|
||||
</dl>
|
||||
<h3>Details</h3>
|
||||
<p>You may also enable the input pullup resistor or the pulldown resistor.</p>
|
||||
|
@ -21,7 +21,7 @@
|
||||
<dt>payload <span class="property-type">数値</span></dt>
|
||||
<dd>ペイロードには、0 または 1 が設定されます。</dd>
|
||||
<dt>topic <span class="property-type">文字列</span></dt>
|
||||
<dd>トピックには、<code>pi/{ピン番号}</code>が設定されます。</dd>
|
||||
<dd>トピックには、<code>gpio/{ピン番号}</code>が設定されます。</dd>
|
||||
</dl>
|
||||
<h3>詳細</h3>
|
||||
<p>入力のプルアップ抵抗またはプルダウン抵抗を有効にすることもできます。</p>
|
||||
|
@ -21,7 +21,7 @@
|
||||
<dt>payload <span class="property-type">수치</span></dt>
|
||||
<dd>페이로드에는, 0 또는 1이 설정됩니다.</dd>
|
||||
<dt>topic <span class="property-type">문자열</span></dt>
|
||||
<dd>토픽에는, <code>pi/{핀 번호}</code>가 설정됩니다.</dd>
|
||||
<dd>토픽에는, <code>gpio/{핀 번호}</code>가 설정됩니다.</dd>
|
||||
</dl>
|
||||
<h3>상세</h3>
|
||||
<p>입력의 풀 업 저항 또는, 풀 다운 저항을 유효화 할 수도 있습니다.</p>
|
||||
|
@ -31,7 +31,7 @@ bounce = 25
|
||||
if len(sys.argv) > 2:
|
||||
cmd = sys.argv[1].lower()
|
||||
pin = int(sys.argv[2])
|
||||
GPIO.setmode(GPIO.BOARD)
|
||||
GPIO.setmode(GPIO.BCM)
|
||||
GPIO.setwarnings(False)
|
||||
|
||||
if cmd == "pwm":
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red-node-pi-gpio",
|
||||
"version": "1.2.3",
|
||||
"version": "2.0.0-beta2",
|
||||
"description": "The basic Node-RED node for Pi GPIO",
|
||||
"dependencies" : {
|
||||
},
|
||||
|
15
hardware/PiLcd/locales/de/pilcd.html
Normal file
15
hardware/PiLcd/locales/de/pilcd.html
Normal file
@ -0,0 +1,15 @@
|
||||
<script type="text/html" data-help-name="rpi-lcd">
|
||||
<p>Raspberry-Pi-Ausgabe auf ein HD44780-artiges LCD mit üblicherweise 1, 2, oder 4 Schriftzeilen.</p>
|
||||
<h3>Eingangsdaten</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload<span class="property-type">string</span></dt>
|
||||
<dd>Anzuzeigender Text</dd>
|
||||
</dl>
|
||||
<h3>Details</h3>
|
||||
<p>Der Node erwartet einen <code>msg.payload</code> mit der anzuzeigenden Text-Zeichenfolge (string).</p>
|
||||
<p>Die Texte für die zweite Zeile des Displays müssen mit <code>2:</code> beginnen, die dritte Zeile mit <code>3:</code> und die vierte mit <code>4:</code></p>
|
||||
<p>Um das Display zu leeren ist der Text <code>clr:</code> zu senden.</p>
|
||||
<p>Es muss selbst darauf geachtet werden, dass die Textlängen in das Displayfenster hineinpassen.</p>
|
||||
<p>Zum Betrieb wird die RPi.GPIO-Python-Bibliothek Version 0.5.8 (oder besser) benötigt.</p>
|
||||
<p><b>Hinweis</b>: Die Pinnummern beziehen sich auf die physischen Pinnummern des Steckverbinders P1, wodurch sie einfacher zu lokalisieren sind.</p>
|
||||
</script>
|
19
hardware/PiLcd/locales/de/pilcd.json
Normal file
19
hardware/PiLcd/locales/de/pilcd.json
Normal file
@ -0,0 +1,19 @@
|
||||
{
|
||||
"pilcd": {
|
||||
"label": {
|
||||
"pins": "Pins"
|
||||
},
|
||||
"tip": {
|
||||
"tip": "<b>Tipp</b>: Bei Pins muss eine Komma-getrennte Liste von 6 GPIO-Anschlusspin-Nummern eingetragen werden, die mit RS, E, D4, D5, D6 und D7 des LCD verbunden sind."
|
||||
},
|
||||
"status": {
|
||||
"not-available": "Nicht verfügbar",
|
||||
"na": "Nicht anwendbar: __value__"
|
||||
},
|
||||
"errors": {
|
||||
"ignorenode": "Raspberry-Pi-spezifische Nodes inaktiv gesetzt",
|
||||
"libnotfound": "RPi.GPIO-Python-Bibliothek nicht gefunden",
|
||||
"needtobeexecutable": "__command__ muss ausführbar sein"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,5 +1,11 @@
|
||||
<script type="text/html" data-help-name="rpi-lcd">
|
||||
<p>Raspberry Pi output to a HD44780 style LCD. Usually 1, 2, or 4 lines of characters.</p>
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload<span class="property-type">string</span></dt>
|
||||
<dd>Text to be displayed</dd>
|
||||
</dl>
|
||||
<h3>Details</h3>
|
||||
<p>Expects a <code>msg.payload</code> with a string in it.</p>
|
||||
<p>Strings for the second line of the display must start <b>2:</b> - the third start <b>3:</b> - and the fourth <b>4:</b></p>
|
||||
<p>To clear the display send the string <b>clr:</b></p>
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name" : "node-red-node-pilcd",
|
||||
"version" : "0.1.0",
|
||||
"version" : "0.2.0",
|
||||
"description" : "A Node-RED node for Raspberry Pi to write to HD44780 style LCD panels.",
|
||||
"dependencies" : {
|
||||
},
|
||||
|
38
hardware/pigpiod/locales/de/pi-gpiod.html
Normal file
38
hardware/pigpiod/locales/de/pi-gpiod.html
Normal file
@ -0,0 +1,38 @@
|
||||
|
||||
<script type="text/html" data-help-name="pi-gpiod in">
|
||||
<p>Raspberry-Pi-Eingangs-Node.
|
||||
Generiert eine <code>msg.payload</code> mit einem Wert von 0 oder 1 in Abhängigkeit vom Status des Eingangspins.
|
||||
<a href="http://abyz.me.uk/rpi/pigpio/index.html" target="_new">pi-gpiod</a>-Daemon erforderlich.</p>
|
||||
<h3>Ausgangsdaten</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload<span class="property-type">number</span></dt>
|
||||
<dd>Pinstatus (0 or 1)</dd>
|
||||
<dt>topic<span class="property-type">string</span></dt>
|
||||
<dd>Pinnummer <code>pi/{the pin number}</code></dd>
|
||||
</dl>
|
||||
<h3>Details</h3>
|
||||
<p>Es können auch die Pullup- (↑) oder Pulldown- (↓) Eingangs-Widerstände aktiviert werden.</p>
|
||||
<p>Bei Benutzung mit Docker auf dem Pi sollte die Standard-Host-IP <code>172.17.0.1</code> sein.
|
||||
Es muss ebenso <code>sudo pigpiod</code> auf dem Host gestartet werden.</p>
|
||||
<p><b>Hinweis</b>: Die Pinnummern beziehen sich auf die physischen Pinnummern des Steckverbinders P1, wodurch sie einfacher zu lokalisieren sind.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="pi-gpiod out">
|
||||
<p>Raspberry-Pi-Ausgangs-Node.
|
||||
Digital-, PWM- oder Servo-Modus unterstützt.
|
||||
<a href="http://abyz.me.uk/rpi/pigpio/index.html" target="_new">pi-gpiod</a>-Daemon erforderlich.</p>
|
||||
<h3>Eingangsdaten</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload<span class="property-type">number | string</span></dt>
|
||||
<dd>0,1 (Digital), 0-100 (PWM, Servo)</dd>
|
||||
</dl>
|
||||
<h3>Details</h3>
|
||||
<p>Im digitalen Modus erwartet der Node eine <code>msg.payload</code> von entweder 0 oder 1 (oder false oder true)
|
||||
und setzt den ausgewählten physischen Pin entsprechend dem übergebenen Wert entweder auf low oder high.</p>
|
||||
<p>Der Anfangswert des Pins kann bei der Übernahme (Deploy) auf 0 oder 1 gesetzt werden.</p>
|
||||
<p>Im PWM-Modus erwartet der Node einen Eingangszahlenwert von 0 bis 100. Es kann auch eine Gleitkommazahl sein.</p>
|
||||
<p>Im Servo-Modus kann die Ausgabe gestoppt werden, indem ein <code>msg.payload</code> von <code>null</code> oder <code>""</code> übergeben wird.</p>
|
||||
<p>Bei Benutzung mit Docker auf dem Pi sollte die Standard-Host-IP <code>172.17.0.1</code> sein.
|
||||
Es muss ebenso <code>sudo pigpiod</code> auf dem Host gestartet werden.</p>
|
||||
<p><b>Hinweis</b>: Die Pinnummern beziehen sich auf die physischen Pinnummern des Steckverbinders P1, wodurch sie einfacher zu lokalisieren sind.</p>
|
||||
</script>
|
59
hardware/pigpiod/locales/de/pi-gpiod.json
Normal file
59
hardware/pigpiod/locales/de/pi-gpiod.json
Normal file
@ -0,0 +1,59 @@
|
||||
{
|
||||
"pi-gpiod": {
|
||||
"label": {
|
||||
"gpiopin": "GPIO",
|
||||
"selectpin": "Pin-Auswahl",
|
||||
"host": "Host",
|
||||
"resistor": "Widerstand",
|
||||
"readinitial": "Initalzustand bei Übernahme/Neustart lesen",
|
||||
"type": "Typ",
|
||||
"initpin": "Pin-Zustand initialisieren",
|
||||
"debounce": "Entprellung",
|
||||
"limits": "Limits",
|
||||
"min": "min.",
|
||||
"max": "max.",
|
||||
"freq": "Frequenz"
|
||||
},
|
||||
"place": {
|
||||
"host": "Lokale oder entfernte IP",
|
||||
"port": "Port"
|
||||
},
|
||||
"resistor": {
|
||||
"none": "Kein",
|
||||
"pullup": "Pull-Up",
|
||||
"pulldown": "Pull-Down"
|
||||
},
|
||||
"digout": "Digitaler Ausgang",
|
||||
"pwmout": "PWM-Ausgang",
|
||||
"servo": "Servo-Ausgang",
|
||||
"initpin0": "Initalzustand low (0)",
|
||||
"initpin1": "Initalzustand high (1)",
|
||||
"pinname": "Pin",
|
||||
"tip": {
|
||||
"pin": "<b>Pins in Verwendung</b>: ",
|
||||
"in": "Nur digitaler Eingang unterstützt - Eingangszustand muss 0 oder 1 sein",
|
||||
"dig": "Digitaler Ausgang - Node-Eingangswert muss 0 oder 1 sein",
|
||||
"pwm": "PWM-Ausgang - Node-Eingangswert muss zwischen 0 und 100 sein",
|
||||
"ser": "Servo-Ausgang - Node-Eingangswert muss zwischen 0 und 100 sein. 50 ist die Mitte.<br/>Min. muss mindestens 500 µs und Max. muss 2500 µs oder weniger sein.",
|
||||
"dual": "Blaue Pins sind mehrfach verwendbar. Es ist sicherzustellen, dass keine andere Verwendung aktiviert ist, um sie als GPIO zu verwenden."
|
||||
},
|
||||
"types": {
|
||||
"digout": "Digitaler Ausgang",
|
||||
"input": "Eingang",
|
||||
"pullup": "Eingang mit Pull-Up",
|
||||
"pulldown": "Eingang mit Pull-Down",
|
||||
"pwmout": "PWM-Ausgang",
|
||||
"servo": "Servo-Ausgang"
|
||||
},
|
||||
"status": {
|
||||
"stopped": "Gestoppt",
|
||||
"closed": "Geschlossen",
|
||||
"not-running": "Nicht aktiv"
|
||||
},
|
||||
"errors": {
|
||||
"invalidpin": "Ungültiger GPIO-Pin",
|
||||
"invalidinput": "Ungültige Eingabe",
|
||||
"error": "FEHLER: __error__"
|
||||
}
|
||||
}
|
||||
}
|
36
hardware/pigpiod/locales/en-US/pi-gpiod.html
Normal file
36
hardware/pigpiod/locales/en-US/pi-gpiod.html
Normal file
@ -0,0 +1,36 @@
|
||||
|
||||
<script type="text/html" data-help-name="pi-gpiod in">
|
||||
<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.
|
||||
Requires the <a href="http://abyz.me.uk/rpi/pigpio/index.html" target="_new">pi-gpiod</a>
|
||||
daemon to be running on the host computer in order to work.</p>
|
||||
<h3>Outputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload<span class="property-type">number</span></dt>
|
||||
<dd>the level of the pin (0 or 1)</dd>
|
||||
<dt>topic<span class="property-type">string</span></dt>
|
||||
<dd>pin number <code>pi/{the pin number}</code></dd>
|
||||
</dl>
|
||||
<h3>Details</h3>
|
||||
<p>You may also enable the input pullup resistor ↑ or the pulldown resistor ↓.</p>
|
||||
<p>If using with Docker on Pi then the default Host IP should be <code>172.17.0.1</code>. You will also need to run <code>sudo pigpiod</code> on the host.</p>
|
||||
<p><b>Note:</b> the pin numbers refer the physical pin numbers on connector P1 as they are easier to locate.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="pi-gpiod out">
|
||||
<p>Raspberry Pi output node. Can be used in Digital, PWM or Servo modes. Requires the
|
||||
<a href="http://abyz.me.uk/rpi/pigpio/index.html" target="_new">pi-gpiod</a> daemon to be running in order to work.</p>
|
||||
<h3>Inputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>payload<span class="property-type">number | string</span></dt>
|
||||
<dd>0,1 (Digital), 0-100 (PWM, Servo)</dd>
|
||||
</dl>
|
||||
<h3>Details</h3>
|
||||
<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 and Servo modes, the input value should be a number 0 - 100, and can be floating point.</p>
|
||||
<p>In Servo mode you can stop the output by sending a <code>msg.payload</code> of <code>null</code> or <code>""</code>.</p>
|
||||
<p>If using with Docker on Pi then the default Host IP should be <code>172.17.0.1</code>. You will also need to run <code>sudo pigpiod</code> on the host.</p>
|
||||
<p><b>Note</b>: the pin numbers refer the physical pin numbers on connector P1 as they are easier to locate.</p>
|
||||
</script>
|
@ -11,7 +11,8 @@
|
||||
"debounce": "Debounce",
|
||||
"limits": "Limits",
|
||||
"min": "min",
|
||||
"max": "max"
|
||||
"max": "max",
|
||||
"freq": "Frequency"
|
||||
},
|
||||
"place": {
|
||||
"host": "local or remote ip",
|
||||
@ -33,7 +34,8 @@
|
||||
"in": "Only Digital Input is supported - input must be 0 or 1.",
|
||||
"dig": "Digital output - input must be 0 or 1.",
|
||||
"pwm": "PWM output - input must be between 0 to 100.",
|
||||
"ser": "Servo output - input must be between 0 to 100. 50 is centre.<br/>Min must be 500uS or more, Max must be 2500uS or less."
|
||||
"ser": "Servo output - input must be between 0 to 100. 50 is centre.<br/>min. must be 500 us or more, max. must be 2500 us or less.",
|
||||
"dual": "Pins marked in blue are dual use. Make sure they are not enabled for their other use before using as GPIO."
|
||||
},
|
||||
"types": {
|
||||
"digout": "digital output",
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red-node-pi-gpiod",
|
||||
"version": "0.2.0",
|
||||
"version": "0.4.0",
|
||||
"description": "A node-red node for PiGPIOd",
|
||||
"dependencies" : {
|
||||
"js-pigpio": "*"
|
||||
|
@ -164,26 +164,9 @@
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
|
||||
</div>
|
||||
<div class="form-tips"><span data-i18n="[html]pi-gpiod.tip.in"></span></div>
|
||||
<div class="form-tips" id="pin-tip">Pins marked in blue are dual use. Make sure they are not enabled for
|
||||
their other use before using as GPIO.</div>
|
||||
<div class="form-tips" id="pin-tip"><span data-i18n="[html]pi-gpiod.tip.dual"></span></div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="pi-gpiod in">
|
||||
<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.
|
||||
Requires the <a href="http://abyz.me.uk/rpi/pigpio/index.html" target="_new">pi-gpiod</a>
|
||||
daemon to be running on the host computer in order to work.</p>
|
||||
<p><b>Outputs</b>
|
||||
<ul>
|
||||
<li><code>msg.payload</code> - <i>number</i> - the level of the pin (0 or 1).</li>
|
||||
<li><code>msg.topic</code> - <i>string</i> - pi/{the pin number}</li>
|
||||
</ul>
|
||||
<p><b>Details</b></p>
|
||||
<p>You may also enable the input pullup resistor ↑ or the pulldown resistor ↓.</p>
|
||||
<p>If using with Docker on Pi then the default Host IP should be <code>172.17.0.1</code>. You will also need to run <code>sudo pigpiod</code> on the host.</p>
|
||||
<p><b>Note:</b> the pin numbers refer the physical pin numbers on connector P1 as they are easier to locate.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
var bcm2pin = {
|
||||
"2":"3", "3":"5", "4":"7", "14":"8", "15":"10", "17":"11", "18":"12", "27":"13", "22":"15",
|
||||
@ -383,9 +366,9 @@
|
||||
</div>
|
||||
<div class="form-row" id="node-set-minimax">
|
||||
<label> <span data-i18n="pi-gpiod.label.limits"></label>
|
||||
<span data-i18n="pi-gpiod.label.min"></span> <input type="text" id="node-input-sermin" style="width:70px;"> uS
|
||||
<span data-i18n="pi-gpiod.label.min"></span> <input type="text" id="node-input-sermin" style="width:70px;"> us
|
||||
|
||||
<span data-i18n="pi-gpiod.label.max"></span> <input type="text" id="node-input-sermax" style="width:70px;"> uS
|
||||
<span data-i18n="pi-gpiod.label.max"></span> <input type="text" id="node-input-sermax" style="width:70px;"> us
|
||||
</div>
|
||||
<div class="form-row" id="node-set-tick">
|
||||
<label> </label>
|
||||
@ -400,8 +383,8 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row" id="node-set-freq">
|
||||
<label for="node-input-freq"> <span data-i18n="rpi-gpio.label.freq"></span></label>
|
||||
Frequency: <select id="node-input-freq" style="width:80px;">
|
||||
<label for="node-input-freq"> <span data-i18n="pi-gpiod.label.freq"></span></label>
|
||||
<select id="node-input-freq" style="width:80px;">
|
||||
<option value="8000">8000</option>
|
||||
<option value="4000">4000</option>
|
||||
<option value="2000">2000</option>
|
||||
@ -433,25 +416,7 @@
|
||||
<div class="form-tips" id="dig-tip"><span data-i18n="[html]pi-gpiod.tip.dig"></span></div>
|
||||
<div class="form-tips" id="pwm-tip"><span data-i18n="[html]pi-gpiod.tip.pwm"></span></div>
|
||||
<div class="form-tips" id="ser-tip"><span data-i18n="[html]pi-gpiod.tip.ser"></span></div>
|
||||
<div class="form-tips" id="pin-tip">Pins marked in blue are dual use. Make sure they are not enabled for
|
||||
their other use before using as GPIO.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="pi-gpiod out">
|
||||
<p>Raspberry Pi output node. Can be used in Digital, PWM or Servo modes. Requires the
|
||||
<a href="http://abyz.me.uk/rpi/pigpio/index.html" target="_new">pi-gpiod</a> daemon to be running in order to work.</p>
|
||||
<p><b>Inputs</b>
|
||||
<ul>
|
||||
<li><code>msg.payload</code> - <i>number | string</i> - 0,1 (Digital), 0-100 (PWM, Servo)</li>
|
||||
</ul>
|
||||
<p><b>Details</b></p>
|
||||
<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 and Servo modes, the input value should be a number 0 - 100, and can be floating point.</p>
|
||||
<p>In Servo mode you can stop the output by sending a <code>msg.payload</code> of <code>null</code> or <code>""</code>.</p>
|
||||
<p>If using with Docker on Pi then the default Host IP should be <code>172.17.0.1</code>. You will also need to run <code>sudo pigpiod</code> on the host.</p>
|
||||
<p><b>Note</b>: the pin numbers refer the physical pin numbers on connector P1 as they are easier to locate.</p>
|
||||
<div class="form-tips" id="pin-tip"><span data-i18n="[html]pi-gpiod.tip.dual"></span></div>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
12
hardware/sensehat/locales/de/sensehat.json
Normal file
12
hardware/sensehat/locales/de/sensehat.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"sensehat": {
|
||||
"label": {
|
||||
"outputs": "Ausgänge",
|
||||
"motionEvents": "Bewegungsereignisse",
|
||||
"motionEventsExamples": "Beschleunigungsmesser, Gyroskop, Magnetometer, Kompass",
|
||||
"environmentEvents": "Umgebungsereignisse",
|
||||
"environmentEventsExamples": "Temperatur, Luftfeuchtigkeit, Luftdruck",
|
||||
"joystickEvents": "Joystick-Ereignisse"
|
||||
}
|
||||
}
|
||||
}
|
100
hardware/sensehat/locales/en-US/sensehat.html
Normal file
100
hardware/sensehat/locales/en-US/sensehat.html
Normal file
@ -0,0 +1,100 @@
|
||||
|
||||
<script type="text/html" data-help-name="rpi-sensehat in">
|
||||
<p>Raspberry Pi Sense HAT input node.</p>
|
||||
<p>This node sends readings from the various sensors on the Sense HAT,
|
||||
grouped into three sets; motion events, environment events and joystick events.</p>
|
||||
<p><b>Motion events</b></p>
|
||||
<p>Motion events include readings from the accelerometer, gyroscope and magnetometer,
|
||||
as well as the current compass heading. They are sent at a rate of approximately 10
|
||||
per second. The <code>topic</code> is set to <code>motion</code> and the
|
||||
<code>payload</code> is an object with the following values:</p>
|
||||
<ul>
|
||||
<li><code>acceleration.x/y/z</code> : the acceleration intensity in Gs</li>
|
||||
<li><code>gyroscope.x/y/z</code> : the rotational intensity in radians/s</li>
|
||||
<li><code>orientation.roll/pitch/yaw</code> : the angle of the axis in degrees</li>
|
||||
<li><code>compass</code> : the direction of North in degrees</li>
|
||||
</ul>
|
||||
<p><b>Environment events</b></p>
|
||||
<p>Environment events include readings from the temperature, humidity and pressure
|
||||
sensors. They are sent at a rate of approximately 1 per second. The <code>topic</code>
|
||||
is set to <code>environment</code> and the <code>payload</code> is an object
|
||||
with the following values:</p>
|
||||
<ul>
|
||||
<li><code>temperature</code> : degrees Celsius</li>
|
||||
<li><code>humidity</code> : percentage of relative humidity</li>
|
||||
<li><code>pressure</code> : Millibars</li>
|
||||
</ul>
|
||||
<p><b>Joystick events</b></p>
|
||||
<p>Joystick events are sent when the Sense HAT joystick is interacted with. The
|
||||
<code>topic</code> is set to <code>joystick</code> and the <code>payload</code>
|
||||
is an object with the following values:</p>
|
||||
<ul>
|
||||
<li><code>key</code> : one of <code>UP</code>, <code>DOWN</code>, <code>LEFT</code>, <code>RIGHT</code>, <code>ENTER</code></li>
|
||||
<li><code>state</code> : the state of the key:
|
||||
<ul>
|
||||
<li><code>0</code> : the key has been released</li>
|
||||
<li><code>1</code> : the key has been pressed</li>
|
||||
<li><code>2</code> : the key is being held down</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="rpi-sensehat out">
|
||||
<p>Raspberry Pi Sense HAT output node.</p>
|
||||
<p>This node sends commands to the 8x8 LED display on the Sense HAT.</p>
|
||||
<p>Commands are sent to the node in <code>msg.payload</code>. Multiple commands can
|
||||
be sent in a single message by separating them with newline (\n) characters. You must
|
||||
use a function node or a change node (jsonata expression) when using the newline (\n)
|
||||
character to create a payload containing multiple commands.<p>
|
||||
|
||||
<p><b>Set the colour of individual pixels</b></p>
|
||||
<p>Format: <code><x>,<y>,<colour></code>
|
||||
<p><code>x</code> and <code>y</code> must either be a value from 0 to 7, a
|
||||
<code>*</code> to indicate the entire row or column, or a range such as <code>3-6</code>.</p>
|
||||
<p><code>colour</code> must be one of:
|
||||
<ul>
|
||||
<li>the well-known <a href="https://en.wikipedia.org/wiki/Web_colors" target="_new">HTML colour names</a>
|
||||
- eg <code>red</code> or <code>aquamarine</code>,</li>
|
||||
<li>the <a href="http://cheerlights.com/cheerlights-api/">CheerLights colour names</a>,</li>
|
||||
<li>a HEX colour value - eg <code>#aa9900</code></li>
|
||||
<li>an RGB triple - <code>190,255,0</code></li>
|
||||
<li>or simply <code>off</code></li>
|
||||
</ul>
|
||||
|
||||
<p><i>Examples</i></p>
|
||||
<p>To set the entire screen to red:</p>
|
||||
<p><code>*,*,red</code></p>
|
||||
<p>To set the four corners of the display to red, green (#00ff00), yellow and blue (0,0,255):</p>
|
||||
<p><code>0,0,red,0,7,#00ff00,7,7,yellow,7,0,0,0,255</code></p>
|
||||
<p>To set a 3-pixel wide column to purple:</p>
|
||||
<p><code>4-6,*,purple</code></p>
|
||||
|
||||
<p><b>Rotate the screen</b></p>
|
||||
<p>Format: <code>R<angle></code></p>
|
||||
<p><code>angle</code> must be 0, 90, 180 or 270.</p>
|
||||
<p>Example: <code>R180</code></p>
|
||||
|
||||
<p><b>Flip the screen</b></p>
|
||||
<p>Format: <code>F<axis></code></p>
|
||||
<p><code>axis</code> must be either <code>H</code> or <code>V</code> to flip on
|
||||
the horizontal or vertical axis respectively.</p>
|
||||
<p>Example: <code>FV</code></p>
|
||||
|
||||
<p><b>Scroll a message</b></p>
|
||||
<p>If <code>msg.payload</code> is not recognised as any of the above commands,
|
||||
it is treated as a text message to be scrolled across the screen.</p>
|
||||
<p>If the text is a single character, it will be displayed without scrolling.
|
||||
To scroll a single character, append a blank space after it - <code>"A "</code>.</p>
|
||||
<p>The following message properties can be used to customise the appearance:</p>
|
||||
<ul>
|
||||
<li><code>msg.color</code> - the colour of the text, default: <code>white</code></li>
|
||||
<li><code>msg.background</code> - the colour of the background, default: <code>off</code></li>
|
||||
<li><code>msg.speed</code> - the scroll speed. A value in the range 1 (slower) to 5 (faster), default: <code>3</code></li>
|
||||
</ul>
|
||||
|
||||
<p><b>Set the screen brightness</b></p>
|
||||
<p>Format: <code>D<level></code></p>
|
||||
<p><code>level</code> must be 0 (low) or 1 (high).</p>
|
||||
<p>Example: <code>D1</code></p>
|
||||
</script>
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name" : "node-red-node-pi-sense-hat",
|
||||
"version" : "0.0.18",
|
||||
"version" : "0.1.0",
|
||||
"description" : "A Node-RED node to interact with a Raspberry Pi Sense HAT",
|
||||
"repository" : {
|
||||
"type":"git",
|
||||
|
@ -1,132 +1,33 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="rpi-sensehat in">
|
||||
<div class="form-row">
|
||||
<label><i class="fa fa-arrow-right"></i> <span data-i18n="sensehat.label.outputs"></label>
|
||||
<label style="width: auto" for="node-input-motion"><input style="vertical-align: top; width: auto; margin-right: 5px;" type="checkbox" id="node-input-motion"> <span data-i18n="sensehat.label.motionEvents"></label>
|
||||
<div style="padding-left: 125px; margin-top: -5px; color: #bbb;" data-i18n="sensehat.label.motionEventsExamples"></div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label></label>
|
||||
<label style="width: auto" for="node-input-env"><input style="vertical-align: top; width: auto; margin-right: 5px;" type="checkbox" id="node-input-env"> <span data-i18n="sensehat.label.environmentEvents"></label>
|
||||
<div style="padding-left: 125px; margin-top: -5px; color: #bbb;" data-i18n="sensehat.label.environmentEventsExamples"></div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label></label>
|
||||
<label style="width: auto" for="node-input-stick"><input style="vertical-align: top; width: auto; margin-right: 5px;" type="checkbox" id="node-input-stick"> <span data-i18n="sensehat.label.joystickEvents"></label>
|
||||
</div>
|
||||
<script type="text/html" data-template-name="rpi-sensehat in">
|
||||
<div class="form-row">
|
||||
<label><i class="fa fa-arrow-right"></i> <span data-i18n="sensehat.label.outputs"></label>
|
||||
<label style="width: auto" for="node-input-motion"><input style="vertical-align: top; width: auto; margin-right: 5px;" type="checkbox" id="node-input-motion"> <span data-i18n="sensehat.label.motionEvents"></label>
|
||||
<div style="padding-left: 125px; margin-top: -5px; color: #bbb;" data-i18n="sensehat.label.motionEventsExamples"></div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label></label>
|
||||
<label style="width: auto" for="node-input-env"><input style="vertical-align: top; width: auto; margin-right: 5px;" type="checkbox" id="node-input-env"> <span data-i18n="sensehat.label.environmentEvents"></label>
|
||||
<div style="padding-left: 125px; margin-top: -5px; color: #bbb;" data-i18n="sensehat.label.environmentEventsExamples"></div>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label></label>
|
||||
<label style="width: auto" for="node-input-stick"><input style="vertical-align: top; width: auto; margin-right: 5px;" type="checkbox" id="node-input-stick"> <span data-i18n="sensehat.label.joystickEvents"></label>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="rpi-sensehat out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
|
||||
</div>
|
||||
<script type="text/html" data-template-name="rpi-sensehat out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="node-red:common.label.name"></label>
|
||||
<input type="text" id="node-input-name" data-i18n="[placeholder]node-red:common.label.name">
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-sensehat in">
|
||||
<p>Raspberry Pi Sense HAT input node.</p>
|
||||
<p>This node sends readings from the various sensors on the Sense HAT,
|
||||
grouped into three sets; motion events, environment events and joystick events.</p>
|
||||
<p><b>Motion events</b></p>
|
||||
<p>Motion events include readings from the accelerometer, gyroscope and magnetometer,
|
||||
as well as the current compass heading. They are sent at a rate of approximately 10
|
||||
per second. The <code>topic</code> is set to <code>motion</code> and the
|
||||
<code>payload</code> is an object with the following values:</p>
|
||||
<ul>
|
||||
<li><code>acceleration.x/y/z</code> : the acceleration intensity in Gs</li>
|
||||
<li><code>gyroscope.x/y/z</code> : the rotational intensity in radians/s</li>
|
||||
<li><code>orientation.roll/pitch/yaw</code> : the angle of the axis in degrees</li>
|
||||
<li><code>compass</code> : the direction of North in degrees</li>
|
||||
</ul>
|
||||
<p><b>Environment events</b></p>
|
||||
<p>Environment events include readings from the temperature, humidity and pressure
|
||||
sensors. They are sent at a rate of approximately 1 per second. The <code>topic</code>
|
||||
is set to <code>environment</code> and the <code>payload</code> is an object
|
||||
with the following values:</p>
|
||||
<ul>
|
||||
<li><code>temperature</code> : degrees Celsius</li>
|
||||
<li><code>humidity</code> : percentage of relative humidity</li>
|
||||
<li><code>pressure</code> : Millibars</li>
|
||||
</ul>
|
||||
<p><b>Joystick events</b></p>
|
||||
<p>Joystick events are sent when the Sense HAT joystick is interacted with. The
|
||||
<code>topic</code> is set to <code>joystick</code> and the <code>payload</code>
|
||||
is an object with the following values:</p>
|
||||
<ul>
|
||||
<li><code>key</code> : one of <code>UP</code>, <code>DOWN</code>, <code>LEFT</code>, <code>RIGHT</code>, <code>ENTER</code></li>
|
||||
<li><code>state</code> : the state of the key:
|
||||
<ul>
|
||||
<li><code>0</code> : the key has been released</li>
|
||||
<li><code>1</code> : the key has been pressed</li>
|
||||
<li><code>2</code> : the key is being held down</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="rpi-sensehat out">
|
||||
<p>Raspberry Pi Sense HAT output node.</p>
|
||||
<p>This node sends commands to the 8x8 LED display on the Sense HAT.</p>
|
||||
<p>Commands are sent to the node in <code>msg.payload</code>. Multiple commands can
|
||||
be sent in a single message by separating them with newline (\n) characters. You must
|
||||
use a function node or a change node (jsonata expression) when using the newline (\n)
|
||||
character to create a payload containing multiple commands.<p>
|
||||
|
||||
<p><b>Set the colour of individual pixels</b></p>
|
||||
<p>Format: <code><x>,<y>,<colour></code>
|
||||
<p><code>x</code> and <code>y</code> must either be a value from 0 to 7, a
|
||||
<code>*</code> to indicate the entire row or column, or a range such as <code>3-6</code>.</p>
|
||||
<p><code>colour</code> must be one of:
|
||||
<ul>
|
||||
<li>the well-known <a href="https://en.wikipedia.org/wiki/Web_colors" target="_new">HTML colour names</a>
|
||||
- eg <code>red</code> or <code>aquamarine</code>,</li>
|
||||
<li>the <a href="http://cheerlights.com/cheerlights-api/">CheerLights colour names</a>,</li>
|
||||
<li>a HEX colour value - eg <code>#aa9900</code></li>
|
||||
<li>an RGB triple - <code>190,255,0</code></li>
|
||||
<li>or simply <code>off</code></li>
|
||||
</ul>
|
||||
|
||||
<p><i>Examples</i></p>
|
||||
<p>To set the entire screen to red:</p>
|
||||
<p><code>*,*,red</code></p>
|
||||
<p>To set the four corners of the display to red, green (#00ff00), yellow and blue (0,0,255):</p>
|
||||
<p><code>0,0,red,0,7,#00ff00,7,7,yellow,7,0,0,0,255</code></p>
|
||||
<p>To set a 3-pixel wide column to purple:</p>
|
||||
<p><code>4-6,*,purple</code></p>
|
||||
|
||||
<p><b>Rotate the screen</b></p>
|
||||
<p>Format: <code>R<angle></code></p>
|
||||
<p><code>angle</code> must be 0, 90, 180 or 270.</p>
|
||||
<p>Example: <code>R180</code></p>
|
||||
|
||||
<p><b>Flip the screen</b></p>
|
||||
<p>Format: <code>F<axis></code></p>
|
||||
<p><code>axis</code> must be either <code>H</code> or <code>V</code> to flip on
|
||||
the horizontal or vertical axis respectively.</p>
|
||||
<p>Example: <code>FV</code></p>
|
||||
|
||||
<p><b>Scroll a message</b></p>
|
||||
<p>If <code>msg.payload</code> is not recognised as any of the above commands,
|
||||
it is treated as a text message to be scrolled across the screen.</p>
|
||||
<p>If the text is a single character, it will be displayed without scrolling.
|
||||
To scroll a single character, append a blank space after it - <code>"A "</code>.</p>
|
||||
<p>The following message properties can be used to customise the appearance:</p>
|
||||
<ul>
|
||||
<li><code>msg.color</code> - the colour of the text, default: <code>white</code></li>
|
||||
<li><code>msg.background</code> - the colour of the background, default: <code>off</code></li>
|
||||
<li><code>msg.speed</code> - the scroll speed. A value in the range 1 (slower) to 5 (faster), default: <code>3</code></li>
|
||||
</ul>
|
||||
|
||||
<p><b>Set the screen brightness</b></p>
|
||||
<p>Format: <code>D<level></code></p>
|
||||
<p><code>level</code> must be 0 (low) or 1 (high).</p>
|
||||
<p>Example: <code>D1</code></p>
|
||||
</script>
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('rpi-sensehat in',{
|
||||
category: 'Raspberry Pi',
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="emoncms">
|
||||
<script type="text/html" data-template-name="emoncms">
|
||||
<div class="form-row">
|
||||
<label for="node-input-emonServer"><i class="fa fa-globe"></i> Emoncms server</label>
|
||||
<input type="text" id="node-input-emonServer">
|
||||
@ -21,10 +21,9 @@
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Emoncms">
|
||||
</div>
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="emoncms">
|
||||
<script type="text/html" data-help-name="emoncms">
|
||||
<p>Posts data to Emoncms.</p>
|
||||
<p>The <code>msg.payload</code> can contain either a comma separated list of name
|
||||
value pairs (legacy) e.g. <pre>name:value,...</pre> or a comma separated list of values (CSV) e.g. <pre>1,2,...</pre>
|
||||
@ -33,7 +32,7 @@
|
||||
<p>The node must be specified either by the <i>Node</i> element or if left blank by <code>msg.nodegroup</code></p>
|
||||
<p>Data Type must be one of <pre>legacy, json, fulljson, CSV</pre></p>
|
||||
<p>Insertion time can be set by using <code>msg.time</code>.
|
||||
This can either be a valid ISO 8601 format or seconds since 1970. Not setting a time or setting an incorrect
|
||||
This can either be a valid ISO 8601 format or seconds since 1970. Not setting a time or setting an incorrect
|
||||
time format will result in data being pushed to Emoncms without the time element.</p>
|
||||
<p>The output node contains the server response</p>
|
||||
</script>
|
||||
@ -66,7 +65,8 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="emoncms in">
|
||||
|
||||
<script type="text/html" data-template-name="emoncms in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-emonServer"><i class="fa fa-globe"></i> Emoncms server</label>
|
||||
<input type="text" id="node-input-emonServer">
|
||||
@ -81,9 +81,11 @@
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="emoncms in">
|
||||
<script type="text/html" data-help-name="emoncms in">
|
||||
<p>Fetches data from emoncms.</p>
|
||||
<p>The <code>msg.payload</code> contains last emoncms feed value
|
||||
<p>The <code>msg.topic</code> contains the name of the Feed</p>
|
||||
<p>The <code>msg.payload</code> contains last emoncms feed value</p>
|
||||
<p>The <code>msg.feed_data</code> contains all the feed data</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
@ -109,18 +111,7 @@
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<script type="text/x-red" data-template-name="emoncms-server">
|
||||
<script type="text/html" data-template-name="emoncms-server">
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-server"><i class="fa fa-globe"></i> Base URL</label>
|
||||
<input type="text" id="node-config-input-server">
|
||||
@ -133,7 +124,7 @@
|
||||
<label for="node-config-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-config-input-name">
|
||||
</div>
|
||||
<div class="form-tips">The <b>Base URL</b> is the URL to the Emoncms root directory.</div>
|
||||
<div class="form-tips">The <b>Base URL</b> is the URL to the Emoncms root directory.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
@ -160,7 +160,7 @@ module.exports = function(RED) {
|
||||
if (this.baseurl.substring(0,5) === "https") { http = require("https"); }
|
||||
else { http = require("http"); }
|
||||
this.on("input", function(msg) {
|
||||
this.url = this.baseurl + '/feed/value.json';
|
||||
this.url = this.baseurl + '/feed/aget.json';
|
||||
this.url += '&apikey='+this.apikey;
|
||||
var feedid = this.feedid || msg.feedid;
|
||||
if (feedid !== "") {
|
||||
@ -169,14 +169,17 @@ module.exports = function(RED) {
|
||||
http.get(this.url, function(res) {
|
||||
msg.rc = res.statusCode;
|
||||
msg.payload = "";
|
||||
msg.feed_data = "";
|
||||
res.setEncoding('utf8');
|
||||
res.on('data', function(chunk) {
|
||||
msg.payload += chunk;
|
||||
msg.feed_data += chunk;
|
||||
});
|
||||
res.on('end', function() {
|
||||
if (msg.rc === 200) {
|
||||
try {
|
||||
msg.payload = JSON.parse(msg.payload);
|
||||
msg.feed_data = JSON.parse(msg.feed_data);
|
||||
msg.topic = msg.feed_data.name;
|
||||
msg.payload = msg.feed_data.value;
|
||||
}
|
||||
catch(err) {
|
||||
// Failed to parse, pass it on
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name" : "node-red-node-emoncms",
|
||||
"version" : "0.2.1",
|
||||
"version" : "0.3.0",
|
||||
"description" : "A Node-RED node to fetch/post data to/from emoncms",
|
||||
"dependencies" : {
|
||||
},
|
||||
|
@ -4,6 +4,14 @@
|
||||
<label for="node-input-host"><i class="fa fa-dot-circle-o"></i> <span data-i18n="ping.label.target"></span></label>
|
||||
<input type="text" id="node-input-host" placeholder="192.168.0.1, www.google.com">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-protocol"><i class="fa fa-gear"></i> <span data-i18n="ping.label.protocol"></label>
|
||||
<select type="text" id="node-input-protocol" style="width: 70%">
|
||||
<option value="Automatic" data-i18n="ping.label.protocol_option.auto"></option>
|
||||
<option value="IPv4" data-i18n="ping.label.protocol_option.ipv4"></option>
|
||||
<option value="IPv6" data-i18n="ping.label.protocol_option.ipv6"></option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-mode"><i class="fa fa-wrench"></i> <span data-i18n="ping.label.mode"></label>
|
||||
<select type="text" id="node-input-mode" style="width: 70%">
|
||||
@ -54,6 +62,7 @@ var timerParameterValidator = function(node,v){
|
||||
category: "network-input",
|
||||
color:"#fdf0c2",
|
||||
defaults: {
|
||||
protocol: {value:"Automatic"},
|
||||
mode: {value:"timed"},
|
||||
name: {value:""},
|
||||
host: {value:"", validate: function(v){
|
||||
|
@ -6,7 +6,7 @@ module.exports = function(RED) {
|
||||
|
||||
function doPing(node, host, arrayMode) {
|
||||
const defTimeout = 5000;
|
||||
var ex, hostOptions, commandLineOptions;
|
||||
var ex, ex6, hostOptions, commandLineOptions;
|
||||
if (typeof host === "string") {
|
||||
hostOptions = {
|
||||
host: host,
|
||||
@ -25,12 +25,33 @@ module.exports = function(RED) {
|
||||
if (arrayMode) {
|
||||
msg.ping = hostOptions
|
||||
}
|
||||
|
||||
//User Selected Protocol
|
||||
if (plat == "linux" || plat == "android") {
|
||||
commandLineOptions = ["-n", "-w", timeoutS, "-c", "1"]
|
||||
if (node.protocol === "IPv4") {
|
||||
commandLineOptions = ["-n", "-4", "-w", timeoutS, "-c", "1"]; //IPv4
|
||||
} else if (node.protocol === "IPv6") {
|
||||
commandLineOptions = ["-n", "-6", "-w", timeoutS, "-c", "1"]; //IPv6
|
||||
} else {
|
||||
commandLineOptions = ["-n", "-w", timeoutS, "-c", "1"]; //Automatic
|
||||
}
|
||||
} else if (plat.match(/^win/)) {
|
||||
commandLineOptions = ["-n", "1", "-w", hostOptions.timeout]
|
||||
if (node.protocol === "IPv4") {
|
||||
commandLineOptions = ["-n", "1", "-4", "-w", hostOptions.timeout]; //IPv4
|
||||
} else if (node.protocol === "IPv6") {
|
||||
commandLineOptions = ["-n", "1", "-6", "-w", hostOptions.timeout]; //IPv6
|
||||
} else {
|
||||
commandLineOptions = ["-n", "1", "-w", hostOptions.timeout]; //Automatic
|
||||
}
|
||||
} else if (plat == "darwin" || plat == "freebsd") {
|
||||
commandLineOptions = ["-n", "-t", timeoutS, "-c", "1"]
|
||||
if (node.protocol === "IPv4") {
|
||||
commandLineOptions = ["-n", "-4", "-t", timeoutS, "-c", "1"]; //IPv4
|
||||
} else if (node.protocol === "IPv6") {
|
||||
commandLineOptions = ["-n", "-6", "-t", timeoutS, "-c", "1"]; //IPv6
|
||||
} else {
|
||||
commandLineOptions = ["-n", "-t", timeoutS, "-c", "1"]; //Automatic
|
||||
}
|
||||
|
||||
} else {
|
||||
node.error("Sorry - your platform - "+plat+" - is not recognised.", msg);
|
||||
return; //dont pass go - just return!
|
||||
@ -53,6 +74,23 @@ module.exports = function(RED) {
|
||||
var fail = false;
|
||||
//var regex = /from.*time.(.*)ms/;
|
||||
var regex = /=.*[<|=]([0-9]*).*TTL|ttl..*=([0-9\.]*)/;
|
||||
|
||||
var tryPing6 = false;
|
||||
//catch error msg from ping
|
||||
ex.stderr.setEncoding('utf8');
|
||||
ex.stderr.on("data", function (data) {
|
||||
if (!data.includes('Usage')) { // !data: only get the error and not how to use the ping command
|
||||
if (data.includes('invalid') && data.includes('6')) { //if IPv6 not supported in version of ping try ping6
|
||||
tryPing6 = true;
|
||||
//node.error(data, msg); // used for testing output of -6 on ping command. Keep this line untill out of beta testing please. Contact---> https://discourse.nodered.org/u/meeki007
|
||||
} else if (data.includes('Network is unreachable')) {
|
||||
node.error(data + " Please check that your service provider or network device has IPv6 enabled", msg);
|
||||
} else {
|
||||
node.error(data, msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ex.stdout.on("data", function (data) {
|
||||
line += data.toString();
|
||||
});
|
||||
@ -72,20 +110,88 @@ module.exports = function(RED) {
|
||||
}
|
||||
});
|
||||
ex.on("close", function (code) {
|
||||
if (fail) { fail = false; return; }
|
||||
var m = regex.exec(line)||"";
|
||||
if (m !== "") {
|
||||
if (m[1]) { res = Number(m[1]); }
|
||||
if (m[2]) { res = Number(m[2]); }
|
||||
if (tryPing6 === false) {
|
||||
if (fail) { fail = false; return; }
|
||||
var m = regex.exec(line)||"";
|
||||
if (m !== "") {
|
||||
if (m[1]) { res = Number(m[1]); }
|
||||
if (m[2]) { res = Number(m[2]); }
|
||||
}
|
||||
if (code === 0) { msg.payload = res }
|
||||
try { node.send(msg); }
|
||||
catch(e) {console.warn(e)}
|
||||
|
||||
} else {
|
||||
//fallback to ping6 for OS's that have not updated/out of date
|
||||
if (plat == "linux" || plat == "android") {
|
||||
commandLineOptions = ["-n", "-w", timeoutS, "-c", "1"];
|
||||
} else if (plat == "darwin" || plat == "freebsd") {
|
||||
commandLineOptions = ["-n", "-c", "1"] //NOTE: -X / timeout does not work on mac OSX and most freebsd systems
|
||||
} else {
|
||||
node.error("Sorry IPv6 on your platform - "+plat+" - is not supported.", msg);
|
||||
}
|
||||
//spawn with timeout in case of os issue
|
||||
ex6 = spawn("ping6", [...commandLineOptions, hostOptions.host]);
|
||||
|
||||
//monitor every spawned process & SIGINT if too long
|
||||
var spawnTout = setTimeout(() => {
|
||||
node.log(`ping6 - Host '${hostOptions.host}' process timeout - sending SIGINT`)
|
||||
try {
|
||||
if (ex6 && ex6.pid) { ex6.kill("SIGINT"); }
|
||||
}
|
||||
catch(e) {console.warn(e); }
|
||||
}, hostOptions.timeout+1000); //add 1s for grace
|
||||
|
||||
//catch error msg from ping6
|
||||
ex6.stderr.setEncoding('utf8');
|
||||
ex6.stderr.on("data", function (data) {
|
||||
if (!data.includes('Usage')) { // !data: only get the error and not how to use the ping6 command
|
||||
if (data.includes('Network is unreachable')) {
|
||||
node.error(data + " Please check that your service provider or network device has IPv6 enabled", msg);
|
||||
} else {
|
||||
node.error(data, msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ex6.stdout.on("data", function (data) {
|
||||
line += data.toString();
|
||||
});
|
||||
ex6.on("exit", function (err) {
|
||||
clearTimeout(spawnTout);
|
||||
});
|
||||
ex6.on("error", function (err) {
|
||||
fail = true;
|
||||
if (err.code === "ENOENT") {
|
||||
node.error(err.code + " ping6 command not found", msg);
|
||||
}
|
||||
else if (err.code === "EACCES") {
|
||||
node.error(err.code + " can't run ping6 command", msg);
|
||||
}
|
||||
else {
|
||||
node.error(err.code, msg);
|
||||
}
|
||||
});
|
||||
ex6.on("close", function (code) {
|
||||
if (fail) { fail = false; return; }
|
||||
var m = regex.exec(line)||"";
|
||||
if (m !== "") {
|
||||
if (m[1]) { res = Number(m[1]); }
|
||||
if (m[2]) { res = Number(m[2]); }
|
||||
}
|
||||
if (code === 0) { msg.payload = res }
|
||||
try { node.send(msg); }
|
||||
catch(e) {console.warn(e)}
|
||||
});
|
||||
}
|
||||
if (code === 0) { msg.payload = res }
|
||||
try { node.send(msg); }
|
||||
catch(e) {console.warn(e)}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function PingNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.protocol = n.protocol||'Automatic';
|
||||
this.mode = n.mode;
|
||||
this.host = n.host;
|
||||
this.timer = n.timer * 1000;
|
||||
@ -132,4 +238,4 @@ module.exports = function(RED) {
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("ping",PingNode);
|
||||
}
|
||||
}
|
||||
|
15
io/ping/locales/de/88-ping.json
Normal file
15
io/ping/locales/de/88-ping.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"ping": {
|
||||
"ping": "ping",
|
||||
"label": {
|
||||
"target": "Ziel",
|
||||
"ping": "Ping (S)",
|
||||
"mode": "Modus",
|
||||
"mode_option": {
|
||||
"timed": "Zeitgesteuert",
|
||||
"triggered": "Getriggert"
|
||||
},
|
||||
"tip": "Hinweis: Ziel-Eintrag leer lassen, damit über msg.payload der Hosts dynamisch gesetzt werden kann"
|
||||
}
|
||||
}
|
||||
}
|
@ -15,6 +15,19 @@
|
||||
<p>Returns <b>false</b> if no response received, or if the host is unresolveable.</p>
|
||||
<p>Default ping is every 20 seconds but can be configured.</p>
|
||||
|
||||
<h4>Protocol...</h4>
|
||||
<ul>
|
||||
<li><b>Automatic</b><br>
|
||||
<P>Will use any Protocol, IPv4 or IPv6, to reach host; based on your operating system network settings</P>
|
||||
</li>
|
||||
<li><b>IPv4</b><br>
|
||||
<P>Forces use of IPv4 to reach host. Will fail if no route availibe</P>
|
||||
</li>
|
||||
<li><b>IPv6</b><br>
|
||||
<P>Forces use of IPv6 to reach host. Will fail if no route availibe</P>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>Mode...</h4>
|
||||
<ul>
|
||||
<li><b>Timed</b><br>
|
||||
|
@ -9,6 +9,12 @@
|
||||
"timed": "Timed",
|
||||
"triggered": "Triggered"
|
||||
},
|
||||
"protocol": "Protocol",
|
||||
"protocol_option": {
|
||||
"auto": "Automatic",
|
||||
"ipv4": "IPv4",
|
||||
"ipv6": "IPv6"
|
||||
},
|
||||
"tip": "Note: Leave Target field blank to allow msg.payload to set hosts dynamically."
|
||||
}
|
||||
}
|
||||
|
@ -15,6 +15,19 @@
|
||||
<p>ホスト名が解決できなかったり、レスポンスが得られなければ、<b>false</b>を返します。</p>
|
||||
<p>デフォルトでは20秒ごとにpingを送りますが、設定で変更できます。</p>
|
||||
|
||||
<h4>Protocol...</h4>
|
||||
<ul>
|
||||
<li><b>Automatic</b><br>
|
||||
<P>Will use any Protocol, IPv4 or IPv6, to reach host; based on your operating system network settings</P>
|
||||
</li>
|
||||
<li><b>IPv4</b><br>
|
||||
<P>Forces use of IPv4 to reach host. Will fail if no route availibe</P>
|
||||
</li>
|
||||
<li><b>IPv6</b><br>
|
||||
<P>Forces use of IPv6 to reach host. Will fail if no route availibe</P>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<h4>モード...</h4>
|
||||
<ul>
|
||||
<li><b>時間</b><br>
|
||||
@ -25,7 +38,7 @@
|
||||
<li><b>トリガー</b><br>
|
||||
<p><code>トリガー</code>モードでは、入力ワイヤを結線し、<code>msg</code>入力によってping処理を起動します。
|
||||
<p><code>ターゲット</code>フィールドに入力した値はホスト名もしくはIPアドレスとして使用します。 ターゲットはホスト名/IPアドレスをカンマで区切ったものです。例: <code>"192.168.0.1"</code> あるいは <code>"192.168.0.1, www.google.com"</code></p>
|
||||
|
||||
|
||||
<p><code>ターゲット</code>を空にした場合、カンマ区切り文字列、もしくは、ホストの配列を<code>msg.payload</code>に指定します。
|
||||
<ul>
|
||||
<li><code>文字列</code> - カンマ区切りのホスト名/IPアドレス 例: <code>"192.168.0.1"</code> あるいは <code>"192.168.0.1, www.google.com"</code> </li>
|
||||
@ -33,12 +46,12 @@
|
||||
<li>配列ペイロードの例: <pre>[
|
||||
"192.168.0.99",
|
||||
{
|
||||
"host":"192.168.0.1",
|
||||
"host":"192.168.0.1",
|
||||
"name":"ルータ"
|
||||
},
|
||||
},
|
||||
{
|
||||
"host":"myapiserver.com",
|
||||
"name":"拡張API",
|
||||
"host":"myapiserver.com",
|
||||
"name":"拡張API",
|
||||
"timeout": 20000,
|
||||
"support":"support@myapiserver.com"
|
||||
}
|
||||
|
@ -9,6 +9,12 @@
|
||||
"timed": "時間",
|
||||
"triggered": "トリガー"
|
||||
},
|
||||
"protocol": "プロトコル",
|
||||
"protocol_option": {
|
||||
"auto": "自動の",
|
||||
"ipv4": "IPv4",
|
||||
"ipv6": "IPv6"
|
||||
},
|
||||
"tip": "注: msg.payloadでホスト名を動的に指定する場合は、ターゲットフィールドを空にします。"
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name" : "node-red-node-ping",
|
||||
"version" : "0.2.2",
|
||||
"version" : "0.3.0",
|
||||
"description" : "A Node-RED node to ping a remote server, for use as a keep-alive check.",
|
||||
"dependencies" : {
|
||||
},
|
||||
|
@ -10,17 +10,6 @@
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="serial in">
|
||||
<p>Reads data from a local serial port.</p>
|
||||
<p>Can either <ul><li>wait for a "split" character (default \n). Also accepts hex notation (0x0d).</li>
|
||||
<li>Wait for a timeout in milliseconds from the first character received</li>
|
||||
<li>Wait to fill a fixed sized buffer</li></ul></p>
|
||||
<p>It then outputs <code>msg.payload</code> as either a UTF8 ascii string or a binary Buffer object.</p>
|
||||
<p><code>msg.port</code> is set to the name of the port selected.</p>
|
||||
<p>If no split character is specified, or a timeout or buffer size of 0, then a stream of single characters
|
||||
is sent - again either as ascii chars or size 1 binary buffers.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('serial in',{
|
||||
category: 'network',
|
||||
@ -54,14 +43,6 @@
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="serial out">
|
||||
<p>Provides a connection to an outbound serial port.</p>
|
||||
<p>Only the <code>msg.payload</code> is sent.</p>
|
||||
<p>Optionally the baudrate can be changed using <code>msg.baudrate</code></p>
|
||||
<p>Optionally the new line character used to split the input can be appended to every message sent out to the serial port.</p>
|
||||
<p>Binary payloads can be sent by using a Buffer object.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('serial out',{
|
||||
category: 'network',
|
||||
@ -95,33 +76,6 @@
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="serial request">
|
||||
<p>Provides a connection to a request/response serial port.</p>
|
||||
<p>This node behaves as a tightly coupled combination of <code>serial in</code> and <code>serial out</code> nodes,
|
||||
with which it shares the configuration.</p>
|
||||
<p>Send the request message in <code>msg.payload</code> as you would do with a <code>serial out</code> node.
|
||||
The message will be forwarded to the serial port following a strict FIFO (First In, First Out) queue, waiting for a single response before transmitting the next request.
|
||||
Once a response is received (with the same logic of a <code>serial in</code> node), or after a timeout occurs, a message is sent to the output (see Outputs below),
|
||||
with <code>msg.payload</code> containing the received response (or missing in case if timeout) and all other fields preserved.</p>
|
||||
<p>For consistency with the <code>serial in</code> node, <code>msg.port</code> is set to the name of the port selected.</p>
|
||||
<h3>Inputs</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<code>msg.timeout</code> is the timeout (in ms) after which the incoming message is propagated to the output with <code>msg.status</code> set to <code>"ERR_TIMEOUT"</code> and missing payload.
|
||||
If not present, the default value is 10000 (10s).
|
||||
</li>
|
||||
<li><code>msg.count</code> if set this will override the configured number of characters as long as it is less than the number configured.</li>
|
||||
<li><code>msg.waitfor</code> single character, escape code, or hex code. If set, the node will wait until it matches that character in the stream and then start the output.</li>
|
||||
<li>Optionally the baudrate can be changed using <code>msg.baudrate</code></li>
|
||||
</ul>
|
||||
<h3>Outputs</h3>
|
||||
<ul>
|
||||
<li><code>msg.payload</code> is the response. If no response occured, this field is removed.</li>
|
||||
<li><code>msg.status</code> is <code>"OK"</code> in case a response is received, or <code>"ERR_TIMEOUT"</code> if a timeout occurs.</li>
|
||||
<li>Any other field coming from the input will be preserved.</li>
|
||||
</ul>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('serial request',{
|
||||
category: 'network',
|
||||
@ -272,16 +226,6 @@
|
||||
<div class="form-tips" id="tip-count" hidden><span data-i18n="serial.tip.count"></span></div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="serial-port">
|
||||
<p>Provides configuration options for a serial port.</p>
|
||||
<p>The search button should return a list of available serial ports to choose from, or you
|
||||
can type in the location if known.</p>
|
||||
<p>The DTR, RTS, CTS and DSR switches can be used to permanently pull the corresponding flow control pin high or low, e.g. in order to power devices via those pins.</p>
|
||||
<p>The node can optionally wait until it matches a pre-defined character.
|
||||
The data can then be split on a fixed character, after a timeout, or after a fixed number of characters.</p>
|
||||
<p>If using a character, it can be specified as either the character, the escaped shortcut (e.g. \n), or the hex code (e.g. 0x0d).</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('serial-port',{
|
||||
category: 'config',
|
||||
|
@ -72,7 +72,7 @@ module.exports = function(RED) {
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.error(RED._("serial.errors.missing-conf"));
|
||||
this.error(RED._("serial.errors.missing-conf"), {});
|
||||
}
|
||||
|
||||
this.on("close", function(done) {
|
||||
@ -109,7 +109,7 @@ module.exports = function(RED) {
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.error(RED._("serial.errors.missing-conf"));
|
||||
this.error(RED._("serial.errors.missing-conf"), {});
|
||||
}
|
||||
|
||||
this.on("close", function(done) {
|
||||
@ -186,7 +186,7 @@ module.exports = function(RED) {
|
||||
});
|
||||
}
|
||||
else {
|
||||
this.error(RED._("serial.errors.missing-conf"));
|
||||
this.error(RED._("serial.errors.missing-conf"), {});
|
||||
}
|
||||
|
||||
this.on("close", function(done) {
|
||||
@ -347,7 +347,7 @@ module.exports = function(RED) {
|
||||
if (err) {
|
||||
if (err.toString() !== olderr) {
|
||||
olderr = err.toString();
|
||||
RED.log.error(RED._("serial.errors.error",{port:port,error:olderr}));
|
||||
RED.log.error(RED._("serial.errors.error",{port:port,error:olderr}), {});
|
||||
}
|
||||
obj.tout = setTimeout(function() {
|
||||
setupSerial();
|
||||
@ -355,7 +355,7 @@ module.exports = function(RED) {
|
||||
}
|
||||
});
|
||||
obj.serial.on('error', function(err) {
|
||||
RED.log.error(RED._("serial.errors.error",{port:port,error:err.toString()}));
|
||||
RED.log.error(RED._("serial.errors.error",{port:port,error:err.toString()}), {});
|
||||
obj._emitter.emit('closed');
|
||||
if (obj.tout) { clearTimeout(obj.tout); }
|
||||
obj.tout = setTimeout(function() {
|
||||
@ -366,7 +366,7 @@ module.exports = function(RED) {
|
||||
if (!obj._closing) {
|
||||
if (olderr !== "unexpected") {
|
||||
olderr = "unexpected";
|
||||
RED.log.error(RED._("serial.errors.unexpected-close",{port:port}));
|
||||
RED.log.error(RED._("serial.errors.unexpected-close",{port:port}), {});
|
||||
}
|
||||
obj._emitter.emit('closed');
|
||||
if (obj.tout) { clearTimeout(obj.tout); }
|
||||
@ -472,7 +472,7 @@ module.exports = function(RED) {
|
||||
connections[port]._closing = true;
|
||||
try {
|
||||
connections[port].close(function() {
|
||||
RED.log.info(RED._("serial.errors.closed",{port:port}));
|
||||
RED.log.info(RED._("serial.errors.closed",{port:port}), {});
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
73
io/serialport/locales/de/25-serial.json
Normal file
73
io/serialport/locales/de/25-serial.json
Normal file
@ -0,0 +1,73 @@
|
||||
{
|
||||
"serial": {
|
||||
"status": {
|
||||
"waiting": "Wartend",
|
||||
"timeout": "Zeitablauf"
|
||||
},
|
||||
"label": {
|
||||
"serialport": "Serieller Port",
|
||||
"settings": "Einstellungen",
|
||||
"baudrate": "Baudrate",
|
||||
"databits": "Datenbits",
|
||||
"parity": "Parität",
|
||||
"stopbits": "Stoppbits",
|
||||
"input": "Empfang",
|
||||
"split": "Aufteilung",
|
||||
"deliver": "und Ausgabe",
|
||||
"output": "Versand",
|
||||
"request": "Anforderung",
|
||||
"responsetimeout": "Standardwert Antwort-Zeitablauf",
|
||||
"ms": "ms",
|
||||
"serial": "seriell",
|
||||
"none": "none",
|
||||
"start": "Optional Warten auf das Startzeichen",
|
||||
"startor": ", dann"
|
||||
},
|
||||
"placeholder": {
|
||||
"serialport": "z. B. /dev/ttyUSB0/"
|
||||
},
|
||||
"parity": {
|
||||
"none": "Keine",
|
||||
"even": "Gerade",
|
||||
"mark": "Mark",
|
||||
"odd": "Ungerade",
|
||||
"space": "Space"
|
||||
},
|
||||
"linestates": {
|
||||
"none": "Auto",
|
||||
"high": "High",
|
||||
"low": "Low"
|
||||
},
|
||||
"split": {
|
||||
"character": "anhand Zeichen",
|
||||
"timeout": "nach Zeitablauf von",
|
||||
"silent": "nach Ruhezeit von",
|
||||
"lengths": "in feste Längen von"
|
||||
},
|
||||
"output": {
|
||||
"ascii": "als ASCII-Strings",
|
||||
"binary": "binäre Buffer"
|
||||
},
|
||||
"addsplit": "Zeichen zu Ausgangsnachrichten hinzufügen",
|
||||
"tip": {
|
||||
"responsetimeout": "Tipp: Der Standardwert des Antwort-Zeitablaufs (default response timeout) kann durch Setzen von msg.timeout überschrieben werden",
|
||||
"split": "Tipp: Das Aufteilungszeichen wird benutzt, um die empfangenen Daten in einzelne Nachrichten aufzuteilen. Es werden Zeichen ($), Escape-Codes (\\n) oder Hex-Codes (0x03) akzeptiert.",
|
||||
"silent": "Tipp: Im Ruhezeit-Modus wird die Ruhezeitmessung bei jedem neu empfangenen Zeichen neu gestartet",
|
||||
"timeout": "Tipp: Im Zeitablauf-Modus startet die Zeitmessung mit Empfang des ersten Zeichens",
|
||||
"count": "Tipp: Im Modus der festen Längen kann msg.count die vorgegebene Anzahl überschreiben, sofern dieser Wert kleiner ist",
|
||||
"waitfor": "Tipp: Optional. Leer lassen, um alle Daten zu empfangen. Es werden Zeichen ($), Escape-Codes (\\n) oder Hex-Codes (0x03) akzeptiert." ,
|
||||
"addchar": "Tipp: Dieses Zeichen wird jeder über den seriellen Port gesendeten Nachricht hinzugefügt. Üblicherweise \\r oder \\n."
|
||||
},
|
||||
"onopen": "Seriellen Port __port__ geöffnet mit __baud__ Baud, __config__",
|
||||
"errors": {
|
||||
"missing-conf": "Fehlende serielle Konfiguration",
|
||||
"serial-port": "Serieller Port",
|
||||
"error": "Serieller Port __port__ Fehler: __error__",
|
||||
"unexpected-close": "Serieller Port __port__ unerwartet geschlossen",
|
||||
"disconnected": "Serieller Port __port__ getrennt",
|
||||
"closed": "Serieller Port __port__ geschlossen",
|
||||
"list": "Port-Auflistung fehlgeschlagen. Bitte manuell eintragen.",
|
||||
"badbaudrate": "Ungültige Baudrate"
|
||||
}
|
||||
}
|
||||
}
|
56
io/serialport/locales/en-US/25-serial.html
Normal file
56
io/serialport/locales/en-US/25-serial.html
Normal file
@ -0,0 +1,56 @@
|
||||
|
||||
<script type="text/html" data-help-name="serial in">
|
||||
<p>Reads data from a local serial port.</p>
|
||||
<p>Can either <ul><li>wait for a "split" character (default \n). Also accepts hex notation (0x0d).</li>
|
||||
<li>Wait for a timeout in milliseconds from the first character received</li>
|
||||
<li>Wait to fill a fixed sized buffer</li></ul></p>
|
||||
<p>It then outputs <code>msg.payload</code> as either a UTF8 ascii string or a binary Buffer object.</p>
|
||||
<p><code>msg.port</code> is set to the name of the port selected.</p>
|
||||
<p>If no split character is specified, or a timeout or buffer size of 0, then a stream of single characters
|
||||
is sent - again either as ascii chars or size 1 binary buffers.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="serial out">
|
||||
<p>Provides a connection to an outbound serial port.</p>
|
||||
<p>Only the <code>msg.payload</code> is sent.</p>
|
||||
<p>Optionally the baudrate can be changed using <code>msg.baudrate</code></p>
|
||||
<p>Optionally the new line character used to split the input can be appended to every message sent out to the serial port.</p>
|
||||
<p>Binary payloads can be sent by using a Buffer object.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="serial request">
|
||||
<p>Provides a connection to a request/response serial port.</p>
|
||||
<p>This node behaves as a tightly coupled combination of <code>serial in</code> and <code>serial out</code> nodes,
|
||||
with which it shares the configuration.</p>
|
||||
<p>Send the request message in <code>msg.payload</code> as you would do with a <code>serial out</code> node.
|
||||
The message will be forwarded to the serial port following a strict FIFO (First In, First Out) queue, waiting for a single response before transmitting the next request.
|
||||
Once a response is received (with the same logic of a <code>serial in</code> node), or after a timeout occurs, a message is sent to the output (see Outputs below),
|
||||
with <code>msg.payload</code> containing the received response (or missing in case if timeout) and all other fields preserved.</p>
|
||||
<p>For consistency with the <code>serial in</code> node, <code>msg.port</code> is set to the name of the port selected.</p>
|
||||
<h3>Inputs</h3>
|
||||
<ul>
|
||||
<li>
|
||||
<code>msg.timeout</code> is the timeout (in ms) after which the incoming message is propagated to the output with <code>msg.status</code> set to <code>"ERR_TIMEOUT"</code> and missing payload.
|
||||
If not present, the default value is 10000 (10s).
|
||||
</li>
|
||||
<li><code>msg.count</code> if set this will override the configured number of characters as long as it is less than the number configured.</li>
|
||||
<li><code>msg.waitfor</code> single character, escape code, or hex code. If set, the node will wait until it matches that character in the stream and then start the output.</li>
|
||||
<li>Optionally the baudrate can be changed using <code>msg.baudrate</code></li>
|
||||
</ul>
|
||||
<h3>Outputs</h3>
|
||||
<ul>
|
||||
<li><code>msg.payload</code> is the response. If no response occured, this field is removed.</li>
|
||||
<li><code>msg.status</code> is <code>"OK"</code> in case a response is received, or <code>"ERR_TIMEOUT"</code> if a timeout occurs.</li>
|
||||
<li>Any other field coming from the input will be preserved.</li>
|
||||
</ul>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="serial-port">
|
||||
<p>Provides configuration options for a serial port.</p>
|
||||
<p>The search button should return a list of available serial ports to choose from, or you
|
||||
can type in the location if known.</p>
|
||||
<p>The DTR, RTS, CTS and DSR switches can be used to permanently pull the corresponding flow control pin high or low, e.g. in order to power devices via those pins.</p>
|
||||
<p>The node can optionally wait until it matches a pre-defined character.
|
||||
The data can then be split on a fixed character, after a timeout, or after a fixed number of characters.</p>
|
||||
<p>If using a character, it can be specified as either the character, the escaped shortcut (e.g. \n), or the hex code (e.g. 0x0d).</p>
|
||||
</script>
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"name" : "node-red-node-serialport",
|
||||
"version" : "0.11.1",
|
||||
"version" : "0.13.0",
|
||||
"description" : "Node-RED nodes to talk to serial ports",
|
||||
"dependencies" : {
|
||||
"serialport" : "^9.0.2"
|
||||
"serialport" : "^9.0.7"
|
||||
},
|
||||
"repository" : {
|
||||
"type":"git",
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="stomp in">
|
||||
<script type="text/html" data-template-name="stomp in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-server" style="width: 110px;"><i class="fa fa-bookmark"></i> Server</label>
|
||||
<input type="text" id="node-input-server">
|
||||
@ -14,7 +14,7 @@
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="stomp in">
|
||||
<script type="text/html" data-help-name="stomp in">
|
||||
<p>Connects to a server using the Stomp protocol to receive messages.</p>
|
||||
<p>If the message received is JSON <code>msg.payload</code> will be parsed into an
|
||||
object. If not it will be the raw data.</p>
|
||||
@ -47,7 +47,7 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="stomp out">
|
||||
<script type="text/html" data-template-name="stomp out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-server" style="width: 110px;"><i class="fa fa-bookmark"></i> Server</label>
|
||||
<input type="text" id="node-input-server">
|
||||
@ -64,7 +64,7 @@
|
||||
property of the message.</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="stomp out">
|
||||
<script type="text/html" data-help-name="stomp out">
|
||||
<p>Connects to an Stomp capable server to send messages.</p>
|
||||
<p>The <b>Destination</b> field is optional. If set it overrides the <code>msg.topic</code>
|
||||
property of the message.</p>
|
||||
@ -99,7 +99,7 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="stomp-server">
|
||||
<script type="text/html" data-template-name="stomp-server">
|
||||
<div class="form-row node-input-server">
|
||||
<label for="node-config-input-server"><i class="fa fa-bookmark"></i> Server</label>
|
||||
<input class="input-append-left" type="text" id="node-config-input-server" placeholder="localhost" style="width: 45%;" >
|
||||
|
24
parsers/base64/locales/de/70-base64.json
Normal file
24
parsers/base64/locales/de/70-base64.json
Normal file
@ -0,0 +1,24 @@
|
||||
{
|
||||
"base64": {
|
||||
"base64": "base64",
|
||||
"label": {
|
||||
"action": "Aktion"
|
||||
},
|
||||
"convert": {
|
||||
"buffer": "Konvertierung Buffer <-> Base64",
|
||||
"encode": "Kodierung als Base64",
|
||||
"decode": "Konvertierung Base64 zu String"
|
||||
},
|
||||
"log": {
|
||||
"nonbase64encode": "Kein Base64-String - möglicherweise soll es kodiert werden..."
|
||||
},
|
||||
"warn": {
|
||||
"cannothandle": "Dieser Node kann nur Strings oder Buffer verarbeiten",
|
||||
"noproperty": "Keine Eigenschaft zur Verarbeitung gefunden"
|
||||
},
|
||||
"error": {
|
||||
"invalid": "Ungültiger Base64-String",
|
||||
"nonbase64": "Kein Base64-String"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name" : "node-red-node-base64",
|
||||
"version" : "0.2.1",
|
||||
"version" : "0.3.0",
|
||||
"description" : "A Node-RED node to pack and unpack objects to base64 format",
|
||||
"dependencies" : {
|
||||
},
|
||||
|
@ -119,9 +119,16 @@ module.exports = function(RED) {
|
||||
else {
|
||||
var payload = RED.util.ensureString(msg.payload);
|
||||
sendopts.text = payload; // plaintext body
|
||||
if (/<[a-z][\s\S]*>/i.test(payload)) { sendopts.html = payload; } // html body
|
||||
if (msg.attachments && Array.isArray(msg.attachments)) {
|
||||
sendopts.attachments = msg.attachments;
|
||||
if (/<[a-z][\s\S]*>/i.test(payload)) {
|
||||
sendopts.html = payload; // html body
|
||||
if (msg.hasOwnProperty("plaintext")) {
|
||||
var plaintext = RED.util.ensureString(msg.plaintext);
|
||||
sendopts.text = plaintext; // plaintext body - specific plaintext version
|
||||
}
|
||||
}
|
||||
if (msg.attachments) {
|
||||
if (!Array.isArray(msg.attachments)) { sendopts.attachments = [ msg.attachments ]; }
|
||||
else { sendopts.attachments = msg.attachments; }
|
||||
for (var a=0; a < sendopts.attachments.length; a++) {
|
||||
if (sendopts.attachments[a].hasOwnProperty("content")) {
|
||||
if (typeof sendopts.attachments[a].content !== "string" && !Buffer.isBuffer(sendopts.attachments[a].content)) {
|
||||
@ -506,7 +513,11 @@ module.exports = function(RED) {
|
||||
if (this.interval_id != null) {
|
||||
clearTimeout(this.interval_id);
|
||||
}
|
||||
if (imap) { imap.destroy(); }
|
||||
if (imap) {
|
||||
imap.end();
|
||||
setTimeout(function() { imap.destroy(); },1000);
|
||||
node.status({});
|
||||
}
|
||||
});
|
||||
|
||||
function setInputRepeatTimeout() {
|
||||
|
69
social/email/locales/de/61-email.html
Normal file
69
social/email/locales/de/61-email.html
Normal file
@ -0,0 +1,69 @@
|
||||
<script type="text/html" data-help-name="e-mail">
|
||||
<p>Versand von <code>msg.payload</code> als E-Mail mit <code>msg.topic</code> als Subjekt.</p>
|
||||
<p>Der Standard-Nachrichtenempfänger kann im Node vorgegeben werden.
|
||||
Wenn nicht angegeben, muss der Nachrichtenempfänger über die <code>msg.to</code>-Eigenschaft
|
||||
der eingehenden Nachricht übergeben werden.
|
||||
Ebenso können einige oder alle vorgegeben werden von: <code>msg.cc</code>, <code>msg.bcc</code>, <code>msg.replyTo</code>,
|
||||
<code>msg.inReplyTo</code>, <code>msg.references</code>, <code>msg.headers</code> oder <code>msg.priority</code>-Eigenschaften.</p>
|
||||
<p>Es kann optional auch <code>msg.from</code> in den Nutzdaten (Payload) vorgegeben werden,
|
||||
was die eingestellte <code>Benutzer-ID</code> überschreiben würde.</p>
|
||||
<h3>Gmail-Benutzer</h3>
|
||||
<p>Beim Zugriff auf Gmail kann es nötig sein, entweder <a target="_new" href="https://support.google.com/mail/answer/185833?hl=de">ein App-Passwort</a> zu aktivieren oder den <a target="_new" href="https://support.google.com/accounts/answer/6010255?hl=de">Zugriff aufs Google-Konto durch weniger sichere Apps</a> über die Google-Konto-Einstellungen zu erlauben.</p>
|
||||
<h3>Details</h3>
|
||||
<p>Die Nachricht in <code>msg.payload</code> kann als HTML formatiert sein.
|
||||
Ein separater, davon abweichender Plaintext kann in <code>msg.plaintext</code> angegeben werden. Ansonsten wird auch <code>msg.payload</code> verwendet.
|
||||
<code>msg.plaintext</code> wird ignoriert, wenn <code>msg.payload</code> kein HTML enthält.</p>
|
||||
<p>Wenn <code>msg.payload</code> ein binärer Buffer ist, so wird sie in einen Nachrichten-Dateianhang (attachment) konvertiert.
|
||||
Der Dateiname sollte mittels <code>msg.filename</code> angegeben werden.
|
||||
Optional kann <code>msg.description</code> als Nachrichtentext hinzugefügt werden.</p>
|
||||
<p>Alternativ kann auch <code>msg.attachments</code> übergeben werden, welches ein Datenfeld (array) mit einen oder mehreren
|
||||
Dateianhängen im <a href="https://nodemailer.com/message/attachments/" target="_new">nodemailer</a>-Format enthält.</p>
|
||||
<p>Falls vom Empfänger benötigt, kann zusätzlich über <code>msg.envelope</code> ein Objekt übergeben werden, welches typischerweise zusätzliche <code>from</code>- und <code>to</code>-Eigenschaften enthält.</p>
|
||||
<p>Wenn ein selbstausgestelltes Zertifikates vorliegt, kann sich Nodemailer darüber beschweren und das Senden der Nachricht ablehnen.
|
||||
In diesem Fall kann versucht werden TLS abzuschalten.</p>
|
||||
<p><b>Hinweis</b>: Verwendet SMTP mit SSL über Port 465.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="e-mail in">
|
||||
<p>Regelmäßiger Abruf von E-Mails von einem POP3- oder IMAP-Server und Weiterleitung der Nachricht, falls diese noch nicht angezeigt wurde.</p>
|
||||
<p>Der Subjekttext wird in <code>msg.topic</code> und der Klartextinhalt in <code>msg.payload</code> abgelegt.
|
||||
Wenn text/html vorliegt, dann wird dieser in <code>msg.html</code> abgelegt.
|
||||
<code>msg.from</code> und <code>msg.date</code> sind ebenfalls für die weitere Nutzung gesetzt.</p>
|
||||
<p>Zusätzlich enthält <code>msg.header</code> den kompletten Mailkopf (Header) als Objekt mit
|
||||
<i>to</i>, <i>cc</i> und anderen eventuell nützlichen Eigenschaften.</p>
|
||||
<p>Der Node kann optional die Nachricht als gelesen markieren (Standard-Einstellung), sie löschen oder sie als unmarkiert belassen.</p>
|
||||
<p>Verwendet wird das <a href="https://github.com/mscdex/node-imap/blob/master/README.md" target="_new">node-imap-Modul</a> -
|
||||
siehe dort für Informationen über das <code>msg.criteria</code>-Format, falls benötigt.</p>
|
||||
<p>Alle Dateianhänge mitgeliefert in eingehenden E-Mails können in der <code>msg.attachments</code>-Eigenschaft gefunden werden.
|
||||
Es wird dann ein Datenfeld (Array) von Objekten übergeben, wo jedes Objekt ein einzelner Dateianhang (attachment) darstellt.
|
||||
Das Objektformat ist:</p>
|
||||
<pre>
|
||||
{
|
||||
contentType: // Die MIME-Inhaltsbeschreibung (MIME content description)
|
||||
fileName: // Ein vorgeschlagener Dateiname, der diesem Anhang zugeordnet ist
|
||||
transferEncoding: // Wie wurde der ursprüngliche E-Mail-Anhang verschlüsselt?
|
||||
contentDisposition: // Unbekannt
|
||||
generatedFileName: // Ein vorgeschlagener Dateiname, der diesem Anhang zugeordnet ist
|
||||
contentId: // Eine eindeutige generierte ID für diesen Anhang
|
||||
checksum: // Eine Prüfsumme gegen die Daten
|
||||
length: // Datengröße in Bytes
|
||||
content: // Der tatsächliche Inhalt der in einem Node.js-Pufferobjekt enthaltenen Daten
|
||||
// Wir können dies in eine base64-Datenzeichenfolge mit content.toString('base64') umwandeln
|
||||
}
|
||||
</pre>
|
||||
<p><b>Hinweis</b>: Bei POP3 sind die Standard-Portnummern 110 für ungesichertes TCP und 995 für SSL. Bei IMAP 143 für ungesichertes TCP und 993 für SSL.</p>
|
||||
<p><b>Hinweis</b>: Das maximale Aktualisierungsintervall ist 2147483 Sekunden (24,8 Tage).</p>
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="e-mail mta">
|
||||
<p>Mail Transfer Agent - Portüberwachung für eingehende SMTP-Mails.</p>
|
||||
<p><b>Hinweis</b>: "NICHT für Produktivbetrieb", da keine Sicherheitsfunktionen eingebaut sind!
|
||||
Dies dient hauptsächlich zum lokalen Testen des Versands ausgehender E-Mails,
|
||||
kann jedoch bei Bedarf verwendet werden als Mail-Weiterleitung an einen echten E-Mail-Dienst.</p>
|
||||
<p>Um Ports unter 1024 (z.B. 25 or 465) zu benutzen, könnten höhere Zugriffsrechte nötig sein.
|
||||
Auf Linux-Systemen kann dieses erreicht werden durch Starten von
|
||||
<pre>sudo setcap 'cap_net_bind_service=+eip' $(which node)</pre>
|
||||
und Neustart von Node-RED.
|
||||
Es ist zu beachten, dass dadurch alle Knotenanwendungen auf alle Ports zugreifen können.</p>
|
||||
</script>
|
67
social/email/locales/de/61-email.json
Normal file
67
social/email/locales/de/61-email.json
Normal file
@ -0,0 +1,67 @@
|
||||
{
|
||||
"email": {
|
||||
"email": "email",
|
||||
"label": {
|
||||
"getmail":"Mailempfang",
|
||||
"auto": "automatisch",
|
||||
"trigger": "wenn getriggert",
|
||||
"to": "An",
|
||||
"server": "Server",
|
||||
"port": "Port",
|
||||
"useSecureConnection": "Sichere Verbindung verwenden",
|
||||
"userid": "Benutzer-ID",
|
||||
"password": "Passwort",
|
||||
"repeat": "alle",
|
||||
"seconds": "Sekunden",
|
||||
"folder": "Verzeichnis",
|
||||
"protocol": "Protokoll",
|
||||
"useSSL": "SSL",
|
||||
"useTLS": "TLS",
|
||||
"disposition": "Behandlung",
|
||||
"none": "Keine",
|
||||
"read": "Gelesen markieren",
|
||||
"delete": "Löschen",
|
||||
"criteria": "Kriterium",
|
||||
"criteriaFromMsg": "Gesetzt durch msg.criteria",
|
||||
"all": "Alle",
|
||||
"answered": "Beantwortet",
|
||||
"flagged": "Markiert",
|
||||
"seen": "Gesichtet",
|
||||
"unanswered": "Unbeantwortet",
|
||||
"unflagged": "Unmarkiert",
|
||||
"unseen": "Ungesehen"
|
||||
},
|
||||
"default-message": "__description__\n\nDatei von Node-RED ist angehängt: __filename__",
|
||||
"tip": {
|
||||
"cred": "<b>Hinweis</b>: Berechtigungen von globaler emailkeys.js-Datei kopiert",
|
||||
"recent": "Tipp: Es wird nur die letzte E-Mail abgerufen",
|
||||
"mta": "<b>Hinweis</b>: Um Ports unter 1024 zu verwenden könnten höhere (root) Rechte benötigt werden. Siehe Hilfe-Seitenleiste."
|
||||
},
|
||||
"status": {
|
||||
"messagesent": "Nachricht gesendet: __response__",
|
||||
"fetching": "Rufe ab",
|
||||
"foldererror": "Fehler bei Verzeichnisabruf",
|
||||
"messageerror": "Fehler bei Nachrichtenabruf",
|
||||
"message": "Nachricht #__number__",
|
||||
"newemail": "Neue E-Mail empfangen: __topic__",
|
||||
"duplicate": "Duplikat nicht gesendet: __topic__",
|
||||
"inboxzero": "Posteingang leer",
|
||||
"sending": "Sende",
|
||||
"sendfail": "Senden fehlgeschlagen",
|
||||
"parseerror": "Analyse der Nachricht fehlgeschlagen",
|
||||
"connecterror": "Verbindungsfehler"
|
||||
},
|
||||
"errors": {
|
||||
"nouserid": "Kein E-Mail-Benutzer-ID angegeben",
|
||||
"nopassword": "Kein E-Mail-Passwort angegeben",
|
||||
"nocredentials": "Keine E-Mail-Berechtigungen gefunden. Siehe Info-Anzeige.",
|
||||
"nosmtptransport": "Kein SMTP-Transport. Siehe Info-Anzeige.",
|
||||
"nopayload": "Keine sendbaren Nutzdaten (Payload)",
|
||||
"fetchfail": "Verzeichnisabruf fehlgeschlagen: __folder__",
|
||||
"parsefail": "Analyse der Nachricht fehlgeschlagen",
|
||||
"messageerror": "Nachrichtenabruf fehlgeschlagen: __error__",
|
||||
"refreshtoolarge": "Abrufintervall ist zu groß. Max. Limit sind 2147483 Sekunden.",
|
||||
"invalidattachment": "Ungültiger Anhang-Inhalt. Es muss ein String oder ein Buffer sein."
|
||||
}
|
||||
}
|
||||
}
|
@ -6,11 +6,13 @@
|
||||
<code>msg.inReplyTo</code>, <code>msg.references</code>, <code>msg.headers</code>, or <code>msg.priority</code> properties.</p>
|
||||
<p>You may optionally set <code>msg.from</code> in the payload which will override the <code>userid</code>
|
||||
default value.</p>
|
||||
<h3>GMail users</h3>
|
||||
<p>If you are accessing GMail you may need to either enable <a target="_new" href="https://support.google.com/mail/answer/185833?hl=en">an application password</a>,
|
||||
<h3>Gmail users</h3>
|
||||
<p>If you are accessing Gmail you may need to either enable <a target="_new" href="https://support.google.com/mail/answer/185833?hl=en">an application password</a>,
|
||||
or enable <a target="_new" href="https://support.google.com/accounts/answer/6010255?hl=en">less secure access</a> via your Google account settings.</p>
|
||||
<h3>Details</h3>
|
||||
<p>The payload can be html format.</p>
|
||||
<p>The payload can be html format. You may supply a separate plaintext version using <code>msg.plaintext</code>.
|
||||
If you don't and <code>msg.payload</code> contains html, it will also be used for the plaintext.
|
||||
<code>msg.plaintext</code> will be ignored if <code>msg.payload</code> doesn't contain html.</p>
|
||||
<p>If the payload is a binary buffer then it will be converted to an attachment.
|
||||
The filename should be set using <code>msg.filename</code>. Optionally <code>msg.description</code> can be added for the body text.</p>
|
||||
<p>Alternatively you may provide <code>msg.attachments</code> which should contain an array of one or
|
||||
@ -21,7 +23,7 @@
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="e-mail in">
|
||||
<p>Repeatedly gets emails from an IMAP server and forwards on as a msg if not already seen.</p>
|
||||
<p>Repeatedly gets emails from a POP3 or IMAP server and forwards on as a msg if not already seen.</p>
|
||||
<p>The subject is loaded into <code>msg.topic</code> and <code>msg.payload</code> is the plain text body.
|
||||
If there is text/html then that is returned in <code>msg.html</code>. <code>msg.from</code> and <code>msg.date</code> are also set if you need them.</p>
|
||||
<p>Additionally <code>msg.header</code> contains the complete header object including
|
||||
@ -29,10 +31,8 @@
|
||||
<p>It can optionally mark the message as Read (default), Delete it, or leave unmarked (None).</p>
|
||||
<p>Uses the <a href="https://github.com/mscdex/node-imap/blob/master/README.md" target="_new">node-imap module</a> - see that page for
|
||||
information on the <code>msg.criteria</code> format if needed.</p>
|
||||
<p><b>Note</b>: uses IMAP with SSL to port 993.</p>
|
||||
<p>Any attachments supplied in the incoming email can be found in the <code>msg.attachments</code> property. This will be an array of objects where
|
||||
each object represents a specific attachments. The format of the object is:</p>
|
||||
|
||||
<pre>
|
||||
{
|
||||
contentType: // The MIME content description
|
||||
@ -47,13 +47,13 @@
|
||||
// We can turn this into a base64 data string with content.toString('base64')
|
||||
}
|
||||
</pre>
|
||||
<p>For POP3, the default port numbers are 110 for plain TCP and 995 for SSL. For IMAP the port numbers are 143 for plain TCP and 993 for SSL.</p>
|
||||
<p>The maximum refresh interval is 2147483 seconds (24.8 days).</p>
|
||||
<p><b>Note</b>: For POP3, the default port numbers are 110 for plain TCP and 995 for SSL. For IMAP the port numbers are 143 for plain TCP and 993 for SSL.</p>
|
||||
<p><b>Note</b>: The maximum refresh interval is 2147483 seconds (24.8 days).</p>
|
||||
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="e-mail mta">
|
||||
<p>Mail Transfer Agent - listens on a port for incoming SMTP mail.</p>
|
||||
<p>Mail Transfer Agent - listens on a port for incoming SMTP mails.</p>
|
||||
<p><b>Note</b>: "NOT for production use" as there is no security built in.
|
||||
This is primarily for local testing of outbound mail sending, but could be used
|
||||
as a mail forwarder to a real email service if required.</p>
|
||||
|
@ -1,14 +1,21 @@
|
||||
{
|
||||
"name": "node-red-node-email",
|
||||
"version": "1.8.3",
|
||||
"version": "1.11.0",
|
||||
"description": "Node-RED nodes to send and receive simple emails.",
|
||||
"dependencies": {
|
||||
"imap": "^0.8.19",
|
||||
"poplib": "^0.1.7",
|
||||
"mailparser": "^3.0.1",
|
||||
"nodemailer": "~6.4.17",
|
||||
"mailparser": "^3.1.0",
|
||||
"nodemailer": "~6.5.0",
|
||||
"smtp-server": "^3.8.0"
|
||||
},
|
||||
"bundledDependencies": [
|
||||
"imap",
|
||||
"poplib",
|
||||
"mailparser",
|
||||
"nodemailer",
|
||||
"smtp-server"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/node-red/node-red-nodes/tree/master/social/email"
|
||||
|
@ -1,4 +1,4 @@
|
||||
<script type="text/x-red" data-template-name="feedparse">
|
||||
<script type="text/html" data-template-name="feedparse">
|
||||
<div class="form-row">
|
||||
<label for="node-input-url"><i class="fa fa-globe"></i> <span data-i18n="feedparse.label.feedurl"></span></label>
|
||||
<input type="text" id="node-input-url">
|
||||
|
15
social/feedparser/locales/de/32-feedparse.html
Normal file
15
social/feedparser/locales/de/32-feedparse.html
Normal file
@ -0,0 +1,15 @@
|
||||
<script type="text/html" data-help-name="feedparse">
|
||||
<p>Überwacht einen RSS/atom-Feed auf neue Einträge.</p>
|
||||
<h3>Outputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>topic <span class="property-type">string</span></dt>
|
||||
<dd>Der originale Artikel-Link</dd>
|
||||
<dt>payload <span class="property-type">string</span></dt>
|
||||
<dd>Beschreibung</dd>
|
||||
<dt>article <span class="property-type">object</span></dt>
|
||||
<dd>Komplettes Artikel-Objekt</dd>
|
||||
</dl>
|
||||
<p>Die <code>msg.article</code>-Eigenschaft enthält das komplette Artikel-Objekt,
|
||||
welches Eigenschaften wie <code>.title</code>, <code>.summary</code>, <code>.date</code> usw. enthält.</p>
|
||||
<p>Das Aktualisierungsintervall kann nicht größer als 35790 Minuten sein (ca. 24,8 Tage).
|
||||
</script>
|
15
social/feedparser/locales/de/32-feedparse.json
Normal file
15
social/feedparser/locales/de/32-feedparse.json
Normal file
@ -0,0 +1,15 @@
|
||||
{
|
||||
"feedparse": {
|
||||
"feedparse": "feedparser",
|
||||
"label": {
|
||||
"feedurl": "Feed-URL",
|
||||
"refresh": "Aktualisierung",
|
||||
"minutes": "Minuten"
|
||||
},
|
||||
"errors": {
|
||||
"badstatuscode": "Fehler - Fehlerhafter Statuscode",
|
||||
"invalidurl": "Ungültige URL",
|
||||
"invalidinterval": "Aktualisierungsintervall zu groß"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,15 @@
|
||||
<script type="text/html" data-help-name="feedparse">
|
||||
<p>Monitors an RSS/atom feed for new entries.</p>
|
||||
<p>The <code>msg.topic</code> contains the original article link. The <code>msg.payload</code>
|
||||
contains the description, and <code>msg.article</code> contains the complete article object,
|
||||
which has properties such as <code>.title</code>, <code>.summary</code>, <code>.date</code> and so on.</p>
|
||||
<p>The Refresh interval cannot be greater than 35790 minutes (approx 24.8 days).
|
||||
<h3>Outputs</h3>
|
||||
<dl class="message-properties">
|
||||
<dt>topic <span class="property-type">string</span></dt>
|
||||
<dd>Original article link</dd>
|
||||
<dt>payload <span class="property-type">string</span></dt>
|
||||
<dd>Description</dd>
|
||||
<dt>article <span class="property-type">object</span></dt>
|
||||
<dd>Complete article object</dd>
|
||||
</dl>
|
||||
<p>The <code>msg.article</code> property contains the complete article object,
|
||||
which has properties such as <code>.title</code>, <code>.summary</code>, <code>.date</code> and so on.</p>
|
||||
<p>The refresh interval cannot be greater than 35790 minutes (approx 24.8 days).
|
||||
</script>
|
||||
|
@ -1,10 +1,10 @@
|
||||
{
|
||||
"name": "node-red-node-feedparser",
|
||||
"version": "0.1.16",
|
||||
"version": "0.2.1",
|
||||
"description": "A Node-RED node to get RSS Atom feeds.",
|
||||
"dependencies": {
|
||||
"feedparser": "^2.2.10",
|
||||
"request": "^2.88.0"
|
||||
"request": "^2.88.2"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -1,5 +1,5 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="irc in">
|
||||
<script type="text/html" data-template-name="irc in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-ircserver"><i class="fa fa-globe"></i> <span data-i18n="irc.label.ircserver"></span></label>
|
||||
<input type="text" id="node-input-ircserver">
|
||||
@ -15,64 +15,6 @@
|
||||
<div class="form-tips"><span data-i18n="[html]irc.tip.in"></span></div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="irc in">
|
||||
<p>Connects to a channel on an IRC server.</p>
|
||||
<p>You may join multiple channels by comma separating a list - #chan1,#chan2,#etc.</p>
|
||||
<p>Any messages on that channel will appear on the <code>msg.payload</code> at the output,
|
||||
while <code>msg.topic</code> will contain who it is from.
|
||||
<code>msg.to</code> contains either the name of the channel or PRIV in the case of a pm.</p>
|
||||
<p>The second output provides a <code>msg.payload</code> that has any status messages such as joins, parts, kicks etc.</p>
|
||||
<p>The type of the status message is set as <code>msg.payload.type</code>.</p>
|
||||
<p>The possible status types are: <br />
|
||||
<table border="1" cellpadding="1" cellspacing="1">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Type</th>
|
||||
<th scope="col">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>message</td>
|
||||
<td>message is sent into the channel</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>pm</td>
|
||||
<td>private message to the bot</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>join</td>
|
||||
<td>a user joined the channel (also triggered when the bot joins a channel)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>invite</td>
|
||||
<td>the bot is being invited to a channel</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>part</td>
|
||||
<td>a user leaves a channel</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>quit</td>
|
||||
<td>a user quits a channel</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>kick</td>
|
||||
<td>a user is kicked from a channel</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>topic</td>
|
||||
<td>a topic has been changed on a joined channel</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>names</td>
|
||||
<td>retrieves the list of users when the bot joins a channel</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('irc in',{
|
||||
category: 'social-input',
|
||||
@ -107,8 +49,7 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/x-red" data-template-name="irc out">
|
||||
<script type="text/html" data-template-name="irc out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-ircserver"><i class="fa fa-globe"></i> <span data-i18n="irc.label.ircserver"></span></label>
|
||||
<input type="text" id="node-input-ircserver">
|
||||
@ -132,15 +73,6 @@
|
||||
<div class="form-tips"><span data-i18n="[html]irc.tip.out"></span></div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="irc out">
|
||||
<p>Sends messages to a channel on an IRC server</p>
|
||||
<p>You can send just the <code>msg.payload</code>, or the complete <code>msg</code> object to the selected channel,
|
||||
or you can select to use <code>msg.topic</code> to send the <code>msg.payload</code> to a specific user (private message) or channel.</p>
|
||||
<p>If multiple output channels are listed (eg. #chan1,#chan2), then the message will be sent to all of them.</p>
|
||||
<p><b>Note:</b> you can only send to channels you have previously joined so they MUST be specified in the node - even if you then decide to use a subset in msg.topic</p>
|
||||
<p>You may send RAW commands using <code>msg.raw</code> - This must contain an array of parameters - eg. <pre>["privmsg","#nodered","Hello world"]</pre></p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('irc out',{
|
||||
category: 'social-output',
|
||||
@ -171,8 +103,7 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/x-red" data-template-name="irc-server">
|
||||
<script type="text/html" data-template-name="irc-server">
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-server"><i class="fa fa-globe"></i> <span data-i18n="irc.label.ircserver"></span></label>
|
||||
<input type="text" id="node-config-input-server" placeholder="irc.freenode.net" style="width: 45%;" >
|
||||
|
44
social/irc/locales/de/91-irc.json
Normal file
44
social/irc/locales/de/91-irc.json
Normal file
@ -0,0 +1,44 @@
|
||||
{
|
||||
"irc": {
|
||||
"label": {
|
||||
"ircserver": "IRC-Server",
|
||||
"channel": "Kanal",
|
||||
"action": "Aktion",
|
||||
"port": "Port",
|
||||
"ssl": "Sichere SSL-Verbindung",
|
||||
"self": "Selbstausgestellte Zertifikate erlauben",
|
||||
"nickname": "Nickname",
|
||||
"username": "Benutzername",
|
||||
"password": "Passwort"
|
||||
},
|
||||
"placeholder": {
|
||||
"ifreq": "wenn vom Server benötigt"
|
||||
},
|
||||
"payload": "Sende Nutzdaten (Payload) an Kanäle",
|
||||
"topic": "Benutze msg.topic um Nicknamen oder Kanäle vorzugeben",
|
||||
"msg": "Sende komplettes msg-Objekt an Kanäle",
|
||||
"tip": {
|
||||
"in": "Der beizutretende Kanal muss mit einer # (Raute) beginnen.<br/>Bei mehreren Kanälen müssen diese mit Kommas getrennt angegeben werden. Z. B. #chan1,#chan2,etc.",
|
||||
"out": "Der beizutretende Kanal muss mit einer # (Raute) beginnen.<br/>Beim Senden eines kompletten Objekt wird es zuvor in Strings umgewandelt."
|
||||
},
|
||||
"errors": {
|
||||
"connect": "Verbinde",
|
||||
"err": "Fehler",
|
||||
"net": "NET",
|
||||
"connected": "Verbunden",
|
||||
"online": "Online",
|
||||
"joined": "Beigetreten",
|
||||
"ping": "Ping von",
|
||||
"quit": "Quit",
|
||||
"restart": "Neustart",
|
||||
"connectionlost": "Verbindung verloren?",
|
||||
"hasjoined": "ist beigetreten",
|
||||
"sentinvite": "Sende Einladung an",
|
||||
"hasleft": "ist ausgetreten",
|
||||
"hasquit": "hat beendet (quit)",
|
||||
"kickedfrom": "wurde gekickt von",
|
||||
"rawcommand": "Rohbefehl",
|
||||
"topicnotset": "msg.topic nicht gesetzt"
|
||||
}
|
||||
}
|
||||
}
|
67
social/irc/locales/en-US/91-irc.html
Normal file
67
social/irc/locales/en-US/91-irc.html
Normal file
@ -0,0 +1,67 @@
|
||||
|
||||
<script type="text/x-red" data-help-name="irc in">
|
||||
<p>Connects to a channel on an IRC server.</p>
|
||||
<p>You may join multiple channels by comma separating a list - #chan1,#chan2,#etc.</p>
|
||||
<p>Any messages on that channel will appear on the <code>msg.payload</code> at the output,
|
||||
while <code>msg.topic</code> will contain who it is from.
|
||||
<code>msg.to</code> contains either the name of the channel or PRIV in the case of a pm.</p>
|
||||
<p>The second output provides a <code>msg.payload</code> that has any status messages such as joins, parts, kicks etc.</p>
|
||||
<p>The type of the status message is set as <code>msg.payload.type</code>.</p>
|
||||
<p>The possible status types are: <br />
|
||||
<table border="1" cellpadding="1" cellspacing="1">
|
||||
<thead>
|
||||
<tr>
|
||||
<th scope="col">Type</th>
|
||||
<th scope="col">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>message</td>
|
||||
<td>message is sent into the channel</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>pm</td>
|
||||
<td>private message to the bot</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>join</td>
|
||||
<td>a user joined the channel (also triggered when the bot joins a channel)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>invite</td>
|
||||
<td>the bot is being invited to a channel</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>part</td>
|
||||
<td>a user leaves a channel</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>quit</td>
|
||||
<td>a user quits a channel</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>kick</td>
|
||||
<td>a user is kicked from a channel</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>topic</td>
|
||||
<td>a topic has been changed on a joined channel</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>names</td>
|
||||
<td>retrieves the list of users when the bot joins a channel</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</p>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="irc out">
|
||||
<p>Sends messages to a channel on an IRC server</p>
|
||||
<p>You can send just the <code>msg.payload</code>, or the complete <code>msg</code> object to the selected channel,
|
||||
or you can select to use <code>msg.topic</code> to send the <code>msg.payload</code> to a specific user (private message) or channel.</p>
|
||||
<p>If multiple output channels are listed (eg. #chan1,#chan2), then the message will be sent to all of them.</p>
|
||||
<p><b>Note:</b> you can only send to channels you have previously joined so they MUST be specified in the node - even if you then decide to use a subset in msg.topic</p>
|
||||
<p>You may send RAW commands using <code>msg.raw</code> - This must contain an array of parameters - eg. <pre>["privmsg","#nodered","Hello world"]</pre></p>
|
||||
</script>
|
@ -1,9 +1,9 @@
|
||||
{
|
||||
"name" : "node-red-node-irc",
|
||||
"version" : "0.0.8",
|
||||
"version" : "0.1.0",
|
||||
"description" : "A Node-RED node to talk to an IRC server",
|
||||
"dependencies" : {
|
||||
"irc" : "~0.4.0"
|
||||
"irc" : "^0.5.2"
|
||||
},
|
||||
"repository" : {
|
||||
"type":"git",
|
||||
|
@ -10,13 +10,6 @@
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-help-name="nnotify">
|
||||
<p>Uses node-notifier to provide a desktop popup containing the <code>msg.payload</code>. Only useful on the local machine.</p>
|
||||
<p>Optionally uses <code>msg.topic</code> as the title, and <code>msg.icon</code> as the full path to an icon file to display.</p>
|
||||
<p>Uses node-notifier so should work cross platform but may need to intall pre-reqs... see <i><a href="https://www.npmjs.com/package/node-notifier" target="_new">this link.</a></i></p>
|
||||
<p>If installing on Windows you MUST read the install instructions... or it WILL NOT work.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('nnotify',{
|
||||
category: 'output',
|
||||
|
7
social/notify/locales/en-US/57-notify.html
Normal file
7
social/notify/locales/en-US/57-notify.html
Normal file
@ -0,0 +1,7 @@
|
||||
|
||||
<script type="text/x-red" data-help-name="nnotify">
|
||||
<p>Uses node-notifier to provide a desktop popup containing the <code>msg.payload</code>. Only useful on the local machine.</p>
|
||||
<p>Optionally uses <code>msg.topic</code> as the title, and <code>msg.icon</code> as the full path to an icon file to display.</p>
|
||||
<p>Uses node-notifier so should work cross platform but may need to intall pre-reqs... see <i><a href="https://www.npmjs.com/package/node-notifier" target="_new">this link.</a></i></p>
|
||||
<p>If installing on Windows you MUST read the install instructions... or it WILL NOT work.</p>
|
||||
</script>
|
@ -82,7 +82,10 @@
|
||||
<p><code>msg.attachment</code>: attach an image (Buffer or file path)</p>
|
||||
<p><code>msg.url</code>: to add a web address</p>
|
||||
<p><code>msg.url_title</code>: to add a url title if not already set in the properties</p>
|
||||
<p><code>msg.html</code>: set to true or 1 if message is HTML formatted, <i><a href="https://pushover.net/api#html" target="_new">see the supported tags</a></i></p>
|
||||
<p><code>msg.sound</code>: set the notification sound, <i><a href="https://pushover.net/api#sounds" target="_new">see the available options</a></i></p>
|
||||
<p><code>msg.retry</code>: set retry interval for Emergency priority (2) messages, <i><a href="https://pushover.net/api#priority" target="_new">see details</a></i></p>
|
||||
<p><code>msg.expire</code>: set retry duration for Emergency priority (2) messages, <i><a href="https://pushover.net/api#priority" target="_new">see details</a></i></p>
|
||||
<p>Uses Pushover. See <i><a href="https://pushover.net" target="_new">this link</a></i> for more details.</p>
|
||||
</script>
|
||||
|
||||
|
@ -37,12 +37,30 @@ module.exports = function(RED) {
|
||||
var sound = node.sound || msg.sound || null;
|
||||
var url = node.url || msg.url || null;
|
||||
var url_title = node.url_title || msg.url_title || null;
|
||||
var html = node.html || false;
|
||||
var html = node.html || msg.html || false;
|
||||
var attachment = msg.attachment || null;
|
||||
var retry = msg.retry || 30;
|
||||
var expire = msg.expire || 600;
|
||||
if (isNaN(pri)) {pri=0;}
|
||||
if (pri > 2) {pri = 2;}
|
||||
if (pri < -2) {pri = -2;}
|
||||
if (!msg.payload) { msg.payload = ""; }
|
||||
if (isNaN(retry)) {
|
||||
retry = 30;
|
||||
node.warn("No valid number for retry found, using default 30s retry interval");
|
||||
}
|
||||
if (isNaN(expire)) {
|
||||
expire = 600;
|
||||
node.warn("No valid number for expire time found, using default 600s retry duration");
|
||||
}
|
||||
if (retry < 30) {
|
||||
retry = 30;
|
||||
node.warn("Retry interval too low, using minimal 30s retry interval");
|
||||
}
|
||||
if (expire > 10800) {
|
||||
expire = 10800;
|
||||
node.warn("Expire time too high, using maximum setting of 10800s (3 hours) retry duration");
|
||||
}
|
||||
if (typeof msg.payload === 'undefined') { msg.payload = "(undefined msg.payload)"; }
|
||||
if (typeof(msg.payload) === 'object') {
|
||||
msg.payload = JSON.stringify(msg.payload);
|
||||
}
|
||||
@ -52,8 +70,8 @@ module.exports = function(RED) {
|
||||
message: msg.payload,
|
||||
title: title,
|
||||
priority: pri,
|
||||
retry: 30,
|
||||
expire: 600,
|
||||
retry: retry,
|
||||
expire: expire,
|
||||
html: html
|
||||
};
|
||||
if (dev) { pushmsg.device = dev; }
|
||||
|
@ -24,7 +24,10 @@ Optionally uses `msg.topic` to set the configuration, if not already set in the
|
||||
- `msg.attachment`: to specify an image to attach to message (path as a string or Buffer containing image)
|
||||
- `msg.url`: to add a web address
|
||||
- `msg.url_title`: to add a url title
|
||||
- `msg.html`: set to true or 1 if message is HTML formatted, see the [supported tags](https://pushover.net/api#html)
|
||||
- `msg.sound`: to set the alert sound, see the [available options](https://pushover.net/api#sounds)
|
||||
- `msg.retry`: to set retry interval for Emergency priority (2) messages, see [priority](https://pushover.net/api#priority)
|
||||
- `msg.expire`: to set retry duration for Emergency priority (2) messages, see [priority](https://pushover.net/api#priority)
|
||||
|
||||
The User-key and API-token are stored in a separate credentials file.
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name" : "node-red-node-pushover",
|
||||
"version" : "0.0.20",
|
||||
"version" : "0.0.24",
|
||||
"description" : "A Node-RED node to send alerts via Pushover",
|
||||
"dependencies" : {
|
||||
"pushover-notifications" : "^1.2.2"
|
||||
|
@ -1,4 +1,4 @@
|
||||
<script type="text/x-red" data-template-name="twitter-credentials">
|
||||
<script type="text/html" data-template-name="twitter-credentials">
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-screen_name"><i class="fa fa-twitter"></i> <span data-i18n="twitter.label.twitter-id"></span></label>
|
||||
<i class="fa fa-at"></i> <input type="text" id="node-config-input-screen_name">
|
||||
@ -74,7 +74,7 @@
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="twitter in">
|
||||
<script type="text/html" data-template-name="twitter in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-twitter"><i class="fa fa-user"></i> <span data-i18n="twitter.label.twitter-id"></span></label>
|
||||
<input type="text" id="node-input-twitter">
|
||||
@ -167,7 +167,7 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/x-red" data-template-name="twitter out">
|
||||
<script type="text/html" data-template-name="twitter out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-twitter"><i class="fa fa-user"></i> <span data-i18n="twitter.label.twitter-id"></span></label>
|
||||
<input type="text" id="node-input-twitter">
|
||||
|
54
social/twitter/locales/de/27-twitter.json
Normal file
54
social/twitter/locales/de/27-twitter.json
Normal file
@ -0,0 +1,54 @@
|
||||
{
|
||||
"twitter": {
|
||||
"label": {
|
||||
"twitter-id": "Twitter-ID",
|
||||
"search": "Suche",
|
||||
"for": "nach",
|
||||
"user": "Benutzer",
|
||||
"dmslabel": "DMs",
|
||||
"followers": "Verfolgt von",
|
||||
"tweetslabel": "Tweets",
|
||||
"eventslabel": "Ereignisse",
|
||||
"create": "Eigene Applikation erstellen auf Seite",
|
||||
"copy-consumer": "Consumer API keys vom 'Keys und Tokens' Abschnitt hierher kopieren",
|
||||
"consumer_key": "API key",
|
||||
"consumer_secret": "API secret key",
|
||||
"copy-accessToken": "Neue 'Access token & access token secret' erzeugen und hierher kopieren",
|
||||
"access_key": "Access token",
|
||||
"access_secret": "Access token secret",
|
||||
"enter-id": "Setze Deine Twitter-ID"
|
||||
},
|
||||
"placeholder": {
|
||||
"for": "Komma-getrennte Wörter, @ids, #tags",
|
||||
"user": "Komma-getrennte @twitter handles"
|
||||
},
|
||||
"search": {
|
||||
"public": "alle öffentlichen Tweets",
|
||||
"follow": "alle Tweets von Usern, denen ich folge",
|
||||
"user": "Tweets bestimmter User",
|
||||
"direct": "meine direkten Nachrichten",
|
||||
"events": "meine Twitter-Ereignisse"
|
||||
},
|
||||
"tip": "Tipp: Nur Kommas ohne Leerzeichen zwischen mehreren Suchbegriffen verwenden. Komma = ODER, Leerzeichen = UND.<br/>Die Twitter-API wird nicht 100% aller Tweets liefern.<br/>Tweets von gefolgten Usern enthalten ihre Retweets und Favoriten.<br/>Das <b>nach</b>-Feld leer lassen, um es durch msg.payload setzen zu können.",
|
||||
"status": {
|
||||
"using-geo": "Benutze Geo-Lokation: __location__",
|
||||
"tweeting": "Tweeting",
|
||||
"failed": "Fehlgeschlagen"
|
||||
},
|
||||
"warn": {
|
||||
"nousers": "User-Option ausgewählt, aber keine User angegeben",
|
||||
"waiting": "Warte auf Suchbegriff"
|
||||
},
|
||||
"errors": {
|
||||
"ratelimit": "Ratenlimit erfolgt",
|
||||
"limitrate": "Begrenze Rate",
|
||||
"streamerror": "Stream-Fehler: __error__ (__rc__)",
|
||||
"unexpectedend": "Stream unerwartet beendet",
|
||||
"invalidtag": "Ungültige Tag-Eigenschaft",
|
||||
"missingcredentials": "Fehlende Twitter-Berechtigungen",
|
||||
"truncated": "Tweet abgeschnitten nach mehr als 280 Zeichen",
|
||||
"sendfail": "Tweet-Senden fehlgeschlagen: __error__",
|
||||
"nopayload": "Keine Nutzdaten (Payload) zu tweeten"
|
||||
}
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red-node-twitter",
|
||||
"version": "1.1.7",
|
||||
"version": "1.2.0",
|
||||
"description": "A Node-RED node to talk to Twitter",
|
||||
"dependencies": {
|
||||
"twitter-ng": "0.6.2",
|
||||
|
@ -13,10 +13,18 @@
|
||||
<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" id="node-room-pwd">
|
||||
<label for="node-input-password"><i class="fa fa-lock"></i> Password</label>
|
||||
<input type="password" id="node-input-password" placeholder="optional room password">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
</div>
|
||||
<div class="form-tips"><b>Note:</b> By leaving Buddy empty and ticking "Is a chat room",
|
||||
the node will try to listen to all the rooms the user has access to.
|
||||
You can specify multiple rooms by separating them by a :
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="xmpp in">
|
||||
@ -37,6 +45,9 @@
|
||||
to: {value:""},
|
||||
join: {value:false}
|
||||
},
|
||||
credentials: {
|
||||
password: {type:"password"}
|
||||
},
|
||||
inputs:0,
|
||||
outputs:2,
|
||||
icon: "xmpp.png",
|
||||
@ -45,6 +56,16 @@
|
||||
},
|
||||
labelStyle: function() {
|
||||
return (this.name)?"node_label_italic":"";
|
||||
},
|
||||
oneditprepare: function() {
|
||||
$('#node-input-join').change(function() {
|
||||
if ($("#node-input-join").is(':checked') && $("#node-input-to").val() && $("#node-input-to").val().indexOf(':') === -1) { $("#node-room-pwd").show(); }
|
||||
else { $("#node-room-pwd").hide(); }
|
||||
});
|
||||
$('#node-input-to').change(function() {
|
||||
if ($("#node-input-join").is(':checked') && $("#node-input-to").val() && $("#node-input-to").val().indexOf(':') === -1) { $("#node-room-pwd").show(); }
|
||||
else { $("#node-room-pwd").hide(); }
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@ -69,6 +90,10 @@
|
||||
<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" id="node-room-pwd">
|
||||
<label for="node-input-password"><i class="fa fa-lock"></i> Password</label>
|
||||
<input type="password" id="node-input-password" placeholder="optional room password">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
|
||||
<input type="text" id="node-input-name" placeholder="Name">
|
||||
@ -79,7 +104,6 @@
|
||||
<script type="text/html" data-help-name="xmpp out">
|
||||
<p>Connects to an XMPP server to send messages.</p>
|
||||
<p>The <b>To</b> field is optional. If not set the <code>msg.topic</code> property of the message is used.</p>
|
||||
<p>If you are joining a room then the <b>To</b> field must be supplied.</p>
|
||||
<p>You may also send a msg with <code>msg.presence</code> to set your presence to one of <i>chat, away, dnd</i> or <i>xa</i>.
|
||||
If you do so then the <code>msg.payload</code> will set your status message.</p>
|
||||
</script>
|
||||
@ -95,6 +119,9 @@
|
||||
join: {value:false},
|
||||
sendObject: {value:false}
|
||||
},
|
||||
credentials: {
|
||||
password: {type:"password"}
|
||||
},
|
||||
inputs:1,
|
||||
outputs:0,
|
||||
icon: "xmpp.png",
|
||||
@ -104,6 +131,16 @@
|
||||
},
|
||||
labelStyle: function() {
|
||||
return (this.name)?"node_label_italic":"";
|
||||
},
|
||||
oneditprepare: function() {
|
||||
$('#node-input-join').change(function() {
|
||||
if ($("#node-input-join").is(':checked') && $("#node-input-to").val() && $("#node-input-to").val().indexOf(':') === -1) { $("#node-room-pwd").show(); }
|
||||
else { $("#node-room-pwd").hide(); }
|
||||
});
|
||||
$('#node-input-to').change(function() {
|
||||
if ($("#node-input-join").is(':checked') && $("#node-input-to").val() && $("#node-input-to").val().indexOf(':') === -1) { $("#node-room-pwd").show(); }
|
||||
else { $("#node-room-pwd").hide(); }
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
@ -124,7 +161,7 @@
|
||||
<input type="text" id="node-config-input-nickname" placeholder="Joe (optional)">
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-pass"><i class="fa fa-lock"></i> Password</label>
|
||||
<label for="node-config-input-password"><i class="fa fa-lock"></i> Password</label>
|
||||
<input type="password" id="node-config-input-password">
|
||||
</div>
|
||||
</script>
|
||||
|
@ -15,13 +15,13 @@ module.exports = function(RED) {
|
||||
if ("undefined" === typeof n.server || n.server === "") {
|
||||
this.server = n.user.split('@')[1];
|
||||
}
|
||||
else{
|
||||
else {
|
||||
this.server = n.server;
|
||||
}
|
||||
if ("undefined" === typeof n.port || n.port === "") {
|
||||
this.port = 5222;
|
||||
}
|
||||
else{
|
||||
else {
|
||||
this.port = parseInt(n.port);
|
||||
}
|
||||
|
||||
@ -50,6 +50,8 @@ module.exports = function(RED) {
|
||||
this.connected = false;
|
||||
// store the nodes that have us as config so we know when to tear it all down.
|
||||
this.users = {};
|
||||
// store the chatrooms (MUC) that we've joined (sent "presence" XML to) already
|
||||
this.MUCs = {};
|
||||
// helper variable, because "this" changes definition inside a callback
|
||||
var that = this;
|
||||
|
||||
@ -57,7 +59,7 @@ module.exports = function(RED) {
|
||||
this.register = function(xmppThat) {
|
||||
if (RED.settings.verbose || LOGITALL) {that.log("registering "+xmppThat.id); }
|
||||
that.users[xmppThat.id] = xmppThat;
|
||||
// So we could start the connection here, but we already have the logic in the thats.
|
||||
// So we could start the connection here, but we already have the logic in the nodes that takes care of that.
|
||||
// if (Object.keys(that.users).length === 1) {
|
||||
// this.client.start();
|
||||
// }
|
||||
@ -73,7 +75,8 @@ module.exports = function(RED) {
|
||||
if (Object.keys(that.users).length === 0) {
|
||||
if (that.client && that.client.connected) {
|
||||
return that.client.stop(done);
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
return done();
|
||||
}
|
||||
}
|
||||
@ -82,6 +85,7 @@ module.exports = function(RED) {
|
||||
|
||||
// store the last node to use us, in case we get an error back
|
||||
this.lastUsed = undefined;
|
||||
|
||||
// function for a node to tell us it has just sent a message to our server
|
||||
// so we know which node to blame if it all goes Pete Tong
|
||||
this.used = function(xmppThat) {
|
||||
@ -89,11 +93,11 @@ module.exports = function(RED) {
|
||||
that.lastUsed = xmppThat;
|
||||
}
|
||||
|
||||
|
||||
// Some errors come back as a message :-(
|
||||
// this means we need to figure out which node might have sent it
|
||||
// we also deal with subscriptions (i.e. presence information) here
|
||||
this.client.on('stanza', async (stanza) =>{
|
||||
this.client.on('stanza', async (stanza) => {
|
||||
//console.log("STANZA",stanza.toString())
|
||||
if (stanza.is('message')) {
|
||||
if (stanza.attrs.type == 'error') {
|
||||
if (RED.settings.verbose || LOGITALL) {
|
||||
@ -103,23 +107,27 @@ module.exports = function(RED) {
|
||||
var err = stanza.getChild('error');
|
||||
if (err) {
|
||||
var textObj = err.getChild('text');
|
||||
var text = "node-red:common.status.error";
|
||||
if ("undefined" !== typeof textObj) {
|
||||
var text = "error";
|
||||
if (typeof textObj !== "undefined") {
|
||||
text = textObj.getText();
|
||||
}
|
||||
else{
|
||||
textObj = err.getChild('code');
|
||||
if ("undefined" !== typeof textObj) {
|
||||
text = textObj.getText();
|
||||
else {
|
||||
textObj = err.getAttr('code');
|
||||
if (typeof textObj !== "undefined") {
|
||||
text = textObj;
|
||||
}
|
||||
}
|
||||
if (RED.settings.verbose || LOGITALL) {that.log("Culprit: "+that.lastUsed); }
|
||||
if ("undefined" !== typeof that.lastUsed) {
|
||||
that.lastUsed.status({fill:"red",shape:"ring",text:text});
|
||||
that.lastUsed.warn(text);
|
||||
if (RED.settings.verbose || LOGITALL) {that.log("Culprit: "+that.lastUsed.id); }
|
||||
if (typeof that.lastUsed !== "undefined") {
|
||||
that.lastUsed.status({fill:"yellow",shape:"dot",text:"warning. "+text});
|
||||
that.lastUsed.warn("Warning. "+text);
|
||||
if (that.lastUsed.join) {
|
||||
// it was trying to MUC things up
|
||||
clearMUC(that);
|
||||
}
|
||||
}
|
||||
if (RED.settings.verbose || LOGITALL) {
|
||||
that.log("We did wrong: "+text);
|
||||
that.log("We did wrong: Error "+text);
|
||||
that.log(stanza);
|
||||
}
|
||||
|
||||
@ -144,6 +152,24 @@ module.exports = function(RED) {
|
||||
that.log("Was told we've "+stanza.attrs.type+" from "+stanza.attrs.from+" but we don't really care");
|
||||
}
|
||||
}
|
||||
if (stanza.attrs.to && stanza.attrs.to.indexOf(that.jid) !== -1) {
|
||||
var _x = stanza.getChild("x")
|
||||
if (_x !== undefined) {
|
||||
var _stat = _x.getChildren("status");
|
||||
for (var i = 0; i<_stat.length; i++) {
|
||||
if (_stat[i].attrs.code == 201) {
|
||||
if (RED.settings.verbose || LOGITALL) {that.log("created new room"); }
|
||||
var stanza = xml('iq',
|
||||
{type:'set', id:that.id, from:that.jid, to:stanza.attrs.from.split('/')[0]},
|
||||
xml('query', 'http://jabber.org/protocol/muc#owner',
|
||||
xml('x', {xmlns:'jabber:x:data', type:'submit'})
|
||||
)
|
||||
);
|
||||
that.client.send(stanza);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (stanza.is('iq')) {
|
||||
if (RED.settings.verbose || LOGITALL) {that.log("got an iq query"); }
|
||||
@ -154,17 +180,9 @@ module.exports = function(RED) {
|
||||
that.lastUsed.warn(stanza.getChild('error'));
|
||||
}
|
||||
}
|
||||
else if (stanza.attrs.type === 'result') {
|
||||
// AM To-Do check for 'bind' result with our current jid
|
||||
var query = stanza.getChild('query');
|
||||
if (RED.settings.verbose || LOGITALL) {that.log("result!"); }
|
||||
if (RED.settings.verbose || LOGITALL) {that.log(query); }
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// We shouldn't have any errors here that the input/output nodes can't handle
|
||||
// if you need to see everything though; uncomment this block
|
||||
// this.client.on('error', err => {
|
||||
@ -189,8 +207,12 @@ module.exports = function(RED) {
|
||||
|
||||
// gets called when the node is destroyed, e.g. if N-R is being stopped.
|
||||
this.on("close", async done => {
|
||||
if (that.client.connected) {
|
||||
await that.client.send(xml('presence', {type: 'unavailable'}));
|
||||
const rooms = Object.keys(this.MUCs)
|
||||
for (const room of rooms) {
|
||||
await that.client.send(xml('presence', {to:room, type:'unavailable'}));
|
||||
}
|
||||
if (that.connected) {
|
||||
await that.client.send(xml('presence', {type:'unavailable'}));
|
||||
try{
|
||||
if (RED.settings.verbose || LOGITALL) {
|
||||
that.log("Calling stop() after close, status is "+that.client.status);
|
||||
@ -211,6 +233,103 @@ module.exports = function(RED) {
|
||||
}
|
||||
});
|
||||
|
||||
function getItems(thing,id,xmpp) {
|
||||
// Now try to get a list of all items/conference rooms available on this server
|
||||
var stanza = xml('iq',
|
||||
{type:'get', id:id, to:thing},
|
||||
xml('query', 'http://jabber.org/protocol/disco#items')
|
||||
);
|
||||
xmpp.send(stanza);
|
||||
}
|
||||
|
||||
function joinMUC(node, xmpp, name) {
|
||||
// the presence with the muc x element signifies we want to join the muc
|
||||
// if we want to support passwords, we need to add that as a child of the x element
|
||||
// (third argument to the x/muc/children )
|
||||
// We also turn off chat history (maxstanzas 0) because that's not what this node is about.
|
||||
// Yes, there's a race condition, but it's not a huge problem to send two messages
|
||||
// so we don't care.
|
||||
var mu = name.split("/")[0];
|
||||
if (mu in node.serverConfig.MUCs) {
|
||||
if (RED.settings.verbose || LOGITALL) { node.log("already joined MUC "+name); }
|
||||
}
|
||||
else {
|
||||
var stanza = xml('presence',
|
||||
{"to":name},
|
||||
xml("x",'http://jabber.org/protocol/muc',
|
||||
xml("history", {maxstanzas:0, seconds:1}) // We don't want any history
|
||||
)
|
||||
);
|
||||
if (node.hasOwnProperty("credentials") && node.credentials.hasOwnProperty("password")) {
|
||||
stanza = xml('presence',
|
||||
{"to":name},
|
||||
xml("x",'http://jabber.org/protocol/muc',
|
||||
xml("history", {maxstanzas:0, seconds:1}), // We don't want any history
|
||||
xml("password", {}, node.credentials.password) // Add the password
|
||||
)
|
||||
);
|
||||
}
|
||||
node.serverConfig.used(node);
|
||||
node.serverConfig.MUCs[mu] = "joined";
|
||||
if (RED.settings.verbose || LOGITALL) { node.log("JOINED "+mu); }
|
||||
xmpp.send(stanza);
|
||||
}
|
||||
}
|
||||
|
||||
function clearMUC(config) {
|
||||
//something has happened, so clear out our presence indicators
|
||||
if (RED.settings.verbose || LOGITALL) {
|
||||
config.log("cleared all MUC membership");
|
||||
}
|
||||
config.MUCs = {};
|
||||
}
|
||||
|
||||
// separated out since we want the same functionality from both in and out nodes
|
||||
function errorHandler(node, err){
|
||||
if (!node.quiet) {
|
||||
node.quiet = true;
|
||||
// if the error has a "stanza" then we've probably done something wrong and the
|
||||
// server is unhappy with us
|
||||
if (err.hasOwnProperty("stanza")) {
|
||||
if (err.stanza.name === 'stream:error') { node.error("stream:error - bad login id/pwd ?",err); }
|
||||
else { node.error(err.stanza.name,err); }
|
||||
node.status({fill:"red",shape:"ring",text:"bad login"});
|
||||
}
|
||||
// The error might be a string
|
||||
else if (err == "TimeoutError") {
|
||||
// OK, this happens with OpenFire, suppress it, but invalidate MUC membership as it will need to be re-established.
|
||||
clearMUC(node.serverConfig);
|
||||
node.status({fill:"grey",shape:"dot",text:"TimeoutError"});
|
||||
node.log("Timed out! ",err);
|
||||
// node.status({fill:"red",shape:"ring",text:"XMPP timeout"});
|
||||
}
|
||||
else if (err === "XMPP authentication failure") {
|
||||
node.error(err,err);
|
||||
node.status({fill:"red",shape:"ring",text:"XMPP authentication failure"});
|
||||
}
|
||||
// or it might have a name that tells us what's wrong
|
||||
else if (err.name === "SASLError") {
|
||||
node.error("Authorization error! "+err.condition,err);
|
||||
node.status({fill:"red",shape:"ring",text:"XMPP authorization failure"});
|
||||
}
|
||||
// or it might have the errno set.
|
||||
else if (err.errno === "ETIMEDOUT") {
|
||||
node.error("Timeout connecting to server",err);
|
||||
node.status({fill:"red",shape:"ring",text:"timeout"});
|
||||
}
|
||||
else if (err.errno === "ENOTFOUND") {
|
||||
node.error("Server doesn't exist "+node.serverConfig.server,err);
|
||||
node.status({fill:"red",shape:"ring",text:"bad address"});
|
||||
}
|
||||
// nothing we've seen before!
|
||||
else {
|
||||
node.error("Unknown error: "+err,err);
|
||||
node.status({fill:"red",shape:"ring",text:"error"});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function XmppInNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.server = n.server;
|
||||
@ -219,9 +338,27 @@ module.exports = function(RED) {
|
||||
this.join = n.join || false;
|
||||
this.sendAll = n.sendObject;
|
||||
// Yes, it's called "from", don't ask me why; I don't know why
|
||||
this.from = n.to || "";
|
||||
// (because it's where you are asking to get messages from...)
|
||||
this.from = ((n.to || "").split(':')).map(s => s.trim());
|
||||
this.quiet = false;
|
||||
this.subject = {};
|
||||
// MUC == Multi-User-Chat == chatroom
|
||||
//this.muc = this.join && (this.from !== "")
|
||||
var node = this;
|
||||
|
||||
var joinrooms = function() {
|
||||
if (node.from[0] === "") {
|
||||
// try to get list of all rooms and join them all.
|
||||
getItems(node.serverConfig.server, node.serverConfig.id, xmpp);
|
||||
}
|
||||
else {
|
||||
// if we want to use a chatroom, we need to tell the server we want to join it
|
||||
for (var i=0; i<node.from.length; i++) {
|
||||
joinMUC(node, xmpp, node.from[i]+'/'+node.nick);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var xmpp = this.serverConfig.client;
|
||||
|
||||
/* connection states
|
||||
@ -237,29 +374,30 @@ module.exports = function(RED) {
|
||||
disconnect: Socket is disconnected
|
||||
*/
|
||||
|
||||
// if we're already connected, then do the actions now, otherwise register a callback
|
||||
// if (xmpp.status === "online") {
|
||||
// node.status({fill:"green",shape:"dot",text:"connected"});
|
||||
// if (node.muc) {
|
||||
// joinMUC(node, xmpp, node.from+'/'+node.nick);
|
||||
// }
|
||||
// }
|
||||
// sod it, register it anyway, that way things will work better on a reconnect:
|
||||
xmpp.on('online', async address => {
|
||||
node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"});
|
||||
if ((node.join) && (node.from !== "")) {
|
||||
var to = node.from+'/'+node.nick;
|
||||
// the presence with the muc x element signifies we want to join the muc
|
||||
// if we want to support passwords, we need to add that as a child of the x element
|
||||
// (third argument to the x/muc/children )
|
||||
// We also turn off chat history (maxstanzas 0) because that's not what this node is about.
|
||||
var stanza = xml('presence',
|
||||
{"to": to},
|
||||
xml("x",'http://jabber.org/protocol/muc'),
|
||||
{ maxstanzas:0, seconds:1 }
|
||||
);
|
||||
node.serverConfig.used(node);
|
||||
xmpp.send(stanza).catch(error => {node.warn("Got error when sending presence: "+error)});
|
||||
node.quiet = false;
|
||||
node.status({fill:"green",shape:"dot",text:"connected"});
|
||||
if (node.join) {
|
||||
node.jointick = setInterval(function() { joinrooms(); }, 60000);
|
||||
joinrooms();
|
||||
}
|
||||
});
|
||||
|
||||
xmpp.on('connecting', async address => {
|
||||
node.status({fill:"grey",shape:"dot",text:"node-red:common.status.connecting"});
|
||||
if (!node.quiet) {
|
||||
node.status({fill:"grey",shape:"dot",text:"connecting"});
|
||||
}
|
||||
});
|
||||
xmpp.on('connect', async address => {
|
||||
node.status({fill:"grey",shape:"dot",text:"node-red:common.status.connected"});
|
||||
node.status({fill:"grey",shape:"dot",text:"connected"});
|
||||
});
|
||||
xmpp.on('opening', async address => {
|
||||
node.status({fill:"grey",shape:"dot",text:"opening"});
|
||||
@ -271,7 +409,7 @@ module.exports = function(RED) {
|
||||
node.status({fill:"grey",shape:"dot",text:"closing"});
|
||||
});
|
||||
xmpp.on('close', async address => {
|
||||
node.status({fill:"grey",shape:"dot",text:"closed"});
|
||||
node.status({fill:"grey",shape:"ring",text:"closed"});
|
||||
});
|
||||
xmpp.on('disconnecting', async address => {
|
||||
node.status({fill:"grey",shape:"dot",text:"disconnecting"});
|
||||
@ -281,57 +419,29 @@ module.exports = function(RED) {
|
||||
// Should we listen on other's status (chatstate) or a chatroom state (groupbuddy)?
|
||||
xmpp.on('error', err => {
|
||||
if (RED.settings.verbose || LOGITALL) { node.log("XMPP Error: "+err); }
|
||||
if (err.hasOwnProperty("stanza")) {
|
||||
if (err.stanza.name === 'stream:error') { node.error("stream:error - bad login id/pwd ?",err); }
|
||||
else { node.error(err.stanza.name,err); }
|
||||
node.status({fill:"red",shape:"ring",text:"bad login"});
|
||||
}
|
||||
else {
|
||||
if (err.errno === "ETIMEDOUT") {
|
||||
node.error("Timeout connecting to server",err);
|
||||
node.status({fill:"red",shape:"ring",text:"timeout"});
|
||||
}
|
||||
if (err.errno === "ENOTFOUND") {
|
||||
node.error("Server doesn't exist "+xmpp.options.service,err);
|
||||
node.status({fill:"red",shape:"ring",text:"bad address"});
|
||||
}
|
||||
else if (err === "XMPP authentication failure") {
|
||||
node.error("Authentication failure! "+err,err);
|
||||
node.status({fill:"red",shape:"ring",text:"XMPP authentication failure"});
|
||||
}
|
||||
else if (err.name === "SASLError") {
|
||||
node.error("Authorization error! "+err.condition,err);
|
||||
node.status({fill:"red",shape:"ring",text:"XMPP authorization failure"});
|
||||
}
|
||||
else if (err == "TimeoutError") {
|
||||
// Suppress it!
|
||||
node.warn("Timed out! ");
|
||||
node.status({fill:"grey",shape:"dot",text:"opening"});
|
||||
//node.status({fill:"red",shape:"ring",text:"XMPP timeout"});
|
||||
}
|
||||
else {
|
||||
node.error(err,err);
|
||||
node.status({fill:"red",shape:"ring",text:"node-red:common.status.error"});
|
||||
}
|
||||
}
|
||||
errorHandler(node, err);
|
||||
});
|
||||
|
||||
// Meat of it, a stanza object contains chat messages (and other things)
|
||||
xmpp.on('stanza', async (stanza) =>{
|
||||
// node.log("Received stanza");
|
||||
if (RED.settings.verbose || LOGITALL) {node.log(stanza); }
|
||||
xmpp.on('stanza', async (stanza) => {
|
||||
if (RED.settings.verbose || LOGITALL) { node.log(stanza); }
|
||||
if (stanza.is('message')) {
|
||||
var subj = stanza.getChild("subject");
|
||||
if (subj) {
|
||||
subj = subj.getText();
|
||||
if (subj.trim() !== "") { node.subject[stanza.attrs.from.split('/')[0]] = subj; }
|
||||
}
|
||||
if (stanza.attrs.type == 'chat') {
|
||||
var body = stanza.getChild('body');
|
||||
if (body) {
|
||||
var msg = { payload:body.getText() };
|
||||
var msg = { payload:body.getText(), subject:node.subject[stanza.attrs.from.split('/')[0]] };
|
||||
var ids = stanza.attrs.from.split('/');
|
||||
if (ids[1].length !== 36) {
|
||||
msg.topic = stanza.attrs.from
|
||||
}
|
||||
else { msg.topic = ids[0]; }
|
||||
// if (RED.settings.verbose || LOGITALL) {node.log("Received a message from "+stanza.attrs.from); }
|
||||
if (!node.join && ((node.from === "") || (node.from === stanza.attrs.to))) {
|
||||
// if (RED.settings.verbose || LOGITALL) { node.log("Received a message from "+stanza.attrs.from); }
|
||||
if (!node.join && ((node.from[0] === "") || (node.from.includes(stanza.attrs.to)))) {
|
||||
node.send([msg,null]);
|
||||
}
|
||||
}
|
||||
@ -340,42 +450,74 @@ module.exports = function(RED) {
|
||||
const parts = stanza.attrs.from.split("/");
|
||||
var conference = parts[0];
|
||||
var from = parts[1];
|
||||
var msg = { topic:from, room:conference, subject:node.subject[stanza.attrs.from.split('/')[0]] };
|
||||
var body = stanza.getChild('body');
|
||||
var payload = "";
|
||||
if ("undefined" !== typeof body) {
|
||||
payload = body.getText();
|
||||
}
|
||||
var msg = { topic:from, payload:payload, room:conference };
|
||||
if (stanza.attrs.from != node.nick) {
|
||||
if ((node.join) && (node.from === conference)) {
|
||||
if (typeof body !== "undefined") {
|
||||
msg.payload = body.getText();
|
||||
//if (from && stanza.attrs.from != node.nick && from != node.nick) {
|
||||
if (from && node.join && (node.from[0] === "" || node.from.includes(conference))) {
|
||||
node.send([msg,null]);
|
||||
}
|
||||
}
|
||||
//}
|
||||
}
|
||||
}
|
||||
else if (stanza.is('presence')) {
|
||||
if (['subscribe','subscribed','unsubscribe','unsubscribed'].indexOf(stanza.attrs.type) > -1) {
|
||||
// this isn't for us, let the config node deal with it.
|
||||
|
||||
}
|
||||
else{
|
||||
else {
|
||||
if (stanza.attrs.type === 'error') {
|
||||
var error = stanza.getChild('error');
|
||||
if (error.attrs.code) {
|
||||
var reas = "";
|
||||
try {
|
||||
reas = error.toString().split('><')[1].split(" xml")[0].trim();
|
||||
if (reas == "registration-required") { reas = "membership-required"; }
|
||||
}
|
||||
catch(e) {}
|
||||
var msg = {
|
||||
topic:stanza.attrs.from,
|
||||
payload: {
|
||||
code:error.attrs.code,
|
||||
status:"error",
|
||||
reason:reas,
|
||||
name:node.serverConfig.MUCs[stanza.attrs.from.split('/')[0]]
|
||||
}
|
||||
};
|
||||
node.send([null,msg]);
|
||||
node.status({fill:"red",shape:"ring",text:"error : "+error.attrs.code+", "+error.attrs.type+", "+reas});
|
||||
node.error(error.attrs.type+" error. "+error.attrs.code+" "+reas,msg);
|
||||
}
|
||||
}
|
||||
|
||||
var state = stanza.getChild('show');
|
||||
if (state) { state = state.getText(); }
|
||||
else { state = "available"; }
|
||||
var statusText="";
|
||||
if (stanza.attrs.type === 'unavailable') {
|
||||
// the user might not exist, but the server doesn't tell us that!
|
||||
statusText = "offline";
|
||||
state = "offline";
|
||||
}
|
||||
var status = stanza.getChild('status');
|
||||
if ("undefined" !== typeof status) {
|
||||
if (typeof status !== "undefined") {
|
||||
statusText = status.getText();
|
||||
}
|
||||
// right, do we care if there's no status?
|
||||
if (statusText !== "") {
|
||||
var from = stanza.attrs.from;
|
||||
var state = stanza.attrs.show;
|
||||
var msg = {topic:from, payload: {presence:state, status:statusText} };
|
||||
var msg = {
|
||||
topic:from,
|
||||
payload: {
|
||||
presence:state,
|
||||
status:statusText,
|
||||
name:node.serverConfig.MUCs[stanza.attrs.from.split('/')[0]]
|
||||
}
|
||||
};
|
||||
node.send([null,msg]);
|
||||
}
|
||||
else{
|
||||
else {
|
||||
if (RED.settings.verbose || LOGITALL) {
|
||||
node.log("not propagating blank status");
|
||||
node.log(stanza);
|
||||
@ -383,6 +525,49 @@ module.exports = function(RED) {
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (stanza.attrs.type === 'result') {
|
||||
// AM To-Do check for 'bind' result with our current jid
|
||||
var query = stanza.getChild('query');
|
||||
if (RED.settings.verbose || LOGITALL) { this.log("result!"); }
|
||||
if (RED.settings.verbose || LOGITALL) { this.log(query); }
|
||||
|
||||
// handle query for list of rooms available
|
||||
if (query && query.attrs.hasOwnProperty("xmlns") && query.attrs["xmlns"] === "http://jabber.org/protocol/disco#items") {
|
||||
var _items = stanza.getChild('query').getChildren('item');
|
||||
for (var i = 0; i<_items.length; i++) {
|
||||
if ( _items[i].attrs.jid.indexOf('@') === -1 ) {
|
||||
// if no @ in jid then it's probably the root or the room server so ask again
|
||||
getItems(_items[i].attrs.jid,this.serverConfig.jid,xmpp);
|
||||
}
|
||||
else {
|
||||
var name = _items[i].attrs.jid+'/'+node.serverConfig.username;
|
||||
if (!(name in node.serverConfig.MUCs)) {
|
||||
if (RED.settings.verbose || LOGITALL) { node.log("Need to Join room:"+name); }
|
||||
joinMUC(node, xmpp, name);
|
||||
node.serverConfig.MUCs[name.split('/')[0]] = _items[i].attrs.name.split('/')[0];
|
||||
}
|
||||
else {
|
||||
if (RED.settings.verbose || LOGITALL) { node.log("Already joined:"+name); }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (query && query.attrs.hasOwnProperty("xmlns") && query.attrs["xmlns"] === "http://jabber.org/protocol/disco#info") {
|
||||
var fe = [];
|
||||
var _items = stanza.getChild('query').getChildren('feature');
|
||||
for (var i = 0; i<_items.length; i++) {
|
||||
fe.push(_items[i].attrs);
|
||||
}
|
||||
var id = []
|
||||
var _idents = stanza.getChild('query').getChildren('identity');
|
||||
for (var i = 0; i<_idents.length; i++) {
|
||||
id.push(_idents[i].attrs);
|
||||
}
|
||||
var from = stanza.attrs.from;
|
||||
var msg = {topic:from, payload: { identity:id, features:fe} };
|
||||
node.send([null,msg]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// xmpp.on('subscribe', from => {
|
||||
@ -394,31 +579,38 @@ module.exports = function(RED) {
|
||||
// Now actually make the connection
|
||||
try {
|
||||
if (xmpp.status === "online") {
|
||||
node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"});
|
||||
node.status({fill:"green",shape:"dot",text:"connected"});
|
||||
}
|
||||
else{
|
||||
node.status({fill:"grey",shape:"dot",text:"node-red:common.status.connecting"});
|
||||
else {
|
||||
node.status({fill:"grey",shape:"dot",text:"connecting"});
|
||||
if (xmpp.status === "offline") {
|
||||
if (RED.settings.verbose || LOGITALL) {
|
||||
node.log("starting xmpp client");
|
||||
}
|
||||
xmpp.start().catch(error => {node.warn("Got error on start: "+error); node.warn("XMPP Status is now: "+xmpp.status)});
|
||||
xmpp.start().catch(error => {
|
||||
node.warn("Got error on start: "+error);
|
||||
node.warn("XMPP Status is now: "+xmpp.status)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(e) {
|
||||
node.error("Bad xmpp configuration; service: "+xmpp.options.service+" jid: "+node.serverConfig.jid);
|
||||
node.warn(e);
|
||||
node.warn(e.stack);
|
||||
node.status({fill:"red",shape:"ring",text:"node-red:common.status.disconnected"});
|
||||
node.status({fill:"red",shape:"ring",text:"disconnected"});
|
||||
}
|
||||
|
||||
node.on("close", function(removed, done) {
|
||||
node.status({fill:"red",shape:"ring",text:"node-red:common.status.disconnected"});
|
||||
if (node.jointick) { clearInterval(node.jointick); }
|
||||
node.status({fill:"grey",shape:"ring",text:"disconnected"});
|
||||
node.serverConfig.deregister(node, done);
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("xmpp in",XmppInNode);
|
||||
RED.nodes.registerType("xmpp in",XmppInNode,{
|
||||
credentials: {
|
||||
password: {type: "password"}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
function XmppOutNode(n) {
|
||||
@ -429,6 +621,9 @@ module.exports = function(RED) {
|
||||
this.join = n.join || false;
|
||||
this.sendAll = n.sendObject;
|
||||
this.to = n.to || "";
|
||||
this.quiet = false;
|
||||
// MUC == Multi-User-Chat == chatroom
|
||||
this.muc = this.join && (this.to !== "")
|
||||
var node = this;
|
||||
|
||||
var xmpp = this.serverConfig.client;
|
||||
@ -446,30 +641,31 @@ module.exports = function(RED) {
|
||||
disconnect: Socket is disconnected
|
||||
*/
|
||||
|
||||
// if we're already connected, then do the actions now, otherwise register a callback
|
||||
// if (xmpp.status === "online") {
|
||||
// node.status({fill:"green",shape:"dot",text:"connected"});
|
||||
// if (node.muc){
|
||||
// // if we want to use a chatroom, we need to tell the server we want to join it
|
||||
// joinMUC(node, xmpp, node.from+'/'+node.nick);
|
||||
// }
|
||||
// }
|
||||
// sod it, register it anyway, that way things will work better on a reconnect:
|
||||
xmpp.on('online', function(data) {
|
||||
node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"});
|
||||
if ((node.join) && (node.to !== "")) {
|
||||
// disable chat history
|
||||
var to = node.to+'/'+node.nick;
|
||||
// the presence with the muc x element signifies we want to join the muc
|
||||
// if we want to support passwords, we need to add that as a child of the x element
|
||||
// (third argument to the x/muc/children )
|
||||
// We also turn off chat history (maxstanzas 0) because that's not what this node is about.
|
||||
var stanza = xml('presence',
|
||||
{"to": to},
|
||||
xml("x",'http://jabber.org/protocol/muc'),
|
||||
{ maxstanzas:0, seconds:1 }
|
||||
);
|
||||
node.serverConfig.used(node);
|
||||
xmpp.send(stanza);
|
||||
node.quiet = false;
|
||||
node.status({fill:"green",shape:"dot",text:"connected"});
|
||||
if (node.muc) {
|
||||
// if we want to use a chatroom, we need to tell the server we want to join it
|
||||
joinMUC(node, xmpp, node.from+'/'+node.nick);
|
||||
}
|
||||
});
|
||||
|
||||
xmpp.on('connecting', async address => {
|
||||
node.status({fill:"grey",shape:"dot",text:"node-red:common.status.connecting"});
|
||||
if (!node.quiet) {
|
||||
node.status({fill:"grey",shape:"dot",text:"connecting"});
|
||||
}
|
||||
});
|
||||
xmpp.on('connect', async address => {
|
||||
node.status({fill:"grey",shape:"dot",text:"node-red:common.status.connected"});
|
||||
node.status({fill:"grey",shape:"dot",text:"connected"});
|
||||
});
|
||||
xmpp.on('opening', async address => {
|
||||
node.status({fill:"grey",shape:"dot",text:"opening"});
|
||||
@ -490,33 +686,30 @@ module.exports = function(RED) {
|
||||
|
||||
xmpp.on('error', function(err) {
|
||||
if (RED.settings.verbose || LOGITALL) { node.log(err); }
|
||||
if (err.hasOwnProperty("stanza")) {
|
||||
if (err.stanza.name === 'stream:error') { node.error("stream:error - bad login id/pwd ?",err); }
|
||||
else { node.error(err.stanza.name,err); }
|
||||
node.status({fill:"red",shape:"ring",text:"bad login"});
|
||||
}
|
||||
else {
|
||||
if (err.errno === "ETIMEDOUT") {
|
||||
node.error("Timeout connecting to server",err);
|
||||
node.status({fill:"red",shape:"ring",text:"timeout"});
|
||||
}
|
||||
else if (err.errno === "ENOTFOUND") {
|
||||
node.error("Server doesn't exist "+xmpp.options.service,err);
|
||||
node.status({fill:"red",shape:"ring",text:"bad address"});
|
||||
}
|
||||
else if (err === "XMPP authentication failure") {
|
||||
node.error(err,err);
|
||||
node.status({fill:"red",shape:"ring",text:"XMPP authentication failure"});
|
||||
}
|
||||
else if (err == "TimeoutError") {
|
||||
// OK, this happens with OpenFire, suppress it.
|
||||
node.status({fill:"grey",shape:"dot",text:"opening"});
|
||||
node.log("Timed out! ",err);
|
||||
// node.status({fill:"red",shape:"ring",text:"XMPP timeout"});
|
||||
}
|
||||
else {
|
||||
node.error("Unknown error: "+err,err);
|
||||
node.status({fill:"red",shape:"ring",text:"node-red:common.status.error"});
|
||||
errorHandler(node, err)
|
||||
});
|
||||
|
||||
xmpp.on('stanza', async (stanza) => {
|
||||
if (stanza.attrs.type === 'error') {
|
||||
var error = stanza.getChild('error');
|
||||
if (error.attrs.code) {
|
||||
var reas = "";
|
||||
try {
|
||||
reas = error.toString().split('><')[1].split(" xml")[0].trim();
|
||||
if (reas == "registration-required") { reas = "membership-required"; }
|
||||
}
|
||||
catch(e) {}
|
||||
var msg = {
|
||||
topic:stanza.attrs.from,
|
||||
payload: {
|
||||
code:error.attrs.code,
|
||||
status:"error",
|
||||
reason:reas,
|
||||
name:node.serverConfig.MUCs[stanza.attrs.from.split('/')[0]]
|
||||
}
|
||||
};
|
||||
node.status({fill:"red",shape:"ring",text:"error : "+error.attrs.code+", "+error.attrs.type+", "+reas});
|
||||
node.error(error.attrs.type+" error. "+error.attrs.code+" "+reas,msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
@ -527,25 +720,24 @@ module.exports = function(RED) {
|
||||
if (xmpp.status === "online") {
|
||||
node.status({fill:"green",shape:"dot",text:"online"});
|
||||
}
|
||||
else{
|
||||
node.status({fill:"grey",shape:"dot",text:"node-red:common.status.connecting"});
|
||||
else {
|
||||
node.status({fill:"grey",shape:"dot",text:"connecting"});
|
||||
if (xmpp.status === "offline") {
|
||||
xmpp.start().catch(error => {
|
||||
node.error("Bad xmpp configuration; service: "+xmpp.options.service+" jid: "+node.serverConfig.jid);
|
||||
node.warn(error);
|
||||
node.warn(error.stack);
|
||||
node.status({fill:"red",shape:"ring",text:"node-red:common.status.error"});
|
||||
node.status({fill:"red",shape:"ring",text:"error"});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Let's get down to business and actually send a message
|
||||
node.on("input", function(msg) {
|
||||
var to = node.to || msg.topic || "";
|
||||
if (msg.presence) {
|
||||
if (['away', 'dnd', 'xa', 'chat'].indexOf(msg.presence) > -1 ) {
|
||||
var stanza = xml('presence',
|
||||
{"show":msg.presence},
|
||||
xml('status',{},msg.payload));
|
||||
var stanza = xml('presence', {"show":msg.presence}, xml('status', {}, msg.payload));
|
||||
node.serverConfig.used(node);
|
||||
xmpp.send(stanza);
|
||||
}
|
||||
@ -553,35 +745,56 @@ module.exports = function(RED) {
|
||||
}
|
||||
else if (msg.command) {
|
||||
if (msg.command === "subscribe") {
|
||||
var stanza = xml('presence',
|
||||
{type:'subscribe', to: msg.payload});
|
||||
var stanza = xml('presence', {type:'subscribe', to:msg.payload});
|
||||
node.serverConfig.used(node);
|
||||
xmpp.send(stanza);
|
||||
}
|
||||
else if (msg.command === "get") {
|
||||
var to = node.to || msg.topic || "";
|
||||
var stanza = xml('iq',
|
||||
{type:'get', id:node.id, to: to},
|
||||
{type:'get', id:node.id, to:to},
|
||||
xml('query', 'http://jabber.org/protocol/muc#admin',
|
||||
xml('item',{affiliation:msg.payload})));
|
||||
xml('item', {affiliation:msg.payload})
|
||||
)
|
||||
);
|
||||
node.serverConfig.used(node);
|
||||
if (RED.settings.verbose || LOGITALL) {node.log("sending stanza "+stanza.toString()); }
|
||||
if (RED.settings.verbose || LOGITALL) { node.log("sending stanza "+stanza.toString()); }
|
||||
xmpp.send(stanza);
|
||||
}
|
||||
else if (msg.command === "info") {
|
||||
var stanza = xml('iq',
|
||||
{type:'get', id:node.id, to:to},
|
||||
xml('query', 'http://jabber.org/protocol/disco#info')
|
||||
);
|
||||
node.serverConfig.used(node);
|
||||
if (RED.settings.verbose || LOGITALL) { node.log("sending stanza "+stanza.toString()); }
|
||||
xmpp.send(stanza);
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
var to = node.to || msg.topic || "";
|
||||
if (to !== "") {
|
||||
var message;
|
||||
var type = node.join? "groupchat":"chat";
|
||||
var type = "chat";
|
||||
if (node.join) {
|
||||
// we want to connect to groupchat / chatroom / MUC
|
||||
type = "groupchat";
|
||||
// joinMUC will do nothing if we're already joined
|
||||
joinMUC(node, xmpp, to+'/'+node.nick);
|
||||
}
|
||||
if (msg.subject) {
|
||||
var stanza = xml(
|
||||
"message",
|
||||
{ type:type, to:to, from:node.serverConfig.jid },
|
||||
xml("subject", {}, msg.subject.toString())
|
||||
);
|
||||
node.serverConfig.used(node);
|
||||
xmpp.send(stanza);
|
||||
}
|
||||
if (node.sendAll) {
|
||||
message = xml(
|
||||
"message",
|
||||
{ type: type, to: to },
|
||||
xml("body", {}, JSON.stringify(msg))
|
||||
);
|
||||
|
||||
}
|
||||
else if (msg.payload) {
|
||||
if (typeof(msg.payload) === "object") {
|
||||
@ -599,17 +812,23 @@ module.exports = function(RED) {
|
||||
);
|
||||
}
|
||||
}
|
||||
node.serverConfig.used(node);
|
||||
xmpp.send(message);
|
||||
if (message) {
|
||||
node.serverConfig.used(node);
|
||||
xmpp.send(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
node.on("close", function(removed, done) {
|
||||
if (RED.settings.verbose || LOGITALL) {node.log("Closing"); }
|
||||
node.status({fill:"red",shape:"ring",text:"node-red:common.status.disconnected"});
|
||||
if (RED.settings.verbose || LOGITALL) { node.log("Closing"); }
|
||||
node.status({fill:"grey",shape:"ring",text:"disconnected"});
|
||||
node.serverConfig.deregister(node, done);
|
||||
});
|
||||
}
|
||||
RED.nodes.registerType("xmpp out",XmppOutNode);
|
||||
RED.nodes.registerType("xmpp out",XmppOutNode,{
|
||||
credentials: {
|
||||
password: {type: "password"}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
{
|
||||
"name": "node-red-node-xmpp",
|
||||
"version": "0.3.1",
|
||||
"version": "0.5.1",
|
||||
"description": "A Node-RED node to talk to an XMPP server",
|
||||
"dependencies": {
|
||||
"@xmpp/client": "^0.11.1"
|
||||
"@xmpp/client": "^0.12.0"
|
||||
},
|
||||
"bundledDependencies": [
|
||||
"@xmpp/client"
|
||||
],
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/node-red/node-red-nodes/tree/master/social/xmpp"
|
||||
|
@ -6,7 +6,7 @@
|
||||
</div>
|
||||
<div class="form-row">
|
||||
<label for="node-config-input-encoding"><i class="fa fa-random"></i> Values are</label>
|
||||
|
||||
|
||||
<select type="text" id="node-config-input-encoding">
|
||||
<option value="utf8">text</option>
|
||||
<option value="json">JSON</option>
|
||||
@ -39,13 +39,6 @@
|
||||
</div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="leveldb in">
|
||||
<p>Uses <a href="https://code.google.com/p/leveldb/" target="_new"><i>LevelDB</i></a> for a simple key value pair database.</p>
|
||||
<p>Use this node to <b>get</b>, or retrieve the data already saved in the database.</p>
|
||||
<p><code>msg.topic</code> must hold the <i>key</i> for the database, and the result is returned in <code>msg.payload</code>.</p>
|
||||
<p>If nothing is found for the key then <code>msg.payload</code> is set to the <i>null</i> object.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('leveldb in',{
|
||||
category: 'storage-input',
|
||||
@ -67,7 +60,6 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/html" data-template-name="leveldb out">
|
||||
<div class="form-row node-input-level">
|
||||
<label for="node-input-level"><i class="fa fa-briefcase"></i> Database</label>
|
||||
@ -86,13 +78,6 @@
|
||||
</div>
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/html" data-help-name="leveldb out">
|
||||
<p>Uses <a href="https://code.google.com/p/leveldb/" target="_new"><i>LevelDB</i></a> for a simple key value pair database.</p>
|
||||
<p>Use this node to either <b>put</b> (store) the <code>msg.payload</code> to the named database file, using <code>msg.topic</code> as the key.</p>
|
||||
<p>To <b>delete</b> information select delete in the properties dialogue and again use <code>msg.topic</code> as the key.</b>.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('leveldb out',{
|
||||
category: 'storage-output',
|
||||
|
13
storage/leveldb/locales/en-US/67-leveldb.html
Normal file
13
storage/leveldb/locales/en-US/67-leveldb.html
Normal file
@ -0,0 +1,13 @@
|
||||
|
||||
<script type="text/html" data-help-name="leveldb in">
|
||||
<p>Uses <a href="https://code.google.com/p/leveldb/" target="_new"><i>LevelDB</i></a> for a simple key value pair database.</p>
|
||||
<p>Use this node to <b>get</b>, or retrieve the data already saved in the database.</p>
|
||||
<p><code>msg.topic</code> must hold the <i>key</i> for the database, and the result is returned in <code>msg.payload</code>.</p>
|
||||
<p>If nothing is found for the key then <code>msg.payload</code> is set to the <i>null</i> object.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="leveldb out">
|
||||
<p>Uses <a href="https://code.google.com/p/leveldb/" target="_new"><i>LevelDB</i></a> for a simple key value pair database.</p>
|
||||
<p>Use this node to either <b>put</b> (store) the <code>msg.payload</code> to the named database file, using <code>msg.topic</code> as the key.</p>
|
||||
<p>To <b>delete</b> information select delete in the properties dialogue and again use <code>msg.topic</code> as the key.</b>.</p>
|
||||
</script>
|
@ -74,44 +74,6 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="mongodb">
|
||||
<p>Define a connection method to your MongoDB server instance.</p>
|
||||
<p>There are 3 supported options:
|
||||
<details><summary>Standard/direct</summary>
|
||||
For databases that request connections in the form
|
||||
<code>
|
||||
mongodb://[username]:[password]@[hostname]:[port]/[dbname]
|
||||
</code>
|
||||
Most often used for local MongoDB instances (localhost:27017), and other stand-alone instances.
|
||||
</details>
|
||||
<details><summary>Standard/replicaset</summary>
|
||||
For databases that request connections in the form
|
||||
<code>
|
||||
mongodb://[username]:[password]@[hostnameA]:[port],[hostnameB]:[port]/[dbname]?replicaSet=[replsetname]
|
||||
</code>
|
||||
Often used with <q>database as a service</q> offerings,
|
||||
or on-premises instances that have been configured for availability and resilience
|
||||
</details>
|
||||
<details><summary>Clustered by DNS seedlist</summary>
|
||||
For databases that request connections in the form
|
||||
<code>
|
||||
mongodb+srv://[username]:[password]@[clustername]/[dbname]?retryWrites=true&w=majority
|
||||
</code>
|
||||
A configuration of MongoDB instances that provide availability and performance
|
||||
through replication and sharding, accessed through a cluster alias name, rather than
|
||||
by specific host:port connections. This is the default for MongoDB instances in the
|
||||
<a href="https://www.mongodb.com/cloud/atlas" target="_blank">Atlas cloud service</a>.
|
||||
</details>
|
||||
<p><strong>Connect options</strong> is where you add the optional parameters required by your MongoDB instance.
|
||||
This might include:
|
||||
<ul><li>w=majority</li><li>replicaSet=replset</li><li>authSource=admin</li></ul> and any other options appropriate -
|
||||
full set available at <a href="https://docs.mongodb.com/manual/reference/connection-string/" target="_blank">
|
||||
Connection String URI Format — MongoDB Manual</a>.
|
||||
<p>If you are connecting to <a href="https://cloud.ibm.com/catalog/services/databases-for-mongodb-group" target="_blank">
|
||||
IBM Databases for MongoDB</a>, as a replica-set, be sure to append <code>ssl=true&tlsAllowInvalidCertificates=true </code>
|
||||
to the <strong>Connect options</strong>.
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-template-name="mongodb out">
|
||||
<div class="form-row">
|
||||
<label for="node-input-mongodb"><i class="fa fa-bookmark"></i> <span data-i18n="mongodb.label.server"></span></label>
|
||||
@ -152,27 +114,6 @@
|
||||
<div class="form-tips" id="node-warning" style="display: none"><span data-i18n="[html]mongodb.tip"></span></div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="mongodb out">
|
||||
<p>A simple MongoDB output node. Can save, insert, update and remove objects from a chosen collection.</p>
|
||||
<p>Save will update an existing object or insert a new object if one does not already exist.</p>
|
||||
<p>Insert will insert a new object.</p>
|
||||
<p>Save and insert either store <code>msg</code> or <code>msg.payload</code>.</p>
|
||||
<p>Update will modify an existing object or objects. The query to select objects to update uses <code>msg.query</code>
|
||||
and the update to the element uses <code>msg.payload</code>. If <code>msg.query._id</code> is
|
||||
a valid mongo ObjectId string it will be converted to an ObjectId type.</p>
|
||||
<p>Update can add a object if it does not exist or update multiple objects.</p>
|
||||
<p>Remove will remove objects that match the query passed in on <code>msg.payload</code>. A blank query will delete
|
||||
<i>all of the objects</i> in the collection.</p>
|
||||
<p>You can either set the collection method in the node config or on <code>msg.collection</code>. Setting it in the
|
||||
node will override <code>msg.collection</code>.</p>
|
||||
<p>By default MongoDB creates an <i>_id</i> property as the primary key - so repeated injections of the
|
||||
same <code>msg</code> will result in many database entries.</p>
|
||||
<p>If this is NOT the desired behaviour - ie. you want repeated entries to overwrite, then you must set
|
||||
the <code>msg._id</code> property to be a constant by the use of a previous function node.</p>
|
||||
<p>This could be a unique constant or you could create one based on some other msg property.</p>
|
||||
<p>Currently we do not limit or cap the collection size at all... this may well change.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
function oneditprepare() {
|
||||
$("#node-input-operation").change(function () {
|
||||
@ -225,7 +166,6 @@
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<script type="text/html" data-template-name="mongodb in">
|
||||
<div class="form-row">
|
||||
<label for="node-input-mongodb"><i class="fa fa-bookmark"></i> <span data-i18n="mongodb.label.server"></span></label>
|
||||
@ -250,21 +190,6 @@
|
||||
<div class="form-tips" id="node-warning" style="display: none"><span data-i18n="[html]mongodb.tip"></span></div>
|
||||
</script>
|
||||
|
||||
<script type="text/html" data-help-name="mongodb in">
|
||||
<p>Calls a MongoDB collection method based on the selected operator.</p>
|
||||
<p>Find queries a collection using the <code>msg.payload</code> as the query statement as per the .find() function.
|
||||
Optionally, you may also (via a function) set a <code>msg.projection</code> object to constrain the returned
|
||||
fields, a <code>msg.sort</code> object, a <code>msg.limit</code> number and a <code>msg.skip</code> number.</p>
|
||||
<p>Count returns a count of the number of documents in a collection or matching a query using the
|
||||
<code>msg.payload</code> as the query statement.</p>
|
||||
<p>Aggregate provides access to the aggregation pipeline using the <code>msg.payload</code> as the pipeline array.</p>
|
||||
<p>You can either set the collection method in the node config or on <code>msg.collection</code>. Setting it in
|
||||
the node will override <code>msg.collection</code>.</p>
|
||||
<p>See the <a href="http://docs.mongodb.org/manual/reference/method/db.collection.find/" target="new"><i>MongoDB
|
||||
collection methods docs</i></a> for examples.</p>
|
||||
<p>The result is returned in <code>msg.payload</code>.</p>
|
||||
</script>
|
||||
|
||||
<script type="text/javascript">
|
||||
RED.nodes.registerType('mongodb in', {
|
||||
category: 'storage-input',
|
||||
|
38
storage/mongodb/locales/de/66-mongodb.json
Normal file
38
storage/mongodb/locales/de/66-mongodb.json
Normal file
@ -0,0 +1,38 @@
|
||||
{
|
||||
"mongodb": {
|
||||
"label": {
|
||||
"host": "Host",
|
||||
"topology":"Verbindungs- topologie",
|
||||
"connectOptions":"Verbindungs- optionen",
|
||||
"port": "Port",
|
||||
"database": "Datenbank",
|
||||
"username": "Benutzername",
|
||||
"password": "Passwort",
|
||||
"server": "Server",
|
||||
"collection": "Collection",
|
||||
"operation": "Operation",
|
||||
"onlystore": "Nur msg.payload-Objekt speichern",
|
||||
"createnew": "Erzeuge ein neues Dokument, wenn keine Übereinstimmung gefunden",
|
||||
"updateall": "Aktualisiere alle übereinstimmenden Dokumente"
|
||||
},
|
||||
"operation": {
|
||||
"save": "Speichern",
|
||||
"insert": "Einfügen",
|
||||
"update": "Aktualisieren",
|
||||
"remove": "Entfernen",
|
||||
"find": "Finden",
|
||||
"count": "Zählen",
|
||||
"aggregate": "Vereinen"
|
||||
},
|
||||
"status": {
|
||||
"connecting": "Verbinde",
|
||||
"connected": "Verbunden",
|
||||
"error": "Fehler"
|
||||
},
|
||||
"tip": "<b>Tipp:</b> Wenn keine Collection vorgegeben ist, muss <code>msg.collection</code> den Collection-Namen enthalten",
|
||||
"errors": {
|
||||
"nocollection": "Keine Collection angegeben",
|
||||
"missingconfig": "Fehlende MongoDB-Konfiguration"
|
||||
}
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user