node-switchbot 2.5.0-beta.32 → 2.5.0-beta.33

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 (104) hide show
  1. package/dist/advertising.d.ts +3 -3
  2. package/dist/advertising.d.ts.map +1 -1
  3. package/dist/advertising.js +26 -25
  4. package/dist/advertising.js.map +1 -1
  5. package/dist/device/woblindtilt.d.ts +3 -4
  6. package/dist/device/woblindtilt.d.ts.map +1 -1
  7. package/dist/device/woblindtilt.js +7 -3
  8. package/dist/device/woblindtilt.js.map +1 -1
  9. package/dist/device/wobulb.d.ts +2 -3
  10. package/dist/device/wobulb.d.ts.map +1 -1
  11. package/dist/device/wobulb.js +8 -4
  12. package/dist/device/wobulb.js.map +1 -1
  13. package/dist/device/woceilinglight.d.ts +4 -4
  14. package/dist/device/woceilinglight.d.ts.map +1 -1
  15. package/dist/device/woceilinglight.js +10 -5
  16. package/dist/device/woceilinglight.js.map +1 -1
  17. package/dist/device/wocontact.d.ts +2 -3
  18. package/dist/device/wocontact.d.ts.map +1 -1
  19. package/dist/device/wocontact.js +3 -3
  20. package/dist/device/wocontact.js.map +1 -1
  21. package/dist/device/wocurtain.d.ts +2 -3
  22. package/dist/device/wocurtain.d.ts.map +1 -1
  23. package/dist/device/wocurtain.js +7 -3
  24. package/dist/device/wocurtain.js.map +1 -1
  25. package/dist/device/wohand.d.ts +2 -3
  26. package/dist/device/wohand.d.ts.map +1 -1
  27. package/dist/device/wohand.js +7 -3
  28. package/dist/device/wohand.js.map +1 -1
  29. package/dist/device/wohub2.d.ts +2 -3
  30. package/dist/device/wohub2.d.ts.map +1 -1
  31. package/dist/device/wohub2.js +3 -3
  32. package/dist/device/wohub2.js.map +1 -1
  33. package/dist/device/wohumi.d.ts +2 -3
  34. package/dist/device/wohumi.d.ts.map +1 -1
  35. package/dist/device/wohumi.js +7 -3
  36. package/dist/device/wohumi.js.map +1 -1
  37. package/dist/device/woiosensorth.d.ts +2 -3
  38. package/dist/device/woiosensorth.d.ts.map +1 -1
  39. package/dist/device/woiosensorth.js +4 -4
  40. package/dist/device/woiosensorth.js.map +1 -1
  41. package/dist/device/woplugmini.d.ts +5 -4
  42. package/dist/device/woplugmini.d.ts.map +1 -1
  43. package/dist/device/woplugmini.js +13 -7
  44. package/dist/device/woplugmini.js.map +1 -1
  45. package/dist/device/wopresence.d.ts +2 -3
  46. package/dist/device/wopresence.d.ts.map +1 -1
  47. package/dist/device/wopresence.js +3 -3
  48. package/dist/device/wopresence.js.map +1 -1
  49. package/dist/device/wosensorth.d.ts +4 -4
  50. package/dist/device/wosensorth.d.ts.map +1 -1
  51. package/dist/device/wosensorth.js +6 -5
  52. package/dist/device/wosensorth.js.map +1 -1
  53. package/dist/device/wosmartlock.d.ts +8 -3
  54. package/dist/device/wosmartlock.d.ts.map +1 -1
  55. package/dist/device/wosmartlock.js +9 -3
  56. package/dist/device/wosmartlock.js.map +1 -1
  57. package/dist/device/wosmartlockpro.d.ts +8 -3
  58. package/dist/device/wosmartlockpro.d.ts.map +1 -1
  59. package/dist/device/wosmartlockpro.js +9 -3
  60. package/dist/device/wosmartlockpro.js.map +1 -1
  61. package/dist/device/wostrip.d.ts +2 -3
  62. package/dist/device/wostrip.d.ts.map +1 -1
  63. package/dist/device/wostrip.js +3 -3
  64. package/dist/device/wostrip.js.map +1 -1
  65. package/dist/device.d.ts +9 -1
  66. package/dist/device.d.ts.map +1 -1
  67. package/dist/device.js +13 -2
  68. package/dist/device.js.map +1 -1
  69. package/dist/switchbot-ble.d.ts.map +1 -1
  70. package/dist/switchbot-ble.js +2 -2
  71. package/dist/switchbot-ble.js.map +1 -1
  72. package/dist/test/advertising.test.js +7 -4
  73. package/dist/test/advertising.test.js.map +1 -1
  74. package/dist/test/woblindtilt.test.js +75 -1
  75. package/dist/test/woblindtilt.test.js.map +1 -1
  76. package/dist/test/wobulb.test.js +94 -1
  77. package/dist/test/wobulb.test.js.map +1 -1
  78. package/dist/test/woceilinglight.test.js +80 -1
  79. package/dist/test/woceilinglight.test.js.map +1 -1
  80. package/dist/test/wocontact.test.js +64 -1
  81. package/dist/test/wocontact.test.js.map +1 -1
  82. package/dist/test/wocurtain.test.js +74 -1
  83. package/dist/test/wocurtain.test.js.map +1 -1
  84. package/dist/test/wohand.test.js +55 -1
  85. package/dist/test/wohand.test.js.map +1 -1
  86. package/dist/test/wohub2.test.js +79 -1
  87. package/dist/test/wohub2.test.js.map +1 -1
  88. package/dist/test/wohumi.test.js +81 -1
  89. package/dist/test/wohumi.test.js.map +1 -1
  90. package/dist/test/woiosensorth.test.js +39 -1
  91. package/dist/test/woiosensorth.test.js.map +1 -1
  92. package/dist/test/woplugmini.test.js +113 -1
  93. package/dist/test/woplugmini.test.js.map +1 -1
  94. package/dist/test/wopresence.test.js +67 -1
  95. package/dist/test/wopresence.test.js.map +1 -1
  96. package/dist/test/wosensorth.test.js +50 -1
  97. package/dist/test/wosensorth.test.js.map +1 -1
  98. package/dist/test/wosmartlock.test.js +150 -1
  99. package/dist/test/wosmartlock.test.js.map +1 -1
  100. package/dist/test/wosmartlockpro.test.js +150 -1
  101. package/dist/test/wosmartlockpro.test.js.map +1 -1
  102. package/dist/test/wostrip.test.js +101 -1
  103. package/dist/test/wostrip.test.js.map +1 -1
  104. package/package.json +1 -1
