@switchbot/homebridge-switchbot 3.7.1-beta.9 → 3.8.0

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 (195) hide show
  1. package/CHANGELOG.md +8 -2
  2. package/README.md +14 -0
  3. package/assets/security-privacy-bluetooth.png +0 -0
  4. package/config.schema.json +76 -1
  5. package/dist/device/blindtilt.d.ts +18 -8
  6. package/dist/device/blindtilt.d.ts.map +1 -1
  7. package/dist/device/blindtilt.js +108 -70
  8. package/dist/device/blindtilt.js.map +1 -1
  9. package/dist/device/bot.d.ts +9 -9
  10. package/dist/device/bot.d.ts.map +1 -1
  11. package/dist/device/bot.js +133 -160
  12. package/dist/device/bot.js.map +1 -1
  13. package/dist/device/ceilinglight.d.ts +13 -13
  14. package/dist/device/ceilinglight.d.ts.map +1 -1
  15. package/dist/device/ceilinglight.js +38 -73
  16. package/dist/device/ceilinglight.js.map +1 -1
  17. package/dist/device/colorbulb.d.ts +12 -12
  18. package/dist/device/colorbulb.d.ts.map +1 -1
  19. package/dist/device/colorbulb.js +41 -79
  20. package/dist/device/colorbulb.js.map +1 -1
  21. package/dist/device/contact.d.ts +5 -5
  22. package/dist/device/contact.d.ts.map +1 -1
  23. package/dist/device/contact.js +20 -42
  24. package/dist/device/contact.js.map +1 -1
  25. package/dist/device/curtain.d.ts +15 -5
  26. package/dist/device/curtain.d.ts.map +1 -1
  27. package/dist/device/curtain.js +127 -81
  28. package/dist/device/curtain.js.map +1 -1
  29. package/dist/device/device.d.ts +18 -18
  30. package/dist/device/device.d.ts.map +1 -1
  31. package/dist/device/device.js +33 -36
  32. package/dist/device/device.js.map +1 -1
  33. package/dist/device/fan.d.ts +8 -8
  34. package/dist/device/fan.d.ts.map +1 -1
  35. package/dist/device/fan.js +43 -75
  36. package/dist/device/fan.js.map +1 -1
  37. package/dist/device/hub.d.ts +5 -5
  38. package/dist/device/hub.d.ts.map +1 -1
  39. package/dist/device/hub.js +18 -39
  40. package/dist/device/hub.js.map +1 -1
  41. package/dist/device/humidifier.d.ts +5 -5
  42. package/dist/device/humidifier.d.ts.map +1 -1
  43. package/dist/device/humidifier.js +38 -78
  44. package/dist/device/humidifier.js.map +1 -1
  45. package/dist/device/iosensor.d.ts +5 -5
  46. package/dist/device/iosensor.d.ts.map +1 -1
  47. package/dist/device/iosensor.js +21 -40
  48. package/dist/device/iosensor.js.map +1 -1
  49. package/dist/device/lightstrip.d.ts +6 -6
  50. package/dist/device/lightstrip.d.ts.map +1 -1
  51. package/dist/device/lightstrip.js +34 -73
  52. package/dist/device/lightstrip.js.map +1 -1
  53. package/dist/device/lock.d.ts +9 -9
  54. package/dist/device/lock.d.ts.map +1 -1
  55. package/dist/device/lock.js +37 -52
  56. package/dist/device/lock.js.map +1 -1
  57. package/dist/device/meter.d.ts +5 -5
  58. package/dist/device/meter.d.ts.map +1 -1
  59. package/dist/device/meter.js +21 -39
  60. package/dist/device/meter.js.map +1 -1
  61. package/dist/device/meterplus.d.ts +5 -5
  62. package/dist/device/meterplus.d.ts.map +1 -1
  63. package/dist/device/meterplus.js +21 -38
  64. package/dist/device/meterplus.js.map +1 -1
  65. package/dist/device/motion.d.ts +5 -5
  66. package/dist/device/motion.d.ts.map +1 -1
  67. package/dist/device/motion.js +14 -32
  68. package/dist/device/motion.js.map +1 -1
  69. package/dist/device/plug.d.ts +12 -12
  70. package/dist/device/plug.d.ts.map +1 -1
  71. package/dist/device/plug.js +16 -25
  72. package/dist/device/plug.js.map +1 -1
  73. package/dist/device/robotvacuumcleaner.d.ts +11 -11
  74. package/dist/device/robotvacuumcleaner.d.ts.map +1 -1
  75. package/dist/device/robotvacuumcleaner.js +42 -56
  76. package/dist/device/robotvacuumcleaner.js.map +1 -1
  77. package/dist/device/waterdetector.d.ts +5 -5
  78. package/dist/device/waterdetector.d.ts.map +1 -1
  79. package/dist/device/waterdetector.js +47 -44
  80. package/dist/device/waterdetector.js.map +1 -1
  81. package/dist/homebridge-ui/server.js +2 -2
  82. package/dist/homebridge-ui/server.js.map +1 -1
  83. package/dist/index.d.ts.map +1 -1
  84. package/dist/index.js +0 -4
  85. package/dist/index.js.map +1 -1
  86. package/dist/irdevice/airconditioner.d.ts +8 -8
  87. package/dist/irdevice/airconditioner.d.ts.map +1 -1
  88. package/dist/irdevice/airconditioner.js +61 -105
  89. package/dist/irdevice/airconditioner.js.map +1 -1
  90. package/dist/irdevice/airpurifier.d.ts +10 -10
  91. package/dist/irdevice/airpurifier.d.ts.map +1 -1
  92. package/dist/irdevice/airpurifier.js +22 -42
  93. package/dist/irdevice/airpurifier.js.map +1 -1
  94. package/dist/irdevice/camera.d.ts +9 -9
  95. package/dist/irdevice/camera.d.ts.map +1 -1
  96. package/dist/irdevice/camera.js +15 -25
  97. package/dist/irdevice/camera.js.map +1 -1
  98. package/dist/irdevice/fan.d.ts +8 -8
  99. package/dist/irdevice/fan.d.ts.map +1 -1
  100. package/dist/irdevice/fan.js +21 -40
  101. package/dist/irdevice/fan.js.map +1 -1
  102. package/dist/irdevice/irdevice.d.ts +11 -11
  103. package/dist/irdevice/irdevice.d.ts.map +1 -1
  104. package/dist/irdevice/irdevice.js +14 -22
  105. package/dist/irdevice/irdevice.js.map +1 -1
  106. package/dist/irdevice/light.d.ts +9 -9
  107. package/dist/irdevice/light.d.ts.map +1 -1
  108. package/dist/irdevice/light.js +24 -47
  109. package/dist/irdevice/light.js.map +1 -1
  110. package/dist/irdevice/other.d.ts +9 -9
  111. package/dist/irdevice/other.d.ts.map +1 -1
  112. package/dist/irdevice/other.js +40 -83
  113. package/dist/irdevice/other.js.map +1 -1
  114. package/dist/irdevice/tv.d.ts +9 -9
  115. package/dist/irdevice/tv.d.ts.map +1 -1
  116. package/dist/irdevice/tv.js +29 -54
  117. package/dist/irdevice/tv.js.map +1 -1
  118. package/dist/irdevice/vacuumcleaner.d.ts +5 -5
  119. package/dist/irdevice/vacuumcleaner.d.ts.map +1 -1
  120. package/dist/irdevice/vacuumcleaner.js +11 -21
  121. package/dist/irdevice/vacuumcleaner.js.map +1 -1
  122. package/dist/irdevice/waterheater.d.ts +5 -5
  123. package/dist/irdevice/waterheater.d.ts.map +1 -1
  124. package/dist/irdevice/waterheater.js +11 -22
  125. package/dist/irdevice/waterheater.js.map +1 -1
  126. package/dist/platform.d.ts +20 -19
  127. package/dist/platform.d.ts.map +1 -1
  128. package/dist/platform.js +466 -710
  129. package/dist/platform.js.map +1 -1
  130. package/dist/settings.d.ts +5 -2
  131. package/dist/settings.d.ts.map +1 -1
  132. package/dist/settings.js.map +1 -1
  133. package/dist/types/bledevicestatus.d.ts +9 -9
  134. package/dist/types/bledevicestatus.d.ts.map +1 -1
  135. package/dist/types/devicelist.d.ts +6 -6
  136. package/dist/types/devicelist.d.ts.map +1 -1
  137. package/dist/types/deviceresponse.d.ts +4 -4
  138. package/dist/types/deviceresponse.d.ts.map +1 -1
  139. package/dist/types/devicestatus.d.ts +2 -2
  140. package/dist/types/devicestatus.d.ts.map +1 -1
  141. package/dist/types/devicewebhookstatus.d.ts +5 -5
  142. package/dist/types/devicewebhookstatus.d.ts.map +1 -1
  143. package/dist/types/irdevicelist.d.ts +4 -4
  144. package/dist/types/irdevicelist.d.ts.map +1 -1
  145. package/dist/types/pushbody.d.ts +2 -2
  146. package/dist/types/pushbody.d.ts.map +1 -1
  147. package/dist/utils.d.ts +4 -4
  148. package/dist/utils.d.ts.map +1 -1
  149. package/dist/utils.js +9 -13
  150. package/dist/utils.js.map +1 -1
  151. package/eslint.config.js +48 -93
  152. package/package.json +61 -54
  153. package/src/device/blindtilt.ts +509 -460
  154. package/src/device/bot.ts +696 -718
  155. package/src/device/ceilinglight.ts +331 -364
  156. package/src/device/colorbulb.ts +412 -448
  157. package/src/device/contact.ts +200 -221
  158. package/src/device/curtain.ts +506 -444
  159. package/src/device/device.ts +206 -208
  160. package/src/device/fan.ts +307 -340
  161. package/src/device/hub.ts +184 -209
  162. package/src/device/humidifier.ts +297 -342
  163. package/src/device/iosensor.ts +182 -204
  164. package/src/device/lightstrip.ts +362 -399
  165. package/src/device/lock.ts +262 -276
  166. package/src/device/meter.ts +183 -205
  167. package/src/device/meterplus.ts +183 -204
  168. package/src/device/motion.ts +169 -185
  169. package/src/device/plug.ts +174 -177
  170. package/src/device/robotvacuumcleaner.ts +256 -269
  171. package/src/device/waterdetector.ts +185 -185
  172. package/src/homebridge-ui/server.ts +16 -15
  173. package/src/index.ts +5 -6
  174. package/src/irdevice/airconditioner.ts +277 -326
  175. package/src/irdevice/airpurifier.ts +124 -143
  176. package/src/irdevice/camera.ts +58 -64
  177. package/src/irdevice/fan.ts +106 -123
  178. package/src/irdevice/irdevice.ts +116 -119
  179. package/src/irdevice/light.ts +119 -143
  180. package/src/irdevice/other.ts +417 -461
  181. package/src/irdevice/tv.ts +155 -177
  182. package/src/irdevice/vacuumcleaner.ts +54 -60
  183. package/src/irdevice/waterheater.ts +56 -63
  184. package/src/platform.ts +1462 -1678
  185. package/src/settings.ts +173 -170
  186. package/src/types/bledevicestatus.ts +252 -256
  187. package/src/types/devicelist.ts +79 -79
  188. package/src/types/deviceresponse.ts +12 -13
  189. package/src/types/devicestatus.ts +124 -124
  190. package/src/types/devicewebhookstatus.ts +126 -131
  191. package/src/types/irdevicelist.ts +10 -10
  192. package/src/types/pushbody.ts +5 -5
  193. package/src/utils.ts +64 -65
  194. package/tsconfig.json +10 -9
  195. package/.github/npm-version-script.cjs +0 -81
