Tidy up exif test, lint Arduino code

This commit is contained in:
Dave Conway-Jones
2025-08-08 13:52:18 +01:00
parent 213ab0f8d2
commit 38b283e50b
5 changed files with 131 additions and 111 deletions

View File

@@ -45,7 +45,7 @@ module.exports = function(grunt) {
html: ['*/*/*.html', '!node_modules/*/*.html', '!*/node_modules/*.html'], html: ['*/*/*.html', '!node_modules/*/*.html', '!*/node_modules/*.html'],
options: { options: {
jshintrc: ".jshintrc" jshintrc: ".jshintrc"
//,reporter: require('jshint-stylish') ,reporter: require('jshint-stylish')
} }
}, },
jscs: { jscs: {
@@ -53,7 +53,7 @@ module.exports = function(grunt) {
options: { options: {
config: ".jscsrc", config: ".jscsrc",
reporter: "inline" reporter: "inline"
//,fix: true ,fix: true
} }
} }
}); });
@@ -63,6 +63,6 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-lint-inline'); grunt.loadNpmTasks('grunt-lint-inline');
grunt.loadNpmTasks('grunt-jscs'); grunt.loadNpmTasks('grunt-jscs');
grunt.registerTask('default', ['jshint:all', 'inlinelint:html', 'simplemocha:all']); grunt.registerTask('default', ['jshint:all', 'simplemocha:all']);
grunt.registerTask('style', ['jscs']); grunt.registerTask('style', ['jscs']);
}; };

View File

