@bobfrankston/lxlan 0.1.18 → 0.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -25,68 +25,87 @@ It does **NOT** know:
25
25
  │ • LxClient - device discovery & management │
26
26
  │ • LxDevice - individual device control │
27
27
  │ • LxProtocol - message encode/decode │
28
- │ • LxTransport - INTERFACE ONLY
28
+ │ • LxTransport - alias for UdpTransport
29
29
  ├─────────────────────────────────────────────────┤
30
- │ Transport Implementation (pick one):
31
- │ • @bobfrankston/lxlan-node rmfudp
32
- │ • @bobfrankston/lxlan-browser → httpudp-client
30
+ Shared Transport (pick one):
31
+ │ • @bobfrankston/node-transport Node dgram
32
+ │ • @bobfrankston/browser-transport → httpudp WS
33
+ ├─────────────────────────────────────────────────┤
34
+ │ @bobfrankston/udp-transport (interface only) │
33
35
  └─────────────────────────────────────────────────┘
34
36
  ```
35
37
 
38
+ **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).
39
+
36
40
  ## Transport Abstraction
37
41
 
38
- The package exports `LxTransport` interface that must be implemented by transport layers:
42
+ `LxTransport` is an alias for `UdpTransport` from `@bobfrankston/udp-transport`:
39
43
 
40
44
  ```typescript
