0.2.0 • Published 4 years ago

lego-wireless-protocol v0.2.0

Weekly downloads
5
License
MIT
Repository
github
Last release
4 years ago

lego-wireless-protocol

A partial implementation of the LEGO wireless protocol using JavaScript.

The documentation of the LEGO wireless protocol can be found here.

Installation

Using yarn:

yarn add lego-wireless-protocol

Using npm:

npm install lego-wireless-protocol --save

Usage Example

Parsing An Incoming Message

import {parseIncomingMessage} from 'lego-wireless-protocol';

const incomingMessage = parseIncomingMessage(
  Uint8Array.from([9, 0, 4, 16, 2, 39, 0, 0, 1]).buffer
);

assert.deepEqual(incomingMessage, {
  messageType: 'HubAttachedIo',
  port: {portType: 'External', portId: 16},
  eventType: 'HubAttachedVirtualIo',
  ioType: 'InternalMotorWithTacho',
  portA: {portType: 'External', portId: 0},
  portB: {portType: 'External', portId: 1}
});

Serializing An Outgoing Message

import {serializeOutgoingMessage} from 'lego-wireless-protocol';

const data = serializeOutgoingMessage({
  messageType: 'PortInformationRequest',
  portId: 0,
  portInformationRequestType: 'ModeInfo'
});

assert.deepEqual([...new Uint8Array(data)], [5, 0, 33, 0, 1]);

API Reference

function parseIncomingMessage(data: ArrayBuffer): IncomingMessage;
function serializeOutgoingMessage(
  outgoingMessage: OutgoingMessage
): ArrayBuffer;

IncomingMessage

type IncomingMessage =
  | HubAttachedIoIncomingMessage
  | ErrorIncomingMessage
  | PortInformationIncomingMessage
  | PortModeInformationIncomingMessage
  | PortValueIncomingMessage
  | PortInputFormatIncomingMessage
  | UnknownIncomingMessage;

HubAttachedIoIncomingMessage

type HubAttachedIoIncomingMessage = {
  readonly messageType: 'HubAttachedIo';
} & (
  | {
      readonly port: Port;
      readonly eventType: 'HubAttachedIo';
      readonly ioType: IoType;
    }
  | {
      readonly port: Port;
      readonly eventType: 'HubAttachedVirtualIo';
      readonly ioType: IoType;
      readonly portA: Port;
      readonly portB: Port;
    }
  | {
      readonly port: Port;
      readonly eventType: 'HubDetachedIo';
    }
);

interface Port {
  readonly portType: 'External' | 'Internal' | 'Reserved';
  readonly portId: number;
}

type IoType =
  | 'Motor'
  | 'SystemTrainMotor'
  | 'Button'
  | 'LedLight'
  | 'Voltage'
  | 'Current'
  | 'PiezoTone'
  | 'RgbLight'
  | 'ExternalTiltSensor'
  | 'MotionSensor'
  | 'VisionSensor'
  | 'ExternalMotorWithTacho'
  | 'InternalMotorWithTacho'
  | 'InternalTilt'
  | 'Unknown';

ErrorIncomingMessage

interface ErrorIncomingMessage {
  readonly messageType: 'Error';
  readonly commandTypeId: number;
  readonly errorCode: ErrorCode;
}

type ErrorCode =
  | 'Ack'
  | 'Mack'
  | 'BufferOverflow'
  | 'Timeout'
  | 'CommandNotRecognized'
  | 'InvalidUse'
  | 'Overcurrent'
  | 'InternalError'
  | 'Unknown';

PortInformationIncomingMessage

type PortInformationIncomingMessage = {
  readonly messageType: 'PortInformation';
} & (
  | {
      readonly portId: number;
      readonly portInformationType: 'ModeInfo';
      readonly inputModeIds: number[];
      readonly outputModeIds: number[];
    }
  | {
      readonly portId: number;
      readonly portInformationType: 'PossibleModeCombinations';
    }
);

PortModeInformationIncomingMessage

type PortModeInformationIncomingMessage = {
  readonly messageType: 'PortModeInformation';
  readonly portId: number;
  readonly modeId: number;
} & (
  | {
      readonly portModeInformationType: 'Name';
      readonly name: string;
    }
  | {
      readonly portModeInformationType: 'Raw';
      readonly rawRange: [number, number];
    }
  | {
      readonly portModeInformationType: 'Pct';
      readonly pctRange: [number, number];
    }
  | {
      readonly portModeInformationType: 'Si';
      readonly siRange: [number, number];
    }
  | {
      readonly portModeInformationType: 'Symbol';
      readonly symbol: string;
    }
  | {
      readonly portModeInformationType: 'ValueFormat';
      readonly valueFormat: ValueFormat;
    }
  | {
      readonly portModeInformationType: 'Unknown';
    }
);

interface ValueFormat {
  readonly datasetType: DatasetType;
  readonly numberOfDatasets: number;
}

type DatasetType = 'Int8' | 'Int16' | 'Int32' | 'Float' | 'Unknown';

PortValueIncomingMessage

interface PortValueIncomingMessage {
  readonly messageType: 'PortValue';
  readonly portId: number;
  readonly valueData: ArrayBuffer;
}

PortInputFormatIncomingMessage

interface PortInputFormatIncomingMessage {
  readonly messageType: 'PortInputFormat';
  readonly portId: number;
  readonly modeId: number;
  readonly deltaInterval: number;
  readonly notificationsEnabled: boolean;
}

UnknownIncomingMessage

interface UnknownIncomingMessage {
  readonly messageType: 'Unknown';
}

OutgoingMessage

type OutgoingMessage =
  | PortInformationRequestOutgoingMessage
  | PortModeInformationRequestOutgoingMessage
  | PortInputFormatSetupOutgoingMessage
  | PortOutputCommandOutgoingMessage;

PortInformationRequestOutgoingMessage

interface PortInformationRequestOutgoingMessage {
  readonly messageType: 'PortInformationRequest';
  readonly portId: number;
  readonly portInformationRequestType: 'PortValue' | 'ModeInfo';
}

PortModeInformationRequestOutgoingMessage

interface PortModeInformationRequestOutgoingMessage {
  readonly messageType: 'PortModeInformationRequest';
  readonly portId: number;
  readonly modeId: number;
  readonly portModeInformationRequestType: PortModeInformationRequestType;
}

type PortModeInformationRequestType =
  | 'Name'
  | 'Raw'
  | 'Pct'
  | 'Si'
  | 'Symbol'
  | 'ValueFormat';

PortInputFormatSetupOutgoingMessage

interface PortInputFormatSetupOutgoingMessage {
  readonly messageType: 'PortInputFormatSetup';
  readonly portId: number;
  readonly modeId: number;
  readonly deltaInterval: number;
  readonly notificationsEnabled: boolean;
}

PortOutputCommandOutgoingMessage

interface PortOutputCommandOutgoingMessage {
  readonly messageType: 'PortOutputCommand';
  readonly portId: number;
  readonly portOutputSubCommandData: ArrayBuffer;
}

Development

Publish A New Release

yarn release patch
yarn release minor
yarn release major

After a new release has been created by pushing the tag, it must be published via the GitHub UI. This triggers the final publication to npm.


Copyright (c) 2020, Clemens Akens. Released under the terms of the MIT License.