homebridge-bedjet 0.2.1 → 0.2.3
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 +1 -0
- package/dist/bedjet/BedJet.d.ts +0 -2
- package/dist/bedjet/BedJet.js +13 -29
- package/dist/bedjet/BedJet.js.map +1 -1
- package/homebridge-ui/public/index.html +307 -0
- package/homebridge-ui/server.js +67 -0
- package/package.json +2 -1
- package/src/bedjet/BedJet.ts +16 -32
package/config.schema.json
CHANGED
package/dist/bedjet/BedJet.d.ts
CHANGED
|
@@ -13,7 +13,6 @@ export declare class BedJet extends EventEmitter {
|
|
|
13
13
|
private destroyed;
|
|
14
14
|
private bleDestroy;
|
|
15
15
|
private commandChar;
|
|
16
|
-
private disconnectTimer;
|
|
17
16
|
private staleTimer;
|
|
18
17
|
constructor(config: BedJetConfig, log: Logger);
|
|
19
18
|
get state(): BedJetState;
|
|
@@ -32,7 +31,6 @@ export declare class BedJet extends EventEmitter {
|
|
|
32
31
|
setRuntimeRemaining(hours: number, minutes: number): Promise<void>;
|
|
33
32
|
setLed(on: boolean): Promise<void>;
|
|
34
33
|
setMuted(muted: boolean): Promise<void>;
|
|
35
|
-
private _resetDisconnectTimer;
|
|
36
34
|
private _resetStaleTimer;
|
|
37
35
|
private _onDisconnected;
|
|
38
36
|
private _scheduleReconnect;
|
package/dist/bedjet/BedJet.js
CHANGED
|
@@ -5,6 +5,8 @@ const events_1 = require("events");
|
|
|
5
5
|
const NodeBle = require("node-ble");
|
|
6
6
|
const { createBluetooth } = NodeBle;
|
|
7
7
|
const constants_1 = require("./constants");
|
|
8
|
+
// Max delay between reconnect attempts (ms)
|
|
9
|
+
const MAX_RECONNECT_DELAY_MS = 60000;
|
|
8
10
|
const types_1 = require("./types");
|
|
9
11
|
// node-ble uses BlueZ D-Bus — works alongside BlueZ without raw HCI conflicts.
|
|
10
12
|
// This mirrors how Python bleak / Home Assistant ha-bedjet connects.
|
|
@@ -21,7 +23,6 @@ class BedJet extends events_1.EventEmitter {
|
|
|
21
23
|
this.destroyed = false;
|
|
22
24
|
this.bleDestroy = null;
|
|
23
25
|
this.commandChar = null;
|
|
24
|
-
this.disconnectTimer = null;
|
|
25
26
|
this.staleTimer = null;
|
|
26
27
|
}
|
|
27
28
|
get state() { return this._state; }
|
|
@@ -101,7 +102,6 @@ class BedJet extends events_1.EventEmitter {
|
|
|
101
102
|
}
|
|
102
103
|
this.reconnectAttempts = 0;
|
|
103
104
|
this._state = { ...this._state, isConnected: true };
|
|
104
|
-
this._resetDisconnectTimer();
|
|
105
105
|
this._resetStaleTimer();
|
|
106
106
|
this.emit('connected');
|
|
107
107
|
this.emit('stateChange', this._state);
|
|
@@ -148,13 +148,17 @@ class BedJet extends events_1.EventEmitter {
|
|
|
148
148
|
// ── Commands ────────────────────────────────────────────────────────────────
|
|
149
149
|
async _sendCommand(command, ...args) {
|
|
150
150
|
if (!this.commandChar) {
|
|
151
|
+
// Kick off a reconnect attempt if one isn't already in progress
|
|
152
|
+
if (!this.connecting && !this.destroyed) {
|
|
153
|
+
this.log.info(`[${this.config.name}] Command issued while disconnected — reconnecting`);
|
|
154
|
+
this.connect().catch(err => this.log.error(`[${this.config.name}] Reconnect on command failed: ${err}`));
|
|
155
|
+
}
|
|
151
156
|
throw new Error(`[${this.config.name}] Not connected`);
|
|
152
157
|
}
|
|
153
158
|
const buf = Buffer.from([command, ...args]);
|
|
154
159
|
try {
|
|
155
160
|
// writeValueWithResponse = write with response, required for BedJet V3
|
|
156
161
|
await this.commandChar.writeValueWithResponse(buf);
|
|
157
|
-
this._resetDisconnectTimer();
|
|
158
162
|
}
|
|
159
163
|
catch (err) {
|
|
160
164
|
this.log.error(`[${this.config.name}] Command 0x${command.toString(16)} failed: ${err}`);
|
|
@@ -187,15 +191,6 @@ class BedJet extends events_1.EventEmitter {
|
|
|
187
191
|
await this.pressButton(muted ? constants_1.BedJetButton.MUTE : constants_1.BedJetButton.UNMUTE);
|
|
188
192
|
}
|
|
189
193
|
// ── Timers ──────────────────────────────────────────────────────────────────
|
|
190
|
-
_resetDisconnectTimer() {
|
|
191
|
-
if (this.disconnectTimer) {
|
|
192
|
-
clearTimeout(this.disconnectTimer);
|
|
193
|
-
}
|
|
194
|
-
this.disconnectTimer = setTimeout(async () => {
|
|
195
|
-
this.log.debug(`[${this.config.name}] Inactivity timeout — disconnecting`);
|
|
196
|
-
await this.disconnect();
|
|
197
|
-
}, constants_1.DISCONNECT_DELAY_MS);
|
|
198
|
-
}
|
|
199
194
|
_resetStaleTimer() {
|
|
200
195
|
if (this.staleTimer) {
|
|
201
196
|
clearTimeout(this.staleTimer);
|
|
@@ -209,10 +204,6 @@ class BedJet extends events_1.EventEmitter {
|
|
|
209
204
|
// ── Disconnect / reconnect ──────────────────────────────────────────────────
|
|
210
205
|
_onDisconnected() {
|
|
211
206
|
this.commandChar = null;
|
|
212
|
-
if (this.disconnectTimer) {
|
|
213
|
-
clearTimeout(this.disconnectTimer);
|
|
214
|
-
this.disconnectTimer = null;
|
|
215
|
-
}
|
|
216
207
|
if (this.staleTimer) {
|
|
217
208
|
clearTimeout(this.staleTimer);
|
|
218
209
|
this.staleTimer = null;
|
|
@@ -223,17 +214,14 @@ class BedJet extends events_1.EventEmitter {
|
|
|
223
214
|
this._scheduleReconnect();
|
|
224
215
|
}
|
|
225
216
|
_scheduleReconnect() {
|
|
226
|
-
if (this.destroyed
|
|
227
|
-
if (!this.destroyed && this.reconnectAttempts >= constants_1.MAX_RECONNECT_ATTEMPTS) {
|
|
228
|
-
this.log.error(`[${this.config.name}] Max reconnect attempts reached`);
|
|
229
|
-
this.emit('maxReconnectReached');
|
|
230
|
-
}
|
|
217
|
+
if (this.destroyed) {
|
|
231
218
|
return;
|
|
232
219
|
}
|
|
233
|
-
|
|
234
|
-
this.reconnectAttempts
|
|
235
|
-
|
|
236
|
-
|
|
220
|
+
// Exponential backoff capped at MAX_RECONNECT_DELAY_MS — retries indefinitely
|
|
221
|
+
const delay = Math.min(MAX_RECONNECT_DELAY_MS, Math.pow(2, this.reconnectAttempts + 1) * 1000);
|
|
222
|
+
// Cap the counter so the exponent doesn't grow forever
|
|
223
|
+
this.reconnectAttempts = Math.min(this.reconnectAttempts + 1, 10);
|
|
224
|
+
this.log.info(`[${this.config.name}] Reconnecting in ${delay / 1000}s (attempt ${this.reconnectAttempts})`);
|
|
237
225
|
setTimeout(() => {
|
|
238
226
|
this.connect().catch(err => this.log.error(`[${this.config.name}] Reconnect failed: ${err}`));
|
|
239
227
|
}, delay);
|
|
@@ -241,10 +229,6 @@ class BedJet extends events_1.EventEmitter {
|
|
|
241
229
|
async disconnect() {
|
|
242
230
|
this.destroyed = true;
|
|
243
231
|
this.commandChar = null;
|
|
244
|
-
if (this.disconnectTimer) {
|
|
245
|
-
clearTimeout(this.disconnectTimer);
|
|
246
|
-
this.disconnectTimer = null;
|
|
247
|
-
}
|
|
248
232
|
if (this.staleTimer) {
|
|
249
233
|
clearTimeout(this.staleTimer);
|
|
250
234
|
this.staleTimer = null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"BedJet.js","sourceRoot":"","sources":["../../src/bedjet/BedJet.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"BedJet.js","sourceRoot":"","sources":["../../src/bedjet/BedJet.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<title>BedJet Discovery</title>
|
|
7
|
+
<style>
|
|
8
|
+
:root {
|
|
9
|
+
--card-bg: #1e1e1e;
|
|
10
|
+
--card-border: #3a3a3a;
|
|
11
|
+
--text: #e0e0e0;
|
|
12
|
+
--text-muted: #888;
|
|
13
|
+
--btn-bg: #c25700;
|
|
14
|
+
--btn-hover: #d96200;
|
|
15
|
+
--btn-text: #fff;
|
|
16
|
+
--add-bg: #1a6b3a;
|
|
17
|
+
--add-hover: #1f8047;
|
|
18
|
+
--done-bg: #2a4a2a;
|
|
19
|
+
--done-text: #6fcf97;
|
|
20
|
+
--error-bg: #4a1a1a;
|
|
21
|
+
--error-text: #f28b82;
|
|
22
|
+
--row-border: #2e2e2e;
|
|
23
|
+
--spinner-color: #c25700;
|
|
24
|
+
--address-color: #aaa;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
body {
|
|
28
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
|
|
29
|
+
margin: 0;
|
|
30
|
+
padding: 16px;
|
|
31
|
+
background: transparent;
|
|
32
|
+
color: var(--text);
|
|
33
|
+
font-size: 14px;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
h6 {
|
|
37
|
+
font-size: 13px;
|
|
38
|
+
font-weight: 600;
|
|
39
|
+
text-transform: uppercase;
|
|
40
|
+
letter-spacing: 0.05em;
|
|
41
|
+
color: var(--text-muted);
|
|
42
|
+
margin: 0 0 12px;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
.scan-row {
|
|
46
|
+
display: flex;
|
|
47
|
+
align-items: center;
|
|
48
|
+
gap: 12px;
|
|
49
|
+
margin-bottom: 16px;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
button {
|
|
53
|
+
padding: 8px 18px;
|
|
54
|
+
border: none;
|
|
55
|
+
border-radius: 6px;
|
|
56
|
+
font-size: 14px;
|
|
57
|
+
font-weight: 500;
|
|
58
|
+
cursor: pointer;
|
|
59
|
+
transition: background 0.15s;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
#scanBtn {
|
|
63
|
+
background: var(--btn-bg);
|
|
64
|
+
color: var(--btn-text);
|
|
65
|
+
}
|
|
66
|
+
#scanBtn:hover:not(:disabled) { background: var(--btn-hover); }
|
|
67
|
+
#scanBtn:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
68
|
+
|
|
69
|
+
#status {
|
|
70
|
+
font-size: 13px;
|
|
71
|
+
color: var(--text-muted);
|
|
72
|
+
display: flex;
|
|
73
|
+
align-items: center;
|
|
74
|
+
gap: 8px;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
.spinner {
|
|
78
|
+
width: 14px;
|
|
79
|
+
height: 14px;
|
|
80
|
+
border: 2px solid transparent;
|
|
81
|
+
border-top-color: var(--spinner-color);
|
|
82
|
+
border-radius: 50%;
|
|
83
|
+
animation: spin 0.7s linear infinite;
|
|
84
|
+
flex-shrink: 0;
|
|
85
|
+
}
|
|
86
|
+
@keyframes spin { to { transform: rotate(360deg); } }
|
|
87
|
+
|
|
88
|
+
.progress-bar-wrap {
|
|
89
|
+
height: 3px;
|
|
90
|
+
background: var(--card-border);
|
|
91
|
+
border-radius: 2px;
|
|
92
|
+
overflow: hidden;
|
|
93
|
+
margin-bottom: 14px;
|
|
94
|
+
}
|
|
95
|
+
.progress-bar-fill {
|
|
96
|
+
height: 100%;
|
|
97
|
+
background: var(--btn-bg);
|
|
98
|
+
width: 0%;
|
|
99
|
+
transition: width 0.4s linear;
|
|
100
|
+
border-radius: 2px;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
#results {
|
|
104
|
+
margin-top: 4px;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.device-card {
|
|
108
|
+
display: flex;
|
|
109
|
+
align-items: center;
|
|
110
|
+
justify-content: space-between;
|
|
111
|
+
padding: 10px 12px;
|
|
112
|
+
border-radius: 6px;
|
|
113
|
+
border: 1px solid var(--card-border);
|
|
114
|
+
background: var(--card-bg);
|
|
115
|
+
margin-bottom: 8px;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.device-info {
|
|
119
|
+
display: flex;
|
|
120
|
+
flex-direction: column;
|
|
121
|
+
gap: 2px;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.device-name {
|
|
125
|
+
font-weight: 500;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.device-address {
|
|
129
|
+
font-size: 12px;
|
|
130
|
+
color: var(--address-color);
|
|
131
|
+
font-family: 'SF Mono', 'Consolas', monospace;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.add-btn {
|
|
135
|
+
background: var(--add-bg);
|
|
136
|
+
color: #fff;
|
|
137
|
+
padding: 6px 14px;
|
|
138
|
+
font-size: 13px;
|
|
139
|
+
border-radius: 5px;
|
|
140
|
+
flex-shrink: 0;
|
|
141
|
+
}
|
|
142
|
+
.add-btn:hover:not(:disabled) { background: var(--add-hover); }
|
|
143
|
+
.add-btn:disabled {
|
|
144
|
+
background: var(--done-bg);
|
|
145
|
+
color: var(--done-text);
|
|
146
|
+
cursor: default;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
.empty-state, .error-state {
|
|
150
|
+
padding: 12px 14px;
|
|
151
|
+
border-radius: 6px;
|
|
152
|
+
font-size: 13px;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
.empty-state {
|
|
156
|
+
background: var(--card-bg);
|
|
157
|
+
border: 1px solid var(--card-border);
|
|
158
|
+
color: var(--text-muted);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
.error-state {
|
|
162
|
+
background: var(--error-bg);
|
|
163
|
+
border: 1px solid #6b2020;
|
|
164
|
+
color: var(--error-text);
|
|
165
|
+
}
|
|
166
|
+
</style>
|
|
167
|
+
</head>
|
|
168
|
+
<body>
|
|
169
|
+
|
|
170
|
+
<h6>Bluetooth Discovery</h6>
|
|
171
|
+
|
|
172
|
+
<div class="scan-row">
|
|
173
|
+
<button id="scanBtn" onclick="startScan()">Scan for BedJets</button>
|
|
174
|
+
<div id="status"></div>
|
|
175
|
+
</div>
|
|
176
|
+
|
|
177
|
+
<div class="progress-bar-wrap" id="progressWrap" style="display:none">
|
|
178
|
+
<div class="progress-bar-fill" id="progressFill"></div>
|
|
179
|
+
</div>
|
|
180
|
+
|
|
181
|
+
<div id="results"></div>
|
|
182
|
+
|
|
183
|
+
<script>
|
|
184
|
+
const SCAN_DURATION_MS = 12000;
|
|
185
|
+
let scanning = false;
|
|
186
|
+
let existingAddresses = new Set();
|
|
187
|
+
|
|
188
|
+
// Load existing configured addresses so we can mark them
|
|
189
|
+
async function loadExisting() {
|
|
190
|
+
try {
|
|
191
|
+
const configs = await homebridge.getPluginConfig();
|
|
192
|
+
const cfg = configs[0] || {};
|
|
193
|
+
(cfg.devices || []).forEach(d => {
|
|
194
|
+
if (d.address) existingAddresses.add(d.address.toUpperCase());
|
|
195
|
+
});
|
|
196
|
+
} catch {}
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
loadExisting();
|
|
200
|
+
|
|
201
|
+
async function startScan() {
|
|
202
|
+
if (scanning) return;
|
|
203
|
+
scanning = true;
|
|
204
|
+
|
|
205
|
+
const btn = document.getElementById('scanBtn');
|
|
206
|
+
const status = document.getElementById('status');
|
|
207
|
+
const progressWrap = document.getElementById('progressWrap');
|
|
208
|
+
const progressFill = document.getElementById('progressFill');
|
|
209
|
+
const results = document.getElementById('results');
|
|
210
|
+
|
|
211
|
+
btn.disabled = true;
|
|
212
|
+
results.innerHTML = '';
|
|
213
|
+
progressFill.style.width = '0%';
|
|
214
|
+
progressWrap.style.display = 'block';
|
|
215
|
+
status.innerHTML = '<div class="spinner"></div> Scanning…';
|
|
216
|
+
|
|
217
|
+
// Animate progress bar over scan duration
|
|
218
|
+
let elapsed = 0;
|
|
219
|
+
const tick = 200;
|
|
220
|
+
const timer = setInterval(() => {
|
|
221
|
+
elapsed += tick;
|
|
222
|
+
const pct = Math.min(100, (elapsed / SCAN_DURATION_MS) * 100);
|
|
223
|
+
progressFill.style.width = pct + '%';
|
|
224
|
+
if (elapsed >= SCAN_DURATION_MS) clearInterval(timer);
|
|
225
|
+
}, tick);
|
|
226
|
+
|
|
227
|
+
try {
|
|
228
|
+
const res = await homebridge.request('/scan');
|
|
229
|
+
clearInterval(timer);
|
|
230
|
+
progressFill.style.width = '100%';
|
|
231
|
+
status.textContent = '';
|
|
232
|
+
|
|
233
|
+
if (!res.devices || res.devices.length === 0) {
|
|
234
|
+
results.innerHTML = '<div class="empty-state">No BedJet devices found nearby. Make sure your BedJet is powered on and not already connected to another device.</div>';
|
|
235
|
+
} else {
|
|
236
|
+
// Reload existing in case user added something during scan
|
|
237
|
+
await loadExisting();
|
|
238
|
+
results.innerHTML = res.devices.map(d => buildCard(d)).join('');
|
|
239
|
+
}
|
|
240
|
+
} catch (err) {
|
|
241
|
+
clearInterval(timer);
|
|
242
|
+
status.textContent = '';
|
|
243
|
+
const msg = (err && err.message) ? err.message : String(err);
|
|
244
|
+
results.innerHTML = `<div class="error-state">⚠ ${msg}</div>`;
|
|
245
|
+
} finally {
|
|
246
|
+
setTimeout(() => { progressWrap.style.display = 'none'; progressFill.style.width = '0%'; }, 600);
|
|
247
|
+
btn.disabled = false;
|
|
248
|
+
scanning = false;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function buildCard(device) {
|
|
253
|
+
const alreadyAdded = existingAddresses.has(device.address.toUpperCase());
|
|
254
|
+
return `
|
|
255
|
+
<div class="device-card">
|
|
256
|
+
<div class="device-info">
|
|
257
|
+
<span class="device-name">${esc(device.name)}</span>
|
|
258
|
+
<span class="device-address">${esc(device.address)}</span>
|
|
259
|
+
</div>
|
|
260
|
+
<button
|
|
261
|
+
class="add-btn"
|
|
262
|
+
${alreadyAdded ? 'disabled' : ''}
|
|
263
|
+
onclick="addDevice(${JSON.stringify(device.name)}, ${JSON.stringify(device.address)}, this)"
|
|
264
|
+
>${alreadyAdded ? '✓ Added' : 'Add to Config'}</button>
|
|
265
|
+
</div>`;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
async function addDevice(name, address, btn) {
|
|
269
|
+
btn.disabled = true;
|
|
270
|
+
btn.textContent = 'Adding…';
|
|
271
|
+
|
|
272
|
+
try {
|
|
273
|
+
const configs = await homebridge.getPluginConfig();
|
|
274
|
+
const cfg = configs[0] || { platform: 'BedJetPlatform' };
|
|
275
|
+
if (!cfg.devices) cfg.devices = [];
|
|
276
|
+
|
|
277
|
+
// Avoid duplicates
|
|
278
|
+
if (cfg.devices.some(d => d.address && d.address.toUpperCase() === address.toUpperCase())) {
|
|
279
|
+
btn.textContent = '✓ Added';
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
cfg.devices.push({ name, address, scanTimeout: 30 });
|
|
284
|
+
await homebridge.updatePluginConfig([cfg]);
|
|
285
|
+
await homebridge.savePluginConfig();
|
|
286
|
+
|
|
287
|
+
existingAddresses.add(address.toUpperCase());
|
|
288
|
+
btn.textContent = '✓ Added';
|
|
289
|
+
homebridge.toast.success(`${name} added to config. Restart Homebridge to activate.`, 'Device Added');
|
|
290
|
+
} catch (err) {
|
|
291
|
+
btn.disabled = false;
|
|
292
|
+
btn.textContent = 'Add to Config';
|
|
293
|
+
homebridge.toast.error('Failed to save config: ' + ((err && err.message) || err), 'Error');
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function esc(str) {
|
|
298
|
+
return String(str)
|
|
299
|
+
.replace(/&/g, '&')
|
|
300
|
+
.replace(/</g, '<')
|
|
301
|
+
.replace(/>/g, '>')
|
|
302
|
+
.replace(/"/g, '"');
|
|
303
|
+
}
|
|
304
|
+
</script>
|
|
305
|
+
|
|
306
|
+
</body>
|
|
307
|
+
</html>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { HomebridgePluginUiServer } = require('@homebridge/plugin-ui-utils');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
// Resolve node-ble from the plugin root (one level up from homebridge-ui/)
|
|
7
|
+
const NodeBle = require(path.join(__dirname, '..', 'node_modules', 'node-ble'));
|
|
8
|
+
const { createBluetooth } = NodeBle;
|
|
9
|
+
|
|
10
|
+
const SCAN_DURATION_MS = 12000;
|
|
11
|
+
|
|
12
|
+
class BedJetUiServer extends HomebridgePluginUiServer {
|
|
13
|
+
constructor() {
|
|
14
|
+
super();
|
|
15
|
+
this.onRequest('/scan', this.handleScan.bind(this));
|
|
16
|
+
this.ready();
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async handleScan() {
|
|
20
|
+
let destroy = null;
|
|
21
|
+
const found = [];
|
|
22
|
+
|
|
23
|
+
try {
|
|
24
|
+
const ble = createBluetooth();
|
|
25
|
+
destroy = ble.destroy;
|
|
26
|
+
|
|
27
|
+
const adapter = await ble.bluetooth.defaultAdapter();
|
|
28
|
+
|
|
29
|
+
const wasDiscovering = await adapter.isDiscovering();
|
|
30
|
+
if (!wasDiscovering) {
|
|
31
|
+
await adapter.startDiscovery();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Scan for SCAN_DURATION_MS
|
|
35
|
+
await new Promise(resolve => setTimeout(resolve, SCAN_DURATION_MS));
|
|
36
|
+
|
|
37
|
+
if (!wasDiscovering) {
|
|
38
|
+
await adapter.stopDiscovery().catch(() => {});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Query all devices BlueZ discovered
|
|
42
|
+
const addresses = await adapter.devices();
|
|
43
|
+
|
|
44
|
+
for (const address of addresses) {
|
|
45
|
+
try {
|
|
46
|
+
const device = await adapter.getDevice(address);
|
|
47
|
+
const name = await device.getName().catch(() => null);
|
|
48
|
+
if (name && name.toUpperCase().includes('BEDJET')) {
|
|
49
|
+
found.push({ name, address });
|
|
50
|
+
}
|
|
51
|
+
} catch {
|
|
52
|
+
// ignore individual device errors
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
} catch (err) {
|
|
56
|
+
throw new Error(`Bluetooth scan failed: ${err.message || err}`);
|
|
57
|
+
} finally {
|
|
58
|
+
if (destroy) {
|
|
59
|
+
try { destroy(); } catch { /* ignore */ }
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return { devices: found };
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
new BedJetUiServer();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "homebridge-bedjet",
|
|
3
3
|
"displayName": "BedJet",
|
|
4
|
-
"version": "0.2.
|
|
4
|
+
"version": "0.2.3",
|
|
5
5
|
"description": "Homebridge plugin for BedJet V3 via Bluetooth LE",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"main": "dist/index.js",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
"node": ">=18.0.0"
|
|
17
17
|
},
|
|
18
18
|
"dependencies": {
|
|
19
|
+
"@homebridge/plugin-ui-utils": "^1.0.0",
|
|
19
20
|
"node-ble": "^1.10.1"
|
|
20
21
|
},
|
|
21
22
|
"devDependencies": {
|
package/src/bedjet/BedJet.ts
CHANGED
|
@@ -9,13 +9,14 @@ import {
|
|
|
9
9
|
BEDJET3_COMMAND_UUID,
|
|
10
10
|
BEDJET3_NOTIFICATION_LENGTH,
|
|
11
11
|
BEDJET3_STATUS_LENGTH,
|
|
12
|
-
DISCONNECT_DELAY_MS,
|
|
13
|
-
MAX_RECONNECT_ATTEMPTS,
|
|
14
12
|
OperatingMode,
|
|
15
13
|
BedJetCommand,
|
|
16
14
|
BedJetButton,
|
|
17
15
|
OPERATING_MODE_BUTTON_MAP,
|
|
18
16
|
} from './constants';
|
|
17
|
+
|
|
18
|
+
// Max delay between reconnect attempts (ms)
|
|
19
|
+
const MAX_RECONNECT_DELAY_MS = 60_000;
|
|
19
20
|
import type { BedJetConfig, BedJetState } from './types';
|
|
20
21
|
import { DEFAULT_STATE } from './types';
|
|
21
22
|
|
|
@@ -33,7 +34,6 @@ export class BedJet extends EventEmitter {
|
|
|
33
34
|
|
|
34
35
|
private bleDestroy: (() => void) | null = null;
|
|
35
36
|
private commandChar: NodeBle.GattCharacteristic | null = null;
|
|
36
|
-
private disconnectTimer: NodeJS.Timeout | null = null;
|
|
37
37
|
private staleTimer: NodeJS.Timeout | null = null;
|
|
38
38
|
|
|
39
39
|
constructor(
|
|
@@ -135,7 +135,6 @@ export class BedJet extends EventEmitter {
|
|
|
135
135
|
|
|
136
136
|
this.reconnectAttempts = 0;
|
|
137
137
|
this._state = { ...this._state, isConnected: true };
|
|
138
|
-
this._resetDisconnectTimer();
|
|
139
138
|
this._resetStaleTimer();
|
|
140
139
|
|
|
141
140
|
this.emit('connected');
|
|
@@ -189,13 +188,19 @@ export class BedJet extends EventEmitter {
|
|
|
189
188
|
|
|
190
189
|
private async _sendCommand(command: BedJetCommand, ...args: number[]): Promise<void> {
|
|
191
190
|
if (!this.commandChar) {
|
|
191
|
+
// Kick off a reconnect attempt if one isn't already in progress
|
|
192
|
+
if (!this.connecting && !this.destroyed) {
|
|
193
|
+
this.log.info(`[${this.config.name}] Command issued while disconnected — reconnecting`);
|
|
194
|
+
this.connect().catch(err =>
|
|
195
|
+
this.log.error(`[${this.config.name}] Reconnect on command failed: ${err}`),
|
|
196
|
+
);
|
|
197
|
+
}
|
|
192
198
|
throw new Error(`[${this.config.name}] Not connected`);
|
|
193
199
|
}
|
|
194
200
|
const buf = Buffer.from([command, ...args]);
|
|
195
201
|
try {
|
|
196
202
|
// writeValueWithResponse = write with response, required for BedJet V3
|
|
197
203
|
await this.commandChar.writeValueWithResponse(buf);
|
|
198
|
-
this._resetDisconnectTimer();
|
|
199
204
|
} catch (err) {
|
|
200
205
|
this.log.error(`[${this.config.name}] Command 0x${command.toString(16)} failed: ${err}`);
|
|
201
206
|
throw err;
|
|
@@ -237,16 +242,6 @@ export class BedJet extends EventEmitter {
|
|
|
237
242
|
|
|
238
243
|
// ── Timers ──────────────────────────────────────────────────────────────────
|
|
239
244
|
|
|
240
|
-
private _resetDisconnectTimer(): void {
|
|
241
|
-
if (this.disconnectTimer) {
|
|
242
|
-
clearTimeout(this.disconnectTimer);
|
|
243
|
-
}
|
|
244
|
-
this.disconnectTimer = setTimeout(async () => {
|
|
245
|
-
this.log.debug(`[${this.config.name}] Inactivity timeout — disconnecting`);
|
|
246
|
-
await this.disconnect();
|
|
247
|
-
}, DISCONNECT_DELAY_MS);
|
|
248
|
-
}
|
|
249
|
-
|
|
250
245
|
private _resetStaleTimer(): void {
|
|
251
246
|
if (this.staleTimer) {
|
|
252
247
|
clearTimeout(this.staleTimer);
|
|
@@ -263,10 +258,6 @@ export class BedJet extends EventEmitter {
|
|
|
263
258
|
private _onDisconnected(): void {
|
|
264
259
|
this.commandChar = null;
|
|
265
260
|
|
|
266
|
-
if (this.disconnectTimer) {
|
|
267
|
-
clearTimeout(this.disconnectTimer);
|
|
268
|
-
this.disconnectTimer = null;
|
|
269
|
-
}
|
|
270
261
|
if (this.staleTimer) {
|
|
271
262
|
clearTimeout(this.staleTimer);
|
|
272
263
|
this.staleTimer = null;
|
|
@@ -280,18 +271,15 @@ export class BedJet extends EventEmitter {
|
|
|
280
271
|
}
|
|
281
272
|
|
|
282
273
|
private _scheduleReconnect(): void {
|
|
283
|
-
if (this.destroyed
|
|
284
|
-
if (!this.destroyed && this.reconnectAttempts >= MAX_RECONNECT_ATTEMPTS) {
|
|
285
|
-
this.log.error(`[${this.config.name}] Max reconnect attempts reached`);
|
|
286
|
-
this.emit('maxReconnectReached');
|
|
287
|
-
}
|
|
274
|
+
if (this.destroyed) {
|
|
288
275
|
return;
|
|
289
276
|
}
|
|
290
|
-
|
|
291
|
-
this.reconnectAttempts
|
|
277
|
+
// Exponential backoff capped at MAX_RECONNECT_DELAY_MS — retries indefinitely
|
|
278
|
+
const delay = Math.min(MAX_RECONNECT_DELAY_MS, Math.pow(2, this.reconnectAttempts + 1) * 1000);
|
|
279
|
+
// Cap the counter so the exponent doesn't grow forever
|
|
280
|
+
this.reconnectAttempts = Math.min(this.reconnectAttempts + 1, 10);
|
|
292
281
|
this.log.info(
|
|
293
|
-
`[${this.config.name}] Reconnecting in ${delay / 1000}s
|
|
294
|
-
`(attempt ${this.reconnectAttempts}/${MAX_RECONNECT_ATTEMPTS})`,
|
|
282
|
+
`[${this.config.name}] Reconnecting in ${delay / 1000}s (attempt ${this.reconnectAttempts})`,
|
|
295
283
|
);
|
|
296
284
|
setTimeout(() => {
|
|
297
285
|
this.connect().catch(err =>
|
|
@@ -304,10 +292,6 @@ export class BedJet extends EventEmitter {
|
|
|
304
292
|
this.destroyed = true;
|
|
305
293
|
this.commandChar = null;
|
|
306
294
|
|
|
307
|
-
if (this.disconnectTimer) {
|
|
308
|
-
clearTimeout(this.disconnectTimer);
|
|
309
|
-
this.disconnectTimer = null;
|
|
310
|
-
}
|
|
311
295
|
if (this.staleTimer) {
|
|
312
296
|
clearTimeout(this.staleTimer);
|
|
313
297
|
this.staleTimer = null;
|