homebridge-tsvesync 1.0.63 → 1.0.64

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.
@@ -15,6 +15,7 @@ export declare class HumidifierAccessory extends BaseAccessory {
15
15
  private getActive;
16
16
  private setActive;
17
17
  private getRotationSpeed;
18
+ private setTargetState;
18
19
  private handleSetRotationSpeed;
19
20
  }
20
21
  //# sourceMappingURL=humidifier.accessory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"humidifier.accessory.d.ts","sourceRoot":"","sources":["../../src/accessories/humidifier.accessory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE7E,qBAAa,mBAAoB,SAAQ,aAAa;IACpD,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAC5C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;gBAGhD,QAAQ,EAAE,gBAAgB,EAC1B,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,gBAAgB;IAO1B,SAAS,CAAC,YAAY,IAAI,IAAI;IA0B9B;;OAEG;cACa,0BAA0B,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IA8CvE,SAAS,CAAC,qBAAqB,IAAI,kBAAkB;YAcvC,SAAS;YAIT,SAAS;YAiBT,gBAAgB;YAqBhB,sBAAsB;CAiCrC"}
1
+ {"version":3,"file":"humidifier.accessory.d.ts","sourceRoot":"","sources":["../../src/accessories/humidifier.accessory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAO7E,qBAAa,mBAAoB,SAAQ,aAAa;IACpD,SAAS,CAAC,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAC5C,OAAO,CAAC,QAAQ,CAAC,YAAY,CAAqB;gBAGhD,QAAQ,EAAE,gBAAgB,EAC1B,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,gBAAgB;IAO1B,SAAS,CAAC,YAAY,IAAI,IAAI;IAwD9B;;OAEG;cACa,0BAA0B,CAAC,OAAO,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAyEvE,SAAS,CAAC,qBAAqB,IAAI,kBAAkB;YAcvC,SAAS;YAIT,SAAS;YAiBT,gBAAgB;YAqBhB,cAAc;YAyBd,sBAAsB;CAiCrC"}
@@ -14,24 +14,44 @@ class HumidifierAccessory extends base_accessory_1.BaseAccessory {
14
14
  this.accessory.addService(this.platform.Service.HumidifierDehumidifier);
15
15
  // Set up required characteristics
16
16
  this.setupCharacteristic(this.platform.Characteristic.Active, this.getActive.bind(this), this.setActive.bind(this));
17
- // Set up speed control
17
+ // Set up target state characteristic for mode mapping
18
+ this.setupCharacteristic(this.platform.Characteristic.TargetHumidifierDehumidifierState, async () => 1, this.setTargetState.bind(this));
19
+ // Set up rotation speed characteristic
18
20
  this.setupCharacteristic(this.platform.Characteristic.RotationSpeed, this.getRotationSpeed.bind(this), this.handleSetRotationSpeed.bind(this));
19
21
  // Add Name characteristic
20
22
  this.setupCharacteristic(this.platform.Characteristic.Name, async () => this.device.deviceName);
23
+ // Add Current Relative Humidity if supported
24
+ if (this.capabilities.hasHumidity) {
25
+ if (!this.service.testCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity)) {
26
+ this.service.addCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity);
27
+ }
28
+ }
29
+ // Add Water Level characteristic if supported (mapping inferred from water_lacks/water_tank_lifted)
30
+ if (this.capabilities.hasWaterLevel) {
31
+ if (!this.service.testCharacteristic(this.platform.Characteristic.WaterLevel)) {
32
+ this.service.addCharacteristic(this.platform.Characteristic.WaterLevel);
33
+ }
34
+ }
35
+ // Add Lock Physical Controls characteristic if supported
36
+ if (this.capabilities.hasChildLock) {
37
+ this.setupCharacteristic(this.platform.Characteristic.LockPhysicalControls, async () => false, async (value) => { throw new Error('Locking physical controls is not supported by the tsvesync API.'); });
38
+ }
21
39
  }
22
40
  /**
23
41
  * Update device states based on the latest details
24
42
  */
