@evops/lightwaverf 1.0.3 → 1.0.5

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.
@@ -0,0 +1,39 @@
1
+ import { Debugger } from "debug";
2
+ export interface QueuedTransaction {
3
+ id: number;
4
+ originalMessage: string;
5
+ message: string;
6
+ resolve: (value: TransactionResponse) => void;
7
+ reject: (error: Error) => void;
8
+ timeoutId?: ReturnType<typeof setTimeout>;
9
+ retryTimeoutId?: ReturnType<typeof setTimeout>;
10
+ delay: number;
11
+ completed: boolean;
12
+ }
13
+ export interface TransactionResponse {
14
+ id: number;
15
+ [key: string]: unknown;
16
+ }
17
+ export interface LightwaveCommandQueueOptions {
18
+ debug: Debugger;
19
+ delay?: number;
20
+ timeout?: number;
21
+ onExecute: (message: string) => void;
22
+ }
23
+ export declare class LightwaveCommandQueue {
24
+ private queue;
25
+ private transactions;
26
+ private busy;
27
+ private debug;
28
+ private delay;
29
+ private timeout;
30
+ private onExecute;
31
+ constructor(options: LightwaveCommandQueueOptions);
32
+ send(message: string | Buffer): Promise<TransactionResponse>;
33
+ handleResponse(response: TransactionResponse): void;
34
+ handleRetryableError(transactionId: number): void;
35
+ destroy(): void;
36
+ private processQueue;
37
+ private completeTransaction;
38
+ private failTransaction;
39
+ }
@@ -0,0 +1,146 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LightwaveCommandQueue = void 0;
4
+ class LightwaveCommandQueue {
5
+ queue = [];
6
+ transactions = new Map();
7
+ busy = false;
8
+ debug;
9
+ delay;
10
+ timeout;
11
+ onExecute;
12
+ constructor(options) {
13
+ this.debug = options.debug.extend("queue");
14
+ this.delay = options.delay ?? 800;
15
+ this.timeout = options.timeout ?? 10000;
16
+ this.onExecute = options.onExecute;
17
+ }
18
+ send(message) {
19
+ const transactionId = Math.round(Math.random() * Math.pow(10, 8));
20
+ const messageStr = typeof message === "string" ? message : message.toString("utf-8");
21
+ const messageWithTransaction = `${transactionId},${messageStr}`;
22
+ this.debug("[%d] Queueing message: %s", Date.now(), messageWithTransaction);
23
+ const { promise, resolve, reject } = Promise.withResolvers();
24
+ const transaction = {
25
+ id: transactionId,
26
+ originalMessage: messageStr,
27
+ message: messageWithTransaction,
28
+ resolve,
29
+ reject,
30
+ delay: this.delay,
31
+ completed: false,
32
+ };
33
+ this.queue.push(transaction);
34
+ this.transactions.set(transactionId, transaction);
35
+ this.processQueue();
36
+ return promise;
37
+ }
38
+ handleResponse(response) {
39
+ const transaction = this.transactions.get(response.id);
40
+ if (!transaction || transaction.completed) {
41
+ this.debug("No pending transaction found for id %d or already completed", response.id);
42
+ return;
43
+ }
44
+ this.debug("[%d] Transaction %d completed", Date.now(), response.id);
45
+ this.completeTransaction(transaction, response);
46
+ }
47
+ handleRetryableError(transactionId) {
48
+ const transaction = this.transactions.get(transactionId);
49
+ if (!transaction || transaction.completed) {
50
+ return;
51
+ }
52
+ // Clear existing timeout
53
+ if (transaction.timeoutId) {
54
+ clearTimeout(transaction.timeoutId);
55
+ transaction.timeoutId = undefined;
56
+ }
57
+ // Exponential backoff, max 10 seconds
58
+ transaction.delay = Math.min(transaction.delay * 2, 10000);
59
+ const retryMessage = `${transactionId},${transaction.originalMessage}`;
60
+ this.debug("Message errored, retrying: %s with delay: %d", retryMessage, transaction.delay);
61
+ // Set timeout for retry
62
+ transaction.timeoutId = setTimeout(() => {
63
+ if (transaction.completed)
64
+ return;
65
+ this.debug("Retry timeout expired for transaction %d", transactionId);
66
+ this.failTransaction(transaction, new Error(`Retry timeout expired ${transactionId}`));
67
+ }, 5000 + transaction.delay * 2);
68
+ // Schedule retry
69
+ transaction.retryTimeoutId = setTimeout(() => {
70
+ if (transaction.completed)
71
+ return;
72
+ this.onExecute(retryMessage);
73
+ }, Math.round(transaction.delay * 2));
74
+ }
75
+ destroy() {
76
+ for (const transaction of this.transactions.values()) {
77
+ if (transaction.timeoutId) {
78
+ clearTimeout(transaction.timeoutId);
79
+ }
80
+ if (transaction.retryTimeoutId) {
81
+ clearTimeout(transaction.retryTimeoutId);
82
+ }
83
+ if (!transaction.completed) {
84
+ transaction.reject(new Error("Queue destroyed"));
85
+ transaction.completed = true;
86
+ }
87
+ }
88
+ this.transactions.clear();
89
+ this.queue = [];
90
+ this.busy = false;
91
+ }
92
+ processQueue() {
93
+ if (this.busy) {
94
+ this.debug("Queue is busy, waiting to process");
95
+ return;
96
+ }
97
+ const transaction = this.queue.shift();
98
+ if (!transaction) {
99
+ return;
100
+ }
101
+ this.debug("Processing transaction: %d", transaction.id);
102
+ this.busy = true;
103
+ // Set timeout for response
104
+ transaction.timeoutId = setTimeout(() => {
105
+ if (transaction.completed)
106
+ return;
107
+ this.debug("Transaction %d timed out", transaction.id);
108
+ this.failTransaction(transaction, new Error(`Execution expired ${transaction.id}`));
109
+ }, this.timeout);
110
+ this.onExecute(transaction.message);
111
+ }
112
+ completeTransaction(transaction, response) {
113
+ if (transaction.completed)
114
+ return;
115
+ transaction.completed = true;
116
+ if (transaction.timeoutId) {
117
+ clearTimeout(transaction.timeoutId);
118
+ }
119
+ if (transaction.retryTimeoutId) {
120
+ clearTimeout(transaction.retryTimeoutId);
121
+ }
122
+ this.transactions.delete(transaction.id);
123
+ transaction.resolve(response);
124
+ this.debug("Transaction %d completed, scheduling next in %dms", transaction.id, this.delay);
125
+ setTimeout(() => {
126
+ this.busy = false;
127
+ this.processQueue();
128
+ }, this.delay);
129
+ }
130
+ failTransaction(transaction, error) {
131
+ if (transaction.completed)
132
+ return;
133
+ transaction.completed = true;
134
+ if (transaction.timeoutId) {
135
+ clearTimeout(transaction.timeoutId);
136
+ }
137
+ if (transaction.retryTimeoutId) {
138
+ clearTimeout(transaction.retryTimeoutId);
139
+ }
140
+ this.transactions.delete(transaction.id);
141
+ transaction.reject(error);
142
+ this.busy = false;
143
+ this.processQueue();
144
+ }
145
+ }
146
+ exports.LightwaveCommandQueue = LightwaveCommandQueue;
@@ -1,6 +1,6 @@
1
1
  import { Debugger } from "debug";
