@switchbot/homebridge-switchbot 3.7.1-beta.9 → 3.8.1-beta.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 (194) 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 +47 -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
package/CHANGELOG.md CHANGED
@@ -2,13 +2,19 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. This project uses [Semantic Versioning](https://semver.org/)
4
4
 
5
- ## [3.7.1](https://github.com/OpenWonderLabs/homebridge-switchbot/releases/tag/v3.7.1) (2024-07-23)
5
+ ## [3.8.0](https://github.com/OpenWonderLabs/homebridge-switchbot/releases/tag/v3.8.0) (2024-09-11)
6
6
 
7
7
  ### What's Changed
8
+ - Added specific macOS Bluetooth permission instructions to Readme [#1026](https://github.com/OpenWonderLabs/homebridge-switchbot/pull/1026), Thanks [@rSffsE](https://github.com/rSffsE)
9
+ - Added partial support for `Roller Shade` deviceType. Currently only supports status.
10
+ - Added `silentModeSwitch` config option for both `Curtain` & `Blind Titl` deviceTypes, allowing two switches to be display for Closing and Moding Mode. If turned on then Silent Mode is enabled.
11
+ - Added option to allow invalid Characters in displayName with config `allowInvalidCharacters`
12
+ - Added `dry` config option to enable Dry Status support for Water Detector
8
13
  - Fixed Platform BLE Scanning events not registering
14
+ - Fix `On` state for robot vacuum cleaners [#1028](https://github.com/OpenWonderLabs/homebridge-switchbot/pull/1028), Thanks [@JannThomas](https://github.com/JannThomas)
9
15
  - Housekeeping and updated dependencies.
10
16
 
11
- **Full Changelog**: https://github.com/OpenWonderLabs/homebridge-switchbot/compare/v3.7.0...v3.7.1
17
+ **Full Changelog**: https://github.com/OpenWonderLabs/homebridge-switchbot/compare/v3.7.0...v3.8.0
12
18
 
13
19
  ## [3.7.0](https://github.com/OpenWonderLabs/homebridge-switchbot/releases/tag/v3.7.0) (2024-07-21)
14
20
 
package/README.md CHANGED
@@ -65,6 +65,20 @@
65
65
 
66
66
  This lists all discovered Bluetooth devices. The BLE address of the SwitchBot device should be included in this list, otherwise your computer does not discover it.
67
67
 
68
+ - ### If using MacOS
69
+ 1. Manually grant Bluetooth access in System Settings UI for `Security & Privacy -> Privacy` to the node executable, eg `/usr/local/bin/node`
70
+ ![Security & Privacy -> Privacy](assets/security-privacy-bluetooth.png)
71
+ (This is what is intended in documentation for the noble bluetooth package [prerequisites](https://github.com/abandonware/noble#prerequisites) by "Add terminal app", however for HomeBridge it is `node` that needs the permission granted, not `terminal`.
72
+ Without this step, then you will receive the following error when the swichbot plugin launches, which will cause Homebridge or the child bridge process to restart:
73
+ ```
74
+ Error: Failed to initialize the Noble object: unauthorized
75
+ at Noble.<anonymous> (file:///usr/local/lib/node_modules/@switchbot/homebridge-switchbot/node_modules/node-switchbot/src/switchbot.ts:244:19)
76
+ at Object.onceWrapper (node:events:629:26)
77
+ at Noble.emit (node:events:514:28)
78
+ at Noble.onStateChange (/usr/local/lib/node_modules/@switchbot/homebridge-switchbot/node_modules/@stoprocent/noble/lib/noble.js:92:8)
79
+ at NobleMac.emit (node:events:514:28)
80
+ ```
81
+
68
82
  ## Supported SwitchBot Devices
69
83
 
70
84
  - [SwitchBot Humidifier](https://www.switch-bot.com/products/switchbot-smart-humidifier)
@@ -221,6 +221,12 @@
221
221
  "Robot Vacuum Cleaner S1 Plus"
222
222
  ]
223
223
  },
224
+ {
225
+ "title": "Roller Shade",
226
+ "enum": [
227
+ "Roller Shade"
228
+ ]
229
+ },
224
230
  {
225
231
  "title": "Smart Fan",
226
232
  "enum": [
@@ -587,6 +593,14 @@
587
593
  "condition": {
588
594
  "functionBody": "return (model.options && model.options.devices && !model.options.devices[arrayIndices].hide_device && model.options.devices[arrayIndices].configDeviceType === 'Water Detector' && model.options.devices[arrayIndices].deviceId);"
589
595
  }
596
+ },
597
+ "dry": {
598
+ "title": "Water Detector's Dry Alert",
599
+ "type": "boolean",
600
+ "description": "If true, the Water Detector will send an alert when it is dry.",
601
+ "condition": {
602
+ "functionBody": "return (model.options && model.options.devices && !model.options.devices[arrayIndices].hide_device && model.options.devices[arrayIndices].configDeviceType === 'Water Detector' && model.options.devices[arrayIndices].deviceId);"
603
+ }
590
604
  }
591
605
  }
592
606
  },
@@ -699,6 +713,13 @@
699
713
  "functionBody": "return (model.options && model.options.devices && !model.options.devices[arrayIndices].hide_device && (model.options.devices[arrayIndices].configDeviceType === 'Curtain' || model.options.devices[arrayIndices].configDeviceType === 'Curtain3') && model.options.devices[arrayIndices].deviceId);"
700
714
  }
701
715
  },
716
+ "silentModeSwitch": {
717
+ "title": "Enable Curtain Silent Mode Switches",
718
+ "type": "boolean",
719
+ "condition": {
720
+ "functionBody": "return (model.options && model.options.devices && !model.options.devices[arrayIndices].hide_device && (model.options.devices[arrayIndices].configDeviceType === 'Curtain' || model.options.devices[arrayIndices].configDeviceType === 'Curtain3') && model.options.devices[arrayIndices].deviceId);"
721
+ }
722
+ },
702
723
  "hide_lightsensor": {
703
724
  "title": "Hide Light Sensor",
704
725
  "type": "boolean",
@@ -810,6 +831,55 @@
810
831
  "condition": {
811
832
  "functionBody": "return (model.options && model.options.devices && !model.options.devices[arrayIndices].hide_device && model.options.devices[arrayIndices].configDeviceType === 'Blind Tilt' && model.options.devices[arrayIndices].deviceId);"
812
833
  }
834
+ },
835
+ "setOpenMode": {
836
+ "title": "Blind Tilt's Opening Mode",
837
+ "type": "string",
838
+ "oneOf": [
839
+ {
840
+ "enum": [
841
+ "0"
842
+ ],
843
+ "title": "Performance Mode"
844
+ },
845
+ {
846
+ "enum": [
847
+ "1"
848
+ ],
849
+ "title": "Silent Mode"
850
+ }
851
+ ],
852
+ "condition": {
853
+ "functionBody": "return (model.options && model.options.devices && !model.options.devices[arrayIndices].hide_device && model.options.devices[arrayIndices].configDeviceType === 'Blind Tilt' && model.options.devices[arrayIndices].deviceId);"
854
+ }
855
+ },
856
+ "setCloseMode": {
857
+ "title": "Blind Tilt's Closing Mode",
858
+ "type": "string",
859
+ "oneOf": [
860
+ {
861
+ "enum": [
862
+ "0"
863
+ ],
864
+ "title": "Performance Mode"
865
+ },
866
+ {
867
+ "enum": [
868
+ "1"
869
+ ],
870
+ "title": "Silent Mode"
871
+ }
872
+ ],
873
+ "condition": {
874
+ "functionBody": "return (model.options && model.options.devices && !model.options.devices[arrayIndices].hide_device && model.options.devices[arrayIndices].configDeviceType === 'Blind Tilt' && model.options.devices[arrayIndices].deviceId);"
875
+ }
876
+ },
877
+ "silentModeSwitch": {
878
+ "title": "Enable Blind Tilt Silent Mode Switches",
879
+ "type": "boolean",
880
+ "condition": {
881
+ "functionBody": "return (model.options && model.options.devices && !model.options.devices[arrayIndices].hide_device && model.options.devices[arrayIndices].configDeviceType === 'Blind Tilt' && model.options.devices[arrayIndices].deviceId);"
882
+ }
813
883
  }
814
884
  }
