mirror of
https://github.com/node-red/node-red-nodes.git
synced 2023-10-10 13:36:58 +02:00
Merge branch 'master' into feature-setfrequency-for-pwm
This commit is contained in:
commit
d177d6d7a5
@ -62,7 +62,7 @@
|
|||||||
|
|
||||||
<script type="text/x-red" data-template-name="arduino out">
|
<script type="text/x-red" data-template-name="arduino out">
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
<label for="node-input-arduino"><i class="fa fa-tasks"></i> <span data-i18n="arduino.label.arduino"></span></label>
|
<label for="node-input-arduino"><i class="fa fa-tasks"></i> Arduino</label>
|
||||||
<input type="text" id="node-input-arduino">
|
<input type="text" id="node-input-arduino">
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row">
|
||||||
|
@ -10,26 +10,40 @@ module.exports = function(RED) {
|
|||||||
RED.nodes.createNode(this,n);
|
RED.nodes.createNode(this,n);
|
||||||
this.device = n.device || null;
|
this.device = n.device || null;
|
||||||
var node = this;
|
var node = this;
|
||||||
|
var running = false;
|
||||||
|
var reported = false;
|
||||||
|
|
||||||
node.board = new Board(node.device, function(e) {
|
var startup = function() {
|
||||||
//console.log("ERR",e);
|
node.board = new Board(node.device, function(e) {
|
||||||
if ((e !== undefined) && (e.toString().indexOf("cannot open") !== -1) ) {
|
if ((e !== undefined) && (e.toString().indexOf("cannot open") !== -1) ) {
|
||||||
node.error(RED._("arduino.errors.portnotfound",{device:node.device}));
|
if (!reported) {
|
||||||
}
|
node.error(RED._("arduino.errors.portnotfound",{device:node.device}));
|
||||||
else if (e === undefined) {
|
reported = true;
|
||||||
node.board.on('ready', function() {
|
|
||||||
node.log(RED._("arduino.status.connected",{device:node.board.sp.path}));
|
|
||||||
if (RED.settings.verbose) {
|
|
||||||
node.log(RED._("arduino.status.version",{version:node.board.firmware.name+"-"+node.board.version.major+"."+node.board.version.minor}));
|
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
}
|
else if (e === undefined) {
|
||||||
node.board.on('close', function() {
|
running = true;
|
||||||
node.error(RED._("arduino.status.portclosed"));
|
reported = false;
|
||||||
|
node.board.once('ready', function() {
|
||||||
|
node.log(RED._("arduino.status.connected",{device:node.board.sp.path}));
|
||||||
|
if (RED.settings.verbose) {
|
||||||
|
node.log(RED._("arduino.status.version",{version:node.board.firmware.name+"-"+node.board.version.major+"."+node.board.version.minor}));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
node.board.once('close', function() {
|
||||||
|
node.error(RED._("arduino.status.portclosed"));
|
||||||
|
});
|
||||||
|
node.board.once('disconnect', function() {
|
||||||
|
if (running) { setTimeout(function() { running = false; startup(); }, 5000); }
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
setTimeout(function() { if (!running) { startup(); } }, 5000);
|
||||||
|
};
|
||||||
|
startup();
|
||||||
|
|
||||||
node.on('close', function(done) {
|
node.on('close', function(done) {
|
||||||
|
running = false;
|
||||||
if (node.board) {
|
if (node.board) {
|
||||||
try {
|
try {
|
||||||
node.board.transport.close(function() {
|
node.board.transport.close(function() {
|
||||||
@ -53,59 +67,68 @@ module.exports = function(RED) {
|
|||||||
this.state = n.state;
|
this.state = n.state;
|
||||||
this.arduino = n.arduino;
|
this.arduino = n.arduino;
|
||||||
this.serverConfig = RED.nodes.getNode(this.arduino);
|
this.serverConfig = RED.nodes.getNode(this.arduino);
|
||||||
|
this.running = false;
|
||||||
|
var node = this;
|
||||||
if (typeof this.serverConfig === "object") {
|
if (typeof this.serverConfig === "object") {
|
||||||
this.board = this.serverConfig.board;
|
var startup = function() {
|
||||||
var node = this;
|
node.board = node.serverConfig.board;
|
||||||
node.oldval = "";
|
node.oldval = "";
|
||||||
node.status({fill:"red",shape:"ring",text:"node-red:common.status.connecting"});
|
node.status({fill:"grey",shape:"ring",text:"node-red:common.status.connecting"});
|
||||||
var doit = function() {
|
var doit = function() {
|
||||||
node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"});
|
node.running = true;
|
||||||
if (node.state === "ANALOG") {
|
node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"});
|
||||||
node.board.pinMode(node.pin, 0x02);
|
if (node.state === "ANALOG") {
|
||||||
node.board.analogRead(node.pin, function(v) {
|
node.board.pinMode(node.pin, 0x02);
|
||||||
if (v !== node.oldval) {
|
node.board.analogRead(node.pin, function(v) {
|
||||||
node.oldval = v;
|
if (v !== node.oldval) {
|
||||||
node.send({payload:v, topic:"A"+node.pin});
|
node.oldval = v;
|
||||||
}
|
node.send({payload:v, topic:"A"+node.pin});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (node.state === "INPUT") {
|
||||||
|
node.board.pinMode(node.pin, 0x00);
|
||||||
|
node.board.digitalRead(node.pin, function(v) {
|
||||||
|
if (v !== node.oldval) {
|
||||||
|
node.oldval = v;
|
||||||
|
node.send({payload:v, topic:node.pin});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (node.state === "PULLUP") {
|
||||||
|
node.board.pinMode(node.pin, 0x0B);
|
||||||
|
node.board.digitalRead(node.pin, function(v) {
|
||||||
|
if (v !== node.oldval) {
|
||||||
|
node.oldval = v;
|
||||||
|
node.send({payload:v, topic:node.pin});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (node.state == "STRING") {
|
||||||
|
node.board.on('string', function(v) {
|
||||||
|
if (v !== node.oldval) {
|
||||||
|
node.oldval = v;
|
||||||
|
node.send({payload:v, topic:"string"});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
node.board.once('disconnect', function() {
|
||||||
|
node.status({fill:"red",shape:"ring",text:"node-red:common.status.not-connected"});
|
||||||
|
if (node.running) { setTimeout(function() { node.running = false; startup(); }, 5500); }
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
if (node.state === "INPUT") {
|
if (node.board.isReady) { doit(); }
|
||||||
node.board.pinMode(node.pin, 0x00);
|
else { node.board.once("ready", function() { doit(); }); }
|
||||||
node.board.digitalRead(node.pin, function(v) {
|
setTimeout(function() { if (node.running === false) { startup(); } }, 4500);
|
||||||
if (v !== node.oldval) {
|
|
||||||
node.oldval = v;
|
|
||||||
node.send({payload:v, topic:node.pin});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (node.state === "PULLUP") {
|
|
||||||
node.board.pinMode(node.pin, 0x0B);
|
|
||||||
node.board.digitalRead(node.pin, function(v) {
|
|
||||||
if (v !== node.oldval) {
|
|
||||||
node.oldval = v;
|
|
||||||
node.send({payload:v, topic:node.pin});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if (node.state == "STRING") {
|
|
||||||
node.board.on('string', function(v) {
|
|
||||||
if (v !== node.oldval) {
|
|
||||||
node.oldval = v;
|
|
||||||
node.send({payload:v, topic:"string"});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// node.board.on('close', function() {
|
|
||||||
// node.board.removeAllListeners();
|
|
||||||
// node.status({fill:"grey",shape:"ring",text:"node-red:common.status.not-connected"});
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
if (node.board.isReady) { doit(); }
|
startup();
|
||||||
else { node.board.on("ready", function() { doit(); }); }
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.warn(RED._("arduino.errors.portnotconf"));
|
node.warn(RED._("arduino.errors.portnotconf"));
|
||||||
}
|
}
|
||||||
|
node.on('close', function() {
|
||||||
|
node.running = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
RED.nodes.registerType("arduino in",DuinoNodeIn);
|
RED.nodes.registerType("arduino in",DuinoNodeIn);
|
||||||
|
|
||||||
@ -118,53 +141,65 @@ module.exports = function(RED) {
|
|||||||
this.state = n.state;
|
this.state = n.state;
|
||||||
this.arduino = n.arduino;
|
this.arduino = n.arduino;
|
||||||
this.serverConfig = RED.nodes.getNode(this.arduino);
|
this.serverConfig = RED.nodes.getNode(this.arduino);
|
||||||
if (typeof this.serverConfig === "object") {
|
this.running = false;
|
||||||
this.board = this.serverConfig.board;
|
var node = this;
|
||||||
var node = this;
|
if (typeof node.serverConfig === "object") {
|
||||||
node.status({fill:"red",shape:"ring",text:"node-red:common.status.connecting"});
|
var startup = function() {
|
||||||
var doit = function() {
|
node.board = node.serverConfig.board;
|
||||||
node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"});
|
node.status({fill:"grey",shape:"ring",text:"node-red:common.status.connecting"});
|
||||||
node.on("input", function(msg) {
|
var doit = function() {
|
||||||
if (node.state === "OUTPUT") {
|
node.running = true;
|
||||||
node.board.pinMode(node.pin, 0x01);
|
node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"});
|
||||||
if ((msg.payload === true)||(msg.payload.toString() == "1")||(msg.payload.toString().toLowerCase() == "on")) {
|
node.on("input", function(msg) {
|
||||||
node.board.digitalWrite(node.pin, node.board.HIGH);
|
if (node.board.isReady) {
|
||||||
|
if (node.state === "OUTPUT") {
|
||||||
|
node.board.pinMode(node.pin, 0x01);
|
||||||
|
if ((msg.payload === true)||(msg.payload.toString() == "1")||(msg.payload.toString().toLowerCase() == "on")) {
|
||||||
|
node.board.digitalWrite(node.pin, node.board.HIGH);
|
||||||
|
}
|
||||||
|
if ((msg.payload === false)||(msg.payload.toString() == "0")||(msg.payload.toString().toLowerCase() == "off")) {
|
||||||
|
node.board.digitalWrite(node.pin, node.board.LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node.state === "PWM") {
|
||||||
|
node.board.pinMode(node.pin, 0x03);
|
||||||
|
msg.payload = parseInt((msg.payload * 1) + 0.5);
|
||||||
|
if ((msg.payload >= 0) && (msg.payload <= 255)) {
|
||||||
|
node.board.analogWrite(node.pin, msg.payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node.state === "SERVO") {
|
||||||
|
node.board.pinMode(node.pin, 0x04);
|
||||||
|
msg.payload = parseInt((msg.payload * 1) + 0.5);
|
||||||
|
if ((msg.payload >= 0) && (msg.payload <= 180)) {
|
||||||
|
node.board.servoWrite(node.pin, msg.payload);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (node.state === "SYSEX") {
|
||||||
|
node.board.sysexCommand(msg.payload);
|
||||||
|
}
|
||||||
|
if (node.state === "STRING") {
|
||||||
|
node.board.sendString(msg.payload.toString());
|
||||||
}
|
}
|
||||||
if ((msg.payload === false)||(msg.payload.toString() == "0")||(msg.payload.toString().toLowerCase() == "off")) {
|
|
||||||
node.board.digitalWrite(node.pin, node.board.LOW);
|
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
if (node.state === "PWM") {
|
node.board.once('disconnect', function() {
|
||||||
node.board.pinMode(node.pin, 0x03);
|
node.status({fill:"red",shape:"ring",text:"node-red:common.status.not-connected"});
|
||||||
msg.payload = parseInt((msg.payload * 1) + 0.5);
|
if (node.running) { setTimeout(function() { node.running = false; startup(); }, 5500); }
|
||||||
if ((msg.payload >= 0) && (msg.payload <= 255)) {
|
});
|
||||||
node.board.analogWrite(node.pin, msg.payload);
|
}
|
||||||
}
|
if (node.board.isReady) { doit(); }
|
||||||
}
|
else { node.board.once("ready", function() { doit(); }); }
|
||||||
if (node.state === "SERVO") {
|
setTimeout(function() { if (!node.running) { startup(); } }, 4500);
|
||||||
node.board.pinMode(node.pin, 0x04);
|
|
||||||
msg.payload = parseInt((msg.payload * 1) + 0.5);
|
|
||||||
if ((msg.payload >= 0) && (msg.payload <= 180)) {
|
|
||||||
node.board.servoWrite(node.pin, msg.payload);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (node.state === "SYSEX") {
|
|
||||||
node.board.sysexCommand(msg.payload);
|
|
||||||
}
|
|
||||||
if (node.state === "STRING") {
|
|
||||||
node.board.sendString(msg.payload.toString());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
// node.board.on('close', function() {
|
|
||||||
// node.status({fill:"grey",shape:"ring",text:"node-red:common.status.not-connected"});
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
if (node.board.isReady) { doit(); }
|
startup();
|
||||||
else { node.board.on("ready", function() { doit(); }); }
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
this.warn(RED._("arduino.errors.portnotconf"));
|
node.warn(RED._("arduino.errors.portnotconf"));
|
||||||
}
|
}
|
||||||
|
node.on('close', function() {
|
||||||
|
node.running = false;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
RED.nodes.registerType("arduino out",DuinoNodeOut);
|
RED.nodes.registerType("arduino out",DuinoNodeOut);
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name" : "node-red-node-arduino",
|
"name" : "node-red-node-arduino",
|
||||||
"version" : "0.1.0",
|
"version" : "0.2.2",
|
||||||
"description" : "A Node-RED node to talk to an Arduino running firmata",
|
"description" : "A Node-RED node to talk to an Arduino running firmata",
|
||||||
"dependencies" : {
|
"dependencies" : {
|
||||||
"firmata" : "^2.0.0"
|
"firmata" : "^2.0.0"
|
||||||
|
@ -99,7 +99,7 @@
|
|||||||
with which it shares the configuration.</p>
|
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.
|
<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.
|
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 produced to the output (see Outputs below),
|
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>
|
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>
|
<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>
|
<h3>Inputs</h3>
|
||||||
@ -108,7 +108,8 @@
|
|||||||
<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.
|
<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).
|
If not present, the default value is 10000 (10s).
|
||||||
</li>
|
</li>
|
||||||
<li>Any other field will be propagated to the output so to allow to match responses with requests.</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>
|
||||||
</ul>
|
</ul>
|
||||||
<h3>Outputs</h3>
|
<h3>Outputs</h3>
|
||||||
<ul>
|
<ul>
|
||||||
@ -178,59 +179,66 @@
|
|||||||
</select>
|
</select>
|
||||||
</td></tr></table>
|
</td></tr></table>
|
||||||
</div>
|
</div>
|
||||||
<br/>
|
<div class="form-row" style="margin-top:16px; margin-bottom:0;">
|
||||||
<div class="form-row">
|
|
||||||
<label><i class="fa fa-sign-in"></i> <span data-i18n="serial.label.input"></span></label>
|
<label><i class="fa fa-sign-in"></i> <span data-i18n="serial.label.input"></span></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row" style="padding-left:10px;">
|
<div class="form-row" style="padding-left:18px; margin-bottom:4px;">
|
||||||
|
<span data-i18n="serial.label.start"></span>
|
||||||
|
<input type="text" id="node-config-input-waitfor" style="width:50px; height:28px;">
|
||||||
|
<span data-i18n="serial.label.startor"></span>
|
||||||
|
</div>
|
||||||
|
<div class="form-row" style="padding-left:18px; margin-bottom:4px;">
|
||||||
<span data-i18n="serial.label.split"></span>
|
<span data-i18n="serial.label.split"></span>
|
||||||
<select type="text" id="node-config-input-out" style="margin-left:5px; width:200px;">
|
<select type="text" id="node-config-input-out" style="margin-left:11px; width:200px; height:28px;">
|
||||||
<option value="char" data-i18n="serial.split.character"></option>
|
<option value="char" data-i18n="serial.split.character"></option>
|
||||||
<option value="time" data-i18n="serial.split.timeout"></option>
|
<option value="time" data-i18n="serial.split.timeout"></option>
|
||||||
<option value="interbyte" data-i18n="serial.split.silent"></option>
|
<option value="interbyte" data-i18n="serial.split.silent"></option>
|
||||||
<option value="count" data-i18n="serial.split.lengths"></option>
|
<option value="count" data-i18n="serial.split.lengths"></option>
|
||||||
</select>
|
</select>
|
||||||
<input type="text" id="node-config-input-newline" style="width:50px;">
|
<input type="text" id="node-config-input-newline" style="width:50px; height:28px;">
|
||||||
<span id="node-units"></span>
|
<span id="node-units"></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row" style="padding-left:10px;">
|
<div class="form-row" style="padding-left:18px; margin-bottom:4px;">
|
||||||
<span data-i18n="serial.label.deliver"></span>
|
<span data-i18n="serial.label.deliver"></span>
|
||||||
<select type="text" id="node-config-input-bin" style="margin-left:5px; width:150px;">
|
<select type="text" id="node-config-input-bin" style="margin-left:5px; width:150px; height:28px;">
|
||||||
<option value="false" data-i18n="serial.output.ascii"></option>
|
<option value="false" data-i18n="serial.output.ascii"></option>
|
||||||
<option value="bin" data-i18n="serial.output.binary"></option>
|
<option value="bin" data-i18n="serial.output.binary"></option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<br/>
|
|
||||||
<div id="node-config-addchar">
|
<div id="node-config-addchar">
|
||||||
<div class="form-row">
|
<div class="form-row" style="margin-top:16px; margin-bottom:0;">
|
||||||
<label><i class="fa fa-sign-out"></i> <span data-i18n="serial.label.output"></span></label>
|
<label><i class="fa fa-sign-out"></i> <span data-i18n="serial.label.output"></span></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row">
|
<div class="form-row" style="padding-left:18px; margin-bottom:4px;">
|
||||||
<input style="width:30px; margin-left:10px; vertical-align:top;" type="checkbox" id="node-config-input-addchar"><label style="width:auto;" for="node-config-input-addchar"><span data-i18n="serial.addsplit"></span></label>
|
<label style="width:auto;" for="node-config-input-addchar"><span data-i18n="serial.addsplit"></span></label>
|
||||||
|
<input type="text" id="node-config-input-addchar" style="width:50px; height:28px;">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<br/>
|
<div id="node-config-req">
|
||||||
<div id="node-config-addchar">
|
<div class="form-row" style="margin-top:16px; margin-bottom:0;">
|
||||||
<div class="form-row">
|
|
||||||
<label><i class="fa fa-exchange"></i> <span data-i18n="serial.label.request"></span></label>
|
<label><i class="fa fa-exchange"></i> <span data-i18n="serial.label.request"></span></label>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-row" style="padding-left:10px;">
|
<div class="form-row" style="padding-left:18px; margin-bottom:18px;">
|
||||||
<span data-i18n="serial.label.responsetimeout"></span>
|
<span data-i18n="serial.label.responsetimeout"></span>
|
||||||
<input type="text" id="node-config-input-responsetimeout" style="width:60px;">
|
<input type="text" id="node-config-input-responsetimeout" style="width:60px; height:28px;">
|
||||||
<span data-i18n="serial.label.ms"></span>
|
<span data-i18n="serial.label.ms"></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-tips" id="tip-waitfor" hidden><span data-i18n="serial.tip.waitfor"></span></div>
|
||||||
|
<div class="form-tips" id="tip-addchar" hidden><span data-i18n="serial.tip.addchar"></span></div>
|
||||||
<div class="form-tips" id="tip-responsetimeout" hidden><span data-i18n="serial.tip.responsetimeout"></span></div>
|
<div class="form-tips" id="tip-responsetimeout" hidden><span data-i18n="serial.tip.responsetimeout"></span></div>
|
||||||
<div class="form-tips" id="tip-split"><span data-i18n="serial.tip.split"></span></div>
|
<div class="form-tips" id="tip-split"><span data-i18n="serial.tip.split"></span></div>
|
||||||
<div class="form-tips" id="tip-timeout" hidden><span data-i18n="serial.tip.timeout"></span></div>
|
<div class="form-tips" id="tip-timeout" hidden><span data-i18n="serial.tip.timeout"></span></div>
|
||||||
<div class="form-tips" id="tip-silent" hidden><span data-i18n="serial.tip.silent"></span></div>
|
<div class="form-tips" id="tip-silent" hidden><span data-i18n="serial.tip.silent"></span></div>
|
||||||
|
<div class="form-tips" id="tip-count" hidden><span data-i18n="serial.tip.count"></span></div>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<script type="text/x-red" data-help-name="serial-port">
|
<script type="text/x-red" data-help-name="serial-port">
|
||||||
<p>Provides configuration options for a serial port.</p>
|
<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
|
<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>
|
can type in the location if known.</p>
|
||||||
<p>The input can be split on a fixed character, after a timeout, or after a fixed number of characters.</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>
|
<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>
|
||||||
|
|
||||||
@ -244,6 +252,7 @@
|
|||||||
databits: {value:8,required:true},
|
databits: {value:8,required:true},
|
||||||
parity: {value:"none",required:true},
|
parity: {value:"none",required:true},
|
||||||
stopbits: {value:1,required:true},
|
stopbits: {value:1,required:true},
|
||||||
|
waitfor: {value:""},
|
||||||
newline: {value:"\\n"},
|
newline: {value:"\\n"},
|
||||||
bin: {value:"false"},
|
bin: {value:"false"},
|
||||||
out: {value:"char"},
|
out: {value:"char"},
|
||||||
@ -290,41 +299,50 @@
|
|||||||
if ($("#node-config-input-out").val() == "char") {
|
if ($("#node-config-input-out").val() == "char") {
|
||||||
if (previous != "char") { $("#node-config-input-newline").val("\\n"); }
|
if (previous != "char") { $("#node-config-input-newline").val("\\n"); }
|
||||||
$("#node-units").text("");
|
$("#node-units").text("");
|
||||||
$("#node-config-addchar").show();
|
// $("#node-config-addchar").show();
|
||||||
$("#tip-split").show();
|
$("#tip-split").show();
|
||||||
$("#tip-timeout").hide();
|
$("#tip-timeout").hide();
|
||||||
$("#tip-silent").hide();
|
$("#tip-silent").hide();
|
||||||
|
$("#tip-count").hide();
|
||||||
}
|
}
|
||||||
else if ($("#node-config-input-out").val() == "time") {
|
else if ($("#node-config-input-out").val() == "time") {
|
||||||
if (previous != "time") { $("#node-config-input-newline").val("0"); }
|
if (previous != "time") { $("#node-config-input-newline").val("0"); }
|
||||||
$("#node-units").text("ms");
|
$("#node-units").text("ms");
|
||||||
$("#node-config-addchar").hide();
|
// $("#node-config-addchar").hide();
|
||||||
$("#node-config-input-addchar").val("false");
|
// $("#node-config-input-addchar").val("false");
|
||||||
$("#tip-split").hide();
|
$("#tip-split").hide();
|
||||||
$("#tip-timeout").show();
|
$("#tip-timeout").show();
|
||||||
$("#tip-silent").hide();
|
$("#tip-silent").hide();
|
||||||
|
$("#tip-count").hide();
|
||||||
}
|
}
|
||||||
else if ($("#node-config-input-out").val() == "interbyte") {
|
else if ($("#node-config-input-out").val() == "interbyte") {
|
||||||
if (previous != "interbyte") { $("#node-config-input-newline").val("0"); }
|
if (previous != "interbyte") { $("#node-config-input-newline").val("0"); }
|
||||||
$("#node-units").text("ms");
|
$("#node-units").text("ms");
|
||||||
$("#node-config-addchar").hide();
|
// $("#node-config-addchar").hide();
|
||||||
$("#node-config-input-addchar").val("false");
|
// $("#node-config-input-addchar").val("false");
|
||||||
$("#tip-split").hide();
|
$("#tip-split").hide();
|
||||||
$("#tip-timeout").hide();
|
$("#tip-timeout").hide();
|
||||||
$("#tip-silent").show();
|
$("#tip-silent").show();
|
||||||
|
$("#tip-count").hide();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (previous != "count") { $("#node-config-input-newline").val(""); }
|
if (previous != "count") { $("#node-config-input-newline").val(""); }
|
||||||
$("#node-units").text("chars");
|
$("#node-units").text("chars");
|
||||||
$("#node-config-addchar").hide();
|
// $("#node-config-addchar").hide();
|
||||||
$("#node-config-input-addchar").val("false");
|
// $("#node-config-input-addchar").val("false");
|
||||||
$("#tip-split").hide();
|
$("#tip-split").hide();
|
||||||
$("#tip-timeout").hide();
|
$("#tip-timeout").hide();
|
||||||
$("#tip-silent").hide();
|
$("#tip-silent").hide();
|
||||||
|
$("#tip-count").show();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#node-config-input-responsetimeout").on('focus', function () { $("#tip-responsetimeout").show(); });
|
$("#node-config-input-responsetimeout").on('focus', function () { $("#tip-responsetimeout").show(); });
|
||||||
|
$("#node-config-input-responsetimeout").on('blur', function () { $("#tip-responsetimeout").hide(); });
|
||||||
|
$("#node-config-input-waitfor").on('focus', function () { $("#tip-waitfor").show(); });
|
||||||
|
$("#node-config-input-waitfor").on('blur', function () { $("#tip-waitfor").hide(); });
|
||||||
|
$("#node-config-input-addchar").on('focus', function () { $("#tip-addchar").show(); });
|
||||||
|
$("#node-config-input-addchar").on('blur', function () { $("#tip-addchar").hide(); });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$("#node-config-input-serialport").autocomplete( "destroy" );
|
$("#node-config-input-serialport").autocomplete( "destroy" );
|
||||||
|
@ -13,13 +13,14 @@ module.exports = function(RED) {
|
|||||||
RED.nodes.createNode(this,n);
|
RED.nodes.createNode(this,n);
|
||||||
this.serialport = n.serialport;
|
this.serialport = n.serialport;
|
||||||
this.newline = n.newline; /* overloaded: split character, timeout, or character count */
|
this.newline = n.newline; /* overloaded: split character, timeout, or character count */
|
||||||
this.addchar = n.addchar || "false";
|
this.addchar = n.addchar || "";
|
||||||
this.serialbaud = parseInt(n.serialbaud) || 57600;
|
this.serialbaud = parseInt(n.serialbaud) || 57600;
|
||||||
this.databits = parseInt(n.databits) || 8;
|
this.databits = parseInt(n.databits) || 8;
|
||||||
this.parity = n.parity || "none";
|
this.parity = n.parity || "none";
|
||||||
this.stopbits = parseInt(n.stopbits) || 1;
|
this.stopbits = parseInt(n.stopbits) || 1;
|
||||||
this.bin = n.bin || "false";
|
this.bin = n.bin || "false";
|
||||||
this.out = n.out || "char";
|
this.out = n.out || "char";
|
||||||
|
this.waitfor = n.waitfor || "";
|
||||||
this.responsetimeout = n.responsetimeout || 10000;
|
this.responsetimeout = n.responsetimeout || 10000;
|
||||||
}
|
}
|
||||||
RED.nodes.registerType("serial-port",SerialPortNode);
|
RED.nodes.registerType("serial-port",SerialPortNode);
|
||||||
@ -117,6 +118,10 @@ module.exports = function(RED) {
|
|||||||
// Serial Out
|
// Serial Out
|
||||||
node.on("input",function(msg) {
|
node.on("input",function(msg) {
|
||||||
if (!msg.hasOwnProperty("payload")) { return; } // do nothing unless we have a payload
|
if (!msg.hasOwnProperty("payload")) { return; } // do nothing unless we have a payload
|
||||||
|
if (msg.hasOwnProperty("count") && (typeof msg.count === "number") && (node.serialConfig.out === "count")) {
|
||||||
|
node.serialConfig.newline = msg.count;
|
||||||
|
}
|
||||||
|
if (msg.hasOwnProperty("flush") && msg.flush === true) { node.port.serial.flush(); }
|
||||||
node.status({fill:"yellow",shape:"dot",text:"serial.status.waiting"});
|
node.status({fill:"yellow",shape:"dot",text:"serial.status.waiting"});
|
||||||
node.port.enqueue(msg,node,function(err,res) {
|
node.port.enqueue(msg,node,function(err,res) {
|
||||||
if (err) {
|
if (err) {
|
||||||
@ -176,6 +181,7 @@ module.exports = function(RED) {
|
|||||||
stopbits = serialConfig.stopbits,
|
stopbits = serialConfig.stopbits,
|
||||||
newline = serialConfig.newline,
|
newline = serialConfig.newline,
|
||||||
spliton = serialConfig.out,
|
spliton = serialConfig.out,
|
||||||
|
waitfor = serialConfig.waitfor,
|
||||||
binoutput = serialConfig.bin,
|
binoutput = serialConfig.bin,
|
||||||
addchar = serialConfig.addchar,
|
addchar = serialConfig.addchar,
|
||||||
responsetimeout = serialConfig.responsetimeout;
|
responsetimeout = serialConfig.responsetimeout;
|
||||||
@ -191,18 +197,24 @@ module.exports = function(RED) {
|
|||||||
// "time" : a msg will be sent after .newline milliseconds
|
// "time" : a msg will be sent after .newline milliseconds
|
||||||
// "count" : a msg will be sent after .newline characters
|
// "count" : a msg will be sent after .newline characters
|
||||||
// if we use "count", we already know how big the buffer will be
|
// if we use "count", we already know how big the buffer will be
|
||||||
var bufSize = spliton == "count" ? Number(newline): bufMaxSize;
|
var bufSize = (spliton === "count") ? Number(newline): bufMaxSize;
|
||||||
var buf = new Buffer(bufSize);
|
|
||||||
|
waitfor = waitfor.replace("\\n","\n").replace("\\r","\r").replace("\\t","\t").replace("\\e","\e").replace("\\f","\f").replace("\\0","\0"); // jshint ignore:line
|
||||||
|
if (waitfor.substr(0,2) == "0x") { waitfor = parseInt(waitfor,16); }
|
||||||
|
if (waitfor.length === 1) { waitfor = waitfor.charCodeAt(0); }
|
||||||
|
var active = (waitfor === "") ? true : false;
|
||||||
|
var buf = new Buffer.alloc(bufSize);
|
||||||
|
|
||||||
var splitc; // split character
|
var splitc; // split character
|
||||||
// Parse the split character onto a 1-char buffer we can immediately compare against
|
// Parse the split character onto a 1-char buffer we can immediately compare against
|
||||||
if (newline.substr(0,2) == "0x") {
|
if (newline.substr(0,2) == "0x") {
|
||||||
splitc = new Buffer([parseInt(newline)]);
|
splitc = new Buffer.alloc([parseInt(newline,16)]);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
splitc = new Buffer(newline.replace("\\n","\n").replace("\\r","\r").replace("\\t","\t").replace("\\e","\e").replace("\\f","\f").replace("\\0","\0")); // jshint ignore:line
|
splitc = new Buffer.from(newline.replace("\\n","\n").replace("\\r","\r").replace("\\t","\t").replace("\\e","\e").replace("\\f","\f").replace("\\0","\0")); // jshint ignore:line
|
||||||
}
|
}
|
||||||
|
if (addchar === true) { addchar = splitc; }
|
||||||
|
|
||||||
connections[id] = (function() {
|
connections[id] = (function() {
|
||||||
var obj = {
|
var obj = {
|
||||||
_emitter: new events.EventEmitter(),
|
_emitter: new events.EventEmitter(),
|
||||||
@ -220,10 +232,10 @@ module.exports = function(RED) {
|
|||||||
else {
|
else {
|
||||||
payload = payload.toString();
|
payload = payload.toString();
|
||||||
}
|
}
|
||||||
if ((spliton === "char") && (addchar === true)) { payload += splitc; }
|
if ((spliton === "char") && (addchar !== "")) { payload += addchar; }
|
||||||
}
|
}
|
||||||
else if ((spliton === "char") && (addchar === true) && (splitc !== "")) {
|
else if ((spliton === "char") && (addchar !== "")) {
|
||||||
payload = Buffer.concat([payload,splitc]);
|
payload = Buffer.concat([payload,addchar]);
|
||||||
}
|
}
|
||||||
return payload;
|
return payload;
|
||||||
},
|
},
|
||||||
@ -287,6 +299,7 @@ module.exports = function(RED) {
|
|||||||
//newline = newline.replace("\\n","\n").replace("\\r","\r");
|
//newline = newline.replace("\\n","\n").replace("\\r","\r");
|
||||||
var olderr = "";
|
var olderr = "";
|
||||||
var setupSerial = function() {
|
var setupSerial = function() {
|
||||||
|
|
||||||
obj.serial = new serialp(port,{
|
obj.serial = new serialp(port,{
|
||||||
baudRate: baud,
|
baudRate: baud,
|
||||||
dataBits: databits,
|
dataBits: databits,
|
||||||
@ -331,23 +344,26 @@ module.exports = function(RED) {
|
|||||||
|
|
||||||
obj.serial.on('data',function(d) {
|
obj.serial.on('data',function(d) {
|
||||||
function emitData(data) {
|
function emitData(data) {
|
||||||
var m = Buffer.from(data);
|
if (active === true) {
|
||||||
var last_sender = null;
|
var m = Buffer.from(data);
|
||||||
if (obj.queue.length) { last_sender = obj.queue[0].sender; }
|
var last_sender = null;
|
||||||
if (binoutput !== "bin") { m = m.toString(); }
|
if (obj.queue.length) { last_sender = obj.queue[0].sender; }
|
||||||
var msgout = obj.dequeue() || {};
|
if (binoutput !== "bin") { m = m.toString(); }
|
||||||
msgout.payload = m;
|
var msgout = obj.dequeue() || {};
|
||||||
msgout.port = port;
|
msgout.payload = m;
|
||||||
obj._emitter.emit('data',
|
msgout.port = port;
|
||||||
msgout,
|
obj._emitter.emit('data', msgout, last_sender);
|
||||||
last_sender);
|
}
|
||||||
|
active = (waitfor === "") ? true : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var z=0; z<d.length; z++) {
|
for (var z=0; z<d.length; z++) {
|
||||||
var c = d[z];
|
var c = d[z];
|
||||||
|
if (c === waitfor) { active = true; }
|
||||||
// handle the trivial case first -- single char buffer
|
// handle the trivial case first -- single char buffer
|
||||||
|
if (!active) { return; }
|
||||||
if ((newline === 0)||(newline === "")) {
|
if ((newline === 0)||(newline === "")) {
|
||||||
emitData(new Buffer([c]));
|
emitData(new Buffer.from([c]));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -376,6 +392,7 @@ module.exports = function(RED) {
|
|||||||
}
|
}
|
||||||
// count bytes into a buffer...
|
// count bytes into a buffer...
|
||||||
else if (spliton === "count") {
|
else if (spliton === "count") {
|
||||||
|
newline = serialConfig.newline;
|
||||||
if ( i >= parseInt(newline)) {
|
if ( i >= parseInt(newline)) {
|
||||||
emitData(buf.slice(0,i));
|
emitData(buf.slice(0,i));
|
||||||
i=0;
|
i=0;
|
||||||
|
@ -19,7 +19,9 @@
|
|||||||
"responsetimeout": "Default response timeout",
|
"responsetimeout": "Default response timeout",
|
||||||
"ms": "ms",
|
"ms": "ms",
|
||||||
"serial": "serial",
|
"serial": "serial",
|
||||||
"none": "none"
|
"none": "none",
|
||||||
|
"start": "Optionally wait for a start character of",
|
||||||
|
"startor": ", then"
|
||||||
},
|
},
|
||||||
"placeholder": {
|
"placeholder": {
|
||||||
"serialport": "for example: /dev/ttyUSB0/"
|
"serialport": "for example: /dev/ttyUSB0/"
|
||||||
@ -41,12 +43,15 @@
|
|||||||
"ascii": "ascii strings",
|
"ascii": "ascii strings",
|
||||||
"binary": "binary buffers"
|
"binary": "binary buffers"
|
||||||
},
|
},
|
||||||
"addsplit": "add split character to output messages",
|
"addsplit": "Add character to output messages",
|
||||||
"tip": {
|
"tip": {
|
||||||
"responsetimeout": "Tip: The default response timeout can be overridden by setting msg.timeout.",
|
"responsetimeout": "Tip: The default response timeout can be overridden by setting msg.timeout.",
|
||||||
"split": "Tip: the \"Split on\" character is used to split the input into separate messages. It can also be added to every message sent out to the serial port.",
|
"split": "Tip: the \"Split on\" character is used to split the input into separate messages. Can accept chars ($), escape codes (\\n), or hex codes (0x03).",
|
||||||
"silent": "Tip: In line-silent mode timeout is restarted upon arrival of any character (i.e. inter-byte timeout).",
|
"silent": "Tip: In line-silent mode timeout is restarted upon arrival of any character (i.e. inter-byte timeout).",
|
||||||
"timeout": "Tip: In timeout mode timeout starts from arrival of first character."
|
"timeout": "Tip: In timeout mode timeout starts from arrival of first character.",
|
||||||
|
"count": "Tip: In count mode msg.count can override the configured count as long as it smaller than the configured value.",
|
||||||
|
"waitfor": "Tip: Optional. Leave blank to receive all data. Can accept chars ($), escape codes (\\n), or hex codes (0x02)." ,
|
||||||
|
"addchar": "Tip: This character is added to every message sent out to the serial port. Usually \\r or \\n."
|
||||||
},
|
},
|
||||||
"onopen": "serial port __port__ opened at __baud__ baud __config__",
|
"onopen": "serial port __port__ opened at __baud__ baud __config__",
|
||||||
"errors": {
|
"errors": {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name" : "node-red-node-serialport",
|
"name" : "node-red-node-serialport",
|
||||||
"version" : "0.7.1",
|
"version" : "0.8.1",
|
||||||
"description" : "Node-RED nodes to talk to serial ports",
|
"description" : "Node-RED nodes to talk to serial ports",
|
||||||
"dependencies" : {
|
"dependencies" : {
|
||||||
"serialport" : "^7.1.4"
|
"serialport" : "^7.1.4"
|
||||||
|
@ -116,10 +116,10 @@ module.exports = function(RED) {
|
|||||||
smtpTransport.sendMail(sendopts, function(error, info) {
|
smtpTransport.sendMail(sendopts, function(error, info) {
|
||||||
if (error) {
|
if (error) {
|
||||||
node.error(error,msg);
|
node.error(error,msg);
|
||||||
node.status({fill:"red",shape:"ring",text:"email.status.sendfail"});
|
node.status({fill:"red",shape:"ring",text:"email.status.sendfail",response:error.response,msg:{to:msg.to,topic:msg.topic,id:msg._msgid}});
|
||||||
} else {
|
} else {
|
||||||
node.log(RED._("email.status.messagesent",{response:info.response}));
|
node.log(RED._("email.status.messagesent",{response:info.response}));
|
||||||
node.status({});
|
node.status({text:"",response:info.response,msg:{to:msg.to,topic:msg.topic,id:msg._msgid}});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -357,7 +357,7 @@ module.exports = function(RED) {
|
|||||||
//console.log("> search - err=%j, results=%j", err, results);
|
//console.log("> search - err=%j, results=%j", err, results);
|
||||||
if (results.length === 0) {
|
if (results.length === 0) {
|
||||||
//console.log(" [X] - Nothing to fetch");
|
//console.log(" [X] - Nothing to fetch");
|
||||||
node.status({});
|
node.status({results:0});
|
||||||
imap.end();
|
imap.end();
|
||||||
s = false;
|
s = false;
|
||||||
setInputRepeatTimeout();
|
setInputRepeatTimeout();
|
||||||
@ -397,7 +397,7 @@ module.exports = function(RED) {
|
|||||||
|
|
||||||
// When we have fetched all the messages, we don't need the imap connection any more.
|
// When we have fetched all the messages, we don't need the imap connection any more.
|
||||||
fetch.on('end', function() {
|
fetch.on('end', function() {
|
||||||
node.status({});
|
node.status({results:results.length});
|
||||||
var cleanup = function() {
|
var cleanup = function() {
|
||||||
imap.end();
|
imap.end();
|
||||||
s = false;
|
s = false;
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"name": "node-red-node-email",
|
"name": "node-red-node-email",
|
||||||
"version": "1.3.0",
|
"version": "1.4.0",
|
||||||
"description": "Node-RED nodes to send and receive simple emails",
|
"description": "Node-RED nodes to send and receive simple emails",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"imap": "^0.8.19",
|
"imap": "^0.8.19",
|
||||||
"mailparser-mit": "^1.0.0",
|
"mailparser-mit": "^1.0.0",
|
||||||
"nodemailer": "^4.7.0",
|
"nodemailer": "^5.1.1",
|
||||||
"poplib": "^0.1.7"
|
"poplib": "^0.1.7"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
Loading…
Reference in New Issue
Block a user