@bobfrankston/lxlan 0.1.0 → 0.1.3
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/.gitattributes +5 -0
- package/client.d.ts +36 -18
- package/client.d.ts.map +1 -1
- package/client.js +92 -35
- package/client.js.map +1 -1
- package/device.d.ts +58 -4
- package/device.d.ts.map +1 -1
- package/device.js +111 -11
- package/device.js.map +1 -1
- package/events.d.ts +24 -0
- package/events.d.ts.map +1 -0
- package/events.js +7 -0
- package/events.js.map +1 -0
- package/index.d.ts +2 -0
- package/index.d.ts.map +1 -1
- package/index.js +1 -0
- package/index.js.map +1 -1
- package/package.json +14 -6
- package/protocol.d.ts +23 -0
- package/protocol.d.ts.map +1 -1
- package/protocol.js +27 -0
- package/protocol.js.map +1 -1
- package/transport.d.ts +30 -0
- package/transport.d.ts.map +1 -0
- package/transport.js +9 -0
- package/transport.js.map +1 -0
- package/types.d.ts +13 -0
- package/types.d.ts.map +1 -1
- package/types.js +8 -0
- package/types.js.map +1 -1
- package/.claude/settings.local.json +0 -13
- package/client.ts +0 -214
- package/device.ts +0 -170
- package/index.ts +0 -4
- package/notes.md +0 -530
- package/protocol.ts +0 -209
- package/tsconfig.json +0 -20
- package/types.ts +0 -129
package/.gitattributes
ADDED
package/client.d.ts
CHANGED
|
@@ -1,19 +1,24 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { LxTransport } from './transport.js';
|
|
2
|
+
import { LxEventEmitter } from './events.js';
|
|
3
3
|
import { LxDevice } from './device.js';
|
|
4
4
|
/**
|
|
5
5
|
* Options for LxClient constructor
|
|
6
6
|
*/
|
|
7
7
|
export interface LxClientOptions {
|
|
8
|
-
/**
|
|
8
|
+
/** Transport layer implementation (required) */
|
|
9
|
+
transport: LxTransport;
|
|
10
|
+
/** Broadcast addresses for discovery */
|
|
11
|
+
broadcastAddresses: string[];
|
|
12
|
+
/** Event emitter implementation (required - use Node EventEmitter or browser equivalent) */
|
|
13
|
+
eventEmitter: LxEventEmitter;
|
|
14
|
+
/** LIFX port (default 56700) */
|
|
9
15
|
port?: number;
|
|
10
|
-
/** Broadcast addresses for discovery (auto-detected from network interfaces if not specified) */
|
|
11
|
-
broadcastAddresses?: string[];
|
|
12
16
|
/** Auto-discovery interval in ms (0 = manual only, default 0) */
|
|
13
17
|
discoveryInterval?: number;
|
|
14
18
|
}
|
|
15
19
|
/**
|
|
16
20
|
* LIFX LAN client for device discovery and control.
|
|
21
|
+
* Platform-agnostic core - requires event emitter and transport to be provided.
|
|
17
22
|
*
|
|
18
23
|
* Events:
|
|
19
24
|
* - `device` (device: LxDevice) - new device discovered
|
|
@@ -24,24 +29,34 @@ export interface LxClientOptions {
|
|
|
24
29
|
* - `group` (device: LxDevice) - group info updated
|
|
25
30
|
* - `location` (device: LxDevice) - location info updated
|
|
26
31
|
* - `version` (device: LxDevice) - version info received
|
|
32
|
+
* - `hostInfo` (device: LxDevice) - host info received
|
|
33
|
+
* - `hostFirmware` (device: LxDevice) - firmware info received
|
|
34
|
+
* - `wifiInfo` (device: LxDevice) - WiFi info received
|
|
35
|
+
* - `info` (device: LxDevice) - device uptime/downtime info received
|
|
36
|
+
* - `deviceInfo` (device: LxDevice) - comprehensive device info updated (after getDeviceInfo())
|
|
27
37
|
* - `error` (err: Error) - transport or protocol error
|
|
28
38
|
*/
|
|
29
|
-
export declare class LxClient
|
|
30
|
-
private
|
|
39
|
+
export declare class LxClient {
|
|
40
|
+
private emitter;
|
|
41
|
+
private transport;
|
|
31
42
|
private port;
|
|
32
43
|
private broadcastAddresses;
|
|
33
|
-
private discoveryTimer
|
|
44
|
+
private discoveryTimer?;
|
|
34
45
|
/** Cached devices by MAC address (lowercase) */
|
|
35
46
|
devices: Map<string, LxDevice>;
|
|
36
|
-
constructor(options
|
|
47
|
+
constructor(options: LxClientOptions);
|
|
48
|
+
/** Register event listener */
|
|
49
|
+
on(event: string, listener: (...args: any[]) => void): this;
|
|
50
|
+
/** Register one-time event listener */
|
|
51
|
+
once(event: string, listener: (...args: any[]) => void): this;
|
|
52
|
+
/** Remove event listener */
|
|
53
|
+
off(event: string, listener: (...args: any[]) => void): this;
|
|
54
|
+
/** Emit event */
|
|
55
|
+
private emit;
|
|
37
56
|
/** Start listening */
|
|
38
57
|
start(): Promise<void>;
|
|
39
58
|
/** Stop and cleanup */
|
|
40
59
|
stop(): void;
|
|
41
|
-
/** Set retry options at runtime */
|
|
42
|
-
setRetryOptions(options: UdpRetryOptions): void;
|
|
43
|
-
/** Get current retry options */
|
|
44
|
-
getRetryOptions(): Required<UdpRetryOptions>;
|
|
45
60
|
/** Broadcast discovery to all interfaces */
|
|
46
61
|
discover(): void;
|
|
47
62
|
/**
|
|
@@ -49,17 +64,20 @@ export declare class LxClient extends EventEmitter {
|
|
|
49
64
|
* @param mac - MAC address (case-insensitive, with or without colons)
|
|
50
65
|
* @returns LxDevice or undefined if not found
|
|
51
66
|
*/
|
|
52
|
-
getDevice(mac: string): LxDevice;
|
|
67
|
+
getDevice(mac: string): LxDevice | undefined;
|
|
53
68
|
/**
|
|
54
69
|
* Add device manually (bypassing discovery).
|
|
55
|
-
* Use when you know the device
|
|
70
|
+
* Use when you know the device MAC from external source (e.g., database).
|
|
71
|
+
* IP can be provided if known, or left empty to be discovered.
|
|
56
72
|
* @param mac - MAC address
|
|
57
|
-
* @param ip - IP address
|
|
58
|
-
* @param port - UDP port (default 56700)
|
|
73
|
+
* @param ip - IP address (optional, can be discovered)
|
|
74
|
+
* @param port - UDP port (default LIFX_PORT = 56700)
|
|
59
75
|
* @returns LxDevice instance (new or existing)
|
|
60
76
|
*/
|
|
61
|
-
addDevice(mac: string, ip
|
|
77
|
+
addDevice(mac: string, ip?: string, port?: number): LxDevice;
|
|
62
78
|
/** Handle incoming message */
|
|
63
79
|
private handleMessage;
|
|
80
|
+
/** Check if device info is complete and emit deviceInfo event */
|
|
81
|
+
private checkDeviceInfoComplete;
|
|
64
82
|
}
|
|
65
83
|
//# sourceMappingURL=client.d.ts.map
|
package/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["client.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["client.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAiBvC;;GAEG;AACH,MAAM,WAAW,eAAe;IAC5B,gDAAgD;IAChD,SAAS,EAAE,WAAW,CAAC;IACvB,wCAAwC;IACxC,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,4FAA4F;IAC5F,YAAY,EAAE,cAAc,CAAC;IAC7B,gCAAgC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,qBAAa,QAAQ;IACjB,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,IAAI,CAAS;IACrB,OAAO,CAAC,kBAAkB,CAAW;IACrC,OAAO,CAAC,cAAc,CAAC,CAAM;IAE7B,gDAAgD;IAChD,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAa;gBAE/B,OAAO,EAAE,eAAe;IAmBpC,8BAA8B;IAC9B,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,GAAG,IAAI;IAK3D,uCAAuC;IACvC,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,GAAG,IAAI;IAK7D,4BAA4B;IAC5B,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,GAAG,IAAI;IAK5D,iBAAiB;IACjB,OAAO,CAAC,IAAI;IAIZ,sBAAsB;IAChB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAI5B,uBAAuB;IACvB,IAAI,IAAI,IAAI;IAKZ,4CAA4C;IAC5C,QAAQ,IAAI,IAAI;IAShB;;;;OAIG;IACH,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,QAAQ,GAAG,SAAS;IAI5C;;;;;;;;OAQG;IACH,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,IAAI,GAAE,MAAkB,GAAG,QAAQ;IAkBvE,8BAA8B;IAC9B,OAAO,CAAC,aAAa;IA0HrB,iEAAiE;IACjE,OAAO,CAAC,uBAAuB;CAMlC"}
|
package/client.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
|
-
import { EventEmitter } from 'node:events';
|
|
2
1
|
import { hsbk16ToHsbk } from '@bobfrankston/colorlib';
|
|
3
|
-
import { UdpSocket, getBroadcastAddresses } from '@bobfrankston/lxudp';
|
|
4
2
|
import { LxDevice } from './device.js';
|
|
5
3
|
import { MessageType, LIFX_PORT } from './types.js';
|
|
6
|
-
import { encodeMessage, decodeMessage, decodeState, decodeStatePower, decodeStateLabel, decodeStateVersion, decodeStateGroup, decodeStateService } from './protocol.js';
|
|
4
|
+
import { encodeMessage, decodeMessage, decodeState, decodeStatePower, decodeStateLabel, decodeStateVersion, decodeStateGroup, decodeStateService, decodeStateHostInfo, decodeStateHostFirmware, decodeStateWifiInfo, decodeStateInfo } from './protocol.js';
|
|
7
5
|
/**
|
|
8
6
|
* LIFX LAN client for device discovery and control.
|
|
7
|
+
* Platform-agnostic core - requires event emitter and transport to be provided.
|
|
9
8
|
*
|
|
10
9
|
* Events:
|
|
11
10
|
* - `device` (device: LxDevice) - new device discovered
|
|
@@ -16,50 +15,64 @@ import { encodeMessage, decodeMessage, decodeState, decodeStatePower, decodeStat
|
|
|
16
15
|
* - `group` (device: LxDevice) - group info updated
|
|
17
16
|
* - `location` (device: LxDevice) - location info updated
|
|
18
17
|
* - `version` (device: LxDevice) - version info received
|
|
18
|
+
* - `hostInfo` (device: LxDevice) - host info received
|
|
19
|
+
* - `hostFirmware` (device: LxDevice) - firmware info received
|
|
20
|
+
* - `wifiInfo` (device: LxDevice) - WiFi info received
|
|
21
|
+
* - `info` (device: LxDevice) - device uptime/downtime info received
|
|
22
|
+
* - `deviceInfo` (device: LxDevice) - comprehensive device info updated (after getDeviceInfo())
|
|
19
23
|
* - `error` (err: Error) - transport or protocol error
|
|
20
24
|
*/
|
|
21
|
-
export class LxClient
|
|
22
|
-
|
|
25
|
+
export class LxClient {
|
|
26
|
+
emitter;
|
|
27
|
+
transport;
|
|
23
28
|
port;
|
|
24
29
|
broadcastAddresses;
|
|
25
|
-
discoveryTimer;
|
|
30
|
+
discoveryTimer; // NodeJS.Timeout in Node, number in browser
|
|
26
31
|
/** Cached devices by MAC address (lowercase) */
|
|
27
32
|
devices = new Map();
|
|
28
|
-
constructor(options
|
|
29
|
-
|
|
33
|
+
constructor(options) {
|
|
34
|
+
this.emitter = options.eventEmitter;
|
|
35
|
+
this.transport = options.transport;
|
|
30
36
|
this.port = options.port ?? LIFX_PORT;
|
|
31
|
-
this.broadcastAddresses = options.broadcastAddresses
|
|
32
|
-
this.
|
|
33
|
-
port: this.port,
|
|
34
|
-
reuseAddr: true
|
|
35
|
-
});
|
|
36
|
-
this.socket.on('message', (data, rinfo) => {
|
|
37
|
+
this.broadcastAddresses = options.broadcastAddresses;
|
|
38
|
+
this.transport.onMessage((data, rinfo) => {
|
|
37
39
|
this.handleMessage(data, rinfo.address, rinfo.port);
|
|
38
40
|
});
|
|
39
|
-
this.
|
|
40
|
-
this.emit('error', err);
|
|
41
|
+
this.transport.onError((err) => {
|
|
42
|
+
this.emitter.emit('error', err);
|
|
41
43
|
});
|
|
42
44
|
if (options.discoveryInterval && options.discoveryInterval > 0) {
|
|
43
45
|
this.discoveryTimer = setInterval(() => this.discover(), options.discoveryInterval);
|
|
44
46
|
}
|
|
45
47
|
}
|
|
48
|
+
/** Register event listener */
|
|
49
|
+
on(event, listener) {
|
|
50
|
+
this.emitter.on(event, listener);
|
|
51
|
+
return this;
|
|
52
|
+
}
|
|
53
|
+
/** Register one-time event listener */
|
|
54
|
+
once(event, listener) {
|
|
55
|
+
this.emitter.once(event, listener);
|
|
56
|
+
return this;
|
|
57
|
+
}
|
|
58
|
+
/** Remove event listener */
|
|
59
|
+
off(event, listener) {
|
|
60
|
+
this.emitter.off(event, listener);
|
|
61
|
+
return this;
|
|
62
|
+
}
|
|
63
|
+
/** Emit event */
|
|
64
|
+
emit(event, ...args) {
|
|
65
|
+
return this.emitter.emit(event, ...args);
|
|
66
|
+
}
|
|
46
67
|
/** Start listening */
|
|
47
68
|
async start() {
|
|
48
|
-
await this.
|
|
69
|
+
await this.transport.bind();
|
|
49
70
|
}
|
|
50
71
|
/** Stop and cleanup */
|
|
51
72
|
stop() {
|
|
52
73
|
if (this.discoveryTimer)
|
|
53
74
|
clearInterval(this.discoveryTimer);
|
|
54
|
-
this.
|
|
55
|
-
}
|
|
56
|
-
/** Set retry options at runtime */
|
|
57
|
-
setRetryOptions(options) {
|
|
58
|
-
this.socket.setRetryOptions(options);
|
|
59
|
-
}
|
|
60
|
-
/** Get current retry options */
|
|
61
|
-
getRetryOptions() {
|
|
62
|
-
return this.socket.getRetryOptions();
|
|
75
|
+
this.transport.close();
|
|
63
76
|
}
|
|
64
77
|
/** Broadcast discovery to all interfaces */
|
|
65
78
|
discover() {
|
|
@@ -67,9 +80,7 @@ export class LxClient extends EventEmitter {
|
|
|
67
80
|
type: MessageType.GetService,
|
|
68
81
|
tagged: true
|
|
69
82
|
});
|
|
70
|
-
|
|
71
|
-
this.socket.send(addr, this.port, msg);
|
|
72
|
-
}
|
|
83
|
+
this.transport.broadcast(msg, this.port, this.broadcastAddresses);
|
|
73
84
|
}
|
|
74
85
|
/**
|
|
75
86
|
* Get device by MAC address
|
|
@@ -81,23 +92,26 @@ export class LxClient extends EventEmitter {
|
|
|
81
92
|
}
|
|
82
93
|
/**
|
|
83
94
|
* Add device manually (bypassing discovery).
|
|
84
|
-
* Use when you know the device
|
|
95
|
+
* Use when you know the device MAC from external source (e.g., database).
|
|
96
|
+
* IP can be provided if known, or left empty to be discovered.
|
|
85
97
|
* @param mac - MAC address
|
|
86
|
-
* @param ip - IP address
|
|
87
|
-
* @param port - UDP port (default 56700)
|
|
98
|
+
* @param ip - IP address (optional, can be discovered)
|
|
99
|
+
* @param port - UDP port (default LIFX_PORT = 56700)
|
|
88
100
|
* @returns LxDevice instance (new or existing)
|
|
89
101
|
*/
|
|
90
102
|
addDevice(mac, ip, port = LIFX_PORT) {
|
|
91
103
|
const normalizedMac = mac.toLowerCase();
|
|
92
104
|
let device = this.devices.get(normalizedMac);
|
|
93
105
|
if (!device) {
|
|
94
|
-
device = new LxDevice(normalizedMac, ip
|
|
106
|
+
device = new LxDevice(normalizedMac, ip);
|
|
107
|
+
device.setTransport(this.transport);
|
|
95
108
|
device.port = port;
|
|
96
109
|
this.devices.set(normalizedMac, device);
|
|
97
110
|
this.emit('device', device);
|
|
98
111
|
}
|
|
99
112
|
else {
|
|
100
|
-
|
|
113
|
+
if (ip)
|
|
114
|
+
device.ip = ip;
|
|
101
115
|
device.port = port;
|
|
102
116
|
}
|
|
103
117
|
return device;
|
|
@@ -118,13 +132,18 @@ export class LxClient extends EventEmitter {
|
|
|
118
132
|
let device = this.devices.get(mac);
|
|
119
133
|
const isNew = !device;
|
|
120
134
|
if (!device) {
|
|
121
|
-
device = new LxDevice(mac, fromIp
|
|
135
|
+
device = new LxDevice(mac, fromIp);
|
|
136
|
+
device.setTransport(this.transport);
|
|
122
137
|
device.port = fromPort;
|
|
123
138
|
this.devices.set(mac, device);
|
|
124
139
|
}
|
|
125
140
|
device.ip = fromIp;
|
|
126
141
|
device.port = fromPort;
|
|
127
142
|
device.markSeen();
|
|
143
|
+
// Check for duplicate message (some LIFX devices send responses twice)
|
|
144
|
+
if (device.isDuplicate(msg.sequence)) {
|
|
145
|
+
return; // Ignore duplicate
|
|
146
|
+
}
|
|
128
147
|
if (isNew) {
|
|
129
148
|
this.emit('device', device);
|
|
130
149
|
}
|
|
@@ -170,6 +189,44 @@ export class LxClient extends EventEmitter {
|
|
|
170
189
|
this.emit('location', device);
|
|
171
190
|
break;
|
|
172
191
|
}
|
|
192
|
+
case MessageType.StateHostInfo: {
|
|
193
|
+
const info = decodeStateHostInfo(msg.payload);
|
|
194
|
+
device.signal = info.signal;
|
|
195
|
+
device.rssi = Math.round(10 * Math.log10(info.signal));
|
|
196
|
+
this.emit('hostInfo', device);
|
|
197
|
+
this.checkDeviceInfoComplete(device);
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
case MessageType.StateHostFirmware: {
|
|
201
|
+
const fw = decodeStateHostFirmware(msg.payload);
|
|
202
|
+
device.firmwareVersion = fw.version;
|
|
203
|
+
this.emit('hostFirmware', device);
|
|
204
|
+
this.checkDeviceInfoComplete(device);
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
case MessageType.StateWifiInfo: {
|
|
208
|
+
const info = decodeStateWifiInfo(msg.payload);
|
|
209
|
+
device.signal = info.signal;
|
|
210
|
+
device.rssi = Math.round(10 * Math.log10(info.signal));
|
|
211
|
+
this.emit('wifiInfo', device);
|
|
212
|
+
this.checkDeviceInfoComplete(device);
|
|
213
|
+
break;
|
|
214
|
+
}
|
|
215
|
+
case MessageType.StateInfo: {
|
|
216
|
+
const info = decodeStateInfo(msg.payload);
|
|
217
|
+
device.uptime = info.uptime;
|
|
218
|
+
device.downtime = info.downtime;
|
|
219
|
+
this.emit('info', device);
|
|
220
|
+
this.checkDeviceInfoComplete(device);
|
|
221
|
+
break;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
/** Check if device info is complete and emit deviceInfo event */
|
|
226
|
+
checkDeviceInfoComplete(device) {
|
|
227
|
+
// If we have key info fields populated, emit deviceInfo event
|
|
228
|
+
if (device.vendor && device.label && device.firmwareVersion && device.signal !== undefined) {
|
|
229
|
+
this.emit('deviceInfo', device);
|
|
173
230
|
}
|
|
174
231
|
}
|
|
175
232
|
}
|
package/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["client.ts"],"names":[],"mappings":"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"}
|
package/device.d.ts
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { HSBK, ColorInput } from '@bobfrankston/colorlib';
|
|
2
|
-
import {
|
|
2
|
+
import { LxTransport } from './transport.js';
|
|
3
3
|
import { GroupInfo } from './types.js';
|
|
4
4
|
/**
|
|
5
5
|
* Represents a LIFX device on the LAN.
|
|
6
6
|
* State is cached and updated via events from LxClient.
|
|
7
|
+
*
|
|
8
|
+
* **IMPORTANT:** Do not create devices directly with `new LxDevice()`.
|
|
9
|
+
* Always use `client.addDevice(mac, ip)` or obtain devices from `client.devices`.
|
|
10
|
+
* Directly instantiated devices will not have a transport and will fail at runtime.
|
|
7
11
|
*/
|
|
8
12
|
export declare class LxDevice {
|
|
9
13
|
/** MAC address (lowercase, colon-separated) */
|
|
10
14
|
readonly mac: string;
|
|
11
15
|
/** Current IP address */
|
|
12
16
|
ip: string;
|
|
13
|
-
/** UDP port (default 56700) */
|
|
17
|
+
/** UDP port (default LIFX_PORT = 56700) */
|
|
14
18
|
port: number;
|
|
15
19
|
/** Power state (true = on) */
|
|
16
20
|
power: boolean;
|
|
@@ -26,14 +30,43 @@ export declare class LxDevice {
|
|
|
26
30
|
vendor: number;
|
|
27
31
|
/** Product ID (see Products table) */
|
|
28
32
|
product: number;
|
|
33
|
+
/** Firmware version (encoded as 0x00RRMMPP) */
|
|
34
|
+
firmwareVersion?: number;
|
|
35
|
+
/** WiFi signal strength (0.0 to 1.0) */
|
|
36
|
+
signal?: number;
|
|
37
|
+
/** RSSI in dBm (calculated from signal) */
|
|
38
|
+
rssi?: number;
|
|
39
|
+
/** Device uptime in milliseconds */
|
|
40
|
+
uptime?: number;
|
|
41
|
+
/** Device downtime in milliseconds */
|
|
42
|
+
downtime?: number;
|
|
29
43
|
/** Group membership */
|
|
30
44
|
group: GroupInfo;
|
|
31
45
|
/** Location membership */
|
|
32
46
|
location: GroupInfo;
|
|
33
|
-
|
|
34
|
-
|
|
47
|
+
/** Recent message sequences for deduplication (sequence -> timestamp) */
|
|
48
|
+
private recentSequences;
|
|
49
|
+
private transport?;
|
|
50
|
+
/**
|
|
51
|
+
* Create a LIFX device
|
|
52
|
+
*
|
|
53
|
+
* **WARNING:** This constructor is for internal use by LxClient.
|
|
54
|
+
* Do not call directly - use `client.addDevice(mac, ip)` instead.
|
|
55
|
+
* Devices created directly will not have a transport and will throw errors when used.
|
|
56
|
+
*
|
|
57
|
+
* @param mac - MAC address (will be normalized to lowercase)
|
|
58
|
+
* @param ip - IP address (optional, can be discovered)
|
|
59
|
+
* @internal
|
|
60
|
+
*/
|
|
61
|
+
constructor(mac: string, ip?: string);
|
|
62
|
+
/** Throw error if transport is not set */
|
|
63
|
+
private requireTransport;
|
|
64
|
+
/** Throw error if IP address is not set */
|
|
65
|
+
private requireIP;
|
|
35
66
|
/** Get product name from product ID */
|
|
36
67
|
get productName(): string;
|
|
68
|
+
/** Set the transport (used by LxClient when managing devices) */
|
|
69
|
+
setTransport(transport: LxTransport): void;
|
|
37
70
|
/** Send raw message to device */
|
|
38
71
|
send(type: number, payload?: Buffer): void;
|
|
39
72
|
/** Set power on/off */
|
|
@@ -69,7 +102,28 @@ export declare class LxDevice {
|
|
|
69
102
|
getLocation(): void;
|
|
70
103
|
/** Query version */
|
|
71
104
|
getVersion(): void;
|
|
105
|
+
/** Query host info (signal, tx, rx) */
|
|
106
|
+
getHostInfo(): void;
|
|
107
|
+
/** Query host firmware */
|
|
108
|
+
getHostFirmware(): void;
|
|
109
|
+
/** Query WiFi info */
|
|
110
|
+
getWifiInfo(): void;
|
|
111
|
+
/** Query device info (uptime, downtime) */
|
|
112
|
+
getInfo(): void;
|
|
113
|
+
/**
|
|
114
|
+
* Query all device information
|
|
115
|
+
* Sends multiple requests to gather comprehensive device metadata.
|
|
116
|
+
* Listen for 'deviceInfo' event on client to get results.
|
|
117
|
+
*/
|
|
118
|
+
getDeviceInfo(): void;
|
|
72
119
|
/** Update last seen timestamp and online status */
|
|
73
120
|
markSeen(): void;
|
|
121
|
+
/**
|
|
122
|
+
* Check if message is a duplicate based on sequence number.
|
|
123
|
+
* LIFX devices sometimes send duplicate responses.
|
|
124
|
+
* @param sequence - Message sequence number
|
|
125
|
+
* @returns true if duplicate (already seen recently)
|
|
126
|
+
*/
|
|
127
|
+
isDuplicate(sequence: number): boolean;
|
|
74
128
|
}
|
|
75
129
|
//# sourceMappingURL=device.d.ts.map
|
package/device.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device.d.ts","sourceRoot":"","sources":["device.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAwB,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"device.d.ts","sourceRoot":"","sources":["device.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,UAAU,EAAwB,MAAM,wBAAwB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,SAAS,EAAoC,MAAM,YAAY,CAAC;AAGzE;;;;;;;GAOG;AACH,qBAAa,QAAQ;IACjB,+CAA+C;IAC/C,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,yBAAyB;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,2CAA2C;IAC3C,IAAI,EAAE,MAAM,CAAa;IAEzB,8BAA8B;IAC9B,KAAK,EAAE,OAAO,CAAS;IACvB,mCAAmC;IACnC,KAAK,EAAE,IAAI,CAAiC;IAC5C,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAM;IACnB,mCAAmC;IACnC,MAAM,EAAE,OAAO,CAAS;IACxB,0CAA0C;IAC1C,QAAQ,EAAE,MAAM,CAAK;IAErB,2BAA2B;IAC3B,MAAM,EAAE,MAAM,CAAK;IACnB,sCAAsC;IACtC,OAAO,EAAE,MAAM,CAAK;IACpB,+CAA+C;IAC/C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wCAAwC;IACxC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2CAA2C;IAC3C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,oCAAoC;IACpC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,sCAAsC;IACtC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,uBAAuB;IACvB,KAAK,EAAE,SAAS,CAAuC;IACvD,0BAA0B;IAC1B,QAAQ,EAAE,SAAS,CAAuC;IAE1D,yEAAyE;IACzE,OAAO,CAAC,eAAe,CAAkC;IACzD,OAAO,CAAC,SAAS,CAAC,CAAc;IAEhC;;;;;;;;;;OAUG;gBACS,GAAG,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM;IAKpC,0CAA0C;IAC1C,OAAO,CAAC,gBAAgB;IAIxB,2CAA2C;IAC3C,OAAO,CAAC,SAAS;IAIjB,uCAAuC;IACvC,IAAI,WAAW,IAAI,MAAM,CAExB;IAED,iEAAiE;IACjE,YAAY,CAAC,SAAS,EAAE,WAAW,GAAG,IAAI;IAI1C,iCAAiC;IACjC,IAAI,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAc1C,uBAAuB;IACvB,QAAQ,CAAC,EAAE,EAAE,OAAO,GAAG,IAAI;IAW3B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,GAAE,MAAU,GAAG,IAAI;IAavD;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,GAAE,MAAY,EAAE,QAAQ,GAAE,MAAU,GAAG,IAAI;IAI9E,uBAAuB;IACvB,QAAQ,IAAI,IAAI;IAIhB,wBAAwB;IACxB,QAAQ,IAAI,IAAI;IAIhB,gBAAgB;IAChB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAW7B,kBAAkB;IAClB,QAAQ,IAAI,IAAI;IAIhB,gBAAgB;IAChB,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAWzC,kBAAkB;IAClB,QAAQ,IAAI,IAAI;IAIhB,mBAAmB;IACnB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI;IAW5C,qBAAqB;IACrB,WAAW,IAAI,IAAI;IAInB,oBAAoB;IACpB,UAAU,IAAI,IAAI;IAIlB,uCAAuC;IACvC,WAAW,IAAI,IAAI;IAInB,0BAA0B;IAC1B,eAAe,IAAI,IAAI;IAIvB,sBAAsB;IACtB,WAAW,IAAI,IAAI;IAInB,2CAA2C;IAC3C,OAAO,IAAI,IAAI;IAIf;;;;OAIG;IACH,aAAa,IAAI,IAAI;IAWrB,mDAAmD;IACnD,QAAQ,IAAI,IAAI;IAKhB;;;;;OAKG;IACH,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO;CAmBzC"}
|