node-arduino-firmata: support serialport 7.x
support serialport 7.x Takeover of PKG_MAINTAINER Major Makefile Updates Signed-off-by: Hirokazu MORIKAWA <morikw2@gmail.com>
This commit is contained in:
parent
6d535fd282
commit
63cef91f20
|
@ -10,19 +10,16 @@ include $(TOPDIR)/rules.mk
|
||||||
PKG_NPM_NAME:=arduino-firmata
|
PKG_NPM_NAME:=arduino-firmata
|
||||||
PKG_NAME:=node-$(PKG_NPM_NAME)
|
PKG_NAME:=node-$(PKG_NPM_NAME)
|
||||||
PKG_VERSION:=0.3.4
|
PKG_VERSION:=0.3.4
|
||||||
PKG_RELEASE:=2
|
PKG_RELEASE:=3
|
||||||
|
|
||||||
PKG_SOURCE_PROTO:=git
|
PKG_SOURCE:=$(PKG_NPM_NAME)-$(PKG_VERSION).tgz
|
||||||
PKG_SOURCE_URL:=https://github.com/shokai/node-arduino-firmata.git
|
PKG_SOURCE_URL:=https://registry.npmjs.org/$(PKG_NPM_NAME)/-/
|
||||||
PKG_MIRROR_HASH:=1aef93dc704ea771b9eab51cb64103533f829aee5b2886ad55d173adf3f11ede
|
PKG_HASH:=d7157e02867eae82887cb5e17b90c963fe7489bacd464110bfd20c672b8d5a98
|
||||||
PKG_SOURCE_VERSION:=v0.3.4
|
|
||||||
PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_SOURCE_VERSION)
|
|
||||||
PKG_SOURCE:=$(PKG_NAME)-$(PKG_SOURCE_VERSION).tar.gz
|
|
||||||
|
|
||||||
PKG_BUILD_DEPENDS:=node/host
|
PKG_BUILD_DEPENDS:=node/host
|
||||||
PKG_NODE_VERSION:=`$(STAGING_DIR_HOSTPKG)/bin/node --version`
|
PKG_USE_MIPS16:=0
|
||||||
|
|
||||||
PKG_MAINTAINER:=John Crispin <blogic@openwrt.org>
|
PKG_MAINTAINER:=Hirokazu MORIKAWA <morikw2@gmail.com>
|
||||||
PKG_LICENSE:=MIT
|
PKG_LICENSE:=MIT
|
||||||
PKG_LICENSE_FILES:=LICENSE.txt
|
PKG_LICENSE_FILES:=LICENSE.txt
|
||||||
|
|
||||||
|
@ -32,47 +29,44 @@ define Package/node-arduino-firmata
|
||||||
SUBMENU:=Node.js
|
SUBMENU:=Node.js
|
||||||
SECTION:=lang
|
SECTION:=lang
|
||||||
CATEGORY:=Languages
|
CATEGORY:=Languages
|
||||||
TITLE:=Node.js package to access serial ports for reading and writing
|
TITLE:=Arduino Firmata implementation for Node.js
|
||||||
URL:=https://www.npmjs.org/package/serialport
|
URL:=https://www.npmjs.com/package/arduino-firmata
|
||||||
DEPENDS:=+node +node-npm +node-serialport
|
DEPENDS:=+node +node-npm +node-serialport
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/node-arduino-firmata/description
|
define Package/node-arduino-firmata/description
|
||||||
Node.js package to access serial ports for reading and writing OR Welcome your robotic JavaScript overlords. Better yet, program them!
|
Arduino Firmata protocol (http://firmata.org) implementation on Node.js.
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Build/Prepare
|
TAR_OPTIONS+= --strip-components 1
|
||||||
/bin/tar xzf $(DL_DIR)/$(PKG_SOURCE) -C $(PKG_BUILD_DIR) --strip-components 1
|
TAR_CMD=$(HOST_TAR) -C $(1) $(TAR_OPTIONS)
|
||||||
$(Build/Patch)
|
|
||||||
endef
|
|
||||||
|
|
||||||
EXTRA_LDFLAGS="-L$(TOOLCHAIN_DIR)/lib/ -Wl,-rpath-link $(TOOLCHAIN_DIR)/lib/" \
|
NODEJS_CPU:=$(subst powerpc,ppc,$(subst aarch64,arm64,$(subst x86_64,x64,$(subst i386,ia32,$(ARCH)))))
|
||||||
|
|
||||||
define Build/Compile
|
define Build/Compile
|
||||||
cd $(PKG_BUILD_DIR) ; \
|
$(MAKE_VARS) \
|
||||||
$(MAKE_FLAGS) \
|
$(MAKE_FLAGS) \
|
||||||
npm_config_arch=$(CONFIG_ARCH) \
|
npm_config_arch=$(NODEJS_CPU) \
|
||||||
npm_config_nodedir=$(BUILD_DIR)/node-$(PKG_NODE_VERSION)/ \
|
npm_config_target_arch=$(NODEJS_CPU) \
|
||||||
npm_config_cache=$(BUILD_DIR)/node-$(PKG_NODE_VERSION)/npm-cache \
|
npm_config_build_from_source=true \
|
||||||
PREFIX="$(PKG_INSTALL_DIR)/usr/" \
|
npm_config_nodedir=$(STAGING_DIR)/usr/ \
|
||||||
npm install -g `npm pack $(PKG_BUILD_DIR) | tail -n 1`
|
npm_config_prefix=$(PKG_INSTALL_DIR)/usr/ \
|
||||||
|
npm_config_cache=$(TMP_DIR)/npm-cache \
|
||||||
|
npm_config_tmp=$(TMP_DIR)/npm-tmp \
|
||||||
|
npm install -g $(PKG_BUILD_DIR)
|
||||||
|
rm -rf $(TMP_DIR)/npm-tmp
|
||||||
|
rm -rf $(TMP_DIR)/npm-cache
|
||||||
endef
|
endef
|
||||||
|
|
||||||
define Package/node-arduino-firmata/install
|
define Package/node-arduino-firmata/install
|
||||||
mkdir -p $(1)/usr/lib/node
|
$(INSTALL_DIR) $(1)/usr/lib/node/$(PKG_NPM_NAME)
|
||||||
$(CP) $(PKG_INSTALL_DIR)/usr/lib/node_modules/. $(1)/usr/lib/node
|
$(CP) $(PKG_INSTALL_DIR)/usr/lib/node_modules/$(PKG_NPM_NAME)/{package.json,README.md} \
|
||||||
rm -rf $(1)/usr/lib/node/arduino-firmata/node_modules/serialport/ \
|
$(1)/usr/lib/node/$(PKG_NPM_NAME)/
|
||||||
$(1)/usr/lib/node/arduino-firmata/patches \
|
$(CP) $(PKG_INSTALL_DIR)/usr/lib/node_modules/$(PKG_NPM_NAME)/{tests,*.txt} \
|
||||||
$(1)/usr/lib/node/arduino-firmata/.p* \
|
$(1)/usr/lib/node/$(PKG_NPM_NAME)/
|
||||||
$(1)/usr/lib/node/arduino-firmata/.quilt* \
|
$(CP) $(PKG_INSTALL_DIR)/usr/lib/node_modules/$(PKG_NPM_NAME)/{node_modules,lib} \
|
||||||
$(1)/usr/lib/node/arduino-firmata/.built* \
|
$(1)/usr/lib/node/$(PKG_NPM_NAME)/
|
||||||
$(1)/usr/lib/node/arduino-firmata/.config*
|
|
||||||
# Strip PKG_BUILD_DIR from useless metadata inserted by npm install
|
|
||||||
# https://github.com/npm/npm/issues/10393
|
|
||||||
# https://github.com/npm/npm/issues/12110
|
|
||||||
find $(1)/usr/lib/node -name package.json -exec sed -i -e 's,$(PKG_BUILD_DIR),,g' {} +
|
|
||||||
$(CP) ./files/* $(1)/
|
$(CP) ./files/* $(1)/
|
||||||
endef
|
endef
|
||||||
|
|
||||||
$(eval $(call BuildPackage,node-arduino-firmata))
|
$(eval $(call BuildPackage,node-arduino-firmata))
|
||||||
|
|
||||||
|
|
|
@ -1,17 +1,249 @@
|
||||||
(function() {
|
(function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
var ArduinoFirmata, SerialPort, debug, events, exports, serialport,
|
var ArduinoFirmata, debug, events, exports, serialport;
|
||||||
extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
|
|
||||||
hasProp = {}.hasOwnProperty;
|
|
||||||
|
|
||||||
events = require('eventemitter2');
|
events = require('eventemitter2');
|
||||||
|
|
||||||
SerialPort = (serialport = require('serialport')).SerialPort;
|
serialport = require('serialport');
|
||||||
|
|
||||||
debug = require('debug')('arduino-firmata');
|
debug = require('debug')('arduino-firmata');
|
||||||
|
|
||||||
exports = module.exports = ArduinoFirmata = (function(superClass) {
|
exports = module.exports = ArduinoFirmata = (function() {
|
||||||
extend(ArduinoFirmata, superClass);
|
class ArduinoFirmata extends events.EventEmitter2 {
|
||||||
|
static list(callback) {
|
||||||
|
return serialport.list(function(err, ports) {
|
||||||
|
var devices, j, len, port;
|
||||||
|
if (err) {
|
||||||
|
return callback(err);
|
||||||
|
}
|
||||||
|
devices = [];
|
||||||
|
for (j = 0, len = ports.length; j < len; j++) {
|
||||||
|
port = ports[j];
|
||||||
|
if (/usb|acm|com|ama\d+/i.test(port.comName)) {
|
||||||
|
devices.push(port.comName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return callback(null, devices);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
this.status = ArduinoFirmata.Status.CLOSE;
|
||||||
|
this.wait_for_data = 0;
|
||||||
|
this.execute_multi_byte_command = 0;
|
||||||
|
this.multi_byte_channel = 0;
|
||||||
|
this.stored_input_data = [];
|
||||||
|
this.parsing_sysex = false;
|
||||||
|
this.sysex_bytes_read = 0;
|
||||||
|
this.digital_output_data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
|
this.digital_input_data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
|
this.analog_input_data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||||
|
this.boardVersion = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
isOldArduinoDevice() {
|
||||||
|
return /usbserial|USB/.test(this.serialport_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
connect(serialport_name, opts = {
|
||||||
|
baudRate: 57600
|
||||||
|
}) {
|
||||||
|
this.serialport_name = serialport_name;
|
||||||
|
opts.parser = serialport.parsers.raw;
|
||||||
|
if (!this.serialport_name) {
|
||||||
|
ArduinoFirmata.list((err, devices) => {
|
||||||
|
return this.connect(devices[0], opts);
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
this.once('boardReady', function() {
|
||||||
|
var io_init_wait;
|
||||||
|
debug('boardReady');
|
||||||
|
io_init_wait = this.isOldArduinoDevice() ? (debug(`old arduino device found ${this.serialport_name}`), 3000) : (debug(`new arduino device found ${this.serialport_name}`), 100);
|
||||||
|
debug(`wait ${io_init_wait}(msec)`);
|
||||||
|
return setTimeout(() => {
|
||||||
|
var i, j, k;
|
||||||
|
for (i = j = 0; j < 6; i = ++j) {
|
||||||
|
this.write([ArduinoFirmata.REPORT_ANALOG | i, 1]);
|
||||||
|
}
|
||||||
|
for (i = k = 0; k < 2; i = ++k) {
|
||||||
|
this.write([ArduinoFirmata.REPORT_DIGITAL | i, 1]);
|
||||||
|
}
|
||||||
|
debug('init IO ports');
|
||||||
|
return this.emit('connect');
|
||||||
|
}, io_init_wait);
|
||||||
|
});
|
||||||
|
this.serialport = new serialport(this.serialport_name, opts);
|
||||||
|
this.serialport.once('open', () => {
|
||||||
|
var cid;
|
||||||
|
cid = setInterval(() => {
|
||||||
|
debug('request REPORT_VERSION');
|
||||||
|
return this.write([ArduinoFirmata.REPORT_VERSION]);
|
||||||
|
}, 500);
|
||||||
|
this.once('boardVersion', (version) => {
|
||||||
|
clearInterval(cid);
|
||||||
|
this.status = ArduinoFirmata.Status.OPEN;
|
||||||
|
return this.emit('boardReady');
|
||||||
|
});
|
||||||
|
return this.serialport.on('data', (data) => {
|
||||||
|
var byte, j, len, results;
|
||||||
|
results = [];
|
||||||
|
for (j = 0, len = data.length; j < len; j++) {
|
||||||
|
byte = data[j];
|
||||||
|
results.push(this.process_input(byte));
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
isOpen() {
|
||||||
|
return this.status === ArduinoFirmata.Status.OPEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(callback) {
|
||||||
|
this.status = ArduinoFirmata.Status.CLOSE;
|
||||||
|
return this.serialport.close(callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
reset(callback) {
|
||||||
|
return this.write([ArduinoFirmata.SYSTEM_RESET], callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
write(bytes, callback) {
|
||||||
|
return this.serialport.write(bytes, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
sysex(command, data = [], callback) {
|
||||||
|
var write_data;
|
||||||
|
//# http://firmata.org/wiki/V2.1ProtocolDetails#Sysex_Message_Format
|
||||||
|
data = data.map(function(i) {
|
||||||
|
return i & 0b1111111; // 7bit
|
||||||
|
});
|
||||||
|
write_data = [ArduinoFirmata.START_SYSEX, command].concat(data, [ArduinoFirmata.END_SYSEX]);
|
||||||
|
return this.write(write_data, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
pinMode(pin, mode, callback) {
|
||||||
|
switch (mode) {
|
||||||
|
case true:
|
||||||
|
mode = ArduinoFirmata.OUTPUT;
|
||||||
|
break;
|
||||||
|
case false:
|
||||||
|
mode = ArduinoFirmata.INPUT;
|
||||||
|
}
|
||||||
|
return this.write([ArduinoFirmata.SET_PIN_MODE, pin, mode], callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
digitalWrite(pin, value, callback) {
|
||||||
|
var port_num;
|
||||||
|
this.pinMode(pin, ArduinoFirmata.OUTPUT);
|
||||||
|
port_num = (pin >>> 3) & 0x0F;
|
||||||
|
if (value === 0 || value === false) {
|
||||||
|
this.digital_output_data[port_num] &= ~(1 << (pin & 0x07));
|
||||||
|
} else {
|
||||||
|
this.digital_output_data[port_num] |= 1 << (pin & 0x07);
|
||||||
|
}
|
||||||
|
return this.write([ArduinoFirmata.DIGITAL_MESSAGE | port_num, this.digital_output_data[port_num] & 0x7F, this.digital_output_data[port_num] >>> 7], callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
analogWrite(pin, value, callback) {
|
||||||
|
value = Math.floor(value);
|
||||||
|
this.pinMode(pin, ArduinoFirmata.PWM);
|
||||||
|
return this.write([ArduinoFirmata.ANALOG_MESSAGE | (pin & 0x0F), value & 0x7F, value >>> 7], callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
servoWrite(pin, angle, callback) {
|
||||||
|
this.pinMode(pin, ArduinoFirmata.SERVO);
|
||||||
|
return this.write([ArduinoFirmata.ANALOG_MESSAGE | (pin & 0x0F), angle & 0x7F, angle >>> 7], callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
digitalRead(pin) {
|
||||||
|
return ((this.digital_input_data[pin >>> 3] >>> (pin & 0x07)) & 0x01) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
analogRead(pin) {
|
||||||
|
return this.analog_input_data[pin];
|
||||||
|
}
|
||||||
|
|
||||||
|
process_input(input_data) {
|
||||||
|
var analog_value, command, diff, i, j, old_analog_value, results, stat, sysex_command, sysex_data;
|
||||||
|
if (this.parsing_sysex) {
|
||||||
|
if (input_data === ArduinoFirmata.END_SYSEX) {
|
||||||
|
this.parsing_sysex = false;
|
||||||
|
sysex_command = this.stored_input_data[0];
|
||||||
|
sysex_data = this.stored_input_data.slice(1, this.sysex_bytes_read);
|
||||||
|
return this.emit('sysex', {
|
||||||
|
command: sysex_command,
|
||||||
|
data: sysex_data
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.stored_input_data[this.sysex_bytes_read] = input_data;
|
||||||
|
return this.sysex_bytes_read += 1;
|
||||||
|
}
|
||||||
|
} else if (this.wait_for_data > 0 && input_data < 128) {
|
||||||
|
this.wait_for_data -= 1;
|
||||||
|
this.stored_input_data[this.wait_for_data] = input_data;
|
||||||
|
if (this.execute_multi_byte_command !== 0 && this.wait_for_data === 0) {
|
||||||
|
switch (this.execute_multi_byte_command) {
|
||||||
|
case ArduinoFirmata.DIGITAL_MESSAGE:
|
||||||
|
input_data = (this.stored_input_data[0] << 7) + this.stored_input_data[1];
|
||||||
|
diff = this.digital_input_data[this.multi_byte_channel] ^ input_data;
|
||||||
|
this.digital_input_data[this.multi_byte_channel] = input_data;
|
||||||
|
if (this.listeners('digitalChange').length > 0) {
|
||||||
|
results = [];
|
||||||
|
for (i = j = 0; j <= 13; i = ++j) {
|
||||||
|
if (((0x01 << i) & diff) > 0) {
|
||||||
|
stat = (input_data & diff) > 0;
|
||||||
|
results.push(this.emit('digitalChange', {
|
||||||
|
pin: i + this.multi_byte_channel * 8,
|
||||||
|
value: stat,
|
||||||
|
old_value: !stat
|
||||||
|
}));
|
||||||
|
} else {
|
||||||
|
results.push(void 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ArduinoFirmata.ANALOG_MESSAGE:
|
||||||
|
analog_value = (this.stored_input_data[0] << 7) + this.stored_input_data[1];
|
||||||
|
old_analog_value = this.analogRead(this.multi_byte_channel);
|
||||||
|
this.analog_input_data[this.multi_byte_channel] = analog_value;
|
||||||
|
if (old_analog_value !== analog_value) {
|
||||||
|
return this.emit('analogChange', {
|
||||||
|
pin: this.multi_byte_channel,
|
||||||
|
value: analog_value,
|
||||||
|
old_value: old_analog_value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case ArduinoFirmata.REPORT_VERSION:
|
||||||
|
this.boardVersion = `${this.stored_input_data[1]}.${this.stored_input_data[0]}`;
|
||||||
|
return this.emit('boardVersion', this.boardVersion);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (input_data < 0xF0) {
|
||||||
|
command = input_data & 0xF0;
|
||||||
|
this.multi_byte_channel = input_data & 0x0F;
|
||||||
|
} else {
|
||||||
|
command = input_data;
|
||||||
|
}
|
||||||
|
if (command === ArduinoFirmata.START_SYSEX) {
|
||||||
|
this.parsing_sysex = true;
|
||||||
|
return this.sysex_bytes_read = 0;
|
||||||
|
} else if (command === ArduinoFirmata.DIGITAL_MESSAGE || command === ArduinoFirmata.ANALOG_MESSAGE || command === ArduinoFirmata.REPORT_VERSION) {
|
||||||
|
this.wait_for_data = 2;
|
||||||
|
return this.execute_multi_byte_command = command;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
ArduinoFirmata.Status = {
|
ArduinoFirmata.Status = {
|
||||||
CLOSE: 0,
|
CLOSE: 0,
|
||||||
|
@ -38,269 +270,26 @@
|
||||||
|
|
||||||
ArduinoFirmata.MAX_DATA_BYTES = 32;
|
ArduinoFirmata.MAX_DATA_BYTES = 32;
|
||||||
|
|
||||||
ArduinoFirmata.DIGITAL_MESSAGE = 0x90;
|
ArduinoFirmata.DIGITAL_MESSAGE = 0x90; // send data for a digital port
|
||||||
|
|
||||||
ArduinoFirmata.ANALOG_MESSAGE = 0xE0;
|
ArduinoFirmata.ANALOG_MESSAGE = 0xE0; // send data for an analog pin (or PWM)
|
||||||
|
|
||||||
ArduinoFirmata.REPORT_ANALOG = 0xC0;
|
ArduinoFirmata.REPORT_ANALOG = 0xC0; // enable analog input by pin
|
||||||
|
|
||||||
ArduinoFirmata.REPORT_DIGITAL = 0xD0;
|
ArduinoFirmata.REPORT_DIGITAL = 0xD0; // enable digital input by port
|
||||||
|
|
||||||
ArduinoFirmata.SET_PIN_MODE = 0xF4;
|
ArduinoFirmata.SET_PIN_MODE = 0xF4; // set a pin to INPUT/OUTPUT/PWM/etc
|
||||||
|
|
||||||
ArduinoFirmata.REPORT_VERSION = 0xF9;
|
ArduinoFirmata.REPORT_VERSION = 0xF9; // report firmware version
|
||||||
|
|
||||||
ArduinoFirmata.SYSTEM_RESET = 0xFF;
|
ArduinoFirmata.SYSTEM_RESET = 0xFF; // reset from MIDI
|
||||||
|
|
||||||
ArduinoFirmata.START_SYSEX = 0xF0;
|
ArduinoFirmata.START_SYSEX = 0xF0; // start a MIDI SysEx message
|
||||||
|
|
||||||
ArduinoFirmata.END_SYSEX = 0xF7;
|
ArduinoFirmata.END_SYSEX = 0xF7; // end a MIDI SysEx message
|
||||||
|
|
||||||
ArduinoFirmata.list = function(callback) {
|
|
||||||
return serialport.list(function(err, ports) {
|
|
||||||
var devices, j, len, port;
|
|
||||||
if (err) {
|
|
||||||
return callback(err);
|
|
||||||
}
|
|
||||||
devices = [];
|
|
||||||
for (j = 0, len = ports.length; j < len; j++) {
|
|
||||||
port = ports[j];
|
|
||||||
if (/usb|acm|com\d+/i.test(port.comName)) {
|
|
||||||
devices.push(port.comName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return callback(null, devices);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
function ArduinoFirmata() {
|
|
||||||
this.status = ArduinoFirmata.Status.CLOSE;
|
|
||||||
this.wait_for_data = 0;
|
|
||||||
this.execute_multi_byte_command = 0;
|
|
||||||
this.multi_byte_channel = 0;
|
|
||||||
this.stored_input_data = [];
|
|
||||||
this.parsing_sysex = false;
|
|
||||||
this.sysex_bytes_read = 0;
|
|
||||||
this.digital_output_data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
||||||
this.digital_input_data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
||||||
this.analog_input_data = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
||||||
this.boardVersion = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
ArduinoFirmata.prototype.isOldArduinoDevice = function() {
|
|
||||||
return /usbserial|USB/.test(this.serialport_name);
|
|
||||||
};
|
|
||||||
|
|
||||||
ArduinoFirmata.prototype.connect = function(serialport_name, opts) {
|
|
||||||
this.serialport_name = serialport_name;
|
|
||||||
if (opts == null) {
|
|
||||||
opts = {
|
|
||||||
baudrate: 57600
|
|
||||||
};
|
|
||||||
}
|
|
||||||
opts.parser = serialport.parsers.raw;
|
|
||||||
if (!this.serialport_name) {
|
|
||||||
ArduinoFirmata.list((function(_this) {
|
|
||||||
return function(err, devices) {
|
|
||||||
return _this.connect(devices[0], opts);
|
|
||||||
};
|
|
||||||
})(this));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
this.once('boardReady', function() {
|
|
||||||
var io_init_wait;
|
|
||||||
debug('boardReady');
|
|
||||||
io_init_wait = this.isOldArduinoDevice() ? (debug("old arduino device found " + this.serialport_name), 3000) : (debug("new arduino device found " + this.serialport_name), 100);
|
|
||||||
debug("wait " + io_init_wait + "(msec)");
|
|
||||||
return setTimeout((function(_this) {
|
|
||||||
return function() {
|
|
||||||
var i, j, k;
|
|
||||||
for (i = j = 0; j < 6; i = ++j) {
|
|
||||||
_this.write([ArduinoFirmata.REPORT_ANALOG | i, 1]);
|
|
||||||
}
|
|
||||||
for (i = k = 0; k < 2; i = ++k) {
|
|
||||||
_this.write([ArduinoFirmata.REPORT_DIGITAL | i, 1]);
|
|
||||||
}
|
|
||||||
debug('init IO ports');
|
|
||||||
return _this.emit('connect');
|
|
||||||
};
|
|
||||||
})(this), io_init_wait);
|
|
||||||
});
|
|
||||||
this.serialport = new SerialPort(this.serialport_name, opts);
|
|
||||||
this.serialport.once('open', (function(_this) {
|
|
||||||
return function() {
|
|
||||||
var cid;
|
|
||||||
cid = setInterval(function() {
|
|
||||||
debug('request REPORT_VERSION');
|
|
||||||
return _this.write([ArduinoFirmata.REPORT_VERSION]);
|
|
||||||
}, 500);
|
|
||||||
_this.once('boardVersion', function(version) {
|
|
||||||
clearInterval(cid);
|
|
||||||
_this.status = ArduinoFirmata.Status.OPEN;
|
|
||||||
return _this.emit('boardReady');
|
|
||||||
});
|
|
||||||
return _this.serialport.on('data', function(data) {
|
|
||||||
var byte, j, len, results;
|
|
||||||
results = [];
|
|
||||||
for (j = 0, len = data.length; j < len; j++) {
|
|
||||||
byte = data[j];
|
|
||||||
results.push(_this.process_input(byte));
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
})(this));
|
|
||||||
return this;
|
|
||||||
};
|
|
||||||
|
|
||||||
ArduinoFirmata.prototype.isOpen = function() {
|
|
||||||
return this.status === ArduinoFirmata.Status.OPEN;
|
|
||||||
};
|
|
||||||
|
|
||||||
ArduinoFirmata.prototype.close = function(callback) {
|
|
||||||
this.status = ArduinoFirmata.Status.CLOSE;
|
|
||||||
return this.serialport.close(callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
ArduinoFirmata.prototype.reset = function(callback) {
|
|
||||||
return this.write([ArduinoFirmata.SYSTEM_RESET], callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
ArduinoFirmata.prototype.write = function(bytes, callback) {
|
|
||||||
return this.serialport.write(bytes, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
ArduinoFirmata.prototype.sysex = function(command, data, callback) {
|
|
||||||
var write_data;
|
|
||||||
if (data == null) {
|
|
||||||
data = [];
|
|
||||||
}
|
|
||||||
data = data.map(function(i) {
|
|
||||||
return i & 0x7f;
|
|
||||||
});
|
|
||||||
write_data = [ArduinoFirmata.START_SYSEX, command].concat(data, [ArduinoFirmata.END_SYSEX]);
|
|
||||||
return this.write(write_data, callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
ArduinoFirmata.prototype.pinMode = function(pin, mode, callback) {
|
|
||||||
switch (mode) {
|
|
||||||
case true:
|
|
||||||
mode = ArduinoFirmata.OUTPUT;
|
|
||||||
break;
|
|
||||||
case false:
|
|
||||||
mode = ArduinoFirmata.INPUT;
|
|
||||||
}
|
|
||||||
return this.write([ArduinoFirmata.SET_PIN_MODE, pin, mode], callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
ArduinoFirmata.prototype.digitalWrite = function(pin, value, callback) {
|
|
||||||
var port_num;
|
|
||||||
this.pinMode(pin, ArduinoFirmata.OUTPUT);
|
|
||||||
port_num = (pin >>> 3) & 0x0F;
|
|
||||||
if (value === 0 || value === false) {
|
|
||||||
this.digital_output_data[port_num] &= ~(1 << (pin & 0x07));
|
|
||||||
} else {
|
|
||||||
this.digital_output_data[port_num] |= 1 << (pin & 0x07);
|
|
||||||
}
|
|
||||||
return this.write([ArduinoFirmata.DIGITAL_MESSAGE | port_num, this.digital_output_data[port_num] & 0x7F, this.digital_output_data[port_num] >>> 7], callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
ArduinoFirmata.prototype.analogWrite = function(pin, value, callback) {
|
|
||||||
value = Math.floor(value);
|
|
||||||
this.pinMode(pin, ArduinoFirmata.PWM);
|
|
||||||
return this.write([ArduinoFirmata.ANALOG_MESSAGE | (pin & 0x0F), value & 0x7F, value >>> 7], callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
ArduinoFirmata.prototype.servoWrite = function(pin, angle, callback) {
|
|
||||||
this.pinMode(pin, ArduinoFirmata.SERVO);
|
|
||||||
return this.write([ArduinoFirmata.ANALOG_MESSAGE | (pin & 0x0F), angle & 0x7F, angle >>> 7], callback);
|
|
||||||
};
|
|
||||||
|
|
||||||
ArduinoFirmata.prototype.digitalRead = function(pin) {
|
|
||||||
return ((this.digital_input_data[pin >>> 3] >>> (pin & 0x07)) & 0x01) > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
ArduinoFirmata.prototype.analogRead = function(pin) {
|
|
||||||
return this.analog_input_data[pin];
|
|
||||||
};
|
|
||||||
|
|
||||||
ArduinoFirmata.prototype.process_input = function(input_data) {
|
|
||||||
var analog_value, command, diff, i, j, old_analog_value, results, stat, sysex_command, sysex_data;
|
|
||||||
if (this.parsing_sysex) {
|
|
||||||
if (input_data === ArduinoFirmata.END_SYSEX) {
|
|
||||||
this.parsing_sysex = false;
|
|
||||||
sysex_command = this.stored_input_data[0];
|
|
||||||
sysex_data = this.stored_input_data.slice(1, this.sysex_bytes_read);
|
|
||||||
return this.emit('sysex', {
|
|
||||||
command: sysex_command,
|
|
||||||
data: sysex_data
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.stored_input_data[this.sysex_bytes_read] = input_data;
|
|
||||||
return this.sysex_bytes_read += 1;
|
|
||||||
}
|
|
||||||
} else if (this.wait_for_data > 0 && input_data < 128) {
|
|
||||||
this.wait_for_data -= 1;
|
|
||||||
this.stored_input_data[this.wait_for_data] = input_data;
|
|
||||||
if (this.execute_multi_byte_command !== 0 && this.wait_for_data === 0) {
|
|
||||||
switch (this.execute_multi_byte_command) {
|
|
||||||
case ArduinoFirmata.DIGITAL_MESSAGE:
|
|
||||||
input_data = (this.stored_input_data[0] << 7) + this.stored_input_data[1];
|
|
||||||
diff = this.digital_input_data[this.multi_byte_channel] ^ input_data;
|
|
||||||
this.digital_input_data[this.multi_byte_channel] = input_data;
|
|
||||||
if (this.listeners('digitalChange').length > 0) {
|
|
||||||
results = [];
|
|
||||||
for (i = j = 0; j <= 13; i = ++j) {
|
|
||||||
if (((0x01 << i) & diff) > 0) {
|
|
||||||
stat = (input_data & diff) > 0;
|
|
||||||
results.push(this.emit('digitalChange', {
|
|
||||||
pin: i + this.multi_byte_channel * 8,
|
|
||||||
value: stat,
|
|
||||||
old_value: !stat
|
|
||||||
}));
|
|
||||||
} else {
|
|
||||||
results.push(void 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ArduinoFirmata.ANALOG_MESSAGE:
|
|
||||||
analog_value = (this.stored_input_data[0] << 7) + this.stored_input_data[1];
|
|
||||||
old_analog_value = this.analogRead(this.multi_byte_channel);
|
|
||||||
this.analog_input_data[this.multi_byte_channel] = analog_value;
|
|
||||||
if (old_analog_value !== analog_value) {
|
|
||||||
return this.emit('analogChange', {
|
|
||||||
pin: this.multi_byte_channel,
|
|
||||||
value: analog_value,
|
|
||||||
old_value: old_analog_value
|
|
||||||
});
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case ArduinoFirmata.REPORT_VERSION:
|
|
||||||
this.boardVersion = this.stored_input_data[1] + "." + this.stored_input_data[0];
|
|
||||||
return this.emit('boardVersion', this.boardVersion);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (input_data < 0xF0) {
|
|
||||||
command = input_data & 0xF0;
|
|
||||||
this.multi_byte_channel = input_data & 0x0F;
|
|
||||||
} else {
|
|
||||||
command = input_data;
|
|
||||||
}
|
|
||||||
if (command === ArduinoFirmata.START_SYSEX) {
|
|
||||||
this.parsing_sysex = true;
|
|
||||||
return this.sysex_bytes_read = 0;
|
|
||||||
} else if (command === ArduinoFirmata.DIGITAL_MESSAGE || command === ArduinoFirmata.ANALOG_MESSAGE || command === ArduinoFirmata.REPORT_VERSION) {
|
|
||||||
this.wait_for_data = 2;
|
|
||||||
return this.execute_multi_byte_command = command;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return ArduinoFirmata;
|
return ArduinoFirmata;
|
||||||
|
|
||||||
})(events.EventEmitter2);
|
}).call(this);
|
||||||
|
|
||||||
}).call(this);
|
}).call(this);
|
||||||
|
|
Loading…
Reference in New Issue