@@ -2,84 +2,98 @@
2
2
  *
3
3
  * curtain.ts: @switchbot/homebridge-switchbot.
4
4
  */
5
- import { hostname } from 'os';
6
- import { deviceBase } from './device.js';
5
+ import type { CharacteristicChange, CharacteristicValue, PlatformAccessory, Service } from 'homebridge'
6
+
7
+ import type { SwitchBotPlatform } from '../platform.js'
8
+ import type { devicesConfig } from '../settings.js'
9
+ import type { curtain3ServiceData, curtainServiceData } from '../types/bledevicestatus.js'
10
+ import type { device } from '../types/devicelist.js'
11
+ import type { curtainStatus } from '../types/devicestatus.js'
12
+ import type { curtain3WebhookContext, curtainWebhookContext } from '../types/devicewebhookstatus.js'
13
+
14
+ import { hostname } from 'node:os'
15
+
7
16
  /*
8
17
  * For Testing Locally:
9
18
  * import { SwitchBotBLEModel, SwitchBotBLEModelName } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js';
10
19
  */
11
- import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot';
12
-
13
- import { Subject, debounceTime, interval, skipWhile, take, tap } from 'rxjs';
20
+ import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot'
21
+ import { debounceTime, interval, skipWhile, Subject, take, tap } from 'rxjs'
14
22
 
15
- import type { devicesConfig } from '../settings.js';
16
- import type { device } from '../types/devicelist.js';
17
- import type { SwitchBotPlatform } from '../platform.js';
18
- import type { curtainStatus } from '../types/devicestatus.js';
19
- import type { curtainServiceData, curtain3ServiceData } from '../types/bledevicestatus.js';
20
- import type { curtain3WebhookContext, curtainWebhookContext } from '../types/devicewebhookstatus.js';
21
- import type { Service, PlatformAccessory, CharacteristicValue, CharacteristicChange } from 'homebridge';
23
+ import { deviceBase } from './device.js'
22
24
 
23
25
  export class Curtain extends deviceBase {
24
26
  // Services
25
27
  private WindowCovering: {
26
- Name: CharacteristicValue;
27
- Service: Service;
28
- PositionState: CharacteristicValue;
29
- TargetPosition: CharacteristicValue;
30
- CurrentPosition: CharacteristicValue;
31
- HoldPosition: CharacteristicValue;
32
- };
28
+ Name: CharacteristicValue
29
+ Service: Service
30
+ PositionState: CharacteristicValue
31
+ TargetPosition: CharacteristicValue
32
+ CurrentPosition: CharacteristicValue
33
+ HoldPosition: CharacteristicValue
34
+ }
33
35
 
34
36
  private Battery: {
35
- Name: CharacteristicValue;
36
- Service: Service;
37
- BatteryLevel: CharacteristicValue;
38
- StatusLowBattery: CharacteristicValue;
39
- ChargingState: CharacteristicValue;
40
- };
37
+ Name: CharacteristicValue
38
+ Service: Service
39
+ BatteryLevel: CharacteristicValue
40
+ StatusLowBattery: CharacteristicValue
41
+ ChargingState: CharacteristicValue
42
+ }
41
43
 
42
44
  private LightSensor?: {
43
- Name: CharacteristicValue;
44
- Service: Service;
45
- CurrentAmbientLightLevel?: CharacteristicValue;
46
- };
45
+ Name: CharacteristicValue
46
+ Service: Service
47
+ CurrentAmbientLightLevel?: CharacteristicValue
48
+ }
49
+
50
+ private OpenModeSwitch?: {
51
+ Name: string
52
+ Service: Service
53
+ On: CharacteristicValue
54
+ }
55
+
56
+ private CloseModeSwitch?: {
57
+ Name: string
58
+ Service: Service
59
+ On: CharacteristicValue
60
+ }
47
61
 
48
62
  // OpenAPI
49
- deviceStatus!: curtainStatus;
63
+ deviceStatus!: curtainStatus
50
64
 
51
- //Webhook
52
- webhookContext!: curtainWebhookContext | curtain3WebhookContext;
65
+ // Webhook
66
+ webhookContext!: curtainWebhookContext | curtain3WebhookContext
53
67
 
54
68
  // BLE
55
- serviceData!: curtainServiceData | curtain3ServiceData;
69
+ serviceData!: curtainServiceData | curtain3ServiceData
56
70
 
57
71
  // Target
58
- setNewTarget!: boolean;
59
- setNewTargetTimer!: NodeJS.Timeout;
72
+ setNewTarget!: boolean
73
+ setNewTargetTimer!: NodeJS.Timeout
60
74
 
61
75
  // Updates
62
- curtainMoving!: boolean;
63
- curtainUpdateInProgress!: boolean;
64
- doCurtainUpdate!: Subject<void>;
76
+ curtainMoving!: boolean
77
+ curtainUpdateInProgress!: boolean
78
+ doCurtainUpdate!: Subject<void>
65
79
 
66
80
  constructor(
67
81
  readonly platform: SwitchBotPlatform,
68
82
  accessory: PlatformAccessory,
69
83
  device: device & devicesConfig,
70
84
  ) {
71
- super(platform, accessory, device);
85
+ super(platform, accessory, device)
72
86
  // Set category
73
- accessory.category = this.hap.Categories.WINDOW_COVERING;
87
+ accessory.category = this.hap.Categories.WINDOW_COVERING
74
88
 
75
89
  // this is subject we use to track when we need to POST changes to the SwitchBot API
76
- this.doCurtainUpdate = new Subject();
77
- this.curtainMoving = false;
78
- this.curtainUpdateInProgress = false;
79
- this.setNewTarget = false;
90
+ this.doCurtainUpdate = new Subject()
91
+ this.curtainMoving = false
92
+ this.curtainUpdateInProgress = false
93
+ this.setNewTarget = false
80
94
 
81
95
  // Initialize WindowCovering Service
82
- accessory.context.WindowCovering = accessory.context.WindowCovering ?? {};
96
+ accessory.context.WindowCovering = accessory.context.WindowCovering ?? {}
83
97
  this.WindowCovering = {
84
98
  Name: accessory.displayName,
85
99
  Service: accessory.getService(this.hap.Service.WindowCovering) ?? accessory.addService(this.hap.Service.WindowCovering) as Service,
@@ -87,186 +101,217 @@ export class Curtain extends deviceBase {
87
101
  TargetPosition: accessory.context.TargetPosition ?? 100,
88
102
  CurrentPosition: accessory.context.CurrentPosition ?? 100,
89
103
  HoldPosition: accessory.context.HoldPosition ?? false,
90
- };
91
- accessory.context.WindowCovering = this.WindowCovering as object;
104
+ }
105
+ accessory.context.WindowCovering = this.WindowCovering as object
92
106
 
93
107
  // Initialize WindowCovering Service
94
- this.WindowCovering.Service.
95
- setCharacteristic(this.hap.Characteristic.Name, this.WindowCovering.Name)
96
- .setCharacteristic(this.hap.Characteristic.ObstructionDetected, false)
97
- .getCharacteristic(this.hap.Characteristic.PositionState)
98
- .onGet(() => {
99
- return this.WindowCovering.PositionState;
100
- });
108
+ this.WindowCovering.Service.setCharacteristic(this.hap.Characteristic.Name, this.WindowCovering.Name).setCharacteristic(this.hap.Characteristic.ObstructionDetected, false).getCharacteristic(this.hap.Characteristic.PositionState).onGet(() => {
109
+ return this.WindowCovering.PositionState
110
+ })
101
111
 
102
112
  // Initialize WindowCovering CurrentPosition
103
- this.WindowCovering.Service
104
- .getCharacteristic(this.hap.Characteristic.CurrentPosition)
105
- .setProps({
106
- minStep: device.curtain?.set_minStep ?? 1,
107
- minValue: 0,
108
- maxValue: 100,
109
- validValueRanges: [0, 100],
110
- })
111
- .onGet(() => {
112
- return this.WindowCovering.CurrentPosition;
113
- });
113
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.CurrentPosition).setProps({
114
+ minStep: device.curtain?.set_minStep ?? 1,
115
+ minValue: 0,
116
+ maxValue: 100,
117
+ validValueRanges: [0, 100],
118
+ }).onGet(() => {
119
+ return this.WindowCovering.CurrentPosition
120
+ })
114
121
 
115
122
  // Initialize WindowCovering TargetPosition
