@switchbot/homebridge-switchbot 3.5.0-beta.57 → 3.5.0-beta.59

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 (164) hide show
  1. package/.vscode/settings.json +4 -1
  2. package/dist/device/blindtilt.d.ts +5 -5
  3. package/dist/device/blindtilt.d.ts.map +1 -1
  4. package/dist/device/blindtilt.js +103 -69
  5. package/dist/device/blindtilt.js.map +1 -1
  6. package/dist/device/bot.d.ts +4 -4
  7. package/dist/device/bot.d.ts.map +1 -1
  8. package/dist/device/bot.js +201 -154
  9. package/dist/device/bot.js.map +1 -1
  10. package/dist/device/ceilinglight.d.ts +3 -3
  11. package/dist/device/ceilinglight.d.ts.map +1 -1
  12. package/dist/device/ceilinglight.js +41 -36
  13. package/dist/device/ceilinglight.js.map +1 -1
  14. package/dist/device/colorbulb.d.ts +3 -3
  15. package/dist/device/colorbulb.d.ts.map +1 -1
  16. package/dist/device/colorbulb.js +36 -37
  17. package/dist/device/colorbulb.js.map +1 -1
  18. package/dist/device/contact.d.ts +4 -4
  19. package/dist/device/contact.d.ts.map +1 -1
  20. package/dist/device/contact.js +76 -55
  21. package/dist/device/contact.js.map +1 -1
  22. package/dist/device/curtain.d.ts +4 -4
  23. package/dist/device/curtain.d.ts.map +1 -1
  24. package/dist/device/curtain.js +99 -55
  25. package/dist/device/curtain.js.map +1 -1
  26. package/dist/device/device.d.ts +4 -4
  27. package/dist/device/device.d.ts.map +1 -1
  28. package/dist/device/device.js +11 -9
  29. package/dist/device/device.js.map +1 -1
  30. package/dist/device/fan.d.ts +3 -3
  31. package/dist/device/fan.d.ts.map +1 -1
  32. package/dist/device/fan.js +54 -24
  33. package/dist/device/fan.js.map +1 -1
  34. package/dist/device/hub.d.ts +4 -4
  35. package/dist/device/hub.d.ts.map +1 -1
  36. package/dist/device/hub.js +40 -57
  37. package/dist/device/hub.js.map +1 -1
  38. package/dist/device/humidifier.d.ts +3 -3
  39. package/dist/device/humidifier.d.ts.map +1 -1
  40. package/dist/device/humidifier.js +39 -39
  41. package/dist/device/humidifier.js.map +1 -1
  42. package/dist/device/iosensor.d.ts +3 -3
  43. package/dist/device/iosensor.d.ts.map +1 -1
  44. package/dist/device/iosensor.js +41 -50
  45. package/dist/device/iosensor.js.map +1 -1
  46. package/dist/device/lightstrip.d.ts +4 -4
  47. package/dist/device/lightstrip.d.ts.map +1 -1
  48. package/dist/device/lightstrip.js +36 -33
  49. package/dist/device/lightstrip.js.map +1 -1
  50. package/dist/device/lock.d.ts +3 -3
  51. package/dist/device/lock.d.ts.map +1 -1
  52. package/dist/device/lock.js +68 -59
  53. package/dist/device/lock.js.map +1 -1
  54. package/dist/device/meter.d.ts +3 -3
  55. package/dist/device/meter.d.ts.map +1 -1
  56. package/dist/device/meter.js +42 -51
  57. package/dist/device/meter.js.map +1 -1
  58. package/dist/device/meterplus.d.ts +3 -3
  59. package/dist/device/meterplus.d.ts.map +1 -1
  60. package/dist/device/meterplus.js +42 -51
  61. package/dist/device/meterplus.js.map +1 -1
  62. package/dist/device/motion.d.ts +3 -3
  63. package/dist/device/motion.d.ts.map +1 -1
  64. package/dist/device/motion.js +52 -40
  65. package/dist/device/motion.js.map +1 -1
  66. package/dist/device/plug.d.ts +3 -3
  67. package/dist/device/plug.d.ts.map +1 -1
  68. package/dist/device/plug.js +13 -13
  69. package/dist/device/plug.js.map +1 -1
  70. package/dist/device/robotvacuumcleaner.d.ts +4 -4
  71. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  72. package/dist/device/robotvacuumcleaner.js +81 -98
  73. package/dist/device/robotvacuumcleaner.js.map +1 -1
  74. package/dist/device/waterdetector.d.ts +3 -3
  75. package/dist/device/waterdetector.d.ts.map +1 -1
  76. package/dist/device/waterdetector.js +39 -31
  77. package/dist/device/waterdetector.js.map +1 -1
  78. package/dist/homebridge-ui/public/index.html +20 -14
  79. package/dist/index.d.ts +1 -1
  80. package/dist/index.d.ts.map +1 -1
  81. package/dist/index.js +1 -1
  82. package/dist/index.js.map +1 -1
  83. package/dist/irdevice/airconditioner.d.ts +3 -3
  84. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  85. package/dist/irdevice/airconditioner.js +9 -9
  86. package/dist/irdevice/airconditioner.js.map +1 -1
  87. package/dist/irdevice/airpurifier.d.ts +3 -3
  88. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  89. package/dist/irdevice/airpurifier.js +1 -1
  90. package/dist/irdevice/airpurifier.js.map +1 -1
  91. package/dist/irdevice/camera.d.ts +3 -3
  92. package/dist/irdevice/camera.d.ts.map +1 -1
  93. package/dist/irdevice/camera.js +2 -2
  94. package/dist/irdevice/camera.js.map +1 -1
  95. package/dist/irdevice/fan.d.ts +6 -6
  96. package/dist/irdevice/fan.d.ts.map +1 -1
  97. package/dist/irdevice/fan.js +37 -29
  98. package/dist/irdevice/fan.js.map +1 -1
  99. package/dist/irdevice/irdevice.d.ts +3 -3
  100. package/dist/irdevice/irdevice.d.ts.map +1 -1
  101. package/dist/irdevice/irdevice.js.map +1 -1
  102. package/dist/irdevice/light.d.ts +9 -14
  103. package/dist/irdevice/light.d.ts.map +1 -1
  104. package/dist/irdevice/light.js +67 -88
  105. package/dist/irdevice/light.js.map +1 -1
  106. package/dist/irdevice/other.d.ts +3 -3
  107. package/dist/irdevice/other.d.ts.map +1 -1
  108. package/dist/irdevice/other.js +1 -1
  109. package/dist/irdevice/other.js.map +1 -1
  110. package/dist/irdevice/tv.d.ts +3 -3
  111. package/dist/irdevice/tv.d.ts.map +1 -1
  112. package/dist/irdevice/tv.js +3 -3
  113. package/dist/irdevice/tv.js.map +1 -1
  114. package/dist/irdevice/vacuumcleaner.d.ts +3 -3
  115. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  116. package/dist/irdevice/vacuumcleaner.js +2 -2
  117. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  118. package/dist/irdevice/waterheater.d.ts +3 -3
  119. package/dist/irdevice/waterheater.d.ts.map +1 -1
  120. package/dist/irdevice/waterheater.js +2 -2
  121. package/dist/irdevice/waterheater.js.map +1 -1
  122. package/dist/platform.d.ts +7 -7
  123. package/dist/platform.d.ts.map +1 -1
  124. package/dist/platform.js +20 -23
  125. package/dist/platform.js.map +1 -1
  126. package/dist/settings.d.ts +24 -10
  127. package/dist/settings.d.ts.map +1 -1
  128. package/dist/settings.js +16 -0
  129. package/dist/settings.js.map +1 -1
  130. package/eslint.config.js +89 -78
  131. package/package.json +3 -3
  132. package/src/device/blindtilt.ts +120 -87
  133. package/src/device/bot.ts +238 -175
  134. package/src/device/ceilinglight.ts +49 -46
  135. package/src/device/colorbulb.ts +40 -43
  136. package/src/device/contact.ts +91 -65
  137. package/src/device/curtain.ts +113 -66
  138. package/src/device/device.ts +12 -13
  139. package/src/device/fan.ts +66 -29
  140. package/src/device/hub.ts +53 -60
  141. package/src/device/humidifier.ts +54 -56
  142. package/src/device/iosensor.ts +57 -56
  143. package/src/device/lightstrip.ts +43 -39
  144. package/src/device/lock.ts +79 -68
  145. package/src/device/meter.ts +54 -54
  146. package/src/device/meterplus.ts +54 -54
  147. package/src/device/motion.ts +62 -46
  148. package/src/device/plug.ts +19 -18
  149. package/src/device/robotvacuumcleaner.ts +89 -104
  150. package/src/device/waterdetector.ts +46 -34
  151. package/src/homebridge-ui/public/index.html +20 -14
  152. package/src/index.ts +3 -2
  153. package/src/irdevice/airconditioner.ts +13 -11
  154. package/src/irdevice/airpurifier.ts +5 -3
  155. package/src/irdevice/camera.ts +6 -4
  156. package/src/irdevice/fan.ts +42 -29
  157. package/src/irdevice/irdevice.ts +4 -5
  158. package/src/irdevice/light.ts +83 -103
  159. package/src/irdevice/other.ts +5 -3
  160. package/src/irdevice/tv.ts +7 -5
  161. package/src/irdevice/vacuumcleaner.ts +6 -4
  162. package/src/irdevice/waterheater.ts +6 -4
  163. package/src/platform.ts +59 -66
  164. package/src/settings.ts +73 -58