@@ -1,2 +1,40 @@
1
- export {};
1
+ import { Buffer } from 'node:buffer';
2
+ import { describe, expect, it, vi } from 'vitest';
3
+ import { WoIOSensorTH } from '../device/woiosensorth.js';
4
+ import { SwitchBotBLEModel, SwitchBotBLEModelFriendlyName, SwitchBotBLEModelName } from '../types/types.js';
5
+ describe('woIOSensorTH', () => {
6
+ describe('parseServiceData', () => {
7
+ const emitLog = vi.fn();
8
+ it('should return parsed data for valid buffers', async () => {
9
+ const serviceData = Buffer.from([0x00, 0x00, 0x64]);
10
+ const manufacturerData = Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x2A, 0x50, 0x00]);
11
+ const result = await WoIOSensorTH.parseServiceData(serviceData, manufacturerData, emitLog);
12
+ expect(result).toEqual({
13
+ model: SwitchBotBLEModel.OutdoorMeter,
14
+ modelName: SwitchBotBLEModelName.OutdoorMeter,
15
+ modelFriendlyName: SwitchBotBLEModelFriendlyName.OutdoorMeter,
16
+ celsius: 42.6,
17
+ fahrenheit: 108.7,
18
+ fahrenheit_mode: true,
19
+ humidity: 80,
20
+ battery: 100,
21
+ });
22
+ expect(emitLog).not.toHaveBeenCalled();
23
+ });
24
+ it('should return null for invalid serviceData length', async () => {
25
+ const serviceData = Buffer.from([0x00, 0x00]);
26
+ const manufacturerData = Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x2A, 0x50, 0x00]);
27
+ const result = await WoIOSensorTH.parseServiceData(serviceData, manufacturerData, emitLog);
28
+ expect(result).toBeNull();
29
+ expect(emitLog).toHaveBeenCalledWith('error', '[parseServiceDataForWoIOSensorTH] Service Data Buffer length 2 !== 3!');
30
+ });
31
+ it('should return null for invalid manufacturerData length', async () => {
32
+ const serviceData = Buffer.from([0x00, 0x00, 0x64]);
33
+ const manufacturerData = Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1E, 0x2A]);
34
+ const result = await WoIOSensorTH.parseServiceData(serviceData, manufacturerData, emitLog);
35
+ expect(result).toBeNull();
36
+ expect(emitLog).toHaveBeenCalledWith('error', '[parseServiceDataForWoIOSensorTH] Manufacturer Data Buffer length 12 !== 14!');
37
+ });
38
+ });
39
+ });
2
40
  //# sourceMappingURL=woiosensorth.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"woiosensorth.test.js","sourceRoot":"","sources":["../../src/test/woiosensorth.test.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"woiosensorth.test.js","sourceRoot":"","sources":["../../src/test/woiosensorth.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,114 @@
