@switchbot/homebridge-switchbot 4.1.6-beta.1 → 4.1.6-beta.10

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.
Files changed (50) hide show
  1. package/config.schema.json +31 -24
  2. package/dist/device/colorbulb.js +19 -19
  3. package/dist/device/colorbulb.js.map +1 -1
  4. package/dist/device/curtain.d.ts.map +1 -1
  5. package/dist/device/curtain.js +4 -5
  6. package/dist/device/curtain.js.map +1 -1
  7. package/dist/device/device.d.ts +1 -1
  8. package/dist/device/device.d.ts.map +1 -1
  9. package/dist/device/device.js +2 -1
  10. package/dist/device/device.js.map +1 -1
  11. package/dist/device/fan.d.ts.map +1 -1
  12. package/dist/device/fan.js +2 -3
  13. package/dist/device/fan.js.map +1 -1
  14. package/dist/device/humidifier.d.ts.map +1 -1
  15. package/dist/device/humidifier.js +1 -2
  16. package/dist/device/humidifier.js.map +1 -1
  17. package/dist/device/lightstrip.js +2 -2
  18. package/dist/device/lightstrip.js.map +1 -1
  19. package/dist/device/lock.d.ts.map +1 -1
  20. package/dist/device/lock.js +2 -2
  21. package/dist/device/lock.js.map +1 -1
  22. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  23. package/dist/device/robotvacuumcleaner.js +2 -3
  24. package/dist/device/robotvacuumcleaner.js.map +1 -1
  25. package/dist/platform.d.ts +1 -1
  26. package/dist/platform.d.ts.map +1 -1
  27. package/dist/platform.js +3 -3
  28. package/dist/platform.js.map +1 -1
  29. package/dist/settings.d.ts +1 -0
  30. package/dist/settings.d.ts.map +1 -1
  31. package/dist/settings.js.map +1 -1
  32. package/dist/utils.d.ts +7 -0
  33. package/dist/utils.d.ts.map +1 -1
  34. package/dist/utils.js +18 -0
  35. package/dist/utils.js.map +1 -1
  36. package/docs/assets/main.js +3 -3
  37. package/docs/assets/style.css +14 -0
  38. package/docs/functions/default.html +1 -1
  39. package/package.json +13 -13
  40. package/src/device/colorbulb.ts +19 -19
  41. package/src/device/curtain.ts +4 -5
  42. package/src/device/device.ts +2 -1
  43. package/src/device/fan.ts +2 -3
  44. package/src/device/humidifier.ts +1 -2
  45. package/src/device/lightstrip.ts +2 -2
  46. package/src/device/lock.ts +3 -3
  47. package/src/device/robotvacuumcleaner.ts +2 -3
  48. package/src/platform.ts +10 -10
  49. package/src/settings.ts +1 -0
  50. package/src/utils.ts +19 -0
@@ -82,25 +82,6 @@ export class ColorBulb extends deviceBase {
82
82
  }
83
83
  accessory.context.LightBulb = this.LightBulb as object
84
84
 
85
- if (this.adaptiveLighting && this.adaptiveLightingShift === -1 && this.LightBulb) {
86
- accessory.removeService(this.LightBulb.Service)
87
- this.LightBulb.Service = accessory.addService(this.hap.Service.Lightbulb)
88
- accessory.context.adaptiveLighting = false
89
- this.debugLog(`adaptiveLighting: ${this.adaptiveLighting}`)
90
- } else if (this.adaptiveLighting && this.adaptiveLightingShift >= 0 && this.LightBulb) {
91
- this.AdaptiveLightingController = new platform.api.hap.AdaptiveLightingController(this.LightBulb.Service, {
92
- controllerMode: this.hap.AdaptiveLightingControllerMode.AUTOMATIC,
93
- customTemperatureAdjustment: this.adaptiveLightingShift,
94
- })
95
- accessory.configureController(this.AdaptiveLightingController)
96
- accessory.context.adaptiveLighting = true
97
- this.debugLog(`adaptiveLighting: ${this.adaptiveLighting}, adaptiveLightingShift: ${this.adaptiveLightingShift}`,
98
- )
99
- } else {
100
- accessory.context.adaptiveLighting = false
101
- this.debugLog(`adaptiveLighting: ${accessory.context.adaptiveLighting}`)
102
- }
103
-
104
85
  // Initialize LightBulb Characteristics