815
885
  },
@@ -1800,6 +1870,7 @@
1800
1870
  "options.devices[].hub.hide_humidity",
1801
1871
  "options.devices[].hub.hide_lightsensor",
1802
1872
  "options.devices[].waterdetector.hide_leak",
1873
+ "options.devices[].waterdetector.dry",
1803
1874
  "options.devices[].humidifier.set_minStep",
1804
1875
  "options.devices[].humidifier.hide_temperature",
1805
1876
  "options.devices[].curtain.set_minStep",
@@ -1807,6 +1878,7 @@
1807
1878
  "options.devices[].curtain.set_max",
1808
1879
  "options.devices[].curtain.setOpenMode",
1809
1880
  "options.devices[].curtain.setCloseMode",
1881
+ "options.devices[].curtain.silentModeSwitch",
1810
1882
  "options.devices[].curtain.updateRate",
1811
1883
  "options.devices[].curtain.disable_group",
1812
1884
  "options.devices[].curtain.hide_lightsensor",
@@ -1818,6 +1890,9 @@
1818
1890
  "options.devices[].blindTilt.set_max",
1819
1891
  "options.devices[].blindTilt.hide_lightsensor",
1820
1892
  "options.devices[].blindTilt.updateRate",
1893
+ "options.devices[].blindTilt.setOpenMode",
1894
+ "options.devices[].blindTilt.setCloseMode",
1895
+ "options.devices[].blindTilt.silentModeSwitch",
1821
1896
  "options.devices[].contact.hide_lightsensor",
1822
1897
  "options.devices[].contact.set_minlux",
1823
1898
  "options.devices[].contact.set_maxlux",
@@ -1939,4 +2014,4 @@
1939
2014
  ]
1940
2015
  }
1941
2016
  ]