1
- export {};
1
+ import { Buffer } from 'node:buffer';
2
+ import sinon from 'sinon';
3
+ import { describe, expect, it } from 'vitest';
4
+ import { WoPlugMini } from '../device/woplugmini.js';
5
+ import { SwitchBotBLEModel } from '../types/types.js';
6
+ describe('woPlugMini', () => {
7
+ let emitLog;
8
+ beforeEach(() => {
9
+ emitLog = sinon.spy();
10
+ });
11
+ describe('parseServiceData_US', () => {
12
+ it('should parse valid service data for US model', async () => {
13
+ const manufacturerData = Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0]);
14
+ const result = await WoPlugMini.parseServiceData_US(manufacturerData, emitLog);
15
+ expect(result).toEqual({
16
+ model: SwitchBotBLEModel.PlugMiniUS,
17
+ modelName: 'PlugMini',
18
+ modelFriendlyName: 'PlugMini',
19
+ state: 'on',
20
+ delay: false,
21
+ timer: false,
22
+ syncUtcTime: false,
23
+ wifiRssi: 0,
24
+ overload: false,
25
+ currentPower: 0,
26
+ });
27
+ });
28
+ it('should return null for invalid service data length', async () => {
29
+ const manufacturerData = Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
30
+ const result = await WoPlugMini.parseServiceData_US(manufacturerData, emitLog);
31
+ expect(result).toBeNull();
32
+ expect(emitLog.calledWith('error', '[parseServiceDataForWoPlugMini] Buffer length 10 should be 14')).toBe(true);
33
+ });
34
+ });
35
+ describe('parseServiceData_JP', () => {
36
+ it('should parse valid service data for JP model', async () => {
37
+ const manufacturerData = Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0x80, 0, 0, 0, 0]);
38
+ const result = await WoPlugMini.parseServiceData_JP(manufacturerData, emitLog);
39
+ expect(result).toEqual({
40
+ model: SwitchBotBLEModel.PlugMiniJP,
41
+ modelName: 'PlugMini',
42
+ modelFriendlyName: 'PlugMini',
43
+ state: 'on',
44
+ delay: false,
45
+ timer: false,
46
+ syncUtcTime: false,
47
+ wifiRssi: 0,
48
+ overload: false,
49
+ currentPower: 0,
50
+ });
51
+ });
52
+ it('should return null for invalid service data length', async () => {
53
+ const manufacturerData = Buffer.from([0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
54
+ const result = await WoPlugMini.parseServiceData_JP(manufacturerData, emitLog);
55
+ expect(result).toBeNull();
56
+ expect(emitLog.calledWith('error', '[parseServiceDataForWoPlugMini] Buffer length 10 should be 14')).toBe(true);
57
+ });
58
+ });
59
+ describe('operatePlug', () => {
60
+ let woPlugMini;
61
+ let commandStub;
62
+ beforeEach(() => {
63
+ const peripheral = {};
64
+ woPlugMini = new WoPlugMini(peripheral, emitLog);
65
+ commandStub = sinon.stub(woPlugMini, 'command');
66
+ });
67
+ it('should return true when the plug is turned on', async () => {
68
+ commandStub.resolves([0x57, 0x80]);
69
+ const result = await woPlugMini.operatePlug([0x57, 0x0F, 0x51, 0x01]);
70
+ expect(result).toBe(true);
71
+ });
72
+ it('should return false when the plug is turned off', async () => {
73
+ commandStub.resolves([0x57, 0x00]);
74
+ const result = await woPlugMini.operatePlug([0x57, 0x0F, 0x51, 0x01]);
75
+ expect(result).toBe(false);
76
+ });
77
+ it('should throw an error for invalid response length', async () => {
78
+ commandStub.resolves([0x57]);
79
+ await expect(woPlugMini.operatePlug([0x57, 0x0F, 0x51, 0x01])).rejects.toThrow('Expecting a 2-byte response, got instead: 0x57');
80
+ });
81
+ it('should throw an error for invalid response code', async () => {
82
+ commandStub.resolves([0x57, 0x01]);
83
+ await expect(woPlugMini.operatePlug([0x57, 0x0F, 0x51, 0x01])).rejects.toThrow('The device returned an error: 0x5701');
84
+ });
85
+ });
86
+ describe('state operations', () => {
87
+ let woPlugMini;
88
+ let setStateStub;
89
+ beforeEach(() => {
90
+ const peripheral = {};
91
+ woPlugMini = new WoPlugMini(peripheral, emitLog);
92
+ setStateStub = sinon.stub(woPlugMini, 'setState');
93
+ });
94
+ it('should turn on the plug', async () => {
95
+ setStateStub.resolves(true);
96
+ const result = await woPlugMini.turnOn();
97
+ expect(result).toBe(true);
98
+ expect(setStateStub.calledWith([0x01, 0x80])).toBe(true);
99
+ });
100
+ it('should turn off the plug', async () => {
101
+ setStateStub.resolves(false);
102
+ const result = await woPlugMini.turnOff();
103
+ expect(result).toBe(false);
104
+ expect(setStateStub.calledWith([0x01, 0x00])).toBe(true);
105
+ });
106
+ it('should toggle the plug state', async () => {
107
+ setStateStub.resolves(true);
108
+ const result = await woPlugMini.toggle();
109
+ expect(result).toBe(true);
110
+ expect(setStateStub.calledWith([0x02, 0x80])).toBe(true);
111
+ });
112
+ });
113
+ });
2
114
  //# sourceMappingURL=woplugmini.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"woplugmini.test.js","sourceRoot":"","sources":["../../src/test/woplugmini.test.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"woplugmini.test.js","sourceRoot":"","sources":["../../src/test/woplugmini.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,68 @@
