From 84cc9bb49ef8ddf2007face68d20a6403ac5ead8 Mon Sep 17 00:00:00 2001 From: NorthernMan54 <19808920+NorthernMan54@users.noreply.github.com> Date: Tue, 24 Sep 2024 22:03:33 -0400 Subject: [PATCH] Initial build --- config.schema copy.json | 364 +++++++++++++++++++++++++ config.schema.json | 1 + homebridge-ui/public/index.html | 468 ++++++++++++++++++++++++++++++++ homebridge-ui/server.js | 89 ++++++ lib/alexaActions.js | 2 +- package-lock.json | 306 ++++++++------------- package.json | 4 +- plugin.js | 5 + 8 files changed, 1038 insertions(+), 201 deletions(-) create mode 100644 config.schema copy.json create mode 100644 homebridge-ui/public/index.html create mode 100644 homebridge-ui/server.js diff --git a/config.schema copy.json b/config.schema copy.json new file mode 100644 index 0000000..9af81d8 --- /dev/null +++ b/config.schema copy.json @@ -0,0 +1,364 @@ +{ + "pluginAlias": "Alexa", + "pluginType": "platform", + "singular": true, + "headerDisplay": "

Allow your Amazon Alexa to control your homebridge devices


To setup the service:

1 - First create an account on https://www.homebridge.ca/.
2 - Then enter the username and password for your account below.
3 - Save the settings and restart homebridge.
4 - In the Amazon Alexa Application on your smart phone, search for the Homebridge Skill and enable it. When you enable the skill, it will take you to the https://www.homebridge.ca/ website to enable and link the skill to the plugin.
5 - You can now ask Alexa to `discover devices` and it should discover your homebridge devices.

Detailed setup instructions are available here.
", + "footerDisplay": "Homebridge Alexa Skill: https://www.amazon.com/Northern-Man-54-Homebridge/dp/B07B9QMTFQ", + "schema": { + "type": "object", + "properties": { + "name": { + "title": "Name", + "type": "string", + "required": true, + "default": "Alexa", + "description": "Plugin name as displayed in the Homebridge log" + }, + "username": { + "title": "Username", + "type": "string", + "required": true, + "description": "Username for https://www.homebridge.ca/" + }, + "password": { + "title": "Password", + "type": "string", + "required": true, + "description": "Password for https://www.homebridge.ca/" + }, + "pin": { + "title": "Homebridge Pin", + "type": "string", + "placeholder": "031-45-154", + "description": "This needs to match the Homebridge pin set in your config.json file" + }, + "routines": { + "title": "Routines", + "type": "boolean", + "placeholder": false, + "description": "Enables passing of Motion and Contact sensor events to Alexa. For use in the Alexa app to create Routines triggered by these sensors." + }, + "blind": { + "title": "Blind", + "type": "boolean", + "placeholder": false, + "description": "Enables natural wording for opening and closing blinds, and window coverings. Not supported in all countries. Defaults to false" + }, + "door": { + "title": "Door", + "type": "boolean", + "placeholder": false, + "description": "Enables natural wording for opening and closing garage doors. Not supported in all countries. Please note that opening a garage door requires setting a voice pin within the Alexa app. Defaults to false" + }, + "debug": { + "title": "Debug", + "type": "boolean", + "placeholder": false, + "description": "Enable debug level logging to assist in problem investigation." + }, + "beta": { + "title": "beta", + "type": "boolean", + "placeholder": false, + "description": "Enable beta test environment. Only available by invitation." + }, + "refresh": { + "title": "Accessory Cache Refresh Interval", + "type": "integer", + "default": 900, + "description": "Frequency of refreshes of the homebridge accessory cache, in seconds. Defaults to 900 Seconds ( 15 minutes ). This is the interval before new devices/homebridge instances are discovered. This should never require changing, unless you are frequently changing your homebridge configuration without restarting the plugin.", + "minimum": 120, + "maximum": 86400 + }, + "keepalive": { + "title": "Cloud Server Connection Keepalive", + "type": "integer", + "default": "5", + "description": "Frequency of keepalive messages to cloud server, in minutes. Defaults to 5 minutes. Do not change from default unless requested as part of problem investigation.", + "minimum": 1, + "maximum": 59, + "condition": { + "functionBody": "return model.CloudTransport !== 'wss';" + } + }, + "mergeServiceName": { + "title": "Alternate device naming approach", + "type": "boolean", + "description": "This is an alternate device naming approach, which combines the internal HomeKit names for a device. It may resolve duplicate device name issues. Do not enable on an existing implementation, as you will lose control of your existing devices.", + "placeholder": false + }, + "thermostatTurnOn": { + "title": "Thermostat Turn On Behaviour", + "description": "Set Thermostat `Turn On` Behaviour to either Heat, Cool or Auto when Alexa is asked to turn on a Thermostat. Defaults to doing nothing and saying `That command does not work on device ...`.", + "type": "integer", + "oneOf": [ + { + "title": "Heat", + "enum": [ + 1 + ] + }, + { + "title": "Cool", + "enum": [ + 2 + ] + }, + { + "title": "Auto", + "enum": [ + 3 + ] + } + ] + }, + "CloudTransport": { + "title": "Cloud Server Connection Transport", + "description": "Transport options for cloud server connection. MQTTS - this is the recommended setting. MQTT - this is the original/legacy option. WSS - this is the an alternative transport option.", + "type": "string", + "default": "mqtts", + "required": true, + "oneOf": [ + { + "title": "MQTTS", + "enum": [ + "mqtts" + ] + }, + { + "title": "WSS", + "enum": [ + "wss" + ] + }, + { + "title": "MQTT", + "enum": [ + "mqtt" + ] + } + ] + }, + "filter": { + "title": "Homebridge Instance Filter", + "type": "string", + "placeholder": "eg. 192.168.1.122:51826", + "description": "Limits accessories shared with Alexa to particular homebridge instances. Uses ip address and port of homebridge instance, eg. '192.168.1.122:51826' or '192.168.1.11:51551, 192.168.1.11:46047'.", + "pattern": "^(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}:\\d{1,5})(,\\s*\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}:\\d{1,5})*$" + }, + "deviceListHandling": { + "title": "Device List", + "type": "string", + "description": "Allows filtering of devices by name. You can either allow or ignore a list of device names.", + "default": "none", + "required": true, + "oneOf": [ + { + "title": "None", + "enum": [ + "none" + ] + }, + { + "title": "Allow devices", + "enum": [ + "allow" + ] + }, + { + "title": "Ignore devices", + "enum": [ + "deny" + ] + } + ] + }, + "deviceList": { + "title": "Devices to be allowed or denied", + "type": "array", + "items": { + "type": "string" + }, + "condition": { + "functionBody": "if (model.deviceListHandling === 'allow' || model.deviceListHandling === 'deny') { return true } else { return false };" + } + }, + "combine": { + "type": "array", + "items": { + "title": "Combine", + "type": "object", + "properties": { + "into": { + "title": "Into", + "type": "string" + }, + "from": { + "title": "From", + "type": "array", + "items": { + "type": "string" + } + } + } + } + }, + "speakers": { + "title": "Speakers", + "type": "array", + "items": { + "title": "Speaker", + "type": "object", + "properties": { + "manufacturer": { + "title": "Manufacturer", + "type": "string" + }, + "name": { + "title": "Name", + "type": "string" + } + } + } + }, + "enhancedSkip": { + "title": "For 'appletv-enhanced', enable skip", + "type": "boolean", + "placeholder": false, + "description": "This option will change the behaviour of the next or skip command of the 'appletv-enhanced' plugin, from skip to select. This will enable the wording 'Alexa tv skip' to press the select button on the Apple TV remote. This is useful for skipping adds on YouTube." + } + } + }, + "layout": [ + { + "type": "fieldset", + "title": "Required Settings", + "items": [ + { + "type": "flex", + "flex-flow": "row wrap", + "items": [ + "username", + { + "key": "password", + "type": "password" + } + ] + } + ] + }, + { + "type": "fieldset", + "title": "Optional Settings", + "expandable": true, + "expanded": false, + "items": [ + "pin", + "routines", + "debug", + "thermostatTurnOn", + "enhancedSkip", + "deviceListHandling", + { + "key": "deviceList", + "type": "array", + "items": { + "title": "DeviceName", + "description": "Name of the device you want to allow or ignore", + "type": "string" + }, + "condition": { + "functionBody": "return model.deviceListHandling !== 'none';" + } + } + ] + }, + { + "type": "fieldset", + "title": "Advanced Settings", + "expandable": true, + "expanded": false, + "items": [ + "CloudTransport", + "keepalive", + "refresh", + "filter", + "mergeServiceName", + "blind", + "door" + ] + }, + { + "type": "fieldset", + "title": "Speakers", + "description": "Devices to configure as speakers as HomeKit currently does not have a Speaker service.", + "expandable": true, + "expanded": false, + "items": [ + { + "notitle": true, + "key": "speakers", + "type": "array", + "items": [ + { + "type": "div", + "displayFlex": true, + "flex-direction": "row", + "items": [ + { + "key": "speakers[].manufacturer", + "flex": "1 1 50px", + "notitle": true, + "placeholder": "Manufacturer" + }, + { + "key": "speakers[].name", + "flex": "4 4 200px", + "notitle": true, + "placeholder": "Name" + } + ] + } + ] + } + ] + }, + { + "type": "fieldset", + "title": "Combine Accessories", + "description": "Combine disparate accessories into one common device.", + "expandable": true, + "expanded": false, + "items": [ + { + "notitle": true, + "key": "combine", + "type": "array", + "items": [ + { + "type": "div", + "items": [ + { + "key": "combine[].into", + "title": "Into", + "placeholder": "Target Accessory Name" + }, + { + "key": "combine[].from", + "notitle": true, + "items": [ + { + "title": "From", + "key": "combine[].from[]", + "placeholder": "Source Accessory Name" + } + ] + } + ] + } + ] + } + ] + } + ] +} \ No newline at end of file diff --git a/config.schema.json b/config.schema.json index 9af81d8..039b9c5 100644 --- a/config.schema.json +++ b/config.schema.json @@ -2,6 +2,7 @@ "pluginAlias": "Alexa", "pluginType": "platform", "singular": true, + "customUi": true, "headerDisplay": "

Allow your Amazon Alexa to control your homebridge devices


To setup the service:

1 - First create an account on https://www.homebridge.ca/.
2 - Then enter the username and password for your account below.
3 - Save the settings and restart homebridge.
4 - In the Amazon Alexa Application on your smart phone, search for the Homebridge Skill and enable it. When you enable the skill, it will take you to the https://www.homebridge.ca/ website to enable and link the skill to the plugin.
5 - You can now ask Alexa to `discover devices` and it should discover your homebridge devices.

Detailed setup instructions are available here.
", "footerDisplay": "Homebridge Alexa Skill: https://www.amazon.com/Northern-Man-54-Homebridge/dp/B07B9QMTFQ", "schema": { diff --git a/homebridge-ui/public/index.html b/homebridge-ui/public/index.html new file mode 100644 index 0000000..d021e1a --- /dev/null +++ b/homebridge-ui/public/index.html @@ -0,0 +1,468 @@ + + + +
+ + + + + + + + +
+ + \ No newline at end of file diff --git a/homebridge-ui/server.js b/homebridge-ui/server.js new file mode 100644 index 0000000..140ae22 --- /dev/null +++ b/homebridge-ui/server.js @@ -0,0 +1,89 @@ +const axios = require('axios') +const { HomebridgePluginUiServer, RequestError } = require('@homebridge/plugin-ui-utils'); + +class UiServer extends HomebridgePluginUiServer { + constructor() { + super(); + + this.endpointUrl = 'https://app.ecpiot.co.il/mobile/mobilecommand'; + this.imei; + + // create request handlers + this.onRequest('/request-otp', this.requestOtp.bind(this)); + this.onRequest('/check-otp', this.checkOtp.bind(this)); + + // must be called when the script is ready to accept connections + this.ready(); + } + + + /** + * Handle requests sent to /request-otp + */ + async requestOtp(body) { + this.imei = this.generateIMEI(); + + const data = { + 'pvdid': 1, + 'id': 99, + 'cmd': 'SEND_OTP', + 'data': { + 'imei': this.imei, + 'phone': body.phone, + } + } + + try { + const response = await axios.post(this.endpointUrl, data); + return response.data; + } catch (e) { + throw e.response.data; + } + } + + /** + * Handle requests sent to /check-otp + */ + async checkOtp(body) { + const data = { + 'pvdid': 1, + 'id': 99, + 'cmd': 'CHECK_OTP', + 'data': { + 'imei': this.imei, + 'phone': body.phone, + 'code': body.code, + 'os': 'android', + 'osver': 'M4B30Z' + } + } + + let response; + + try { + response = await axios.post(this.endpointUrl, data); + } catch (e) { + throw new RequestError(e.response ? e.response.data : e.message); + } + + if (response.data.data && response.data.data.token) { + return { + imei: this.imei, + token: response.data.data.token, + } + } else { + throw new RequestError(`Could NOT get the token: ${response.data.data ? response.data.data.res_desc : JSON.stringify(response.data)}`); + } + } + + generateIMEI() { + const min = Math.pow(10, 7) + const max = Math.pow(10, 8) - 1 + return '2b950000' + (Math.floor(Math.random() * (max - min) + min) + 1) + } +} + +// start the instance of the class +(() => { + return new UiServer; +})(); \ No newline at end of file diff --git a/lib/alexaActions.js b/lib/alexaActions.js index 3638a65..8d0a4c2 100644 --- a/lib/alexaActions.js +++ b/lib/alexaActions.js @@ -116,7 +116,7 @@ function alexaDiscovery(message, callback) { } if (response && response.event.payload.endpoints.length < 1) { - this.log("ERROR: HAP Discovery failed, please review config"); + this.log.error("ERROR: HAP Discovery failed, please review config"); } else { if (process.uptime() > 600) { // Only use console during startup debug("alexaDiscovery - returned %s devices", response.event.payload.endpoints.length); diff --git a/package-lock.json b/package-lock.json index d2ec520..54db86e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,8 @@ "version": "0.8.0", "license": "Apache-2.0", "dependencies": { + "@homebridge/plugin-ui-utils": "^1.0.3", + "axios": "^1.7.7", "bottleneck": "2.19.5", "debug": "4.3.7", "hap-node-client": "^0.2.9", @@ -652,6 +654,12 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", "dev": true }, + "node_modules/@homebridge/plugin-ui-utils": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@homebridge/plugin-ui-utils/-/plugin-ui-utils-1.0.3.tgz", + "integrity": "sha512-p2S/czGYNRnRtMICxBUk4Uar+KCezfyxjqfStfxKgykD2082SNayVDncYUK1xRai78EGHCbif9eoyrmDweh4tQ==", + "license": "MIT" + }, "node_modules/@jest/types": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", @@ -1377,24 +1385,6 @@ "node": ">=8" } }, - "node_modules/@oznu/hap-client/node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "node_modules/@oznu/hap-client/node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/@oznu/hap-client/node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -1662,18 +1652,6 @@ "color-support": "bin.js" } }, - "node_modules/@oznu/hap-client/node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/@oznu/hap-client/node_modules/commander": { "version": "10.0.1", "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", @@ -1828,15 +1806,6 @@ "node": ">=10" } }, - "node_modules/@oznu/hap-client/node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/@oznu/hap-client/node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -2002,26 +1971,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@oznu/hap-client/node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, "node_modules/@oznu/hap-client/node_modules/foreground-child": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", @@ -2038,20 +1987,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/@oznu/hap-client/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/@oznu/hap-client/node_modules/form-data-encoder": { "version": "2.1.4", "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-2.1.4.tgz", @@ -2849,27 +2784,6 @@ "node": ">=8.6" } }, - "node_modules/@oznu/hap-client/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/@oznu/hap-client/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/@oznu/hap-client/node_modules/mimic-response": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-4.0.0.tgz", @@ -3861,12 +3775,6 @@ "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==", "dev": true }, - "node_modules/@oznu/hap-client/node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true - }, "node_modules/@oznu/hap-client/node_modules/pupa": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/pupa/-/pupa-3.1.0.tgz", @@ -5410,6 +5318,105 @@ "undici-types": "~6.19.2" } }, + "node_modules/axios": { + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/axios/node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/axios/node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/axios/node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/axios/node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/axios/node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/axios/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/axios/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/axios/node_modules/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", + "license": "MIT" + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -6704,12 +6711,6 @@ "integrity": "sha512-zPMVc3ZYlGLNk4mpK1NzP2wg0ml9t7fUgDsayR5Y5rSzxQilzR9FGu/EH2jQOcKSAeAfWeylyW8juy3OkWRvNA==", "license": "MIT" }, - "node_modules/hap-node-client/node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "license": "MIT" - }, "node_modules/hap-node-client/node_modules/available-typed-arrays": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", @@ -6725,17 +6726,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hap-node-client/node_modules/axios": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", - "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", - "license": "MIT", - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, "node_modules/hap-node-client/node_modules/axios-retry": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/axios-retry/-/axios-retry-4.5.0.tgz", @@ -6836,18 +6826,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hap-node-client/node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, "node_modules/hap-node-client/node_modules/deep-equal": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", @@ -6914,15 +6892,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hap-node-client/node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "license": "MIT", - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/hap-node-client/node_modules/dns-packet": { "version": "5.6.1", "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz", @@ -6981,26 +6950,6 @@ "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" }, - "node_modules/hap-node-client/node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, "node_modules/hap-node-client/node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", @@ -7010,20 +6959,6 @@ "is-callable": "^1.1.3" } }, - "node_modules/hap-node-client/node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "license": "MIT", - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/hap-node-client/node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -7417,27 +7352,6 @@ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "license": "MIT" }, - "node_modules/hap-node-client/node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "license": "MIT", - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/hap-node-client/node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "license": "MIT", - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/hap-node-client/node_modules/multicast-dns": { "version": "7.2.5", "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz", @@ -7534,12 +7448,6 @@ "node": ">= 0.4" } }, - "node_modules/hap-node-client/node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "license": "MIT" - }, "node_modules/hap-node-client/node_modules/regexp.prototype.flags": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", diff --git a/package.json b/package.json index 108cbfa..d136f2e 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ "watch": [], "ext": "js", "ignore": [], - "exec": "~/npm/bin/homebridge -D -R -P ~/Code", + "exec": "~/npm/bin/homebridge -D -P ~/Code", "signal": "SIGTERM", "env": { "NODE_OPTIONS": "--trace-warnings" @@ -47,6 +47,8 @@ "ws": "^8.14.2" }, "dependencies": { + "@homebridge/plugin-ui-utils": "^1.0.3", + "axios": "^1.7.7", "bottleneck": "2.19.5", "debug": "4.3.7", "hap-node-client": "^0.2.9", diff --git a/plugin.js b/plugin.js index a1bf723..24adf53 100644 --- a/plugin.js +++ b/plugin.js @@ -149,6 +149,11 @@ alexaHome.prototype.didFinishLaunching = function () { }; // Initialize HAP Connections + if (options.filter) { + this.log(`Starting Homebridge discovery with filter: '${options.filter}'`,); + } else { + this.log("Starting Homebridge discovery"); + } alexaActions.hapDiscovery(options); var alexa = new AlexaLocal(options);