1942
- }
2017
+ }
@@ -1,18 +1,20 @@
1
- import { deviceBase } from './device.js';
2
- import { BlindTiltMappingMode } from '../utils.js';
3
- import { Subject } from 'rxjs';
4
- import type { devicesConfig } from '../settings.js';
5
- import type { device } from '../types/devicelist.js';
1
+ import type { CharacteristicValue, PlatformAccessory } from 'homebridge';
6
2
  import type { SwitchBotPlatform } from '../platform.js';
3
+ import type { devicesConfig } from '../settings.js';
7
4
  import type { blindTiltServiceData } from '../types/bledevicestatus.js';
5
+ import type { device } from '../types/devicelist.js';
8
6
  import type { blindTiltStatus } from '../types/devicestatus.js';
9
7
  import type { blindTiltWebhookContext } from '../types/devicewebhookstatus.js';
10
- import type { PlatformAccessory, CharacteristicValue } from 'homebridge';
8
+ import { Subject } from 'rxjs';
9
+ import { BlindTiltMappingMode } from '../utils.js';
10
+ import { deviceBase } from './device.js';
11
11
  export declare class BlindTilt extends deviceBase {
12
12
  readonly platform: SwitchBotPlatform;
13
13
  private WindowCovering;
14
14
  private Battery;
15
15
  private LightSensor?;
16
+ private OpenModeSwitch?;
17
+ private CloseModeSwitch?;
16
18
  deviceStatus: blindTiltStatus;
17
19
  mappingMode: BlindTiltMappingMode;
18
20
  webhookContext: blindTiltWebhookContext;
@@ -52,6 +54,14 @@ export declare class BlindTilt extends deviceBase {
52
54
  */
53
55
  TargetPositionSet(value: CharacteristicValue): Promise<void>;
54
56
  startUpdatingBlindTiltIfNeeded(): Promise<void>;
57
+ /**
58
+ * Handle requests to set the value of the "Target Position" characteristic
59
+ */
60
+ OpenModeSwitchSet(value: CharacteristicValue): Promise<void>;
61
+ /**
62
+ * Handle requests to set the value of the "Target Position" characteristic
63
+ */
64
+ CloseModeSwitchSet(value: CharacteristicValue): Promise<void>;
55
65
  updateHomeKitCharacteristics(): Promise<void>;
56
66
  BLEPushConnection(): Promise<void>;
57
67
  BLERefreshConnection(switchbot: any): Promise<void>;
@@ -67,7 +77,7 @@ export declare class BlindTilt extends deviceBase {
67
77
  * Maps device values to homekit values
68
78
  *
69
79
  * @param devicePosition the position as reported by the devide
70
- * @param direction the direction as reported by the device
80
+ * @param deviceDirection the direction as reported by the device
71
81
  * @returns [homekit position, homekit tiltAngle]
72
82
  */
73
83
  mapDeviceValuesToHomekitValues(devicePosition: number, deviceDirection: string): [CharacteristicValue, CharacteristicValue?];
@@ -75,7 +85,7 @@ export declare class BlindTilt extends deviceBase {
75
85
  * Maps homekit values to device values
76
86
  *
77
87
  * @param homekitPosition the position as reported by homekit
78
- * @param homekitTiltAngle? the tilt angle as reported by homekit
88
+ * @param homekitTiltAngle the tilt angle as reported by homekit
79
89
  * @returns [device position, device direction]
80
90
  */
81
91
  mapHomekitValuesToDeviceValues(homekitPosition: number, homekitTiltAngle: number): [string, number];
@@ -1 +1 @@
1
- {"version":3,"file":"blindtilt.d.ts","sourceRoot":"","sources":["../../src/device/blindtilt.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"blindtilt.d.ts","sourceRoot":"","sources":["../../src/device/blindtilt.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAW,MAAM,YAAY,CAAA;AAEjF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AACvE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,wBAAwB,CAAA;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC/D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,iCAAiC,CAAA;AAO9E,OAAO,EAAqC,OAAO,EAAa,MAAM,MAAM,CAAA;AAE5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExC,qBAAa,SAAU,SAAQ,UAAU;IA0DrC,QAAQ,CAAC,QAAQ,EAAE,iBAAiB;IAxDtC,OAAO,CAAC,cAAc,CAQrB;IAED,OAAO,CAAC,OAAO,CAMd;IAED,OAAO,CAAC,WAAW,CAAC,CAInB;IAED,OAAO,CAAC,cAAc,CAAC,CAItB;IAED,OAAO,CAAC,eAAe,CAAC,CAIvB;IAGD,YAAY,EAAG,eAAe,CAAA;IAC9B,WAAW,EAAE,oBAAoB,CAA8B;IAG/D,cAAc,EAAG,uBAAuB,CAAA;IAGxC,WAAW,EAAG,oBAAoB,CAAA;IAGlC,YAAY,EAAG,OAAO,CAAA;IACtB,iBAAiB,EAAG,MAAM,CAAC,OAAO,CAAA;IAGlC,eAAe,EAAE,OAAO,CAAA;IACxB,yBAAyB,EAAE,OAAO,CAAA;IAClC,iBAAiB,EAAE,OAAO,CAAC,IAAI,CAAC,CAAA;gBAGrB,QAAQ,EAAE,iBAAiB,EACpC,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,MAAM,GAAG,aAAa;IA4NhC;;OAEG;IACG,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IA4DrC;;OAEG;IACG,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IA+CnC,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IAyBzC;;OAEG;IACG,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAa9B,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAuBjC,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBpC,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IAqBrC,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;IAkBhC,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAoB5B,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAqC/B,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IAqDzC;;OAEG;IACG,4BAA4B,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAa7E;;OAEG;IACG,iBAAiB,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAY5D,8BAA8B,IAAI,OAAO,CAAC,IAAI,CAAC;IAmCrD;;OAEG;IACG,iBAAiB,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IASlE;;OAEG;IACG,kBAAkB,CAAC,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAS7D,4BAA4B,IAAI,OAAO,CAAC,IAAI,CAAC;IAyB7C,iBAAiB;IAOjB,oBAAoB,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAQnD,cAAc;;;;IA6Bd,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB1B,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAU3B,QAAQ,CAAC,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAe/B,2BAA2B,CAC/B,SAAS,EAAE,eAAe,CAAC,WAAW,CAAC,GAAG,uBAAuB,CAAC,WAAW,CAAC,EAC9E,aAAa,EAAE,eAAe,CAAC,eAAe,CAAC,GAAG,uBAAuB,CAAC,eAAe,CAAC;IAiD5F;;;;;;OAMG;IACH,8BAA8B,CAAC,cAAc,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,CAAC,mBAAmB,EAAE,mBAAmB,CAAC,CAAC;IAiD5H;;;;;;OAMG;IACH,8BAA8B,CAAC,eAAe,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC;CAyDpG"}
@@ -1,25 +1,23 @@
1
- /* Copyright(C) 2021-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
2
- *
3
- * blindtilt.ts: @switchbot/homebridge-switchbot.
4
- */
5
- import { deviceBase } from './device.js';
6
- import { BlindTiltMappingMode } from '../utils.js';
7
1
  /*
8
2
  * For Testing Locally:
9
3
  * import { SwitchBotBLEModel, SwitchBotBLEModelName } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js';
10
4
  */
11
5
  import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot';
12
- import { Subject, debounceTime, interval, skipWhile, take, tap } from 'rxjs';
6
+ import { debounceTime, interval, skipWhile, Subject, take, tap } from 'rxjs';
7
+ import { BlindTiltMappingMode } from '../utils.js';
8
+ import { deviceBase } from './device.js';
13
9
  export class BlindTilt extends deviceBase {
14
10
  platform;
15
11
  // Services
16
12
  WindowCovering;
17
13
  Battery;
18
14
  LightSensor;
15
+ OpenModeSwitch;
16
+ CloseModeSwitch;
19
17
  // OpenAPI
20
18
  deviceStatus;
21
19
  mappingMode = BlindTiltMappingMode.OnlyUp;
22
- //Webhook
20
+ // Webhook
23
21
  webhookContext;
24
22
  // BLE
25
23
  serviceData;
@@ -56,23 +54,16 @@ export class BlindTilt extends deviceBase {
56
54
  };
57
55
  accessory.context.WindowCovering = this.WindowCovering;
58
56
  // Initialize WindowCovering Characteristics
59
- this.WindowCovering.Service
60
- .setCharacteristic(this.hap.Characteristic.Name, this.WindowCovering.Name)
61
- .getCharacteristic(this.hap.Characteristic.TargetPosition)
62
- .setProps({
57
+ this.WindowCovering.Service.setCharacteristic(this.hap.Characteristic.Name, this.WindowCovering.Name).getCharacteristic(this.hap.Characteristic.TargetPosition).setProps({
63
58
  minStep: device.blindTilt?.set_minStep ?? 1,
64
59
  minValue: 0,
65
60
  maxValue: 100,
66
61
  validValueRanges: [0, 100],
67
- })
68
- .onGet(() => {
62
+ }).onGet(() => {
69
63
  return this.WindowCovering.TargetPosition;
70
- })
71
- .onSet(this.TargetPositionSet.bind(this));
64
+ }).onSet(this.TargetPositionSet.bind(this));
72
65
  // Initialize WindowCovering CurrentPosition Characteristic
73
- this.WindowCovering.Service
74
- .getCharacteristic(this.hap.Characteristic.CurrentPosition)
75
- .setProps({
66
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.CurrentPosition).setProps({
76
67
  minStep: device.blindTilt?.set_minStep ?? 1,
77
68
  minValue: 0,
78
69
  maxValue: 100,
@@ -81,22 +72,16 @@ export class BlindTilt extends deviceBase {
81
72
  return this.WindowCovering.CurrentPosition ?? 0;
82
73
  });
83
74
  // Initialize WindowCovering TargetHorizontalTiltAngle Characteristic
84
- this.WindowCovering.Service
85
- .getCharacteristic(this.hap.Characteristic.TargetHorizontalTiltAngle)
86
- .setProps({
75
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.TargetHorizontalTiltAngle).setProps({
87
76
  minStep: 180,
88
77
  minValue: -90,
89
78
  maxValue: 90,
90
79
  validValues: [-90, 90],
91
- })
92
- .onGet(() => {
80
+ }).onGet(() => {
93
81
  return this.WindowCovering.TargetHorizontalTiltAngle;
94
- })
95
- .onSet(this.TargetHorizontalTiltAngleSet.bind(this));
82
+ }).onSet(this.TargetHorizontalTiltAngleSet.bind(this));
96
83
  // Initialize WindowCovering CurrentHorizontalTiltAngle Characteristic
97
- this.WindowCovering.Service
98
- .getCharacteristic(this.hap.Characteristic.CurrentHorizontalTiltAngle)
99
- .setProps({
84
+ this.WindowCovering.Service.getCharacteristic(this.hap.Characteristic.CurrentHorizontalTiltAngle).setProps({
100
85
  minStep: 180,
101
86
  minValue: -90,
102
87
  maxValue: 90,
@@ -115,9 +100,7 @@ export class BlindTilt extends deviceBase {
115
100
  };
116
101
  accessory.context.Battery = this.Battery;
117
102
  // Initialize Battery Name Characteristic
118
- this.Battery.Service
119
- .setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name)
120
- .setCharacteristic(this.hap.Characteristic.ChargingState, this.hap.Characteristic.ChargingState.NOT_CHARGEABLE);
103
+ this.Battery.Service.setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name).setCharacteristic(this.hap.Characteristic.ChargingState, this.hap.Characteristic.ChargingState.NOT_CHARGEABLE);
121
104
  // Initialize LightSensor Service
122
105
  if (device.blindTilt?.hide_lightsensor) {
123
106
  if (this.LightSensor?.Service) {
@@ -139,14 +122,56 @@ export class BlindTilt extends deviceBase {
139
122
  };
140
123
  accessory.context.LightSensor = this.LightSensor;
141
124
  // Initialize LightSensor Characteristics
142
- this.LightSensor.Service
143
- .setCharacteristic(this.hap.Characteristic.Name, this.LightSensor.Name)
144
- .setCharacteristic(this.hap.Characteristic.StatusActive, true)
145
- .getCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel)
146
- .onGet(() => {
125
+ this.LightSensor.Service.setCharacteristic(this.hap.Characteristic.Name, this.LightSensor.Name).setCharacteristic(this.hap.Characteristic.StatusActive, true).getCharacteristic(this.hap.Characteristic.CurrentAmbientLightLevel).onGet(() => {
147
126
  return this.LightSensor?.CurrentAmbientLightLevel ?? 0.0001;
148
127
  });
149
128
  }
129
+ // Initialize Open Mode Switch Service
130
+ if (!device.blindTilt?.silentModeSwitch) {
131
+ if (this.OpenModeSwitch?.Service) {
132
+ this.debugLog('Removing Open Mode Switch Service');
133
+ this.OpenModeSwitch.Service = this.accessory.getService(this.hap.Service.Switch);
134
+ accessory.removeService(this.OpenModeSwitch.Service);
135
+ accessory.context.OpenModeSwitch = {};
136
+ }
137
+ }
138
+ else {
139
+ accessory.context.OpenModeSwitch = accessory.context.OpenModeSwitch ?? {};
140
+ this.OpenModeSwitch = {
141
+ Name: `${accessory.displayName} Silent Open Mode`,
142
+ Service: accessory.getService(this.hap.Service.Switch) ?? accessory.addService(this.hap.Service.Switch),
143
+ On: accessory.context.OpenModeSwitch.On ?? false,
144
+ };
145
+ accessory.context.OpenModeSwitch = this.OpenModeSwitch;
146
+ // Initialize Open Mode Switch Service
147
+ this.OpenModeSwitch.Service.setCharacteristic(this.hap.Characteristic.Name, this.OpenModeSwitch.Name).getCharacteristic(this.hap.Characteristic.On).onGet(() => {
148
+ return this.OpenModeSwitch?.On ?? false;
149
+ });
150
+ this.OpenModeSwitch.Service.getCharacteristic(this.hap.Characteristic.On).onSet(this.OpenModeSwitchSet.bind(this));
151
+ }
152
+ // Initialize Close Mode Switch Service
153
+ if (!device.blindTilt?.silentModeSwitch) {
154
+ if (this.CloseModeSwitch?.Service) {
155
+ this.debugLog('Removing Close Mode Switch Service');
156
+ this.CloseModeSwitch.Service = this.accessory.getService(this.hap.Service.Switch);
157
+ accessory.removeService(this.CloseModeSwitch.Service);
158
+ accessory.context.CloseModeSwitch = {};
159
+ }
160
+ }
161
+ else {
162
+ accessory.context.CloseModeSwitch = accessory.context.CloseModeSwitch ?? {};
163
+ this.CloseModeSwitch = {
164
+ Name: `${accessory.displayName} Silent Close Mode`,
165
+ Service: accessory.getService(this.hap.Service.Switch) ?? accessory.addService(this.hap.Service.Switch),
166
+ On: accessory.context.CloseModeSwitch.On ?? false,
167
+ };
168
+ accessory.context.CloseModeSwitch = this.CloseModeSwitch;
169
+ // Initialize Close Mode Switch Service
170
+ this.CloseModeSwitch.Service.setCharacteristic(this.hap.Characteristic.Name, this.CloseModeSwitch.Name).getCharacteristic(this.hap.Characteristic.On).onGet(() => {
171
+ return this.CloseModeSwitch?.On ?? false;
172
+ });
173
+ this.CloseModeSwitch.Service.getCharacteristic(this.hap.Characteristic.On).onSet(this.CloseModeSwitchSet.bind(this));
174
+ }
150
175
  // Retrieve initial values and updateHomekit
151
176
  try {
152
177
  this.debugLog('Retrieve initial values and update Homekit');
@@ -155,7 +180,7 @@ export class BlindTilt extends deviceBase {
155
180
  catch (e) {
156
181
  this.errorLog(`failed to retrieve initial values and update Homekit, Error: ${e}`);
157
182
  }
158
- //regisiter webhook event handler if enabled
183
+ // regisiter webhook event handler if enabled
159
184
  try {
160
185
  this.debugLog('Registering Webhook Event Handler');
161
186
  this.registerWebhook();
@@ -163,7 +188,7 @@ export class BlindTilt extends deviceBase {
163
188
  catch (e) {
164
189
  this.errorLog(`failed to registerWebhook, Error: ${e}`);
165
190
  }
166
- //regisiter platform BLE event handler if enabled
191
+ // regisiter platform BLE event handler if enabled
167
192
  try {
168
193
  this.debugLog('Registering Platform BLE Event Handler');
169
194
  this.registerPlatformBLE();
@@ -209,9 +234,7 @@ export class BlindTilt extends deviceBase {
209
234
  */
210
235
  async BLEparseStatus() {
211
236
  await this.debugLog('BLEparseStatus');
212
- await this.debugLog(`(direction, slidePosition, battery, version) = BLE:(${this.serviceData.tilt}, ${this.serviceData.tilt},`
213
- + ` ${this.serviceData.battery}, ${this.accessory.context.version}), current:(${this.WindowCovering.CurrentHorizontalTiltAngle},`
214
- + ` ${this.WindowCovering.CurrentPosition}, ${this.Battery.BatteryLevel}, ${this.accessory.context.version})`);
237
+ await this.debugLog(`(direction, slidePosition, battery, version) = BLE:(${this.serviceData.tilt}, ${this.serviceData.tilt}, ${this.serviceData.battery}, ${this.accessory.context.version}), current:(${this.WindowCovering.CurrentHorizontalTiltAngle}, ${this.WindowCovering.CurrentPosition}, ${this.Battery.BatteryLevel}, ${this.accessory.context.version})`);
215
238
  // CurrentPosition
216
239
  this.WindowCovering.CurrentPosition = 100 - Number(this.serviceData.tilt);
217
240
  await this.setMinMax();
@@ -248,8 +271,7 @@ export class BlindTilt extends deviceBase {
248
271
  this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
249
272
  await this.debugLog(`Stopped, PositionState: ${this.WindowCovering.PositionState}`);
250
273
  }
251
- await this.debugLog(`CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition: ${this.WindowCovering.TargetPosition},`
252
- + ` PositionState: ${this.WindowCovering.PositionState}`);
274
+ await this.debugLog(`CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition: ${this.WindowCovering.TargetPosition}, PositionState: ${this.WindowCovering.PositionState}`);
253
275
  // CurrentAmbientLightLevel
254
276
  if (!this.device.blindTilt?.hide_lightsensor && this.LightSensor?.Service) {
255
277
  const set_minLux = this.device.blindTilt?.set_minLux ?? 1;
@@ -263,7 +285,8 @@ export class BlindTilt extends deviceBase {
263
285
  await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`);
264
286
  // StatusLowBattery
265
287
  this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
266
- ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
288
+ ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW
289
+ : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
267
290
  await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`);
268
291
  }
269
292
  ;
@@ -272,9 +295,7 @@ export class BlindTilt extends deviceBase {
272
295
  */
273
296
  async openAPIparseStatus() {
274
297
  await this.debugLog('openAPIparseStatus');
275
- await this.debugLog(`(direction, slidePosition, battery, version) = OpenAPI:(${this.deviceStatus.direction}, ${this.deviceStatus.slidePosition},`
276
- + ` ${this.deviceStatus.battery}, ${this.deviceStatus.version}), current:(${this.WindowCovering.CurrentHorizontalTiltAngle},`
277
- + ` ${this.WindowCovering.CurrentPosition}, ${this.Battery.BatteryLevel}, ${this.accessory.context.version})`);
298
+ await this.debugLog(`(direction, slidePosition, battery, version) = OpenAPI:(${this.deviceStatus.direction}, ${this.deviceStatus.slidePosition}, ${this.deviceStatus.battery}, ${this.deviceStatus.version}), current:(${this.WindowCovering.CurrentHorizontalTiltAngle}, ${this.WindowCovering.CurrentPosition}, ${this.Battery.BatteryLevel}, ${this.accessory.context.version})`);
278
299
  // CurrentPosition
279
300
  await this.getCurrentPosttionDirection(this.deviceStatus.direction, this.deviceStatus.slidePosition);
280
301
  if (!this.device.blindTilt?.hide_lightsensor && this.LightSensor?.Service) {
@@ -289,7 +310,8 @@ export class BlindTilt extends deviceBase {
289
310
  await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`);
290
311
  // StatusLowBattery
291
312
  this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
292
- ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
313
+ ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW
314
+ : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
293
315
  await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`);
294
316
  // Firmware Version
295
317
  const version = this.deviceStatus.version.toString();
@@ -297,7 +319,7 @@ export class BlindTilt extends deviceBase {
297
319
  let deviceVersion;
298
320
  if (version?.includes('.') === false) {
299
321
  const replace = version?.replace(/^V|-.*$/g, '');
300
- const match = replace?.match(/.{1,1}/g);
322
+ const match = replace?.match(/./g);
301
323
  const blindTiltVersion = match?.join('.') ?? '0.0.0';
302
324
  deviceVersion = blindTiltVersion;
303
325
  }
@@ -315,9 +337,7 @@ export class BlindTilt extends deviceBase {
315
337
  }
316
338
  async parseStatusWebhook() {
317
339
  await this.debugLog('parseStatusWebhook');
318
- await this.debugLog(`(slidePosition, battery, version) = Webhook:(${this.webhookContext.direction}, ${this.webhookContext.slidePosition},`
319
- + ` ${this.webhookContext.battery}, ${this.webhookContext.version}, current:(${this.WindowCovering.CurrentHorizontalTiltAngle},`
320
- + ` ${this.WindowCovering.CurrentPosition}, ${this.Battery.BatteryLevel}, ${this.accessory.context.version})`);
340
+ await this.debugLog(`(slidePosition, battery, version) = Webhook:(${this.webhookContext.direction}, ${this.webhookContext.slidePosition}, ${this.webhookContext.battery}, ${this.webhookContext.version}, current:(${this.WindowCovering.CurrentHorizontalTiltAngle}, ${this.WindowCovering.CurrentPosition}, ${this.Battery.BatteryLevel}, ${this.accessory.context.version})`);
321
341
  // CurrentPosition and CurrentHorizontalTiltAngle
322
342
  await this.getCurrentPosttionDirection(this.webhookContext.direction, this.webhookContext.slidePosition);
323
343
  // BatteryLevel
@@ -325,7 +345,8 @@ export class BlindTilt extends deviceBase {
325
345
  await this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`);
326
346
  // StatusLowBattery
327
347
  this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
328
- ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
348
+ ? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW
349
+ : this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
329
350
  await this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`);
330
351
  // Firmware Version
331
352
  const deviceVersion = this.webhookContext.version.replace(/^V|-.*$/g, '') ?? '0.0.0';
@@ -408,7 +429,6 @@ export class BlindTilt extends deviceBase {
408
429
  const { body, statusCode } = await this.deviceRefreshStatus();
409
430
  const deviceStatus = await body.json();
410
431
  await this.debugLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
411
- ;
412
432
  if (await this.successfulStatusCodes(statusCode, deviceStatus)) {
413
433
  await this.debugSuccessLog(`statusCode: ${statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`);
414
434
  this.deviceStatus = deviceStatus.body;
@@ -501,8 +521,7 @@ export class BlindTilt extends deviceBase {
501
521
  }
502
522
  }
503
523
  else {
504
- await this.debugLog(`No changes (BLEpushChanges), TargetPosition: ${this.WindowCovering.TargetPosition},`
505
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
524
+ await this.debugLog(`No changes (BLEpushChanges), TargetPosition: ${this.WindowCovering.TargetPosition}, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
506
525
  }
507
526
  }
508
527
  async openAPIpushChanges() {
@@ -557,10 +576,8 @@ export class BlindTilt extends deviceBase {
557
576
  }
558
577
  }
559
578
  else {
560
- await this.debugLog(`No changes (openAPIpushChanges), TargetPosition: ${this.WindowCovering.TargetPosition},`
561
- + ` CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
562
- await this.debugLog(`No changes (openAPIpushChanges), TargetHorizontalTiltAngle: ${this.WindowCovering.TargetHorizontalTiltAngle},`
563
- + ` CurrentHorizontalTiltAngle: ${this.WindowCovering.CurrentHorizontalTiltAngle}`);
579
+ await this.debugLog(`No changes (openAPIpushChanges), TargetPosition: ${this.WindowCovering.TargetPosition}, CurrentPosition: ${this.WindowCovering.CurrentPosition}`);
580
+ await this.debugLog(`No changes (openAPIpushChanges), TargetHorizontalTiltAngle: ${this.WindowCovering.TargetHorizontalTiltAngle}, CurrentHorizontalTiltAngle: ${this.WindowCovering.CurrentHorizontalTiltAngle}`);
564
581
  }
565
582
  }
566
583
  /**
@@ -573,7 +590,7 @@ export class BlindTilt extends deviceBase {
573
590
  else {
574
591
  await this.debugLog(`No changes, TargetHorizontalTiltAngle: ${value}`);
575
592
  }
576
- //value = value < 0 ? -90 : 90;
593
+ // value = value < 0 ? -90 : 90;
577
594
  this.WindowCovering.TargetHorizontalTiltAngle = value;
578
595
  await this.mqtt('TargetHorizontalTiltAngle', this.WindowCovering.TargetHorizontalTiltAngle);
579
596
  await this.startUpdatingBlindTiltIfNeeded();
@@ -627,6 +644,28 @@ export class BlindTilt extends deviceBase {
627
644
  }
628
645
  this.doBlindTiltUpdate.next();
629
646
  }
647
+ /**
648
+ * Handle requests to set the value of the "Target Position" characteristic
649
+ */
650
+ async OpenModeSwitchSet(value) {
651
+ if (this.OpenModeSwitch && this.device.blindTilt?.silentModeSwitch) {
652
+ this.debugLog(`Silent Open Mode: ${value}`);
653
+ this.OpenModeSwitch.On = value;
654
+ this.accessory.context.OpenModeSwitch.On = value;
655
+ this.doBlindTiltUpdate.next();
656
+ }
657
+ }
658
+ /**
659
+ * Handle requests to set the value of the "Target Position" characteristic
660
+ */
661
+ async CloseModeSwitchSet(value) {
662
+ if (this.CloseModeSwitch && this.device.blindTilt?.silentModeSwitch) {
663
+ this.debugLog(`Silent Close Mode: ${value}`);
664
+ this.CloseModeSwitch.On = value;
665
+ this.accessory.context.CloseModeSwitch.On = value;
666
+ this.doBlindTiltUpdate.next();
667
+ }
668
+ }
630
669
  async updateHomeKitCharacteristics() {
631
670
  await this.setMinMax();
632
671
  // CurrentHorizontalTiltAngle
@@ -668,11 +707,11 @@ export class BlindTilt extends deviceBase {
668
707
  let setPositionMode;
669
708
  let Mode;
670
709
  if (Number(this.WindowCovering.TargetPosition) > 50) {
671
- if (this.device.blindTilt?.setOpenMode === '1') {
710
+ if (this.device.blindTilt?.setOpenMode === '1' || this.OpenModeSwitch?.On) {
672
711
  setPositionMode = 1;
673
712
  Mode = 'Silent Mode';
674
713
  }
675
- else if (this.device.blindTilt?.setOpenMode === '0') {
714
+ else if (this.device.blindTilt?.setOpenMode === '0' || !this.OpenModeSwitch?.On) {
676
715
  setPositionMode = 0;
677
716
  Mode = 'Performance Mode';
678
717
  }
@@ -682,11 +721,11 @@ export class BlindTilt extends deviceBase {
682
721
  }
683
722
  }
684
723
  else {
685
- if (this.device.blindTilt?.setCloseMode === '1') {
724
+ if (this.device.blindTilt?.setCloseMode === '1' || this.CloseModeSwitch?.On) {
686
725
  setPositionMode = 1;
687
726
  Mode = 'Silent Mode';
688
727
  }
689
- else if (this.device.blindTilt?.setOpenMode === '0') {
728
+ else if (this.device.blindTilt?.setOpenMode === '0' || !this.CloseModeSwitch?.On) {
690
729
  setPositionMode = 0;
691
730
  Mode = 'Performance Mode';
692
731
  }
@@ -785,14 +824,13 @@ export class BlindTilt extends deviceBase {
785
824
  this.WindowCovering.PositionState = this.hap.Characteristic.PositionState.STOPPED;
786
825
  await this.debugLog(`Stopped, PositionState: ${this.WindowCovering.PositionState}`);
787
826
  }
788
- await this.debugLog(`CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition: ${this.WindowCovering.TargetPosition},`
789
- + ` PositionState: ${this.WindowCovering.PositionState}`);
827
+ await this.debugLog(`CurrentPosition: ${this.WindowCovering.CurrentPosition}, TargetPosition: ${this.WindowCovering.TargetPosition}, PositionState: ${this.WindowCovering.PositionState}`);
790
828
  }
791
829
  /**
792
830
  * Maps device values to homekit values
793
831
  *
794
832
  * @param devicePosition the position as reported by the devide
795
- * @param direction the direction as reported by the device
833
+ * @param deviceDirection the direction as reported by the device
796
834
  * @returns [homekit position, homekit tiltAngle]
797
835
  */
798
836
  mapDeviceValuesToHomekitValues(devicePosition, deviceDirection) {
@@ -845,7 +883,7 @@ export class BlindTilt extends deviceBase {
845
883
  * Maps homekit values to device values
846
884
  *
847
885
  * @param homekitPosition the position as reported by homekit
848
- * @param homekitTiltAngle? the tilt angle as reported by homekit
886
+ * @param homekitTiltAngle the tilt angle as reported by homekit
849
887
  * @returns [device position, device direction]
850
888
  */
851
889
  mapHomekitValuesToDeviceValues(homekitPosition, homekitTiltAngle) {