1
- export {};
1
+ import { Buffer } from 'node:buffer';
2
+ import { describe, expect, it, vi } from 'vitest';
3
+ import { WoPresence } from '../device/wopresence.js';
4
+ import { SwitchBotBLEModel, SwitchBotBLEModelFriendlyName, SwitchBotBLEModelName } from '../types/types.js';
5
+ describe('woPresence', () => {
6
+ describe('parseServiceData', () => {
7
+ const emitLog = vi.fn();
8
+ it('should return null if buffer length is not 6', async () => {
9
+ const serviceData = Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05]);
10
+ const result = await WoPresence.parseServiceData(serviceData, emitLog);
11
+ expect(result).toBeNull();
12
+ expect(emitLog).toHaveBeenCalledWith('error', '[parseServiceDataForWoPresence] Buffer length 5 !== 6!');
13
+ });
14
+ it('should parse valid service data correctly', async () => {
15
+ const serviceData = Buffer.from([0b10000000, 0b01111111, 0x00, 0x00, 0x00, 0b00101101]);
16
+ const expectedData = {
17
+ model: SwitchBotBLEModel.MotionSensor,
18
+ modelName: SwitchBotBLEModelName.MotionSensor,
19
+ modelFriendlyName: SwitchBotBLEModelFriendlyName.MotionSensor,
20
+ tested: true,
21
+ movement: false,
22
+ battery: 127,
23
+ led: 1,
24
+ iot: 1,
25
+ sense_distance: 3,
26
+ lightLevel: 'unknown',
27
+ is_light: true,
28
+ };
29
+ const result = await WoPresence.parseServiceData(serviceData, emitLog);
30
+ expect(result).toEqual(expectedData);
31
+ });
32
+ it('should handle different light levels correctly', async () => {
33
+ const serviceDataDark = Buffer.from([0b10000000, 0b01111111, 0x00, 0x00, 0x00, 0b00101100]);
34
+ const serviceDataBright = Buffer.from([0b10000000, 0b01111111, 0x00, 0x00, 0x00, 0b00101110]);
35
+ const expectedDataDark = {
36
+ model: SwitchBotBLEModel.MotionSensor,
37
+ modelName: SwitchBotBLEModelName.MotionSensor,
38
+ modelFriendlyName: SwitchBotBLEModelFriendlyName.MotionSensor,
39
+ tested: true,
40
+ movement: false,
41
+ battery: 127,
42
+ led: 1,
43
+ iot: 1,
44
+ sense_distance: 3,
45
+ lightLevel: 'dark',
46
+ is_light: false,
47
+ };
48
+ const expectedDataBright = {
49
+ model: SwitchBotBLEModel.MotionSensor,
50
+ modelName: SwitchBotBLEModelName.MotionSensor,
51
+ modelFriendlyName: SwitchBotBLEModelFriendlyName.MotionSensor,
52
+ tested: true,
53
+ movement: false,
54
+ battery: 127,
55
+ led: 1,
56
+ iot: 1,
57
+ sense_distance: 3,
58
+ lightLevel: 'bright',
59
+ is_light: true,
60
+ };
61
+ const resultDark = await WoPresence.parseServiceData(serviceDataDark, emitLog);
62
+ const resultBright = await WoPresence.parseServiceData(serviceDataBright, emitLog);
63
+ expect(resultDark).toEqual(expectedDataDark);
64
+ expect(resultBright).toEqual(expectedDataBright);
65
+ });
66
+ });
67
+ });
2
68
  //# sourceMappingURL=wopresence.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wopresence.test.js","sourceRoot":"","sources":["../../src/test/wopresence.test.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"wopresence.test.js","sourceRoot":"","sources":["../../src/test/wopresence.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,51 @@
