@switchbot/homebridge-switchbot 5.0.0-beta.22 → 5.0.0-beta.24

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.
Files changed (66) hide show
  1. package/dist/platform-matter.d.ts.map +1 -1
  2. package/dist/platform-matter.js +71 -6
  3. package/dist/platform-matter.js.map +1 -1
  4. package/dist/test/devices-matter/baseMatterAccessory.test.d.ts.map +1 -0
  5. package/dist/{devices-matter → test/devices-matter}/baseMatterAccessory.test.js +1 -1
  6. package/dist/test/devices-matter/baseMatterAccessory.test.js.map +1 -0
  7. package/dist/test/helpers/platform-fixtures.d.ts +9 -0
  8. package/dist/test/helpers/platform-fixtures.d.ts.map +1 -0
  9. package/dist/test/helpers/platform-fixtures.js +30 -0
  10. package/dist/test/helpers/platform-fixtures.js.map +1 -0
  11. package/dist/test/platform-matter.additional.test.d.ts +2 -0
  12. package/dist/test/platform-matter.additional.test.d.ts.map +1 -0
  13. package/dist/test/platform-matter.additional.test.js +35 -0
  14. package/dist/test/platform-matter.additional.test.js.map +1 -0
  15. package/dist/test/platform-matter.bleparse.test.d.ts +2 -0
  16. package/dist/test/platform-matter.bleparse.test.d.ts.map +1 -0
  17. package/dist/test/platform-matter.bleparse.test.js +43 -0
  18. package/dist/test/platform-matter.bleparse.test.js.map +1 -0
  19. package/dist/test/platform-matter.cleanup.test.d.ts.map +1 -0
  20. package/dist/{platform-matter.cleanup.test.js → test/platform-matter.cleanup.test.js} +13 -28
  21. package/dist/test/platform-matter.cleanup.test.js.map +1 -0
  22. package/dist/test/platform-matter.keepstale.test.d.ts +2 -0
  23. package/dist/test/platform-matter.keepstale.test.d.ts.map +1 -0
  24. package/dist/test/platform-matter.keepstale.test.js +27 -0
  25. package/dist/test/platform-matter.keepstale.test.js.map +1 -0
  26. package/dist/test/platform-matter.mapping.test.d.ts.map +1 -0
  27. package/dist/{platform-matter.mapping.test.js → test/platform-matter.mapping.test.js} +16 -23
  28. package/dist/test/platform-matter.mapping.test.js.map +1 -0
  29. package/dist/test/platform-matter.openapi-mapping.test.d.ts +2 -0
  30. package/dist/test/platform-matter.openapi-mapping.test.d.ts.map +1 -0
  31. package/dist/test/platform-matter.openapi-mapping.test.js +84 -0
  32. package/dist/test/platform-matter.openapi-mapping.test.js.map +1 -0
  33. package/dist/test/platform-matter.test.d.ts.map +1 -0
  34. package/dist/{platform-matter.test.js → test/platform-matter.test.js} +9 -19
  35. package/dist/test/platform-matter.test.js.map +1 -0
  36. package/dist/test/platform-matter.unregister.test.d.ts.map +1 -0
  37. package/dist/{platform-matter.unregister.test.js → test/platform-matter.unregister.test.js} +4 -11
  38. package/dist/test/platform-matter.unregister.test.js.map +1 -0
  39. package/docs/variables/default.html +1 -1
  40. package/package.json +1 -1
  41. package/src/platform-matter.ts +64 -6
  42. package/src/{devices-matter → test/devices-matter}/baseMatterAccessory.test.ts +1 -1
  43. package/src/test/helpers/platform-fixtures.ts +33 -0
  44. package/src/test/platform-matter.additional.test.ts +44 -0
  45. package/src/test/platform-matter.bleparse.test.ts +47 -0
  46. package/src/{platform-matter.cleanup.test.ts → test/platform-matter.cleanup.test.ts} +14 -29
  47. package/src/test/platform-matter.keepstale.test.ts +37 -0
  48. package/src/{platform-matter.mapping.test.ts → test/platform-matter.mapping.test.ts} +22 -25
  49. package/src/test/platform-matter.openapi-mapping.test.ts +109 -0
  50. package/src/{platform-matter.test.ts → test/platform-matter.test.ts} +9 -20
  51. package/src/{platform-matter.unregister.test.ts → test/platform-matter.unregister.test.ts} +4 -13
  52. package/dist/devices-matter/baseMatterAccessory.test.d.ts.map +0 -1
  53. package/dist/devices-matter/baseMatterAccessory.test.js.map +0 -1
  54. package/dist/platform-matter.cleanup.test.d.ts.map +0 -1
  55. package/dist/platform-matter.cleanup.test.js.map +0 -1
  56. package/dist/platform-matter.mapping.test.d.ts.map +0 -1
  57. package/dist/platform-matter.mapping.test.js.map +0 -1
  58. package/dist/platform-matter.test.d.ts.map +0 -1
  59. package/dist/platform-matter.test.js.map +0 -1
  60. package/dist/platform-matter.unregister.test.d.ts.map +0 -1
  61. package/dist/platform-matter.unregister.test.js.map +0 -1
  62. /package/dist/{devices-matter → test/devices-matter}/baseMatterAccessory.test.d.ts +0 -0
  63. /package/dist/{platform-matter.cleanup.test.d.ts → test/platform-matter.cleanup.test.d.ts} +0 -0
  64. /package/dist/{platform-matter.mapping.test.d.ts → test/platform-matter.mapping.test.d.ts} +0 -0
  65. /package/dist/{platform-matter.test.d.ts → test/platform-matter.test.d.ts} +0 -0
  66. /package/dist/{platform-matter.unregister.test.d.ts → test/platform-matter.unregister.test.d.ts} +0 -0
