Support for Super Mario
This commit is contained in:
commit
be8495a2f2
40
examples/mario.js
Normal file
40
examples/mario.js
Normal file
@ -0,0 +1,40 @@
|
||||
/*
|
||||
*
|
||||
* This demonstrates connecting to LEGO Super Mario.
|
||||
*
|
||||
*/
|
||||
|
||||
const PoweredUP = require("..");
|
||||
|
||||
const poweredUP = new PoweredUP.PoweredUP();
|
||||
poweredUP.scan(); // Start scanning for hubs
|
||||
|
||||
console.log("Looking for Mario...");
|
||||
|
||||
poweredUP.on("discover", async (hub) => { // Wait to discover hubs
|
||||
|
||||
if (hub instanceof PoweredUP.Mario) {
|
||||
const mario = hub;
|
||||
await mario.connect(); // Connect to Mario
|
||||
console.log(`Connected to Mario!`);
|
||||
|
||||
const pants = await mario.waitForDeviceByType(PoweredUP.Consts.DeviceType.MARIO_PANTS_SENSOR);
|
||||
pants.on("pants", ({ pants }) => {
|
||||
console.log("Pants detected", pants);
|
||||
});
|
||||
|
||||
const barcodeSensor = await mario.waitForDeviceByType(PoweredUP.Consts.DeviceType.MARIO_BARCODE_SENSOR);
|
||||
barcodeSensor.on("barcode", ({ barcode, color }) => {
|
||||
if (color) {
|
||||
console.log("Color detected", color);
|
||||
} else if (barcode) {
|
||||
console.log("Barcode detected", barcode);
|
||||
}
|
||||
});
|
||||
|
||||
mario.on("disconnect", () => {
|
||||
console.log("Mario disconnected");
|
||||
});
|
||||
}
|
||||
|
||||
});
|
@ -7,6 +7,7 @@
|
||||
* @property {number} POWERED_UP_REMOTE 4
|
||||
* @property {number} DUPLO_TRAIN_HUB 5
|
||||
* @property {number} CONTROL_PLUS_HUB 6
|
||||
* @property {number} MARIO 7
|
||||
*/
|
||||
export enum HubType {
|
||||
UNKNOWN = 0,
|
||||
@ -15,7 +16,8 @@ export enum HubType {
|
||||
HUB = 3,
|
||||
REMOTE_CONTROL = 4,
|
||||
DUPLO_TRAIN_BASE = 5,
|
||||
TECHNIC_MEDIUM_HUB = 6
|
||||
TECHNIC_MEDIUM_HUB = 6,
|
||||
MARIO = 7,
|
||||
}
|
||||
|
||||
|
||||
@ -83,6 +85,8 @@ export enum DeviceType {
|
||||
TECHNIC_COLOR_SENSOR = 61, // Spike Prime
|
||||
TECHNIC_DISTANCE_SENSOR = 62, // Spike Prime
|
||||
TECHNIC_FORCE_SENSOR = 63, // Spike Prime
|
||||
MARIO_BARCODE_SENSOR = 73,
|
||||
MARIO_PANTS_SENSOR = 74,
|
||||
TECHNIC_MEDIUM_ANGULAR_MOTOR_GREY = 75, // Technic Control+
|
||||
TECHNIC_LARGE_ANGULAR_MOTOR_GREY = 76, // Technic Control+
|
||||
}
|
||||
@ -178,6 +182,7 @@ export enum BLEManufacturerData {
|
||||
MOVE_HUB_ID = 64,
|
||||
HUB_ID = 65,
|
||||
REMOTE_CONTROL_ID = 66,
|
||||
MARIO_ID = 67,
|
||||
TECHNIC_MEDIUM_HUB = 128
|
||||
}
|
||||
|
||||
@ -636,4 +641,43 @@ export enum PortInputFormatSetupSubCommand {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @typedef MarioPantsType
|
||||
* @param {number} NONE 0x00
|
||||
* @param {number} PROPELLER 0x06
|
||||
* @param {number} CAT 0x11
|
||||
* @param {number} FIRE 0x12
|
||||
* @param {number} NORMAL 0x21
|
||||
* @param {number} BUILDER 0x22
|
||||
*/
|
||||
export enum MarioPantsType {
|
||||
NONE = 0x00,
|
||||
PROPELLER = 0x06,
|
||||
CAT = 0x11,
|
||||
FIRE = 0x12,
|
||||
NORMAL = 0x21,
|
||||
BUILDER = 0x22,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @typedef MarioColor
|
||||
* @param {number} WHITE 0x1300
|
||||
* @param {number} RED 0x1500
|
||||
* @param {number} BLUE 0x1700
|
||||
* @param {number} YELLOW 0x1800
|
||||
* @param {number} BLACK 0x1a00
|
||||
* @param {number} GREEN 0x2500
|
||||
* @param {number} BROWN 0x6a00
|
||||
* @param {number} CYAN 0x4201
|
||||
*/
|
||||
export enum MarioColor {
|
||||
WHITE = 0x1300,
|
||||
RED = 0x1500,
|
||||
BLUE = 0x1700,
|
||||
YELLOW = 0x1800,
|
||||
BLACK = 0x1a00,
|
||||
GREEN = 0x2500,
|
||||
BROWN = 0x6a00,
|
||||
CYAN = 0x4201,
|
||||
}
|
||||
|
66
src/devices/mariobarcodesensor.ts
Normal file
66
src/devices/mariobarcodesensor.ts
Normal file
@ -0,0 +1,66 @@
|
||||
import { Device } from "./device";
|
||||
|
||||
import { IDeviceInterface } from "../interfaces";
|
||||
|
||||
import * as Consts from "../consts";
|
||||
|
||||
/**
|
||||
* @class MarioBarcodeSensor
|
||||
* @extends Device
|
||||
*/
|
||||
export class MarioBarcodeSensor extends Device {
|
||||
|
||||
constructor (hub: IDeviceInterface, portId: number) {
|
||||
super(hub, portId, ModeMap, Consts.DeviceType.MARIO_BARCODE_SENSOR);
|
||||
}
|
||||
|
||||
public receive (message: Buffer) {
|
||||
const mode = this._mode;
|
||||
|
||||
switch (mode) {
|
||||
case Mode.BARCODE:
|
||||
/**
|
||||
* Emits when the barcode sensor sees a barcode.
|
||||
* @event MarioBarcodeSensor#barcode
|
||||
* @type {object}
|
||||
* @param {number} id
|
||||
*/
|
||||
const barcode = message.readUInt16LE(4);
|
||||
const color = message.readUInt16LE(6);
|
||||
if (color === 0xffff) {
|
||||
// This is a barcode
|
||||
this.notify("barcode", { barcode });
|
||||
} else if (barcode === 0xffff) {
|
||||
// This is a color
|
||||
this.notify("barcode", { color });
|
||||
}
|
||||
break;
|
||||
case Mode.RGB:
|
||||
/**
|
||||
* Emits when the barcode sensor sees a RGB color.
|
||||
* @event MarioBarcodeSensor#rgb
|
||||
* @type {object}
|
||||
* @param {number} r
|
||||
* @param {number} g
|
||||
* @param {number} b
|
||||
*/
|
||||
const r = message[4];
|
||||
const g = message[5];
|
||||
const b = message[6];
|
||||
this.notify("rgb", { r, g, b });
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export enum Mode {
|
||||
BARCODE = 0x00,
|
||||
RGB = 0x01,
|
||||
}
|
||||
|
||||
export const ModeMap: {[event: string]: number} = {
|
||||
"barcode": Mode.BARCODE,
|
||||
"rgb": Mode.RGB,
|
||||
};
|
42
src/devices/mariopantssensor.ts
Normal file
42
src/devices/mariopantssensor.ts
Normal file
@ -0,0 +1,42 @@
|
||||
import { Device } from "./device";
|
||||
|
||||
import { IDeviceInterface } from "../interfaces";
|
||||
|
||||
import * as Consts from "../consts";
|
||||
|
||||
/**
|
||||
* @class MarioPantsSensor
|
||||
* @extends Device
|
||||
*/
|
||||
export class MarioPantsSensor extends Device {
|
||||
|
||||
constructor (hub: IDeviceInterface, portId: number) {
|
||||
super(hub, portId, ModeMap, Consts.DeviceType.MARIO_PANTS_SENSOR);
|
||||
}
|
||||
|
||||
public receive (message: Buffer) {
|
||||
const mode = this._mode;
|
||||
|
||||
switch (mode) {
|
||||
case Mode.PANTS:
|
||||
/**
|
||||
* Emits when the user changes the pants on Mario.
|
||||
* @event MarioPantsSensor#pants
|
||||
* @type {object}
|
||||
* @param {number} pants
|
||||
*/
|
||||
const pants = message[4];
|
||||
this.notify("pants", { pants });
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export enum Mode {
|
||||
PANTS = 0x00,
|
||||
}
|
||||
|
||||
export const ModeMap: {[event: string]: number} = {
|
||||
"pants": Mode.PANTS,
|
||||
};
|
@ -13,6 +13,8 @@ import { DuploTrainBaseSpeedometer } from "../devices/duplotrainbasespeedometer"
|
||||
|
||||
import { HubLED } from "../devices/hubled";
|
||||
import { Light } from "../devices/light";
|
||||
import { MarioBarcodeSensor } from "../devices/mariobarcodesensor";
|
||||
import { MarioPantsSensor } from "../devices/mariopantssensor";
|
||||
import { MediumLinearMotor } from "../devices/mediumlinearmotor";
|
||||
import { MotionSensor } from "../devices/motionsensor";
|
||||
import { MoveHubMediumLinearMotor } from "../devices/movehubmediumlinearmotor";
|
||||
@ -416,7 +418,9 @@ export class BaseHub extends EventEmitter {
|
||||
[Consts.DeviceType.DUPLO_TRAIN_BASE_COLOR_SENSOR]: DuploTrainBaseColorSensor,
|
||||
[Consts.DeviceType.DUPLO_TRAIN_BASE_MOTOR]: DuploTrainBaseMotor,
|
||||
[Consts.DeviceType.DUPLO_TRAIN_BASE_SPEAKER]: DuploTrainBaseSpeaker,
|
||||
[Consts.DeviceType.DUPLO_TRAIN_BASE_SPEEDOMETER]: DuploTrainBaseSpeedometer
|
||||
[Consts.DeviceType.DUPLO_TRAIN_BASE_SPEEDOMETER]: DuploTrainBaseSpeedometer,
|
||||
[Consts.DeviceType.MARIO_BARCODE_SENSOR]: MarioBarcodeSensor,
|
||||
[Consts.DeviceType.MARIO_PANTS_SENSOR]: MarioPantsSensor,
|
||||
};
|
||||
|
||||
constructor = deviceConstructors[deviceType as Consts.DeviceType];
|
||||
|
50
src/hubs/mario.ts
Normal file
50
src/hubs/mario.ts
Normal file
@ -0,0 +1,50 @@
|
||||
import { Peripheral } from "@abandonware/noble";
|
||||
import compareVersion from "compare-versions";
|
||||
|
||||
import { IBLEAbstraction } from "../interfaces";
|
||||
|
||||
import { LPF2Hub } from "./lpf2hub";
|
||||
|
||||
import * as Consts from "../consts";
|
||||
|
||||
import Debug = require("debug");
|
||||
const debug = Debug("movehub");
|
||||
|
||||
|
||||
/**
|
||||
* Mario is emitted if the discovered device is a LEGO Super Mario brick.
|
||||
* @class Mario
|
||||
* @extends LPF2Hub
|
||||
* @extends BaseHub
|
||||
*/
|
||||
export class Mario extends LPF2Hub {
|
||||
|
||||
|
||||
public static IsMario (peripheral: Peripheral) {
|
||||
return (
|
||||
peripheral.advertisement &&
|
||||
peripheral.advertisement.serviceUuids &&
|
||||
peripheral.advertisement.serviceUuids.indexOf(Consts.BLEService.LPF2_HUB.replace(/-/g, "")) >= 0 &&
|
||||
peripheral.advertisement.manufacturerData &&
|
||||
peripheral.advertisement.manufacturerData.length > 3 &&
|
||||
peripheral.advertisement.manufacturerData[3] === Consts.BLEManufacturerData.MARIO_ID
|
||||
);
|
||||
}
|
||||
|
||||
constructor (device: IBLEAbstraction) {
|
||||
super(device, PortMap, Consts.HubType.MOVE_HUB);
|
||||
debug("Discovered Mario");
|
||||
}
|
||||
|
||||
|
||||
public async connect () {
|
||||
debug("Connecting to Mario");
|
||||
await super.connect();
|
||||
debug("Connect completed");
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
export const PortMap: {[portName: string]: number} = {
|
||||
};
|
@ -5,6 +5,7 @@ import { PoweredUP } from "./poweredup-browser";
|
||||
import { BaseHub } from "./hubs/basehub";
|
||||
import { DuploTrainBase } from "./hubs/duplotrainbase";
|
||||
import { Hub } from "./hubs/hub";
|
||||
import { Mario } from "./hubs/mario";
|
||||
import { MoveHub } from "./hubs/movehub";
|
||||
import { RemoteControl } from "./hubs/remotecontrol";
|
||||
import { TechnicMediumHub } from "./hubs/technicmediumhub";
|
||||
@ -63,6 +64,7 @@ window.PoweredUP = {
|
||||
DuploTrainBaseSpeedometer,
|
||||
HubLED,
|
||||
Light,
|
||||
Mario,
|
||||
MediumLinearMotor,
|
||||
MotionSensor,
|
||||
MoveHub,
|
||||
|
@ -5,6 +5,7 @@ import { PoweredUP } from "./poweredup-node";
|
||||
import { BaseHub } from "./hubs/basehub";
|
||||
import { DuploTrainBase } from "./hubs/duplotrainbase";
|
||||
import { Hub } from "./hubs/hub";
|
||||
import { Mario } from "./hubs/mario";
|
||||
import { MoveHub } from "./hubs/movehub";
|
||||
import { RemoteControl } from "./hubs/remotecontrol";
|
||||
import { TechnicMediumHub } from "./hubs/technicmediumhub";
|
||||
@ -63,6 +64,7 @@ export {
|
||||
DuploTrainBaseSpeedometer,
|
||||
HubLED,
|
||||
Light,
|
||||
Mario,
|
||||
MediumLinearMotor,
|
||||
MotionSensor,
|
||||
MoveHub,
|
||||
|
@ -3,6 +3,7 @@ import { WebBLEDevice } from "./webbleabstraction";
|
||||
import { BaseHub } from "./hubs/basehub";
|
||||
import { DuploTrainBase } from "./hubs/duplotrainbase";
|
||||
import { Hub } from "./hubs/hub";
|
||||
import { Mario } from "./hubs/mario";
|
||||
import { MoveHub } from "./hubs/movehub";
|
||||
import { RemoteControl } from "./hubs/remotecontrol";
|
||||
import { TechnicMediumHub } from "./hubs/technicmediumhub";
|
||||
@ -210,6 +211,9 @@ export class PoweredUP extends EventEmitter {
|
||||
case Consts.HubType.TECHNIC_MEDIUM_HUB:
|
||||
hub = new TechnicMediumHub(device);
|
||||
break;
|
||||
case Consts.HubType.MARIO:
|
||||
hub = new Mario(device);
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import { NobleDevice } from "./nobleabstraction";
|
||||
import { BaseHub } from "./hubs/basehub";
|
||||
import { DuploTrainBase } from "./hubs/duplotrainbase";
|
||||
import { Hub } from "./hubs/hub";
|
||||
import { Mario } from "./hubs/mario";
|
||||
import { MoveHub } from "./hubs/movehub";
|
||||
import { RemoteControl } from "./hubs/remotecontrol";
|
||||
import { TechnicMediumHub } from "./hubs/technicmediumhub";
|
||||
@ -169,6 +170,8 @@ export class PoweredUP extends EventEmitter {
|
||||
hub = new DuploTrainBase(device);
|
||||
} else if (TechnicMediumHub.IsTechnicMediumHub(peripheral)) {
|
||||
hub = new TechnicMediumHub(device);
|
||||
} else if (Mario.IsMario(peripheral)) {
|
||||
hub = new Mario(device);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user