@@ -6,14 +6,17 @@ import { hostname } from 'os';
6
6
  import { request } from 'undici';
7
7
  import { interval, Subject } from 'rxjs';
8
8
  import { deviceBase } from './device.js';
9
- import { SwitchBotPlatform } from '../platform.js';
9
+ import { Devices } from '../settings.js';
10
10
  import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
11
- import { Service, PlatformAccessory, CharacteristicValue, CharacteristicChange } from 'homebridge';
12
- import { device, devicesConfig, serviceData, deviceStatus, Devices } from '../settings.js';
11
+
12
+ import type { SwitchBotPlatform } from '../platform.js';
13
+ import type { device, devicesConfig, serviceData, deviceStatus} from '../settings.js';
14
+ import type { Service, PlatformAccessory, CharacteristicValue, CharacteristicChange } from 'homebridge';
13
15
 
14
16
  export class Curtain extends deviceBase {
15
17
  // Services
16
- private WindowCovering!: {
18
+ private WindowCovering: {
19
+ Name: CharacteristicValue;
17
20
  Service: Service;
18
21
  PositionState: CharacteristicValue;
19
22
  TargetPosition: CharacteristicValue;
@@ -21,13 +24,16 @@ export class Curtain extends deviceBase {
21
24
  HoldPosition: CharacteristicValue;
22
25
  };
23
26
 
24
- private Battery!: {
27
+ private Battery: {
28
+ Name: CharacteristicValue;
25
29
  Service: Service;
26
30
  BatteryLevel: CharacteristicValue;
27
31
  StatusLowBattery: CharacteristicValue;
32
+ ChargingState: CharacteristicValue;
28
33
  };
29
34
 
30
35
  private LightSensor?: {
36
+ Name: CharacteristicValue;
31
37
  Service: Service;
32
38
  CurrentAmbientLightLevel?: CharacteristicValue;
33
39
  };
@@ -55,49 +61,29 @@ export class Curtain extends deviceBase {
55
61
 
56
62
  // Initialize LightBulb property
57
63
  this.WindowCovering = {
58
- Service: accessory.getService(this.hap.Service.WindowCovering) as Service,
59
- PositionState: accessory.context.PositionState || this.hap.Characteristic.PositionState.STOPPED,
60
- TargetPosition: accessory.context.TargetPosition || 100,
61
- CurrentPosition: accessory.context.CurrentPosition || 100,
62
- HoldPosition: accessory.context.HoldPosition || false,
63
- };
64
-
65
- // Initialize Battery property
66
- this.Battery = {
67
- Service: accessory.getService(this.hap.Service.Battery) as Service,
68
- BatteryLevel: accessory.context.BatteryLevel || 100,
69
- StatusLowBattery: accessory.context.StatusLowBattery || this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,
64
+ Name: accessory.context.WindowCovering.Name ?? accessory.displayName,
65
+ Service: accessory.getService(this.hap.Service.WindowCovering) ?? accessory.addService(this.hap.Service.WindowCovering) as Service,
66
+ PositionState: accessory.context.PositionState ?? this.hap.Characteristic.PositionState.STOPPED,
67
+ TargetPosition: accessory.context.TargetPosition ?? 100,
68
+ CurrentPosition: accessory.context.CurrentPosition ?? 100,
69
+ HoldPosition: accessory.context.HoldPosition ?? false,
70
70
  };
71
71
 
72
- // Initialize LightSensor property
73
- if (!this.device.curtain?.hide_lightsensor) {
74
- this.LightSensor = {
75
- Service: accessory.getService(this.hap.Service.LightSensor) as Service,
76
- CurrentAmbientLightLevel: accessory.context.CurrentAmbientLightLevel || 0.0001,
77
- };
78
- }
79
-
80
- // Retrieve initial values and updateHomekit
81
- this.refreshStatus();
82
-
83
- // get the WindowCovering service if it exists, otherwise create a new WindowCovering service
84
- // you can create multiple services for each accessory
85
- const WindowCoveringService = `${accessory.displayName} ${device.deviceType}`;
86
- (this.WindowCovering.Service = accessory.getService(this.hap.Service.WindowCovering)
87
- || accessory.addService(this.hap.Service.WindowCovering)), WindowCoveringService;
88
-
89
- this.WindowCovering.Service.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
90
-
91
- // each service must implement at-minimum the "required characteristics" for the given service type
92
- // see https://developers.homebridge.io/#/service/WindowCovering
93
-
94
- // create handlers for required characteristics
95
- this.WindowCovering.Service.setCharacteristic(this.hap.Characteristic.PositionState, this.WindowCovering.PositionState);
72
+ // Initialize WindowCovering Service
73
+ this.WindowCovering.Service.
74
+ setCharacteristic(this.hap.Characteristic.Name, this.WindowCovering.Name)
75
+ .setCharacteristic(this.hap.Characteristic.ObstructionDetected, false)
76
+ .getCharacteristic(this.hap.Characteristic.PositionState)
77
+ .onGet(() => {
78
+ return this.WindowCovering.PositionState;
79
+ });
80
+ accessory.context.WindowCovering.Name = this.WindowCovering.Name;
96
81
 
82
+ // Initialize WindowCovering CurrentPosition
97
83
  this.WindowCovering.Service
98
84
  .getCharacteristic(this.hap.Characteristic.CurrentPosition)
99
85
  .setProps({
100
- minStep: this.minStep(device),
86
+ minStep: Number(this.minStep(device)),
101
87
  minValue: 0,
102
88
  maxValue: 100,
103
89
  validValueRanges: [0, 100],
@@ -106,42 +92,83 @@ export class Curtain extends deviceBase {
106
92
  return this.WindowCovering.CurrentPosition;
107
93
  });
108
94
 
95
+ // Initialize WindowCovering TargetPosition
109
96
  this.WindowCovering.Service
110
97
  .getCharacteristic(this.hap.Characteristic.TargetPosition)
111
98
  .setProps({
112
- minStep: this.minStep(device),
99
+ minStep: Number(this.minStep(device)),
113
100
  minValue: 0,
114
101
  maxValue: 100,
115
102
  validValueRanges: [0, 100],
116
103
  })
104
+ .onGet(() => {
105
+ return this.WindowCovering.TargetPosition;
106
+ })
117
107
  .onSet(this.TargetPositionSet.bind(this));
118
108
 
109
+ // Initialize WindowCovering TargetPosition
119
110
  this.WindowCovering.Service
120
111
  .getCharacteristic(this.hap.Characteristic.HoldPosition)
112
+ .onGet(() => {
113
+ return this.WindowCovering.HoldPosition;
114
+ })
121
115
  .onSet(this.HoldPositionSet.bind(this));
122
116
 
123
- // Light Sensor Service
117
+ // Initialize Battery property
118
+ this.Battery = {
119
+ Name: accessory.context.Battery.Name ?? `${accessory.displayName} Battery`,
120
+ Service: accessory.getService(this.hap.Service.Battery) ?? accessory.addService(this.hap.Service.Battery) as Service,
121
+ BatteryLevel: accessory.context.BatteryLevel ?? 100,
122
+ StatusLowBattery: accessory.context.StatusLowBattery ?? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,
123
+ ChargingState: accessory.context.ChargingState ?? this.hap.Characteristic.ChargingState.NOT_CHARGING,
124
+ };
125
+
126
+ // Initialize Battery Service
127
+ this.Battery.Service
128
+ .setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name)
129
+ .getCharacteristic(this.hap.Characteristic.BatteryLevel)
130
+ .onGet(() => {
131
+ return this.Battery.BatteryLevel;
132
+ });
133
+ accessory.context.Battery.Name = this.Battery.Name;
134
+
135
+ this.Battery.Service
136
+ .getCharacteristic(this.hap.Characteristic.StatusLowBattery)
137
+ .onGet(() => {
138
+ return this.Battery.StatusLowBattery;
139
+ });
140
+
141
+ this.Battery.Service
142
+ .getCharacteristic(this.hap.Characteristic.ChargingState)
143
+ .onGet(() => {
144
+ return this.Battery.ChargingState;
145
+ });
146
+
147
+ // Initialize LightSensor Service
124
148
  if (device.curtain?.hide_lightsensor) {
125
149
  this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Light Sensor Service`);
126
150
  this.LightSensor!.Service = this.accessory.getService(this.hap.Service.LightSensor) as Service;
127
151
  accessory.removeService(this.LightSensor!.Service);
128
- } else if (!this.LightSensor?.Service) {
129
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Light Sensor Service`);
130
- const LightSensorService = `${accessory.displayName} Light Sensor`;
131
- (this.LightSensor!.Service = this.accessory.getService(this.hap.Service.LightSensor)
132
- || this.accessory.addService(this.hap.Service.LightSensor)), LightSensorService;
133
-
134
- this.LightSensor!.Service.setCharacteristic(this.hap.Characteristic.Name, LightSensorService);
135
152
  } else {
136
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Light Sensor Service Not Added`);
137
- }
153
+ this.LightSensor = {
154
+ Name: accessory.context.LightSensor.Name ?? `${accessory.displayName} Light Sensor`,
155
+ Service: accessory.getService(this.hap.Service.LightSensor) ?? this.accessory.addService(this.hap.Service.LightSensor) as Service,
156
+ CurrentAmbientLightLevel: accessory.context.CurrentAmbientLightLevel ?? 0.0001,
157
+ };
138
158
 
139
- // Battery Service
140
- const batteryService = `${accessory.displayName} Battery`;
141
- (this.Battery.Service = this.accessory.getService(this.hap.Service.Battery)
142
- || accessory.addService(this.hap.Service.Battery)), batteryService;
159
+ // Initialize LightSensor Characteristic
160
+ this.LightSensor.Service
161
+ .setCharacteristic(this.hap.Characteristic.Name, this.LightSensor.Name)
162
+ .setCharacteristic(this.hap.Characteristic.StatusActive, true)
163
+ .getCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel)
164
+ .onGet(() => {
165
+ return this.LightSensor!.CurrentAmbientLightLevel!;
166
+ });
167
+ accessory.context.LightSensor.Name = this.LightSensor.Name;
168
+ }
143
169
 
144
- this.Battery.Service.setCharacteristic(this.hap.Characteristic.Name, `${accessory.displayName} Battery`);
170
+ // Retrieve initial values and updateHomekit
171
+ this.refreshStatus();
145
172
 
146
173
  // Update Homekit
147
174
  this.updateHomeKitCharacteristics();
@@ -343,30 +370,37 @@ export class Curtain extends deviceBase {
343
370
  case 3:
344
371
  this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 2;
345
372
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
373
+ this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
346
374
  break;
347
375
  case 4:
348
376
  this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 3;
349
377
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
378
+ this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
350
379
  break;
351
380
  case 5:
352
381
  this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 4;
353
382
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
383
+ this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
354
384
  break;
355
385
  case 6:
356
386
  this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 5;
357
387
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
388
+ this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
358
389
  break;
359
390
  case 7:
360
391
  this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 6;
361
392
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
393
+ this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
362
394
  break;
363
395
  case 8:
364
396
  this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 7;
365
397
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
398
+ this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
366
399
  break;
367
400
  case 9:
368
401
  this.LightSensor!.CurrentAmbientLightLevel = ((set_maxLux - set_minLux) / spaceBetweenLevels) * 8;
369
402
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} LightLevel: ${serviceData.lightLevel}`);
403
+ this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
370
404
  break;
371
405
  case 10:
372
406
  default:
@@ -439,12 +473,13 @@ export class Curtain extends deviceBase {
439
473
  const set_minLux = await this.minLux();
440
474
  const set_maxLux = await this.maxLux();
441
475
  switch (deviceStatus.body.brightness) {
442
- case 'dim':
443
- this.LightSensor!.CurrentAmbientLightLevel = set_minLux;
444
- break;
445
476
  case 'bright':
446
- default:
447
477
  this.LightSensor!.CurrentAmbientLightLevel = set_maxLux;
478
+ this.Battery.ChargingState = this.hap.Characteristic.ChargingState.CHARGING;
479
+ break;
480
+ case 'dim':
481
+ default:
482
+ this.LightSensor!.CurrentAmbientLightLevel = set_minLux;
448
483
  }
449
484
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName}`
450
485
  + ` CurrentAmbientLightLevel: ${this.LightSensor!.CurrentAmbientLightLevel}`);
@@ -841,6 +876,17 @@ export class Curtain extends deviceBase {
841
876
  this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
842
877
  + ` StatusLowBattery: ${this.Battery.StatusLowBattery}`);
843
878
  }
879
+ if (this.Battery.ChargingState === undefined) {
880
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} ChargingState: ${this.Battery.ChargingState}`);
881
+ } else {
882
+ if (this.device.mqttURL) {
883
+ this.mqttPublish('ChargingState', this.Battery.ChargingState.toString());
884
+ }
885
+ this.accessory.context.ChargingState = this.Battery.ChargingState;
886
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.ChargingState, this.Battery.ChargingState);
887
+ this.debugLog(`${this.device.deviceType}: ${this.accessory.displayName} updateCharacteristic`
888
+ + ` ChargingState: ${this.Battery.ChargingState}`);
889
+ }
844
890
  }
