diff --git a/firmata/firmata-tests.ts b/firmata/firmata-tests.ts
new file mode 100644
index 0000000000..93cbb7d8db
--- /dev/null
+++ b/firmata/firmata-tests.ts
@@ -0,0 +1,46 @@
+// Tests for firmata.d.ts
+// Project: https://github.com/firmata/firmata.js
+// Definitions by: Troy W.
+
+import * as Board from 'firmata'
+
+function test_basic_board()
+{
+ let board = new Board('');
+}
+
+function test_board_with_callback()
+{
+ let board = new Board('', (error:any) =>
+ {
+ board.pinMode(13, board.MODES.OUTPUT);
+ board.pinMode(12, Board.PIN_MODES.OUTPUT);
+ });
+}
+
+function test_board_with_listener()
+{
+ let board = new Board('');
+
+ board.on('ready', () =>
+ {
+ board.pinMode(13, board.MODES.OUTPUT);
+ board.pinMode(12, Board.PIN_MODES.OUTPUT);
+ });
+}
+
+function test_class_extension()
+{
+ class MyBoard extends Board
+ {
+ Disconnect()
+ {
+ this.transport.close((error:any) => {});
+ }
+ }
+
+ let myBoard:MyBoard = new MyBoard('', () =>
+ {
+ myBoard.Disconnect();
+ });
+}
\ No newline at end of file
diff --git a/firmata/firmata.d.ts b/firmata/firmata.d.ts
new file mode 100644
index 0000000000..a732f01339
--- /dev/null
+++ b/firmata/firmata.d.ts
@@ -0,0 +1,274 @@
+// Type definitions for firmata.js v0.15.0
+// Project: https://github.com/firmata/firmata.js
+// Definitions by: Troy W.
+
+declare module 'firmata'
+{
+ import * as SerialPort from 'serialport'
+ import { EventEmitter } from 'events'
+
+ /**
+ * Most of these are generated by observing https://github.com/firmata/firmata.js/blob/master/lib/firmata.js
+ * items not exported are intentionally so, they exist only to inform intelligent completion and should not be exported
+ * without good reasoning.
+ *
+ * Also, this is a starting point that appeared to work fine for months within a project of my company, but I give no
+ * guarantee that it cannot be improved.
+ */
+ class Board extends EventEmitter
+ {
+ constructor(serialPort:string, callback?:(error:any) => void)
+
+ public MODES:Board.IPinModes;
+ public STEPPER:Board.IStepperConstants;
+ public I2C_MODES:Board.II2cModes;
+ public SERIAL_MODES:Board.ISerialModes;
+ public SERIAL_PORT_IDs:Board.ISerialPortIds;
+ public SERIAL_PIN_TYPES:Board.ISerialPinTypes;
+ public HIGH:Board.PIN_STATE;
+ public LOW:Board.PIN_STATE;
+ public pins:Board.IPins[];
+ public ports:number[];
+ public analogPins:number[];
+ public version:Board.IVersion;
+ public firmware:Board.IFirmware;
+ public settings:Board.ISettings;
+
+ public reportVersion(callback:() => void):void
+ public queryFirmware(callback:() => void):void
+ public analogRead(pin:number, callback:(value:number) => void):void
+ public analogWrite(pin:number, value:number):void
+ public pwmWrite(pin:number, value:number):void
+ public servoConfig(pin:number, min:number, max:number):void
+ public servoWrite(pin:number, value:number):void
+ public pinMode(pin:number, mode:Board.PIN_MODES):void
+ public digitalWrite(pin:number, val:Board.PIN_STATE):void
+ public digitalRead(pin:number, callback:(val:Board.PIN_STATE) => void):void
+ public queryCapabilities(callback:() => void):void
+ public queryAnalogMapping(callback:() => void):void
+ public queryPinState(pin:number, callback:() => void):void
+ public sendString(str):void // TODO untested/incomplete --- TWW
+ public sendI2CConfig(delay):void // TODO untested/incomplete --- TWW
+ public i2cConfig(options):void // TODO untested/incomplete --- TWW
+ public sendI2CWriteRequest(slaveAddress, bytes):void // TODO untested/incomplete --- TWW
+ public i2cWrite(address, registerOrData, inBytes):void // TODO untested/incomplete --- TWW
+ public i2cWriteReg(address, register, byte):void // TODO untested/incomplete --- TWW
+ public sendI2CReadRequest(address, numBytes, callback):void // TODO untested/incomplete --- TWW
+ public i2cRead(address, register, bytesToRead, callback):void // TODO untested/incomplete --- TWW
+ public i2cStop(options):void // TODO untested/incomplete --- TWW
+ public i2cReadOnce(address, register, bytesToRead, callback):void // TODO untested/incomplete --- TWW
+ public sendOneWireConfig(pin, enableParasiticPower):void // TODO untested/incomplete --- TWW
+ public sendOneWireSearch(pin, callback):void // TODO untested/incomplete --- TWW
+ public sendOneWireAlarmsSearch(pin, callback):void // TODO untested/incomplete --- TWW
+ public sendOneWireRead(pin, device, numBytesToRead, callback):void // TODO untested/incomplete --- TWW
+ public sendOneWireReset(pin):void // TODO untested/incomplete --- TWW
+ public sendOneWireWrite(pin, device, data):void // TODO untested/incomplete --- TWW
+ public sendOneWireDelay(pin, delay):void // TODO untested/incomplete --- TWW
+ public sendOneWireWriteAndRead(pin, device, data, numBytesToRead, callback):void // TODO untested/incomplete --- TWW
+ public setSamplingInterval(interval:number):void
+ public getSamplingInterval():number // TODO untested/incomplete --- TWW
+ public reportAnalogPin(pin:number, value:Board.REPORTING):void
+ public reportDigitalPin(pin:number, value:Board.REPORTING):void
+ public pingRead(opts, callback):void // TODO untested/incomplete --- TWW
+ public stepperConfig(deviceNum:number, type:number, stepsPerRev:number, dirOrMotor1Pin:number,
+ stepOrMotor2Pin:number,
+ motor3Pin?:number, motor4Pin?:number):void
+ public stepperStep(deviceNum:number, direction:number, steps:number, speed:number, accel:number, decel:number,
+ callback:(bool?:boolean) => void):void
+ public serialConfig(options):void // TODO untested/incomplete --- TWW
+ public serialWrite(portId, inBytes):void // TODO untested/incomplete --- TWW
+ public serialRead(portId, maxBytesToRead, callback):void // TODO untested/incomplete --- TWW
+ public serialStop(portId):void // TODO untested/incomplete --- TWW
+ public serialClose(portId):void // TODO untested/incomplete --- TWW
+ public serialFlush(portId):void // TODO untested/incomplete --- TWW
+ public serialListen(portId):void // TODO untested/incomplete --- TWW
+ public sysexResponse(commandByte, handler):void // TODO untested/incomplete --- TWW
+ public sysexCommand(message):void // TODO untested/incomplete --- TWW
+ public reset():void
+ public static isAcceptablePort(port:Board.IPort):boolean // TODO untested/incomplete --- TWW
+ public static requestPort(callback:(error:any, port:Board.IPort) => any):void // TODO untested/incomplete --- TWW
+ public static encode(data:number[]):number[] // TODO untested/incomplete --- TWW
+ public static decode(data:number[]):number[] // TODO untested/incomplete --- TWW
+
+ protected transport:SerialPort;
+
+ protected _sendOneWireSearch(type, event, pin, callback):void // TODO untested/incomplete --- TWW
+ protected _sendOneWireRequest(pin, subcommand, device, numBytesToRead, correlationId, delay, dataToWrite, event,
+ callback):void // TODO untested/incomplete --- TWW
+ }
+
+ namespace Board
+ {
+ export interface IPinModes
+ {
+ INPUT:PIN_MODES, OUTPUT:PIN_MODES, ANALOG:PIN_MODES, PWM:PIN_MODES, SERVO:PIN_MODES,
+ SHIFT:PIN_MODES, I2C:PIN_MODES, ONEWIRE:PIN_MODES, STEPPER:PIN_MODES, SERIAL:PIN_MODES,
+ PULLUP:PIN_MODES, IGNORE:PIN_MODES, PING_READ:PIN_MODES, UNKOWN:PIN_MODES
+ }
+
+ export interface IStepperConstants
+ {
+ TYPE:{ DRIVER:STEPPER_TYPES, TWO_WIRE:STEPPER_TYPES, FOUR_WIRE:STEPPER_TYPES },
+ RUNSTATE:{
+ STOP:STEPPER_RUN_STATES, ACCEL:STEPPER_RUN_STATES, DECEL:STEPPER_RUN_STATES, RUN:STEPPER_RUN_STATES
+ },
+ DIRECTION:{ CCW:STEPPER_DIRECTIONS, CW:STEPPER_DIRECTIONS }
+ }
+
+ export interface II2cModes
+ {
+ WRITE:I2C_MODES, READ:I2C_MODES, CONTINUOUS_READ:I2C_MODES, STOP_READING:I2C_MODES
+ }
+
+ export interface ISerialModes
+ {
+ CONTINUOUS_READ:SERIAL_MODES, STOP_READING:SERIAL_MODES
+ }
+
+ export interface ISerialPortIds
+ {
+ HW_SERIAL0:SERIAL_PORT_IDs, HW_SERIAL1:SERIAL_PORT_IDs, HW_SERIAL2:SERIAL_PORT_IDs, HW_SERIAL3:SERIAL_PORT_IDs,
+ SW_SERIAL0:SERIAL_PORT_IDs, SW_SERIAL1:SERIAL_PORT_IDs,SW_SERIAL2:SERIAL_PORT_IDs, SW_SERIAL3:SERIAL_PORT_IDs,
+ DEFAULT:SERIAL_PORT_IDs,
+ }
+
+ export interface ISerialPinTypes
+ {
+ RES_RX0:SERIAL_PIN_TYPES, RES_TX0:SERIAL_PIN_TYPES, RES_RX1:SERIAL_PIN_TYPES, RES_TX1:SERIAL_PIN_TYPES,
+ RES_RX2:SERIAL_PIN_TYPES, RES_TX2:SERIAL_PIN_TYPES, RES_RX3:SERIAL_PIN_TYPES, RES_TX3:SERIAL_PIN_TYPES,
+ }
+
+ export interface IPins
+ {
+ mode:PIN_MODES,
+ value:PIN_STATE|number,
+ supportedModes:PIN_MODES[],
+ analogChannel:number,
+ report:REPORTING,
+ state:PIN_STATE|PULLUP_STATE, // TODO not sure if this exists anymore... --- TWW
+ }
+
+ export interface IFirmware
+ {
+ name:string,
+ version:IVersion,
+ }
+
+ export interface ISettings
+ {
+ reportVersionTimeout:number,
+ samplingInterval:number,
+ serialport:{
+ baudRate:number,
+ bufferSize:number
+ }
+ }
+
+ export interface IPort
+ {
+ comName:string,
+ }
+
+ export interface IVersion
+ {
+ major:number,
+ minor:number
+ }
+
+ // TODO these enums could actually be non-const in the future (provides some benefits) --- TWW
+ // https://github.com/firmata/firmata.js/blob/master/lib/firmata.js#L431
+ export const enum PIN_MODES {
+ INPUT = 0x00,
+ OUTPUT = 0x01,
+ ANALOG = 0x02,
+ PWM = 0x03,
+ SERVO = 0x04,
+ SHIFT = 0x05,
+ I2C = 0x06,
+ ONEWIRE = 0x07,
+ STEPPER = 0x08,
+ SERIAL = 0x0A,
+ PULLUP = 0x0B,
+ IGNORE = 0x7F,
+ PING_READ = 0x75,
+ UNKNOWN = 0x10,
+ }
+
+ export const enum PIN_STATE {
+ LOW = 0,
+ HIGH = 1,
+ }
+
+ export const enum REPORTING {
+ ON = 1,
+ OFF = 0,
+ }
+
+ export const enum PULLUP_STATE {
+ ENABLED = 1,
+ DISABLED = 0,
+ }
+
+ // https://github.com/firmata/firmata.js/blob/master/lib/firmata.js#L456
+ export const enum STEPPER_TYPES {
+ DRIVER = 1,
+ TWO_WIRE = 2,
+ FOUR_WIRE = 4,
+ }
+
+ // https://github.com/firmata/firmata.js/blob/master/lib/firmata.js#L461
+ export const enum STEPPER_RUN_STATES {
+ STOP = 0,
+ ACCEL = 1,
+ DECEL = 2,
+ RUN = 3,
+ }
+
+ // https://github.com/firmata/firmata.js/blob/master/lib/firmata.js#L467
+ export const enum STEPPER_DIRECTIONS {
+ CCW = 0,
+ CW = 1,
+ }
+
+ // https://github.com/firmata/firmata.js/blob/master/lib/firmata.js#L448
+ export const enum I2C_MODES {
+ WRITE = 0,
+ READ = 1,
+ CONTINUOUS_READ = 2,
+ STOP_READING = 3
+ }
+
+ // https://github.com/firmata/firmata.js/blob/master/lib/firmata.js#L473
+ export const enum SERIAL_MODES {
+ CONTINUOUS_READ = 0x00,
+ STOP_READING = 0x01,
+ }
+
+ // https://github.com/firmata/firmata.js/blob/master/lib/firmata.js#L479
+ export const enum SERIAL_PORT_IDs {
+ HW_SERIAL0 = 0x00,
+ HW_SERIAL1 = 0x01,
+ HW_SERIAL2 = 0x02,
+ HW_SERIAL3 = 0x03,
+ SW_SERIAL0 = 0x08,
+ SW_SERIAL1 = 0x09,
+ SW_SERIAL2 = 0x10,
+ SW_SERIAL3 = 0x11,
+ DEFAULT = 0x08,
+ }
+
+ // https://github.com/firmata/firmata.js/blob/master/lib/firmata.js#L497
+ export const enum SERIAL_PIN_TYPES {
+ RES_RX0 = 0x00,
+ RES_TX0 = 0x01,
+ RES_RX1 = 0x02,
+ RES_TX1 = 0x03,
+ RES_RX2 = 0x04,
+ RES_TX2 = 0x05,
+ RES_RX3 = 0x06,
+ RES_TX3 = 0x07,
+ }
+ }
+
+ export = Board;
+}
\ No newline at end of file
diff --git a/firmata/readme.md b/firmata/readme.md
new file mode 100644
index 0000000000..32bb7df11f
--- /dev/null
+++ b/firmata/readme.md
@@ -0,0 +1,46 @@
+# Usage
+
+For typescript projects, instead of
+
+```js
+var Board = require('firmata');
+```
+
+you should use
+
+```typescript
+import * as Board from 'firmata'
+```
+
+You will find that `const enums` are exported under the namespace `Board` for ease of comparison or
+use with other libraries before any boards are actually instantiated.
+
+It's also important to note that if you want to extend the `Board` class in typescript, the
+following will work (as long as you turn on `--noImplicitUseStrict` when compiling); here's
+an example:
+
+```typescript
+// store as script.ts and compile with `tsc --noImplicitUseStrict script.ts`
+// then run `node script.js`
+
+import * as Board from 'firmata'
+
+let portString = 'port string';
+
+class MyBoard extends Board
+{
+ Disconnect()
+ {
+ this.transport.close(() =>
+ {
+ console.log('extended board closed');
+ });
+ }
+}
+
+let myBoard:MyBoard = new MyBoard(portString, () =>
+{
+ console.log('extended board ready');
+ myBoard.Disconnect();
+});
+```
\ No newline at end of file
diff --git a/firmata/tsconfig.json b/firmata/tsconfig.json
new file mode 100644
index 0000000000..c1b83e40b5
--- /dev/null
+++ b/firmata/tsconfig.json
@@ -0,0 +1,22 @@
+{
+ "compilerOptions": {
+ "module": "commonjs",
+ "lib": [
+ "es6"
+ ],
+ "noImplicitAny": true,
+ "noImplicitThis": true,
+ "strictNullChecks": false,
+ "baseUrl": "../",
+ "typeRoots": [
+ "../"
+ ],
+ "types": [],
+ "noEmit": true,
+ "forceConsistentCasingInFileNames": true
+ },
+ "files": [
+ "firmata.d.ts",
+ "firmata-tests.ts"
+ ]
+}
\ No newline at end of file