1
- export {};
1
+ import { Buffer } from 'node:buffer';
2
+ import { WoSensorTH } from '../device/wosensorth.js';
3
+ import { SwitchBotBLEModel, SwitchBotBLEModelFriendlyName, SwitchBotBLEModelName } from '../types/types.js';
4
+ describe('woSensorTH', () => {
5
+ const emitLog = jest.fn();
6
+ describe('parseServiceData', () => {
7
+ it('should return null if buffer length is not 6', async () => {
8
+ const serviceData = Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05]);
9
+ const result = await WoSensorTH.parseServiceData(serviceData, emitLog);
10
+ expect(result).toBeNull();
11
+ expect(emitLog).toHaveBeenCalledWith('error', '[parseServiceDataForWoSensorTH] Buffer length 5 !== 6!');
12
+ });
13
+ it('should parse valid service data correctly', async () => {
14
+ const serviceData = Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]);
15
+ const result = await WoSensorTH.parseServiceData(serviceData, emitLog);
16
+ expect(result).toEqual({
17
+ model: SwitchBotBLEModel.Meter,
18
+ modelName: SwitchBotBLEModelName.Meter,
19
+ modelFriendlyName: SwitchBotBLEModelFriendlyName.Meter,
20
+ celsius: -0.4,
21
+ fahrenheit: 31.3,
22
+ fahrenheit_mode: false,
23
+ humidity: 6,
24
+ battery: 2,
25
+ });
26
+ });
27
+ });
28
+ describe('parseServiceData_Plus', () => {
29
+ it('should return null if buffer length is not 6', async () => {
30
+ const serviceData = Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05]);
31
+ const result = await WoSensorTH.parseServiceData_Plus(serviceData, emitLog);
32
+ expect(result).toBeNull();
33
+ expect(emitLog).toHaveBeenCalledWith('error', '[parseServiceDataForWoSensorTHPlus] Buffer length 5 !== 6!');
34
+ });
35
+ it('should parse valid service data correctly', async () => {
36
+ const serviceData = Buffer.from([0x01, 0x02, 0x03, 0x04, 0x05, 0x06]);
37
+ const result = await WoSensorTH.parseServiceData_Plus(serviceData, emitLog);
38
+ expect(result).toEqual({
39
+ model: SwitchBotBLEModel.MeterPlus,
40
+ modelName: SwitchBotBLEModelName.MeterPlus,
41
+ modelFriendlyName: SwitchBotBLEModelFriendlyName.MeterPlus,
42
+ celsius: -0.4,
43
+ fahrenheit: 31.3,
44
+ fahrenheit_mode: false,
45
+ humidity: 6,
46
+ battery: 2,
47
+ });
48
+ });
49
+ });
50
+ });
2
51
  //# sourceMappingURL=wosensorth.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wosensorth.test.js","sourceRoot":"","sources":["../../src/test/wosensorth.test.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"wosensorth.test.js","sourceRoot":"","sources":["../../src/test/wosensorth.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,151 @@
