@evops/lightwaverf 1.0.3 → 1.0.4
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/.dist/LightwaveRFClient.d.ts +4 -1
- package/.dist/LightwaveRFClient.js +30 -23
- package/.dist/index.d.ts +3 -1
- package/.dist/index.js +34 -4
- package/.dist/index.test.js +13 -4
- package/package.json +1 -1
|
@@ -22,7 +22,10 @@ export declare class LightwaveRFClient extends events.EventEmitter implements Li
|
|
|
22
22
|
model?: string;
|
|
23
23
|
uptime?: number;
|
|
24
24
|
version?: string;
|
|
25
|
-
|
|
25
|
+
discoverLinkIp: boolean;
|
|
26
|
+
constructor(debug: Debugger, ip?: string, { discoverLinkIp }?: {
|
|
27
|
+
discoverLinkIp?: boolean;
|
|
28
|
+
});
|
|
26
29
|
connect(): Promise<void>;
|
|
27
30
|
disconnect(): Promise<[void, void]>;
|
|
28
31
|
private checkRegistration;
|
|
@@ -19,15 +19,17 @@ class LightwaveRFClient extends events_1.default.EventEmitter {
|
|
|
19
19
|
messageProcessors = [];
|
|
20
20
|
debug;
|
|
21
21
|
transactionListeners = new Map();
|
|
22
|
-
delay =
|
|
22
|
+
delay = 800;
|
|
23
23
|
serial;
|
|
24
24
|
mac;
|
|
25
25
|
model;
|
|
26
26
|
uptime;
|
|
27
27
|
version;
|
|
28
|
-
|
|
28
|
+
discoverLinkIp;
|
|
29
|
+
constructor(debug, ip = "255.255.255.255", { discoverLinkIp = true } = {}) {
|
|
29
30
|
super();
|
|
30
31
|
this.ip = ip;
|
|
32
|
+
this.discoverLinkIp = discoverLinkIp;
|
|
31
33
|
this.debug = debug.extend("client");
|
|
32
34
|
this.senderSocket = dgram_1.default.createSocket("udp4");
|
|
33
35
|
this.senderSocket.unref();
|
|
@@ -78,18 +80,18 @@ class LightwaveRFClient extends events_1.default.EventEmitter {
|
|
|
78
80
|
});
|
|
79
81
|
}
|
|
80
82
|
send(message, callback) {
|
|
81
|
-
const
|
|
82
|
-
const messageWithTransaction = `${
|
|
83
|
-
const transactionDebug = this.debug.extend("tx:" +
|
|
84
|
-
this.transactionListeners.set(
|
|
83
|
+
const transactionId = Math.round(Math.random() * Math.pow(10, 8));
|
|
84
|
+
const messageWithTransaction = `${transactionId},${message}`;
|
|
85
|
+
const transactionDebug = this.debug.extend("tx:" + transactionId);
|
|
86
|
+
this.transactionListeners.set(transactionId, {
|
|
85
87
|
message: message,
|
|
86
88
|
debug: transactionDebug,
|
|
87
89
|
delay: this.delay,
|
|
88
90
|
callback: callback,
|
|
89
91
|
});
|
|
90
|
-
this.debug("Queueing message: %s", messageWithTransaction);
|
|
92
|
+
this.debug("[%d] Queueing message: %s", Date.now(), messageWithTransaction);
|
|
91
93
|
this.commandQueue.add({
|
|
92
|
-
id:
|
|
94
|
+
id: transactionId,
|
|
93
95
|
message: messageWithTransaction,
|
|
94
96
|
debug: transactionDebug,
|
|
95
97
|
callback,
|
|
@@ -98,26 +100,31 @@ class LightwaveRFClient extends events_1.default.EventEmitter {
|
|
|
98
100
|
}
|
|
99
101
|
async processSendQueue() {
|
|
100
102
|
if (this.commandQueue.busy) {
|
|
101
|
-
|
|
103
|
+
this.debug(`The queue is busy, will wait to process`);
|
|
102
104
|
return;
|
|
103
105
|
}
|
|
104
106
|
const command = this.commandQueue.next();
|
|
105
107
|
if (!command)
|
|
106
108
|
return;
|
|
109
|
+
this.debug(`Processing command: %o`, { command });
|
|
107
110
|
this.commandQueue.busy = true;
|
|
108
111
|
const transactionListener = this.transactionListeners.get(command.id);
|
|
109
112
|
const originalCallback = transactionListener.callback;
|
|
110
113
|
transactionListener.callback = (transaction, error) => {
|
|
111
|
-
this.commandQueue.busy = false;
|
|
112
114
|
originalCallback?.(transaction, error);
|
|
113
|
-
|
|
115
|
+
this.debug("Transaction %d completed, scheduling next processing in %dms !!!!!!!!!!", transaction.id, this.delay);
|
|
116
|
+
setTimeout(() => {
|
|
117
|
+
this.commandQueue.busy = false;
|
|
118
|
+
this.processSendQueue();
|
|
119
|
+
}, this.delay);
|
|
114
120
|
};
|
|
115
121
|
// If we didn't hear back within the timeout
|
|
116
122
|
setTimeout(() => {
|
|
117
123
|
const listener = this.transactionListeners.get(command.id);
|
|
118
124
|
if (!listener)
|
|
119
125
|
return;
|
|
120
|
-
originalCallback?.(null, new Error("Execution expired"));
|
|
126
|
+
originalCallback?.(null, new Error("Execution expired " + command.id));
|
|
127
|
+
this.commandQueue.busy = false;
|
|
121
128
|
this.transactionListeners.delete(command.id);
|
|
122
129
|
this.processSendQueue();
|
|
123
130
|
}, 5000);
|
|
@@ -144,15 +151,14 @@ class LightwaveRFClient extends events_1.default.EventEmitter {
|
|
|
144
151
|
if (messageProcessor.canProcess(message)) {
|
|
145
152
|
this.debug("Message can be processed by %s", messageProcessor.constructor.name);
|
|
146
153
|
const lightwaveMessage = messageProcessor.process(message);
|
|
147
|
-
this.processLightwaveMessage(lightwaveMessage);
|
|
154
|
+
this.processLightwaveMessage(lightwaveMessage, remoteInfo);
|
|
148
155
|
return;
|
|
149
156
|
}
|
|
150
157
|
}
|
|
151
158
|
throw "Message cannot be processed";
|
|
152
159
|
}
|
|
153
|
-
processLightwaveMessage(lightwaveMessage) {
|
|
160
|
+
processLightwaveMessage(lightwaveMessage, remoteInfo) {
|
|
154
161
|
this.debug("Processing lightwave message: %o", lightwaveMessage);
|
|
155
|
-
this.debug("Current listeners: %o", this.transactionListeners);
|
|
156
162
|
this.debug("Link response fn", lightwaveMessage.fn);
|
|
157
163
|
// update info from link
|
|
158
164
|
if (lightwaveMessage.serial) {
|
|
@@ -167,8 +173,8 @@ class LightwaveRFClient extends events_1.default.EventEmitter {
|
|
|
167
173
|
if (lightwaveMessage.uptime) {
|
|
168
174
|
this.uptime = lightwaveMessage.uptime;
|
|
169
175
|
}
|
|
170
|
-
if (
|
|
171
|
-
this.ip =
|
|
176
|
+
if (this.discoverLinkIp) {
|
|
177
|
+
this.ip = remoteInfo.address;
|
|
172
178
|
}
|
|
173
179
|
if (lightwaveMessage.fw) {
|
|
174
180
|
this.version ??= lightwaveMessage.fw;
|
|
@@ -194,20 +200,21 @@ class LightwaveRFClient extends events_1.default.EventEmitter {
|
|
|
194
200
|
if (!listener)
|
|
195
201
|
return;
|
|
196
202
|
if (lightwaveMessage.error?.match(/^ERR,6,/)) {
|
|
197
|
-
|
|
198
|
-
|
|
203
|
+
// Storing delay on a message level provides the ability to implement
|
|
204
|
+
// exponential backoff, here the maximum is 10 seconds
|
|
205
|
+
listener.delay = Math.min(listener.delay * 2, 10000);
|
|
206
|
+
const msg = `${lightwaveMessage.id},${listener.message}`;
|
|
199
207
|
this.debug("message errorred, retrying: %o, %o with delay: %o", msg, listener, listener.delay);
|
|
200
208
|
setTimeout(() => {
|
|
201
209
|
this.exec(msg);
|
|
202
|
-
}, Math.round(listener.delay));
|
|
210
|
+
}, Math.round(listener.delay * 2));
|
|
203
211
|
return;
|
|
204
212
|
}
|
|
205
|
-
this.commandQueue.busy = false;
|
|
206
213
|
if (listener) {
|
|
207
214
|
listener.debug("Found transaction listener");
|
|
208
|
-
listener.
|
|
209
|
-
listener.debug("Transaction completed, removing listener");
|
|
215
|
+
listener.debug("[%d] Transaction completed, removing listener", Date.now());
|
|
210
216
|
this.transactionListeners.delete(lightwaveMessage.id);
|
|
217
|
+
listener.callback(lightwaveMessage, null);
|
|
211
218
|
}
|
|
212
219
|
else {
|
|
213
220
|
this.debug("Listener not found for message: %o", lightwaveMessage);
|
package/.dist/index.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ declare class LightwaveRFConfiguration {
|
|
|
12
12
|
host?: any;
|
|
13
13
|
email?: any;
|
|
14
14
|
pin?: any;
|
|
15
|
+
linkDisplayUpdates?: boolean;
|
|
15
16
|
}
|
|
16
17
|
declare interface ILightwaveRF {
|
|
17
18
|
on(event: "deviceTurnedOn", listener: (roomId: number, deviceId: number) => void): this;
|
|
@@ -42,7 +43,8 @@ export default class LightwaveRF extends EventEmitter<LightwaveEvents> implement
|
|
|
42
43
|
lwClient: LightwaveRFClient;
|
|
43
44
|
lwAccount: LightwaveAccount;
|
|
44
45
|
debug: debug.Debugger;
|
|
45
|
-
|
|
46
|
+
private linkDisplayUpdates;
|
|
47
|
+
constructor({ email, pin, ip, timeout, linkDisplayUpdates, }: LightwaveRFConfiguration);
|
|
46
48
|
get serial(): string | undefined;
|
|
47
49
|
get mac(): string | undefined;
|
|
48
50
|
get uptime(): number | undefined;
|
package/.dist/index.js
CHANGED
|
@@ -17,6 +17,7 @@ class LightwaveRFConfiguration {
|
|
|
17
17
|
host;
|
|
18
18
|
email;
|
|
19
19
|
pin;
|
|
20
|
+
linkDisplayUpdates;
|
|
20
21
|
}
|
|
21
22
|
/** * LightwaveRF API
|
|
22
23
|
*
|
|
@@ -37,10 +38,12 @@ class LightwaveRF extends events_1.EventEmitter {
|
|
|
37
38
|
lwClient;
|
|
38
39
|
lwAccount;
|
|
39
40
|
debug;
|
|
40
|
-
|
|
41
|
+
linkDisplayUpdates;
|
|
42
|
+
constructor({ email, pin, ip, timeout, linkDisplayUpdates = true, }) {
|
|
41
43
|
super();
|
|
42
44
|
this.setMaxListeners(255);
|
|
43
45
|
this.debug = (0, debug_1.default)("lightwave");
|
|
46
|
+
this.linkDisplayUpdates = linkDisplayUpdates;
|
|
44
47
|
this.debug("Initialising LightwaveRF Client");
|
|
45
48
|
this.lwClient = new LightwaveRFClient_1.LightwaveRFClient(this.debug, ip);
|
|
46
49
|
this.lwClient.once("ready", () => {
|
|
@@ -83,14 +86,41 @@ class LightwaveRF extends events_1.EventEmitter {
|
|
|
83
86
|
}));
|
|
84
87
|
}
|
|
85
88
|
async turnOn({ roomId, deviceId, roomName, deviceName }) {
|
|
86
|
-
|
|
89
|
+
const { promise, resolve, reject } = Promise.withResolvers();
|
|
90
|
+
const linkDisplayUpdate = this.linkDisplayUpdates
|
|
91
|
+
? `|${roomName} ${deviceName}|Turn on|`
|
|
92
|
+
: "";
|
|
93
|
+
this.lwClient.send(`!F1R${roomId}D${deviceId}${linkDisplayUpdate}`, (_, error) => {
|
|
94
|
+
if (error)
|
|
95
|
+
return reject(error);
|
|
96
|
+
resolve();
|
|
97
|
+
});
|
|
98
|
+
return promise;
|
|
87
99
|
}
|
|
88
100
|
async turnOff({ roomId, deviceId, roomName, deviceName }) {
|
|
89
|
-
|
|
101
|
+
const { promise, resolve, reject } = Promise.withResolvers();
|
|
102
|
+
const linkDisplayUpdate = this.linkDisplayUpdates
|
|
103
|
+
? `|${roomName} ${deviceName}|Turn off|`
|
|
104
|
+
: "";
|
|
105
|
+
this.lwClient.send(`!F0R${roomId}D${deviceId}${linkDisplayUpdate}`, (_, error) => {
|
|
106
|
+
if (error)
|
|
107
|
+
return reject(error);
|
|
108
|
+
resolve();
|
|
109
|
+
});
|
|
110
|
+
return promise;
|
|
90
111
|
}
|
|
91
112
|
async dim({ roomId, deviceId, roomName, deviceName }, percentage) {
|
|
113
|
+
const { promise, resolve, reject } = Promise.withResolvers();
|
|
92
114
|
const lwDim = Math.round(percentage * 0.32);
|
|
93
|
-
|
|
115
|
+
const linkDisplayUpdate = this.linkDisplayUpdates
|
|
116
|
+
? `|${roomName} ${deviceName}|Dim to ${percentage}%|`
|
|
117
|
+
: "";
|
|
118
|
+
this.lwClient.send(`!FdP${lwDim}R${roomId}D${deviceId}${linkDisplayUpdate}`, (_, error) => {
|
|
119
|
+
if (error)
|
|
120
|
+
return reject(error);
|
|
121
|
+
resolve();
|
|
122
|
+
});
|
|
123
|
+
return promise;
|
|
94
124
|
}
|
|
95
125
|
async connect() {
|
|
96
126
|
return this.lwClient.connect();
|
package/.dist/index.test.js
CHANGED
|
@@ -22,22 +22,31 @@ const _1 = __importDefault(require("."));
|
|
|
22
22
|
// const devices = await lw.getDevices();
|
|
23
23
|
await lw.connect();
|
|
24
24
|
await lw.ensureRegistration();
|
|
25
|
+
await lw.lwClient.disconnect();
|
|
25
26
|
});
|
|
26
27
|
(0, vitest_1.it)("should turn device on", async () => {
|
|
27
28
|
const lw = new _1.default({
|
|
28
29
|
email: "some@user.com",
|
|
29
30
|
pin: "1234",
|
|
31
|
+
// Disabling link display updates as they cause buffer issues in the link
|
|
32
|
+
// device
|
|
33
|
+
linkDisplayUpdates: true,
|
|
30
34
|
});
|
|
31
35
|
// const devices = await lw.getDevices();
|
|
32
36
|
await lw.connect();
|
|
33
37
|
// await lw.ensureRegistration();
|
|
34
38
|
const devices = await lw.getDevices();
|
|
35
39
|
const wallLamps = devices?.find((d) => {
|
|
36
|
-
return d.deviceName === "
|
|
40
|
+
return d.deviceName === "Table lamp";
|
|
37
41
|
});
|
|
38
42
|
if (!wallLamps) {
|
|
39
|
-
throw new Error("Could not find
|
|
43
|
+
throw new Error("Could not find table lamp in the config");
|
|
40
44
|
}
|
|
41
|
-
|
|
42
|
-
|
|
45
|
+
for (let i = 0; i < 5; i++) {
|
|
46
|
+
console.debug("Turning device on and off", i);
|
|
47
|
+
await lw.turnOn(wallLamps);
|
|
48
|
+
await lw.turnOff(wallLamps);
|
|
49
|
+
}
|
|
50
|
+
await lw.lwClient.disconnect();
|
|
51
|
+
}, 30000);
|
|
43
52
|
});
|