116
- this.WindowCovering.Service
117
- .getCharacteristic(this.hap.Characteristic.TargetPosition)
118
- .setProps({
119
- minStep: device.curtain?.set_minStep ?? 1,
120
- minValue: 0,
121
- maxValue: 100,
122
- validValueRanges: [0, 100],
123
- })
124
- .onGet(() => {
125
- return this.WindowCovering.TargetPosition;
126
- })
127
- .onSet(this.TargetPositionSet.bind(this));
123
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.TargetPosition).setProps({
124
+ minStep: device.curtain?.set_minStep ?? 1,
125
+ minValue: 0,
126
+ maxValue: 100,
127
+ validValueRanges: [0, 100],
128
+ }).onGet(() => {
129
+ return this.WindowCovering.TargetPosition
130
+ }).onSet(this.TargetPositionSet.bind(this))
128
131
 
129
132
  // Initialize WindowCovering TargetPosition
130
- this.WindowCovering.Service
131
- .getCharacteristic(this.hap.Characteristic.HoldPosition)
132
- .onGet(() => {
133
- return this.WindowCovering.HoldPosition;
134
- })
135
- .onSet(this.HoldPositionSet.bind(this));
133
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.HoldPosition).onGet(() => {
134
+ return this.WindowCovering.HoldPosition
135
+ }).onSet(this.HoldPositionSet.bind(this))
136
136
 
137
137
  // Initialize Battery Service
138
- accessory.context.Battery = accessory.context.Battery ?? {};
138
+ accessory.context.Battery = accessory.context.Battery ?? {}
139
139
  this.Battery = {
140
140
  Name: `${accessory.displayName} Battery`,
141
141
  Service: accessory.getService(this.hap.Service.Battery) ?? accessory.addService(this.hap.Service.Battery) as Service,
142
142
  BatteryLevel: accessory.context.BatteryLevel ?? 100,
143
143
  StatusLowBattery: accessory.context.StatusLowBattery ?? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,
144
144
  ChargingState: accessory.context.ChargingState ?? this.hap.Characteristic.ChargingState.NOT_CHARGING,
145
- };
146
- accessory.context.Battery = this.Battery as object;
145
+ }
146
+ accessory.context.Battery = this.Battery as object
147
147
 
148
148
  // Initialize Battery Service
149
- this.Battery.Service
150
- .setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name)
151
- .getCharacteristic(this.hap.Characteristic.BatteryLevel)
152
- .onGet(() => {
153
- return this.Battery.BatteryLevel;
154
- });
155
-
156
- this.Battery.Service
157
- .getCharacteristic(this.hap.Characteristic.StatusLowBattery)
158
- .onGet(() => {
159
- return this.Battery.StatusLowBattery;
160
- });
161
-
162
- this.Battery.Service
163
- .getCharacteristic(this.hap.Characteristic.ChargingState)
164
- .onGet(() => {
165
- return this.Battery.ChargingState;
166
- });
149
+ this.Battery.Service.setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name).getCharacteristic(this.hap.Characteristic.BatteryLevel).onGet(() => {
150
+ return this.Battery.BatteryLevel
151
+ })
152
+
153
+ this.Battery.Service.getCharacteristic(this.hap.Characteristic.StatusLowBattery).onGet(() => {
154
+ return this.Battery.StatusLowBattery
155
+ })
156
+
157
+ this.Battery.Service.getCharacteristic(this.hap.Characteristic.ChargingState).onGet(() => {
158
+ return this.Battery.ChargingState
159
+ })
167
160
 
168
161
  // Initialize LightSensor Service
169
- if (device.curtain?.hide_lightsensor) {
162
+ if (device.curtain?.hide_lightsensor || (device.deviceType !== 'curtain' && device.deviceType !== 'curtain3')) {
170
163
  if (this.LightSensor?.Service) {
171
- this.debugLog('Removing Light Sensor Service');
172
- this.LightSensor.Service = this.accessory.getService(this.hap.Service.LightSensor) as Service;
173
- accessory.removeService(this.LightSensor.Service);
174
- accessory.context.LightSensor = {};
164
+ this.debugLog('Removing Light Sensor Service')
165
+ this.LightSensor.Service = this.accessory.getService(this.hap.Service.LightSensor) as Service
166
+ accessory.removeService(this.LightSensor.Service)
167
+ accessory.context.LightSensor = {}
175
168
  }
176
- } else {
177
- accessory.context.LightSensor = accessory.context.LightSensor ?? {};
169
+ } else if (device.deviceType === 'curtain' || device.deviceType === 'curtain3') {
170
+ accessory.context.LightSensor = accessory.context.LightSensor ?? {}
178
171
  this.LightSensor = {
179
172
  Name: `${accessory.displayName} Light Sensor`,
180
173
  Service: accessory.getService(this.hap.Service.LightSensor) ?? this.accessory.addService(this.hap.Service.LightSensor) as Service,
181
174
  CurrentAmbientLightLevel: accessory.context.CurrentAmbientLightLevel ?? 0.0001,
182
- };
183
- accessory.context.LightSensor = this.LightSensor as object;
175
+ }
176
+ accessory.context.LightSensor = this.LightSensor as object
184
177
 
185
178
  // Initialize LightSensor Characteristic
186
- this.LightSensor.Service
187
- .setCharacteristic(this.hap.Characteristic.Name, this.LightSensor.Name)
188
- .setCharacteristic(this.hap.Characteristic.StatusActive, true)
189
- .getCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel)
190
- .onGet(() => {
191
- return this.LightSensor!.CurrentAmbientLightLevel!;
192
- });
179
+ this.LightSensor.Service.setCharacteristic(this.hap.Characteristic.Name, this.LightSensor.Name).setCharacteristic(this.hap.Characteristic.StatusActive, true).getCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel).onGet(() => {
180
+ return this.LightSensor!.CurrentAmbientLightLevel!
181
+ })
182
+ }
183
+
184
+ // Initialize Open Mode Switch Service
185
+ if (!device.curtain?.silentModeSwitch) {
186
+ if (this.OpenModeSwitch?.Service) {
187
+ this.debugLog('Removing Open Mode Switch Service')
188
+ this.OpenModeSwitch.Service = this.accessory.getService(this.hap.Service.Switch) as Service
189
+ accessory.removeService(this.OpenModeSwitch.Service)
190
+ accessory.context.OpenModeSwitch = {}
191
+ }
192
+ } else {
193
+ accessory.context.OpenModeSwitch = accessory.context.OpenModeSwitch ?? {}
194
+ this.debugLog('Adding Open Mode Switch Service')
195
+ const name = `${accessory.displayName} Silent Open Mode`
196
+ const uuid = this.api.hap.uuid.generate(name)
197
+ this.OpenModeSwitch = {
198
+ Name: name,
199
+ Service: accessory.getService(name) ?? accessory.addService(this.hap.Service.Switch, name, uuid) as Service,
200
+ On: accessory.context.OpenModeSwitch.On ?? false,
201
+ }
202
+ accessory.context.OpenModeSwitch = this.OpenModeSwitch as object
203
+
204
+ // Initialize Open Mode Switch Service
205
+ this.OpenModeSwitch.Service.setCharacteristic(this.hap.Characteristic.Name, this.OpenModeSwitch.Name).getCharacteristic(this.hap.Characteristic.On).onGet(() => {
206
+ return this.OpenModeSwitch?.On ?? false
207
+ })
208
+
209
+ this.OpenModeSwitch.Service.getCharacteristic(this.hap.Characteristic.On).onSet(this.OpenModeSwitchSet.bind(this))
210
+ }
211
+
212
+ // Initialize Close Mode Switch Service
213
+ if (!device.curtain?.silentModeSwitch) {
214
+ if (this.CloseModeSwitch?.Service) {
215
+ this.debugLog('Removing Close Mode Switch Service')
216
+ this.CloseModeSwitch.Service = this.accessory.getService(this.hap.Service.Switch) as Service
217
+ accessory.removeService(this.CloseModeSwitch.Service)
218
+ accessory.context.CloseModeSwitch = {}
219
+ }
220
+ } else {
221
+ accessory.context.CloseModeSwitch = accessory.context.CloseModeSwitch ?? {}
222
+ this.debugLog('Adding Close Mode Switch Service')
223
+ const name = `${accessory.displayName} Silent Close Mode`
224
+ const uuid = this.api.hap.uuid.generate(name)
225
+ this.CloseModeSwitch = {
226
+ Name: name,
227
+ Service: this.accessory.getService(name) ?? accessory.addService(this.hap.Service.Switch, name, uuid) as Service,
228
+ On: accessory.context.CloseModeSwitch.On ?? false,
229
+ }
230
+ accessory.context.CloseModeSwitch = this.CloseModeSwitch as object
231
+
232
+ // Initialize Close Mode Switch Service
233
+ this.CloseModeSwitch.Service.setCharacteristic(this.hap.Characteristic.Name, this.CloseModeSwitch.Name).getCharacteristic(this.hap.Characteristic.On).onGet(() => {
234
+ return this.CloseModeSwitch?.On ?? false
235
+ })
236
+
237
+ this.CloseModeSwitch.Service.getCharacteristic(this.hap.Characteristic.On).onSet(this.CloseModeSwitchSet.bind(this))
193
238
  }
194
239
 
195
240
  // Retrieve initial values and updateHomekit
196
241
  try {
197
- this.debugLog('Retrieve initial values and update Homekit');
198
- this.refreshStatus();
242
+ this.debugLog('Retrieve initial values and update Homekit')
243
+ this.refreshStatus()
199
244
  } catch (e: any) {
200
- this.errorLog(`failed to retrieve initial values and update Homekit, Error: ${e}`);
245
+ this.errorLog(`failed to retrieve initial values and update Homekit, Error: ${e}`)
201
246
  }
202
247
 
203
- //regisiter webhook event handler if enabled
248
+ // regisiter webhook event handler if enabled
204
249
  try {
205
- this.debugLog('Registering Webhook Event Handler');
206
- this.registerWebhook();
250
+ this.debugLog('Registering Webhook Event Handler')
251
+ this.registerWebhook()
207
252
  } catch (e: any) {
208
- this.errorLog(`failed to registerWebhook, Error: ${e}`);
253
+ this.errorLog(`failed to registerWebhook, Error: ${e}`)
209
254
  }