@@ -0,0 +1,43 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { SwitchBotMatterPlatform } from '../platform-matter.js';
3
+ import { makeApiStub, makeLogStub } from './helpers/platform-fixtures.js';
4
+ describe('platform-matter BLE advertisement parser', () => {
5
+ it('parses extended serviceData fields correctly', () => {
6
+ const updateAccessoryState = vi.fn();
7
+ const api = makeApiStub({ updateAccessoryState });
8
+ const log = makeLogStub();
9
+ const platform = new SwitchBotMatterPlatform(log, {}, api);
10
+ const dev = { deviceId: 'DEV-TEST' };
11
+ const sd = {
12
+ temp: 22.3,
13
+ humid: 45,
14
+ pm25: 12,
15
+ pm10: 34,
16
+ voc: 120,
17
+ co2: 420,
18
+ motion: 1,
19
+ open: 0,
20
+ leak: 0,
21
+ position: 30,
22
+ fanSpeed: 75,
23
+ battery: 88,
24
+ rgb: '255:128:64',
25
+ };
26
+ const parsed = platform.parseAdvertisementForDevice(dev, sd);
27
+ expect(parsed).toBeTruthy();
28
+ expect(parsed.temperature).toBeCloseTo(22.3);
29
+ expect(parsed.humidity).toBe(45);
30
+ expect(parsed.pm25).toBe(12);
31
+ expect(parsed.pm10).toBe(34);
32
+ expect(parsed.voc).toBe(120);
33
+ expect(parsed.co2).toBe(420);
34
+ expect(parsed.motion).toBeTruthy();
35
+ expect(parsed.contact).toBeDefined();
36
+ expect(parsed.leak).toBeFalsy();
37
+ expect(parsed.position).toBe(30);
38
+ expect(parsed.fanSpeed).toBe(75);
39
+ expect(parsed.battery).toBe(88);
40
+ expect(parsed.color).toEqual({ r: 255, g: 128, b: 64 });
41
+ });
42
+ });
43
+ //# sourceMappingURL=platform-matter.bleparse.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-matter.bleparse.test.js","sourceRoot":"","sources":["../../src/test/platform-matter.bleparse.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAEjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AAC/D,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAA;AAEzE,QAAQ,CAAC,0CAA0C,EAAE,GAAG,EAAE;IACxD,EAAE,CAAC,8CAA8C,EAAE,GAAG,EAAE;QACtD,MAAM,oBAAoB,GAAG,EAAE,CAAC,EAAE,EAAE,CAAA;QACpC,MAAM,GAAG,GAAQ,WAAW,CAAC,EAAE,oBAAoB,EAAE,CAAC,CAAA;QAEtD,MAAM,GAAG,GAAQ,WAAW,EAAE,CAAA;QAC9B,MAAM,QAAQ,GAAG,IAAI,uBAAuB,CAAC,GAAU,EAAE,EAAS,EAAE,GAAG,CAAC,CAAA;QAExE,MAAM,GAAG,GAAQ,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAA;QACzC,MAAM,EAAE,GAAG;YACT,IAAI,EAAE,IAAI;YACV,KAAK,EAAE,EAAE;YACT,IAAI,EAAE,EAAE;YACR,IAAI,EAAE,EAAE;YACR,GAAG,EAAE,GAAG;YACR,GAAG,EAAE,GAAG;YACR,MAAM,EAAE,CAAC;YACT,IAAI,EAAE,CAAC;YACP,IAAI,EAAE,CAAC;YACP,QAAQ,EAAE,EAAE;YACZ,QAAQ,EAAE,EAAE;YACZ,OAAO,EAAE,EAAE;YACX,GAAG,EAAE,YAAY;SAClB,CAAA;QAED,MAAM,MAAM,GAAI,QAAgB,CAAC,2BAA2B,CAAC,GAAG,EAAE,EAAE,CAAC,CAAA;QACrE,MAAM,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,CAAA;QAC3B,MAAM,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,WAAW,CAAC,IAAI,CAAC,CAAA;QAC5C,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAChC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAC5B,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAC5B,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC5B,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAC5B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,CAAA;QAClC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAA;QACpC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,CAAA;QAC/B,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAChC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAChC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAC/B,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,CAAA;IACzD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-matter.cleanup.test.d.ts","sourceRoot":"","sources":["../../src/test/platform-matter.cleanup.test.ts"],"names":[],"mappings":""}
@@ -1,23 +1,16 @@
1
1
  import { describe, expect, it, vi } from 'vitest';
