homebridge-bedjet 0.3.3 → 0.3.5

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.
@@ -46,12 +46,12 @@
46
46
  "description": "Mode to activate when the BedJet is turned on from HomeKit"
47
47
  },
48
48
  "defaultTemperature": {
49
- "title": "Default Temperature °C (when turned on)",
49
+ "title": "Default Temperature °F (when turned on)",
50
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."
51
+ "minimum": 66,
52
+ "maximum": 109,
53
+ "multipleOf": 1,
54
+ "description": "Target temperature to set when turned on, in °F. Range: 66–109°F. Leave blank to keep the BedJet's last-used temperature."
55
55
  },
56
56
  "defaultFanSpeed": {
57
57
  "title": "Default Fan Speed % (when turned on)",
package/dist/accessory.js CHANGED
@@ -3,6 +3,7 @@ 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 utils_1 = require("./utils");
6
7
  const DEFAULT_MODE_MAP = {
7
8
  heat: constants_1.OperatingMode.HEAT,
8
9
  turbo: constants_1.OperatingMode.TURBO,
@@ -10,20 +11,6 @@ const DEFAULT_MODE_MAP = {
10
11
  cool: constants_1.OperatingMode.COOL,
11
12
  dry: constants_1.OperatingMode.DRY,
12
13
  };
13
- /**
14
- * HomeKit only allows alphanumeric, space, and apostrophe characters in names,
15
- * starting and ending with alphanumeric. Underscores and other punctuation
16
- * cause HAP warnings and may prevent the accessory from pairing.
17
- */
18
- function sanitizeName(name) {
19
- return name
20
- .replace(/_/g, ' ') // underscores → spaces
21
- .replace(/[^a-zA-Z0-9 ']/g, ' ') // anything else invalid → space
22
- .replace(/\s+/g, ' ') // collapse multiple spaces
23
- .trim()
24
- .replace(/^[^a-zA-Z0-9]+/, '') // must start with alphanumeric
25
- .replace(/[^a-zA-Z0-9]+$/, '') || 'BedJet'; // must end with alphanumeric
26
- }
27
14
  // OperatingMode → CurrentHeatingCoolingState value
28
15
  const CURRENT_STATE_MAP = {
29
16
  [constants_1.OperatingMode.STANDBY]: 0, // OFF
@@ -66,7 +53,7 @@ class BedJetAccessory {
66
53
  this.pendingMode = null;
67
54
  this.pendingModeTimer = null;
68
55
  const { Service, Characteristic } = platform.api.hap;
69
- const safeName = sanitizeName(config.name);
56
+ const safeName = (0, utils_1.sanitizeName)(config.name);
70
57
  // AccessoryInformation
71
58
  const infoService = this.accessory.getService(Service.AccessoryInformation)
72
59
  ?? this.accessory.addService(Service.AccessoryInformation);
@@ -184,8 +171,16 @@ class BedJetAccessory {
184
171
  await this.bedjet.setOperatingMode(mode);
185
172
  if (applyDefaults) {
186
173
  if (config.defaultTemperature !== undefined) {
187
- this.setPending(config.defaultTemperature, 'pendingTemp', 'pendingTempTimer', 5000);
188
- await this.bedjet.setTemperature(config.defaultTemperature);
174
+ // Config stores °F (values > 43 are unambiguously Fahrenheit).
175
+ // Old configs stored °C (≤ 43) — leave those as-is for backward compat.
176
+ let tempC = config.defaultTemperature;
177
+ if (tempC > 43) {
178
+ tempC = (tempC - 32) * 5 / 9;
179
+ }
180
+ // Clamp to BedJet V3 valid range 19–43 °C, rounded to nearest 0.5
181
+ tempC = Math.max(19, Math.min(43, Math.round(tempC * 2) / 2));
182
+ this.setPending(tempC, 'pendingTemp', 'pendingTempTimer', 5000);
183
+ await this.bedjet.setTemperature(tempC);
189
184
  }
190
185
  if (config.defaultFanSpeed !== undefined) {
191
186
  this.setPending(config.defaultFanSpeed, 'pendingFanSpeed', 'pendingFanSpeedTimer', 5000);
package/dist/platform.js CHANGED
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BedJetPlatform = exports.PLUGIN_NAME = exports.PLATFORM_NAME = void 0;
4
4
  const accessory_1 = require("./accessory");
5
+ const utils_1 = require("./utils");
5
6
  exports.PLATFORM_NAME = 'BedJetPlatform';
6
7
  exports.PLUGIN_NAME = 'homebridge-bedjet';
7
8
  class BedJetPlatform {
@@ -35,15 +36,18 @@ class BedJetPlatform {
35
36
  const uuid = this.api.hap.uuid.generate(device.address.toLowerCase());
36
37
  this.discoveredUUIDs.push(uuid);
37
38
  const existing = this.accessories.get(uuid);
39
+ const safeName = (0, utils_1.sanitizeName)(device.name);
38
40
  if (existing) {
39
41
  this.log.info('Restoring existing accessory from cache:', existing.displayName);
40
42
  existing.context.device = device;
43
+ // Update the display name in case the config name changed or was invalid
44
+ existing.displayName = safeName;
41
45
  this.api.updatePlatformAccessories([existing]);
42
46
  new accessory_1.BedJetAccessory(this, existing, device);
43
47
  }
44
48
  else {
45
- this.log.info('Adding new accessory:', device.name);
46
- const accessory = new this.api.platformAccessory(device.name, uuid);
49
+ this.log.info('Adding new accessory:', safeName);
50
+ const accessory = new this.api.platformAccessory(safeName, uuid);
47
51
  accessory.context.device = device;
48
52
  new accessory_1.BedJetAccessory(this, accessory, device);
49
53
  this.api.registerPlatformAccessories(exports.PLUGIN_NAME, exports.PLATFORM_NAME, [accessory]);
@@ -0,0 +1,7 @@
1
+ /**
2
+ * HomeKit only allows alphanumeric, space, and apostrophe characters in
3
+ * accessory/service names, starting and ending with an alphanumeric character.
4
+ * Underscores and other punctuation cause HAP warnings and may prevent the
5
+ * accessory from being added to the Home app.
6
+ */
7
+ export declare function sanitizeName(name: string): string;
package/dist/utils.js ADDED
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sanitizeName = sanitizeName;
4
+ /**
5
+ * HomeKit only allows alphanumeric, space, and apostrophe characters in
6
+ * accessory/service names, starting and ending with an alphanumeric character.
7
+ * Underscores and other punctuation cause HAP warnings and may prevent the
8
+ * accessory from being added to the Home app.
9
+ */
10
+ function sanitizeName(name) {
11
+ return name
12
+ .replace(/_/g, ' ') // underscores → spaces
13
+ .replace(/[^a-zA-Z0-9 ']/g, ' ') // other invalid chars → space
14
+ .replace(/\s+/g, ' ') // collapse runs of spaces
15
+ .trim()
16
+ .replace(/^[^a-zA-Z0-9]+/, '') // must start with alphanumeric
17
+ .replace(/[^a-zA-Z0-9]+$/, '') // must end with alphanumeric
18
+ || 'BedJet';
19
+ }
20
+ //# sourceMappingURL=utils.js.map
@@ -362,19 +362,27 @@
362
362
  modeField.appendChild(modeSelect);
363
363
  row.appendChild(modeField);
364
364
 
365
- // Temperature
365
+ // Temperature — stored and entered in °F.
366
+ // Old configs may have stored °C (≤ 43); convert those to °F for display.
367
+ var tempF = null;
368
+ if (currentTemp != null) {
369
+ tempF = currentTemp > 43
370
+ ? Math.round(currentTemp) // already °F
371
+ : Math.round(currentTemp * 9 / 5 + 32); // was °C — convert for display
372
+ }
373
+
366
374
  var tempField = document.createElement('div');
367
375
  tempField.className = 'field';
368
376
  var tempLabel = document.createElement('label');
369
- tempLabel.textContent = 'Temp °C';
377
+ tempLabel.textContent = 'Temp °F';
370
378
  var tempInput = document.createElement('input');
371
379
  tempInput.type = 'number';
372
380
  tempInput.className = 'field-temp';
373
- tempInput.min = '19';
374
- tempInput.max = '43';
375
- tempInput.step = '0.5';
381
+ tempInput.min = '66';
382
+ tempInput.max = '109';
383
+ tempInput.step = '1';
376
384
  tempInput.placeholder = 'Optional';
377
- if (currentTemp != null) tempInput.value = currentTemp;
385
+ if (tempF !== null) tempInput.value = tempF;
378
386
  tempField.appendChild(tempLabel);
379
387
  tempField.appendChild(tempInput);
380
388
  row.appendChild(tempField);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "homebridge-bedjet",
3
3
  "displayName": "BedJet",
4
- "version": "0.3.3",
4
+ "version": "0.3.5",
5
5
  "description": "Homebridge plugin for BedJet V3 via Bluetooth LE",
6
6
  "license": "MIT",
7
7
  "main": "dist/index.js",
package/src/accessory.ts CHANGED
@@ -3,6 +3,7 @@ import { BedJet } from './bedjet/BedJet';
3
3
  import { OperatingMode } from './bedjet/constants';
4
4
  import type { BedJetConfig, BedJetState, DefaultMode } from './bedjet/types';
5
5
  import type { BedJetPlatform } from './platform';
6
+ import { sanitizeName } from './utils';
6
7
 
7
8
  const DEFAULT_MODE_MAP: Record<DefaultMode, OperatingMode> = {
8
9
  heat: OperatingMode.HEAT,
@@ -12,20 +13,6 @@ const DEFAULT_MODE_MAP: Record<DefaultMode, OperatingMode> = {
12
13
  dry: OperatingMode.DRY,
13
14
  };
14
15
 
15
- /**
16
- * HomeKit only allows alphanumeric, space, and apostrophe characters in names,
17
- * starting and ending with alphanumeric. Underscores and other punctuation
18
- * cause HAP warnings and may prevent the accessory from pairing.
19
- */
20
- function sanitizeName(name: string): string {
21
- return name
22
- .replace(/_/g, ' ') // underscores → spaces
23
- .replace(/[^a-zA-Z0-9 ']/g, ' ') // anything else invalid → space
24
- .replace(/\s+/g, ' ') // collapse multiple spaces
25
- .trim()
26
- .replace(/^[^a-zA-Z0-9]+/, '') // must start with alphanumeric
27
- .replace(/[^a-zA-Z0-9]+$/, '') || 'BedJet'; // must end with alphanumeric
28
- }
29
16
 
30
17
  // OperatingMode → CurrentHeatingCoolingState value
31
18
  const CURRENT_STATE_MAP: Record<OperatingMode, number> = {
@@ -235,8 +222,16 @@ export class BedJetAccessory {
235
222
 
236
223
  if (applyDefaults) {
237
224
  if (config.defaultTemperature !== undefined) {
238
- this.setPending(config.defaultTemperature, 'pendingTemp', 'pendingTempTimer', 5000);
239
- await this.bedjet.setTemperature(config.defaultTemperature);
225
+ // Config stores °F (values > 43 are unambiguously Fahrenheit).
226
+ // Old configs stored °C (≤ 43) — leave those as-is for backward compat.
227
+ let tempC = config.defaultTemperature;
228
+ if (tempC > 43) {
229
+ tempC = (tempC - 32) * 5 / 9;
230
+ }
231
+ // Clamp to BedJet V3 valid range 19–43 °C, rounded to nearest 0.5
232
+ tempC = Math.max(19, Math.min(43, Math.round(tempC * 2) / 2));
233
+ this.setPending(tempC, 'pendingTemp', 'pendingTempTimer', 5000);
234
+ await this.bedjet.setTemperature(tempC);
240
235
  }
241
236
  if (config.defaultFanSpeed !== undefined) {
242
237
  this.setPending(config.defaultFanSpeed, 'pendingFanSpeed', 'pendingFanSpeedTimer', 5000);
@@ -27,7 +27,7 @@ export interface BedJetConfig {
27
27
  address: string; // BLE MAC e.g. "AA:BB:CC:DD:EE:FF"
28
28
  scanTimeout?: number; // seconds (default 30)
29
29
  defaultMode?: DefaultMode; // mode to activate when turned on from HomeKit
30
- defaultTemperature?: number; // °C, applied on turn-on
30
+ defaultTemperature?: number; // °F (values >43 treated as °F; ≤43 treated as °C for backward compat)
31
31
  defaultFanSpeed?: number; // percent 5–100, applied on turn-on
32
32
  }
33
33
 
package/src/platform.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { API, DynamicPlatformPlugin, Logging, PlatformAccessory, PlatformConfig } from 'homebridge';
2
2
  import { BedJetAccessory } from './accessory';
3
3
  import type { BedJetConfig } from './bedjet/types';
4
+ import { sanitizeName } from './utils';
4
5
 
5
6
  export const PLATFORM_NAME = 'BedJetPlatform';
6
7
  export const PLUGIN_NAME = 'homebridge-bedjet';
@@ -45,15 +46,18 @@ export class BedJetPlatform implements DynamicPlatformPlugin {
45
46
  this.discoveredUUIDs.push(uuid);
46
47
 
47
48
  const existing = this.accessories.get(uuid);
49
+ const safeName = sanitizeName(device.name);
48
50
 
49
51
  if (existing) {
50
52
  this.log.info('Restoring existing accessory from cache:', existing.displayName);
51
53
  existing.context.device = device;
54
+ // Update the display name in case the config name changed or was invalid
55
+ existing.displayName = safeName;
52
56
  this.api.updatePlatformAccessories([existing]);
53
57
  new BedJetAccessory(this, existing, device);
54
58
  } else {
55
- this.log.info('Adding new accessory:', device.name);
56
- const accessory = new this.api.platformAccessory(device.name, uuid);
59
+ this.log.info('Adding new accessory:', safeName);
60
+ const accessory = new this.api.platformAccessory(safeName, uuid);
57
61
  accessory.context.device = device;
58
62
  new BedJetAccessory(this, accessory, device);
59
63
  this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
package/src/utils.ts ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * HomeKit only allows alphanumeric, space, and apostrophe characters in
3
+ * accessory/service names, starting and ending with an alphanumeric character.
4
+ * Underscores and other punctuation cause HAP warnings and may prevent the
5
+ * accessory from being added to the Home app.
6
+ */
7
+ export function sanitizeName(name: string): string {
8
+ return name
9
+ .replace(/_/g, ' ') // underscores → spaces
10
+ .replace(/[^a-zA-Z0-9 ']/g, ' ') // other invalid chars → space
11
+ .replace(/\s+/g, ' ') // collapse runs of spaces
12
+ .trim()
13
+ .replace(/^[^a-zA-Z0-9]+/, '') // must start with alphanumeric
14
+ .replace(/[^a-zA-Z0-9]+$/, '') // must end with alphanumeric
15
+ || 'BedJet';
16
+ }