@bobfrankston/lxlan
v0.1.23
Published
LIFX LAN protocol library for device control via UDP
Maintainers
Readme
@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:
NodeUdpTransportfrom@bobfrankston/node-transport(dgram) - Browser:
BrowserUdpTransportfrom@bobfrankston/browser-transport(httpudp WebSocket)
See transport-architecture.md for the full transport stack reference.
Installation
npm install @bobfrankston/lxlanThen pick a transport for your platform:
# Node.js
npm install @bobfrankston/node-transport
# Browser
npm install @bobfrankston/browser-transportNote: The legacy convenience wrappers
@bobfrankston/lxlan-nodeand@bobfrankston/lxlan-browserare deprecated. Use@bobfrankston/lxlandirectly 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';Related Packages
- @bobfrankston/devdefs - Shared device base class and MAC utilities
- @bobfrankston/lxlan-node - Node.js convenience wrapper (deprecated)
- @bobfrankston/lxlan-browser - Browser convenience wrapper (deprecated)
- @bobfrankston/udp-transport - UdpTransport interface definition
- @bobfrankston/node-transport - Shared Node.js UDP transport (NodeUdpTransport, NodeEventEmitter)
- @bobfrankston/browser-transport - Shared browser UDP transport (BrowserUdpTransport, BrowserEventEmitter)
- @bobfrankston/httpudp - WebSocket-to-UDP proxy server
- @bobfrankston/httpudp-client - Browser WebSocket UDP client (used by browser-transport)
- @bobfrankston/colorlib - Color utilities
- Transport Architecture - Full transport stack reference
TypeScript Configuration
This package uses strictNullChecks: false - undefined is treated as a first-class value throughout the codebase.
License
MIT
