homebridge-bedjet 0.2.5 → 0.2.6
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/homebridge-ui/public/index.html +87 -63
- package/package.json +1 -1
|
@@ -144,7 +144,7 @@
|
|
|
144
144
|
<h6>Bluetooth Discovery</h6>
|
|
145
145
|
|
|
146
146
|
<div class="scan-row">
|
|
147
|
-
<button id="scanBtn"
|
|
147
|
+
<button id="scanBtn">Scan for BedJets</button>
|
|
148
148
|
<div id="scanStatus"></div>
|
|
149
149
|
</div>
|
|
150
150
|
|
|
@@ -155,44 +155,57 @@
|
|
|
155
155
|
<div id="results"></div>
|
|
156
156
|
|
|
157
157
|
<script>
|
|
158
|
-
|
|
159
|
-
|
|
158
|
+
var SCAN_MS = 12000;
|
|
159
|
+
var scanning = false;
|
|
160
160
|
|
|
161
|
-
// ──
|
|
161
|
+
// ── Wire up buttons via addEventListener, never inline onclick ────────────
|
|
162
|
+
|
|
163
|
+
document.getElementById('scanBtn').addEventListener('click', startScan);
|
|
164
|
+
|
|
165
|
+
// Event delegation for dynamically created Add buttons
|
|
166
|
+
document.getElementById('results').addEventListener('click', function (e) {
|
|
167
|
+
var btn = e.target;
|
|
168
|
+
if (!btn.classList.contains('add-btn') || btn.disabled) return;
|
|
169
|
+
var name = btn.getAttribute('data-name');
|
|
170
|
+
var address = btn.getAttribute('data-address');
|
|
171
|
+
addDevice(btn, name, address);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// ── Scan ──────────────────────────────────────────────────────────────────
|
|
162
175
|
|
|
163
176
|
async function startScan() {
|
|
164
177
|
if (scanning) return;
|
|
165
178
|
scanning = true;
|
|
166
179
|
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
180
|
+
var scanBtn = document.getElementById('scanBtn');
|
|
181
|
+
var status = document.getElementById('scanStatus');
|
|
182
|
+
var pWrap = document.getElementById('progressWrap');
|
|
183
|
+
var pFill = document.getElementById('progressFill');
|
|
184
|
+
var results = document.getElementById('results');
|
|
172
185
|
|
|
173
|
-
|
|
186
|
+
scanBtn.disabled = true;
|
|
174
187
|
results.innerHTML = '';
|
|
175
188
|
pFill.style.width = '0%';
|
|
176
189
|
pWrap.style.display = 'block';
|
|
177
190
|
status.innerHTML = '<div class="spinner"></div> Scanning…';
|
|
178
191
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
192
|
+
var elapsed = 0;
|
|
193
|
+
var tickMs = 200;
|
|
194
|
+
var timer = setInterval(function () {
|
|
182
195
|
elapsed += tickMs;
|
|
183
196
|
pFill.style.width = Math.min(100, (elapsed / SCAN_MS) * 100) + '%';
|
|
184
197
|
if (elapsed >= SCAN_MS) clearInterval(timer);
|
|
185
198
|
}, tickMs);
|
|
186
199
|
|
|
187
200
|
try {
|
|
188
|
-
|
|
201
|
+
var res = await homebridge.request('/scan');
|
|
189
202
|
clearInterval(timer);
|
|
190
203
|
pFill.style.width = '100%';
|
|
191
204
|
status.innerHTML = '';
|
|
192
205
|
|
|
193
|
-
|
|
206
|
+
var devices = (res && Array.isArray(res.devices)) ? res.devices : [];
|
|
194
207
|
if (devices.length === 0) {
|
|
195
|
-
results.innerHTML = '<div class="notice">No BedJet devices found. Make sure your BedJet is powered on and not
|
|
208
|
+
results.innerHTML = '<div class="notice">No BedJet devices found nearby. Make sure your BedJet is powered on and not connected to another app, then try again.</div>';
|
|
196
209
|
} else {
|
|
197
210
|
results.innerHTML = devices.map(renderCard).join('');
|
|
198
211
|
}
|
|
@@ -201,70 +214,81 @@
|
|
|
201
214
|
status.innerHTML = '';
|
|
202
215
|
results.innerHTML = '<div class="notice error">Scan failed: ' + esc(err && err.message ? err.message : String(err)) + '</div>';
|
|
203
216
|
} finally {
|
|
204
|
-
setTimeout(()
|
|
205
|
-
|
|
217
|
+
setTimeout(function () { pWrap.style.display = 'none'; pFill.style.width = '0%'; }, 500);
|
|
218
|
+
scanBtn.disabled = false;
|
|
206
219
|
scanning = false;
|
|
207
220
|
}
|
|
208
221
|
}
|
|
209
222
|
|
|
210
|
-
// ── Card
|
|
223
|
+
// ── Card ──────────────────────────────────────────────────────────────────
|
|
224
|
+
// Device name/address stored in data-* attributes — no inline JS strings
|
|
211
225
|
|
|
212
226
|
function renderCard(d) {
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
227
|
+
var card = document.createElement('div');
|
|
228
|
+
card.className = 'device-card';
|
|
229
|
+
|
|
230
|
+
var info = document.createElement('div');
|
|
231
|
+
|
|
232
|
+
var nameEl = document.createElement('div');
|
|
233
|
+
nameEl.className = 'device-name';
|
|
234
|
+
nameEl.textContent = d.name;
|
|
235
|
+
|
|
236
|
+
var addrEl = document.createElement('div');
|
|
237
|
+
addrEl.className = 'device-addr';
|
|
238
|
+
addrEl.textContent = d.address;
|
|
239
|
+
|
|
240
|
+
info.appendChild(nameEl);
|
|
241
|
+
info.appendChild(addrEl);
|
|
242
|
+
|
|
243
|
+
var right = document.createElement('div');
|
|
244
|
+
right.className = 'device-right';
|
|
245
|
+
|
|
246
|
+
var btn = document.createElement('button');
|
|
247
|
+
btn.className = 'add-btn';
|
|
248
|
+
btn.textContent = 'Add to Config';
|
|
249
|
+
btn.setAttribute('data-name', d.name);
|
|
250
|
+
btn.setAttribute('data-address', d.address);
|
|
251
|
+
|
|
252
|
+
var msgEl = document.createElement('div');
|
|
253
|
+
msgEl.className = 'card-msg';
|
|
254
|
+
|
|
255
|
+
right.appendChild(btn);
|
|
256
|
+
right.appendChild(msgEl);
|
|
257
|
+
card.appendChild(info);
|
|
258
|
+
card.appendChild(right);
|
|
259
|
+
|
|
260
|
+
// Store msgEl reference on btn for easy access in handler
|
|
261
|
+
btn._msgEl = msgEl;
|
|
262
|
+
|
|
263
|
+
return card.outerHTML;
|
|
230
264
|
}
|
|
231
265
|
|
|
232
|
-
// ── Add device
|
|
233
|
-
// Uses homebridge.request() — same path as the scan, which we know works.
|
|
234
|
-
// The server reads/writes config.json directly; no client-side config APIs needed.
|
|
266
|
+
// ── Add device ─────────────────────────────────────────────────────────────
|
|
235
267
|
|
|
236
|
-
async function addDevice(name, address
|
|
237
|
-
|
|
238
|
-
|
|
268
|
+
async function addDevice(btn, name, address) {
|
|
269
|
+
// Find the sibling message element
|
|
270
|
+
var msg = btn.parentElement ? btn.parentElement.querySelector('.card-msg') : null;
|
|
239
271
|
|
|
240
|
-
// Immediate visual feedback before any async work
|
|
241
272
|
btn.disabled = true;
|
|
242
273
|
btn.textContent = 'Saving…';
|
|
243
|
-
msg.textContent = '';
|
|
244
|
-
msg.className = 'card-msg';
|
|
274
|
+
if (msg) { msg.textContent = ''; msg.className = 'card-msg'; }
|
|
245
275
|
|
|
246
|
-
let result;
|
|
247
276
|
try {
|
|
248
|
-
result = await homebridge.request('/add-device', { name: name, address: address });
|
|
277
|
+
var result = await homebridge.request('/add-device', { name: name, address: address });
|
|
278
|
+
|
|
279
|
+
if (result && result.status === 'already_exists') {
|
|
280
|
+
btn.textContent = '✓ Already added';
|
|
281
|
+
if (msg) { msg.textContent = 'Already in config.'; msg.className = 'card-msg ok'; }
|
|
282
|
+
} else {
|
|
283
|
+
btn.textContent = '✓ Added!';
|
|
284
|
+
btn.style.background = '#145c30';
|
|
285
|
+
if (msg) { msg.textContent = 'Saved — restart Homebridge.'; msg.className = 'card-msg ok'; }
|
|
286
|
+
}
|
|
249
287
|
} catch (err) {
|
|
250
|
-
// Request itself failed — show error and re-enable
|
|
251
288
|
btn.disabled = false;
|
|
252
289
|
btn.textContent = 'Add to Config';
|
|
253
|
-
|
|
254
|
-
msg.className = 'card-msg err';
|
|
255
|
-
return;
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// Request succeeded
|
|
259
|
-
if (result && result.status === 'already_exists') {
|
|
260
|
-
btn.textContent = '✓ Already in config';
|
|
261
|
-
msg.textContent = 'Restart Homebridge to see it.';
|
|
262
|
-
msg.className = 'card-msg ok';
|
|
263
|
-
} else {
|
|
264
|
-
btn.textContent = '✓ Added!';
|
|
265
|
-
btn.style.background = '#145c30';
|
|
266
|
-
msg.textContent = 'Saved. Restart Homebridge.';
|
|
267
|
-
msg.className = 'card-msg ok';
|
|
290
|
+
var errMsg = err && err.message ? err.message : String(err);
|
|
291
|
+
if (msg) { msg.textContent = 'Error: ' + errMsg; msg.className = 'card-msg err'; }
|
|
268
292
|
}
|
|
269
293
|
}
|
|
270
294
|
|