25
43
  async updateDeviceSpecificStates(details) {
26
44
  const humidifierDetails = details;
27
- // Update active state
28
45
  const isActive = humidifierDetails.deviceStatus === 'on';
46
+ // Update active state
29
47
  this.updateCharacteristicValue(this.platform.Characteristic.Active, isActive ? 1 : 0);
30
- // Update current state (INACTIVE = 0, IDLE = 1, HUMIDIFYING = 2, DEHUMIDIFYING = 3)
31
- this.updateCharacteristicValue(this.platform.Characteristic.CurrentHumidifierDehumidifierState, isActive ? 2 : 0);
32
- // Update target state (HUMIDIFIER = 1, DEHUMIDIFIER = 2, AUTO = 0)
33
- this.updateCharacteristicValue(this.platform.Characteristic.TargetHumidifierDehumidifierState, 1 // Always humidifier mode
34
- );
48
+ // Update current state based on API mapping
49
+ // HomeKit states: 0 = INACTIVE, 1 = IDLE, 2 = HUMIDIFYING, 3 = DEHUMIDIFYING
50
+ // Mapping: if active and mode is 'manual' -> HUMIDIFYING (2), else INACTIVE (0)
51
+ const currentState = (isActive && humidifierDetails.mode === 'manual') ? 2 : 0;
52
+ this.updateCharacteristicValue(this.platform.Characteristic.CurrentHumidifierDehumidifierState, currentState);
53
+ // Update target state; always humidifier mode (1) as only humidification is supported
54
+ this.updateCharacteristicValue(this.platform.Characteristic.TargetHumidifierDehumidifierState, 1);
35
55
  // Update rotation speed - convert device speed (1-9) to HomeKit percentage (0-100)
36
56
  let rotationSpeed = 0;
37
57
  if (isActive && humidifierDetails.speed !== undefined) {
@@ -66,6 +86,18 @@ class HumidifierAccessory extends base_accessory_1.BaseAccessory {
66
86
  }
67
87
  }
68
88
  this.updateCharacteristicValue(this.platform.Characteristic.RotationSpeed, rotationSpeed);
89
+ // Update relative humidity if supported
90
+ if (this.capabilities.hasHumidity && humidifierDetails.humidity !== undefined) {
91
+ this.updateCharacteristicValue(this.platform.Characteristic.CurrentRelativeHumidity, humidifierDetails.humidity);
92
+ }
93
+ // Update water level if supported (inferred from water_lacks/water_tank_lifted)
94
+ if (this.capabilities.hasWaterLevel) {
95
+ const waterLow = humidifierDetails.water_lacks || humidifierDetails.water_tank_lifted;
96
+ if (this.service.getCharacteristic(this.platform.Characteristic.WaterLevel)) {
97
+ // Map water level as 0 for low water, 100 for sufficient water
98
+ this.updateCharacteristicValue(this.platform.Characteristic.WaterLevel, waterLow ? 0 : 100);
99
+ }
100
+ }
69
101
  }