210
255
 
211
- //regisiter platform BLE event handler if enabled
256
+ // regisiter platform BLE event handler if enabled
212
257
  try {
213
- this.debugLog('Registering Platform BLE Event Handler');
214
- this.registerPlatformBLE();
258
+ this.debugLog('Registering Platform BLE Event Handler')
259
+ this.registerPlatformBLE()
215
260
  } catch (e: any) {
216
- this.errorLog(`failed to registerPlatformBLE, Error: ${e}`);
261
+ this.errorLog(`failed to registerPlatformBLE, Error: ${e}`)
217
262
  }
218
263
 
219
264
  // History
220
- this.history();
265
+ this.history()
221
266
 
222
267
  // Start an update interval
223
268
  interval(this.deviceRefreshRate * 1000)
224
269
  .pipe(skipWhile(() => this.curtainUpdateInProgress))
225
270
  .subscribe(async () => {
226
- await this.refreshStatus();
227
- });
271
+ await this.refreshStatus()
272
+ })
228
273
 
229
274
  // update slide progress
230
275
  interval(this.deviceUpdateRate * 1000)
231
276
  .pipe(skipWhile(() => !this.curtainMoving))
232
277
  .subscribe(async () => {
233
278
  if (this.WindowCovering.PositionState === this.hap.Characteristic.PositionState.STOPPED) {
234
- return;
279
+ return
235
280
  }
236
- await this.debugLog(`Refresh Status When Moving, PositionState: ${this.WindowCovering.PositionState}`);
237
- await this.refreshStatus();
238
- });
281
+ await this.debugLog(`Refresh Status When Moving, PositionState: ${this.WindowCovering.PositionState}`)
282
+ await this.refreshStatus()
283
+ })
239
284
 
240
285
  // Watch for Curtain change events
241
286
  // We put in a debounce of 100ms so we don't make duplicate calls
242
287
  this.doCurtainUpdate
243
288
  .pipe(
244
289
  tap(() => {
245
- this.curtainUpdateInProgress = true;
290
+ this.curtainUpdateInProgress = true
246
291
  }),
247
292
  debounceTime(this.devicePushRate * 1000),
248
293
  )
249
294
  .subscribe(async () => {
250
295
  try {
251
- await this.pushChanges();
296
+ await this.pushChanges()
252
297
  } catch (e: any) {
253
- await this.apiError(e);
254
- await this.errorLog(`failed pushChanges with ${device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`);
298
+ await this.apiError(e)
299
+ await this.errorLog(`failed pushChanges with ${device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`)
255
300
  }
256
- this.curtainUpdateInProgress = false;
257
- });
301
+ this.curtainUpdateInProgress = false
302
+ })
258
303
 
259
304
  // Setup EVE history features
260
- this.setupHistoryService();
305
+ this.setupHistoryService()
261
306
  }
262
307
 
263
308
  async history() {
264
309
  if (this.device.history === true) {
265
310
  // initialize when this accessory is newly created.
266
- this.accessory.context.lastActivation = this.accessory.context.lastActivation ?? 0;
311
+ this.accessory.context.lastActivation = this.accessory.context.lastActivation ?? 0
267
312
  } else {
268
313
  // removes cached values if history is turned off
269
- delete this.accessory.context.lastActivation;
314
+ delete this.accessory.context.lastActivation
270
315
  }
271
316
  }
272
317
 
@@ -275,173 +320,171 @@ export class Curtain extends deviceBase {
275
320
  */
276
321
  async setupHistoryService(): Promise<void> {
277
322
  if (this.device.history !== true) {
278
- return;
323
+ return
279
324
  }
280
325
 
281
326
  const mac = this.device
282
327
  .deviceId!.match(/.{1,2}/g)!
283
328
  .join(':')
284
- .toLowerCase();
329
+ .toLowerCase()
285
330
  this.historyService = new this.platform.fakegatoAPI('custom', this.accessory, {
286
331
  log: this.platform.log,
287
332
  storage: 'fs',
288
333
  filename: `${hostname().split('.')[0]}_${mac}_persist.json`,
289
- });
290
- const motion: Service =
291
- this.accessory.getService(this.hap.Service.MotionSensor) ||
292
- this.accessory.addService(this.hap.Service.MotionSensor, 'Motion');
293
- motion.addOptionalCharacteristic(this.platform.eve.Characteristics.LastActivation);
334
+ })
335
+ const motion: Service
336
+ = this.accessory.getService(this.hap.Service.MotionSensor)
337
+ || this.accessory.addService(this.hap.Service.MotionSensor, 'Motion')
338
+ motion.addOptionalCharacteristic(this.platform.eve.Characteristics.LastActivation)
294
339
  motion.getCharacteristic(this.platform.eve.Characteristics.LastActivation).onGet(() => {
295
340
  const lastActivation = this.accessory.context.lastActivation
296
341
  ? Math.max(0, this.accessory.context.lastActivation - this.historyService.getInitialTime())
297
- : 0;
298
- return lastActivation;
299
- });
300
- await this.setMinMax();
342
+ : 0
343
+ return lastActivation
344
+ })
345
+ await this.setMinMax()
301
346
  motion.getCharacteristic(this.hap.Characteristic.MotionDetected).on('change', (event: CharacteristicChange) => {
302
347
  if (event.newValue !== event.oldValue) {
303
- const sensor = this.accessory.getService(this.hap.Service.MotionSensor);
348
+ const sensor = this.accessory.getService(this.hap.Service.MotionSensor)
304
349
  const entry = {
305
350
  time: Math.round(new Date().valueOf() / 1000),
306
351
  motion: event.newValue,
307
- };
308
- this.accessory.context.lastActivation = entry.time;
352
+ }
353
+ this.accessory.context.lastActivation = entry.time
309
354
  sensor?.updateCharacteristic(
310
355
  this.platform.eve.Characteristics.LastActivation,
311
- Math.max(0, this.accessory.context.lastActivation - this.historyService.getInitialTime()));
312
- this.historyService.addEntry(entry);
356
+ Math.max(0, this.accessory.context.lastActivation - this.historyService.getInitialTime()),
357
+ )
358
+ this.historyService.addEntry(entry)
313
359
  }
314
- });
315
- this.updateHistory();
360
+ })
361
+ this.updateHistory()
316
362
  }
317
363
 
318
364
  async updateHistory(): Promise<void> {
319
- const motion = Number(this.WindowCovering.CurrentPosition) > 0 ? 1 : 0;
365
+ const motion = Number(this.WindowCovering.CurrentPosition) > 0 ? 1 : 0
320
366
  this.historyService.addEntry({
321
367
  time: Math.round(new Date().valueOf() / 1000),
322
- motion: motion,
323
- });
368
+ motion,
369
+ })
324
370
  setTimeout(async () => {
325
- await this.updateHistory();
326
- }, 10 * 60 * 1000);
371
+ await this.updateHistory()
372
+ }, 10 * 60 * 1000)
327
373
  }
328
374
 