105
86
  this.LightBulb.Service.setCharacteristic(this.hap.Characteristic.Name, this.LightBulb.Name).getCharacteristic(this.hap.Characteristic.On).onGet(() => {
106
87
  return this.LightBulb.On
@@ -139,6 +120,25 @@ export class ColorBulb extends deviceBase {
139
120
  return this.LightBulb.Saturation
140
121
  }).onSet(this.SaturationSet.bind(this))
141
122
 
123
+ if (this.adaptiveLighting && this.adaptiveLightingShift === -1 && this.LightBulb) {
124
+ accessory.removeService(this.LightBulb.Service)
125
+ this.LightBulb.Service = accessory.addService(this.hap.Service.Lightbulb)
126
+ accessory.context.adaptiveLighting = false
127
+ this.debugLog(`adaptiveLighting: ${this.adaptiveLighting}`)
128
+ } else if (this.adaptiveLighting && this.adaptiveLightingShift >= 0 && this.LightBulb) {
129
+ this.AdaptiveLightingController = new platform.api.hap.AdaptiveLightingController(this.LightBulb.Service, {
130
+ controllerMode: this.hap.AdaptiveLightingControllerMode.AUTOMATIC,
131
+ customTemperatureAdjustment: this.adaptiveLightingShift,
132
+ })
133
+ accessory.configureController(this.AdaptiveLightingController)
134
+ accessory.context.adaptiveLighting = true
135
+ this.debugLog(`adaptiveLighting: ${this.adaptiveLighting}, adaptiveLightingShift: ${this.adaptiveLightingShift}`,
136
+ )
137
+ } else {
138
+ accessory.context.adaptiveLighting = false
139
+ this.debugLog(`adaptiveLighting: ${accessory.context.adaptiveLighting}`)
140
+ }
141
+
142
142
  // Retrieve initial values and updateHomekit
143
143
  try {
144
144
  this.debugLog('Retrieve initial values and update Homekit')
@@ -844,7 +844,6 @@ export class Curtain extends deviceBase {
844
844
  this.hasLoggedStandby = false
845
845
  this.infoLog('Checking Status ...')
846
846
  this.curtainMoving = true
847
- await this.setMinMax()
848
847
  if (this.WindowCovering.TargetPosition > this.WindowCovering.CurrentPosition) {
849
848
  this.debugLog(`Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition}`)
850
849
  this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING
@@ -877,13 +876,13 @@ export class Curtain extends deviceBase {
877
876
 
878
877
  async setMinMax(): Promise<void> {
879
878
  if ((this.device as curtainConfig).set_min) {
880
- if (Number(this.WindowCovering.CurrentPosition) <= (this.device as curtainConfig).set_min!) {
881
- this.WindowCovering.CurrentPosition = 0
879
+ if (Number(this.WindowCovering.CurrentPosition) >= (this.device as curtainConfig).set_min!) {
880
+ this.WindowCovering.CurrentPosition = 100
882
881
  }
883
882
  }
884
883
  if ((this.device as curtainConfig).set_max) {
885
- if (Number(this.WindowCovering.CurrentPosition) >= (this.device as curtainConfig).set_max!) {
886
- this.WindowCovering.CurrentPosition = 100
884
+ if (Number(this.WindowCovering.CurrentPosition) <= (this.device as curtainConfig).set_max!) {
885
+ this.WindowCovering.CurrentPosition = 0
887
886
  }
888
887
  }
889
888
  if (this.device.history) {
@@ -14,7 +14,7 @@ import { hostname } from 'node:os'
14
14
 
15
15
  import { SwitchBotBLEModel, SwitchBotBLEModelFriendlyName, SwitchBotBLEModelName, SwitchBotModel } from 'node-switchbot'
16
16
 
17
- import { formatDeviceIdAsMac, sleep } from '../utils.js'
17
+ import { formatDeviceIdAsMac, safeStringify, sleep } from '../utils.js'
18
18
 
19
19
  export abstract class deviceBase {
20
20
  public readonly api: API
@@ -315,6 +315,7 @@ export abstract class deviceBase {
315
315
  // Set an event handler
316
316
  let serviceData = { model: this.device.bleModel, modelName: this.device.bleModelName } as ad['serviceData']
317
317
  switchbot.onadvertisement = (ad: ad) => {
318
+ this.debugLog(`ad: ${safeStringify(ad)}`)
318
319
  if (this.device.bleMac === ad.address && ad.serviceData.model === this.device.bleModel) {
319
320
  this.debugLog(`${JSON.stringify(ad, null, ' ')}`)
320
321
  this.debugLog(`address: ${ad.address}, model: ${ad.serviceData.model}`)
package/src/device/fan.ts CHANGED
@@ -460,14 +460,13 @@ export class Fan extends deviceBase {
460
460
  switchBotBLE
461
461
  .discover({ model: this.device.bleModel, id: this.device.bleMac })
462
462
  .then(async (device_list: SwitchbotDevice[]) => {
463
- const deviceList = device_list as SwitchbotDevice[]
464
463
  return await this.retryBLE({
465
464
  max: this.maxRetryBLE(),
466
465
  fn: async () => {
467
466
  if (this.Fan.Active) {
468
- return await deviceList[0].turnOn()
467
+ return await (device_list[0] as any).turnOn()
469
468
  } else {
470
- return await deviceList[0].turnOff()
469
+ return await (device_list[0] as any).turnOff()
471
470
  }
472
471
  },
473
472
  })
@@ -438,8 +438,7 @@ export class Humidifier extends deviceBase {
438
438
  switchBotBLE
439
439
  .discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac })
440
440
  .then(async (device_list: SwitchbotDevice[]) => {
441
- const deviceList = device_list as WoHumi[]
442
- return await deviceList[0].percentage(this.HumidifierDehumidifier.RelativeHumidityHumidifierThreshold)
441
+ return await (device_list[0] as WoHumi).percentage(Number(this.HumidifierDehumidifier.RelativeHumidityHumidifierThreshold))
443
442
  })
444
443
  .then(async () => {
445
444
  this.successLog(`RelativeHumidityHumidifierThreshold: ${this.HumidifierDehumidifier.RelativeHumidityHumidifierThreshold} sent over BLE, sent successfully`)
@@ -512,7 +512,7 @@ export class StripLight extends deviceBase {
512
512
  .discover({ model: this.device.bleModel, id: this.device.bleMac })
513
513
  .then(async (device_list: SwitchbotDevice[]) => {
514
514
  this.infoLog(`Brightness: ${this.LightBulb.Brightness}`)
515
- return await device_list[0].setBrightness(this.LightBulb.Brightness)
515
+ return await (device_list[0] as WoStrip).setBrightness(Number(this.LightBulb.Brightness))
516
516
  })
517
517
  .then(async () => {
518
518
  this.successLog(`Brightness: ${this.LightBulb.Brightness} sent over SwitchBot BLE, sent successfully`)
@@ -551,7 +551,7 @@ export class StripLight extends deviceBase {
551
551
  .discover({ model: this.device.bleModel, id: this.device.bleMac })
552
552
  .then(async (device_list: SwitchbotDevice[]) => {
553
553
  this.infoLog(`RGB: ${(this.LightBulb.Brightness, red, green, blue)}`)
554
- return await device_list[0].setRGB(this.LightBulb.Brightness, red, green, blue)
554
+ return await (device_list[0] as WoStrip).setRGB(Number(this.LightBulb.Brightness), red, green, blue)
555
555
  })
556
556
  .then(async () => {
557
557
  this.successLog(`RGB: ${(this.LightBulb.Brightness, red, green, blue)} sent over SwitchBot BLE, sent successfully`)
@@ -3,7 +3,7 @@
3
3
  * lock.ts: @switchbot/homebridge-switchbot.
4
4
  */
5
5
  import type { CharacteristicValue, PlatformAccessory, Service } from 'homebridge'
6
- import type { bodyChange, device, lockProServiceData, lockProStatus, lockProWebhookContext, lockServiceData, lockStatus, lockWebhookContext, SwitchbotDevice } from 'node-switchbot'
6
+ import type { bodyChange, device, lockProServiceData, lockProStatus, lockProWebhookContext, lockServiceData, lockStatus, lockWebhookContext, SwitchbotDevice, WoSmartLock } from 'node-switchbot'
7
7
 
8
8
  import type { SwitchBotPlatform } from '../platform.js'
9
9
  import type { devicesConfig, lockConfig } from '../settings.js'
@@ -451,9 +451,9 @@ export class Lock extends deviceBase {
451
451
  max: this.maxRetryBLE(),
452
452
  fn: async () => {
453
453
  if (this.LockMechanism.LockTargetState === this.hap.Characteristic.LockTargetState.SECURED) {
454
- return await device_list[0].lock({ id: this.device.bleMac })
454
+ return await (device_list[0] as WoSmartLock).lock()
455
455
  } else {
456
- return await device_list[0].unlock({ id: this.device.bleMac })
456
+ return await (device_list[0] as WoSmartLock).unlock()
457
457
  }
458
458
  },
459
459
  })
@@ -392,15 +392,14 @@ export class RobotVacuumCleaner extends deviceBase {
392
392
  switchBotBLE
393
393
  .discover({ model: this.device.bleModel, id: this.device.bleMac })
394
394
  .then(async (device_list: SwitchbotDevice[]) => {
395
- const deviceList = device_list as SwitchbotDevice[]
396
395
  this.infoLog(`On: ${this.LightBulb.On}`)
397
396
  return await this.retryBLE({
398
397
  max: this.maxRetryBLE(),
399
398
  fn: async () => {
400
399
  if (this.LightBulb.On) {
401
- return await deviceList[0].turnOn()
400
+ return await (device_list[0] as any).turnOn()
402
401
  } else {
403
- return await deviceList[0].turnOff()
402
+ return await (device_list[0] as any).turnOff()
404
403
  }
405
404
  },
406
405
  })
package/src/platform.ts CHANGED
@@ -6,22 +6,22 @@ import type { Server } from 'node:http'
6
6
 
7
7
  import type { API, DynamicPlatformPlugin, Logging, PlatformAccessory } from 'homebridge'
8
8
  import type { MqttClient } from 'mqtt'
9
+ /*
10
+ * For Testing Locally:
11
+ * import type { blindTilt, curtain, curtain3, device, irdevice } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js';
12
+ * import { LogLevel, SwitchBotBLE, SwitchBotModel, SwitchBotOpenAPI } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js';
13
+ */
14
+ import type { blindTilt, curtain, curtain3, device, deviceStatus, deviceStatusRequest, irdevice } from 'node-switchbot'
9
15
 
10
16
  import type { blindTiltConfig, curtainConfig, devicesConfig, irDevicesConfig, options, SwitchBotPlatformConfig } from './settings.js'
11
17
 
12
18
  import { readFileSync } from 'node:fs'
19
+ import { hostname } from 'node:os'
13
20
  import process, { argv } from 'node:process'
14
21
 
15
22
  import asyncmqtt from 'async-mqtt'
16
23
  import fakegato from 'fakegato-history'
17
24
  import { EveHomeKitTypes } from 'homebridge-lib/EveHomeKitTypes'
18
- /*
19
- * For Testing Locally:
20
- * import type { blindTilt, curtain, curtain3, device, irdevice } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js';
21
- * import { LogLevel, SwitchBotBLE, SwitchBotModel, SwitchBotOpenAPI } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js';
22
- */
23
- import type { blindTilt, curtain, curtain3, device, deviceStatus, deviceStatusRequest, irdevice } from 'node-switchbot'
24
-
25
25
  import { LogLevel, SwitchBotBLE, SwitchBotModel, SwitchBotOpenAPI } from 'node-switchbot'
26
26
  import { queueScheduler } from 'rxjs'
27
27
 
@@ -54,7 +54,7 @@ import { TV } from './irdevice/tv.js'
54
54
  import { VacuumCleaner } from './irdevice/vacuumcleaner.js'
55
55
  import { WaterHeater } from './irdevice/waterheater.js'
56
56
  import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js'
57
- import { formatDeviceIdAsMac, isBlindTiltDevice, isCurtainDevice, sleep } from './utils.js'
57
+ import { formatDeviceIdAsMac, isBlindTiltDevice, isCurtainDevice, safeStringify, sleep } from './utils.js'
58
58
 
59
59
  /**
60
60
  * HomebridgePlatform
@@ -139,7 +139,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
139
139
 
140
140
  // SwitchBot OpenAPI
141
141
  if (this.config.credentials?.token && this.config.credentials?.secret) {
142
- this.switchBotAPI = new SwitchBotOpenAPI(this.config.credentials.token, this.config.credentials.secret)
142
+ this.switchBotAPI = new SwitchBotOpenAPI(this.config.credentials.token, this.config.credentials.secret, this.config.options?.hostname)
143
143
  } else {
144
144
  this.debugErrorLog('Missing SwitchBot API credentials (token or secret).')
145
145
  }
@@ -2630,7 +2630,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
2630
2630
  async connectBLE(accessory: PlatformAccessory, device: device & devicesConfig): Promise<any> {
2631
2631
  try {
2632
2632
  queueScheduler.schedule(async () => this.switchBotBLE)
2633
- this.debugLog(`${device.deviceType}: ${accessory.displayName} 'node-switchbot' found: ${this.switchBotBLE}`)
2633
+ this.debugLog(`${device.deviceType}: ${accessory.displayName} 'node-switchbot' found: ${safeStringify(this.switchBotBLE)}`)
2634
2634
  return this.switchBotBLE
2635
2635
  } catch (e: any) {
2636
2636
  this.errorLog(`${device.deviceType}: ${accessory.displayName} 'node-switchbot' not found, Error: ${e.message ?? e}`)
package/src/settings.ts CHANGED
@@ -43,6 +43,7 @@ export interface options {
43
43
  discoverBLE?: boolean
44
44
  disableLogsforBLE?: boolean
45
45
  disableLogsforOpenAPI?: boolean
46
+ hostname?: string
46
47
  webhookURL?: string
47
48
  maxRetries?: number
48
49
  delayBetweenRetries?: number
package/src/utils.ts CHANGED
@@ -54,6 +54,25 @@ export function convertUnits(value: number, unit: string, convert?: string): num
54
54
  return value
55
55
  }
56
56
 
57
+ /**
58
+ * Safely serializes an object to a JSON string, handling circular references.
59
+ *
60
+ * @param obj - The object to be serialized.
61
+ * @returns The JSON string representation of the object.
62
+ */
63
+ export function safeStringify(obj: any) {
64
+ const seen = new WeakSet()
65
+ return JSON.stringify(obj, (_key, value) => {
66
+ if (typeof value === 'object' && value !== null) {
67
+ if (seen.has(value)) {
68
+ return
69
+ }
70
+ seen.add(value)
71
+ }
72
+ return value
73
+ }, ' ')
74
+ }
75
+
57
76
  /**
58
77
  * Formats a device ID as a MAC address.
59
78
  * Ensures the device ID does not already contain colons.