homebridge-plejd 1.6.2 → 1.7.0-beta
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/CHANGELOG.md +7 -0
- package/cache/plejdCacheSite.json +3774 -0
- package/cache/plejdLogin.json +24 -0
- package/cache/plejdSites.json +34 -0
- package/config.schema.json +7 -0
- package/dist/PlejdHbAccessory.d.ts +7 -5
- package/dist/PlejdHbAccessory.js +23 -5
- package/dist/PlejdHbAccessory.js.map +1 -1
- package/dist/PlejdHbPlatform.js +24 -31
- package/dist/PlejdHbPlatform.js.map +1 -1
- package/dist/{settings.d.ts → constants.d.ts} +7 -3
- package/dist/constants.js +35 -0
- package/dist/constants.js.map +1 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/model/userInputConfig.d.ts +1 -1
- package/dist/plejdApi.d.ts +2 -2
- package/dist/plejdApi.js +27 -24
- package/dist/plejdApi.js.map +1 -1
- package/dist/plejdService.d.ts +24 -2
- package/dist/plejdService.js +51 -32
- package/dist/plejdService.js.map +1 -1
- package/dist/utils.d.ts +4 -0
- package/dist/utils.js +39 -0
- package/dist/utils.js.map +1 -1
- package/jest.config.js +4 -5
- package/package.json +5 -5
- package/tests/plejdService.spec.ts +125 -0
- package/tests/utils.spec.ts +286 -0
- package/dist/plejdUtils.d.ts +0 -3
- package/dist/plejdUtils.js +0 -40
- package/dist/plejdUtils.js.map +0 -1
- package/dist/settings.js +0 -47
- package/dist/settings.js.map +0 -1
- package/tests/settings.spec.ts +0 -59
@@ -0,0 +1,286 @@
|
|
1
|
+
import {
|
2
|
+
isDimmable,
|
3
|
+
isAddon,
|
4
|
+
delay,
|
5
|
+
race,
|
6
|
+
plejdChallageResp as plejdChalResp,
|
7
|
+
plejdEncodeDecode,
|
8
|
+
} from "../src/utils";
|
9
|
+
|
10
|
+
describe("plejdChalResp", () => {
|
11
|
+
it("should produce consistent output for same key and challenge", () => {
|
12
|
+
const key = Buffer.from("0123456789abcdef0123456789abcdef", "hex");
|
13
|
+
const challenge = Buffer.from("fedcba9876543210fedcba9876543210", "hex");
|
14
|
+
|
15
|
+
const result1 = plejdChalResp(key, challenge);
|
16
|
+
const result2 = plejdChalResp(key, challenge);
|
17
|
+
|
18
|
+
expect(result1).toEqual(result2);
|
19
|
+
});
|
20
|
+
|
21
|
+
it("should produce different outputs for different challenges", () => {
|
22
|
+
const key = Buffer.from("0123456789abcdef0123456789abcdef", "hex");
|
23
|
+
const challenge1 = Buffer.from("1111111111111111111111111111111", "hex");
|
24
|
+
const challenge2 = Buffer.from("2222222222222222222222222222222", "hex");
|
25
|
+
|
26
|
+
const result1 = plejdChalResp(key, challenge1);
|
27
|
+
const result2 = plejdChalResp(key, challenge2);
|
28
|
+
|
29
|
+
expect(result1).not.toEqual(result2);
|
30
|
+
});
|
31
|
+
|
32
|
+
it("should produce different outputs for different keys", () => {
|
33
|
+
const key1 = Buffer.from("1111111111111111111111111111111", "hex");
|
34
|
+
const key2 = Buffer.from("2222222222222222222222222222222", "hex");
|
35
|
+
const challenge = Buffer.from("fedcba9876543210fedcba9876543210", "hex");
|
36
|
+
|
37
|
+
const result1 = plejdChalResp(key1, challenge);
|
38
|
+
const result2 = plejdChalResp(key2, challenge);
|
39
|
+
|
40
|
+
expect(result1).not.toEqual(result2);
|
41
|
+
});
|
42
|
+
|
43
|
+
it("should return 16-byte buffer", () => {
|
44
|
+
const key = Buffer.from("0123456789abcdef0123456789abcdef", "hex");
|
45
|
+
const challenge = Buffer.from("fedcba9876543210fedcba9876543210", "hex");
|
46
|
+
|
47
|
+
const result = plejdChalResp(key, challenge);
|
48
|
+
|
49
|
+
expect(result).toBeInstanceOf(Buffer);
|
50
|
+
expect(result.length).toBe(16);
|
51
|
+
});
|
52
|
+
|
53
|
+
it("should handle known test vector", () => {
|
54
|
+
// Test with zero key and challenge for predictable result
|
55
|
+
const key = Buffer.alloc(16, 0);
|
56
|
+
const challenge = Buffer.alloc(16, 0);
|
57
|
+
|
58
|
+
const result = plejdChalResp(key, challenge);
|
59
|
+
|
60
|
+
expect(result.length).toBe(16);
|
61
|
+
expect(result).toBeInstanceOf(Buffer);
|
62
|
+
});
|
63
|
+
});
|
64
|
+
|
65
|
+
describe("plejdEncodeDecode", () => {
|
66
|
+
const testKey = Buffer.from("0123456789abcdef0123456789abcdef", "hex");
|
67
|
+
const testAddress = Buffer.from("001122334455", "hex");
|
68
|
+
|
69
|
+
it("should produce consistent output for same inputs", () => {
|
70
|
+
const data = Buffer.from("hello world", "ascii");
|
71
|
+
|
72
|
+
const result1 = plejdEncodeDecode(testKey, testAddress, data);
|
73
|
+
const result2 = plejdEncodeDecode(testKey, testAddress, data);
|
74
|
+
|
75
|
+
expect(result1).toEqual(result2);
|
76
|
+
});
|
77
|
+
|
78
|
+
it("should be reversible (encode/decode)", () => {
|
79
|
+
const originalData = Buffer.from("test message", "ascii");
|
80
|
+
|
81
|
+
const encoded = plejdEncodeDecode(testKey, testAddress, originalData);
|
82
|
+
const decoded = plejdEncodeDecode(testKey, testAddress, encoded);
|
83
|
+
|
84
|
+
expect(decoded).toEqual(originalData);
|
85
|
+
});
|
86
|
+
|
87
|
+
it("should handle empty data", () => {
|
88
|
+
const emptyData = Buffer.alloc(0);
|
89
|
+
|
90
|
+
const result = plejdEncodeDecode(testKey, testAddress, emptyData);
|
91
|
+
|
92
|
+
expect(result).toEqual(Buffer.alloc(0));
|
93
|
+
});
|
94
|
+
|
95
|
+
it("should handle single byte", () => {
|
96
|
+
const data = Buffer.from([65]); // 'A'
|
97
|
+
|
98
|
+
const result = plejdEncodeDecode(testKey, testAddress, data);
|
99
|
+
|
100
|
+
expect(result.length).toBe(1);
|
101
|
+
});
|
102
|
+
|
103
|
+
it("should produce different output for different keys", () => {
|
104
|
+
const data = Buffer.from("test", "ascii");
|
105
|
+
const key2 = Buffer.from("fedcba9876543210fedcba9876543210", "hex");
|
106
|
+
|
107
|
+
const result1 = plejdEncodeDecode(testKey, testAddress, data);
|
108
|
+
const result2 = plejdEncodeDecode(key2, testAddress, data);
|
109
|
+
|
110
|
+
expect(result1).not.toEqual(result2);
|
111
|
+
});
|
112
|
+
|
113
|
+
it("should produce different output for different addresses", () => {
|
114
|
+
const data = Buffer.from("test", "ascii");
|
115
|
+
const address2 = Buffer.from("aabbccddeeff", "hex");
|
116
|
+
|
117
|
+
const result1 = plejdEncodeDecode(testKey, testAddress, data);
|
118
|
+
const result2 = plejdEncodeDecode(testKey, address2, data);
|
119
|
+
|
120
|
+
expect(result1).not.toEqual(result2);
|
121
|
+
});
|
122
|
+
|
123
|
+
it("should handle data longer than keystream (16 bytes)", () => {
|
124
|
+
const longData = Buffer.from(
|
125
|
+
"this is a very long message that exceeds sixteen bytes",
|
126
|
+
"ascii",
|
127
|
+
);
|
128
|
+
|
129
|
+
const encoded = plejdEncodeDecode(testKey, testAddress, longData);
|
130
|
+
const decoded = plejdEncodeDecode(testKey, testAddress, encoded);
|
131
|
+
|
132
|
+
expect(decoded).toEqual(longData);
|
133
|
+
expect(encoded.length).toBe(longData.length);
|
134
|
+
});
|
135
|
+
|
136
|
+
it("should handle binary data", () => {
|
137
|
+
const binaryData = Buffer.from([0x00, 0xff, 0x80, 0x7f, 0x01, 0xfe]);
|
138
|
+
|
139
|
+
const encoded = plejdEncodeDecode(testKey, testAddress, binaryData);
|
140
|
+
const decoded = plejdEncodeDecode(testKey, testAddress, encoded);
|
141
|
+
|
142
|
+
expect(decoded).toEqual(binaryData);
|
143
|
+
});
|
144
|
+
|
145
|
+
it("should create proper keystream buffer from address", () => {
|
146
|
+
// Use proper 6-byte MAC address format
|
147
|
+
const address = Buffer.from("001122334455", "hex"); // 6 bytes
|
148
|
+
const data = Buffer.from([0x00]); // XOR with 0 reveals keystream
|
149
|
+
|
150
|
+
const result = plejdEncodeDecode(testKey, address, data);
|
151
|
+
|
152
|
+
// Should return the first byte of the keystream
|
153
|
+
expect(result.length).toBe(1);
|
154
|
+
});
|
155
|
+
|
156
|
+
it("should repeat keystream every 16 bytes", () => {
|
157
|
+
// Create data that will reveal the keystream pattern
|
158
|
+
const data = Buffer.alloc(32, 0); // 32 zeros
|
159
|
+
|
160
|
+
const result = plejdEncodeDecode(testKey, testAddress, data);
|
161
|
+
|
162
|
+
// Bytes 0 and 16 should be the same (keystream repeats)
|
163
|
+
expect(result[0]).toBe(result[16]);
|
164
|
+
expect(result[15]).toBe(result[31]);
|
165
|
+
});
|
166
|
+
});
|
167
|
+
|
168
|
+
describe("delay", () => {
|
169
|
+
it("should resolve after specified milliseconds", async () => {
|
170
|
+
const start = Date.now();
|
171
|
+
|
172
|
+
await delay(100);
|
173
|
+
|
174
|
+
const elapsed = Date.now() - start;
|
175
|
+
expect(elapsed).toBeGreaterThanOrEqual(95); // Allow some tolerance
|
176
|
+
expect(elapsed).toBeLessThan(150);
|
177
|
+
});
|
178
|
+
|
179
|
+
it("should resolve immediately for 0ms delay", async () => {
|
180
|
+
const start = Date.now();
|
181
|
+
|
182
|
+
await delay(0);
|
183
|
+
|
184
|
+
const elapsed = Date.now() - start;
|
185
|
+
expect(elapsed).toBeLessThan(10);
|
186
|
+
});
|
187
|
+
});
|
188
|
+
|
189
|
+
describe("race", () => {
|
190
|
+
it("should resolve when operation completes before timeout", async () => {
|
191
|
+
const operation = async () => {
|
192
|
+
await delay(100);
|
193
|
+
return "success";
|
194
|
+
};
|
195
|
+
|
196
|
+
const result = await race(operation, 200);
|
197
|
+
|
198
|
+
expect(result).toBe("success");
|
199
|
+
});
|
200
|
+
|
201
|
+
it("should reject with timeout error when operation takes too long", async () => {
|
202
|
+
const operation = async () => {
|
203
|
+
await delay(200);
|
204
|
+
return "success";
|
205
|
+
};
|
206
|
+
|
207
|
+
await expect(race(operation, 100)).rejects.toThrow("BLE operation timeout");
|
208
|
+
});
|
209
|
+
|
210
|
+
it("should reject when operation throws before timeout", async () => {
|
211
|
+
const operation = async () => {
|
212
|
+
throw new Error("operation failed");
|
213
|
+
};
|
214
|
+
|
215
|
+
await expect(race(operation, 100)).rejects.toThrow("operation failed");
|
216
|
+
});
|
217
|
+
|
218
|
+
it("should handle operation that returns different types", async () => {
|
219
|
+
const numberOperation = async () => 42;
|
220
|
+
const objectOperation = async () => ({ key: "value" });
|
221
|
+
|
222
|
+
const numberResult = await race(numberOperation, 100);
|
223
|
+
const objectResult = await race(objectOperation, 100);
|
224
|
+
|
225
|
+
expect(numberResult).toBe(42);
|
226
|
+
expect(objectResult).toEqual({ key: "value" });
|
227
|
+
});
|
228
|
+
});
|
229
|
+
|
230
|
+
describe("Device Type Detection", () => {
|
231
|
+
describe("isDimmable", () => {
|
232
|
+
const testCases = [
|
233
|
+
{ model: "DIM-01", expected: true },
|
234
|
+
{ model: "DIM-02", expected: true },
|
235
|
+
{ model: "LED-10", expected: true },
|
236
|
+
{ model: "DIM-01-2P", expected: true },
|
237
|
+
{ model: "LED-75", expected: true },
|
238
|
+
{ model: "DIM-02-LC 2024 Q2", expected: true },
|
239
|
+
{ model: "Dim 2.2.1 Release Candidate", expected: true },
|
240
|
+
{ model: "RTR-01", expected: false },
|
241
|
+
{ model: "WPH-01", expected: false },
|
242
|
+
{ model: "UNKNOWN-MODEL", expected: false },
|
243
|
+
];
|
244
|
+
|
245
|
+
testCases.forEach(({ model, expected }) => {
|
246
|
+
it(`should identify ${model} as ${expected ? "dimmable" : "non-dimmable"}`, () => {
|
247
|
+
expect(isDimmable(model)).toBe(expected);
|
248
|
+
});
|
249
|
+
});
|
250
|
+
|
251
|
+
// Test with real-world data
|
252
|
+
const realWorldDimmers = [
|
253
|
+
"DIM-02-LC 2024 Q2",
|
254
|
+
"Dim 2.2.1 Release Candidate",
|
255
|
+
"DIM-02",
|
256
|
+
"DIM-01",
|
257
|
+
];
|
258
|
+
|
259
|
+
realWorldDimmers.forEach((model) => {
|
260
|
+
it(`should identify real-world model ${model} as dimmable`, () => {
|
261
|
+
expect(isDimmable(model)).toBe(true);
|
262
|
+
});
|
263
|
+
});
|
264
|
+
});
|
265
|
+
|
266
|
+
describe("isAddon", () => {
|
267
|
+
const testCases = [
|
268
|
+
{ model: "RTR-01", expected: true },
|
269
|
+
{ model: "WPH-01", expected: true },
|
270
|
+
{ model: "WRT-01", expected: true },
|
271
|
+
{ model: "MNT-01", expected: true },
|
272
|
+
{ model: "MNT-02", expected: true },
|
273
|
+
{ model: "GWY-01", expected: true },
|
274
|
+
{ model: "BAT-01", expected: true },
|
275
|
+
{ model: "EXT-01", expected: true },
|
276
|
+
{ model: "DIM-01", expected: false },
|
277
|
+
{ model: "UNKNOWN-MODEL", expected: false },
|
278
|
+
];
|
279
|
+
|
280
|
+
testCases.forEach(({ model, expected }) => {
|
281
|
+
it(`should identify ${model} as ${expected ? "addon" : "non-addon"}`, () => {
|
282
|
+
expect(isAddon(model)).toBe(expected);
|
283
|
+
});
|
284
|
+
});
|
285
|
+
});
|
286
|
+
});
|
package/dist/plejdUtils.d.ts
DELETED
package/dist/plejdUtils.js
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
import { createCipheriv, createHash } from 'crypto';
|
2
|
-
export const plejdChalResp = (key, chal) => {
|
3
|
-
const intermediate = createHash('sha256').update(xor(key, chal)).digest();
|
4
|
-
const part1 = intermediate.slice(0, 16);
|
5
|
-
const part2 = intermediate.slice(16);
|
6
|
-
return xor(part1, part2);
|
7
|
-
};
|
8
|
-
export const plejdEncodeDecode = (key, addressBuffer, data) => {
|
9
|
-
const buf = Buffer.concat([
|
10
|
-
addressBuffer,
|
11
|
-
addressBuffer,
|
12
|
-
addressBuffer.subarray(0, 4),
|
13
|
-
]);
|
14
|
-
const cipher = createCipheriv('aes-128-ecb', key, '');
|
15
|
-
cipher.setAutoPadding(false);
|
16
|
-
let ct = cipher.update(buf).toString('hex');
|
17
|
-
ct += cipher.final().toString('hex');
|
18
|
-
const ctBuff = Buffer.from(ct, 'hex');
|
19
|
-
let output = '';
|
20
|
-
for (let i = 0, length = data.length; i < length; i++) {
|
21
|
-
output += String.fromCharCode(data[i] ^ ctBuff[i % 16]);
|
22
|
-
}
|
23
|
-
return Buffer.from(output, 'ascii');
|
24
|
-
};
|
25
|
-
export const reverseBuffer = (src) => {
|
26
|
-
const buffer = Buffer.allocUnsafe(src.length);
|
27
|
-
for (let i = 0, j = src.length - 1; i <= j; ++i, --j) {
|
28
|
-
buffer[i] = src[j];
|
29
|
-
buffer[j] = src[i];
|
30
|
-
}
|
31
|
-
return buffer;
|
32
|
-
};
|
33
|
-
const xor = (first, second) => {
|
34
|
-
const result = Buffer.alloc(first.length);
|
35
|
-
for (let i = 0; i < first.length; i++) {
|
36
|
-
result[i] = first[i] ^ second[i];
|
37
|
-
}
|
38
|
-
return result;
|
39
|
-
};
|
40
|
-
//# sourceMappingURL=plejdUtils.js.map
|
package/dist/plejdUtils.js.map
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"plejdUtils.js","sourceRoot":"","sources":["../src/plejdUtils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpD,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAW,EAAE,IAAY,EAAE,EAAE;IACzD,MAAM,YAAY,GAAG,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAE1E,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IAErC,OAAO,GAAG,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC3B,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,GAAW,EACX,aAAqB,EACrB,IAAY,EACJ,EAAE;IACV,MAAM,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC;QACxB,aAAa;QACb,aAAa;QACb,aAAa,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC;KAC7B,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,cAAc,CAAC,aAAa,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;IACtD,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IAE7B,IAAI,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC5C,EAAE,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,CAAC,CAAC;IAEtC,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtD,MAAM,IAAI,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACtC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,GAAW,EAAU,EAAE;IACnD,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;IAE9C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;QACrD,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QACnB,MAAM,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAEF,MAAM,GAAG,GAAG,CAAC,KAAa,EAAE,MAAc,EAAU,EAAE;IACpD,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1C,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACtC,MAAM,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC"}
|
package/dist/settings.js
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
/**
|
2
|
-
* This is the name of the platform that users will use to register the plugin in the Homebridge config.json
|
3
|
-
*/
|
4
|
-
export const PLATFORM_NAME = "Plejd";
|
5
|
-
/**
|
6
|
-
* This must match the name of your plugin as defined the package.json
|
7
|
-
*/
|
8
|
-
export const PLUGIN_NAME = "homebridge-plejd";
|
9
|
-
export const PLEJD_WRITE_TIMEOUT = 200;
|
10
|
-
export const PLEJD_PING_TIMEOUT = 3000;
|
11
|
-
export const isDimmable = (type) => {
|
12
|
-
const normalizedType = type.toLowerCase();
|
13
|
-
// Check if the model starts with any of the basic dimmer types
|
14
|
-
return PLEJD_LIGHTS.some((light) => normalizedType.startsWith(light.toLowerCase()) ||
|
15
|
-
normalizedType.includes("dim"));
|
16
|
-
};
|
17
|
-
export const isAddon = (type) => {
|
18
|
-
for (const x of PLEJD_ADDONS) {
|
19
|
-
if (type.toLowerCase().includes(x.toLowerCase())) {
|
20
|
-
return true;
|
21
|
-
}
|
22
|
-
}
|
23
|
-
return false;
|
24
|
-
};
|
25
|
-
/**
|
26
|
-
* Lights and switches from Plejd
|
27
|
-
*/
|
28
|
-
const PLEJD_LIGHTS = ["DIM-01", "DIM-02", "LED-10", "DIM-01-2P", "LED-75"];
|
29
|
-
// const PLEJD_SWITCHES = [
|
30
|
-
// "REL-01",
|
31
|
-
// "REL-02",
|
32
|
-
// "REL-01-2P",
|
33
|
-
// "DAL-01",
|
34
|
-
// "SPR-01",
|
35
|
-
// "CTR-01",
|
36
|
-
// ];
|
37
|
-
const PLEJD_ADDONS = [
|
38
|
-
"RTR-01",
|
39
|
-
"WPH-01",
|
40
|
-
"WRT-01",
|
41
|
-
"MNT-01",
|
42
|
-
"MNT-02",
|
43
|
-
"GWY-01",
|
44
|
-
"BAT-01",
|
45
|
-
"EXT-01",
|
46
|
-
];
|
47
|
-
//# sourceMappingURL=settings.js.map
|
package/dist/settings.js.map
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
{"version":3,"file":"settings.js","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,OAAO,CAAC;AAErC;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,kBAAkB,CAAC;AAE9C,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AACvC,MAAM,CAAC,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEvC,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,IAAY,EAAE,EAAE;IACzC,MAAM,cAAc,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;IAC1C,+DAA+D;IAC/D,OAAO,YAAY,CAAC,IAAI,CACtB,CAAC,KAAK,EAAE,EAAE,CACR,cAAc,CAAC,UAAU,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC;QAC9C,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,CACjC,CAAC;AACJ,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,OAAO,GAAG,CAAC,IAAY,EAAE,EAAE;IACtC,KAAK,MAAM,CAAC,IAAI,YAAY,EAAE,CAAC;QAC7B,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;YACjD,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC,CAAC;AAEF;;GAEG;AACH,MAAM,YAAY,GAAG,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,QAAQ,CAAC,CAAC;AAE3E,2BAA2B;AAC3B,cAAc;AACd,cAAc;AACd,iBAAiB;AACjB,cAAc;AACd,cAAc;AACd,cAAc;AACd,KAAK;AAEL,MAAM,YAAY,GAAG;IACnB,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;IACR,QAAQ;CACT,CAAC"}
|
package/tests/settings.spec.ts
DELETED
@@ -1,59 +0,0 @@
|
|
1
|
-
import { isDimmable, isAddon } from "../src/settings";
|
2
|
-
|
3
|
-
describe("Device Type Detection", () => {
|
4
|
-
describe("isDimmable", () => {
|
5
|
-
const testCases = [
|
6
|
-
{ model: "DIM-01", expected: true },
|
7
|
-
{ model: "DIM-02", expected: true },
|
8
|
-
{ model: "LED-10", expected: true },
|
9
|
-
{ model: "DIM-01-2P", expected: true },
|
10
|
-
{ model: "LED-75", expected: true },
|
11
|
-
{ model: "DIM-02-LC 2024 Q2", expected: true },
|
12
|
-
{ model: "Dim 2.2.1 Release Candidate", expected: true },
|
13
|
-
{ model: "RTR-01", expected: false },
|
14
|
-
{ model: "WPH-01", expected: false },
|
15
|
-
{ model: "UNKNOWN-MODEL", expected: false },
|
16
|
-
];
|
17
|
-
|
18
|
-
testCases.forEach(({ model, expected }) => {
|
19
|
-
it(`should identify ${model} as ${expected ? "dimmable" : "non-dimmable"}`, () => {
|
20
|
-
expect(isDimmable(model)).toBe(expected);
|
21
|
-
});
|
22
|
-
});
|
23
|
-
|
24
|
-
// Test with real-world data
|
25
|
-
const realWorldDimmers = [
|
26
|
-
"DIM-02-LC 2024 Q2",
|
27
|
-
"Dim 2.2.1 Release Candidate",
|
28
|
-
"DIM-02",
|
29
|
-
"DIM-01",
|
30
|
-
];
|
31
|
-
|
32
|
-
realWorldDimmers.forEach((model) => {
|
33
|
-
it(`should identify real-world model ${model} as dimmable`, () => {
|
34
|
-
expect(isDimmable(model)).toBe(true);
|
35
|
-
});
|
36
|
-
});
|
37
|
-
});
|
38
|
-
|
39
|
-
describe("isAddon", () => {
|
40
|
-
const testCases = [
|
41
|
-
{ model: "RTR-01", expected: true },
|
42
|
-
{ model: "WPH-01", expected: true },
|
43
|
-
{ model: "WRT-01", expected: true },
|
44
|
-
{ model: "MNT-01", expected: true },
|
45
|
-
{ model: "MNT-02", expected: true },
|
46
|
-
{ model: "GWY-01", expected: true },
|
47
|
-
{ model: "BAT-01", expected: true },
|
48
|
-
{ model: "EXT-01", expected: true },
|
49
|
-
{ model: "DIM-01", expected: false },
|
50
|
-
{ model: "UNKNOWN-MODEL", expected: false },
|
51
|
-
];
|
52
|
-
|
53
|
-
testCases.forEach(({ model, expected }) => {
|
54
|
-
it(`should identify ${model} as ${expected ? "addon" : "non-addon"}`, () => {
|
55
|
-
expect(isAddon(model)).toBe(expected);
|
56
|
-
});
|
57
|
-
});
|
58
|
-
});
|
59
|
-
});
|