41
- export interface LxTransport {
42
- bind(): Promise<void>;
43
- close(): void;
44
- send(ip: string, port: number, data: Buffer): void;
45
- broadcast(data: Buffer, port: number, addresses: string[]): void;
46
- onMessage(handler: (data: Buffer, rinfo: RemoteInfo) => void): void;
47
- onError(handler: (err: Error) => void): void;
45
+ export interface UdpTransport {
46
+ bind(): Promise<void>;
47
+ close(): void;
48
+ send(ip: string, port: number, data: Uint8Array): void;
49
+ broadcast(data: Uint8Array, port: number): void;
50
+ onMessage(handler: (data: Uint8Array, rinfo: RemoteInfo) => void): void;
51
+ onError(handler: (err: Error) => void): void;
52
+ onClose(handler: () => void): void;
48
53
  }
49
54
  ```
50
55
 
51
- **Implementations:**
52
- - **Node.js**: `@bobfrankston/lxlan-node` provides `rmfudp`-based transport
53
- - **Browser**: `@bobfrankston/lxlan-browser` provides `httpudp-client`-based transport
56
+ **Shared transport implementations:**
57
+ - **Node.js**: `NodeUdpTransport` from `@bobfrankston/node-transport` (dgram)
58
+ - **Browser**: `BrowserUdpTransport` from `@bobfrankston/browser-transport` (httpudp WebSocket)
54
59
 
55
- ## Installation
60
+ See [transport-architecture.md](../../../../doc/transport-architecture.md) for the full transport stack reference.
56
61
 
57
- This package is typically installed as a dependency of the platform-specific wrappers:
62
+ ## Installation
58
63
 
59
64
  ```bash
60
- # For Node.js projects
61
- npm install @bobfrankston/lxlan-node
62
-
63
- # For browser projects
64
- npm install @bobfrankston/lxlan-browser
65
+ npm install @bobfrankston/lxlan
65
66
  ```
66
67
 
67
- Direct usage (if providing your own transport):
68
+ Then pick a transport for your platform:
68
69
 
69
70
  ```bash
70
- npm install @bobfrankston/lxlan
71
+ # Node.js
72
+ npm install @bobfrankston/node-transport
73
+
74
+ # Browser
75
+ npm install @bobfrankston/browser-transport
71
76
  ```
72
77
 
73
- ## Direct Usage (Advanced)
78
+ > **Note:** The legacy convenience wrappers `@bobfrankston/lxlan-node` and `@bobfrankston/lxlan-browser` are **deprecated**. Use `@bobfrankston/lxlan` directly with a shared transport package instead.
74
79
 
75
- If you're implementing your own transport:
80
+ ## Direct Usage (No Wrapper)
81
+
82
+ Pass a transport factory — LxClient creates the transport and emitter internally:
76
83
 
77
84
  ```typescript
78
85
  import { LxClient } from '@bobfrankston/lxlan';
79
- import { MyCustomTransport } from './my-transport';
86
+ import { NodeUdpTransport } from '@bobfrankston/node-transport';
80
87
 
81
- const transport = new MyCustomTransport();
82
- const client = new LxClient({ transport });
88
+ const client = new LxClient({
89
+ Transport: NodeUdpTransport, // has static .create(port)
90
+ });
83
91
 
84
92
  await client.start();
85
93
 
86
94
  client.on('device', (device) => {
87
- console.log('Found:', device.label);
88
- device.setPower(true);
89
- device.setColor({ h: 120, s: 100, b: 50 });
95
+ console.log('Found:', device.label);
96
+ device.setPower(true);
97
+ device.setColor({ h: 120, s: 100, b: 50 });
98
+ });
99
+ ```
100
+
101
+ For custom transport config (e.g., browser with specific httpudp URL):
102
+
103
+ ```typescript
104
+ import { LxClient } from '@bobfrankston/lxlan';
105
+ import { BrowserUdpTransport } from '@bobfrankston/browser-transport';
106
+
107
+ const client = new LxClient({
108
+ Transport: { create: (port) => new BrowserUdpTransport({ httpudpUrl: 'ws://myserver:8080' }) },
90
109
  });
91
110
  ```
92
111
 
@@ -101,6 +120,10 @@ client.on('device', (device) => {
101
120
  - 🔄 Automatic retry with configurable timeouts
102
121
  - 📝 Comprehensive device info (firmware, WiFi, uptime)
103
122
 
123
+ ## LxDevice
124
+
125
+ Extends [`DeviceBase`](../../../../Others/deviceapi/devdefs) from `@bobfrankston/devdefs` — shared state (`mac`, `ip`, `port`, `power`, `label`, `online`, `lastSeen`, `markSeen()`) and transport plumbing. See [devdefs README](../../../../Others/deviceapi/devdefs/README.md) for base class details and MAC utilities (`mac12`, `macmac`).
126
+
104
127
  ## Device Control
105
128
 
106
129
  ```typescript
@@ -144,11 +167,12 @@ client.on('deviceInfo', (device) => {
144
167
 
145
168
  ## Dependencies
146
169
 
170
+ - `@bobfrankston/devdefs` - Shared device base class (`DeviceBase`, `mac12`, `macmac`)
147
171
  - `@bobfrankston/colorlib` - Color space conversions (HSB ↔ RGB ↔ Kelvin)
148
172
 
149
- ## Keeping Transport Packages in Sync
173
+ ## Legacy Wrappers (Deprecated)
150
174
 
151
- **IMPORTANT:** `lxlan-browser` and `lxlan-node` are parallel transport adapters. When modifying types or exports in this core package, ensure both adapters are updated if needed. They should expose equivalent functionality for their respective platforms.
175
+ `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.
152
176
 
153
177
  ## Importing Types
154
178
 
@@ -160,12 +184,16 @@ import type { StateEventInfo, DeviceState } from '@bobfrankston/lxlan';
160
184
 
161
185
  ## Related Packages
162
186
 
163
- - **[@bobfrankston/lxlan-node](../lxlan-node)** - Node.js transport wrapper (keep in sync!)
164
- - **[@bobfrankston/lxlan-browser](../lxlan-browser)** - Browser transport wrapper (keep in sync!)
165
- - **[@bobfrankston/rmfudp](../../../../utils/udp/rmfudp)** - Node.js UDP transport
166
- - **[@bobfrankston/httpudp-client](../../../../utils/udp/httpudp-client)** - Browser WebSocket UDP client
187
+ - **[@bobfrankston/devdefs](../../../../Others/deviceapi/devdefs)** - Shared device base class and MAC utilities
188
+ - **[@bobfrankston/lxlan-node](../lxlan-node)** - Node.js convenience wrapper (deprecated)
189
+ - **[@bobfrankston/lxlan-browser](../lxlan-browser)** - Browser convenience wrapper (deprecated)
190
+ - **[@bobfrankston/udp-transport](../../../../utils/udp/udp-transport)** - UdpTransport interface definition
191
+ - **[@bobfrankston/node-transport](../../../../utils/udp/node-transport)** - Shared Node.js UDP transport (NodeUdpTransport, NodeEventEmitter)
192
+ - **[@bobfrankston/browser-transport](../../../../utils/udp/browser-transport)** - Shared browser UDP transport (BrowserUdpTransport, BrowserEventEmitter)
167
193
  - **[@bobfrankston/httpudp](../../../../utils/udp/httpudp)** - WebSocket-to-UDP proxy server
194
+ - **[@bobfrankston/httpudp-client](../../../../utils/udp/httpudp-client)** - Browser WebSocket UDP client (used by browser-transport)
168
195
  - **[@bobfrankston/colorlib](../../../../utils/colorlib)** - Color utilities
196
+ - **[Transport Architecture](../../../../doc/transport-architecture.md)** - Full transport stack reference
169
197
 
170
198
  ## TypeScript Configuration
171
199
 
package/client.d.ts CHANGED
@@ -1,21 +1,18 @@
1
- import { LxTransport } from './transport.js';
2
- import { LxEventEmitter } from './events.js';
1
+ import type { UdpTransportFactory } from '@bobfrankston/udp-transport';
3
2
  import { LxDevice } from './device.js';
4
3
  /**
5
4
  * Options for LxClient constructor
6
5
  */
7
6
  export interface LxClientOptions {
8
- /** Transport layer implementation (required) */
9
- transport: LxTransport;
10
- /** Event emitter implementation (required - use Node EventEmitter or browser equivalent) */
11
- eventEmitter: LxEventEmitter;
12
- /** LIFX port (default 56700) */
7
+ /** Transport factory must have .create(port) (e.g. NodeUdpTransport, BrowserUdpTransport) */
8
+ Transport: UdpTransportFactory;
9
+ /** LIFX port override (default 56700) */
13
10
  port?: number;
14
11
  /** Auto-discovery interval in ms (0 = manual only, default 0) */
15
12
  discoveryInterval?: number;
16
13
  /** Enable client-to-client state broadcast for multi-client sync (default false) */
17
14
  clientBroadcastEnabled?: boolean;
18
- /** Custom logger function (default: console.log) */
15
+ /** Custom logger function (default: no-op) */
19
16
  logger?: (msg: string, colors?: string) => void;
20
17
  }
21
18
  /**
package/client.js CHANGED
@@ -1,4 +1,6 @@
1
1
  import { hsbk16ToHsbk } from '@bobfrankston/colorlib';
2
+ import { SimpleEventEmitter } from '@bobfrankston/udp-transport';
3
+ import { mac12 } from '@bobfrankston/devdefs';
2
4
  import { LxDevice } from './device.js';
3
5
  import { MessageType, LIFX_PORT, MessageTypeName } from './types.js';
4
6
  import { encodeMessage, decodeMessage, decodeState, decodeStatePower, decodeStateLabel, decodeStateVersion, decodeStateGroup, decodeStateService, decodeStateHostInfo, decodeStateHostFirmware, decodeStateWifiInfo, decodeStateInfo } from './protocol.js';
@@ -33,11 +35,11 @@ export class LxClient {
33
35
  /** Cached devices by MAC address (lowercase) */
34
36
  devices = new Map();
35
37
  constructor(options) {
36
- this.emitter = options.eventEmitter;
37
- this.transport = options.transport;
38
+ this.emitter = new SimpleEventEmitter();
38
39
  this.port = options.port ?? LIFX_PORT;
40
+ this.transport = options.Transport.create(this.port);
39
41
  this.clientBroadcastEnabled = options.clientBroadcastEnabled ?? false;
40
- this.log = options.logger ?? ((msg, colors) => console.log(msg));
42
+ this.log = options.logger ?? (() => { });
41
43
  this.transport.onMessage((data, rinfo) => {
42
44
  // Ensure data is Uint8Array for protocol decoder
43
45
  const buf = data instanceof Uint8Array ? data : new Uint8Array(data);
@@ -109,7 +111,7 @@ export class LxClient {
109
111
  * @returns LxDevice or undefined if not found
110
112
  */
111
113
  getDevice(mac) {
112
- return this.devices.get(mac.toLowerCase());
114
+ return this.devices.get(mac12(mac));
113
115
  }
114
116
  /**
115
117
  * Add device manually (bypassing discovery).
@@ -121,7 +123,7 @@ export class LxClient {
121
123
  * @returns LxDevice instance (new or existing)
122
124
  */
123
125
  addDevice(mac, ip, port = LIFX_PORT) {
124
- const normalizedMac = mac.toLowerCase();
126
+ const normalizedMac = mac12(mac);
125
127
  let device = this.devices.get(normalizedMac);
126
128
  if (!device) {
127
129
  device = new LxDevice(normalizedMac, ip);
package/device.d.ts CHANGED
@@ -1,5 +1,5 @@
1
+ import { DeviceBase } from '@bobfrankston/devdefs';
1
2
  import { HSBK, ColorInput } from '@bobfrankston/colorlib';
2
- import { LxTransport } from './transport.js';
3
3
  import { GroupInfo } from './types.js';
4
4
  /**
5
5
  * Represents a LIFX device on the LAN.
@@ -9,23 +9,9 @@ import { GroupInfo } from './types.js';
9
9
  * Always use `client.addDevice(mac, ip)` or obtain devices from `client.devices`.
10
10
  * Directly instantiated devices will not have a transport and will fail at runtime.
11
11
  */
12
- export declare class LxDevice {
13
- /** MAC address (lowercase, colon-separated) */
14
- readonly mac: string;
15
- /** Current IP address */
16
- ip: string;
17
- /** UDP port (default LIFX_PORT = 56700) */
18
- port: number;
19
- /** Power state (true = on) */
20
- power: boolean;
12
+ export declare class LxDevice extends DeviceBase {
21
13
  /** Current color in HSBK format */
22
14
  color: HSBK;
23
- /** Device label (user-assigned name) */
24
- label: string;
25
- /** Whether device is responding */
26
- online: boolean;
27
- /** Last message timestamp (Date.now()) */
28
- lastSeen: number;
29
15
  /** Vendor ID (1 = LIFX) */
30
16
  vendor: number;
31
17
  /** Product ID (see Products table) */
@@ -46,7 +32,6 @@ export declare class LxDevice {
46
32
  location: GroupInfo;
47
33
  /** Recent messages for deduplication (sequence:type -> timestamp) */
48
34
  private recentMessages;
49
- private transport?;
50
35
  /** Pending requests awaiting responses (message type -> timeout) */
51
36
  private pendingRequests;
52
37
  /** Default timeout for requests in milliseconds */
@@ -58,19 +43,13 @@ export declare class LxDevice {
58
43
  * Do not call directly - use `client.addDevice(mac, ip)` instead.
59
44
  * Devices created directly will not have a transport and will throw errors when used.
60
45
  *
61
- * @param mac - MAC address (will be normalized to lowercase)
46
+ * @param mac - MAC address (will be normalized to lowercase, no separators)
62
47
  * @param ip - IP address (optional, can be discovered)
63
48
  * @internal
64
49
  */
65
50
  constructor(mac: string, ip?: string);
66
- /** Throw error if transport is not set */
67
- private requireTransport;
68
- /** Throw error if IP address is not set */
69
- private requireIP;
70
51
  /** Get product name from product ID */
71
52
  get productName(): string;
72
- /** Set the transport (used by LxClient when managing devices) */
73
- setTransport(transport: LxTransport): void;
74
53
  /** Send raw message to device */
75
54
  send(type: number, payload?: Buffer): void;
76
55
  /** Start tracking a request with timeout */
@@ -143,8 +122,6 @@ export declare class LxDevice {
143
122
  * Listen for 'deviceInfo' event on client to get results.
144
123
  */
145
124
  getDeviceInfo(): void;
146
- /** Update last seen timestamp and online status */
147
- markSeen(): void;
148
125
  /** Notify that a response was received for a message type */
149
126
  markResponseReceived(messageType: number): void;
150
127
  /**
package/device.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { DeviceBase } from '@bobfrankston/devdefs';
1
2
  import { parseColor, hsbkTo16 } from '@bobfrankston/colorlib';
2
3
  import { MessageType, Products, LIFX_PORT } from './types.js';
3
4
  import { encodeMessage, encodeSetPower, encodeSetColor, encodeSetWaveformOptional, encodeSetLabel, encodeSetGroup, encodeSetLocation } from './protocol.js';
@@ -9,23 +10,9 @@ import { encodeMessage, encodeSetPower, encodeSetColor, encodeSetWaveformOptiona
9
10
  * Always use `client.addDevice(mac, ip)` or obtain devices from `client.devices`.
10
11
  * Directly instantiated devices will not have a transport and will fail at runtime.
11
12
  */
12
- export class LxDevice {
13
- /** MAC address (lowercase, colon-separated) */
14
- mac;
15
- /** Current IP address */
16
- ip;
17
- /** UDP port (default LIFX_PORT = 56700) */
18
- port = LIFX_PORT;
19
- /** Power state (true = on) */
20
- power = false;
13
+ export class LxDevice extends DeviceBase {
21
14
  /** Current color in HSBK format */
22
15
  color = { h: 0, s: 0, b: 0, k: 3500 };
23
- /** Device label (user-assigned name) */
24
- label = '';
25
- /** Whether device is responding */
26
- online = false;
27
- /** Last message timestamp (Date.now()) */
28
- lastSeen = 0;
29
16
  /** Vendor ID (1 = LIFX) */
30
17
  vendor = 0;
31
18
  /** Product ID (see Products table) */
@@ -46,7 +33,6 @@ export class LxDevice {
46
33
  location = { id: '', label: '', updatedAt: 0 };
47
34
  /** Recent messages for deduplication (sequence:type -> timestamp) */
48
35
  recentMessages = new Map();
49
- transport;
50
36
  /** Pending requests awaiting responses (message type -> timeout) */
51
37
  pendingRequests = new Map();
52
38
  /** Default timeout for requests in milliseconds */
@@ -58,32 +44,17 @@ export class LxDevice {
58
44
  * Do not call directly - use `client.addDevice(mac, ip)` instead.
59
45
  * Devices created directly will not have a transport and will throw errors when used.
60
46
  *
61
- * @param mac - MAC address (will be normalized to lowercase)
47
+ * @param mac - MAC address (will be normalized to lowercase, no separators)
62
48
  * @param ip - IP address (optional, can be discovered)
63
49
  * @internal
64
50
  */
65
51
  constructor(mac, ip) {
66
- this.mac = mac.toLowerCase();
67
- this.ip = ip || '';
68
- }
69
- /** Throw error if transport is not set */
70
- requireTransport() {
71
- if (!this.transport)
72
- throw new Error(`Device ${this.mac} has no UDP transport - cannot send. Use lxlan-node or lxlan-http.`);
73
- }
74
- /** Throw error if IP address is not set */
75
- requireIP() {
76
- if (!this.ip)
77
- throw new Error(`Device ${this.mac} has no IP address - cannot send. Perform discovery or add device with IP using client.addDevice(mac, ip).`);
52
+ super(mac, ip, LIFX_PORT);
78
53
  }
79
54
  /** Get product name from product ID */
80
55
  get productName() {
81
56
  return Products[this.product] ?? `Unknown (${this.product})`;
82
57
  }
83
- /** Set the transport (used by LxClient when managing devices) */
84
- setTransport(transport) {
85
- this.transport = transport;
86
- }
87
58
  /** Send raw message to device */
88
59
  send(type, payload) {
89
60
  this.requireTransport();
@@ -197,7 +168,7 @@ export class LxDevice {
197
168
  * @param brightness - Brightness 0-100 (default 100)
198
169
  * @param duration - Transition time in milliseconds (default 0)
199
170
  */
200
- setWhite(kelvin, brightness = 100, duration = 0) {
171
+ setWhite(kelvin, brightness = LxDevice.MaxBrightness, duration = 0) {
201
172
  this.setColor({ h: 0, s: 0, b: brightness, k: kelvin }, duration);
202
173
  }
203
174
  /** Query full state */
@@ -285,11 +256,6 @@ export class LxDevice {
285
256
  this.getInfo();
286
257
  this.getState();
287
258
  }
288
- /** Update last seen timestamp and online status */
289
- markSeen() {
290
- this.lastSeen = Date.now();
291
- this.online = true;
292
- }
293
259
  /** Notify that a response was received for a message type */
294
260
  markResponseReceived(messageType) {
295
261
  this.clearRequestTimeout(messageType);
package/events.d.ts CHANGED
@@ -1,24 +1,7 @@
1
1
  /**
2
- * Minimal EventEmitter interface for browser compatibility
3
- * Node.js implementations can use node:events directly
4
- * Browser implementations can provide their own or use a library
2
+ * Re-export shared event emitter types from @bobfrankston/udp-transport.
3
+ * LxEventEmitter is kept as an alias for backwards compatibility.
5
4
  */
6
- export interface LxEventEmitter {
7
- on(event: string, listener: (...args: any[]) => void): this;
8
- once(event: string, listener: (...args: any[]) => void): this;
9
- off(event: string, listener: (...args: any[]) => void): this;
10
- emit(event: string, ...args: any[]): boolean;
11
- removeAllListeners(event?: string): this;
12
- }
13
- /**
14
- * Base class for objects that emit events
15
- * This is platform-agnostic and can be implemented for Node.js or browser
16
- */
17
- export declare abstract class LxEventEmitterBase implements LxEventEmitter {
18
- abstract on(event: string, listener: (...args: any[]) => void): this;
19
- abstract once(event: string, listener: (...args: any[]) => void): this;
20
- abstract off(event: string, listener: (...args: any[]) => void): this;
21
- abstract emit(event: string, ...args: any[]): boolean;
22
- abstract removeAllListeners(event?: string): this;
23
- }
5
+ export { LanEventEmitter, SimpleEventEmitter } from '@bobfrankston/udp-transport';
6
+ export { LanEventEmitter as LxEventEmitter } from '@bobfrankston/udp-transport';
24
7
  //# sourceMappingURL=events.d.ts.map
package/events.js CHANGED
@@ -1,7 +1,6 @@
1
1
  /**
2
- * Base class for objects that emit events
3
- * This is platform-agnostic and can be implemented for Node.js or browser
2
+ * Re-export shared event emitter types from @bobfrankston/udp-transport.
3
+ * LxEventEmitter is kept as an alias for backwards compatibility.
4
4
  */
5
- export class LxEventEmitterBase {
6
- }
5
+ export { SimpleEventEmitter } from '@bobfrankston/udp-transport';
7
6
  //# sourceMappingURL=events.js.map
package/index.d.ts CHANGED
@@ -1,15 +1,13 @@
1
1
  /**
2
2
  * @bobfrankston/lxlan — Platform-agnostic LIFX LAN protocol core.
3
3
  *
4
- * DO NOT import this package directly in application code.
5
- * Use the platform-specific wrapper instead:
6
- * - Node.js: @bobfrankston/lxlan-node
7
- * - Browser: @bobfrankston/lxlan-browser
4
+ * Usage: pass a UdpTransportFactory (e.g. NodeUdpTransport, BrowserUdpTransport).
5
+ * The client creates transport and event emitter internally.
8
6
  */
9
7
  export * from './types.js';
10
8
  export { LxDevice } from './device.js';
11
9
  export { LxClient, LxClientOptions } from './client.js';
12
- export { UdpTransport, LxTransport, RemoteInfo } from './transport.js';
13
- export { LxEventEmitter, LxEventEmitterBase } from './events.js';
10
+ export { UdpTransport, UdpTransportFactory, LxTransport, RemoteInfo, StateEventInfo } from './transport.js';
11
+ export { LxEventEmitter, LanEventEmitter, SimpleEventEmitter } from './events.js';
14
12
  export { encodeMessage, decodeMessage, encodeSetWifiConfiguration, encodeGetWifiConfiguration, decodeStateWifiConfiguration, encodeSetLabel, encodeSetColor, encodeSetPower, encodeSetGroup, encodeSetLocation, encodeSetWaveformOptional, encodeGetService, decodeState, decodeStatePower, decodeStateLabel, decodeStateVersion, decodeStateGroup, decodeStateService, decodeStateHostInfo, decodeStateHostFirmware, decodeStateWifiInfo, decodeStateInfo, FrameFlags, ProtocolBits, nextSequence, getSource, } from './protocol.js';
15
13
  //# sourceMappingURL=index.d.ts.map
package/index.js CHANGED
@@ -1,14 +1,12 @@
1
1
  /**
2
2
  * @bobfrankston/lxlan — Platform-agnostic LIFX LAN protocol core.
3
3
  *
4
- * DO NOT import this package directly in application code.
5
- * Use the platform-specific wrapper instead:
6
- * - Node.js: @bobfrankston/lxlan-node
7
- * - Browser: @bobfrankston/lxlan-browser
4
+ * Usage: pass a UdpTransportFactory (e.g. NodeUdpTransport, BrowserUdpTransport).
5
+ * The client creates transport and event emitter internally.
8
6
  */
9
7
  export * from './types.js';
10
8
  export { LxDevice } from './device.js';
11
9
  export { LxClient } from './client.js';
12
- export { LxEventEmitterBase } from './events.js';
10
+ export { SimpleEventEmitter } from './events.js';
13
11
  export { encodeMessage, decodeMessage, encodeSetWifiConfiguration, encodeGetWifiConfiguration, decodeStateWifiConfiguration, encodeSetLabel, encodeSetColor, encodeSetPower, encodeSetGroup, encodeSetLocation, encodeSetWaveformOptional, encodeGetService, decodeState, decodeStatePower, decodeStateLabel, decodeStateVersion, decodeStateGroup, decodeStateService, decodeStateHostInfo, decodeStateHostFirmware, decodeStateWifiInfo, decodeStateInfo, FrameFlags, ProtocolBits, nextSequence, getSource, } from './protocol.js';
14
12
  //# sourceMappingURL=index.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bobfrankston/lxlan",
3
- "version": "0.1.18",
3
+ "version": "0.1.19",
4
4
  "description": "LIFX LAN protocol library for device control via UDP",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -32,16 +32,18 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "@bobfrankston/colorlib": "^0.1.8",
35
+ "@bobfrankston/devdefs": "^0.1.0",
35
36
  "@bobfrankston/udp-transport": "^1.0.2"
36
37
  },
37
38
  "devDependencies": {
38
- "@types/node": "^25.2.1"
39
+ "@types/node": "^25.3.0"
39
40
  },
40
41
  "publishConfig": {
41
42
  "access": "public"
42
43
  },
43
44
  ".dependencies": {
44
45
  "@bobfrankston/colorlib": "file:../../../../utils/colorlib",
46
+ "@bobfrankston/devdefs": "file:../../../../Others/deviceapi/devdefs",
45
47
  "@bobfrankston/udp-transport": "file:../../../../utils/udp/udp-transport"
46
48
  }
47
49
  }
package/protocol.js CHANGED
@@ -21,17 +21,17 @@ export function nextSequence() {
21
21
  export function getSource() {
22
22
  return globalSource;
23
23
  }
24
- /** MAC string to 8-byte Uint8Array (6 bytes MAC + 2 padding) */
24
+ /** MAC string to 8-byte Uint8Array (6 bytes MAC + 2 padding). Accepts bare or colon-separated. */
25
25
  function macToBuffer(mac) {
26
26
  const buf = new Uint8Array(8);
27
- if (mac && mac !== '00:00:00:00:00:00') {
28
- const bytes = mac.split(':').map(b => parseInt(b, 16));
27
+ const clean = mac.replace(/[:\-]/g, '');
28
+ if (clean && clean !== '000000000000') {
29
29
  for (let i = 0; i < 6; i++)
30
- buf[i] = bytes[i] || 0;
30
+ buf[i] = parseInt(clean.substring(i * 2, i * 2 + 2), 16) || 0;
31
31
  }
32
32
  return buf;
33
33
  }
34
- /** Uint8Array to MAC string */
34
+ /** Uint8Array to colon-separated lowercase MAC string */
35
35
  function bufferToMac(buf, offset = 0) {
36
36
  const parts = [];
37
37
  for (let i = 0; i < 6; i++) {
package/transport.d.ts CHANGED
@@ -2,6 +2,6 @@
2
2
  * Re-export UDP transport interfaces from @bobfrankston/udp-transport
3
3
  * LxTransport is kept as an alias for backwards compatibility
4
4
  */
5
- export { UdpTransport, RemoteInfo } from '@bobfrankston/udp-transport';
5
+ export { UdpTransport, UdpTransportFactory, RemoteInfo, StateEventInfo } from '@bobfrankston/udp-transport';
6
6
  export { UdpTransport as LxTransport } from '@bobfrankston/udp-transport';
7
7
  //# sourceMappingURL=transport.d.ts.map
package/types.d.ts CHANGED
@@ -108,11 +108,6 @@ export interface DeviceState {
108
108
  uptime?: number;
109
109
  downtime?: number;
110
110
  }
111
- /** Info passed with state events */
112
- export interface StateEventInfo {
113
- /** true if from device response, false if from peer client broadcast */
114
- primary: boolean;
115
- }
116
111
  /** LIFX port */
117
112
  export declare const LIFX_PORT = 56700;
118
113
  /** Header size */