homebridge-bedjet 0.2.7 → 0.2.8
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/config.schema.json +29 -0
- package/dist/accessory.d.ts +8 -0
- package/dist/accessory.js +45 -9
- package/dist/bedjet/types.d.ts +4 -0
- package/package.json +1 -1
- package/src/accessory.ts +58 -12
- package/src/bedjet/types.ts +7 -2
package/config.schema.json
CHANGED
|
@@ -31,6 +31,35 @@
|
|
|
31
31
|
"type": "integer",
|
|
32
32
|
"default": 30,
|
|
33
33
|
"description": "How long to scan for the device before giving up (default: 30)"
|
|
34
|
+
},
|
|
35
|
+
"defaultMode": {
|
|
36
|
+
"title": "Default Mode (when turned on)",
|
|
37
|
+
"type": "string",
|
|
38
|
+
"default": "heat",
|
|
39
|
+
"oneOf": [
|
|
40
|
+
{ "title": "Heat", "enum": ["heat"] },
|
|
41
|
+
{ "title": "Turbo", "enum": ["turbo"] },
|
|
42
|
+
{ "title": "Extended Heat", "enum": ["extendedHeat"] },
|
|
43
|
+
{ "title": "Cool (Fan Only)", "enum": ["cool"] },
|
|
44
|
+
{ "title": "Dry", "enum": ["dry"] }
|
|
45
|
+
],
|
|
46
|
+
"description": "Mode to activate when the BedJet is turned on from HomeKit"
|
|
47
|
+
},
|
|
48
|
+
"defaultTemperature": {
|
|
49
|
+
"title": "Default Temperature °C (when turned on)",
|
|
50
|
+
"type": "number",
|
|
51
|
+
"minimum": 19,
|
|
52
|
+
"maximum": 43,
|
|
53
|
+
"multipleOf": 0.5,
|
|
54
|
+
"description": "Target temperature to set when turned on. Range: 19–43°C (66–109°F). Leave blank to keep the BedJet's last-used temperature."
|
|
55
|
+
},
|
|
56
|
+
"defaultFanSpeed": {
|
|
57
|
+
"title": "Default Fan Speed % (when turned on)",
|
|
58
|
+
"type": "integer",
|
|
59
|
+
"minimum": 5,
|
|
60
|
+
"maximum": 100,
|
|
61
|
+
"multipleOf": 5,
|
|
62
|
+
"description": "Fan speed to set when turned on (5–100% in 5% steps). Leave blank to keep the BedJet's last-used speed."
|
|
34
63
|
}
|
|
35
64
|
}
|
|
36
65
|
}
|
package/dist/accessory.d.ts
CHANGED
|
@@ -18,5 +18,13 @@ export declare class BedJetAccessory {
|
|
|
18
18
|
private pendingModeTimer;
|
|
19
19
|
private setPending;
|
|
20
20
|
constructor(platform: BedJetPlatform, accessory: PlatformAccessory, config: BedJetConfig);
|
|
21
|
+
/**
|
|
22
|
+
* Set the operating mode, then optionally apply default temperature and fan
|
|
23
|
+
* speed from config. applyDefaults=true when turning on from off.
|
|
24
|
+
* applyMode=true when the mode itself should come from defaultMode config
|
|
25
|
+
* (fan turn-on path); false when HomeKit supplied the mode explicitly
|
|
26
|
+
* (thermostat path).
|
|
27
|
+
*/
|
|
28
|
+
private _applyModeAndDefaults;
|
|
21
29
|
private _syncHomeKit;
|
|
22
30
|
}
|
package/dist/accessory.js
CHANGED
|
@@ -3,6 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.BedJetAccessory = void 0;
|
|
4
4
|
const BedJet_1 = require("./bedjet/BedJet");
|
|
5
5
|
const constants_1 = require("./bedjet/constants");
|
|
6
|
+
const DEFAULT_MODE_MAP = {
|
|
7
|
+
heat: constants_1.OperatingMode.HEAT,
|
|
8
|
+
turbo: constants_1.OperatingMode.TURBO,
|
|
9
|
+
extendedHeat: constants_1.OperatingMode.EXTENDED_HEAT,
|
|
10
|
+
cool: constants_1.OperatingMode.COOL,
|
|
11
|
+
dry: constants_1.OperatingMode.DRY,
|
|
12
|
+
};
|
|
6
13
|
// OperatingMode → CurrentHeatingCoolingState value
|
|
7
14
|
const CURRENT_STATE_MAP = {
|
|
8
15
|
[constants_1.OperatingMode.STANDBY]: 0, // OFF
|
|
@@ -84,8 +91,12 @@ class BedJetAccessory {
|
|
|
84
91
|
})
|
|
85
92
|
.onSet((value) => {
|
|
86
93
|
this.setPending(value, 'pendingMode', 'pendingModeTimer');
|
|
94
|
+
const wasOff = this.bedjet.state.operatingMode === constants_1.OperatingMode.STANDBY
|
|
95
|
+
|| this.bedjet.state.operatingMode === constants_1.OperatingMode.WAIT;
|
|
96
|
+
const turningOn = value !== 0;
|
|
87
97
|
const mode = TARGET_TO_MODE[value] ?? constants_1.OperatingMode.STANDBY;
|
|
88
|
-
|
|
98
|
+
// Apply the requested mode, then defaults (temp/fan) if turning on from off
|
|
99
|
+
this._applyModeAndDefaults(mode, wasOff && turningOn, false).catch(err => this.platform.log.error(`[${config.name}] setOperatingMode failed: ${err}`));
|
|
89
100
|
});
|
|
90
101
|
// FanV2 service
|
|
91
102
|
this.fanService = this.accessory.getService(Service.Fanv2)
|
|
@@ -95,17 +106,16 @@ class BedJetAccessory {
|
|
|
95
106
|
? Characteristic.Active.ACTIVE
|
|
96
107
|
: Characteristic.Active.INACTIVE)
|
|
97
108
|
.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');
|
|
101
109
|
if (value === Characteristic.Active.INACTIVE) {
|
|
110
|
+
this.setPending(0, 'pendingMode', 'pendingModeTimer');
|
|
102
111
|
this.bedjet.setOperatingMode(constants_1.OperatingMode.STANDBY).catch(err => this.platform.log.error(`[${config.name}] setOperatingMode(STANDBY) failed: ${err}`));
|
|
103
112
|
}
|
|
104
|
-
else {
|
|
105
|
-
//
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
113
|
+
else if (this.bedjet.state.operatingMode === constants_1.OperatingMode.STANDBY) {
|
|
114
|
+
// Turning on — use configured default mode and apply all defaults
|
|
115
|
+
const mode = this.config.defaultMode
|
|
116
|
+
? DEFAULT_MODE_MAP[this.config.defaultMode]
|
|
117
|
+
: constants_1.OperatingMode.HEAT;
|
|
118
|
+
this._applyModeAndDefaults(mode, true, true).catch(err => this.platform.log.error(`[${config.name}] turn on failed: ${err}`));
|
|
109
119
|
}
|
|
110
120
|
});
|
|
111
121
|
this.fanService.getCharacteristic(Characteristic.RotationSpeed)
|
|
@@ -133,6 +143,32 @@ class BedJetAccessory {
|
|
|
133
143
|
// Start connecting — errors are logged but don't crash Homebridge
|
|
134
144
|
this.bedjet.connect().catch(err => this.platform.log.error(`[${config.name}] Initial connect failed: ${err}`));
|
|
135
145
|
}
|
|
146
|
+
/**
|
|
147
|
+
* Set the operating mode, then optionally apply default temperature and fan
|
|
148
|
+
* speed from config. applyDefaults=true when turning on from off.
|
|
149
|
+
* applyMode=true when the mode itself should come from defaultMode config
|
|
150
|
+
* (fan turn-on path); false when HomeKit supplied the mode explicitly
|
|
151
|
+
* (thermostat path).
|
|
152
|
+
*/
|
|
153
|
+
async _applyModeAndDefaults(mode, applyDefaults, applyMode) {
|
|
154
|
+
const { config } = this;
|
|
155
|
+
// Determine HomeKit target state for pending optimistic value
|
|
156
|
+
const pendingState = mode === constants_1.OperatingMode.STANDBY ? 0
|
|
157
|
+
: mode === constants_1.OperatingMode.COOL || mode === constants_1.OperatingMode.DRY ? 2
|
|
158
|
+
: 1;
|
|
159
|
+
this.setPending(pendingState, 'pendingMode', 'pendingModeTimer', 5000);
|
|
160
|
+
await this.bedjet.setOperatingMode(mode);
|
|
161
|
+
if (applyDefaults) {
|
|
162
|
+
if (config.defaultTemperature !== undefined) {
|
|
163
|
+
this.setPending(config.defaultTemperature, 'pendingTemp', 'pendingTempTimer', 5000);
|
|
164
|
+
await this.bedjet.setTemperature(config.defaultTemperature);
|
|
165
|
+
}
|
|
166
|
+
if (config.defaultFanSpeed !== undefined) {
|
|
167
|
+
this.setPending(config.defaultFanSpeed, 'pendingFanSpeed', 'pendingFanSpeedTimer', 5000);
|
|
168
|
+
await this.bedjet.setFanSpeed(config.defaultFanSpeed);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
136
172
|
_syncHomeKit(state) {
|
|
137
173
|
const { Characteristic } = this.platform.api.hap;
|
|
138
174
|
// Clamp helper — keeps values within the bounds HomeKit expects
|
package/dist/bedjet/types.d.ts
CHANGED
|
@@ -17,9 +17,13 @@ export interface BedJetState {
|
|
|
17
17
|
unitsSetup?: boolean;
|
|
18
18
|
notificationCode?: number;
|
|
19
19
|
}
|
|
20
|
+
export type DefaultMode = 'heat' | 'turbo' | 'extendedHeat' | 'cool' | 'dry';
|
|
20
21
|
export interface BedJetConfig {
|
|
21
22
|
name: string;
|
|
22
23
|
address: string;
|
|
23
24
|
scanTimeout?: number;
|
|
25
|
+
defaultMode?: DefaultMode;
|
|
26
|
+
defaultTemperature?: number;
|
|
27
|
+
defaultFanSpeed?: number;
|
|
24
28
|
}
|
|
25
29
|
export declare const DEFAULT_STATE: BedJetState;
|
package/package.json
CHANGED
package/src/accessory.ts
CHANGED
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
import type { CharacteristicValue, PlatformAccessory, Service } from 'homebridge';
|
|
2
2
|
import { BedJet } from './bedjet/BedJet';
|
|
3
3
|
import { OperatingMode } from './bedjet/constants';
|
|
4
|
-
import type { BedJetConfig, BedJetState } from './bedjet/types';
|
|
4
|
+
import type { BedJetConfig, BedJetState, DefaultMode } from './bedjet/types';
|
|
5
5
|
import type { BedJetPlatform } from './platform';
|
|
6
6
|
|
|
7
|
+
const DEFAULT_MODE_MAP: Record<DefaultMode, OperatingMode> = {
|
|
8
|
+
heat: OperatingMode.HEAT,
|
|
9
|
+
turbo: OperatingMode.TURBO,
|
|
10
|
+
extendedHeat: OperatingMode.EXTENDED_HEAT,
|
|
11
|
+
cool: OperatingMode.COOL,
|
|
12
|
+
dry: OperatingMode.DRY,
|
|
13
|
+
};
|
|
14
|
+
|
|
7
15
|
// OperatingMode → CurrentHeatingCoolingState value
|
|
8
16
|
const CURRENT_STATE_MAP: Record<OperatingMode, number> = {
|
|
9
17
|
[OperatingMode.STANDBY]: 0, // OFF
|
|
@@ -107,8 +115,12 @@ export class BedJetAccessory {
|
|
|
107
115
|
})
|
|
108
116
|
.onSet((value: CharacteristicValue) => {
|
|
109
117
|
this.setPending(value as number, 'pendingMode', 'pendingModeTimer');
|
|
118
|
+
const wasOff = this.bedjet.state.operatingMode === OperatingMode.STANDBY
|
|
119
|
+
|| this.bedjet.state.operatingMode === OperatingMode.WAIT;
|
|
120
|
+
const turningOn = (value as number) !== 0;
|
|
110
121
|
const mode = TARGET_TO_MODE[value as number] ?? OperatingMode.STANDBY;
|
|
111
|
-
|
|
122
|
+
// Apply the requested mode, then defaults (temp/fan) if turning on from off
|
|
123
|
+
this._applyModeAndDefaults(mode, wasOff && turningOn, false).catch(err =>
|
|
112
124
|
this.platform.log.error(`[${config.name}] setOperatingMode failed: ${err}`),
|
|
113
125
|
);
|
|
114
126
|
});
|
|
@@ -124,20 +136,19 @@ export class BedJetAccessory {
|
|
|
124
136
|
: Characteristic.Active.INACTIVE,
|
|
125
137
|
)
|
|
126
138
|
.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');
|
|
130
139
|
if (value === Characteristic.Active.INACTIVE) {
|
|
140
|
+
this.setPending(0, 'pendingMode', 'pendingModeTimer');
|
|
131
141
|
this.bedjet.setOperatingMode(OperatingMode.STANDBY).catch(err =>
|
|
132
142
|
this.platform.log.error(`[${config.name}] setOperatingMode(STANDBY) failed: ${err}`),
|
|
133
143
|
);
|
|
134
|
-
} else {
|
|
135
|
-
//
|
|
136
|
-
|
|
137
|
-
this.
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
144
|
+
} else if (this.bedjet.state.operatingMode === OperatingMode.STANDBY) {
|
|
145
|
+
// Turning on — use configured default mode and apply all defaults
|
|
146
|
+
const mode = this.config.defaultMode
|
|
147
|
+
? DEFAULT_MODE_MAP[this.config.defaultMode]
|
|
148
|
+
: OperatingMode.HEAT;
|
|
149
|
+
this._applyModeAndDefaults(mode, true, true).catch(err =>
|
|
150
|
+
this.platform.log.error(`[${config.name}] turn on failed: ${err}`),
|
|
151
|
+
);
|
|
141
152
|
}
|
|
142
153
|
});
|
|
143
154
|
|
|
@@ -174,6 +185,41 @@ export class BedJetAccessory {
|
|
|
174
185
|
);
|
|
175
186
|
}
|
|
176
187
|
|
|
188
|
+
/**
|
|
189
|
+
* Set the operating mode, then optionally apply default temperature and fan
|
|
190
|
+
* speed from config. applyDefaults=true when turning on from off.
|
|
191
|
+
* applyMode=true when the mode itself should come from defaultMode config
|
|
192
|
+
* (fan turn-on path); false when HomeKit supplied the mode explicitly
|
|
193
|
+
* (thermostat path).
|
|
194
|
+
*/
|
|
195
|
+
private async _applyModeAndDefaults(
|
|
196
|
+
mode: OperatingMode,
|
|
197
|
+
applyDefaults: boolean,
|
|
198
|
+
applyMode: boolean,
|
|
199
|
+
): Promise<void> {
|
|
200
|
+
const { config } = this;
|
|
201
|
+
|
|
202
|
+
// Determine HomeKit target state for pending optimistic value
|
|
203
|
+
const pendingState =
|
|
204
|
+
mode === OperatingMode.STANDBY ? 0
|
|
205
|
+
: mode === OperatingMode.COOL || mode === OperatingMode.DRY ? 2
|
|
206
|
+
: 1;
|
|
207
|
+
this.setPending(pendingState, 'pendingMode', 'pendingModeTimer', 5000);
|
|
208
|
+
|
|
209
|
+
await this.bedjet.setOperatingMode(mode);
|
|
210
|
+
|
|
211
|
+
if (applyDefaults) {
|
|
212
|
+
if (config.defaultTemperature !== undefined) {
|
|
213
|
+
this.setPending(config.defaultTemperature, 'pendingTemp', 'pendingTempTimer', 5000);
|
|
214
|
+
await this.bedjet.setTemperature(config.defaultTemperature);
|
|
215
|
+
}
|
|
216
|
+
if (config.defaultFanSpeed !== undefined) {
|
|
217
|
+
this.setPending(config.defaultFanSpeed, 'pendingFanSpeed', 'pendingFanSpeedTimer', 5000);
|
|
218
|
+
await this.bedjet.setFanSpeed(config.defaultFanSpeed);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
177
223
|
private _syncHomeKit(state: BedJetState): void {
|
|
178
224
|
const { Characteristic } = this.platform.api.hap;
|
|
179
225
|
|
package/src/bedjet/types.ts
CHANGED
|
@@ -20,10 +20,15 @@ export interface BedJetState {
|
|
|
20
20
|
notificationCode?: number;
|
|
21
21
|
}
|
|
22
22
|
|
|
23
|
+
export type DefaultMode = 'heat' | 'turbo' | 'extendedHeat' | 'cool' | 'dry';
|
|
24
|
+
|
|
23
25
|
export interface BedJetConfig {
|
|
24
26
|
name: string;
|
|
25
|
-
address: string;
|
|
26
|
-
scanTimeout?: number;
|
|
27
|
+
address: string; // BLE MAC e.g. "AA:BB:CC:DD:EE:FF"
|
|
28
|
+
scanTimeout?: number; // seconds (default 30)
|
|
29
|
+
defaultMode?: DefaultMode; // mode to activate when turned on from HomeKit
|
|
30
|
+
defaultTemperature?: number; // °C, applied on turn-on
|
|
31
|
+
defaultFanSpeed?: number; // percent 5–100, applied on turn-on
|
|
27
32
|
}
|
|
28
33
|
|
|
29
34
|
export const DEFAULT_STATE: BedJetState = {
|