Hello hello, I'm relatively new to Johnny Five but I find it a lot of fun. Anyway, I have an issue that _may be_ a small deal but to me it's just a nuisance in my protoyping.
Basically, I have three LEDs (a set of traffic lights), and connecting them up is no problem, and even turning them off with repl.inject is no problem. However, on exit, the first LED is the only one that turns off, while the remaining three are still on after the event.
Is there a particular reason for this on the exit event?
The circuit being used is one that is being followed from a tutorial on Make Use Of.

Code displayed is in ES6 syntax but does exactly the same in older JavaScript, so ES6 or Babel isn't the issue.
// Import Johnny Five classes for use
import { Board, Leds } from 'johnny-five';
// Store `Board()` in new constant
const board = new Board();
board.on('ready', function() {
// Log that board is active
console.log('[johnny-five] Robot Online.');
const lights = new Leds([11, 10, 9]);
// When activated, add a pulse to show lights are working
lights.pulse();
// Add repl functions
this.repl.inject({
// This works...
off: () => {
lights.stop().off();
},
});
// ...yet this doesn't? Only one light turns off.
board.on('exit', function() {
lights.stop().off();
});
});
Anyone have any ideas why this is happening?
Also note: I sometimes have difficulty understanding reading code as I'm not an expert with this library or JavaScript, possibly because of my autism. If you have an answer with code, please be as comprehensive as possible i.e. showing the necessary block of code with comments in it and explaining what is necessary to get it to work.
Apologies for this, understanding small blocks of code that aren't explicit can be very hard. :/
I understand the intent, and I don't think you are doing anything wrong here.
Something in the chain of calls triggered by lights.stop().off() must be put off until the next pass through the javascript event loop so the stop().off() calls never really run before the process ends.
Also, we are using a method in the node that is deprecated so maybe we need to revisit this in the Johnny-Five Board() code?
I added a bit of debug logging in j5 and firmata, basically all the way down to the call this.transport.write(...) in analogWrite...
To the program, I added:
// ...yet this doesn't? Only one light turns off.
board.on('exit', function() {
lights.stop().off();
console.log('AFTER');
});
In lib/repl.js:
cmd.on("exit", function() {
state.board.emit("exit");
state.board.warn("Board", "Closing.");
process.nextTick(() => {
console.log('now in the next tick, will really exit...');
process.reallyExit();
});
});
In lib/mixins/collection.js, I added (to Collection.installMethodForwarding):
for (var i = 0; i < length; i++) {
console.log(`${method}: ${this[i].pin}`);
this[i][method].apply(this[i], arguments);
}
In lib/led/led.js:
Led.prototype.off = function() {
var state = priv.get(this);
state.value = 0;
console.log('calling update within off');
this.update();
return this;
};
Then in node_modules/firmata/lib/firmata.js (in Board.prototype.pwmWrite):
console.log('Firmata: analogWrite. ', new Buffer(data), [pin, value]);
this.transport.write(new Buffer(data));
};
Which resulted in:
stop: 11
stop: 10
stop: 9
off: 11
calling update within off
Firmata: analogWrite. <Buffer eb 00 00> [ 11, 0 ]
off: 10
calling update within off
Firmata: analogWrite. <Buffer ea 00 00> [ 10, 0 ]
off: 9
calling update within off
Firmata: analogWrite. <Buffer e9 00 00> [ 9, 0 ]
AFTER
1490125254206 Board Closing.
now in the next tick, will really exit...
BUT, the issue is reproducing every time. I need more time to work in this.
@dtex
we are using a method in the node that is deprecated
We need a bug for this
I tracked it to SerialPortBinding.write—the writes aren't complete when the next tick handler containing the call to process.reallyExit(); is executed. I figured this out by adding console.log('sp write callback'); to:
SerialPortBinding.write(this.fd, buffer, function(err) {
if (err) {
debug('SerialPortBinding.write had an error', err);
return this._error(err, callback);
}
console.log('sp write callback');
if (callback) { callback.call(this, null) }
}.bind(this));
...inside serialport/lib/serialport.js. When I comment out process.reallyExit(); in lib/repl.js, this prints three times, but look where:
calling update within off
Firmata: analogWrite. <Buffer eb 00 00> [ 11, 0 ]
serialport write 3 bytes of data +12ms
calling update within off
Firmata: analogWrite. <Buffer ea 00 00> [ 10, 0 ]
serialport write 3 bytes of data +0ms
calling update within off
Firmata: analogWrite. <Buffer e9 00 00> [ 9, 0 ]
serialport write 3 bytes of data +0ms
AFTER
1490128645871 Board Closing.
now in the next tick, will really exit...
sp write callback
sp write callback
sp write callback
Because the writes to the serialport are async, and j5 is closing the process before the writes are sent down the wire, they are never sent. I'm working on a way to make Firmata.js aware of pending and completed writes
@IainIsCreative It sounds like you identified a legit need in firmata.js (this will help libraries beyond Johnny-Five). Good catch and thanks for the clear and complete report.
@dtex @rwaldron not a problem! Glad I could present an error and bring up an issue that's obviously an issue beyond Johnny-Five. I try and present the issue as clear as possible.
Once this is reviewed and merged, we'll be able to write a patch for johnny-five that:
pending property on the io plugin instance@IainIsCreative Ok, the patch to firmata has been written, reviewed, landed and released. Today I wrote the patch for J5 as well and just need some review. Can you do me a favor and follow this smoke test:
npm init -ynpm install rwaldron/johnny-five#1306Create a new file called index.js and paste the following into it:
const five = require("johnny-five");
const board = new five.Board();
board.on("ready", () => {
console.log("[johnny-five] Robot Online.");
const lights = new five.Leds([11, 10, 9]);
lights.pulse();
board.on("exit", () => {
lights.stop().off();
});
});
You should see all lights shut off and the program exits
I've been using this branch with Arduino, Tessel, Edison, Joule and Photon since pushing it, so I'm going to merge it today.
@rwaldron whoops! Somehow this just flew right by me — I'm sure it's working but I'll give it a bash and let you know if anything is wrong.