@switchbot/homebridge-switchbot 5.0.0-beta.8 → 5.0.0-beta.80
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.
- package/.github/ISSUE_TEMPLATE/e2e-verification.md +36 -0
- package/.github/workflows/ci.yml +61 -0
- package/.github/workflows/manual-e2e.yml +103 -0
- package/CHANGELOG.md +35 -0
- package/E2E-VERIFICATION.md +121 -0
- package/MIGRATION.md +44 -0
- package/README.md +56 -3
- package/config.schema.json +83 -14807
- package/dist/deviceFactory.d.ts +13 -0
- package/dist/deviceFactory.d.ts.map +1 -0
- package/dist/deviceFactory.js +81 -0
- package/dist/deviceFactory.js.map +1 -0
- package/dist/devices/deviceBase.d.ts +50 -0
- package/dist/devices/deviceBase.d.ts.map +1 -0
- package/dist/devices/deviceBase.js +119 -0
- package/dist/devices/deviceBase.js.map +1 -0
- package/dist/devices/genericDevice.d.ts +283 -0
- package/dist/devices/genericDevice.d.ts.map +1 -0
- package/dist/devices/genericDevice.js +1035 -0
- package/dist/devices/genericDevice.js.map +1 -0
- package/dist/homebridge-ui/public/index.html +425 -243
- package/dist/homebridge-ui/server.d.ts +3 -1
- package/dist/homebridge-ui/server.d.ts.map +1 -1
- package/dist/homebridge-ui/server.js +276 -35
- package/dist/homebridge-ui/server.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -11
- package/dist/index.js.map +1 -1
- package/dist/platform.d.ts +27 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +404 -0
- package/dist/platform.js.map +1 -0
- package/dist/settings.d.ts +10 -249
- package/dist/settings.d.ts.map +1 -1
- package/dist/settings.js +5 -30
- package/dist/settings.js.map +1 -1
- package/dist/switchbotClient.d.ts +32 -0
- package/dist/switchbotClient.d.ts.map +1 -0
- package/dist/switchbotClient.js +194 -0
- package/dist/switchbotClient.js.map +1 -0
- package/dist/utils.d.ts +39 -50
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +39 -688
- package/dist/utils.js.map +1 -1
- package/docs/assets/highlight.css +14 -0
- package/docs/assets/icons.js +1 -1
- package/docs/assets/icons.svg +1 -1
- package/docs/assets/main.js +2 -2
- package/docs/assets/style.css +3 -3
- package/docs/index.html +77 -13
- package/docs/variables/default.html +1 -1
- package/eslint.config.js +2 -8
- package/package.json +21 -28
- package/scripts/e2e/README.md +25 -0
- package/scripts/e2e/curtain-e2e.sh +70 -0
- package/scripts/e2e/fan-e2e.sh +75 -0
- package/scripts/e2e/light-advanced-e2e.sh +97 -0
- package/scripts/e2e/light-e2e.sh +75 -0
- package/scripts/e2e/list-accessories.sh +19 -0
- package/scripts/e2e/lock-e2e.sh +65 -0
- package/scripts/generate-matter-maps.js +60 -0
- package/scripts/run-e2e-local.sh +14 -0
- package/src/deviceFactory.ts +122 -0
- package/src/devices/deviceBase.ts +141 -0
- package/src/devices/genericDevice.ts +965 -0
- package/src/homebridge-ui/public/index.html +425 -243
- package/src/homebridge-ui/server.ts +329 -40
- package/src/index.ts +4 -12
- package/src/platform.ts +395 -0
- package/src/settings.ts +12 -277
- package/src/switchbotClient.ts +203 -0
- package/src/utils.ts +45 -713
- package/test/accessory-restore.spec.ts +73 -0
- package/test/device-mapping.spec.ts +37 -0
- package/test/deviceFactory.spec.ts +18 -0
- package/test/e2e/run-e2e.spec.ts +50 -0
- package/test/fan-swing.spec.ts +29 -0
- package/test/helpers/matter-harness.ts +53 -0
- package/test/lock-users.spec.ts +44 -0
- package/test/matter-childbridge.spec.ts +55 -0
- package/test/matter-descriptors.spec.ts +97 -0
- package/test/matter-device-state.spec.ts +101 -0
- package/test/matter-integration.spec.ts +70 -0
- package/test/platform.integration.spec.ts +55 -0
- package/test/switchbot-client-debounce.spec.ts +131 -0
- package/test/switchbot-client-openapi.spec.ts +56 -0
- package/test/switchbotClient.spec.ts +10 -0
- package/test/utils.spec.ts +20 -0
- package/vitest.config.ts +7 -0
- package/coverage/base.css +0 -224
- package/coverage/block-navigation.js +0 -87
- package/coverage/clover.xml +0 -15847
- package/coverage/coverage-final.json +0 -42
- package/coverage/docs/assets/dmt/dmt-component-data.js.html +0 -85
- package/coverage/docs/assets/dmt/dmt-components.js.html +0 -286
- package/coverage/docs/assets/dmt/index.html +0 -131
- package/coverage/docs/assets/hierarchy.js.html +0 -85
- package/coverage/docs/assets/icons.js.html +0 -136
- package/coverage/docs/assets/index.html +0 -146
- package/coverage/docs/assets/main.js.html +0 -265
- package/coverage/favicon.png +0 -0
- package/coverage/index.html +0 -191
- package/coverage/prettify.css +0 -1
- package/coverage/prettify.js +0 -2
- package/coverage/sort-arrow-sprite.png +0 -0
- package/coverage/sorter.js +0 -196
- package/coverage/src/device/blindtilt.ts.html +0 -3238
- package/coverage/src/device/bot.ts.html +0 -2803
- package/coverage/src/device/ceilinglight.ts.html +0 -2338
- package/coverage/src/device/colorbulb.ts.html +0 -2824
- package/coverage/src/device/contact.ts.html +0 -1465
- package/coverage/src/device/curtain.ts.html +0 -2869
- package/coverage/src/device/device.ts.html +0 -2500
- package/coverage/src/device/fan.ts.html +0 -2242
- package/coverage/src/device/hub.ts.html +0 -1408
- package/coverage/src/device/humidifier.ts.html +0 -2116
- package/coverage/src/device/index.html +0 -416
- package/coverage/src/device/iosensor.ts.html +0 -1375
- package/coverage/src/device/lightstrip.ts.html +0 -2617
- package/coverage/src/device/lock.ts.html +0 -1963
- package/coverage/src/device/meter.ts.html +0 -1372
- package/coverage/src/device/meterplus.ts.html +0 -1384
- package/coverage/src/device/meterpro.ts.html +0 -1618
- package/coverage/src/device/motion.ts.html +0 -1264
- package/coverage/src/device/plug.ts.html +0 -1372
- package/coverage/src/device/relayswitch.ts.html +0 -2284
- package/coverage/src/device/robotvacuumcleaner.ts.html +0 -1810
- package/coverage/src/device/waterdetector.ts.html +0 -1294
- package/coverage/src/homebridge-ui/index.html +0 -116
- package/coverage/src/homebridge-ui/server.ts.html +0 -229
- package/coverage/src/index.html +0 -161
- package/coverage/src/index.ts.html +0 -124
- package/coverage/src/irdevice/airconditioner.ts.html +0 -1687
- package/coverage/src/irdevice/airpurifier.ts.html +0 -844
- package/coverage/src/irdevice/camera.ts.html +0 -475
- package/coverage/src/irdevice/fan.ts.html +0 -766
- package/coverage/src/irdevice/index.html +0 -251
- package/coverage/src/irdevice/irdevice.ts.html +0 -1117
- package/coverage/src/irdevice/light.ts.html +0 -826
- package/coverage/src/irdevice/other.ts.html +0 -2458
- package/coverage/src/irdevice/tv.ts.html +0 -1222
- package/coverage/src/irdevice/vacuumcleaner.ts.html +0 -466
- package/coverage/src/irdevice/waterheater.ts.html +0 -469
- package/coverage/src/platform.ts.html +0 -8776
- package/coverage/src/settings.ts.html +0 -934
- package/coverage/src/utils.ts.html +0 -2092
- package/dist/devices-hap/airpurifier.d.ts +0 -54
- package/dist/devices-hap/airpurifier.d.ts.map +0 -1
- package/dist/devices-hap/airpurifier.js +0 -527
- package/dist/devices-hap/airpurifier.js.map +0 -1
- package/dist/devices-hap/blindtilt.d.ts +0 -90
- package/dist/devices-hap/blindtilt.d.ts.map +0 -1
- package/dist/devices-hap/blindtilt.js +0 -974
- package/dist/devices-hap/blindtilt.js.map +0 -1
- package/dist/devices-hap/bot.d.ts +0 -102
- package/dist/devices-hap/bot.d.ts.map +0 -1
- package/dist/devices-hap/bot.js +0 -811
- package/dist/devices-hap/bot.js.map +0 -1
- package/dist/devices-hap/ceilinglight.d.ts +0 -85
- package/dist/devices-hap/ceilinglight.d.ts.map +0 -1
- package/dist/devices-hap/ceilinglight.js +0 -701
- package/dist/devices-hap/ceilinglight.js.map +0 -1
- package/dist/devices-hap/colorbulb.d.ts +0 -88
- package/dist/devices-hap/colorbulb.d.ts.map +0 -1
- package/dist/devices-hap/colorbulb.js +0 -881
- package/dist/devices-hap/colorbulb.js.map +0 -1
- package/dist/devices-hap/contact.d.ts +0 -44
- package/dist/devices-hap/contact.d.ts.map +0 -1
- package/dist/devices-hap/contact.js +0 -409
- package/dist/devices-hap/contact.js.map +0 -1
- package/dist/devices-hap/curtain.d.ts +0 -73
- package/dist/devices-hap/curtain.d.ts.map +0 -1
- package/dist/devices-hap/curtain.js +0 -869
- package/dist/devices-hap/curtain.js.map +0 -1
- package/dist/devices-hap/device.d.ts +0 -98
- package/dist/devices-hap/device.d.ts.map +0 -1
- package/dist/devices-hap/device.js +0 -749
- package/dist/devices-hap/device.js.map +0 -1
- package/dist/devices-hap/fan.d.ts +0 -69
- package/dist/devices-hap/fan.d.ts.map +0 -1
- package/dist/devices-hap/fan.js +0 -649
- package/dist/devices-hap/fan.js.map +0 -1
- package/dist/devices-hap/hub.d.ts +0 -37
- package/dist/devices-hap/hub.d.ts.map +0 -1
- package/dist/devices-hap/hub.js +0 -392
- package/dist/devices-hap/hub.js.map +0 -1
- package/dist/devices-hap/humidifier.d.ts +0 -68
- package/dist/devices-hap/humidifier.d.ts.map +0 -1
- package/dist/devices-hap/humidifier.js +0 -628
- package/dist/devices-hap/humidifier.js.map +0 -1
- package/dist/devices-hap/iosensor.d.ts +0 -42
- package/dist/devices-hap/iosensor.d.ts.map +0 -1
- package/dist/devices-hap/iosensor.js +0 -382
- package/dist/devices-hap/iosensor.js.map +0 -1
- package/dist/devices-hap/lightstrip.d.ts +0 -79
- package/dist/devices-hap/lightstrip.d.ts.map +0 -1
- package/dist/devices-hap/lightstrip.js +0 -797
- package/dist/devices-hap/lightstrip.js.map +0 -1
- package/dist/devices-hap/lock.d.ts +0 -53
- package/dist/devices-hap/lock.d.ts.map +0 -1
- package/dist/devices-hap/lock.js +0 -561
- package/dist/devices-hap/lock.js.map +0 -1
- package/dist/devices-hap/meter.d.ts +0 -37
- package/dist/devices-hap/meter.d.ts.map +0 -1
- package/dist/devices-hap/meter.js +0 -379
- package/dist/devices-hap/meter.js.map +0 -1
- package/dist/devices-hap/meterplus.d.ts +0 -42
- package/dist/devices-hap/meterplus.d.ts.map +0 -1
- package/dist/devices-hap/meterplus.js +0 -384
- package/dist/devices-hap/meterplus.js.map +0 -1
- package/dist/devices-hap/meterpro.d.ts +0 -43
- package/dist/devices-hap/meterpro.d.ts.map +0 -1
- package/dist/devices-hap/meterpro.js +0 -468
- package/dist/devices-hap/meterpro.js.map +0 -1
- package/dist/devices-hap/motion.d.ts +0 -42
- package/dist/devices-hap/motion.d.ts.map +0 -1
- package/dist/devices-hap/motion.js +0 -345
- package/dist/devices-hap/motion.js.map +0 -1
- package/dist/devices-hap/plug.d.ts +0 -49
- package/dist/devices-hap/plug.d.ts.map +0 -1
- package/dist/devices-hap/plug.js +0 -395
- package/dist/devices-hap/plug.js.map +0 -1
- package/dist/devices-hap/relayswitch.d.ts +0 -96
- package/dist/devices-hap/relayswitch.d.ts.map +0 -1
- package/dist/devices-hap/relayswitch.js +0 -642
- package/dist/devices-hap/relayswitch.js.map +0 -1
- package/dist/devices-hap/robotvacuumcleaner.d.ts +0 -54
- package/dist/devices-hap/robotvacuumcleaner.d.ts.map +0 -1
- package/dist/devices-hap/robotvacuumcleaner.js +0 -523
- package/dist/devices-hap/robotvacuumcleaner.js.map +0 -1
- package/dist/devices-hap/waterdetector.d.ts +0 -41
- package/dist/devices-hap/waterdetector.d.ts.map +0 -1
- package/dist/devices-hap/waterdetector.js +0 -356
- package/dist/devices-hap/waterdetector.js.map +0 -1
- package/dist/devices-matter/BaseMatterAccessory.d.ts +0 -63
- package/dist/devices-matter/BaseMatterAccessory.d.ts.map +0 -1
- package/dist/devices-matter/BaseMatterAccessory.js +0 -100
- package/dist/devices-matter/BaseMatterAccessory.js.map +0 -1
- package/dist/devices-matter/ColorLightAccessory.d.ts +0 -20
- package/dist/devices-matter/ColorLightAccessory.d.ts.map +0 -1
- package/dist/devices-matter/ColorLightAccessory.js +0 -95
- package/dist/devices-matter/ColorLightAccessory.js.map +0 -1
- package/dist/devices-matter/ColorTemperatureLightAccessory.d.ts +0 -18
- package/dist/devices-matter/ColorTemperatureLightAccessory.d.ts.map +0 -1
- package/dist/devices-matter/ColorTemperatureLightAccessory.js +0 -78
- package/dist/devices-matter/ColorTemperatureLightAccessory.js.map +0 -1
- package/dist/devices-matter/ContactSensorAccessory.d.ts +0 -12
- package/dist/devices-matter/ContactSensorAccessory.d.ts.map +0 -1
- package/dist/devices-matter/ContactSensorAccessory.js +0 -34
- package/dist/devices-matter/ContactSensorAccessory.js.map +0 -1
- package/dist/devices-matter/DimmableLightAccessory.d.ts +0 -58
- package/dist/devices-matter/DimmableLightAccessory.d.ts.map +0 -1
- package/dist/devices-matter/DimmableLightAccessory.js +0 -167
- package/dist/devices-matter/DimmableLightAccessory.js.map +0 -1
- package/dist/devices-matter/DoorLockAccessory.d.ts +0 -14
- package/dist/devices-matter/DoorLockAccessory.d.ts.map +0 -1
- package/dist/devices-matter/DoorLockAccessory.js +0 -50
- package/dist/devices-matter/DoorLockAccessory.js.map +0 -1
- package/dist/devices-matter/ExtendedColorLightAccessory.d.ts +0 -21
- package/dist/devices-matter/ExtendedColorLightAccessory.d.ts.map +0 -1
- package/dist/devices-matter/ExtendedColorLightAccessory.js +0 -107
- package/dist/devices-matter/ExtendedColorLightAccessory.js.map +0 -1
- package/dist/devices-matter/FanAccessory.d.ts +0 -16
- package/dist/devices-matter/FanAccessory.d.ts.map +0 -1
- package/dist/devices-matter/FanAccessory.js +0 -81
- package/dist/devices-matter/FanAccessory.js.map +0 -1
- package/dist/devices-matter/HumiditySensorAccessory.d.ts +0 -12
- package/dist/devices-matter/HumiditySensorAccessory.d.ts.map +0 -1
- package/dist/devices-matter/HumiditySensorAccessory.js +0 -34
- package/dist/devices-matter/HumiditySensorAccessory.js.map +0 -1
- package/dist/devices-matter/LeakSensorAccessory.d.ts +0 -12
- package/dist/devices-matter/LeakSensorAccessory.d.ts.map +0 -1
- package/dist/devices-matter/LeakSensorAccessory.js +0 -33
- package/dist/devices-matter/LeakSensorAccessory.js.map +0 -1
- package/dist/devices-matter/LightSensorAccessory.d.ts +0 -12
- package/dist/devices-matter/LightSensorAccessory.d.ts.map +0 -1
- package/dist/devices-matter/LightSensorAccessory.js +0 -34
- package/dist/devices-matter/LightSensorAccessory.js.map +0 -1
- package/dist/devices-matter/OccupancySensorAccessory.d.ts +0 -12
- package/dist/devices-matter/OccupancySensorAccessory.d.ts.map +0 -1
- package/dist/devices-matter/OccupancySensorAccessory.js +0 -39
- package/dist/devices-matter/OccupancySensorAccessory.js.map +0 -1
- package/dist/devices-matter/OnOffLightAccessory.d.ts +0 -38
- package/dist/devices-matter/OnOffLightAccessory.d.ts.map +0 -1
- package/dist/devices-matter/OnOffLightAccessory.js +0 -118
- package/dist/devices-matter/OnOffLightAccessory.js.map +0 -1
- package/dist/devices-matter/OnOffOutletAccessory.d.ts +0 -12
- package/dist/devices-matter/OnOffOutletAccessory.d.ts.map +0 -1
- package/dist/devices-matter/OnOffOutletAccessory.js +0 -40
- package/dist/devices-matter/OnOffOutletAccessory.js.map +0 -1
- package/dist/devices-matter/OnOffSwitchAccessory.d.ts +0 -14
- package/dist/devices-matter/OnOffSwitchAccessory.d.ts.map +0 -1
- package/dist/devices-matter/OnOffSwitchAccessory.js +0 -42
- package/dist/devices-matter/OnOffSwitchAccessory.js.map +0 -1
- package/dist/devices-matter/RoboticVacuumAccessory.d.ts +0 -68
- package/dist/devices-matter/RoboticVacuumAccessory.d.ts.map +0 -1
- package/dist/devices-matter/RoboticVacuumAccessory.js +0 -334
- package/dist/devices-matter/RoboticVacuumAccessory.js.map +0 -1
- package/dist/devices-matter/SmokeCOAlarmAccessory.d.ts +0 -11
- package/dist/devices-matter/SmokeCOAlarmAccessory.d.ts.map +0 -1
- package/dist/devices-matter/SmokeCOAlarmAccessory.js +0 -49
- package/dist/devices-matter/SmokeCOAlarmAccessory.js.map +0 -1
- package/dist/devices-matter/TemperatureSensorAccessory.d.ts +0 -12
- package/dist/devices-matter/TemperatureSensorAccessory.d.ts.map +0 -1
- package/dist/devices-matter/TemperatureSensorAccessory.js +0 -36
- package/dist/devices-matter/TemperatureSensorAccessory.js.map +0 -1
- package/dist/devices-matter/ThermostatAccessory.d.ts +0 -19
- package/dist/devices-matter/ThermostatAccessory.d.ts.map +0 -1
- package/dist/devices-matter/ThermostatAccessory.js +0 -95
- package/dist/devices-matter/ThermostatAccessory.js.map +0 -1
- package/dist/devices-matter/VenetianBlindAccessory.d.ts +0 -19
- package/dist/devices-matter/VenetianBlindAccessory.d.ts.map +0 -1
- package/dist/devices-matter/VenetianBlindAccessory.js +0 -99
- package/dist/devices-matter/VenetianBlindAccessory.js.map +0 -1
- package/dist/devices-matter/WindowBlindAccessory.d.ts +0 -17
- package/dist/devices-matter/WindowBlindAccessory.d.ts.map +0 -1
- package/dist/devices-matter/WindowBlindAccessory.js +0 -80
- package/dist/devices-matter/WindowBlindAccessory.js.map +0 -1
- package/dist/devices-matter/custom/PowerStripAccessory.d.ts +0 -97
- package/dist/devices-matter/custom/PowerStripAccessory.d.ts.map +0 -1
- package/dist/devices-matter/custom/PowerStripAccessory.js +0 -265
- package/dist/devices-matter/custom/PowerStripAccessory.js.map +0 -1
- package/dist/devices-matter/custom/index.d.ts +0 -8
- package/dist/devices-matter/custom/index.d.ts.map +0 -1
- package/dist/devices-matter/custom/index.js +0 -8
- package/dist/devices-matter/custom/index.js.map +0 -1
- package/dist/devices-matter/index.d.ts +0 -29
- package/dist/devices-matter/index.d.ts.map +0 -1
- package/dist/devices-matter/index.js +0 -28
- package/dist/devices-matter/index.js.map +0 -1
- package/dist/index.test.d.ts +0 -2
- package/dist/index.test.d.ts.map +0 -1
- package/dist/index.test.js +0 -14
- package/dist/index.test.js.map +0 -1
- package/dist/irdevice/airconditioner.d.ts +0 -61
- package/dist/irdevice/airconditioner.d.ts.map +0 -1
- package/dist/irdevice/airconditioner.js +0 -472
- package/dist/irdevice/airconditioner.js.map +0 -1
- package/dist/irdevice/airpurifier.d.ts +0 -50
- package/dist/irdevice/airpurifier.d.ts.map +0 -1
- package/dist/irdevice/airpurifier.js +0 -213
- package/dist/irdevice/airpurifier.js.map +0 -1
- package/dist/irdevice/camera.d.ts +0 -32
- package/dist/irdevice/camera.d.ts.map +0 -1
- package/dist/irdevice/camera.js +0 -107
- package/dist/irdevice/camera.js.map +0 -1
- package/dist/irdevice/fan.d.ts +0 -36
- package/dist/irdevice/fan.d.ts.map +0 -1
- package/dist/irdevice/fan.js +0 -200
- package/dist/irdevice/fan.js.map +0 -1
- package/dist/irdevice/irdevice.d.ts +0 -68
- package/dist/irdevice/irdevice.d.ts.map +0 -1
- package/dist/irdevice/irdevice.js +0 -298
- package/dist/irdevice/irdevice.js.map +0 -1
- package/dist/irdevice/light.d.ts +0 -36
- package/dist/irdevice/light.d.ts.map +0 -1
- package/dist/irdevice/light.js +0 -206
- package/dist/irdevice/light.js.map +0 -1
- package/dist/irdevice/other.d.ts +0 -57
- package/dist/irdevice/other.d.ts.map +0 -1
- package/dist/irdevice/other.js +0 -778
- package/dist/irdevice/other.js.map +0 -1
- package/dist/irdevice/tv.d.ts +0 -45
- package/dist/irdevice/tv.d.ts.map +0 -1
- package/dist/irdevice/tv.js +0 -327
- package/dist/irdevice/tv.js.map +0 -1
- package/dist/irdevice/vacuumcleaner.d.ts +0 -28
- package/dist/irdevice/vacuumcleaner.d.ts.map +0 -1
- package/dist/irdevice/vacuumcleaner.js +0 -104
- package/dist/irdevice/vacuumcleaner.js.map +0 -1
- package/dist/irdevice/waterheater.d.ts +0 -30
- package/dist/irdevice/waterheater.d.ts.map +0 -1
- package/dist/irdevice/waterheater.js +0 -105
- package/dist/irdevice/waterheater.js.map +0 -1
- package/dist/platform-hap.d.ts +0 -149
- package/dist/platform-hap.d.ts.map +0 -1
- package/dist/platform-hap.js +0 -2861
- package/dist/platform-hap.js.map +0 -1
- package/dist/platform-matter.d.ts +0 -120
- package/dist/platform-matter.d.ts.map +0 -1
- package/dist/platform-matter.js +0 -966
- package/dist/platform-matter.js.map +0 -1
- package/dist/verifyconfig.test.d.ts +0 -2
- package/dist/verifyconfig.test.d.ts.map +0 -1
- package/dist/verifyconfig.test.js +0 -167
- package/dist/verifyconfig.test.js.map +0 -1
- package/src/custom.d.ts +0 -7
- package/src/devices-hap/airpurifier.ts +0 -563
- package/src/devices-hap/blindtilt.ts +0 -1049
- package/src/devices-hap/bot.ts +0 -900
- package/src/devices-hap/ceilinglight.ts +0 -742
- package/src/devices-hap/colorbulb.ts +0 -904
- package/src/devices-hap/contact.ts +0 -457
- package/src/devices-hap/curtain.ts +0 -944
- package/src/devices-hap/device.ts +0 -811
- package/src/devices-hap/fan.ts +0 -711
- package/src/devices-hap/hub.ts +0 -439
- package/src/devices-hap/humidifier.ts +0 -669
- package/src/devices-hap/iosensor.ts +0 -427
- package/src/devices-hap/lightstrip.ts +0 -836
- package/src/devices-hap/lock.ts +0 -620
- package/src/devices-hap/meter.ts +0 -426
- package/src/devices-hap/meterplus.ts +0 -430
- package/src/devices-hap/meterpro.ts +0 -522
- package/src/devices-hap/motion.ts +0 -390
- package/src/devices-hap/plug.ts +0 -423
- package/src/devices-hap/relayswitch.ts +0 -727
- package/src/devices-hap/robotvacuumcleaner.ts +0 -568
- package/src/devices-hap/waterdetector.ts +0 -400
- package/src/devices-matter/BaseMatterAccessory.ts +0 -131
- package/src/devices-matter/ColorLightAccessory.ts +0 -110
- package/src/devices-matter/ColorTemperatureLightAccessory.ts +0 -92
- package/src/devices-matter/ContactSensorAccessory.ts +0 -41
- package/src/devices-matter/DimmableLightAccessory.ts +0 -192
- package/src/devices-matter/DoorLockAccessory.ts +0 -60
- package/src/devices-matter/ExtendedColorLightAccessory.ts +0 -123
- package/src/devices-matter/FanAccessory.ts +0 -95
- package/src/devices-matter/HumiditySensorAccessory.ts +0 -41
- package/src/devices-matter/LeakSensorAccessory.ts +0 -40
- package/src/devices-matter/LightSensorAccessory.ts +0 -41
- package/src/devices-matter/OccupancySensorAccessory.ts +0 -48
- package/src/devices-matter/OnOffLightAccessory.ts +0 -133
- package/src/devices-matter/OnOffOutletAccessory.ts +0 -46
- package/src/devices-matter/OnOffSwitchAccessory.ts +0 -51
- package/src/devices-matter/RoboticVacuumAccessory.ts +0 -407
- package/src/devices-matter/SmokeCOAlarmAccessory.ts +0 -59
- package/src/devices-matter/TemperatureSensorAccessory.ts +0 -43
- package/src/devices-matter/ThermostatAccessory.ts +0 -110
- package/src/devices-matter/VenetianBlindAccessory.ts +0 -115
- package/src/devices-matter/WindowBlindAccessory.ts +0 -92
- package/src/devices-matter/custom/PowerStripAccessory.ts +0 -309
- package/src/devices-matter/custom/index.ts +0 -8
- package/src/devices-matter/index.ts +0 -29
- package/src/index.test.ts +0 -19
- package/src/irdevice/airconditioner.ts +0 -533
- package/src/irdevice/airpurifier.ts +0 -252
- package/src/irdevice/camera.ts +0 -129
- package/src/irdevice/fan.ts +0 -226
- package/src/irdevice/irdevice.ts +0 -344
- package/src/irdevice/light.ts +0 -246
- package/src/irdevice/other.ts +0 -790
- package/src/irdevice/tv.ts +0 -378
- package/src/irdevice/vacuumcleaner.ts +0 -126
- package/src/irdevice/waterheater.ts +0 -127
- package/src/platform-hap.ts +0 -2997
- package/src/platform-matter.ts +0 -1092
- package/src/verifyconfig.test.ts +0 -197
|
@@ -1,400 +0,0 @@
|
|
|
1
|
-
/* Copyright(C) 2021-2024, donavanbecker (https://github.com/donavanbecker). All rights reserved.
|
|
2
|
-
*
|
|
3
|
-
* waterdetector.ts: @switchbot/homebridge-switchbot.
|
|
4
|
-
*/
|
|
5
|
-
import type { CharacteristicValue, PlatformAccessory, Service } from 'homebridge'
|
|
6
|
-
import type { device, SwitchBotBLE, waterLeakDetectorServiceData, waterLeakDetectorStatus, waterLeakDetectorWebhookContext } from 'node-switchbot'
|
|
7
|
-
|
|
8
|
-
import type { SwitchBotHAPPlatform } from '../platform-hap.js'
|
|
9
|
-
import type { devicesConfig, waterDetectorConfig } from '../settings.js'
|
|
10
|
-
|
|
11
|
-
/*
|
|
12
|
-
* For Testing Locally:
|
|
13
|
-
* import { SwitchBotBLEModel, SwitchBotBLEModelName } from '/Users/Shared/GitHub/OpenWonderLabs/node-switchbot/dist/index.js';
|
|
14
|
-
*/
|
|
15
|
-
import { SwitchBotBLEModel, SwitchBotBLEModelName } from 'node-switchbot'
|
|
16
|
-
import { interval, skipWhile, Subject } from 'rxjs'
|
|
17
|
-
|
|
18
|
-
import { formatDeviceIdAsMac } from '../utils.js'
|
|
19
|
-
import { deviceBase } from './device.js'
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Platform Accessory
|
|
23
|
-
* An instance of this class is created for each accessory your platform registers
|
|
24
|
-
* Each accessory may expose multiple services of different service types.
|
|
25
|
-
*/
|
|
26
|
-
export class WaterDetector extends deviceBase {
|
|
27
|
-
// Services
|
|
28
|
-
private Battery: {
|
|
29
|
-
Name: CharacteristicValue
|
|
30
|
-
Service: Service
|
|
31
|
-
BatteryLevel: CharacteristicValue
|
|
32
|
-
StatusLowBattery: CharacteristicValue
|
|
33
|
-
ChargingState: CharacteristicValue
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
private LeakSensor?: {
|
|
37
|
-
Name: CharacteristicValue
|
|
38
|
-
Service: Service
|
|
39
|
-
StatusActive: CharacteristicValue
|
|
40
|
-
LeakDetected: CharacteristicValue
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// OpenAPI
|
|
44
|
-
deviceStatus!: waterLeakDetectorStatus
|
|
45
|
-
|
|
46
|
-
// Webhook
|
|
47
|
-
webhookContext!: waterLeakDetectorWebhookContext
|
|
48
|
-
|
|
49
|
-
// BLE
|
|
50
|
-
serviceData!: waterLeakDetectorServiceData
|
|
51
|
-
|
|
52
|
-
// Updates
|
|
53
|
-
WaterDetectorUpdateInProgress!: boolean
|
|
54
|
-
doWaterDetectorUpdate: Subject<void>
|
|
55
|
-
|
|
56
|
-
constructor(
|
|
57
|
-
readonly platform: SwitchBotHAPPlatform,
|
|
58
|
-
accessory: PlatformAccessory,
|
|
59
|
-
device: device & devicesConfig,
|
|
60
|
-
) {
|
|
61
|
-
super(platform, accessory, device)
|
|
62
|
-
// Set category
|
|
63
|
-
accessory.category = this.hap.Categories.SENSOR
|
|
64
|
-
|
|
65
|
-
// this is subject we use to track when we need to POST changes to the SwitchBot API
|
|
66
|
-
this.doWaterDetectorUpdate = new Subject()
|
|
67
|
-
this.WaterDetectorUpdateInProgress = false
|
|
68
|
-
|
|
69
|
-
// Initialize Battery Service
|
|
70
|
-
accessory.context.Battery = accessory.context.Battery ?? {}
|
|
71
|
-
this.Battery = {
|
|
72
|
-
Name: `${accessory.displayName} Battery`,
|
|
73
|
-
Service: accessory.getService(this.hap.Service.Battery) ?? accessory.addService(this.hap.Service.Battery) as Service,
|
|
74
|
-
BatteryLevel: accessory.context.BatteryLevel ?? 100,
|
|
75
|
-
StatusLowBattery: accessory.context.StatusLowBattery ?? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,
|
|
76
|
-
ChargingState: accessory.context.ChargingState ?? this.hap.Characteristic.ChargingState.NOT_CHARGEABLE,
|
|
77
|
-
}
|
|
78
|
-
accessory.context.Battery = this.Battery as object
|
|
79
|
-
|
|
80
|
-
// Initialize Battery Characteristic
|
|
81
|
-
this.Battery.Service.setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name).setCharacteristic(this.hap.Characteristic.ChargingState, this.hap.Characteristic.ChargingState.NOT_CHARGEABLE).getCharacteristic(this.hap.Characteristic.BatteryLevel).onGet(() => {
|
|
82
|
-
return this.Battery.StatusLowBattery
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
this.Battery.Service.getCharacteristic(this.hap.Characteristic.StatusLowBattery).onGet(() => {
|
|
86
|
-
return this.Battery.StatusLowBattery
|
|
87
|
-
})
|
|
88
|
-
|
|
89
|
-
// Initialize Leak Sensor Service
|
|
90
|
-
if ((device as waterDetectorConfig).hide_leak) {
|
|
91
|
-
if (this.LeakSensor) {
|
|
92
|
-
this.debugLog('Removing Leak Sensor Service')
|
|
93
|
-
this.LeakSensor.Service = this.accessory.getService(this.hap.Service.LeakSensor) as Service
|
|
94
|
-
accessory.removeService(this.LeakSensor.Service)
|
|
95
|
-
} else {
|
|
96
|
-
this.debugLog('Leak Sensor Service Not Found')
|
|
97
|
-
}
|
|
98
|
-
} else {
|
|
99
|
-
accessory.context.LeakSensor = accessory.context.LeakSensor ?? {}
|
|
100
|
-
this.LeakSensor = {
|
|
101
|
-
Name: `${accessory.displayName} Leak Sensor`,
|
|
102
|
-
Service: accessory.getService(this.hap.Service.LeakSensor) ?? this.accessory.addService(this.hap.Service.LeakSensor) as Service,
|
|
103
|
-
StatusActive: accessory.context.StatusActive ?? false,
|
|
104
|
-
LeakDetected: accessory.context.LeakDetected ?? this.hap.Characteristic.LeakDetected.LEAK_NOT_DETECTED,
|
|
105
|
-
}
|
|
106
|
-
accessory.context.LeakSensor = this.LeakSensor as object
|
|
107
|
-
|
|
108
|
-
// Initialize LeakSensor Characteristic
|
|
109
|
-
this.LeakSensor.Service.setCharacteristic(this.hap.Characteristic.Name, this.LeakSensor.Name).setCharacteristic(this.hap.Characteristic.StatusActive, true)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Retrieve initial values and updateHomekit
|
|
113
|
-
try {
|
|
114
|
-
this.debugLog('Retrieve initial values and update Homekit')
|
|
115
|
-
this.refreshStatus()
|
|
116
|
-
} catch (e: any) {
|
|
117
|
-
this.errorLog(`failed to retrieve initial values and update Homekit, Error: ${e.message ?? e}`)
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// regisiter webhook event handler if enabled
|
|
121
|
-
try {
|
|
122
|
-
this.debugLog('Registering Webhook Event Handler')
|
|
123
|
-
this.registerWebhook()
|
|
124
|
-
} catch (e: any) {
|
|
125
|
-
this.errorLog(`failed to registerWebhook, Error: ${e.message ?? e}`)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// regisiter platform BLE event handler if enabled
|
|
129
|
-
try {
|
|
130
|
-
this.debugLog('Registering Platform BLE Event Handler')
|
|
131
|
-
this.registerPlatformBLE()
|
|
132
|
-
} catch (e: any) {
|
|
133
|
-
this.errorLog(`failed to registerPlatformBLE, Error: ${e.message ?? e}`)
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
// Start an update interval
|
|
137
|
-
interval(this.deviceRefreshRate * 1000)
|
|
138
|
-
.pipe(skipWhile(() => this.WaterDetectorUpdateInProgress))
|
|
139
|
-
.subscribe(async () => {
|
|
140
|
-
this.debugLog(`update interval: ${this.deviceRefreshRate * 1000} seconds`)
|
|
141
|
-
await this.refreshStatus()
|
|
142
|
-
})
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
async BLEparseStatus(): Promise<void> {
|
|
146
|
-
this.debugLog('BLEparseStatus')
|
|
147
|
-
this.debugLog(`(leak, tampered, battery) = BLE: (${this.serviceData.leak}, ${this.serviceData.tampered}, ${this.serviceData.battery}), current:(${this.LeakSensor?.LeakDetected}, ${this.LeakSensor?.StatusActive}, ${this.Battery.BatteryLevel})`)
|
|
148
|
-
|
|
149
|
-
// LeakSensor
|
|
150
|
-
if (!(this.device as waterDetectorConfig).hide_leak && this.LeakSensor?.Service) {
|
|
151
|
-
// StatusActive
|
|
152
|
-
this.LeakSensor.StatusActive = this.serviceData.tampered
|
|
153
|
-
this.debugLog(`StatusActive: ${this.LeakSensor.StatusActive}`)
|
|
154
|
-
|
|
155
|
-
// LeakDetected
|
|
156
|
-
this.LeakSensor.LeakDetected = (this.device as waterDetectorConfig).dry
|
|
157
|
-
? !this.serviceData.leak ? this.hap.Characteristic.LeakDetected.LEAK_DETECTED : this.hap.Characteristic.LeakDetected.LEAK_NOT_DETECTED
|
|
158
|
-
: this.serviceData.leak ? this.hap.Characteristic.LeakDetected.LEAK_DETECTED : this.hap.Characteristic.LeakDetected.LEAK_NOT_DETECTED
|
|
159
|
-
this.LeakSensor.LeakDetected === this.hap.Characteristic.LeakDetected.LEAK_DETECTED ? this.warnLog(`LeakDetected: ${this.LeakSensor.LeakDetected}, dry: ${(this.device as waterDetectorConfig).dry}, BLE`) : this.debugLog(`LeakDetected: ${this.LeakSensor.LeakDetected}, dry: ${(this.device as waterDetectorConfig).dry}, BLE`)
|
|
160
|
-
}
|
|
161
|
-
// Battery Info
|
|
162
|
-
if ('battery' in this.serviceData) {
|
|
163
|
-
// BatteryLevel
|
|
164
|
-
this.Battery.BatteryLevel = this.serviceData.battery
|
|
165
|
-
this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`)
|
|
166
|
-
// StatusLowBattery
|
|
167
|
-
this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
|
|
168
|
-
? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW
|
|
169
|
-
: this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL
|
|
170
|
-
this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`)
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
async openAPIparseStatus(): Promise<void> {
|
|
175
|
-
this.debugLog('openAPIparseStatus')
|
|
176
|
-
this.debugLog(`(status, battery) = OpenAPI: (${this.deviceStatus.status}, ${this.deviceStatus.battery}), current:(${this.LeakSensor?.LeakDetected}, ${this.Battery.BatteryLevel})`)
|
|
177
|
-
|
|
178
|
-
// LeakSensor
|
|
179
|
-
if (!(this.device as waterDetectorConfig).hide_leak && this.LeakSensor?.Service) {
|
|
180
|
-
// StatusActive
|
|
181
|
-
this.LeakSensor.StatusActive = this.deviceStatus.battery !== 0
|
|
182
|
-
this.debugLog(`StatusActive: ${this.LeakSensor.StatusActive}`)
|
|
183
|
-
|
|
184
|
-
// LeakDetected
|
|
185
|
-
this.LeakSensor.LeakDetected = (this.device as waterDetectorConfig).dry
|
|
186
|
-
? this.deviceStatus.status === 0 ? this.hap.Characteristic.LeakDetected.LEAK_DETECTED : this.hap.Characteristic.LeakDetected.LEAK_NOT_DETECTED
|
|
187
|
-
: this.deviceStatus.status === 1 ? this.hap.Characteristic.LeakDetected.LEAK_DETECTED : this.hap.Characteristic.LeakDetected.LEAK_NOT_DETECTED
|
|
188
|
-
this.LeakSensor.LeakDetected === this.hap.Characteristic.LeakDetected.LEAK_DETECTED ? this.warnLog(`LeakDetected: ${this.LeakSensor.LeakDetected}, dry: ${(this.device as waterDetectorConfig).dry}, OpenAPI`) : this.debugLog(`LeakDetected: ${this.LeakSensor.LeakDetected}, dry: ${(this.device as waterDetectorConfig).dry}, OpenAPI`)
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
// BatteryLevel
|
|
192
|
-
this.Battery.BatteryLevel = this.deviceStatus.battery
|
|
193
|
-
this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`)
|
|
194
|
-
|
|
195
|
-
// StatusLowBattery
|
|
196
|
-
this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
|
|
197
|
-
? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW
|
|
198
|
-
: this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL
|
|
199
|
-
this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`)
|
|
200
|
-
|
|
201
|
-
// FirmwareVersion
|
|
202
|
-
if (this.deviceStatus.version) {
|
|
203
|
-
const version = this.deviceStatus.version.toString()
|
|
204
|
-
this.debugLog(`FirmwareVersion: ${version.replace(/^V|-.*$/g, '')}`)
|
|
205
|
-
const deviceVersion = version.replace(/^V|-.*$/g, '') ?? '0.0.0'
|
|
206
|
-
this.accessory
|
|
207
|
-
.getService(this.hap.Service.AccessoryInformation)!
|
|
208
|
-
.setCharacteristic(this.hap.Characteristic.HardwareRevision, deviceVersion)
|
|
209
|
-
.setCharacteristic(this.hap.Characteristic.FirmwareRevision, deviceVersion)
|
|
210
|
-
.getCharacteristic(this.hap.Characteristic.FirmwareRevision)
|
|
211
|
-
.updateValue(deviceVersion)
|
|
212
|
-
this.accessory.context.version = deviceVersion
|
|
213
|
-
this.debugSuccessLog(`version: ${this.accessory.context.version}`)
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
async parseStatusWebhook(): Promise<void> {
|
|
218
|
-
this.debugLog('parseStatusWebhook')
|
|
219
|
-
this.debugLog(`(detectionState, battery) = Webhook: (${this.webhookContext.detectionState}, ${this.webhookContext.battery}), current:(${this.LeakSensor?.LeakDetected}, ${this.Battery.BatteryLevel})`)
|
|
220
|
-
|
|
221
|
-
// LeakSensor
|
|
222
|
-
if (!(this.device as waterDetectorConfig).hide_leak && this.LeakSensor?.Service) {
|
|
223
|
-
// StatusActive
|
|
224
|
-
this.LeakSensor.StatusActive = !!this.webhookContext.detectionState
|
|
225
|
-
this.debugLog(`StatusActive: ${this.LeakSensor.StatusActive}`)
|
|
226
|
-
|
|
227
|
-
// LeakDetected
|
|
228
|
-
this.LeakSensor.LeakDetected = (this.device as waterDetectorConfig).dry
|
|
229
|
-
? this.webhookContext.detectionState === 0 ? this.hap.Characteristic.LeakDetected.LEAK_DETECTED : this.hap.Characteristic.LeakDetected.LEAK_NOT_DETECTED
|
|
230
|
-
: this.webhookContext.detectionState === 1 ? this.hap.Characteristic.LeakDetected.LEAK_DETECTED : this.hap.Characteristic.LeakDetected.LEAK_NOT_DETECTED
|
|
231
|
-
this.LeakSensor.LeakDetected === this.hap.Characteristic.LeakDetected.LEAK_DETECTED ? this.warnLog(`LeakDetected: ${this.LeakSensor.LeakDetected}, dry: ${(this.device as waterDetectorConfig).dry}, Webhook`) : this.debugLog(`LeakDetected: ${this.LeakSensor.LeakDetected}, dry: ${(this.device as waterDetectorConfig).dry}, Webhook`)
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// BatteryLevel
|
|
235
|
-
this.Battery.BatteryLevel = this.webhookContext.battery
|
|
236
|
-
this.debugLog(`BatteryLevel: ${this.Battery.BatteryLevel}`)
|
|
237
|
-
|
|
238
|
-
// StatusLowBattery
|
|
239
|
-
this.Battery.StatusLowBattery = this.Battery.BatteryLevel < 10
|
|
240
|
-
? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW
|
|
241
|
-
: this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL
|
|
242
|
-
this.debugLog(`StatusLowBattery: ${this.Battery.StatusLowBattery}`)
|
|
243
|
-
}
|
|
244
|
-
|
|
245
|
-
/**
|
|
246
|
-
* Asks the SwitchBot API for the latest device information
|
|
247
|
-
*/
|
|
248
|
-
async refreshStatus(): Promise<void> {
|
|
249
|
-
if (this.BLE) {
|
|
250
|
-
await this.BLERefreshStatus()
|
|
251
|
-
} else if (this.OpenAPI && this.platform.config.credentials?.token) {
|
|
252
|
-
await this.openAPIRefreshStatus()
|
|
253
|
-
} else {
|
|
254
|
-
await this.offlineOff()
|
|
255
|
-
this.debugWarnLog(`Connection Type: ${this.device.connectionType}, refreshStatus will not happen.`)
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
async BLERefreshStatus(): Promise<void> {
|
|
260
|
-
this.debugLog('BLERefreshStatus')
|
|
261
|
-
const switchBotBLE = await this.switchbotBLE()
|
|
262
|
-
if (switchBotBLE === undefined) {
|
|
263
|
-
await this.BLERefreshConnection(switchBotBLE)
|
|
264
|
-
} else {
|
|
265
|
-
// Start to monitor advertisement packets
|
|
266
|
-
(async () => {
|
|
267
|
-
// Start to monitor advertisement packets
|
|
268
|
-
const serviceData = await this.monitorAdvertisementPackets(switchBotBLE) as waterLeakDetectorServiceData
|
|
269
|
-
// Update HomeKit
|
|
270
|
-
if (serviceData.model === SwitchBotBLEModel.Leak && serviceData.modelName === SwitchBotBLEModelName.Leak) {
|
|
271
|
-
this.serviceData = serviceData
|
|
272
|
-
if (serviceData !== undefined || serviceData !== null) {
|
|
273
|
-
await this.BLEparseStatus()
|
|
274
|
-
await this.updateHomeKitCharacteristics()
|
|
275
|
-
} else {
|
|
276
|
-
this.errorLog(`serviceData is either undefined or null, serviceData: ${JSON.stringify(serviceData)}`)
|
|
277
|
-
await this.BLERefreshConnection(switchBotBLE)
|
|
278
|
-
}
|
|
279
|
-
} else {
|
|
280
|
-
this.errorLog(`failed to get serviceData, serviceData: ${JSON.stringify(serviceData)}`)
|
|
281
|
-
await this.BLERefreshConnection(switchBotBLE)
|
|
282
|
-
}
|
|
283
|
-
})()
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
async registerPlatformBLE(): Promise<void> {
|
|
288
|
-
this.debugLog('registerPlatformBLE')
|
|
289
|
-
if (this.config.options?.BLE && !this.device.disablePlatformBLE) {
|
|
290
|
-
this.debugLog('is listening to Platform BLE.')
|
|
291
|
-
try {
|
|
292
|
-
const formattedDeviceId = formatDeviceIdAsMac(this.device.deviceId)
|
|
293
|
-
this.device.bleMac = formattedDeviceId
|
|
294
|
-
this.debugLog(`bleMac: ${this.device.bleMac}`)
|
|
295
|
-
this.platform.bleEventHandler[this.device.bleMac] = async (context: waterLeakDetectorServiceData) => {
|
|
296
|
-
try {
|
|
297
|
-
this.serviceData = context
|
|
298
|
-
if (context !== undefined || context !== null) {
|
|
299
|
-
this.debugLog(`received BLE: ${JSON.stringify(context)}`)
|
|
300
|
-
await this.BLEparseStatus()
|
|
301
|
-
await this.updateHomeKitCharacteristics()
|
|
302
|
-
} else {
|
|
303
|
-
this.errorLog(`context is either undefined or null, context: ${JSON.stringify(context)}`)
|
|
304
|
-
await this.BLERefreshConnection(context)
|
|
305
|
-
}
|
|
306
|
-
} catch (e: any) {
|
|
307
|
-
this.errorLog(`failed to handle BLE. Received: ${JSON.stringify(context)} Error: ${e.message ?? e}`)
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
} catch (error) {
|
|
311
|
-
this.errorLog(`failed to format device ID as MAC, Error: ${error}`)
|
|
312
|
-
}
|
|
313
|
-
} else {
|
|
314
|
-
this.debugLog('is not listening to Platform BLE')
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
async openAPIRefreshStatus(): Promise<void> {
|
|
319
|
-
this.debugLog('openAPIRefreshStatus')
|
|
320
|
-
try {
|
|
321
|
-
const deviceStatus = await this.deviceRefreshStatus<waterLeakDetectorStatus>()
|
|
322
|
-
this.debugLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
|
|
323
|
-
if (await this.successfulStatusCodes(deviceStatus)) {
|
|
324
|
-
this.debugSuccessLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
|
|
325
|
-
this.deviceStatus = deviceStatus.body
|
|
326
|
-
await this.openAPIparseStatus()
|
|
327
|
-
await this.updateHomeKitCharacteristics()
|
|
328
|
-
} else {
|
|
329
|
-
this.debugWarnLog(`statusCode: ${deviceStatus.statusCode}, deviceStatus: ${JSON.stringify(deviceStatus)}`)
|
|
330
|
-
}
|
|
331
|
-
} catch (e: any) {
|
|
332
|
-
await this.apiError(e)
|
|
333
|
-
this.errorLog(`failed openAPIRefreshStatus with ${this.device.connectionType} Connection, Error Message: ${JSON.stringify(e.message)}`)
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
|
|
337
|
-
async registerWebhook() {
|
|
338
|
-
if (this.device.webhook) {
|
|
339
|
-
this.debugLog('is listening webhook.')
|
|
340
|
-
this.platform.webhookEventHandler[this.device.deviceId] = async (context: waterLeakDetectorWebhookContext) => {
|
|
341
|
-
try {
|
|
342
|
-
this.webhookContext = context
|
|
343
|
-
if (context !== undefined || context !== null) {
|
|
344
|
-
this.debugLog(`received Webhook: ${JSON.stringify(context)}`)
|
|
345
|
-
await this.parseStatusWebhook()
|
|
346
|
-
await this.updateHomeKitCharacteristics()
|
|
347
|
-
} else {
|
|
348
|
-
this.errorLog(`context is either undefined or null, context: ${JSON.stringify(context)}`)
|
|
349
|
-
}
|
|
350
|
-
} catch (e: any) {
|
|
351
|
-
this.errorLog(`failed to handle webhook. Received: ${JSON.stringify(context)} Error: ${e.message ?? e}`)
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
} else {
|
|
355
|
-
this.debugLog('is not listening webhook.')
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
/**
|
|
360
|
-
* Updates the status for each of the HomeKit Characteristics
|
|
361
|
-
*/
|
|
362
|
-
async updateHomeKitCharacteristics(): Promise<void> {
|
|
363
|
-
if (!(this.device as waterDetectorConfig).hide_leak && this.LeakSensor?.Service) {
|
|
364
|
-
// StatusActive
|
|
365
|
-
await this.updateCharacteristic(this.LeakSensor.Service, this.hap.Characteristic.StatusActive, this.LeakSensor.StatusActive, 'StatusActive')
|
|
366
|
-
// LeakDetected
|
|
367
|
-
await this.updateCharacteristic(this.LeakSensor.Service, this.hap.Characteristic.LeakDetected, this.LeakSensor.LeakDetected, 'LeakDetected')
|
|
368
|
-
}
|
|
369
|
-
// BatteryLevel
|
|
370
|
-
await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel, 'BatteryLevel')
|
|
371
|
-
// StatusLowBattery
|
|
372
|
-
await this.updateCharacteristic(this.Battery.Service, this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery, 'StatusLowBattery')
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
async BLERefreshConnection(switchbot: SwitchBotBLE): Promise<void> {
|
|
376
|
-
this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`)
|
|
377
|
-
if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') {
|
|
378
|
-
this.warnLog('Using OpenAPI Connection to Refresh Status')
|
|
379
|
-
await this.openAPIRefreshStatus()
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
|
|
383
|
-
async offlineOff(): Promise<void> {
|
|
384
|
-
if (this.device.offline) {
|
|
385
|
-
if (!(this.device as waterDetectorConfig).hide_leak && this.LeakSensor?.Service) {
|
|
386
|
-
this.LeakSensor.Service.updateCharacteristic(this.hap.Characteristic.StatusActive, false)
|
|
387
|
-
this.LeakSensor.Service.updateCharacteristic(this.hap.Characteristic.LeakDetected, this.hap.Characteristic.LeakDetected.LEAK_NOT_DETECTED)
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
async apiError(e: any): Promise<void> {
|
|
393
|
-
if (!(this.device as waterDetectorConfig).hide_leak && this.LeakSensor?.Service) {
|
|
394
|
-
this.LeakSensor.Service.updateCharacteristic(this.hap.Characteristic.StatusActive, e)
|
|
395
|
-
this.LeakSensor.Service.updateCharacteristic(this.hap.Characteristic.LeakDetected, e)
|
|
396
|
-
}
|
|
397
|
-
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e)
|
|
398
|
-
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e)
|
|
399
|
-
}
|
|
400
|
-
}
|
|
@@ -1,131 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Base Matter Accessory Class
|
|
3
|
-
*
|
|
4
|
-
* This base class implements the MatterAccessory interface and provides
|
|
5
|
-
* common functionality that all Matter devices can use.
|
|
6
|
-
*
|
|
7
|
-
* Individual device types should extend this class and call super() with
|
|
8
|
-
* the required configuration.
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import type { API, EndpointType, Logger, MatterAccessory } from 'homebridge'
|
|
12
|
-
|
|
13
|
-
export interface BaseMatterAccessoryConfig {
|
|
14
|
-
uuid: string
|
|
15
|
-
displayName: string
|
|
16
|
-
deviceType: EndpointType
|
|
17
|
-
serialNumber: string
|
|
18
|
-
manufacturer: string
|
|
19
|
-
model: string
|
|
20
|
-
firmwareRevision: string
|
|
21
|
-
hardwareRevision: string
|
|
22
|
-
context?: Record<string, unknown>
|
|
23
|
-
clusters?: MatterAccessory['clusters']
|
|
24
|
-
handlers?: MatterAccessory['handlers']
|
|
25
|
-
parts?: MatterAccessory['parts']
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Base class for all Matter accessories
|
|
30
|
-
* Implements the MatterAccessory interface and provides common methods
|
|
31
|
-
*/
|
|
32
|
-
export abstract class BaseMatterAccessory implements MatterAccessory {
|
|
33
|
-
// Required MatterAccessory properties
|
|
34
|
-
public readonly uuid: string
|
|
35
|
-
public readonly displayName: string
|
|
36
|
-
public readonly deviceType: EndpointType
|
|
37
|
-
public readonly serialNumber: string
|
|
38
|
-
public readonly manufacturer: string
|
|
39
|
-
public readonly model: string
|
|
40
|
-
public readonly firmwareRevision: string
|
|
41
|
-
public readonly hardwareRevision: string
|
|
42
|
-
public readonly context: Record<string, unknown>
|
|
43
|
-
public readonly clusters?: MatterAccessory['clusters']
|
|
44
|
-
public readonly handlers?: MatterAccessory['handlers']
|
|
45
|
-
public readonly parts?: MatterAccessory['parts']
|
|
46
|
-
|
|
47
|
-
// Protected properties available to child classes
|
|
48
|
-
protected readonly api: API
|
|
49
|
-
protected readonly log: Logger
|
|
50
|
-
|
|
51
|
-
constructor(
|
|
52
|
-
api: API,
|
|
53
|
-
log: Logger,
|
|
54
|
-
config: BaseMatterAccessoryConfig,
|
|
55
|
-
) {
|
|
56
|
-
this.api = api
|
|
57
|
-
this.log = log
|
|
58
|
-
|
|
59
|
-
// Set all required properties
|
|
60
|
-
this.uuid = config.uuid
|
|
61
|
-
this.displayName = config.displayName
|
|
62
|
-
this.deviceType = config.deviceType
|
|
63
|
-
this.serialNumber = config.serialNumber
|
|
64
|
-
this.manufacturer = config.manufacturer
|
|
65
|
-
this.model = config.model
|
|
66
|
-
this.firmwareRevision = config.firmwareRevision
|
|
67
|
-
this.hardwareRevision = config.hardwareRevision
|
|
68
|
-
this.clusters = config.clusters
|
|
69
|
-
this.handlers = config.handlers
|
|
70
|
-
this.parts = config.parts
|
|
71
|
-
|
|
72
|
-
// Set context with all metadata
|
|
73
|
-
this.context = {
|
|
74
|
-
serialNumber: this.serialNumber,
|
|
75
|
-
manufacturer: this.manufacturer,
|
|
76
|
-
model: this.model,
|
|
77
|
-
firmwareRevision: this.firmwareRevision,
|
|
78
|
-
hardwareRevision: this.hardwareRevision,
|
|
79
|
-
...config.context,
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
/**
|
|
84
|
-
* Update the accessory state
|
|
85
|
-
* Helper method to update cluster attributes
|
|
86
|
-
*/
|
|
87
|
-
protected async updateState(cluster: string, attributes: Record<string, unknown>): Promise<void> {
|
|
88
|
-
await this.api.matter.updateAccessoryState(this.uuid, cluster, attributes)
|
|
89
|
-
this.log.debug(`[${this.displayName}] Updated ${cluster} state:`, attributes)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Log helper methods
|
|
94
|
-
*/
|
|
95
|
-
protected logInfo(message: string, ...args: unknown[]): void {
|
|
96
|
-
this.log.info(`[${this.displayName}] ${message}`, ...args)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
protected logError(message: string, ...args: unknown[]): void {
|
|
100
|
-
this.log.error(`[${this.displayName}] ${message}`, ...args)
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
protected logDebug(message: string, ...args: unknown[]): void {
|
|
104
|
-
this.log.debug(`[${this.displayName}] ${message}`, ...args)
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
protected logWarn(message: string, ...args: unknown[]): void {
|
|
108
|
-
this.log.warn(`[${this.displayName}] ${message}`, ...args)
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/**
|
|
112
|
-
* Convert this class instance to a plain MatterAccessory object
|
|
113
|
-
* This is what gets registered with Homebridge
|
|
114
|
-
*/
|
|
115
|
-
public toAccessory(): MatterAccessory {
|
|
116
|
-
return {
|
|
117
|
-
uuid: this.uuid,
|
|
118
|
-
displayName: this.displayName,
|
|
119
|
-
deviceType: this.deviceType,
|
|
120
|
-
serialNumber: this.serialNumber,
|
|
121
|
-
manufacturer: this.manufacturer,
|
|
122
|
-
model: this.model,
|
|
123
|
-
firmwareRevision: this.firmwareRevision,
|
|
124
|
-
hardwareRevision: this.hardwareRevision,
|
|
125
|
-
context: this.context,
|
|
126
|
-
clusters: this.clusters,
|
|
127
|
-
handlers: this.handlers,
|
|
128
|
-
parts: this.parts,
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
}
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Color Light Accessory Class (HS only)
|
|
3
|
-
* Hue and Saturation color control
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import type { API, Logger, MatterRequests } from 'homebridge'
|
|
7
|
-
|
|
8
|
-
import { BaseMatterAccessory } from './BaseMatterAccessory.js'
|
|
9
|
-
|
|
10
|
-
export class ColorLightAccessory extends BaseMatterAccessory {
|
|
11
|
-
constructor(api: API, log: Logger, opts?: Partial<import('./BaseMatterAccessory').BaseMatterAccessoryConfig & { deviceId?: string }>) {
|
|
12
|
-
const serialNumber = opts?.serialNumber ?? 'LIGHT-004'
|
|
13
|
-
const displayName = opts?.displayName ?? 'Colour Light (HS)'
|
|
14
|
-
const manufacturer = opts?.manufacturer ?? 'Homebridge Matter'
|
|
15
|
-
const model = opts?.model ?? 'HB-MATTER-LIGHT-COLOUR-HS'
|
|
16
|
-
const firmwareRevision = opts?.firmwareRevision ?? '2.0.0'
|
|
17
|
-
const hardwareRevision = opts?.hardwareRevision ?? '1.0.0'
|
|
18
|
-
|
|
19
|
-
const clusters = opts?.clusters ?? {
|
|
20
|
-
onOff: { onOff: false },
|
|
21
|
-
levelControl: { currentLevel: 127, minLevel: 1, maxLevel: 254 },
|
|
22
|
-
colorControl: {
|
|
23
|
-
colorMode: api.matter.types.ColorControl.ColorMode.CurrentHueAndCurrentSaturation,
|
|
24
|
-
currentHue: 0,
|
|
25
|
-
currentSaturation: 254,
|
|
26
|
-
currentX: 41942,
|
|
27
|
-
currentY: 21626,
|
|
28
|
-
},
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
const handlers = opts?.handlers ?? {
|
|
32
|
-
onOff: { on: async () => this.handleOn(), off: async () => this.handleOff() },
|
|
33
|
-
levelControl: { moveToLevelWithOnOff: async (request: MatterRequests.MoveToLevel) => this.handleSetLevel(request) },
|
|
34
|
-
colorControl: {
|
|
35
|
-
moveToColorLogic: async (request: MatterRequests.MoveToColor) => this.handleSetColor(request),
|
|
36
|
-
moveToHueAndSaturationLogic: async (request: MatterRequests.MoveToHueAndSaturation) => this.handleSetHueSaturation(request),
|
|
37
|
-
},
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
super(api, log, {
|
|
41
|
-
uuid: opts?.uuid ?? api.matter.uuid.generate(serialNumber),
|
|
42
|
-
displayName,
|
|
43
|
-
deviceType: api.matter.deviceTypes.ExtendedColorLight,
|
|
44
|
-
serialNumber,
|
|
45
|
-
manufacturer,
|
|
46
|
-
model,
|
|
47
|
-
firmwareRevision,
|
|
48
|
-
hardwareRevision,
|
|
49
|
-
clusters,
|
|
50
|
-
handlers,
|
|
51
|
-
context: { deviceId: opts?.deviceId, ...(opts?.context ?? {}) },
|
|
52
|
-
})
|
|
53
|
-
|
|
54
|
-
this.logInfo('initialized.')
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
private async handleOn(): Promise<void> {
|
|
58
|
-
this.logInfo('turning on.')
|
|
59
|
-
// TODO: await myLightAPI.turnOn()
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
private async handleOff(): Promise<void> {
|
|
63
|
-
this.logInfo('turning off.')
|
|
64
|
-
// TODO: await myLightAPI.turnOff()
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
private async handleSetLevel(request: MatterRequests.MoveToLevel): Promise<void> {
|
|
68
|
-
this.logInfo(`MoveToLevel request: ${JSON.stringify(request)}`)
|
|
69
|
-
const { level } = request
|
|
70
|
-
const brightnessPercent = Math.round((level / 254) * 100)
|
|
71
|
-
this.logInfo(`setting brightness to ${brightnessPercent}%.`)
|
|
72
|
-
// TODO: await myLightAPI.setBrightness(brightnessPercent)
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
private async handleSetColor(request: MatterRequests.MoveToColor): Promise<void> {
|
|
76
|
-
this.logInfo(`MoveToColor request: ${JSON.stringify(request)}`)
|
|
77
|
-
const { colorX, colorY, transitionTime } = request
|
|
78
|
-
const xFloat = (colorX / 65535).toFixed(4)
|
|
79
|
-
const yFloat = (colorY / 65535).toFixed(4)
|
|
80
|
-
this.logInfo(`setting xy color to (${xFloat}, ${yFloat}) with transition ${transitionTime}.`)
|
|
81
|
-
// TODO: await myLightAPI.setXY(xFloat, yFloat, transitionTime)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
private async handleSetHueSaturation(request: MatterRequests.MoveToHueAndSaturation): Promise<void> {
|
|
85
|
-
this.logInfo(`MoveToHueAndSaturation request: ${JSON.stringify(request)}`)
|
|
86
|
-
const { hue, saturation, transitionTime } = request
|
|
87
|
-
const hueDegrees = Math.round((hue / 254) * 360)
|
|
88
|
-
const saturationPercent = Math.round((saturation / 254) * 100)
|
|
89
|
-
this.logInfo(`setting color to ${hueDegrees}°, ${saturationPercent}% with transition ${transitionTime}.`)
|
|
90
|
-
// TODO: await myLightAPI.setColor(hueDegrees, saturationPercent, transitionTime)
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
public updateOnOffState(isOn: boolean): void {
|
|
94
|
-
this.updateState(this.api.matter.clusterNames.OnOff, { onOff: isOn })
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
public updateBrightness(percent: number): void {
|
|
98
|
-
const matterLevel = Math.max(1, Math.round((percent / 100) * 254))
|
|
99
|
-
this.updateState(this.api.matter.clusterNames.LevelControl, { currentLevel: matterLevel })
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
public updateHueSaturation(hue: number, saturation: number): void {
|
|
103
|
-
const matterHue = Math.round((hue / 360) * 254)
|
|
104
|
-
const matterSat = Math.round((saturation / 100) * 254)
|
|
105
|
-
this.updateState(this.api.matter.clusterNames.ColorControl, {
|
|
106
|
-
currentHue: matterHue,
|
|
107
|
-
currentSaturation: matterSat,
|
|
108
|
-
})
|
|
109
|
-
}
|
|
110
|
-
}
|