845
891
 
846
892
  async BLEPushConnection() {
@@ -906,7 +952,7 @@ export class Curtain extends deviceBase {
906
952
  }
907
953
  }
908
954
 
909
- minStep(device: device & devicesConfig): number {
955
+ async minStep(device: device & devicesConfig): Promise<number> {
910
956
  let set_minStep: number;
911
957
  if (device.curtain?.set_minStep) {
912
958
  set_minStep = device.curtain?.set_minStep;
@@ -948,11 +994,12 @@ export class Curtain extends deviceBase {
948
994
  this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, e);
949
995
  this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, e);
950
996
  this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, e);
997
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e);
998
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e);
999
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.ChargingState, e);
951
1000
  if (!this.device.curtain?.hide_lightsensor) {
952
1001
  this.LightSensor!.Service.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, e);
1002
+ this.LightSensor!.Service.updateCharacteristic(this.hap.Characteristic.StatusActive, e);
953
1003
  }
954
- this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e);
955
- this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e);
956
- //throw new this.platform.api.hap.HapStatusError(HAPStatus.SERVICE_COMMUNICATION_FAILURE);
957
1004
  }
958
1005
  }
@@ -2,15 +2,16 @@
2
2
  *
3
3
  * device.ts: @switchbot/homebridge-switchbot.
