homebridge-bedjet 0.2.0 → 0.2.1
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/accessory.d.ts +7 -0
- package/dist/accessory.js +33 -7
- package/dist/accessory.js.map +1 -1
- package/package.json +1 -1
- package/src/accessory.ts +46 -12
package/dist/accessory.d.ts
CHANGED
|
@@ -10,6 +10,13 @@ export declare class BedJetAccessory {
|
|
|
10
10
|
private readonly bedjet;
|
|
11
11
|
private tempDebounce;
|
|
12
12
|
private fanDebounce;
|
|
13
|
+
private pendingTemp;
|
|
14
|
+
private pendingTempTimer;
|
|
15
|
+
private pendingFanSpeed;
|
|
16
|
+
private pendingFanSpeedTimer;
|
|
17
|
+
private pendingMode;
|
|
18
|
+
private pendingModeTimer;
|
|
19
|
+
private setPending;
|
|
13
20
|
constructor(platform: BedJetPlatform, accessory: PlatformAccessory, config: BedJetConfig);
|
|
14
21
|
private _syncHomeKit;
|
|
15
22
|
}
|
package/dist/accessory.js
CHANGED
|
@@ -21,6 +21,15 @@ const TARGET_TO_MODE = {
|
|
|
21
21
|
3: constants_1.OperatingMode.HEAT, // AUTO — fall back to heat
|
|
22
22
|
};
|
|
23
23
|
class BedJetAccessory {
|
|
24
|
+
setPending(value, store, timer, ms = 3000) {
|
|
25
|
+
if (this[timer]) {
|
|
26
|
+
clearTimeout(this[timer]);
|
|
27
|
+
}
|
|
28
|
+
this[store] = value;
|
|
29
|
+
this[timer] = setTimeout(() => {
|
|
30
|
+
this[store] = null;
|
|
31
|
+
}, ms);
|
|
32
|
+
}
|
|
24
33
|
constructor(platform, accessory, config) {
|
|
25
34
|
this.platform = platform;
|
|
26
35
|
this.accessory = accessory;
|
|
@@ -28,6 +37,13 @@ class BedJetAccessory {
|
|
|
28
37
|
// Debounce handles for setter commands
|
|
29
38
|
this.tempDebounce = null;
|
|
30
39
|
this.fanDebounce = null;
|
|
40
|
+
// Optimistic values — held after a set to suppress stale BLE notification bounces
|
|
41
|
+
this.pendingTemp = null;
|
|
42
|
+
this.pendingTempTimer = null;
|
|
43
|
+
this.pendingFanSpeed = null;
|
|
44
|
+
this.pendingFanSpeedTimer = null;
|
|
45
|
+
this.pendingMode = null;
|
|
46
|
+
this.pendingModeTimer = null;
|
|
31
47
|
const { Service, Characteristic } = platform.api.hap;
|
|
32
48
|
// AccessoryInformation
|
|
33
49
|
const infoService = this.accessory.getService(Service.AccessoryInformation)
|
|
@@ -45,8 +61,9 @@ class BedJetAccessory {
|
|
|
45
61
|
.onGet(() => this.bedjet.state.currentTemperature);
|
|
46
62
|
this.thermostatService.getCharacteristic(Characteristic.TargetTemperature)
|
|
47
63
|
.setProps({ minValue: 19, maxValue: 43, minStep: 0.5 })
|
|
48
|
-
.onGet(() => this.bedjet.state.targetTemperature)
|
|
64
|
+
.onGet(() => this.pendingTemp ?? this.bedjet.state.targetTemperature)
|
|
49
65
|
.onSet((value) => {
|
|
66
|
+
this.setPending(value, 'pendingTemp', 'pendingTempTimer');
|
|
50
67
|
if (this.tempDebounce) {
|
|
51
68
|
clearTimeout(this.tempDebounce);
|
|
52
69
|
}
|
|
@@ -66,6 +83,7 @@ class BedJetAccessory {
|
|
|
66
83
|
return 1; // HEAT / TURBO / EXTENDED_HEAT
|
|
67
84
|
})
|
|
68
85
|
.onSet((value) => {
|
|
86
|
+
this.setPending(value, 'pendingMode', 'pendingModeTimer');
|
|
69
87
|
const mode = TARGET_TO_MODE[value] ?? constants_1.OperatingMode.STANDBY;
|
|
70
88
|
this.bedjet.setOperatingMode(mode).catch(err => this.platform.log.error(`[${config.name}] setOperatingMode failed: ${err}`));
|
|
71
89
|
});
|
|
@@ -77,6 +95,9 @@ class BedJetAccessory {
|
|
|
77
95
|
? Characteristic.Active.ACTIVE
|
|
78
96
|
: Characteristic.Active.INACTIVE)
|
|
79
97
|
.onSet((value) => {
|
|
98
|
+
// pendingMode: 0=OFF, 1=HEAT (active), used to suppress stale BLE bounce
|
|
99
|
+
const pendingModeValue = value === Characteristic.Active.INACTIVE ? 0 : 1;
|
|
100
|
+
this.setPending(pendingModeValue, 'pendingMode', 'pendingModeTimer');
|
|
80
101
|
if (value === Characteristic.Active.INACTIVE) {
|
|
81
102
|
this.bedjet.setOperatingMode(constants_1.OperatingMode.STANDBY).catch(err => this.platform.log.error(`[${config.name}] setOperatingMode(STANDBY) failed: ${err}`));
|
|
82
103
|
}
|
|
@@ -89,8 +110,9 @@ class BedJetAccessory {
|
|
|
89
110
|
});
|
|
90
111
|
this.fanService.getCharacteristic(Characteristic.RotationSpeed)
|
|
91
112
|
.setProps({ minValue: 5, maxValue: 100, minStep: 5 })
|
|
92
|
-
.onGet(() => this.bedjet.state.fanSpeed)
|
|
113
|
+
.onGet(() => this.pendingFanSpeed ?? this.bedjet.state.fanSpeed)
|
|
93
114
|
.onSet((value) => {
|
|
115
|
+
this.setPending(value, 'pendingFanSpeed', 'pendingFanSpeedTimer');
|
|
94
116
|
if (this.fanDebounce) {
|
|
95
117
|
clearTimeout(this.fanDebounce);
|
|
96
118
|
}
|
|
@@ -122,18 +144,22 @@ class BedJetAccessory {
|
|
|
122
144
|
.getCharacteristic(Characteristic.TargetTemperature)
|
|
123
145
|
.setProps({ minValue: minTemp, maxValue: maxTemp });
|
|
124
146
|
this.thermostatService.updateCharacteristic(Characteristic.CurrentTemperature, clamp(state.currentTemperature, -270, 100));
|
|
125
|
-
|
|
126
|
-
this.
|
|
127
|
-
const
|
|
147
|
+
// Use pending (optimistic) values if set — suppresses stale BLE notification bounces
|
|
148
|
+
const targetTemp = this.pendingTemp ?? clamp(state.targetTemperature, minTemp, maxTemp);
|
|
149
|
+
const fanSpeed = this.pendingFanSpeed ?? clamp(state.fanSpeed, 5, 100);
|
|
150
|
+
const derivedTargetState = state.operatingMode === constants_1.OperatingMode.STANDBY || state.operatingMode === constants_1.OperatingMode.WAIT
|
|
128
151
|
? 0
|
|
129
152
|
: state.operatingMode === constants_1.OperatingMode.COOL || state.operatingMode === constants_1.OperatingMode.DRY
|
|
130
153
|
? 2
|
|
131
154
|
: 1;
|
|
155
|
+
const targetState = this.pendingMode ?? derivedTargetState;
|
|
156
|
+
this.thermostatService.updateCharacteristic(Characteristic.TargetTemperature, targetTemp);
|
|
157
|
+
this.thermostatService.updateCharacteristic(Characteristic.CurrentHeatingCoolingState, CURRENT_STATE_MAP[state.operatingMode] ?? 0);
|
|
132
158
|
this.thermostatService.updateCharacteristic(Characteristic.TargetHeatingCoolingState, targetState);
|
|
133
|
-
this.fanService.updateCharacteristic(Characteristic.Active,
|
|
159
|
+
this.fanService.updateCharacteristic(Characteristic.Active, targetState !== 0
|
|
134
160
|
? Characteristic.Active.ACTIVE
|
|
135
161
|
: Characteristic.Active.INACTIVE);
|
|
136
|
-
this.fanService.updateCharacteristic(Characteristic.RotationSpeed,
|
|
162
|
+
this.fanService.updateCharacteristic(Characteristic.RotationSpeed, fanSpeed);
|
|
137
163
|
}
|
|
138
164
|
}
|
|
139
165
|
exports.BedJetAccessory = BedJetAccessory;
|
package/dist/accessory.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"accessory.js","sourceRoot":"","sources":["../src/accessory.ts"],"names":[],"mappings":";;;AACA,4CAAyC;AACzC,kDAAmD;AAInD,mDAAmD;AACnD,MAAM,iBAAiB,GAAkC;IACvD,CAAC,yBAAa,CAAC,OAAO,CAAC,EAAQ,CAAC,EAAE,MAAM;IACxC,CAAC,yBAAa,CAAC,IAAI,CAAC,EAAW,CAAC,EAAE,OAAO;IACzC,CAAC,yBAAa,CAAC,KAAK,CAAC,EAAU,CAAC,EAAE,OAAO;IACzC,CAAC,yBAAa,CAAC,aAAa,CAAC,EAAE,CAAC,EAAE,OAAO;IACzC,CAAC,yBAAa,CAAC,IAAI,CAAC,EAAW,CAAC,EAAE,OAAO;IACzC,CAAC,yBAAa,CAAC,GAAG,CAAC,EAAY,CAAC,EAAE,OAAO;IACzC,CAAC,yBAAa,CAAC,IAAI,CAAC,EAAW,CAAC,EAAE,MAAM;CACzC,CAAC;AAEF,kDAAkD;AAClD,MAAM,cAAc,GAAkC;IACpD,CAAC,EAAE,yBAAa,CAAC,OAAO;IACxB,CAAC,EAAE,yBAAa,CAAC,IAAI;IACrB,CAAC,EAAE,yBAAa,CAAC,IAAI;IACrB,CAAC,EAAE,yBAAa,CAAC,IAAI,EAAE,2BAA2B;CACnD,CAAC;AAEF,MAAa,eAAe;
|
|
1
|
+
{"version":3,"file":"accessory.js","sourceRoot":"","sources":["../src/accessory.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
package/src/accessory.ts
CHANGED
|
@@ -32,6 +32,29 @@ export class BedJetAccessory {
|
|
|
32
32
|
private tempDebounce: NodeJS.Timeout | null = null;
|
|
33
33
|
private fanDebounce: NodeJS.Timeout | null = null;
|
|
34
34
|
|
|
35
|
+
// Optimistic values — held after a set to suppress stale BLE notification bounces
|
|
36
|
+
private pendingTemp: number | null = null;
|
|
37
|
+
private pendingTempTimer: NodeJS.Timeout | null = null;
|
|
38
|
+
private pendingFanSpeed: number | null = null;
|
|
39
|
+
private pendingFanSpeedTimer: NodeJS.Timeout | null = null;
|
|
40
|
+
private pendingMode: number | null = null;
|
|
41
|
+
private pendingModeTimer: NodeJS.Timeout | null = null;
|
|
42
|
+
|
|
43
|
+
private setPending<T>(
|
|
44
|
+
value: T,
|
|
45
|
+
store: 'pendingTemp' | 'pendingFanSpeed' | 'pendingMode',
|
|
46
|
+
timer: 'pendingTempTimer' | 'pendingFanSpeedTimer' | 'pendingModeTimer',
|
|
47
|
+
ms = 3000,
|
|
48
|
+
): void {
|
|
49
|
+
if (this[timer]) {
|
|
50
|
+
clearTimeout(this[timer] as NodeJS.Timeout);
|
|
51
|
+
}
|
|
52
|
+
(this as unknown as Record<string, unknown>)[store] = value;
|
|
53
|
+
(this as unknown as Record<string, unknown>)[timer] = setTimeout(() => {
|
|
54
|
+
(this as unknown as Record<string, unknown>)[store] = null;
|
|
55
|
+
}, ms);
|
|
56
|
+
}
|
|
57
|
+
|
|
35
58
|
constructor(
|
|
36
59
|
private readonly platform: BedJetPlatform,
|
|
37
60
|
private readonly accessory: PlatformAccessory,
|
|
@@ -59,8 +82,9 @@ export class BedJetAccessory {
|
|
|
59
82
|
|
|
60
83
|
this.thermostatService.getCharacteristic(Characteristic.TargetTemperature)
|
|
61
84
|
.setProps({ minValue: 19, maxValue: 43, minStep: 0.5 })
|
|
62
|
-
.onGet(() => this.bedjet.state.targetTemperature)
|
|
85
|
+
.onGet(() => this.pendingTemp ?? this.bedjet.state.targetTemperature)
|
|
63
86
|
.onSet((value: CharacteristicValue) => {
|
|
87
|
+
this.setPending(value as number, 'pendingTemp', 'pendingTempTimer');
|
|
64
88
|
if (this.tempDebounce) {
|
|
65
89
|
clearTimeout(this.tempDebounce);
|
|
66
90
|
}
|
|
@@ -82,6 +106,7 @@ export class BedJetAccessory {
|
|
|
82
106
|
return 1; // HEAT / TURBO / EXTENDED_HEAT
|
|
83
107
|
})
|
|
84
108
|
.onSet((value: CharacteristicValue) => {
|
|
109
|
+
this.setPending(value as number, 'pendingMode', 'pendingModeTimer');
|
|
85
110
|
const mode = TARGET_TO_MODE[value as number] ?? OperatingMode.STANDBY;
|
|
86
111
|
this.bedjet.setOperatingMode(mode).catch(err =>
|
|
87
112
|
this.platform.log.error(`[${config.name}] setOperatingMode failed: ${err}`),
|
|
@@ -99,6 +124,9 @@ export class BedJetAccessory {
|
|
|
99
124
|
: Characteristic.Active.INACTIVE,
|
|
100
125
|
)
|
|
101
126
|
.onSet((value: CharacteristicValue) => {
|
|
127
|
+
// pendingMode: 0=OFF, 1=HEAT (active), used to suppress stale BLE bounce
|
|
128
|
+
const pendingModeValue = value === Characteristic.Active.INACTIVE ? 0 : 1;
|
|
129
|
+
this.setPending(pendingModeValue, 'pendingMode', 'pendingModeTimer');
|
|
102
130
|
if (value === Characteristic.Active.INACTIVE) {
|
|
103
131
|
this.bedjet.setOperatingMode(OperatingMode.STANDBY).catch(err =>
|
|
104
132
|
this.platform.log.error(`[${config.name}] setOperatingMode(STANDBY) failed: ${err}`),
|
|
@@ -115,8 +143,9 @@ export class BedJetAccessory {
|
|
|
115
143
|
|
|
116
144
|
this.fanService.getCharacteristic(Characteristic.RotationSpeed)
|
|
117
145
|
.setProps({ minValue: 5, maxValue: 100, minStep: 5 })
|
|
118
|
-
.onGet(() => this.bedjet.state.fanSpeed)
|
|
146
|
+
.onGet(() => this.pendingFanSpeed ?? this.bedjet.state.fanSpeed)
|
|
119
147
|
.onSet((value: CharacteristicValue) => {
|
|
148
|
+
this.setPending(value as number, 'pendingFanSpeed', 'pendingFanSpeedTimer');
|
|
120
149
|
if (this.fanDebounce) {
|
|
121
150
|
clearTimeout(this.fanDebounce);
|
|
122
151
|
}
|
|
@@ -165,9 +194,21 @@ export class BedJetAccessory {
|
|
|
165
194
|
clamp(state.currentTemperature, -270, 100),
|
|
166
195
|
);
|
|
167
196
|
|
|
197
|
+
// Use pending (optimistic) values if set — suppresses stale BLE notification bounces
|
|
198
|
+
const targetTemp = this.pendingTemp ?? clamp(state.targetTemperature, minTemp, maxTemp);
|
|
199
|
+
const fanSpeed = this.pendingFanSpeed ?? clamp(state.fanSpeed, 5, 100);
|
|
200
|
+
|
|
201
|
+
const derivedTargetState =
|
|
202
|
+
state.operatingMode === OperatingMode.STANDBY || state.operatingMode === OperatingMode.WAIT
|
|
203
|
+
? 0
|
|
204
|
+
: state.operatingMode === OperatingMode.COOL || state.operatingMode === OperatingMode.DRY
|
|
205
|
+
? 2
|
|
206
|
+
: 1;
|
|
207
|
+
const targetState = this.pendingMode ?? derivedTargetState;
|
|
208
|
+
|
|
168
209
|
this.thermostatService.updateCharacteristic(
|
|
169
210
|
Characteristic.TargetTemperature,
|
|
170
|
-
|
|
211
|
+
targetTemp,
|
|
171
212
|
);
|
|
172
213
|
|
|
173
214
|
this.thermostatService.updateCharacteristic(
|
|
@@ -175,13 +216,6 @@ export class BedJetAccessory {
|
|
|
175
216
|
CURRENT_STATE_MAP[state.operatingMode] ?? 0,
|
|
176
217
|
);
|
|
177
218
|
|
|
178
|
-
const targetState =
|
|
179
|
-
state.operatingMode === OperatingMode.STANDBY || state.operatingMode === OperatingMode.WAIT
|
|
180
|
-
? 0
|
|
181
|
-
: state.operatingMode === OperatingMode.COOL || state.operatingMode === OperatingMode.DRY
|
|
182
|
-
? 2
|
|
183
|
-
: 1;
|
|
184
|
-
|
|
185
219
|
this.thermostatService.updateCharacteristic(
|
|
186
220
|
Characteristic.TargetHeatingCoolingState,
|
|
187
221
|
targetState,
|
|
@@ -189,14 +223,14 @@ export class BedJetAccessory {
|
|
|
189
223
|
|
|
190
224
|
this.fanService.updateCharacteristic(
|
|
191
225
|
Characteristic.Active,
|
|
192
|
-
|
|
226
|
+
targetState !== 0
|
|
193
227
|
? Characteristic.Active.ACTIVE
|
|
194
228
|
: Characteristic.Active.INACTIVE,
|
|
195
229
|
);
|
|
196
230
|
|
|
197
231
|
this.fanService.updateCharacteristic(
|
|
198
232
|
Characteristic.RotationSpeed,
|
|
199
|
-
|
|
233
|
+
fanSpeed,
|
|
200
234
|
);
|
|
201
235
|
}
|
|
202
236
|
}
|