npm.io
0.1.24 • Published 1h ago

@bobfrankston/lxlan

Licence
MIT
Version
0.1.24
Deps
3
Size
73 kB
Vulns
0
Weekly
0

@bobfrankston/lxlan

Core LIFX LAN protocol library. Transport-agnostic implementation of the LIFX LAN protocol for controlling LIFX devices over local networks.

Purpose

This package provides the protocol-level implementation for LIFX device control. It knows:

  • LIFX protocol messages (SetPower, SetColor, GetState, etc.)
  • Message encoding/decoding (binary packet format)
  • Device state management (power, color, label, etc.)
  • Event emission patterns (device discovery, state updates)

It does NOT know:

  • How to send UDP packets (no Node.js dgram)
  • How to open WebSockets (no browser APIs)
  • Any specific transport implementation

Architecture Factoring

┌─────────────────────────────────────────────────┐
│  Application (your code)                        │
├─────────────────────────────────────────────────┤
│  @bobfrankston/lxlan (this package)             │
│  • LxClient - device discovery & management     │
│  • LxDevice - individual device control         │
│  • LxProtocol - message encode/decode           │
│  • LxTransport - alias for UdpTransport         │
├─────────────────────────────────────────────────┤
│  Shared Transport (pick one):                   │
│  • @bobfrankston/node-transport    → Node dgram │
│  • @bobfrankston/browser-transport → httpudp WS │
├─────────────────────────────────────────────────┤
│  @bobfrankston/udp-transport (interface only)   │
└─────────────────────────────────────────────────┘

Legacy wrappers (lxlan-node, lxlan-browser) pre-wire transport + event emitter and re-export everything. These are deprecated — use @bobfrankston/lxlan directly with a shared transport package instead (see Direct Usage below).

Transport Abstraction

LxTransport is an alias for UdpTransport from @bobfrankston/udp-transport:

export interface UdpTransport {
    bind(): Promise<void>;
    close(): void;
    send(ip: string, port: number, data: Uint8Array): void;
    broadcast(data: Uint8Array, port: number): void;
    onMessage(handler: (data: Uint8Array, rinfo: RemoteInfo) => void): void;
    onError(handler: (err: Error) => void): void;
    onClose(handler: () => void): void;
}

Shared transport implementations:

  • Node.js: NodeUdpTransport from @bobfrankston/node-transport (dgram)
  • Browser: BrowserUdpTransport from @bobfrankston/browser-transport (httpudp WebSocket)

See transport-architecture.md for the full transport stack reference.

Installation

npm install @bobfrankston/lxlan

Then pick a transport for your platform:

# Node.js
npm install @bobfrankston/node-transport

# Browser
npm install @bobfrankston/browser-transport

Note: The legacy convenience wrappers @bobfrankston/lxlan-node and @bobfrankston/lxlan-browser are deprecated. Use @bobfrankston/lxlan directly with a shared transport package instead.

Direct Usage (No Wrapper)

Pass a transport factory — LxClient creates the transport and emitter internally:

import { LxClient } from '@bobfrankston/lxlan';
import { NodeUdpTransport } from '@bobfrankston/node-transport';

const client = new LxClient({
    Transport: NodeUdpTransport,   // has static .create(port)
});

await client.start();

client.on('device', (device) => {
    console.log('Found:', device.label);
    device.setPower(true);
    device.setColor({ h: 120, s: 100, b: 50 });
});

For custom transport config (e.g., browser with specific httpudp URL):

import { LxClient } from '@bobfrankston/lxlan';
import { BrowserUdpTransport } from '@bobfrankston/browser-transport';

const client = new LxClient({
    Transport: { create: (port) => new BrowserUdpTransport({ httpudpUrl: 'ws://myserver:8080' }) },
});

Features

  • Full LIFX LAN protocol support
  • Automatic device discovery
  • Color control (HSB, RGB, Kelvin)
  • Power control
  • Device state caching
  • Event-driven architecture
  • Automatic retry with configurable timeouts
  • Comprehensive device info (firmware, WiFi, uptime)

LxDevice

Extends DeviceBase from @bobfrankston/devdefs — shared state (mac, ip, port, power, label, online, lastSeen, markSeen()) and transport plumbing. See devdefs README for base class details and MAC utilities (mac12, macmac).

Device Control

// Power control
device.setPower(true);
device.setPower(false);

// Color control
device.setColor({ h: 180, s: 100, b: 75 });      // HSB
device.setColor({ r: 255, g: 0, b: 0 });         // RGB
device.setColor({ kelvin: 3500 });               // White temperature

// Get comprehensive device info
device.getDeviceInfo();  // Triggers 'deviceInfo' event

// State queries
console.log(device.label, device.power, device.color);

Events

client.on('device', (device) => {
  // New device discovered
});

client.on('state', (device, info) => {
  // Device state updated
  // info.primary = true if direct response from device
  // info.primary = false if received via peer client broadcast
  if (info.primary) {
    console.log('Direct update from device');
  }
});

client.on('deviceInfo', (device) => {
  // Complete device info received (firmware, signal, uptime)
  console.log(device.firmwareVersion, device.signal, device.uptime);
});

Dependencies

  • @bobfrankston/devdefs - Shared device base class (DeviceBase, mac12, macmac)
  • @bobfrankston/colorlib - Color space conversions (HSB RGB Kelvin)

Legacy Wrappers (Deprecated)

lxlan-node and lxlan-browser are legacy convenience wrappers that pre-wire transport + event emitter. They still work but are deprecated — prefer direct usage with shared transport packages. No new features will be added to the wrappers.

Importing Types

Types should be imported from this package using import type:

import type { StateEventInfo, DeviceState } from '@bobfrankston/lxlan';

TypeScript Configuration

This package uses strictNullChecks: false - undefined is treated as a first-class value throughout the codebase.

License

MIT

Keywords