329
375
  async BLEparseStatus(): Promise<void> {
330
- await this.debugLog('BLEparseStatus');
331
- await this.debugLog(`(position, battery) = BLE:(${this.serviceData.position}, ${this.serviceData.battery}),`
332
- + ` current:(${this.WindowCovering.CurrentPosition}, ${this.Battery.BatteryLevel})`);
376
+ await this.debugLog('BLEparseStatus')
377
+ await this.debugLog(`(position, battery) = BLE:(${this.serviceData.position}, ${this.serviceData.battery}), current:(${this.WindowCovering.CurrentPosition}, ${this.Battery.BatteryLevel})`)
333
378
  // CurrentPosition
334
- this.WindowCovering.CurrentPosition = 100 -this.serviceData.position;
335
- await this.getCurrentPostion();
379
+ this.WindowCovering.CurrentPosition = 100 - this.serviceData.position
380
+ await this.getCurrentPostion()
336
381
  // CurrentAmbientLightLevel
337
382
  if (!this.device.curtain?.hide_lightsensor && this.LightSensor?.Service) {
338
- const set_minLux = this.device.curtain?.set_minLux ?? 1;
339
- const set_maxLux = this.device.curtain?.set_maxLux ?? 6001;
340
- const lightLevel = this.serviceData.lightLevel;
341
- this.LightSensor.CurrentAmbientLightLevel = await this.getLightLevel(lightLevel, set_minLux, set_maxLux, 19);
342
- this.debugLog(`LightLevel: ${this.serviceData.lightLevel},`
343
- + ` CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
383
+ const set_minLux = this.device.curtain?.set_minLux ?? 1
384
+ const set_maxLux = this.device.curtain?.set_maxLux ?? 6001
385
+ const lightLevel = this.serviceData.lightLevel
386
+ this.LightSensor.CurrentAmbientLightLevel = await this.getLightLevel(lightLevel, set_minLux, set_maxLux, 19)
387
+ this.debugLog(`LightLevel: ${this.serviceData.lightLevel}, CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`)
344
388
  }
345
389
  // BatteryLevel
346
- this.Battery.BatteryLevel = this.serviceData.battery;
347
- await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`);
390
+ this.Battery.BatteryLevel = this.serviceData.battery
391
+ await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`)
348
392
  // StatusLowBattery
349
393
  this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
350
- ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
351
- await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`);
394
+ ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW
395
+ : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL
396
+ await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`)
352
397
  }
353
398
 
354
399
  async openAPIparseStatus(): Promise<void> {
355
- await this.debugLog('openAPIparseStatus');
356
- await this.debugLog(`(slidePosition, battery) = OpenAPI:(${this.deviceStatus.slidePosition}, ${this.deviceStatus.battery}),`
357
- + ` current:(${this.WindowCovering.CurrentPosition}, ${this.Battery.BatteryLevel})`);
400
+ await this.debugLog('openAPIparseStatus')
401
+ await this.debugLog(`(slidePosition, battery, version) = OpenAPI:(${this.deviceStatus.slidePosition}, ${this.deviceStatus.battery}, ${this.deviceStatus.version}), current:(${this.WindowCovering.CurrentPosition}, ${this.Battery.BatteryLevel}, ${this.accessory.context.version})`)
358
402
  // CurrentPosition
359
- this.WindowCovering.CurrentPosition = 100 - this.deviceStatus.slidePosition;
360
- await this.setMinMax();
361
- await this.debugLog(`CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
362
- if (this.setNewTarget) {
363
- await this.infoLog('Checking Status ...');
364
- }
365
- if (this.setNewTarget && this.deviceStatus.moving) {
366
- this.curtainMoving = true;
367
- await this.setMinMax();
403
+ this.WindowCovering.CurrentPosition = 100 - this.deviceStatus.slidePosition
404
+ await this.setMinMax()
405
+ await this.debugLog(`CurrentPosition: ${this.WindowCovering.CurrentPosition}`)
406
+ if (this.setNewTarget || this.deviceStatus.moving) {
407
+ await this.infoLog('Checking Status ...')
408
+ this.curtainMoving = true
409
+ await this.setMinMax()
368
410
  if (Number(this.WindowCovering.TargetPosition) > this.WindowCovering.CurrentPosition) {
369
- await this.debugLog(`Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
370
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
371
- this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
372
- await this.debugLog(`Increasing, PositionState: ${this.WindowCovering.PositionState}`);
411
+ await this.debugLog(`Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition}`)
412
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING
413
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState)
414
+ await this.debugLog(`Increasing, PositionState: ${this.WindowCovering.PositionState}`)
373
415
  } else if (Number(this.WindowCovering.TargetPosition) < this.WindowCovering.CurrentPosition) {
374
- await this.debugLog(`Opening, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
375
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
376
- this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
377
- await this.debugLog(`Decreasing, PositionState: ${this.WindowCovering.PositionState}`);
416
+ await this.debugLog(`Opening, CurrentPosition: ${this.WindowCovering.CurrentPosition}`)
417
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING
418
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState)
419
+ await this.debugLog(`Decreasing, PositionState: ${this.WindowCovering.PositionState}`)
378
420
  } else {
379
- await this.debugLog(`Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
380
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
381
- this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
382
- await this.debugLog(`Stopped, PositionState: ${this.WindowCovering.PositionState}`);
421
+ await this.debugLog(`Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`)
422
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED
423
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState)
424
+ await this.debugLog(`Stopped, PositionState: ${this.WindowCovering.PositionState}`)
383
425
  }
384
426
  } else {
385
- this.curtainMoving = false;
386
- await this.debugLog(`Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
387
- this.WindowCovering.TargetPosition = this.WindowCovering.CurrentPosition;
388
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
389
- await this.debugLog(`Stopped, PositionState: ${this.WindowCovering.PositionState}`);
427
+ await this.infoLog('Standby ...')
428
+ this.curtainMoving = false
429
+ await this.debugLog(`Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`)
430
+ this.WindowCovering.TargetPosition = this.WindowCovering.CurrentPosition
431
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED
432
+ await this.debugLog(`Stopped, PositionState: ${this.WindowCovering.PositionState}`)
390
433
  }
391
- await this.debugLog(`CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition: ${this.WindowCovering.TargetPosition},`
392
- + ` PositionState: ${this.WindowCovering.PositionState},`);
434
+ await this.debugLog(`CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition: ${this.WindowCovering.TargetPosition}, PositionState: ${this.WindowCovering.PositionState},`)
393
435
 
394
436
  // Brightness
395
437
  if (!this.device.curtain?.hide_lightsensor && this.LightSensor?.Service) {
396
- const set_minLux = this.device.curtain?.set_minLux ?? 1;
397
- const set_maxLux = this.device.curtain?.set_maxLux ?? 6001;
398
- const lightLevel = this.deviceStatus.lightLevel === 'bright' ? set_maxLux : set_minLux;
399
- this.LightSensor.CurrentAmbientLightLevel = await this.getLightLevel(lightLevel, set_minLux, set_maxLux, 2);
400
- await this.debugLog(`CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`);
438
+ const set_minLux = this.device.curtain?.set_minLux ?? 1
439
+ const set_maxLux = this.device.curtain?.set_maxLux ?? 6001
440
+ const lightLevel = this.deviceStatus.lightLevel === 'bright' ? set_maxLux : set_minLux
441
+ this.LightSensor.CurrentAmbientLightLevel = await this.getLightLevel(lightLevel, set_minLux, set_maxLux, 2)
442
+ await this.debugLog(`CurrentAmbientLightLevel: ${this.LightSensor.CurrentAmbientLightLevel}`)
401
443
  }
402
444
 
403
445
  // BatteryLevel
404
- this.Battery.BatteryLevel = this.deviceStatus.battery;
405
- await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`);
446
+ this.Battery.BatteryLevel = this.deviceStatus.battery
447
+ await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`)
406
448
 
407
449
  // StatusLowBattery
408
450
  this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
409
- ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
410
- await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`);
451
+ ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW
452
+ : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL
453
+ await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`)
411
454
 
412
455
  // Firmware Version
413
456
  if (this.deviceStatus.version) {
414
- const version = this.deviceStatus.version.toString();
415
- await this.debugLog(`Firmware Version: ${version.replace(/^V|-.*$/g, '')}`);
416
- const deviceVersion = version.replace(/^V|-.*$/g, '') ?? '0.0.0';
457
+ const version = this.deviceStatus.version.toString()
458
+ await this.debugLog(`Firmware Version: ${version.replace(/^V|-.*$/g, '')}`)
459
+ const deviceVersion = version.replace(/^V|-.*$/g, '') ?? '0.0.0'
417
460
  this.accessory
418
461
  .getService(this.hap.Service.AccessoryInformation)!
419
462
  .setCharacteristic(this.hap.Characteristic.HardwareRevision, deviceVersion)
420
463
  .setCharacteristic(this.hap.Characteristic.FirmwareRevision, deviceVersion)
421
464
  .getCharacteristic(this.hap.Characteristic.FirmwareRevision)
422
- .updateValue(deviceVersion);
423
- this.accessory.context.version = deviceVersion;
424
- await this.debugSuccessLog(`version: ${this.accessory.context.version}`);
465
+ .updateValue(deviceVersion)
466
+ this.accessory.context.version = deviceVersion
467
+ await this.debugSuccessLog(`version: ${this.accessory.context.version}`)
425
468
  }
426
469
  }
427
470
 
428
471
  async parseStatusWebhook(): Promise<void> {
429
- await this.debugLog('parseStatusWebhook');
430
- await this.debugLog(`(slidePosition, battery) = Webhook:(${this.webhookContext.slidePosition}, ${this.webhookContext.battery}),`
431
- + ` current:(${this.WindowCovering.CurrentPosition}, ${this.Battery.BatteryLevel})`);
472
+ await this.debugLog('parseStatusWebhook')
473
+ await this.debugLog(`(slidePosition, battery) = Webhook:(${this.webhookContext.slidePosition}, ${this.webhookContext.battery}), current:(${this.WindowCovering.CurrentPosition}, ${this.Battery.BatteryLevel})`)
432
474
 
433
475
  // CurrentPosition
434
- this.WindowCovering.CurrentPosition = 100 - this.webhookContext.slidePosition;
435
- await this.getCurrentPostion();
476
+ this.WindowCovering.CurrentPosition = 100 - this.webhookContext.slidePosition
477
+ await this.getCurrentPostion()
436
478
 
437
479
  // BatteryLevel
438
- this.Battery.BatteryLevel = this.webhookContext.battery;
439
- await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`);
480
+ this.Battery.BatteryLevel = this.webhookContext.battery
481
+ await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`)
440
482
 
441
483
  // StatusLowBattery
442
484
  this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
443
- ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
444
- await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`);
485
+ ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW
486
+ : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL
487
+ await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`)
445
488
  }
446
489
 
447
490
  /**
@@ -449,98 +492,98 @@ export class Curtain extends deviceBase {
449
492
  */
450
493
  async refreshStatus(): Promise<void> {
451
494
  if (!this.device.enableCloudService && this.OpenAPI) {
452
- await this.errorLog(`refreshStatus enableCloudService: ${this.device.enableCloudService}`);
495
+ await this.errorLog(`refreshStatus enableCloudService: ${this.device.enableCloudService}`)
453
496
  } else if (this.BLE) {
454
- await this.BLERefreshStatus();
497
+ await this.BLERefreshStatus()
455
498
  } else if (this.OpenAPI && this.platform.config.credentials?.token) {
456
- await this.openAPIRefreshStatus();
499
+ await this.openAPIRefreshStatus()
457
500
  } else {
458
- await this.offlineOff();
459
- await this.debugWarnLog(`Connection Type: ${this.device.connectionType}, refreshStatus will not happen.`);
501
+ await this.offlineOff()
502
+ await this.debugWarnLog(`Connection Type: ${this.device.connectionType}, refreshStatus will not happen.`)
460
503
  }
461
504
  }
462
505
 