2
2
  import events from "events";
3
- import { LightwaveTransaction } from "./LightwaveTransaction";
3
+ import { TransactionResponse } from "./LightwaveCommandQueue";
4
4
  declare interface LightwaveRFClientInterface {
5
5
  on(event: "ready", listener: (client: LightwaveRFClient) => void): this;
6
6
  on(event: "deviceTurnedOn", listener: (room: number, device: number) => void): this;
@@ -15,19 +15,20 @@ export declare class LightwaveRFClient extends events.EventEmitter implements Li
15
15
  private commandQueue;
16
16
  private messageProcessors;
17
17
  private debug;
18
- private transactionListeners;
19
18
  delay: number;
20
19
  serial?: string;
21
20
  mac?: string;
22
21
  model?: string;
23
22
  uptime?: number;
24
23
  version?: string;
25
- constructor(debug: Debugger, ip?: string);
24
+ discoverLinkIp: boolean;
25
+ constructor(debug: Debugger, ip?: string, { discoverLinkIp }?: {
26
+ discoverLinkIp?: boolean;
27
+ });
26
28
  connect(): Promise<void>;
27
29
  disconnect(): Promise<[void, void]>;
28
30
  private checkRegistration;
29
- send(message: string | Buffer, callback?: (transaction: LightwaveTransaction | null, error: Error) => void): void;
30
- private processSendQueue;
31
+ send(message: string | Buffer): Promise<TransactionResponse>;
31
32
  private exec;
32
33
  private processRawMessage;
33
34
  private processLightwaveMessage;
@@ -6,33 +6,39 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.LightwaveRFClient = void 0;
7
7
  const dgram_1 = __importDefault(require("dgram"));
8
8
  const events_1 = __importDefault(require("events"));
9
+ const LightwaveCommandQueue_1 = require("./LightwaveCommandQueue");
9
10
  const LightwaveMessageProcessorForJson_1 = require("./LightwaveMessageProcessorForJson");
10
11
  const LightwaveMessageProcessorForText_1 = __importDefault(require("./LightwaveMessageProcessorForText"));
11
- const Queue_1 = require("./Queue");
12
12
  const LIGHTWAVE_LINK_SEND_PORT = 9760;
13
13
  const LIGHTWAVE_LINK_RECEIVE_PORT = 9761;
14
14
  class LightwaveRFClient extends events_1.default.EventEmitter {
15
15
  ip;
16
16
  senderSocket;
17
17
  receiverSocket;
18
- commandQueue = new Queue_1.Queue();
18
+ commandQueue;
19
19
  messageProcessors = [];
20
20
  debug;
21
- transactionListeners = new Map();
22
- delay = 125;
21
+ delay = 800;
23
22
  serial;
24
23
  mac;
25
24
  model;
26
25
  uptime;
27
26
  version;
28
- constructor(debug, ip = "255.255.255.255") {
27
+ discoverLinkIp;
28
+ constructor(debug, ip = "255.255.255.255", { discoverLinkIp = true } = {}) {
29
29
  super();
30
30
  this.ip = ip;
31
+ this.discoverLinkIp = discoverLinkIp;
31
32
  this.debug = debug.extend("client");
32
33
  this.senderSocket = dgram_1.default.createSocket("udp4");
33
34
  this.senderSocket.unref();
34
35
  this.receiverSocket = dgram_1.default.createSocket("udp4");
35
36
  this.receiverSocket.unref();
37
+ this.commandQueue = new LightwaveCommandQueue_1.LightwaveCommandQueue({
38
+ debug: this.debug,
39
+ delay: this.delay,
40
+ onExecute: (message) => this.exec(message),
41
+ });
36
42
  this.messageProcessors.push(new LightwaveMessageProcessorForJson_1.LightwaveMessageProcessorForJson(this.debug));
37
43
  this.messageProcessors.push(new LightwaveMessageProcessorForText_1.default(this.debug));
38
44
  }
@@ -61,69 +67,26 @@ class LightwaveRFClient extends events_1.default.EventEmitter {
61
67
  async disconnect() {
62
68
  this.receiverSocket.removeAllListeners();
63
69
  this.senderSocket.removeAllListeners();
70
+ this.commandQueue.destroy();
64
71
  const { promise: senderPromise, resolve: senderResolve } = Promise.withResolvers();
65
72
  const { promise: receiverPromise, resolve: receiverResolve } = Promise.withResolvers();
66
73
  this.senderSocket.close(senderResolve);
67
74
  this.receiverSocket.close(receiverResolve);
68
75
  return Promise.all([senderPromise, receiverPromise]);
69
76
  }
70
- checkRegistration() {
77
+ async checkRegistration() {
71
78
  this.debug("Checking registration");
72
- this.send("@H", (transaction, error) => {
73
- if (error) {
74
- this.debug("Error: %o", error);
75
- }
79
+ try {
80
+ const transaction = await this.send("@H");
76
81
  this.debug(transaction);
77
- this.emit("ready", this);
78
- });
79
- }
80
- send(message, callback) {
81
- const transaction = Math.round(Math.random() * Math.pow(10, 8));
82
- const messageWithTransaction = `${transaction},${message}`;
83
- const transactionDebug = this.debug.extend("tx:" + transaction);
84
- this.transactionListeners.set(transaction, {
85
- message: message,
86
- debug: transactionDebug,
87
- delay: this.delay,
88
- callback: callback,
89
- });
90
- this.debug("Queueing message: %s", messageWithTransaction);
91
- this.commandQueue.add({
92
- id: transaction,
93
- message: messageWithTransaction,
94
- debug: transactionDebug,
95
- callback,
96
- });
97
- this.processSendQueue();
98
- }
99
- async processSendQueue() {
100
- if (this.commandQueue.busy) {
101
- setTimeout(this.processSendQueue.bind(this), this.delay);
102
- return;
103
82
  }
104
- const command = this.commandQueue.next();
105
- if (!command)
106
- return;
107
- this.commandQueue.busy = true;
108
- const transactionListener = this.transactionListeners.get(command.id);
109
- const originalCallback = transactionListener.callback;
110
- transactionListener.callback = (transaction, error) => {
111
- this.commandQueue.busy = false;
112
- originalCallback?.(transaction, error);
113
- setTimeout(this.processSendQueue.bind(this), this.delay);
114
- };
115
- // If we didn't hear back within the timeout
116
- setTimeout(() => {
117
- const listener = this.transactionListeners.get(command.id);
118
- if (!listener)
119
- return;
120
- originalCallback?.(null, new Error("Execution expired"));
121
- this.transactionListeners.delete(command.id);
122
- this.processSendQueue();
123
- }, 5000);
124
- const transactionDebug = this.debug.extend(`transaction:${command?.id}`);
125
- transactionDebug("Starting new transaction");
126
- this.exec(command.message);
83
+ catch (error) {
84
+ this.debug("Error: %o", error);
85
+ }
86
+ this.emit("ready", this);
87
+ }
88
+ send(message) {
89
+ return this.commandQueue.send(message);
127
90
  }
128
91
  exec(message) {
129
92
  if (message === undefined)
@@ -144,15 +107,14 @@ class LightwaveRFClient extends events_1.default.EventEmitter {
144
107
  if (messageProcessor.canProcess(message)) {
145
108
  this.debug("Message can be processed by %s", messageProcessor.constructor.name);
146
109
  const lightwaveMessage = messageProcessor.process(message);
147
- this.processLightwaveMessage(lightwaveMessage);
110
+ this.processLightwaveMessage(lightwaveMessage, remoteInfo);
148
111
  return;
149
112
  }
150
113
  }
151
114
  throw "Message cannot be processed";
152
115
  }
153
- processLightwaveMessage(lightwaveMessage) {
116
+ processLightwaveMessage(lightwaveMessage, remoteInfo) {
154
117
  this.debug("Processing lightwave message: %o", lightwaveMessage);
155
- this.debug("Current listeners: %o", this.transactionListeners);
156
118
  this.debug("Link response fn", lightwaveMessage.fn);
157
119
  // update info from link
158
120
  if (lightwaveMessage.serial) {
@@ -167,8 +129,9 @@ class LightwaveRFClient extends events_1.default.EventEmitter {
167
129
  if (lightwaveMessage.uptime) {
168
130
  this.uptime = lightwaveMessage.uptime;
169
131
  }
170
- if (lightwaveMessage.ip) {
171
- this.ip = lightwaveMessage.ip;
132
+ if (this.discoverLinkIp) {
133
+ this.debug(`Updating link ip to ${remoteInfo.address}`);
134
+ this.ip = remoteInfo.address;
172
135
  }
173
136
  if (lightwaveMessage.fw) {
174
137
  this.version ??= lightwaveMessage.fw;
@@ -190,27 +153,14 @@ class LightwaveRFClient extends events_1.default.EventEmitter {
190
153
  if (lightwaveMessage.fn === "dim") {
191
154
  this.emit("deviceDimmed", lightwaveMessage.room, lightwaveMessage.dev, Math.round((lightwaveMessage.param / 32) * 100));
192
155
  }
193
- const listener = this.transactionListeners.get(lightwaveMessage.id);
194
- if (!listener)
195
- return;
156
+ // Handle retryable errors (ERR,6 = device busy)
196
157
  if (lightwaveMessage.error?.match(/^ERR,6,/)) {
197
- listener.delay = listener.delay * 2;
198
- const msg = `${lightwaveMessage.id},!${listener.message}`;
199
- this.debug("message errorred, retrying: %o, %o with delay: %o", msg, listener, listener.delay);
200
- setTimeout(() => {
201
- this.exec(msg);
202
- }, Math.round(listener.delay));
158
+ this.commandQueue.handleRetryableError(lightwaveMessage.id);
203
159
  return;
204
160
  }
205
- this.commandQueue.busy = false;
206
- if (listener) {
207
- listener.debug("Found transaction listener");
208
- listener.callback(lightwaveMessage, null);
209
- listener.debug("Transaction completed, removing listener");
210
- this.transactionListeners.delete(lightwaveMessage.id);
211
- }
212
- else {
213
- this.debug("Listener not found for message: %o", lightwaveMessage);
161
+ // Pass successful response to the queue
162
+ if (lightwaveMessage.id !== undefined) {
163
+ this.commandQueue.handleResponse(lightwaveMessage);
214
164
  }
215
165
  }
216
166
  }
package/.dist/index.d.ts CHANGED
@@ -12,6 +12,8 @@ declare class LightwaveRFConfiguration {
12
12
  host?: any;
13
13
  email?: any;
14
14
  pin?: any;
15
+ linkDisplayUpdates?: boolean;
16
+ discoverLinkIp?: boolean;
15
17
  }
16
18
  declare interface ILightwaveRF {
17
19
  on(event: "deviceTurnedOn", listener: (roomId: number, deviceId: number) => void): this;
@@ -42,7 +44,8 @@ export default class LightwaveRF extends EventEmitter<LightwaveEvents> implement
42
44
  lwClient: LightwaveRFClient;
43
45
  lwAccount: LightwaveAccount;
44
46
  debug: debug.Debugger;
45
- constructor({ email, pin, ip, timeout }: LightwaveRFConfiguration);
47
+ private linkDisplayUpdates;
48
+ constructor({ email, pin, ip, timeout, linkDisplayUpdates, discoverLinkIp, }: LightwaveRFConfiguration);
46
49
  get serial(): string | undefined;
47
50
  get mac(): string | undefined;
48
51
  get uptime(): number | undefined;
package/.dist/index.js CHANGED
@@ -17,6 +17,8 @@ class LightwaveRFConfiguration {
17
17
  host;
18
18
  email;
19
19
  pin;
20
+ linkDisplayUpdates;
21
+ discoverLinkIp;
20
22
  }
21
23
  /** * LightwaveRF API
22
24
  *
@@ -37,12 +39,16 @@ class LightwaveRF extends events_1.EventEmitter {
37
39
  lwClient;
38
40
  lwAccount;
39
41
  debug;
40
- constructor({ email, pin, ip, timeout }) {
42
+ linkDisplayUpdates;
43
+ constructor({ email, pin, ip, timeout, linkDisplayUpdates = true, discoverLinkIp = true, }) {
41
44
  super();
42
45
  this.setMaxListeners(255);
43
46
  this.debug = (0, debug_1.default)("lightwave");
47
+ this.linkDisplayUpdates = linkDisplayUpdates;
44
48
  this.debug("Initialising LightwaveRF Client");
45
- this.lwClient = new LightwaveRFClient_1.LightwaveRFClient(this.debug, ip);
49
+ this.lwClient = new LightwaveRFClient_1.LightwaveRFClient(this.debug, ip, {
50
+ discoverLinkIp,
51
+ });
46
52
  this.lwClient.once("ready", () => {
47
53
  this.debug("LightwaveRF ready");
48
54
  });
@@ -83,36 +89,41 @@ class LightwaveRF extends events_1.EventEmitter {
83
89
  }));
84
90
  }
85
91
  async turnOn({ roomId, deviceId, roomName, deviceName }) {
86
- this.lwClient.send(`!F1R${roomId}D${deviceId}|${roomName} ${deviceName}|Turn on|`);
92
+ const linkDisplayUpdate = this.linkDisplayUpdates
93
+ ? `|${roomName} ${deviceName}|Turn on|`
94
+ : "";
95
+ await this.lwClient.send(`!F1R${roomId}D${deviceId}${linkDisplayUpdate}`);
87
96
  }
88
97
  async turnOff({ roomId, deviceId, roomName, deviceName }) {
89
- this.lwClient.send(`!F0R${roomId}D${deviceId}|${roomName} ${deviceName}|Turn off|`);
98
+ const linkDisplayUpdate = this.linkDisplayUpdates
99
+ ? `|${roomName} ${deviceName}|Turn off|`
100
+ : "";
101
+ await this.lwClient.send(`!F0R${roomId}D${deviceId}${linkDisplayUpdate}`);
90
102
  }
91
103
  async dim({ roomId, deviceId, roomName, deviceName }, percentage) {
92
104
  const lwDim = Math.round(percentage * 0.32);
93
- this.lwClient.send(`!FdP${lwDim}R${roomId}D${deviceId}|${roomName} ${deviceName}|Dim to ${percentage}%|`);
105
+ const linkDisplayUpdate = this.linkDisplayUpdates
106
+ ? `|${roomName} ${deviceName}|Dim to ${percentage}%|`
107
+ : "";
108
+ await this.lwClient.send(`!FdP${lwDim}R${roomId}D${deviceId}${linkDisplayUpdate}`);
94
109
  }
95
110
  async connect() {
96
111
  return this.lwClient.connect();
97
112
  }
98
113
  async isRegistered() {
99
- return new Promise((resolve) => {
100
- const user = process.env.USER;
101
- this.lwClient.send(`@H|Check registration|user:${user}|`, (response) => {
102
- return resolve(!response?.error);
103
- });
104
- });
114
+ const user = process.env.USER;
115
+ const response = await this.lwClient.send(`@H|Check registration|user:${user}|`);
116
+ return !response?.error;
105
117
  }
106
118
  async ensureRegistration() {
119
+ const user = process.env.USER;
120
+ const response = await this.lwClient.send(`@H|Check registration|user:${user}|`);
121
+ if (!response?.error) {
122
+ return;
123
+ }
124
+ this.debug("We are not registered with the hub");
125
+ await this.lwClient.send("!F*p");
107
126
  return new Promise((resolve) => {
108
- const user = process.env.USER;
109
- this.lwClient.send(`@H|Check registration|user:${user}|`, (response) => {
110
- if (!response?.error) {
111
- return resolve();
112
- }
113
- this.debug("We are not registered with the hub");
114
- this.lwClient.send("!F*p");
115
- });
116
127
  this.lwClient.on("registered", resolve);
117
128
  });
118
129
  }
@@ -7,6 +7,7 @@ const fetch_vcr_1 = __importDefault(require("fetch-vcr"));
7
7
  const vitest_1 = require("vitest");
8
8
  const _1 = __importDefault(require("."));
9
9
  (0, vitest_1.describe)("LightwaveRF", () => {
10
+ let lw;
10
11
  (0, vitest_1.beforeAll)(() => {
11
12
  fetch_vcr_1.default.configure({
12
13
  fixturePath: __dirname + "/.fixtures",
@@ -14,30 +15,44 @@ const _1 = __importDefault(require("."));
14
15
  });
15
16
  global.fetch = fetch_vcr_1.default;
16
17
  });
18
+ (0, vitest_1.afterEach)(async () => {
19
+ await lw.lwClient.disconnect();
20
+ });
17
21
  (0, vitest_1.it)("should allow device linking", async () => {
18
- const lw = new _1.default({
22
+ lw = new _1.default({
19
23
  email: "some@user.com",
20
24
  pin: "1234",
21
25
  });
22
26
  // const devices = await lw.getDevices();
23
27
  await lw.connect();
24
28
  await lw.ensureRegistration();
29
+ await lw.lwClient.disconnect();
25
30
  });
26
31
  (0, vitest_1.it)("should turn device on", async () => {
27
- const lw = new _1.default({
32
+ lw = new _1.default({
28
33
  email: "some@user.com",
29
34
  pin: "1234",
35
+ // Disabling link display updates as they cause buffer issues in the link
36
+ // device
37
+ linkDisplayUpdates: true,
30
38
  });
31
39
  // const devices = await lw.getDevices();
32
40
  await lw.connect();
33
41
  // await lw.ensureRegistration();
34
42
  const devices = await lw.getDevices();
35
- const wallLamps = devices?.find((d) => {
36
- return d.deviceName === "Wall lamps";
43
+ const roomToInteractWith = "TV Room";
44
+ const lightToInteractWith = "Lights";
45
+ const light = devices?.find((d) => {
46
+ return (d.roomName === roomToInteractWith &&
47
+ d.deviceName === lightToInteractWith);
37
48
  });
38
- if (!wallLamps) {
39
- throw new Error("Could not find wall lamps in the config");
49
+ if (!light) {
50
+ throw new Error(`Could not find ${lightToInteractWith} in the config`);
40
51
  }
41
- lw.turnOff(wallLamps);
42
- });
52
+ for (let i = 0; i < 5; i++) {
53
+ console.debug("Turning device on and off", i);
54
+ await lw.turnOn(light);
55
+ await lw.turnOff(light);
56
+ }
57
+ }, 30000);
43
58
  });
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@evops/lightwaverf",
3
3
  "description": "Lightwave RF client library",
4
- "version": "1.0.3",
4
+ "version": "1.0.5",
5
5
  "exports": {
6
6
  ".": {
7
7
  "types": "./.dist/index.d.ts",
package/vitest.config.ts CHANGED
@@ -6,7 +6,7 @@ export default defineConfig({
6
6
  environment: "node",
7
7
  printConsoleTrace: true,
8
8
  env: {
9
- // DEBUG: "lightwave*",
9
+ DEBUG: "lightwave*",
10
10
  },
11
11
  },
12
12
  });