@switchbot/homebridge-switchbot 5.0.0-beta.9 → 5.0.0-beta.91
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 +32 -0
- package/.github/workflows/manual-e2e.yml +115 -0
- package/.github/workflows/release.yml +0 -4
- 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 +91 -14787
- 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 +630 -246
- 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 +367 -36
- package/dist/homebridge-ui/server.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -32
- package/dist/index.js.map +1 -1
- package/dist/platform.d.ts +35 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +514 -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 +630 -246
- package/src/homebridge-ui/server.ts +434 -41
- package/src/index.ts +4 -33
- package/src/platform.ts +515 -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
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Advanced light E2E helper: exercises On/Off, Brightness steps, Color Temperature and RGB color where supported.
|
|
3
|
+
# Usage:
|
|
4
|
+
# 1) Ensure Homebridge is running and the plugin is installed/linked.
|
|
5
|
+
# 2) Populate `HB_URL`, `HB_TOKEN`, and `ACCESSORY_ID` below (or export them).
|
|
6
|
+
# 3) Run: `bash scripts/e2e/light-advanced-e2e.sh`
|
|
7
|
+
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
: ${HB_URL:="http://localhost:8581"}
|
|
11
|
+
: ${HB_TOKEN:=""}
|
|
12
|
+
: ${ACCESSORY_ID:=""}
|
|
13
|
+
: ${ACCESSORY_NAME:=""}
|
|
14
|
+
|
|
15
|
+
# Resolve accessory id (aid) from Homebridge API when ACCESSORY_NAME supplied
|
|
16
|
+
resolve_accessory_id() {
|
|
17
|
+
if [[ -n "$ACCESSORY_ID" ]]; then
|
|
18
|
+
return 0
|
|
19
|
+
fi
|
|
20
|
+
if [[ -z "$ACCESSORY_NAME" ]]; then
|
|
21
|
+
return 1
|
|
22
|
+
fi
|
|
23
|
+
local resp
|
|
24
|
+
resp=$(curl -sS -H "Authorization: Bearer ${HB_TOKEN}" "${HB_URL}/api/accessories") || return 1
|
|
25
|
+
ACCESSORY_ID=$(printf '%s' "$resp" | node -e "const fs=require('fs');const name=process.argv[1];const j=JSON.parse(fs.readFileSync(0,'utf8'));const arr=Array.isArray(j)?j:(j.accessories||j);for(const a of arr||[]){if(a.displayName===name||a.name===name||(a.context&&a.context.deviceId===name)){if(a.aid){console.log(a.aid);process.exit(0);}else if(a.UUID){console.log(a.UUID);process.exit(0);}}}process.exit(1);" "$ACCESSORY_NAME") || return 1
|
|
26
|
+
return 0
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if [[ -z "$HB_TOKEN" ]]; then
|
|
30
|
+
echo "Please set HB_TOKEN environment variable or edit the top of this script."
|
|
31
|
+
exit 1
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
if [[ -z "$ACCESSORY_ID" ]]; then
|
|
35
|
+
if resolve_accessory_id; then
|
|
36
|
+
echo "Discovered ACCESSORY_ID=${ACCESSORY_ID} for name '${ACCESSORY_NAME}'"
|
|
37
|
+
else
|
|
38
|
+
echo "No ACCESSORY_ID or ACCESSORY_NAME resolved. Please set one." && exit 1
|
|
39
|
+
fi
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
echo "Running advanced light E2E script against $HB_URL (accessory $ACCESSORY_ID)"
|
|
43
|
+
|
|
44
|
+
curl_common() {
|
|
45
|
+
local method="$1" path="$2" data="$3"
|
|
46
|
+
if [[ "$method" == "GET" ]]; then
|
|
47
|
+
curl -sS -H "Authorization: Bearer ${HB_TOKEN}" "${HB_URL}${path}"
|
|
48
|
+
else
|
|
49
|
+
curl -sS -X "$method" -H "Authorization: Bearer ${HB_TOKEN}" -H "Content-Type: application/json" -d "$data" "${HB_URL}${path}"
|
|
50
|
+
fi
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
echo "1) Fetch accessories listing"
|
|
54
|
+
curl_common GET "/api/accessories" ""
|
|
55
|
+
|
|
56
|
+
echo
|
|
57
|
+
echo "2) Toggle On"
|
|
58
|
+
curl_common POST "/api/accessories/${ACCESSORY_ID}/characteristics" '{ "characteristics": [{"aid":1,"iid":11,"value":true}] }'
|
|
59
|
+
sleep 1
|
|
60
|
+
|
|
61
|
+
echo
|
|
62
|
+
echo "3) Brightness sweep: 10% -> 50% -> 100%"
|
|
63
|
+
curl_common POST "/api/accessories/${ACCESSORY_ID}/characteristics" '{ "characteristics": [{"aid":1,"iid":12,"value":10}] }'
|
|
64
|
+
sleep 1
|
|
65
|
+
curl_common POST "/api/accessories/${ACCESSORY_ID}/characteristics" '{ "characteristics": [{"aid":1,"iid":12,"value":50}] }'
|
|
66
|
+
sleep 1
|
|
67
|
+
curl_common POST "/api/accessories/${ACCESSORY_ID}/characteristics" '{ "characteristics": [{"aid":1,"iid":12,"value":100}] }'
|
|
68
|
+
sleep 1
|
|
69
|
+
|
|
70
|
+
echo
|
|
71
|
+
echo "4) Color Temperature test (if supported): 2700K -> 4000K -> 6500K"
|
|
72
|
+
# HomeKit uses Mireds for color temperature; approximate conversions used here
|
|
73
|
+
MIREDS_2700=370
|
|
74
|
+
MIREDS_4000=250
|
|
75
|
+
MIREDS_6500=154
|
|
76
|
+
curl_common POST "/api/accessories/${ACCESSORY_ID}/characteristics" "{ \"characteristics\": [{\"aid\":1,\"iid\":14,\"value\":${MIREDS_2700}}] }"
|
|
77
|
+
sleep 1
|
|
78
|
+
curl_common POST "/api/accessories/${ACCESSORY_ID}/characteristics" "{ \"characteristics\": [{\"aid\":1,\"iid\":14,\"value\":${MIREDS_4000}}] }"
|
|
79
|
+
sleep 1
|
|
80
|
+
curl_common POST "/api/accessories/${ACCESSORY_ID}/characteristics" "{ \"characteristics\": [{\"aid\":1,\"iid\":14,\"value\":${MIREDS_6500}}] }"
|
|
81
|
+
sleep 1
|
|
82
|
+
|
|
83
|
+
echo
|
|
84
|
+
echo "5) Color (RGB) test (if supported): Red -> Green -> Blue"
|
|
85
|
+
# Many HomeKit bridges expose Hue (iid 15) and Saturation (iid 16). We'll set hue and sat values accordingly.
|
|
86
|
+
curl_common POST "/api/accessories/${ACCESSORY_ID}/characteristics" '{ "characteristics": [{"aid":1,"iid":15,"value":0},{"aid":1,"iid":16,"value":100}] }'
|
|
87
|
+
sleep 1
|
|
88
|
+
curl_common POST "/api/accessories/${ACCESSORY_ID}/characteristics" '{ "characteristics": [{"aid":1,"iid":15,"value":120},{"aid":1,"iid":16,"value":100}] }'
|
|
89
|
+
sleep 1
|
|
90
|
+
curl_common POST "/api/accessories/${ACCESSORY_ID}/characteristics" '{ "characteristics": [{"aid":1,"iid":15,"value":240},{"aid":1,"iid":16,"value":100}] }'
|
|
91
|
+
sleep 1
|
|
92
|
+
|
|
93
|
+
echo
|
|
94
|
+
echo "6) Toggle Off"
|
|
95
|
+
curl_common POST "/api/accessories/${ACCESSORY_ID}/characteristics" '{ "characteristics": [{"aid":1,"iid":11,"value":false}] }'
|
|
96
|
+
|
|
97
|
+
echo "Done. Review Homebridge logs and physical device behavior."
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Lightweight automated E2E helper for lights.
|
|
3
|
+
# Usage:
|
|
4
|
+
# 1) Ensure Homebridge is running and the plugin is installed/linked.
|
|
5
|
+
# 2) Populate `HB_URL`, `HB_TOKEN`, and `ACCESSORY_ID` below (or export them).
|
|
6
|
+
# 3) Run: `bash scripts/e2e/light-e2e.sh`
|
|
7
|
+
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
: ${HB_URL:="http://localhost:8581"}
|
|
11
|
+
: ${HB_TOKEN:=""}
|
|
12
|
+
: ${ACCESSORY_ID:=""}
|
|
13
|
+
: ${ACCESSORY_NAME:=""}
|
|
14
|
+
|
|
15
|
+
# Resolve accessory id (aid) from Homebridge API when ACCESSORY_NAME supplied
|
|
16
|
+
resolve_accessory_id() {
|
|
17
|
+
if [[ -n "$ACCESSORY_ID" ]]; then
|
|
18
|
+
return 0
|
|
19
|
+
fi
|
|
20
|
+
if [[ -z "$ACCESSORY_NAME" ]]; then
|
|
21
|
+
return 1
|
|
22
|
+
fi
|
|
23
|
+
local resp
|
|
24
|
+
resp=$(curl -sS -H "Authorization: Bearer ${HB_TOKEN}" "${HB_URL}/api/accessories") || return 1
|
|
25
|
+
ACCESSORY_ID=$(printf '%s' "$resp" | node -e "const fs=require('fs');const name=process.argv[1];const j=JSON.parse(fs.readFileSync(0,'utf8'));const arr=Array.isArray(j)?j:(j.accessories||j);for(const a of arr||[]){if(a.displayName===name||a.name===name||(a.context&&a.context.deviceId===name)){if(a.aid){console.log(a.aid);process.exit(0);}else if(a.UUID){console.log(a.UUID);process.exit(0);}}}process.exit(1);" "$ACCESSORY_NAME") || return 1
|
|
26
|
+
return 0
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if [[ -z "$HB_TOKEN" ]]; then
|
|
30
|
+
echo "Please set HB_TOKEN environment variable or edit the top of this script."
|
|
31
|
+
exit 1
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
if [[ -z "$ACCESSORY_ID" ]]; then
|
|
35
|
+
if resolve_accessory_id; then
|
|
36
|
+
echo "Discovered ACCESSORY_ID=${ACCESSORY_ID} for name '${ACCESSORY_NAME}'"
|
|
37
|
+
else
|
|
38
|
+
echo "No ACCESSORY_ID or ACCESSORY_NAME resolved. Please set one." && exit 1
|
|
39
|
+
fi
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
echo "Running light E2E script against $HB_URL (accessory $ACCESSORY_ID)"
|
|
43
|
+
|
|
44
|
+
curl_common() {
|
|
45
|
+
local method="$1" path="$2" data="$3"
|
|
46
|
+
if [[ "$method" == "GET" ]]; then
|
|
47
|
+
curl -sS -H "Authorization: Bearer ${HB_TOKEN}" "${HB_URL}${path}"
|
|
48
|
+
else
|
|
49
|
+
curl -sS -X "$method" -H "Authorization: Bearer ${HB_TOKEN}" -H "Content-Type: application/json" -d "$data" "${HB_URL}${path}"
|
|
50
|
+
fi
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
echo "1) Fetch accessories listing (to verify connectivity)"
|
|
54
|
+
curl_common GET "/api/accessories" ""
|
|
55
|
+
|
|
56
|
+
echo
|
|
57
|
+
echo "2) Toggle On"
|
|
58
|
+
curl_common POST "/api/accessories/${ACCESSORY_ID}/characteristics" '{ "characteristics": [{"aid":1,"iid":11,"value":true}] }'
|
|
59
|
+
sleep 1
|
|
60
|
+
|
|
61
|
+
echo
|
|
62
|
+
echo "3) Set Brightness to 25%"
|
|
63
|
+
curl_common POST "/api/accessories/${ACCESSORY_ID}/characteristics" '{ "characteristics": [{"aid":1,"iid":12,"value":25}] }'
|
|
64
|
+
sleep 1
|
|
65
|
+
|
|
66
|
+
echo
|
|
67
|
+
echo "4) Set Brightness to 100%"
|
|
68
|
+
curl_common POST "/api/accessories/${ACCESSORY_ID}/characteristics" '{ "characteristics": [{"aid":1,"iid":12,"value":100}] }'
|
|
69
|
+
sleep 1
|
|
70
|
+
|
|
71
|
+
echo
|
|
72
|
+
echo "5) Toggle Off"
|
|
73
|
+
curl_common POST "/api/accessories/${ACCESSORY_ID}/characteristics" '{ "characteristics": [{"aid":1,"iid":11,"value":false}] }'
|
|
74
|
+
|
|
75
|
+
echo "Done. Review Homebridge logs and physical device behavior."
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# List accessories from Homebridge UI and print name, aid/UUID, and context.deviceId
|
|
3
|
+
# Usage:
|
|
4
|
+
# export HB_URL=http://localhost:8581
|
|
5
|
+
# export HB_TOKEN=your_token
|
|
6
|
+
# bash scripts/e2e/list-accessories.sh
|
|
7
|
+
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
: ${HB_URL:="http://localhost:8581"}
|
|
11
|
+
: ${HB_TOKEN:=""}
|
|
12
|
+
|
|
13
|
+
if [[ -z "$HB_TOKEN" ]]; then
|
|
14
|
+
echo "Please set HB_TOKEN environment variable (Homebridge UI token)."
|
|
15
|
+
exit 1
|
|
16
|
+
fi
|
|
17
|
+
|
|
18
|
+
resp=$(curl -sS -H "Authorization: Bearer ${HB_TOKEN}" "${HB_URL}/api/accessories")
|
|
19
|
+
node -e "const fs=require('fs');const j=JSON.parse(fs.readFileSync(0,'utf8'));const arr=Array.isArray(j)?j:(j.accessories||j)||[];console.log('Name | aid/UUID | context.deviceId');for(const a of arr){const name=a.displayName||a.name||'(unknown)';const id=a.aid||a.UUID||'';const ctx=(a.context&&a.context.deviceId)||'';console.log(`${name} | ${id} | ${ctx}`);}" <<< "$resp"
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Lightweight automated E2E helper for locks.
|
|
3
|
+
# Usage:
|
|
4
|
+
# 1) Ensure Homebridge is running and the plugin is installed/linked.
|
|
5
|
+
# 2) Populate `HB_URL`, `HB_TOKEN`, and `ACCESSORY_ID` below (or export them).
|
|
6
|
+
# 3) Run: `bash scripts/e2e/lock-e2e.sh`
|
|
7
|
+
|
|
8
|
+
set -euo pipefail
|
|
9
|
+
|
|
10
|
+
: ${HB_URL:="http://localhost:8581"}
|
|
11
|
+
: ${HB_TOKEN:=""}
|
|
12
|
+
: ${ACCESSORY_ID:=""}
|
|
13
|
+
: ${ACCESSORY_NAME:=""}
|
|
14
|
+
|
|
15
|
+
# Resolve accessory id (aid) from Homebridge API when ACCESSORY_NAME supplied
|
|
16
|
+
resolve_accessory_id() {
|
|
17
|
+
if [[ -n "$ACCESSORY_ID" ]]; then
|
|
18
|
+
return 0
|
|
19
|
+
fi
|
|
20
|
+
if [[ -z "$ACCESSORY_NAME" ]]; then
|
|
21
|
+
return 1
|
|
22
|
+
fi
|
|
23
|
+
local resp
|
|
24
|
+
resp=$(curl -sS -H "Authorization: Bearer ${HB_TOKEN}" "${HB_URL}/api/accessories") || return 1
|
|
25
|
+
ACCESSORY_ID=$(printf '%s' "$resp" | node -e "const fs=require('fs');const name=process.argv[1];const j=JSON.parse(fs.readFileSync(0,'utf8'));const arr=Array.isArray(j)?j:(j.accessories||j);for(const a of arr||[]){if(a.displayName===name||a.name===name||(a.context&&a.context.deviceId===name)){if(a.aid){console.log(a.aid);process.exit(0);}else if(a.UUID){console.log(a.UUID);process.exit(0);}}}process.exit(1);" "$ACCESSORY_NAME") || return 1
|
|
26
|
+
return 0
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if [[ -z "$HB_TOKEN" ]]; then
|
|
30
|
+
echo "Please set HB_TOKEN environment variable or edit the top of this script."
|
|
31
|
+
exit 1
|
|
32
|
+
fi
|
|
33
|
+
|
|
34
|
+
if [[ -z "$ACCESSORY_ID" ]]; then
|
|
35
|
+
if resolve_accessory_id; then
|
|
36
|
+
echo "Discovered ACCESSORY_ID=${ACCESSORY_ID} for name '${ACCESSORY_NAME}'"
|
|
37
|
+
else
|
|
38
|
+
echo "No ACCESSORY_ID or ACCESSORY_NAME resolved. Please set one." && exit 1
|
|
39
|
+
fi
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
echo "Running lock E2E script against $HB_URL (accessory $ACCESSORY_ID)"
|
|
43
|
+
|
|
44
|
+
curl_common() {
|
|
45
|
+
local method="$1" path="$2" data="$3"
|
|
46
|
+
if [[ "$method" == "GET" ]]; then
|
|
47
|
+
curl -sS -H "Authorization: Bearer ${HB_TOKEN}" "${HB_URL}${path}"
|
|
48
|
+
else
|
|
49
|
+
curl -sS -X "$method" -H "Authorization: Bearer ${HB_TOKEN}" -H "Content-Type: application/json" -d "$data" "${HB_URL}${path}"
|
|
50
|
+
fi
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
echo "1) Fetch accessories listing"
|
|
54
|
+
curl_common GET "/api/accessories" ""
|
|
55
|
+
|
|
56
|
+
echo
|
|
57
|
+
echo "2) Lock"
|
|
58
|
+
curl_common POST "/api/accessories/${ACCESSORY_ID}/characteristics" '{ "characteristics": [{"aid":1,"iid":11,"value":1}] }'
|
|
59
|
+
sleep 1
|
|
60
|
+
|
|
61
|
+
echo
|
|
62
|
+
echo "3) Unlock"
|
|
63
|
+
curl_common POST "/api/accessories/${ACCESSORY_ID}/characteristics" '{ "characteristics": [{"aid":1,"iid":11,"value":0}] }'
|
|
64
|
+
|
|
65
|
+
echo "Done. Review Homebridge logs and physical device behavior."
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
const fs = require('fs')
|
|
3
|
+
const path = require('path')
|
|
4
|
+
|
|
5
|
+
function usage() {
|
|
6
|
+
console.error('Usage: node scripts/generate-matter-maps.js <input-json> [output-file]')
|
|
7
|
+
process.exit(2)
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const input = process.argv[2]
|
|
11
|
+
const outFile = process.argv[3] || path.join(__dirname, '..', 'src', 'matter-maps.generated.ts')
|
|
12
|
+
|
|
13
|
+
if (!input) usage()
|
|
14
|
+
if (!fs.existsSync(input)) {
|
|
15
|
+
console.error('Input file not found:', input)
|
|
16
|
+
process.exit(2)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const json = JSON.parse(fs.readFileSync(input, 'utf8'))
|
|
20
|
+
|
|
21
|
+
// Expecting structure: { clusters: [{ name, id, attributes: [{ name, id }, ...] }, ...] }
|
|
22
|
+
const clusters = json.clusters || []
|
|
23
|
+
|
|
24
|
+
const clusterMapEntries = []
|
|
25
|
+
const attrGroups = {}
|
|
26
|
+
|
|
27
|
+
for (const c of clusters) {
|
|
28
|
+
if (!c.name || typeof c.id === 'undefined') continue
|
|
29
|
+
const key = c.name.replace(/[^A-Za-z0-9_]/g, '')
|
|
30
|
+
clusterMapEntries.push(` ${key}: 0x${parseInt(String(c.id), 10).toString(16)}`)
|
|
31
|
+
const attrs = {}
|
|
32
|
+
if (Array.isArray(c.attributes)) {
|
|
33
|
+
for (const a of c.attributes) {
|
|
34
|
+
if (!a.name || typeof a.id === 'undefined') continue
|
|
35
|
+
const an = a.name.replace(/[^A-Za-z0-9_]/g, '')
|
|
36
|
+
attrs[an] = `0x${parseInt(String(a.id), 10).toString(16)}`
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (Object.keys(attrs).length) attrGroups[key] = attrs
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const clusterMap = `export const MATTER_CLUSTER_IDS = {
|
|
43
|
+
${clusterMapEntries.join(',\n')}
|
|
44
|
+
} as const
|
|
45
|
+
\n`
|
|
46
|
+
|
|
47
|
+
let attrText = 'export const MATTER_ATTRIBUTE_IDS = {\n'
|
|
48
|
+
for (const [k, v] of Object.entries(attrGroups)) {
|
|
49
|
+
attrText += ` ${k}: {\n`
|
|
50
|
+
for (const [an, aid] of Object.entries(v)) {
|
|
51
|
+
attrText += ` ${an}: ${aid},\n`
|
|
52
|
+
}
|
|
53
|
+
attrText += ` },\n`
|
|
54
|
+
}
|
|
55
|
+
attrText += `} as const\n`
|
|
56
|
+
|
|
57
|
+
const fileContent = `// GENERATED FILE - do not edit by hand.\n// Run: node scripts/generate-matter-maps.js <zap-matter.json>\n\n${clusterMap}\n${attrText}`
|
|
58
|
+
|
|
59
|
+
fs.writeFileSync(outFile, fileContent, 'utf8')
|
|
60
|
+
console.log('Wrote', outFile)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Wrapper to run the repository's E2E vitest harness locally.
|
|
3
|
+
# Usage: export HB_URL HB_TOKEN [LIGHT_ACCESSORY_ID ...]; export RUN_E2E=1; bash scripts/run-e2e-local.sh
|
|
4
|
+
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
: ${RUN_E2E:=1}
|
|
8
|
+
|
|
9
|
+
echo "Running E2E vitest harness (RUN_E2E=${RUN_E2E})"
|
|
10
|
+
|
|
11
|
+
# Run only the e2e spec file so the full unit test suite isn't executed
|
|
12
|
+
npx vitest run test/e2e/run-e2e.spec.ts
|
|
13
|
+
|
|
14
|
+
echo "E2E harness finished. Check logs for per-script output."
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import type { SwitchBotPluginConfig, DeviceType } from './settings.js'
|
|
2
|
+
import { SwitchBotClient } from './switchbotClient.js'
|
|
3
|
+
import {
|
|
4
|
+
GenericDevice,
|
|
5
|
+
BotDevice,
|
|
6
|
+
CurtainDevice,
|
|
7
|
+
FanDevice,
|
|
8
|
+
LightDevice,
|
|
9
|
+
LightStripDevice,
|
|
10
|
+
MotionSensorDevice,
|
|
11
|
+
ContactSensorDevice,
|
|
12
|
+
VacuumDevice,
|
|
13
|
+
LockDevice,
|
|
14
|
+
HumidifierDevice,
|
|
15
|
+
TemperatureSensorDevice,
|
|
16
|
+
RelaySwitchDevice,
|
|
17
|
+
RelaySwitch1PMDevice,
|
|
18
|
+
PlugDevice,
|
|
19
|
+
PlugMiniDevice,
|
|
20
|
+
BlindTiltDevice,
|
|
21
|
+
Curtain3Device,
|
|
22
|
+
RollerShadeDevice,
|
|
23
|
+
Hub2Device,
|
|
24
|
+
MeterDevice,
|
|
25
|
+
WaterDetectorDevice,
|
|
26
|
+
SmartFanDevice,
|
|
27
|
+
StripLightDevice,
|
|
28
|
+
WalletFinderDevice,
|
|
29
|
+
WoSweeperDevice,
|
|
30
|
+
WoSweeperMiniDevice,
|
|
31
|
+
WoSweeperMiniProDevice,
|
|
32
|
+
} from './devices/genericDevice.js'
|
|
33
|
+
|
|
34
|
+
export interface DeviceOptions {
|
|
35
|
+
id: string
|
|
36
|
+
type: DeviceType
|
|
37
|
+
name?: string
|
|
38
|
+
[key: string]: any
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
const DEVICE_CLASS_MAP: Record<string, any> = {
|
|
42
|
+
bot: BotDevice,
|
|
43
|
+
curtain: CurtainDevice,
|
|
44
|
+
fan: FanDevice,
|
|
45
|
+
light: LightDevice,
|
|
46
|
+
lightstrip: LightStripDevice,
|
|
47
|
+
motion: MotionSensorDevice,
|
|
48
|
+
contact: ContactSensorDevice,
|
|
49
|
+
vacuum: VacuumDevice,
|
|
50
|
+
lock: LockDevice,
|
|
51
|
+
humidifier: HumidifierDevice,
|
|
52
|
+
temperature: TemperatureSensorDevice,
|
|
53
|
+
'relay switch 1': RelaySwitchDevice,
|
|
54
|
+
'relay switch 1pm': RelaySwitch1PMDevice,
|
|
55
|
+
plug: PlugDevice,
|
|
56
|
+
'plug mini (jp)': PlugMiniDevice,
|
|
57
|
+
'plug mini (us)': PlugMiniDevice,
|
|
58
|
+
'blind tilt': BlindTiltDevice,
|
|
59
|
+
curtain3: Curtain3Device,
|
|
60
|
+
'worollershade': RollerShadeDevice,
|
|
61
|
+
'wo rollershade': RollerShadeDevice,
|
|
62
|
+
'roller shade': RollerShadeDevice,
|
|
63
|
+
'rollershade': RollerShadeDevice,
|
|
64
|
+
'hub 2': Hub2Device,
|
|
65
|
+
meter: MeterDevice,
|
|
66
|
+
'meterplus': MeterDevice,
|
|
67
|
+
'meter plus (jp)': MeterDevice,
|
|
68
|
+
'meterpro': MeterDevice,
|
|
69
|
+
'meterpro(co2)': MeterDevice,
|
|
70
|
+
'water detector': WaterDetectorDevice,
|
|
71
|
+
'smart fan': SmartFanDevice,
|
|
72
|
+
'strip light': StripLightDevice,
|
|
73
|
+
'walletfinder': WalletFinderDevice,
|
|
74
|
+
'wosweeper': WoSweeperDevice,
|
|
75
|
+
'wosweepermini': WoSweeperMiniDevice,
|
|
76
|
+
'wosweeperminipro': WoSweeperMiniProDevice,
|
|
77
|
+
'k10+': WoSweeperDevice,
|
|
78
|
+
'k10+ pro': WoSweeperDevice,
|
|
79
|
+
'k10+ pro (wosweeperminipro)': WoSweeperMiniProDevice,
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function classForType(type: string) {
|
|
83
|
+
const key = (type || '').toLowerCase()
|
|
84
|
+
return DEVICE_CLASS_MAP[key] ?? GenericDevice
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export async function createDevice(opts: DeviceOptions, cfg: SwitchBotPluginConfig, useMatter: boolean) {
|
|
88
|
+
// Reuse existing client when provided via config to avoid creating
|
|
89
|
+
// a new SwitchBotClient per device (which can be expensive).
|
|
90
|
+
let client: any = (cfg as any)?._client ?? null
|
|
91
|
+
if (!client) {
|
|
92
|
+
client = new SwitchBotClient(cfg)
|
|
93
|
+
await client.init()
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Pass client via config so devices can access it
|
|
97
|
+
const mergedCfg = { ...(cfg as any), _client: client }
|
|
98
|
+
|
|
99
|
+
const DeviceCtor = classForType(opts.type)
|
|
100
|
+
const device = new DeviceCtor(opts, mergedCfg)
|
|
101
|
+
await device.init()
|
|
102
|
+
|
|
103
|
+
// Attach a simple getState delegator to the client where appropriate
|
|
104
|
+
const originalGetState = device.getState.bind(device)
|
|
105
|
+
device.getState = async () => {
|
|
106
|
+
try {
|
|
107
|
+
// Prefer client-backed getDevice when available
|
|
108
|
+
const dev = await client.getDevice(opts.id)
|
|
109
|
+
if (dev) return dev
|
|
110
|
+
} catch (e) {
|
|
111
|
+
// ignore and fallback to device implementation
|
|
112
|
+
}
|
|
113
|
+
return originalGetState()
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Provide accessory factory based on platform selection
|
|
117
|
+
return {
|
|
118
|
+
instance: device,
|
|
119
|
+
createAccessory: (api: any) => (useMatter ? device.createMatterAccessory(api) : device.createHAPAccessory(api)),
|
|
120
|
+
protocol: useMatter ? 'matter' : 'hap',
|
|
121
|
+
}
|
|
122
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import type { SwitchBotPluginConfig } from '../settings.js'
|
|
2
|
+
|
|
3
|
+
import { MATTER_ATTRIBUTE_IDS, MATTER_CLUSTER_IDS } from '../utils.js'
|
|
4
|
+
|
|
5
|
+
export interface DeviceOptions {
|
|
6
|
+
id: string
|
|
7
|
+
type: string
|
|
8
|
+
name?: string
|
|
9
|
+
[key: string]: any
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export abstract class DeviceBase {
|
|
13
|
+
protected opts: DeviceOptions
|
|
14
|
+
protected cfg: SwitchBotPluginConfig
|
|
15
|
+
protected client: any | null
|
|
16
|
+
|
|
17
|
+
constructor(opts: DeviceOptions, cfg: SwitchBotPluginConfig) {
|
|
18
|
+
this.opts = opts
|
|
19
|
+
this.cfg = cfg
|
|
20
|
+
this.client = (cfg as any)?._client ?? null
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Initialize any connections/resources
|
|
24
|
+
async init(): Promise<void> {}
|
|
25
|
+
|
|
26
|
+
// Return current device state from SwitchBot or cache
|
|
27
|
+
abstract getState(): Promise<any>
|
|
28
|
+
|
|
29
|
+
// Apply a state change to the device
|
|
30
|
+
abstract setState(change: any): Promise<any>
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Create and return a HAP accessory descriptor.
|
|
34
|
+
*
|
|
35
|
+
* This method returns a descriptor object (not a platformAccessory instance).
|
|
36
|
+
* The platform will use this descriptor to construct a real HAP accessory.
|
|
37
|
+
*
|
|
38
|
+
* Default descriptor provides a simple Switch service with an `On` characteristic
|
|
39
|
+
* backed by `getState()` / `setState()` so most simple devices work out of the box.
|
|
40
|
+
*
|
|
41
|
+
* If the Homebridge `api` is passed, `Service` and `Characteristic` constructors
|
|
42
|
+
* are included under `_resolved` for callers that need them.
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* {
|
|
46
|
+
* id: 'd1',
|
|
47
|
+
* name: 'My Device',
|
|
48
|
+
* protocol: 'hap',
|
|
49
|
+
* services: [ { type: 'Switch', characteristics: { On: { get: async ()=>true, set: async v=>{} } } } ]
|
|
50
|
+
* }
|
|
51
|
+
*/
|
|
52
|
+
createHAPAccessory(api: any): any {
|
|
53
|
+
const base: any = {
|
|
54
|
+
id: this.opts.id,
|
|
55
|
+
name: this.opts.name ?? this.opts.type,
|
|
56
|
+
protocol: 'hap',
|
|
57
|
+
services: [
|
|
58
|
+
{
|
|
59
|
+
type: 'Switch',
|
|
60
|
+
characteristics: {
|
|
61
|
+
On: {
|
|
62
|
+
get: async () => {
|
|
63
|
+
const s = await this.getState()
|
|
64
|
+
return !!(s && (s.on === true || s.state === 'on' || s.power === 'on'))
|
|
65
|
+
},
|
|
66
|
+
set: async (v: any) => {
|
|
67
|
+
await this.setState({ on: !!v })
|
|
68
|
+
},
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
],
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
const hap = api?.hap
|
|
77
|
+
if (hap && hap.Service && hap.Characteristic) {
|
|
78
|
+
base._resolved = { Service: hap.Service, Characteristic: hap.Characteristic }
|
|
79
|
+
}
|
|
80
|
+
} catch (e) {
|
|
81
|
+
// ignore
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
return base
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Create and return a Matter accessory descriptor.
|
|
89
|
+
*
|
|
90
|
+
* Returns a descriptor containing `clusters` and attribute read/write handlers
|
|
91
|
+
* which the platform will serialize when registering Matter accessories. The
|
|
92
|
+
* default provides an `OnOff` cluster wired to `getState()` / `setState()`.
|
|
93
|
+
*
|
|
94
|
+
* If the Homebridge `api` provides a `matter` namespace it is attached under
|
|
95
|
+
* `_resolved.matter` for callers that need direct access to the Matter API.
|
|
96
|
+
*/
|
|
97
|
+
createMatterAccessory(api: any): any {
|
|
98
|
+
const base: any = {
|
|
99
|
+
id: this.opts.id,
|
|
100
|
+
name: this.opts.name ?? this.opts.type,
|
|
101
|
+
protocol: 'matter',
|
|
102
|
+
clusters: [
|
|
103
|
+
{
|
|
104
|
+
type: 'OnOff',
|
|
105
|
+
clusterId: MATTER_CLUSTER_IDS.OnOff,
|
|
106
|
+
attributes: {
|
|
107
|
+
onOff: {
|
|
108
|
+
read: async () => {
|
|
109
|
+
const s = await this.getState()
|
|
110
|
+
return !!(s && (s.on === true || s.state === 'on' || s.power === 'on'))
|
|
111
|
+
},
|
|
112
|
+
write: async (v: any) => this.setState({ on: !!v }),
|
|
113
|
+
},
|
|
114
|
+
[MATTER_ATTRIBUTE_IDS.OnOff.OnOff]: {
|
|
115
|
+
read: async () => {
|
|
116
|
+
const s = await this.getState()
|
|
117
|
+
return !!(s && (s.on === true || s.state === 'on' || s.power === 'on'))
|
|
118
|
+
},
|
|
119
|
+
write: async (v: any) => this.setState({ on: !!v }),
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
try {
|
|
127
|
+
const matter = api?.matter
|
|
128
|
+
if (matter) {
|
|
129
|
+
base._resolved = {
|
|
130
|
+
matter,
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
} catch (e) {
|
|
134
|
+
// ignore
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
return base
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async destroy(): Promise<void> {}
|
|
141
|
+
}
|