463
506
  async BLERefreshStatus(): Promise<void> {
464
- await this.debugLog('BLERefreshStatus');
465
- const switchbot = await this.switchbotBLE();
507
+ await this.debugLog('BLERefreshStatus')
508
+ const switchbot = await this.switchbotBLE()
466
509
  if (switchbot === undefined) {
467
- await this.BLERefreshConnection(switchbot);
510
+ await this.BLERefreshConnection(switchbot)
468
511
  } else {
469
512
  // Start to monitor advertisement packets
470
513
  (async () => {
471
514
  // Start to monitor advertisement packets
472
- const serviceData = await this.monitorAdvertisementPackets(switchbot) as curtainServiceData | curtain3ServiceData;
515
+ const serviceData = await this.monitorAdvertisementPackets(switchbot) as curtainServiceData | curtain3ServiceData
473
516
  // Update HomeKit
474
517
  if ((serviceData.model === SwitchBotBLEModel.Curtain || SwitchBotBLEModel.Curtain3)
475
518
  && (serviceData.modelName === SwitchBotBLEModelName.Curtain || SwitchBotBLEModelName.Curtain3)) {
476
- this.serviceData = serviceData;
477
- await this.BLEparseStatus();
478
- await this.updateHomeKitCharacteristics();
519
+ this.serviceData = serviceData
520
+ await this.BLEparseStatus()
521
+ await this.updateHomeKitCharacteristics()
479
522
  } else {
480
- await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`);
481
- await this.BLERefreshConnection(switchbot);
523
+ await this.errorLog(`failed to get serviceData, serviceData: ${serviceData}`)
524
+ await this.BLERefreshConnection(switchbot)
482
525
  }
483
- })();
526
+ })()
484
527
  }
485
528
  }
486
529
 
487
530
  async openAPIRefreshStatus(): Promise<void> {
488
- await this.debugLog('openAPIRefreshStatus');
531
+ await this.debugLog('openAPIRefreshStatus')
489
532
  try {
490
- const { body, statusCode } = await this.deviceRefreshStatus();
491
- const deviceStatus: any = await body.json();
492
- await this.debugLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);;
533
+ const { body, statusCode } = await this.deviceRefreshStatus()
534
+ const deviceStatus: any = await body.json()
535
+ await this.debugLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
493
536
  if (await this.successfulStatusCodes(statusCode, deviceStatus)) {
494
- await this.debugSuccessLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
495
- this.deviceStatus = deviceStatus.body;
496
- await this.openAPIparseStatus();
497
- await this.updateHomeKitCharacteristics();
537
+ await this.debugSuccessLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
538
+ this.deviceStatus = deviceStatus.body
539
+ await this.openAPIparseStatus()
540
+ await this.updateHomeKitCharacteristics()
498
541
  } else {
499
- await this.debugWarnLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
500
- await this.debugWarnLog(statusCode, deviceStatus);
542
+ await this.debugWarnLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
543
+ await this.debugWarnLog(statusCode, deviceStatus)
501
544
  }
502
545
  } catch (e: any) {
503
- await this.apiError(e);
504
- await this.errorLog(`failed openAPIRefreshStatus with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`);
546
+ await this.apiError(e)
547
+ await this.errorLog(`failed openAPIRefreshStatus with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`)
505
548
  }
506
549
  }
507
550
 
508
551
  async registerWebhook() {
509
552
  if (this.device.webhook) {
510
- await this.debugLog('is listening webhook.');
553
+ await this.debugLog('is listening webhook.')
511
554
  this.platform.webhookEventHandler[this.device.deviceId] = async (context: curtainWebhookContext | curtain3WebhookContext) => {
512
555
  try {
513
- await this.debugLog(`received Webhook: ${JSON.stringify(context)}`);
514
- this.webhookContext = context;
515
- await this.parseStatusWebhook();
516
- await this.updateHomeKitCharacteristics();
556
+ await this.debugLog(`received Webhook: ${JSON.stringify(context)}`)
557
+ this.webhookContext = context
558
+ await this.parseStatusWebhook()
559
+ await this.updateHomeKitCharacteristics()
517
560
  } catch (e: any) {
518
- await this.errorLog(`failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`);
561
+ await this.errorLog(`failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e}`)
519
562
  }
520
- };
563
+ }
521
564
  } else {
522
- await this.debugLog('is not listening webhook.');
565
+ await this.debugLog('is not listening webhook.')
523
566
  }
524
567
  }
525
568
 
526
569
  async registerPlatformBLE(): Promise<void> {
527
- await this.debugLog('registerPlatformBLE');
570
+ await this.debugLog('registerPlatformBLE')
528
571
  if (this.config.options?.BLE) {
529
- await this.debugLog('is listening to Platform BLE.');
530
- this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase();
531
- await this.debugLog(`bleMac: ${this.device.bleMac}`);
572
+ await this.debugLog('is listening to Platform BLE.')
573
+ this.device.bleMac = this.device.deviceId!.match(/.{1,2}/g)!.join(':').toLowerCase()
574
+ await this.debugLog(`bleMac: ${this.device.bleMac}`)
532
575
  this.platform.bleEventHandler[this.device.bleMac] = async (context: curtainServiceData | curtain3ServiceData) => {
533
576
  try {
534
- await this.debugLog(`received BLE: ${JSON.stringify(context)}`);
535
- this.serviceData = context;
536
- await this.BLEparseStatus();
537
- await this.updateHomeKitCharacteristics();
577
+ await this.debugLog(`received BLE: ${JSON.stringify(context)}`)
578
+ this.serviceData = context
579
+ await this.BLEparseStatus()
580
+ await this.updateHomeKitCharacteristics()
538
581
  } catch (e: any) {
539
- await this.errorLog(`failed to handle BLE. Received: ${JSON.stringify(context)} Error: ${e}`);
582
+ await this.errorLog(`failed to handle BLE. Received: ${JSON.stringify(context)} Error: ${e}`)
540
583
  }
541
- };
584
+ }
542
585
  } else {
543
- await this.debugLog('is not listening to Platform BLE');
586
+ await this.debugLog('is not listening to Platform BLE')
544
587
  }
545
588
  }
546
589
 
@@ -549,32 +592,32 @@ export class Curtain extends deviceBase {
549
592
  */
550
593
  async pushChanges(): Promise<void> {
551
594
  if (!this.device.enableCloudService && this.OpenAPI) {
552
- await this.errorLog(`pushChanges enableCloudService: ${this.device.enableCloudService}`);
595
+ await this.errorLog(`pushChanges enableCloudService: ${this.device.enableCloudService}`)
553
596
  } else if (this.BLE) {
554
- await this.BLEpushChanges();
597
+ await this.BLEpushChanges()
555
598
  } else if (this.OpenAPI && this.platform.config.credentials?.token) {
556
- await this.openAPIpushChanges();
599
+ await this.openAPIpushChanges()
557
600
  } else {
558
- await this.offlineOff();
559
- await this.debugWarnLog(`Connection Type: ${this.device.connectionType}, pushChanges will not happen.`);
601
+ await this.offlineOff()
602
+ await this.debugWarnLog(`Connection Type: ${this.device.connectionType}, pushChanges will not happen.`)
560
603
  }
561
604
  // Refresh the status from the API
562
605
  interval(15000)
563
606
  .pipe(skipWhile(() => this.curtainUpdateInProgress))
564
607
  .pipe(take(1))
565
608
  .subscribe(async () => {
566
- await this.refreshStatus();
567
- });
609
+ await this.refreshStatus()
610
+ })
568
611
  }
569
612
 
570
613
  async BLEpushChanges(): Promise<void> {
571
- await this.debugLog('BLEpushChanges');
614
+ await this.debugLog('BLEpushChanges')
572
615
  if (this.WindowCovering.TargetPosition !== this.WindowCovering.CurrentPosition) {
573
- const switchbot = await this.platform.connectBLE(this.accessory, this.device);
574
- await this.convertBLEAddress();
575
- const { setPositionMode, Mode }: { setPositionMode: number; Mode: string; } = await this.setPerformance();
576
- const adjustedMode = setPositionMode === 1 ? 0x01 : 0xff;
577
- await this.debugLog(`Mode: ${Mode}, setPositionMode: ${setPositionMode}`);
616
+ const switchbot = await this.platform.connectBLE(this.accessory, this.device)
617
+ await this.convertBLEAddress()
618
+ const { setPositionMode, Mode }: { setPositionMode: number, Mode: string } = await this.setPerformance()
619
+ const adjustedMode = setPositionMode === 1 ? 0x01 : 0xFF
620
+ await this.debugLog(`Mode: ${Mode}, setPositionMode: ${setPositionMode}`)
578
621
  if (switchbot !== false) {
579
622
  switchbot
580
623
  .discover({ model: this.device.bleModel, quick: true, id: this.device.bleMac })
@@ -582,70 +625,68 @@ export class Curtain extends deviceBase {
582
625
  return await this.retryBLE({
583
626
  max: await this.maxRetryBLE(),
584
627
  fn: async () => {
585
- return await device_list[0].runToPos(100 - Number(this.WindowCovering.TargetPosition), adjustedMode);
628
+ return await device_list[0].runToPos(100 - Number(this.WindowCovering.TargetPosition), adjustedMode)
586
629
  },
587
- });
630
+ })
588
631
  })
589
632
  .then(async () => {
590
- await this.successLog(`TargetPostion: ${this.WindowCovering.TargetPosition} sent over SwitchBot BLE, sent successfully`);
591
- await this.updateHomeKitCharacteristics();
633
+ await this.successLog(`TargetPostion: ${this.WindowCovering.TargetPosition} sent over SwitchBot BLE, sent successfully`)
634
+ await this.updateHomeKitCharacteristics()
592
635
  })
593
636
  .catch(async (e: any) => {
594
- await this.apiError(e);
595
- await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`);
596
- await this.BLEPushConnection();
597
- });
637
+ await this.apiError(e)
638
+ await this.errorLog(`failed BLEpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`)
639
+ await this.BLEPushConnection()
640
+ })
598
641
  } else {
599
- await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
600
- await this.BLEPushConnection();
642
+ await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`)
643
+ await this.BLEPushConnection()
601
644
  }
602
645
  } else {
603
- await this.debugLog(`No changes (BLEpushChanges), TargetPosition: ${this.WindowCovering.TargetPosition},`
604
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
646
+ await this.debugLog(`No changes (BLEpushChanges), TargetPosition: ${this.WindowCovering.TargetPosition}, CurrentPosition: ${this.WindowCovering.CurrentPosition}`)
605
647
  }
606
648
  }
607
649
 
608
650
  async openAPIpushChanges(): Promise<void> {
609
- await this.debugLog('openAPIpushChanges');
651
+ await this.debugLog('openAPIpushChanges')
610
652
  if (this.WindowCovering.TargetPosition !== this.WindowCovering.CurrentPosition || this.device.disableCaching) {
611
- await this.debugLog(`Pushing ${this.WindowCovering.TargetPosition}`);
612
- const adjustedTargetPosition = 100 - Number(this.WindowCovering.TargetPosition);
613
- const { setPositionMode, Mode }: { setPositionMode: number; Mode: string; } = await this.setPerformance();
614
- await this.debugLog(`Mode: ${Mode}, setPositionMode: ${setPositionMode}`);
615
- const adjustedMode = setPositionMode || 'ff';
616
- let bodyChange: string;
653
+ await this.debugLog(`Pushing ${this.WindowCovering.TargetPosition}`)
654
+ const adjustedTargetPosition = 100 - Number(this.WindowCovering.TargetPosition)
655
+ const { setPositionMode, Mode }: { setPositionMode: number, Mode: string } = await this.setPerformance()
656
+ await this.debugLog(`Mode: ${Mode}, setPositionMode: ${setPositionMode}`)
657
+ const adjustedMode = setPositionMode || 'ff'
658
+ let bodyChange: string
617
659
  if (this.WindowCovering.HoldPosition) {
618
660
  bodyChange = JSON.stringify({
619
661
  command: 'pause',
620
662
  parameter: 'default',
621
663
  commandType: 'command',
622
- });
664
+ })
623
665
  } else {
624
666
  bodyChange = JSON.stringify({
625
667
  command: 'setPosition',
626
668
  parameter: `0,${adjustedMode},${adjustedTargetPosition}`,
627
669
  commandType: 'command',
628
- });
670
+ })
629
671
  }
630
- await this.debugLog(`SwitchBot OpenAPI bodyChange: ${JSON.stringify(bodyChange)}`);
672
+ await this.debugLog(`SwitchBot OpenAPI bodyChange: ${JSON.stringify(bodyChange)}`)
631
673
  try {
632
- const { body, statusCode } = await this.pushChangeRequest(bodyChange);
633
- const deviceStatus: any = await body.json();
634
- await this.debugLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
674
+ const { body, statusCode } = await this.pushChangeRequest(bodyChange)
675
+ const deviceStatus: any = await body.json()
676
+ await this.debugLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
635
677
  if (await this.successfulStatusCodes(statusCode, deviceStatus)) {
636
- await this.debugSuccessLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
637
- await this.updateHomeKitCharacteristics();
678
+ await this.debugSuccessLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
679
+ await this.updateHomeKitCharacteristics()
638
680
  } else {
639
- await this.statusCode(statusCode);
640
- await this.statusCode(deviceStatus.statusCode);
681
+ await this.statusCode(statusCode)
682
+ await this.statusCode(deviceStatus.statusCode)
641
683
  }
642
684
  } catch (e: any) {
643
- await this.apiError(e);
644
- await this.errorLog(`failed openAPIpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`);
685
+ await this.apiError(e)
686
+ await this.errorLog(`failed openAPIpushChanges with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`)
645
687
  }
646
688
  } else {
647
- await this.debugLog(`No changes (openAPIpushChanges), CurrentPosition: ${this.WindowCovering.CurrentPosition},`
648
- + ` TargetPosition: ${this.WindowCovering.TargetPosition}`);
689
+ await this.debugLog(`No changes (openAPIpushChanges), CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition: ${this.WindowCovering.TargetPosition}`)
649
690
  }
650
691
  }
651
692
 
@@ -654,208 +695,229 @@ export class Curtain extends deviceBase {
654
695
  */
655
696
  async TargetPositionSet(value: CharacteristicValue): Promise<void> {
656
697
  if (this.WindowCovering.TargetPosition !== this.accessory.context.TargetPosition) {
657
- await this.infoLog(`Set TargetPosition: ${value}`);
698
+ await this.infoLog(`Set TargetPosition: ${value}`)
658
699
  } else {
659
- await this.debugLog(`No Changes, TargetPosition: ${value}`);
700
+ await this.debugLog(`No Changes, TargetPosition: ${value}`)
660
701
  }
661
702
 
662
703
  // Set HoldPosition to false when TargetPosition is changed
663
- this.WindowCovering.HoldPosition = false;
664
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.HoldPosition, this.WindowCovering.HoldPosition);
704
+ this.WindowCovering.HoldPosition = false
705
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.HoldPosition, this.WindowCovering.HoldPosition)
665
706
 
666
- this.WindowCovering.TargetPosition = value;
667
- await this.mqtt('TargetPosition', this.WindowCovering.TargetPosition);
668
- await this.mqtt('HoldPosition', this.WindowCovering.HoldPosition);
669
- await this.startUpdatingCurtainIfNeeded();
707
+ this.WindowCovering.TargetPosition = value
708
+ await this.mqtt('TargetPosition', this.WindowCovering.TargetPosition)
709
+ await this.mqtt('HoldPosition', this.WindowCovering.HoldPosition)
710
+ await this.startUpdatingCurtainIfNeeded()
670
711
  }
671
712
 
672
713
  async startUpdatingCurtainIfNeeded() {
673
- await this.setMinMax();
714
+ await this.setMinMax()
674
715
  if (this.WindowCovering.TargetPosition > this.WindowCovering.CurrentPosition) {
675
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
676
- this.setNewTarget = true;
677
- await this.debugLog(`value: ${this.WindowCovering.TargetPosition}, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
716
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING
717
+ this.setNewTarget = true
718
+ await this.debugLog(`value: ${this.WindowCovering.TargetPosition}, CurrentPosition: ${this.WindowCovering.CurrentPosition}`)
678
719
  } else if (this.WindowCovering.TargetPosition < this.WindowCovering.CurrentPosition) {
679
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
680
- this.setNewTarget = true;
681
- await this.debugLog(`value: ${this.WindowCovering.TargetPosition}, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
720
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING
721
+ this.setNewTarget = true
722
+ await this.debugLog(`value: ${this.WindowCovering.TargetPosition}, CurrentPosition: ${this.WindowCovering.CurrentPosition}`)
682
723
  } else {
683
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
684
- this.setNewTarget = false;
685
- await this.debugLog(`value: ${this.WindowCovering.TargetPosition}, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
724
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED
725
+ this.setNewTarget = false
726
+ await this.debugLog(`value: ${this.WindowCovering.TargetPosition}, CurrentPosition: ${this.WindowCovering.CurrentPosition}`)
686
727
  }
687
- this.WindowCovering.Service.setCharacteristic(this.hap.Characteristic.PositionState, this.WindowCovering.PositionState);
688
- this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
728
+ this.WindowCovering.Service.setCharacteristic(this.hap.Characteristic.PositionState, this.WindowCovering.PositionState)
729
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState)
689
730
 
