diff --git a/CHANGELOG.md b/CHANGELOG.md
index d638bf8a..6f89c946 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,18 @@
All notable changes to this project will be documented in this file. This project uses [Semantic Versioning](https://semver.org/)
-## [Version 1.3.0](https://github.com/OpenWonderLabs/homebridge-switchbot/releases/tag/v1.3.0) (2021-12-2)
+## [Version 1.4.0](https://github.com/OpenWonderLabs/homebridge-switchbot/releases/tag/v1.4.0) (2021-12-15)
+
+## What's Changed
+* Added Status Messages to logs for discoverDevices request.
+* Added Cached Status to IR device, Status will be saved to accessory context and restored on restart.
+* Added Option `Offline as Off` to be able set the device as off, if API reports offline.
+* Removed Meter Unit Config Option as it was confusing and probably never used.
+* Housekeeping and updated dependencies.
+
+**Full Changelog**: https://github.com/OpenWonderLabs/homebridge-switchbot/compare/v1.3.0...v1.4.0
+
+## [Version 1.3.0](https://github.com/OpenWonderLabs/homebridge-switchbot/releases/tag/v1.3.0) (2021-12-02)
## What's Changed
* Added Adpative Lighting to Color Bulb
diff --git a/config.schema.json b/config.schema.json
index 2626dc88..cf238f96 100644
--- a/config.schema.json
+++ b/config.schema.json
@@ -58,6 +58,14 @@
"hide_device": {
"title": "Hide Device",
"type": "boolean",
+ "description": "If true then devices that are reported as offline will be shown as off in HomeKit.",
+ "condition": {
+ "functionBody": "return (model.options && model.options.devices && model.options.devices[arrayIndices].deviceId);"
+ }
+ },
+ "offline": {
+ "title": "Offline as Off",
+ "type": "boolean",
"condition": {
"functionBody": "return (model.options && model.options.devices && model.options.devices[arrayIndices].deviceId);"
}
@@ -196,27 +204,6 @@
"condition": {
"functionBody": "return (model.options && model.options.devices && !model.options.devices[arrayIndices].hide_device && model.options.devices[arrayIndices].configDeviceType === 'Meter' && model.options.devices[arrayIndices].deviceId);"
}
- },
- "unit": {
- "title": "Convert your Meter's Temperature to Celsius or Fahrenheit",
- "type": "number",
- "oneOf": [
- {
- "title": "Celsius",
- "enum": [
- 0
- ]
- },
- {
- "title": "Fahrenheit",
- "enum": [
- 1
- ]
- }
- ],
- "condition": {
- "functionBody": "return (model.options && model.options.devices && !model.options.devices[arrayIndices].hide_device && model.options.devices[arrayIndices].configDeviceType === 'Meter' && model.options.devices[arrayIndices].deviceId && !model.options.devices[arrayIndices].meter.hide_temperature);"
- }
}
}
},
@@ -561,14 +548,14 @@
"type": "object",
"properties": {
"swing_mode": {
- "title": "Enable Swing Mode by Device ID",
+ "title": "Enable Swing Mode",
"type": "boolean",
"condition": {
"functionBody": "return (model.options && model.options.irdevices && !model.options.irdevices[arrayIndices].hide_device && (model.options.irdevices[arrayIndices].configRemoteType === 'Fan' || model.options.irdevices[arrayIndices].configRemoteType === 'DIY Fan') && model.options.irdevices[arrayIndices].deviceId);"
}
},
"rotation_speed": {
- "title": "Enable Rotation Speed by Device ID",
+ "title": "Enable Rotation Speed",
"type": "boolean",
"condition": {
"functionBody": "return (model.options && model.options.irdevices && !model.options.irdevices[arrayIndices].hide_device && (model.options.irdevices[arrayIndices].configRemoteType === 'Fan' || model.options.irdevices[arrayIndices].configRemoteType === 'DIY Fan') && model.options.irdevices[arrayIndices].deviceId);"
@@ -643,7 +630,7 @@
"type": "string",
"placeholder": "Off",
"condition": {
- "functionBody": "return (model.options && model.options.irdevices && !model.options.irdevices[arrayIndices].hide_device && model.options.irdevices[arrayIndices].configRemoteType === 'Others' && model.options.irdevices[arrayIndices].deviceId && model.options.irdevices[arrayIndices].other && !model.options.irdevices[arrayIndices].other.deviceType);"
+ "functionBody": "return (model.options && model.options.irdevices && !model.options.irdevices[arrayIndices].hide_device && model.options.irdevices[arrayIndices].configRemoteType === 'Others' && model.options.irdevices[arrayIndices].deviceId && model.options.irdevices[arrayIndices].other && model.options.irdevices[arrayIndices].other.deviceType);"
}
}
}
@@ -716,13 +703,13 @@
"options.devices[].configDeviceName",
"options.devices[].deviceId",
"options.devices[].hide_device",
+ "options.devices[].offline",
"options.devices[].ble",
"options.devices[].configDeviceType",
"options.devices[].bot.mode",
"options.devices[].bot.deviceType",
"options.devices[].meter.hide_temperature",
"options.devices[].meter.hide_humidity",
- "options.devices[].meter.unit",
"options.devices[].humidifier.set_minStep",
"options.devices[].humidifier.hide_temperature",
"options.devices[].curtain.set_minStep",
diff --git a/homebridge-ui/public/index.html b/homebridge-ui/public/index.html
index 6654603f..7461d502 100644
--- a/homebridge-ui/public/index.html
+++ b/homebridge-ui/public/index.html
@@ -64,7 +64,10 @@
Firmware Version |
|
-
+
+ Device Type |
+ |
+
Connection Type |
|
@@ -173,6 +176,7 @@ Help/About
document.getElementById('deviceID').innerHTML = context.deviceID
document.getElementById('model').innerHTML = context.model
document.getElementById('firmwareRevision').innerHTML = context.firmwareRevision || 'N/A'
+ document.getElementById('deviceType').innerHTML = context.deviceType
document.getElementById('connectionType').innerHTML = context.connectionType
document.getElementById('deviceTable').style.display = 'inline-table'
homebridge.hideSpinner()
diff --git a/package-lock.json b/package-lock.json
index e0fdb81e..4d3dfd87 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "@switchbot/homebridge-switchbot",
- "version": "1.3.0",
+ "version": "1.4.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@switchbot/homebridge-switchbot",
- "version": "1.3.0",
+ "version": "1.4.0",
"funding": [
{
"type": "Paypal",
@@ -21,21 +21,21 @@
"rxjs": "^7.4.0"
},
"devDependencies": {
- "@types/node": "^16.11.11",
- "@typescript-eslint/eslint-plugin": "^5.5.0",
- "@typescript-eslint/parser": "^5.5.0",
- "eslint": "^8.3.0",
+ "@types/node": "^17.0.0",
+ "@typescript-eslint/eslint-plugin": "^5.7.0",
+ "@typescript-eslint/parser": "^5.7.0",
+ "eslint": "^8.4.1",
"homebridge": "^1.3.8",
"nodemon": "^2.0.15",
- "npm-check-updates": "^12.0.2",
+ "npm-check-updates": "^12.0.5",
"rimraf": "^3.0.2",
"ts-node": "^10.4.0",
- "typescript": "^4.5.2",
+ "typescript": "^4.5.4",
"typescript-axios-wb": "^1.0.3"
},
"engines": {
"homebridge": "^1.3.8",
- "node": "^14.18.1 || ^16.13.0"
+ "node": "^14.18.2 || ^16.13.1"
}
},
"node_modules/@abandonware/bluetooth-hci-socket": {
@@ -103,14 +103,14 @@
}
},
"node_modules/@eslint/eslintrc": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.4.tgz",
- "integrity": "sha512-h8Vx6MdxwWI2WM8/zREHMoqdgLNXEL4QX3MWSVMdyNJGvXVOs+6lp+m2hc3FnuMHDc4poxFNI20vCk0OmI4G0Q==",
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz",
+ "integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==",
"dev": true,
"dependencies": {
"ajv": "^6.12.4",
"debug": "^4.3.2",
- "espree": "^9.0.0",
+ "espree": "^9.2.0",
"globals": "^13.9.0",
"ignore": "^4.0.6",
"import-fresh": "^3.2.1",
@@ -158,12 +158,12 @@
"integrity": "sha512-axFX7lN2Yd7bz/6SlD7dzq5sY/N9+XYuLHPukuiyHQRDtNMRL1uDqJhOx6RVaN2tYDHB75h7YxRQWP7U44Mgzg=="
},
"node_modules/@humanwhocodes/config-array": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz",
- "integrity": "sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==",
+ "version": "0.9.2",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.2.tgz",
+ "integrity": "sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA==",
"dev": true,
"dependencies": {
- "@humanwhocodes/object-schema": "^1.2.0",
+ "@humanwhocodes/object-schema": "^1.2.1",
"debug": "^4.1.1",
"minimatch": "^3.0.4"
},
@@ -239,13 +239,16 @@
}
},
"node_modules/@npmcli/fs": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.0.0.tgz",
- "integrity": "sha512-8ltnOpRR/oJbOp8vaGUnipOi3bqkcW+sLHFlyXIr08OGHmVJLB1Hn7QtGXbYcpVtH1gAYZTlmDXtE4YV0+AMMQ==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.0.tgz",
+ "integrity": "sha512-VhP1qZLXcrXRIaPoqb4YA55JQxLNF3jNR4T55IdOJa3+IFJKNYHtPvtXx8slmeMavj37vCzCfrqQM1vWLsYKLA==",
"dev": true,
"dependencies": {
"@gar/promisify": "^1.0.1",
"semver": "^7.3.5"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16"
}
},
"node_modules/@npmcli/git": {
@@ -405,19 +408,19 @@
"dev": true
},
"node_modules/@types/node": {
- "version": "16.11.11",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.11.tgz",
- "integrity": "sha512-KB0sixD67CeecHC33MYn+eYARkqTheIRNuu97y2XMjR7Wu3XibO1vaY6VBV6O/a89SPI81cEUIYT87UqUWlZNw==",
+ "version": "17.0.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.0.tgz",
+ "integrity": "sha512-eMhwJXc931Ihh4tkU+Y7GiLzT/y/DBNpNtr4yU9O2w3SYBsr9NaOPhQlLKRmoWtI54uNwuo0IOUFQjVOTZYRvw==",
"dev": true
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.5.0.tgz",
- "integrity": "sha512-4bV6fulqbuaO9UMXU0Ia0o6z6if+kmMRW8rMRyfqXj/eGrZZRGedS4n0adeGNnjr8LKAM495hrQ7Tea52UWmQA==",
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.7.0.tgz",
+ "integrity": "sha512-8RTGBpNn5a9M628wBPrCbJ+v3YTEOE2qeZb7TDkGKTDXSj36KGRg92SpFFaR/0S3rSXQxM0Og/kV9EyadsYSBg==",
"dev": true,
"dependencies": {
- "@typescript-eslint/experimental-utils": "5.5.0",
- "@typescript-eslint/scope-manager": "5.5.0",
+ "@typescript-eslint/experimental-utils": "5.7.0",
+ "@typescript-eslint/scope-manager": "5.7.0",
"debug": "^4.3.2",
"functional-red-black-tree": "^1.0.1",
"ignore": "^5.1.8",
@@ -443,15 +446,15 @@
}
},
"node_modules/@typescript-eslint/experimental-utils": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.5.0.tgz",
- "integrity": "sha512-kjWeeVU+4lQ1SLYErRKV5yDXbWDPkpbzTUUlfAUifPYvpX0qZlrcCZ96/6oWxt3QxtK5WVhXz+KsnwW9cIW+3A==",
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.7.0.tgz",
+ "integrity": "sha512-u57eZ5FbEpzN5kSjmVrSesovWslH2ZyNPnaXQMXWgH57d5+EVHEt76W75vVuI9qKZ5BMDKNfRN+pxcPEjQjb2A==",
"dev": true,
"dependencies": {
"@types/json-schema": "^7.0.9",
- "@typescript-eslint/scope-manager": "5.5.0",
- "@typescript-eslint/types": "5.5.0",
- "@typescript-eslint/typescript-estree": "5.5.0",
+ "@typescript-eslint/scope-manager": "5.7.0",
+ "@typescript-eslint/types": "5.7.0",
+ "@typescript-eslint/typescript-estree": "5.7.0",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0"
},
@@ -467,14 +470,14 @@
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.5.0.tgz",
- "integrity": "sha512-JsXBU+kgQOAgzUn2jPrLA+Rd0Y1dswOlX3hp8MuRO1hQDs6xgHtbCXEiAu7bz5hyVURxbXcA2draasMbNqrhmg==",
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.7.0.tgz",
+ "integrity": "sha512-m/gWCCcS4jXw6vkrPQ1BjZ1vomP01PArgzvauBqzsoZ3urLbsRChexB8/YV8z9HwE3qlJM35FxfKZ1nfP/4x8g==",
"dev": true,
"dependencies": {
- "@typescript-eslint/scope-manager": "5.5.0",
- "@typescript-eslint/types": "5.5.0",
- "@typescript-eslint/typescript-estree": "5.5.0",
+ "@typescript-eslint/scope-manager": "5.7.0",
+ "@typescript-eslint/types": "5.7.0",
+ "@typescript-eslint/typescript-estree": "5.7.0",
"debug": "^4.3.2"
},
"engines": {
@@ -494,13 +497,13 @@
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.5.0.tgz",
- "integrity": "sha512-0/r656RmRLo7CbN4Mdd+xZyPJ/fPCKhYdU6mnZx+8msAD8nJSP8EyCFkzbd6vNVZzZvWlMYrSNekqGrCBqFQhg==",
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.7.0.tgz",
+ "integrity": "sha512-7mxR520DGq5F7sSSgM0HSSMJ+TFUymOeFRMfUfGFAVBv8BR+Jv1vHgAouYUvWRZeszVBJlLcc9fDdktxb5kmxA==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "5.5.0",
- "@typescript-eslint/visitor-keys": "5.5.0"
+ "@typescript-eslint/types": "5.7.0",
+ "@typescript-eslint/visitor-keys": "5.7.0"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -511,9 +514,9 @@
}
},
"node_modules/@typescript-eslint/types": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.5.0.tgz",
- "integrity": "sha512-OaYTqkW3GnuHxqsxxJ6KypIKd5Uw7bFiQJZRyNi1jbMJnK3Hc/DR4KwB6KJj6PBRkJJoaNwzMNv9vtTk87JhOg==",
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.7.0.tgz",
+ "integrity": "sha512-5AeYIF5p2kAneIpnLFve8g50VyAjq7udM7ApZZ9JYjdPjkz0LvODfuSHIDUVnIuUoxafoWzpFyU7Sqbxgi79mA==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
@@ -524,13 +527,13 @@
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.5.0.tgz",
- "integrity": "sha512-pVn8btYUiYrjonhMAO0yG8lm7RApzy2L4RC7Td/mC/qFkyf6vRbGyZozoA94+w6D2Y2GRqpMoCWcwx/EUOzyoQ==",
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.7.0.tgz",
+ "integrity": "sha512-aO1Ql+izMrTnPj5aFFlEJkpD4jRqC4Gwhygu2oHK2wfVQpmOPbyDSveJ+r/NQo+PWV43M6uEAeLVbTi09dFLhg==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "5.5.0",
- "@typescript-eslint/visitor-keys": "5.5.0",
+ "@typescript-eslint/types": "5.7.0",
+ "@typescript-eslint/visitor-keys": "5.7.0",
"debug": "^4.3.2",
"globby": "^11.0.4",
"is-glob": "^4.0.3",
@@ -551,12 +554,12 @@
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.5.0.tgz",
- "integrity": "sha512-4GzJ1kRtsWzHhdM40tv0ZKHNSbkDhF0Woi/TDwVJX6UICwJItvP7ZTXbjTkCdrors7ww0sYe0t+cIKDAJwZ7Kw==",
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.7.0.tgz",
+ "integrity": "sha512-hdohahZ4lTFcglZSJ3DGdzxQHBSxsLVqHzkiOmKi7xVAWC4y2c1bIMKmPJSrA4aOEoRUPOKQ87Y/taC7yVHpFg==",
"dev": true,
"dependencies": {
- "@typescript-eslint/types": "5.5.0",
+ "@typescript-eslint/types": "5.7.0",
"eslint-visitor-keys": "^3.0.0"
},
"engines": {
@@ -1072,13 +1075,15 @@
}
},
"node_modules/cli-table": {
- "version": "0.3.9",
- "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.9.tgz",
- "integrity": "sha512-7eA6hFtAZwVx3dWAGoaBqTrzWko5jRUFKpHT64ZHkJpaA3y5wf5NlLjguqTRmqycatJZiwftODYYyGNLbQ7MuA==",
+ "version": "0.3.11",
+ "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz",
+ "integrity": "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==",
"dev": true,
"dependencies": {
- "colors": "1.0.3",
- "strip-ansi": "^6.0.1"
+ "colors": "1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.2.0"
}
},
"node_modules/clone-response": {
@@ -1514,13 +1519,13 @@
}
},
"node_modules/eslint": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.3.0.tgz",
- "integrity": "sha512-aIay56Ph6RxOTC7xyr59Kt3ewX185SaGnAr8eWukoPLeriCrvGjvAubxuvaXOfsxhtwV5g0uBOsyhAom4qJdww==",
+ "version": "8.4.1",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.4.1.tgz",
+ "integrity": "sha512-TxU/p7LB1KxQ6+7aztTnO7K0i+h0tDi81YRY9VzB6Id71kNz+fFYnf5HD5UOQmxkzcoa0TlVZf9dpMtUv0GpWg==",
"dev": true,
"dependencies": {
- "@eslint/eslintrc": "^1.0.4",
- "@humanwhocodes/config-array": "^0.6.0",
+ "@eslint/eslintrc": "^1.0.5",
+ "@humanwhocodes/config-array": "^0.9.2",
"ajv": "^6.10.0",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",
@@ -1531,7 +1536,7 @@
"eslint-scope": "^7.1.0",
"eslint-utils": "^3.0.0",
"eslint-visitor-keys": "^3.1.0",
- "espree": "^9.1.0",
+ "espree": "^9.2.0",
"esquery": "^1.4.0",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
@@ -1649,9 +1654,9 @@
}
},
"node_modules/espree": {
- "version": "9.1.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-9.1.0.tgz",
- "integrity": "sha512-ZgYLvCS1wxOczBYGcQT9DDWgicXwJ4dbocr9uYN+/eresBAUuBu+O4WzB21ufQ/JqQT8gyp7hJ3z8SHii32mTQ==",
+ "version": "9.2.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.2.0.tgz",
+ "integrity": "sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg==",
"dev": true,
"dependencies": {
"acorn": "^8.6.0",
@@ -1858,9 +1863,9 @@
"dev": true
},
"node_modules/follow-redirects": {
- "version": "1.14.5",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz",
- "integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==",
+ "version": "1.14.6",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz",
+ "integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A==",
"funding": [
{
"type": "individual",
@@ -2607,9 +2612,9 @@
}
},
"node_modules/is-negative-zero": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
- "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==",
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
+ "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
"dev": true,
"engines": {
"node": ">= 0.4"
@@ -2771,22 +2776,26 @@
}
},
"node_modules/is-weakref": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.1.tgz",
- "integrity": "sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
"dev": true,
"dependencies": {
- "call-bind": "^1.0.0"
+ "call-bind": "^1.0.2"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-weakset": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.1.tgz",
- "integrity": "sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw==",
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz",
+ "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==",
"dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ },
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
@@ -3172,9 +3181,9 @@
"dev": true
},
"node_modules/minipass": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz",
- "integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==",
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
+ "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
"devOptional": true,
"dependencies": {
"yallist": "^4.0.0"
@@ -3509,15 +3518,15 @@
}
},
"node_modules/npm-check-updates": {
- "version": "12.0.2",
- "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-12.0.2.tgz",
- "integrity": "sha512-VzMNuUXqRta1qpBkFiE0hKfpOGP2FbYwpBBTcJXoJWppOPBSi/paWFVhPVWf7PgRoDWegK+PDAWKhIvhyrBrIg==",
+ "version": "12.0.5",
+ "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-12.0.5.tgz",
+ "integrity": "sha512-ns1liBBogwjmOVZY/PYgeIoarItwdOSBxccJDZKKkxsMkXges/Bp5CAnQIvYwlsz6fByQJFvqXSOqwIUBY6gpQ==",
"dev": true,
"dependencies": {
"chalk": "^4.1.2",
"cint": "^8.2.1",
- "cli-table": "^0.3.6",
- "commander": "^6.2.1",
+ "cli-table": "^0.3.11",
+ "commander": "^8.3.0",
"fast-memoize": "^2.5.2",
"find-up": "5.0.0",
"fp-and-or": "^0.1.3",
@@ -3539,7 +3548,7 @@
"rimraf": "^3.0.2",
"semver": "^7.3.5",
"semver-utils": "^1.1.4",
- "source-map-support": "^0.5.20",
+ "source-map-support": "^0.5.21",
"spawn-please": "^1.0.0",
"update-notifier": "^5.1.0"
},
@@ -3552,12 +3561,12 @@
}
},
"node_modules/npm-check-updates/node_modules/commander": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
- "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
+ "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
"dev": true,
"engines": {
- "node": ">= 6"
+ "node": ">= 12"
}
},
"node_modules/npm-install-checks": {
@@ -3655,9 +3664,9 @@
}
},
"node_modules/object-inspect": {
- "version": "1.11.0",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz",
- "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==",
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.1.tgz",
+ "integrity": "sha512-If7BjFlpkzzBeV1cqgT3OSWT3azyoxDGajR+iGnFBfVV2EWyDyWaZZW2ERDjUaY2QM8i5jI3Sj7mhsM4DDAqWA==",
"dev": true,
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -4801,9 +4810,9 @@
}
},
"node_modules/typescript": {
- "version": "4.5.2",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz",
- "integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==",
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz",
+ "integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
@@ -4932,9 +4941,9 @@
}
},
"node_modules/usb": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/usb/-/usb-1.9.1.tgz",
- "integrity": "sha512-T6DZbJAFNcxhY1FzaYdXhV2oqoRlvLhtSSmnbFAqyCxahUkc+g0BPZVXv7hIeQQxDCAQnr4Ia8bfOk1JlzNzzw==",
+ "version": "1.9.2",
+ "resolved": "https://registry.npmjs.org/usb/-/usb-1.9.2.tgz",
+ "integrity": "sha512-dryNz030LWBPAf6gj8vyq0Iev3vPbCLHCT8dBw3gQRXRzVNsIdeuU+VjPp3ksmSPkeMAl1k+kQ14Ij0QHyeiAg==",
"hasInstallScript": true,
"optional": true,
"dependencies": {
@@ -5195,14 +5204,14 @@
}
},
"@eslint/eslintrc": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.4.tgz",
- "integrity": "sha512-h8Vx6MdxwWI2WM8/zREHMoqdgLNXEL4QX3MWSVMdyNJGvXVOs+6lp+m2hc3FnuMHDc4poxFNI20vCk0OmI4G0Q==",
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.0.5.tgz",
+ "integrity": "sha512-BLxsnmK3KyPunz5wmCCpqy0YelEoxxGmH73Is+Z74oOTMtExcjkr3dDR6quwrjh1YspA8DH9gnX1o069KiS9AQ==",
"dev": true,
"requires": {
"ajv": "^6.12.4",
"debug": "^4.3.2",
- "espree": "^9.0.0",
+ "espree": "^9.2.0",
"globals": "^13.9.0",
"ignore": "^4.0.6",
"import-fresh": "^3.2.1",
@@ -5243,12 +5252,12 @@
"integrity": "sha512-axFX7lN2Yd7bz/6SlD7dzq5sY/N9+XYuLHPukuiyHQRDtNMRL1uDqJhOx6RVaN2tYDHB75h7YxRQWP7U44Mgzg=="
},
"@humanwhocodes/config-array": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.6.0.tgz",
- "integrity": "sha512-JQlEKbcgEUjBFhLIF4iqM7u/9lwgHRBcpHrmUNCALK0Q3amXN6lxdoXLnF0sm11E9VqTmBALR87IlUg1bZ8A9A==",
+ "version": "0.9.2",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.2.tgz",
+ "integrity": "sha512-UXOuFCGcwciWckOpmfKDq/GyhlTf9pN/BzG//x8p8zTOFEcGuA68ANXheFS0AGvy3qgZqLBUkMs7hqzqCKOVwA==",
"dev": true,
"requires": {
- "@humanwhocodes/object-schema": "^1.2.0",
+ "@humanwhocodes/object-schema": "^1.2.1",
"debug": "^4.1.1",
"minimatch": "^3.0.4"
}
@@ -5309,9 +5318,9 @@
}
},
"@npmcli/fs": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.0.0.tgz",
- "integrity": "sha512-8ltnOpRR/oJbOp8vaGUnipOi3bqkcW+sLHFlyXIr08OGHmVJLB1Hn7QtGXbYcpVtH1gAYZTlmDXtE4YV0+AMMQ==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.0.tgz",
+ "integrity": "sha512-VhP1qZLXcrXRIaPoqb4YA55JQxLNF3jNR4T55IdOJa3+IFJKNYHtPvtXx8slmeMavj37vCzCfrqQM1vWLsYKLA==",
"dev": true,
"requires": {
"@gar/promisify": "^1.0.1",
@@ -5449,19 +5458,19 @@
"dev": true
},
"@types/node": {
- "version": "16.11.11",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.11.tgz",
- "integrity": "sha512-KB0sixD67CeecHC33MYn+eYARkqTheIRNuu97y2XMjR7Wu3XibO1vaY6VBV6O/a89SPI81cEUIYT87UqUWlZNw==",
+ "version": "17.0.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.0.tgz",
+ "integrity": "sha512-eMhwJXc931Ihh4tkU+Y7GiLzT/y/DBNpNtr4yU9O2w3SYBsr9NaOPhQlLKRmoWtI54uNwuo0IOUFQjVOTZYRvw==",
"dev": true
},
"@typescript-eslint/eslint-plugin": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.5.0.tgz",
- "integrity": "sha512-4bV6fulqbuaO9UMXU0Ia0o6z6if+kmMRW8rMRyfqXj/eGrZZRGedS4n0adeGNnjr8LKAM495hrQ7Tea52UWmQA==",
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.7.0.tgz",
+ "integrity": "sha512-8RTGBpNn5a9M628wBPrCbJ+v3YTEOE2qeZb7TDkGKTDXSj36KGRg92SpFFaR/0S3rSXQxM0Og/kV9EyadsYSBg==",
"dev": true,
"requires": {
- "@typescript-eslint/experimental-utils": "5.5.0",
- "@typescript-eslint/scope-manager": "5.5.0",
+ "@typescript-eslint/experimental-utils": "5.7.0",
+ "@typescript-eslint/scope-manager": "5.7.0",
"debug": "^4.3.2",
"functional-red-black-tree": "^1.0.1",
"ignore": "^5.1.8",
@@ -5471,55 +5480,55 @@
}
},
"@typescript-eslint/experimental-utils": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.5.0.tgz",
- "integrity": "sha512-kjWeeVU+4lQ1SLYErRKV5yDXbWDPkpbzTUUlfAUifPYvpX0qZlrcCZ96/6oWxt3QxtK5WVhXz+KsnwW9cIW+3A==",
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-5.7.0.tgz",
+ "integrity": "sha512-u57eZ5FbEpzN5kSjmVrSesovWslH2ZyNPnaXQMXWgH57d5+EVHEt76W75vVuI9qKZ5BMDKNfRN+pxcPEjQjb2A==",
"dev": true,
"requires": {
"@types/json-schema": "^7.0.9",
- "@typescript-eslint/scope-manager": "5.5.0",
- "@typescript-eslint/types": "5.5.0",
- "@typescript-eslint/typescript-estree": "5.5.0",
+ "@typescript-eslint/scope-manager": "5.7.0",
+ "@typescript-eslint/types": "5.7.0",
+ "@typescript-eslint/typescript-estree": "5.7.0",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0"
}
},
"@typescript-eslint/parser": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.5.0.tgz",
- "integrity": "sha512-JsXBU+kgQOAgzUn2jPrLA+Rd0Y1dswOlX3hp8MuRO1hQDs6xgHtbCXEiAu7bz5hyVURxbXcA2draasMbNqrhmg==",
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.7.0.tgz",
+ "integrity": "sha512-m/gWCCcS4jXw6vkrPQ1BjZ1vomP01PArgzvauBqzsoZ3urLbsRChexB8/YV8z9HwE3qlJM35FxfKZ1nfP/4x8g==",
"dev": true,
"requires": {
- "@typescript-eslint/scope-manager": "5.5.0",
- "@typescript-eslint/types": "5.5.0",
- "@typescript-eslint/typescript-estree": "5.5.0",
+ "@typescript-eslint/scope-manager": "5.7.0",
+ "@typescript-eslint/types": "5.7.0",
+ "@typescript-eslint/typescript-estree": "5.7.0",
"debug": "^4.3.2"
}
},
"@typescript-eslint/scope-manager": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.5.0.tgz",
- "integrity": "sha512-0/r656RmRLo7CbN4Mdd+xZyPJ/fPCKhYdU6mnZx+8msAD8nJSP8EyCFkzbd6vNVZzZvWlMYrSNekqGrCBqFQhg==",
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.7.0.tgz",
+ "integrity": "sha512-7mxR520DGq5F7sSSgM0HSSMJ+TFUymOeFRMfUfGFAVBv8BR+Jv1vHgAouYUvWRZeszVBJlLcc9fDdktxb5kmxA==",
"dev": true,
"requires": {
- "@typescript-eslint/types": "5.5.0",
- "@typescript-eslint/visitor-keys": "5.5.0"
+ "@typescript-eslint/types": "5.7.0",
+ "@typescript-eslint/visitor-keys": "5.7.0"
}
},
"@typescript-eslint/types": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.5.0.tgz",
- "integrity": "sha512-OaYTqkW3GnuHxqsxxJ6KypIKd5Uw7bFiQJZRyNi1jbMJnK3Hc/DR4KwB6KJj6PBRkJJoaNwzMNv9vtTk87JhOg==",
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.7.0.tgz",
+ "integrity": "sha512-5AeYIF5p2kAneIpnLFve8g50VyAjq7udM7ApZZ9JYjdPjkz0LvODfuSHIDUVnIuUoxafoWzpFyU7Sqbxgi79mA==",
"dev": true
},
"@typescript-eslint/typescript-estree": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.5.0.tgz",
- "integrity": "sha512-pVn8btYUiYrjonhMAO0yG8lm7RApzy2L4RC7Td/mC/qFkyf6vRbGyZozoA94+w6D2Y2GRqpMoCWcwx/EUOzyoQ==",
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.7.0.tgz",
+ "integrity": "sha512-aO1Ql+izMrTnPj5aFFlEJkpD4jRqC4Gwhygu2oHK2wfVQpmOPbyDSveJ+r/NQo+PWV43M6uEAeLVbTi09dFLhg==",
"dev": true,
"requires": {
- "@typescript-eslint/types": "5.5.0",
- "@typescript-eslint/visitor-keys": "5.5.0",
+ "@typescript-eslint/types": "5.7.0",
+ "@typescript-eslint/visitor-keys": "5.7.0",
"debug": "^4.3.2",
"globby": "^11.0.4",
"is-glob": "^4.0.3",
@@ -5528,12 +5537,12 @@
}
},
"@typescript-eslint/visitor-keys": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.5.0.tgz",
- "integrity": "sha512-4GzJ1kRtsWzHhdM40tv0ZKHNSbkDhF0Woi/TDwVJX6UICwJItvP7ZTXbjTkCdrors7ww0sYe0t+cIKDAJwZ7Kw==",
+ "version": "5.7.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.7.0.tgz",
+ "integrity": "sha512-hdohahZ4lTFcglZSJ3DGdzxQHBSxsLVqHzkiOmKi7xVAWC4y2c1bIMKmPJSrA4aOEoRUPOKQ87Y/taC7yVHpFg==",
"dev": true,
"requires": {
- "@typescript-eslint/types": "5.5.0",
+ "@typescript-eslint/types": "5.7.0",
"eslint-visitor-keys": "^3.0.0"
}
},
@@ -5926,13 +5935,12 @@
"dev": true
},
"cli-table": {
- "version": "0.3.9",
- "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.9.tgz",
- "integrity": "sha512-7eA6hFtAZwVx3dWAGoaBqTrzWko5jRUFKpHT64ZHkJpaA3y5wf5NlLjguqTRmqycatJZiwftODYYyGNLbQ7MuA==",
+ "version": "0.3.11",
+ "resolved": "https://registry.npmjs.org/cli-table/-/cli-table-0.3.11.tgz",
+ "integrity": "sha512-IqLQi4lO0nIB4tcdTpN4LCB9FI3uqrJZK7RC515EnhZ6qBaglkIgICb1wjeAqpdoOabm1+SuQtkXIPdYC93jhQ==",
"dev": true,
"requires": {
- "colors": "1.0.3",
- "strip-ansi": "^6.0.1"
+ "colors": "1.0.3"
}
},
"clone-response": {
@@ -6273,13 +6281,13 @@
"dev": true
},
"eslint": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.3.0.tgz",
- "integrity": "sha512-aIay56Ph6RxOTC7xyr59Kt3ewX185SaGnAr8eWukoPLeriCrvGjvAubxuvaXOfsxhtwV5g0uBOsyhAom4qJdww==",
+ "version": "8.4.1",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.4.1.tgz",
+ "integrity": "sha512-TxU/p7LB1KxQ6+7aztTnO7K0i+h0tDi81YRY9VzB6Id71kNz+fFYnf5HD5UOQmxkzcoa0TlVZf9dpMtUv0GpWg==",
"dev": true,
"requires": {
- "@eslint/eslintrc": "^1.0.4",
- "@humanwhocodes/config-array": "^0.6.0",
+ "@eslint/eslintrc": "^1.0.5",
+ "@humanwhocodes/config-array": "^0.9.2",
"ajv": "^6.10.0",
"chalk": "^4.0.0",
"cross-spawn": "^7.0.2",
@@ -6290,7 +6298,7 @@
"eslint-scope": "^7.1.0",
"eslint-utils": "^3.0.0",
"eslint-visitor-keys": "^3.1.0",
- "espree": "^9.1.0",
+ "espree": "^9.2.0",
"esquery": "^1.4.0",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
@@ -6376,9 +6384,9 @@
"dev": true
},
"espree": {
- "version": "9.1.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-9.1.0.tgz",
- "integrity": "sha512-ZgYLvCS1wxOczBYGcQT9DDWgicXwJ4dbocr9uYN+/eresBAUuBu+O4WzB21ufQ/JqQT8gyp7hJ3z8SHii32mTQ==",
+ "version": "9.2.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-9.2.0.tgz",
+ "integrity": "sha512-oP3utRkynpZWF/F2x/HZJ+AGtnIclaR7z1pYPxy7NYM2fSO6LgK/Rkny8anRSPK/VwEA1eqm2squui0T7ZMOBg==",
"dev": true,
"requires": {
"acorn": "^8.6.0",
@@ -6546,9 +6554,9 @@
"dev": true
},
"follow-redirects": {
- "version": "1.14.5",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz",
- "integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA=="
+ "version": "1.14.6",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.6.tgz",
+ "integrity": "sha512-fhUl5EwSJbbl8AR+uYL2KQDxLkdSjZGR36xy46AO7cOMTrCMON6Sa28FmAnC2tRTDbd/Uuzz3aJBv7EBN7JH8A=="
},
"foreach": {
"version": "2.0.5",
@@ -7090,9 +7098,9 @@
"dev": true
},
"is-negative-zero": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
- "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==",
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz",
+ "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==",
"dev": true
},
"is-npm": {
@@ -7194,19 +7202,23 @@
"dev": true
},
"is-weakref": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.1.tgz",
- "integrity": "sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
"dev": true,
"requires": {
- "call-bind": "^1.0.0"
+ "call-bind": "^1.0.2"
}
},
"is-weakset": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.1.tgz",
- "integrity": "sha512-pi4vhbhVHGLxohUw7PhGsueT4vRGFoXhP7+RGN0jKIv9+8PWYCQTqtADngrxOm2g46hoH0+g8uZZBzMrvVGDmw==",
- "dev": true
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.2.tgz",
+ "integrity": "sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==",
+ "dev": true,
+ "requires": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.1.1"
+ }
},
"is-yarn-global": {
"version": "0.3.0",
@@ -7516,9 +7528,9 @@
"dev": true
},
"minipass": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz",
- "integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==",
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.6.tgz",
+ "integrity": "sha512-rty5kpw9/z8SX9dmxblFA6edItUmwJgMeYDZRrwlIVN27i8gysGbznJwUggw2V/FVqFSDdWy040ZPS811DYAqQ==",
"devOptional": true,
"requires": {
"yallist": "^4.0.0"
@@ -7777,15 +7789,15 @@
}
},
"npm-check-updates": {
- "version": "12.0.2",
- "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-12.0.2.tgz",
- "integrity": "sha512-VzMNuUXqRta1qpBkFiE0hKfpOGP2FbYwpBBTcJXoJWppOPBSi/paWFVhPVWf7PgRoDWegK+PDAWKhIvhyrBrIg==",
+ "version": "12.0.5",
+ "resolved": "https://registry.npmjs.org/npm-check-updates/-/npm-check-updates-12.0.5.tgz",
+ "integrity": "sha512-ns1liBBogwjmOVZY/PYgeIoarItwdOSBxccJDZKKkxsMkXges/Bp5CAnQIvYwlsz6fByQJFvqXSOqwIUBY6gpQ==",
"dev": true,
"requires": {
"chalk": "^4.1.2",
"cint": "^8.2.1",
- "cli-table": "^0.3.6",
- "commander": "^6.2.1",
+ "cli-table": "^0.3.11",
+ "commander": "^8.3.0",
"fast-memoize": "^2.5.2",
"find-up": "5.0.0",
"fp-and-or": "^0.1.3",
@@ -7807,15 +7819,15 @@
"rimraf": "^3.0.2",
"semver": "^7.3.5",
"semver-utils": "^1.1.4",
- "source-map-support": "^0.5.20",
+ "source-map-support": "^0.5.21",
"spawn-please": "^1.0.0",
"update-notifier": "^5.1.0"
},
"dependencies": {
"commander": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
- "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
+ "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
"dev": true
}
}
@@ -7897,9 +7909,9 @@
}
},
"object-inspect": {
- "version": "1.11.0",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz",
- "integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg==",
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.1.tgz",
+ "integrity": "sha512-If7BjFlpkzzBeV1cqgT3OSWT3azyoxDGajR+iGnFBfVV2EWyDyWaZZW2ERDjUaY2QM8i5jI3Sj7mhsM4DDAqWA==",
"dev": true
},
"object-is": {
@@ -8719,9 +8731,9 @@
}
},
"typescript": {
- "version": "4.5.2",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.2.tgz",
- "integrity": "sha512-5BlMof9H1yGt0P8/WF+wPNw6GfctgGjXp5hkblpyT+8rkASSmkUKMXrxR0Xg8ThVCi/JnHQiKXeBaEwCeQwMFw==",
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.4.tgz",
+ "integrity": "sha512-VgYs2A2QIRuGphtzFV7aQJduJ2gyfTljngLzjpfW9FoYZF6xuw1W0vW9ghCKLfcWrCFxK81CSGRAvS1pn4fIUg==",
"dev": true
},
"typescript-axios-wb": {
@@ -8822,9 +8834,9 @@
}
},
"usb": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/usb/-/usb-1.9.1.tgz",
- "integrity": "sha512-T6DZbJAFNcxhY1FzaYdXhV2oqoRlvLhtSSmnbFAqyCxahUkc+g0BPZVXv7hIeQQxDCAQnr4Ia8bfOk1JlzNzzw==",
+ "version": "1.9.2",
+ "resolved": "https://registry.npmjs.org/usb/-/usb-1.9.2.tgz",
+ "integrity": "sha512-dryNz030LWBPAf6gj8vyq0Iev3vPbCLHCT8dBw3gQRXRzVNsIdeuU+VjPp3ksmSPkeMAl1k+kQ14Ij0QHyeiAg==",
"optional": true,
"requires": {
"node-addon-api": "^4.2.0",
diff --git a/package.json b/package.json
index cca0fb4e..61f5cdbe 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"displayName": "Homebridge SwitchBot",
"name": "@switchbot/homebridge-switchbot",
- "version": "1.3.0",
+ "version": "1.4.0",
"description": "The [Homebridge](https://homebridge.io) SwitchBot plugin allows you to access your [SwitchBot](https://www.switch-bot.com) device(s) from HomeKit.",
"author": "SwitchBot (https://github.com/SwitchBot)",
"license": "ISC",
@@ -14,7 +14,7 @@
},
"engines": {
"homebridge": "^1.3.8",
- "node": "^14.18.1 || ^16.13.0"
+ "node": "^14.18.2 || ^16.13.1"
},
"main": "dist/index.js",
"scripts": {
@@ -53,16 +53,16 @@
"rxjs": "^7.4.0"
},
"devDependencies": {
- "@types/node": "^16.11.11",
- "@typescript-eslint/eslint-plugin": "^5.5.0",
- "@typescript-eslint/parser": "^5.5.0",
- "eslint": "^8.3.0",
+ "@types/node": "^17.0.0",
+ "@typescript-eslint/eslint-plugin": "^5.7.0",
+ "@typescript-eslint/parser": "^5.7.0",
+ "eslint": "^8.4.1",
"homebridge": "^1.3.8",
"nodemon": "^2.0.15",
- "npm-check-updates": "^12.0.2",
+ "npm-check-updates": "^12.0.5",
"rimraf": "^3.0.2",
"ts-node": "^10.4.0",
- "typescript": "^4.5.2",
+ "typescript": "^4.5.4",
"typescript-axios-wb": "^1.0.3"
}
}
\ No newline at end of file
diff --git a/src/devices/bots.ts b/src/devices/bots.ts
index 1478c78d..2bdf517d 100644
--- a/src/devices/bots.ts
+++ b/src/devices/bots.ts
@@ -3,7 +3,7 @@ import { AxiosResponse } from 'axios';
import Switchbot from 'node-switchbot';
import { interval, Subject } from 'rxjs';
import { SwitchBotPlatform } from '../platform';
-import { debounceTime, skipWhile, tap } from 'rxjs/operators';
+import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
import { DeviceURL, device, devicesConfig, serviceData, ad, switchbot, deviceStatusResponse, payload } from '../settings';
@@ -20,6 +20,7 @@ export class Bot {
// Characteristic Values
On!: CharacteristicValue;
+ OnCached!: CharacteristicValue;
BatteryLevel!: CharacteristicValue;
StatusLowBattery!: CharacteristicValue;
@@ -48,11 +49,15 @@ export class Bot {
public device: device & devicesConfig,
) {
// Bot Config
- this.platform.device(`Bot: ${this.accessory.displayName} Config: (ble: ${device.ble}, mode: ${device.bot?.mode},`
+ this.platform.device(`Bot: ${this.accessory.displayName} Config: (ble: ${device.ble}, offline: ${device.offline}, mode: ${device.bot?.mode},`
+ ` deviceType: ${device.bot?.deviceType})`);
// default placeholders
- this.On = false;
+ if (this.On === undefined) {
+ this.On = false;
+ } else {
+ this.On = this.accessory.context.On;
+ }
this.BatteryLevel = 100;
this.StatusLowBattery = 1;
@@ -61,7 +66,7 @@ export class Bot {
this.botUpdateInProgress = false;
// Retrieve initial values and updateHomekit
- this.parseStatus();
+ this.refreshStatus();
// set accessory information
accessory
@@ -122,7 +127,6 @@ export class Bot {
}
// Retrieve initial values and updateHomekit
- this.refreshStatus();
this.updateHomeKitCharacteristics();
// Start an update interval
@@ -197,6 +201,12 @@ export class Bot {
this.platform.debug(`Bot: ${this.accessory.displayName} OpenAPI parseStatus`);
if (this.device.bot?.mode === 'press') {
this.On = false;
+ } else {
+ if (this.deviceStatus.body.power === 'on') {
+ this.On = true;
+ } else {
+ this.On = false;
+ }
}
this.platform.debug(`Bot ${this.accessory.displayName} On: ${this.On}`);
}
@@ -284,7 +294,9 @@ export class Bot {
if (this.platform.config.credentials?.openToken) {
this.platform.debug(`Bot: ${this.accessory.displayName} OpenAPI refreshStatus`);
try {
- this.deviceStatus = {
+ this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
+ this.platform.device(`Bot: ${this.accessory.displayName} refreshStatus: ${JSON.stringify(this.deviceStatus)}`);
+ /*this.deviceStatus = {
statusCode: 100,
body: {
deviceId: this.device.deviceId!,
@@ -293,7 +305,7 @@ export class Bot {
power: 'on',
},
message: 'success',
- };
+ };*/
this.parseStatus();
this.updateHomeKitCharacteristics();
} catch (e: any) {
@@ -324,61 +336,71 @@ export class Bot {
} else {
await this.openAPIpushChanges();
}
- this.refreshStatus();
+ interval(5000)
+ .pipe(skipWhile(() => this.botUpdateInProgress))
+ .pipe(take(1))
+ .subscribe(() => {
+ this.refreshStatus();
+ });
}
private async BLEpushChanges() {
- this.platform.debug(`Bot: ${this.accessory.displayName} BLE pushChanges`);
- const switchbot = this.connectBLE();
- if (this.device.bot?.mode === 'press') {
- this.platform.device(`Bot: ${this.accessory.displayName} Press Mode: ${this.device.bot?.mode}`);
- switchbot.discover({ model: 'H', quick: true, id: this.device.bleMac }).then((device_list) => {
- this.platform.log.info(`Bot: ${this.accessory.displayName}, On: ${this.On}`);
- return device_list[0].press({ id: this.device.bleMac });
- }).then(() => {
- this.platform.device(`Bot: ${this.accessory.displayName} Done.`);
- }).catch(async (e: any) => {
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection`);
- if (this.deviceDebug) {
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
- + ` Error Message: ${JSON.stringify(e.message)}`);
- }
- if (this.debugDebug) {
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
- + ` Error: ${JSON.stringify(e)}`);
- }
- if (this.platform.config.credentials?.openToken) {
- this.platform.log.warn(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
- await this.openAPIpushChanges();
- }
- this.apiError(e);
- });
- } else if (this.device.bot?.mode === 'switch') {
- this.platform.device(`Bot: ${this.accessory.displayName} Press Mode: ${this.device.bot?.mode}`);
- switchbot.discover({ model: 'H', quick: true, id: this.device.bleMac }).then((device_list: any) => {
- this.platform.log.info(`Bot: ${this.accessory.displayName} On: ${this.On}`);
- return this.turnOnOff(device_list);
- }).then(() => {
- this.platform.device(`Bot: ${this.accessory.displayName} Done.`);
- }).catch(async (e: any) => {
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection`);
- if (this.deviceDebug) {
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
- + ` Error Message: ${JSON.stringify(e.message)}`);
- }
- if (this.debugDebug) {
- this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
- + ` Error: ${JSON.stringify(e)}`);
- }
- if (this.platform.config.credentials?.openToken) {
- this.platform.log.warn(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
- await this.openAPIpushChanges();
- }
- this.apiError(e);
- });
- } else {
- this.platform.log.error(`Bot: ${this.accessory.displayName} Mode Not Set, mode: ${this.device.bot?.mode}`);
+ if (this.On !== this.OnCached) {
+ this.platform.debug(`Bot: ${this.accessory.displayName} BLE pushChanges`);
+ const switchbot = this.connectBLE();
+ if (this.device.bot?.mode === 'press') {
+ this.platform.device(`Bot: ${this.accessory.displayName} Press Mode: ${this.device.bot?.mode}`);
+ switchbot.discover({ model: 'H', quick: true, id: this.device.bleMac })
+ .then((device_list: { press: (arg0: { id: string | undefined; }) => any; }[]) => {
+ this.platform.log.info(`Bot: ${this.accessory.displayName}, On: ${this.On}`);
+ return device_list[0].press({ id: this.device.bleMac });
+ }).then(() => {
+ this.platform.device(`Bot: ${this.accessory.displayName} Done.`);
+ }).catch(async (e: any) => {
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection`);
+ if (this.deviceDebug) {
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
+ + ` Error Message: ${JSON.stringify(e.message)}`);
+ }
+ if (this.debugDebug) {
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
+ + ` Error: ${JSON.stringify(e)}`);
+ }
+ if (this.platform.config.credentials?.openToken) {
+ this.platform.log.warn(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
+ await this.openAPIpushChanges();
+ }
+ this.apiError(e);
+ });
+ } else if (this.device.bot?.mode === 'switch') {
+ this.platform.device(`Bot: ${this.accessory.displayName} Press Mode: ${this.device.bot?.mode}`);
+ switchbot.discover({ model: 'H', quick: true, id: this.device.bleMac }).then((device_list: any) => {
+ this.platform.log.info(`Bot: ${this.accessory.displayName} On: ${this.On}`);
+ return this.turnOnOff(device_list);
+ }).then(() => {
+ this.platform.device(`Bot: ${this.accessory.displayName} Done.`);
+ }).catch(async (e: any) => {
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection`);
+ if (this.deviceDebug) {
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
+ + ` Error Message: ${JSON.stringify(e.message)}`);
+ }
+ if (this.debugDebug) {
+ this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with BLE Connection,`
+ + ` Error: ${JSON.stringify(e)}`);
+ }
+ if (this.platform.config.credentials?.openToken) {
+ this.platform.log.warn(`Bot: ${this.accessory.displayName} Using OpenAPI Connection`);
+ await this.openAPIpushChanges();
+ }
+ this.apiError(e);
+ });
+ } else {
+ this.platform.log.error(`Bot: ${this.accessory.displayName} Mode Not Set, mode: ${this.device.bot?.mode}`);
+ }
}
+ this.OnCached = this.On;
+ this.accessory.context.On = this.OnCached;
}
private turnOnOff(device_list: any) {
@@ -392,35 +414,39 @@ export class Bot {
private async openAPIpushChanges() {
if (this.platform.config.credentials?.openToken) {
try {
- this.platform.debug(`Bot: ${this.accessory.displayName} OpenAPI pushChanges`);
- const payload = {
- commandType: 'command',
- parameter: 'default',
- } as payload;
-
- if (this.device.bot?.mode === 'switch' && this.On) {
- payload.command = 'turnOn';
- this.On = true;
- this.platform.debug(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
- } else if (this.device.bot?.mode === 'switch' && !this.On) {
- payload.command = 'turnOff';
- this.On = false;
- this.platform.debug(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
- } else if (this.device.bot?.mode === 'press') {
- payload.command = 'press';
- this.platform.debug(`Bot: ${this.accessory.displayName} Press Mode`);
- this.On = false;
- } else {
- throw new Error(`Bot: ${this.accessory.displayName} Device Paramters not set for this Bot.`);
- }
+ if (this.On !== this.OnCached) {
+ this.platform.debug(`Bot: ${this.accessory.displayName} OpenAPI pushChanges`);
+ const payload = {
+ commandType: 'command',
+ parameter: 'default',
+ } as payload;
+
+ if (this.device.bot?.mode === 'switch' && this.On) {
+ payload.command = 'turnOn';
+ this.On = true;
+ this.platform.debug(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
+ } else if (this.device.bot?.mode === 'switch' && !this.On) {
+ payload.command = 'turnOff';
+ this.On = false;
+ this.platform.debug(`Bot: ${this.accessory.displayName} Switch Mode, Turning ${this.On}`);
+ } else if (this.device.bot?.mode === 'press') {
+ payload.command = 'press';
+ this.platform.debug(`Bot: ${this.accessory.displayName} Press Mode`);
+ this.On = false;
+ } else {
+ throw new Error(`Bot: ${this.accessory.displayName} Device Paramters not set for this Bot.`);
+ }
- this.platform.log.info(`Bot: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
- + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
+ this.platform.log.info(`Bot: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
+ + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
- // Make the API request
- const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
- this.platform.debug(`Bot ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
- this.statusCode(push);
+ // Make the API request
+ const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
+ this.platform.debug(`Bot ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
+ this.statusCode(push);
+ this.OnCached = this.On;
+ this.accessory.context.On = this.OnCached;
+ }
} catch (e: any) {
this.platform.log.error(`Bot: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
if (this.deviceDebug) {
@@ -491,9 +517,11 @@ export class Bot {
break;
case 161:
this.platform.log.error(`Bot: ${this.accessory.displayName} Device is offline.`);
+ this.offlineOff();
break;
case 171:
- this.platform.log.error(`Bot: ${this.accessory.displayName} Hub Device is offline.`);
+ this.platform.log.error(`Bot: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
+ this.offlineOff();
break;
case 190:
this.platform.log.error(`Bot: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -507,6 +535,17 @@ export class Bot {
}
}
+ private offlineOff() {
+ if (this.device.offline) {
+ this.On = false;
+ if (this.device.bot?.deviceType === 'switch') {
+ this.switchService?.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
+ } else {
+ this.outletService?.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
+ }
+ }
+ }
+
/**
* Handle requests to set the "On" characteristic
*/
diff --git a/src/devices/colorbulb.ts b/src/devices/colorbulb.ts
index 4a466fc2..149eeab2 100644
--- a/src/devices/colorbulb.ts
+++ b/src/devices/colorbulb.ts
@@ -56,13 +56,17 @@ export class ColorBulb {
this.platform.device(`Color Bulb: ${this.accessory.displayName} Config: (ble: ${device.ble}, set_minStep: ${device.colorbulb?.set_minStep}`);
// default placeholders
- this.minKelvin = 2000;
- this.maxKelvin = 9000;
+ if (this.On === undefined) {
+ this.On = false;
+ } else {
+ this.On = this.accessory.context.On;
+ }
this.Hue = 0;
- this.On = false;
this.Brightness = 0;
this.Saturation = 0;
this.ColorTemperature = 140;
+ this.minKelvin = 2000;
+ this.maxKelvin = 9000;
// this is subject we use to track when we need to POST changes to the SwitchBot API
this.doColorBulbUpdate = new Subject();
@@ -299,6 +303,7 @@ export class ColorBulb {
this.platform.debug(`Color Bulb: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
this.statusCode(push);
this.OnCached = this.On;
+ this.accessory.context.On = this.OnCached;
}
// Push Brightness Update
if (this.On) {
@@ -498,9 +503,11 @@ export class ColorBulb {
break;
case 161:
this.platform.log.error(`Color Bulb: ${this.accessory.displayName} Device is offline.`);
+ this.offlineOff();
break;
case 171:
- this.platform.log.error(`Color Bulb: ${this.accessory.displayName} Hub Device is offline.`);
+ this.platform.log.error(`Color Bulb: ${this.accessory.displayName} is offline. Hub: ${this.device.hubDeviceId}`);
+ this.offlineOff();
break;
case 190:
this.platform.log.error(`Color Bulb: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -514,6 +521,13 @@ export class ColorBulb {
}
}
+ private offlineOff() {
+ if (this.device.offline) {
+ this.On = false;
+ this.service.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
+ }
+ }
+
/**
* Handle requests to set the value of the "On" characteristic
*/
diff --git a/src/devices/contact.ts b/src/devices/contact.ts
index 0b8a3746..3c92bffb 100644
--- a/src/devices/contact.ts
+++ b/src/devices/contact.ts
@@ -50,7 +50,7 @@ export class Contact {
public device: device & devicesConfig,
) {
// Contact Config
- this.platform.device(`Contact Sensor: ${this.accessory.displayName} Config: (ble: ${device.ble},`
+ this.platform.device(`Contact Sensor: ${this.accessory.displayName} Config: (ble: ${device.ble}, offline: ${device.offline},`
+ ` hide_lightsensor: ${device.contact?.hide_lightsensor}, hide_motionsensor: ${device.contact?.hide_motionsensor})`);
diff --git a/src/devices/curtains.ts b/src/devices/curtains.ts
index d7f92c3f..610af093 100644
--- a/src/devices/curtains.ts
+++ b/src/devices/curtains.ts
@@ -3,7 +3,7 @@ import { AxiosResponse } from 'axios';
import Switchbot from 'node-switchbot';
import { interval, Subject } from 'rxjs';
import { SwitchBotPlatform } from '../platform';
-import { debounceTime, skipWhile, tap } from 'rxjs/operators';
+import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
import { DeviceURL, device, devicesConfig, serviceData, switchbot, deviceStatusResponse, payload } from '../settings';
@@ -487,7 +487,12 @@ export class Curtain {
} else {
await this.OpenAPIpushChanges();
}
- this.refreshStatus();
+ interval(5000)
+ .pipe(skipWhile(() => this.curtainUpdateInProgress))
+ .pipe(take(1))
+ .subscribe(() => {
+ this.refreshStatus();
+ });
}
private async BLEpushChanges() {
@@ -632,7 +637,7 @@ export class Curtain {
this.platform.log.error(`Curtain: ${this.accessory.displayName} Device is offline.`);
break;
case 171:
- this.platform.log.error(`Curtain: ${this.accessory.displayName} Hub Device is offline.`);
+ this.platform.log.error(`Curtain: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
break;
case 190:
this.platform.log.error(`Curtain: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
diff --git a/src/devices/humidifiers.ts b/src/devices/humidifiers.ts
index 62c53359..41929772 100644
--- a/src/devices/humidifiers.ts
+++ b/src/devices/humidifiers.ts
@@ -2,7 +2,7 @@ import { AxiosResponse } from 'axios';
import Switchbot from 'node-switchbot';
import { interval, Subject } from 'rxjs';
import { SwitchBotPlatform } from '../platform';
-import { debounceTime, skipWhile, tap } from 'rxjs/operators';
+import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
import { DeviceURL, device, devicesConfig, serviceData, ad, deviceStatusResponse, payload } from '../settings';
@@ -50,7 +50,7 @@ export class Humidifier {
public device: device & devicesConfig,
) {
// Humidifiers Config
- this.platform.device(`Humidifier: ${this.accessory.displayName} Config: (ble: ${device.ble}, hide_temperature: `
+ this.platform.device(`Humidifier: ${this.accessory.displayName} Config: (ble: ${device.ble}, offline: ${device.offline}, hide_temperature: `
+ `${device.humidifier?.hide_temperature}, set_minStep: ${device.humidifier?.set_minStep})`);
// default placeholders
@@ -394,7 +394,12 @@ export class Humidifier {
//} else {
await this.OpenAPIpushChanges();
//}
- this.refreshStatus();
+ interval(5000)
+ .pipe(skipWhile(() => this.humidifierUpdateInProgress))
+ .pipe(take(1))
+ .subscribe(() => {
+ this.refreshStatus();
+ });
}
private async BLEpushChanges() {
@@ -628,9 +633,11 @@ export class Humidifier {
break;
case 161:
this.platform.log.error(`Humidifier: ${this.accessory.displayName} Device is offline.`);
+ this.offlineOff();
break;
case 171:
- this.platform.log.error(`Humidifier: ${this.accessory.displayName} Hub Device is offline.`);
+ this.platform.log.error(`Humidifier: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
+ this.offlineOff();
break;
case 190:
this.platform.log.error(`Humidifier: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -644,6 +651,13 @@ export class Humidifier {
}
}
+ private offlineOff() {
+ if (this.device.offline) {
+ this.Active = this.platform.Characteristic.Active.INACTIVE;
+ this.service.getCharacteristic(this.platform.Characteristic.Active).updateValue(this.Active);
+ }
+ }
+
/**
* Handle requests to set the "Target Humidifier Dehumidifier State" characteristic
*/
diff --git a/src/devices/indoorcam.ts b/src/devices/indoorcam.ts
index 0470dcc9..110e2ae3 100644
--- a/src/devices/indoorcam.ts
+++ b/src/devices/indoorcam.ts
@@ -1,7 +1,7 @@
import { AxiosResponse } from 'axios';
import { interval, Subject } from 'rxjs';
import { SwitchBotPlatform } from '../platform';
-import { debounceTime, skipWhile, tap } from 'rxjs/operators';
+import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
import { DeviceURL, device, devicesConfig, deviceStatusResponse, payload } from '../settings';
@@ -10,8 +10,13 @@ export class IndoorCam {
private service: Service;
// Characteristic Values
- On!: CharacteristicValue;
- OutletInUse!: CharacteristicValue;
+ Active!: CharacteristicValue;
+ SetupEndpoints!: CharacteristicValue;
+ StreamingStatus!: CharacteristicValue;
+ SupportedRTPConfiguration!: CharacteristicValue;
+ SelectedRTPStreamConfiguration!: CharacteristicValue;
+ SupportedVideoStreamConfiguration!: CharacteristicValue;
+ SupportedAudioStreamConfiguration!: CharacteristicValue;
// OpenAPI Others
deviceStatus!: deviceStatusResponse;
@@ -29,9 +34,12 @@ export class IndoorCam {
private accessory: PlatformAccessory,
public device: device & devicesConfig,
) {
+ // Indoor Cam Config
+ this.platform.device(`Indoor Cam: ${this.accessory.displayName} Config: (hide_device: ${device.hide_device})`);
+
+ this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} was added but will not work as OpenAPI doesn't support it yet.`);
// default placeholders
- this.On = false;
- this.OutletInUse = true;
+ this.SelectedRTPStreamConfiguration;
// this is subject we use to track when we need to POST changes to the SwitchBot API
this.doCameraUpdate = new Subject();
@@ -50,8 +58,8 @@ export class IndoorCam {
// get the WindowCovering service if it exists, otherwise create a new WindowCovering service
// you can create multiple services for each accessory
(this.service =
- accessory.getService(this.platform.Service.Outlet) ||
- accessory.addService(this.platform.Service.Outlet)), `${accessory.displayName} Indoor Camera`;
+ accessory.getService(this.platform.Service.CameraRTPStreamManagement) ||
+ accessory.addService(this.platform.Service.CameraRTPStreamManagement)), `${accessory.displayName} Indoor Camera`;
// To avoid "Cannot add a Service with the same UUID another Service without also defining a unique 'subtype' property." error,
// when creating multiple services of the same type, you need to use the following syntax to specify a name and subtype id:
@@ -65,9 +73,26 @@ export class IndoorCam {
// see https://developers.homebridge.io/#/service/WindowCovering
// create handlers for required characteristics
- this.service.getCharacteristic(this.platform.Characteristic.On).onSet(this.OnSet.bind(this));
+ this.service.getCharacteristic(this.platform.Characteristic.Active)
+ .onSet(this.ActiveSet.bind(this));
+
+ this.service.getCharacteristic(this.platform.Characteristic.SelectedRTPStreamConfiguration)
+ .onSet(this.SelectedRTPStreamConfigurationSet.bind(this));
+
+ this.service.getCharacteristic(this.platform.Characteristic.SetupEndpoints)
+ .onSet(this.SetupEndpointsSet.bind(this));
+
+ this.service.getCharacteristic(this.platform.Characteristic.StreamingStatus)
+ .onSet(this.StreamingStatusSet.bind(this));
- this.service.setCharacteristic(this.platform.Characteristic.OutletInUse, this.OutletInUse || true);
+ this.service.getCharacteristic(this.platform.Characteristic.SupportedAudioStreamConfiguration)
+ .onSet(this.SupportedAudioStreamConfigurationSet.bind(this));
+
+ this.service.getCharacteristic(this.platform.Characteristic.SupportedRTPConfiguration)
+ .onSet(this.SupportedRTPConfigurationSet.bind(this));
+
+ this.service.getCharacteristic(this.platform.Characteristic.SupportedVideoStreamConfiguration)
+ .onSet(this.SupportedVideoStreamConfigurationSet.bind(this));
// Update Homekit
this.updateHomeKitCharacteristics();
@@ -108,14 +133,7 @@ export class IndoorCam {
}
parseStatus() {
- switch (this.deviceStatus.body.power) {
- case 'on':
- this.On = true;
- break;
- default:
- this.On = false;
- }
- this.platform.debug(`Indoor Cam ${this.accessory.displayName} On: ${this.On}`);
+ this.platform.debug(`Indoor Cam ${this.accessory.displayName} SelectedRTPStreamConfiguration: ${this.SelectedRTPStreamConfiguration}`);
}
@@ -146,45 +164,42 @@ export class IndoorCam {
* Camera - "command" "turnOn" "default" = set to ON state
*/
async pushChanges() {
- const payload = {
- commandType: 'command',
- parameter: 'default',
- } as payload;
-
- if (this.On) {
- payload.command = 'turnOn';
+ if (!this.Active) {
+ const payload = {
+ commandType: 'command',
+ parameter: 'default',
+ command: 'turnOn',
+ } as payload;
+
+ this.platform.log.info(`Indoor Cam: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
+ + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
+
+ // Make the API request
+ const push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
+ this.platform.debug(`Indoor Cam: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
+ this.statusCode(push);
+ interval(5000)
+ .pipe(skipWhile(() => this.cameraUpdateInProgress))
+ .pipe(take(1))
+ .subscribe(() => {
+ this.refreshStatus();
+ });
} else {
- payload.command = 'turnOff';
+ this.platform.device(`Indoor Cam: ${this.accessory.displayName} No pushChanges. Active: ${this.Active}`);
}
-
- this.platform.log.info(`Indoor Cam: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
- + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
-
- // Make the API request
- const push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
- this.platform.debug(`Indoor Cam: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
- this.statusCode(push);
- this.refreshStatus();
}
updateHomeKitCharacteristics() {
- if (this.On === undefined) {
- this.platform.debug(`Indoor Cam: ${this.accessory.displayName} On: ${this.On}`);
- } else {
- this.service.updateCharacteristic(this.platform.Characteristic.On, this.On);
- this.platform.device(`Indoor Cam: ${this.accessory.displayName} updateCharacteristic On: ${this.On}`);
- }
- if (this.OutletInUse === undefined) {
- this.platform.debug(`Indoor Cam: ${this.accessory.displayName} OutletInUse: ${this.OutletInUse}`);
+ if (this.SelectedRTPStreamConfiguration === undefined) {
+ this.platform.debug(`Indoor Cam: ${this.accessory.displayName} On: ${this.SelectedRTPStreamConfiguration}`);
} else {
- this.service.updateCharacteristic(this.platform.Characteristic.OutletInUse, this.OutletInUse);
- this.platform.device(`Indoor Cam: ${this.accessory.displayName} updateCharacteristic OutletInUse: ${this.OutletInUse}`);
+ this.service.updateCharacteristic(this.platform.Characteristic.SelectedRTPStreamConfiguration, this.SelectedRTPStreamConfiguration);
+ this.platform.device(`Indoor Cam: ${this.accessory.displayName} updateCharacteristic On: ${this.SelectedRTPStreamConfiguration}`);
}
}
public apiError(e: any) {
- this.service.updateCharacteristic(this.platform.Characteristic.On, e);
- this.service.updateCharacteristic(this.platform.Characteristic.OutletInUse, e);
+ this.service.updateCharacteristic(this.platform.Characteristic.SelectedRTPStreamConfiguration, e);
}
private statusCode(push: AxiosResponse<{ statusCode: number; }>) {
@@ -200,9 +215,15 @@ export class IndoorCam {
break;
case 161:
this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} Device is offline.`);
+ if (this.device.offline) {
+ this.Active = false;
+ }
break;
case 171:
- this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} Hub Device is offline.`);
+ this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
+ if (this.device.offline) {
+ this.Active = false;
+ }
break;
case 190:
this.platform.log.error(`Indoor Cam: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -216,15 +237,73 @@ export class IndoorCam {
}
}
+ /**
+ * Handle requests to set the value of the "Active" characteristic
+ */
+ ActiveSet(value: CharacteristicValue) {
+ this.platform.debug(`Indoor Cam: ${this.accessory.displayName} Active: ${value}`);
+
+ this.Active = value;
+ this.doCameraUpdate.next();
+ }
+
+ /**
+ * Handle requests to set the value of the "SelectedRTPStreamConfiguration" characteristic
+ */
+ SelectedRTPStreamConfigurationSet(value: CharacteristicValue) {
+ this.platform.debug(`Indoor Cam: ${this.accessory.displayName} SelectedRTPStreamConfiguration: ${value}`);
+
+ this.SelectedRTPStreamConfiguration = value;
+ this.doCameraUpdate.next();
+ }
+
+ /**
+ * Handle requests to set the value of the "On" characteristic
+ */
+ SetupEndpointsSet(value: CharacteristicValue) {
+ this.platform.debug(`Indoor Cam: ${this.accessory.displayName} SetupEndpoints: ${value}`);
+
+ this.SetupEndpoints = value;
+ this.doCameraUpdate.next();
+ }
+
/**
* Handle requests to set the value of the "On" characteristic
*/
- OnSet(value: CharacteristicValue) {
- this.platform.debug(`Indoor Cam: ${this.accessory.displayName} On: ${value}`);
+ SupportedAudioStreamConfigurationSet(value: CharacteristicValue) {
+ this.platform.debug(`Indoor Cam: ${this.accessory.displayName} SupportedAudioStreamConfiguration: ${value}`);
- this.On = value;
+ this.SupportedAudioStreamConfiguration = value;
this.doCameraUpdate.next();
}
+ /**
+ * Handle requests to set the value of the "On" characteristic
+ */
+ SupportedRTPConfigurationSet(value: CharacteristicValue) {
+ this.platform.debug(`Indoor Cam: ${this.accessory.displayName} SupportedRTPConfiguration: ${value}`);
+
+ this.SupportedRTPConfiguration = value;
+ this.doCameraUpdate.next();
+ }
+ /**
+ * Handle requests to set the value of the "On" characteristic
+ */
+ StreamingStatusSet(value: CharacteristicValue) {
+ this.platform.debug(`Indoor Cam: ${this.accessory.displayName} StreamingStatus: ${value}`);
+
+ this.StreamingStatus = value;
+ this.doCameraUpdate.next();
+ }
+
+ /**
+ * Handle requests to set the value of the "On" characteristic
+ */
+ SupportedVideoStreamConfigurationSet(value: CharacteristicValue) {
+ this.platform.debug(`Indoor Cam: ${this.accessory.displayName} SupportedVideoStreamConfiguration: ${value}`);
+
+ this.SupportedVideoStreamConfiguration = value;
+ this.doCameraUpdate.next();
+ }
}
\ No newline at end of file
diff --git a/src/devices/meters.ts b/src/devices/meters.ts
index 8e1462f7..2b075e7e 100644
--- a/src/devices/meters.ts
+++ b/src/devices/meters.ts
@@ -3,7 +3,7 @@ import { interval, Subject } from 'rxjs';
import { skipWhile } from 'rxjs/operators';
import { SwitchBotPlatform } from '../platform';
import { Service, PlatformAccessory, Units, CharacteristicValue } from 'homebridge';
-import { DeviceURL, device, devicesConfig, serviceData, ad, switchbot, deviceStatusResponse } from '../settings';
+import { DeviceURL, device, devicesConfig, serviceData, ad, switchbot, deviceStatusResponse, temperature } from '../settings';
/**
* Platform Accessory
@@ -18,8 +18,11 @@ export class Meter {
// Characteristic Values
CurrentRelativeHumidity!: CharacteristicValue;
+ CurrentRelativeHumidityCached!: CharacteristicValue;
CurrentTemperature!: CharacteristicValue;
+ CurrentTemperatureCached!: CharacteristicValue;
BatteryLevel!: CharacteristicValue;
+ BatteryLevelCached!: CharacteristicValue;
ChargingState!: CharacteristicValue;
StatusLowBattery!: CharacteristicValue;
Active!: CharacteristicValue;
@@ -32,10 +35,9 @@ export class Meter {
connected?: boolean;
switchbot!: switchbot;
serviceData!: serviceData;
+ temperature!: temperature['c'];
battery!: serviceData['battery'];
humidity!: serviceData['humidity'];
- fahrenheit!: serviceData['fahrenheit'];
- temperature!: serviceData['temperature'];
// Config
private readonly deviceDebug = this.platform.config.options?.debug === 'device' || this.platform.debugMode;
@@ -51,15 +53,31 @@ export class Meter {
public device: device & devicesConfig,
) {
// Meter Config
- this.platform.device(`Meter: ${this.accessory.displayName} Config: (ble: ${device.ble}, unit: ${device.meter?.unit},`
- + ` hide_temperature: ${device.meter?.hide_temperature}, hide_humidity: ${device.meter?.hide_humidity})`);
+ this.platform.device(`Meter: ${this.accessory.displayName} Config: (ble: ${device.ble}, hide_temperature: ${device.meter?.hide_temperature},`
+ + ` hide_humidity: ${device.meter?.hide_humidity})`);
// default placeholders
- this.BatteryLevel = 0;
- this.ChargingState = 2;
- this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
- this.CurrentRelativeHumidity = 0;
- this.CurrentTemperature = 0;
+ if (this.BatteryLevel === undefined) {
+ this.BatteryLevel = 100;
+ } else {
+ this.BatteryLevel = this.accessory.context.BatteryLevel;
+ }
+ if (this.BatteryLevel < 15) {
+ this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
+ } else {
+ this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
+ }
+ this.ChargingState = this.platform.Characteristic.ChargingState.NOT_CHARGEABLE;
+ if (this.CurrentRelativeHumidity === undefined) {
+ this.CurrentRelativeHumidity = 0;
+ } else {
+ this.CurrentRelativeHumidity = this.accessory.context.CurrentRelativeHumidity;
+ }
+ if (this.CurrentTemperature === undefined) {
+ this.CurrentTemperature = 0;
+ } else {
+ this.CurrentTemperature = this.accessory.context.CurrentTemperature;
+ }
// this is subject we use to track when we need to POST changes to the SwitchBot API
this.doMeterUpdate = new Subject();
@@ -177,9 +195,9 @@ export class Meter {
// Battery
this.BatteryLevel = Number(this.battery);
if (this.BatteryLevel < 15) {
- this.StatusLowBattery = 1;
+ this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
} else {
- this.StatusLowBattery = 0;
+ this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
}
this.platform.debug(`${this.accessory.displayName} BatteryLevel: ${this.BatteryLevel}, StatusLowBattery: ${this.StatusLowBattery}`);
@@ -191,13 +209,8 @@ export class Meter {
// Current Temperature
if (!this.device.meter?.hide_temperature) {
- if (this.device.meter?.unit === 1) {
- this.CurrentTemperature = this.toFahrenheit(this.temperature!.c);
- } else if (this.device.meter?.unit === 0) {
- this.CurrentTemperature = this.toCelsius(this.temperature!.c);
- } else {
- this.CurrentTemperature = Number(this.temperature?.c);
- }
+ this.temperature < 0 ? 0 : this.temperature > 100 ? 100 : this.temperature;
+ this.CurrentTemperature = this.temperature;
this.platform.debug(`Meter: ${this.accessory.displayName} Temperature: ${this.CurrentTemperature}°c`);
}
}
@@ -211,9 +224,9 @@ export class Meter {
this.BatteryLevel = 10;
}
if (this.BatteryLevel < 15) {
- this.StatusLowBattery = 1;
+ this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
} else {
- this.StatusLowBattery = 0;
+ this.StatusLowBattery = this.platform.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
}
// Current Relative Humidity
if (!this.device.meter?.hide_humidity) {
@@ -223,13 +236,7 @@ export class Meter {
// Current Temperature
if (!this.device.meter?.hide_temperature) {
- if (this.device.meter?.unit === 1) {
- this.CurrentTemperature = this.toFahrenheit(this.deviceStatus.body.temperature!);
- } else if (this.device.meter?.unit === 0) {
- this.CurrentTemperature = this.toCelsius(this.deviceStatus.body.temperature!);
- } else {
- this.CurrentTemperature = Number(this.deviceStatus.body.temperature);
- }
+ this.CurrentTemperature = Number(this.deviceStatus.body.temperature);
this.platform.debug(`Meter: ${this.accessory.displayName} Temperature: ${this.CurrentTemperature}°c`);
}
}
@@ -259,20 +266,18 @@ export class Meter {
const switchbot = this.connectBLE();
// Start to monitor advertisement packets
switchbot.startScan({
- model: 'T',
id: this.device.bleMac,
}).then(() => {
// Set an event hander
switchbot.onadvertisement = (ad: ad) => {
this.serviceData = ad.serviceData;
- this.temperature = ad.serviceData.temperature;
- this.fahrenheit = ad.serviceData.fahrenheit;
+ this.temperature = ad.serviceData.temperature!.c;
this.humidity = ad.serviceData.humidity;
this.battery = ad.serviceData.battery;
this.platform.device(`Meter: ${this.accessory.displayName} serviceData: ${JSON.stringify(ad.serviceData)}`);
this.platform.device(`Meter: ${this.accessory.displayName} model: ${ad.serviceData.model}, modelName: ${ad.serviceData.modelName}, `
- + `temperature: ${JSON.stringify(ad.serviceData.temperature)}, fahrenheit: ${ad.serviceData.fahrenheit}, `
- + `humidity: ${ad.serviceData.humidity}, battery: ${ad.serviceData.battery}`);
+ + `temperature: ${JSON.stringify(ad.serviceData.temperature?.c)}, humidity: ${ad.serviceData.humidity}, `
+ + `battery: ${ad.serviceData.battery}`);
if (this.serviceData) {
this.connected = true;
@@ -288,6 +293,12 @@ export class Meter {
// Stop to monitor
switchbot.stopScan();
if (this.connected) {
+ this.CurrentTemperatureCached = this.temperature;
+ this.accessory.context.CurrentTemperature = this.CurrentTemperatureCached;
+ this.CurrentRelativeHumidityCached = this.humidity!;
+ this.accessory.context.CurrentRelativeHumidity = this.CurrentRelativeHumidityCached;
+ this.BatteryLevelCached = this.battery!;
+ this.accessory.context.BatteryLevel = this.BatteryLevelCached;
this.parseStatus();
this.updateHomeKitCharacteristics();
} else {
@@ -321,6 +332,12 @@ export class Meter {
try {
this.deviceStatus = (await this.platform.axios.get(`${DeviceURL}/${this.device.deviceId}/status`)).data;
this.platform.debug(`Meter: ${this.accessory.displayName} openAPIRefreshStatus: ${JSON.stringify(this.deviceStatus)}`);
+ this.CurrentTemperatureCached = this.deviceStatus.body.humidity!;
+ this.accessory.context.CurrentTemperature = this.CurrentTemperatureCached;
+ this.CurrentRelativeHumidityCached = this.deviceStatus.body.humidity!;
+ this.accessory.context.CurrentRelativeHumidity = this.CurrentRelativeHumidityCached;
+ this.BatteryLevelCached = 100;
+ this.accessory.context.BatteryLevel = this.BatteryLevelCached;
this.parseStatus();
this.updateHomeKitCharacteristics();
} catch (e: any) {
@@ -382,19 +399,4 @@ export class Meter {
this.temperatureservice?.updateCharacteristic(this.platform.Characteristic.CurrentTemperature, e);
}
}
-
- /**
- * Converts the value to celsius if the temperature units are in Fahrenheit
- */
- toCelsius(value: number) {
- // celsius should be to the nearest 0.5 degree
- return Math.round((5 / 9) * (value - 32) * 2) / 2;
- }
-
- /**
- * Converts the value to fahrenheit if the temperature units are in Fahrenheit
- */
- toFahrenheit(value: number) {
- return Math.round((value * 9) / 5 + 32);
- }
}
diff --git a/src/devices/plugs.ts b/src/devices/plugs.ts
index 316018e2..dde823bd 100644
--- a/src/devices/plugs.ts
+++ b/src/devices/plugs.ts
@@ -2,7 +2,7 @@
import { AxiosResponse } from 'axios';
import { interval, Subject } from 'rxjs';
import { SwitchBotPlatform } from '../platform';
-import { debounceTime, skipWhile, tap } from 'rxjs/operators';
+import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
import { Service, PlatformAccessory, CharacteristicValue } from 'homebridge';
import { DeviceURL, device, devicesConfig, deviceStatusResponse, payload } from '../settings';
@@ -12,6 +12,7 @@ export class Plug {
// Characteristic Values
On!: CharacteristicValue;
+ OnCached!: CharacteristicValue;
// OpenAPI Others
deviceStatus!: deviceStatusResponse;
@@ -29,8 +30,15 @@ export class Plug {
private accessory: PlatformAccessory,
public device: device & devicesConfig,
) {
+ // Bot Config
+ this.platform.device(`Plug: ${this.accessory.displayName} Config: (offline: ${device.offline})`);
+
// default placeholders
- this.On = false;
+ if (this.On === undefined) {
+ this.On = false;
+ } else {
+ this.On = this.accessory.context.On;
+ }
// this is subject we use to track when we need to POST changes to the SwitchBot API
this.doPlugUpdate = new Subject();
@@ -142,24 +150,34 @@ export class Plug {
* Plug - "command" "turnOn" "default" = set to ON state
*/
async pushChanges() {
- const payload = {
- commandType: 'command',
- parameter: 'default',
- } as payload;
-
- if (this.On) {
- payload.command = 'turnOn';
- } else {
- payload.command = 'turnOff';
- }
+ if (this.On !== this.OnCached) {
+ const payload = {
+ commandType: 'command',
+ parameter: 'default',
+ } as payload;
+
+ if (this.On) {
+ payload.command = 'turnOn';
+ } else {
+ payload.command = 'turnOff';
+ }
- this.platform.log.info(`Plug: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
- + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
+ this.platform.log.info(`Plug: ${this.accessory.displayName} Sending request to SwitchBot API. command: ${payload.command},`
+ + ` parameter: ${payload.parameter}, commandType: ${payload.commandType}`);
- // Make the API request
- const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
- this.platform.debug(`Plug: ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
- this.statusCode(push);
+ // Make the API request
+ const push: any = (await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload));
+ this.platform.debug(`Plug: ${this.accessory.displayName} pushchanges: ${JSON.stringify(push.data)}`);
+ this.statusCode(push);
+ this.OnCached = this.On;
+ this.accessory.context.On = this.OnCached;
+ }
+ interval(5000)
+ .pipe(skipWhile(() => this.plugUpdateInProgress))
+ .pipe(take(1))
+ .subscribe(() => {
+ this.refreshStatus();
+ });
}
updateHomeKitCharacteristics() {
@@ -188,9 +206,11 @@ export class Plug {
break;
case 161:
this.platform.log.error(`Plug: ${this.accessory.displayName} Device is offline.`);
+ this.offlineOff();
break;
case 171:
- this.platform.log.error(`Plug: ${this.accessory.displayName} Hub Device is offline.`);
+ this.platform.log.error(`Plug: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
+ this.offlineOff();
break;
case 190:
this.platform.log.error(`Plug: ${this.accessory.displayName} Device internal error due to device states not synchronized with server,`
@@ -204,6 +224,13 @@ export class Plug {
}
}
+ private offlineOff() {
+ if (this.device.offline) {
+ this.On = false;
+ this.service.getCharacteristic(this.platform.Characteristic.On).updateValue(this.On);
+ }
+ }
+
/**
* Handle requests to set the value of the "On" characteristic
*/
diff --git a/src/irdevices/airconditioners.ts b/src/irdevices/airconditioners.ts
index c5a8bcea..495eb21e 100644
--- a/src/irdevices/airconditioners.ts
+++ b/src/irdevices/airconditioners.ts
@@ -14,9 +14,11 @@ export class AirConditioner {
// Characteristic Values
Active!: CharacteristicValue;
+ ActiveCached!: CharacteristicValue;
RotationSpeed!: CharacteristicValue;
LastTemperature!: CharacteristicValue;
CurrentTemperature!: CharacteristicValue;
+ CurrentTemperatureCached!: CharacteristicValue;
TargetHeaterCoolerState?: CharacteristicValue;
CurrentHeaterCoolerState!: CharacteristicValue;
HeatingThresholdTemperature?: CharacteristicValue;
@@ -41,7 +43,17 @@ export class AirConditioner {
private accessory: PlatformAccessory,
public device: irdevice & irDevicesConfig,
) {
- this.CurrentTemperature = 24;
+ // default placeholders
+ if (this.Active === undefined) {
+ this.Active = this.platform.Characteristic.Active.INACTIVE;
+ } else {
+ this.Active = this.accessory.context.Active;
+ }
+ if (this.CurrentTemperature === undefined) {
+ this.CurrentTemperature = 24;
+ } else {
+ this.CurrentTemperature = this.accessory.context.CurrentTemperature;
+ }
// set accessory information
accessory
@@ -161,6 +173,8 @@ export class AirConditioner {
this.platform.device(`Air Conditioner: ${this.accessory.displayName} pushAirConditionerOffChanges, Active: ${this.Active}`);
}
this.Active = value;
+ this.ActiveCached = this.Active;
+ this.accessory.context.Active = this.ActiveCached;
}
private updateHomeKitCharacteristics() {
@@ -349,6 +363,8 @@ export class AirConditioner {
const push: any = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
this.platform.log.error(`Air Conditioner: ${this.accessory.displayName} pushChanges: ${JSON.stringify(push.data)}`);
this.statusCode(push);
+ this.CurrentTemperatureCached = this.CurrentTemperature;
+ this.accessory.context.CurrentTemperature = this.CurrentTemperatureCached;
this.updateHomeKitCharacteristics();
} catch (e: any) {
this.platform.log.error(`Air Conditioner: ${this.accessory.displayName} failed pushChanges`);
@@ -379,7 +395,7 @@ export class AirConditioner {
this.platform.log.error(`Air Conditioner: ${this.accessory.displayName} Device is offline.`);
break;
case 171:
- this.platform.log.error(`Air Conditioner: ${this.accessory.displayName} Hub Device is offline.`);
+ this.platform.log.error(`Air Conditioner: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
break;
case 190:
this.platform.log.error(`Air Conditioner: ${this.accessory.displayName} Device internal error due to device states not synchronized`
diff --git a/src/irdevices/airpurifiers.ts b/src/irdevices/airpurifiers.ts
index f8de4877..aa473b77 100644
--- a/src/irdevices/airpurifiers.ts
+++ b/src/irdevices/airpurifiers.ts
@@ -15,11 +15,13 @@ export class AirPurifier {
// Characteristic Values
Active!: CharacteristicValue;
APActive!: CharacteristicValue;
+ ActiveCached!: CharacteristicValue;
CurrentAPTemp!: CharacteristicValue;
CurrentAPMode!: CharacteristicValue;
RotationSpeed!: CharacteristicValue;
CurrentAPFanSpeed!: CharacteristicValue;
CurrentTemperature!: CharacteristicValue;
+ CurrentTemperatureCached!: CharacteristicValue;
CurrentAirPurifierState!: CharacteristicValue;
CurrentHeaterCoolerState!: CharacteristicValue;
@@ -42,6 +44,18 @@ export class AirPurifier {
private accessory: PlatformAccessory,
public device: irdevice & irDevicesConfig,
) {
+ // default placeholders
+ if (this.Active === undefined) {
+ this.Active = this.platform.Characteristic.Active.INACTIVE;
+ } else {
+ this.Active = this.accessory.context.Active;
+ }
+ if (this.CurrentTemperature === undefined) {
+ this.CurrentTemperature = 24;
+ } else {
+ this.CurrentTemperature = this.accessory.context.CurrentTemperature;
+ }
+
// set accessory information
accessory
.getService(this.platform.Service.AccessoryInformation)!
@@ -81,6 +95,8 @@ export class AirPurifier {
this.pushAirConditionerOnChanges();
}
this.Active = value;
+ this.ActiveCached = this.Active;
+ this.accessory.context.Active = this.ActiveCached;
}
private updateHomeKitCharacteristics() {
@@ -210,6 +226,8 @@ export class AirPurifier {
this.platform.debug(`Air Purifier: ${this.accessory.displayName} pushChanges: ${push.data}`);
this.statusCode(push);
this.updateHomeKitCharacteristics();
+ this.CurrentTemperatureCached = this.CurrentTemperature;
+ this.accessory.context.CurrentTemperature = this.CurrentTemperatureCached;
} catch (e: any) {
this.platform.log.error(`Air Purifier: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
if (this.deviceDebug) {
@@ -239,7 +257,7 @@ export class AirPurifier {
this.platform.log.error(`Air Purifier: ${this.accessory.displayName} Device is offline.`);
break;
case 171:
- this.platform.log.error(`Air Purifier: ${this.accessory.displayName} Hub Device is offline.`);
+ this.platform.log.error(`Air Purifier: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
break;
case 190:
this.platform.log.error(`Air Purifier: ${this.accessory.displayName} Device internal error due to device states not synchronized`
diff --git a/src/irdevices/cameras.ts b/src/irdevices/cameras.ts
index 31d45afa..8a978c01 100644
--- a/src/irdevices/cameras.ts
+++ b/src/irdevices/cameras.ts
@@ -14,6 +14,7 @@ export class Camera {
// Characteristic Values
On!: CharacteristicValue;
+ OnCached!: CharacteristicValue;
// Config
private readonly deviceDebug = this.platform.config.options?.debug === 'device' || this.platform.debugMode;
@@ -24,6 +25,13 @@ export class Camera {
private accessory: PlatformAccessory,
public device: irdevice & irDevicesConfig,
) {
+ // default placeholders
+ if (this.On === undefined) {
+ this.On = false;
+ } else {
+ this.On = this.accessory.context.On;
+ }
+
// set accessory information
accessory
.getService(this.platform.Service.AccessoryInformation)!
@@ -110,6 +118,8 @@ export class Camera {
this.platform.debug(`Camera: ${this.accessory.displayName} pushChanges: ${push.data}`);
this.statusCode(push);
this.updateHomeKitCharacteristics();
+ this.OnCached = this.On;
+ this.accessory.context.On = this.OnCached;
} catch (e: any) {
this.platform.log.error(`Camera: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
if (this.deviceDebug) {
@@ -139,7 +149,7 @@ export class Camera {
this.platform.log.error(`Camera: ${this.accessory.displayName} Device is offline.`);
break;
case 171:
- this.platform.log.error(`Camera: ${this.accessory.displayName} Hub Device is offline.`);
+ this.platform.log.error(`Camera: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
break;
case 190:
this.platform.log.error(`Camera: ${this.accessory.displayName} Device internal error due to device states not synchronized`
diff --git a/src/irdevices/fans.ts b/src/irdevices/fans.ts
index 9d426953..e4127a57 100644
--- a/src/irdevices/fans.ts
+++ b/src/irdevices/fans.ts
@@ -14,6 +14,7 @@ export class Fan {
// Characteristic Values
Active!: CharacteristicValue;
+ ActiveCached!: CharacteristicValue;
ActiveIdentifier!: CharacteristicValue;
RotationSpeed!: CharacteristicValue;
SwingMode!: CharacteristicValue;
@@ -34,6 +35,13 @@ export class Fan {
private accessory: PlatformAccessory,
public device: irdevice & irDevicesConfig,
) {
+ // default placeholders
+ if (this.Active === undefined) {
+ this.Active = this.platform.Characteristic.Active.INACTIVE;
+ } else {
+ this.Active = this.accessory.context.Active;
+ }
+
// set accessory information
accessory
.getService(this.platform.Service.AccessoryInformation)!
@@ -164,6 +172,8 @@ export class Fan {
this.pushFanOnChanges();
}
this.Active = value;
+ this.ActiveCached = this.Active;
+ this.accessory.context.Active = this.ActiveCached;
}
/**
@@ -261,7 +271,7 @@ export class Fan {
this.platform.log.error(`Fan: ${this.accessory.displayName} Device is offline.`);
break;
case 171:
- this.platform.log.error(`Fan: ${this.accessory.displayName} Hub Device is offline.`);
+ this.platform.log.error(`Fan: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
break;
case 190:
this.platform.log.error(`Fan: ${this.accessory.displayName} Device internal error due to device states not synchronized`
diff --git a/src/irdevices/lights.ts b/src/irdevices/lights.ts
index 77069135..92cbedf4 100644
--- a/src/irdevices/lights.ts
+++ b/src/irdevices/lights.ts
@@ -14,6 +14,7 @@ export class Light {
// Characteristic Values
On!: CharacteristicValue;
+ OnCached!: CharacteristicValue;
// Config
private readonly deviceDebug = this.platform.config.options?.debug === 'device' || this.platform.debugMode;
@@ -24,6 +25,13 @@ export class Light {
private accessory: PlatformAccessory,
public device: irdevice & irDevicesConfig,
) {
+ // default placeholders
+ if (this.On === undefined) {
+ this.On = false;
+ } else {
+ this.On = this.accessory.context.On;
+ }
+
// set accessory information
accessory
.getService(this.platform.Service.AccessoryInformation)!
@@ -142,6 +150,8 @@ export class Light {
const push = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
this.platform.debug(`Light: ${this.accessory.displayName} pushChanges: ${push.data}`);
this.statusCode(push);
+ this.OnCached = this.On;
+ this.accessory.context.On = this.OnCached;
this.updateHomeKitCharacteristics();
} catch (e: any) {
this.platform.log.error(`Light: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
@@ -173,7 +183,7 @@ export class Light {
this.platform.log.error(`Light: ${this.accessory.displayName} Device is offline.`);
break;
case 171:
- this.platform.log.error(`Light: ${this.accessory.displayName} Hub Device is offline.`);
+ this.platform.log.error(`Light: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
break;
case 190:
this.platform.log.error(`Light: ${this.accessory.displayName} Device internal error due to device states not synchronized`
diff --git a/src/irdevices/others.ts b/src/irdevices/others.ts
index 2dd51f04..8c792258 100644
--- a/src/irdevices/others.ts
+++ b/src/irdevices/others.ts
@@ -14,6 +14,7 @@ export class Others {
// Characteristic Values
Active!: CharacteristicValue;
+ ActiveCached!: CharacteristicValue;
// Config
private readonly deviceDebug = this.platform.config.options?.debug === 'device' || this.platform.debugMode;
@@ -24,6 +25,13 @@ export class Others {
private accessory: PlatformAccessory,
public device: irdevice & irDevicesConfig,
) {
+ // default placeholders
+ if (this.Active === undefined) {
+ this.Active = this.platform.Characteristic.Active.INACTIVE;
+ } else {
+ this.Active = this.accessory.context.Active;
+ }
+
// set accessory information
accessory
.getService(this.platform.Service.AccessoryInformation)!
@@ -54,6 +62,8 @@ export class Others {
this.pushOffChanges();
}
this.Active = value;
+ this.ActiveCached = this.Active;
+ this.accessory.context.Active = this.ActiveCached;
}
private updateHomeKitCharacteristics() {
@@ -160,7 +170,7 @@ export class Others {
this.platform.log.error(`Other: ${this.accessory.displayName} Device is offline.`);
break;
case 171:
- this.platform.log.error(`Other: ${this.accessory.displayName} Hub Device is offline.`);
+ this.platform.log.error(`Other: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
break;
case 190:
this.platform.log.error(`Other: ${this.accessory.displayName} Device internal error due to device states not synchronized`
diff --git a/src/irdevices/tvs.ts b/src/irdevices/tvs.ts
index ef5756ea..783fb97e 100644
--- a/src/irdevices/tvs.ts
+++ b/src/irdevices/tvs.ts
@@ -15,6 +15,7 @@ export class TV {
// Characteristic Values
Active!: CharacteristicValue;
+ ActiveCached!: CharacteristicValue;
ActiveIdentifier!: CharacteristicValue;
// Others
@@ -29,6 +30,13 @@ export class TV {
private accessory: PlatformAccessory,
public device: irdevice & irDevicesConfig,
) {
+ // default placeholders
+ if (this.Active === undefined) {
+ this.Active = this.platform.Characteristic.Active.INACTIVE;
+ } else {
+ this.Active = this.accessory.context.Active;
+ }
+
// set accessory information
accessory
.getService(this.platform.Service.AccessoryInformation)!
@@ -207,6 +215,8 @@ export class TV {
this.pushTvOnChanges();
}
this.Active = value;
+ this.ActiveCached = this.Active;
+ this.accessory.context.Active = this.ActiveCached;
}
}
@@ -377,7 +387,7 @@ export class TV {
this.platform.log.error(`${this.device.remoteType}: ${this.accessory.displayName} Device is offline.`);
break;
case 171:
- this.platform.log.error(`${this.device.remoteType}: ${this.accessory.displayName} Hub Device is offline.`);
+ this.platform.log.error(`${this.device.remoteType}: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
break;
case 190:
this.platform.log.error(`${this.device.remoteType}: `
diff --git a/src/irdevices/vacuumcleaners.ts b/src/irdevices/vacuumcleaners.ts
index b2977ed5..33e25900 100644
--- a/src/irdevices/vacuumcleaners.ts
+++ b/src/irdevices/vacuumcleaners.ts
@@ -14,6 +14,7 @@ export class VacuumCleaner {
// Characteristic Values
On!: CharacteristicValue;
+ OnCached!: CharacteristicValue;
// Config
private readonly deviceDebug = this.platform.config.options?.debug === 'device' || this.platform.debugMode;
@@ -24,6 +25,13 @@ export class VacuumCleaner {
private accessory: PlatformAccessory,
public device: irdevice & irDevicesConfig,
) {
+ // default placeholders
+ if (this.On === undefined) {
+ this.On = false;
+ } else {
+ this.On = this.accessory.context.On;
+ }
+
// set accessory information
accessory
.getService(this.platform.Service.AccessoryInformation)!
@@ -109,6 +117,8 @@ export class VacuumCleaner {
const push = await this.platform.axios.post(`${DeviceURL}/${this.device.deviceId}/commands`, payload);
this.platform.debug(`Vacuum Cleaner: ${this.accessory.displayName} pushChanges: ${push.data}`);
this.statusCode(push);
+ this.OnCached = this.On;
+ this.accessory.context.On = this.OnCached;
this.updateHomeKitCharacteristics();
} catch (e: any) {
this.platform.log.error(`Vacuum Cleaner: ${this.accessory.displayName} failed pushChanges with OpenAPI Connection`);
@@ -139,7 +149,7 @@ export class VacuumCleaner {
this.platform.log.error(`Vacuum Cleaner: ${this.accessory.displayName} Device is offline.`);
break;
case 171:
- this.platform.log.error(`Vacuum Cleaner: ${this.accessory.displayName} Hub Device is offline.`);
+ this.platform.log.error(`Vacuum Cleaner: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
break;
case 190:
this.platform.log.error(`Vacuum Cleaner: ${this.accessory.displayName} Device internal error due to device states not synchronized`
diff --git a/src/irdevices/waterheaters.ts b/src/irdevices/waterheaters.ts
index 7f435554..0e8ccba8 100644
--- a/src/irdevices/waterheaters.ts
+++ b/src/irdevices/waterheaters.ts
@@ -14,6 +14,7 @@ export class WaterHeater {
// Characteristic Values
Active!: CharacteristicValue;
+ ActiveCached!: CharacteristicValue;
// Config
private readonly deviceDebug = this.platform.config.options?.debug === 'device' || this.platform.debugMode;
@@ -24,6 +25,13 @@ export class WaterHeater {
private accessory: PlatformAccessory,
public device: irdevice & irDevicesConfig,
) {
+ // default placeholders
+ if (this.Active === undefined) {
+ this.Active = this.platform.Characteristic.Active.INACTIVE;
+ } else {
+ this.Active = this.accessory.context.Active;
+ }
+
// set accessory information
accessory
.getService(this.platform.Service.AccessoryInformation)!
@@ -71,6 +79,8 @@ export class WaterHeater {
this.service.setCharacteristic(this.platform.Characteristic.InUse, this.platform.Characteristic.InUse.IN_USE);
}
this.Active = value;
+ this.ActiveCached = this.Active;
+ this.accessory.context.Active = this.ActiveCached;
}
private updateHomeKitCharacteristics() {
@@ -153,7 +163,7 @@ export class WaterHeater {
this.platform.log.error(`Water Heater: ${this.accessory.displayName} Device is offline.`);
break;
case 171:
- this.platform.log.error(`Water Heater: ${this.accessory.displayName} Hub Device is offline.`);
+ this.platform.log.error(`Water Heater: ${this.accessory.displayName} Hub Device is offline. Hub: ${this.device.hubDeviceId}`);
break;
case 190:
this.platform.log.error(`Water Heater: ${this.accessory.displayName} Device internal error due to device states not synchronized`
diff --git a/src/platform.ts b/src/platform.ts
index c5bb9042..4a23f234 100644
--- a/src/platform.ts
+++ b/src/platform.ts
@@ -204,7 +204,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
const mergeBydeviceId = (a1: { deviceId: string; }[], a2: any[]) =>
a1.map((itm: { deviceId: string; }) => ({
- ...a2.find((item: { deviceId: string; }) => (item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId) && item),
+ ...a2.find((item: { deviceId: string; }) => (
+ item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '')) && item),
...itm,
}));
@@ -238,7 +239,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
const mergeIRBydeviceId = (a1: { deviceId: string; }[], a2: any[]) =>
a1.map((itm: { deviceId: string; }) => ({
- ...a2.find((item: { deviceId: string; }) => (item.deviceId === itm.deviceId) && item),
+ ...a2.find((item: { deviceId: string; }) => (
+ item.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '') === itm.deviceId.toUpperCase().replace(/[^A-Z0-9]+/g, '')) && item),
...itm,
}));
@@ -265,8 +267,43 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
this.log.error('Neither SwitchBot OpenToken or Device Config are not set.');
}
} catch (e: any) {
- this.log.error('Failed to Discover Devices.', JSON.stringify(e.message));
- this.debug(JSON.stringify(e));
+ if (e.message.includes('400')) {
+ this.log.error('Failed to Discover Devices: Bad Request');
+ this.debug('The client has issued an invalid request. This is commonly used to specify validation errors in a request payload.');
+ } else if (e.message.includes('401')) {
+ this.log.error('Failed to Discover Devices: Unauthorized Request');
+ this.debug('Authorization for the API is required, but the request has not been authenticated.');
+ } else if (e.message.includes('403')) {
+ this.log.error('Failed to Discover Devices: Forbidden Request');
+ this.debug('The request has been authenticated but does not have appropriate permissions, or a requested resource is not found.');
+ } else if (e.message.includes('404')) {
+ this.log.error('Failed to Discover Devices: Requst Not Found');
+ this.debug('Specifies the requested path does not exist.');
+ } else if (e.message.includes('406')) {
+ this.log.error('Failed to Discover Devices: Request Not Acceptable');
+ this.debug('The client has requested a MIME type via the Accept header for a value not supported by the server.');
+ } else if (e.message.includes('415')) {
+ this.log.error('Failed to Discover Devices: Unsupported Requst Header');
+ this.debug('The client has defined a contentType header that is not supported by the server.');
+ } else if (e.message.includes('422')) {
+ this.log.error('Failed to Discover Devices: Unprocessable Entity');
+ this.debug('The client has made a valid request, but the server cannot process it.'
+ + ' This is often used for APIs for which certain limits have been exceeded.');
+ } else if (e.message.includes('429')) {
+ this.log.error('Failed to Discover Devices: Too Many Requests');
+ this.debug('The client has exceeded the number of requests allowed for a given time window.');
+ } else if (e.message.includes('500')) {
+ this.log.error('Failed to Discover Devices: Internal Server Error');
+ this.debug('An unexpected error on the SmartThings servers has occurred. These errors should be rare.');
+ } else {
+ this.log.error('Failed to Discover Devices');
+ }
+ if (this.config.options?.debug === 'device') {
+ this.log.error(`Failed to Discover Devices, Error Message: ${JSON.stringify(e.message)}`);
+ }
+ if (this.config.options?.debug === 'debug' || this.debugMode) {
+ this.log.error(`Failed to Discover Devices, Error: ${JSON.stringify(e)}`);
+ }
}
}
@@ -310,7 +347,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
this.debug(`Discovered ${device.deviceType}: ${device.deviceId}`);
this.createColorBulb(device);
break;
- case 'IndoorCam':
+ case 'Indoor Cam':
this.debug(`Discovered ${device.deviceType}: ${device.deviceId}`);
this.createIndoorCam(device);
break;
@@ -420,6 +457,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
existingAccessory.context.deviceID = device.deviceId;
existingAccessory.displayName = device.deviceName;
existingAccessory.context.firmwareRevision = this.version;
+ existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
await this.connectionTypeExistingAccessory(device, existingAccessory);
this.api.updatePlatformAccessories([existingAccessory]);
// create the accessory handler for the restored accessory
@@ -442,6 +480,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
accessory.context.model = device.deviceType;
accessory.context.deviceID = device.deviceId;
accessory.context.firmwareRevision = this.version;
+ accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
await this.connectionTypeNewAccessory(device, accessory);
// create the accessory handler for the newly create accessory
// this is imported from `platformAccessory.ts`
@@ -475,6 +514,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
existingAccessory.context.deviceID = device.deviceId;
existingAccessory.displayName = device.deviceName;
existingAccessory.context.firmwareRevision = this.version;
+ existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
await this.connectionTypeExistingAccessory(device, existingAccessory);
this.api.updatePlatformAccessories([existingAccessory]);
// create the accessory handler for the restored accessory
@@ -499,6 +539,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
accessory.context.model = device.deviceType;
accessory.context.deviceID = device.deviceId;
accessory.context.firmwareRevision = this.version;
+ accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
await this.connectionTypeNewAccessory(device, accessory);
// accessory.context.firmwareRevision = findaccessories.accessoryAttribute.softwareRevision;
// create the accessory handler for the newly create accessory
@@ -531,6 +572,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
existingAccessory.context.deviceID = device.deviceId;
existingAccessory.displayName = device.deviceName;
existingAccessory.context.firmwareRevision = this.version;
+ existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
await this.connectionTypeExistingAccessory(device, existingAccessory);
this.api.updatePlatformAccessories([existingAccessory]);
// create the accessory handler for the restored accessory
@@ -553,6 +595,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
accessory.context.model = device.deviceType;
accessory.context.deviceID = device.deviceId;
accessory.context.firmwareRevision = this.version;
+ accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
await this.connectionTypeNewAccessory(device, accessory);
// create the accessory handler for the newly create accessory
// this is imported from `platformAccessory.ts`
@@ -584,6 +627,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
existingAccessory.context.deviceID = device.deviceId;
existingAccessory.displayName = device.deviceName;
existingAccessory.context.firmwareRevision = this.version;
+ existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
await this.connectionTypeExistingAccessory(device, existingAccessory);
this.api.updatePlatformAccessories([existingAccessory]);
// create the accessory handler for the restored accessory
@@ -606,6 +650,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
accessory.context.model = device.deviceType;
accessory.context.deviceID = device.deviceId;
accessory.context.firmwareRevision = this.version;
+ accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
await this.connectionTypeNewAccessory(device, accessory);
// create the accessory handler for the newly create accessory
// this is imported from `platformAccessory.ts`
@@ -637,6 +682,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
existingAccessory.context.deviceID = device.deviceId;
existingAccessory.displayName = device.deviceName;
existingAccessory.context.firmwareRevision = this.version;
+ existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
await this.connectionTypeExistingAccessory(device, existingAccessory);
this.api.updatePlatformAccessories([existingAccessory]);
// create the accessory handler for the restored accessory
@@ -659,6 +705,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
accessory.context.model = device.deviceType;
accessory.context.deviceID = device.deviceId;
accessory.context.firmwareRevision = this.version;
+ accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
await this.connectionTypeNewAccessory(device, accessory);
// create the accessory handler for the newly create accessory
// this is imported from `platformAccessory.ts`
@@ -690,6 +737,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
existingAccessory.context.deviceID = device.deviceId;
existingAccessory.displayName = device.deviceName;
existingAccessory.context.firmwareRevision = this.version;
+ existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
await this.connectionTypeExistingAccessory(device, existingAccessory);
this.api.updatePlatformAccessories([existingAccessory]);
// create the accessory handler for the restored accessory
@@ -722,6 +770,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
accessory.context.model = device.deviceType;
accessory.context.deviceID = device.deviceId;
accessory.context.firmwareRevision = this.version;
+ accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
await this.connectionTypeNewAccessory(device, accessory);
// create the accessory handler for the newly create accessory
// this is imported from `platformAccessory.ts`
@@ -766,6 +815,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
existingAccessory.context.deviceID = device.deviceId;
existingAccessory.displayName = device.deviceName;
existingAccessory.context.firmwareRevision = this.version;
+ existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
await this.connectionTypeExistingAccessory(device, existingAccessory);
this.api.updatePlatformAccessories([existingAccessory]);
// create the accessory handler for the restored accessory
@@ -788,6 +838,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
accessory.context.model = device.deviceType;
accessory.context.deviceID = device.deviceId;
accessory.context.firmwareRevision = this.version;
+ accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
await this.connectionTypeNewAccessory(device, accessory);
// create the accessory handler for the newly create accessory
// this is imported from `platformAccessory.ts`
@@ -819,6 +870,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
existingAccessory.context.deviceID = device.deviceId;
existingAccessory.displayName = device.deviceName;
existingAccessory.context.firmwareRevision = this.version;
+ existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
await this.connectionTypeExistingAccessory(device, existingAccessory);
this.api.updatePlatformAccessories([existingAccessory]);
// create the accessory handler for the restored accessory
@@ -841,6 +893,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
accessory.context.model = device.deviceType;
accessory.context.deviceID = device.deviceId;
accessory.context.firmwareRevision = this.version;
+ accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
await this.connectionTypeNewAccessory(device, accessory);
// create the accessory handler for the newly create accessory
// this is imported from `platformAccessory.ts`
@@ -872,6 +925,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
existingAccessory.context.deviceID = device.deviceId;
existingAccessory.displayName = device.deviceName;
existingAccessory.context.firmwareRevision = this.version;
+ existingAccessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
await this.connectionTypeExistingAccessory(device, existingAccessory);
this.api.updatePlatformAccessories([existingAccessory]);
// create the accessory handler for the restored accessory
@@ -894,6 +948,7 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
accessory.context.model = device.deviceType;
accessory.context.deviceID = device.deviceId;
accessory.context.firmwareRevision = this.version;
+ accessory.context.deviceType = `SwitchBot: ${device.deviceType}`;
await this.connectionTypeNewAccessory(device, accessory);
// create the accessory handler for the newly create accessory
// this is imported from `platformAccessory.ts`
@@ -923,7 +978,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
existingAccessory.context.deviceID = device.deviceId;
existingAccessory.displayName = device.deviceName;
existingAccessory.context.firmwareRevision = this.version;
- await this.connectionTypeExistingAccessory(device, existingAccessory);
+ existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
+ await this.connectionTypeExistingIRAccessory(device, existingAccessory);
this.api.updatePlatformAccessories([existingAccessory]);
// create the accessory handler for the restored accessory
// this is imported from `platformAccessory.ts`
@@ -942,7 +998,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
accessory.context.model = device.remoteType;
accessory.context.deviceID = device.deviceId;
accessory.context.firmwareRevision = this.version;
- await this.connectionTypeNewAccessory(device, accessory);
+ accessory.context.deviceType = `IR: ${device.remoteType}`;
+ await this.connectionTypeNewIRAccessory(device, accessory);
// create the accessory handler for the newly create accessory
// this is imported from `platformAccessory.ts`
new TV(this, accessory, device);
@@ -978,7 +1035,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
existingAccessory.context.deviceID = device.deviceId;
existingAccessory.displayName = device.deviceName;
existingAccessory.context.firmwareRevision = this.version;
- await this.connectionTypeExistingAccessory(device, existingAccessory);
+ existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
+ await this.connectionTypeExistingIRAccessory(device, existingAccessory);
this.api.updatePlatformAccessories([existingAccessory]);
// create the accessory handler for the restored accessory
// this is imported from `platformAccessory.ts`
@@ -1000,7 +1058,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
accessory.context.model = device.remoteType;
accessory.context.deviceID = device.deviceId;
accessory.context.firmwareRevision = this.version;
- await this.connectionTypeNewAccessory(device, accessory);
+ accessory.context.deviceType = `IR: ${device.remoteType}`;
+ await this.connectionTypeNewIRAccessory(device, accessory);
// create the accessory handler for the newly create accessory
// this is imported from `platformAccessory.ts`
new Fan(this, accessory, device);
@@ -1031,7 +1090,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
existingAccessory.context.deviceID = device.deviceId;
existingAccessory.displayName = device.deviceName;
existingAccessory.context.firmwareRevision = this.version;
- await this.connectionTypeExistingAccessory(device, existingAccessory);
+ existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
+ await this.connectionTypeExistingIRAccessory(device, existingAccessory);
this.api.updatePlatformAccessories([existingAccessory]);
// create the accessory handler for the restored accessory
// this is imported from `platformAccessory.ts`
@@ -1053,7 +1113,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
accessory.context.model = device.remoteType;
accessory.context.deviceID = device.deviceId;
accessory.context.firmwareRevision = this.version;
- await this.connectionTypeNewAccessory(device, accessory);
+ accessory.context.deviceType = `IR: ${device.remoteType}`;
+ await this.connectionTypeNewIRAccessory(device, accessory);
// create the accessory handler for the newly create accessory
// this is imported from `platformAccessory.ts`
new Light(this, accessory, device);
@@ -1084,7 +1145,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
existingAccessory.context.deviceID = device.deviceId;
existingAccessory.displayName = device.deviceName;
existingAccessory.context.firmwareRevision = this.version;
- await this.connectionTypeExistingAccessory(device, existingAccessory);
+ existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
+ await this.connectionTypeExistingIRAccessory(device, existingAccessory);
this.api.updatePlatformAccessories([existingAccessory]);
// create the accessory handler for the restored accessory
// this is imported from `platformAccessory.ts`
@@ -1106,7 +1168,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
accessory.context.model = device.remoteType;
accessory.context.deviceID = device.deviceId;
accessory.context.firmwareRevision = this.version;
- await this.connectionTypeNewAccessory(device, accessory);
+ accessory.context.deviceType = `IR: ${device.remoteType}`;
+ await this.connectionTypeNewIRAccessory(device, accessory);
// create the accessory handler for the newly create accessory
// this is imported from `platformAccessory.ts`
new AirConditioner(this, accessory, device);
@@ -1137,7 +1200,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
existingAccessory.context.deviceID = device.deviceId;
existingAccessory.displayName = device.deviceName;
existingAccessory.context.firmwareRevision = this.version;
- await this.connectionTypeExistingAccessory(device, existingAccessory);
+ existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
+ await this.connectionTypeExistingIRAccessory(device, existingAccessory);
this.api.updatePlatformAccessories([existingAccessory]);
// create the accessory handler for the restored accessory
// this is imported from `platformAccessory.ts`
@@ -1159,7 +1223,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
accessory.context.model = device.remoteType;
accessory.context.deviceID = device.deviceId;
accessory.context.firmwareRevision = this.version;
- await this.connectionTypeNewAccessory(device, accessory);
+ accessory.context.deviceType = `IR: ${device.remoteType}`;
+ await this.connectionTypeNewIRAccessory(device, accessory);
// create the accessory handler for the newly create accessory
// this is imported from `platformAccessory.ts`
new AirPurifier(this, accessory, device);
@@ -1190,7 +1255,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
existingAccessory.context.deviceID = device.deviceId;
existingAccessory.displayName = device.deviceName;
existingAccessory.context.firmwareRevision = this.version;
- await this.connectionTypeExistingAccessory(device, existingAccessory);
+ existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
+ await this.connectionTypeExistingIRAccessory(device, existingAccessory);
this.api.updatePlatformAccessories([existingAccessory]);
// create the accessory handler for the restored accessory
// this is imported from `platformAccessory.ts`
@@ -1212,7 +1278,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
accessory.context.model = device.remoteType;
accessory.context.deviceID = device.deviceId;
accessory.context.firmwareRevision = this.version;
- await this.connectionTypeNewAccessory(device, accessory);
+ accessory.context.deviceType = `IR: ${device.remoteType}`;
+ await this.connectionTypeNewIRAccessory(device, accessory);
// create the accessory handler for the newly create accessory
// this is imported from `platformAccessory.ts`
new WaterHeater(this, accessory, device);
@@ -1243,7 +1310,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
existingAccessory.context.deviceID = device.deviceId;
existingAccessory.displayName = device.deviceName;
existingAccessory.context.firmwareRevision = this.version;
- await this.connectionTypeExistingAccessory(device, existingAccessory);
+ existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
+ await this.connectionTypeExistingIRAccessory(device, existingAccessory);
this.api.updatePlatformAccessories([existingAccessory]);
// create the accessory handler for the restored accessory
// this is imported from `platformAccessory.ts`
@@ -1265,7 +1333,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
accessory.context.model = device.remoteType;
accessory.context.deviceID = device.deviceId;
accessory.context.firmwareRevision = this.version;
- await this.connectionTypeNewAccessory(device, accessory);
+ accessory.context.deviceType = `IR: ${device.remoteType}`;
+ await this.connectionTypeNewIRAccessory(device, accessory);
// create the accessory handler for the newly create accessory
// this is imported from `platformAccessory.ts`
new VacuumCleaner(this, accessory, device);
@@ -1296,7 +1365,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
existingAccessory.context.deviceID = device.deviceId;
existingAccessory.displayName = device.deviceName;
existingAccessory.context.firmwareRevision = this.version;
- await this.connectionTypeExistingAccessory(device, existingAccessory);
+ existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
+ await this.connectionTypeExistingIRAccessory(device, existingAccessory);
this.api.updatePlatformAccessories([existingAccessory]);
// create the accessory handler for the restored accessory
// this is imported from `platformAccessory.ts`
@@ -1318,7 +1388,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
accessory.context.model = device.remoteType;
accessory.context.deviceID = device.deviceId;
accessory.context.firmwareRevision = this.version;
- await this.connectionTypeNewAccessory(device, accessory);
+ accessory.context.deviceType = `IR: ${device.remoteType}`;
+ await this.connectionTypeNewIRAccessory(device, accessory);
// create the accessory handler for the newly create accessory
// this is imported from `platformAccessory.ts`
new Camera(this, accessory, device);
@@ -1349,7 +1420,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
existingAccessory.context.deviceID = device.deviceId;
existingAccessory.displayName = device.deviceName;
existingAccessory.context.firmwareRevision = this.version;
- await this.connectionTypeExistingAccessory(device, existingAccessory);
+ existingAccessory.context.deviceType = `IR: ${device.remoteType}`;
+ await this.connectionTypeExistingIRAccessory(device, existingAccessory);
this.api.updatePlatformAccessories([existingAccessory]);
// create the accessory handler for the restored accessory
// this is imported from `platformAccessory.ts`
@@ -1371,7 +1443,8 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
accessory.context.model = device.remoteType;
accessory.context.deviceID = device.deviceId;
accessory.context.firmwareRevision = this.version;
- await this.connectionTypeNewAccessory(device, accessory);
+ accessory.context.deviceType = `IR: ${device.remoteType}`;
+ await this.connectionTypeNewIRAccessory(device, accessory);
// create the accessory handler for the newly create accessory
// this is imported from `platformAccessory.ts`
new Others(this, accessory, device);
@@ -1406,6 +1479,19 @@ export class SwitchBotPlatform implements DynamicPlatformPlugin {
}
}
+ public async connectionTypeNewIRAccessory(
+ device: irdevice & devicesConfig,
+ accessory: PlatformAccessory) {
+ accessory.context.connectionType = 'IR wirth OpenAPI';
+ }
+
+ public async connectionTypeExistingIRAccessory(
+ device: irdevice & devicesConfig,
+ existingAccessory: PlatformAccessory,
+ ) {
+ existingAccessory.context.connectionType = 'IR with OpenAPI';
+ }
+
public unregisterPlatformAccessories(existingAccessory: PlatformAccessory) {
// remove platform accessories when no longer present
this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [existingAccessory]);
diff --git a/src/settings.ts b/src/settings.ts
index dd2eaeef..db0874e2 100644
--- a/src/settings.ts
+++ b/src/settings.ts
@@ -49,10 +49,10 @@ export interface devicesConfig extends device {
colorbulb?: colorbulb;
ble?: string;
hide_device?: boolean;
+ offline?: boolean;
}
export type meter = {
- unit?: number;
hide_temperature?: boolean;
hide_humidity?: boolean;
};
@@ -280,10 +280,7 @@ export type serviceData = {
//Humidifier's AutoMode
autoMode?: boolean;
//Meter Temperature Levels
- temperature?: {
- c: number,
- f: number
- };
+ temperature?: temperature;
// Fahrenheit enabled for Meter
fahrenheit: boolean;
// Humidity level for Meter
@@ -303,6 +300,11 @@ export type serviceData = {
position?: number;
};
+export type temperature = {
+ c: number;
+ f: number;
+};
+
export type switchbot = {
discover: (
arg0: