├── .github └── workflows │ └── build.yaml ├── README.md ├── accessory-example-typescript ├── .gitignore ├── LICENSE ├── package-lock.json ├── package.json ├── src │ └── accessory.ts └── tsconfig.json ├── bridged-camera-example-typescript ├── .gitignore ├── LICENSE ├── package-lock.json ├── package.json ├── src │ ├── dynamic-camera-platform.ts │ └── streamingDelegate.ts └── tsconfig.json ├── dynamic-platform-example-typescript ├── .gitignore ├── LICENSE ├── package-lock.json ├── package.json ├── src │ └── dynamic-platform.ts └── tsconfig.json ├── independent-platform-example-typescript ├── .gitignore ├── LICENSE ├── package-lock.json ├── package.json ├── src │ └── independent-platform.ts └── tsconfig.json └── static-platform-example-typescript ├── .gitignore ├── LICENSE ├── package-lock.json ├── package.json ├── src ├── static-platform.ts └── switch-accessory.ts └── tsconfig.json /.github/workflows/build.yaml: -------------------------------------------------------------------------------- 1 | name: Node Build 2 | 3 | on: 4 | push: 5 | branches: [master] 6 | pull_request: 7 | workflow_dispatch: 8 | 9 | jobs: 10 | build: 11 | 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | node_version: [16] 16 | os: [ubuntu-latest] 17 | plugin_dir: [accessory-example-typescript, bridged-camera-example-typescript, dynamic-platform-example-typescript, independent-platform-example-typescript, static-platform-example-typescript] 18 | 19 | runs-on: ${{ matrix.os }} 20 | 21 | steps: 22 | - uses: actions/checkout@v2 23 | - uses: actions/setup-node@v2 24 | with: 25 | node-version: ${{ matrix.node_version }} 26 | registry-url: 'https://registry.npmjs.org' 27 | cache: 'npm' 28 | cache-dependency-path: ${{ matrix.plugin_dir }} 29 | 30 | - name: install 31 | run: npm ci 32 | working-directory: ${{ matrix.plugin_dir }} 33 | env: 34 | CI: true 35 | - name: build 36 | run: npm run build --if-present 37 | working-directory: ${{ matrix.plugin_dir }} 38 | env: 39 | CI: true 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # homebridge-examples 2 | 3 | This repo bundles some example implementations for homebridge plugins. They provide some example code to get 4 | started with. They are also published on npm like regular plugins, so you can easily run them in your local 5 | homebridge instance. Refer to the respective `package.json` for the plugin name and install them as usual. 6 | 7 | The examples are all written in Typescript and thus require at least homebridge `v1.0.0`. 8 | To build a plugin run the following commands in the respective plugin directory. 9 | 10 | Run this command once to install all dependencies required by the plugin: 11 | ``` 12 | npm install 13 | ``` 14 | 15 | After that run the following command to compile the Typescript files into Javascript 16 | (repeat this step every time you change something in the code). 17 | ``` 18 | npm run build 19 | ``` 20 | 21 | 22 | If you're trying to get one of the example plugins to show up in your homebridge installation without installing it 23 | from npm just clone this repo. 24 | Then, just cd into one of the plugin folders and run 25 | ``` 26 | sudo hb-service link 27 | ``` 28 | This creates a symlink from the plugin directory to /var/lib/homebridge/node_modules/plugin_name. 29 | 30 | To undo this run 31 | ``` 32 | sudo hb-service unlink 33 | ``` 34 | 35 | Pay attention to not start homebridge with the --strict-plugin-resolution flag. A standard installation of 36 | homebridge might start it with that flag in a start script, located in /opt/homebridge on linux. 37 | 38 | 39 | If you need inspiration for a plugin written in Javascript you can just run the above commands and look at the 40 | generated Javascript code located in the `./dist` folder. You may need to ignore some code at the beginning of the file 41 | generated by the Typescript compiler. 42 | 43 | ## Examples for different homebridge plugin types 44 | 45 | #### Accessory Plugins 46 | 47 | Accessory plugins are the most basic and simplest plugins for homebridge. They should be used if you only want to 48 | expose a single accessory and don't require any special functionality. 49 | 50 | * [Accessory Plugin](./accessory-example-typescript): A simple Switch accessory. 51 | 52 | #### Platform Plugins: 53 | 54 | Platform plugins are able to expose multiple accessories. Additionally, they are required if you want to use the 55 | Controller API. 56 | 57 | * [Static Platform Plugin](./static-platform-example-typescript): Static platforms know which accessories they want to 58 | expose on start up. The set of accessories cannot change over the lifespan of the plugin. 59 | * [Dynamic Platform Plugin](./dynamic-platform-example-typescript): Dynamic platforms can dynamically add or remove 60 | accessories at runtime. Accessories are fully stored to disk by homebridge, and the exact state is reconstructed on 61 | a reboot. The plugin can store additional context as well. 62 | * [Independent Platform Plugin](./independent-platform-example-typescript): Independent platforms are typically used 63 | when the platform intends to only expose external accessories or provides other functionality while not exposing 64 | an accessory at all. 65 | 66 | ## Other example plugins 67 | 68 | * [Bridged Camera Platform](./bridged-camera-example-typescript) 69 | -------------------------------------------------------------------------------- /accessory-example-typescript/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### HAP-NodeJS files 3 | persist 4 | 5 | ### Node template 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # Diagnostic reports (https://nodejs.org/api/report.html) 15 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | *.seed 21 | *.pid.lock 22 | 23 | # Directory for instrumented libs generated by jscoverage/JSCover 24 | lib-cov 25 | 26 | # Coverage directory used by tools like istanbul 27 | coverage 28 | *.lcov 29 | 30 | # nyc test coverage 31 | .nyc_output 32 | 33 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 34 | .grunt 35 | 36 | # Bower dependency directory (https://bower.io/) 37 | bower_components 38 | 39 | # node-waf configuration 40 | .lock-wscript 41 | 42 | # Compiled binary addons (https://nodejs.org/api/addons.html) 43 | build/Release 44 | 45 | # Dependency directories 46 | node_modules/ 47 | jspm_packages/ 48 | 49 | # Snowpack dependency directory (https://snowpack.dev/) 50 | web_modules/ 51 | 52 | # TypeScript cache 53 | *.tsbuildinfo 54 | 55 | # Optional npm cache directory 56 | .npm 57 | 58 | # Optional eslint cache 59 | .eslintcache 60 | 61 | # Microbundle cache 62 | .rpt2_cache/ 63 | .rts2_cache_cjs/ 64 | .rts2_cache_es/ 65 | .rts2_cache_umd/ 66 | 67 | # Optional REPL history 68 | .node_repl_history 69 | 70 | # Output of 'npm pack' 71 | *.tgz 72 | 73 | # Yarn Integrity file 74 | .yarn-integrity 75 | 76 | # dotenv environment variables file 77 | .env 78 | .env.test 79 | 80 | # parcel-bundler cache (https://parceljs.org/) 81 | .cache 82 | .parcel-cache 83 | 84 | # Next.js build output 85 | .next 86 | 87 | # Nuxt.js build / generate output 88 | .nuxt 89 | dist 90 | 91 | # Gatsby files 92 | .cache/ 93 | # Comment in the public line in if your project uses Gatsby and not Next.js 94 | # https://nextjs.org/blog/next-9-1#public-directory-support 95 | # public 96 | 97 | # vuepress build output 98 | .vuepress/dist 99 | 100 | # Serverless directories 101 | .serverless/ 102 | 103 | # FuseBox cache 104 | .fusebox/ 105 | 106 | # DynamoDB Local files 107 | .dynamodb/ 108 | 109 | # TernJS port file 110 | .tern-port 111 | 112 | # Stores VSCode versions used for testing VSCode extensions 113 | .vscode-test 114 | 115 | # yarn v2 116 | 117 | .yarn/cache 118 | .yarn/unplugged 119 | .yarn/build-state.yml 120 | .pnp.* 121 | 122 | ### VisualStudioCode template 123 | .vscode/* 124 | !.vscode/settings.json 125 | !.vscode/tasks.json 126 | !.vscode/launch.json 127 | !.vscode/extensions.json 128 | *.code-workspace 129 | 130 | # Local History for Visual Studio Code 131 | .history/ 132 | 133 | ### JetBrains template 134 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 135 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 136 | 137 | # User-specific stuff 138 | .idea/**/workspace.xml 139 | .idea/**/tasks.xml 140 | .idea/**/usage.statistics.xml 141 | .idea/**/dictionaries 142 | .idea/**/shelf 143 | 144 | # Generated files 145 | .idea/**/contentModel.xml 146 | 147 | # Sensitive or high-churn files 148 | .idea/**/dataSources/ 149 | .idea/**/dataSources.ids 150 | .idea/**/dataSources.local.xml 151 | .idea/**/sqlDataSources.xml 152 | .idea/**/dynamic.xml 153 | .idea/**/uiDesigner.xml 154 | .idea/**/dbnavigator.xml 155 | 156 | # Gradle 157 | .idea/**/gradle.xml 158 | .idea/**/libraries 159 | 160 | # Gradle and Maven with auto-import 161 | # When using Gradle or Maven with auto-import, you should exclude module files, 162 | # since they will be recreated, and may cause churn. Uncomment if using 163 | # auto-import. 164 | # .idea/artifacts 165 | # .idea/compiler.xml 166 | # .idea/jarRepositories.xml 167 | # .idea/modules.xml 168 | # .idea/*.iml 169 | # .idea/modules 170 | # *.iml 171 | # *.ipr 172 | 173 | # CMake 174 | cmake-build-*/ 175 | 176 | # Mongo Explorer plugin 177 | .idea/**/mongoSettings.xml 178 | 179 | # File-based project format 180 | *.iws 181 | 182 | # IntelliJ 183 | out/ 184 | 185 | # mpeltonen/sbt-idea plugin 186 | .idea_modules/ 187 | 188 | # JIRA plugin 189 | atlassian-ide-plugin.xml 190 | 191 | # Cursive Clojure plugin 192 | .idea/replstate.xml 193 | 194 | # Crashlytics plugin (for Android Studio and IntelliJ) 195 | com_crashlytics_export_strings.xml 196 | crashlytics.properties 197 | crashlytics-build.properties 198 | fabric.properties 199 | 200 | # Editor-based Rest Client 201 | .idea/httpRequests 202 | 203 | # Android studio 3.1+ serialized cache file 204 | .idea/caches/build_file_checksums.ser 205 | 206 | -------------------------------------------------------------------------------- /accessory-example-typescript/LICENSE: -------------------------------------------------------------------------------- 1 | ISC License (ISC) 2 | Copyright (c) 2020 Andreas Bauer 3 | 4 | Permission to use, copy, modify, and/or distribute this software for any 5 | purpose with or without fee is hereby granted, provided that the above 6 | copyright notice and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 9 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 11 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 13 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 | PERFORMANCE OF THIS SOFTWARE. 15 | -------------------------------------------------------------------------------- /accessory-example-typescript/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "homebridge-accessory-example", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "homebridge-accessory-example", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "devDependencies": { 12 | "@types/node": "16.11.7", 13 | "homebridge": "^1.6.1", 14 | "rimraf": "^5.0.0", 15 | "typescript": "^5.0.4" 16 | }, 17 | "engines": { 18 | "homebridge": ">=1.0.0" 19 | } 20 | }, 21 | "node_modules/@homebridge/ciao": { 22 | "version": "1.1.5", 23 | "resolved": "https://registry.npmjs.org/@homebridge/ciao/-/ciao-1.1.5.tgz", 24 | "integrity": "sha512-ZI9tcbPfX2d8oP1PNeLzrZLXISAIDUtJQWk4JVVJKCxktC6tQ3JyWXT9t1FbB5xtl82M1jdCgyAbWbjhUtRWcA==", 25 | "dev": true, 26 | "dependencies": { 27 | "debug": "^4.3.4", 28 | "fast-deep-equal": "^3.1.3", 29 | "source-map-support": "^0.5.21", 30 | "tslib": "^2.4.0" 31 | }, 32 | "bin": { 33 | "ciao-bcs": "lib/bonjour-conformance-testing.js" 34 | } 35 | }, 36 | "node_modules/@homebridge/dbus-native": { 37 | "version": "0.5.1", 38 | "resolved": "https://registry.npmjs.org/@homebridge/dbus-native/-/dbus-native-0.5.1.tgz", 39 | "integrity": "sha512-7xXz3R1W/kcbfQOGp32y4K7etqtowICR1vpx8j85KwPYXbNQrgiZ3zcwDYgDGBWq3FD9xzsW7h4YWJ4vTR2seQ==", 40 | "dev": true, 41 | "dependencies": { 42 | "@homebridge/long": "^5.2.1", 43 | "@homebridge/put": "~0.0.8", 44 | "event-stream": "^4.0.0", 45 | "hexy": "^0.2.10", 46 | "minimist": "^1.2.6", 47 | "safe-buffer": "^5.1.1", 48 | "xml2js": "^0.5.0" 49 | }, 50 | "bin": { 51 | "dbus2js": "bin/dbus2js.js" 52 | } 53 | }, 54 | "node_modules/@homebridge/long": { 55 | "version": "5.2.1", 56 | "resolved": "https://registry.npmjs.org/@homebridge/long/-/long-5.2.1.tgz", 57 | "integrity": "sha512-i5Df8R63XNPCn+Nj1OgAoRdw9e+jHUQb3CNUbvJneI2iu3j4+OtzQj+5PA1Ce+747NR1SPqZSvyvD483dOT3AA==", 58 | "dev": true 59 | }, 60 | "node_modules/@homebridge/put": { 61 | "version": "0.0.8", 62 | "resolved": "https://registry.npmjs.org/@homebridge/put/-/put-0.0.8.tgz", 63 | "integrity": "sha512-mwxLHHqKebOmOSU0tsPEWQSBHGApPhuaqtNpCe7U+AMdsduweANiu64E9SXXUtdpyTjsOpgSMLhD1+kbLHD2gA==", 64 | "dev": true, 65 | "engines": { 66 | "node": ">=0.3.0" 67 | } 68 | }, 69 | "node_modules/@leichtgewicht/ip-codec": { 70 | "version": "2.0.4", 71 | "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", 72 | "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", 73 | "dev": true 74 | }, 75 | "node_modules/@pkgjs/parseargs": { 76 | "version": "0.11.0", 77 | "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", 78 | "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", 79 | "dev": true, 80 | "optional": true, 81 | "engines": { 82 | "node": ">=14" 83 | } 84 | }, 85 | "node_modules/@types/node": { 86 | "version": "16.11.7", 87 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.7.tgz", 88 | "integrity": "sha512-QB5D2sqfSjCmTuWcBWyJ+/44bcjO7VbjSbOE0ucoVbAsSNQc4Lt6QkgkVXkTDwkL4z/beecZNDvVX15D4P8Jbw==", 89 | "dev": true 90 | }, 91 | "node_modules/ansi-regex": { 92 | "version": "5.0.1", 93 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 94 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 95 | "dev": true, 96 | "engines": { 97 | "node": ">=8" 98 | } 99 | }, 100 | "node_modules/ansi-styles": { 101 | "version": "4.3.0", 102 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 103 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 104 | "dev": true, 105 | "dependencies": { 106 | "color-convert": "^2.0.1" 107 | }, 108 | "engines": { 109 | "node": ">=8" 110 | }, 111 | "funding": { 112 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 113 | } 114 | }, 115 | "node_modules/array-buffer-byte-length": { 116 | "version": "1.0.0", 117 | "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", 118 | "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", 119 | "dev": true, 120 | "dependencies": { 121 | "call-bind": "^1.0.2", 122 | "is-array-buffer": "^3.0.1" 123 | }, 124 | "funding": { 125 | "url": "https://github.com/sponsors/ljharb" 126 | } 127 | }, 128 | "node_modules/array-flatten": { 129 | "version": "2.1.2", 130 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", 131 | "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", 132 | "dev": true 133 | }, 134 | "node_modules/available-typed-arrays": { 135 | "version": "1.0.5", 136 | "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", 137 | "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", 138 | "dev": true, 139 | "engines": { 140 | "node": ">= 0.4" 141 | }, 142 | "funding": { 143 | "url": "https://github.com/sponsors/ljharb" 144 | } 145 | }, 146 | "node_modules/balanced-match": { 147 | "version": "1.0.2", 148 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 149 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 150 | "dev": true 151 | }, 152 | "node_modules/bonjour-hap": { 153 | "version": "3.6.4", 154 | "resolved": "https://registry.npmjs.org/bonjour-hap/-/bonjour-hap-3.6.4.tgz", 155 | "integrity": "sha512-a76r95/qTAP5hOEZZhRoiosyFSVPPRSVev09Jh8yDf3JDKyrzELLf0vpQCuEXFueb9DcV9UJf2Jv3dktyuPBng==", 156 | "dev": true, 157 | "dependencies": { 158 | "array-flatten": "^2.1.2", 159 | "deep-equal": "^2.0.5", 160 | "ip": "^1.1.8", 161 | "multicast-dns": "^7.2.5", 162 | "multicast-dns-service-types": "^1.1.0" 163 | } 164 | }, 165 | "node_modules/brace-expansion": { 166 | "version": "2.0.1", 167 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 168 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 169 | "dev": true, 170 | "dependencies": { 171 | "balanced-match": "^1.0.0" 172 | } 173 | }, 174 | "node_modules/buffer-from": { 175 | "version": "1.1.2", 176 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", 177 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", 178 | "dev": true 179 | }, 180 | "node_modules/call-bind": { 181 | "version": "1.0.2", 182 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 183 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 184 | "dev": true, 185 | "dependencies": { 186 | "function-bind": "^1.1.1", 187 | "get-intrinsic": "^1.0.2" 188 | }, 189 | "funding": { 190 | "url": "https://github.com/sponsors/ljharb" 191 | } 192 | }, 193 | "node_modules/chalk": { 194 | "version": "4.1.2", 195 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 196 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 197 | "dev": true, 198 | "dependencies": { 199 | "ansi-styles": "^4.1.0", 200 | "supports-color": "^7.1.0" 201 | }, 202 | "engines": { 203 | "node": ">=10" 204 | }, 205 | "funding": { 206 | "url": "https://github.com/chalk/chalk?sponsor=1" 207 | } 208 | }, 209 | "node_modules/cliui": { 210 | "version": "8.0.1", 211 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", 212 | "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", 213 | "dev": true, 214 | "dependencies": { 215 | "string-width": "^4.2.0", 216 | "strip-ansi": "^6.0.1", 217 | "wrap-ansi": "^7.0.0" 218 | }, 219 | "engines": { 220 | "node": ">=12" 221 | } 222 | }, 223 | "node_modules/color-convert": { 224 | "version": "2.0.1", 225 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 226 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 227 | "dev": true, 228 | "dependencies": { 229 | "color-name": "~1.1.4" 230 | }, 231 | "engines": { 232 | "node": ">=7.0.0" 233 | } 234 | }, 235 | "node_modules/color-name": { 236 | "version": "1.1.4", 237 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 238 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 239 | "dev": true 240 | }, 241 | "node_modules/commander": { 242 | "version": "5.1.0", 243 | "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", 244 | "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", 245 | "dev": true, 246 | "engines": { 247 | "node": ">= 6" 248 | } 249 | }, 250 | "node_modules/cross-spawn": { 251 | "version": "7.0.3", 252 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 253 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 254 | "dev": true, 255 | "dependencies": { 256 | "path-key": "^3.1.0", 257 | "shebang-command": "^2.0.0", 258 | "which": "^2.0.1" 259 | }, 260 | "engines": { 261 | "node": ">= 8" 262 | } 263 | }, 264 | "node_modules/debug": { 265 | "version": "4.3.4", 266 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 267 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 268 | "dev": true, 269 | "dependencies": { 270 | "ms": "2.1.2" 271 | }, 272 | "engines": { 273 | "node": ">=6.0" 274 | }, 275 | "peerDependenciesMeta": { 276 | "supports-color": { 277 | "optional": true 278 | } 279 | } 280 | }, 281 | "node_modules/deep-equal": { 282 | "version": "2.2.1", 283 | "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.1.tgz", 284 | "integrity": "sha512-lKdkdV6EOGoVn65XaOsPdH4rMxTZOnmFyuIkMjM1i5HHCbfjC97dawgTAy0deYNfuqUqW+Q5VrVaQYtUpSd6yQ==", 285 | "dev": true, 286 | "dependencies": { 287 | "array-buffer-byte-length": "^1.0.0", 288 | "call-bind": "^1.0.2", 289 | "es-get-iterator": "^1.1.3", 290 | "get-intrinsic": "^1.2.0", 291 | "is-arguments": "^1.1.1", 292 | "is-array-buffer": "^3.0.2", 293 | "is-date-object": "^1.0.5", 294 | "is-regex": "^1.1.4", 295 | "is-shared-array-buffer": "^1.0.2", 296 | "isarray": "^2.0.5", 297 | "object-is": "^1.1.5", 298 | "object-keys": "^1.1.1", 299 | "object.assign": "^4.1.4", 300 | "regexp.prototype.flags": "^1.5.0", 301 | "side-channel": "^1.0.4", 302 | "which-boxed-primitive": "^1.0.2", 303 | "which-collection": "^1.0.1", 304 | "which-typed-array": "^1.1.9" 305 | }, 306 | "funding": { 307 | "url": "https://github.com/sponsors/ljharb" 308 | } 309 | }, 310 | "node_modules/define-properties": { 311 | "version": "1.2.0", 312 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", 313 | "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", 314 | "dev": true, 315 | "dependencies": { 316 | "has-property-descriptors": "^1.0.0", 317 | "object-keys": "^1.1.1" 318 | }, 319 | "engines": { 320 | "node": ">= 0.4" 321 | }, 322 | "funding": { 323 | "url": "https://github.com/sponsors/ljharb" 324 | } 325 | }, 326 | "node_modules/dns-packet": { 327 | "version": "5.6.0", 328 | "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.0.tgz", 329 | "integrity": "sha512-rza3UH1LwdHh9qyPXp8lkwpjSNk/AMD3dPytUoRoqnypDUhY0xvbdmVhWOfxO68frEfV9BU8V12Ez7ZsHGZpCQ==", 330 | "dev": true, 331 | "dependencies": { 332 | "@leichtgewicht/ip-codec": "^2.0.1" 333 | }, 334 | "engines": { 335 | "node": ">=6" 336 | } 337 | }, 338 | "node_modules/duplexer": { 339 | "version": "0.1.2", 340 | "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", 341 | "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", 342 | "dev": true 343 | }, 344 | "node_modules/emoji-regex": { 345 | "version": "8.0.0", 346 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 347 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 348 | "dev": true 349 | }, 350 | "node_modules/es-get-iterator": { 351 | "version": "1.1.3", 352 | "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", 353 | "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", 354 | "dev": true, 355 | "dependencies": { 356 | "call-bind": "^1.0.2", 357 | "get-intrinsic": "^1.1.3", 358 | "has-symbols": "^1.0.3", 359 | "is-arguments": "^1.1.1", 360 | "is-map": "^2.0.2", 361 | "is-set": "^2.0.2", 362 | "is-string": "^1.0.7", 363 | "isarray": "^2.0.5", 364 | "stop-iteration-iterator": "^1.0.0" 365 | }, 366 | "funding": { 367 | "url": "https://github.com/sponsors/ljharb" 368 | } 369 | }, 370 | "node_modules/event-stream": { 371 | "version": "4.0.1", 372 | "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz", 373 | "integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==", 374 | "dev": true, 375 | "dependencies": { 376 | "duplexer": "^0.1.1", 377 | "from": "^0.1.7", 378 | "map-stream": "0.0.7", 379 | "pause-stream": "^0.0.11", 380 | "split": "^1.0.1", 381 | "stream-combiner": "^0.2.2", 382 | "through": "^2.3.8" 383 | } 384 | }, 385 | "node_modules/fast-deep-equal": { 386 | "version": "3.1.3", 387 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 388 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 389 | "dev": true 390 | }, 391 | "node_modules/fast-srp-hap": { 392 | "version": "2.0.4", 393 | "resolved": "https://registry.npmjs.org/fast-srp-hap/-/fast-srp-hap-2.0.4.tgz", 394 | "integrity": "sha512-lHRYYaaIbMrhZtsdGTwPN82UbqD9Bv8QfOlKs+Dz6YRnByZifOh93EYmf2iEWFtkOEIqR2IK8cFD0UN5wLIWBQ==", 395 | "dev": true, 396 | "engines": { 397 | "node": ">=10.17.0" 398 | } 399 | }, 400 | "node_modules/for-each": { 401 | "version": "0.3.3", 402 | "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", 403 | "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", 404 | "dev": true, 405 | "dependencies": { 406 | "is-callable": "^1.1.3" 407 | } 408 | }, 409 | "node_modules/foreground-child": { 410 | "version": "3.1.1", 411 | "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", 412 | "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", 413 | "dev": true, 414 | "dependencies": { 415 | "cross-spawn": "^7.0.0", 416 | "signal-exit": "^4.0.1" 417 | }, 418 | "engines": { 419 | "node": ">=14" 420 | }, 421 | "funding": { 422 | "url": "https://github.com/sponsors/isaacs" 423 | } 424 | }, 425 | "node_modules/from": { 426 | "version": "0.1.7", 427 | "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", 428 | "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==", 429 | "dev": true 430 | }, 431 | "node_modules/fs-extra": { 432 | "version": "10.1.0", 433 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", 434 | "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", 435 | "dev": true, 436 | "dependencies": { 437 | "graceful-fs": "^4.2.0", 438 | "jsonfile": "^6.0.1", 439 | "universalify": "^2.0.0" 440 | }, 441 | "engines": { 442 | "node": ">=12" 443 | } 444 | }, 445 | "node_modules/function-bind": { 446 | "version": "1.1.1", 447 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 448 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 449 | "dev": true 450 | }, 451 | "node_modules/functions-have-names": { 452 | "version": "1.2.3", 453 | "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", 454 | "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", 455 | "dev": true, 456 | "funding": { 457 | "url": "https://github.com/sponsors/ljharb" 458 | } 459 | }, 460 | "node_modules/futoin-hkdf": { 461 | "version": "1.4.3", 462 | "resolved": "https://registry.npmjs.org/futoin-hkdf/-/futoin-hkdf-1.4.3.tgz", 463 | "integrity": "sha512-K4MIe2xSVRMYxsA4w0ap5fp1C2hA9StA2Ad1JZHX57VMCdHIRB5BSrd1FhuadTQG9MkjggaTCrw7v5XXFyY3/w==", 464 | "dev": true, 465 | "engines": { 466 | "node": ">=8" 467 | } 468 | }, 469 | "node_modules/get-intrinsic": { 470 | "version": "1.2.0", 471 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", 472 | "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", 473 | "dev": true, 474 | "dependencies": { 475 | "function-bind": "^1.1.1", 476 | "has": "^1.0.3", 477 | "has-symbols": "^1.0.3" 478 | }, 479 | "funding": { 480 | "url": "https://github.com/sponsors/ljharb" 481 | } 482 | }, 483 | "node_modules/glob": { 484 | "version": "10.2.2", 485 | "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.2.tgz", 486 | "integrity": "sha512-Xsa0BcxIC6th9UwNjZkhrMtNo/MnyRL8jGCP+uEwhA5oFOCY1f2s1/oNKY47xQ0Bg5nkjsfAEIej1VeH62bDDQ==", 487 | "dev": true, 488 | "dependencies": { 489 | "foreground-child": "^3.1.0", 490 | "jackspeak": "^2.0.3", 491 | "minimatch": "^9.0.0", 492 | "minipass": "^5.0.0", 493 | "path-scurry": "^1.7.0" 494 | }, 495 | "bin": { 496 | "glob": "dist/cjs/src/bin.js" 497 | }, 498 | "engines": { 499 | "node": ">=16 || 14 >=14.17" 500 | }, 501 | "funding": { 502 | "url": "https://github.com/sponsors/isaacs" 503 | } 504 | }, 505 | "node_modules/gopd": { 506 | "version": "1.0.1", 507 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", 508 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", 509 | "dev": true, 510 | "dependencies": { 511 | "get-intrinsic": "^1.1.3" 512 | }, 513 | "funding": { 514 | "url": "https://github.com/sponsors/ljharb" 515 | } 516 | }, 517 | "node_modules/graceful-fs": { 518 | "version": "4.2.11", 519 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", 520 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", 521 | "dev": true 522 | }, 523 | "node_modules/hap-nodejs": { 524 | "version": "0.11.1", 525 | "resolved": "https://registry.npmjs.org/hap-nodejs/-/hap-nodejs-0.11.1.tgz", 526 | "integrity": "sha512-hJuGyjng2jlzhZsviWCldaokT7l7BE3iGmWdlE6DNmQFDTmiBN3deNksAZ2nt7qp5jYEv7ZUvW7WBZqJsLh3ww==", 527 | "dev": true, 528 | "dependencies": { 529 | "@homebridge/ciao": "^1.1.5", 530 | "@homebridge/dbus-native": "^0.5.1", 531 | "bonjour-hap": "~3.6.4", 532 | "debug": "^4.3.4", 533 | "fast-srp-hap": "~2.0.4", 534 | "futoin-hkdf": "~1.4.3", 535 | "node-persist": "^0.0.11", 536 | "source-map-support": "^0.5.21", 537 | "tslib": "^2.4.0", 538 | "tweetnacl": "^1.0.3" 539 | }, 540 | "engines": { 541 | "node": ">=10.17.0" 542 | } 543 | }, 544 | "node_modules/has": { 545 | "version": "1.0.3", 546 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 547 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 548 | "dev": true, 549 | "dependencies": { 550 | "function-bind": "^1.1.1" 551 | }, 552 | "engines": { 553 | "node": ">= 0.4.0" 554 | } 555 | }, 556 | "node_modules/has-bigints": { 557 | "version": "1.0.2", 558 | "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", 559 | "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", 560 | "dev": true, 561 | "funding": { 562 | "url": "https://github.com/sponsors/ljharb" 563 | } 564 | }, 565 | "node_modules/has-flag": { 566 | "version": "4.0.0", 567 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 568 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 569 | "dev": true, 570 | "engines": { 571 | "node": ">=8" 572 | } 573 | }, 574 | "node_modules/has-property-descriptors": { 575 | "version": "1.0.0", 576 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", 577 | "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", 578 | "dev": true, 579 | "dependencies": { 580 | "get-intrinsic": "^1.1.1" 581 | }, 582 | "funding": { 583 | "url": "https://github.com/sponsors/ljharb" 584 | } 585 | }, 586 | "node_modules/has-symbols": { 587 | "version": "1.0.3", 588 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 589 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 590 | "dev": true, 591 | "engines": { 592 | "node": ">= 0.4" 593 | }, 594 | "funding": { 595 | "url": "https://github.com/sponsors/ljharb" 596 | } 597 | }, 598 | "node_modules/has-tostringtag": { 599 | "version": "1.0.0", 600 | "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", 601 | "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", 602 | "dev": true, 603 | "dependencies": { 604 | "has-symbols": "^1.0.2" 605 | }, 606 | "engines": { 607 | "node": ">= 0.4" 608 | }, 609 | "funding": { 610 | "url": "https://github.com/sponsors/ljharb" 611 | } 612 | }, 613 | "node_modules/hexy": { 614 | "version": "0.2.11", 615 | "resolved": "https://registry.npmjs.org/hexy/-/hexy-0.2.11.tgz", 616 | "integrity": "sha512-ciq6hFsSG/Bpt2DmrZJtv+56zpPdnq+NQ4ijEFrveKN0ZG1mhl/LdT1NQZ9se6ty1fACcI4d4vYqC9v8EYpH2A==", 617 | "dev": true, 618 | "bin": { 619 | "hexy": "bin/hexy_cmd.js" 620 | } 621 | }, 622 | "node_modules/homebridge": { 623 | "version": "1.6.1", 624 | "resolved": "https://registry.npmjs.org/homebridge/-/homebridge-1.6.1.tgz", 625 | "integrity": "sha512-hDhSaBDHFbB8wQQuZKbistYj1gjTIcNWmusqgEUb0Umk76Hs+G6VKRTkOEEVuxRaQWoK5hRM5rJTsCGAMCj5cA==", 626 | "dev": true, 627 | "dependencies": { 628 | "chalk": "^4.1.2", 629 | "commander": "5.1.0", 630 | "fs-extra": "^10.1.0", 631 | "hap-nodejs": "~0.11.1", 632 | "qrcode-terminal": "^0.12.0", 633 | "semver": "^7.3.7", 634 | "source-map-support": "^0.5.21" 635 | }, 636 | "bin": { 637 | "homebridge": "bin/homebridge" 638 | }, 639 | "engines": { 640 | "node": ">=10.17.0" 641 | } 642 | }, 643 | "node_modules/internal-slot": { 644 | "version": "1.0.5", 645 | "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", 646 | "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", 647 | "dev": true, 648 | "dependencies": { 649 | "get-intrinsic": "^1.2.0", 650 | "has": "^1.0.3", 651 | "side-channel": "^1.0.4" 652 | }, 653 | "engines": { 654 | "node": ">= 0.4" 655 | } 656 | }, 657 | "node_modules/ip": { 658 | "version": "1.1.8", 659 | "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", 660 | "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", 661 | "dev": true 662 | }, 663 | "node_modules/is-arguments": { 664 | "version": "1.1.1", 665 | "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", 666 | "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", 667 | "dev": true, 668 | "dependencies": { 669 | "call-bind": "^1.0.2", 670 | "has-tostringtag": "^1.0.0" 671 | }, 672 | "engines": { 673 | "node": ">= 0.4" 674 | }, 675 | "funding": { 676 | "url": "https://github.com/sponsors/ljharb" 677 | } 678 | }, 679 | "node_modules/is-array-buffer": { 680 | "version": "3.0.2", 681 | "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", 682 | "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", 683 | "dev": true, 684 | "dependencies": { 685 | "call-bind": "^1.0.2", 686 | "get-intrinsic": "^1.2.0", 687 | "is-typed-array": "^1.1.10" 688 | }, 689 | "funding": { 690 | "url": "https://github.com/sponsors/ljharb" 691 | } 692 | }, 693 | "node_modules/is-bigint": { 694 | "version": "1.0.4", 695 | "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", 696 | "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", 697 | "dev": true, 698 | "dependencies": { 699 | "has-bigints": "^1.0.1" 700 | }, 701 | "funding": { 702 | "url": "https://github.com/sponsors/ljharb" 703 | } 704 | }, 705 | "node_modules/is-boolean-object": { 706 | "version": "1.1.2", 707 | "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", 708 | "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", 709 | "dev": true, 710 | "dependencies": { 711 | "call-bind": "^1.0.2", 712 | "has-tostringtag": "^1.0.0" 713 | }, 714 | "engines": { 715 | "node": ">= 0.4" 716 | }, 717 | "funding": { 718 | "url": "https://github.com/sponsors/ljharb" 719 | } 720 | }, 721 | "node_modules/is-callable": { 722 | "version": "1.2.7", 723 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", 724 | "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", 725 | "dev": true, 726 | "engines": { 727 | "node": ">= 0.4" 728 | }, 729 | "funding": { 730 | "url": "https://github.com/sponsors/ljharb" 731 | } 732 | }, 733 | "node_modules/is-date-object": { 734 | "version": "1.0.5", 735 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", 736 | "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", 737 | "dev": true, 738 | "dependencies": { 739 | "has-tostringtag": "^1.0.0" 740 | }, 741 | "engines": { 742 | "node": ">= 0.4" 743 | }, 744 | "funding": { 745 | "url": "https://github.com/sponsors/ljharb" 746 | } 747 | }, 748 | "node_modules/is-fullwidth-code-point": { 749 | "version": "3.0.0", 750 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 751 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 752 | "dev": true, 753 | "engines": { 754 | "node": ">=8" 755 | } 756 | }, 757 | "node_modules/is-map": { 758 | "version": "2.0.2", 759 | "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", 760 | "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", 761 | "dev": true, 762 | "funding": { 763 | "url": "https://github.com/sponsors/ljharb" 764 | } 765 | }, 766 | "node_modules/is-number-object": { 767 | "version": "1.0.7", 768 | "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", 769 | "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", 770 | "dev": true, 771 | "dependencies": { 772 | "has-tostringtag": "^1.0.0" 773 | }, 774 | "engines": { 775 | "node": ">= 0.4" 776 | }, 777 | "funding": { 778 | "url": "https://github.com/sponsors/ljharb" 779 | } 780 | }, 781 | "node_modules/is-regex": { 782 | "version": "1.1.4", 783 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", 784 | "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", 785 | "dev": true, 786 | "dependencies": { 787 | "call-bind": "^1.0.2", 788 | "has-tostringtag": "^1.0.0" 789 | }, 790 | "engines": { 791 | "node": ">= 0.4" 792 | }, 793 | "funding": { 794 | "url": "https://github.com/sponsors/ljharb" 795 | } 796 | }, 797 | "node_modules/is-set": { 798 | "version": "2.0.2", 799 | "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", 800 | "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", 801 | "dev": true, 802 | "funding": { 803 | "url": "https://github.com/sponsors/ljharb" 804 | } 805 | }, 806 | "node_modules/is-shared-array-buffer": { 807 | "version": "1.0.2", 808 | "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", 809 | "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", 810 | "dev": true, 811 | "dependencies": { 812 | "call-bind": "^1.0.2" 813 | }, 814 | "funding": { 815 | "url": "https://github.com/sponsors/ljharb" 816 | } 817 | }, 818 | "node_modules/is-string": { 819 | "version": "1.0.7", 820 | "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", 821 | "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", 822 | "dev": true, 823 | "dependencies": { 824 | "has-tostringtag": "^1.0.0" 825 | }, 826 | "engines": { 827 | "node": ">= 0.4" 828 | }, 829 | "funding": { 830 | "url": "https://github.com/sponsors/ljharb" 831 | } 832 | }, 833 | "node_modules/is-symbol": { 834 | "version": "1.0.4", 835 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", 836 | "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", 837 | "dev": true, 838 | "dependencies": { 839 | "has-symbols": "^1.0.2" 840 | }, 841 | "engines": { 842 | "node": ">= 0.4" 843 | }, 844 | "funding": { 845 | "url": "https://github.com/sponsors/ljharb" 846 | } 847 | }, 848 | "node_modules/is-typed-array": { 849 | "version": "1.1.10", 850 | "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", 851 | "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", 852 | "dev": true, 853 | "dependencies": { 854 | "available-typed-arrays": "^1.0.5", 855 | "call-bind": "^1.0.2", 856 | "for-each": "^0.3.3", 857 | "gopd": "^1.0.1", 858 | "has-tostringtag": "^1.0.0" 859 | }, 860 | "engines": { 861 | "node": ">= 0.4" 862 | }, 863 | "funding": { 864 | "url": "https://github.com/sponsors/ljharb" 865 | } 866 | }, 867 | "node_modules/is-weakmap": { 868 | "version": "2.0.1", 869 | "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", 870 | "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", 871 | "dev": true, 872 | "funding": { 873 | "url": "https://github.com/sponsors/ljharb" 874 | } 875 | }, 876 | "node_modules/is-weakset": { 877 | "version": "2.0.2", 878 | "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", 879 | "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", 880 | "dev": true, 881 | "dependencies": { 882 | "call-bind": "^1.0.2", 883 | "get-intrinsic": "^1.1.1" 884 | }, 885 | "funding": { 886 | "url": "https://github.com/sponsors/ljharb" 887 | } 888 | }, 889 | "node_modules/isarray": { 890 | "version": "2.0.5", 891 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", 892 | "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", 893 | "dev": true 894 | }, 895 | "node_modules/isexe": { 896 | "version": "2.0.0", 897 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 898 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 899 | "dev": true 900 | }, 901 | "node_modules/jackspeak": { 902 | "version": "2.1.1", 903 | "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.1.1.tgz", 904 | "integrity": "sha512-juf9stUEwUaILepraGOWIJTLwg48bUnBmRqd2ln2Os1sW987zeoj/hzhbvRB95oMuS2ZTpjULmdwHNX4rzZIZw==", 905 | "dev": true, 906 | "dependencies": { 907 | "cliui": "^8.0.1" 908 | }, 909 | "engines": { 910 | "node": ">=14" 911 | }, 912 | "funding": { 913 | "url": "https://github.com/sponsors/isaacs" 914 | }, 915 | "optionalDependencies": { 916 | "@pkgjs/parseargs": "^0.11.0" 917 | } 918 | }, 919 | "node_modules/jsonfile": { 920 | "version": "6.1.0", 921 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", 922 | "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", 923 | "dev": true, 924 | "dependencies": { 925 | "universalify": "^2.0.0" 926 | }, 927 | "optionalDependencies": { 928 | "graceful-fs": "^4.1.6" 929 | } 930 | }, 931 | "node_modules/lru-cache": { 932 | "version": "9.1.1", 933 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.1.tgz", 934 | "integrity": "sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A==", 935 | "dev": true, 936 | "engines": { 937 | "node": "14 || >=16.14" 938 | } 939 | }, 940 | "node_modules/map-stream": { 941 | "version": "0.0.7", 942 | "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", 943 | "integrity": "sha512-C0X0KQmGm3N2ftbTGBhSyuydQ+vV1LC3f3zPvT3RXHXNZrvfPZcoXp/N5DOa8vedX/rTMm2CjTtivFg2STJMRQ==", 944 | "dev": true 945 | }, 946 | "node_modules/minimatch": { 947 | "version": "9.0.0", 948 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", 949 | "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", 950 | "dev": true, 951 | "dependencies": { 952 | "brace-expansion": "^2.0.1" 953 | }, 954 | "engines": { 955 | "node": ">=16 || 14 >=14.17" 956 | }, 957 | "funding": { 958 | "url": "https://github.com/sponsors/isaacs" 959 | } 960 | }, 961 | "node_modules/minimist": { 962 | "version": "1.2.8", 963 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 964 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", 965 | "dev": true, 966 | "funding": { 967 | "url": "https://github.com/sponsors/ljharb" 968 | } 969 | }, 970 | "node_modules/minipass": { 971 | "version": "5.0.0", 972 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", 973 | "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", 974 | "dev": true, 975 | "engines": { 976 | "node": ">=8" 977 | } 978 | }, 979 | "node_modules/mkdirp": { 980 | "version": "0.5.6", 981 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", 982 | "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", 983 | "dev": true, 984 | "dependencies": { 985 | "minimist": "^1.2.6" 986 | }, 987 | "bin": { 988 | "mkdirp": "bin/cmd.js" 989 | } 990 | }, 991 | "node_modules/ms": { 992 | "version": "2.1.2", 993 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 994 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 995 | "dev": true 996 | }, 997 | "node_modules/multicast-dns": { 998 | "version": "7.2.5", 999 | "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", 1000 | "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", 1001 | "dev": true, 1002 | "dependencies": { 1003 | "dns-packet": "^5.2.2", 1004 | "thunky": "^1.0.2" 1005 | }, 1006 | "bin": { 1007 | "multicast-dns": "cli.js" 1008 | } 1009 | }, 1010 | "node_modules/multicast-dns-service-types": { 1011 | "version": "1.1.0", 1012 | "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", 1013 | "integrity": "sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ==", 1014 | "dev": true 1015 | }, 1016 | "node_modules/node-persist": { 1017 | "version": "0.0.11", 1018 | "resolved": "https://registry.npmjs.org/node-persist/-/node-persist-0.0.11.tgz", 1019 | "integrity": "sha512-J3EPzQDgPxPBID7TqHSd5KkpTULFqJUvYDoISfOWg9EihpeVCH3b6YQeDeubzVuc4e6+aiVmkz2sdkWI4K+ghA==", 1020 | "dev": true, 1021 | "dependencies": { 1022 | "mkdirp": "~0.5.1", 1023 | "q": "~1.1.1" 1024 | } 1025 | }, 1026 | "node_modules/object-inspect": { 1027 | "version": "1.12.3", 1028 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", 1029 | "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", 1030 | "dev": true, 1031 | "funding": { 1032 | "url": "https://github.com/sponsors/ljharb" 1033 | } 1034 | }, 1035 | "node_modules/object-is": { 1036 | "version": "1.1.5", 1037 | "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", 1038 | "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", 1039 | "dev": true, 1040 | "dependencies": { 1041 | "call-bind": "^1.0.2", 1042 | "define-properties": "^1.1.3" 1043 | }, 1044 | "engines": { 1045 | "node": ">= 0.4" 1046 | }, 1047 | "funding": { 1048 | "url": "https://github.com/sponsors/ljharb" 1049 | } 1050 | }, 1051 | "node_modules/object-keys": { 1052 | "version": "1.1.1", 1053 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 1054 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 1055 | "dev": true, 1056 | "engines": { 1057 | "node": ">= 0.4" 1058 | } 1059 | }, 1060 | "node_modules/object.assign": { 1061 | "version": "4.1.4", 1062 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", 1063 | "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", 1064 | "dev": true, 1065 | "dependencies": { 1066 | "call-bind": "^1.0.2", 1067 | "define-properties": "^1.1.4", 1068 | "has-symbols": "^1.0.3", 1069 | "object-keys": "^1.1.1" 1070 | }, 1071 | "engines": { 1072 | "node": ">= 0.4" 1073 | }, 1074 | "funding": { 1075 | "url": "https://github.com/sponsors/ljharb" 1076 | } 1077 | }, 1078 | "node_modules/path-key": { 1079 | "version": "3.1.1", 1080 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 1081 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 1082 | "dev": true, 1083 | "engines": { 1084 | "node": ">=8" 1085 | } 1086 | }, 1087 | "node_modules/path-scurry": { 1088 | "version": "1.7.0", 1089 | "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.7.0.tgz", 1090 | "integrity": "sha512-UkZUeDjczjYRE495+9thsgcVgsaCPkaw80slmfVFgllxY+IO8ubTsOpFVjDPROBqJdHfVPUFRHPBV/WciOVfWg==", 1091 | "dev": true, 1092 | "dependencies": { 1093 | "lru-cache": "^9.0.0", 1094 | "minipass": "^5.0.0" 1095 | }, 1096 | "engines": { 1097 | "node": ">=16 || 14 >=14.17" 1098 | }, 1099 | "funding": { 1100 | "url": "https://github.com/sponsors/isaacs" 1101 | } 1102 | }, 1103 | "node_modules/pause-stream": { 1104 | "version": "0.0.11", 1105 | "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", 1106 | "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", 1107 | "dev": true, 1108 | "dependencies": { 1109 | "through": "~2.3" 1110 | } 1111 | }, 1112 | "node_modules/q": { 1113 | "version": "1.1.2", 1114 | "resolved": "https://registry.npmjs.org/q/-/q-1.1.2.tgz", 1115 | "integrity": "sha512-ROtylwux7Vkc4C07oKE/ReigUmb33kVoLtcR4SJ1QVqwaZkBEDL3vX4/kwFzIERQ5PfCl0XafbU8u2YUhyGgVA==", 1116 | "dev": true, 1117 | "engines": { 1118 | "node": ">=0.6.0", 1119 | "teleport": ">=0.2.0" 1120 | } 1121 | }, 1122 | "node_modules/qrcode-terminal": { 1123 | "version": "0.12.0", 1124 | "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz", 1125 | "integrity": "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==", 1126 | "dev": true, 1127 | "bin": { 1128 | "qrcode-terminal": "bin/qrcode-terminal.js" 1129 | } 1130 | }, 1131 | "node_modules/regexp.prototype.flags": { 1132 | "version": "1.5.0", 1133 | "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", 1134 | "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", 1135 | "dev": true, 1136 | "dependencies": { 1137 | "call-bind": "^1.0.2", 1138 | "define-properties": "^1.2.0", 1139 | "functions-have-names": "^1.2.3" 1140 | }, 1141 | "engines": { 1142 | "node": ">= 0.4" 1143 | }, 1144 | "funding": { 1145 | "url": "https://github.com/sponsors/ljharb" 1146 | } 1147 | }, 1148 | "node_modules/rimraf": { 1149 | "version": "5.0.0", 1150 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.0.tgz", 1151 | "integrity": "sha512-Jf9llaP+RvaEVS5nPShYFhtXIrb3LRKP281ib3So0KkeZKo2wIKyq0Re7TOSwanasA423PSr6CCIL4bP6T040g==", 1152 | "dev": true, 1153 | "dependencies": { 1154 | "glob": "^10.0.0" 1155 | }, 1156 | "bin": { 1157 | "rimraf": "dist/cjs/src/bin.js" 1158 | }, 1159 | "engines": { 1160 | "node": ">=14" 1161 | }, 1162 | "funding": { 1163 | "url": "https://github.com/sponsors/isaacs" 1164 | } 1165 | }, 1166 | "node_modules/safe-buffer": { 1167 | "version": "5.2.1", 1168 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1169 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 1170 | "dev": true, 1171 | "funding": [ 1172 | { 1173 | "type": "github", 1174 | "url": "https://github.com/sponsors/feross" 1175 | }, 1176 | { 1177 | "type": "patreon", 1178 | "url": "https://www.patreon.com/feross" 1179 | }, 1180 | { 1181 | "type": "consulting", 1182 | "url": "https://feross.org/support" 1183 | } 1184 | ] 1185 | }, 1186 | "node_modules/sax": { 1187 | "version": "1.2.4", 1188 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", 1189 | "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", 1190 | "dev": true 1191 | }, 1192 | "node_modules/semver": { 1193 | "version": "7.5.0", 1194 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", 1195 | "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", 1196 | "dev": true, 1197 | "dependencies": { 1198 | "lru-cache": "^6.0.0" 1199 | }, 1200 | "bin": { 1201 | "semver": "bin/semver.js" 1202 | }, 1203 | "engines": { 1204 | "node": ">=10" 1205 | } 1206 | }, 1207 | "node_modules/semver/node_modules/lru-cache": { 1208 | "version": "6.0.0", 1209 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 1210 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 1211 | "dev": true, 1212 | "dependencies": { 1213 | "yallist": "^4.0.0" 1214 | }, 1215 | "engines": { 1216 | "node": ">=10" 1217 | } 1218 | }, 1219 | "node_modules/shebang-command": { 1220 | "version": "2.0.0", 1221 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 1222 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 1223 | "dev": true, 1224 | "dependencies": { 1225 | "shebang-regex": "^3.0.0" 1226 | }, 1227 | "engines": { 1228 | "node": ">=8" 1229 | } 1230 | }, 1231 | "node_modules/shebang-regex": { 1232 | "version": "3.0.0", 1233 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 1234 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 1235 | "dev": true, 1236 | "engines": { 1237 | "node": ">=8" 1238 | } 1239 | }, 1240 | "node_modules/side-channel": { 1241 | "version": "1.0.4", 1242 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 1243 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 1244 | "dev": true, 1245 | "dependencies": { 1246 | "call-bind": "^1.0.0", 1247 | "get-intrinsic": "^1.0.2", 1248 | "object-inspect": "^1.9.0" 1249 | }, 1250 | "funding": { 1251 | "url": "https://github.com/sponsors/ljharb" 1252 | } 1253 | }, 1254 | "node_modules/signal-exit": { 1255 | "version": "4.0.1", 1256 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.1.tgz", 1257 | "integrity": "sha512-uUWsN4aOxJAS8KOuf3QMyFtgm1pkb6I+KRZbRF/ghdf5T7sM+B1lLLzPDxswUjkmHyxQAVzEgG35E3NzDM9GVw==", 1258 | "dev": true, 1259 | "engines": { 1260 | "node": ">=14" 1261 | }, 1262 | "funding": { 1263 | "url": "https://github.com/sponsors/isaacs" 1264 | } 1265 | }, 1266 | "node_modules/source-map": { 1267 | "version": "0.6.1", 1268 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 1269 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 1270 | "dev": true, 1271 | "engines": { 1272 | "node": ">=0.10.0" 1273 | } 1274 | }, 1275 | "node_modules/source-map-support": { 1276 | "version": "0.5.21", 1277 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", 1278 | "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", 1279 | "dev": true, 1280 | "dependencies": { 1281 | "buffer-from": "^1.0.0", 1282 | "source-map": "^0.6.0" 1283 | } 1284 | }, 1285 | "node_modules/split": { 1286 | "version": "1.0.1", 1287 | "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", 1288 | "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", 1289 | "dev": true, 1290 | "dependencies": { 1291 | "through": "2" 1292 | }, 1293 | "engines": { 1294 | "node": "*" 1295 | } 1296 | }, 1297 | "node_modules/stop-iteration-iterator": { 1298 | "version": "1.0.0", 1299 | "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", 1300 | "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", 1301 | "dev": true, 1302 | "dependencies": { 1303 | "internal-slot": "^1.0.4" 1304 | }, 1305 | "engines": { 1306 | "node": ">= 0.4" 1307 | } 1308 | }, 1309 | "node_modules/stream-combiner": { 1310 | "version": "0.2.2", 1311 | "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", 1312 | "integrity": "sha512-6yHMqgLYDzQDcAkL+tjJDC5nSNuNIx0vZtRZeiPh7Saef7VHX9H5Ijn9l2VIol2zaNYlYEX6KyuT/237A58qEQ==", 1313 | "dev": true, 1314 | "dependencies": { 1315 | "duplexer": "~0.1.1", 1316 | "through": "~2.3.4" 1317 | } 1318 | }, 1319 | "node_modules/string-width": { 1320 | "version": "4.2.3", 1321 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1322 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1323 | "dev": true, 1324 | "dependencies": { 1325 | "emoji-regex": "^8.0.0", 1326 | "is-fullwidth-code-point": "^3.0.0", 1327 | "strip-ansi": "^6.0.1" 1328 | }, 1329 | "engines": { 1330 | "node": ">=8" 1331 | } 1332 | }, 1333 | "node_modules/strip-ansi": { 1334 | "version": "6.0.1", 1335 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1336 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1337 | "dev": true, 1338 | "dependencies": { 1339 | "ansi-regex": "^5.0.1" 1340 | }, 1341 | "engines": { 1342 | "node": ">=8" 1343 | } 1344 | }, 1345 | "node_modules/supports-color": { 1346 | "version": "7.2.0", 1347 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 1348 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 1349 | "dev": true, 1350 | "dependencies": { 1351 | "has-flag": "^4.0.0" 1352 | }, 1353 | "engines": { 1354 | "node": ">=8" 1355 | } 1356 | }, 1357 | "node_modules/through": { 1358 | "version": "2.3.8", 1359 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 1360 | "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", 1361 | "dev": true 1362 | }, 1363 | "node_modules/thunky": { 1364 | "version": "1.1.0", 1365 | "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", 1366 | "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", 1367 | "dev": true 1368 | }, 1369 | "node_modules/tslib": { 1370 | "version": "2.5.0", 1371 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", 1372 | "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", 1373 | "dev": true 1374 | }, 1375 | "node_modules/tweetnacl": { 1376 | "version": "1.0.3", 1377 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", 1378 | "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", 1379 | "dev": true 1380 | }, 1381 | "node_modules/typescript": { 1382 | "version": "5.0.4", 1383 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", 1384 | "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", 1385 | "dev": true, 1386 | "bin": { 1387 | "tsc": "bin/tsc", 1388 | "tsserver": "bin/tsserver" 1389 | }, 1390 | "engines": { 1391 | "node": ">=12.20" 1392 | } 1393 | }, 1394 | "node_modules/universalify": { 1395 | "version": "2.0.0", 1396 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", 1397 | "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", 1398 | "dev": true, 1399 | "engines": { 1400 | "node": ">= 10.0.0" 1401 | } 1402 | }, 1403 | "node_modules/which": { 1404 | "version": "2.0.2", 1405 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 1406 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 1407 | "dev": true, 1408 | "dependencies": { 1409 | "isexe": "^2.0.0" 1410 | }, 1411 | "bin": { 1412 | "node-which": "bin/node-which" 1413 | }, 1414 | "engines": { 1415 | "node": ">= 8" 1416 | } 1417 | }, 1418 | "node_modules/which-boxed-primitive": { 1419 | "version": "1.0.2", 1420 | "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", 1421 | "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", 1422 | "dev": true, 1423 | "dependencies": { 1424 | "is-bigint": "^1.0.1", 1425 | "is-boolean-object": "^1.1.0", 1426 | "is-number-object": "^1.0.4", 1427 | "is-string": "^1.0.5", 1428 | "is-symbol": "^1.0.3" 1429 | }, 1430 | "funding": { 1431 | "url": "https://github.com/sponsors/ljharb" 1432 | } 1433 | }, 1434 | "node_modules/which-collection": { 1435 | "version": "1.0.1", 1436 | "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", 1437 | "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", 1438 | "dev": true, 1439 | "dependencies": { 1440 | "is-map": "^2.0.1", 1441 | "is-set": "^2.0.1", 1442 | "is-weakmap": "^2.0.1", 1443 | "is-weakset": "^2.0.1" 1444 | }, 1445 | "funding": { 1446 | "url": "https://github.com/sponsors/ljharb" 1447 | } 1448 | }, 1449 | "node_modules/which-typed-array": { 1450 | "version": "1.1.9", 1451 | "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", 1452 | "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", 1453 | "dev": true, 1454 | "dependencies": { 1455 | "available-typed-arrays": "^1.0.5", 1456 | "call-bind": "^1.0.2", 1457 | "for-each": "^0.3.3", 1458 | "gopd": "^1.0.1", 1459 | "has-tostringtag": "^1.0.0", 1460 | "is-typed-array": "^1.1.10" 1461 | }, 1462 | "engines": { 1463 | "node": ">= 0.4" 1464 | }, 1465 | "funding": { 1466 | "url": "https://github.com/sponsors/ljharb" 1467 | } 1468 | }, 1469 | "node_modules/wrap-ansi": { 1470 | "version": "7.0.0", 1471 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 1472 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 1473 | "dev": true, 1474 | "dependencies": { 1475 | "ansi-styles": "^4.0.0", 1476 | "string-width": "^4.1.0", 1477 | "strip-ansi": "^6.0.0" 1478 | }, 1479 | "engines": { 1480 | "node": ">=10" 1481 | }, 1482 | "funding": { 1483 | "url": "https://github.com/chalk/wrap-ansi?sponsor=1" 1484 | } 1485 | }, 1486 | "node_modules/xml2js": { 1487 | "version": "0.5.0", 1488 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", 1489 | "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", 1490 | "dev": true, 1491 | "dependencies": { 1492 | "sax": ">=0.6.0", 1493 | "xmlbuilder": "~11.0.0" 1494 | }, 1495 | "engines": { 1496 | "node": ">=4.0.0" 1497 | } 1498 | }, 1499 | "node_modules/xmlbuilder": { 1500 | "version": "11.0.1", 1501 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", 1502 | "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", 1503 | "dev": true, 1504 | "engines": { 1505 | "node": ">=4.0" 1506 | } 1507 | }, 1508 | "node_modules/yallist": { 1509 | "version": "4.0.0", 1510 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 1511 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 1512 | "dev": true 1513 | } 1514 | }, 1515 | "dependencies": { 1516 | "@homebridge/ciao": { 1517 | "version": "1.1.5", 1518 | "resolved": "https://registry.npmjs.org/@homebridge/ciao/-/ciao-1.1.5.tgz", 1519 | "integrity": "sha512-ZI9tcbPfX2d8oP1PNeLzrZLXISAIDUtJQWk4JVVJKCxktC6tQ3JyWXT9t1FbB5xtl82M1jdCgyAbWbjhUtRWcA==", 1520 | "dev": true, 1521 | "requires": { 1522 | "debug": "^4.3.4", 1523 | "fast-deep-equal": "^3.1.3", 1524 | "source-map-support": "^0.5.21", 1525 | "tslib": "^2.4.0" 1526 | } 1527 | }, 1528 | "@homebridge/dbus-native": { 1529 | "version": "0.5.1", 1530 | "resolved": "https://registry.npmjs.org/@homebridge/dbus-native/-/dbus-native-0.5.1.tgz", 1531 | "integrity": "sha512-7xXz3R1W/kcbfQOGp32y4K7etqtowICR1vpx8j85KwPYXbNQrgiZ3zcwDYgDGBWq3FD9xzsW7h4YWJ4vTR2seQ==", 1532 | "dev": true, 1533 | "requires": { 1534 | "@homebridge/long": "^5.2.1", 1535 | "@homebridge/put": "~0.0.8", 1536 | "event-stream": "^4.0.0", 1537 | "hexy": "^0.2.10", 1538 | "minimist": "^1.2.6", 1539 | "safe-buffer": "^5.1.1", 1540 | "xml2js": "^0.5.0" 1541 | } 1542 | }, 1543 | "@homebridge/long": { 1544 | "version": "5.2.1", 1545 | "resolved": "https://registry.npmjs.org/@homebridge/long/-/long-5.2.1.tgz", 1546 | "integrity": "sha512-i5Df8R63XNPCn+Nj1OgAoRdw9e+jHUQb3CNUbvJneI2iu3j4+OtzQj+5PA1Ce+747NR1SPqZSvyvD483dOT3AA==", 1547 | "dev": true 1548 | }, 1549 | "@homebridge/put": { 1550 | "version": "0.0.8", 1551 | "resolved": "https://registry.npmjs.org/@homebridge/put/-/put-0.0.8.tgz", 1552 | "integrity": "sha512-mwxLHHqKebOmOSU0tsPEWQSBHGApPhuaqtNpCe7U+AMdsduweANiu64E9SXXUtdpyTjsOpgSMLhD1+kbLHD2gA==", 1553 | "dev": true 1554 | }, 1555 | "@leichtgewicht/ip-codec": { 1556 | "version": "2.0.4", 1557 | "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz", 1558 | "integrity": "sha512-Hcv+nVC0kZnQ3tD9GVu5xSMR4VVYOteQIr/hwFPVEvPdlXqgGEuRjiheChHgdM+JyqdgNcmzZOX/tnl0JOiI7A==", 1559 | "dev": true 1560 | }, 1561 | "@pkgjs/parseargs": { 1562 | "version": "0.11.0", 1563 | "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", 1564 | "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", 1565 | "dev": true, 1566 | "optional": true 1567 | }, 1568 | "@types/node": { 1569 | "version": "16.11.7", 1570 | "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.7.tgz", 1571 | "integrity": "sha512-QB5D2sqfSjCmTuWcBWyJ+/44bcjO7VbjSbOE0ucoVbAsSNQc4Lt6QkgkVXkTDwkL4z/beecZNDvVX15D4P8Jbw==", 1572 | "dev": true 1573 | }, 1574 | "ansi-regex": { 1575 | "version": "5.0.1", 1576 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 1577 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 1578 | "dev": true 1579 | }, 1580 | "ansi-styles": { 1581 | "version": "4.3.0", 1582 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", 1583 | "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", 1584 | "dev": true, 1585 | "requires": { 1586 | "color-convert": "^2.0.1" 1587 | } 1588 | }, 1589 | "array-buffer-byte-length": { 1590 | "version": "1.0.0", 1591 | "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", 1592 | "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", 1593 | "dev": true, 1594 | "requires": { 1595 | "call-bind": "^1.0.2", 1596 | "is-array-buffer": "^3.0.1" 1597 | } 1598 | }, 1599 | "array-flatten": { 1600 | "version": "2.1.2", 1601 | "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz", 1602 | "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==", 1603 | "dev": true 1604 | }, 1605 | "available-typed-arrays": { 1606 | "version": "1.0.5", 1607 | "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", 1608 | "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", 1609 | "dev": true 1610 | }, 1611 | "balanced-match": { 1612 | "version": "1.0.2", 1613 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 1614 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", 1615 | "dev": true 1616 | }, 1617 | "bonjour-hap": { 1618 | "version": "3.6.4", 1619 | "resolved": "https://registry.npmjs.org/bonjour-hap/-/bonjour-hap-3.6.4.tgz", 1620 | "integrity": "sha512-a76r95/qTAP5hOEZZhRoiosyFSVPPRSVev09Jh8yDf3JDKyrzELLf0vpQCuEXFueb9DcV9UJf2Jv3dktyuPBng==", 1621 | "dev": true, 1622 | "requires": { 1623 | "array-flatten": "^2.1.2", 1624 | "deep-equal": "^2.0.5", 1625 | "ip": "^1.1.8", 1626 | "multicast-dns": "^7.2.5", 1627 | "multicast-dns-service-types": "^1.1.0" 1628 | } 1629 | }, 1630 | "brace-expansion": { 1631 | "version": "2.0.1", 1632 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", 1633 | "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", 1634 | "dev": true, 1635 | "requires": { 1636 | "balanced-match": "^1.0.0" 1637 | } 1638 | }, 1639 | "buffer-from": { 1640 | "version": "1.1.2", 1641 | "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", 1642 | "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", 1643 | "dev": true 1644 | }, 1645 | "call-bind": { 1646 | "version": "1.0.2", 1647 | "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", 1648 | "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", 1649 | "dev": true, 1650 | "requires": { 1651 | "function-bind": "^1.1.1", 1652 | "get-intrinsic": "^1.0.2" 1653 | } 1654 | }, 1655 | "chalk": { 1656 | "version": "4.1.2", 1657 | "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", 1658 | "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", 1659 | "dev": true, 1660 | "requires": { 1661 | "ansi-styles": "^4.1.0", 1662 | "supports-color": "^7.1.0" 1663 | } 1664 | }, 1665 | "cliui": { 1666 | "version": "8.0.1", 1667 | "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", 1668 | "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", 1669 | "dev": true, 1670 | "requires": { 1671 | "string-width": "^4.2.0", 1672 | "strip-ansi": "^6.0.1", 1673 | "wrap-ansi": "^7.0.0" 1674 | } 1675 | }, 1676 | "color-convert": { 1677 | "version": "2.0.1", 1678 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 1679 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 1680 | "dev": true, 1681 | "requires": { 1682 | "color-name": "~1.1.4" 1683 | } 1684 | }, 1685 | "color-name": { 1686 | "version": "1.1.4", 1687 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 1688 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", 1689 | "dev": true 1690 | }, 1691 | "commander": { 1692 | "version": "5.1.0", 1693 | "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", 1694 | "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", 1695 | "dev": true 1696 | }, 1697 | "cross-spawn": { 1698 | "version": "7.0.3", 1699 | "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", 1700 | "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", 1701 | "dev": true, 1702 | "requires": { 1703 | "path-key": "^3.1.0", 1704 | "shebang-command": "^2.0.0", 1705 | "which": "^2.0.1" 1706 | } 1707 | }, 1708 | "debug": { 1709 | "version": "4.3.4", 1710 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", 1711 | "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", 1712 | "dev": true, 1713 | "requires": { 1714 | "ms": "2.1.2" 1715 | } 1716 | }, 1717 | "deep-equal": { 1718 | "version": "2.2.1", 1719 | "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.1.tgz", 1720 | "integrity": "sha512-lKdkdV6EOGoVn65XaOsPdH4rMxTZOnmFyuIkMjM1i5HHCbfjC97dawgTAy0deYNfuqUqW+Q5VrVaQYtUpSd6yQ==", 1721 | "dev": true, 1722 | "requires": { 1723 | "array-buffer-byte-length": "^1.0.0", 1724 | "call-bind": "^1.0.2", 1725 | "es-get-iterator": "^1.1.3", 1726 | "get-intrinsic": "^1.2.0", 1727 | "is-arguments": "^1.1.1", 1728 | "is-array-buffer": "^3.0.2", 1729 | "is-date-object": "^1.0.5", 1730 | "is-regex": "^1.1.4", 1731 | "is-shared-array-buffer": "^1.0.2", 1732 | "isarray": "^2.0.5", 1733 | "object-is": "^1.1.5", 1734 | "object-keys": "^1.1.1", 1735 | "object.assign": "^4.1.4", 1736 | "regexp.prototype.flags": "^1.5.0", 1737 | "side-channel": "^1.0.4", 1738 | "which-boxed-primitive": "^1.0.2", 1739 | "which-collection": "^1.0.1", 1740 | "which-typed-array": "^1.1.9" 1741 | } 1742 | }, 1743 | "define-properties": { 1744 | "version": "1.2.0", 1745 | "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", 1746 | "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", 1747 | "dev": true, 1748 | "requires": { 1749 | "has-property-descriptors": "^1.0.0", 1750 | "object-keys": "^1.1.1" 1751 | } 1752 | }, 1753 | "dns-packet": { 1754 | "version": "5.6.0", 1755 | "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.0.tgz", 1756 | "integrity": "sha512-rza3UH1LwdHh9qyPXp8lkwpjSNk/AMD3dPytUoRoqnypDUhY0xvbdmVhWOfxO68frEfV9BU8V12Ez7ZsHGZpCQ==", 1757 | "dev": true, 1758 | "requires": { 1759 | "@leichtgewicht/ip-codec": "^2.0.1" 1760 | } 1761 | }, 1762 | "duplexer": { 1763 | "version": "0.1.2", 1764 | "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz", 1765 | "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==", 1766 | "dev": true 1767 | }, 1768 | "emoji-regex": { 1769 | "version": "8.0.0", 1770 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1771 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", 1772 | "dev": true 1773 | }, 1774 | "es-get-iterator": { 1775 | "version": "1.1.3", 1776 | "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", 1777 | "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", 1778 | "dev": true, 1779 | "requires": { 1780 | "call-bind": "^1.0.2", 1781 | "get-intrinsic": "^1.1.3", 1782 | "has-symbols": "^1.0.3", 1783 | "is-arguments": "^1.1.1", 1784 | "is-map": "^2.0.2", 1785 | "is-set": "^2.0.2", 1786 | "is-string": "^1.0.7", 1787 | "isarray": "^2.0.5", 1788 | "stop-iteration-iterator": "^1.0.0" 1789 | } 1790 | }, 1791 | "event-stream": { 1792 | "version": "4.0.1", 1793 | "resolved": "https://registry.npmjs.org/event-stream/-/event-stream-4.0.1.tgz", 1794 | "integrity": "sha512-qACXdu/9VHPBzcyhdOWR5/IahhGMf0roTeZJfzz077GwylcDd90yOHLouhmv7GJ5XzPi6ekaQWd8AvPP2nOvpA==", 1795 | "dev": true, 1796 | "requires": { 1797 | "duplexer": "^0.1.1", 1798 | "from": "^0.1.7", 1799 | "map-stream": "0.0.7", 1800 | "pause-stream": "^0.0.11", 1801 | "split": "^1.0.1", 1802 | "stream-combiner": "^0.2.2", 1803 | "through": "^2.3.8" 1804 | } 1805 | }, 1806 | "fast-deep-equal": { 1807 | "version": "3.1.3", 1808 | "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", 1809 | "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", 1810 | "dev": true 1811 | }, 1812 | "fast-srp-hap": { 1813 | "version": "2.0.4", 1814 | "resolved": "https://registry.npmjs.org/fast-srp-hap/-/fast-srp-hap-2.0.4.tgz", 1815 | "integrity": "sha512-lHRYYaaIbMrhZtsdGTwPN82UbqD9Bv8QfOlKs+Dz6YRnByZifOh93EYmf2iEWFtkOEIqR2IK8cFD0UN5wLIWBQ==", 1816 | "dev": true 1817 | }, 1818 | "for-each": { 1819 | "version": "0.3.3", 1820 | "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", 1821 | "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", 1822 | "dev": true, 1823 | "requires": { 1824 | "is-callable": "^1.1.3" 1825 | } 1826 | }, 1827 | "foreground-child": { 1828 | "version": "3.1.1", 1829 | "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", 1830 | "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", 1831 | "dev": true, 1832 | "requires": { 1833 | "cross-spawn": "^7.0.0", 1834 | "signal-exit": "^4.0.1" 1835 | } 1836 | }, 1837 | "from": { 1838 | "version": "0.1.7", 1839 | "resolved": "https://registry.npmjs.org/from/-/from-0.1.7.tgz", 1840 | "integrity": "sha512-twe20eF1OxVxp/ML/kq2p1uc6KvFK/+vs8WjEbeKmV2He22MKm7YF2ANIt+EOqhJ5L3K/SuuPhk0hWQDjOM23g==", 1841 | "dev": true 1842 | }, 1843 | "fs-extra": { 1844 | "version": "10.1.0", 1845 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", 1846 | "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", 1847 | "dev": true, 1848 | "requires": { 1849 | "graceful-fs": "^4.2.0", 1850 | "jsonfile": "^6.0.1", 1851 | "universalify": "^2.0.0" 1852 | } 1853 | }, 1854 | "function-bind": { 1855 | "version": "1.1.1", 1856 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 1857 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", 1858 | "dev": true 1859 | }, 1860 | "functions-have-names": { 1861 | "version": "1.2.3", 1862 | "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", 1863 | "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", 1864 | "dev": true 1865 | }, 1866 | "futoin-hkdf": { 1867 | "version": "1.4.3", 1868 | "resolved": "https://registry.npmjs.org/futoin-hkdf/-/futoin-hkdf-1.4.3.tgz", 1869 | "integrity": "sha512-K4MIe2xSVRMYxsA4w0ap5fp1C2hA9StA2Ad1JZHX57VMCdHIRB5BSrd1FhuadTQG9MkjggaTCrw7v5XXFyY3/w==", 1870 | "dev": true 1871 | }, 1872 | "get-intrinsic": { 1873 | "version": "1.2.0", 1874 | "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.0.tgz", 1875 | "integrity": "sha512-L049y6nFOuom5wGyRc3/gdTLO94dySVKRACj1RmJZBQXlbTMhtNIgkWkUHq+jYmZvKf14EW1EoJnnjbmoHij0Q==", 1876 | "dev": true, 1877 | "requires": { 1878 | "function-bind": "^1.1.1", 1879 | "has": "^1.0.3", 1880 | "has-symbols": "^1.0.3" 1881 | } 1882 | }, 1883 | "glob": { 1884 | "version": "10.2.2", 1885 | "resolved": "https://registry.npmjs.org/glob/-/glob-10.2.2.tgz", 1886 | "integrity": "sha512-Xsa0BcxIC6th9UwNjZkhrMtNo/MnyRL8jGCP+uEwhA5oFOCY1f2s1/oNKY47xQ0Bg5nkjsfAEIej1VeH62bDDQ==", 1887 | "dev": true, 1888 | "requires": { 1889 | "foreground-child": "^3.1.0", 1890 | "jackspeak": "^2.0.3", 1891 | "minimatch": "^9.0.0", 1892 | "minipass": "^5.0.0", 1893 | "path-scurry": "^1.7.0" 1894 | } 1895 | }, 1896 | "gopd": { 1897 | "version": "1.0.1", 1898 | "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", 1899 | "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", 1900 | "dev": true, 1901 | "requires": { 1902 | "get-intrinsic": "^1.1.3" 1903 | } 1904 | }, 1905 | "graceful-fs": { 1906 | "version": "4.2.11", 1907 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", 1908 | "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", 1909 | "dev": true 1910 | }, 1911 | "hap-nodejs": { 1912 | "version": "0.11.1", 1913 | "resolved": "https://registry.npmjs.org/hap-nodejs/-/hap-nodejs-0.11.1.tgz", 1914 | "integrity": "sha512-hJuGyjng2jlzhZsviWCldaokT7l7BE3iGmWdlE6DNmQFDTmiBN3deNksAZ2nt7qp5jYEv7ZUvW7WBZqJsLh3ww==", 1915 | "dev": true, 1916 | "requires": { 1917 | "@homebridge/ciao": "^1.1.5", 1918 | "@homebridge/dbus-native": "^0.5.1", 1919 | "bonjour-hap": "~3.6.4", 1920 | "debug": "^4.3.4", 1921 | "fast-srp-hap": "~2.0.4", 1922 | "futoin-hkdf": "~1.4.3", 1923 | "node-persist": "^0.0.11", 1924 | "source-map-support": "^0.5.21", 1925 | "tslib": "^2.4.0", 1926 | "tweetnacl": "^1.0.3" 1927 | } 1928 | }, 1929 | "has": { 1930 | "version": "1.0.3", 1931 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 1932 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 1933 | "dev": true, 1934 | "requires": { 1935 | "function-bind": "^1.1.1" 1936 | } 1937 | }, 1938 | "has-bigints": { 1939 | "version": "1.0.2", 1940 | "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", 1941 | "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", 1942 | "dev": true 1943 | }, 1944 | "has-flag": { 1945 | "version": "4.0.0", 1946 | "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", 1947 | "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", 1948 | "dev": true 1949 | }, 1950 | "has-property-descriptors": { 1951 | "version": "1.0.0", 1952 | "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", 1953 | "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", 1954 | "dev": true, 1955 | "requires": { 1956 | "get-intrinsic": "^1.1.1" 1957 | } 1958 | }, 1959 | "has-symbols": { 1960 | "version": "1.0.3", 1961 | "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", 1962 | "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", 1963 | "dev": true 1964 | }, 1965 | "has-tostringtag": { 1966 | "version": "1.0.0", 1967 | "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", 1968 | "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", 1969 | "dev": true, 1970 | "requires": { 1971 | "has-symbols": "^1.0.2" 1972 | } 1973 | }, 1974 | "hexy": { 1975 | "version": "0.2.11", 1976 | "resolved": "https://registry.npmjs.org/hexy/-/hexy-0.2.11.tgz", 1977 | "integrity": "sha512-ciq6hFsSG/Bpt2DmrZJtv+56zpPdnq+NQ4ijEFrveKN0ZG1mhl/LdT1NQZ9se6ty1fACcI4d4vYqC9v8EYpH2A==", 1978 | "dev": true 1979 | }, 1980 | "homebridge": { 1981 | "version": "1.6.1", 1982 | "resolved": "https://registry.npmjs.org/homebridge/-/homebridge-1.6.1.tgz", 1983 | "integrity": "sha512-hDhSaBDHFbB8wQQuZKbistYj1gjTIcNWmusqgEUb0Umk76Hs+G6VKRTkOEEVuxRaQWoK5hRM5rJTsCGAMCj5cA==", 1984 | "dev": true, 1985 | "requires": { 1986 | "chalk": "^4.1.2", 1987 | "commander": "5.1.0", 1988 | "fs-extra": "^10.1.0", 1989 | "hap-nodejs": "~0.11.1", 1990 | "qrcode-terminal": "^0.12.0", 1991 | "semver": "^7.3.7", 1992 | "source-map-support": "^0.5.21" 1993 | } 1994 | }, 1995 | "internal-slot": { 1996 | "version": "1.0.5", 1997 | "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", 1998 | "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", 1999 | "dev": true, 2000 | "requires": { 2001 | "get-intrinsic": "^1.2.0", 2002 | "has": "^1.0.3", 2003 | "side-channel": "^1.0.4" 2004 | } 2005 | }, 2006 | "ip": { 2007 | "version": "1.1.8", 2008 | "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz", 2009 | "integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg==", 2010 | "dev": true 2011 | }, 2012 | "is-arguments": { 2013 | "version": "1.1.1", 2014 | "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", 2015 | "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", 2016 | "dev": true, 2017 | "requires": { 2018 | "call-bind": "^1.0.2", 2019 | "has-tostringtag": "^1.0.0" 2020 | } 2021 | }, 2022 | "is-array-buffer": { 2023 | "version": "3.0.2", 2024 | "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", 2025 | "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", 2026 | "dev": true, 2027 | "requires": { 2028 | "call-bind": "^1.0.2", 2029 | "get-intrinsic": "^1.2.0", 2030 | "is-typed-array": "^1.1.10" 2031 | } 2032 | }, 2033 | "is-bigint": { 2034 | "version": "1.0.4", 2035 | "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", 2036 | "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", 2037 | "dev": true, 2038 | "requires": { 2039 | "has-bigints": "^1.0.1" 2040 | } 2041 | }, 2042 | "is-boolean-object": { 2043 | "version": "1.1.2", 2044 | "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", 2045 | "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", 2046 | "dev": true, 2047 | "requires": { 2048 | "call-bind": "^1.0.2", 2049 | "has-tostringtag": "^1.0.0" 2050 | } 2051 | }, 2052 | "is-callable": { 2053 | "version": "1.2.7", 2054 | "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", 2055 | "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", 2056 | "dev": true 2057 | }, 2058 | "is-date-object": { 2059 | "version": "1.0.5", 2060 | "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", 2061 | "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", 2062 | "dev": true, 2063 | "requires": { 2064 | "has-tostringtag": "^1.0.0" 2065 | } 2066 | }, 2067 | "is-fullwidth-code-point": { 2068 | "version": "3.0.0", 2069 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 2070 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 2071 | "dev": true 2072 | }, 2073 | "is-map": { 2074 | "version": "2.0.2", 2075 | "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", 2076 | "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", 2077 | "dev": true 2078 | }, 2079 | "is-number-object": { 2080 | "version": "1.0.7", 2081 | "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", 2082 | "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", 2083 | "dev": true, 2084 | "requires": { 2085 | "has-tostringtag": "^1.0.0" 2086 | } 2087 | }, 2088 | "is-regex": { 2089 | "version": "1.1.4", 2090 | "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", 2091 | "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", 2092 | "dev": true, 2093 | "requires": { 2094 | "call-bind": "^1.0.2", 2095 | "has-tostringtag": "^1.0.0" 2096 | } 2097 | }, 2098 | "is-set": { 2099 | "version": "2.0.2", 2100 | "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", 2101 | "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", 2102 | "dev": true 2103 | }, 2104 | "is-shared-array-buffer": { 2105 | "version": "1.0.2", 2106 | "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", 2107 | "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", 2108 | "dev": true, 2109 | "requires": { 2110 | "call-bind": "^1.0.2" 2111 | } 2112 | }, 2113 | "is-string": { 2114 | "version": "1.0.7", 2115 | "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", 2116 | "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", 2117 | "dev": true, 2118 | "requires": { 2119 | "has-tostringtag": "^1.0.0" 2120 | } 2121 | }, 2122 | "is-symbol": { 2123 | "version": "1.0.4", 2124 | "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", 2125 | "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", 2126 | "dev": true, 2127 | "requires": { 2128 | "has-symbols": "^1.0.2" 2129 | } 2130 | }, 2131 | "is-typed-array": { 2132 | "version": "1.1.10", 2133 | "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.10.tgz", 2134 | "integrity": "sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A==", 2135 | "dev": true, 2136 | "requires": { 2137 | "available-typed-arrays": "^1.0.5", 2138 | "call-bind": "^1.0.2", 2139 | "for-each": "^0.3.3", 2140 | "gopd": "^1.0.1", 2141 | "has-tostringtag": "^1.0.0" 2142 | } 2143 | }, 2144 | "is-weakmap": { 2145 | "version": "2.0.1", 2146 | "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.1.tgz", 2147 | "integrity": "sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==", 2148 | "dev": true 2149 | }, 2150 | "is-weakset": { 2151 | "version": "2.0.2", 2152 | "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz", 2153 | "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==", 2154 | "dev": true, 2155 | "requires": { 2156 | "call-bind": "^1.0.2", 2157 | "get-intrinsic": "^1.1.1" 2158 | } 2159 | }, 2160 | "isarray": { 2161 | "version": "2.0.5", 2162 | "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", 2163 | "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", 2164 | "dev": true 2165 | }, 2166 | "isexe": { 2167 | "version": "2.0.0", 2168 | "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", 2169 | "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", 2170 | "dev": true 2171 | }, 2172 | "jackspeak": { 2173 | "version": "2.1.1", 2174 | "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.1.1.tgz", 2175 | "integrity": "sha512-juf9stUEwUaILepraGOWIJTLwg48bUnBmRqd2ln2Os1sW987zeoj/hzhbvRB95oMuS2ZTpjULmdwHNX4rzZIZw==", 2176 | "dev": true, 2177 | "requires": { 2178 | "@pkgjs/parseargs": "^0.11.0", 2179 | "cliui": "^8.0.1" 2180 | } 2181 | }, 2182 | "jsonfile": { 2183 | "version": "6.1.0", 2184 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", 2185 | "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", 2186 | "dev": true, 2187 | "requires": { 2188 | "graceful-fs": "^4.1.6", 2189 | "universalify": "^2.0.0" 2190 | } 2191 | }, 2192 | "lru-cache": { 2193 | "version": "9.1.1", 2194 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-9.1.1.tgz", 2195 | "integrity": "sha512-65/Jky17UwSb0BuB9V+MyDpsOtXKmYwzhyl+cOa9XUiI4uV2Ouy/2voFP3+al0BjZbJgMBD8FojMpAf+Z+qn4A==", 2196 | "dev": true 2197 | }, 2198 | "map-stream": { 2199 | "version": "0.0.7", 2200 | "resolved": "https://registry.npmjs.org/map-stream/-/map-stream-0.0.7.tgz", 2201 | "integrity": "sha512-C0X0KQmGm3N2ftbTGBhSyuydQ+vV1LC3f3zPvT3RXHXNZrvfPZcoXp/N5DOa8vedX/rTMm2CjTtivFg2STJMRQ==", 2202 | "dev": true 2203 | }, 2204 | "minimatch": { 2205 | "version": "9.0.0", 2206 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.0.tgz", 2207 | "integrity": "sha512-0jJj8AvgKqWN05mrwuqi8QYKx1WmYSUoKSxu5Qhs9prezTz10sxAHGNZe9J9cqIJzta8DWsleh2KaVaLl6Ru2w==", 2208 | "dev": true, 2209 | "requires": { 2210 | "brace-expansion": "^2.0.1" 2211 | } 2212 | }, 2213 | "minimist": { 2214 | "version": "1.2.8", 2215 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", 2216 | "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", 2217 | "dev": true 2218 | }, 2219 | "minipass": { 2220 | "version": "5.0.0", 2221 | "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", 2222 | "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", 2223 | "dev": true 2224 | }, 2225 | "mkdirp": { 2226 | "version": "0.5.6", 2227 | "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", 2228 | "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", 2229 | "dev": true, 2230 | "requires": { 2231 | "minimist": "^1.2.6" 2232 | } 2233 | }, 2234 | "ms": { 2235 | "version": "2.1.2", 2236 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 2237 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", 2238 | "dev": true 2239 | }, 2240 | "multicast-dns": { 2241 | "version": "7.2.5", 2242 | "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", 2243 | "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==", 2244 | "dev": true, 2245 | "requires": { 2246 | "dns-packet": "^5.2.2", 2247 | "thunky": "^1.0.2" 2248 | } 2249 | }, 2250 | "multicast-dns-service-types": { 2251 | "version": "1.1.0", 2252 | "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz", 2253 | "integrity": "sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ==", 2254 | "dev": true 2255 | }, 2256 | "node-persist": { 2257 | "version": "0.0.11", 2258 | "resolved": "https://registry.npmjs.org/node-persist/-/node-persist-0.0.11.tgz", 2259 | "integrity": "sha512-J3EPzQDgPxPBID7TqHSd5KkpTULFqJUvYDoISfOWg9EihpeVCH3b6YQeDeubzVuc4e6+aiVmkz2sdkWI4K+ghA==", 2260 | "dev": true, 2261 | "requires": { 2262 | "mkdirp": "~0.5.1", 2263 | "q": "~1.1.1" 2264 | } 2265 | }, 2266 | "object-inspect": { 2267 | "version": "1.12.3", 2268 | "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", 2269 | "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", 2270 | "dev": true 2271 | }, 2272 | "object-is": { 2273 | "version": "1.1.5", 2274 | "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz", 2275 | "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==", 2276 | "dev": true, 2277 | "requires": { 2278 | "call-bind": "^1.0.2", 2279 | "define-properties": "^1.1.3" 2280 | } 2281 | }, 2282 | "object-keys": { 2283 | "version": "1.1.1", 2284 | "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", 2285 | "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", 2286 | "dev": true 2287 | }, 2288 | "object.assign": { 2289 | "version": "4.1.4", 2290 | "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", 2291 | "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", 2292 | "dev": true, 2293 | "requires": { 2294 | "call-bind": "^1.0.2", 2295 | "define-properties": "^1.1.4", 2296 | "has-symbols": "^1.0.3", 2297 | "object-keys": "^1.1.1" 2298 | } 2299 | }, 2300 | "path-key": { 2301 | "version": "3.1.1", 2302 | "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", 2303 | "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", 2304 | "dev": true 2305 | }, 2306 | "path-scurry": { 2307 | "version": "1.7.0", 2308 | "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.7.0.tgz", 2309 | "integrity": "sha512-UkZUeDjczjYRE495+9thsgcVgsaCPkaw80slmfVFgllxY+IO8ubTsOpFVjDPROBqJdHfVPUFRHPBV/WciOVfWg==", 2310 | "dev": true, 2311 | "requires": { 2312 | "lru-cache": "^9.0.0", 2313 | "minipass": "^5.0.0" 2314 | } 2315 | }, 2316 | "pause-stream": { 2317 | "version": "0.0.11", 2318 | "resolved": "https://registry.npmjs.org/pause-stream/-/pause-stream-0.0.11.tgz", 2319 | "integrity": "sha512-e3FBlXLmN/D1S+zHzanP4E/4Z60oFAa3O051qt1pxa7DEJWKAyil6upYVXCWadEnuoqa4Pkc9oUx9zsxYeRv8A==", 2320 | "dev": true, 2321 | "requires": { 2322 | "through": "~2.3" 2323 | } 2324 | }, 2325 | "q": { 2326 | "version": "1.1.2", 2327 | "resolved": "https://registry.npmjs.org/q/-/q-1.1.2.tgz", 2328 | "integrity": "sha512-ROtylwux7Vkc4C07oKE/ReigUmb33kVoLtcR4SJ1QVqwaZkBEDL3vX4/kwFzIERQ5PfCl0XafbU8u2YUhyGgVA==", 2329 | "dev": true 2330 | }, 2331 | "qrcode-terminal": { 2332 | "version": "0.12.0", 2333 | "resolved": "https://registry.npmjs.org/qrcode-terminal/-/qrcode-terminal-0.12.0.tgz", 2334 | "integrity": "sha512-EXtzRZmC+YGmGlDFbXKxQiMZNwCLEO6BANKXG4iCtSIM0yqc/pappSx3RIKr4r0uh5JsBckOXeKrB3Iz7mdQpQ==", 2335 | "dev": true 2336 | }, 2337 | "regexp.prototype.flags": { 2338 | "version": "1.5.0", 2339 | "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", 2340 | "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", 2341 | "dev": true, 2342 | "requires": { 2343 | "call-bind": "^1.0.2", 2344 | "define-properties": "^1.2.0", 2345 | "functions-have-names": "^1.2.3" 2346 | } 2347 | }, 2348 | "rimraf": { 2349 | "version": "5.0.0", 2350 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.0.tgz", 2351 | "integrity": "sha512-Jf9llaP+RvaEVS5nPShYFhtXIrb3LRKP281ib3So0KkeZKo2wIKyq0Re7TOSwanasA423PSr6CCIL4bP6T040g==", 2352 | "dev": true, 2353 | "requires": { 2354 | "glob": "^10.0.0" 2355 | } 2356 | }, 2357 | "safe-buffer": { 2358 | "version": "5.2.1", 2359 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 2360 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 2361 | "dev": true 2362 | }, 2363 | "sax": { 2364 | "version": "1.2.4", 2365 | "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", 2366 | "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", 2367 | "dev": true 2368 | }, 2369 | "semver": { 2370 | "version": "7.5.0", 2371 | "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", 2372 | "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", 2373 | "dev": true, 2374 | "requires": { 2375 | "lru-cache": "^6.0.0" 2376 | }, 2377 | "dependencies": { 2378 | "lru-cache": { 2379 | "version": "6.0.0", 2380 | "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", 2381 | "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", 2382 | "dev": true, 2383 | "requires": { 2384 | "yallist": "^4.0.0" 2385 | } 2386 | } 2387 | } 2388 | }, 2389 | "shebang-command": { 2390 | "version": "2.0.0", 2391 | "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", 2392 | "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", 2393 | "dev": true, 2394 | "requires": { 2395 | "shebang-regex": "^3.0.0" 2396 | } 2397 | }, 2398 | "shebang-regex": { 2399 | "version": "3.0.0", 2400 | "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", 2401 | "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", 2402 | "dev": true 2403 | }, 2404 | "side-channel": { 2405 | "version": "1.0.4", 2406 | "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", 2407 | "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", 2408 | "dev": true, 2409 | "requires": { 2410 | "call-bind": "^1.0.0", 2411 | "get-intrinsic": "^1.0.2", 2412 | "object-inspect": "^1.9.0" 2413 | } 2414 | }, 2415 | "signal-exit": { 2416 | "version": "4.0.1", 2417 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.0.1.tgz", 2418 | "integrity": "sha512-uUWsN4aOxJAS8KOuf3QMyFtgm1pkb6I+KRZbRF/ghdf5T7sM+B1lLLzPDxswUjkmHyxQAVzEgG35E3NzDM9GVw==", 2419 | "dev": true 2420 | }, 2421 | "source-map": { 2422 | "version": "0.6.1", 2423 | "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", 2424 | "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", 2425 | "dev": true 2426 | }, 2427 | "source-map-support": { 2428 | "version": "0.5.21", 2429 | "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", 2430 | "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", 2431 | "dev": true, 2432 | "requires": { 2433 | "buffer-from": "^1.0.0", 2434 | "source-map": "^0.6.0" 2435 | } 2436 | }, 2437 | "split": { 2438 | "version": "1.0.1", 2439 | "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", 2440 | "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", 2441 | "dev": true, 2442 | "requires": { 2443 | "through": "2" 2444 | } 2445 | }, 2446 | "stop-iteration-iterator": { 2447 | "version": "1.0.0", 2448 | "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", 2449 | "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", 2450 | "dev": true, 2451 | "requires": { 2452 | "internal-slot": "^1.0.4" 2453 | } 2454 | }, 2455 | "stream-combiner": { 2456 | "version": "0.2.2", 2457 | "resolved": "https://registry.npmjs.org/stream-combiner/-/stream-combiner-0.2.2.tgz", 2458 | "integrity": "sha512-6yHMqgLYDzQDcAkL+tjJDC5nSNuNIx0vZtRZeiPh7Saef7VHX9H5Ijn9l2VIol2zaNYlYEX6KyuT/237A58qEQ==", 2459 | "dev": true, 2460 | "requires": { 2461 | "duplexer": "~0.1.1", 2462 | "through": "~2.3.4" 2463 | } 2464 | }, 2465 | "string-width": { 2466 | "version": "4.2.3", 2467 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 2468 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 2469 | "dev": true, 2470 | "requires": { 2471 | "emoji-regex": "^8.0.0", 2472 | "is-fullwidth-code-point": "^3.0.0", 2473 | "strip-ansi": "^6.0.1" 2474 | } 2475 | }, 2476 | "strip-ansi": { 2477 | "version": "6.0.1", 2478 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 2479 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 2480 | "dev": true, 2481 | "requires": { 2482 | "ansi-regex": "^5.0.1" 2483 | } 2484 | }, 2485 | "supports-color": { 2486 | "version": "7.2.0", 2487 | "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", 2488 | "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", 2489 | "dev": true, 2490 | "requires": { 2491 | "has-flag": "^4.0.0" 2492 | } 2493 | }, 2494 | "through": { 2495 | "version": "2.3.8", 2496 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 2497 | "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", 2498 | "dev": true 2499 | }, 2500 | "thunky": { 2501 | "version": "1.1.0", 2502 | "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", 2503 | "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==", 2504 | "dev": true 2505 | }, 2506 | "tslib": { 2507 | "version": "2.5.0", 2508 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz", 2509 | "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==", 2510 | "dev": true 2511 | }, 2512 | "tweetnacl": { 2513 | "version": "1.0.3", 2514 | "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-1.0.3.tgz", 2515 | "integrity": "sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==", 2516 | "dev": true 2517 | }, 2518 | "typescript": { 2519 | "version": "5.0.4", 2520 | "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", 2521 | "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", 2522 | "dev": true 2523 | }, 2524 | "universalify": { 2525 | "version": "2.0.0", 2526 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", 2527 | "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", 2528 | "dev": true 2529 | }, 2530 | "which": { 2531 | "version": "2.0.2", 2532 | "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", 2533 | "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", 2534 | "dev": true, 2535 | "requires": { 2536 | "isexe": "^2.0.0" 2537 | } 2538 | }, 2539 | "which-boxed-primitive": { 2540 | "version": "1.0.2", 2541 | "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", 2542 | "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", 2543 | "dev": true, 2544 | "requires": { 2545 | "is-bigint": "^1.0.1", 2546 | "is-boolean-object": "^1.1.0", 2547 | "is-number-object": "^1.0.4", 2548 | "is-string": "^1.0.5", 2549 | "is-symbol": "^1.0.3" 2550 | } 2551 | }, 2552 | "which-collection": { 2553 | "version": "1.0.1", 2554 | "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.1.tgz", 2555 | "integrity": "sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==", 2556 | "dev": true, 2557 | "requires": { 2558 | "is-map": "^2.0.1", 2559 | "is-set": "^2.0.1", 2560 | "is-weakmap": "^2.0.1", 2561 | "is-weakset": "^2.0.1" 2562 | } 2563 | }, 2564 | "which-typed-array": { 2565 | "version": "1.1.9", 2566 | "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.9.tgz", 2567 | "integrity": "sha512-w9c4xkx6mPidwp7180ckYWfMmvxpjlZuIudNtDf4N/tTAUB8VJbX25qZoAsrtGuYNnGw3pa0AXgbGKRB8/EceA==", 2568 | "dev": true, 2569 | "requires": { 2570 | "available-typed-arrays": "^1.0.5", 2571 | "call-bind": "^1.0.2", 2572 | "for-each": "^0.3.3", 2573 | "gopd": "^1.0.1", 2574 | "has-tostringtag": "^1.0.0", 2575 | "is-typed-array": "^1.1.10" 2576 | } 2577 | }, 2578 | "wrap-ansi": { 2579 | "version": "7.0.0", 2580 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", 2581 | "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", 2582 | "dev": true, 2583 | "requires": { 2584 | "ansi-styles": "^4.0.0", 2585 | "string-width": "^4.1.0", 2586 | "strip-ansi": "^6.0.0" 2587 | } 2588 | }, 2589 | "xml2js": { 2590 | "version": "0.5.0", 2591 | "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz", 2592 | "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==", 2593 | "dev": true, 2594 | "requires": { 2595 | "sax": ">=0.6.0", 2596 | "xmlbuilder": "~11.0.0" 2597 | } 2598 | }, 2599 | "xmlbuilder": { 2600 | "version": "11.0.1", 2601 | "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", 2602 | "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", 2603 | "dev": true 2604 | }, 2605 | "yallist": { 2606 | "version": "4.0.0", 2607 | "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", 2608 | "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", 2609 | "dev": true 2610 | } 2611 | } 2612 | } 2613 | -------------------------------------------------------------------------------- /accessory-example-typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "homebridge-accessory-example", 3 | "version": "1.0.0", 4 | "description": "An example accessory plugin for homebridge written in Typescript", 5 | "main": "dist/accessory.js", 6 | "scripts": { 7 | "clean": "rimraf ./dist", 8 | "build": "rimraf ./dist && tsc", 9 | "prepublishOnly": "npm run build", 10 | "postpublish": "npm run clean", 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "author": "Andreas Bauer ", 14 | "engines": { 15 | "homebridge": ">=1.0.0" 16 | }, 17 | "keywords": [ 18 | "homebridge-plugin" 19 | ], 20 | "license": "ISC", 21 | "files": [ 22 | "LICENSE", 23 | "dist" 24 | ], 25 | "repository": { 26 | "type": "git", 27 | "url": "git://github.com/homebridge/homebridge-examples.git" 28 | }, 29 | "bugs": { 30 | "url": "https://github.com/homebridge/homebridge-examples/issues" 31 | }, 32 | "devDependencies": { 33 | "@types/node": "16.11.7", 34 | "typescript": "^5.0.4", 35 | "rimraf": "^5.0.0", 36 | "homebridge": "^1.6.1" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /accessory-example-typescript/src/accessory.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AccessoryConfig, 3 | AccessoryPlugin, 4 | API, 5 | CharacteristicEventTypes, 6 | CharacteristicGetCallback, 7 | CharacteristicSetCallback, 8 | CharacteristicValue, 9 | HAP, 10 | Logging, 11 | Service 12 | } from "homebridge"; 13 | 14 | /* 15 | * IMPORTANT NOTICE 16 | * 17 | * One thing you need to take care of is, that you never ever ever import anything directly from the "homebridge" module (or the "hap-nodejs" module). 18 | * The above import block may seem like, that we do exactly that, but actually those imports are only used for types and interfaces 19 | * and will disappear once the code is compiled to Javascript. 20 | * In fact you can check that by running `npm run build` and opening the compiled Javascript file in the `dist` folder. 21 | * You will notice that the file does not contain a `... = require("homebridge");` statement anywhere in the code. 22 | * 23 | * The contents of the above import statement MUST ONLY be used for type annotation or accessing things like CONST ENUMS, 24 | * which is a special case as they get replaced by the actual value and do not remain as a reference in the compiled code. 25 | * Meaning normal enums are bad, const enums can be used. 26 | * 27 | * You MUST NOT import anything else which remains as a reference in the code, as this will result in 28 | * a `... = require("homebridge");` to be compiled into the final Javascript code. 29 | * This typically leads to unexpected behavior at runtime, as in many cases it won't be able to find the module 30 | * or will import another instance of homebridge causing collisions. 31 | * 32 | * To mitigate this the {@link API | Homebridge API} exposes the whole suite of HAP-NodeJS inside the `hap` property 33 | * of the api object, which can be acquired for example in the initializer function. This reference can be stored 34 | * like this for example and used to access all exported variables and classes from HAP-NodeJS. 35 | */ 36 | let hap: HAP; 37 | 38 | /* 39 | * Initializer function called when the plugin is loaded. 40 | */ 41 | export = (api: API) => { 42 | hap = api.hap; 43 | api.registerAccessory("ExampleSwitch", ExampleSwitch); 44 | }; 45 | 46 | class ExampleSwitch implements AccessoryPlugin { 47 | 48 | private readonly log: Logging; 49 | private readonly name: string; 50 | private switchOn = false; 51 | 52 | private readonly switchService: Service; 53 | private readonly informationService: Service; 54 | 55 | constructor(log: Logging, config: AccessoryConfig, api: API) { 56 | this.log = log; 57 | this.name = config.name; 58 | 59 | this.switchService = new hap.Service.Switch(this.name); 60 | this.switchService.getCharacteristic(hap.Characteristic.On) 61 | .on(CharacteristicEventTypes.GET, (callback: CharacteristicGetCallback) => { 62 | log.info("Current state of the switch was returned: " + (this.switchOn? "ON": "OFF")); 63 | callback(undefined, this.switchOn); 64 | }) 65 | .on(CharacteristicEventTypes.SET, (value: CharacteristicValue, callback: CharacteristicSetCallback) => { 66 | this.switchOn = value as boolean; 67 | log.info("Switch state was set to: " + (this.switchOn? "ON": "OFF")); 68 | callback(); 69 | }); 70 | 71 | this.informationService = new hap.Service.AccessoryInformation() 72 | .setCharacteristic(hap.Characteristic.Manufacturer, "Custom Manufacturer") 73 | .setCharacteristic(hap.Characteristic.Model, "Custom Model"); 74 | 75 | log.info("Switch finished initializing!"); 76 | } 77 | 78 | /* 79 | * This method is optional to implement. It is called when HomeKit ask to identify the accessory. 80 | * Typical this only ever happens at the pairing process. 81 | */ 82 | identify(): void { 83 | this.log("Identify!"); 84 | } 85 | 86 | /* 87 | * This method is called directly after creation of this instance. 88 | * It should return all services which should be added to the accessory. 89 | */ 90 | getServices(): Service[] { 91 | return [ 92 | this.informationService, 93 | this.switchService, 94 | ]; 95 | } 96 | 97 | } 98 | -------------------------------------------------------------------------------- /accessory-example-typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2018", 4 | "module": "commonjs", 5 | "lib": [ 6 | "ES2015", 7 | "ES2016", 8 | "ES2017", 9 | "ES2018" 10 | ], 11 | "sourceMap": true, 12 | "rootDir": "src", 13 | "outDir": "dist", 14 | 15 | "strict": true, 16 | "esModuleInterop": true, 17 | "forceConsistentCasingInFileNames": true 18 | }, 19 | "include": [ 20 | "src" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /bridged-camera-example-typescript/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### HAP-NodeJS files 3 | persist 4 | 5 | ### Node template 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # Diagnostic reports (https://nodejs.org/api/report.html) 15 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | *.seed 21 | *.pid.lock 22 | 23 | # Directory for instrumented libs generated by jscoverage/JSCover 24 | lib-cov 25 | 26 | # Coverage directory used by tools like istanbul 27 | coverage 28 | *.lcov 29 | 30 | # nyc test coverage 31 | .nyc_output 32 | 33 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 34 | .grunt 35 | 36 | # Bower dependency directory (https://bower.io/) 37 | bower_components 38 | 39 | # node-waf configuration 40 | .lock-wscript 41 | 42 | # Compiled binary addons (https://nodejs.org/api/addons.html) 43 | build/Release 44 | 45 | # Dependency directories 46 | node_modules/ 47 | jspm_packages/ 48 | 49 | # Snowpack dependency directory (https://snowpack.dev/) 50 | web_modules/ 51 | 52 | # TypeScript cache 53 | *.tsbuildinfo 54 | 55 | # Optional npm cache directory 56 | .npm 57 | 58 | # Optional eslint cache 59 | .eslintcache 60 | 61 | # Microbundle cache 62 | .rpt2_cache/ 63 | .rts2_cache_cjs/ 64 | .rts2_cache_es/ 65 | .rts2_cache_umd/ 66 | 67 | # Optional REPL history 68 | .node_repl_history 69 | 70 | # Output of 'npm pack' 71 | *.tgz 72 | 73 | # Yarn Integrity file 74 | .yarn-integrity 75 | 76 | # dotenv environment variables file 77 | .env 78 | .env.test 79 | 80 | # parcel-bundler cache (https://parceljs.org/) 81 | .cache 82 | .parcel-cache 83 | 84 | # Next.js build output 85 | .next 86 | 87 | # Nuxt.js build / generate output 88 | .nuxt 89 | dist 90 | 91 | # Gatsby files 92 | .cache/ 93 | # Comment in the public line in if your project uses Gatsby and not Next.js 94 | # https://nextjs.org/blog/next-9-1#public-directory-support 95 | # public 96 | 97 | # vuepress build output 98 | .vuepress/dist 99 | 100 | # Serverless directories 101 | .serverless/ 102 | 103 | # FuseBox cache 104 | .fusebox/ 105 | 106 | # DynamoDB Local files 107 | .dynamodb/ 108 | 109 | # TernJS port file 110 | .tern-port 111 | 112 | # Stores VSCode versions used for testing VSCode extensions 113 | .vscode-test 114 | 115 | # yarn v2 116 | 117 | .yarn/cache 118 | .yarn/unplugged 119 | .yarn/build-state.yml 120 | .pnp.* 121 | 122 | ### VisualStudioCode template 123 | .vscode/* 124 | !.vscode/settings.json 125 | !.vscode/tasks.json 126 | !.vscode/launch.json 127 | !.vscode/extensions.json 128 | *.code-workspace 129 | 130 | # Local History for Visual Studio Code 131 | .history/ 132 | 133 | ### JetBrains template 134 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 135 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 136 | 137 | # User-specific stuff 138 | .idea/**/workspace.xml 139 | .idea/**/tasks.xml 140 | .idea/**/usage.statistics.xml 141 | .idea/**/dictionaries 142 | .idea/**/shelf 143 | 144 | # Generated files 145 | .idea/**/contentModel.xml 146 | 147 | # Sensitive or high-churn files 148 | .idea/**/dataSources/ 149 | .idea/**/dataSources.ids 150 | .idea/**/dataSources.local.xml 151 | .idea/**/sqlDataSources.xml 152 | .idea/**/dynamic.xml 153 | .idea/**/uiDesigner.xml 154 | .idea/**/dbnavigator.xml 155 | 156 | # Gradle 157 | .idea/**/gradle.xml 158 | .idea/**/libraries 159 | 160 | # Gradle and Maven with auto-import 161 | # When using Gradle or Maven with auto-import, you should exclude module files, 162 | # since they will be recreated, and may cause churn. Uncomment if using 163 | # auto-import. 164 | # .idea/artifacts 165 | # .idea/compiler.xml 166 | # .idea/jarRepositories.xml 167 | # .idea/modules.xml 168 | # .idea/*.iml 169 | # .idea/modules 170 | # *.iml 171 | # *.ipr 172 | 173 | # CMake 174 | cmake-build-*/ 175 | 176 | # Mongo Explorer plugin 177 | .idea/**/mongoSettings.xml 178 | 179 | # File-based project format 180 | *.iws 181 | 182 | # IntelliJ 183 | out/ 184 | 185 | # mpeltonen/sbt-idea plugin 186 | .idea_modules/ 187 | 188 | # JIRA plugin 189 | atlassian-ide-plugin.xml 190 | 191 | # Cursive Clojure plugin 192 | .idea/replstate.xml 193 | 194 | # Crashlytics plugin (for Android Studio and IntelliJ) 195 | com_crashlytics_export_strings.xml 196 | crashlytics.properties 197 | crashlytics-build.properties 198 | fabric.properties 199 | 200 | # Editor-based Rest Client 201 | .idea/httpRequests 202 | 203 | # Android studio 3.1+ serialized cache file 204 | .idea/caches/build_file_checksums.ser 205 | 206 | -------------------------------------------------------------------------------- /bridged-camera-example-typescript/LICENSE: -------------------------------------------------------------------------------- 1 | ISC License (ISC) 2 | Copyright (c) 2020 Andreas Bauer 3 | 4 | Permission to use, copy, modify, and/or distribute this software for any 5 | purpose with or without fee is hereby granted, provided that the above 6 | copyright notice and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 9 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 11 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 13 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 | PERFORMANCE OF THIS SOFTWARE. 15 | -------------------------------------------------------------------------------- /bridged-camera-example-typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "homebridge-bridged-camera-example", 3 | "version": "1.0.0", 4 | "description": "An example dynamic platform plugin exposing cameras behind a bridge for homebridge written in Typescript", 5 | "main": "dist/dynamic-camera-platform.js", 6 | "scripts": { 7 | "clean": "rimraf ./dist", 8 | "build": "rimraf ./dist && tsc", 9 | "prepublishOnly": "npm run build", 10 | "postpublish": "npm run clean", 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "author": "Andreas Bauer ", 14 | "engines": { 15 | "homebridge": ">=1.0.0" 16 | }, 17 | "keywords": [ 18 | "homebridge-plugin" 19 | ], 20 | "license": "ISC", 21 | "files": [ 22 | "LICENSE", 23 | "dist" 24 | ], 25 | "repository": { 26 | "type": "git", 27 | "url": "git://github.com/homebridge/homebridge-examples.git" 28 | }, 29 | "bugs": { 30 | "url": "https://github.com/homebridge/homebridge-examples/issues" 31 | }, 32 | "dependencies": { 33 | "ip": "^1.1.8" 34 | }, 35 | "devDependencies": { 36 | "@types/node": "16.11.7", 37 | "@types/ip": "^1.1.0", 38 | "typescript": "^5.0.4", 39 | "rimraf": "^5.0.0", 40 | "homebridge": "^1.6.1" 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /bridged-camera-example-typescript/src/dynamic-camera-platform.ts: -------------------------------------------------------------------------------- 1 | import http, {IncomingMessage, Server, ServerResponse} from "http"; 2 | import { 3 | API, 4 | APIEvent, 5 | CameraControllerOptions, 6 | DynamicPlatformPlugin, 7 | HAP, 8 | Logging, 9 | PlatformAccessory, 10 | PlatformAccessoryEvent, 11 | PlatformConfig, 12 | } from "homebridge"; 13 | import {ExampleFFMPEGStreamingDelegate} from "./streamingDelegate"; 14 | 15 | const PLUGIN_NAME = "homebridge-bridged-camera-example"; 16 | const PLATFORM_NAME = "ExampleDynamicCameraPlatform"; 17 | 18 | /* 19 | * IMPORTANT NOTICE 20 | * 21 | * One thing you need to take care of is, that you never ever ever import anything directly from the "homebridge" module (or the "hap-nodejs" module). 22 | * The above import block may seem like, that we do exactly that, but actually those imports are only used for types and interfaces 23 | * and will disappear once the code is compiled to Javascript. 24 | * In fact you can check that by running `npm run build` and opening the compiled Javascript file in the `dist` folder. 25 | * You will notice that the file does not contain a `... = require("homebridge");` statement anywhere in the code. 26 | * 27 | * The contents of the above import statement MUST ONLY be used for type annotation or accessing things like CONST ENUMS, 28 | * which is a special case as they get replaced by the actual value and do not remain as a reference in the compiled code. 29 | * Meaning normal enums are bad, const enums can be used. 30 | * 31 | * You MUST NOT import anything else which remains as a reference in the code, as this will result in 32 | * a `... = require("homebridge");` to be compiled into the final Javascript code. 33 | * This typically leads to unexpected behavior at runtime, as in many cases it won't be able to find the module 34 | * or will import another instance of homebridge causing collisions. 35 | * 36 | * To mitigate this the {@link API | Homebridge API} exposes the whole suite of HAP-NodeJS inside the `hap` property 37 | * of the api object, which can be acquired for example in the initializer function. This reference can be stored 38 | * like this for example and used to access all exported variables and classes from HAP-NodeJS. 39 | */ 40 | let hap: HAP; 41 | let Accessory: typeof PlatformAccessory; 42 | 43 | export = (api: API) => { 44 | hap = api.hap; 45 | Accessory = api.platformAccessory; 46 | 47 | api.registerPlatform(PLATFORM_NAME, ExampleDynamicPlatform); 48 | }; 49 | 50 | class ExampleDynamicPlatform implements DynamicPlatformPlugin { 51 | 52 | private readonly log: Logging; 53 | private readonly api: API; 54 | 55 | private requestServer?: Server; 56 | 57 | private readonly accessories: PlatformAccessory[] = []; 58 | 59 | constructor(log: Logging, config: PlatformConfig, api: API) { 60 | this.log = log; 61 | this.api = api; 62 | 63 | // probably parse config or something here 64 | 65 | log.info("Example platform finished initializing!"); 66 | 67 | /* 68 | * When this event is fired, homebridge restored all cached accessories from disk and did call their respective 69 | * `configureAccessory` method for all of them. Dynamic Platform plugins should only register new accessories 70 | * after this event was fired, in order to ensure they weren't added to homebridge already. 71 | * This event can also be used to start discovery of new accessories. 72 | */ 73 | api.on(APIEvent.DID_FINISH_LAUNCHING, () => { 74 | log.info("Example platform 'didFinishLaunching'"); 75 | 76 | // The idea of this plugin is that we open a http service which exposes api calls to add or remove accessories 77 | this.createHttpService(); 78 | }); 79 | } 80 | 81 | /* 82 | * This function is invoked when homebridge restores cached accessories from disk at startup. 83 | * It should be used to setup event handlers for characteristics and update respective values. 84 | */ 85 | configureAccessory(accessory: PlatformAccessory): void { 86 | this.log("Configuring accessory %s", accessory.displayName); 87 | 88 | accessory.on(PlatformAccessoryEvent.IDENTIFY, () => { 89 | this.log("%s identified!", accessory.displayName); 90 | }); 91 | 92 | const streamingDelegate = new ExampleFFMPEGStreamingDelegate(hap); 93 | const options: CameraControllerOptions = { 94 | cameraStreamCount: 2, // HomeKit requires at least 2 streams, but 1 is also just fine 95 | delegate: streamingDelegate, 96 | 97 | streamingOptions: { 98 | // srtp: true, // legacy option which will just enable AES_CM_128_HMAC_SHA1_80 (can still be used though) 99 | supportedCryptoSuites: [hap.SRTPCryptoSuites.NONE, hap.SRTPCryptoSuites.AES_CM_128_HMAC_SHA1_80], // NONE is not supported by iOS just there for testing with Wireshark for example 100 | video: { 101 | codec: { 102 | profiles: [hap.H264Profile.BASELINE, hap.H264Profile.MAIN, hap.H264Profile.HIGH], 103 | levels: [hap.H264Level.LEVEL3_1, hap.H264Level.LEVEL3_2, hap.H264Level.LEVEL4_0], 104 | }, 105 | resolutions: [ 106 | [1920, 1080, 30], // width, height, framerate 107 | [1280, 960, 30], 108 | [1280, 720, 30], 109 | [1024, 768, 30], 110 | [640, 480, 30], 111 | [640, 360, 30], 112 | [480, 360, 30], 113 | [480, 270, 30], 114 | [320, 240, 30], 115 | [320, 240, 15], // Apple Watch requires this configuration (Apple Watch also seems to required OPUS @16K) 116 | [320, 180, 30], 117 | ], 118 | }, 119 | /* audio option is omitted, as it is not supported in this example; HAP-NodeJS will fake an appropriate audio codec 120 | audio: { 121 | comfort_noise: false, // optional, default false 122 | codecs: [ 123 | { 124 | type: AudioStreamingCodecType.OPUS, 125 | audioChannels: 1, // optional, default 1 126 | samplerate: [AudioStreamingSamplerate.KHZ_16, AudioStreamingSamplerate.KHZ_24], // 16 and 24 must be present for AAC-ELD or OPUS 127 | }, 128 | ], 129 | }, 130 | // */ 131 | } 132 | } 133 | 134 | const cameraController = new hap.CameraController(options); 135 | streamingDelegate.controller = cameraController; 136 | 137 | accessory.configureController(cameraController); 138 | 139 | this.accessories.push(accessory); 140 | } 141 | 142 | // --------------------------- CUSTOM METHODS --------------------------- 143 | 144 | addAccessory(name: string) { 145 | this.log.info("Adding new accessory with name %s", name); 146 | 147 | // uuid must be generated from a unique but not changing data source, name should not be used in the most cases. But works in this specific example. 148 | const uuid = hap.uuid.generate(name); 149 | const accessory = new Accessory(name, uuid); 150 | 151 | this.configureAccessory(accessory); // abusing the configureAccessory here 152 | 153 | this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]); 154 | } 155 | 156 | removeAccessories() { 157 | // we don't have any special identifiers, we just remove all our accessories 158 | 159 | this.log.info("Removing all accessories"); 160 | 161 | this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, this.accessories); 162 | this.accessories.splice(0, this.accessories.length); // clear out the array 163 | } 164 | 165 | createHttpService() { 166 | this.requestServer = http.createServer(this.handleRequest.bind(this)); 167 | this.requestServer.listen(18081, () => this.log.info("Http server listening on 18081...")); 168 | } 169 | 170 | private handleRequest(request: IncomingMessage, response: ServerResponse) { 171 | if (request.url === "/add") { 172 | this.addAccessory(new Date().toISOString()); 173 | } else if (request.url === "/remove") { 174 | this.removeAccessories(); 175 | } 176 | 177 | response.writeHead(204); // 204 No content 178 | response.end(); 179 | } 180 | 181 | // ---------------------------------------------------------------------- 182 | 183 | } 184 | -------------------------------------------------------------------------------- /bridged-camera-example-typescript/src/streamingDelegate.ts: -------------------------------------------------------------------------------- 1 | import ip from "ip"; 2 | import {ChildProcess, spawn} from "child_process"; 3 | import { 4 | CameraController, 5 | CameraStreamingDelegate, 6 | HAP, 7 | PrepareStreamCallback, 8 | PrepareStreamRequest, 9 | PrepareStreamResponse, 10 | SnapshotRequest, 11 | SnapshotRequestCallback, 12 | SRTPCryptoSuites, 13 | StreamingRequest, 14 | StreamRequestCallback, 15 | StreamRequestTypes, 16 | StreamSessionIdentifier, 17 | VideoInfo 18 | } from "homebridge"; 19 | 20 | type SessionInfo = { 21 | address: string, // address of the HAP controller 22 | 23 | videoPort: number, 24 | videoCryptoSuite: SRTPCryptoSuites, // should be saved if multiple suites are supported 25 | videoSRTP: Buffer, // key and salt concatenated 26 | videoSSRC: number, // rtp synchronisation source 27 | 28 | /* Won't be save as audio is not supported by this example 29 | audioPort: number, 30 | audioCryptoSuite: SRTPCryptoSuites, 31 | audioSRTP: Buffer, 32 | audioSSRC: number, 33 | */ 34 | } 35 | 36 | const FFMPEGH264ProfileNames = [ 37 | "baseline", 38 | "main", 39 | "high" 40 | ]; 41 | const FFMPEGH264LevelNames = [ 42 | "3.1", 43 | "3.2", 44 | "4.0" 45 | ]; 46 | 47 | export class ExampleFFMPEGStreamingDelegate implements CameraStreamingDelegate { 48 | 49 | private ffmpegDebugOutput: boolean = false; 50 | 51 | private readonly hap: HAP; 52 | controller?: CameraController; 53 | 54 | // keep track of sessions 55 | pendingSessions: Record = {}; 56 | ongoingSessions: Record = {}; 57 | 58 | constructor(hap: HAP) { 59 | this.hap = hap; 60 | } 61 | 62 | handleSnapshotRequest(request: SnapshotRequest, callback: SnapshotRequestCallback): void { 63 | const ffmpegCommand = `-f lavfi -i testsrc=s=${request.width}x${request.height} -vframes 1 -f mjpeg -`; 64 | const ffmpeg = spawn("ffmpeg", ffmpegCommand.split(" "), {env: process.env}); 65 | 66 | const snapshotBuffers: Buffer[] = []; 67 | 68 | ffmpeg.stdout.on('data', data => snapshotBuffers.push(data)); 69 | ffmpeg.stderr.on('data', data => { 70 | if (this.ffmpegDebugOutput) { 71 | console.log("SNAPSHOT: " + String(data)); 72 | } 73 | }); 74 | 75 | ffmpeg.on('exit', (code, signal) => { 76 | if (signal) { 77 | console.log("Snapshot process was killed with signal: " + signal); 78 | callback(new Error("killed with signal " + signal)); 79 | } else if (code === 0) { 80 | console.log(`Successfully captured snapshot at ${request.width}x${request.height}`); 81 | callback(undefined, Buffer.concat(snapshotBuffers)); 82 | } else { 83 | console.log("Snapshot process exited with code " + code); 84 | callback(new Error("Snapshot process exited with code " + code)); 85 | } 86 | }); 87 | } 88 | 89 | // called when iOS request rtp setup 90 | prepareStream(request: PrepareStreamRequest, callback: PrepareStreamCallback): void { 91 | const sessionId: StreamSessionIdentifier = request.sessionID; 92 | const targetAddress = request.targetAddress; 93 | 94 | const video = request.video; 95 | const videoPort = video.port; 96 | 97 | const videoCryptoSuite = video.srtpCryptoSuite; // could be used to support multiple crypto suite (or support no suite for debugging) 98 | const videoSrtpKey = video.srtp_key; 99 | const videoSrtpSalt = video.srtp_salt; 100 | 101 | const videoSSRC = this.hap.CameraController.generateSynchronisationSource(); 102 | 103 | const sessionInfo: SessionInfo = { 104 | address: targetAddress, 105 | 106 | videoPort: videoPort, 107 | videoCryptoSuite: videoCryptoSuite, 108 | videoSRTP: Buffer.concat([videoSrtpKey, videoSrtpSalt]), 109 | videoSSRC: videoSSRC, 110 | }; 111 | 112 | const currentAddress = ip.address("public", request.addressVersion); // ipAddress version must match 113 | const response: PrepareStreamResponse = { 114 | address: currentAddress, 115 | video: { 116 | port: videoPort, 117 | ssrc: videoSSRC, 118 | 119 | srtp_key: videoSrtpKey, 120 | srtp_salt: videoSrtpSalt, 121 | }, 122 | // audio is omitted as we do not support audio in this example 123 | }; 124 | 125 | this.pendingSessions[sessionId] = sessionInfo; 126 | callback(undefined, response); 127 | } 128 | 129 | // called when iOS device asks stream to start/stop/reconfigure 130 | handleStreamRequest(request: StreamingRequest, callback: StreamRequestCallback): void { 131 | const sessionId = request.sessionID; 132 | 133 | switch (request.type) { 134 | case StreamRequestTypes.START: 135 | const sessionInfo = this.pendingSessions[sessionId]; 136 | 137 | const video: VideoInfo = request.video; 138 | 139 | const profile = FFMPEGH264ProfileNames[video.profile]; 140 | const level = FFMPEGH264LevelNames[video.level]; 141 | const width = video.width; 142 | const height = video.height; 143 | const fps = video.fps; 144 | 145 | const payloadType = video.pt; 146 | const maxBitrate = video.max_bit_rate; 147 | const rtcpInterval = video.rtcp_interval; // usually 0.5 148 | const mtu = video.mtu; // maximum transmission unit 149 | 150 | const address = sessionInfo.address; 151 | const videoPort = sessionInfo.videoPort; 152 | const ssrc = sessionInfo.videoSSRC; 153 | const cryptoSuite = sessionInfo.videoCryptoSuite; 154 | const videoSRTP = sessionInfo.videoSRTP.toString("base64"); 155 | 156 | console.log(`Starting video stream (${width}x${height}, ${fps} fps, ${maxBitrate} kbps, ${mtu} mtu)...`); 157 | 158 | let videoffmpegCommand = `-f lavfi -i testsrc=size=${width}x${height}:rate=${fps} -map 0:0 ` + 159 | `-c:v libx264 -pix_fmt yuv420p -r ${fps} -an -sn -dn -b:v ${maxBitrate}k -bufsize ${2*maxBitrate}k -maxrate ${maxBitrate}k ` + 160 | `-payload_type ${payloadType} -ssrc ${ssrc} -f rtp `; // -profile:v ${profile} -level:v ${level} 161 | 162 | if (cryptoSuite === SRTPCryptoSuites.AES_CM_128_HMAC_SHA1_80) { // actually ffmpeg just supports AES_CM_128_HMAC_SHA1_80 163 | videoffmpegCommand += `-srtp_out_suite AES_CM_128_HMAC_SHA1_80 -srtp_out_params ${videoSRTP} s`; 164 | } 165 | 166 | videoffmpegCommand += `rtp://${address}:${videoPort}?rtcpport=${videoPort}&localrtcpport=${videoPort}&pkt_size=${mtu}`; 167 | 168 | if (this.ffmpegDebugOutput) { 169 | console.log("FFMPEG command: ffmpeg " + videoffmpegCommand); 170 | } 171 | 172 | const ffmpegVideo = spawn('ffmpeg', videoffmpegCommand.split(' '), {env: process.env}); 173 | 174 | let started = false; 175 | ffmpegVideo.stderr.on('data', data => { 176 | if (!started) { 177 | started = true; 178 | console.log("FFMPEG: received first frame"); 179 | 180 | callback(); // do not forget to execute callback once set up 181 | } 182 | 183 | if (this.ffmpegDebugOutput) { 184 | console.log("VIDEO: " + String(data)); 185 | } 186 | }); 187 | ffmpegVideo.on('error', error => { 188 | console.log("[Video] Failed to start video stream: " + error.message); 189 | callback(new Error("ffmpeg process creation failed!")); 190 | }); 191 | ffmpegVideo.on('exit', (code, signal) => { 192 | const message = "[Video] ffmpeg exited with code: " + code + " and signal: " + signal; 193 | 194 | if (code == null || code === 255) { 195 | console.log(message + " (Video stream stopped!)"); 196 | } else { 197 | console.log(message + " (error)"); 198 | 199 | if (!started) { 200 | callback(new Error(message)); 201 | } else { 202 | this.controller!.forceStopStreamingSession(sessionId); 203 | } 204 | } 205 | }); 206 | 207 | this.ongoingSessions[sessionId] = ffmpegVideo; 208 | delete this.pendingSessions[sessionId]; 209 | 210 | break; 211 | case StreamRequestTypes.RECONFIGURE: 212 | // not supported by this example 213 | console.log("Received (unsupported) request to reconfigure to: " + JSON.stringify(request.video)); 214 | callback(); 215 | break; 216 | case StreamRequestTypes.STOP: 217 | const ffmpegProcess = this.ongoingSessions[sessionId]; 218 | 219 | try { 220 | if (ffmpegProcess) { 221 | ffmpegProcess.kill('SIGKILL'); 222 | } 223 | } catch (e) { 224 | console.log("Error occurred terminating the video process!"); 225 | console.log(e); 226 | } 227 | 228 | delete this.ongoingSessions[sessionId]; 229 | 230 | console.log("Stopped streaming session!"); 231 | callback(); 232 | break; 233 | } 234 | } 235 | 236 | } 237 | -------------------------------------------------------------------------------- /bridged-camera-example-typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2018", 4 | "module": "commonjs", 5 | "lib": [ 6 | "ES2015", 7 | "ES2016", 8 | "ES2017", 9 | "ES2018" 10 | ], 11 | "sourceMap": true, 12 | "rootDir": "src", 13 | "outDir": "dist", 14 | 15 | "strict": true, 16 | "esModuleInterop": true, 17 | "forceConsistentCasingInFileNames": true 18 | }, 19 | "include": [ 20 | "src" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /dynamic-platform-example-typescript/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### HAP-NodeJS files 3 | persist 4 | 5 | ### Node template 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # Diagnostic reports (https://nodejs.org/api/report.html) 15 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | *.seed 21 | *.pid.lock 22 | 23 | # Directory for instrumented libs generated by jscoverage/JSCover 24 | lib-cov 25 | 26 | # Coverage directory used by tools like istanbul 27 | coverage 28 | *.lcov 29 | 30 | # nyc test coverage 31 | .nyc_output 32 | 33 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 34 | .grunt 35 | 36 | # Bower dependency directory (https://bower.io/) 37 | bower_components 38 | 39 | # node-waf configuration 40 | .lock-wscript 41 | 42 | # Compiled binary addons (https://nodejs.org/api/addons.html) 43 | build/Release 44 | 45 | # Dependency directories 46 | node_modules/ 47 | jspm_packages/ 48 | 49 | # Snowpack dependency directory (https://snowpack.dev/) 50 | web_modules/ 51 | 52 | # TypeScript cache 53 | *.tsbuildinfo 54 | 55 | # Optional npm cache directory 56 | .npm 57 | 58 | # Optional eslint cache 59 | .eslintcache 60 | 61 | # Microbundle cache 62 | .rpt2_cache/ 63 | .rts2_cache_cjs/ 64 | .rts2_cache_es/ 65 | .rts2_cache_umd/ 66 | 67 | # Optional REPL history 68 | .node_repl_history 69 | 70 | # Output of 'npm pack' 71 | *.tgz 72 | 73 | # Yarn Integrity file 74 | .yarn-integrity 75 | 76 | # dotenv environment variables file 77 | .env 78 | .env.test 79 | 80 | # parcel-bundler cache (https://parceljs.org/) 81 | .cache 82 | .parcel-cache 83 | 84 | # Next.js build output 85 | .next 86 | 87 | # Nuxt.js build / generate output 88 | .nuxt 89 | dist 90 | 91 | # Gatsby files 92 | .cache/ 93 | # Comment in the public line in if your project uses Gatsby and not Next.js 94 | # https://nextjs.org/blog/next-9-1#public-directory-support 95 | # public 96 | 97 | # vuepress build output 98 | .vuepress/dist 99 | 100 | # Serverless directories 101 | .serverless/ 102 | 103 | # FuseBox cache 104 | .fusebox/ 105 | 106 | # DynamoDB Local files 107 | .dynamodb/ 108 | 109 | # TernJS port file 110 | .tern-port 111 | 112 | # Stores VSCode versions used for testing VSCode extensions 113 | .vscode-test 114 | 115 | # yarn v2 116 | 117 | .yarn/cache 118 | .yarn/unplugged 119 | .yarn/build-state.yml 120 | .pnp.* 121 | 122 | ### VisualStudioCode template 123 | .vscode/* 124 | !.vscode/settings.json 125 | !.vscode/tasks.json 126 | !.vscode/launch.json 127 | !.vscode/extensions.json 128 | *.code-workspace 129 | 130 | # Local History for Visual Studio Code 131 | .history/ 132 | 133 | ### JetBrains template 134 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 135 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 136 | 137 | # User-specific stuff 138 | .idea/**/workspace.xml 139 | .idea/**/tasks.xml 140 | .idea/**/usage.statistics.xml 141 | .idea/**/dictionaries 142 | .idea/**/shelf 143 | 144 | # Generated files 145 | .idea/**/contentModel.xml 146 | 147 | # Sensitive or high-churn files 148 | .idea/**/dataSources/ 149 | .idea/**/dataSources.ids 150 | .idea/**/dataSources.local.xml 151 | .idea/**/sqlDataSources.xml 152 | .idea/**/dynamic.xml 153 | .idea/**/uiDesigner.xml 154 | .idea/**/dbnavigator.xml 155 | 156 | # Gradle 157 | .idea/**/gradle.xml 158 | .idea/**/libraries 159 | 160 | # Gradle and Maven with auto-import 161 | # When using Gradle or Maven with auto-import, you should exclude module files, 162 | # since they will be recreated, and may cause churn. Uncomment if using 163 | # auto-import. 164 | # .idea/artifacts 165 | # .idea/compiler.xml 166 | # .idea/jarRepositories.xml 167 | # .idea/modules.xml 168 | # .idea/*.iml 169 | # .idea/modules 170 | # *.iml 171 | # *.ipr 172 | 173 | # CMake 174 | cmake-build-*/ 175 | 176 | # Mongo Explorer plugin 177 | .idea/**/mongoSettings.xml 178 | 179 | # File-based project format 180 | *.iws 181 | 182 | # IntelliJ 183 | out/ 184 | 185 | # mpeltonen/sbt-idea plugin 186 | .idea_modules/ 187 | 188 | # JIRA plugin 189 | atlassian-ide-plugin.xml 190 | 191 | # Cursive Clojure plugin 192 | .idea/replstate.xml 193 | 194 | # Crashlytics plugin (for Android Studio and IntelliJ) 195 | com_crashlytics_export_strings.xml 196 | crashlytics.properties 197 | crashlytics-build.properties 198 | fabric.properties 199 | 200 | # Editor-based Rest Client 201 | .idea/httpRequests 202 | 203 | # Android studio 3.1+ serialized cache file 204 | .idea/caches/build_file_checksums.ser 205 | 206 | -------------------------------------------------------------------------------- /dynamic-platform-example-typescript/LICENSE: -------------------------------------------------------------------------------- 1 | ISC License (ISC) 2 | Copyright (c) 2020 Andreas Bauer 3 | 4 | Permission to use, copy, modify, and/or distribute this software for any 5 | purpose with or without fee is hereby granted, provided that the above 6 | copyright notice and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 9 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 11 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 13 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 | PERFORMANCE OF THIS SOFTWARE. 15 | -------------------------------------------------------------------------------- /dynamic-platform-example-typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "homebridge-dynamic-platform-example", 3 | "version": "1.0.0", 4 | "description": "An example dynamic platform plugin for homebridge written in Typescript", 5 | "main": "dist/dynamic-platform.js", 6 | "scripts": { 7 | "clean": "rimraf ./dist", 8 | "build": "rimraf ./dist && tsc", 9 | "prepublishOnly": "npm run build", 10 | "postpublish": "npm run clean", 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "author": "Andreas Bauer ", 14 | "engines": { 15 | "homebridge": ">=1.0.0" 16 | }, 17 | "license": "ISC", 18 | "files": [ 19 | "LICENSE", 20 | "dist" 21 | ], 22 | "repository": { 23 | "type": "git", 24 | "url": "git://github.com/homebridge/homebridge-examples.git" 25 | }, 26 | "bugs": { 27 | "url": "https://github.com/homebridge/homebridge-examples/issues" 28 | }, 29 | "devDependencies": { 30 | "@types/node": "16.11.7", 31 | "typescript": "^5.0.4", 32 | "rimraf": "^5.0.0", 33 | "homebridge": "^1.6.1" 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /dynamic-platform-example-typescript/src/dynamic-platform.ts: -------------------------------------------------------------------------------- 1 | import http, {IncomingMessage, Server, ServerResponse} from "http"; 2 | import { 3 | API, 4 | APIEvent, 5 | CharacteristicEventTypes, 6 | CharacteristicSetCallback, 7 | CharacteristicValue, 8 | DynamicPlatformPlugin, 9 | HAP, 10 | Logging, 11 | PlatformAccessory, 12 | PlatformAccessoryEvent, 13 | PlatformConfig, 14 | } from "homebridge"; 15 | 16 | const PLUGIN_NAME = "homebridge-dynamic-platform-example"; 17 | const PLATFORM_NAME = "ExampleDynamicPlatform"; 18 | 19 | /* 20 | * IMPORTANT NOTICE 21 | * 22 | * One thing you need to take care of is, that you never ever ever import anything directly from the "homebridge" module (or the "hap-nodejs" module). 23 | * The above import block may seem like, that we do exactly that, but actually those imports are only used for types and interfaces 24 | * and will disappear once the code is compiled to Javascript. 25 | * In fact you can check that by running `npm run build` and opening the compiled Javascript file in the `dist` folder. 26 | * You will notice that the file does not contain a `... = require("homebridge");` statement anywhere in the code. 27 | * 28 | * The contents of the above import statement MUST ONLY be used for type annotation or accessing things like CONST ENUMS, 29 | * which is a special case as they get replaced by the actual value and do not remain as a reference in the compiled code. 30 | * Meaning normal enums are bad, const enums can be used. 31 | * 32 | * You MUST NOT import anything else which remains as a reference in the code, as this will result in 33 | * a `... = require("homebridge");` to be compiled into the final Javascript code. 34 | * This typically leads to unexpected behavior at runtime, as in many cases it won't be able to find the module 35 | * or will import another instance of homebridge causing collisions. 36 | * 37 | * To mitigate this the {@link API | Homebridge API} exposes the whole suite of HAP-NodeJS inside the `hap` property 38 | * of the api object, which can be acquired for example in the initializer function. This reference can be stored 39 | * like this for example and used to access all exported variables and classes from HAP-NodeJS. 40 | */ 41 | let hap: HAP; 42 | let Accessory: typeof PlatformAccessory; 43 | 44 | export = (api: API) => { 45 | hap = api.hap; 46 | Accessory = api.platformAccessory; 47 | 48 | api.registerPlatform(PLATFORM_NAME, ExampleDynamicPlatform); 49 | }; 50 | 51 | class ExampleDynamicPlatform implements DynamicPlatformPlugin { 52 | 53 | private readonly log: Logging; 54 | private readonly api: API; 55 | 56 | private requestServer?: Server; 57 | 58 | private readonly accessories: PlatformAccessory[] = []; 59 | 60 | constructor(log: Logging, config: PlatformConfig, api: API) { 61 | this.log = log; 62 | this.api = api; 63 | 64 | // probably parse config or something here 65 | 66 | log.info("Example platform finished initializing!"); 67 | 68 | /* 69 | * When this event is fired, homebridge restored all cached accessories from disk and did call their respective 70 | * `configureAccessory` method for all of them. Dynamic Platform plugins should only register new accessories 71 | * after this event was fired, in order to ensure they weren't added to homebridge already. 72 | * This event can also be used to start discovery of new accessories. 73 | */ 74 | api.on(APIEvent.DID_FINISH_LAUNCHING, () => { 75 | log.info("Example platform 'didFinishLaunching'"); 76 | 77 | // The idea of this plugin is that we open a http service which exposes api calls to add or remove accessories 78 | this.createHttpService(); 79 | }); 80 | } 81 | 82 | /* 83 | * This function is invoked when homebridge restores cached accessories from disk at startup. 84 | * It should be used to setup event handlers for characteristics and update respective values. 85 | */ 86 | configureAccessory(accessory: PlatformAccessory): void { 87 | this.log("Configuring accessory %s", accessory.displayName); 88 | 89 | accessory.on(PlatformAccessoryEvent.IDENTIFY, () => { 90 | this.log("%s identified!", accessory.displayName); 91 | }); 92 | 93 | accessory.getService(hap.Service.Lightbulb)!.getCharacteristic(hap.Characteristic.On) 94 | .on(CharacteristicEventTypes.SET, (value: CharacteristicValue, callback: CharacteristicSetCallback) => { 95 | this.log.info("%s Light was set to: " + value); 96 | callback(); 97 | }); 98 | 99 | this.accessories.push(accessory); 100 | } 101 | 102 | // --------------------------- CUSTOM METHODS --------------------------- 103 | 104 | addAccessory(name: string) { 105 | this.log.info("Adding new accessory with name %s", name); 106 | 107 | // uuid must be generated from a unique but not changing data source, name should not be used in the most cases. But works in this specific example. 108 | const uuid = hap.uuid.generate(name); 109 | const accessory = new Accessory(name, uuid); 110 | 111 | accessory.addService(hap.Service.Lightbulb, "Test Light"); 112 | 113 | this.configureAccessory(accessory); // abusing the configureAccessory here 114 | 115 | this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]); 116 | } 117 | 118 | removeAccessories() { 119 | // we don't have any special identifiers, we just remove all our accessories 120 | 121 | this.log.info("Removing all accessories"); 122 | 123 | this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, this.accessories); 124 | this.accessories.splice(0, this.accessories.length); // clear out the array 125 | } 126 | 127 | createHttpService() { 128 | this.requestServer = http.createServer(this.handleRequest.bind(this)); 129 | this.requestServer.listen(18081, () => this.log.info("Http server listening on 18081...")); 130 | } 131 | 132 | private handleRequest(request: IncomingMessage, response: ServerResponse) { 133 | if (request.url === "/add") { 134 | this.addAccessory(new Date().toISOString()); 135 | } else if (request.url === "/remove") { 136 | this.removeAccessories(); 137 | } 138 | 139 | response.writeHead(204); // 204 No content 140 | response.end(); 141 | } 142 | 143 | // ---------------------------------------------------------------------- 144 | 145 | } 146 | -------------------------------------------------------------------------------- /dynamic-platform-example-typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2018", 4 | "module": "commonjs", 5 | "lib": [ 6 | "ES2015", 7 | "ES2016", 8 | "ES2017", 9 | "ES2018" 10 | ], 11 | "sourceMap": true, 12 | "rootDir": "src", 13 | "outDir": "dist", 14 | 15 | "strict": true, 16 | "esModuleInterop": true, 17 | "forceConsistentCasingInFileNames": true 18 | }, 19 | "include": [ 20 | "src" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /independent-platform-example-typescript/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### HAP-NodeJS files 3 | persist 4 | 5 | ### Node template 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # Diagnostic reports (https://nodejs.org/api/report.html) 15 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | *.seed 21 | *.pid.lock 22 | 23 | # Directory for instrumented libs generated by jscoverage/JSCover 24 | lib-cov 25 | 26 | # Coverage directory used by tools like istanbul 27 | coverage 28 | *.lcov 29 | 30 | # nyc test coverage 31 | .nyc_output 32 | 33 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 34 | .grunt 35 | 36 | # Bower dependency directory (https://bower.io/) 37 | bower_components 38 | 39 | # node-waf configuration 40 | .lock-wscript 41 | 42 | # Compiled binary addons (https://nodejs.org/api/addons.html) 43 | build/Release 44 | 45 | # Dependency directories 46 | node_modules/ 47 | jspm_packages/ 48 | 49 | # Snowpack dependency directory (https://snowpack.dev/) 50 | web_modules/ 51 | 52 | # TypeScript cache 53 | *.tsbuildinfo 54 | 55 | # Optional npm cache directory 56 | .npm 57 | 58 | # Optional eslint cache 59 | .eslintcache 60 | 61 | # Microbundle cache 62 | .rpt2_cache/ 63 | .rts2_cache_cjs/ 64 | .rts2_cache_es/ 65 | .rts2_cache_umd/ 66 | 67 | # Optional REPL history 68 | .node_repl_history 69 | 70 | # Output of 'npm pack' 71 | *.tgz 72 | 73 | # Yarn Integrity file 74 | .yarn-integrity 75 | 76 | # dotenv environment variables file 77 | .env 78 | .env.test 79 | 80 | # parcel-bundler cache (https://parceljs.org/) 81 | .cache 82 | .parcel-cache 83 | 84 | # Next.js build output 85 | .next 86 | 87 | # Nuxt.js build / generate output 88 | .nuxt 89 | dist 90 | 91 | # Gatsby files 92 | .cache/ 93 | # Comment in the public line in if your project uses Gatsby and not Next.js 94 | # https://nextjs.org/blog/next-9-1#public-directory-support 95 | # public 96 | 97 | # vuepress build output 98 | .vuepress/dist 99 | 100 | # Serverless directories 101 | .serverless/ 102 | 103 | # FuseBox cache 104 | .fusebox/ 105 | 106 | # DynamoDB Local files 107 | .dynamodb/ 108 | 109 | # TernJS port file 110 | .tern-port 111 | 112 | # Stores VSCode versions used for testing VSCode extensions 113 | .vscode-test 114 | 115 | # yarn v2 116 | 117 | .yarn/cache 118 | .yarn/unplugged 119 | .yarn/build-state.yml 120 | .pnp.* 121 | 122 | ### VisualStudioCode template 123 | .vscode/* 124 | !.vscode/settings.json 125 | !.vscode/tasks.json 126 | !.vscode/launch.json 127 | !.vscode/extensions.json 128 | *.code-workspace 129 | 130 | # Local History for Visual Studio Code 131 | .history/ 132 | 133 | ### JetBrains template 134 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 135 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 136 | 137 | # User-specific stuff 138 | .idea/**/workspace.xml 139 | .idea/**/tasks.xml 140 | .idea/**/usage.statistics.xml 141 | .idea/**/dictionaries 142 | .idea/**/shelf 143 | 144 | # Generated files 145 | .idea/**/contentModel.xml 146 | 147 | # Sensitive or high-churn files 148 | .idea/**/dataSources/ 149 | .idea/**/dataSources.ids 150 | .idea/**/dataSources.local.xml 151 | .idea/**/sqlDataSources.xml 152 | .idea/**/dynamic.xml 153 | .idea/**/uiDesigner.xml 154 | .idea/**/dbnavigator.xml 155 | 156 | # Gradle 157 | .idea/**/gradle.xml 158 | .idea/**/libraries 159 | 160 | # Gradle and Maven with auto-import 161 | # When using Gradle or Maven with auto-import, you should exclude module files, 162 | # since they will be recreated, and may cause churn. Uncomment if using 163 | # auto-import. 164 | # .idea/artifacts 165 | # .idea/compiler.xml 166 | # .idea/jarRepositories.xml 167 | # .idea/modules.xml 168 | # .idea/*.iml 169 | # .idea/modules 170 | # *.iml 171 | # *.ipr 172 | 173 | # CMake 174 | cmake-build-*/ 175 | 176 | # Mongo Explorer plugin 177 | .idea/**/mongoSettings.xml 178 | 179 | # File-based project format 180 | *.iws 181 | 182 | # IntelliJ 183 | out/ 184 | 185 | # mpeltonen/sbt-idea plugin 186 | .idea_modules/ 187 | 188 | # JIRA plugin 189 | atlassian-ide-plugin.xml 190 | 191 | # Cursive Clojure plugin 192 | .idea/replstate.xml 193 | 194 | # Crashlytics plugin (for Android Studio and IntelliJ) 195 | com_crashlytics_export_strings.xml 196 | crashlytics.properties 197 | crashlytics-build.properties 198 | fabric.properties 199 | 200 | # Editor-based Rest Client 201 | .idea/httpRequests 202 | 203 | # Android studio 3.1+ serialized cache file 204 | .idea/caches/build_file_checksums.ser 205 | 206 | -------------------------------------------------------------------------------- /independent-platform-example-typescript/LICENSE: -------------------------------------------------------------------------------- 1 | ISC License (ISC) 2 | Copyright (c) 2020 Andreas Bauer 3 | 4 | Permission to use, copy, modify, and/or distribute this software for any 5 | purpose with or without fee is hereby granted, provided that the above 6 | copyright notice and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 9 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 11 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 13 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 | PERFORMANCE OF THIS SOFTWARE. 15 | -------------------------------------------------------------------------------- /independent-platform-example-typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "homebridge-independent-platform-example", 3 | "version": "1.0.0", 4 | "description": "An example independent platform plugin for homebridge written in Typescript", 5 | "main": "dist/independent-platform.js", 6 | "scripts": { 7 | "clean": "rimraf ./dist", 8 | "build": "rimraf ./dist && tsc", 9 | "prepublishOnly": "npm run build", 10 | "postpublish": "npm run clean", 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "author": "Andreas Bauer ", 14 | "engines": { 15 | "homebridge": ">=1.0.0" 16 | }, 17 | "keywords": [ 18 | "homebridge-plugin" 19 | ], 20 | "license": "ISC", 21 | "files": [ 22 | "LICENSE", 23 | "dist" 24 | ], 25 | "repository": { 26 | "type": "git", 27 | "url": "git://github.com/homebridge/homebridge-examples.git" 28 | }, 29 | "bugs": { 30 | "url": "https://github.com/homebridge/homebridge-examples/issues" 31 | }, 32 | "devDependencies": { 33 | "@types/node": "16.18.25", 34 | "typescript": "^5.0.4", 35 | "rimraf": "^5.0.0", 36 | "homebridge": "^1.6.1" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /independent-platform-example-typescript/src/independent-platform.ts: -------------------------------------------------------------------------------- 1 | import { 2 | API, 3 | CharacteristicEventTypes, 4 | CharacteristicGetCallback, 5 | CharacteristicSetCallback, 6 | CharacteristicValue, 7 | HAP, 8 | IndependentPlatformPlugin, 9 | Logging, 10 | PlatformAccessory, 11 | PlatformConfig, 12 | } from "homebridge"; 13 | 14 | const PLUGIN_NAME = "homebridge-independent-platform-example"; 15 | const PLATFORM_NAME = "ExampleIndependentPlatform"; 16 | 17 | /* 18 | * IMPORTANT NOTICE 19 | * 20 | * One thing you need to take care of is, that you never ever ever import anything directly from the "homebridge" module (or the "hap-nodejs" module). 21 | * The above import block may seem like, that we do exactly that, but actually those imports are only used for types and interfaces 22 | * and will disappear once the code is compiled to Javascript. 23 | * In fact you can check that by running `npm run build` and opening the compiled Javascript file in the `dist` folder. 24 | * You will notice that the file does not contain a `... = require("homebridge");` statement anywhere in the code. 25 | * 26 | * The contents of the above import statement MUST ONLY be used for type annotation or accessing things like CONST ENUMS, 27 | * which is a special case as they get replaced by the actual value and do not remain as a reference in the compiled code. 28 | * Meaning normal enums are bad, const enums can be used. 29 | * 30 | * You MUST NOT import anything else which remains as a reference in the code, as this will result in 31 | * a `... = require("homebridge");` to be compiled into the final Javascript code. 32 | * This typically leads to unexpected behavior at runtime, as in many cases it won't be able to find the module 33 | * or will import another instance of homebridge causing collisions. 34 | * 35 | * To mitigate this the {@link API | Homebridge API} exposes the whole suite of HAP-NodeJS inside the `hap` property 36 | * of the api object, which can be acquired for example in the initializer function. This reference can be stored 37 | * like this for example and used to access all exported variables and classes from HAP-NodeJS. 38 | */ 39 | let hap: HAP; 40 | let Accessory: typeof PlatformAccessory; 41 | 42 | export = (api: API) => { 43 | hap = api.hap; 44 | Accessory = api.platformAccessory; 45 | 46 | api.registerPlatform(PLATFORM_NAME, ExampleIndependentPlatform); 47 | }; 48 | 49 | class ExampleIndependentPlatform implements IndependentPlatformPlugin { 50 | 51 | private readonly log: Logging; 52 | private readonly api: API; 53 | 54 | constructor(log: Logging, config: PlatformConfig, api: API) { 55 | this.log = log; 56 | this.api = api; 57 | 58 | // probably parse config or something here 59 | 60 | this.publishExampleExternalAccessory("MySwitch 1"); 61 | 62 | log.info("Example platform finished initializing!"); 63 | } 64 | 65 | publishExampleExternalAccessory(name: string) { 66 | let switchOn = false; 67 | 68 | const uuid = hap.uuid.generate("homebridge:examples:external-switch:" + name); 69 | const accessory = new Accessory("External Switch", uuid); 70 | 71 | const switchService = new hap.Service.Switch(name); 72 | switchService.getCharacteristic(hap.Characteristic.On) 73 | .on(CharacteristicEventTypes.GET, (callback: CharacteristicGetCallback) => { 74 | this.log.info("Current state of the switch was returned: " + (switchOn? "ON": "OFF")); 75 | callback(undefined, switchOn); 76 | }) 77 | .on(CharacteristicEventTypes.SET, (value: CharacteristicValue, callback: CharacteristicSetCallback) => { 78 | switchOn = value as boolean; 79 | this.log.info("Switch state was set to: " + (switchOn? "ON": "OFF")); 80 | callback(); 81 | }); 82 | 83 | accessory.getService(hap.Service.AccessoryInformation)! 84 | .setCharacteristic(hap.Characteristic.Manufacturer, "Custom Manufacturer") 85 | .setCharacteristic(hap.Characteristic.Model, "External Switch"); 86 | 87 | accessory.addService(switchService); 88 | 89 | // will be exposed as an additional accessory and must be paired separately with the pincode of homebridge 90 | this.api.publishExternalAccessories(PLUGIN_NAME, [accessory]); 91 | } 92 | 93 | } 94 | -------------------------------------------------------------------------------- /independent-platform-example-typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2018", 4 | "module": "commonjs", 5 | "lib": [ 6 | "ES2015", 7 | "ES2016", 8 | "ES2017", 9 | "ES2018" 10 | ], 11 | "sourceMap": true, 12 | "rootDir": "src", 13 | "outDir": "dist", 14 | 15 | "strict": true, 16 | "esModuleInterop": true, 17 | "forceConsistentCasingInFileNames": true 18 | }, 19 | "include": [ 20 | "src" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /static-platform-example-typescript/.gitignore: -------------------------------------------------------------------------------- 1 | # Created by .ignore support plugin (hsz.mobi) 2 | ### HAP-NodeJS files 3 | persist 4 | 5 | ### Node template 6 | # Logs 7 | logs 8 | *.log 9 | npm-debug.log* 10 | yarn-debug.log* 11 | yarn-error.log* 12 | lerna-debug.log* 13 | 14 | # Diagnostic reports (https://nodejs.org/api/report.html) 15 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json 16 | 17 | # Runtime data 18 | pids 19 | *.pid 20 | *.seed 21 | *.pid.lock 22 | 23 | # Directory for instrumented libs generated by jscoverage/JSCover 24 | lib-cov 25 | 26 | # Coverage directory used by tools like istanbul 27 | coverage 28 | *.lcov 29 | 30 | # nyc test coverage 31 | .nyc_output 32 | 33 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 34 | .grunt 35 | 36 | # Bower dependency directory (https://bower.io/) 37 | bower_components 38 | 39 | # node-waf configuration 40 | .lock-wscript 41 | 42 | # Compiled binary addons (https://nodejs.org/api/addons.html) 43 | build/Release 44 | 45 | # Dependency directories 46 | node_modules/ 47 | jspm_packages/ 48 | 49 | # Snowpack dependency directory (https://snowpack.dev/) 50 | web_modules/ 51 | 52 | # TypeScript cache 53 | *.tsbuildinfo 54 | 55 | # Optional npm cache directory 56 | .npm 57 | 58 | # Optional eslint cache 59 | .eslintcache 60 | 61 | # Microbundle cache 62 | .rpt2_cache/ 63 | .rts2_cache_cjs/ 64 | .rts2_cache_es/ 65 | .rts2_cache_umd/ 66 | 67 | # Optional REPL history 68 | .node_repl_history 69 | 70 | # Output of 'npm pack' 71 | *.tgz 72 | 73 | # Yarn Integrity file 74 | .yarn-integrity 75 | 76 | # dotenv environment variables file 77 | .env 78 | .env.test 79 | 80 | # parcel-bundler cache (https://parceljs.org/) 81 | .cache 82 | .parcel-cache 83 | 84 | # Next.js build output 85 | .next 86 | 87 | # Nuxt.js build / generate output 88 | .nuxt 89 | dist 90 | 91 | # Gatsby files 92 | .cache/ 93 | # Comment in the public line in if your project uses Gatsby and not Next.js 94 | # https://nextjs.org/blog/next-9-1#public-directory-support 95 | # public 96 | 97 | # vuepress build output 98 | .vuepress/dist 99 | 100 | # Serverless directories 101 | .serverless/ 102 | 103 | # FuseBox cache 104 | .fusebox/ 105 | 106 | # DynamoDB Local files 107 | .dynamodb/ 108 | 109 | # TernJS port file 110 | .tern-port 111 | 112 | # Stores VSCode versions used for testing VSCode extensions 113 | .vscode-test 114 | 115 | # yarn v2 116 | 117 | .yarn/cache 118 | .yarn/unplugged 119 | .yarn/build-state.yml 120 | .pnp.* 121 | 122 | ### VisualStudioCode template 123 | .vscode/* 124 | !.vscode/settings.json 125 | !.vscode/tasks.json 126 | !.vscode/launch.json 127 | !.vscode/extensions.json 128 | *.code-workspace 129 | 130 | # Local History for Visual Studio Code 131 | .history/ 132 | 133 | ### JetBrains template 134 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio, WebStorm and Rider 135 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 136 | 137 | # User-specific stuff 138 | .idea/**/workspace.xml 139 | .idea/**/tasks.xml 140 | .idea/**/usage.statistics.xml 141 | .idea/**/dictionaries 142 | .idea/**/shelf 143 | 144 | # Generated files 145 | .idea/**/contentModel.xml 146 | 147 | # Sensitive or high-churn files 148 | .idea/**/dataSources/ 149 | .idea/**/dataSources.ids 150 | .idea/**/dataSources.local.xml 151 | .idea/**/sqlDataSources.xml 152 | .idea/**/dynamic.xml 153 | .idea/**/uiDesigner.xml 154 | .idea/**/dbnavigator.xml 155 | 156 | # Gradle 157 | .idea/**/gradle.xml 158 | .idea/**/libraries 159 | 160 | # Gradle and Maven with auto-import 161 | # When using Gradle or Maven with auto-import, you should exclude module files, 162 | # since they will be recreated, and may cause churn. Uncomment if using 163 | # auto-import. 164 | # .idea/artifacts 165 | # .idea/compiler.xml 166 | # .idea/jarRepositories.xml 167 | # .idea/modules.xml 168 | # .idea/*.iml 169 | # .idea/modules 170 | # *.iml 171 | # *.ipr 172 | 173 | # CMake 174 | cmake-build-*/ 175 | 176 | # Mongo Explorer plugin 177 | .idea/**/mongoSettings.xml 178 | 179 | # File-based project format 180 | *.iws 181 | 182 | # IntelliJ 183 | out/ 184 | 185 | # mpeltonen/sbt-idea plugin 186 | .idea_modules/ 187 | 188 | # JIRA plugin 189 | atlassian-ide-plugin.xml 190 | 191 | # Cursive Clojure plugin 192 | .idea/replstate.xml 193 | 194 | # Crashlytics plugin (for Android Studio and IntelliJ) 195 | com_crashlytics_export_strings.xml 196 | crashlytics.properties 197 | crashlytics-build.properties 198 | fabric.properties 199 | 200 | # Editor-based Rest Client 201 | .idea/httpRequests 202 | 203 | # Android studio 3.1+ serialized cache file 204 | .idea/caches/build_file_checksums.ser 205 | 206 | -------------------------------------------------------------------------------- /static-platform-example-typescript/LICENSE: -------------------------------------------------------------------------------- 1 | ISC License (ISC) 2 | Copyright (c) 2020 Andreas Bauer 3 | 4 | Permission to use, copy, modify, and/or distribute this software for any 5 | purpose with or without fee is hereby granted, provided that the above 6 | copyright notice and this permission notice appear in all copies. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH 9 | REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY 10 | AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, 11 | INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM 12 | LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 13 | OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 14 | PERFORMANCE OF THIS SOFTWARE. 15 | -------------------------------------------------------------------------------- /static-platform-example-typescript/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "homebridge-static-platform-example", 3 | "version": "1.0.0", 4 | "description": "An example static platform plugin for homebridge written in Typescript", 5 | "main": "dist/static-platform.js", 6 | "scripts": { 7 | "clean": "rimraf ./dist", 8 | "build": "rimraf ./dist && tsc", 9 | "prepublishOnly": "npm run build", 10 | "postpublish": "npm run clean", 11 | "test": "echo \"Error: no test specified\" && exit 1" 12 | }, 13 | "author": "Andreas Bauer ", 14 | "engines": { 15 | "homebridge": ">=1.0.0" 16 | }, 17 | "keywords": [ 18 | "homebridge-plugin" 19 | ], 20 | "license": "ISC", 21 | "files": [ 22 | "LICENSE", 23 | "dist" 24 | ], 25 | "repository": { 26 | "type": "git", 27 | "url": "git://github.com/homebridge/homebridge-examples.git" 28 | }, 29 | "bugs": { 30 | "url": "https://github.com/homebridge/homebridge-examples/issues" 31 | }, 32 | "devDependencies": { 33 | "@types/node": "16.11.7", 34 | "typescript": "^5.0.4", 35 | "rimraf": "^5.0.0", 36 | "homebridge": "^1.6.1" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /static-platform-example-typescript/src/static-platform.ts: -------------------------------------------------------------------------------- 1 | import {AccessoryPlugin, API, HAP, Logging, PlatformConfig, StaticPlatformPlugin,} from "homebridge"; 2 | import {ExampleSwitch} from "./switch-accessory"; 3 | 4 | const PLATFORM_NAME = "ExampleStaticPlatform"; 5 | 6 | /* 7 | * IMPORTANT NOTICE 8 | * 9 | * One thing you need to take care of is, that you never ever ever import anything directly from the "homebridge" module (or the "hap-nodejs" module). 10 | * The above import block may seem like, that we do exactly that, but actually those imports are only used for types and interfaces 11 | * and will disappear once the code is compiled to Javascript. 12 | * In fact you can check that by running `npm run build` and opening the compiled Javascript file in the `dist` folder. 13 | * You will notice that the file does not contain a `... = require("homebridge");` statement anywhere in the code. 14 | * 15 | * The contents of the above import statement MUST ONLY be used for type annotation or accessing things like CONST ENUMS, 16 | * which is a special case as they get replaced by the actual value and do not remain as a reference in the compiled code. 17 | * Meaning normal enums are bad, const enums can be used. 18 | * 19 | * You MUST NOT import anything else which remains as a reference in the code, as this will result in 20 | * a `... = require("homebridge");` to be compiled into the final Javascript code. 21 | * This typically leads to unexpected behavior at runtime, as in many cases it won't be able to find the module 22 | * or will import another instance of homebridge causing collisions. 23 | * 24 | * To mitigate this the {@link API | Homebridge API} exposes the whole suite of HAP-NodeJS inside the `hap` property 25 | * of the api object, which can be acquired for example in the initializer function. This reference can be stored 26 | * like this for example and used to access all exported variables and classes from HAP-NodeJS. 27 | */ 28 | let hap: HAP; 29 | 30 | export = (api: API) => { 31 | hap = api.hap; 32 | 33 | api.registerPlatform(PLATFORM_NAME, ExampleStaticPlatform); 34 | }; 35 | 36 | class ExampleStaticPlatform implements StaticPlatformPlugin { 37 | 38 | private readonly log: Logging; 39 | 40 | constructor(log: Logging, config: PlatformConfig, api: API) { 41 | this.log = log; 42 | 43 | // probably parse config or something here 44 | 45 | log.info("Example platform finished initializing!"); 46 | } 47 | 48 | /* 49 | * This method is called to retrieve all accessories exposed by the platform. 50 | * The Platform can delay the response my invoking the callback at a later time, 51 | * it will delay the bridge startup though, so keep it to a minimum. 52 | * The set of exposed accessories CANNOT change over the lifetime of the plugin! 53 | */ 54 | accessories(callback: (foundAccessories: AccessoryPlugin[]) => void): void { 55 | callback([ 56 | new ExampleSwitch(hap, this.log, "Switch 1"), 57 | new ExampleSwitch(hap, this.log, "Switch 2"), 58 | ]); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /static-platform-example-typescript/src/switch-accessory.ts: -------------------------------------------------------------------------------- 1 | import { 2 | AccessoryPlugin, 3 | CharacteristicGetCallback, 4 | CharacteristicSetCallback, 5 | CharacteristicValue, 6 | HAP, 7 | Logging, 8 | Service, 9 | CharacteristicEventTypes 10 | } from "homebridge"; 11 | 12 | export class ExampleSwitch implements AccessoryPlugin { 13 | 14 | private readonly log: Logging; 15 | 16 | private switchOn = false; 17 | 18 | // This property must be existent!! 19 | name: string; 20 | 21 | private readonly switchService: Service; 22 | private readonly informationService: Service; 23 | 24 | constructor(hap: HAP, log: Logging, name: string) { 25 | this.log = log; 26 | this.name = name; 27 | 28 | this.switchService = new hap.Service.Switch(name); 29 | this.switchService.getCharacteristic(hap.Characteristic.On) 30 | .on(CharacteristicEventTypes.GET, (callback: CharacteristicGetCallback) => { 31 | log.info("Current state of the switch was returned: " + (this.switchOn? "ON": "OFF")); 32 | callback(undefined, this.switchOn); 33 | }) 34 | .on(CharacteristicEventTypes.SET, (value: CharacteristicValue, callback: CharacteristicSetCallback) => { 35 | this.switchOn = value as boolean; 36 | log.info("Switch state was set to: " + (this.switchOn? "ON": "OFF")); 37 | callback(); 38 | }); 39 | 40 | this.informationService = new hap.Service.AccessoryInformation() 41 | .setCharacteristic(hap.Characteristic.Manufacturer, "Custom Manufacturer") 42 | .setCharacteristic(hap.Characteristic.Model, "Custom Model"); 43 | 44 | log.info("Example switch '%s' created!", name); 45 | } 46 | 47 | /* 48 | * This method is optional to implement. It is called when HomeKit ask to identify the accessory. 49 | * Typical this only ever happens at the pairing process. 50 | */ 51 | identify(): void { 52 | this.log("Identify!"); 53 | } 54 | 55 | /* 56 | * This method is called directly after creation of this instance. 57 | * It should return all services which should be added to the accessory. 58 | */ 59 | getServices(): Service[] { 60 | return [ 61 | this.informationService, 62 | this.switchService, 63 | ]; 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /static-platform-example-typescript/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2018", 4 | "module": "commonjs", 5 | "lib": [ 6 | "ES2015", 7 | "ES2016", 8 | "ES2017", 9 | "ES2018" 10 | ], 11 | "sourceMap": true, 12 | "rootDir": "src", 13 | "outDir": "dist", 14 | 15 | "strict": true, 16 | "esModuleInterop": true, 17 | "forceConsistentCasingInFileNames": true 18 | }, 19 | "include": [ 20 | "src" 21 | ] 22 | } 23 | --------------------------------------------------------------------------------