homebridge-tsvesync 1.0.13 → 1.0.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/accessories/air-purifier.accessory.d.ts +32 -2
- package/dist/accessories/air-purifier.accessory.d.ts.map +1 -1
- package/dist/accessories/air-purifier.accessory.js +110 -51
- package/dist/accessories/air-purifier.accessory.js.map +1 -1
- package/dist/accessories/base.accessory.d.ts +12 -3
- package/dist/accessories/base.accessory.d.ts.map +1 -1
- package/dist/accessories/base.accessory.js +53 -24
- package/dist/accessories/base.accessory.js.map +1 -1
- package/dist/accessories/fan.accessory.d.ts +6 -2
- package/dist/accessories/fan.accessory.d.ts.map +1 -1
- package/dist/accessories/fan.accessory.js +27 -33
- package/dist/accessories/fan.accessory.js.map +1 -1
- package/dist/accessories/humidifier.accessory.d.ts +6 -2
- package/dist/accessories/humidifier.accessory.d.ts.map +1 -1
- package/dist/accessories/humidifier.accessory.js +38 -37
- package/dist/accessories/humidifier.accessory.js.map +1 -1
- package/dist/accessories/light.accessory.d.ts +5 -1
- package/dist/accessories/light.accessory.d.ts.map +1 -1
- package/dist/accessories/light.accessory.js +25 -19
- package/dist/accessories/light.accessory.js.map +1 -1
- package/dist/accessories/outlet.accessory.d.ts +7 -1
- package/dist/accessories/outlet.accessory.d.ts.map +1 -1
- package/dist/accessories/outlet.accessory.js +25 -14
- package/dist/accessories/outlet.accessory.js.map +1 -1
- package/dist/types/device.types.d.ts +1 -1
- package/dist/types/device.types.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/accessories/air-purifier.accessory.ts +117 -84
- package/src/accessories/base.accessory.ts +62 -35
- package/src/accessories/fan.accessory.ts +40 -44
- package/src/accessories/humidifier.accessory.ts +61 -48
- package/src/accessories/light.accessory.ts +32 -18
- package/src/accessories/outlet.accessory.ts +33 -14
- package/src/types/device.types.ts +1 -1
|
@@ -5,14 +5,16 @@ import { DeviceCapabilities, VeSyncHumidifier } from '../types/device.types';
|
|
|
5
5
|
|
|
6
6
|
export class HumidifierAccessory extends BaseAccessory {
|
|
7
7
|
protected readonly device: VeSyncHumidifier;
|
|
8
|
+
private readonly capabilities: DeviceCapabilities;
|
|
8
9
|
|
|
9
10
|
constructor(
|
|
10
11
|
platform: TSVESyncPlatform,
|
|
11
12
|
accessory: PlatformAccessory,
|
|
12
|
-
device: VeSyncHumidifier
|
|
13
|
+
device: VeSyncHumidifier
|
|
13
14
|
) {
|
|
14
15
|
super(platform, accessory, device);
|
|
15
16
|
this.device = device;
|
|
17
|
+
this.capabilities = this.getDeviceCapabilities();
|
|
16
18
|
}
|
|
17
19
|
|
|
18
20
|
protected setupService(): void {
|
|
@@ -56,7 +58,7 @@ export class HumidifierAccessory extends BaseAccessory {
|
|
|
56
58
|
this.setupCharacteristic(
|
|
57
59
|
this.platform.Characteristic.RotationSpeed,
|
|
58
60
|
this.getRotationSpeed.bind(this),
|
|
59
|
-
this.
|
|
61
|
+
this.handleSetRotationSpeed.bind(this)
|
|
60
62
|
);
|
|
61
63
|
}
|
|
62
64
|
|
|
@@ -82,61 +84,80 @@ export class HumidifierAccessory extends BaseAccessory {
|
|
|
82
84
|
);
|
|
83
85
|
}
|
|
84
86
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
/**
|
|
88
|
+
* Update device states based on the latest details
|
|
89
|
+
*/
|
|
90
|
+
protected async updateDeviceSpecificStates(details: any): Promise<void> {
|
|
91
|
+
const humidifierDetails = details as {
|
|
92
|
+
deviceStatus: string;
|
|
93
|
+
humidity: number;
|
|
94
|
+
targetHumidity: number;
|
|
95
|
+
speed: number;
|
|
96
|
+
childLock: boolean;
|
|
97
|
+
waterLevel: number;
|
|
98
|
+
};
|
|
87
99
|
|
|
88
|
-
// Update
|
|
89
|
-
|
|
100
|
+
// Update active state
|
|
101
|
+
const isActive = humidifierDetails.deviceStatus === 'on';
|
|
102
|
+
this.updateCharacteristicValue(
|
|
103
|
+
this.platform.Characteristic.Active,
|
|
104
|
+
isActive ? 1 : 0
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
// Update current state
|
|
108
|
+
this.updateCharacteristicValue(
|
|
109
|
+
this.platform.Characteristic.CurrentHumidifierDehumidifierState,
|
|
110
|
+
isActive ? 2 : 0
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
// Update target state
|
|
114
|
+
this.updateCharacteristicValue(
|
|
115
|
+
this.platform.Characteristic.TargetHumidifierDehumidifierState,
|
|
116
|
+
1 // Always HUMIDIFIER for these devices
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
// Update current humidity
|
|
120
|
+
if (humidifierDetails.humidity !== undefined) {
|
|
90
121
|
this.updateCharacteristicValue(
|
|
91
122
|
this.platform.Characteristic.CurrentRelativeHumidity,
|
|
92
|
-
|
|
123
|
+
humidifierDetails.humidity
|
|
93
124
|
);
|
|
94
125
|
}
|
|
95
126
|
|
|
96
|
-
|
|
127
|
+
// Update target humidity
|
|
128
|
+
if (humidifierDetails.targetHumidity !== undefined) {
|
|
97
129
|
this.updateCharacteristicValue(
|
|
98
130
|
this.platform.Characteristic.RelativeHumidityHumidifierThreshold,
|
|
99
|
-
|
|
131
|
+
humidifierDetails.targetHumidity
|
|
100
132
|
);
|
|
101
133
|
}
|
|
102
134
|
|
|
103
|
-
// Update speed if
|
|
104
|
-
if (capabilities.hasSpeed
|
|
105
|
-
const normalizedSpeed = (details.speed / this.device.maxSpeed) * 100;
|
|
135
|
+
// Update rotation speed if supported
|
|
136
|
+
if (this.capabilities.hasSpeed) {
|
|
106
137
|
this.updateCharacteristicValue(
|
|
107
138
|
this.platform.Characteristic.RotationSpeed,
|
|
108
|
-
|
|
139
|
+
humidifierDetails.speed
|
|
109
140
|
);
|
|
110
141
|
}
|
|
111
142
|
|
|
112
|
-
// Update
|
|
113
|
-
if (capabilities.
|
|
143
|
+
// Update child lock if supported
|
|
144
|
+
if (this.capabilities.hasChildLock) {
|
|
114
145
|
this.updateCharacteristicValue(
|
|
115
|
-
this.platform.Characteristic.
|
|
116
|
-
|
|
146
|
+
this.platform.Characteristic.LockPhysicalControls,
|
|
147
|
+
humidifierDetails.childLock ? 1 : 0
|
|
117
148
|
);
|
|
118
149
|
}
|
|
119
150
|
|
|
120
|
-
// Update
|
|
121
|
-
if (capabilities.
|
|
151
|
+
// Update water level if supported
|
|
152
|
+
if (this.capabilities.hasWaterLevel && humidifierDetails.waterLevel !== undefined) {
|
|
122
153
|
this.updateCharacteristicValue(
|
|
123
|
-
this.platform.Characteristic.
|
|
124
|
-
|
|
154
|
+
this.platform.Characteristic.WaterLevel,
|
|
155
|
+
humidifierDetails.waterLevel
|
|
125
156
|
);
|
|
126
157
|
}
|
|
127
158
|
|
|
128
|
-
// Update active
|
|
129
|
-
|
|
130
|
-
this.updateCharacteristicValue(
|
|
131
|
-
this.platform.Characteristic.Active,
|
|
132
|
-
isActive ? 1 : 0
|
|
133
|
-
);
|
|
134
|
-
|
|
135
|
-
// Update current state
|
|
136
|
-
this.updateCharacteristicValue(
|
|
137
|
-
this.platform.Characteristic.CurrentHumidifierDehumidifierState,
|
|
138
|
-
isActive ? 2 : 0 // 0 = INACTIVE, 2 = HUMIDIFYING
|
|
139
|
-
);
|
|
159
|
+
// Update polling state based on active status
|
|
160
|
+
this.updatePollingState(isActive);
|
|
140
161
|
}
|
|
141
162
|
|
|
142
163
|
protected getDeviceCapabilities(): DeviceCapabilities {
|
|
@@ -209,23 +230,15 @@ export class HumidifierAccessory extends BaseAccessory {
|
|
|
209
230
|
}
|
|
210
231
|
}
|
|
211
232
|
|
|
212
|
-
private async
|
|
213
|
-
|
|
233
|
+
private async handleSetRotationSpeed(value: CharacteristicValue): Promise<void> {
|
|
234
|
+
const speed = Math.round((value as number / 100) * this.device.maxSpeed);
|
|
235
|
+
await this.withRetry(async () => {
|
|
236
|
+
await this.device.changeFanSpeed(speed);
|
|
237
|
+
}, 'set rotation speed');
|
|
214
238
|
}
|
|
215
239
|
|
|
216
|
-
private async
|
|
217
|
-
|
|
218
|
-
const speed = Math.round((value as number / 100) * this.device.maxSpeed);
|
|
219
|
-
const success = await this.device.setSpeed(speed);
|
|
220
|
-
|
|
221
|
-
if (!success) {
|
|
222
|
-
throw new Error(`Failed to set speed to ${speed}`);
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
await this.persistDeviceState('speed', speed);
|
|
226
|
-
} catch (error) {
|
|
227
|
-
this.handleDeviceError('set rotation speed', error);
|
|
228
|
-
}
|
|
240
|
+
private async getRotationSpeed(): Promise<CharacteristicValue> {
|
|
241
|
+
return (this.device.speed / this.device.maxSpeed) * 100;
|
|
229
242
|
}
|
|
230
243
|
|
|
231
244
|
private async getWaterLevel(): Promise<CharacteristicValue> {
|
|
@@ -10,14 +10,16 @@ const DEFAULT_COLOR_TEMP = MIN_COLOR_TEMP;
|
|
|
10
10
|
|
|
11
11
|
export class LightAccessory extends BaseAccessory {
|
|
12
12
|
protected readonly device: VeSyncBulb;
|
|
13
|
+
private readonly capabilities: DeviceCapabilities;
|
|
13
14
|
|
|
14
15
|
constructor(
|
|
15
16
|
platform: TSVESyncPlatform,
|
|
16
17
|
accessory: PlatformAccessory,
|
|
17
|
-
device: VeSyncBulb
|
|
18
|
+
device: VeSyncBulb
|
|
18
19
|
) {
|
|
19
20
|
super(platform, accessory, device);
|
|
20
21
|
this.device = device;
|
|
22
|
+
this.capabilities = this.getDeviceCapabilities();
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
protected setupService(): void {
|
|
@@ -84,48 +86,60 @@ export class LightAccessory extends BaseAccessory {
|
|
|
84
86
|
);
|
|
85
87
|
}
|
|
86
88
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
/**
|
|
90
|
+
* Update device states based on the latest details
|
|
91
|
+
*/
|
|
92
|
+
protected async updateDeviceSpecificStates(details: any): Promise<void> {
|
|
93
|
+
const lightDetails = details as {
|
|
94
|
+
deviceStatus: string;
|
|
95
|
+
brightness: number;
|
|
96
|
+
colorTemp?: number;
|
|
97
|
+
hue?: number;
|
|
98
|
+
saturation?: number;
|
|
99
|
+
};
|
|
89
100
|
|
|
90
|
-
// Update
|
|
91
|
-
const
|
|
101
|
+
// Update active state
|
|
102
|
+
const isActive = lightDetails.deviceStatus === 'on';
|
|
92
103
|
this.updateCharacteristicValue(
|
|
93
104
|
this.platform.Characteristic.On,
|
|
94
|
-
|
|
105
|
+
isActive
|
|
95
106
|
);
|
|
96
107
|
|
|
97
|
-
// Update brightness if
|
|
98
|
-
if (capabilities.hasBrightness &&
|
|
108
|
+
// Update brightness if supported
|
|
109
|
+
if (this.capabilities.hasBrightness && lightDetails.brightness !== undefined) {
|
|
99
110
|
this.updateCharacteristicValue(
|
|
100
111
|
this.platform.Characteristic.Brightness,
|
|
101
|
-
|
|
112
|
+
lightDetails.brightness
|
|
102
113
|
);
|
|
103
114
|
}
|
|
104
115
|
|
|
105
|
-
// Update color temperature if
|
|
106
|
-
if (capabilities.hasColorTemp &&
|
|
116
|
+
// Update color temperature if supported
|
|
117
|
+
if (this.capabilities.hasColorTemp && lightDetails.colorTemp !== undefined) {
|
|
107
118
|
this.updateCharacteristicValue(
|
|
108
119
|
this.platform.Characteristic.ColorTemperature,
|
|
109
|
-
|
|
120
|
+
lightDetails.colorTemp
|
|
110
121
|
);
|
|
111
122
|
}
|
|
112
123
|
|
|
113
|
-
// Update color if
|
|
114
|
-
if (capabilities.hasColor) {
|
|
115
|
-
if (
|
|
124
|
+
// Update color if supported
|
|
125
|
+
if (this.capabilities.hasColor) {
|
|
126
|
+
if (lightDetails.hue !== undefined) {
|
|
116
127
|
this.updateCharacteristicValue(
|
|
117
128
|
this.platform.Characteristic.Hue,
|
|
118
|
-
|
|
129
|
+
lightDetails.hue
|
|
119
130
|
);
|
|
120
131
|
}
|
|
121
132
|
|
|
122
|
-
if (
|
|
133
|
+
if (lightDetails.saturation !== undefined) {
|
|
123
134
|
this.updateCharacteristicValue(
|
|
124
135
|
this.platform.Characteristic.Saturation,
|
|
125
|
-
|
|
136
|
+
lightDetails.saturation
|
|
126
137
|
);
|
|
127
138
|
}
|
|
128
139
|
}
|
|
140
|
+
|
|
141
|
+
// Update polling state based on active status
|
|
142
|
+
this.updatePollingState(isActive);
|
|
129
143
|
}
|
|
130
144
|
|
|
131
145
|
protected getDeviceCapabilities(): DeviceCapabilities {
|
|
@@ -22,6 +22,11 @@ export class OutletAccessory extends BaseAccessory {
|
|
|
22
22
|
protected readonly device: VeSyncOutlet;
|
|
23
23
|
private powerService?: Service;
|
|
24
24
|
|
|
25
|
+
// Custom characteristics for power monitoring
|
|
26
|
+
private readonly POWER_UUID = '7B2B25B0-DB50-4351-9A8B-5B9F3E3E3E3E';
|
|
27
|
+
private readonly VOLTAGE_UUID = '7B2B25B1-DB50-4351-9A8B-5B9F3E3E3E3E';
|
|
28
|
+
private readonly ENERGY_UUID = '7B2B25B2-DB50-4351-9A8B-5B9F3E3E3E3E';
|
|
29
|
+
|
|
25
30
|
constructor(
|
|
26
31
|
platform: TSVESyncPlatform,
|
|
27
32
|
accessory: PlatformAccessory,
|
|
@@ -122,34 +127,48 @@ export class OutletAccessory extends BaseAccessory {
|
|
|
122
127
|
}
|
|
123
128
|
}
|
|
124
129
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
130
|
+
/**
|
|
131
|
+
* Update device states based on the latest details
|
|
132
|
+
*/
|
|
133
|
+
protected async updateDeviceSpecificStates(details: any): Promise<void> {
|
|
134
|
+
const outletDetails = details as {
|
|
135
|
+
deviceStatus: string;
|
|
136
|
+
power?: number;
|
|
137
|
+
voltage?: number;
|
|
138
|
+
energy?: number;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
// Update active state
|
|
142
|
+
const isActive = outletDetails.deviceStatus === 'on';
|
|
128
143
|
this.updateCharacteristicValue(
|
|
129
144
|
this.platform.Characteristic.On,
|
|
130
|
-
|
|
145
|
+
isActive
|
|
131
146
|
);
|
|
132
147
|
|
|
133
|
-
// Update outlet in use
|
|
148
|
+
// Update outlet in use (always true when device is on)
|
|
134
149
|
this.updateCharacteristicValue(
|
|
135
150
|
this.platform.Characteristic.OutletInUse,
|
|
136
|
-
|
|
151
|
+
isActive
|
|
137
152
|
);
|
|
138
153
|
|
|
139
|
-
// Update power
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
154
|
+
// Update power monitoring characteristics if available
|
|
155
|
+
const powerService = this.accessory.getService('Power Monitor');
|
|
156
|
+
if (powerService) {
|
|
157
|
+
if (outletDetails.power !== undefined) {
|
|
158
|
+
powerService.updateCharacteristic(this.POWER_UUID, outletDetails.power);
|
|
143
159
|
}
|
|
144
160
|
|
|
145
|
-
if (
|
|
146
|
-
|
|
161
|
+
if (outletDetails.voltage !== undefined) {
|
|
162
|
+
powerService.updateCharacteristic(this.VOLTAGE_UUID, outletDetails.voltage);
|
|
147
163
|
}
|
|
148
164
|
|
|
149
|
-
if (
|
|
150
|
-
|
|
165
|
+
if (outletDetails.energy !== undefined) {
|
|
166
|
+
powerService.updateCharacteristic(this.ENERGY_UUID, outletDetails.energy);
|
|
151
167
|
}
|
|
152
168
|
}
|
|
169
|
+
|
|
170
|
+
// Update polling state based on active status
|
|
171
|
+
this.updatePollingState(isActive);
|
|
153
172
|
}
|
|
154
173
|
|
|
155
174
|
protected getDeviceCapabilities(): DeviceCapabilities {
|
|
@@ -34,7 +34,7 @@ export interface VeSyncDeviceWithColor extends VeSyncDeviceWithBrightness {
|
|
|
34
34
|
export interface VeSyncDeviceWithSpeed extends VeSyncDeviceWithPower {
|
|
35
35
|
speed: number;
|
|
36
36
|
maxSpeed: number;
|
|
37
|
-
|
|
37
|
+
changeFanSpeed(value: number): Promise<boolean>;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
40
|
export interface VeSyncDeviceWithRotation extends VeSyncDeviceWithPower {
|