homebridge-bedjet 0.1.0

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.
@@ -0,0 +1,330 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BedJet = void 0;
4
+ const events_1 = require("events");
5
+ // noble is a singleton process-level instance; require() gives us the live object.
6
+ // The default ESM export doesn't expose `.state` in its type — we patch it here.
7
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
8
+ const noble = require('@abandonware/noble');
9
+ const constants_1 = require("./constants");
10
+ const types_1 = require("./types");
11
+ // noble strips hyphens from UUIDs internally
12
+ const normalize = (uuid) => uuid.replace(/-/g, '').toLowerCase();
13
+ const NORM_STATUS_UUID = normalize(constants_1.BEDJET3_STATUS_UUID);
14
+ const NORM_NAME_UUID = normalize(constants_1.BEDJET3_NAME_UUID);
15
+ const NORM_COMMAND_UUID = normalize(constants_1.BEDJET3_COMMAND_UUID);
16
+ const NORM_SERVICE_UUID = normalize(constants_1.BEDJET3_SERVICE_UUID);
17
+ class BedJet extends events_1.EventEmitter {
18
+ constructor(config, log) {
19
+ super();
20
+ this.config = config;
21
+ this.log = log;
22
+ this.peripheral = null;
23
+ this.commandChar = null;
24
+ this.statusChar = null;
25
+ this.disconnectTimer = null;
26
+ this.staleTimer = null;
27
+ this.reconnectAttempts = 0;
28
+ this.connecting = false;
29
+ this._state = { ...types_1.DEFAULT_STATE };
30
+ this.deviceName = null;
31
+ this.firmwareVersion = null;
32
+ }
33
+ get state() {
34
+ return this._state;
35
+ }
36
+ get name() {
37
+ return this.deviceName ?? this.config.name;
38
+ }
39
+ get firmware() {
40
+ return this.firmwareVersion;
41
+ }
42
+ // ── Connection ────────────────────────────────────────────────────────────
43
+ async connect() {
44
+ if (this.connecting) {
45
+ return;
46
+ }
47
+ this.connecting = true;
48
+ try {
49
+ await this._scan();
50
+ }
51
+ catch (err) {
52
+ this.connecting = false;
53
+ throw err;
54
+ }
55
+ this.connecting = false;
56
+ }
57
+ _scan() {
58
+ return new Promise((resolve, reject) => {
59
+ const targetAddress = this.config.address.toLowerCase().replace(/:/g, '');
60
+ const timeoutMs = (this.config.scanTimeout ?? 30) * 1000;
61
+ const scanTimeout = setTimeout(() => {
62
+ noble.stopScanning();
63
+ noble.removeListener('discover', onDiscover);
64
+ reject(new Error(`[${this.config.name}] Scan timed out after ${this.config.scanTimeout ?? 30}s`));
65
+ }, timeoutMs);
66
+ const onDiscover = async (peripheral) => {
67
+ const addr = peripheral.address.toLowerCase().replace(/:/g, '');
68
+ if (addr !== targetAddress) {
69
+ return;
70
+ }
71
+ clearTimeout(scanTimeout);
72
+ noble.stopScanning();
73
+ noble.removeListener('discover', onDiscover);
74
+ try {
75
+ await this._connectPeripheral(peripheral);
76
+ resolve();
77
+ }
78
+ catch (err) {
79
+ reject(err);
80
+ }
81
+ };
82
+ noble.on('discover', onDiscover);
83
+ const startScan = () => {
84
+ // Pass full UUID with hyphens — noble handles normalisation for scanning
85
+ noble.startScanning([constants_1.BEDJET3_SERVICE_UUID], false, (err) => {
86
+ if (err) {
87
+ clearTimeout(scanTimeout);
88
+ noble.removeListener('discover', onDiscover);
89
+ reject(new Error(`[${this.config.name}] startScanning failed: ${err}`));
90
+ }
91
+ });
92
+ };
93
+ if (noble.state === 'poweredOn') {
94
+ startScan();
95
+ }
96
+ else {
97
+ noble.once('stateChange', (state) => {
98
+ if (state === 'poweredOn') {
99
+ startScan();
100
+ }
101
+ else {
102
+ clearTimeout(scanTimeout);
103
+ noble.removeListener('discover', onDiscover);
104
+ reject(new Error(`[${this.config.name}] Bluetooth not available (state: ${state})`));
105
+ }
106
+ });
107
+ }
108
+ });
109
+ }
110
+ async _connectPeripheral(peripheral) {
111
+ this.peripheral = peripheral;
112
+ this.log.info(`[${this.config.name}] Connecting to ${peripheral.address}…`);
113
+ peripheral.once('disconnect', () => this._onDisconnected());
114
+ await peripheral.connectAsync();
115
+ this.log.debug(`[${this.config.name}] Connected — discovering services…`);
116
+ const { characteristics } = await peripheral.discoverSomeServicesAndCharacteristicsAsync([NORM_SERVICE_UUID], [NORM_STATUS_UUID, NORM_NAME_UUID, NORM_COMMAND_UUID]);
117
+ for (const char of characteristics) {
118
+ const uuid = normalize(char.uuid);
119
+ if (uuid === NORM_STATUS_UUID) {
120
+ this.statusChar = char;
121
+ }
122
+ else if (uuid === NORM_COMMAND_UUID) {
123
+ this.commandChar = char;
124
+ }
125
+ }
126
+ if (!this.commandChar || !this.statusChar) {
127
+ throw new Error(`[${this.config.name}] Required characteristics not found`);
128
+ }
129
+ // Subscribe to notifications on the status characteristic
130
+ await this.statusChar.subscribeAsync();
131
+ this.statusChar.on('data', (data) => this._handleNotification(data));
132
+ // Read extended status and device name
133
+ await this._readDeviceStatus();
134
+ await this._readDeviceName();
135
+ this.reconnectAttempts = 0;
136
+ this._state = { ...this._state, isConnected: true };
137
+ this._resetDisconnectTimer();
138
+ this._resetStaleTimer();
139
+ this.emit('connected');
140
+ this.emit('stateChange', this._state);
141
+ this.log.info(`[${this.config.name}] Ready (firmware: ${this.firmwareVersion ?? 'unknown'})`);
142
+ }
143
+ // ── Packet parsing ────────────────────────────────────────────────────────
144
+ _handleNotification(data) {
145
+ if (data.length !== constants_1.BEDJET3_NOTIFICATION_LENGTH) {
146
+ return;
147
+ }
148
+ this._state = {
149
+ ...this._state,
150
+ hoursRemaining: data[4],
151
+ minutesRemaining: data[5],
152
+ secondsRemaining: data[6],
153
+ currentTemperature: data[7] / 2,
154
+ targetTemperature: data[8] / 2,
155
+ operatingMode: data[9],
156
+ fanSpeed: (data[10] + 1) * 5,
157
+ // data[11] = maximum_hours, data[12] = maximum_minutes (not stored in state)
158
+ minimumTemperature: data[13] / 2,
159
+ maximumTemperature: data[14] / 2,
160
+ // bytes [15–16] = turbo_time uint16 big-endian
161
+ turboTimeSeconds: (data[15] << 8) | data[16],
162
+ ambientTemperature: data[17] / 2,
163
+ // data[18] = shutdown_reason (not stored)
164
+ isConnected: true,
165
+ };
166
+ this._resetStaleTimer();
167
+ this.emit('stateChange', this._state);
168
+ }
169
+ _handleStatusRead(data) {
170
+ if (data.length !== constants_1.BEDJET3_STATUS_LENGTH) {
171
+ return;
172
+ }
173
+ const flags = data[7];
174
+ this._state = {
175
+ ...this._state,
176
+ isDualZone: (data[2] & 0x02) !== 0,
177
+ // flags bits MSB→LSB: [_, _, connTestPassed, ledEnabled, _, unitsSetup, _, beepsMuted]
178
+ connTestPassed: (flags & 0x20) !== 0,
179
+ ledEnabled: (flags & 0x10) !== 0,
180
+ unitsSetup: (flags & 0x04) !== 0,
181
+ beepsMuted: (flags & 0x01) !== 0,
182
+ notificationCode: data[9],
183
+ };
184
+ }
185
+ async _readDeviceName() {
186
+ if (!this.peripheral) {
187
+ return;
188
+ }
189
+ try {
190
+ // Rediscover to get the name characteristic
191
+ const { characteristics } = await this.peripheral.discoverSomeServicesAndCharacteristicsAsync([NORM_SERVICE_UUID], [NORM_NAME_UUID]);
192
+ const nameChar = characteristics.find(c => normalize(c.uuid) === NORM_NAME_UUID);
193
+ if (nameChar) {
194
+ const data = await nameChar.readAsync();
195
+ this.deviceName = data.toString('utf8').replace(/\0/g, '').trim();
196
+ this.log.debug(`[${this.config.name}] Device name: ${this.deviceName}`);
197
+ }
198
+ }
199
+ catch (err) {
200
+ this.log.warn(`[${this.config.name}] Could not read device name: ${err}`);
201
+ }
202
+ }
203
+ async _readDeviceStatus() {
204
+ if (!this.statusChar) {
205
+ return;
206
+ }
207
+ try {
208
+ const data = await this.statusChar.readAsync();
209
+ this._handleStatusRead(data);
210
+ }
211
+ catch (err) {
212
+ this.log.warn(`[${this.config.name}] Could not read device status: ${err}`);
213
+ }
214
+ }
215
+ // ── Commands ──────────────────────────────────────────────────────────────
216
+ async _sendCommand(command, ...args) {
217
+ if (!this.commandChar) {
218
+ throw new Error(`[${this.config.name}] Not connected`);
219
+ }
220
+ const buf = Buffer.from([command, ...args]);
221
+ try {
222
+ // withoutResponse = false (write with response) — required for V3
223
+ await this.commandChar.writeAsync(buf, false);
224
+ this._resetDisconnectTimer();
225
+ }
226
+ catch (err) {
227
+ this.log.error(`[${this.config.name}] Command 0x${command.toString(16)} failed: ${err}`);
228
+ throw err;
229
+ }
230
+ }
231
+ async setTemperature(celsius) {
232
+ await this._sendCommand(constants_1.BedJetCommand.SET_TEMPERATURE, Math.round(celsius * 2));
233
+ }
234
+ async setFanSpeed(percent) {
235
+ const step = Math.max(0, Math.min(19, Math.round(percent / 5) - 1));
236
+ await this._sendCommand(constants_1.BedJetCommand.SET_FAN, step);
237
+ }
238
+ async setOperatingMode(mode) {
239
+ await this._sendCommand(constants_1.BedJetCommand.BUTTON, constants_1.OPERATING_MODE_BUTTON_MAP[mode]);
240
+ }
241
+ async pressButton(button) {
242
+ await this._sendCommand(constants_1.BedJetCommand.BUTTON, button);
243
+ }
244
+ async setClock(hour, minute) {
245
+ await this._sendCommand(constants_1.BedJetCommand.SET_CLOCK, hour, minute);
246
+ }
247
+ async setRuntimeRemaining(hours, minutes) {
248
+ await this._sendCommand(constants_1.BedJetCommand.SET_RUNTIME, hours, minutes);
249
+ }
250
+ async setLed(on) {
251
+ await this.pressButton(on ? constants_1.BedJetButton.LED_ON : constants_1.BedJetButton.LED_OFF);
252
+ }
253
+ async setMuted(muted) {
254
+ await this.pressButton(muted ? constants_1.BedJetButton.MUTE : constants_1.BedJetButton.UNMUTE);
255
+ }
256
+ // ── Timers ────────────────────────────────────────────────────────────────
257
+ _resetDisconnectTimer() {
258
+ if (this.disconnectTimer) {
259
+ clearTimeout(this.disconnectTimer);
260
+ }
261
+ this.disconnectTimer = setTimeout(async () => {
262
+ this.log.debug(`[${this.config.name}] Inactivity timeout — disconnecting`);
263
+ await this.disconnect();
264
+ }, constants_1.DISCONNECT_DELAY_MS);
265
+ }
266
+ // Mark stale and update HomeKit if no notification arrives within 65s
267
+ _resetStaleTimer() {
268
+ if (this.staleTimer) {
269
+ clearTimeout(this.staleTimer);
270
+ }
271
+ this.staleTimer = setTimeout(() => {
272
+ this.log.warn(`[${this.config.name}] No notification received — marking disconnected`);
273
+ this._state = { ...this._state, isConnected: false };
274
+ this.emit('stateChange', this._state);
275
+ }, 65000);
276
+ }
277
+ // ── Disconnect / reconnect ────────────────────────────────────────────────
278
+ _onDisconnected() {
279
+ this.commandChar = null;
280
+ this.statusChar = null;
281
+ if (this.disconnectTimer) {
282
+ clearTimeout(this.disconnectTimer);
283
+ this.disconnectTimer = null;
284
+ }
285
+ if (this.staleTimer) {
286
+ clearTimeout(this.staleTimer);
287
+ this.staleTimer = null;
288
+ }
289
+ this._state = { ...this._state, isConnected: false };
290
+ this.emit('disconnected');
291
+ this.emit('stateChange', this._state);
292
+ if (this.reconnectAttempts < constants_1.MAX_RECONNECT_ATTEMPTS) {
293
+ // Exponential backoff: 2s, 4s, 8s, 16s, 32s
294
+ const delay = Math.pow(2, this.reconnectAttempts + 1) * 1000;
295
+ this.reconnectAttempts++;
296
+ this.log.info(`[${this.config.name}] Disconnected — reconnecting in ${delay / 1000}s ` +
297
+ `(attempt ${this.reconnectAttempts}/${constants_1.MAX_RECONNECT_ATTEMPTS})`);
298
+ setTimeout(() => {
299
+ this.connect().catch(err => this.log.error(`[${this.config.name}] Reconnect failed: ${err}`));
300
+ }, delay);
301
+ }
302
+ else {
303
+ this.log.error(`[${this.config.name}] Max reconnect attempts reached — giving up`);
304
+ this.emit('maxReconnectReached');
305
+ }
306
+ }
307
+ async disconnect() {
308
+ if (this.disconnectTimer) {
309
+ clearTimeout(this.disconnectTimer);
310
+ this.disconnectTimer = null;
311
+ }
312
+ if (this.staleTimer) {
313
+ clearTimeout(this.staleTimer);
314
+ this.staleTimer = null;
315
+ }
316
+ // Setting max attempts prevents the disconnect handler from triggering a reconnect
317
+ this.reconnectAttempts = constants_1.MAX_RECONNECT_ATTEMPTS;
318
+ if (this.peripheral) {
319
+ try {
320
+ await this.peripheral.disconnectAsync();
321
+ }
322
+ catch {
323
+ // ignore errors during intentional disconnect
324
+ }
325
+ this.peripheral = null;
326
+ }
327
+ }
328
+ }
329
+ exports.BedJet = BedJet;
330
+ //# sourceMappingURL=BedJet.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BedJet.js","sourceRoot":"","sources":["../../src/bedjet/BedJet.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,63 @@
1
+ export declare const BEDJET3_SERVICE_UUID = "00001000-bed0-0080-aa55-4265644a6574";
2
+ export declare const BEDJET3_STATUS_UUID = "00002000-bed0-0080-aa55-4265644a6574";
3
+ export declare const BEDJET3_NAME_UUID = "00002001-bed0-0080-aa55-4265644a6574";
4
+ export declare const BEDJET3_SSID_UUID = "00002002-bed0-0080-aa55-4265644a6574";
5
+ export declare const BEDJET3_PASSWORD_UUID = "00002003-bed0-0080-aa55-4265644a6574";
6
+ export declare const BEDJET3_COMMAND_UUID = "00002004-bed0-0080-aa55-4265644a6574";
7
+ export declare const BEDJET3_BIODATA_UUID = "00002005-bed0-0080-aa55-4265644a6574";
8
+ export declare const BEDJET3_BIODATA_FULL_UUID = "00002006-bed0-0080-aa55-4265644a6574";
9
+ export declare const BEDJET3_NOTIFICATION_LENGTH = 20;
10
+ export declare const BEDJET3_STATUS_LENGTH = 11;
11
+ export declare const DISCONNECT_DELAY_MS = 60000;
12
+ export declare const MAX_RECONNECT_ATTEMPTS = 5;
13
+ export declare enum OperatingMode {
14
+ STANDBY = 0,
15
+ HEAT = 1,
16
+ TURBO = 2,
17
+ EXTENDED_HEAT = 3,
18
+ COOL = 4,// fan only — no compressor
19
+ DRY = 5,
20
+ WAIT = 6
21
+ }
22
+ export declare enum BedJetCommand {
23
+ BUTTON = 1,
24
+ SET_RUNTIME = 2,
25
+ SET_TEMPERATURE = 3,
26
+ SET_STEP = 4,
27
+ SET_HACKS = 5,
28
+ STATUS = 6,
29
+ SET_FAN = 7,
30
+ SET_CLOCK = 8,
31
+ SET_BIO = 64,
32
+ GET_BIO = 65
33
+ }
34
+ export declare enum BedJetButton {
35
+ OFF = 1,
36
+ COOL = 2,
37
+ HEAT = 3,
38
+ TURBO = 4,
39
+ DRY = 5,
40
+ EXTENDED_HEAT = 6,
41
+ M1 = 32,
42
+ M2 = 33,
43
+ M3 = 34,
44
+ DEBUG_ON = 64,
45
+ DEBUG_OFF = 65,
46
+ CONNECTION_TEST = 66,
47
+ UPDATE_FIRMWARE = 67,
48
+ LED_ON = 70,
49
+ LED_OFF = 71,
50
+ MUTE = 72,
51
+ UNMUTE = 73,
52
+ NOTIFY_ACK = 82,
53
+ BIORHYTHM_1 = 128,
54
+ BIORHYTHM_2 = 129,
55
+ BIORHYTHM_3 = 130
56
+ }
57
+ export declare const OPERATING_MODE_BUTTON_MAP: Record<OperatingMode, BedJetButton>;
58
+ export declare enum BioDataRequest {
59
+ DEVICE_NAME = 0,
60
+ MEMORY_NAMES = 1,
61
+ BIORHYTHM_NAMES = 4,
62
+ FIRMWARE_VERSIONS = 32
63
+ }
@@ -0,0 +1,84 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BioDataRequest = exports.OPERATING_MODE_BUTTON_MAP = exports.BedJetButton = exports.BedJetCommand = exports.OperatingMode = exports.MAX_RECONNECT_ATTEMPTS = exports.DISCONNECT_DELAY_MS = exports.BEDJET3_STATUS_LENGTH = exports.BEDJET3_NOTIFICATION_LENGTH = exports.BEDJET3_BIODATA_FULL_UUID = exports.BEDJET3_BIODATA_UUID = exports.BEDJET3_COMMAND_UUID = exports.BEDJET3_PASSWORD_UUID = exports.BEDJET3_SSID_UUID = exports.BEDJET3_NAME_UUID = exports.BEDJET3_STATUS_UUID = exports.BEDJET3_SERVICE_UUID = void 0;
4
+ // BedJet V3 BLE UUIDs (confirmed from ESPHome + pybedjet)
5
+ exports.BEDJET3_SERVICE_UUID = '00001000-bed0-0080-aa55-4265644a6574';
6
+ exports.BEDJET3_STATUS_UUID = '00002000-bed0-0080-aa55-4265644a6574';
7
+ exports.BEDJET3_NAME_UUID = '00002001-bed0-0080-aa55-4265644a6574';
8
+ exports.BEDJET3_SSID_UUID = '00002002-bed0-0080-aa55-4265644a6574';
9
+ exports.BEDJET3_PASSWORD_UUID = '00002003-bed0-0080-aa55-4265644a6574';
10
+ exports.BEDJET3_COMMAND_UUID = '00002004-bed0-0080-aa55-4265644a6574';
11
+ exports.BEDJET3_BIODATA_UUID = '00002005-bed0-0080-aa55-4265644a6574';
12
+ exports.BEDJET3_BIODATA_FULL_UUID = '00002006-bed0-0080-aa55-4265644a6574';
13
+ // Discard notification packets that are not exactly this length
14
+ exports.BEDJET3_NOTIFICATION_LENGTH = 20;
15
+ // Discard direct status reads that are not exactly this length
16
+ exports.BEDJET3_STATUS_LENGTH = 11;
17
+ exports.DISCONNECT_DELAY_MS = 60000;
18
+ exports.MAX_RECONNECT_ATTEMPTS = 5;
19
+ // byte [9] of notification packet
20
+ var OperatingMode;
21
+ (function (OperatingMode) {
22
+ OperatingMode[OperatingMode["STANDBY"] = 0] = "STANDBY";
23
+ OperatingMode[OperatingMode["HEAT"] = 1] = "HEAT";
24
+ OperatingMode[OperatingMode["TURBO"] = 2] = "TURBO";
25
+ OperatingMode[OperatingMode["EXTENDED_HEAT"] = 3] = "EXTENDED_HEAT";
26
+ OperatingMode[OperatingMode["COOL"] = 4] = "COOL";
27
+ OperatingMode[OperatingMode["DRY"] = 5] = "DRY";
28
+ OperatingMode[OperatingMode["WAIT"] = 6] = "WAIT";
29
+ })(OperatingMode || (exports.OperatingMode = OperatingMode = {}));
30
+ // Write to BEDJET3_COMMAND_UUID as Buffer.from([command_byte, ...args])
31
+ var BedJetCommand;
32
+ (function (BedJetCommand) {
33
+ BedJetCommand[BedJetCommand["BUTTON"] = 1] = "BUTTON";
34
+ BedJetCommand[BedJetCommand["SET_RUNTIME"] = 2] = "SET_RUNTIME";
35
+ BedJetCommand[BedJetCommand["SET_TEMPERATURE"] = 3] = "SET_TEMPERATURE";
36
+ BedJetCommand[BedJetCommand["SET_STEP"] = 4] = "SET_STEP";
37
+ BedJetCommand[BedJetCommand["SET_HACKS"] = 5] = "SET_HACKS";
38
+ BedJetCommand[BedJetCommand["STATUS"] = 6] = "STATUS";
39
+ BedJetCommand[BedJetCommand["SET_FAN"] = 7] = "SET_FAN";
40
+ BedJetCommand[BedJetCommand["SET_CLOCK"] = 8] = "SET_CLOCK";
41
+ BedJetCommand[BedJetCommand["SET_BIO"] = 64] = "SET_BIO";
42
+ BedJetCommand[BedJetCommand["GET_BIO"] = 65] = "GET_BIO";
43
+ })(BedJetCommand || (exports.BedJetCommand = BedJetCommand = {}));
44
+ var BedJetButton;
45
+ (function (BedJetButton) {
46
+ BedJetButton[BedJetButton["OFF"] = 1] = "OFF";
47
+ BedJetButton[BedJetButton["COOL"] = 2] = "COOL";
48
+ BedJetButton[BedJetButton["HEAT"] = 3] = "HEAT";
49
+ BedJetButton[BedJetButton["TURBO"] = 4] = "TURBO";
50
+ BedJetButton[BedJetButton["DRY"] = 5] = "DRY";
51
+ BedJetButton[BedJetButton["EXTENDED_HEAT"] = 6] = "EXTENDED_HEAT";
52
+ BedJetButton[BedJetButton["M1"] = 32] = "M1";
53
+ BedJetButton[BedJetButton["M2"] = 33] = "M2";
54
+ BedJetButton[BedJetButton["M3"] = 34] = "M3";
55
+ BedJetButton[BedJetButton["DEBUG_ON"] = 64] = "DEBUG_ON";
56
+ BedJetButton[BedJetButton["DEBUG_OFF"] = 65] = "DEBUG_OFF";
57
+ BedJetButton[BedJetButton["CONNECTION_TEST"] = 66] = "CONNECTION_TEST";
58
+ BedJetButton[BedJetButton["UPDATE_FIRMWARE"] = 67] = "UPDATE_FIRMWARE";
59
+ BedJetButton[BedJetButton["LED_ON"] = 70] = "LED_ON";
60
+ BedJetButton[BedJetButton["LED_OFF"] = 71] = "LED_OFF";
61
+ BedJetButton[BedJetButton["MUTE"] = 72] = "MUTE";
62
+ BedJetButton[BedJetButton["UNMUTE"] = 73] = "UNMUTE";
63
+ BedJetButton[BedJetButton["NOTIFY_ACK"] = 82] = "NOTIFY_ACK";
64
+ BedJetButton[BedJetButton["BIORHYTHM_1"] = 128] = "BIORHYTHM_1";
65
+ BedJetButton[BedJetButton["BIORHYTHM_2"] = 129] = "BIORHYTHM_2";
66
+ BedJetButton[BedJetButton["BIORHYTHM_3"] = 130] = "BIORHYTHM_3";
67
+ })(BedJetButton || (exports.BedJetButton = BedJetButton = {}));
68
+ exports.OPERATING_MODE_BUTTON_MAP = {
69
+ [OperatingMode.STANDBY]: BedJetButton.OFF,
70
+ [OperatingMode.HEAT]: BedJetButton.HEAT,
71
+ [OperatingMode.TURBO]: BedJetButton.TURBO,
72
+ [OperatingMode.EXTENDED_HEAT]: BedJetButton.EXTENDED_HEAT,
73
+ [OperatingMode.COOL]: BedJetButton.COOL,
74
+ [OperatingMode.DRY]: BedJetButton.DRY,
75
+ [OperatingMode.WAIT]: BedJetButton.OFF,
76
+ };
77
+ var BioDataRequest;
78
+ (function (BioDataRequest) {
79
+ BioDataRequest[BioDataRequest["DEVICE_NAME"] = 0] = "DEVICE_NAME";
80
+ BioDataRequest[BioDataRequest["MEMORY_NAMES"] = 1] = "MEMORY_NAMES";
81
+ BioDataRequest[BioDataRequest["BIORHYTHM_NAMES"] = 4] = "BIORHYTHM_NAMES";
82
+ BioDataRequest[BioDataRequest["FIRMWARE_VERSIONS"] = 32] = "FIRMWARE_VERSIONS";
83
+ })(BioDataRequest || (exports.BioDataRequest = BioDataRequest = {}));
84
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/bedjet/constants.ts"],"names":[],"mappings":";;;AAAA,0DAA0D;AAC7C,QAAA,oBAAoB,GAAQ,sCAAsC,CAAC;AACnE,QAAA,mBAAmB,GAAS,sCAAsC,CAAC;AACnE,QAAA,iBAAiB,GAAW,sCAAsC,CAAC;AACnE,QAAA,iBAAiB,GAAW,sCAAsC,CAAC;AACnE,QAAA,qBAAqB,GAAO,sCAAsC,CAAC;AACnE,QAAA,oBAAoB,GAAQ,sCAAsC,CAAC;AACnE,QAAA,oBAAoB,GAAQ,sCAAsC,CAAC;AACnE,QAAA,yBAAyB,GAAG,sCAAsC,CAAC;AAEhF,gEAAgE;AACnD,QAAA,2BAA2B,GAAG,EAAE,CAAC;AAC9C,+DAA+D;AAClD,QAAA,qBAAqB,GAAS,EAAE,CAAC;AAEjC,QAAA,mBAAmB,GAAQ,KAAM,CAAC;AAClC,QAAA,sBAAsB,GAAK,CAAC,CAAC;AAE1C,kCAAkC;AAClC,IAAY,aAQX;AARD,WAAY,aAAa;IACvB,uDAAiB,CAAA;IACjB,iDAAiB,CAAA;IACjB,mDAAiB,CAAA;IACjB,mEAAiB,CAAA;IACjB,iDAAiB,CAAA;IACjB,+CAAiB,CAAA;IACjB,iDAAiB,CAAA;AACnB,CAAC,EARW,aAAa,6BAAb,aAAa,QAQxB;AAED,wEAAwE;AACxE,IAAY,aAWX;AAXD,WAAY,aAAa;IACvB,qDAAsB,CAAA;IACtB,+DAAsB,CAAA;IACtB,uEAAsB,CAAA;IACtB,yDAAsB,CAAA;IACtB,2DAAsB,CAAA;IACtB,qDAAsB,CAAA;IACtB,uDAAsB,CAAA;IACtB,2DAAsB,CAAA;IACtB,wDAAsB,CAAA;IACtB,wDAAsB,CAAA;AACxB,CAAC,EAXW,aAAa,6BAAb,aAAa,QAWxB;AAED,IAAY,YAsBX;AAtBD,WAAY,YAAY;IACtB,6CAAsB,CAAA;IACtB,+CAAsB,CAAA;IACtB,+CAAsB,CAAA;IACtB,iDAAsB,CAAA;IACtB,6CAAsB,CAAA;IACtB,iEAAsB,CAAA;IACtB,4CAAsB,CAAA;IACtB,4CAAsB,CAAA;IACtB,4CAAsB,CAAA;IACtB,wDAAsB,CAAA;IACtB,0DAAsB,CAAA;IACtB,sEAAsB,CAAA;IACtB,sEAAsB,CAAA;IACtB,oDAAsB,CAAA;IACtB,sDAAsB,CAAA;IACtB,gDAAsB,CAAA;IACtB,oDAAsB,CAAA;IACtB,4DAAsB,CAAA;IACtB,+DAAsB,CAAA;IACtB,+DAAsB,CAAA;IACtB,+DAAsB,CAAA;AACxB,CAAC,EAtBW,YAAY,4BAAZ,YAAY,QAsBvB;AAEY,QAAA,yBAAyB,GAAwC;IAC5E,CAAC,aAAa,CAAC,OAAO,CAAC,EAAQ,YAAY,CAAC,GAAG;IAC/C,CAAC,aAAa,CAAC,IAAI,CAAC,EAAW,YAAY,CAAC,IAAI;IAChD,CAAC,aAAa,CAAC,KAAK,CAAC,EAAU,YAAY,CAAC,KAAK;IACjD,CAAC,aAAa,CAAC,aAAa,CAAC,EAAE,YAAY,CAAC,aAAa;IACzD,CAAC,aAAa,CAAC,IAAI,CAAC,EAAW,YAAY,CAAC,IAAI;IAChD,CAAC,aAAa,CAAC,GAAG,CAAC,EAAY,YAAY,CAAC,GAAG;IAC/C,CAAC,aAAa,CAAC,IAAI,CAAC,EAAW,YAAY,CAAC,GAAG;CAChD,CAAC;AAEF,IAAY,cAKX;AALD,WAAY,cAAc;IACxB,iEAAqB,CAAA;IACrB,mEAAqB,CAAA;IACrB,yEAAqB,CAAA;IACrB,8EAAsB,CAAA;AACxB,CAAC,EALW,cAAc,8BAAd,cAAc,QAKzB"}
@@ -0,0 +1,27 @@
1
+ import { OperatingMode } from './constants';
2
+ export interface BedJetState {
3
+ currentTemperature: number;
4
+ targetTemperature: number;
5
+ operatingMode: OperatingMode;
6
+ fanSpeed: number;
7
+ minimumTemperature: number;
8
+ maximumTemperature: number;
9
+ ambientTemperature: number;
10
+ hoursRemaining: number;
11
+ minutesRemaining: number;
12
+ secondsRemaining: number;
13
+ turboTimeSeconds: number;
14
+ isConnected: boolean;
15
+ isDualZone?: boolean;
16
+ ledEnabled?: boolean;
17
+ beepsMuted?: boolean;
18
+ connTestPassed?: boolean;
19
+ unitsSetup?: boolean;
20
+ notificationCode?: number;
21
+ }
22
+ export interface BedJetConfig {
23
+ name: string;
24
+ address: string;
25
+ scanTimeout?: number;
26
+ }
27
+ export declare const DEFAULT_STATE: BedJetState;
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_STATE = void 0;
4
+ const constants_1 = require("./constants");
5
+ exports.DEFAULT_STATE = {
6
+ currentTemperature: 20,
7
+ targetTemperature: 28,
8
+ operatingMode: constants_1.OperatingMode.STANDBY,
9
+ fanSpeed: 50,
10
+ minimumTemperature: 19,
11
+ maximumTemperature: 43,
12
+ ambientTemperature: 20,
13
+ hoursRemaining: 0,
14
+ minutesRemaining: 0,
15
+ secondsRemaining: 0,
16
+ turboTimeSeconds: 0,
17
+ isConnected: false,
18
+ };
19
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/bedjet/types.ts"],"names":[],"mappings":";;;AAAA,2CAA4C;AA8B/B,QAAA,aAAa,GAAgB;IACxC,kBAAkB,EAAE,EAAE;IACtB,iBAAiB,EAAE,EAAE;IACrB,aAAa,EAAE,yBAAa,CAAC,OAAO;IACpC,QAAQ,EAAE,EAAE;IACZ,kBAAkB,EAAE,EAAE;IACtB,kBAAkB,EAAE,EAAE;IACtB,kBAAkB,EAAE,EAAE;IACtB,cAAc,EAAE,CAAC;IACjB,gBAAgB,EAAE,CAAC;IACnB,gBAAgB,EAAE,CAAC;IACnB,gBAAgB,EAAE,CAAC;IACnB,WAAW,EAAE,KAAK;CACnB,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { API } from 'homebridge';
2
+ declare const _default: (api: API) => void;
3
+ export = _default;
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ const platform_1 = require("./platform");
3
+ module.exports = (api) => {
4
+ api.registerPlatform(platform_1.PLUGIN_NAME, platform_1.PLATFORM_NAME, platform_1.BedJetPlatform);
5
+ };
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,yCAAwE;AAExE,iBAAS,CAAC,GAAQ,EAAE,EAAE;IACpB,GAAG,CAAC,gBAAgB,CAAC,sBAAW,EAAE,wBAAa,EAAE,yBAAc,CAAC,CAAC;AACnE,CAAC,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { API, DynamicPlatformPlugin, Logging, PlatformAccessory, PlatformConfig } from 'homebridge';
2
+ export declare const PLATFORM_NAME = "BedJetPlatform";
3
+ export declare const PLUGIN_NAME = "homebridge-bedjet";
4
+ export declare class BedJetPlatform implements DynamicPlatformPlugin {
5
+ readonly log: Logging;
6
+ readonly config: PlatformConfig;
7
+ readonly api: API;
8
+ private readonly accessories;
9
+ private readonly discoveredUUIDs;
10
+ constructor(log: Logging, config: PlatformConfig, api: API);
11
+ configureAccessory(accessory: PlatformAccessory): void;
12
+ private discoverDevices;
13
+ }
@@ -0,0 +1,62 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BedJetPlatform = exports.PLUGIN_NAME = exports.PLATFORM_NAME = void 0;
4
+ const accessory_1 = require("./accessory");
5
+ exports.PLATFORM_NAME = 'BedJetPlatform';
6
+ exports.PLUGIN_NAME = 'homebridge-bedjet';
7
+ class BedJetPlatform {
8
+ constructor(log, config, api) {
9
+ this.log = log;
10
+ this.config = config;
11
+ this.api = api;
12
+ this.accessories = new Map();
13
+ this.discoveredUUIDs = [];
14
+ this.log.debug('BedJetPlatform initializing');
15
+ this.api.on('didFinishLaunching', () => {
16
+ this.log.debug('didFinishLaunching');
17
+ this.discoverDevices();
18
+ });
19
+ }
20
+ configureAccessory(accessory) {
21
+ this.log.info('Loading accessory from cache:', accessory.displayName);
22
+ this.accessories.set(accessory.UUID, accessory);
23
+ }
24
+ discoverDevices() {
25
+ const devices = this.config['devices'] ?? [];
26
+ if (devices.length === 0) {
27
+ this.log.warn('No BedJet devices configured. Add at least one device in the plugin settings.');
28
+ return;
29
+ }
30
+ for (const device of devices) {
31
+ if (!device.address) {
32
+ this.log.warn(`Skipping device "${device.name}" — no address configured`);
33
+ continue;
34
+ }
35
+ const uuid = this.api.hap.uuid.generate(device.address.toLowerCase());
36
+ this.discoveredUUIDs.push(uuid);
37
+ const existing = this.accessories.get(uuid);
38
+ if (existing) {
39
+ this.log.info('Restoring existing accessory from cache:', existing.displayName);
40
+ existing.context.device = device;
41
+ this.api.updatePlatformAccessories([existing]);
42
+ new accessory_1.BedJetAccessory(this, existing, device);
43
+ }
44
+ else {
45
+ this.log.info('Adding new accessory:', device.name);
46
+ const accessory = new this.api.platformAccessory(device.name, uuid);
47
+ accessory.context.device = device;
48
+ new accessory_1.BedJetAccessory(this, accessory, device);
49
+ this.api.registerPlatformAccessories(exports.PLUGIN_NAME, exports.PLATFORM_NAME, [accessory]);
50
+ }
51
+ }
52
+ // Remove accessories that are no longer in the config
53
+ for (const [uuid, accessory] of this.accessories) {
54
+ if (!this.discoveredUUIDs.includes(uuid)) {
55
+ this.log.info('Removing stale accessory from cache:', accessory.displayName);
56
+ this.api.unregisterPlatformAccessories(exports.PLUGIN_NAME, exports.PLATFORM_NAME, [accessory]);
57
+ }
58
+ }
59
+ }
60
+ }
61
+ exports.BedJetPlatform = BedJetPlatform;
62
+ //# sourceMappingURL=platform.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"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"}