4
4
  */
5
- import { API, HAP, Logging, PlatformAccessory } from 'homebridge';
6
5
 
7
6
  import { hostname } from 'os';
8
- import { MqttClient } from 'mqtt';
9
7
  import asyncmqtt from 'async-mqtt';
10
- import { SwitchBotPlatform } from '../platform.js';
11
- import { SwitchBotPlatformConfig, device, devicesConfig } from '../settings.js';
12
8
  import { BlindTiltMappingMode, SwitchBotModel, SwitchBotBLEModel, sleep } from '../utils.js';
13
9
 
10
+ import type { MqttClient } from 'mqtt';
11
+ import type { SwitchBotPlatform } from '../platform.js';
12
+ import type { API, HAP, Logging, PlatformAccessory } from 'homebridge';
13
+ import type { SwitchBotPlatformConfig, device, devicesConfig } from '../settings.js';
14
+
14
15
  export abstract class deviceBase {
15
16
  public readonly api: API;
16
17
  public readonly log: Logging;
@@ -564,15 +565,13 @@ export abstract class deviceBase {
564
565
  }
565
566
 
566
567
  async statusCode(statusCode: number): Promise<void> {
567
- switch (statusCode) {
568
- case 171:
569
- switch (this.device.deviceId) {
570
- case this.device.hubDeviceId:
571
- case '000000000000':
572
- statusCode = 161;
573
- break;
574
- }
575
- break;
568
+ if (statusCode === 171) {
569
+ if (this.device.deviceId === this.device.hubDeviceId) {
570
+ statusCode = 161;
571
+ }
572
+ if (this.device.deviceId === '000000000000') {
573
+ statusCode = 161;
574
+ }
576
575
  }
577
576
  switch (statusCode) {
578
577
  case 151:
package/src/device/fan.ts CHANGED
@@ -4,14 +4,17 @@
4
4
  */
5
5
  import { request } from 'undici';
6
6
  import { deviceBase } from './device.js';
7
- import { SwitchBotPlatform } from '../platform.js';
7
+ import { Devices } from '../settings.js';
8
8
  import { Subject, debounceTime, interval, skipWhile, take, tap } from 'rxjs';
9
- import { CharacteristicValue, PlatformAccessory, Service } from 'homebridge';
10
- import { device, devicesConfig, serviceData, deviceStatus, Devices } from '../settings.js';
9
+
10
+ import type { SwitchBotPlatform } from '../platform.js';
11
+ import type { CharacteristicValue, PlatformAccessory, Service } from 'homebridge';
12
+ import type { device, devicesConfig, serviceData, deviceStatus} from '../settings.js';
11
13
 
12
14
  export class Fan extends deviceBase {
13
15
  // Services
14
16
  private Fan: {
17
+ Name: CharacteristicValue;
15
18
  Service: Service;
16
19
  Active: CharacteristicValue;
17
20
  SwingMode: CharacteristicValue;
@@ -19,6 +22,7 @@ export class Fan extends deviceBase {
19
22
  };
20
23
 
21
24
  private Battery: {
25
+ Name: CharacteristicValue;
22
26
  Service: Service;
23
27
  BatteryLevel: CharacteristicValue;
24
28
  StatusLowBattery: CharacteristicValue;
@@ -39,42 +43,75 @@ export class Fan extends deviceBase {
39
43
  this.doPlugUpdate = new Subject();
40
44
  this.plugUpdateInProgress = false;
41
45
 
42
- // Initialize Fan property
46
+ // Initialize Fan Service
43
47
  this.Fan = {
44
- Service: accessory.getService(this.hap.Service.Fanv2) as Service,
45
- Active: accessory.context.Active || this.hap.Characteristic.Active.INACTIVE,
46
- SwingMode: accessory.context.SwingMode || this.hap.Characteristic.SwingMode.SWING_DISABLED,
47
- RotationSpeed: accessory.context.RotationSpeed || 0,
48
+ Name: accessory.context.Fan.Name ?? accessory.displayName,
49
+ Service: accessory.getService(this.hap.Service.Fanv2) ?? accessory.addService(this.hap.Service.Fanv2) as Service,
50
+ Active: accessory.context.Active ?? this.hap.Characteristic.Active.INACTIVE,
51
+ SwingMode: accessory.context.SwingMode ?? this.hap.Characteristic.SwingMode.SWING_DISABLED,
52
+ RotationSpeed: accessory.context.RotationSpeed ?? 0,
48
53
  };
49
54
 
55
+ // Initialize Fan Service
56
+ this.Fan.Service
57
+ .setCharacteristic(this.hap.Characteristic.Name, this.Fan.Name)
58
+ .getCharacteristic(this.hap.Characteristic.Active)
59
+ .onGet(() => {
60
+ return this.Fan.Active;
61
+ })
62
+ .onSet(this.ActiveSet.bind(this));
63
+
64
+ // Initialize Fan RotationSpeed Characteristic
65
+ this.Fan.Service
66
+ .getCharacteristic(this.hap.Characteristic.RotationSpeed)
67
+ .onGet(() => {
68
+ return this.Fan.RotationSpeed;
69
+ })
70
+ .onSet(this.RotationSpeedSet.bind(this));
71
+
72
+ // Initialize Fan SwingMode Characteristic
73
+ this.Fan.Service.getCharacteristic(this.hap.Characteristic.SwingMode)
74
+ .onGet(() => {
75
+ return this.Fan.SwingMode;
76
+ })
77
+ .onSet(this.SwingModeSet.bind(this));
78
+ accessory.context.Fan.Name = this.Fan.Name;
79
+
50
80
  // Initialize Battery property
51
81
  this.Battery = {
52
- Service: accessory.getService(this.hap.Service.Battery) as Service,
53
- BatteryLevel: accessory.context.BatteryLevel || 100,
54
- StatusLowBattery: accessory.context.StatusLowBattery || this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,
55
- ChargingState: accessory.context.ChargingState || this.hap.Characteristic.ChargingState.NOT_CHARGING,
82
+ Name: accessory.context.Battery.Name ?? accessory.displayName,
83
+ Service: accessory.getService(this.hap.Service.Battery) ?? accessory.addService(this.hap.Service.Battery) as Service,
84
+ BatteryLevel: accessory.context.BatteryLevel ?? 100,
85
+ StatusLowBattery: accessory.context.StatusLowBattery ?? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,
86
+ ChargingState: accessory.context.ChargingState ?? this.hap.Characteristic.ChargingState.NOT_CHARGING,
56
87
  };
57
88
 
89
+ // Initialize Battery Service
90
+ this.Battery.Service
91
+ .setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name)
92
+ .getCharacteristic(this.hap.Characteristic.BatteryLevel)
93
+ .onGet(() => {
94
+ return this.Battery.BatteryLevel;
95
+ });
96
+
97
+ // Initialize Battery ChargingState Characteristic
98
+ this.Battery.Service
99
+ .getCharacteristic(this.hap.Characteristic.ChargingState)
100
+ .onGet(() => {
101
+ return this.Battery.ChargingState;
102
+ });
103
+
104
+ // Initialize Battery StatusLowBattery Characteristic
105
+ this.Battery.Service
106
+ .getCharacteristic(this.hap.Characteristic.StatusLowBattery)
107
+ .onGet(() => {
108
+ return this.Battery.StatusLowBattery;
109
+ });
110
+ accessory.context.Battery.Name = this.Battery.Name;
111
+
58
112
  // Retrieve initial values and updateHomekit
59
113
  this.refreshStatus();
60
114
 
61
- // get the Fan service if it exists, otherwise create a new Fanv2 service
62
- // you can create multiple services for each accessory
63
- const FanService = `${accessory.displayName} ${device.deviceType}`;
64
- (this.Fan.Service = accessory.getService(this.hap.Service.Fanv2)
65
- || accessory.addService(this.hap.Service.Fanv2)), FanService;
66
-
67
- this.Fan.Service.setCharacteristic(this.hap.Characteristic.Name, accessory.displayName);
68
- // each service must implement at-minimum the "required characteristics" for the given service type
69
- // see https://developers.homebridge.io/#/service/Fanv2
70
-
71
- // create handlers for required characteristics
72
- this.Fan.Service.getCharacteristic(this.hap.Characteristic.Active).onSet(this.ActiveSet.bind(this));
73
- // create handlers for required characteristics
74
- this.Fan.Service.getCharacteristic(this.hap.Characteristic.RotationSpeed).onSet(this.RotationSpeedSet.bind(this));
75
- // create handlers for required characteristics
76
- this.Fan.Service.getCharacteristic(this.hap.Characteristic.SwingMode).onSet(this.SwingModeSet.bind(this));
77
-
78
115
  // Update Homekit
79
116
  this.updateHomeKitCharacteristics();
80
117
 
package/src/device/hub.ts CHANGED
@@ -2,26 +2,32 @@
2
2
  *
3
3
  * hub.ts: @switchbot/homebridge-switchbot.
4
4
  */
5
- import { Subject, interval, skipWhile } from 'rxjs';
5
+ import { Units } from 'homebridge';
6
6
  import { deviceBase } from './device.js';
7
- import { SwitchBotPlatform } from '../platform.js';
8
- import { Devices, device, deviceStatus, devicesConfig } from '../settings.js';
9
- import { CharacteristicValue, PlatformAccessory, Service, Units } from 'homebridge';
7
+ import { Devices } from '../settings.js';
10
8
  import { convertUnits } from '../utils.js';
9
+ import { Subject, interval, skipWhile } from 'rxjs';
10
+
11
+ import type { SwitchBotPlatform } from '../platform.js';
12
+ import type { device, deviceStatus, devicesConfig } from '../settings.js';
13
+ import type { CharacteristicValue, PlatformAccessory, Service } from 'homebridge';
11
14
 
12
15
  export class Hub extends deviceBase {
13
16
  // Services
14
17
  private LightSensor?: {
18
+ Name: CharacteristicValue;
15
19
  Service: Service;
16
20
  CurrentAmbientLightLevel: CharacteristicValue;
17
21
  };
18
22
 
19
23
  private HumiditySensor?: {
24
+ Name: CharacteristicValue;
20
25
  Service: Service;
21
26
  CurrentRelativeHumidity: CharacteristicValue;
22
27
  };
23
28
 
24
29
  private TemperatureSensor?: {
30
+ Name: CharacteristicValue;
25
31
  Service: Service;
26
32
  CurrentTemperature: CharacteristicValue;
27
33
  };
@@ -40,46 +46,21 @@ export class Hub extends deviceBase {
40
46
  this.doHubUpdate = new Subject();
41
47
  this.hubUpdateInProgress = false;
42
48
 
43
- // Initialize Temperature Sensor property
44
- if (!device.hub?.hide_temperature) {
45
- this.TemperatureSensor = {
46
- Service: accessory.getService(this.hap.Service.TemperatureSensor) as Service,
47
- CurrentTemperature: accessory.context.CurrentTemperature || 0,
48
- };
49
- }
50
-
51
- // Initialize Humidity Sensor property
52
- if (!device.hub?.hide_humidity) {
53
- this.HumiditySensor = {
54
- Service: accessory.getService(this.hap.Service.HumiditySensor) as Service,
55
- CurrentRelativeHumidity: accessory.context.CurrentRelativeHumidity || 0,
56
- };
57
- }
58
-
59
- // Initialize Light Sensor property
60
- if (!device.hub?.hide_lightsensor) {
61
- this.LightSensor = {
62
- Service: accessory.getService(this.hap.Service.LightSensor) as Service,
63
- CurrentAmbientLightLevel: accessory.context.CurrentAmbientLightLevel || 0.0001,
64
- };
65
- }
66
-
67
- // Retrieve initial values and updateHomekit
68
- this.refreshStatus();
69
-
70
- // Temperature Sensor Service
49
+ // Initialize Temperature Sensor Service
71
50
  if (device.hub?.hide_temperature) {
72
51
  this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Temperature Sensor Service`);
73
52
  this.TemperatureSensor!.Service = this.accessory.getService(this.hap.Service.TemperatureSensor) as Service;
74
53
  accessory.removeService(this.TemperatureSensor!.Service);
75
- } else if (!this.TemperatureSensor?.Service) {
76
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Temperature Sensor Service`);
77
- const TemperatureSensorService = `${accessory.displayName} Temperature Sensor`;
78
- (this.TemperatureSensor!.Service = this.accessory.getService(this.hap.Service.TemperatureSensor)
79
- || this.accessory.addService(this.hap.Service.TemperatureSensor)), TemperatureSensorService;
80
-
81
- this.TemperatureSensor!.Service.setCharacteristic(this.hap.Characteristic.Name, TemperatureSensorService);
82
- this.TemperatureSensor!.Service
54
+ } else {
55
+ this.TemperatureSensor = {
56
+ Name: accessory.context.TemperatureSensor.Name ?? `${accessory.displayName} Temperature Sensor`,
57
+ Service: accessory.getService(this.hap.Service.TemperatureSensor) ?? this.accessory.addService(this.hap.Service.TemperatureSensor) as Service,
58
+ CurrentTemperature: accessory.context.CurrentTemperature ?? 0,
59
+ };
60
+
61
+ // Initialize Temperature Sensor Characteristic
62
+ this.TemperatureSensor.Service
63
+ .setCharacteristic(this.hap.Characteristic.Name, this.TemperatureSensor.Name)
83
64
  .getCharacteristic(this.hap.Characteristic.CurrentTemperature)
84
65
  .setProps({
85
66
  unit: Units['CELSIUS'],
@@ -91,23 +72,24 @@ export class Hub extends deviceBase {
91
72
  .onGet(() => {
92
73
  return this.TemperatureSensor!.CurrentTemperature;
93
74
  });
94
- } else {
95
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Temperature Sensor Service Not Added`);
75
+ accessory.context.TemperatureSensor.Name = this.TemperatureSensor.Name;
96
76
  }
97
77
 
98
- // Humidity Sensor Service
78
+ // Initialize Humidity Sensor Service
99
79
  if (device.hub?.hide_humidity) {
100
80
  this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Humidity Sensor Service`);
101
81
  this.HumiditySensor!.Service = this.accessory.getService(this.hap.Service.HumiditySensor) as Service;
102
82
  accessory.removeService(this.HumiditySensor!.Service);
103
- } else if (!this.HumiditySensor?.Service) {
104
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Humidity Sensor Service`);
105
- const HumiditySensorService = `${accessory.displayName} Humidity Sensor`;
106
- (this.HumiditySensor!.Service = this.accessory.getService(this.hap.Service.HumiditySensor)
107
- || this.accessory.addService(this.hap.Service.HumiditySensor)), HumiditySensorService;
83
+ } else {
84
+ this.HumiditySensor = {
85
+ Name: accessory.context.HumiditySensor.Name ?? `${accessory.displayName} Humidity Sensor`,
86
+ Service: accessory.getService(this.hap.Service.HumiditySensor) ?? this.accessory.addService(this.hap.Service.HumiditySensor) as Service,
87
+ CurrentRelativeHumidity: accessory.context.CurrentRelativeHumidity ?? 0,
88
+ };
108
89
 
109
- this.HumiditySensor!.Service.setCharacteristic(this.hap.Characteristic.Name, HumiditySensorService);
90
+ // Initialize Humidity Sensor Characteristics
110
91
  this.HumiditySensor!.Service
92
+ .setCharacteristic(this.hap.Characteristic.Name, this.HumiditySensor.Name)
111
93
  .getCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity)
112
94
  .setProps({
113
95
  minStep: 0.1,
@@ -115,26 +97,37 @@ export class Hub extends deviceBase {
115
97
  .onGet(() => {
116
98
  return this.HumiditySensor!.CurrentRelativeHumidity;
117
99
  });
118
- } else {
119
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Humidity Sensor Service Not Added`);
100
+ accessory.context.HumiditySensor.Name = this.HumiditySensor.Name;
120
101
  }
121
102
 
122
- // Light Sensor Service
103
+ // Initialize Light Sensor Service
123
104
  if (device.hub?.hide_lightsensor) {
124
105
  this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Removing Light Sensor Service`);
125
106
  this.LightSensor!.Service = this.accessory.getService(this.hap.Service.LightSensor) as Service;
126
107
  accessory.removeService(this.LightSensor!.Service);
127
- } else if (!this.LightSensor?.Service) {
128
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Add Light Sensor Service`);
129
- const LightSensorService = `${accessory.displayName} Light Sensor`;
130
- (this.LightSensor!.Service = this.accessory.getService(this.hap.Service.LightSensor)
131
- || this.accessory.addService(this.hap.Service.LightSensor)), LightSensorService;
132
-
133
- this.LightSensor!.Service.setCharacteristic(this.hap.Characteristic.Name, LightSensorService);
134
108
  } else {
135
- this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Light Sensor Service Not Added`);
109
+ this.LightSensor = {
110
+ Name: accessory.context.LightSensor.Name ?? `${accessory.displayName} Light Sensor`,
111
+ Service: accessory.getService(this.hap.Service.LightSensor) ?? this.accessory.addService(this.hap.Service.LightSensor) as Service,
112
+ CurrentAmbientLightLevel: accessory.context.CurrentAmbientLightLevel ?? 0.0001,
113
+ };
114
+
115
+ // Initialize Light Sensor Characteristics
116
+ this.LightSensor!.Service
117
+ .setCharacteristic(this.hap.Characteristic.Name, this.LightSensor.Name)
118
+ .getCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel)
119
+ .setProps({
120
+ minStep: 1,
121
+ })
122
+ .onGet(() => {
123
+ return this.LightSensor!.CurrentAmbientLightLevel;
124
+ });
125
+ accessory.context.LightSensor.Name = this.LightSensor.Name;
136
126
  }
137
127
 
128
+ // Retrieve initial values and updateHomekit
129
+ this.refreshStatus();
130
+
138
131
  // Retrieve initial values and update Homekit
139
132
  this.updateHomeKitCharacteristics();
140
133