Initial commit - working Toy Pad interaction
This commit is contained in:
commit
c403ec3f2b
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
.idea/
|
||||||
|
node_modules/
|
10
data/minifigs.json
Normal file
10
data/minifigs.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"47 5c 0a 6e 40 81": "Batman",
|
||||||
|
"19 a9 7a 99 40 80": "Gandalf",
|
||||||
|
"11 d3 da 98 40 81": "Wyldstyle",
|
||||||
|
"d9 e6 52 5c 49 80": "Unikitty",
|
||||||
|
"40 42 b2 2a 49 80": "Slimer",
|
||||||
|
"ed 0c 32 75 40 84": "Bane",
|
||||||
|
"d4 61 82 55 42 80": "Lloyd",
|
||||||
|
"54 60 a2 5b 49 81": "Krusty-the-Clown"
|
||||||
|
}
|
24
main.js
Normal file
24
main.js
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
let ToyPad = require("./src/toypad.js");
|
||||||
|
|
||||||
|
let toyPad = new ToyPad();
|
||||||
|
|
||||||
|
toyPad.on("connect", () => {
|
||||||
|
console.log("Toy Pad connected");
|
||||||
|
toyPad.setColor(ToyPad.Panel.CENTER, 0xffff44, 0.5);
|
||||||
|
});
|
||||||
|
|
||||||
|
toyPad.on("error", () => {
|
||||||
|
console.log("Toy Pad connection error");
|
||||||
|
});
|
||||||
|
|
||||||
|
toyPad.on("add", (data) => {
|
||||||
|
let name = ToyPad.minifigNameFromSignature(data.sig);
|
||||||
|
console.log(`Minifig added to panel ${data.panel} (${name})`);
|
||||||
|
});
|
||||||
|
|
||||||
|
toyPad.on("remove", (data) => {
|
||||||
|
let name = ToyPad.minifigNameFromSignature(data.sig);
|
||||||
|
console.log(`Minifig removed from panel ${data.panel} (${name})`);
|
||||||
|
});
|
||||||
|
|
||||||
|
toyPad.connect();
|
14
package.json
Normal file
14
package.json
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"name": "retrodimensions",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "Retro Dimensions",
|
||||||
|
"main": "main.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"author": "Nathan Kunicki <me@nathankunicki.com>",
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"node-hid": "0.5.1"
|
||||||
|
}
|
||||||
|
}
|
167
src/toypad.js
Normal file
167
src/toypad.js
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
let EventEmitter = require("events").EventEmitter,
|
||||||
|
HID = require("node-hid");
|
||||||
|
|
||||||
|
|
||||||
|
const minifigData = require("../data/minifigs.json");
|
||||||
|
let Minifig = {};
|
||||||
|
|
||||||
|
Object.keys(minifigData).forEach((sig) => {
|
||||||
|
Minifig[minifigData[sig].toUpperCase().replace(/\W+/g, "_")] = sig;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const Action = {
|
||||||
|
ADD: 0,
|
||||||
|
REMOVE: 1
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const Command = {
|
||||||
|
CONNECTED: 0x19,
|
||||||
|
ACTION: 0x0b
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
const Panel = {
|
||||||
|
ALL: 0,
|
||||||
|
CENTER: 1,
|
||||||
|
LEFT: 2,
|
||||||
|
RIGHT: 3
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class ToyPad extends EventEmitter {
|
||||||
|
|
||||||
|
|
||||||
|
constructor () {
|
||||||
|
super();
|
||||||
|
this._device = null;
|
||||||
|
this._requestId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static get Panel () {
|
||||||
|
return Panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static get Minifig () {
|
||||||
|
return Minifig;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static minifigNameFromSignature (sig) {
|
||||||
|
if (minifigData[sig]) {
|
||||||
|
return minifigData[sig];
|
||||||
|
} else {
|
||||||
|
return `Unknown - ${sig}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static _bufferToHexString (buf) {
|
||||||
|
let str = "";
|
||||||
|
for (let i = 0; i < buf.length; i++) {
|
||||||
|
str +=
|
||||||
|
((buf[i] >> 4) & 0xf).toString(16) +
|
||||||
|
(buf[i] & 0xf).toString(16) +
|
||||||
|
" ";
|
||||||
|
}
|
||||||
|
return str.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static _checksum (data) {
|
||||||
|
let checksum = 0;
|
||||||
|
for (let i = 0; i < data.length; i++) {
|
||||||
|
checksum += data[i];
|
||||||
|
}
|
||||||
|
data.push(checksum & 0xFF);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static _pad (data) {
|
||||||
|
while (data.length < 32) {
|
||||||
|
data.push(0x00);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
connect () {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
this._device = new HID.HID(3695, 577);
|
||||||
|
|
||||||
|
this._device.on("data", (data) => {
|
||||||
|
|
||||||
|
let cmd = data[1];
|
||||||
|
|
||||||
|
if (cmd == Command.CONNECTED) {
|
||||||
|
this.emit("connect");
|
||||||
|
} else if (cmd == Command.ACTION) {
|
||||||
|
|
||||||
|
let action = data[5];
|
||||||
|
|
||||||
|
let emitPayload = {
|
||||||
|
panel: data[2],
|
||||||
|
sig: ToyPad._bufferToHexString(data.slice(7, 13))
|
||||||
|
};
|
||||||
|
|
||||||
|
if (action == Action.ADD) {
|
||||||
|
this.emit("add", emitPayload);
|
||||||
|
} else if (action == Action.REMOVE) {
|
||||||
|
this.emit("remove", emitPayload);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
this._device.on("error", (err) => {
|
||||||
|
this.emit(err);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wake the Toy Pad
|
||||||
|
this._device.write([0x00,
|
||||||
|
0x55, 0x0f, 0xb0, 0x01,
|
||||||
|
0x28, 0x63, 0x29, 0x20,
|
||||||
|
0x4c, 0x45, 0x47, 0x4f,
|
||||||
|
0x20, 0x32, 0x30, 0x31,
|
||||||
|
0x34, 0xf7, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00]);
|
||||||
|
|
||||||
|
} catch (err) {
|
||||||
|
this.emit("error");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
setColor (panel, color, speed = 1) {
|
||||||
|
let data = [
|
||||||
|
this._requestId & 0xff,
|
||||||
|
panel,
|
||||||
|
((1 - speed) * 0xff) & 0xff,
|
||||||
|
0x01, (color >> 16) & 0xff,
|
||||||
|
(color >> 8) & 0xff,
|
||||||
|
color & 0xff
|
||||||
|
];
|
||||||
|
this._requestId++;
|
||||||
|
this._write([0x55, 0x08, 0xc2].concat(data));
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
_write (data) {
|
||||||
|
this._device.write([0x00].concat(ToyPad._pad(ToyPad._checksum(data))));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = ToyPad;
|
Loading…
x
Reference in New Issue
Block a user