1
- export {};
1
+ import { Buffer } from 'node:buffer';
2
+ import { describe, expect, it, vi } from 'vitest';
3
+ import { WoSmartLock } from '../device/wosmartlock.js';
4
+ import { WoSmartLockCommands } from '../settings.js';
5
+ import { SwitchBotBLEModel, SwitchBotBLEModelFriendlyName, SwitchBotBLEModelName } from '../types/types.js';
6
+ describe('woSmartLock', () => {
7
+ let mockPeripheral;
8
+ let mockNoble;
9
+ let lock;
10
+ beforeEach(() => {
11
+ mockPeripheral = {};
12
+ mockNoble = {};
13
+ lock = new WoSmartLock(mockPeripheral, mockNoble);
14
+ });
15
+ describe('parseServiceData', () => {
16
+ it('should return null if buffer length is not 18', async () => {
17
+ const serviceData = Buffer.alloc(10);
18
+ const manufacturerData = Buffer.alloc(0);
19
+ const emitLog = vi.fn();
20
+ const result = await WoSmartLock.parseServiceData(serviceData, manufacturerData, emitLog);
21
+ expect(result).toBeNull();
22
+ expect(emitLog).toHaveBeenCalledWith('error', '[parseServiceDataForWoStrip] Buffer length 10 !== 18!');
23
+ });
24
+ it('should parse valid service data correctly', async () => {
25
+ const serviceData = Buffer.from([0, 0, 0, 255, 128, 64, 0, 129, 136, 127, 254, 0, 0, 0, 0, 0, 0, 0]);
26
+ const manufacturerData = Buffer.alloc(0);
27
+ const emitLog = vi.fn();
28
+ const result = await WoSmartLock.parseServiceData(serviceData, manufacturerData, emitLog);
29
+ const expected = {
30
+ model: SwitchBotBLEModel.Lock,
31
+ modelName: SwitchBotBLEModelName.Lock,
32
+ modelFriendlyName: SwitchBotBLEModelFriendlyName.Lock,
33
+ battery: 100,
34
+ calibration: true,
35
+ status: 'LOCKED',
36
+ door_open: false,
37
+ update_from_secondary_lock: false,
38
+ double_lock_mode: false,
39
+ unclosed_alarm: false,
40
+ unlocked_alarm: false,
41
+ auto_lock_paused: false,
42
+ night_latch: false,
43
+ };
44
+ expect(result).toEqual(expected);
45
+ });
46
+ });
47
+ it('should initialize with default values', () => {
48
+ expect(lock.iv).toBeNull();
49
+ expect(lock.key_id).toBe('');
50
+ expect(lock.encryption_key).toBeNull();
51
+ });
52
+ it('should set key correctly', async () => {
53
+ const keyId = 'testKeyId';
54
+ const encryptionKey = '0123456789abcdef0123456789abcdef';
55
+ await lock.setKey(keyId, encryptionKey);
56
+ expect(lock.key_id).toBe(keyId);
57
+ expect(lock.encryption_key?.toString('hex')).toBe(encryptionKey);
58
+ });
59
+ it('should validate response correctly', async () => {
60
+ const res = Buffer.from([0x01, 0x00, 0x00]);
61
+ const result = await WoSmartLock.validateResponse(res);
62
+ expect(result).toBe(WoSmartLock.Result.SUCCESS);
63
+ });
64
+ it('should get lock status correctly', () => {
65
+ const status = WoSmartLock.getLockStatus(0b0010000);
66
+ expect(status).toBe('UNLOCKED');
67
+ });
68
+ it('should parse service data correctly', async () => {
69
+ const serviceData = Buffer.from([0x00, 0x00, 0x7F]);
70
+ const manufacturerData = Buffer.from([0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00]);
71
+ const emitLog = jest.fn();
72
+ const data = await WoSmartLock.parseServiceData(serviceData, manufacturerData, emitLog);
73
+ expect(data).toEqual({
74
+ model: 'Lock',
75
+ modelName: 'Lock',
76
+ modelFriendlyName: 'Lock',
77
+ battery: 127,
78
+ calibration: true,
79
+ status: 'LOCKED',
80
+ update_from_secondary_lock: false,
81
+ door_open: false,
82
+ double_lock_mode: false,
83
+ unclosed_alarm: false,
84
+ unlocked_alarm: false,
85
+ auto_lock_paused: false,
86
+ night_latch: false,
87
+ });
88
+ });
89
+ it('should unlock the smart lock', async () => {
90
+ jest.spyOn(lock, 'operateLock').mockResolvedValue(Buffer.from([0x01]));
91
+ const result = await lock.unlock();
92
+ expect(result).toBe(WoSmartLock.Result.SUCCESS);
93
+ });
94
+ it('should lock the smart lock', async () => {
95
+ jest.spyOn(lock, 'operateLock').mockResolvedValue(Buffer.from([0x01]));
96
+ const result = await lock.lock();
97
+ expect(result).toBe(WoSmartLock.Result.SUCCESS);
98
+ });
99
+ it('should get lock info', async () => {
100
+ jest.spyOn(lock, 'operateLock').mockResolvedValue(Buffer.from([0x01, 0b10000000, 0b00100000]));
101
+ const info = await lock.info();
102
+ expect(info).toEqual({
103
+ calibration: true,
104
+ status: 'LOCKED',
105
+ door_open: false,
106
+ unclosed_alarm: true,
107
+ unlocked_alarm: false,
108
+ });
109
+ });
110
+ it('should encrypt data correctly', async () => {
111
+ const keyId = 'testKeyId';
112
+ const encryptionKey = '0123456789abcdef0123456789abcdef';
113
+ await lock.setKey(keyId, encryptionKey);
114
+ lock.iv = Buffer.from('0123456789abcdef', 'hex');
115
+ const encrypted = await lock.encrypt('testdata');
116
+ expect(encrypted).toBe('expectedEncryptedHexString'); // Replace with actual expected encrypted string
117
+ });
118
+ it('should decrypt data correctly', async () => {
119
+ const keyId = 'testKeyId';
120
+ const encryptionKey = '0123456789abcdef0123456789abcdef';
121
+ await lock.setKey(keyId, encryptionKey);
122
+ lock.iv = Buffer.from('0123456789abcdef', 'hex');
123
+ const decrypted = await lock.decrypt(Buffer.from('expectedEncryptedHexString', 'hex')); // Replace with actual encrypted string
124
+ expect(decrypted.toString()).toBe('testdata');
125
+ });
126
+ it('should retrieve IV from the device', async () => {
127
+ jest.spyOn(lock, 'operateLock').mockResolvedValue(Buffer.from([0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04]));
128
+ const iv = await lock.getIv();
129
+ expect(iv.toString('hex')).toBe('01020304');
130
+ });
131
+ it('should send encrypted command to the device', async () => {
132
+ jest.spyOn(lock, 'getIv').mockResolvedValue(Buffer.from('01020304', 'hex'));
133
+ jest.spyOn(lock, 'encrypt').mockResolvedValue('encryptedCommand');
134
+ jest.spyOn(lock, 'command').mockResolvedValue(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x05, 0x06, 0x07, 0x08]));
135
+ const response = await lock.encryptedCommand('testCommand');
136
+ expect(response.toString('hex')).toBe('expectedResponseHexString'); // Replace with actual expected response
137
+ });
138
+ describe('operateLock', () => {
139
+ it('should operate the lock with encryption', async () => {
140
+ jest.spyOn(lock, 'encryptedCommand').mockResolvedValue(Buffer.from([0x01]));
141
+ const response = await lock.operateLock(WoSmartLockCommands.LOCK);
142
+ expect(response).toBeDefined();
143
+ });
144
+ it('should operate the lock without encryption', async () => {
145
+ jest.spyOn(lock, 'command').mockResolvedValue(Buffer.from([0x01, 0x00, 0x00, 0x00]));
146
+ const response = await lock.operateLock(WoSmartLockCommands.LOCK, false);
147
+ expect(response).toBeDefined();
148
+ });
149
+ });
150
+ });
2
151
  //# sourceMappingURL=wosmartlock.test.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"wosmartlock.test.js","sourceRoot":"","sources":["../../src/test/wosmartlock.test.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"wosmartlock.test.js","sourceRoot":"","sources":["../../src/test/wosmartlock.test.ts"],"names":[],"mappings":"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"}