70
102
  getDeviceCapabilities() {
71
103
  return {
@@ -104,7 +136,7 @@ class HumidifierAccessory extends base_accessory_1.BaseAccessory {
104
136
  }
105
137
  // Convert device speed (1-9) to HomeKit percentage (0-100)
106
138
  switch (this.device.speed) {
107
- case 0: return 0; // Off
139
+ case 0: return 0;
108
140
  case 1: return 11;
109
141
  case 2: return 22;
110
142
  case 3: return 33;
@@ -117,6 +149,34 @@ class HumidifierAccessory extends base_accessory_1.BaseAccessory {
117
149
  default: return 0;
118
150
  }
119
151
  }
152
+ async setTargetState(value) {
153
+ try {
154
+ // HomeKit Target State: 1 = Humidifier, 2 = Dehumidifier, 0 = Auto
155
+ const device = this.device;
156
+ if (value === 1) {
157
+ if (typeof device.setMode === 'function') {
158
+ const success = await device.setMode('manual');
159
+ if (!success) {
160
+ throw new Error('Failed to set device mode to humidification (manual)');
161
+ }
162
+ }
163
+ else {
164
+ throw new Error('Device API does not support setMode operation');
165
+ }
166
+ }
167
+ else if (value === 2) {
168
+ throw new Error('Dehumidification mode is not supported by this device');
169
+ }
170
+ else {
171
+ throw new Error('Unsupported target state value');
172
+ }
173
+ // After setting, update the target state to reflect humidifier mode (1)
174
+ this.updateCharacteristicValue(this.platform.Characteristic.TargetHumidifierDehumidifierState, 1);
175
+ }
176
+ catch (error) {
177
+ this.handleDeviceError('set target state', error);
178
+ }
179
+ }
120
180
  async handleSetRotationSpeed(value) {
121
181
  const percentage = value;
122
182
  if (percentage === 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"humidifier.accessory.js","sourceRoot":"","sources":["../../src/accessories/humidifier.accessory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"humidifier.accessory.js","sourceRoot":"","sources":["../../src/accessories/humidifier.accessory.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "homebridge-tsvesync",
3
- "version": "1.0.63",
3
+ "version": "1.0.64",
4
4
  "description": "Homebridge plugin for VeSync devices including Levoit air purifiers, humidifiers, and Etekcity smart outlets",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -98,7 +98,7 @@
98
98
  "axios": "^1.6.5",
99
99
  "dotenv": "^16.3.1",
100
100
  "js-yaml": "^4.1.0",
101
- "tsvesync": "1.0.63"
101
+ "tsvesync": "1.0.64"
102
102
  },
103
103
  "devDependencies": {
104
104
  "@types/jest": "^29.5.11",
@@ -3,6 +3,11 @@ import { BaseAccessory } from './base.accessory';
3
3
  import { TSVESyncPlatform } from '../platform';
4
4
  import { DeviceCapabilities, VeSyncHumidifier } from '../types/device.types';
5
5
 
6
+ // Extended interface to include optional setMode method for humidifiers
7
+ interface ExtendedVeSyncHumidifier extends VeSyncHumidifier {
8
+ setMode?(mode: 'manual'): Promise<boolean>;
9
+ }
10
+
6
11
  export class HumidifierAccessory extends BaseAccessory {
7
12
  protected readonly device: VeSyncHumidifier;
8
13
  private readonly capabilities: DeviceCapabilities;
@@ -29,7 +34,14 @@ export class HumidifierAccessory extends BaseAccessory {
29
34
  this.setActive.bind(this)
30
35
  );
31
36
 
32
- // Set up speed control
37
+ // Set up target state characteristic for mode mapping
38
+ this.setupCharacteristic(
39
+ this.platform.Characteristic.TargetHumidifierDehumidifierState,
40
+ async () => 1,
41
+ this.setTargetState.bind(this)
42
+ );
43
+
44
+ // Set up rotation speed characteristic
33
45
  this.setupCharacteristic(
34
46
  this.platform.Characteristic.RotationSpeed,
35
47
  this.getRotationSpeed.bind(this),
@@ -41,6 +53,29 @@ export class HumidifierAccessory extends BaseAccessory {
41
53
  this.platform.Characteristic.Name,
42
54
  async () => this.device.deviceName
43
55
  );
56
+
57
+ // Add Current Relative Humidity if supported
58
+ if (this.capabilities.hasHumidity) {
59
+ if (!this.service.testCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity)) {
60
+ this.service.addCharacteristic(this.platform.Characteristic.CurrentRelativeHumidity);
61
+ }
62
+ }
63
+
64
+ // Add Water Level characteristic if supported (mapping inferred from water_lacks/water_tank_lifted)
65
+ if (this.capabilities.hasWaterLevel) {
66
+ if (!this.service.testCharacteristic(this.platform.Characteristic.WaterLevel)) {
67
+ this.service.addCharacteristic(this.platform.Characteristic.WaterLevel);
68
+ }
69
+ }
70
+
71
+ // Add Lock Physical Controls characteristic if supported
72
+ if (this.capabilities.hasChildLock) {
73
+ this.setupCharacteristic(
74
+ this.platform.Characteristic.LockPhysicalControls,
75
+ async () => false,
76
+ async (value: CharacteristicValue) => { throw new Error('Locking physical controls is not supported by the tsvesync API.'); }
77
+ );
78
+ }
44
79
  }
45
80
 
46
81
  /**
@@ -50,25 +85,32 @@ export class HumidifierAccessory extends BaseAccessory {
50
85
  const humidifierDetails = details as {
51
86
  deviceStatus: string;
52
87
  speed: number;
88
+ mode?: string;
89
+ humidity?: number;
90
+ water_lacks?: boolean;
91
+ water_tank_lifted?: boolean;
53
92
  };
54
93
 
55
- // Update active state
56
94
  const isActive = humidifierDetails.deviceStatus === 'on';
95
+ // Update active state
57
96
  this.updateCharacteristicValue(
58
97
  this.platform.Characteristic.Active,
59
98
  isActive ? 1 : 0
60
99
  );
61
100
 
62
- // Update current state (INACTIVE = 0, IDLE = 1, HUMIDIFYING = 2, DEHUMIDIFYING = 3)
101
+ // Update current state based on API mapping
102
+ // HomeKit states: 0 = INACTIVE, 1 = IDLE, 2 = HUMIDIFYING, 3 = DEHUMIDIFYING
103
+ // Mapping: if active and mode is 'manual' -> HUMIDIFYING (2), else INACTIVE (0)
104
+ const currentState = (isActive && humidifierDetails.mode === 'manual') ? 2 : 0;
63
105
  this.updateCharacteristicValue(
64
106
  this.platform.Characteristic.CurrentHumidifierDehumidifierState,
65
- isActive ? 2 : 0
107
+ currentState
66
108
  );
67
109
 
68
- // Update target state (HUMIDIFIER = 1, DEHUMIDIFIER = 2, AUTO = 0)
110
+ // Update target state; always humidifier mode (1) as only humidification is supported
69
111
  this.updateCharacteristicValue(
70
112
  this.platform.Characteristic.TargetHumidifierDehumidifierState,
71
- 1 // Always humidifier mode
113
+ 1
72
114
  );
73
115
 
74
116
  // Update rotation speed - convert device speed (1-9) to HomeKit percentage (0-100)
@@ -90,6 +132,26 @@ export class HumidifierAccessory extends BaseAccessory {
90
132
  this.platform.Characteristic.RotationSpeed,
91
133
  rotationSpeed
92
134
  );
135
+
136
+ // Update relative humidity if supported
137
+ if (this.capabilities.hasHumidity && humidifierDetails.humidity !== undefined) {
138
+ this.updateCharacteristicValue(
139
+ this.platform.Characteristic.CurrentRelativeHumidity,
140
+ humidifierDetails.humidity
141
+ );
142
+ }
143
+
144
+ // Update water level if supported (inferred from water_lacks/water_tank_lifted)
145
+ if (this.capabilities.hasWaterLevel) {
146
+ const waterLow = humidifierDetails.water_lacks || humidifierDetails.water_tank_lifted;
147
+ if (this.service.getCharacteristic(this.platform.Characteristic.WaterLevel)) {
148
+ // Map water level as 0 for low water, 100 for sufficient water
149
+ this.updateCharacteristicValue(
150
+ this.platform.Characteristic.WaterLevel,
151
+ waterLow ? 0 : 100
152
+ );
153
+ }
154
+ }
93
155
  }
94
156
 
95
157
  protected getDeviceCapabilities(): DeviceCapabilities {
@@ -134,7 +196,7 @@ export class HumidifierAccessory extends BaseAccessory {
134
196
 
135
197
  // Convert device speed (1-9) to HomeKit percentage (0-100)
136
198
  switch (this.device.speed) {
137
- case 0: return 0; // Off
199
+ case 0: return 0;
138
200
  case 1: return 11;
139
201
  case 2: return 22;
140
202
  case 3: return 33;
@@ -148,6 +210,31 @@ export class HumidifierAccessory extends BaseAccessory {
148
210
  }
149
211
  }
150
212
 
213
+ private async setTargetState(value: CharacteristicValue): Promise<void> {
214
+ try {
215
+ // HomeKit Target State: 1 = Humidifier, 2 = Dehumidifier, 0 = Auto
216
+ const device = this.device as ExtendedVeSyncHumidifier;
217
+ if (value === 1) {
218
+ if (typeof device.setMode === 'function') {
219
+ const success = await device.setMode('manual');
220
+ if (!success) {
221
+ throw new Error('Failed to set device mode to humidification (manual)');
222
+ }
223
+ } else {
224
+ throw new Error('Device API does not support setMode operation');
225
+ }
226
+ } else if (value === 2) {
227
+ throw new Error('Dehumidification mode is not supported by this device');
228
+ } else {
229
+ throw new Error('Unsupported target state value');
230
+ }
231
+ // After setting, update the target state to reflect humidifier mode (1)
232
+ this.updateCharacteristicValue(this.platform.Characteristic.TargetHumidifierDehumidifierState, 1);
233
+ } catch (error) {
234
+ this.handleDeviceError('set target state', error);
235
+ }
236
+ }
237
+
151
238
  private async handleSetRotationSpeed(value: CharacteristicValue): Promise<void> {
152
239
  const percentage = value as number;
153
240