@@ -38,13 +38,13 @@
log2consol : {value: false, required: false} log2consol : {value: false, required: false}
}, },
label: function() { label: function() {
if (this.name !== "") return this.name if (this.name !== "") { return this.name }
else return this.device || "firmata-board-" + this.id; // (bad naming :-( ) device should be: "port" else { return this.device || "firmata-board-" + this.id; } // (bad naming :-( ) device should be: "port"
}, },
oneditprepare: function() { oneditprepare: function() {
try { try {
$("#node-config-input-device").autocomplete( "destroy" ); // Remove auto-complete functionality from an <input>. $("#node-config-input-device").autocomplete( "destroy" ); // Remove auto-complete functionality from an <input>.
} catch(err) { }; } catch(err) { }
$("#node-config-lookup-serial").click(async function() { // Board's serial port search function $("#node-config-lookup-serial").click(async function() { // Board's serial port search function
console.log("Serial Auto-search started."); console.log("Serial Auto-search started.");

View File

@@ -162,17 +162,17 @@ module.exports = function(RED) {
function resetBoard(_brdNode){ function resetBoard(_brdNode){
if ((_brdNode == null) || (_brdNode.board == null)) return; if ((_brdNode == null) || (_brdNode.board == null)) { return; }
// console.log('pins: %o', nodeIn.board.analogPins); // console.log('pins: %o', nodeIn.board.analogPins);
if (moreLogs) console.info(c_fbr + " Board RESET. Port= " + _brdNode.port ); // =parent.device if (moreLogs) { console.info(c_fbr + " Board RESET. Port= " + _brdNode.port ); } // =parent.device
try { try {
_brdNode.board.reset(); _brdNode.board.reset();
if (moreLogs) console.info(c_fbr + " .. Reset sent. Port= " + _brdNode.port ); if (moreLogs) { console.info(c_fbr + " .. Reset sent. Port= " + _brdNode.port ); }
} }
catch(err) { catch(err) {
_brdNode.error(c_fbr + "sending: reset failed. Error: " + err); _brdNode.error(c_fbr + "sending: reset failed. Error: " + err);
} }
}; }
// state types of Input/Output nodes: // state types of Input/Output nodes:
@@ -186,11 +186,9 @@ module.exports = function(RED) {
}); });
function updateNodeStatus(_n, new_stat) { function updateNodeStatus(_n, new_stat) {
if (_n.parentNode == null) new_stat = ndStats.noBoard; if (_n.parentNode == null) { new_stat = ndStats.noBoard; }
if (((_n.parentNode != null) && (_n.parentNode.b_stat !== BdStates.OK)) if (((_n.parentNode != null) && (_n.parentNode.b_stat !== BdStates.OK)) || (new_stat === ndStats.equalsBoard) ) { // if the main board has some error, it has priority, Except: [noBoard, missingPin pinConflict]
|| (new_stat === ndStats.equalsBoard) ) // if the main board has some error, it has priority, Except: [noBoard, missingPin pinConflict]
{
_n.n_status = ndStats.equalsBoard; _n.n_status = ndStats.equalsBoard;
switch (_n.parentNode.b_stat) { switch (_n.parentNode.b_stat) {
case BdStates.permanentError: _n.status({fill:c_red , shape:c_ring, text:"Permanent Error: Board"}); break; // -9 case BdStates.permanentError: _n.status({fill:c_red , shape:c_ring, text:"Permanent Error: Board"}); break; // -9
@@ -204,7 +202,7 @@ module.exports = function(RED) {
} }
} }
else { else {
if (_n.n_status === new_stat) return; if (_n.n_status === new_stat) { return; }
_n.n_status = new_stat; _n.n_status = new_stat;
switch (new_stat) { switch (new_stat) {
case ndStats.noBoard : _n.status({fill:c_red , shape:c_ring, text:"Error: No board"}); break; // -3 case ndStats.noBoard : _n.status({fill:c_red , shape:c_ring, text:"Error: No board"}); break; // -3
@@ -218,30 +216,32 @@ module.exports = function(RED) {
} }
} }
function pinAlreadyUsed (_parentNode, _newNode) { // Check, if there is already a Node registered with same pin -> report pin-conflict
if (_parentNode.myChirdren.length === 0) return false;
if (([c_RESET, c_STRING, c_SYSEX, c_INTER]).includes(_newNode.pinType)) return false;
let _pin = _newNode.pin;
if (_newNode.pinType === c_ANALOG) {
if (_newNode.pin >= _parentNode.board.analogPins.length) return false; // wrong pin number
_pin = _parentNode.board.analogPins[_newNode.pin]; // get from the reference Like: [26,27,28,29] _pin=3 -> _pin=29
}
for (let i = 0; i < _parentNode.myChirdren.length; i++) {
const _ch = _parentNode.myChirdren[i];
if (_ch == null ) continue;
if (_ch === _newNode) continue; // itself
function reportErrorAndExit() { function reportErrorAndExit() {
updateNodeStatus(_newNode, ndStats.pinConflict); updateNodeStatus(_newNode, ndStats.pinConflict);
_newNode.error("This pin number is already in use by this Node:" + _newNode.id); _newNode.error("This pin number is already in use by this Node:" + _newNode.id);
return true; return true;
} }
function pinAlreadyUsed (_parentNode, _newNode) { // Check, if there is already a Node registered with same pin -> report pin-conflict
if (_parentNode.myChirdren.length === 0) { return false; }
if (([c_RESET, c_STRING, c_SYSEX, c_INTER]).includes(_newNode.pinType)) { return false; }
let _pin = _newNode.pin;
if (_newNode.pinType === c_ANALOG) {
if (_newNode.pin >= _parentNode.board.analogPins.length) { return false; } // wrong pin number
_pin = _parentNode.board.analogPins[_newNode.pin]; // get from the reference Like: [26,27,28,29] _pin=3 -> _pin=29
}
for (let i = 0; i < _parentNode.myChirdren.length; i++) {
const _ch = _parentNode.myChirdren[i];
if (_ch == null ) { continue; }
if (_ch === _newNode) { continue; } // itself
if ( _ch.pinType === c_ANALOG) { if ( _ch.pinType === c_ANALOG) {
if (_pin === _parentNode.board.analogPins[_ch.pin]) return reportErrorAndExit(); // found similar! Exit if (_pin === _parentNode.board.analogPins[_ch.pin]) { return reportErrorAndExit(); }// found similar! Exit
} else { } else {
if (_pin === _ch.pin) return reportErrorAndExit(); // found similar! Exit if (_pin === _ch.pin) { return reportErrorAndExit(); } // found similar! Exit
} }
} }
return false; // not found any pin-conflict return false; // not found any pin-conflict
@@ -250,9 +250,9 @@ module.exports = function(RED) {
function removeFromChildren(_ch) { function removeFromChildren(_ch) {
if (_ch != null) { if (_ch != null) {
let _x =_ch.parentNode.myChirdren.indexOf(_ch); let _x =_ch.parentNode.myChirdren.indexOf(_ch);
if (_x >= 0) _ch.parentNode.myChirdren.splice(_x, 1); if (_x >= 0) { _ch.parentNode.myChirdren.splice(_x, 1); }
}; }
}; }
@@ -266,7 +266,7 @@ module.exports = function(RED) {
brdNode.b_stat = BdStates.start; // the status of the board brdNode.b_stat = BdStates.start; // the status of the board
brdNode.name = _setup.name || ""; brdNode.name = _setup.name || "";
brdNode.samplingInt= _setup.samplingInt || 250; brdNode.samplingInt= _setup.samplingInt || 250;
if ((_setup.log2consol || moreLogs) === true) moreLogs = true; if ((_setup.log2consol || moreLogs) === true) { moreLogs = true; }
brdNode.port = _setup.device || ""; // port path. Like: "COM3" or "/dev/serial/by-id/usb-Arduino_RaspberryPi_Pico_076461E62D414FE3-if00" brdNode.port = _setup.device || ""; // port path. Like: "COM3" or "/dev/serial/by-id/usb-Arduino_RaspberryPi_Pico_076461E62D414FE3-if00"
// see also: "n.settings.serialport.path" . Sadly the original HTML is named it "device" :-( // see also: "n.settings.serialport.path" . Sadly the original HTML is named it "device" :-(
brdNode.FirmwareName = ""; brdNode.FirmwareName = "";
@@ -283,36 +283,36 @@ module.exports = function(RED) {
baudRate: 57600, // TODO: test, if it would be possible to increase speed during run via fimata.Update() baudRate: 57600, // TODO: test, if it would be possible to increase speed during run via fimata.Update()
path : brdNode.port path : brdNode.port
} }
}; }
function updateBrdState(_newState) { function updateBrdState(_newState) {
if (brdNode.b_stat === _newState) return; // nothing changed -> exit if (brdNode.b_stat === _newState) { return; } // nothing changed -> exit
brdNode.b_stat = _newState; brdNode.b_stat = _newState;
// Send event to all nodeIn + nodeOut to update visual state // Send event to all nodeIn + nodeOut to update visual state
for (let x = 0; x < brdNode.myChirdren.length; x++) { for (let x = 0; x < brdNode.myChirdren.length; x++) {
const _ch = brdNode.myChirdren[x]; const _ch = brdNode.myChirdren[x];
if (_ch != null) _ch.emit(c_brdStateChanged, true); if (_ch != null) { _ch.emit(c_brdStateChanged, true); }
} }
} }
function startBoardLoopTimer() { function startBoardLoopTimer() {
if (brdNode.loop != null) return; // timer already set! if (brdNode.loop != null) { return; }// timer already set!
if (brdNode.loopWaitMs < 10000) brdNode.loopWaitMs += (brdNode.loopWaitMs < 1500) ? 100 : 1000; if (brdNode.loopWaitMs < 10000) { brdNode.loopWaitMs += (brdNode.loopWaitMs < 1500) ? 100 : 1000; }
brdNode.loop = setTimeout(function() { update_reconnect_MyBoard(); }, brdNode.loopWaitMs); brdNode.loop = setTimeout(function() { update_reconnect_MyBoard(); }, brdNode.loopWaitMs);
} }
function update_reconnect_MyBoard() { function update_reconnect_MyBoard() {
clearTimeout(brdNode.loop); brdNode.loop = null; clearTimeout(brdNode.loop); brdNode.loop = null;
if (brdNode.board == null) return; // ... for any case if (brdNode.board == null) { return; } // ... for any case
if (brdNode.board.transport == null) return; // ... for any case if (brdNode.board.transport == null) { return; } // ... for any case
const _t = brdNode.board.transport; // shorter form const _t = brdNode.board.transport; // shorter form
// if everything is fine. Startup already happened once, (and no disconnection since than,) so no need to run more times. // if everything is fine. Startup already happened once, (and no disconnection since than,) so no need to run more times.
if ((brdNode.b_stat === BdStates.OK) && (brdNode.board != null) && (brdNode.board.isReady) && (_t.isOpen)) { if ((brdNode.b_stat === BdStates.OK) && (brdNode.board != null) && (brdNode.board.isReady) && (_t.isOpen)) {
if (moreLogs) console.info(c_fbr + " is already running fine. No need to start again. Port:" + brdNode.port ); if (moreLogs) { console.info(c_fbr + " is already running fine. No need to start again. Port:" + brdNode.port ); }
// TODO: send a test: queryPinState(pin, callback) // TODO: send a test: queryPinState(pin, callback)
brdNode.b_stat = BdStates.OK; brdNode.b_stat = BdStates.OK;
brdNode.loopWaitMs = 0; // reset brdNode.loopWaitMs = 0; // reset
@@ -320,15 +320,18 @@ module.exports = function(RED) {
} }
let _newState = BdStates.connecting; // first time start let _newState = BdStates.connecting; // first time start
if (brdNode.b_stat < 0) if (brdNode.b_stat < 0) {
_newState = BdStates.tryReconnect; _newState = BdStates.tryReconnect;
else }
if (!_t.opening && _t.isOpen && !brdNode.board.isReady) else {
if (!_t.opening && _t.isOpen && !brdNode.board.isReady) {
_newState = BdStates.gettingVersion; // first time start _newState = BdStates.gettingVersion; // first time start
}
}
updateBrdState( _newState ); updateBrdState( _newState );
if (!_t.opening && !_t.isOpen) // if not opening and not opened if (!_t.opening && !_t.isOpen) { // if not opening and not opened
_t.open(); _t.open();
}
startBoardLoopTimer(); // increase time and check again startBoardLoopTimer(); // increase time and check again
} }
@@ -342,25 +345,25 @@ module.exports = function(RED) {
if (brdNode.board === null) {// if board does not exists yet ... if (brdNode.board === null) {// if board does not exists yet ...
brdNode.b_stat = BdStates.connecting; // first time start brdNode.b_stat = BdStates.connecting; // first time start
if (moreLogs) brdNode.log(c_fbr + "creating new instance. Port:" + brdNode.port + " | Sampling-interval=" + brdNode.samplingInt); if (moreLogs) { brdNode.log(c_fbr + "creating new instance. Port:" + brdNode.port + " | Sampling-interval=" + brdNode.samplingInt); }
// creating new board, starting async promice to report state changes: // creating new board, starting async promice to report state changes:
brdNode.board = new firmataBoard(brdNode.port, startOptions, function(e) { // (port, options, callback) brdNode.board = new firmataBoard(brdNode.port, startOptions, function(e) { // (port, options, callback)
if (e == null) { update_reconnect_MyBoard(); return; }; if (e == null) { update_reconnect_MyBoard(); return; }
const _s = e.toString(); const _s = e.toString();
if (moreLogs) brdNode.log(c_fbr + brdNode.name + " Port:" + brdNode.port + " state changed to:" + _s if (moreLogs) {
+ " | opening:" + brdNode.board.transport.opening + " | is open:" + brdNode.board.transport.isOpen); brdNode.log(c_fbr + brdNode.name + " Port:" + brdNode.port + " state changed to:" + _s + " | opening:" + brdNode.board.transport.opening + " | is open:" + brdNode.board.transport.isOpen);
}
// *** if some kind of error happened *** // // *** if some kind of error happened *** //
if ( (e.name === "Error") || (_s.indexOf("cannot open") !== -1) || (_s.indexOf("Error") !== -1) if ( (e.name === "Error") || (_s.indexOf("cannot open") !== -1) || (_s.indexOf("Error") !== -1)) {
) {
updateBrdState(BdStates.permanentError); updateBrdState(BdStates.permanentError);
brdNode.error(RED._("arduino.errors.portnotfound", {device:brdNode.port})); brdNode.error(RED._("arduino.errors.portnotfound", {device:brdNode.port}));
brdNode.loopWaitMs = 20000; brdNode.loopWaitMs = 20000;
startBoardLoopTimer(); startBoardLoopTimer();
return; return;
}; }
update_reconnect_MyBoard(); // this will update state, restart check-timer if needed. update_reconnect_MyBoard(); // this will update state, restart check-timer if needed.
//if (brdNode.board.versionReceived === true) updateBrdState(BdStates.OK) //if (brdNode.board.versionReceived === true) updateBrdState(BdStates.OK)
@@ -373,7 +376,7 @@ module.exports = function(RED) {
brdNode.on('destroy', function() { brdNode.on('destroy', function() {
brdNode.closing = true; brdNode.closing = true;
brdNode.myChirdren = []; brdNode.myChirdren = [];
if (brdNode.board == null) return; // exit if (brdNode.board == null) { return; } // exit
brdNode.board.removeAllListeners('connect'); brdNode.board.removeAllListeners('connect');
brdNode.board.removeAllListeners('ready'); brdNode.board.removeAllListeners('ready');
brdNode.board.removeAllListeners('close'); brdNode.board.removeAllListeners('close');
@@ -383,20 +386,21 @@ module.exports = function(RED) {
// Firmata-board emitters: // Firmata-board emitters:
brdNode.board.on('error', function(err) { brdNode.board.on('error', function(err) {
updateBrdState(BdStates.unknownError); updateBrdState(BdStates.unknownError);
if (moreLogs) brdNode.error(c_fbr + ' Error: ' + JSON.stringify(err) ); //+ if (moreLogs) { brdNode.error(c_fbr + ' Error: ' + JSON.stringify(err) ); } //+
}); });
// "connect" is called, once serial communication is established. After that queryFirmware is called. See: "ready" // "connect" is called, once serial communication is established. After that queryFirmware is called. See: "ready"
brdNode.board.on('connect', function() { brdNode.board.on('connect', function() {
brdNode.closing = false; brdNode.closing = false;
if (moreLogs) brdNode.log(c_fbr + "connecting to:" + brdNode.port ); if (moreLogs) { brdNode.log(c_fbr + "connecting to:" + brdNode.port ); }
if (brdNode.FirmwareName) // version already aquired once if (brdNode.FirmwareName) { // version already aquired once
updateBrdState(BdStates.OK); updateBrdState(BdStates.OK);
}
else { else {
if (brdNode.board.versionReceived) brdNode.warn("versionReceived but FirmwareName=[]"); if (brdNode.board.versionReceived) { brdNode.warn("versionReceived but FirmwareName=[]"); }
updateBrdState(BdStates.gettingVersion); updateBrdState(BdStates.gettingVersion);
startBoardLoopTimer(); startBoardLoopTimer();
}; }
}); });
// "ready" event is called, after the Firmware name+version + capabilities got querried within 5000ms successfully // "ready" event is called, after the Firmware name+version + capabilities got querried within 5000ms successfully
@@ -410,7 +414,7 @@ module.exports = function(RED) {
// notifying all children // notifying all children
for (let x = 0; x < brdNode.myChirdren.length; x++) { for (let x = 0; x < brdNode.myChirdren.length; x++) {
const _ch = brdNode.myChirdren[x]; const _ch = brdNode.myChirdren[x];
if (_ch != null) _ch.emit(c_brdReady, true); if (_ch != null) { _ch.emit(c_brdReady, true); }
} }
}); });
@@ -418,42 +422,45 @@ module.exports = function(RED) {
// todo : removed // todo : removed
updateBrdState(BdStates.disconnected); updateBrdState(BdStates.disconnected);
resetBoard(brdNode); // this will try to send a "last minute" signal to the board to: reset. resetBoard(brdNode); // this will try to send a "last minute" signal to the board to: reset.
if ( ! brdNode.closing) brdNode.error(RED._("arduino.status.portclosed")); if ( ! brdNode.closing) { brdNode.error(RED._("arduino.status.portclosed")); }
if (done !== undefined) done(); if (done !== undefined) { done(); }
}); });
brdNode.board.on('disconnect', function() { brdNode.board.on('disconnect', function() {
updateBrdState(BdStates.disconnected); updateBrdState(BdStates.disconnected);
if (moreLogs) brdNode.log(c_fbr + "Disconnected. Port:" + brdNode.port + " Firmware Name: ["+ brdNode.FirmwareName +"]"); if (moreLogs) { brdNode.log(c_fbr + "Disconnected. Port:" + brdNode.port + " Firmware Name: ["+ brdNode.FirmwareName +"]"); }
if ( ! brdNode.closing) startBoardLoopTimer(); // do not start, if proper closing is happening if ( ! brdNode.closing) { startBoardLoopTimer(); } // do not start, if proper closing is happening
}); });
}; }
//debugger //debugger
// START board initialization the first time // START board initialization the first time
startupBrd(); startupBrd();
if (brdNode.loop == null) if (brdNode.loop == null) {
startBoardLoopTimer(); startBoardLoopTimer();
else }
if (moreLogs) brdNode.log(c_fbr + "already present. Loop start skipped. "); else {
if (moreLogs) { brdNode.log(c_fbr + "already present. Loop start skipped. "); }
}
// brdNode.removeAllListeners('close'); // brdNode.removeAllListeners('close');
brdNode.on('close', function(removed, done) { // the Node itself is getting destoyed memo: function(done) did not work, TypeError brdNode.on('close', function(removed, done) { // the Node itself is getting destoyed memo: function(done) did not work, TypeError
brdNode.closing = true; brdNode.closing = true;
if (!removed) updateBrdState(BdStates.disconnected); // this will notify clients too if (!removed) { updateBrdState(BdStates.disconnected); } // this will notify clients too
clearTimeout(brdNode.loop); brdNode.loop = null; clearTimeout(brdNode.loop);
brdNode.loop = null;
if ((brdNode.board == null) || (brdNode.board.transport == null) ) { if ((brdNode.board == null) || (brdNode.board.transport == null) ) {
if (done !== undefined) done(); if (done !== undefined) { done(); }
return; return;
} }
if (brdNode.board.transport.closing) { if (brdNode.board.transport.closing) {
if (moreLogs) { brdNode.log(c_fbr + "Nothing to do, because this port is already closing: " + brdNode.port); } if (moreLogs) { brdNode.log(c_fbr + "Nothing to do, because this port is already closing: " + brdNode.port); }
if (done !== undefined) done(); if (done !== undefined) { done(); }
return;// EXIT return;// EXIT
}; }
if (moreLogs) { brdNode.log(c_fbr + "Trying to close port:" + brdNode.port); } if (moreLogs) { brdNode.log(c_fbr + "Trying to close port:" + brdNode.port); }
@@ -463,13 +470,16 @@ module.exports = function(RED) {
brdNode.board.transport.close(function(err) { brdNode.board.transport.close(function(err) {
if (moreLogs) { brdNode.log(RED._("arduino.status.portclosed") + err?"Err: ":"" , err); } if (moreLogs) { brdNode.log(RED._("arduino.status.portclosed") + err?"Err: ":"" , err); }
}); });
if (done !== undefined) done(); if (done !== undefined) { done(); }
} }
catch(e) { catch(e) {
if (moreLogs) { brdNode.error("Could not close port: " + brdNode.port + (e?"Err: ":"") , e); } if (moreLogs) { brdNode.error("Could not close port: " + brdNode.port + (e?"Err: ":"") , e); }
} }
} }
else { if (done !== undefined) done(); return;} else {
if (done !== undefined) { done(); }
return;
}
}); });
} }
// *** REGISTERING the (parent) board node *** // // *** REGISTERING the (parent) board node *** //
@@ -497,7 +507,7 @@ module.exports = function(RED) {
if (nodeIn.frmBoard == null) { if (nodeIn.frmBoard == null) {
updateNodeStatus(nodeIn, ndStats.noBoard); updateNodeStatus(nodeIn, ndStats.noBoard);
return; // EXIT return; // EXIT
}; }
nodeIn.parentNode.myChirdren.push(nodeIn); // subscribe to main nodes array to recieve state changes nodeIn.parentNode.myChirdren.push(nodeIn); // subscribe to main nodes array to recieve state changes
// handle if parent Node's (= firmata-Board's) status is changed // handle if parent Node's (= firmata-Board's) status is changed
@@ -507,23 +517,21 @@ module.exports = function(RED) {
// *** first initialization *** // // *** first initialization *** //
let startupIn = function() { let startupIn = function() {
if (moreLogs) console.info(c_fbr + "Node-In created." + (nodeIn.name ? " Name=["+ nodeIn.name +"]" : "") + " Pin=" + nodeIn.pin + " Type=" + nodeIn.pinType); if (moreLogs) { console.info(c_fbr + "Node-In created." + (nodeIn.name ? " Name=["+ nodeIn.name +"]" : "") + " Pin=" + nodeIn.pin + " Type=" + nodeIn.pinType); }
if (loopIn !== null) {clearTimeout(loopIn); loopIn = null}; if (loopIn !== null) {clearTimeout(loopIn); loopIn = null}
//nodeIn.frmBoard.setMaxListeners(0); Deleted 2025-03-17. DO NOT USE THIS ! See: https://stackoverflow.com/a/44143119 //nodeIn.frmBoard.setMaxListeners(0); Deleted 2025-03-17. DO NOT USE THIS ! See: https://stackoverflow.com/a/44143119
// nodeIn.frmBoard.setMaxListeners(11); // no need either // nodeIn.frmBoard.setMaxListeners(11); // no need either
nodeIn.oldval = ""; nodeIn.oldval = "";
updateNodeStatus(nodeIn, ndStats.equalsBoard); updateNodeStatus(nodeIn, ndStats.equalsBoard);
let doit = function() { let doit = function() {
if (pinAlreadyUsed(nodeIn.parentNode, nodeIn) === true) return; // EXIT; // pin-conflict check if (pinAlreadyUsed(nodeIn.parentNode, nodeIn) === true) { return; } // EXIT; // pin-conflict check
if (moreLogs) console.info(c_fbr + "Node-In init started." + (nodeIn.name ? " Name=["+ nodeIn.name +"]" : "") + " Pin=" + nodeIn.pin + " Type=" + nodeIn.pinType); if (moreLogs) { console.info(c_fbr + "Node-In init started." + (nodeIn.name ? " Name=["+ nodeIn.name +"]" : "") + " Pin=" + nodeIn.pin + " Type=" + nodeIn.pinType); }
let goodPin = (nodeIn.pin != null) && !isNaN(nodeIn.pin) && (nodeIn.pin >=0) && (nodeIn.pin < nodeIn.frmBoard.pins.length); let goodPin = (nodeIn.pin != null) && !isNaN(nodeIn.pin) && (nodeIn.pin >=0) && (nodeIn.pin < nodeIn.frmBoard.pins.length);
if (goodPin === true && nodeIn.pinType === c_ANALOG) { if (goodPin === true && nodeIn.pinType === c_ANALOG) {
goodPin = ( nodeIn.pin in nodeIn.frmBoard.analogPins ); // found analogue pin goodPin = ( nodeIn.pin in nodeIn.frmBoard.analogPins ); // found analogue pin
if (!goodPin){ nodeIn.error( c_invalidPin + nodeIn.pin if (!goodPin) {
+ (nodeIn.frmBoard.analogPins ? ". Only these analogue pin numbers are allowed: [0.." nodeIn.error( c_invalidPin + nodeIn.pin + (nodeIn.frmBoard.analogPins ? ". Only these analogue pin numbers are allowed: [0.." + (nodeIn.frmBoard.analogPins.length-1) + "]/n Reference GPIOs:" + nodeIn.frmBoard.analogPins : "NO analogue pins are allowed with this firmware / board!"));
+ (nodeIn.frmBoard.analogPins.length-1) + "]/n Reference GPIOs:" + nodeIn.frmBoard.analogPins
: "NO analogue pins are allowed with this firmware / board!"));
//console.log('pins: %o', nodeIn.board.analogPins); // TESTS //console.log('pins: %o', nodeIn.board.analogPins); // TESTS
//const jsonString = JSON.stringify(node.board.pins); //const jsonString = JSON.stringify(node.board.pins);
//console.log( jsonString ); //console.log( jsonString );
@@ -545,7 +553,7 @@ module.exports = function(RED) {
// subscribing to pin-event listeners. These will call at firmata-io.js: board.addListener(`analog-read-${pin}`, callback); // subscribing to pin-event listeners. These will call at firmata-io.js: board.addListener(`analog-read-${pin}`, callback);
if (nodeIn.pinType === c_ANALOG) { if (nodeIn.pinType === c_ANALOG) {
nodeIn.frmBoard.analogRead(nodeIn.pin, function(v) { nodeIn.frmBoard.analogRead(nodeIn.pin, function(v) {
if (nodeIn.n_status !== ndStats.OK) updateNodeStatus(nodeIn, ndStats.OK); if (nodeIn.n_status !== ndStats.OK) { updateNodeStatus(nodeIn, ndStats.OK); }
if (v !== nodeIn.oldval) { if (v !== nodeIn.oldval) {
nodeIn.oldval = v; nodeIn.oldval = v;
nodeIn.send({payload:v, topic:"A"+nodeIn.pin}); nodeIn.send({payload:v, topic:"A"+nodeIn.pin});
@@ -554,7 +562,7 @@ module.exports = function(RED) {
} else } else
if (nodeIn.pinType === c_INPUT) { if (nodeIn.pinType === c_INPUT) {
nodeIn.frmBoard.digitalRead(nodeIn.pin, function(v) { nodeIn.frmBoard.digitalRead(nodeIn.pin, function(v) {
if (nodeIn.n_status !== ndStats.OK) updateNodeStatus(nodeIn, ndStats.OK); if (nodeIn.n_status !== ndStats.OK) { updateNodeStatus(nodeIn, ndStats.OK); }
if (v !== nodeIn.oldval) { if (v !== nodeIn.oldval) {
nodeIn.oldval = v; nodeIn.oldval = v;
nodeIn.send({payload:v, topic:nodeIn.pin}); nodeIn.send({payload:v, topic:nodeIn.pin});
@@ -564,7 +572,7 @@ module.exports = function(RED) {
} else } else
if (nodeIn.pinType === c_PULLUP) { if (nodeIn.pinType === c_PULLUP) {
nodeIn.frmBoard.digitalRead(nodeIn.pin, function(v) { nodeIn.frmBoard.digitalRead(nodeIn.pin, function(v) {
if (nodeIn.n_status !== ndStats.OK) updateNodeStatus(nodeIn, ndStats.OK); if (nodeIn.n_status !== ndStats.OK) { updateNodeStatus(nodeIn, ndStats.OK); }
if (v !== nodeIn.oldval) { if (v !== nodeIn.oldval) {
nodeIn.oldval = v; nodeIn.oldval = v;
nodeIn.send({payload:v, topic:nodeIn.pin}); nodeIn.send({payload:v, topic:nodeIn.pin});
@@ -574,13 +582,13 @@ module.exports = function(RED) {
} else } else
if (nodeIn.pinType == c_STRING) { if (nodeIn.pinType == c_STRING) {
nodeIn.frmBoard.on('string', function(v) { nodeIn.frmBoard.on('string', function(v) {
if (nodeIn.n_status !== ndStats.OK) updateNodeStatus(nodeIn, ndStats.OK); if (nodeIn.n_status !== ndStats.OK) { updateNodeStatus(nodeIn, ndStats.OK); }
// if (v !== nodeIn.oldval) { //OMG! deleted 2025-03-17 // if (v !== nodeIn.oldval) { //OMG! deleted 2025-03-17
// nodeIn.oldval = v; // nodeIn.oldval = v;
nodeIn.send({payload:v, topic:"string"}); nodeIn.send({payload:v, topic:"string"});
// } // }
}); });
}; }
} }
else { else {
updateNodeStatus(nodeIn, ndStats.wrongPin); updateNodeStatus(nodeIn, ndStats.wrongPin);
@@ -616,7 +624,7 @@ module.exports = function(RED) {
clearTimeout(loopIn); clearTimeout(loopIn);
if (removed) {removeFromChildren(nodeIn);} if (removed) {removeFromChildren(nodeIn);}
else {updateNodeStatus(nodeIn, ndStats.equalsBoard);} else {updateNodeStatus(nodeIn, ndStats.equalsBoard);}
if (done !== undefined) done(); if (done !== undefined) { done(); }
}); });
} }
RED.nodes.registerType("arduino in", DuinoNodeIn); RED.nodes.registerType("arduino in", DuinoNodeIn);
@@ -642,11 +650,11 @@ module.exports = function(RED) {
if ( Boolean(msg.payload) === true) { if ( Boolean(msg.payload) === true) {
try { try {
resetBoard(nodeOut.parentNode); resetBoard(nodeOut.parentNode);
if (moreLogs) nodeOut.warn(c_fbr + "... sending reset from NR"); if (moreLogs) { nodeOut.warn(c_fbr + "... sending reset from NR"); }
} catch (_error) { } catch (_error) {
nodeOut.error(c_fbr + "Could not send RESET to the board.", _error); nodeOut.error(c_fbr + "Could not send RESET to the board.", _error);
}; }
if (done !== undefined) done(); if (done !== undefined) { done(); }
} }
}); });
} }
@@ -664,7 +672,7 @@ module.exports = function(RED) {
if (nodeOut.frmBoard == null) { if (nodeOut.frmBoard == null) {
updateNodeStatus(nodeOut, ndStats.noBoard); updateNodeStatus(nodeOut, ndStats.noBoard);
return; // EXIT return; // EXIT
}; }
nodeOut.parentNode.myChirdren.push(nodeOut); // subscribe to main nodes array to recieve state changes nodeOut.parentNode.myChirdren.push(nodeOut); // subscribe to main nodes array to recieve state changes
// if parent Node's (= firmata-Board's) status is changed // if parent Node's (= firmata-Board's) status is changed
@@ -673,14 +681,17 @@ module.exports = function(RED) {
}); });
let startupOut = function() { let startupOut = function() {
if (moreLogs) console.info(c_fbr + "Node-Out created." + (nodeOut.name ? " Name=["+ nodeOut.name + "]" : "") + " Pin=" + nodeOut.pin + " Type=" + nodeOut.pinType); if (moreLogs) { console.info(c_fbr + "Node-Out created." + (nodeOut.name ? " Name=["+ nodeOut.name + "]" : "") + " Pin=" + nodeOut.pin + " Type=" + nodeOut.pinType); }
if (loopOut !== null) {clearTimeout(loopOut); loopOut = null}; if (loopOut !== null) {
clearTimeout(loopOut);
loopOut = null;
}
updateNodeStatus(nodeOut, ndStats.equalsBoard); updateNodeStatus(nodeOut, ndStats.equalsBoard);
let doit = function() { let doit = function() {
if (pinAlreadyUsed(nodeOut.parentNode, nodeOut) === true) return; // EXIT; // pin-conflict check if (pinAlreadyUsed(nodeOut.parentNode, nodeOut) === true) { return; } // EXIT; // pin-conflict check
if (moreLogs) console.info(c_fbr + "Node-Out init started." + (nodeOut.name ? " Name=["+ nodeOut.name + "]" : "") + " Pin=" + nodeOut.pin + " Type=" + nodeOut.pinType); if (moreLogs) { console.info(c_fbr + "Node-Out init started." + (nodeOut.name ? " Name=["+ nodeOut.name + "]" : "") + " Pin=" + nodeOut.pin + " Type=" + nodeOut.pinType); }
if ((nodeOut.pin != null) && !isNaN(nodeOut.pin) && nodeOut.pin >=0 && nodeOut.pin < nodeOut.frmBoard.pins.length) { if ((nodeOut.pin != null) && !isNaN(nodeOut.pin) && nodeOut.pin >=0 && nodeOut.pin < nodeOut.frmBoard.pins.length) {
if (nodeOut.pinType === c_OUTPUT) { nodeOut.frmBoard.pinMode(nodeOut.pin, 0x01); } if (nodeOut.pinType === c_OUTPUT) { nodeOut.frmBoard.pinMode(nodeOut.pin, 0x01); }
@@ -692,7 +703,7 @@ module.exports = function(RED) {
nodeOut.on("input", function(msg, send, done) { nodeOut.on("input", function(msg, send, done) {
if ((msg == null) || (msg.payload == null)) { // NULL input -> send warning & exit if ((msg == null) || (msg.payload == null)) { // NULL input -> send warning & exit
nodeOut.warn("msg.payload must not be null!"); nodeOut.warn("msg.payload must not be null!");
if (done !== undefined) done(); if (done !== undefined) { done(); }
return; return;
} }
@@ -709,19 +720,23 @@ module.exports = function(RED) {
} else } else
if ((msg.payload === false) || (str === "0") || (str.toLowerCase() === "off")) { if ((msg.payload === false) || (str === "0") || (str.toLowerCase() === "off")) {
nodeOut.frmBoard.digitalWrite(nodeOut.pin, nodeOut.frmBoard.LOW); nodeOut.frmBoard.digitalWrite(nodeOut.pin, nodeOut.frmBoard.LOW);
}; }
} else } else
if (nodeOut.pinType === c_PWM) { if (nodeOut.pinType === c_PWM) {
msg.payload = parseInt((msg.payload * 1) + 0.5); // round to int msg.payload = parseInt((msg.payload * 1) + 0.5); // round to int
if ((msg.payload >= 0) && (msg.payload <= 255)) { if ((msg.payload >= 0) && (msg.payload <= 255)) {
nodeOut.frmBoard.analogWrite(nodeOut.pin, msg.payload); nodeOut.frmBoard.analogWrite(nodeOut.pin, msg.payload);
} else nodeOut.warn("PWM value must be: 0..255"); } else {
nodeOut.warn("PWM value must be: 0..255");
}
} else } else
if (nodeOut.pinType === c_SERVO) { if (nodeOut.pinType === c_SERVO) {
msg.payload = parseInt((msg.payload * 1) + 0.5); msg.payload = parseInt((msg.payload * 1) + 0.5);
if ((msg.payload >= 0) && (msg.payload <= 180)) { if ((msg.payload >= 0) && (msg.payload <= 180)) {
nodeOut.frmBoard.servoWrite(nodeOut.pin, msg.payload); nodeOut.frmBoard.servoWrite(nodeOut.pin, msg.payload);
} else nodeOut.warn("PWM value must be: 0..180"); } else {
nodeOut.warn("PWM value must be: 0..180");
}
} else } else
if (nodeOut.pinType === c_SYSEX) { if (nodeOut.pinType === c_SYSEX) {
nodeOut.frmBoard.sysexCommand(msg.payload); nodeOut.frmBoard.sysexCommand(msg.payload);
@@ -740,13 +755,13 @@ module.exports = function(RED) {
if (i < 10 || i > 65535) { if (i < 10 || i > 65535) {
nodeOut.warn("Invalid new interval input value (10-65535): ["+ msg.payload +"]"); nodeOut.warn("Invalid new interval input value (10-65535): ["+ msg.payload +"]");
return; return;
}; }
nodeOut.samplingInterval = i; nodeOut.samplingInterval = i;
nodeOut.frmBoard.setSamplingInterval(i); nodeOut.frmBoard.setSamplingInterval(i);
nodeOut.status({fill:c_yellow, shape:c_ring, text:"Interval= " + i}); nodeOut.status({fill:c_yellow, shape:c_ring, text:"Interval= " + i});
} }
} }
if (done !== undefined) done(); if (done !== undefined) { done(); }
}); });
} }
else { else {
@@ -780,8 +795,8 @@ module.exports = function(RED) {
nodeOut.on('close', function(removed, done) { // if remove === true -> it means this Node is getting deleted nodeOut.on('close', function(removed, done) { // if remove === true -> it means this Node is getting deleted
clearTimeout(loopOut); clearTimeout(loopOut);
if (removed === true) {removeFromChildren(nodeOut);} if (removed === true) {removeFromChildren(nodeOut);}
else {updateNodeStatus(nodeOut, ndStats.equalsBoard);}; else {updateNodeStatus(nodeOut, ndStats.equalsBoard);}
if (done !== undefined) done(); if (done !== undefined) { done(); }
}); });
} }
RED.nodes.registerType("arduino out", DuinoNodeOut); RED.nodes.registerType("arduino out", DuinoNodeOut);
@@ -796,11 +811,12 @@ module.exports = function(RED) {
async function listSerialPorts() { async function listSerialPorts() {
try { try {
const ports = await SerialPort.list(); const ports = await SerialPort.list();
if ((ports != null) && (Array.isArray(ports)) && ports.length !== 0) if ((ports != null) && (Array.isArray(ports)) && ports.length !== 0) {
_arr = ports.map(p => p.path); _arr = ports.map(p => p.path);
}
res.json(_arr); res.json(_arr);
} catch (err) { } catch (err) {
this.log('Error listing ports: '+ err); console.log('Error listing ports: '+ err);
_arr.push( err.toString ); _arr.push( err.toString );
res.json(_arr); res.json(_arr);
} }

View File

@@ -31,7 +31,7 @@
"flow" "flow"
], ],
"devDependencies": { "devDependencies": {
"exifreader": "^4.31.1", "exif": "^0.6.0",
"feedparser": "^2.2.10", "feedparser": "^2.2.10",
"grunt": "^1.6.1", "grunt": "^1.6.1",
"grunt-cli": "^1.4.3", "grunt-cli": "^1.4.3",
@@ -46,10 +46,10 @@
"msgpack-lite": "^0.1.26", "msgpack-lite": "^0.1.26",
"multilang-sentiment": "^1.2.0", "multilang-sentiment": "^1.2.0",
"ngeohash": "^0.6.3", "ngeohash": "^0.6.3",
"node-pop3": "^0.9.1",
"node-red": "^4.0.9", "node-red": "^4.0.9",
"node-red-node-test-helper": "^0.3.2", "node-red-node-test-helper": "^0.3.2",
"nodemailer": "^7.0.5", "nodemailer": "^7.0.5",
"node-pop3": "^0.9.1",
"proxyquire": "^2.1.3", "proxyquire": "^2.1.3",
"pushbullet": "^2.4.0", "pushbullet": "^2.4.0",
"sentiment": "^2.1.0", "sentiment": "^2.1.0",
@@ -61,5 +61,9 @@
}, },
"engines": { "engines": {
"node": ">=12" "node": ">=12"
},
"dependencies": {
"jshint": "~2.13.6",
"jshint-stylish": "~2.2.1"
} }
} }

View File

@@ -142,9 +142,9 @@ describe('exif node', function() {
var logEvents = helper.log().args.filter(function(evt) { var logEvents = helper.log().args.filter(function(evt) {
return evt[0].type == "exif"; return evt[0].type == "exif";
}); });
logEvents.should.have.length(1); logEvents.should.have.length(2);
logEvents[0][0].should.have.a.property('msg'); logEvents[0][0].should.have.a.property('msg');
logEvents[0][0].msg.toString().should.startWith("Invalid payload received, "); logEvents[0][0].msg.toString().should.startWith("An error occurred while extracting Exif");
done(); done();
},150); },150);