@@ -1,2 +1,151 @@
1
- export {};
1
+ import { Buffer } from 'node:buffer';
2
+ import * as Noble from '@stoprocent/noble';
3
+ import { describe, expect, it, vi } from 'vitest';
4
+ import { WoSmartLockPro } from '../device/wosmartlockpro.js';
5
+ import { WoSmartLockProCommands } from '../settings.js';
6
+ import { SwitchBotBLEModel, SwitchBotBLEModelFriendlyName, SwitchBotBLEModelName } from '../types/types.js';
7
+ describe('woSmartLockPro', () => {
8
+ let lock;
9
+ let mockPeripheral;
10
+ let mockNoble;
11
+ beforeEach(() => {
12
+ mockPeripheral = {};
13
+ mockNoble = Noble;
14
+ lock = new WoSmartLockPro(mockPeripheral, mockNoble);
15
+ });
16
+ describe('parseServiceData', () => {
17
+ it('should return null if buffer length is not 18', async () => {
18
+ const serviceData = Buffer.alloc(10);
19
+ const manufacturerData = Buffer.alloc(0);
20
+ const emitLog = vi.fn();
21
+ const result = await WoSmartLockPro.parseServiceData(serviceData, manufacturerData, emitLog);
22
+ expect(result).toBeNull();
23
+ expect(emitLog).toHaveBeenCalledWith('error', '[parseServiceDataForWoStrip] Buffer length 10 !== 18!');
24
+ });
25
+ it('should parse valid service data correctly', async () => {
26
+ const serviceData = Buffer.from([0, 0, 0, 255, 128, 64, 0, 129, 136, 127, 254, 0, 0, 0, 0, 0, 0, 0]);
27
+ const manufacturerData = Buffer.alloc(0);
28
+ const emitLog = vi.fn();
29
+ const result = await WoSmartLockPro.parseServiceData(serviceData, manufacturerData, emitLog);
30
+ const expected = {
31
+ model: SwitchBotBLEModel.LockPro,
32
+ modelName: SwitchBotBLEModelName.LockPro,
33
+ modelFriendlyName: SwitchBotBLEModelFriendlyName.LockPro,
34
+ battery: 100,
35
+ calibration: true,
36
+ status: 'LOCKED',
37
+ door_open: false,
38
+ update_from_secondary_lock: false,
39
+ double_lock_mode: false,
40
+ unclosed_alarm: false,
41
+ unlocked_alarm: false,
42
+ auto_lock_paused: false,
43
+ night_latch: false,
44
+ };
45
+ expect(result).toEqual(expected);
46
+ });
47
+ });
48
+ describe('validateResponse', () => {
49
+ it('should return SUCCESS for valid response', async () => {
50
+ const res = Buffer.from([0x01, 0x00, 0x00]);
51
+ const result = await WoSmartLockPro.validateResponse(res);
52
+ expect(result).toBe(WoSmartLockPro.Result.SUCCESS);
53
+ });
54
+ it('should return ERROR for invalid response', async () => {
55
+ const res = Buffer.from([0x00, 0x00, 0x00]);
56
+ const result = await WoSmartLockPro.validateResponse(res);
57
+ expect(result).toBe(WoSmartLockPro.Result.ERROR);
58
+ });
59
+ });
60
+ describe('getLockStatus', () => {
61
+ it('should return LOCKED for code 0b0000000', () => {
62
+ const status = WoSmartLockPro.getLockStatus(0b0000000);
63
+ expect(status).toBe('LOCKED');
64
+ });
65
+ it('should return UNKNOWN for unknown code', () => {
66
+ const status = WoSmartLockPro.getLockStatus(0b1111111);
67
+ expect(status).toBe('UNKNOWN');
68
+ });
69
+ });
70
+ describe('setKey', () => {
71
+ it('should set the key ID and encryption key', async () => {
72
+ await lock.setKey('keyId', 'encryptionKey');
73
+ expect(lock.key_id).toBe('keyId');
74
+ expect(lock.encryption_key).toEqual(Buffer.from('encryptionKey', 'hex'));
75
+ });
76
+ });
77
+ describe('unlock', () => {
78
+ it('should unlock the lock', async () => {
79
+ jest.spyOn(lock, 'operateLockPro').mockResolvedValue(Buffer.from([0x01]));
80
+ const result = await lock.unlock();
81
+ expect(result).toBe(WoSmartLockPro.Result.SUCCESS);
82
+ });
83
+ });
84
+ describe('lock', () => {
85
+ it('should lock the lock', async () => {
86
+ jest.spyOn(lock, 'operateLockPro').mockResolvedValue(Buffer.from([0x01]));
87
+ const result = await lock.lock();
88
+ expect(result).toBe(WoSmartLockPro.Result.SUCCESS);
89
+ });
90
+ });
91
+ describe('info', () => {
92
+ it('should return lock info', async () => {
93
+ const mockResponse = Buffer.from([0b10000000, 0b00100000]);
94
+ jest.spyOn(lock, 'operateLockPro').mockResolvedValue(mockResponse);
95
+ const info = await lock.info();
96
+ expect(info).toEqual({
97
+ calibration: true,
98
+ status: 'LOCKED',
99
+ door_open: false,
100
+ unclosed_alarm: true,
101
+ unlocked_alarm: false,
102
+ });
103
+ });
104
+ });
105
+ describe('encrypt', () => {
106
+ it('should encrypt a string', async () => {
107
+ lock.encryption_key = Buffer.from('encryptionKey', 'hex');
108
+ lock.iv = Buffer.from('iv', 'hex');
109
+ const encrypted = await lock.encrypt('test');
110
+ expect(encrypted).toBeDefined();
111
+ });
112
+ });
113
+ describe('decrypt', () => {
114
+ it('should decrypt a buffer', async () => {
115
+ lock.encryption_key = Buffer.from('encryptionKey', 'hex');
116
+ lock.iv = Buffer.from('iv', 'hex');
117
+ const decrypted = await lock.decrypt(Buffer.from('test', 'hex'));
118
+ expect(decrypted).toBeDefined();
119
+ });
120
+ });
121
+ describe('getIv', () => {
122
+ it('should retrieve the IV from the device', async () => {
123
+ const mockResponse = Buffer.from([0x00, 0x00, 0x00, 0x00, 0x01, 0x02]);
124
+ jest.spyOn(lock, 'operateLockPro').mockResolvedValue(mockResponse);
125
+ const iv = await lock.getIv();
126
+ expect(iv).toEqual(Buffer.from([0x01, 0x02]));
127
+ });
128
+ });
129
+ describe('encryptedCommand', () => {
130
+ it('should send an encrypted command to the device', async () => {
131
+ jest.spyOn(lock, 'getIv').mockResolvedValue(Buffer.from([0x01, 0x02]));
132
+ jest.spyOn(lock, 'encrypt').mockResolvedValue('encrypted');
133
+ jest.spyOn(lock, 'command').mockResolvedValue(Buffer.from([0x01, 0x00, 0x00, 0x00, 0x01, 0x02]));
134
+ const response = await lock.encryptedCommand('key');
135
+ expect(response).toBeDefined();
136
+ });
137
+ });
138
+ describe('operateLockPro', () => {
139
+ it('should operate the lock with encryption', async () => {
140
+ jest.spyOn(lock, 'encryptedCommand').mockResolvedValue(Buffer.from([0x01]));
141
+ const response = await lock.operateLockPro(WoSmartLockProCommands.LOCK);
142
+ expect(response).toBeDefined();
143
+ });
144
+ it('should operate the lock without encryption', async () => {
145
+ jest.spyOn(lock, 'command').mockResolvedValue(Buffer.from([0x01, 0x00, 0x00, 0x00]));
146
+ const response = await lock.operateLockPro(WoSmartLockProCommands.LOCK, false);
147
+ expect(response).toBeDefined();
148
+ });
149
+ });
150
+ });
2
151
  //# sourceMappingURL=wosmartlockpro.test.js.map