firmata/firmata.js

Unable to use sysexResponse with multiple boards

Closed this issue · 2 comments

I'm trying to use the sysexResponse with multiple boards. So I'd like to do something like this:

var Board = require("firmata");
var board1 = new Board("COM4");
var board2 = new Board("COM5");

const MY_COMMAND = 0xf;

board1.on("ready", function() {
  board1.sysexResponse(MY_COMMAND, (data) => this.responseHandler1(data));
});

board2.on("ready", function() {
  board2.sysexResponse(MY_COMMAND, (data) => this.responseHandler2(data));
});

function responseHandler1(data) {
    console.info(data);
}

function responseHandler2(data) {
    console.info(data);
}

Unfortunately the way the sysexResponse function works, you can only register 1 handler per command.
The problem is that if I register only one handler the handler does not know which board the message came from.

My suggestion is to change the firmata.js code for the sysexResponse to this:

Board.prototype.sysexResponse = function(commandByte, handler) {
  if (Board.SYSEX_RESPONSE[commandByte]) {
    throw new Error(commandByte + " is not an available SYSEX_RESPONSE byte");
  }

  Board.SYSEX_RESPONSE[commandByte] = function(board) {
    handler(board.currentBuffer.slice(2, -1), board);    // <<-- adding the board to the call back
  };

  return this;
};

If we add a reference to the board in the callback handler we can can solve this problem.

As a workaround I have assigned a handler directly to Board.SYSEX_RESPONSE[commandByte] instead of calling sysexResponse.

Isn't the context of "this" within the handler equal to the board the handler is registered with?

I would think something like this would work, but I haven't tested it:

function responseHandler(data) {
  console.log(this); // the board that the message came from
  console.info(data);
}

@soundanalogous I thought the same thing, but that's not the case. I've just written a patch to correct for that intuition.