Integrated oznu's hapclient library.
This commit is contained in:
parent
b20d657674
commit
498b59bfef
649
package-lock.json
generated
649
package-lock.json
generated
@ -1,5 +1,652 @@
|
|||||||
{
|
{
|
||||||
"name": "homebridge-automation",
|
"name": "homebridge-automation",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"lockfileVersion": 1
|
"lockfileVersion": 1,
|
||||||
|
"requires": true,
|
||||||
|
"dependencies": {
|
||||||
|
"@babel/runtime-corejs2": {
|
||||||
|
"version": "7.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.5.5.tgz",
|
||||||
|
"integrity": "sha512-FYATQVR00NSNi7mUfpPDp7E8RYMXDuO8gaix7u/w3GekfUinKgX1AcTxs7SoiEmoEW9mbpjrwqWSW6zCmw5h8A==",
|
||||||
|
"requires": {
|
||||||
|
"core-js": "^2.6.5",
|
||||||
|
"regenerator-runtime": "^0.13.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/bluebird": {
|
||||||
|
"version": "3.5.27",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/bluebird/-/bluebird-3.5.27.tgz",
|
||||||
|
"integrity": "sha512-6BmYWSBea18+tSjjSC3QIyV93ZKAeNWGM7R6aYt1ryTZXrlHF+QLV0G2yV0viEGVyRkyQsWfMoJ0k/YghBX5sQ=="
|
||||||
|
},
|
||||||
|
"@types/bonjour": {
|
||||||
|
"version": "3.5.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.5.tgz",
|
||||||
|
"integrity": "sha512-4fHAqgL0SYHgDmdBrm201hUl7gIavk8KAtwBuDX9TjVdEZbUENdKmnago4GsmDO8QALMUE651F+nNpaCF+B4+A==",
|
||||||
|
"requires": {
|
||||||
|
"@types/node": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/caseless": {
|
||||||
|
"version": "0.12.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/caseless/-/caseless-0.12.2.tgz",
|
||||||
|
"integrity": "sha512-6ckxMjBBD8URvjB6J3NcnuAn5Pkl7t3TizAg+xdlzzQGSPSmBcXf8KoIH0ua/i+tio+ZRUHEXp0HEmvaR4kt0w=="
|
||||||
|
},
|
||||||
|
"@types/inflection": {
|
||||||
|
"version": "1.5.28",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/inflection/-/inflection-1.5.28.tgz",
|
||||||
|
"integrity": "sha1-Q9VeDXLPMzot/9nE7AQHRVobCTE="
|
||||||
|
},
|
||||||
|
"@types/node": {
|
||||||
|
"version": "12.7.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-12.7.3.tgz",
|
||||||
|
"integrity": "sha512-3SiLAIBkDWDg6vFo0+5YJyHPWU9uwu40Qe+v+0MH8wRKYBimHvvAOyk3EzMrD/TrIlLYfXrqDqrg913PynrMJQ=="
|
||||||
|
},
|
||||||
|
"@types/request": {
|
||||||
|
"version": "2.48.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/request/-/request-2.48.2.tgz",
|
||||||
|
"integrity": "sha512-gP+PSFXAXMrd5PcD7SqHeUjdGshAI8vKQ3+AvpQr3ht9iQea+59LOKvKITcQI+Lg+1EIkDP6AFSBUJPWG8GDyA==",
|
||||||
|
"requires": {
|
||||||
|
"@types/caseless": "*",
|
||||||
|
"@types/node": "*",
|
||||||
|
"@types/tough-cookie": "*",
|
||||||
|
"form-data": "^2.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/request-promise": {
|
||||||
|
"version": "4.1.44",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/request-promise/-/request-promise-4.1.44.tgz",
|
||||||
|
"integrity": "sha512-RId7eFsUKxfal1LirDDIcOp9u3MM3NXFDBcC3sqIMcmu7f4U6DsCEMD8RbLZtnPrQlN5Jc79di/WPsIEDO4keg==",
|
||||||
|
"requires": {
|
||||||
|
"@types/bluebird": "*",
|
||||||
|
"@types/request": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/request-promise-native": {
|
||||||
|
"version": "1.0.16",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/request-promise-native/-/request-promise-native-1.0.16.tgz",
|
||||||
|
"integrity": "sha512-gbLf6cg1XGBU8BObOgs5VkCQo5JFz2GstgZjyE4FRbig/jiCEdiynu2fCzJlw3qYPuoj59spKnvuRLN4PsMvhA==",
|
||||||
|
"requires": {
|
||||||
|
"@types/request": "*"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@types/tough-cookie": {
|
||||||
|
"version": "2.3.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/tough-cookie/-/tough-cookie-2.3.5.tgz",
|
||||||
|
"integrity": "sha512-SCcK7mvGi3+ZNz833RRjFIxrn4gI1PPR3NtuIS+6vMkvmsGjosqTJwRt5bAEFLRz+wtJMWv8+uOnZf2hi2QXTg=="
|
||||||
|
},
|
||||||
|
"ajv": {
|
||||||
|
"version": "6.10.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz",
|
||||||
|
"integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==",
|
||||||
|
"requires": {
|
||||||
|
"fast-deep-equal": "^2.0.1",
|
||||||
|
"fast-json-stable-stringify": "^2.0.0",
|
||||||
|
"json-schema-traverse": "^0.4.1",
|
||||||
|
"uri-js": "^4.2.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"array-flatten": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ=="
|
||||||
|
},
|
||||||
|
"asn1": {
|
||||||
|
"version": "0.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz",
|
||||||
|
"integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==",
|
||||||
|
"requires": {
|
||||||
|
"safer-buffer": "~2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"assert-plus": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
|
||||||
|
},
|
||||||
|
"asynckit": {
|
||||||
|
"version": "0.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
|
||||||
|
"integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k="
|
||||||
|
},
|
||||||
|
"aws-sign2": {
|
||||||
|
"version": "0.7.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||||
|
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
|
||||||
|
},
|
||||||
|
"aws4": {
|
||||||
|
"version": "1.8.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz",
|
||||||
|
"integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ=="
|
||||||
|
},
|
||||||
|
"bcrypt-pbkdf": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=",
|
||||||
|
"requires": {
|
||||||
|
"tweetnacl": "^0.14.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bonjour": {
|
||||||
|
"version": "3.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
|
||||||
|
"integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU=",
|
||||||
|
"requires": {
|
||||||
|
"array-flatten": "^2.1.0",
|
||||||
|
"deep-equal": "^1.0.1",
|
||||||
|
"dns-equal": "^1.0.0",
|
||||||
|
"dns-txt": "^2.0.2",
|
||||||
|
"multicast-dns": "^6.0.1",
|
||||||
|
"multicast-dns-service-types": "^1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"buffer-from": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
|
||||||
|
},
|
||||||
|
"buffer-indexof": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g=="
|
||||||
|
},
|
||||||
|
"caseless": {
|
||||||
|
"version": "0.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
|
||||||
|
"integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
|
||||||
|
},
|
||||||
|
"combined-stream": {
|
||||||
|
"version": "1.0.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
|
||||||
|
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
|
||||||
|
"requires": {
|
||||||
|
"delayed-stream": "~1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"core-js": {
|
||||||
|
"version": "2.6.9",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.9.tgz",
|
||||||
|
"integrity": "sha512-HOpZf6eXmnl7la+cUdMnLvUxKNqLUzJvgIziQ0DiF3JwSImNphIqdGqzj6hIKyX04MmV0poclQ7+wjWvxQyR2A=="
|
||||||
|
},
|
||||||
|
"core-util-is": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||||
|
"integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
|
||||||
|
},
|
||||||
|
"dashdash": {
|
||||||
|
"version": "1.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
|
||||||
|
"integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=",
|
||||||
|
"requires": {
|
||||||
|
"assert-plus": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"decamelize": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-4TgkVUsmmu7oCSyGBm5FvfMoACuoh9EOidm7V5/J2X2djAwwt57qb3F2KMP2ITqODTCSwb+YRV+0Zqrv18k/hw==",
|
||||||
|
"requires": {
|
||||||
|
"xregexp": "^4.2.4"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"deep-equal": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-ZbfWJq/wN1Z273o7mUSjILYqehAktR2NVoSrOukDkU9kg2v/Uv89yU4Cvz8seJeAmtN5oqiefKq8FPuXOboqLw==",
|
||||||
|
"requires": {
|
||||||
|
"is-arguments": "^1.0.4",
|
||||||
|
"is-date-object": "^1.0.1",
|
||||||
|
"is-regex": "^1.0.4",
|
||||||
|
"object-is": "^1.0.1",
|
||||||
|
"object-keys": "^1.1.1",
|
||||||
|
"regexp.prototype.flags": "^1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"define-properties": {
|
||||||
|
"version": "1.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
|
||||||
|
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
|
||||||
|
"requires": {
|
||||||
|
"object-keys": "^1.0.12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"delayed-stream": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk="
|
||||||
|
},
|
||||||
|
"dns-equal": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0="
|
||||||
|
},
|
||||||
|
"dns-packet": {
|
||||||
|
"version": "1.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz",
|
||||||
|
"integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==",
|
||||||
|
"requires": {
|
||||||
|
"ip": "^1.1.0",
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"dns-txt": {
|
||||||
|
"version": "2.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
|
||||||
|
"integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY=",
|
||||||
|
"requires": {
|
||||||
|
"buffer-indexof": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ecc-jsbn": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
|
||||||
|
"integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=",
|
||||||
|
"requires": {
|
||||||
|
"jsbn": "~0.1.0",
|
||||||
|
"safer-buffer": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extend": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
|
||||||
|
},
|
||||||
|
"extsprintf": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
|
||||||
|
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
|
||||||
|
},
|
||||||
|
"fast-deep-equal": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz",
|
||||||
|
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk="
|
||||||
|
},
|
||||||
|
"fast-json-stable-stringify": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I="
|
||||||
|
},
|
||||||
|
"forever-agent": {
|
||||||
|
"version": "0.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
|
||||||
|
"integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE="
|
||||||
|
},
|
||||||
|
"form-data": {
|
||||||
|
"version": "2.5.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.5.1.tgz",
|
||||||
|
"integrity": "sha512-m21N3WOmEEURgk6B9GLOE4RuWOFf28Lhh9qGYeNlGq4VDXUlJy2th2slBNU8Gp8EzloYZOibZJ7t5ecIrFSjVA==",
|
||||||
|
"requires": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.6",
|
||||||
|
"mime-types": "^2.1.12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"function-bind": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
||||||
|
},
|
||||||
|
"getpass": {
|
||||||
|
"version": "0.1.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
|
||||||
|
"integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=",
|
||||||
|
"requires": {
|
||||||
|
"assert-plus": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"har-schema": {
|
||||||
|
"version": "2.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
|
||||||
|
"integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI="
|
||||||
|
},
|
||||||
|
"har-validator": {
|
||||||
|
"version": "5.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.3.tgz",
|
||||||
|
"integrity": "sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g==",
|
||||||
|
"requires": {
|
||||||
|
"ajv": "^6.5.5",
|
||||||
|
"har-schema": "^2.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"has": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
||||||
|
"requires": {
|
||||||
|
"function-bind": "^1.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"http-signature": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||||
|
"integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=",
|
||||||
|
"requires": {
|
||||||
|
"assert-plus": "^1.0.0",
|
||||||
|
"jsprim": "^1.2.2",
|
||||||
|
"sshpk": "^1.7.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"inflection": {
|
||||||
|
"version": "1.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz",
|
||||||
|
"integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY="
|
||||||
|
},
|
||||||
|
"ip": {
|
||||||
|
"version": "1.1.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
|
||||||
|
"integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo="
|
||||||
|
},
|
||||||
|
"is-arguments": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA=="
|
||||||
|
},
|
||||||
|
"is-date-object": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY="
|
||||||
|
},
|
||||||
|
"is-regex": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
|
||||||
|
"integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
|
||||||
|
"requires": {
|
||||||
|
"has": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"is-typedarray": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
|
||||||
|
"integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo="
|
||||||
|
},
|
||||||
|
"isstream": {
|
||||||
|
"version": "0.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
|
||||||
|
"integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo="
|
||||||
|
},
|
||||||
|
"jsbn": {
|
||||||
|
"version": "0.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
|
||||||
|
"integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM="
|
||||||
|
},
|
||||||
|
"json-schema": {
|
||||||
|
"version": "0.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz",
|
||||||
|
"integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM="
|
||||||
|
},
|
||||||
|
"json-schema-traverse": {
|
||||||
|
"version": "0.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
|
||||||
|
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
|
||||||
|
},
|
||||||
|
"json-stringify-safe": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
|
||||||
|
"integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus="
|
||||||
|
},
|
||||||
|
"jsprim": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz",
|
||||||
|
"integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=",
|
||||||
|
"requires": {
|
||||||
|
"assert-plus": "1.0.0",
|
||||||
|
"extsprintf": "1.3.0",
|
||||||
|
"json-schema": "0.2.3",
|
||||||
|
"verror": "1.10.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"lodash": {
|
||||||
|
"version": "4.17.15",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz",
|
||||||
|
"integrity": "sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A=="
|
||||||
|
},
|
||||||
|
"mime-db": {
|
||||||
|
"version": "1.40.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.40.0.tgz",
|
||||||
|
"integrity": "sha512-jYdeOMPy9vnxEqFRRo6ZvTZ8d9oPb+k18PKoYNYUe2stVEBPPwsln/qWzdbmaIvnhZ9v2P+CuecK+fpUfsV2mA=="
|
||||||
|
},
|
||||||
|
"mime-types": {
|
||||||
|
"version": "2.1.24",
|
||||||
|
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.24.tgz",
|
||||||
|
"integrity": "sha512-WaFHS3MCl5fapm3oLxU4eYDw77IQM2ACcxQ9RIxfaC3ooc6PFuBMGZZsYpvoXS5D5QTWPieo1jjLdAm3TBP3cQ==",
|
||||||
|
"requires": {
|
||||||
|
"mime-db": "1.40.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"multicast-dns": {
|
||||||
|
"version": "6.2.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz",
|
||||||
|
"integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==",
|
||||||
|
"requires": {
|
||||||
|
"dns-packet": "^1.3.1",
|
||||||
|
"thunky": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"multicast-dns-service-types": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
|
||||||
|
"integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE="
|
||||||
|
},
|
||||||
|
"oauth-sign": {
|
||||||
|
"version": "0.9.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
|
||||||
|
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ=="
|
||||||
|
},
|
||||||
|
"object-is": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/object-is/-/object-is-1.0.1.tgz",
|
||||||
|
"integrity": "sha1-CqYOyZiaCz7Xlc9NBvYs8a1lObY="
|
||||||
|
},
|
||||||
|
"object-keys": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
|
||||||
|
},
|
||||||
|
"performance-now": {
|
||||||
|
"version": "2.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
|
||||||
|
"integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns="
|
||||||
|
},
|
||||||
|
"psl": {
|
||||||
|
"version": "1.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/psl/-/psl-1.3.0.tgz",
|
||||||
|
"integrity": "sha512-avHdspHO+9rQTLbv1RO+MPYeP/SzsCoxofjVnHanETfQhTJrmB0HlDoW+EiN/R+C0BZ+gERab9NY0lPN2TxNag=="
|
||||||
|
},
|
||||||
|
"punycode": {
|
||||||
|
"version": "2.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
|
||||||
|
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
|
||||||
|
},
|
||||||
|
"qs": {
|
||||||
|
"version": "6.5.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
|
||||||
|
"integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA=="
|
||||||
|
},
|
||||||
|
"regenerator-runtime": {
|
||||||
|
"version": "0.13.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.3.tgz",
|
||||||
|
"integrity": "sha512-naKIZz2GQ8JWh///G7L3X6LaQUAMp2lvb1rvwwsURe/VXwD6VMfr+/1NuNw3ag8v2kY1aQ/go5SNn79O9JU7yw=="
|
||||||
|
},
|
||||||
|
"regexp.prototype.flags": {
|
||||||
|
"version": "1.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.2.0.tgz",
|
||||||
|
"integrity": "sha512-ztaw4M1VqgMwl9HlPpOuiYgItcHlunW0He2fE6eNfT6E/CF2FtYi9ofOYe4mKntstYk0Fyh/rDRBdS3AnxjlrA==",
|
||||||
|
"requires": {
|
||||||
|
"define-properties": "^1.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"request": {
|
||||||
|
"version": "2.88.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz",
|
||||||
|
"integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==",
|
||||||
|
"requires": {
|
||||||
|
"aws-sign2": "~0.7.0",
|
||||||
|
"aws4": "^1.8.0",
|
||||||
|
"caseless": "~0.12.0",
|
||||||
|
"combined-stream": "~1.0.6",
|
||||||
|
"extend": "~3.0.2",
|
||||||
|
"forever-agent": "~0.6.1",
|
||||||
|
"form-data": "~2.3.2",
|
||||||
|
"har-validator": "~5.1.0",
|
||||||
|
"http-signature": "~1.2.0",
|
||||||
|
"is-typedarray": "~1.0.0",
|
||||||
|
"isstream": "~0.1.2",
|
||||||
|
"json-stringify-safe": "~5.0.1",
|
||||||
|
"mime-types": "~2.1.19",
|
||||||
|
"oauth-sign": "~0.9.0",
|
||||||
|
"performance-now": "^2.1.0",
|
||||||
|
"qs": "~6.5.2",
|
||||||
|
"safe-buffer": "^5.1.2",
|
||||||
|
"tough-cookie": "~2.4.3",
|
||||||
|
"tunnel-agent": "^0.6.0",
|
||||||
|
"uuid": "^3.3.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"form-data": {
|
||||||
|
"version": "2.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
|
||||||
|
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
|
||||||
|
"requires": {
|
||||||
|
"asynckit": "^0.4.0",
|
||||||
|
"combined-stream": "^1.0.6",
|
||||||
|
"mime-types": "^2.1.12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"punycode": {
|
||||||
|
"version": "1.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
|
||||||
|
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
|
||||||
|
},
|
||||||
|
"tough-cookie": {
|
||||||
|
"version": "2.4.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz",
|
||||||
|
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==",
|
||||||
|
"requires": {
|
||||||
|
"psl": "^1.1.24",
|
||||||
|
"punycode": "^1.4.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"request-promise-core": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/request-promise-core/-/request-promise-core-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-UHYyq1MO8GsefGEt7EprS8UrXsm1TxEvFUX1IMTuSLU2Rh7fTIdFtl8xD7JiEYiWU2dl+NYAjCTksTehQUxPag==",
|
||||||
|
"requires": {
|
||||||
|
"lodash": "^4.17.11"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"request-promise-native": {
|
||||||
|
"version": "1.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/request-promise-native/-/request-promise-native-1.0.7.tgz",
|
||||||
|
"integrity": "sha512-rIMnbBdgNViL37nZ1b3L/VfPOpSi0TqVDQPAvO6U14lMzOLrt5nilxCQqtDKhZeDiW0/hkCXGoQjhgJd/tCh6w==",
|
||||||
|
"requires": {
|
||||||
|
"request-promise-core": "1.1.2",
|
||||||
|
"stealthy-require": "^1.1.1",
|
||||||
|
"tough-cookie": "^2.3.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"safe-buffer": {
|
||||||
|
"version": "5.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz",
|
||||||
|
"integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg=="
|
||||||
|
},
|
||||||
|
"safer-buffer": {
|
||||||
|
"version": "2.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||||
|
},
|
||||||
|
"source-map": {
|
||||||
|
"version": "0.6.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
|
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
||||||
|
},
|
||||||
|
"source-map-support": {
|
||||||
|
"version": "0.5.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
|
||||||
|
"integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
|
||||||
|
"requires": {
|
||||||
|
"buffer-from": "^1.0.0",
|
||||||
|
"source-map": "^0.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"sshpk": {
|
||||||
|
"version": "1.16.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
|
||||||
|
"integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
|
||||||
|
"requires": {
|
||||||
|
"asn1": "~0.2.3",
|
||||||
|
"assert-plus": "^1.0.0",
|
||||||
|
"bcrypt-pbkdf": "^1.0.0",
|
||||||
|
"dashdash": "^1.12.0",
|
||||||
|
"ecc-jsbn": "~0.1.1",
|
||||||
|
"getpass": "^0.1.1",
|
||||||
|
"jsbn": "~0.1.0",
|
||||||
|
"safer-buffer": "^2.0.2",
|
||||||
|
"tweetnacl": "~0.14.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"stealthy-require": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz",
|
||||||
|
"integrity": "sha1-NbCYdbT/SfJqd35QmzCQoyJr8ks="
|
||||||
|
},
|
||||||
|
"thunky": {
|
||||||
|
"version": "1.0.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/thunky/-/thunky-1.0.3.tgz",
|
||||||
|
"integrity": "sha512-YwT8pjmNcAXBZqrubu22P4FYsh2D4dxRmnWBOL8Jk8bUcRUtc5326kx32tuTmFDAZtLOGEVNl8POAR8j896Iow=="
|
||||||
|
},
|
||||||
|
"tough-cookie": {
|
||||||
|
"version": "2.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
|
||||||
|
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
|
||||||
|
"requires": {
|
||||||
|
"psl": "^1.1.28",
|
||||||
|
"punycode": "^2.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tunnel-agent": {
|
||||||
|
"version": "0.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
|
||||||
|
"integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=",
|
||||||
|
"requires": {
|
||||||
|
"safe-buffer": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tweetnacl": {
|
||||||
|
"version": "0.14.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||||
|
"integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q="
|
||||||
|
},
|
||||||
|
"uri-js": {
|
||||||
|
"version": "4.2.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz",
|
||||||
|
"integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==",
|
||||||
|
"requires": {
|
||||||
|
"punycode": "^2.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uuid": {
|
||||||
|
"version": "3.3.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz",
|
||||||
|
"integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ=="
|
||||||
|
},
|
||||||
|
"verror": {
|
||||||
|
"version": "1.10.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
|
||||||
|
"integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=",
|
||||||
|
"requires": {
|
||||||
|
"assert-plus": "^1.0.0",
|
||||||
|
"core-util-is": "1.0.2",
|
||||||
|
"extsprintf": "^1.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"xregexp": {
|
||||||
|
"version": "4.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.2.4.tgz",
|
||||||
|
"integrity": "sha512-sO0bYdYeJAJBcJA8g7MJJX7UrOZIfJPd8U2SC7B2Dd/J24U0aQNoGp33shCaBSWeb0rD5rh6VBUIXOkGal1TZA==",
|
||||||
|
"requires": {
|
||||||
|
"@babel/runtime-corejs2": "^7.2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
13
package.json
13
package.json
@ -22,5 +22,16 @@
|
|||||||
],
|
],
|
||||||
"author": "Brandon Watson",
|
"author": "Brandon Watson",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {}
|
"dependencies": {
|
||||||
|
"@types/bonjour": "^3.5.5",
|
||||||
|
"@types/inflection": "^1.5.28",
|
||||||
|
"@types/request-promise": "^4.1.44",
|
||||||
|
"@types/request-promise-native": "^1.0.16",
|
||||||
|
"bonjour": "^3.5.0",
|
||||||
|
"decamelize": "^3.2.0",
|
||||||
|
"inflection": "^1.12.0",
|
||||||
|
"request": "^2.88.0",
|
||||||
|
"request-promise-native": "^1.0.7",
|
||||||
|
"source-map-support": "^0.5.13"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
298
src/3rdParty/HapClient/eventedHttpClient/httpParser.ts
vendored
Executable file
298
src/3rdParty/HapClient/eventedHttpClient/httpParser.ts
vendored
Executable file
@ -0,0 +1,298 @@
|
|||||||
|
/**
|
||||||
|
* The contents in this file were taken from NorthernMan54/Hap-Node-Client
|
||||||
|
* https://raw.githubusercontent.com/NorthernMan54/Hap-Node-Client/master/lib/httpParser.js
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Borrowed and heaviliy modifed from https://github.com/miguelmota/http-message-parser
|
||||||
|
|
||||||
|
import { Buffer } from 'buffer';
|
||||||
|
import { Dictionary } from '../../../Types/types';
|
||||||
|
|
||||||
|
interface httpResult {
|
||||||
|
protocol?: string,
|
||||||
|
httpVersion?: number,
|
||||||
|
statusCode?: number,
|
||||||
|
statusMessage?: string,
|
||||||
|
method?: string,
|
||||||
|
url?: string,
|
||||||
|
headers?: Dictionary<string | number>,
|
||||||
|
body?: any,
|
||||||
|
boundary?: any,
|
||||||
|
multipart?: any,
|
||||||
|
additional?: any,
|
||||||
|
meta?: any
|
||||||
|
}
|
||||||
|
|
||||||
|
function httpMessageParser(message: any) {
|
||||||
|
const result: httpResult = {}
|
||||||
|
|
||||||
|
let messageString = '';
|
||||||
|
let headerNewlineIndex = 0;
|
||||||
|
let fullBoundary: any = null;
|
||||||
|
|
||||||
|
if (httpMessageParser._isBuffer(message)) {
|
||||||
|
messageString = message.toString();
|
||||||
|
} else if (typeof message === 'string') {
|
||||||
|
messageString = message;
|
||||||
|
message = new Buffer(messageString);
|
||||||
|
} else {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Strip extra return characters
|
||||||
|
*/
|
||||||
|
messageString = messageString.replace(/\r\n/gim, '\n');
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Trim leading whitespace
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
const firstNonWhitespaceRegex = /[\w-]+/gim;
|
||||||
|
const firstNonWhitespaceIndex = messageString.search(firstNonWhitespaceRegex);
|
||||||
|
if (firstNonWhitespaceIndex > 0) {
|
||||||
|
message = message.slice(firstNonWhitespaceIndex, message.length);
|
||||||
|
messageString = message.toString();
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
/* Parse request line
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
const possibleRequestLine = messageString.split(/\n|\r\n/)[0];
|
||||||
|
const requestLineMatch = possibleRequestLine.match(httpMessageParser._requestLineRegex);
|
||||||
|
|
||||||
|
if (Array.isArray(requestLineMatch) && requestLineMatch.length > 1) {
|
||||||
|
result.protocol = requestLineMatch[1];
|
||||||
|
result.httpVersion = parseFloat(requestLineMatch[2]);
|
||||||
|
result.statusCode = parseInt(requestLineMatch[3], 10);
|
||||||
|
result.statusMessage = requestLineMatch[4];
|
||||||
|
} else {
|
||||||
|
const responseLineMath = possibleRequestLine.match(httpMessageParser._responseLineRegex);
|
||||||
|
if (Array.isArray(responseLineMath) && responseLineMath.length > 1) {
|
||||||
|
result.method = responseLineMath[1];
|
||||||
|
result.url = responseLineMath[2];
|
||||||
|
result.httpVersion = parseFloat(responseLineMath[3]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
/* Parse headers
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
headerNewlineIndex = messageString.search(httpMessageParser._headerNewlineRegex);
|
||||||
|
if (headerNewlineIndex > -1) {
|
||||||
|
headerNewlineIndex = headerNewlineIndex + 1; // 1 for newline length
|
||||||
|
} else {
|
||||||
|
/* There's no line breaks so check if request line exists
|
||||||
|
* because the message might be all headers and no body
|
||||||
|
*/
|
||||||
|
if (result.httpVersion) {
|
||||||
|
headerNewlineIndex = messageString.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const headersString = messageString.substr(0, headerNewlineIndex);
|
||||||
|
const headers = httpMessageParser._parseHeaders(headersString);
|
||||||
|
|
||||||
|
if (Object.keys(headers).length > 0) {
|
||||||
|
result.headers = headers;
|
||||||
|
|
||||||
|
// TOOD: extract boundary.
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
/* Try to get boundary if no boundary header
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
if (!result.boundary) {
|
||||||
|
const boundaryMatch = messageString.match(httpMessageParser._boundaryRegex);
|
||||||
|
|
||||||
|
if (Array.isArray(boundaryMatch) && boundaryMatch.length) {
|
||||||
|
fullBoundary = boundaryMatch[0].replace(/[\r\n]+/gi, '');
|
||||||
|
const boundary = fullBoundary.replace(/^--/, '');
|
||||||
|
result.boundary = boundary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
/* Parse body
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
let start = headerNewlineIndex;
|
||||||
|
let contentLength: number = result.headers!['Content-Length'] as number;
|
||||||
|
|
||||||
|
let end = (result.headers && result.headers['Content-Length'] && contentLength ? contentLength + start : messageString.length);
|
||||||
|
|
||||||
|
const firstBoundaryIndex = messageString.indexOf(fullBoundary);
|
||||||
|
|
||||||
|
if (firstBoundaryIndex > -1 && result.boundary) {
|
||||||
|
start = headerNewlineIndex;
|
||||||
|
end = firstBoundaryIndex;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (headerNewlineIndex > -1) {
|
||||||
|
const body = messageString.slice(start, end);
|
||||||
|
result.additional = messageString.slice(end); // Pass back any unparsed data for running thru again
|
||||||
|
// console.log("Lengths: total %s -> start %s -> end %s -> final %s", messageString.length, start, end, body.length);
|
||||||
|
|
||||||
|
if (body && body.length) {
|
||||||
|
if ((result.headers && result.headers['Content-Type'] === 'application/hap+json') ||
|
||||||
|
(result.headers && result.headers['Content-Type'] === 'application/json')) {
|
||||||
|
// JSON.parse JSON message's
|
||||||
|
try {
|
||||||
|
if (result.headers['Content-Length']) {
|
||||||
|
result.body = body;
|
||||||
|
} else {
|
||||||
|
result.body = body.split('\n')[1];
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
result.body = body;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
/* Parse multipart sections
|
||||||
|
*/
|
||||||
|
(function () {
|
||||||
|
if (result.boundary) {
|
||||||
|
const multipartStart = messageString.indexOf(fullBoundary) + fullBoundary.length;
|
||||||
|
const multipartEnd = messageString.lastIndexOf(fullBoundary);
|
||||||
|
const multipartBody = messageString.substr(multipartStart, multipartEnd);
|
||||||
|
const splitRegex = new RegExp('^' + fullBoundary + '.*[\n\r]?$', 'gm');
|
||||||
|
const parts = multipartBody.split(splitRegex);
|
||||||
|
|
||||||
|
result.multipart = parts.filter(httpMessageParser._isTruthy).map(function (part, i) {
|
||||||
|
// tslint:disable-next-line: no-shadowed-variable
|
||||||
|
const result: httpResult = {};
|
||||||
|
|
||||||
|
const newlineRegex = /\n\n|\r\n\r\n/gim;
|
||||||
|
let newlineIndex = 0;
|
||||||
|
let newlineMatch = newlineRegex.exec(part);
|
||||||
|
let body = null;
|
||||||
|
|
||||||
|
if (newlineMatch) {
|
||||||
|
newlineIndex = newlineMatch.index;
|
||||||
|
if (newlineMatch.index <= 0) {
|
||||||
|
newlineMatch = newlineRegex.exec(part);
|
||||||
|
if (newlineMatch) {
|
||||||
|
newlineIndex = newlineMatch.index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const possibleHeadersString = part.substr(0, newlineIndex);
|
||||||
|
|
||||||
|
let startOffset = null;
|
||||||
|
let endOffset = null;
|
||||||
|
|
||||||
|
if (newlineIndex > -1) {
|
||||||
|
const headers = httpMessageParser._parseHeaders(possibleHeadersString);
|
||||||
|
if (Object.keys(headers).length > 0) {
|
||||||
|
result.headers = headers;
|
||||||
|
|
||||||
|
const boundaryIndexes: Array<number> = [];
|
||||||
|
for (let j = 0; j >= 0;) {
|
||||||
|
j = message.indexOf(fullBoundary, j);
|
||||||
|
|
||||||
|
if (j >= 0) {
|
||||||
|
boundaryIndexes.push(j);
|
||||||
|
j += fullBoundary.length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const boundaryNewlineIndexes: Array<number> = [];
|
||||||
|
boundaryIndexes.slice(0, boundaryIndexes.length - 1).forEach(function (m, k) {
|
||||||
|
const partBody = message.slice(boundaryIndexes[k], boundaryIndexes[k + 1]).toString();
|
||||||
|
// tslint:disable-next-line: no-shadowed-variable
|
||||||
|
let headerNewlineIndex = partBody.search(/\n\n|\r\n\r\n/gim) + 2;
|
||||||
|
headerNewlineIndex = boundaryIndexes[k] + headerNewlineIndex;
|
||||||
|
boundaryNewlineIndexes.push(headerNewlineIndex);
|
||||||
|
});
|
||||||
|
|
||||||
|
startOffset = boundaryNewlineIndexes[i];
|
||||||
|
endOffset = boundaryIndexes[i + 1];
|
||||||
|
body = message.slice(startOffset, endOffset);
|
||||||
|
} else {
|
||||||
|
body = part;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
body = part;
|
||||||
|
}
|
||||||
|
|
||||||
|
result.body = body;
|
||||||
|
result.meta.body.byteOffset.start = startOffset;
|
||||||
|
result.meta.body.byteOffset.end = endOffset;
|
||||||
|
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
httpMessageParser._isTruthy = function _isTruthy(value: any) {
|
||||||
|
return !!value;
|
||||||
|
};
|
||||||
|
|
||||||
|
httpMessageParser._isNumeric = function _isNumeric(value: any) {
|
||||||
|
if (typeof value === 'number' && !isNaN(value)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
value = (value || '').toString().trim();
|
||||||
|
|
||||||
|
if (!value) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return !isNaN(value);
|
||||||
|
};
|
||||||
|
|
||||||
|
httpMessageParser._isBuffer = function (item: any) {
|
||||||
|
return ((httpMessageParser._isNodeBufferSupported() &&
|
||||||
|
typeof global === 'object' &&
|
||||||
|
global.Buffer.isBuffer(item)) ||
|
||||||
|
(item instanceof Object &&
|
||||||
|
item._isBuffer));
|
||||||
|
};
|
||||||
|
|
||||||
|
httpMessageParser._isNodeBufferSupported = function () {
|
||||||
|
return (typeof global === 'object' &&
|
||||||
|
typeof global.Buffer === 'function' &&
|
||||||
|
typeof global.Buffer.isBuffer === 'function');
|
||||||
|
};
|
||||||
|
|
||||||
|
httpMessageParser._parseHeaders = function _parseHeaders(body: any) {
|
||||||
|
const headers: Dictionary<string | number> = {};
|
||||||
|
|
||||||
|
if (typeof body !== 'string') {
|
||||||
|
return headers;
|
||||||
|
}
|
||||||
|
|
||||||
|
body.split(/[\r\n]/).forEach(function (string) {
|
||||||
|
const match = string.match(/([\w-]+):\s*(.*)/i);
|
||||||
|
|
||||||
|
if (Array.isArray(match) && match.length === 3) {
|
||||||
|
const key = match[1];
|
||||||
|
const value = match[2];
|
||||||
|
|
||||||
|
headers[key] = httpMessageParser._isNumeric(value) ? Number(value) : value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return headers;
|
||||||
|
};
|
||||||
|
|
||||||
|
httpMessageParser._requestLineRegex = /(HTTP|EVENT)\/(1\.0|1\.1|2\.0)\s+(\d+)\s+([\w\s-_]+)/i;
|
||||||
|
httpMessageParser._responseLineRegex = /(GET|POST|PUT|DELETE|PATCH|OPTIONS|HEAD|TRACE|CONNECT)\s+(.*)\s+HTTP\/(1\.0|1\.1|2\.0)/i;
|
||||||
|
// httpMessageParser._headerNewlineRegex = /^[\r\n]+/gim;
|
||||||
|
httpMessageParser._headerNewlineRegex = /^[\r\n]+/gim;
|
||||||
|
httpMessageParser._boundaryRegex = /(\n|\r\n)+--[\w-]+(\n|\r\n)+/g;
|
||||||
|
|
||||||
|
export default httpMessageParser;
|
59
src/3rdParty/HapClient/eventedHttpClient/index.ts
vendored
Executable file
59
src/3rdParty/HapClient/eventedHttpClient/index.ts
vendored
Executable file
@ -0,0 +1,59 @@
|
|||||||
|
/**
|
||||||
|
* The contents in this file were taken from NorthernMan54/Hap-Node-Client
|
||||||
|
* https://github.com/NorthernMan54/Hap-Node-Client/blob/master/lib/eventedHttpClient.js
|
||||||
|
*/
|
||||||
|
|
||||||
|
import * as net from 'net';
|
||||||
|
import * as url from 'url';
|
||||||
|
import httpMessageParser from './/httpParser';
|
||||||
|
import { Dictionary } from '../../../Types/types';
|
||||||
|
|
||||||
|
export const parseMessage = httpMessageParser;
|
||||||
|
|
||||||
|
export function createConnection(instance: { ipAddress: string, port: number }, pin: string, body: any) {
|
||||||
|
const client = net.createConnection({
|
||||||
|
host: instance.ipAddress,
|
||||||
|
port: instance.port,
|
||||||
|
});
|
||||||
|
|
||||||
|
client.write(_buildMessage({
|
||||||
|
method: 'PUT',
|
||||||
|
url: 'http://' + instance.ipAddress + ':' + instance.port + '/characteristics',
|
||||||
|
maxAttempts: 1, // (default) try 5 times
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'Application/json',
|
||||||
|
'authorization': pin,
|
||||||
|
'connection': 'keep-alive'
|
||||||
|
},
|
||||||
|
body: JSON.stringify(body)
|
||||||
|
}));
|
||||||
|
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _headersToString(headers: Dictionary<string>) {
|
||||||
|
let response = '';
|
||||||
|
|
||||||
|
for (const header of Object.keys(headers)) {
|
||||||
|
response = response + header + ': ' + headers[header] + '\r\n';
|
||||||
|
}
|
||||||
|
return (response);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _buildMessage(request: any) {
|
||||||
|
const context = url.parse(request.url);
|
||||||
|
let message;
|
||||||
|
|
||||||
|
message = request.method + ' ' + context.pathname;
|
||||||
|
if (context.search) {
|
||||||
|
message = message + context.search;
|
||||||
|
}
|
||||||
|
message = message + ' HTTP/1.1\r\nHost: ' + context.host + '\r\n' + _headersToString(request.headers);
|
||||||
|
if (request.body) {
|
||||||
|
message = message + 'Content-Length: ' + request.body.length + '\r\n\r\n' + request.body + '\r\n\r\n';
|
||||||
|
} else {
|
||||||
|
message = message + '\r\n\r\n';
|
||||||
|
}
|
||||||
|
// debug("Message ->", message);
|
||||||
|
return (message);
|
||||||
|
}
|
378
src/3rdParty/HapClient/hap-types.ts
vendored
Executable file
378
src/3rdParty/HapClient/hap-types.ts
vendored
Executable file
@ -0,0 +1,378 @@
|
|||||||
|
import { Dictionary } from "../../Types/types";
|
||||||
|
|
||||||
|
/* This file is automatically generated */
|
||||||
|
|
||||||
|
export const Services: Dictionary<string> = {
|
||||||
|
'0000003E-0000-1000-8000-0026BB765291': 'AccessoryInformation',
|
||||||
|
'AccessoryInformation': '0000003E-0000-1000-8000-0026BB765291',
|
||||||
|
'000000BB-0000-1000-8000-0026BB765291': 'AirPurifier',
|
||||||
|
'AirPurifier': '000000BB-0000-1000-8000-0026BB765291',
|
||||||
|
'0000008D-0000-1000-8000-0026BB765291': 'AirQualitySensor',
|
||||||
|
'AirQualitySensor': '0000008D-0000-1000-8000-0026BB765291',
|
||||||
|
'00000096-0000-1000-8000-0026BB765291': 'BatteryService',
|
||||||
|
'BatteryService': '00000096-0000-1000-8000-0026BB765291',
|
||||||
|
'00000110-0000-1000-8000-0026BB765291': 'CameraRTPStreamManagement',
|
||||||
|
'CameraRTPStreamManagement': '00000110-0000-1000-8000-0026BB765291',
|
||||||
|
'00000097-0000-1000-8000-0026BB765291': 'CarbonDioxideSensor',
|
||||||
|
'CarbonDioxideSensor': '00000097-0000-1000-8000-0026BB765291',
|
||||||
|
'0000007F-0000-1000-8000-0026BB765291': 'CarbonMonoxideSensor',
|
||||||
|
'CarbonMonoxideSensor': '0000007F-0000-1000-8000-0026BB765291',
|
||||||
|
'00000080-0000-1000-8000-0026BB765291': 'ContactSensor',
|
||||||
|
'ContactSensor': '00000080-0000-1000-8000-0026BB765291',
|
||||||
|
'00000081-0000-1000-8000-0026BB765291': 'Door',
|
||||||
|
'Door': '00000081-0000-1000-8000-0026BB765291',
|
||||||
|
'00000121-0000-1000-8000-0026BB765291': 'Doorbell',
|
||||||
|
'Doorbell': '00000121-0000-1000-8000-0026BB765291',
|
||||||
|
'00000040-0000-1000-8000-0026BB765291': 'Fan',
|
||||||
|
'Fan': '00000040-0000-1000-8000-0026BB765291',
|
||||||
|
'000000B7-0000-1000-8000-0026BB765291': 'Fanv2',
|
||||||
|
'Fanv2': '000000B7-0000-1000-8000-0026BB765291',
|
||||||
|
'000000BA-0000-1000-8000-0026BB765291': 'FilterMaintenance',
|
||||||
|
'FilterMaintenance': '000000BA-0000-1000-8000-0026BB765291',
|
||||||
|
'000000D7-0000-1000-8000-0026BB765291': 'Faucet',
|
||||||
|
'Faucet': '000000D7-0000-1000-8000-0026BB765291',
|
||||||
|
'00000041-0000-1000-8000-0026BB765291': 'GarageDoorOpener',
|
||||||
|
'GarageDoorOpener': '00000041-0000-1000-8000-0026BB765291',
|
||||||
|
'000000BC-0000-1000-8000-0026BB765291': 'HeaterCooler',
|
||||||
|
'HeaterCooler': '000000BC-0000-1000-8000-0026BB765291',
|
||||||
|
'000000BD-0000-1000-8000-0026BB765291': 'HumidifierDehumidifier',
|
||||||
|
'HumidifierDehumidifier': '000000BD-0000-1000-8000-0026BB765291',
|
||||||
|
'00000082-0000-1000-8000-0026BB765291': 'HumiditySensor',
|
||||||
|
'HumiditySensor': '00000082-0000-1000-8000-0026BB765291',
|
||||||
|
'000000CF-0000-1000-8000-0026BB765291': 'IrrigationSystem',
|
||||||
|
'IrrigationSystem': '000000CF-0000-1000-8000-0026BB765291',
|
||||||
|
'00000083-0000-1000-8000-0026BB765291': 'LeakSensor',
|
||||||
|
'LeakSensor': '00000083-0000-1000-8000-0026BB765291',
|
||||||
|
'00000084-0000-1000-8000-0026BB765291': 'LightSensor',
|
||||||
|
'LightSensor': '00000084-0000-1000-8000-0026BB765291',
|
||||||
|
'00000043-0000-1000-8000-0026BB765291': 'Lightbulb',
|
||||||
|
'Lightbulb': '00000043-0000-1000-8000-0026BB765291',
|
||||||
|
'00000044-0000-1000-8000-0026BB765291': 'LockManagement',
|
||||||
|
'LockManagement': '00000044-0000-1000-8000-0026BB765291',
|
||||||
|
'00000045-0000-1000-8000-0026BB765291': 'LockMechanism',
|
||||||
|
'LockMechanism': '00000045-0000-1000-8000-0026BB765291',
|
||||||
|
'00000112-0000-1000-8000-0026BB765291': 'Microphone',
|
||||||
|
'Microphone': '00000112-0000-1000-8000-0026BB765291',
|
||||||
|
'00000085-0000-1000-8000-0026BB765291': 'MotionSensor',
|
||||||
|
'MotionSensor': '00000085-0000-1000-8000-0026BB765291',
|
||||||
|
'00000086-0000-1000-8000-0026BB765291': 'OccupancySensor',
|
||||||
|
'OccupancySensor': '00000086-0000-1000-8000-0026BB765291',
|
||||||
|
'00000047-0000-1000-8000-0026BB765291': 'Outlet',
|
||||||
|
'Outlet': '00000047-0000-1000-8000-0026BB765291',
|
||||||
|
'0000007E-0000-1000-8000-0026BB765291': 'SecuritySystem',
|
||||||
|
'SecuritySystem': '0000007E-0000-1000-8000-0026BB765291',
|
||||||
|
'000000CC-0000-1000-8000-0026BB765291': 'ServiceLabel',
|
||||||
|
'ServiceLabel': '000000CC-0000-1000-8000-0026BB765291',
|
||||||
|
'000000B9-0000-1000-8000-0026BB765291': 'Slat',
|
||||||
|
'Slat': '000000B9-0000-1000-8000-0026BB765291',
|
||||||
|
'00000087-0000-1000-8000-0026BB765291': 'SmokeSensor',
|
||||||
|
'SmokeSensor': '00000087-0000-1000-8000-0026BB765291',
|
||||||
|
'00000113-0000-1000-8000-0026BB765291': 'Speaker',
|
||||||
|
'Speaker': '00000113-0000-1000-8000-0026BB765291',
|
||||||
|
'00000089-0000-1000-8000-0026BB765291': 'StatelessProgrammableSwitch',
|
||||||
|
'StatelessProgrammableSwitch': '00000089-0000-1000-8000-0026BB765291',
|
||||||
|
'00000049-0000-1000-8000-0026BB765291': 'Switch',
|
||||||
|
'Switch': '00000049-0000-1000-8000-0026BB765291',
|
||||||
|
'0000008A-0000-1000-8000-0026BB765291': 'TemperatureSensor',
|
||||||
|
'TemperatureSensor': '0000008A-0000-1000-8000-0026BB765291',
|
||||||
|
'0000004A-0000-1000-8000-0026BB765291': 'Thermostat',
|
||||||
|
'Thermostat': '0000004A-0000-1000-8000-0026BB765291',
|
||||||
|
'000000D0-0000-1000-8000-0026BB765291': 'Valve',
|
||||||
|
'Valve': '000000D0-0000-1000-8000-0026BB765291',
|
||||||
|
'0000008B-0000-1000-8000-0026BB765291': 'Window',
|
||||||
|
'Window': '0000008B-0000-1000-8000-0026BB765291',
|
||||||
|
'0000008C-0000-1000-8000-0026BB765291': 'WindowCovering',
|
||||||
|
'WindowCovering': '0000008C-0000-1000-8000-0026BB765291',
|
||||||
|
'000000D8-0000-1000-8000-0026BB765291': 'Television',
|
||||||
|
'Television': '000000D8-0000-1000-8000-0026BB765291',
|
||||||
|
'000000D9-0000-1000-8000-0026BB765291': 'InputSource',
|
||||||
|
'InputSource': '000000D9-0000-1000-8000-0026BB765291',
|
||||||
|
'TelevisionSpeaker': '00000113-0000-1000-8000-0026BB765291',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const Characteristics: Dictionary<string> = {
|
||||||
|
'000000A6-0000-1000-8000-0026BB765291': 'AccessoryFlags',
|
||||||
|
'AccessoryFlags': '000000A6-0000-1000-8000-0026BB765291',
|
||||||
|
'000000B0-0000-1000-8000-0026BB765291': 'Active',
|
||||||
|
'Active': '000000B0-0000-1000-8000-0026BB765291',
|
||||||
|
'00000001-0000-1000-8000-0026BB765291': 'AdministratorOnlyAccess',
|
||||||
|
'AdministratorOnlyAccess': '00000001-0000-1000-8000-0026BB765291',
|
||||||
|
'00000064-0000-1000-8000-0026BB765291': 'AirParticulateDensity',
|
||||||
|
'AirParticulateDensity': '00000064-0000-1000-8000-0026BB765291',
|
||||||
|
'00000065-0000-1000-8000-0026BB765291': 'AirParticulateSize',
|
||||||
|
'AirParticulateSize': '00000065-0000-1000-8000-0026BB765291',
|
||||||
|
'00000095-0000-1000-8000-0026BB765291': 'AirQuality',
|
||||||
|
'AirQuality': '00000095-0000-1000-8000-0026BB765291',
|
||||||
|
'00000005-0000-1000-8000-0026BB765291': 'AudioFeedback',
|
||||||
|
'AudioFeedback': '00000005-0000-1000-8000-0026BB765291',
|
||||||
|
'00000068-0000-1000-8000-0026BB765291': 'BatteryLevel',
|
||||||
|
'BatteryLevel': '00000068-0000-1000-8000-0026BB765291',
|
||||||
|
'00000008-0000-1000-8000-0026BB765291': 'Brightness',
|
||||||
|
'Brightness': '00000008-0000-1000-8000-0026BB765291',
|
||||||
|
'00000092-0000-1000-8000-0026BB765291': 'CarbonDioxideDetected',
|
||||||
|
'CarbonDioxideDetected': '00000092-0000-1000-8000-0026BB765291',
|
||||||
|
'00000093-0000-1000-8000-0026BB765291': 'CarbonDioxideLevel',
|
||||||
|
'CarbonDioxideLevel': '00000093-0000-1000-8000-0026BB765291',
|
||||||
|
'00000094-0000-1000-8000-0026BB765291': 'CarbonDioxidePeakLevel',
|
||||||
|
'CarbonDioxidePeakLevel': '00000094-0000-1000-8000-0026BB765291',
|
||||||
|
'00000069-0000-1000-8000-0026BB765291': 'CarbonMonoxideDetected',
|
||||||
|
'CarbonMonoxideDetected': '00000069-0000-1000-8000-0026BB765291',
|
||||||
|
'00000090-0000-1000-8000-0026BB765291': 'CarbonMonoxideLevel',
|
||||||
|
'CarbonMonoxideLevel': '00000090-0000-1000-8000-0026BB765291',
|
||||||
|
'00000091-0000-1000-8000-0026BB765291': 'CarbonMonoxidePeakLevel',
|
||||||
|
'CarbonMonoxidePeakLevel': '00000091-0000-1000-8000-0026BB765291',
|
||||||
|
'0000008F-0000-1000-8000-0026BB765291': 'ChargingState',
|
||||||
|
'ChargingState': '0000008F-0000-1000-8000-0026BB765291',
|
||||||
|
'000000CE-0000-1000-8000-0026BB765291': 'ColorTemperature',
|
||||||
|
'ColorTemperature': '000000CE-0000-1000-8000-0026BB765291',
|
||||||
|
'0000006A-0000-1000-8000-0026BB765291': 'ContactSensorState',
|
||||||
|
'ContactSensorState': '0000006A-0000-1000-8000-0026BB765291',
|
||||||
|
'0000000D-0000-1000-8000-0026BB765291': 'CoolingThresholdTemperature',
|
||||||
|
'CoolingThresholdTemperature': '0000000D-0000-1000-8000-0026BB765291',
|
||||||
|
'000000A9-0000-1000-8000-0026BB765291': 'CurrentAirPurifierState',
|
||||||
|
'CurrentAirPurifierState': '000000A9-0000-1000-8000-0026BB765291',
|
||||||
|
'0000006B-0000-1000-8000-0026BB765291': 'CurrentAmbientLightLevel',
|
||||||
|
'CurrentAmbientLightLevel': '0000006B-0000-1000-8000-0026BB765291',
|
||||||
|
'0000000E-0000-1000-8000-0026BB765291': 'CurrentDoorState',
|
||||||
|
'CurrentDoorState': '0000000E-0000-1000-8000-0026BB765291',
|
||||||
|
'000000AF-0000-1000-8000-0026BB765291': 'CurrentFanState',
|
||||||
|
'CurrentFanState': '000000AF-0000-1000-8000-0026BB765291',
|
||||||
|
'000000B1-0000-1000-8000-0026BB765291': 'CurrentHeaterCoolerState',
|
||||||
|
'CurrentHeaterCoolerState': '000000B1-0000-1000-8000-0026BB765291',
|
||||||
|
'0000000F-0000-1000-8000-0026BB765291': 'CurrentHeatingCoolingState',
|
||||||
|
'CurrentHeatingCoolingState': '0000000F-0000-1000-8000-0026BB765291',
|
||||||
|
'0000006C-0000-1000-8000-0026BB765291': 'CurrentHorizontalTiltAngle',
|
||||||
|
'CurrentHorizontalTiltAngle': '0000006C-0000-1000-8000-0026BB765291',
|
||||||
|
'000000B3-0000-1000-8000-0026BB765291': 'CurrentHumidifierDehumidifierState',
|
||||||
|
'CurrentHumidifierDehumidifierState': '000000B3-0000-1000-8000-0026BB765291',
|
||||||
|
'0000006D-0000-1000-8000-0026BB765291': 'CurrentPosition',
|
||||||
|
'CurrentPosition': '0000006D-0000-1000-8000-0026BB765291',
|
||||||
|
'00000010-0000-1000-8000-0026BB765291': 'CurrentRelativeHumidity',
|
||||||
|
'CurrentRelativeHumidity': '00000010-0000-1000-8000-0026BB765291',
|
||||||
|
'000000AA-0000-1000-8000-0026BB765291': 'CurrentSlatState',
|
||||||
|
'CurrentSlatState': '000000AA-0000-1000-8000-0026BB765291',
|
||||||
|
'00000011-0000-1000-8000-0026BB765291': 'CurrentTemperature',
|
||||||
|
'CurrentTemperature': '00000011-0000-1000-8000-0026BB765291',
|
||||||
|
'000000C1-0000-1000-8000-0026BB765291': 'CurrentTiltAngle',
|
||||||
|
'CurrentTiltAngle': '000000C1-0000-1000-8000-0026BB765291',
|
||||||
|
'0000006E-0000-1000-8000-0026BB765291': 'CurrentVerticalTiltAngle',
|
||||||
|
'CurrentVerticalTiltAngle': '0000006E-0000-1000-8000-0026BB765291',
|
||||||
|
'0000011D-0000-1000-8000-0026BB765291': 'DigitalZoom',
|
||||||
|
'DigitalZoom': '0000011D-0000-1000-8000-0026BB765291',
|
||||||
|
'000000AC-0000-1000-8000-0026BB765291': 'FilterChangeIndication',
|
||||||
|
'FilterChangeIndication': '000000AC-0000-1000-8000-0026BB765291',
|
||||||
|
'000000AB-0000-1000-8000-0026BB765291': 'FilterLifeLevel',
|
||||||
|
'FilterLifeLevel': '000000AB-0000-1000-8000-0026BB765291',
|
||||||
|
'00000052-0000-1000-8000-0026BB765291': 'FirmwareRevision',
|
||||||
|
'FirmwareRevision': '00000052-0000-1000-8000-0026BB765291',
|
||||||
|
'00000053-0000-1000-8000-0026BB765291': 'HardwareRevision',
|
||||||
|
'HardwareRevision': '00000053-0000-1000-8000-0026BB765291',
|
||||||
|
'00000012-0000-1000-8000-0026BB765291': 'HeatingThresholdTemperature',
|
||||||
|
'HeatingThresholdTemperature': '00000012-0000-1000-8000-0026BB765291',
|
||||||
|
'0000006F-0000-1000-8000-0026BB765291': 'HoldPosition',
|
||||||
|
'HoldPosition': '0000006F-0000-1000-8000-0026BB765291',
|
||||||
|
'00000013-0000-1000-8000-0026BB765291': 'Hue',
|
||||||
|
'Hue': '00000013-0000-1000-8000-0026BB765291',
|
||||||
|
'00000014-0000-1000-8000-0026BB765291': 'Identify',
|
||||||
|
'Identify': '00000014-0000-1000-8000-0026BB765291',
|
||||||
|
'0000011F-0000-1000-8000-0026BB765291': 'ImageMirroring',
|
||||||
|
'ImageMirroring': '0000011F-0000-1000-8000-0026BB765291',
|
||||||
|
'0000011E-0000-1000-8000-0026BB765291': 'ImageRotation',
|
||||||
|
'ImageRotation': '0000011E-0000-1000-8000-0026BB765291',
|
||||||
|
'000000D2-0000-1000-8000-0026BB765291': 'InUse',
|
||||||
|
'InUse': '000000D2-0000-1000-8000-0026BB765291',
|
||||||
|
'000000D6-0000-1000-8000-0026BB765291': 'IsConfigured',
|
||||||
|
'IsConfigured': '000000D6-0000-1000-8000-0026BB765291',
|
||||||
|
'00000070-0000-1000-8000-0026BB765291': 'LeakDetected',
|
||||||
|
'LeakDetected': '00000070-0000-1000-8000-0026BB765291',
|
||||||
|
'00000019-0000-1000-8000-0026BB765291': 'LockControlPoint',
|
||||||
|
'LockControlPoint': '00000019-0000-1000-8000-0026BB765291',
|
||||||
|
'0000001D-0000-1000-8000-0026BB765291': 'LockCurrentState',
|
||||||
|
'LockCurrentState': '0000001D-0000-1000-8000-0026BB765291',
|
||||||
|
'0000001C-0000-1000-8000-0026BB765291': 'LockLastKnownAction',
|
||||||
|
'LockLastKnownAction': '0000001C-0000-1000-8000-0026BB765291',
|
||||||
|
'0000001A-0000-1000-8000-0026BB765291': 'LockManagementAutoSecurityTimeout',
|
||||||
|
'LockManagementAutoSecurityTimeout': '0000001A-0000-1000-8000-0026BB765291',
|
||||||
|
'000000A7-0000-1000-8000-0026BB765291': 'LockPhysicalControls',
|
||||||
|
'LockPhysicalControls': '000000A7-0000-1000-8000-0026BB765291',
|
||||||
|
'0000001E-0000-1000-8000-0026BB765291': 'LockTargetState',
|
||||||
|
'LockTargetState': '0000001E-0000-1000-8000-0026BB765291',
|
||||||
|
'0000001F-0000-1000-8000-0026BB765291': 'Logs',
|
||||||
|
'Logs': '0000001F-0000-1000-8000-0026BB765291',
|
||||||
|
'00000020-0000-1000-8000-0026BB765291': 'Manufacturer',
|
||||||
|
'Manufacturer': '00000020-0000-1000-8000-0026BB765291',
|
||||||
|
'00000021-0000-1000-8000-0026BB765291': 'Model',
|
||||||
|
'Model': '00000021-0000-1000-8000-0026BB765291',
|
||||||
|
'00000022-0000-1000-8000-0026BB765291': 'MotionDetected',
|
||||||
|
'MotionDetected': '00000022-0000-1000-8000-0026BB765291',
|
||||||
|
'0000011A-0000-1000-8000-0026BB765291': 'Mute',
|
||||||
|
'Mute': '0000011A-0000-1000-8000-0026BB765291',
|
||||||
|
'00000023-0000-1000-8000-0026BB765291': 'Name',
|
||||||
|
'Name': '00000023-0000-1000-8000-0026BB765291',
|
||||||
|
'0000011B-0000-1000-8000-0026BB765291': 'NightVision',
|
||||||
|
'NightVision': '0000011B-0000-1000-8000-0026BB765291',
|
||||||
|
'000000C4-0000-1000-8000-0026BB765291': 'NitrogenDioxideDensity',
|
||||||
|
'NitrogenDioxideDensity': '000000C4-0000-1000-8000-0026BB765291',
|
||||||
|
'00000024-0000-1000-8000-0026BB765291': 'ObstructionDetected',
|
||||||
|
'ObstructionDetected': '00000024-0000-1000-8000-0026BB765291',
|
||||||
|
'00000071-0000-1000-8000-0026BB765291': 'OccupancyDetected',
|
||||||
|
'OccupancyDetected': '00000071-0000-1000-8000-0026BB765291',
|
||||||
|
'00000025-0000-1000-8000-0026BB765291': 'On',
|
||||||
|
'On': '00000025-0000-1000-8000-0026BB765291',
|
||||||
|
'0000011C-0000-1000-8000-0026BB765291': 'OpticalZoom',
|
||||||
|
'OpticalZoom': '0000011C-0000-1000-8000-0026BB765291',
|
||||||
|
'00000026-0000-1000-8000-0026BB765291': 'OutletInUse',
|
||||||
|
'OutletInUse': '00000026-0000-1000-8000-0026BB765291',
|
||||||
|
'000000C3-0000-1000-8000-0026BB765291': 'OzoneDensity',
|
||||||
|
'OzoneDensity': '000000C3-0000-1000-8000-0026BB765291',
|
||||||
|
'0000004C-0000-1000-8000-0026BB765291': 'PairSetup',
|
||||||
|
'PairSetup': '0000004C-0000-1000-8000-0026BB765291',
|
||||||
|
'0000004E-0000-1000-8000-0026BB765291': 'PairVerify',
|
||||||
|
'PairVerify': '0000004E-0000-1000-8000-0026BB765291',
|
||||||
|
'0000004F-0000-1000-8000-0026BB765291': 'PairingFeatures',
|
||||||
|
'PairingFeatures': '0000004F-0000-1000-8000-0026BB765291',
|
||||||
|
'00000050-0000-1000-8000-0026BB765291': 'PairingPairings',
|
||||||
|
'PairingPairings': '00000050-0000-1000-8000-0026BB765291',
|
||||||
|
'000000C7-0000-1000-8000-0026BB765291': 'PM10Density',
|
||||||
|
'PM10Density': '000000C7-0000-1000-8000-0026BB765291',
|
||||||
|
'000000C6-0000-1000-8000-0026BB765291': 'PM2_5Density',
|
||||||
|
'PM2_5Density': '000000C6-0000-1000-8000-0026BB765291',
|
||||||
|
'00000072-0000-1000-8000-0026BB765291': 'PositionState',
|
||||||
|
'PositionState': '00000072-0000-1000-8000-0026BB765291',
|
||||||
|
'000000D1-0000-1000-8000-0026BB765291': 'ProgramMode',
|
||||||
|
'ProgramMode': '000000D1-0000-1000-8000-0026BB765291',
|
||||||
|
'00000073-0000-1000-8000-0026BB765291': 'ProgrammableSwitchEvent',
|
||||||
|
'ProgrammableSwitchEvent': '00000073-0000-1000-8000-0026BB765291',
|
||||||
|
'000000C9-0000-1000-8000-0026BB765291': 'RelativeHumidityDehumidifierThreshold',
|
||||||
|
'RelativeHumidityDehumidifierThreshold': '000000C9-0000-1000-8000-0026BB765291',
|
||||||
|
'000000CA-0000-1000-8000-0026BB765291': 'RelativeHumidityHumidifierThreshold',
|
||||||
|
'RelativeHumidityHumidifierThreshold': '000000CA-0000-1000-8000-0026BB765291',
|
||||||
|
'000000D4-0000-1000-8000-0026BB765291': 'RemainingDuration',
|
||||||
|
'RemainingDuration': '000000D4-0000-1000-8000-0026BB765291',
|
||||||
|
'000000AD-0000-1000-8000-0026BB765291': 'ResetFilterIndication',
|
||||||
|
'ResetFilterIndication': '000000AD-0000-1000-8000-0026BB765291',
|
||||||
|
'00000028-0000-1000-8000-0026BB765291': 'RotationDirection',
|
||||||
|
'RotationDirection': '00000028-0000-1000-8000-0026BB765291',
|
||||||
|
'00000029-0000-1000-8000-0026BB765291': 'RotationSpeed',
|
||||||
|
'RotationSpeed': '00000029-0000-1000-8000-0026BB765291',
|
||||||
|
'0000002F-0000-1000-8000-0026BB765291': 'Saturation',
|
||||||
|
'Saturation': '0000002F-0000-1000-8000-0026BB765291',
|
||||||
|
'0000008E-0000-1000-8000-0026BB765291': 'SecuritySystemAlarmType',
|
||||||
|
'SecuritySystemAlarmType': '0000008E-0000-1000-8000-0026BB765291',
|
||||||
|
'00000066-0000-1000-8000-0026BB765291': 'SecuritySystemCurrentState',
|
||||||
|
'SecuritySystemCurrentState': '00000066-0000-1000-8000-0026BB765291',
|
||||||
|
'00000067-0000-1000-8000-0026BB765291': 'SecuritySystemTargetState',
|
||||||
|
'SecuritySystemTargetState': '00000067-0000-1000-8000-0026BB765291',
|
||||||
|
'00000117-0000-1000-8000-0026BB765291': 'SelectedRTPStreamConfiguration',
|
||||||
|
'SelectedRTPStreamConfiguration': '00000117-0000-1000-8000-0026BB765291',
|
||||||
|
'00000030-0000-1000-8000-0026BB765291': 'SerialNumber',
|
||||||
|
'SerialNumber': '00000030-0000-1000-8000-0026BB765291',
|
||||||
|
'000000CB-0000-1000-8000-0026BB765291': 'ServiceLabelIndex',
|
||||||
|
'ServiceLabelIndex': '000000CB-0000-1000-8000-0026BB765291',
|
||||||
|
'000000CD-0000-1000-8000-0026BB765291': 'ServiceLabelNamespace',
|
||||||
|
'ServiceLabelNamespace': '000000CD-0000-1000-8000-0026BB765291',
|
||||||
|
'000000D3-0000-1000-8000-0026BB765291': 'SetDuration',
|
||||||
|
'SetDuration': '000000D3-0000-1000-8000-0026BB765291',
|
||||||
|
'00000118-0000-1000-8000-0026BB765291': 'SetupEndpoints',
|
||||||
|
'SetupEndpoints': '00000118-0000-1000-8000-0026BB765291',
|
||||||
|
'000000C0-0000-1000-8000-0026BB765291': 'SlatType',
|
||||||
|
'SlatType': '000000C0-0000-1000-8000-0026BB765291',
|
||||||
|
'00000076-0000-1000-8000-0026BB765291': 'SmokeDetected',
|
||||||
|
'SmokeDetected': '00000076-0000-1000-8000-0026BB765291',
|
||||||
|
'00000075-0000-1000-8000-0026BB765291': 'StatusActive',
|
||||||
|
'StatusActive': '00000075-0000-1000-8000-0026BB765291',
|
||||||
|
'00000077-0000-1000-8000-0026BB765291': 'StatusFault',
|
||||||
|
'StatusFault': '00000077-0000-1000-8000-0026BB765291',
|
||||||
|
'00000078-0000-1000-8000-0026BB765291': 'StatusJammed',
|
||||||
|
'StatusJammed': '00000078-0000-1000-8000-0026BB765291',
|
||||||
|
'00000079-0000-1000-8000-0026BB765291': 'StatusLowBattery',
|
||||||
|
'StatusLowBattery': '00000079-0000-1000-8000-0026BB765291',
|
||||||
|
'0000007A-0000-1000-8000-0026BB765291': 'StatusTampered',
|
||||||
|
'StatusTampered': '0000007A-0000-1000-8000-0026BB765291',
|
||||||
|
'00000120-0000-1000-8000-0026BB765291': 'StreamingStatus',
|
||||||
|
'StreamingStatus': '00000120-0000-1000-8000-0026BB765291',
|
||||||
|
'000000C5-0000-1000-8000-0026BB765291': 'SulphurDioxideDensity',
|
||||||
|
'SulphurDioxideDensity': '000000C5-0000-1000-8000-0026BB765291',
|
||||||
|
'00000115-0000-1000-8000-0026BB765291': 'SupportedAudioStreamConfiguration',
|
||||||
|
'SupportedAudioStreamConfiguration': '00000115-0000-1000-8000-0026BB765291',
|
||||||
|
'00000116-0000-1000-8000-0026BB765291': 'SupportedRTPConfiguration',
|
||||||
|
'SupportedRTPConfiguration': '00000116-0000-1000-8000-0026BB765291',
|
||||||
|
'00000114-0000-1000-8000-0026BB765291': 'SupportedVideoStreamConfiguration',
|
||||||
|
'SupportedVideoStreamConfiguration': '00000114-0000-1000-8000-0026BB765291',
|
||||||
|
'000000B6-0000-1000-8000-0026BB765291': 'SwingMode',
|
||||||
|
'SwingMode': '000000B6-0000-1000-8000-0026BB765291',
|
||||||
|
'000000A8-0000-1000-8000-0026BB765291': 'TargetAirPurifierState',
|
||||||
|
'TargetAirPurifierState': '000000A8-0000-1000-8000-0026BB765291',
|
||||||
|
'000000AE-0000-1000-8000-0026BB765291': 'TargetAirQuality',
|
||||||
|
'TargetAirQuality': '000000AE-0000-1000-8000-0026BB765291',
|
||||||
|
'00000032-0000-1000-8000-0026BB765291': 'TargetDoorState',
|
||||||
|
'TargetDoorState': '00000032-0000-1000-8000-0026BB765291',
|
||||||
|
'000000BF-0000-1000-8000-0026BB765291': 'TargetFanState',
|
||||||
|
'TargetFanState': '000000BF-0000-1000-8000-0026BB765291',
|
||||||
|
'000000B2-0000-1000-8000-0026BB765291': 'TargetHeaterCoolerState',
|
||||||
|
'TargetHeaterCoolerState': '000000B2-0000-1000-8000-0026BB765291',
|
||||||
|
'00000033-0000-1000-8000-0026BB765291': 'TargetHeatingCoolingState',
|
||||||
|
'TargetHeatingCoolingState': '00000033-0000-1000-8000-0026BB765291',
|
||||||
|
'0000007B-0000-1000-8000-0026BB765291': 'TargetHorizontalTiltAngle',
|
||||||
|
'TargetHorizontalTiltAngle': '0000007B-0000-1000-8000-0026BB765291',
|
||||||
|
'000000B4-0000-1000-8000-0026BB765291': 'TargetHumidifierDehumidifierState',
|
||||||
|
'TargetHumidifierDehumidifierState': '000000B4-0000-1000-8000-0026BB765291',
|
||||||
|
'0000007C-0000-1000-8000-0026BB765291': 'TargetPosition',
|
||||||
|
'TargetPosition': '0000007C-0000-1000-8000-0026BB765291',
|
||||||
|
'00000034-0000-1000-8000-0026BB765291': 'TargetRelativeHumidity',
|
||||||
|
'TargetRelativeHumidity': '00000034-0000-1000-8000-0026BB765291',
|
||||||
|
'000000BE-0000-1000-8000-0026BB765291': 'TargetSlatState',
|
||||||
|
'TargetSlatState': '000000BE-0000-1000-8000-0026BB765291',
|
||||||
|
'00000035-0000-1000-8000-0026BB765291': 'TargetTemperature',
|
||||||
|
'TargetTemperature': '00000035-0000-1000-8000-0026BB765291',
|
||||||
|
'000000C2-0000-1000-8000-0026BB765291': 'TargetTiltAngle',
|
||||||
|
'TargetTiltAngle': '000000C2-0000-1000-8000-0026BB765291',
|
||||||
|
'0000007D-0000-1000-8000-0026BB765291': 'TargetVerticalTiltAngle',
|
||||||
|
'TargetVerticalTiltAngle': '0000007D-0000-1000-8000-0026BB765291',
|
||||||
|
'00000036-0000-1000-8000-0026BB765291': 'TemperatureDisplayUnits',
|
||||||
|
'TemperatureDisplayUnits': '00000036-0000-1000-8000-0026BB765291',
|
||||||
|
'000000D5-0000-1000-8000-0026BB765291': 'ValveType',
|
||||||
|
'ValveType': '000000D5-0000-1000-8000-0026BB765291',
|
||||||
|
'00000037-0000-1000-8000-0026BB765291': 'Version',
|
||||||
|
'Version': '00000037-0000-1000-8000-0026BB765291',
|
||||||
|
'000000C8-0000-1000-8000-0026BB765291': 'VOCDensity',
|
||||||
|
'VOCDensity': '000000C8-0000-1000-8000-0026BB765291',
|
||||||
|
'00000119-0000-1000-8000-0026BB765291': 'Volume',
|
||||||
|
'Volume': '00000119-0000-1000-8000-0026BB765291',
|
||||||
|
'000000B5-0000-1000-8000-0026BB765291': 'WaterLevel',
|
||||||
|
'WaterLevel': '000000B5-0000-1000-8000-0026BB765291',
|
||||||
|
'000000E7-0000-1000-8000-0026BB765291': 'ActiveIdentifier',
|
||||||
|
'ActiveIdentifier': '000000E7-0000-1000-8000-0026BB765291',
|
||||||
|
'000000E3-0000-1000-8000-0026BB765291': 'ConfiguredName',
|
||||||
|
'ConfiguredName': '000000E3-0000-1000-8000-0026BB765291',
|
||||||
|
'000000E8-0000-1000-8000-0026BB765291': 'SleepDiscoveryMode',
|
||||||
|
'SleepDiscoveryMode': '000000E8-0000-1000-8000-0026BB765291',
|
||||||
|
'000000DD-0000-1000-8000-0026BB765291': 'ClosedCaptions',
|
||||||
|
'ClosedCaptions': '000000DD-0000-1000-8000-0026BB765291',
|
||||||
|
'00000136-0000-1000-8000-0026BB765291': 'DisplayOrder',
|
||||||
|
'DisplayOrder': '00000136-0000-1000-8000-0026BB765291',
|
||||||
|
'000000E0-0000-1000-8000-0026BB765291': 'CurrentMediaState',
|
||||||
|
'CurrentMediaState': '000000E0-0000-1000-8000-0026BB765291',
|
||||||
|
'00000137-0000-1000-8000-0026BB765291': 'TargetMediaState',
|
||||||
|
'TargetMediaState': '00000137-0000-1000-8000-0026BB765291',
|
||||||
|
'000000E2-0000-1000-8000-0026BB765291': 'PictureMode',
|
||||||
|
'PictureMode': '000000E2-0000-1000-8000-0026BB765291',
|
||||||
|
'000000DF-0000-1000-8000-0026BB765291': 'PowerModeSelection',
|
||||||
|
'PowerModeSelection': '000000DF-0000-1000-8000-0026BB765291',
|
||||||
|
'000000E1-0000-1000-8000-0026BB765291': 'RemoteKey',
|
||||||
|
'RemoteKey': '000000E1-0000-1000-8000-0026BB765291',
|
||||||
|
'000000DB-0000-1000-8000-0026BB765291': 'InputSourceType',
|
||||||
|
'InputSourceType': '000000DB-0000-1000-8000-0026BB765291',
|
||||||
|
'000000DC-0000-1000-8000-0026BB765291': 'InputDeviceType',
|
||||||
|
'InputDeviceType': '000000DC-0000-1000-8000-0026BB765291',
|
||||||
|
'000000E6-0000-1000-8000-0026BB765291': 'Identifier',
|
||||||
|
'Identifier': '000000E6-0000-1000-8000-0026BB765291',
|
||||||
|
'00000135-0000-1000-8000-0026BB765291': 'CurrentVisibilityState',
|
||||||
|
'CurrentVisibilityState': '00000135-0000-1000-8000-0026BB765291',
|
||||||
|
'00000134-0000-1000-8000-0026BB765291': 'TargetVisibilityState',
|
||||||
|
'TargetVisibilityState': '00000134-0000-1000-8000-0026BB765291',
|
||||||
|
'000000E9-0000-1000-8000-0026BB765291': 'VolumeControlType',
|
||||||
|
'VolumeControlType': '000000E9-0000-1000-8000-0026BB765291',
|
||||||
|
'000000EA-0000-1000-8000-0026BB765291': 'VolumeSelector',
|
||||||
|
'VolumeSelector': '000000EA-0000-1000-8000-0026BB765291',
|
||||||
|
};
|
425
src/3rdParty/HapClient/index.ts
vendored
Executable file
425
src/3rdParty/HapClient/index.ts
vendored
Executable file
@ -0,0 +1,425 @@
|
|||||||
|
import 'source-map-support/register';
|
||||||
|
import * as crypto from 'crypto';
|
||||||
|
import decamelize from 'decamelize';
|
||||||
|
import * as inflection from 'inflection';
|
||||||
|
import Bonjour, { Service } from 'bonjour';
|
||||||
|
import { EventEmitter } from 'events';
|
||||||
|
import { get, put } from 'request-promise-native';
|
||||||
|
|
||||||
|
import { Services, Characteristics } from './hap-types';
|
||||||
|
import { HapMonitor } from './monitor';
|
||||||
|
import { IHapAccessoriesRespType, IServiceType, ICharacteristicType, IHapInstance, createDefaultCharacteristicType } from './interfaces';
|
||||||
|
|
||||||
|
export type HapAccessoriesRespType = IHapAccessoriesRespType;
|
||||||
|
export type ServiceType = IServiceType;
|
||||||
|
export type CharacteristicType = ICharacteristicType;
|
||||||
|
|
||||||
|
export interface IDevice {
|
||||||
|
addresses: Array<string>
|
||||||
|
fqdn: string,
|
||||||
|
host: string,
|
||||||
|
name: string,
|
||||||
|
port: number,
|
||||||
|
protocol: "tcp" | "udp",
|
||||||
|
rawTxt: Buffer,
|
||||||
|
referer: {
|
||||||
|
address: string,
|
||||||
|
family: "IPv4" | "IPv6",
|
||||||
|
port: number,
|
||||||
|
size: number,
|
||||||
|
},
|
||||||
|
subtypes: Array<any>,
|
||||||
|
txt: any,
|
||||||
|
type: string
|
||||||
|
}
|
||||||
|
|
||||||
|
export class HapClient extends EventEmitter {
|
||||||
|
private bonjour = Bonjour();
|
||||||
|
private browser?: Bonjour.Browser;
|
||||||
|
private discoveryInProgress = false;
|
||||||
|
|
||||||
|
private log: (msg: string) => void;
|
||||||
|
private pin: string;
|
||||||
|
private debugEnabled: boolean;
|
||||||
|
private config: {
|
||||||
|
debug?: boolean;
|
||||||
|
instanceBlacklist?: string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
private instances: IHapInstance[] = [];
|
||||||
|
|
||||||
|
private hiddenServices = [
|
||||||
|
Services.AccessoryInformation
|
||||||
|
];
|
||||||
|
|
||||||
|
private hiddenCharacteristics = [
|
||||||
|
Characteristics.Name
|
||||||
|
];
|
||||||
|
|
||||||
|
constructor(opts: {
|
||||||
|
pin: string;
|
||||||
|
logger?: any;
|
||||||
|
config: any;
|
||||||
|
}) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.pin = opts.pin;
|
||||||
|
this.log = opts.logger;
|
||||||
|
this.debugEnabled = true;
|
||||||
|
this.config = opts.config;
|
||||||
|
this.startDiscovery();
|
||||||
|
}
|
||||||
|
|
||||||
|
private debug(msg: any) {
|
||||||
|
if (this.debugEnabled) {
|
||||||
|
this.log(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private debugErr(msg: string, err: Error) {
|
||||||
|
if (this.debugEnabled) {
|
||||||
|
this.log(`${msg}: ${err.message}\n ${err.stack}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public refreshInstances() {
|
||||||
|
if (!this.discoveryInProgress) {
|
||||||
|
this.startDiscovery();
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
this.debug(`[HapClient] Discovery :: Re-broadcasting discovery query`);
|
||||||
|
if (this.browser) {
|
||||||
|
this.browser.update();
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (e) { }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async startDiscovery() {
|
||||||
|
this.discoveryInProgress = true;
|
||||||
|
|
||||||
|
this.browser = this.bonjour.find({
|
||||||
|
type: 'hap'
|
||||||
|
});
|
||||||
|
|
||||||
|
// start matching services
|
||||||
|
this.browser.start();
|
||||||
|
this.debug(`[HapClient] Discovery :: Started`);
|
||||||
|
|
||||||
|
// stop discovery after 20 seconds
|
||||||
|
setTimeout(() => {
|
||||||
|
if (this.browser) {
|
||||||
|
this.browser.stop();
|
||||||
|
}
|
||||||
|
this.debug(`[HapClient] Discovery :: Ended`);
|
||||||
|
this.discoveryInProgress = false;
|
||||||
|
}, 60000);
|
||||||
|
|
||||||
|
// service found
|
||||||
|
this.browser.on('up', async (service: any) => {
|
||||||
|
let device = service as IDevice;
|
||||||
|
if (!device || !device.txt) {
|
||||||
|
this.debug(`[HapClient] Discovery :: Ignoring device that contains no txt records. ${JSON.stringify(device)}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const instance: IHapInstance = {
|
||||||
|
displayName: device.name,
|
||||||
|
ipAddress: device.addresses[0],
|
||||||
|
name: device.txt.md,
|
||||||
|
username: device.txt.id,
|
||||||
|
port: device.port,
|
||||||
|
}
|
||||||
|
|
||||||
|
this.debug(`[HapClient] Discovery :: Found HAP device ${instance.displayName} with username ${instance.username}`);
|
||||||
|
|
||||||
|
// update an existing instance
|
||||||
|
const existingInstanceIndex = this.instances.findIndex(x => x.username === instance.username);
|
||||||
|
if (existingInstanceIndex > -1) {
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.instances[existingInstanceIndex].port !== instance.port ||
|
||||||
|
this.instances[existingInstanceIndex].name !== instance.name
|
||||||
|
) {
|
||||||
|
this.instances[existingInstanceIndex].port = instance.port;
|
||||||
|
this.instances[existingInstanceIndex].name = instance.name;
|
||||||
|
this.debug(`[HapClient] Discovery :: [${this.instances[existingInstanceIndex].ipAddress}:${instance.port} ` +
|
||||||
|
`(${instance.username})] Instance Updated`);
|
||||||
|
this.emit('instance-discovered', instance);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Comenting out because of lack of config
|
||||||
|
|
||||||
|
// check instance is not on the blacklist
|
||||||
|
// if (this.config.instanceBlacklist && this.config.instanceBlacklist.find(x => instance.username.toLowerCase() === x.toLowerCase())) {
|
||||||
|
// this.debug(`[HapClient] Discovery :: Instance with username ${instance.username} found in blacklist. Disregarding.`);
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
|
||||||
|
for (const ip of device.addresses) {
|
||||||
|
if (ip.match(/^(?:(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])(\.(?!$)|$)){4}$/)) {
|
||||||
|
try {
|
||||||
|
this.debug(`[HapClient] Discovery :: Testing ${instance.displayName} ${instance.username} via http://${ip}:${device.port}/accessories`);
|
||||||
|
const test = await get(`http://${ip}:${device.port}/accessories`, {
|
||||||
|
json: true,
|
||||||
|
timeout: 1000,
|
||||||
|
});
|
||||||
|
if (test.accessories) {
|
||||||
|
this.debug(`[HapClient] Discovery :: Success ${instance.displayName} ${instance.username} via http://${ip}:${device.port}/accessories`);
|
||||||
|
instance.ipAddress = ip;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} catch (e) {
|
||||||
|
this.debug(`[HapClient] Discovery :: ***Failed*** ${instance.displayName} ${instance.username} via http://${ip}:${device.port}/accessories`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// store instance record
|
||||||
|
if (instance.ipAddress) {
|
||||||
|
this.instances.push(instance);
|
||||||
|
this.debug(`[HapClient] Discovery :: [${instance.displayName} - ${instance.ipAddress}:${instance.port} (${instance.username})] Instance Registered`);
|
||||||
|
this.emit('instance-discovered', instance);
|
||||||
|
} else {
|
||||||
|
this.debug(`[HapClient] Discovery :: Could not register to device ${instance.displayName} with username ${instance.username}`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private async getAccessories() {
|
||||||
|
if (!this.instances.length) {
|
||||||
|
this.debug('[HapClient] Cannot load accessories. No Homebridge instances have been discovered.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const accessories = [];
|
||||||
|
for (const instance of this.instances) {
|
||||||
|
try {
|
||||||
|
const resp: IHapAccessoriesRespType = await get(`http://${instance.ipAddress}:${instance.port}/accessories`, { json: true });
|
||||||
|
for (const accessory of resp.accessories) {
|
||||||
|
accessory.instance = instance;
|
||||||
|
accessories.push(accessory);
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
if (this.log) {
|
||||||
|
this.debugErr(`[HapClient] [${instance.displayName} - ${instance.ipAddress}:${instance.port} (${instance.username})] Failed to connect`, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return accessories;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async monitorCharacteristics(): Promise<HapMonitor> {
|
||||||
|
const services = await this.getAllServices();
|
||||||
|
return new HapMonitor(this.log, this.debug.bind(this), this.pin, services);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async getAllServices(): Promise<Array<IServiceType>> {
|
||||||
|
/* Get Accessories from HAP */
|
||||||
|
const accessories = await this.getAccessories();
|
||||||
|
|
||||||
|
const services: Array<IServiceType> = [];
|
||||||
|
|
||||||
|
/* Parse All Accessories */
|
||||||
|
accessories.forEach(accessory => {
|
||||||
|
|
||||||
|
/* Parse Accessory Information */
|
||||||
|
const accessoryInformationService = accessory.services.find(x => x.type === Services.AccessoryInformation);
|
||||||
|
const accessoryInformation: { [key: string]: any } = {};
|
||||||
|
|
||||||
|
if (accessoryInformationService && accessoryInformationService.characteristics) {
|
||||||
|
accessoryInformationService.characteristics.forEach((c) => {
|
||||||
|
if (c.value) {
|
||||||
|
accessoryInformation[c.description] = c.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse All Services */
|
||||||
|
accessory.services
|
||||||
|
.filter((s) => this.hiddenServices.indexOf(s.type) < 0 && Services[s.type])
|
||||||
|
.map((s) => {
|
||||||
|
let serviceName = s.characteristics.find(x => x.type === Characteristics.Name);
|
||||||
|
|
||||||
|
/* Set default name characteristic if none defined */
|
||||||
|
serviceName = serviceName ? serviceName : {
|
||||||
|
iid: 0,
|
||||||
|
type: Characteristics.Name,
|
||||||
|
description: 'Name',
|
||||||
|
format: 'string',
|
||||||
|
value: this.humanizeString(Services[s.type]),
|
||||||
|
perms: ['pr']
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Parse Service Characteristics */
|
||||||
|
const serviceCharacteristics: Array<ICharacteristicType> = s.characteristics
|
||||||
|
.filter((c) => this.hiddenCharacteristics.indexOf(c.type) < 0 && Characteristics[c.type])
|
||||||
|
.map((c) => {
|
||||||
|
return {
|
||||||
|
aid: accessory.aid,
|
||||||
|
iid: c.iid,
|
||||||
|
uuid: c.type,
|
||||||
|
type: Characteristics[c.type],
|
||||||
|
serviceType: Services[s.type],
|
||||||
|
serviceName: serviceName!.value.toString(),
|
||||||
|
description: c.description,
|
||||||
|
value: c.value,
|
||||||
|
format: c.format,
|
||||||
|
perms: c.perms,
|
||||||
|
unit: c.unit,
|
||||||
|
maxValue: c.maxValue,
|
||||||
|
minValue: c.minValue,
|
||||||
|
minStep: c.minStep,
|
||||||
|
canRead: c.perms.includes('pr'),
|
||||||
|
canWrite: c.perms.includes('pw'),
|
||||||
|
ev: c.perms.includes('ev'),
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const service: IServiceType = {
|
||||||
|
aid: accessory.aid,
|
||||||
|
iid: s.iid,
|
||||||
|
uuid: s.type,
|
||||||
|
type: Services[s.type],
|
||||||
|
humanType: this.humanizeString(Services[s.type]),
|
||||||
|
serviceName: serviceName.value.toString(),
|
||||||
|
serviceCharacteristics: serviceCharacteristics,
|
||||||
|
accessoryInformation: accessoryInformation,
|
||||||
|
values: {},
|
||||||
|
linked: s.linked,
|
||||||
|
instance: accessory.instance,
|
||||||
|
};
|
||||||
|
|
||||||
|
// generate unique id for service
|
||||||
|
service.uniqueId = crypto.createHash('sha256')
|
||||||
|
.update(`${service.instance.username}${service.aid}${service.iid}${service.type}`)
|
||||||
|
.digest('hex');
|
||||||
|
|
||||||
|
/* Helper function to trigger a call to the accessory to get all the characteristic values */
|
||||||
|
service.refreshCharacteristics = () => {
|
||||||
|
return this.refreshServiceCharacteristics.bind(this)(service);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Helper function to set the value of a characteristic */
|
||||||
|
service.setCharacteristic = (iid: number, value: number | string | boolean): Promise<IServiceType | ICharacteristicType> => {
|
||||||
|
return this.setCharacteristic.bind(this)(service, iid, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Helper function to returns a characteristic by it's type name */
|
||||||
|
service.getCharacteristic = (type: string): ICharacteristicType => {
|
||||||
|
let characteristic = service.serviceCharacteristics.find(c => c.type === type);
|
||||||
|
return characteristic ? characteristic : createDefaultCharacteristicType();
|
||||||
|
};
|
||||||
|
|
||||||
|
service.serviceCharacteristics.forEach((cType: ICharacteristicType) => {
|
||||||
|
/* Helper function to set the value of a characteristic */
|
||||||
|
cType.setValue = async (value: number | string | boolean): Promise<ICharacteristicType> => {
|
||||||
|
return await this.setCharacteristic.bind(this)(service, cType.iid, value);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Helper function to get the value of a characteristic from the accessory */
|
||||||
|
cType.getValue = async (): Promise<ICharacteristicType> => {
|
||||||
|
return await this.getCharacteristic.bind(this)(service, cType.iid);
|
||||||
|
};
|
||||||
|
|
||||||
|
/* set the values for each characteristic type in an easy-to-access object */
|
||||||
|
service.values[cType.type] = cType.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
services.push(service);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return services;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getService(iid: number) {
|
||||||
|
const services = await this.getAllServices();
|
||||||
|
return services.find(x => x.iid === iid);
|
||||||
|
}
|
||||||
|
|
||||||
|
async getServiceByName(serviceName: string) {
|
||||||
|
const services = await this.getAllServices();
|
||||||
|
return services.find(x => x.serviceName === serviceName);
|
||||||
|
}
|
||||||
|
|
||||||
|
async refreshServiceCharacteristics(service: IServiceType): Promise<IServiceType> {
|
||||||
|
const iids: number[] = service.serviceCharacteristics.map(c => c.iid);
|
||||||
|
|
||||||
|
const resp = await get(`http://${service.instance.ipAddress}:${service.instance.port}/characteristics`, {
|
||||||
|
qs: {
|
||||||
|
id: iids.map(iid => `${service.aid}.${iid}`).join(',')
|
||||||
|
},
|
||||||
|
json: true
|
||||||
|
});
|
||||||
|
|
||||||
|
resp.characteristics.forEach((c: ICharacteristicType) => {
|
||||||
|
const characteristic = service.serviceCharacteristics.find(x => x.iid === c.iid && x.aid === service.aid);
|
||||||
|
characteristic!.value = c.value;
|
||||||
|
});
|
||||||
|
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getCharacteristic(service: IServiceType, iid: number): Promise<ICharacteristicType> {
|
||||||
|
const resp = await get(`http://${service.instance.ipAddress}:${service.instance.port}/characteristics`, {
|
||||||
|
qs: {
|
||||||
|
id: `${service.aid}.${iid}`
|
||||||
|
},
|
||||||
|
json: true
|
||||||
|
});
|
||||||
|
|
||||||
|
const characteristic = service.serviceCharacteristics.find(x => x.iid === resp.characteristics[0].iid && x.aid === service.aid);
|
||||||
|
if (characteristic) {
|
||||||
|
characteristic.value = resp.characteristics[0].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return characteristic ? characteristic : createDefaultCharacteristicType();
|
||||||
|
}
|
||||||
|
|
||||||
|
async setCharacteristic(service: IServiceType, iid: number, value: number | string | boolean): Promise<ICharacteristicType> {
|
||||||
|
let characteristic = createDefaultCharacteristicType();
|
||||||
|
try {
|
||||||
|
await put(`http://${service.instance.ipAddress}:${service.instance.port}/characteristics`, {
|
||||||
|
headers: {
|
||||||
|
Authorization: this.pin
|
||||||
|
},
|
||||||
|
json: {
|
||||||
|
characteristics: [
|
||||||
|
{
|
||||||
|
aid: service.aid,
|
||||||
|
iid: iid,
|
||||||
|
value: value
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
characteristic = await this.getCharacteristic(service, iid);
|
||||||
|
} catch (e) {
|
||||||
|
if (this.log) {
|
||||||
|
this.debugErr(`[HapClient] [${service.instance.ipAddress}:${service.instance.port} (${service.instance.username})] ` +
|
||||||
|
`Failed to set value for ${service.serviceName}.`, e);
|
||||||
|
if (e.statusCode === 401) {
|
||||||
|
this.debug(`[HapClient] [${service.instance.ipAddress}:${service.instance.port} (${service.instance.username})] ` +
|
||||||
|
`Make sure Homebridge pin for this instance is set to ${this.pin}.`);
|
||||||
|
} else {
|
||||||
|
this.debug(e.message);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return characteristic
|
||||||
|
}
|
||||||
|
|
||||||
|
private humanizeString(string: string) {
|
||||||
|
return inflection.titleize(decamelize(string));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
116
src/3rdParty/HapClient/interfaces.ts
vendored
Executable file
116
src/3rdParty/HapClient/interfaces.ts
vendored
Executable file
@ -0,0 +1,116 @@
|
|||||||
|
import { Socket } from 'net';
|
||||||
|
|
||||||
|
export interface IHapInstance {
|
||||||
|
displayName: string
|
||||||
|
name: string;
|
||||||
|
ipAddress: string;
|
||||||
|
port: number;
|
||||||
|
username: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IHapEvInstance {
|
||||||
|
name: string;
|
||||||
|
ipAddress: string;
|
||||||
|
port: number;
|
||||||
|
username: string;
|
||||||
|
evCharacteristics?: { aid: number, iid: number, ev: boolean }[];
|
||||||
|
socket?: Socket;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IHapAccessoriesRespType {
|
||||||
|
accessories: Array<{
|
||||||
|
instance: {
|
||||||
|
ipAddress: string;
|
||||||
|
port: number;
|
||||||
|
username: string;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
aid: number;
|
||||||
|
services: Array<{
|
||||||
|
iid: number;
|
||||||
|
type: string;
|
||||||
|
primary: boolean;
|
||||||
|
hidden: boolean;
|
||||||
|
linked?: Array<number>;
|
||||||
|
characteristics: Array<{
|
||||||
|
iid: number;
|
||||||
|
type: string;
|
||||||
|
description: string;
|
||||||
|
value: number | string | boolean;
|
||||||
|
format: 'bool' | 'int' | 'float' | 'string' | 'uint8' | 'uint16' | 'uint32' | 'uint64' | 'data' | 'tlv8' | 'array' | 'dictionary';
|
||||||
|
perms: Array<'pr' | 'pw' | 'ev' | 'aa' | 'tw' | 'hd'>;
|
||||||
|
unit?: 'unit' | 'percentage' | 'celsius' | 'arcdegrees' | 'lux' | 'seconds';
|
||||||
|
maxValue?: number;
|
||||||
|
minValue?: number;
|
||||||
|
minStep?: number;
|
||||||
|
}>;
|
||||||
|
}>;
|
||||||
|
}>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IServiceType {
|
||||||
|
aid: number;
|
||||||
|
iid: number;
|
||||||
|
uuid: string;
|
||||||
|
type: string;
|
||||||
|
linked?: Array<number>;
|
||||||
|
linkedServices?: {
|
||||||
|
[iid: number]: IServiceType;
|
||||||
|
};
|
||||||
|
hidden?: boolean;
|
||||||
|
humanType: string;
|
||||||
|
serviceName: string;
|
||||||
|
serviceCharacteristics: ICharacteristicType[];
|
||||||
|
accessoryInformation: any;
|
||||||
|
refreshCharacteristics?: () => Promise<IServiceType>;
|
||||||
|
setCharacteristic?: (iid: number, value: number | string | boolean) => Promise<IServiceType | ICharacteristicType>;
|
||||||
|
getCharacteristic?: (type: string) => ICharacteristicType;
|
||||||
|
values: any;
|
||||||
|
instance: {
|
||||||
|
ipAddress: string;
|
||||||
|
port: number;
|
||||||
|
username: string;
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
uniqueId?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICharacteristicType {
|
||||||
|
aid: number;
|
||||||
|
iid: number;
|
||||||
|
uuid: string;
|
||||||
|
type: string;
|
||||||
|
serviceType: string;
|
||||||
|
serviceName: string;
|
||||||
|
description: string;
|
||||||
|
value: number | string | boolean;
|
||||||
|
format: 'bool' | 'int' | 'float' | 'string' | 'uint8' | 'uint16' | 'uint32' | 'uint64' | 'data' | 'tlv8' | 'array' | 'dictionary';
|
||||||
|
perms: Array<'pr' | 'pw' | 'ev' | 'aa' | 'tw' | 'hd'>;
|
||||||
|
unit?: 'unit' | 'percentage' | 'celsius' | 'arcdegrees' | 'lux' | 'seconds';
|
||||||
|
maxValue?: number;
|
||||||
|
minValue?: number;
|
||||||
|
minStep?: number;
|
||||||
|
canRead: boolean;
|
||||||
|
canWrite: boolean;
|
||||||
|
ev: boolean;
|
||||||
|
setValue?: (value: number | string | boolean) => Promise<ICharacteristicType>;
|
||||||
|
getValue?: () => Promise<ICharacteristicType>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const createDefaultCharacteristicType = (): ICharacteristicType => {
|
||||||
|
return {
|
||||||
|
aid: -1,
|
||||||
|
iid: -1,
|
||||||
|
uuid: "",
|
||||||
|
type: "",
|
||||||
|
serviceType: "",
|
||||||
|
serviceName: "",
|
||||||
|
description: "",
|
||||||
|
value: "",
|
||||||
|
format: 'bool',
|
||||||
|
perms: [],
|
||||||
|
canRead: false,
|
||||||
|
canWrite: false,
|
||||||
|
ev: false,
|
||||||
|
};
|
||||||
|
}
|
117
src/3rdParty/HapClient/monitor.ts
vendored
Executable file
117
src/3rdParty/HapClient/monitor.ts
vendored
Executable file
@ -0,0 +1,117 @@
|
|||||||
|
import { EventEmitter } from 'events';
|
||||||
|
import { IServiceType, IHapEvInstance } from './interfaces';
|
||||||
|
import { createConnection, parseMessage } from './eventedHttpClient';
|
||||||
|
import { CharacteristicType } from '.';
|
||||||
|
|
||||||
|
export class HapMonitor extends EventEmitter {
|
||||||
|
private pin: string;
|
||||||
|
private evInstances: IHapEvInstance[];
|
||||||
|
private services: IServiceType[];
|
||||||
|
private logger: any;
|
||||||
|
private debug: any;
|
||||||
|
|
||||||
|
constructor(logger: any, debug: any, pin: string, services: IServiceType[]) {
|
||||||
|
super();
|
||||||
|
this.logger = logger;
|
||||||
|
this.debug = debug;
|
||||||
|
this.pin = pin;
|
||||||
|
this.services = services;
|
||||||
|
this.evInstances = [];
|
||||||
|
|
||||||
|
// get a list of characteristics we can watch for each instance
|
||||||
|
this.parseServices();
|
||||||
|
|
||||||
|
// start watching
|
||||||
|
this.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
for (const instance of this.evInstances) {
|
||||||
|
instance.socket = createConnection(instance, this.pin, { characteristics: instance.evCharacteristics });
|
||||||
|
|
||||||
|
this.debug(`[HapClient] [${instance.ipAddress}:${instance.port} (${instance.username})] Connected`);
|
||||||
|
|
||||||
|
instance.socket.on('data', (data) => {
|
||||||
|
const message = parseMessage(data);
|
||||||
|
|
||||||
|
|
||||||
|
if (message.statusCode === 401) {
|
||||||
|
if (this.logger) {
|
||||||
|
this.logger.warn(`[HapClient] [${instance.ipAddress}:${instance.port} (${instance.username})] ` +
|
||||||
|
`${message.statusCode} ${message.statusMessage} - make sure Homebridge pin for this instance is set to ${this.pin}.`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (message.protocol === 'EVENT') {
|
||||||
|
try {
|
||||||
|
const body = JSON.parse(message.body);
|
||||||
|
if (body.characteristics && body.characteristics.length) {
|
||||||
|
this.debug(`[HapClient] [${instance.ipAddress}:${instance.port} (${instance.username})] ` +
|
||||||
|
`Got Event: ${JSON.stringify(body.characteristics)}`);
|
||||||
|
|
||||||
|
const response = body.characteristics.map((c: CharacteristicType): IServiceType | undefined => {
|
||||||
|
// find the matching service for each characteristics
|
||||||
|
const service = this.services.find(x => x.aid === c.aid && x.instance.username === instance.username);
|
||||||
|
|
||||||
|
if (service) {
|
||||||
|
// find the correct characteristic and update it
|
||||||
|
const characteristic = service.serviceCharacteristics.find(x => x.iid === c.iid);
|
||||||
|
if (characteristic) {
|
||||||
|
characteristic.value = c.value;
|
||||||
|
service.values[characteristic.type] = c.value;
|
||||||
|
return service;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// push update to listeners
|
||||||
|
this.emit('service-update', response.filter((x: any) => x));
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
finish() {
|
||||||
|
for (const instance of this.evInstances) {
|
||||||
|
if (instance.socket) {
|
||||||
|
try {
|
||||||
|
instance.socket.destroy();
|
||||||
|
this.debug(`[HapClient] [${instance.ipAddress}:${instance.port} (${instance.username})] Disconnected`);
|
||||||
|
} catch (e) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parseServices() {
|
||||||
|
// get a list of characteristics we can watch for each instance
|
||||||
|
for (const service of this.services) {
|
||||||
|
const evCharacteristics = service.serviceCharacteristics.filter(x => x.perms.includes('ev'));
|
||||||
|
|
||||||
|
if (evCharacteristics.length) {
|
||||||
|
// register the instance if it's not already there
|
||||||
|
if (!this.evInstances.find(x => x.username === service.instance.username)) {
|
||||||
|
const newInstance = Object.assign({}, service.instance) as IHapEvInstance;
|
||||||
|
newInstance.evCharacteristics = [];
|
||||||
|
this.evInstances.push(newInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
const instance = this.evInstances.find(x => x.username === service.instance.username);
|
||||||
|
|
||||||
|
for (const evCharacteristic of evCharacteristics) {
|
||||||
|
if (!instance!.evCharacteristics!.find(x => x.aid === service.aid && x.iid === evCharacteristic.iid)) {
|
||||||
|
instance!.evCharacteristics!.push({ aid: service.aid, iid: evCharacteristic.iid, ev: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
src/Types/types.ts
Normal file
1
src/Types/types.ts
Normal file
@ -0,0 +1 @@
|
|||||||
|
export type Dictionary<T> = { [key: string]: T };
|
16
src/index.ts
16
src/index.ts
@ -1,3 +1,6 @@
|
|||||||
|
import { HapClient } from "./3rdParty/HapClient";
|
||||||
|
import { HapMonitor } from "./3rdParty/HapClient/monitor";
|
||||||
|
|
||||||
let Accessory: any;
|
let Accessory: any;
|
||||||
let Homebridge: any;
|
let Homebridge: any;
|
||||||
|
|
||||||
@ -20,6 +23,7 @@ class AutomationPlatform {
|
|||||||
log: any = {};
|
log: any = {};
|
||||||
config: any = {};
|
config: any = {};
|
||||||
api: any;
|
api: any;
|
||||||
|
client: HapClient;
|
||||||
|
|
||||||
constructor(log: any, config: any, api: any) {
|
constructor(log: any, config: any, api: any) {
|
||||||
this.log = log;
|
this.log = log;
|
||||||
@ -28,8 +32,16 @@ class AutomationPlatform {
|
|||||||
this.log('INFO - Registering automation platform');
|
this.log('INFO - Registering automation platform');
|
||||||
this.api.on('didFinishLaunching', this.didFinishLaunching.bind(this));
|
this.api.on('didFinishLaunching', this.didFinishLaunching.bind(this));
|
||||||
|
|
||||||
// let asdf: any = api.getAllServices();
|
this.client = new HapClient({
|
||||||
// let asdff = "asdf";
|
pin: "031-45-154",
|
||||||
|
logger: log,
|
||||||
|
config: config
|
||||||
|
});
|
||||||
|
|
||||||
|
this.client.on('instance-discovered', async (instance: any) => {
|
||||||
|
let asdf = instance;
|
||||||
|
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user