2
- import { SwitchBotMatterPlatform } from './platform-matter.js';
3
- import { formatDeviceIdAsMac } from './utils.js';
2
+ import { SwitchBotMatterPlatform } from '../platform-matter.js';
3
+ import { formatDeviceIdAsMac } from '../utils.js';
4
+ import { makeApiStub, makeLogStub } from './helpers/platform-fixtures.js';
4
5
  describe('platform-matter lifecycle cleanup', () => {
5
6
  it('clearDeviceResources removes timers, instances and BLE handler entries', async () => {
6
7
  // Setup stubbed API and logs
7
8
  const handlers = {};
8
- const api = {
9
- matter: {
10
- uuid: { generate: (s) => `uuid-${s}` },
11
- registerPlatformAccessories: vi.fn(),
12
- unregisterPlatformAccessories: vi.fn(),
13
- clusterNames: { OnOff: 'OnOff' },
14
- },
15
- isMatterAvailable: () => true,
16
- isMatterEnabled: () => true,
17
- on: (ev, fn) => { handlers[ev] = fn; },
18
- _handlers: handlers,
19
- };
20
- const log = { info: vi.fn(), debug: vi.fn(), warn: vi.fn(), error: vi.fn(), success: vi.fn() };
9
+ const api = makeApiStub({ registerPlatformAccessories: vi.fn(), unregisterPlatformAccessories: vi.fn(), clusterNames: { OnOff: 'OnOff' } });
10
+ api._handlers = handlers;
11
+ // keep api.on as a single-statement arrow to satisfy lint
12
+ api.on = (ev, fn) => (handlers[ev] = fn);
13
+ const log = makeLogStub();
21
14
  const platform = new SwitchBotMatterPlatform(log, {}, api);
22
15
  // Insert a fake timer, accessory instance, and BLE handler
23
16
  const deviceId = 'AA:BB:CC:11:22:33';
@@ -39,19 +32,11 @@ describe('platform-matter lifecycle cleanup', () => {
39
32
  it('shutdown handler clears all timers and handlers when invoked', async () => {
40
33
  // Setup stubbed API and logs
41
34
  const handlers = {};
42
- const api = {
43
- matter: {
44
- uuid: { generate: (s) => `uuid-${s}` },
45
- registerPlatformAccessories: vi.fn(),
46
- unregisterPlatformAccessories: vi.fn(),
47
- clusterNames: { OnOff: 'OnOff' },
48
- },
49
- isMatterAvailable: () => true,
50
- isMatterEnabled: () => true,
51
- on: (ev, fn) => { handlers[ev] = fn; },
52
- _handlers: handlers,
53
- };
54
- const log = { info: vi.fn(), debug: vi.fn(), warn: vi.fn(), error: vi.fn(), success: vi.fn() };
35
+ const api = makeApiStub({ registerPlatformAccessories: vi.fn(), unregisterPlatformAccessories: vi.fn(), clusterNames: { OnOff: 'OnOff' } });
36
+ api._handlers = handlers;
37
+ // keep api.on as a single-statement arrow to satisfy lint
38
+ api.on = (ev, fn) => (handlers[ev] = fn);
39
+ const log = makeLogStub();
55
40
  const platform = new SwitchBotMatterPlatform(log, {}, api);
56
41
  // Add two timers to the platform (using normalized ids)
57
42
  const ids = ['devA', 'devB'];
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-matter.cleanup.test.js","sourceRoot":"","sources":["../../src/test/platform-matter.cleanup.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=platform-matter.keepstale.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-matter.keepstale.test.d.ts","sourceRoot":"","sources":["../../src/test/platform-matter.keepstale.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,27 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { SwitchBotMatterPlatform } from '../platform-matter.js';
3
+ import { makeApiStub, makeLogStub } from './helpers/platform-fixtures.js';
4
+ describe('keepStaleAccessories config flag behavior', () => {
5
+ it('keeps previously-registered accessories when options.keepStaleAccessories=true', async () => {
6
+ const unregister = vi.fn();
7
+ const register = vi.fn();
8
+ const api = makeApiStub({ unregisterPlatformAccessories: unregister, registerPlatformAccessories: register });
9
+ const log = makeLogStub();
10
+ // Create platform with keepStaleAccessories = true
11
+ const platform = new SwitchBotMatterPlatform(log, { options: { keepStaleAccessories: true } }, api);
12
+ platform.discoveredDevices = [{ deviceId: 'DEV1', deviceType: 'Plug', deviceName: 'Device 1' }];
13
+ // Insert a stale accessory into matterAccessories
14
+ const staleUuid = api.matter.uuid.generate('stale-device');
15
+ const staleAcc = { uuid: staleUuid, displayName: 'Stale', context: { deviceId: 'STALE_DEVICE' } };
16
+ platform.matterAccessories.set(staleUuid, staleAcc);
17
+ // Mock createAccessoryFromDevice to return a simple accessory for DEV1
18
+ vi.spyOn(platform, 'createAccessoryFromDevice').mockResolvedValue({ displayName: 'Device 1', uuid: 'uuid-DEV1', context: { deviceId: 'DEV1' } });
19
+ // Run registration which includes stale-removal logic
20
+ await platform.registerMatterAccessories();
21
+ // Expect unregister NOT called (we kept stale accessory)
22
+ expect(unregister).not.toHaveBeenCalled();
23
+ // Stale accessory should still be present in matterAccessories
24
+ expect(platform.matterAccessories.get(staleUuid)).toBeDefined();
25
+ });
26
+ });
27
+ //# sourceMappingURL=platform-matter.keepstale.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-matter.keepstale.test.js","sourceRoot":"","sources":["../../src/test/platform-matter.keepstale.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAEjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AAC/D,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAA;AAEzE,QAAQ,CAAC,2CAA2C,EAAE,GAAG,EAAE;IACzD,EAAE,CAAC,gFAAgF,EAAE,KAAK,IAAI,EAAE;QAC9F,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,EAAE,CAAA;QAC1B,MAAM,QAAQ,GAAG,EAAE,CAAC,EAAE,EAAE,CAAA;QACxB,MAAM,GAAG,GAAQ,WAAW,CAAC,EAAE,6BAA6B,EAAE,UAAU,EAAE,2BAA2B,EAAE,QAAQ,EAAE,CAAC,CAAA;QAElH,MAAM,GAAG,GAAQ,WAAW,EAAE,CAAA;QAE9B,mDAAmD;QACnD,MAAM,QAAQ,GAAG,IAAI,uBAAuB,CAAC,GAAU,EAAE,EAAE,OAAO,EAAE,EAAE,oBAAoB,EAAE,IAAI,EAAE,EAAS,EAAE,GAAG,CAAC,CAGhH;QAAC,QAAgB,CAAC,iBAAiB,GAAG,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,EAAE,CAAC,CAAA;QAEzG,kDAAkD;QAClD,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAA;QAC1D,MAAM,QAAQ,GAAQ,EAAE,IAAI,EAAE,SAAS,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,cAAc,EAAE,EAAE,CACrG;QAAC,QAAgB,CAAC,iBAAiB,CAAC,GAAG,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;QAE7D,uEAAuE;QACvE,EAAE,CAAC,KAAK,CAAC,QAAe,EAAE,2BAA2B,CAAC,CAAC,iBAAiB,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAS,CAAC,CAAA;QAE9J,sDAAsD;QACtD,MAAO,QAAgB,CAAC,yBAAyB,EAAE,CAAA;QAEnD,yDAAyD;QACzD,MAAM,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAA;QAEzC,+DAA+D;QAC/D,MAAM,CAAE,QAAgB,CAAC,iBAAiB,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,EAAE,CAAA;IAC1E,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-matter.mapping.test.d.ts","sourceRoot":"","sources":["../../src/test/platform-matter.mapping.test.ts"],"names":[],"mappings":""}
@@ -1,19 +1,11 @@
1
1
  import { describe, expect, it, vi } from 'vitest';
2
- import { SwitchBotMatterPlatform } from './platform-matter.js';
2
+ import { SwitchBotMatterPlatform } from '../platform-matter.js';
3
+ import { makeApiStub, makeLogStub } from './helpers/platform-fixtures.js';
3
4
  describe('platform-matter mapping helper', () => {
4
5
  it('prefers accessory instance update methods for battery and falls back to api.matter.updateAccessoryState', async () => {
5
6
  const updateAccessoryState = vi.fn();
6
- const api = {
7
- matter: {
8
- uuid: { generate: (s) => `uuid-${s}` },
9
- updateAccessoryState,
10
- clusterNames: { OnOff: 'OnOff', LevelControl: 'LevelControl', ColorControl: 'ColorControl', PowerSource: 'powerSource' },
11
- },
12
- isMatterAvailable: () => true,
13
- isMatterEnabled: () => true,
14
- on: () => { },
15
- };
16
- const log = { info: vi.fn(), warn: vi.fn(), debug: vi.fn(), error: vi.fn() };
7
+ const api = makeApiStub({ updateAccessoryState, clusterNames: { OnOff: 'OnOff', LevelControl: 'LevelControl', ColorControl: 'ColorControl', PowerSource: 'powerSource' } });
8
+ const log = makeLogStub();
17
9
  const platform = new SwitchBotMatterPlatform(log, {}, api);
18
10
  // Create a fake accessory instance with updateBatteryPercentage
19
11
  const deviceId = 'DEV123';
@@ -29,22 +21,23 @@ describe('platform-matter mapping helper', () => {
29
21
  });
30
22
  it('handles temperature and humidity synonyms', async () => {
31
23
  const updateAccessoryState = vi.fn();
32
- const api = {
33
- matter: {
34
- uuid: { generate: (s) => `uuid-${s}` },
35
- updateAccessoryState,
36
- clusterNames: {},
37
- },
38
- isMatterAvailable: () => true,
39
- isMatterEnabled: () => true,
40
- on: () => { },
41
- };
42
- const log = { info: vi.fn(), warn: vi.fn(), debug: vi.fn(), error: vi.fn() };
24
+ const api = makeApiStub({ updateAccessoryState });
25
+ const log = makeLogStub();
43
26
  const platform = new SwitchBotMatterPlatform(log, {}, api);
44
27
  const deviceId = 'DEV-TEMP';
45
28
  await platform.applyStatusToAccessory('uuid-temp', { deviceId }, { temp: 21.5, humid: 48 });
46
29
  // Expect updateAccessoryState to have been called for temperature and humidity
47
30
  expect(updateAccessoryState).toHaveBeenCalled();
48
31
  });
32
+ it('applies VOC and PM10 mappings when present', async () => {
33
+ const updateAccessoryState = vi.fn();
34
+ const api = makeApiStub({ updateAccessoryState });
35
+ const log = makeLogStub();
36
+ const platform = new SwitchBotMatterPlatform(log, {}, api);
37
+ const deviceId = 'DEV-AQ';
38
+ await platform.applyStatusToAccessory('uuid-aq', { deviceId }, { voc: 123, pm10: 56 });
39
+ // Expect updateAccessoryState (or safeUpdate fallback) to have been called for voc and pm10
40
+ expect(updateAccessoryState).toHaveBeenCalled();
41
+ });
49
42
  });
50
43
  //# sourceMappingURL=platform-matter.mapping.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-matter.mapping.test.js","sourceRoot":"","sources":["../../src/test/platform-matter.mapping.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=platform-matter.openapi-mapping.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-matter.openapi-mapping.test.d.ts","sourceRoot":"","sources":["../../src/test/platform-matter.openapi-mapping.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,84 @@
1
+ import { describe, expect, it, vi } from 'vitest';
2
+ import { SwitchBotMatterPlatform } from '../platform-matter.js';
3
+ import { makeApiStub, makeLogStub } from './helpers/platform-fixtures.js';
4
+ describe('platform-matter OpenAPI -> Matter mapping', () => {
5
+ it('maps light OpenAPI status (on/off, brightness, color, battery) to accessory instance helpers', async () => {
6
+ const api = makeApiStub();
7
+ const log = makeLogStub();
8
+ const platform = new SwitchBotMatterPlatform(log, {}, api);
9
+ const deviceId = 'LIGHT-1';
10
+ const nid = platform.normalizeDeviceId(deviceId);
11
+ const instance = {
12
+ updateOnOffState: vi.fn(),
13
+ updateBrightness: vi.fn(),
14
+ updateHueSaturation: vi.fn(),
15
+ updateBatteryPercentage: vi.fn(),
16
+ };
17
+ platform.accessoryInstances.set(nid, instance);
18
+ const status = { power: true, brightness: 80, color: '255:128:64', battery: 92 };
19
+ await platform.applyStatusToAccessory('uuid-light', { deviceId }, status);
20
+ expect(instance.updateOnOffState).toHaveBeenCalled();
21
+ expect(instance.updateBrightness).toHaveBeenCalled();
22
+ expect(instance.updateHueSaturation).toHaveBeenCalled();
23
+ expect(instance.updateBatteryPercentage).toHaveBeenCalled();
24
+ });
25
+ it('maps MeterPro OpenAPI status (temp, humid, co2, pm25, voc) to accessory instance helpers', async () => {
26
+ const api = makeApiStub();
27
+ const log = makeLogStub();
28
+ const platform = new SwitchBotMatterPlatform(log, {}, api);
29
+ const deviceId = 'METERPRO-1';
30
+ const nid = platform.normalizeDeviceId(deviceId);
31
+ const instance = {
32
+ updateTemperature: vi.fn(),
33
+ updateHumidity: vi.fn(),
34
+ updateCO2: vi.fn(),
35
+ updatePM25: vi.fn(),
36
+ updateVOC: vi.fn(),
37
+ };
38
+ platform.accessoryInstances.set(nid, instance);
39
+ const status = { temp: 21.4, humid: 45, co2: 410, pm25: 12, voc: 85 };
40
+ await platform.applyStatusToAccessory('uuid-meter', { deviceId }, status);
41
+ expect(instance.updateTemperature).toHaveBeenCalled();
42
+ expect(instance.updateHumidity).toHaveBeenCalled();
43
+ expect(instance.updateCO2).toHaveBeenCalled();
44
+ expect(instance.updatePM25).toHaveBeenCalled();
45
+ expect(instance.updateVOC).toHaveBeenCalled();
46
+ });
47
+ it('maps lock OpenAPI status to lock helper', async () => {
48
+ const api = makeApiStub();
49
+ const log = makeLogStub();
50
+ const platform = new SwitchBotMatterPlatform(log, {}, api);
51
+ const deviceId = 'LOCK-1';
52
+ const nid = platform.normalizeDeviceId(deviceId);
53
+ const instance = { updateLockState: vi.fn() };
54
+ platform.accessoryInstances.set(nid, instance);
55
+ const status = { lock: true };
56
+ await platform.applyStatusToAccessory('uuid-lock', { deviceId }, status);
57
+ expect(instance.updateLockState).toHaveBeenCalled();
58
+ });
59
+ it('maps curtain position synonyms to lift position helper', async () => {
60
+ const api = makeApiStub();
61
+ const log = makeLogStub();
62
+ const platform = new SwitchBotMatterPlatform(log, {}, api);
63
+ const deviceId = 'CURTAIN-1';
64
+ const nid = platform.normalizeDeviceId(deviceId);
65
+ const instance = { updateLiftPosition: vi.fn() };
66
+ platform.accessoryInstances.set(nid, instance);
67
+ await platform.applyStatusToAccessory('uuid-cur', { deviceId, deviceType: 'Curtain' }, { position: 25 });
68
+ await platform.applyStatusToAccessory('uuid-cur', { deviceId, deviceType: 'Curtain' }, { slidePosition: 75 });
69
+ expect(instance.updateLiftPosition).toHaveBeenCalled();
70
+ });
71
+ it('maps robot vacuum run state / on to updateRunMode or updateOperationalState', async () => {
72
+ const api = makeApiStub();
73
+ const log = makeLogStub();
74
+ const platform = new SwitchBotMatterPlatform(log, {}, api);
75
+ const deviceId = 'RVC-1';
76
+ const nid = platform.normalizeDeviceId(deviceId);
77
+ const instance = { updateRunMode: vi.fn(), updateOperationalState: vi.fn() };
78
+ platform.accessoryInstances.set(nid, instance);
79
+ await platform.applyStatusToAccessory('uuid-rvc', { deviceId, deviceType: 'K10+' }, { runState: 'cleaning', power: true });
80
+ const calls = (instance.updateRunMode.mock?.calls?.length || 0) + (instance.updateOperationalState.mock?.calls?.length || 0);
81
+ expect(calls).toBeGreaterThan(0);
82
+ });
83
+ });
84
+ //# sourceMappingURL=platform-matter.openapi-mapping.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-matter.openapi-mapping.test.js","sourceRoot":"","sources":["../../src/test/platform-matter.openapi-mapping.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-matter.test.d.ts","sourceRoot":"","sources":["../../src/test/platform-matter.test.ts"],"names":[],"mappings":""}
@@ -1,26 +1,16 @@
1
1
  import { describe, expect, it, vi } from 'vitest';
2
- import { SwitchBotMatterPlatform } from './platform-matter.js';
3
- import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js';
2
+ import { SwitchBotMatterPlatform } from '../platform-matter.js';
3
+ import { PLATFORM_NAME, PLUGIN_NAME } from '../settings.js';
4
+ import { makeApiStub, makeLogStub } from './helpers/platform-fixtures.js';
4
5
  describe('platform-matter discovered devices', () => {
5
6
  it('uses discovered devices and registers them (platform + robotic)', async () => {
6
7
  const mockRegister = vi.fn();
7
- const api = {
8
- matter: {
9
- uuid: { generate: (s) => `uuid-${s}` },
10
- registerPlatformAccessories: mockRegister,
11
- clusterNames: { OnOff: 'OnOff', LevelControl: 'LevelControl', ColorControl: 'ColorControl' },
12
- deviceTypes: { RoboticVacuumCleaner: 'rvc' },
13
- },
14
- isMatterAvailable: () => true,
15
- isMatterEnabled: () => true,
16
- on: () => { },
17
- };
18
- const log = {
19
- info: vi.fn(),
20
- warn: vi.fn(),
21
- debug: vi.fn(),
22
- error: vi.fn(),
23
- };
8
+ const api = makeApiStub({
9
+ registerPlatformAccessories: mockRegister,
10
+ clusterNames: { OnOff: 'OnOff', LevelControl: 'LevelControl', ColorControl: 'ColorControl' },
11
+ deviceTypes: { RoboticVacuumCleaner: 'rvc' },
12
+ });
13
+ const log = makeLogStub();
24
14
  const config = {};
25
15
  const platform = new SwitchBotMatterPlatform(log, config, api);
26
16
  platform.discoveredDevices = [
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-matter.test.js","sourceRoot":"","sources":["../../src/test/platform-matter.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-matter.unregister.test.d.ts","sourceRoot":"","sources":["../../src/test/platform-matter.unregister.test.ts"],"names":[],"mappings":""}
@@ -1,19 +1,12 @@
1
1
  import { describe, expect, it, vi } from 'vitest';
2
- import { SwitchBotMatterPlatform } from './platform-matter.js';
2
+ import { SwitchBotMatterPlatform } from '../platform-matter.js';
3
+ import { makeApiStub, makeLogStub } from './helpers/platform-fixtures.js';
3
4
  describe('removeDisabledAccessories and unregister edge cases', () => {
4
5
  it('clears resources and unregisters accessory even with invalid timer and non-MAC deviceId', async () => {
5
6
  // Prepare API stub
6
7
  const unregister = vi.fn();
7
- const api = {
8
- matter: {
9
- uuid: { generate: (s) => `uuid-${s}` },
10
- unregisterPlatformAccessories: unregister,
11
- },
12
- isMatterAvailable: () => true,
13
- isMatterEnabled: () => true,
14
- on: () => { },
15
- };
16
- const log = { info: vi.fn(), warn: vi.fn(), debug: vi.fn(), error: vi.fn(), success: vi.fn() };
8
+ const api = makeApiStub({ unregisterPlatformAccessories: unregister });
9
+ const log = makeLogStub();
17
10
  const platform = new SwitchBotMatterPlatform(log, { enableOnOffLight: false }, api);
18
11
  // Build a fake serialized accessory matching the generated UUID for OnOff Light
19
12
  const uuid = api.matter.uuid.generate('matter-onoff-light');
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform-matter.unregister.test.js","sourceRoot":"","sources":["../../src/test/platform-matter.unregister.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,QAAQ,CAAA;AAEjD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AAC/D,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAA;AAEzE,QAAQ,CAAC,qDAAqD,EAAE,GAAG,EAAE;IACnE,EAAE,CAAC,yFAAyF,EAAE,KAAK,IAAI,EAAE;QACvG,mBAAmB;QACnB,MAAM,UAAU,GAAG,EAAE,CAAC,EAAE,EAAE,CAAA;QAC1B,MAAM,GAAG,GAAQ,WAAW,CAAC,EAAE,6BAA6B,EAAE,UAAU,EAAE,CAAC,CAAA;QAC3E,MAAM,GAAG,GAAQ,WAAW,EAAE,CAAA;QAC9B,MAAM,QAAQ,GAAG,IAAI,uBAAuB,CAAC,GAAU,EAAE,EAAE,gBAAgB,EAAE,KAAK,EAAS,EAAE,GAAG,CAAC,CAAA;QAEjG,gFAAgF;QAChF,MAAM,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAA;QAC3D,MAAM,SAAS,GAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,aAAa,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,CAAA;QAE/F,wEAAwE;QACxE,MAAM,GAAG,GAAI,QAAgB,CAAC,iBAAiB,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAC1E;QAAC,QAAgB,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,IAAW,CAAC,CACrD;QAAC,QAAgB,CAAC,kBAAkB,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAG9D;QAAC,QAAgB,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;QAEzD,8BAA8B;QAC9B,MAAM,QAAQ,GAAG,EAAE,CAAC,KAAK,CAAC,QAAe,EAAE,sBAAsB,CAAC,CAAA;QAElE,0CAA0C;QAC1C,MAAO,QAAgB,CAAC,yBAAyB,EAAE,CAAA;QAEnD,6DAA6D;QAC7D,MAAM,CAAC,UAAU,CAAC,CAAC,gBAAgB,EAAE,CAAA;QACrC,MAAM,CAAE,QAAgB,CAAC,iBAAiB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,EAAE,CAAA;QAErE,2EAA2E;QAC3E,MAAM,CAAC,QAAQ,CAAC,CAAC,oBAAoB,CAAC,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IACnE,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -1 +1 @@
1
- <!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>default | @switchbot/homebridge-switchbot</title><meta name="description" content="Documentation for @switchbot/homebridge-switchbot"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">@switchbot/homebridge-switchbot</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="" aria-current="page">default</a></li></ul><h1>Variable default</h1></div><div class="tsd-signature"><span class="tsd-kind-variable">default</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span> <span class="tsd-signature-symbol">=&gt;</span> <span class="tsd-signature-type">void</span></div><div class="tsd-type-declaration"><h4>Type Declaration</h4><ul class="tsd-parameters"><li class="tsd-parameter-signature"><ul class="tsd-signatures"><li class="tsd-signature" id="__type"><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">void</span></li><li class="tsd-description"><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">api</span>: <span class="tsd-signature-type">API</span></span></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4></li></ul></li></ul></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/OpenWonderLabs/homebridge-switchbot/blob/576df990204f81d3133d394c440084009081ab15/src/index.ts#L13">index.ts:13</a></li></ul></aside></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">@switchbot/homebridge-switchbot</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer></footer><div class="overlay"></div></body></html>
1
+ <!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>default | @switchbot/homebridge-switchbot</title><meta name="description" content="Documentation for @switchbot/homebridge-switchbot"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">@switchbot/homebridge-switchbot</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="" aria-current="page">default</a></li></ul><h1>Variable default</h1></div><div class="tsd-signature"><span class="tsd-kind-variable">default</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span> <span class="tsd-signature-symbol">=&gt;</span> <span class="tsd-signature-type">void</span></div><div class="tsd-type-declaration"><h4>Type Declaration</h4><ul class="tsd-parameters"><li class="tsd-parameter-signature"><ul class="tsd-signatures"><li class="tsd-signature" id="__type"><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">void</span></li><li class="tsd-description"><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">api</span>: <span class="tsd-signature-type">API</span></span></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4></li></ul></li></ul></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/OpenWonderLabs/homebridge-switchbot/blob/01dadecbae96cbcec5c8d3103de61e6cd1c65274/src/index.ts#L13">index.ts:13</a></li></ul></aside></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">@switchbot/homebridge-switchbot</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer></footer><div class="overlay"></div></body></html>
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@switchbot/homebridge-switchbot",
3
3
  "displayName": "SwitchBot",
4
4
  "type": "module",
5
- "version": "5.0.0-beta.22",
5
+ "version": "5.0.0-beta.24",
6
6
  "description": "The SwitchBot plugin allows you to access your SwitchBot device(s) from HomeKit.",
7
7
  "author": "SwitchBot <support@wondertechlabs.com> (https://github.com/SwitchBot)",
8
8
  "contributors": [
@@ -660,6 +660,12 @@ export class SwitchBotMatterPlatform implements DynamicPlatformPlugin {
660
660
  // First try model-specific / normalized parsing of BLE advertisement
661
661
  try {
662
662
  const parsed = this.parseAdvertisementForDevice(dev, serviceData)
663
+ try {
664
+ const _p = JSON.stringify(parsed)
665
+ this.debugLog(`BLE advertisement parsed for ${dev.deviceId}: ${_p}`)
666
+ } catch (e) {
667
+ this.debugLog(`BLE advertisement parsed for ${dev.deviceId}: [unstringifiable parse result]`)
668
+ }
663
669
  if (parsed) {
664
670
  // Power
665
671
  if (parsed.power !== undefined) {
@@ -821,11 +827,17 @@ export class SwitchBotMatterPlatform implements DynamicPlatformPlugin {
821
827
  }
822
828
  try {
823
829
  const { response, statusCode } = await this.switchBotAPI.getDeviceStatus(dev.deviceId, this.config.credentials?.token, this.config.credentials?.secret)
830
+ const respAny: any = response
831
+ const body = respAny?.body ?? respAny
832
+ try {
833
+ const s = JSON.stringify(body)
834
+ this.debugLog(`OpenAPI getDeviceStatus for ${dev.deviceId} returned statusCode=${statusCode} body=${s}`)
835
+ } catch (e) {
836
+ this.debugLog(`OpenAPI getDeviceStatus for ${dev.deviceId} returned statusCode=${statusCode} (body not stringifiable)`)
837
+ }
824
838
  if (!(statusCode === 100 || statusCode === 200)) {
825
839
  return
826
840
  }
827
- const respAny: any = response
828
- const body = respAny?.body ?? respAny
829
841
  const status = body?.status ?? body
830
842
 
831
843
  // Use centralized mapper which prefers accessory instance update helpers
@@ -854,9 +866,15 @@ export class SwitchBotMatterPlatform implements DynamicPlatformPlugin {
854
866
  ;(async () => {
855
867
  try {
856
868
  const { response, statusCode } = await this.switchBotAPI!.getDeviceStatus(dev.deviceId, this.config.credentials?.token, this.config.credentials?.secret)
869
+ const respAny: any = response
870
+ const body = respAny?.body ?? respAny
871
+ try {
872
+ const s = JSON.stringify(body)
873
+ this.debugLog(`Initial OpenAPI refresh for ${dev.deviceId} returned statusCode=${statusCode} body=${s}`)
874
+ } catch (e) {
875
+ this.debugLog(`Initial OpenAPI refresh for ${dev.deviceId} returned statusCode=${statusCode} (body not stringifiable)`)
876
+ }
857
877
  if (statusCode === 100 || statusCode === 200) {
858
- const respAny: any = response
859
- const body = respAny?.body ?? respAny
860
878
  const status = body?.status ?? body
861
879
  await this.applyStatusToAccessory(uuid, dev, status)
862
880
  }
@@ -868,9 +886,15 @@ export class SwitchBotMatterPlatform implements DynamicPlatformPlugin {
868
886
  const timer = setInterval(async () => {
869
887
  try {
870
888
  const { response, statusCode } = await this.switchBotAPI!.getDeviceStatus(dev.deviceId, this.config.credentials?.token, this.config.credentials?.secret)
889
+ const respAny: any = response
890
+ const body = respAny?.body ?? respAny
891
+ try {
892
+ const s = JSON.stringify(body)
893
+ this.debugLog(`Periodic OpenAPI refresh for ${dev.deviceId} returned statusCode=${statusCode} body=${s}`)
894
+ } catch (e) {
895
+ this.debugLog(`Periodic OpenAPI refresh for ${dev.deviceId} returned statusCode=${statusCode} (body not stringifiable)`)
896
+ }
871
897
  if (statusCode === 100 || statusCode === 200) {
872
- const respAny: any = response
873
- const body = respAny?.body ?? respAny
874
898
  const status = body?.status ?? body
875
899
  await this.applyStatusToAccessory(uuid, dev, status)
876
900
  }
@@ -1125,6 +1149,40 @@ export class SwitchBotMatterPlatform implements DynamicPlatformPlugin {
1125
1149
  await safeUpdate(this.api.matter.clusterNames.OnOff, { onOff: on }, 'updateOnOffState')
1126
1150
  }
1127
1151
 
1152
+ // Robot vacuum: some OpenAPI responses use 'runState' or similar textual
1153
+ // fields to indicate cleaning/mapping/idle. Map common textual values to
1154
+ // the numeric run mode values expected by the RoboticVacuumAccessory and
1155
+ // prefer calling accessory helpers when present.
1156
+ if (status?.runState !== undefined || status?.run_state !== undefined || status?.run !== undefined) {
1157
+ try {
1158
+ const raw = status?.runState ?? status?.run_state ?? status?.run
1159
+ let mode: number | undefined
1160
+ if (typeof raw === 'number') {
1161
+ mode = Number(raw)
1162
+ } else if (typeof raw === 'string') {
1163
+ const s = raw.toLowerCase()
1164
+ if (s.includes('clean')) {
1165
+ mode = 1 // Cleaning
1166
+ } else if (s.includes('map')) {
1167
+ mode = 2 // Mapping
1168
+ } else if (s.includes('idle') || s.includes('stop') || s.includes('dock') || s.includes('charge') || s.includes('docked')) {
1169
+ mode = 0 // Idle
1170
+ } else {
1171
+ const n = Number(raw)
1172
+ if (!Number.isNaN(n)) {
1173
+ mode = n
1174
+ }
1175
+ }
1176
+ }
1177
+
1178
+ if (mode !== undefined) {
1179
+ await safeUpdate('rvcRunMode', { currentMode: Number(mode) }, 'updateRunMode')
1180
+ }
1181
+ } catch (e: any) {
1182
+ this.debugLog(`Failed to apply runState for ${dev.deviceId}: ${e?.message ?? e}`)
1183
+ }
1184
+ }
1185
+
1128
1186
  // Brightness
1129
1187
  if (status?.brightness !== undefined) {
1130
1188
  const level = Math.round((Number(status.brightness) / 100) * 254)
@@ -1,6 +1,6 @@
1
1
  import { describe, expect, it, vi } from 'vitest'
2
2
 
3
- import { BaseMatterAccessory } from './BaseMatterAccessory.js'
3
+ import { BaseMatterAccessory } from '../../devices-matter/BaseMatterAccessory.js'
4
4
 
5
5
  // Minimal concrete subclass for testing
6
6
  class TestAccessory extends BaseMatterAccessory {