690
731
  /**
691
732
  * If Curtain movement time is short, the moving flag from backend is always false.
692
733
  * The minimum time depends on the network control latency.
693
734
  */
694
- clearTimeout(this.setNewTargetTimer);
695
- await this.debugLog(`deviceUpdateRate: ${this.deviceUpdateRate}`);
735
+ clearTimeout(this.setNewTargetTimer)
736
+ await this.debugLog(`deviceUpdateRate: ${this.deviceUpdateRate}`)
696
737
  if (this.setNewTarget) {
697
738
  this.setNewTargetTimer = setTimeout(async () => {
698
- await this.debugLog(`setNewTarget ${this.setNewTarget} timeout`);
699
- this.setNewTarget = false;
700
- }, this.deviceUpdateRate * 1000);
739
+ await this.debugLog(`setNewTarget ${this.setNewTarget} timeout`)
740
+ this.setNewTarget = false
741
+ }, this.deviceUpdateRate * 1000)
701
742
  }
702
- this.doCurtainUpdate.next();
743
+ this.doCurtainUpdate.next()
703
744
  }
704
745
 
705
746
  /**
706
747
  * Handle requests to set the value of the "Target Position" characteristic
707
748
  */
708
749
  async HoldPositionSet(value: CharacteristicValue): Promise<void> {
709
- this.debugLog(`HoldPosition: ${value}`);
710
- this.WindowCovering.HoldPosition = value;
711
- this.doCurtainUpdate.next();
750
+ this.debugLog(`HoldPosition: ${value}`)
751
+ this.WindowCovering.HoldPosition = value
752
+ this.doCurtainUpdate.next()
753
+ }
754
+
755
+ /**
756
+ * Handle requests to set the value of the "Target Position" characteristic
757
+ */
758
+ async OpenModeSwitchSet(value: CharacteristicValue): Promise<void> {
759
+ if (this.OpenModeSwitch && this.device.curtain?.silentModeSwitch) {
760
+ this.debugLog(`Silent Open Mode: ${value}`)
761
+ this.OpenModeSwitch.On = value
762
+ this.accessory.context.OpenModeSwitch.On = value
763
+ if (value === true) {
764
+ this.infoLog('Silent Open Mode is enabled')
765
+ }
766
+ }
767
+ }
768
+
769
+ /**
770
+ * Handle requests to set the value of the "Target Position" characteristic
771
+ */
772
+ async CloseModeSwitchSet(value: CharacteristicValue): Promise<void> {
773
+ if (this.CloseModeSwitch && this.device.curtain?.silentModeSwitch) {
774
+ this.debugLog(`Silent Close Mode: ${value}`)
775
+ this.CloseModeSwitch.On = value
776
+ this.accessory.context.CloseModeSwitch.On = value
777
+ if (value === true) {
778
+ this.infoLog('Silent Close Mode is enabled')
779
+ }
780
+ }
712
781
  }
713
782
 
714
783
  async updateHomeKitCharacteristics(): Promise<void> {
715
- await this.setMinMax();
784
+ await this.setMinMax()
716
785
  // CurrentPosition
717
- await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.CurrentPosition,
718
- this.WindowCovering.CurrentPosition, 'CurrentPosition');
786
+ await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.CurrentPosition, this.WindowCovering.CurrentPosition, 'CurrentPosition')
719
787
  // PositionState
720
- await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.PositionState,
721
- this.WindowCovering.PositionState, 'PositionState');
788
+ await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.PositionState, this.WindowCovering.PositionState, 'PositionState')
722
789
  // TargetPosition
723
- await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.TargetPosition,
724
- this.WindowCovering.TargetPosition, 'TargetPosition');
790
+ await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.TargetPosition, this.WindowCovering.TargetPosition, 'TargetPosition')
725
791
  // HoldPosition
726
- await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.HoldPosition,
727
- this.WindowCovering.HoldPosition, 'HoldPosition');
792
+ await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.HoldPosition, this.WindowCovering.HoldPosition, 'HoldPosition')
728
793
  // CurrentAmbientLightLevel
