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.
@@ -144,7 +144,7 @@
144
144
  <h6>Bluetooth Discovery</h6>
145
145
 
146
146
  <div class="scan-row">
147
- <button id="scanBtn" onclick="startScan()">Scan for BedJets</button>
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
- const SCAN_MS = 12000;
159
- let scanning = false;
158
+ var SCAN_MS = 12000;
159
+ var scanning = false;
160
160
 
161
- // ── Scan ─────────────────────────────────────────────────────────────────
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
- const btn = document.getElementById('scanBtn');
168
- const status = document.getElementById('scanStatus');
169
- const pWrap = document.getElementById('progressWrap');
170
- const pFill = document.getElementById('progressFill');
171
- const results = document.getElementById('results');
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
- btn.disabled = true;
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>&nbsp;Scanning…';
178
191
 
179
- let elapsed = 0;
180
- const tickMs = 200;
181
- const timer = setInterval(() => {
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
- const res = await homebridge.request('/scan');
201
+ var res = await homebridge.request('/scan');
189
202
  clearInterval(timer);
190
203
  pFill.style.width = '100%';
191
204
  status.innerHTML = '';
192
205
 
193
- const devices = (res && Array.isArray(res.devices)) ? res.devices : [];
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 already connected to another app, then try again.</div>';
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(() => { pWrap.style.display = 'none'; pFill.style.width = '0%'; }, 500);
205
- btn.disabled = false;
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 rendering ────────────────────────────────────────────────────────
223
+ // ── Card ──────────────────────────────────────────────────────────────────
224
+ // Device name/address stored in data-* attributes — no inline JS strings
211
225
 
212
226
  function renderCard(d) {
213
- // Use address as a safe DOM-id suffix
214
- const safeid = d.address.replace(/[^a-zA-Z0-9]/g, '_');
215
- return [
216
- '<div class="device-card">',
217
- ' <div>',
218
- ' <div class="device-name">' + esc(d.name) + '</div>',
219
- ' <div class="device-addr">' + esc(d.address) + '</div>',
220
- ' </div>',
221
- ' <div class="device-right">',
222
- ' <button class="add-btn" id="btn_' + safeid + '"',
223
- ' onclick="addDevice(' + JSON.stringify(d.name) + ',' + JSON.stringify(d.address) + ',' + JSON.stringify(safeid) + ')">',
224
- ' Add to Config',
225
- ' </button>',
226
- ' <div class="card-msg" id="msg_' + safeid + '"></div>',
227
- ' </div>',
228
- '</div>',
229
- ].join('\n');
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 via server endpoint ────────────────────────────────────────
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, safeid) {
237
- const btn = document.getElementById('btn_' + safeid);
238
- const msg = document.getElementById('msg_' + safeid);
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
- msg.textContent = 'Error: ' + esc(err && err.message ? err.message : String(err));
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
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "homebridge-bedjet",
3
3
  "displayName": "BedJet",
4
- "version": "0.2.5",
4
+ "version": "0.2.6",
5
5
  "description": "Homebridge plugin for BedJet V3 via Bluetooth LE",
6
6
  "license": "MIT",
7
7
  "main": "dist/index.js",