@switchbot/homebridge-switchbot 3.6.1-beta.2 → 3.6.1-beta.4

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.
@@ -42,8 +42,9 @@ export class ColorBulb extends deviceBase {
42
42
  serviceData!: colorBulbServiceData;
43
43
 
44
44
  // Adaptive Lighting
45
+ adaptiveLighting!: boolean;
46
+ adaptiveLightingShift!: number;
45
47
  AdaptiveLightingController?: ControllerConstructor | Controller<ControllerServiceMap>;
46
- adaptiveLightingShift?: number;
47
48
 
48
49
  // Updates
49
50
  colorBulbUpdateInProgress!: boolean;
@@ -59,7 +60,7 @@ export class ColorBulb extends deviceBase {
59
60
  accessory.category = this.hap.Categories.LIGHTBULB;
60
61
 
61
62
  // default placeholders
62
- this.adaptiveLighting(device);
63
+ this.getAdaptiveLightingSettings(accessory, device);
63
64
 
64
65
  // this is subject we use to track when we need to POST changes to the SwitchBot API
65
66
  this.doColorBulbUpdate = new Subject();
@@ -78,23 +79,24 @@ export class ColorBulb extends deviceBase {
78
79
  };
79
80
  accessory.context.LightBulb = this.LightBulb as object;
80
81
 
81
- // Adaptive Lighting
82
- if (this.adaptiveLightingShift === -1 && accessory.context.adaptiveLighting) {
82
+ if (this.adaptiveLighting && this.adaptiveLightingShift === -1 && this.LightBulb) {
83
83
  accessory.removeService(this.LightBulb.Service);
84
84
  this.LightBulb.Service = accessory.addService(this.hap.Service.Lightbulb);
85
85
  accessory.context.adaptiveLighting = false;
86
- this.debugLog(`adaptiveLighting: ${accessory.context.adaptiveLighting}`);
87
- }
88
- if (this.adaptiveLightingShift !== -1) {
86
+ this.debugLog(`adaptiveLighting: ${this.adaptiveLighting}`);
87
+ } else if (this.adaptiveLighting && this.adaptiveLightingShift >= 0 && this.LightBulb) {
89
88
  this.AdaptiveLightingController = new platform.api.hap.AdaptiveLightingController(this.LightBulb.Service, {
89
+ controllerMode: this.hap.AdaptiveLightingControllerMode.AUTOMATIC,
90
90
  customTemperatureAdjustment: this.adaptiveLightingShift,
91
91
  });
92
92
  accessory.configureController(this.AdaptiveLightingController);
93
93
  accessory.context.adaptiveLighting = true;
94
- this.debugLog(`adaptiveLighting: ${accessory.context.adaptiveLighting},`
95
- + ` adaptiveLightingShift: ${this.adaptiveLightingShift}`);
94
+ this.debugLog(`adaptiveLighting: ${this.adaptiveLighting}, adaptiveLightingShift: ${this.adaptiveLightingShift}`,
95
+ );
96
+ } else {
97
+ accessory.context.adaptiveLighting = false;
98
+ this.debugLog(`adaptiveLighting: ${accessory.context.adaptiveLighting}`);
96
99
  }
97
- this.debugLog(`adaptiveLightingShift: ${this.adaptiveLightingShift}`);
98
100
 
99
101
  // Initialize LightBulb Characteristics
100
102
  this.LightBulb.Service
@@ -833,13 +835,18 @@ export class ColorBulb extends deviceBase {
833
835
  this.LightBulb.Saturation, 'Saturation');
834
836
  }
835
837
 
836
- async adaptiveLighting(device: device & devicesConfig): Promise<void> {
838
+ async getAdaptiveLightingSettings(accessory: PlatformAccessory, device: device & devicesConfig): Promise<void> {
839
+ // Adaptive Lighting
840
+ this.adaptiveLighting = accessory.context.adaptiveLighting ?? true;
841
+ await this.debugLog(`adaptiveLighting: ${this.adaptiveLighting}`);
842
+ // Adaptive Lighting Shift
837
843
  if (device.colorbulb?.adaptiveLightingShift) {
838
844
  this.adaptiveLightingShift = device.colorbulb.adaptiveLightingShift;
845
+ this.debugLog(`adaptiveLightingShift: ${this.adaptiveLightingShift}`);
839
846
  } else {
840
847
  this.adaptiveLightingShift = 0;
848
+ this.debugLog(`adaptiveLightingShift: ${this.adaptiveLightingShift}`);
841
849
  }
842
- await this.debugLog(`adaptiveLightingShift: ${this.adaptiveLightingShift}`);
843
850
  }
844
851
 
845
852
  async BLEPushConnection() {
@@ -79,13 +79,20 @@ export abstract class deviceBase {
79
79
  .getService(this.hap.Service.AccessoryInformation)!
80
80
  .setCharacteristic(this.hap.Characteristic.Manufacturer, 'SwitchBot')
81
81
  .setCharacteristic(this.hap.Characteristic.AppMatchingIdentifier, 'id1087374760')
82
- .setCharacteristic(this.hap.Characteristic.Name, device.configDeviceName ?? device.deviceName ?? accessory.displayName)
83
- .setCharacteristic(this.hap.Characteristic.ConfiguredName, device.configDeviceName ?? device.deviceName ?? accessory.displayName)
82
+ .setCharacteristic(this.hap.Characteristic.Name, this.validName(accessory, device))
83
+ .setCharacteristic(this.hap.Characteristic.ConfiguredName, this.validName(accessory, device))
84
84
  .setCharacteristic(this.hap.Characteristic.Model, device.model ?? accessory.context.model)
85
85
  .setCharacteristic(this.hap.Characteristic.ProductData, device.deviceId ?? accessory.context.deviceId)
86
86
  .setCharacteristic(this.hap.Characteristic.SerialNumber, device.deviceId);
87
87
  }
88
88
 
89
+ public validName(accessory: PlatformAccessory, device: device & devicesConfig) {
90
+ const Name = device.configDeviceName ?? device.deviceName ?? accessory.displayName;
91
+ const NameOfName = device.configDeviceName ? 'configDeviceName' : device.deviceName ? 'deviceName' : 'displayName';
92
+ const validName = this.validateAndCleanString(Name, NameOfName, Name);
93
+ return validName;
94
+ }
95
+
89
96
  async getDeviceLogSettings(accessory: PlatformAccessory, device: device & devicesConfig): Promise<void> {
90
97
  this.deviceLogging = this.platform.debugMode ? 'debugMode' : device.logging ?? this.config.logging ?? 'standard';
91
98
  const logging = this.platform.debugMode ? 'Debug Mode' : device.logging ? 'Device Config' : this.config.logging ? 'Platform Config' : 'Default';
@@ -374,7 +381,7 @@ export abstract class deviceBase {
374
381
  this.debugLog(`serviceData: ${JSON.stringify(ad.serviceData)}`);
375
382
  }
376
383
  };
377
- // Wait 10 seconds
384
+ // Wait
378
385
  await switchbot.wait(this.scanDuration * 1000);
379
386
  // Stop to monitor
380
387
  await switchbot.stopScan();
@@ -765,6 +772,32 @@ export abstract class deviceBase {
765
772
  }
766
773
  }
767
774
 
775
+ /**
776
+ * Validate and clean a string value for a Name Characteristic.
777
+ * @param displayName
778
+ * @param name
779
+ * @param value
780
+ * @returns string value
781
+ */
782
+ validateAndCleanString(displayName: string, name: string, value: string): string {
783
+ const validPattern = /^[a-zA-Z0-9][a-zA-Z0-9 ']*[a-zA-Z0-9]$/;
784
+ const invalidCharsPattern = /[^a-zA-Z0-9 ']/g;
785
+
786
+ if (!validPattern.test(value)) {
787
+ this.warnLog(`WARNING: The accessory '${displayName}' has an invalid '${name}' characteristic ('${value}'). Please use only alphanumeric,`
788
+ + ' space, and apostrophe characters. Ensure it starts and ends with an alphabetic or numeric character, and avoid emojis. This may'
789
+ + ' prevent the accessory from being added in the Home App or cause unresponsiveness.');
790
+
791
+ // Remove invalid characters
792
+ value = value.replace(invalidCharsPattern, '');
793
+
794
+ // Ensure it starts and ends with an alphanumeric character
795
+ value = value.replace(/^[^a-zA-Z0-9]+|[^a-zA-Z0-9]+$/g, '');
796
+ }
797
+
798
+ return value;
799
+ }
800
+
768
801
  /**
769
802
  * Logging for Device
770
803
  */
@@ -10,8 +10,8 @@ import { Subject, debounceTime, interval, skipWhile, take, tap } from 'rxjs';
10
10
  import type { devicesConfig } from '../settings.js';
11
11
  import type { device } from '../types/devicelist.js';
12
12
  import type { SwitchBotPlatform } from '../platform.js';
13
- import type { stripLightServiceData } from '../types/bledevicestatus.js';
14
13
  import type { stripLightStatus } from '../types/devicestatus.js';
14
+ import type { stripLightServiceData } from '../types/bledevicestatus.js';
15
15
  import type { stripLightWebhookContext } from '../types/devicewebhookstatus.js';
16
16
  import type { Service, PlatformAccessory, CharacteristicValue, ControllerConstructor, Controller, ControllerServiceMap } from 'homebridge';
17
17
 
@@ -42,8 +42,9 @@ export class StripLight extends deviceBase {
42
42
  serviceData!: stripLightServiceData;
43
43
 
44
44
  // Adaptive Lighting
45
+ adaptiveLighting!: boolean;
46
+ adaptiveLightingShift!: number;
45
47
  AdaptiveLightingController?: ControllerConstructor | Controller<ControllerServiceMap>;
46
- adaptiveLightingShift?: number;
47
48
 
48
49
  // Updates
49
50
  stripLightUpdateInProgress!: boolean;
@@ -59,7 +60,8 @@ export class StripLight extends deviceBase {
59
60
  accessory.category = this.hap.Categories.LIGHTBULB;
60
61
 
61
62
  // Adaptive Lighting
62
- this.adaptiveLighting(device);
63
+ this.getAdaptiveLightingSettings(accessory, device);
64
+
63
65
  // this is subject we use to track when we need to POST changes to the SwitchBot API
64
66
  this.doStripLightUpdate = new Subject();
65
67
  this.stripLightUpdateInProgress = false;
@@ -77,23 +79,24 @@ export class StripLight extends deviceBase {
77
79
  };
78
80
  accessory.context.LightBulb = this.LightBulb as object;
79
81
 
80
- // Adaptive Lighting
81
- if (this.adaptiveLightingShift === -1 && this.accessory.context.adaptiveLighting) {
82
- this.accessory.removeService(this.LightBulb.Service);
83
- this.LightBulb.Service = this.accessory.addService(this.hap.Service.Lightbulb);
84
- this.accessory.context.adaptiveLighting = false;
85
- this.debugLog(`adaptiveLighting: ${this.accessory.context.adaptiveLighting}`);
86
- }
87
- if (this.adaptiveLightingShift !== -1) {
82
+ if (this.adaptiveLighting && this.adaptiveLightingShift === -1 && this.LightBulb) {
83
+ accessory.removeService(this.LightBulb.Service);
84
+ this.LightBulb.Service = accessory.addService(this.hap.Service.Lightbulb);
85
+ accessory.context.adaptiveLighting = false;
86
+ this.debugLog(`adaptiveLighting: ${this.adaptiveLighting}`);
87
+ } else if (this.adaptiveLighting && this.adaptiveLightingShift >= 0 && this.LightBulb) {
88
88
  this.AdaptiveLightingController = new platform.api.hap.AdaptiveLightingController(this.LightBulb.Service, {
89
+ controllerMode: this.hap.AdaptiveLightingControllerMode.AUTOMATIC,
89
90
  customTemperatureAdjustment: this.adaptiveLightingShift,
90
91
  });
91
- this.accessory.configureController(this.AdaptiveLightingController);
92
- this.accessory.context.adaptiveLighting = true;
93
- this.debugLog(`adaptiveLighting: ${this.accessory.context.adaptiveLighting},`
94
- + ` adaptiveLightingShift: ${this.adaptiveLightingShift}`);
92
+ accessory.configureController(this.AdaptiveLightingController);
93
+ accessory.context.adaptiveLighting = true;
94
+ this.debugLog(`adaptiveLighting: ${this.adaptiveLighting}, adaptiveLightingShift: ${this.adaptiveLightingShift}`,
95
+ );
96
+ } else {
97
+ accessory.context.adaptiveLighting = false;
98
+ this.debugLog(`adaptiveLighting: ${accessory.context.adaptiveLighting}`);
95
99
  }
96
- this.debugLog(`adaptiveLightingShift: ${this.adaptiveLightingShift}`);
97
100
 
98
101
  // Initialize LightBulb Characteristics
99
102
  this.LightBulb.Service
@@ -773,7 +776,11 @@ export class StripLight extends deviceBase {
773
776
  this.LightBulb.Saturation, 'Saturation');
774
777
  }
775
778
 
776
- async adaptiveLighting(device: device & devicesConfig): Promise<void> {
779
+ async getAdaptiveLightingSettings(accessory: PlatformAccessory, device: device & devicesConfig): Promise<void> {
780
+ // Adaptive Lighting
781
+ this.adaptiveLighting = accessory.context.adaptiveLighting ?? true;
782
+ await this.debugLog(`adaptiveLighting: ${this.adaptiveLighting}`);
783
+ // Adaptive Lighting Shift
777
784
  if (device.striplight?.adaptiveLightingShift) {
778
785
  this.adaptiveLightingShift = device.striplight.adaptiveLightingShift;
779
786
  this.debugLog(`adaptiveLightingShift: ${this.adaptiveLightingShift}`);