729
794
  if (!this.device.curtain?.hide_lightsensor && this.LightSensor?.Service) {
730
- const history = { time: Math.round(new Date().valueOf() / 1000), lux: this.LightSensor.CurrentAmbientLightLevel };
731
- await this.updateCharacteristic(this.LightSensor?.Service, this.hap.Characteristic.CurrentAmbientLightLevel,
732
- this.LightSensor?.CurrentAmbientLightLevel, 'CurrentAmbientLightLevel', history);
795
+ const history = { time: Math.round(new Date().valueOf() / 1000), lux: this.LightSensor.CurrentAmbientLightLevel }
796
+ await this.updateCharacteristic(this.LightSensor?.Service, this.hap.Characteristic.CurrentAmbientLightLevel, this.LightSensor?.CurrentAmbientLightLevel, 'CurrentAmbientLightLevel', history)
733
797
  }
734
798
  // BatteryLevel
735
- await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.BatteryLevel,
736
- this.Battery.BatteryLevel, 'BatteryLevel');
799
+ await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel, 'BatteryLevel')
737
800
  // StatusLowBattery
738
- await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.StatusLowBattery,
739
- this.Battery.StatusLowBattery, 'StatusLowBattery');
801
+ await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery, 'StatusLowBattery')
740
802
  // ChargingState
741
- await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.ChargingState,
742
- this.Battery.ChargingState, 'ChargingState');
803
+ await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.ChargingState, this.Battery.ChargingState, 'ChargingState')
743
804
  }
744
805
 
745
806
  async BLEPushConnection() {
746
807
  if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
747
- await this.warnLog('Using OpenAPI Connection to Push Changes');
748
- await this.openAPIpushChanges();
808
+ await this.warnLog('Using OpenAPI Connection to Push Changes')
809
+ await this.openAPIpushChanges()
749
810
  }
750
811
  }
751
812
 
752
813
  async BLERefreshConnection(switchbot: any): Promise<void> {
753
- await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`);
814
+ await this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`)
754
815
  if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
755
- await this.warnLog('Using OpenAPI Connection to Refresh Status');
756
- await this.openAPIRefreshStatus();
816
+ await this.warnLog('Using OpenAPI Connection to Refresh Status')
817
+ await this.openAPIRefreshStatus()
757
818
  }
758
819
  }
759
820
 
760
821
  async setPerformance() {
761
- let setPositionMode: number;
762
- let Mode: string;
822
+ let setPositionMode: number
823
+ let Mode: string
763
824
  if (Number(this.WindowCovering.TargetPosition) > 50) {
764
- if (this.device.curtain?.setOpenMode === '1') {
765
- setPositionMode = 1;
766
- Mode = 'Silent Mode';
767
- } else if (this.device.curtain?.setOpenMode === '0') {
768
- setPositionMode = 0;
769
- Mode = 'Performance Mode';
825
+ if (this.device.curtain?.setOpenMode === '1' || this.OpenModeSwitch?.On) {
826
+ setPositionMode = 1
827
+ Mode = 'Silent Mode'
828
+ } else if (this.device.curtain?.setOpenMode === '0' || !this.OpenModeSwitch?.On) {
829
+ setPositionMode = 0
830
+ Mode = 'Performance Mode'
770
831
  } else {
771
- setPositionMode = 0;
772
- Mode = 'Default Mode';
832
+ setPositionMode = 0
833
+ Mode = 'Default Mode'
773
834
  }
774
835
  } else {
775
- if (this.device.curtain?.setCloseMode === '1') {
776
- setPositionMode = 1;
777
- Mode = 'Silent Mode';
778
- } else if (this.device.curtain?.setOpenMode === '0') {
779
- setPositionMode = 0;
780
- Mode = 'Performance Mode';
836
+ if (this.device.curtain?.setCloseMode === '1' || this.CloseModeSwitch?.On) {
837
+ setPositionMode = 1
838
+ Mode = 'Silent Mode'
839
+ } else if (this.device.curtain?.setCloseMode === '0' || !this.CloseModeSwitch?.On) {
840
+ setPositionMode = 0
841
+ Mode = 'Performance Mode'
781
842
  } else {
782
- setPositionMode = 0;
783
- Mode = 'Default Mode';
843
+ setPositionMode = 0
844
+ Mode = 'Default Mode'
784
845
  }
785
846
  }
786
- return { setPositionMode, Mode };
847
+ this.infoLog(`Position Mode: ${setPositionMode}, Mode: ${Mode}`)
848
+ return { setPositionMode, Mode }
787
849
  }
788
850
 
789
851
  async getCurrentPostion() {
790
- await this.setMinMax();
791
- await this.debugLog(`CurrentPosition ${this.WindowCovering.CurrentPosition}`);
852
+ await this.setMinMax()
853
+ await this.debugLog(`CurrentPosition ${this.WindowCovering.CurrentPosition}`)
792
854
  if (this.setNewTarget) {
793
- this.curtainMoving = true;
794
- this.infoLog('Checking Status ...');
795
- await this.setMinMax();
855
+ this.infoLog('Checking Status ...')
856
+ this.curtainMoving = true
857
+ await this.setMinMax()
796
858
  if (this.WindowCovering.TargetPosition > this.WindowCovering.CurrentPosition) {
797
- await this.debugLog(`Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
798
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING;
799
- this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
800
- await this.debugLog(`Increasing, PositionState: ${this.WindowCovering.PositionState}`);
859
+ await this.debugLog(`Closing, CurrentPosition: ${this.WindowCovering.CurrentPosition}`)
860
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.INCREASING
861
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState)
862
+ await this.debugLog(`Increasing, PositionState: ${this.WindowCovering.PositionState}`)
801
863
  } else if (this.WindowCovering.TargetPosition < this.WindowCovering.CurrentPosition) {
802
- await this.debugLog(`Opening, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
803
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING;
804
- this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
805
- await this.debugLog(`Decreasing, PositionState: ${this.WindowCovering.PositionState}`);
864
+ await this.debugLog(`Opening, CurrentPosition: ${this.WindowCovering.CurrentPosition}`)
865
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.DECREASING
866
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState)
867
+ await this.debugLog(`Decreasing, PositionState: ${this.WindowCovering.PositionState}`)
806
868
  } else {
807
- await this.debugLog(`Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
808
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
809
- this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState);
810
- await this.debugLog(`Stopped, PositionState: ${this.WindowCovering.PositionState}`);
869
+ await this.debugLog(`Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`)
870
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED
871
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.PositionState).updateValue(this.WindowCovering.PositionState)
872
+ await this.debugLog(`Stopped, PositionState: ${this.WindowCovering.PositionState}`)
811
873
  }
812
874
  } else {
813
- this.curtainMoving = false;
814
- await this.debugLog(`Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
815
- this.WindowCovering.TargetPosition = this.WindowCovering.CurrentPosition;
816
- this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
817
- await this.debugLog(`Stopped, PositionState: ${this.WindowCovering.PositionState}`);
818
- }
819
- await this.debugLog(`CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition: ${this.WindowCovering.TargetPosition},`
820
- + ` PositionState: ${this.WindowCovering.PositionState},`);
875
+ await this.infoLog('Standby ...')
876
+ this.curtainMoving = false
877
+ await this.debugLog(`Standby, CurrentPosition: ${this.WindowCovering.CurrentPosition}`)
878
+ this.WindowCovering.TargetPosition = this.WindowCovering.CurrentPosition
879
+ this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED
880
+ await this.debugLog(`Stopped, PositionState: ${this.WindowCovering.PositionState}`)
881
+ }
882
+ await this.debugLog(`CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition: ${this.WindowCovering.TargetPosition}, PositionState: ${this.WindowCovering.PositionState},`)
821
883
  }
822
884
 
823
885
  async setMinMax(): Promise<void> {
824
886
  if (this.device.curtain?.set_min) {
825
887
  if (Number(this.WindowCovering.CurrentPosition) <= this.device.curtain?.set_min) {
826
- this.WindowCovering.CurrentPosition = 0;
888
+ this.WindowCovering.CurrentPosition = 0
827
889
  }
828
890
  }
829
891
  if (this.device.curtain?.set_max) {
830
892
  if (Number(this.WindowCovering.CurrentPosition) >= this.device.curtain?.set_max) {
831
- this.WindowCovering.CurrentPosition = 100;
893
+ this.WindowCovering.CurrentPosition = 100
832
894
  }
833
895
  }
834
896
  if (this.device.history) {
835
- const motion = this.accessory.getService(this.hap.Service.MotionSensor);
836
- const state = Number(this.WindowCovering.CurrentPosition) > 0 ? 1 : 0;
837
- motion?.updateCharacteristic(this.hap.Characteristic.MotionDetected, state);
897
+ const motion = this.accessory.getService(this.hap.Service.MotionSensor)
898
+ const state = Number(this.WindowCovering.CurrentPosition) > 0 ? 1 : 0
899
+ motion?.updateCharacteristic(this.hap.Characteristic.MotionDetected, state)
838
900
  }
839
901
  }
840
902
 
841
903
  async offlineOff(): Promise<void> {
842
904
  if (this.device.offline) {
843
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 100);
844
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 100);
845
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED);
905
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, 100)
906
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, 100)
907
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, this.hap.Characteristic.PositionState.STOPPED)
846
908
  }
847
909
  }
848
910
 
849
911
  async apiError(e: any): Promise<void> {
850
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, e);
851
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, e);
852
- this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, e);
853
- this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e);
854
- this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e);
855
- this.Battery.Service.updateCharacteristic(this.hap.Characteristic.ChargingState, e);
912
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.CurrentPosition, e)
913
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.PositionState, e)
914
+ this.WindowCovering.Service.updateCharacteristic(this.hap.Characteristic.TargetPosition, e)
915
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e)
916
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e)
917
+ this.Battery.Service.updateCharacteristic(this.hap.Characteristic.ChargingState, e)
856
918
  if (!this.device.curtain?.hide_lightsensor && this.LightSensor?.Service) {
857
- this.LightSensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, e);
858
- this.LightSensor.Service.updateCharacteristic(this.hap.Characteristic.StatusActive, e);
919
+ this.LightSensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel, e)
920
+ this.LightSensor.Service.updateCharacteristic(this.hap.Characteristic.StatusActive, e)
859
921
  }
860
922
  }
861
923
  }