iobroker.tapo 0.4.1 → 0.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -0
- package/build/lib/utils/camera/tapoCamera.js +17 -2
- package/build/lib/utils/camera/tapoCamera.js.map +2 -2
- package/build/lib/utils/p100.js +98 -22
- package/build/lib/utils/p100.js.map +3 -3
- package/build/main.js +18 -9
- package/build/main.js.map +2 -2
- package/io-package.json +99 -68
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -32,6 +32,10 @@ tapo.0.id.remote auf true/false setzen steuert den jeweiligen Befehl. Der Befehl
|
|
|
32
32
|
<https://forum.iobroker.net/topic/57336/test-adapter-tp-link-tapo/>
|
|
33
33
|
|
|
34
34
|
## Changelog
|
|
35
|
+
### 0.4.2 (2024-12-09)
|
|
36
|
+
|
|
37
|
+
- fix handshake for device with HW v1.20
|
|
38
|
+
|
|
35
39
|
### 0.4.1 (2024-11-29)
|
|
36
40
|
|
|
37
41
|
- fixed Get Device Info failed error
|
|
@@ -161,7 +161,15 @@ const _TAPOCamera = class extends import_onvifCamera.OnvifCamera {
|
|
|
161
161
|
})
|
|
162
162
|
};
|
|
163
163
|
}
|
|
164
|
-
const responseLogin = await this.fetch(`https://${this.config.ipAddress}`, fetchParams)
|
|
164
|
+
const responseLogin = await this.fetch(`https://${this.config.ipAddress}`, fetchParams).catch((e) => {
|
|
165
|
+
this.log.debug("refreshStok: Error during login", e);
|
|
166
|
+
return null;
|
|
167
|
+
});
|
|
168
|
+
if (!responseLogin) {
|
|
169
|
+
this.log.debug("refreshStok: empty response login, raising exception");
|
|
170
|
+
this.log.error("Empty response login");
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
165
173
|
const responseLoginData = await responseLogin.json();
|
|
166
174
|
let response, responseData;
|
|
167
175
|
if (!responseLoginData) {
|
|
@@ -369,7 +377,14 @@ const _TAPOCamera = class extends import_onvifCamera.OnvifCamera {
|
|
|
369
377
|
} else {
|
|
370
378
|
fetchParams.body = JSON.stringify(req);
|
|
371
379
|
}
|
|
372
|
-
const response = await this.fetch(url, fetchParams)
|
|
380
|
+
const response = await this.fetch(url, fetchParams).catch((e) => {
|
|
381
|
+
this.log.debug("Error during camera fetch", e);
|
|
382
|
+
return;
|
|
383
|
+
});
|
|
384
|
+
if (!response) {
|
|
385
|
+
this.log.debug("API request failed, empty response");
|
|
386
|
+
return {};
|
|
387
|
+
}
|
|
373
388
|
const responseDataTmp = await response.json();
|
|
374
389
|
if (isSecureConnection && response.status === 500) {
|
|
375
390
|
this.log.debug("Stok expired, reauthenticating on next request, setting STOK to undefined");
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/lib/utils/camera/tapoCamera.ts"],
|
|
4
|
-
"sourcesContent": ["// import https, { Agent } from \"https\";\nimport crypto from \"crypto\";\nimport { OnvifCamera } from \"./onvifCamera\";\nimport type {\n TAPOBasicInfo,\n TAPOCameraEncryptedRequest,\n TAPOCameraEncryptedResponse,\n TAPOCameraLoginResponse,\n TAPOCameraRefreshStokResponse,\n TAPOCameraRequest,\n TAPOCameraResponse,\n TAPOCameraResponseDeviceInfo,\n TAPOCameraSetRequest,\n} from \"./types/tapo\";\n\nconst MAX_LOGIN_RETRIES = 3;\nconst AES_BLOCK_SIZE = 16;\n\nimport { Agent, setGlobalDispatcher } from \"undici\";\n\nconst ERROR_CODES_MAP = {\n \"-40401\": \"Invalid stok value\",\n \"-40210\": \"Function not supported\",\n \"-64303\": \"Action cannot be done while camera is in patrol mode.\",\n \"-64324\": \"Privacy mode is ON, not able to execute\",\n \"-64302\": \"Preset ID not found\",\n \"-64321\": \"Preset ID was deleted so no longer exists\",\n \"-40106\": \"Parameter to get/do does not exist\",\n \"-40105\": \"Method does not exist\",\n \"-40101\": \"Parameter to set does not exist\",\n \"-40209\": \"Invalid login credentials\",\n \"-64304\": \"Maximum Pan/Tilt range reached\",\n \"-71103\": \"User ID is not authorized\",\n};\n\nexport type Status = {\n eyes: boolean | undefined;\n alarm: boolean | undefined;\n notifications: boolean | undefined;\n motionDetection: boolean | undefined;\n led: boolean | undefined;\n};\ntype CameraConfig = {\n name: string;\n ipAddress: string;\n username: string;\n password: string;\n streamUser: string;\n streamPassword: string;\n\n pullInterval?: number;\n disableStreaming?: boolean;\n disableEyesToggleAccessory?: boolean;\n disableAlarmToggleAccessory?: boolean;\n disableNotificationsToggleAccessory?: boolean;\n disableMotionDetectionToggleAccessory?: boolean;\n disableLEDToggleAccessory?: boolean;\n\n disableMotionSensorAccessory?: boolean;\n lowQuality?: boolean;\n\n videoMaxWidth?: number;\n videoMaxHeight?: number;\n videoMaxFPS?: number;\n videoForceMax?: boolean;\n videoMaxBirate?: number;\n videoPacketSize?: number;\n videoCodec?: string;\n\n videoConfig?: VideoConfig;\n\n eyesToggleAccessoryName?: string;\n alarmToggleAccessoryName?: string;\n notificationsToggleAccessoryName?: string;\n motionDetectionToggleAccessoryName?: string;\n ledToggleAccessoryName?: string;\n};\nexport class TAPOCamera extends OnvifCamera {\n private readonly kStreamPort = 554;\n private readonly fetchAgent: Agent;\n\n private readonly hashedPassword: string;\n private readonly hashedSha256Password: string;\n private passwordEncryptionMethod: \"md5\" | \"sha256\" | null = null;\n\n private isSecureConnectionValue: boolean | null = null;\n\n private stokPromise: (() => Promise<void>) | undefined;\n\n private readonly cnonce: string;\n private lsk: Buffer | undefined;\n private ivb: Buffer | undefined;\n private seq: number | undefined;\n private stok: string | undefined;\n\n constructor(\n protected readonly log: any,\n protected readonly config: CameraConfig,\n ) {\n super(log, config);\n process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;\n this.fetchAgent = new Agent({\n connectTimeout: 5_000,\n connect: {\n // TAPO devices have self-signed certificates\n rejectUnauthorized: false,\n ciphers: \"AES256-SHA:AES128-GCM-SHA256\",\n },\n });\n setGlobalDispatcher(this.fetchAgent);\n\n this.cnonce = this.generateCnonce();\n\n this.hashedPassword = crypto.createHash(\"md5\").update(config.password).digest(\"hex\").toUpperCase();\n this.hashedSha256Password = crypto.createHash(\"sha256\").update(config.password).digest(\"hex\").toUpperCase();\n }\n\n private getUsername() {\n return this.config.username || \"admin\";\n }\n\n private getHeaders(): Record<string, string> {\n return {\n Host: `https://${this.config.ipAddress}`,\n Referer: `https://${this.config.ipAddress}`,\n Accept: \"application/json\",\n \"Accept-Encoding\": \"gzip, deflate\",\n \"User-Agent\": \"Tapo CameraClient Android\",\n Connection: \"close\",\n requestByApp: \"true\",\n \"Content-Type\": \"application/json; charset=UTF-8\",\n };\n }\n\n private getHashedPassword() {\n if (this.passwordEncryptionMethod === \"md5\") {\n return this.hashedPassword;\n } else if (this.passwordEncryptionMethod === \"sha256\") {\n return this.hashedSha256Password;\n } else {\n this.log.error(\"Unknown password encryption method\");\n }\n }\n\n private fetch(url: string, data: RequestInit) {\n return fetch(url, {\n headers: this.getHeaders(),\n // @ts-expect-error Dispatcher type not there\n dispatcher: this.fetchAgent,\n ...data,\n });\n }\n\n private generateEncryptionToken(tokenType: string, nonce: string): Buffer {\n const hashedKey = crypto\n .createHash(\"sha256\")\n .update(this.cnonce + this.getHashedPassword() + nonce)\n .digest(\"hex\")\n .toUpperCase();\n return crypto\n .createHash(\"sha256\")\n .update(tokenType + this.cnonce + nonce + hashedKey)\n .digest()\n .slice(0, 16);\n }\n\n getAuthenticatedStreamUrl(lowQuality = false) {\n const prefix = `rtsp://${this.config.streamUser}:${this.config.streamPassword}@${this.config.ipAddress}:${this.kStreamPort}`;\n return lowQuality ? `${prefix}/stream2` : `${prefix}/stream1`;\n }\n\n private generateCnonce() {\n return crypto.randomBytes(8).toString(\"hex\").toUpperCase();\n }\n\n private validateDeviceConfirm(nonce: string, deviceConfirm: string) {\n this.passwordEncryptionMethod = null;\n\n const hashedNoncesWithSHA256 = crypto\n .createHash(\"sha256\")\n .update(this.cnonce + this.hashedSha256Password + nonce)\n .digest(\"hex\")\n .toUpperCase();\n if (deviceConfirm === hashedNoncesWithSHA256 + nonce + this.cnonce) {\n this.passwordEncryptionMethod = \"sha256\";\n return true;\n }\n\n const hashedNoncesWithMD5 = crypto\n .createHash(\"md5\")\n .update(this.cnonce + this.hashedPassword + nonce)\n .digest(\"hex\")\n .toUpperCase();\n if (deviceConfirm === hashedNoncesWithMD5 + nonce + this.cnonce) {\n this.passwordEncryptionMethod = \"md5\";\n return true;\n }\n\n this.log.debug('Invalid device confirm, expected \"sha256\" or \"md5\" to match, but none found', {\n hashedNoncesWithMD5,\n hashedNoncesWithSHA256,\n deviceConfirm,\n nonce,\n cnonce: this,\n });\n\n return this.passwordEncryptionMethod !== null;\n }\n\n async refreshStok(loginRetryCount = 0): Promise<void> {\n this.log.debug(\"refreshStok: Refreshing stok...\");\n\n const isSecureConnection = await this.isSecureConnection();\n\n let fetchParams = {};\n if (isSecureConnection) {\n fetchParams = {\n method: \"post\",\n body: JSON.stringify({\n method: \"login\",\n params: {\n cnonce: this.cnonce,\n encrypt_type: \"3\",\n username: this.getUsername(),\n },\n }),\n };\n } else {\n fetchParams = {\n method: \"post\",\n body: JSON.stringify({\n method: \"login\",\n params: {\n username: this.getUsername(),\n password: this.hashedPassword,\n hashed: true,\n },\n }),\n };\n }\n\n const responseLogin = await this.fetch(`https://${this.config.ipAddress}`, fetchParams);\n const responseLoginData = (await responseLogin.json()) as TAPOCameraRefreshStokResponse;\n\n let response, responseData;\n\n if (!responseLoginData) {\n this.log.debug(\"refreshStok: empty response login data, raising exception\", responseLogin.status);\n this.log.error(\"Empty response login data\");\n }\n\n this.log.debug(\"refreshStok: Login response\", responseLogin.status, responseLoginData);\n\n if (responseLogin.status === 401 && responseLoginData.result?.data?.code === -40411) {\n this.log.debug(\"refreshStok: invalid credentials, raising exception\", responseLogin.status);\n this.log.error(\"Invalid credentials\");\n }\n\n if (isSecureConnection) {\n const nonce = responseLoginData.result?.data?.nonce;\n const deviceConfirm = responseLoginData.result?.data?.device_confirm;\n if (nonce && deviceConfirm && this.validateDeviceConfirm(nonce, deviceConfirm)) {\n const digestPasswd = crypto\n .createHash(\"sha256\")\n .update(this.getHashedPassword() + this.cnonce + nonce)\n .digest(\"hex\")\n .toUpperCase();\n\n const digestPasswdFull = Buffer.concat([\n Buffer.from(digestPasswd, \"utf8\"),\n Buffer.from(this.cnonce!, \"utf8\"),\n Buffer.from(nonce, \"utf8\"),\n ]).toString(\"utf8\");\n\n this.log.debug(\"refreshStok: sending start_seq request\");\n\n response = await this.fetch(`https://${this.config.ipAddress}`, {\n method: \"POST\",\n body: JSON.stringify({\n method: \"login\",\n params: {\n cnonce: this.cnonce,\n encrypt_type: \"3\",\n digest_passwd: digestPasswdFull,\n username: this.getUsername(),\n },\n }),\n });\n\n responseData = (await response.json()) as TAPOCameraRefreshStokResponse;\n\n if (!responseData) {\n this.log.debug(\"refreshStock: empty response start_seq data, raising exception\", response.status);\n this.log.error(\"Empty response start_seq data\");\n return;\n }\n\n this.log.debug(\"refreshStok: start_seq response\", response.status, JSON.stringify(responseData));\n\n if (responseData.result?.start_seq) {\n if (responseData.result?.user_group !== \"root\") {\n this.log.debug(\"refreshStock: Incorrect user_group detected\");\n\n // # encrypted control via 3rd party account does not seem to be supported\n // # see https://github.com/JurajNyiri/HomeAssistant-Tapo-Control/issues/456\n this.log.error(\"Incorrect user_group detected\");\n }\n\n this.lsk = this.generateEncryptionToken(\"lsk\", nonce);\n this.ivb = this.generateEncryptionToken(\"ivb\", nonce);\n this.seq = responseData.result.start_seq;\n }\n } else {\n if (responseLoginData.error_code === -40413 && loginRetryCount < MAX_LOGIN_RETRIES) {\n this.log.debug(\n `refreshStock: Invalid device confirm, retrying: ${loginRetryCount}/${MAX_LOGIN_RETRIES}.`,\n responseLogin.status,\n responseLoginData,\n );\n return this.refreshStok(loginRetryCount + 1);\n }\n\n this.log.debug(\n \"refreshStock: Invalid device confirm and loginRetryCount exhausted, raising exception\",\n loginRetryCount,\n responseLoginData,\n );\n this.log.error(\"Invalid device confirm. Firmware Fix by TP-Link expected in Dezember 2024. Only motion detection is supported.\");\n this.log.error(\"Or follow https://github.com/JurajNyiri/HomeAssistant-Tapo-Control/blob/main/add_camera_with_new_firmware.md\");\n return;\n }\n } else {\n this.passwordEncryptionMethod = \"md5\";\n response = responseLogin;\n responseData = responseLoginData;\n }\n\n if (responseData.result?.data?.sec_left && responseData.result.data.sec_left > 0) {\n this.log.debug(\"refreshStok: temporary suspension\", responseData);\n\n this.log.error(`Temporary Suspension: Try again in ${responseData.result.data.sec_left} seconds`);\n }\n\n if (responseData?.data?.code === -40404 && responseData?.data?.sec_left && responseData.data.sec_left > 0) {\n this.log.debug(\"refreshStok: temporary suspension\", responseData);\n\n this.log.error(`refreshStok: Temporary Suspension: Try again in ${responseData.data.sec_left} seconds`);\n }\n\n if (responseData?.result?.stok) {\n this.stok = responseData.result.stok;\n this.log.debug(\"refreshStok: Success in obtaining STOK\", this.stok);\n return;\n }\n\n if (responseData?.error_code === -40413 && loginRetryCount < MAX_LOGIN_RETRIES) {\n this.log.debug(\n `refreshStock: Unexpected response, retrying: ${loginRetryCount}/${MAX_LOGIN_RETRIES}.`,\n response.status,\n responseData,\n );\n return this.refreshStok(loginRetryCount + 1);\n }\n\n this.log.debug(\"refreshStock: Unexpected end of flow, raising exception\");\n this.log.error(\"Invalid authentication data\");\n }\n\n async isSecureConnection() {\n if (this.isSecureConnectionValue === null) {\n this.log.debug(\"isSecureConnection: Checking secure connection...\");\n\n const response = await this.fetch(`https://${this.config.ipAddress}`, {\n method: \"post\",\n body: JSON.stringify({\n method: \"login\",\n params: {\n encrypt_type: \"3\",\n username: this.getUsername(),\n },\n }),\n });\n const responseData = (await response.json()) as TAPOCameraLoginResponse;\n\n this.log.debug(\"isSecureConnection response\", response.status, JSON.stringify(responseData));\n\n this.isSecureConnectionValue =\n responseData?.error_code == -40413 && String(responseData.result?.data?.encrypt_type || \"\")?.includes(\"3\");\n }\n\n return this.isSecureConnectionValue;\n }\n\n getStok(loginRetryCount = 0): Promise<string> {\n return new Promise((resolve) => {\n if (this.stok) {\n return resolve(this.stok);\n }\n\n if (!this.stokPromise) {\n this.stokPromise = () => this.refreshStok(loginRetryCount);\n }\n\n this.stokPromise()\n .then(() => {\n if (!this.stok) {\n this.log.error(\"STOK not found\");\n }\n resolve(this.stok!);\n })\n .finally(() => {\n this.stokPromise = undefined;\n });\n });\n }\n\n private async getAuthenticatedAPIURL(loginRetryCount = 0) {\n const token = await this.getStok(loginRetryCount);\n return `https://${this.config.ipAddress}/stok=${token}/ds`;\n }\n\n encryptRequest(request: string) {\n const cipher = crypto.createCipheriv(\"aes-128-cbc\", this.lsk!, this.ivb!);\n let ct_bytes = cipher.update(this.encryptPad(request, AES_BLOCK_SIZE), \"utf-8\", \"hex\");\n ct_bytes += cipher.final(\"hex\");\n return Buffer.from(ct_bytes, \"hex\");\n }\n\n private encryptPad(text: string, blocksize: number) {\n const padSize = blocksize - (text.length % blocksize);\n const padding = String.fromCharCode(padSize).repeat(padSize);\n return text + padding;\n }\n\n private decryptResponse(response: string): string {\n const decipher = crypto.createDecipheriv(\"aes-128-cbc\", this.lsk!, this.ivb!);\n let decrypted = decipher.update(response, \"base64\", \"utf-8\");\n decrypted += decipher.final(\"utf-8\");\n return this.encryptUnpad(decrypted, AES_BLOCK_SIZE);\n }\n\n private encryptUnpad(text: string, blockSize: number): string {\n const paddingLength = Number(text[text.length - 1]) || 0;\n if (paddingLength > blockSize || paddingLength > text.length) {\n this.log.error(\"Invalid padding\");\n }\n for (let i = text.length - paddingLength; i < text.length; i++) {\n if (text.charCodeAt(i) !== paddingLength) {\n this.log.error(\"Invalid padding\");\n }\n }\n return text.slice(0, text.length - paddingLength).toString();\n }\n\n private getTapoTag(request: TAPOCameraEncryptedRequest) {\n const tag = crypto\n .createHash(\"sha256\")\n .update(this.getHashedPassword() + this.cnonce)\n .digest(\"hex\")\n .toUpperCase();\n return crypto\n .createHash(\"sha256\")\n .update(tag + JSON.stringify(request) + this.seq!.toString())\n .digest(\"hex\")\n .toUpperCase();\n }\n\n private pendingAPIRequests: Map<string, Promise<TAPOCameraResponse>> = new Map();\n\n private async apiRequest(req: TAPOCameraRequest, loginRetryCount = 0): Promise<TAPOCameraResponse> {\n const reqJson = JSON.stringify(req);\n\n if (this.pendingAPIRequests.has(reqJson)) {\n this.log.debug(\"API request already pending\", reqJson);\n return this.pendingAPIRequests.get(reqJson) as Promise<TAPOCameraResponse>;\n } else {\n this.log.debug(\"New API request\", reqJson);\n }\n\n this.pendingAPIRequests.set(\n reqJson,\n (async () => {\n try {\n const isSecureConnection = await this.isSecureConnection();\n const url = await this.getAuthenticatedAPIURL(loginRetryCount);\n\n const fetchParams: RequestInit = {\n method: \"post\",\n };\n\n if (this.seq && isSecureConnection) {\n const encryptedRequest: TAPOCameraEncryptedRequest = {\n method: \"securePassthrough\",\n params: {\n request: Buffer.from(this.encryptRequest(JSON.stringify(req))).toString(\"base64\"),\n },\n };\n fetchParams.headers = {\n ...this.getHeaders(),\n Tapo_tag: this.getTapoTag(encryptedRequest),\n Seq: this.seq.toString(),\n };\n fetchParams.body = JSON.stringify(encryptedRequest);\n this.seq += 1;\n } else {\n fetchParams.body = JSON.stringify(req);\n }\n\n const response = await this.fetch(url, fetchParams);\n const responseDataTmp = await response.json();\n\n // Apparently the Tapo C200 returns 500 on successful requests,\n // but it's indicating an expiring token, therefore refresh the token next time\n if (isSecureConnection && response.status === 500) {\n this.log.debug(\"Stok expired, reauthenticating on next request, setting STOK to undefined\");\n this.stok = undefined;\n }\n\n let responseData: TAPOCameraResponse | null = null;\n\n if (isSecureConnection) {\n const encryptedResponse = responseDataTmp as TAPOCameraEncryptedResponse;\n if (encryptedResponse?.result?.response) {\n const decryptedResponse = this.decryptResponse(encryptedResponse.result.response);\n responseData = JSON.parse(decryptedResponse) as TAPOCameraResponse;\n }\n } else {\n responseData = responseDataTmp as TAPOCameraResponse;\n }\n\n this.log.debug(\"API response\", response.status, JSON.stringify(responseData));\n\n // Log error codes\n if (responseData && responseData.error_code !== 0) {\n const errorCode = String(responseData.error_code);\n const errorMessage =\n errorCode in ERROR_CODES_MAP ? ERROR_CODES_MAP[errorCode as keyof typeof ERROR_CODES_MAP] : \"Unknown error\";\n this.log.debug(`API request failed with specific error code ${errorCode}: ${errorMessage}`);\n }\n\n if (!responseData || responseData.error_code === -40401 || responseData.error_code === -1) {\n this.log.debug(\"API request failed\", responseData);\n this.stok = undefined;\n return {} as TAPOCameraResponse;\n // return this.apiRequest(req, loginRetryCount + 1);\n }\n\n // Success\n return responseData;\n } finally {\n this.pendingAPIRequests.delete(reqJson);\n }\n })(),\n );\n\n return this.pendingAPIRequests.get(reqJson) as Promise<TAPOCameraResponse>;\n }\n\n static SERVICE_MAP: Record<keyof Status, (value: boolean) => TAPOCameraSetRequest> = {\n eyes: (value) => ({\n method: \"setLensMaskConfig\",\n params: {\n lens_mask: {\n lens_mask_info: {\n // Watch out for the inversion\n enabled: value ? \"off\" : \"on\",\n },\n },\n },\n }),\n alarm: (value) => ({\n method: \"setAlertConfig\",\n params: {\n msg_alarm: {\n chn1_msg_alarm_info: {\n enabled: value ? \"on\" : \"off\",\n },\n },\n },\n }),\n notifications: (value) => ({\n method: \"setMsgPushConfig\",\n params: {\n msg_push: {\n chn1_msg_push_info: {\n notification_enabled: value ? \"on\" : \"off\",\n rich_notification_enabled: value ? \"on\" : \"off\",\n },\n },\n },\n }),\n motionDetection: (value) => ({\n method: \"setDetectionConfig\",\n params: {\n motion_detection: {\n motion_det: {\n enabled: value ? \"on\" : \"off\",\n },\n },\n },\n }),\n led: (value) => ({\n method: \"setLedStatus\",\n params: {\n led: {\n config: {\n enabled: value ? \"on\" : \"off\",\n },\n },\n },\n }),\n };\n\n async setStatus(service: keyof Status, value: boolean) {\n const responseData = await this.apiRequest({\n method: \"multipleRequest\",\n params: {\n requests: [TAPOCamera.SERVICE_MAP[service](value)],\n },\n });\n\n if (responseData.error_code !== 0) {\n this.log.error(`Failed to perform ${service} action`);\n }\n\n const method = TAPOCamera.SERVICE_MAP[service](value).method;\n const operation = responseData.result.responses.find((e) => e.method === method);\n if (operation?.error_code !== 0) {\n this.log.error(`Failed to perform ${service} action`);\n }\n\n return operation.result;\n }\n\n async getBasicInfo(): Promise<TAPOBasicInfo> {\n const responseData = await this.apiRequest({\n method: \"multipleRequest\",\n params: {\n requests: [\n {\n method: \"getDeviceInfo\",\n params: {\n device_info: {\n name: [\"basic_info\"],\n },\n },\n },\n ],\n },\n });\n\n const info = responseData.result.responses[0] as TAPOCameraResponseDeviceInfo;\n return info.result.device_info.basic_info;\n }\n\n async getStatus(): Promise<Status> {\n const responseData = await this.apiRequest({\n method: \"multipleRequest\",\n params: {\n requests: [\n {\n method: \"getAlertConfig\",\n params: {\n msg_alarm: {\n name: \"chn1_msg_alarm_info\",\n },\n },\n },\n {\n method: \"getLensMaskConfig\",\n params: {\n lens_mask: {\n name: \"lens_mask_info\",\n },\n },\n },\n {\n method: \"getMsgPushConfig\",\n params: {\n msg_push: {\n name: \"chn1_msg_push_info\",\n },\n },\n },\n {\n method: \"getDetectionConfig\",\n params: {\n motion_detection: {\n name: \"motion_det\",\n },\n },\n },\n {\n method: \"getLedStatus\",\n params: {\n led: {\n name: \"config\",\n },\n },\n },\n ],\n },\n });\n\n if (!responseData || !responseData.result || !responseData.result.responses) {\n this.log.error(\"No response data found\");\n return {\n alarm: undefined,\n eyes: undefined,\n notifications: undefined,\n motionDetection: undefined,\n led: undefined,\n };\n }\n const operations = responseData.result.responses;\n\n const alert = operations.find((r) => r.method === \"getAlertConfig\");\n const lensMask = operations.find((r) => r.method === \"getLensMaskConfig\");\n const notifications = operations.find((r) => r.method === \"getMsgPushConfig\");\n const motionDetection = operations.find((r) => r.method === \"getDetectionConfig\");\n const led = operations.find((r) => r.method === \"getLedStatus\");\n\n if (!alert) this.log.debug(\"No alert config found\");\n if (!lensMask) this.log.debug(\"No lens mask config found\");\n if (!notifications) this.log.debug(\"No notifications config found\");\n if (!motionDetection) this.log.debug(\"No motion detection config found\");\n if (!led) this.log.debug(\"No led config found\");\n\n return {\n alarm: alert ? alert.result.msg_alarm.chn1_msg_alarm_info.enabled === \"on\" : undefined,\n // Watch out for the inversion\n eyes: lensMask ? lensMask.result.lens_mask.lens_mask_info.enabled === \"off\" : undefined,\n notifications: notifications ? notifications.result.msg_push.chn1_msg_push_info.notification_enabled === \"on\" : undefined,\n motionDetection: motionDetection ? motionDetection.result.motion_detection.motion_det.enabled === \"on\" : undefined,\n led: led ? led.result.led.config.enabled === \"on\" : undefined,\n };\n }\n async setForceWhitelampState(value: boolean) {\n const json = await this.apiRequest({\n method: \"multipleRequest\",\n params: {\n requests: [\n {\n method: \"setForceWhitelampState\",\n params: {\n image: {\n switch: {\n force_wtl_state: value ? \"on\" : \"off\",\n },\n },\n },\n },\n ],\n },\n });\n\n return json.error_code !== 0;\n }\n async moveMotorStep(angle: string) {\n angle = angle.toString();\n const json = await this.apiRequest({ method: \"do\", motor: { movestep: { direction: angle } } });\n\n return json.error_code !== 0;\n }\n\n async moveMotor(x: number, y: number) {\n const json = await this.apiRequest({\n method: \"multipleRequest\",\n params: {\n requests: [{ method: \"do\", motor: { move: { x_coord: x, y_coord: y } } }],\n },\n });\n\n return json.error_code !== 0;\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["// import https, { Agent } from \"https\";\nimport crypto from \"crypto\";\nimport { OnvifCamera } from \"./onvifCamera\";\nimport type {\n TAPOBasicInfo,\n TAPOCameraEncryptedRequest,\n TAPOCameraEncryptedResponse,\n TAPOCameraLoginResponse,\n TAPOCameraRefreshStokResponse,\n TAPOCameraRequest,\n TAPOCameraResponse,\n TAPOCameraResponseDeviceInfo,\n TAPOCameraSetRequest,\n} from \"./types/tapo\";\n\nconst MAX_LOGIN_RETRIES = 3;\nconst AES_BLOCK_SIZE = 16;\n\nimport { Agent, setGlobalDispatcher } from \"undici\";\n\nconst ERROR_CODES_MAP = {\n \"-40401\": \"Invalid stok value\",\n \"-40210\": \"Function not supported\",\n \"-64303\": \"Action cannot be done while camera is in patrol mode.\",\n \"-64324\": \"Privacy mode is ON, not able to execute\",\n \"-64302\": \"Preset ID not found\",\n \"-64321\": \"Preset ID was deleted so no longer exists\",\n \"-40106\": \"Parameter to get/do does not exist\",\n \"-40105\": \"Method does not exist\",\n \"-40101\": \"Parameter to set does not exist\",\n \"-40209\": \"Invalid login credentials\",\n \"-64304\": \"Maximum Pan/Tilt range reached\",\n \"-71103\": \"User ID is not authorized\",\n};\n\nexport type Status = {\n eyes: boolean | undefined;\n alarm: boolean | undefined;\n notifications: boolean | undefined;\n motionDetection: boolean | undefined;\n led: boolean | undefined;\n};\ntype CameraConfig = {\n name: string;\n ipAddress: string;\n username: string;\n password: string;\n streamUser: string;\n streamPassword: string;\n\n pullInterval?: number;\n disableStreaming?: boolean;\n disableEyesToggleAccessory?: boolean;\n disableAlarmToggleAccessory?: boolean;\n disableNotificationsToggleAccessory?: boolean;\n disableMotionDetectionToggleAccessory?: boolean;\n disableLEDToggleAccessory?: boolean;\n\n disableMotionSensorAccessory?: boolean;\n lowQuality?: boolean;\n\n videoMaxWidth?: number;\n videoMaxHeight?: number;\n videoMaxFPS?: number;\n videoForceMax?: boolean;\n videoMaxBirate?: number;\n videoPacketSize?: number;\n videoCodec?: string;\n\n videoConfig?: VideoConfig;\n\n eyesToggleAccessoryName?: string;\n alarmToggleAccessoryName?: string;\n notificationsToggleAccessoryName?: string;\n motionDetectionToggleAccessoryName?: string;\n ledToggleAccessoryName?: string;\n};\nexport class TAPOCamera extends OnvifCamera {\n private readonly kStreamPort = 554;\n private readonly fetchAgent: Agent;\n\n private readonly hashedPassword: string;\n private readonly hashedSha256Password: string;\n private passwordEncryptionMethod: \"md5\" | \"sha256\" | null = null;\n\n private isSecureConnectionValue: boolean | null = null;\n\n private stokPromise: (() => Promise<void>) | undefined;\n\n private readonly cnonce: string;\n private lsk: Buffer | undefined;\n private ivb: Buffer | undefined;\n private seq: number | undefined;\n private stok: string | undefined;\n\n constructor(\n protected readonly log: any,\n protected readonly config: CameraConfig,\n ) {\n super(log, config);\n process.env.NODE_TLS_REJECT_UNAUTHORIZED = 0;\n this.fetchAgent = new Agent({\n connectTimeout: 5_000,\n connect: {\n // TAPO devices have self-signed certificates\n rejectUnauthorized: false,\n ciphers: \"AES256-SHA:AES128-GCM-SHA256\",\n },\n });\n setGlobalDispatcher(this.fetchAgent);\n\n this.cnonce = this.generateCnonce();\n\n this.hashedPassword = crypto.createHash(\"md5\").update(config.password).digest(\"hex\").toUpperCase();\n this.hashedSha256Password = crypto.createHash(\"sha256\").update(config.password).digest(\"hex\").toUpperCase();\n }\n\n private getUsername() {\n return this.config.username || \"admin\";\n }\n\n private getHeaders(): Record<string, string> {\n return {\n Host: `https://${this.config.ipAddress}`,\n Referer: `https://${this.config.ipAddress}`,\n Accept: \"application/json\",\n \"Accept-Encoding\": \"gzip, deflate\",\n \"User-Agent\": \"Tapo CameraClient Android\",\n Connection: \"close\",\n requestByApp: \"true\",\n \"Content-Type\": \"application/json; charset=UTF-8\",\n };\n }\n\n private getHashedPassword() {\n if (this.passwordEncryptionMethod === \"md5\") {\n return this.hashedPassword;\n } else if (this.passwordEncryptionMethod === \"sha256\") {\n return this.hashedSha256Password;\n } else {\n this.log.error(\"Unknown password encryption method\");\n }\n }\n\n private fetch(url: string, data: RequestInit) {\n return fetch(url, {\n headers: this.getHeaders(),\n // @ts-expect-error Dispatcher type not there\n dispatcher: this.fetchAgent,\n ...data,\n });\n }\n\n private generateEncryptionToken(tokenType: string, nonce: string): Buffer {\n const hashedKey = crypto\n .createHash(\"sha256\")\n .update(this.cnonce + this.getHashedPassword() + nonce)\n .digest(\"hex\")\n .toUpperCase();\n return crypto\n .createHash(\"sha256\")\n .update(tokenType + this.cnonce + nonce + hashedKey)\n .digest()\n .slice(0, 16);\n }\n\n getAuthenticatedStreamUrl(lowQuality = false) {\n const prefix = `rtsp://${this.config.streamUser}:${this.config.streamPassword}@${this.config.ipAddress}:${this.kStreamPort}`;\n return lowQuality ? `${prefix}/stream2` : `${prefix}/stream1`;\n }\n\n private generateCnonce() {\n return crypto.randomBytes(8).toString(\"hex\").toUpperCase();\n }\n\n private validateDeviceConfirm(nonce: string, deviceConfirm: string) {\n this.passwordEncryptionMethod = null;\n\n const hashedNoncesWithSHA256 = crypto\n .createHash(\"sha256\")\n .update(this.cnonce + this.hashedSha256Password + nonce)\n .digest(\"hex\")\n .toUpperCase();\n if (deviceConfirm === hashedNoncesWithSHA256 + nonce + this.cnonce) {\n this.passwordEncryptionMethod = \"sha256\";\n return true;\n }\n\n const hashedNoncesWithMD5 = crypto\n .createHash(\"md5\")\n .update(this.cnonce + this.hashedPassword + nonce)\n .digest(\"hex\")\n .toUpperCase();\n if (deviceConfirm === hashedNoncesWithMD5 + nonce + this.cnonce) {\n this.passwordEncryptionMethod = \"md5\";\n return true;\n }\n\n this.log.debug('Invalid device confirm, expected \"sha256\" or \"md5\" to match, but none found', {\n hashedNoncesWithMD5,\n hashedNoncesWithSHA256,\n deviceConfirm,\n nonce,\n cnonce: this,\n });\n\n return this.passwordEncryptionMethod !== null;\n }\n\n async refreshStok(loginRetryCount = 0): Promise<void> {\n this.log.debug(\"refreshStok: Refreshing stok...\");\n\n const isSecureConnection = await this.isSecureConnection();\n\n let fetchParams = {};\n if (isSecureConnection) {\n fetchParams = {\n method: \"post\",\n body: JSON.stringify({\n method: \"login\",\n params: {\n cnonce: this.cnonce,\n encrypt_type: \"3\",\n username: this.getUsername(),\n },\n }),\n };\n } else {\n fetchParams = {\n method: \"post\",\n body: JSON.stringify({\n method: \"login\",\n params: {\n username: this.getUsername(),\n password: this.hashedPassword,\n hashed: true,\n },\n }),\n };\n }\n\n const responseLogin = await this.fetch(`https://${this.config.ipAddress}`, fetchParams).catch((e) => {\n this.log.debug(\"refreshStok: Error during login\", e);\n return null;\n });\n if (!responseLogin) {\n this.log.debug(\"refreshStok: empty response login, raising exception\");\n this.log.error(\"Empty response login\");\n return;\n }\n const responseLoginData = (await responseLogin.json()) as TAPOCameraRefreshStokResponse;\n\n let response, responseData;\n\n if (!responseLoginData) {\n this.log.debug(\"refreshStok: empty response login data, raising exception\", responseLogin.status);\n this.log.error(\"Empty response login data\");\n }\n\n this.log.debug(\"refreshStok: Login response\", responseLogin.status, responseLoginData);\n\n if (responseLogin.status === 401 && responseLoginData.result?.data?.code === -40411) {\n this.log.debug(\"refreshStok: invalid credentials, raising exception\", responseLogin.status);\n this.log.error(\"Invalid credentials\");\n }\n\n if (isSecureConnection) {\n const nonce = responseLoginData.result?.data?.nonce;\n const deviceConfirm = responseLoginData.result?.data?.device_confirm;\n if (nonce && deviceConfirm && this.validateDeviceConfirm(nonce, deviceConfirm)) {\n const digestPasswd = crypto\n .createHash(\"sha256\")\n .update(this.getHashedPassword() + this.cnonce + nonce)\n .digest(\"hex\")\n .toUpperCase();\n\n const digestPasswdFull = Buffer.concat([\n Buffer.from(digestPasswd, \"utf8\"),\n Buffer.from(this.cnonce!, \"utf8\"),\n Buffer.from(nonce, \"utf8\"),\n ]).toString(\"utf8\");\n\n this.log.debug(\"refreshStok: sending start_seq request\");\n\n response = await this.fetch(`https://${this.config.ipAddress}`, {\n method: \"POST\",\n body: JSON.stringify({\n method: \"login\",\n params: {\n cnonce: this.cnonce,\n encrypt_type: \"3\",\n digest_passwd: digestPasswdFull,\n username: this.getUsername(),\n },\n }),\n });\n\n responseData = (await response.json()) as TAPOCameraRefreshStokResponse;\n\n if (!responseData) {\n this.log.debug(\"refreshStock: empty response start_seq data, raising exception\", response.status);\n this.log.error(\"Empty response start_seq data\");\n return;\n }\n\n this.log.debug(\"refreshStok: start_seq response\", response.status, JSON.stringify(responseData));\n\n if (responseData.result?.start_seq) {\n if (responseData.result?.user_group !== \"root\") {\n this.log.debug(\"refreshStock: Incorrect user_group detected\");\n\n // # encrypted control via 3rd party account does not seem to be supported\n // # see https://github.com/JurajNyiri/HomeAssistant-Tapo-Control/issues/456\n this.log.error(\"Incorrect user_group detected\");\n }\n\n this.lsk = this.generateEncryptionToken(\"lsk\", nonce);\n this.ivb = this.generateEncryptionToken(\"ivb\", nonce);\n this.seq = responseData.result.start_seq;\n }\n } else {\n if (responseLoginData.error_code === -40413 && loginRetryCount < MAX_LOGIN_RETRIES) {\n this.log.debug(\n `refreshStock: Invalid device confirm, retrying: ${loginRetryCount}/${MAX_LOGIN_RETRIES}.`,\n responseLogin.status,\n responseLoginData,\n );\n return this.refreshStok(loginRetryCount + 1);\n }\n\n this.log.debug(\n \"refreshStock: Invalid device confirm and loginRetryCount exhausted, raising exception\",\n loginRetryCount,\n responseLoginData,\n );\n this.log.error(\"Invalid device confirm. Firmware Fix by TP-Link expected in Dezember 2024. Only motion detection is supported.\");\n this.log.error(\"Or follow https://github.com/JurajNyiri/HomeAssistant-Tapo-Control/blob/main/add_camera_with_new_firmware.md\");\n return;\n }\n } else {\n this.passwordEncryptionMethod = \"md5\";\n response = responseLogin;\n responseData = responseLoginData;\n }\n\n if (responseData.result?.data?.sec_left && responseData.result.data.sec_left > 0) {\n this.log.debug(\"refreshStok: temporary suspension\", responseData);\n\n this.log.error(`Temporary Suspension: Try again in ${responseData.result.data.sec_left} seconds`);\n }\n\n if (responseData?.data?.code === -40404 && responseData?.data?.sec_left && responseData.data.sec_left > 0) {\n this.log.debug(\"refreshStok: temporary suspension\", responseData);\n\n this.log.error(`refreshStok: Temporary Suspension: Try again in ${responseData.data.sec_left} seconds`);\n }\n\n if (responseData?.result?.stok) {\n this.stok = responseData.result.stok;\n this.log.debug(\"refreshStok: Success in obtaining STOK\", this.stok);\n return;\n }\n\n if (responseData?.error_code === -40413 && loginRetryCount < MAX_LOGIN_RETRIES) {\n this.log.debug(\n `refreshStock: Unexpected response, retrying: ${loginRetryCount}/${MAX_LOGIN_RETRIES}.`,\n response.status,\n responseData,\n );\n return this.refreshStok(loginRetryCount + 1);\n }\n\n this.log.debug(\"refreshStock: Unexpected end of flow, raising exception\");\n this.log.error(\"Invalid authentication data\");\n }\n\n async isSecureConnection() {\n if (this.isSecureConnectionValue === null) {\n this.log.debug(\"isSecureConnection: Checking secure connection...\");\n\n const response = await this.fetch(`https://${this.config.ipAddress}`, {\n method: \"post\",\n body: JSON.stringify({\n method: \"login\",\n params: {\n encrypt_type: \"3\",\n username: this.getUsername(),\n },\n }),\n });\n const responseData = (await response.json()) as TAPOCameraLoginResponse;\n\n this.log.debug(\"isSecureConnection response\", response.status, JSON.stringify(responseData));\n\n this.isSecureConnectionValue =\n responseData?.error_code == -40413 && String(responseData.result?.data?.encrypt_type || \"\")?.includes(\"3\");\n }\n\n return this.isSecureConnectionValue;\n }\n\n getStok(loginRetryCount = 0): Promise<string> {\n return new Promise((resolve) => {\n if (this.stok) {\n return resolve(this.stok);\n }\n\n if (!this.stokPromise) {\n this.stokPromise = () => this.refreshStok(loginRetryCount);\n }\n\n this.stokPromise()\n .then(() => {\n if (!this.stok) {\n this.log.error(\"STOK not found\");\n }\n resolve(this.stok!);\n })\n .finally(() => {\n this.stokPromise = undefined;\n });\n });\n }\n\n private async getAuthenticatedAPIURL(loginRetryCount = 0) {\n const token = await this.getStok(loginRetryCount);\n return `https://${this.config.ipAddress}/stok=${token}/ds`;\n }\n\n encryptRequest(request: string) {\n const cipher = crypto.createCipheriv(\"aes-128-cbc\", this.lsk!, this.ivb!);\n let ct_bytes = cipher.update(this.encryptPad(request, AES_BLOCK_SIZE), \"utf-8\", \"hex\");\n ct_bytes += cipher.final(\"hex\");\n return Buffer.from(ct_bytes, \"hex\");\n }\n\n private encryptPad(text: string, blocksize: number) {\n const padSize = blocksize - (text.length % blocksize);\n const padding = String.fromCharCode(padSize).repeat(padSize);\n return text + padding;\n }\n\n private decryptResponse(response: string): string {\n const decipher = crypto.createDecipheriv(\"aes-128-cbc\", this.lsk!, this.ivb!);\n let decrypted = decipher.update(response, \"base64\", \"utf-8\");\n decrypted += decipher.final(\"utf-8\");\n return this.encryptUnpad(decrypted, AES_BLOCK_SIZE);\n }\n\n private encryptUnpad(text: string, blockSize: number): string {\n const paddingLength = Number(text[text.length - 1]) || 0;\n if (paddingLength > blockSize || paddingLength > text.length) {\n this.log.error(\"Invalid padding\");\n }\n for (let i = text.length - paddingLength; i < text.length; i++) {\n if (text.charCodeAt(i) !== paddingLength) {\n this.log.error(\"Invalid padding\");\n }\n }\n return text.slice(0, text.length - paddingLength).toString();\n }\n\n private getTapoTag(request: TAPOCameraEncryptedRequest) {\n const tag = crypto\n .createHash(\"sha256\")\n .update(this.getHashedPassword() + this.cnonce)\n .digest(\"hex\")\n .toUpperCase();\n return crypto\n .createHash(\"sha256\")\n .update(tag + JSON.stringify(request) + this.seq!.toString())\n .digest(\"hex\")\n .toUpperCase();\n }\n\n private pendingAPIRequests: Map<string, Promise<TAPOCameraResponse>> = new Map();\n\n private async apiRequest(req: TAPOCameraRequest, loginRetryCount = 0): Promise<TAPOCameraResponse> {\n const reqJson = JSON.stringify(req);\n\n if (this.pendingAPIRequests.has(reqJson)) {\n this.log.debug(\"API request already pending\", reqJson);\n return this.pendingAPIRequests.get(reqJson) as Promise<TAPOCameraResponse>;\n } else {\n this.log.debug(\"New API request\", reqJson);\n }\n\n this.pendingAPIRequests.set(\n reqJson,\n (async () => {\n try {\n const isSecureConnection = await this.isSecureConnection();\n const url = await this.getAuthenticatedAPIURL(loginRetryCount);\n\n const fetchParams: RequestInit = {\n method: \"post\",\n };\n\n if (this.seq && isSecureConnection) {\n const encryptedRequest: TAPOCameraEncryptedRequest = {\n method: \"securePassthrough\",\n params: {\n request: Buffer.from(this.encryptRequest(JSON.stringify(req))).toString(\"base64\"),\n },\n };\n fetchParams.headers = {\n ...this.getHeaders(),\n Tapo_tag: this.getTapoTag(encryptedRequest),\n Seq: this.seq.toString(),\n };\n fetchParams.body = JSON.stringify(encryptedRequest);\n this.seq += 1;\n } else {\n fetchParams.body = JSON.stringify(req);\n }\n\n const response = await this.fetch(url, fetchParams).catch((e) => {\n this.log.debug(\"Error during camera fetch\", e);\n return;\n });\n if (!response) {\n this.log.debug(\"API request failed, empty response\");\n return {} as TAPOCameraResponse;\n }\n const responseDataTmp = await response.json();\n\n // Apparently the Tapo C200 returns 500 on successful requests,\n // but it's indicating an expiring token, therefore refresh the token next time\n if (isSecureConnection && response.status === 500) {\n this.log.debug(\"Stok expired, reauthenticating on next request, setting STOK to undefined\");\n this.stok = undefined;\n }\n\n let responseData: TAPOCameraResponse | null = null;\n\n if (isSecureConnection) {\n const encryptedResponse = responseDataTmp as TAPOCameraEncryptedResponse;\n if (encryptedResponse?.result?.response) {\n const decryptedResponse = this.decryptResponse(encryptedResponse.result.response);\n responseData = JSON.parse(decryptedResponse) as TAPOCameraResponse;\n }\n } else {\n responseData = responseDataTmp as TAPOCameraResponse;\n }\n\n this.log.debug(\"API response\", response.status, JSON.stringify(responseData));\n\n // Log error codes\n if (responseData && responseData.error_code !== 0) {\n const errorCode = String(responseData.error_code);\n const errorMessage =\n errorCode in ERROR_CODES_MAP ? ERROR_CODES_MAP[errorCode as keyof typeof ERROR_CODES_MAP] : \"Unknown error\";\n this.log.debug(`API request failed with specific error code ${errorCode}: ${errorMessage}`);\n }\n\n if (!responseData || responseData.error_code === -40401 || responseData.error_code === -1) {\n this.log.debug(\"API request failed\", responseData);\n this.stok = undefined;\n return {} as TAPOCameraResponse;\n // return this.apiRequest(req, loginRetryCount + 1);\n }\n\n // Success\n return responseData;\n } finally {\n this.pendingAPIRequests.delete(reqJson);\n }\n })(),\n );\n\n return this.pendingAPIRequests.get(reqJson) as Promise<TAPOCameraResponse>;\n }\n\n static SERVICE_MAP: Record<keyof Status, (value: boolean) => TAPOCameraSetRequest> = {\n eyes: (value) => ({\n method: \"setLensMaskConfig\",\n params: {\n lens_mask: {\n lens_mask_info: {\n // Watch out for the inversion\n enabled: value ? \"off\" : \"on\",\n },\n },\n },\n }),\n alarm: (value) => ({\n method: \"setAlertConfig\",\n params: {\n msg_alarm: {\n chn1_msg_alarm_info: {\n enabled: value ? \"on\" : \"off\",\n },\n },\n },\n }),\n notifications: (value) => ({\n method: \"setMsgPushConfig\",\n params: {\n msg_push: {\n chn1_msg_push_info: {\n notification_enabled: value ? \"on\" : \"off\",\n rich_notification_enabled: value ? \"on\" : \"off\",\n },\n },\n },\n }),\n motionDetection: (value) => ({\n method: \"setDetectionConfig\",\n params: {\n motion_detection: {\n motion_det: {\n enabled: value ? \"on\" : \"off\",\n },\n },\n },\n }),\n led: (value) => ({\n method: \"setLedStatus\",\n params: {\n led: {\n config: {\n enabled: value ? \"on\" : \"off\",\n },\n },\n },\n }),\n };\n\n async setStatus(service: keyof Status, value: boolean) {\n const responseData = await this.apiRequest({\n method: \"multipleRequest\",\n params: {\n requests: [TAPOCamera.SERVICE_MAP[service](value)],\n },\n });\n\n if (responseData.error_code !== 0) {\n this.log.error(`Failed to perform ${service} action`);\n }\n\n const method = TAPOCamera.SERVICE_MAP[service](value).method;\n const operation = responseData.result.responses.find((e) => e.method === method);\n if (operation?.error_code !== 0) {\n this.log.error(`Failed to perform ${service} action`);\n }\n\n return operation.result;\n }\n\n async getBasicInfo(): Promise<TAPOBasicInfo> {\n const responseData = await this.apiRequest({\n method: \"multipleRequest\",\n params: {\n requests: [\n {\n method: \"getDeviceInfo\",\n params: {\n device_info: {\n name: [\"basic_info\"],\n },\n },\n },\n ],\n },\n });\n\n const info = responseData.result.responses[0] as TAPOCameraResponseDeviceInfo;\n return info.result.device_info.basic_info;\n }\n\n async getStatus(): Promise<Status> {\n const responseData = await this.apiRequest({\n method: \"multipleRequest\",\n params: {\n requests: [\n {\n method: \"getAlertConfig\",\n params: {\n msg_alarm: {\n name: \"chn1_msg_alarm_info\",\n },\n },\n },\n {\n method: \"getLensMaskConfig\",\n params: {\n lens_mask: {\n name: \"lens_mask_info\",\n },\n },\n },\n {\n method: \"getMsgPushConfig\",\n params: {\n msg_push: {\n name: \"chn1_msg_push_info\",\n },\n },\n },\n {\n method: \"getDetectionConfig\",\n params: {\n motion_detection: {\n name: \"motion_det\",\n },\n },\n },\n {\n method: \"getLedStatus\",\n params: {\n led: {\n name: \"config\",\n },\n },\n },\n ],\n },\n });\n\n if (!responseData || !responseData.result || !responseData.result.responses) {\n this.log.error(\"No response data found\");\n return {\n alarm: undefined,\n eyes: undefined,\n notifications: undefined,\n motionDetection: undefined,\n led: undefined,\n };\n }\n const operations = responseData.result.responses;\n\n const alert = operations.find((r) => r.method === \"getAlertConfig\");\n const lensMask = operations.find((r) => r.method === \"getLensMaskConfig\");\n const notifications = operations.find((r) => r.method === \"getMsgPushConfig\");\n const motionDetection = operations.find((r) => r.method === \"getDetectionConfig\");\n const led = operations.find((r) => r.method === \"getLedStatus\");\n\n if (!alert) this.log.debug(\"No alert config found\");\n if (!lensMask) this.log.debug(\"No lens mask config found\");\n if (!notifications) this.log.debug(\"No notifications config found\");\n if (!motionDetection) this.log.debug(\"No motion detection config found\");\n if (!led) this.log.debug(\"No led config found\");\n\n return {\n alarm: alert ? alert.result.msg_alarm.chn1_msg_alarm_info.enabled === \"on\" : undefined,\n // Watch out for the inversion\n eyes: lensMask ? lensMask.result.lens_mask.lens_mask_info.enabled === \"off\" : undefined,\n notifications: notifications ? notifications.result.msg_push.chn1_msg_push_info.notification_enabled === \"on\" : undefined,\n motionDetection: motionDetection ? motionDetection.result.motion_detection.motion_det.enabled === \"on\" : undefined,\n led: led ? led.result.led.config.enabled === \"on\" : undefined,\n };\n }\n async setForceWhitelampState(value: boolean) {\n const json = await this.apiRequest({\n method: \"multipleRequest\",\n params: {\n requests: [\n {\n method: \"setForceWhitelampState\",\n params: {\n image: {\n switch: {\n force_wtl_state: value ? \"on\" : \"off\",\n },\n },\n },\n },\n ],\n },\n });\n\n return json.error_code !== 0;\n }\n async moveMotorStep(angle: string) {\n angle = angle.toString();\n const json = await this.apiRequest({ method: \"do\", motor: { movestep: { direction: angle } } });\n\n return json.error_code !== 0;\n }\n\n async moveMotor(x: number, y: number) {\n const json = await this.apiRequest({\n method: \"multipleRequest\",\n params: {\n requests: [{ method: \"do\", motor: { move: { x_coord: x, y_coord: y } } }],\n },\n });\n\n return json.error_code !== 0;\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,oBAAmB;AACnB,yBAA4B;AAgB5B,oBAA2C;AAH3C,MAAM,oBAAoB;AAC1B,MAAM,iBAAiB;AAIvB,MAAM,kBAAkB;AAAA,EACtB,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AAAA,EACV,UAAU;AACZ;AA4CO,MAAM,cAAN,cAAyB,+BAAY;AAAA,EAkB1C,YACqB,KACA,QACnB;AACA,UAAM,KAAK,MAAM;AAHE;AACA;AAnBrB,SAAiB,cAAc;AAK/B,SAAQ,2BAAoD;AAE5D,SAAQ,0BAA0C;AAsYlD,SAAQ,qBAA+D,oBAAI,IAAI;AAvX7E,YAAQ,IAAI,+BAA+B;AAC3C,SAAK,aAAa,IAAI,oBAAM;AAAA,MAC1B,gBAAgB;AAAA,MAChB,SAAS;AAAA,QAEP,oBAAoB;AAAA,QACpB,SAAS;AAAA,MACX;AAAA,IACF,CAAC;AACD,2CAAoB,KAAK,UAAU;AAEnC,SAAK,SAAS,KAAK,eAAe;AAElC,SAAK,iBAAiB,cAAAA,QAAO,WAAW,KAAK,EAAE,OAAO,OAAO,QAAQ,EAAE,OAAO,KAAK,EAAE,YAAY;AACjG,SAAK,uBAAuB,cAAAA,QAAO,WAAW,QAAQ,EAAE,OAAO,OAAO,QAAQ,EAAE,OAAO,KAAK,EAAE,YAAY;AAAA,EAC5G;AAAA,EAEQ,cAAc;AACpB,WAAO,KAAK,OAAO,YAAY;AAAA,EACjC;AAAA,EAEQ,aAAqC;AAC3C,WAAO;AAAA,MACL,MAAM,WAAW,KAAK,OAAO;AAAA,MAC7B,SAAS,WAAW,KAAK,OAAO;AAAA,MAChC,QAAQ;AAAA,MACR,mBAAmB;AAAA,MACnB,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,cAAc;AAAA,MACd,gBAAgB;AAAA,IAClB;AAAA,EACF;AAAA,EAEQ,oBAAoB;AAC1B,QAAI,KAAK,6BAA6B,OAAO;AAC3C,aAAO,KAAK;AAAA,IACd,WAAW,KAAK,6BAA6B,UAAU;AACrD,aAAO,KAAK;AAAA,IACd,OAAO;AACL,WAAK,IAAI,MAAM,oCAAoC;AAAA,IACrD;AAAA,EACF;AAAA,EAEQ,MAAM,KAAa,MAAmB;AAC5C,WAAO,MAAM,KAAK;AAAA,MAChB,SAAS,KAAK,WAAW;AAAA,MAEzB,YAAY,KAAK;AAAA,MACjB,GAAG;AAAA,IACL,CAAC;AAAA,EACH;AAAA,EAEQ,wBAAwB,WAAmB,OAAuB;AACxE,UAAM,YAAY,cAAAA,QACf,WAAW,QAAQ,EACnB,OAAO,KAAK,SAAS,KAAK,kBAAkB,IAAI,KAAK,EACrD,OAAO,KAAK,EACZ,YAAY;AACf,WAAO,cAAAA,QACJ,WAAW,QAAQ,EACnB,OAAO,YAAY,KAAK,SAAS,QAAQ,SAAS,EAClD,OAAO,EACP,MAAM,GAAG,EAAE;AAAA,EAChB;AAAA,EAEA,0BAA0B,aAAa,OAAO;AAC5C,UAAM,SAAS,UAAU,KAAK,OAAO,cAAc,KAAK,OAAO,kBAAkB,KAAK,OAAO,aAAa,KAAK;AAC/G,WAAO,aAAa,GAAG,mBAAmB,GAAG;AAAA,EAC/C;AAAA,EAEQ,iBAAiB;AACvB,WAAO,cAAAA,QAAO,YAAY,CAAC,EAAE,SAAS,KAAK,EAAE,YAAY;AAAA,EAC3D;AAAA,EAEQ,sBAAsB,OAAe,eAAuB;AAClE,SAAK,2BAA2B;AAEhC,UAAM,yBAAyB,cAAAA,QAC5B,WAAW,QAAQ,EACnB,OAAO,KAAK,SAAS,KAAK,uBAAuB,KAAK,EACtD,OAAO,KAAK,EACZ,YAAY;AACf,QAAI,kBAAkB,yBAAyB,QAAQ,KAAK,QAAQ;AAClE,WAAK,2BAA2B;AAChC,aAAO;AAAA,IACT;AAEA,UAAM,sBAAsB,cAAAA,QACzB,WAAW,KAAK,EAChB,OAAO,KAAK,SAAS,KAAK,iBAAiB,KAAK,EAChD,OAAO,KAAK,EACZ,YAAY;AACf,QAAI,kBAAkB,sBAAsB,QAAQ,KAAK,QAAQ;AAC/D,WAAK,2BAA2B;AAChC,aAAO;AAAA,IACT;AAEA,SAAK,IAAI,MAAM,+EAA+E;AAAA,MAC5F;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,QAAQ;AAAA,IACV,CAAC;AAED,WAAO,KAAK,6BAA6B;AAAA,EAC3C;AAAA,EAEA,MAAM,YAAY,kBAAkB,GAAkB;AAjNxD;AAkNI,SAAK,IAAI,MAAM,iCAAiC;AAEhD,UAAM,qBAAqB,MAAM,KAAK,mBAAmB;AAEzD,QAAI,cAAc,CAAC;AACnB,QAAI,oBAAoB;AACtB,oBAAc;AAAA,QACZ,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU;AAAA,UACnB,QAAQ;AAAA,UACR,QAAQ;AAAA,YACN,QAAQ,KAAK;AAAA,YACb,cAAc;AAAA,YACd,UAAU,KAAK,YAAY;AAAA,UAC7B;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF,OAAO;AACL,oBAAc;AAAA,QACZ,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU;AAAA,UACnB,QAAQ;AAAA,UACR,QAAQ;AAAA,YACN,UAAU,KAAK,YAAY;AAAA,YAC3B,UAAU,KAAK;AAAA,YACf,QAAQ;AAAA,UACV;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,UAAM,gBAAgB,MAAM,KAAK,MAAM,WAAW,KAAK,OAAO,aAAa,WAAW,EAAE,MAAM,CAAC,MAAM;AACnG,WAAK,IAAI,MAAM,mCAAmC,CAAC;AACnD,aAAO;AAAA,IACT,CAAC;AACD,QAAI,CAAC,eAAe;AAClB,WAAK,IAAI,MAAM,sDAAsD;AACrE,WAAK,IAAI,MAAM,sBAAsB;AACrC;AAAA,IACF;AACA,UAAM,oBAAqB,MAAM,cAAc,KAAK;AAEpD,QAAI,UAAU;AAEd,QAAI,CAAC,mBAAmB;AACtB,WAAK,IAAI,MAAM,6DAA6D,cAAc,MAAM;AAChG,WAAK,IAAI,MAAM,2BAA2B;AAAA,IAC5C;AAEA,SAAK,IAAI,MAAM,+BAA+B,cAAc,QAAQ,iBAAiB;AAErF,QAAI,cAAc,WAAW,SAAO,6BAAkB,WAAlB,mBAA0B,SAA1B,mBAAgC,UAAS,QAAQ;AACnF,WAAK,IAAI,MAAM,uDAAuD,cAAc,MAAM;AAC1F,WAAK,IAAI,MAAM,qBAAqB;AAAA,IACtC;AAEA,QAAI,oBAAoB;AACtB,YAAM,SAAQ,6BAAkB,WAAlB,mBAA0B,SAA1B,mBAAgC;AAC9C,YAAM,iBAAgB,6BAAkB,WAAlB,mBAA0B,SAA1B,mBAAgC;AACtD,UAAI,SAAS,iBAAiB,KAAK,sBAAsB,OAAO,aAAa,GAAG;AAC9E,cAAM,eAAe,cAAAA,QAClB,WAAW,QAAQ,EACnB,OAAO,KAAK,kBAAkB,IAAI,KAAK,SAAS,KAAK,EACrD,OAAO,KAAK,EACZ,YAAY;AAEf,cAAM,mBAAmB,OAAO,OAAO;AAAA,UACrC,OAAO,KAAK,cAAc,MAAM;AAAA,UAChC,OAAO,KAAK,KAAK,QAAS,MAAM;AAAA,UAChC,OAAO,KAAK,OAAO,MAAM;AAAA,QAC3B,CAAC,EAAE,SAAS,MAAM;AAElB,aAAK,IAAI,MAAM,wCAAwC;AAEvD,mBAAW,MAAM,KAAK,MAAM,WAAW,KAAK,OAAO,aAAa;AAAA,UAC9D,QAAQ;AAAA,UACR,MAAM,KAAK,UAAU;AAAA,YACnB,QAAQ;AAAA,YACR,QAAQ;AAAA,cACN,QAAQ,KAAK;AAAA,cACb,cAAc;AAAA,cACd,eAAe;AAAA,cACf,UAAU,KAAK,YAAY;AAAA,YAC7B;AAAA,UACF,CAAC;AAAA,QACH,CAAC;AAED,uBAAgB,MAAM,SAAS,KAAK;AAEpC,YAAI,CAAC,cAAc;AACjB,eAAK,IAAI,MAAM,kEAAkE,SAAS,MAAM;AAChG,eAAK,IAAI,MAAM,+BAA+B;AAC9C;AAAA,QACF;AAEA,aAAK,IAAI,MAAM,mCAAmC,SAAS,QAAQ,KAAK,UAAU,YAAY,CAAC;AAE/F,aAAI,kBAAa,WAAb,mBAAqB,WAAW;AAClC,gBAAI,kBAAa,WAAb,mBAAqB,gBAAe,QAAQ;AAC9C,iBAAK,IAAI,MAAM,6CAA6C;AAI5D,iBAAK,IAAI,MAAM,+BAA+B;AAAA,UAChD;AAEA,eAAK,MAAM,KAAK,wBAAwB,OAAO,KAAK;AACpD,eAAK,MAAM,KAAK,wBAAwB,OAAO,KAAK;AACpD,eAAK,MAAM,aAAa,OAAO;AAAA,QACjC;AAAA,MACF,OAAO;AACL,YAAI,kBAAkB,eAAe,UAAU,kBAAkB,mBAAmB;AAClF,eAAK,IAAI;AAAA,YACP,mDAAmD,mBAAmB;AAAA,YACtE,cAAc;AAAA,YACd;AAAA,UACF;AACA,iBAAO,KAAK,YAAY,kBAAkB,CAAC;AAAA,QAC7C;AAEA,aAAK,IAAI;AAAA,UACP;AAAA,UACA;AAAA,UACA;AAAA,QACF;AACA,aAAK,IAAI,MAAM,gHAAgH;AAC/H,aAAK,IAAI,MAAM,8GAA8G;AAC7H;AAAA,MACF;AAAA,IACF,OAAO;AACL,WAAK,2BAA2B;AAChC,iBAAW;AACX,qBAAe;AAAA,IACjB;AAEA,UAAI,wBAAa,WAAb,mBAAqB,SAArB,mBAA2B,aAAY,aAAa,OAAO,KAAK,WAAW,GAAG;AAChF,WAAK,IAAI,MAAM,qCAAqC,YAAY;AAEhE,WAAK,IAAI,MAAM,sCAAsC,aAAa,OAAO,KAAK,kBAAkB;AAAA,IAClG;AAEA,UAAI,kDAAc,SAAd,mBAAoB,UAAS,YAAU,kDAAc,SAAd,mBAAoB,aAAY,aAAa,KAAK,WAAW,GAAG;AACzG,WAAK,IAAI,MAAM,qCAAqC,YAAY;AAEhE,WAAK,IAAI,MAAM,mDAAmD,aAAa,KAAK,kBAAkB;AAAA,IACxG;AAEA,SAAI,kDAAc,WAAd,mBAAsB,MAAM;AAC9B,WAAK,OAAO,aAAa,OAAO;AAChC,WAAK,IAAI,MAAM,0CAA0C,KAAK,IAAI;AAClE;AAAA,IACF;AAEA,SAAI,6CAAc,gBAAe,UAAU,kBAAkB,mBAAmB;AAC9E,WAAK,IAAI;AAAA,QACP,gDAAgD,mBAAmB;AAAA,QACnE,SAAS;AAAA,QACT;AAAA,MACF;AACA,aAAO,KAAK,YAAY,kBAAkB,CAAC;AAAA,IAC7C;AAEA,SAAK,IAAI,MAAM,yDAAyD;AACxE,SAAK,IAAI,MAAM,6BAA6B;AAAA,EAC9C;AAAA,EAEA,MAAM,qBAAqB;AAxX7B;AAyXI,QAAI,KAAK,4BAA4B,MAAM;AACzC,WAAK,IAAI,MAAM,mDAAmD;AAElE,YAAM,WAAW,MAAM,KAAK,MAAM,WAAW,KAAK,OAAO,aAAa;AAAA,QACpE,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU;AAAA,UACnB,QAAQ;AAAA,UACR,QAAQ;AAAA,YACN,cAAc;AAAA,YACd,UAAU,KAAK,YAAY;AAAA,UAC7B;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AACD,YAAM,eAAgB,MAAM,SAAS,KAAK;AAE1C,WAAK,IAAI,MAAM,+BAA+B,SAAS,QAAQ,KAAK,UAAU,YAAY,CAAC;AAE3F,WAAK,2BACH,6CAAc,eAAc,YAAU,cAAO,wBAAa,WAAb,mBAAqB,SAArB,mBAA2B,iBAAgB,EAAE,MAApD,mBAAuD,SAAS;AAAA,IAC1G;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,QAAQ,kBAAkB,GAAoB;AAC5C,WAAO,IAAI,QAAQ,CAAC,YAAY;AAC9B,UAAI,KAAK,MAAM;AACb,eAAO,QAAQ,KAAK,IAAI;AAAA,MAC1B;AAEA,UAAI,CAAC,KAAK,aAAa;AACrB,aAAK,cAAc,MAAM,KAAK,YAAY,eAAe;AAAA,MAC3D;AAEA,WAAK,YAAY,EACd,KAAK,MAAM;AACV,YAAI,CAAC,KAAK,MAAM;AACd,eAAK,IAAI,MAAM,gBAAgB;AAAA,QACjC;AACA,gBAAQ,KAAK,IAAK;AAAA,MACpB,CAAC,EACA,QAAQ,MAAM;AACb,aAAK,cAAc;AAAA,MACrB,CAAC;AAAA,IACL,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,uBAAuB,kBAAkB,GAAG;AACxD,UAAM,QAAQ,MAAM,KAAK,QAAQ,eAAe;AAChD,WAAO,WAAW,KAAK,OAAO,kBAAkB;AAAA,EAClD;AAAA,EAEA,eAAe,SAAiB;AAC9B,UAAM,SAAS,cAAAA,QAAO,eAAe,eAAe,KAAK,KAAM,KAAK,GAAI;AACxE,QAAI,WAAW,OAAO,OAAO,KAAK,WAAW,SAAS,cAAc,GAAG,SAAS,KAAK;AACrF,gBAAY,OAAO,MAAM,KAAK;AAC9B,WAAO,OAAO,KAAK,UAAU,KAAK;AAAA,EACpC;AAAA,EAEQ,WAAW,MAAc,WAAmB;AAClD,UAAM,UAAU,YAAa,KAAK,SAAS;AAC3C,UAAM,UAAU,OAAO,aAAa,OAAO,EAAE,OAAO,OAAO;AAC3D,WAAO,OAAO;AAAA,EAChB;AAAA,EAEQ,gBAAgB,UAA0B;AAChD,UAAM,WAAW,cAAAA,QAAO,iBAAiB,eAAe,KAAK,KAAM,KAAK,GAAI;AAC5E,QAAI,YAAY,SAAS,OAAO,UAAU,UAAU,OAAO;AAC3D,iBAAa,SAAS,MAAM,OAAO;AACnC,WAAO,KAAK,aAAa,WAAW,cAAc;AAAA,EACpD;AAAA,EAEQ,aAAa,MAAc,WAA2B;AAC5D,UAAM,gBAAgB,OAAO,KAAK,KAAK,SAAS,EAAE,KAAK;AACvD,QAAI,gBAAgB,aAAa,gBAAgB,KAAK,QAAQ;AAC5D,WAAK,IAAI,MAAM,iBAAiB;AAAA,IAClC;AACA,aAAS,IAAI,KAAK,SAAS,eAAe,IAAI,KAAK,QAAQ,KAAK;AAC9D,UAAI,KAAK,WAAW,CAAC,MAAM,eAAe;AACxC,aAAK,IAAI,MAAM,iBAAiB;AAAA,MAClC;AAAA,IACF;AACA,WAAO,KAAK,MAAM,GAAG,KAAK,SAAS,aAAa,EAAE,SAAS;AAAA,EAC7D;AAAA,EAEQ,WAAW,SAAqC;AACtD,UAAM,MAAM,cAAAA,QACT,WAAW,QAAQ,EACnB,OAAO,KAAK,kBAAkB,IAAI,KAAK,MAAM,EAC7C,OAAO,KAAK,EACZ,YAAY;AACf,WAAO,cAAAA,QACJ,WAAW,QAAQ,EACnB,OAAO,MAAM,KAAK,UAAU,OAAO,IAAI,KAAK,IAAK,SAAS,CAAC,EAC3D,OAAO,KAAK,EACZ,YAAY;AAAA,EACjB;AAAA,EAIA,MAAc,WAAW,KAAwB,kBAAkB,GAAgC;AACjG,UAAM,UAAU,KAAK,UAAU,GAAG;AAElC,QAAI,KAAK,mBAAmB,IAAI,OAAO,GAAG;AACxC,WAAK,IAAI,MAAM,+BAA+B,OAAO;AACrD,aAAO,KAAK,mBAAmB,IAAI,OAAO;AAAA,IAC5C,OAAO;AACL,WAAK,IAAI,MAAM,mBAAmB,OAAO;AAAA,IAC3C;AAEA,SAAK,mBAAmB;AAAA,MACtB;AAAA,OACC,YAAY;AAzenB;AA0eQ,YAAI;AACF,gBAAM,qBAAqB,MAAM,KAAK,mBAAmB;AACzD,gBAAM,MAAM,MAAM,KAAK,uBAAuB,eAAe;AAE7D,gBAAM,cAA2B;AAAA,YAC/B,QAAQ;AAAA,UACV;AAEA,cAAI,KAAK,OAAO,oBAAoB;AAClC,kBAAM,mBAA+C;AAAA,cACnD,QAAQ;AAAA,cACR,QAAQ;AAAA,gBACN,SAAS,OAAO,KAAK,KAAK,eAAe,KAAK,UAAU,GAAG,CAAC,CAAC,EAAE,SAAS,QAAQ;AAAA,cAClF;AAAA,YACF;AACA,wBAAY,UAAU;AAAA,cACpB,GAAG,KAAK,WAAW;AAAA,cACnB,UAAU,KAAK,WAAW,gBAAgB;AAAA,cAC1C,KAAK,KAAK,IAAI,SAAS;AAAA,YACzB;AACA,wBAAY,OAAO,KAAK,UAAU,gBAAgB;AAClD,iBAAK,OAAO;AAAA,UACd,OAAO;AACL,wBAAY,OAAO,KAAK,UAAU,GAAG;AAAA,UACvC;AAEA,gBAAM,WAAW,MAAM,KAAK,MAAM,KAAK,WAAW,EAAE,MAAM,CAAC,MAAM;AAC/D,iBAAK,IAAI,MAAM,6BAA6B,CAAC;AAC7C;AAAA,UACF,CAAC;AACD,cAAI,CAAC,UAAU;AACb,iBAAK,IAAI,MAAM,oCAAoC;AACnD,mBAAO,CAAC;AAAA,UACV;AACA,gBAAM,kBAAkB,MAAM,SAAS,KAAK;AAI5C,cAAI,sBAAsB,SAAS,WAAW,KAAK;AACjD,iBAAK,IAAI,MAAM,2EAA2E;AAC1F,iBAAK,OAAO;AAAA,UACd;AAEA,cAAI,eAA0C;AAE9C,cAAI,oBAAoB;AACtB,kBAAM,oBAAoB;AAC1B,iBAAI,4DAAmB,WAAnB,mBAA2B,UAAU;AACvC,oBAAM,oBAAoB,KAAK,gBAAgB,kBAAkB,OAAO,QAAQ;AAChF,6BAAe,KAAK,MAAM,iBAAiB;AAAA,YAC7C;AAAA,UACF,OAAO;AACL,2BAAe;AAAA,UACjB;AAEA,eAAK,IAAI,MAAM,gBAAgB,SAAS,QAAQ,KAAK,UAAU,YAAY,CAAC;AAG5E,cAAI,gBAAgB,aAAa,eAAe,GAAG;AACjD,kBAAM,YAAY,OAAO,aAAa,UAAU;AAChD,kBAAM,eACJ,aAAa,kBAAkB,gBAAgB,aAA6C;AAC9F,iBAAK,IAAI,MAAM,+CAA+C,cAAc,cAAc;AAAA,UAC5F;AAEA,cAAI,CAAC,gBAAgB,aAAa,eAAe,UAAU,aAAa,eAAe,IAAI;AACzF,iBAAK,IAAI,MAAM,sBAAsB,YAAY;AACjD,iBAAK,OAAO;AACZ,mBAAO,CAAC;AAAA,UAEV;AAGA,iBAAO;AAAA,QACT,UAAE;AACA,eAAK,mBAAmB,OAAO,OAAO;AAAA,QACxC;AAAA,MACF,GAAG;AAAA,IACL;AAEA,WAAO,KAAK,mBAAmB,IAAI,OAAO;AAAA,EAC5C;AAAA,EAyDA,MAAM,UAAU,SAAuB,OAAgB;AACrD,UAAM,eAAe,MAAM,KAAK,WAAW;AAAA,MACzC,QAAQ;AAAA,MACR,QAAQ;AAAA,QACN,UAAU,CAAC,YAAW,YAAY,SAAS,KAAK,CAAC;AAAA,MACnD;AAAA,IACF,CAAC;AAED,QAAI,aAAa,eAAe,GAAG;AACjC,WAAK,IAAI,MAAM,qBAAqB,gBAAgB;AAAA,IACtD;AAEA,UAAM,SAAS,YAAW,YAAY,SAAS,KAAK,EAAE;AACtD,UAAM,YAAY,aAAa,OAAO,UAAU,KAAK,CAAC,MAAM,EAAE,WAAW,MAAM;AAC/E,SAAI,uCAAW,gBAAe,GAAG;AAC/B,WAAK,IAAI,MAAM,qBAAqB,gBAAgB;AAAA,IACtD;AAEA,WAAO,UAAU;AAAA,EACnB;AAAA,EAEA,MAAM,eAAuC;AAC3C,UAAM,eAAe,MAAM,KAAK,WAAW;AAAA,MACzC,QAAQ;AAAA,MACR,QAAQ;AAAA,QACN,UAAU;AAAA,UACR;AAAA,YACE,QAAQ;AAAA,YACR,QAAQ;AAAA,cACN,aAAa;AAAA,gBACX,MAAM,CAAC,YAAY;AAAA,cACrB;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,UAAM,OAAO,aAAa,OAAO,UAAU;AAC3C,WAAO,KAAK,OAAO,YAAY;AAAA,EACjC;AAAA,EAEA,MAAM,YAA6B;AACjC,UAAM,eAAe,MAAM,KAAK,WAAW;AAAA,MACzC,QAAQ;AAAA,MACR,QAAQ;AAAA,QACN,UAAU;AAAA,UACR;AAAA,YACE,QAAQ;AAAA,YACR,QAAQ;AAAA,cACN,WAAW;AAAA,gBACT,MAAM;AAAA,cACR;AAAA,YACF;AAAA,UACF;AAAA,UACA;AAAA,YACE,QAAQ;AAAA,YACR,QAAQ;AAAA,cACN,WAAW;AAAA,gBACT,MAAM;AAAA,cACR;AAAA,YACF;AAAA,UACF;AAAA,UACA;AAAA,YACE,QAAQ;AAAA,YACR,QAAQ;AAAA,cACN,UAAU;AAAA,gBACR,MAAM;AAAA,cACR;AAAA,YACF;AAAA,UACF;AAAA,UACA;AAAA,YACE,QAAQ;AAAA,YACR,QAAQ;AAAA,cACN,kBAAkB;AAAA,gBAChB,MAAM;AAAA,cACR;AAAA,YACF;AAAA,UACF;AAAA,UACA;AAAA,YACE,QAAQ;AAAA,YACR,QAAQ;AAAA,cACN,KAAK;AAAA,gBACH,MAAM;AAAA,cACR;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,QAAI,CAAC,gBAAgB,CAAC,aAAa,UAAU,CAAC,aAAa,OAAO,WAAW;AAC3E,WAAK,IAAI,MAAM,wBAAwB;AACvC,aAAO;AAAA,QACL,OAAO;AAAA,QACP,MAAM;AAAA,QACN,eAAe;AAAA,QACf,iBAAiB;AAAA,QACjB,KAAK;AAAA,MACP;AAAA,IACF;AACA,UAAM,aAAa,aAAa,OAAO;AAEvC,UAAM,QAAQ,WAAW,KAAK,CAAC,MAAM,EAAE,WAAW,gBAAgB;AAClE,UAAM,WAAW,WAAW,KAAK,CAAC,MAAM,EAAE,WAAW,mBAAmB;AACxE,UAAM,gBAAgB,WAAW,KAAK,CAAC,MAAM,EAAE,WAAW,kBAAkB;AAC5E,UAAM,kBAAkB,WAAW,KAAK,CAAC,MAAM,EAAE,WAAW,oBAAoB;AAChF,UAAM,MAAM,WAAW,KAAK,CAAC,MAAM,EAAE,WAAW,cAAc;AAE9D,QAAI,CAAC;AAAO,WAAK,IAAI,MAAM,uBAAuB;AAClD,QAAI,CAAC;AAAU,WAAK,IAAI,MAAM,2BAA2B;AACzD,QAAI,CAAC;AAAe,WAAK,IAAI,MAAM,+BAA+B;AAClE,QAAI,CAAC;AAAiB,WAAK,IAAI,MAAM,kCAAkC;AACvE,QAAI,CAAC;AAAK,WAAK,IAAI,MAAM,qBAAqB;AAE9C,WAAO;AAAA,MACL,OAAO,QAAQ,MAAM,OAAO,UAAU,oBAAoB,YAAY,OAAO;AAAA,MAE7E,MAAM,WAAW,SAAS,OAAO,UAAU,eAAe,YAAY,QAAQ;AAAA,MAC9E,eAAe,gBAAgB,cAAc,OAAO,SAAS,mBAAmB,yBAAyB,OAAO;AAAA,MAChH,iBAAiB,kBAAkB,gBAAgB,OAAO,iBAAiB,WAAW,YAAY,OAAO;AAAA,MACzG,KAAK,MAAM,IAAI,OAAO,IAAI,OAAO,YAAY,OAAO;AAAA,IACtD;AAAA,EACF;AAAA,EACA,MAAM,uBAAuB,OAAgB;AAC3C,UAAM,OAAO,MAAM,KAAK,WAAW;AAAA,MACjC,QAAQ;AAAA,MACR,QAAQ;AAAA,QACN,UAAU;AAAA,UACR;AAAA,YACE,QAAQ;AAAA,YACR,QAAQ;AAAA,cACN,OAAO;AAAA,gBACL,QAAQ;AAAA,kBACN,iBAAiB,QAAQ,OAAO;AAAA,gBAClC;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,WAAO,KAAK,eAAe;AAAA,EAC7B;AAAA,EACA,MAAM,cAAc,OAAe;AACjC,YAAQ,MAAM,SAAS;AACvB,UAAM,OAAO,MAAM,KAAK,WAAW,EAAE,QAAQ,MAAM,OAAO,EAAE,UAAU,EAAE,WAAW,MAAM,EAAE,EAAE,CAAC;AAE9F,WAAO,KAAK,eAAe;AAAA,EAC7B;AAAA,EAEA,MAAM,UAAU,GAAW,GAAW;AACpC,UAAM,OAAO,MAAM,KAAK,WAAW;AAAA,MACjC,QAAQ;AAAA,MACR,QAAQ;AAAA,QACN,UAAU,CAAC,EAAE,QAAQ,MAAM,OAAO,EAAE,MAAM,EAAE,SAAS,GAAG,SAAS,EAAE,EAAE,EAAE,CAAC;AAAA,MAC1E;AAAA,IACF,CAAC;AAED,WAAO,KAAK,eAAe;AAAA,EAC7B;AACF;AAzsBO,IAAM,aAAN;AAAM,WAgfJ,cAA8E;AAAA,EACnF,MAAM,CAAC,WAAW;AAAA,IAChB,QAAQ;AAAA,IACR,QAAQ;AAAA,MACN,WAAW;AAAA,QACT,gBAAgB;AAAA,UAEd,SAAS,QAAQ,QAAQ;AAAA,QAC3B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,OAAO,CAAC,WAAW;AAAA,IACjB,QAAQ;AAAA,IACR,QAAQ;AAAA,MACN,WAAW;AAAA,QACT,qBAAqB;AAAA,UACnB,SAAS,QAAQ,OAAO;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,eAAe,CAAC,WAAW;AAAA,IACzB,QAAQ;AAAA,IACR,QAAQ;AAAA,MACN,UAAU;AAAA,QACR,oBAAoB;AAAA,UAClB,sBAAsB,QAAQ,OAAO;AAAA,UACrC,2BAA2B,QAAQ,OAAO;AAAA,QAC5C;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,iBAAiB,CAAC,WAAW;AAAA,IAC3B,QAAQ;AAAA,IACR,QAAQ;AAAA,MACN,kBAAkB;AAAA,QAChB,YAAY;AAAA,UACV,SAAS,QAAQ,OAAO;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EACA,KAAK,CAAC,WAAW;AAAA,IACf,QAAQ;AAAA,IACR,QAAQ;AAAA,MACN,KAAK;AAAA,QACH,QAAQ;AAAA,UACN,SAAS,QAAQ,OAAO;AAAA,QAC1B;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;",
|
|
6
6
|
"names": ["crypto"]
|
|
7
7
|
}
|
package/build/lib/utils/p100.js
CHANGED
|
@@ -33,6 +33,7 @@ var import_newTpLinkCipher = __toESM(require("./newTpLinkCipher.js"));
|
|
|
33
33
|
var import_axios2 = __toESM(require("axios"));
|
|
34
34
|
var import_crypto = __toESM(require("crypto"));
|
|
35
35
|
var import_utf8 = __toESM(require("utf8"));
|
|
36
|
+
var import_http = __toESM(require("http"));
|
|
36
37
|
class P100 {
|
|
37
38
|
constructor(log, ipAddress, email, password, timeout) {
|
|
38
39
|
this.log = log;
|
|
@@ -142,7 +143,7 @@ class P100 {
|
|
|
142
143
|
requestTimeMils: Math.round(Date.now() * 1e3)
|
|
143
144
|
}
|
|
144
145
|
};
|
|
145
|
-
this.log.debug("Handshake P100 on host: " + this.ip);
|
|
146
|
+
this.log.debug("Old Handshake P100 on host: " + this.ip);
|
|
146
147
|
const headers = {
|
|
147
148
|
Connection: "Keep-Alive"
|
|
148
149
|
};
|
|
@@ -151,7 +152,7 @@ class P100 {
|
|
|
151
152
|
headers
|
|
152
153
|
};
|
|
153
154
|
await this._axios.post(URL, payload, config).then((res) => {
|
|
154
|
-
this.log.debug("Received Handshake P100 on host response: " + this.ip);
|
|
155
|
+
this.log.debug("Received Old Handshake P100 on host response: " + this.ip);
|
|
155
156
|
if (res.data.error_code || res.status !== 200) {
|
|
156
157
|
return this.handleError(res.data.error_code ? res.data.error_code : res.status, "172");
|
|
157
158
|
}
|
|
@@ -177,6 +178,9 @@ class P100 {
|
|
|
177
178
|
Cookie: this.cookie,
|
|
178
179
|
Connection: "Keep-Alive"
|
|
179
180
|
};
|
|
181
|
+
this.log.debug("Old Login to P100 with url " + URL);
|
|
182
|
+
this.log.debug("Headers " + JSON.stringify(headers));
|
|
183
|
+
this.log.debug("Cipher: " + this.tpLinkCipher);
|
|
180
184
|
if (this.tpLinkCipher) {
|
|
181
185
|
const encryptedPayload = this.tpLinkCipher.encrypt(payload);
|
|
182
186
|
const securePassthroughPayload = {
|
|
@@ -189,11 +193,13 @@ class P100 {
|
|
|
189
193
|
headers,
|
|
190
194
|
timeout: this._timeout * 1e3
|
|
191
195
|
};
|
|
196
|
+
this.log.debug("Post request");
|
|
192
197
|
await this._axios.post(URL, securePassthroughPayload, config).then((res) => {
|
|
193
198
|
if (res.data.error_code || res.status !== 200) {
|
|
194
199
|
return this.handleError(res.data.error_code ? res.data.error_code : res.status, "226");
|
|
195
200
|
}
|
|
196
201
|
const decryptedResponse = this.tpLinkCipher.decrypt(res.data.result.response);
|
|
202
|
+
this.log.debug("Decrypted Response: " + decryptedResponse);
|
|
197
203
|
try {
|
|
198
204
|
const response = JSON.parse(decryptedResponse);
|
|
199
205
|
if (response.error_code !== 0) {
|
|
@@ -216,8 +222,7 @@ class P100 {
|
|
|
216
222
|
Connection: "Keep-Alive",
|
|
217
223
|
Host: this.ip,
|
|
218
224
|
Accept: "*/*",
|
|
219
|
-
"Content-Type": "application/octet-stream"
|
|
220
|
-
"User-Agent": "ioBroker"
|
|
225
|
+
"Content-Type": "application/octet-stream"
|
|
221
226
|
};
|
|
222
227
|
if (this.cookie) {
|
|
223
228
|
headers.Cookie = this.cookie;
|
|
@@ -228,6 +233,11 @@ class P100 {
|
|
|
228
233
|
headers,
|
|
229
234
|
params
|
|
230
235
|
};
|
|
236
|
+
this.log.debug("Raw request to P100 with url " + URL);
|
|
237
|
+
this.log.debug("Data: " + data.toString("hex"));
|
|
238
|
+
this.log.debug("Headers: " + JSON.stringify(headers));
|
|
239
|
+
this.log.debug("Params: " + JSON.stringify(params));
|
|
240
|
+
this.log.debug("Cipher: " + this.tpLinkCipher);
|
|
231
241
|
return this._axios.post(URL, data, config).then((res) => {
|
|
232
242
|
this.log.debug("Received request on host response: " + this.ip);
|
|
233
243
|
if (res.data.error_code || res.status !== 200) {
|
|
@@ -265,25 +275,90 @@ class P100 {
|
|
|
265
275
|
this.tpLinkCipher = new import_tpLinkCipher.default(this.log, b_arr, b_arr2);
|
|
266
276
|
}
|
|
267
277
|
async handshake_new() {
|
|
268
|
-
this.log.debug("Trying new
|
|
278
|
+
this.log.debug("Trying new handshake");
|
|
269
279
|
const local_seed = this._crypto.randomBytes(16);
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
280
|
+
const ah = this.calc_auth_hash(this.email, this.password);
|
|
281
|
+
const options = {
|
|
282
|
+
method: "POST",
|
|
283
|
+
hostname: this.ip,
|
|
284
|
+
path: "/app/handshake1",
|
|
285
|
+
headers: {
|
|
286
|
+
Connection: "Keep-Alive",
|
|
287
|
+
"Content-Type": "application/octet-stream",
|
|
288
|
+
"Content-Length": local_seed.length
|
|
289
|
+
},
|
|
290
|
+
agent: new import_http.default.Agent({
|
|
291
|
+
keepAlive: true
|
|
292
|
+
})
|
|
293
|
+
};
|
|
294
|
+
const response = await new Promise((resolve, reject) => {
|
|
295
|
+
const request = import_http.default.request(options, (res) => {
|
|
296
|
+
let chunks = [];
|
|
297
|
+
if (res.headers && res.headers["set-cookie"]) {
|
|
298
|
+
this.cookie = res.headers["set-cookie"][0].split(";")[0];
|
|
299
|
+
}
|
|
300
|
+
res.on("data", (chunk) => {
|
|
301
|
+
chunks.push(chunk);
|
|
302
|
+
});
|
|
303
|
+
res.on("end", (chunk) => {
|
|
304
|
+
var body = Buffer.concat(chunks);
|
|
305
|
+
this.log.debug(body.toString());
|
|
306
|
+
resolve(body);
|
|
307
|
+
});
|
|
308
|
+
res.on("error", (error) => {
|
|
309
|
+
this.log.error(error);
|
|
310
|
+
resolve(Buffer.from(""));
|
|
311
|
+
});
|
|
312
|
+
}).on("error", (error) => {
|
|
313
|
+
this.log.error(error);
|
|
314
|
+
resolve(Buffer.from(""));
|
|
286
315
|
});
|
|
316
|
+
request.write(local_seed);
|
|
317
|
+
request.end();
|
|
318
|
+
});
|
|
319
|
+
if (!response || !response.subarray) {
|
|
320
|
+
this.log.debug("New Handshake 1 failed");
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
this.log.debug("Handshake 1 response: " + response.toString("hex"));
|
|
324
|
+
const remote_seed = response.subarray(0, 16);
|
|
325
|
+
const server_hash = response.subarray(16);
|
|
326
|
+
this.log.debug("remote seed: " + remote_seed.toString("hex"));
|
|
327
|
+
this.log.debug("server hash: " + server_hash.toString("hex"));
|
|
328
|
+
this.log.debug("Extracted hashes");
|
|
329
|
+
let auth_hash = void 0;
|
|
330
|
+
this.log.debug("Calculated auth hash: " + ah.toString("hex"));
|
|
331
|
+
const calculateAuthHash = (email, password) => {
|
|
332
|
+
return this._crypto.createHash("sha256").update(Buffer.concat([local_seed, remote_seed, this.calc_auth_hash(email, password)])).digest();
|
|
333
|
+
};
|
|
334
|
+
const local_seed_auth_hash = calculateAuthHash(this.email, this.password);
|
|
335
|
+
this.log.debug("Calculated local seed auth hash: " + local_seed_auth_hash.toString("hex"));
|
|
336
|
+
this.log.debug("Server hash: " + server_hash.toString("hex"));
|
|
337
|
+
const validateAuthHash = (email, password) => {
|
|
338
|
+
const calculatedHash = calculateAuthHash(email, password);
|
|
339
|
+
this.log.debug(`Calculated auth hash for ${email}: ${calculatedHash.toString("hex")}`);
|
|
340
|
+
return calculatedHash.toString("hex") === server_hash.toString("hex");
|
|
341
|
+
};
|
|
342
|
+
if (validateAuthHash(this.email, this.password)) {
|
|
343
|
+
this.log.debug("New Handshake 1 successful");
|
|
344
|
+
auth_hash = ah;
|
|
345
|
+
} else if (validateAuthHash("", "")) {
|
|
346
|
+
this.log.debug("New Handshake 1 successful with empty auth hash");
|
|
347
|
+
auth_hash = this.calc_auth_hash("", "");
|
|
348
|
+
} else if (validateAuthHash("test@tp-link.net", "test")) {
|
|
349
|
+
this.log.debug("New Handshake 1 successful with test auth hash");
|
|
350
|
+
auth_hash = this.calc_auth_hash("test@tp-link.net", "test");
|
|
351
|
+
} else {
|
|
352
|
+
this.log.debug("New Handshake 1 failed");
|
|
353
|
+
this.log.debug("Local seed auth hash doesn't match server hash");
|
|
354
|
+
auth_hash = ah;
|
|
355
|
+
}
|
|
356
|
+
const req = this._crypto.createHash("sha256").update(Buffer.concat([remote_seed, local_seed, auth_hash])).digest();
|
|
357
|
+
return this.raw_request("handshake2", req, "text").then((res) => {
|
|
358
|
+
this.log.debug("New Handshake 2 successful: " + res);
|
|
359
|
+
this.newTpLinkCipher = new import_newTpLinkCipher.default(local_seed, remote_seed, auth_hash, this.log);
|
|
360
|
+
this.log.debug("New Init cipher successful");
|
|
361
|
+
return;
|
|
287
362
|
});
|
|
288
363
|
}
|
|
289
364
|
async turnOff() {
|
|
@@ -566,11 +641,12 @@ class P100 {
|
|
|
566
641
|
});
|
|
567
642
|
}
|
|
568
643
|
reAuthenticate() {
|
|
644
|
+
this.log.debug("Reauthenticating");
|
|
569
645
|
if (this.is_klap) {
|
|
570
646
|
this.handshake_new().then(() => {
|
|
571
647
|
this.log.info("KLAP Authenticated successfully");
|
|
572
648
|
}).catch(() => {
|
|
573
|
-
this.log.error("KLAP Handshake failed");
|
|
649
|
+
this.log.error("KLAP Handshake New failed");
|
|
574
650
|
this.is_klap = false;
|
|
575
651
|
});
|
|
576
652
|
} else {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/utils/p100.ts"],
|
|
4
|
-
"sourcesContent": ["/* eslint-disable @typescript-eslint/ban-ts-comment */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { PlugSysinfo } from \"./types\";\nimport TpLinkCipher from \"./tpLinkCipher.js\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { AxiosResponse } from \"axios\";\nimport NewTpLinkCipher from \"./newTpLinkCipher.js\";\nimport { TpLinkAccessory } from \"./tplinkAccessory.js\";\nimport axios from \"axios\";\nimport crypto from \"crypto\";\nimport utf8 from \"utf8\";\n\nexport default class P100 implements TpLinkAccessory {\n private _crypto = crypto;\n protected _axios = axios;\n private _utf8 = utf8;\n public is_klap = true;\n\n private encodedPassword!: string;\n private encodedEmail!: string;\n private privateKey!: string;\n private publicKey!: string;\n protected ip: string;\n protected cookie!: string;\n protected tplink_timeout!: number;\n protected token!: string;\n protected terminalUUID: string;\n private _plugSysInfo!: PlugSysinfo;\n private _reconnect_counter: number;\n protected _timeout!: number;\n\n protected tpLinkCipher!: TpLinkCipher;\n protected newTpLinkCipher!: NewTpLinkCipher;\n\n protected ERROR_CODES = {\n \"0\": \"Success\",\n \"-1010\": \"Invalid Public Key Length\",\n \"-1012\": \"Invalid terminalUUID\",\n \"-1501\": \"Invalid Request or Credentials\",\n \"1002\": \"Incorrect Request\",\n \"-1003\": \"JSON formatting error \",\n \"9999\": \"Session Timeout\",\n \"-1301\": \"Device Error\",\n \"1100\": \"Handshake Failed\",\n \"1111\": \"Login Failed\",\n \"1112\": \"Http Transport Failed\",\n \"1200\": \"Multiple Requests Failed\",\n \"-1004\": \"JSON Encode Failed\",\n \"-1005\": \"AES Decode Failed\",\n \"-1006\": \"Request Length Error\",\n \"-2101\": \"Account Error\",\n \"-1\": \"ERR_COMMON_FAILED\",\n \"1000\": \"ERR_NULL_TRANSPORT\",\n \"1001\": \"ERR_CMD_COMMAND_CANCEL\",\n \"-1001\": \"ERR_UNSPECIFIC\",\n \"-1002\": \"ERR_UNKNOWN_METHOD\",\n \"-1007\": \"ERR_CLOUD_FAILED\",\n \"-1008\": \"ERR_PARAMS\",\n \"-1101\": \"ERR_SESSION_PARAM\",\n \"-1201\": \"ERR_QUICK_SETUP\",\n \"-1302\": \"ERR_DEVICE_NEXT_EVENT\",\n \"-1401\": \"ERR_FIRMWARE\",\n \"-1402\": \"ERR_FIRMWARE_VER_ERROR\",\n \"-1601\": \"ERR_TIME\",\n \"-1602\": \"ERR_TIME_SYS\",\n \"-1603\": \"ERR_TIME_SAVE\",\n \"-1701\": \"ERR_WIRELESS\",\n \"-1702\": \"ERR_WIRELESS_UNSUPPORTED\",\n \"-1801\": \"ERR_SCHEDULE\",\n \"-1802\": \"ERR_SCHEDULE_FULL\",\n \"-1803\": \"ERR_SCHEDULE_CONFLICT\",\n \"-1804\": \"ERR_SCHEDULE_SAVE\",\n \"-1805\": \"ERR_SCHEDULE_INDEX\",\n \"-1901\": \"ERR_COUNTDOWN\",\n \"-1902\": \"ERR_COUNTDOWN_CONFLICT\",\n \"-1903\": \"ERR_COUNTDOWN_SAVE\",\n \"-2001\": \"ERR_ANTITHEFT\",\n \"-2002\": \"ERR_ANTITHEFT_CONFLICT\",\n \"-2003\": \"ERR_ANTITHEFT_SAVE\",\n \"-2201\": \"ERR_STAT\",\n \"-2202\": \"ERR_STAT_SAVE\",\n \"-2301\": \"ERR_DST\",\n \"-2302\": \"ERR_DST_SAVE\",\n \"1003\": \"KLAP\",\n };\n\n constructor(\n public readonly log: any,\n public readonly ipAddress: string,\n public readonly email: string,\n public readonly password: string,\n public readonly timeout: number,\n ) {\n this.log.debug(\"Constructing P100 on host: \" + ipAddress);\n this.ip = ipAddress;\n this.encryptCredentials(email, password);\n this.createKeyPair();\n this.terminalUUID = uuidv4();\n this._reconnect_counter = 0;\n this._timeout = timeout;\n }\n\n private encryptCredentials(email: string, password: string) {\n //Password Encoding\n this.encodedPassword = TpLinkCipher.mime_encoder(password);\n\n //Email Encoding\n this.encodedEmail = this.sha_digest_username(email);\n this.encodedEmail = TpLinkCipher.mime_encoder(this.encodedEmail);\n }\n\n private sha_digest_username(data: string): string {\n const digest = this._crypto.createHash(\"sha1\").update(data).digest(\"hex\");\n\n return digest;\n }\n\n private calc_auth_hash(username: string, password: string): Buffer {\n const usernameDigest = this._crypto\n .createHash(\"sha1\")\n .update(Buffer.from(username.normalize(\"NFKC\")))\n .digest();\n const passwordDigest = this._crypto\n .createHash(\"sha1\")\n .update(Buffer.from(password.normalize(\"NFKC\")))\n .digest();\n const digest = this._crypto\n .createHash(\"sha256\")\n .update(Buffer.concat([usernameDigest, passwordDigest]))\n .digest();\n return digest;\n }\n\n private createKeyPair() {\n // Including publicKey and privateKey from\n // generateKeyPairSync() method with its\n // parameters\n const { publicKey, privateKey } = this._crypto.generateKeyPairSync(\"rsa\", {\n publicKeyEncoding: {\n type: \"spki\",\n format: \"pem\",\n },\n privateKeyEncoding: {\n type: \"pkcs1\",\n format: \"pem\",\n },\n modulusLength: 1024,\n });\n\n this.privateKey = privateKey;\n //@ts-ignore\n this.publicKey = publicKey.toString(\"utf8\");\n }\n\n //old tapo requests\n async handshake(): Promise<void> {\n const URL = \"http://\" + this.ip + \"/app\";\n const payload = {\n method: \"handshake\",\n params: {\n key: this.publicKey,\n requestTimeMils: Math.round(Date.now() * 1000),\n },\n };\n this.log.debug(\"Handshake P100 on host: \" + this.ip);\n\n const headers = {\n Connection: \"Keep-Alive\",\n };\n const config = {\n timeout: 5000,\n headers: headers,\n };\n\n await this._axios\n .post(URL, payload, config)\n .then((res: AxiosResponse) => {\n this.log.debug(\"Received Handshake P100 on host response: \" + this.ip);\n\n if (res.data.error_code || res.status !== 200) {\n return this.handleError(res.data!.error_code ? res.data.error_code : res.status, \"172\");\n }\n\n try {\n const encryptedKey = res.data.result.key.toString(\"utf8\");\n this.decode_handshake_key(encryptedKey);\n if (res.headers[\"set-cookie\"]) {\n this.cookie = res.headers[\"set-cookie\"][0].split(\";\")[0];\n }\n return;\n } catch (error) {\n return this.handleError(res.data.error_code, \"106\");\n }\n })\n .catch((error: Error) => {\n this.log.error(\"111 Error: \" + error ? error.message : \"\");\n return error;\n });\n }\n\n async login(): Promise<void> {\n const URL = \"http://\" + this.ip + \"/app\";\n const payload =\n \"{\" +\n '\"method\": \"login_device\",' +\n '\"params\": {' +\n '\"username\": \"' +\n this.encodedEmail +\n '\",' +\n '\"password\": \"' +\n this.encodedPassword +\n '\"' +\n \"},\" +\n '\"requestTimeMils\": ' +\n Math.round(Date.now() * 1000) +\n \"\" +\n \"};\";\n\n const headers = {\n Cookie: this.cookie,\n Connection: \"Keep-Alive\",\n };\n\n if (this.tpLinkCipher) {\n const encryptedPayload = this.tpLinkCipher.encrypt(payload);\n\n const securePassthroughPayload = {\n method: \"securePassthrough\",\n params: {\n request: encryptedPayload,\n },\n };\n\n const config = {\n headers: headers,\n timeout: this._timeout * 1000,\n };\n\n await this._axios\n .post(URL, securePassthroughPayload, config)\n .then((res: AxiosResponse) => {\n if (res.data.error_code || res.status !== 200) {\n return this.handleError(res.data!.error_code ? res.data.error_code : res.status, \"226\");\n }\n const decryptedResponse = this.tpLinkCipher.decrypt(res.data.result.response);\n try {\n const response = JSON.parse(decryptedResponse);\n if (response.error_code !== 0) {\n return this.handleError(res.data.error_code, \"152\");\n }\n this.token = response.result.token;\n return;\n } catch (error) {\n return this.handleError(JSON.parse(decryptedResponse).error_code, \"157\");\n }\n })\n .catch((error: Error) => {\n this.log.error(\"Error Login: \" + error ? error.message : \"\");\n return error;\n });\n }\n }\n\n private async raw_request(path: string, data: Buffer, responseType: string, params?: any): Promise<any> {\n const URL = \"http://\" + this.ip + \"/app/\" + path;\n\n const headers = {\n Connection: \"Keep-Alive\",\n Host: this.ip,\n Accept: \"*/*\",\n \"Content-Type\": \"application/octet-stream\",\n \"User-Agent\": \"ioBroker\",\n };\n\n if (this.cookie) {\n //@ts-ignore\n headers.Cookie = this.cookie;\n }\n\n const config = {\n timeout: 5000,\n responseType: responseType,\n headers: headers,\n params: params,\n };\n //@ts-ignore\n return this._axios\n .post(URL, data, config)\n .then((res: AxiosResponse) => {\n this.log.debug(\"Received request on host response: \" + this.ip);\n if (res.data.error_code || res.status !== 200) {\n return this.handleError(res.data!.error_code ? res.data.error_code : res.status, \"273\");\n }\n\n try {\n if (res.headers && res.headers[\"set-cookie\"]) {\n this.log.debug(\"Handshake 1 cookie: \" + JSON.stringify(res.headers[\"set-cookie\"][0]));\n this.cookie = res.headers[\"set-cookie\"][0].split(\";\")[0];\n this.tplink_timeout = Number(res.headers[\"set-cookie\"][0].split(\";\")[1]);\n }\n return res.data;\n } catch (error) {\n return this.handleError(res.data.error_code, \"318\");\n }\n })\n .catch((error: Error) => {\n this.log.error(\"276 Error: \" + error.message);\n if (error.message.indexOf(\"403\") > -1) {\n this.reAuthenticate();\n }\n return error;\n });\n }\n\n private decode_handshake_key(key: string) {\n const buff = Buffer.from(key, \"base64\");\n\n const decoded = this._crypto.privateDecrypt(\n {\n key: this.privateKey,\n padding: this._crypto.constants.RSA_PKCS1_PADDING,\n },\n buff,\n );\n\n const b_arr = decoded.slice(0, 16);\n const b_arr2 = decoded.slice(16, 32);\n\n this.tpLinkCipher = new TpLinkCipher(this.log, b_arr, b_arr2);\n }\n\n //new tapo klap requests\n async handshake_new(): Promise<void> {\n this.log.debug(\"Trying new habdshake\");\n\n const local_seed = this._crypto.randomBytes(16);\n\n await this.raw_request(\"handshake1\", local_seed, \"arraybuffer\").then((res) => {\n const remote_seed: Buffer = res.subarray(0, 16);\n const server_hash: Buffer = res.subarray(16);\n\n let auth_hash: any = undefined;\n const ah = this.calc_auth_hash(this.email, this.password);\n const local_seed_auth_hash = this._crypto\n .createHash(\"sha256\")\n .update(Buffer.concat([local_seed, remote_seed, ah]))\n .digest();\n\n if (local_seed_auth_hash.toString(\"hex\") === server_hash.toString(\"hex\")) {\n this.log.debug(\"Handshake 1 successful\");\n auth_hash = ah;\n }\n const req = this._crypto\n .createHash(\"sha256\")\n .update(Buffer.concat([remote_seed, local_seed, auth_hash]))\n .digest();\n\n return this.raw_request(\"handshake2\", req, \"text\").then((res) => {\n this.log.debug(\"Handshake 2 successful: \" + res);\n\n this.newTpLinkCipher = new NewTpLinkCipher(local_seed, remote_seed, auth_hash, this.log);\n this.log.debug(\"Init cipher successful\");\n\n return;\n });\n });\n }\n\n async turnOff(): Promise<boolean> {\n const payload =\n \"{\" +\n '\"method\": \"set_device_info\",' +\n '\"params\": {' +\n '\"device_on\": false' +\n \"},\" +\n '\"terminalUUID\": \"' +\n this.terminalUUID +\n '\",' +\n '\"requestTimeMils\": ' +\n Math.round(Date.now() * 1000) +\n \"\" +\n \"};\";\n return this.sendRequest(payload);\n }\n\n async turnOn(): Promise<boolean> {\n const payload =\n \"{\" +\n '\"method\": \"set_device_info\",' +\n '\"params\": {' +\n '\"device_on\": true' +\n \"},\" +\n '\"terminalUUID\": \"' +\n this.terminalUUID +\n '\",' +\n '\"requestTimeMils\": ' +\n Math.round(Date.now() * 1000) +\n \"\" +\n \"};\";\n\n return this.sendRequest(payload);\n }\n\n async setPowerState(state: boolean): Promise<boolean> {\n if (state) {\n return this.turnOn();\n } else {\n return this.turnOff();\n }\n }\n\n async getDeviceInfo(force?: boolean): Promise<PlugSysinfo> {\n if (!force) {\n return new Promise((resolve) => {\n resolve(this.getSysInfo());\n });\n }\n const URL = \"http://\" + this.ip + \"/app?token=\" + this.token;\n\n const payload = \"{\" + '\"method\": \"get_device_info\",' + '\"requestTimeMils\": ' + Math.round(Date.now() * 1000) + \"\" + \"};\";\n const headers = {\n Cookie: this.cookie,\n };\n\n if (this.tpLinkCipher) {\n const encryptedPayload = this.tpLinkCipher.encrypt(payload);\n\n const securePassthroughPayload = {\n method: \"securePassthrough\",\n params: {\n request: encryptedPayload,\n },\n };\n\n const config = {\n headers: headers,\n timeout: this._timeout * 1000,\n };\n //@ts-ignore\n return this._axios\n .post(URL, securePassthroughPayload, config)\n .then((res: any) => {\n if (res.data.error_code) {\n if ((res.data.error_code === \"9999\" || res.data.error_code === 9999) && this._reconnect_counter <= 3) {\n //@ts-ignore\n this.log.error(\" Error Code: \" + res.data.error_code + \", \" + this.ERROR_CODES[res.data.error_code]);\n this.log.debug(\"Trying to reconnect...\");\n return this.reconnect().then(() => {\n return this.getDeviceInfo();\n });\n }\n this._reconnect_counter = 0;\n return this.handleError(res.data.error_code, \"326\");\n }\n\n const decryptedResponse = this.tpLinkCipher.decrypt(res.data.result.response);\n try {\n const response = JSON.parse(decryptedResponse);\n if (response.error_code !== 0) {\n return this.handleError(response.error_code, \"333\");\n }\n this.setSysInfo(response.result);\n this.log.debug(\"Device Info: \", response.result);\n\n return this.getSysInfo();\n } catch (error) {\n this.log.debug(error.stack);\n return this.handleError(JSON.parse(decryptedResponse).error_code, \"340\");\n }\n })\n .catch((error: Error) => {\n this.log.error(\"371 Error: \" + error ? error.message : \"\");\n return error;\n });\n } else if (this.newTpLinkCipher) {\n const data = this.newTpLinkCipher.encrypt(payload);\n\n const URL = \"http://\" + this.ip + \"/app/\" + \"request\";\n const headers = {\n Connection: \"Keep-Alive\",\n Host: this.ip,\n Accept: \"*/*\",\n \"Content-Type\": \"application/octet-stream\",\n };\n\n if (this.cookie) {\n //@ts-ignore\n headers.Cookie = this.cookie;\n }\n\n const config = {\n timeout: 5000,\n responseType: \"arraybuffer\",\n headers: headers,\n params: { seq: data.seq.toString() },\n };\n //@ts-ignore\n return this._axios\n .post(URL, data.encryptedPayload, config)\n .then((res: AxiosResponse) => {\n if (res.data.error_code) {\n return this.handleError(res.data.error_code, \"309\");\n }\n\n try {\n if (res.headers && res.headers[\"set-cookie\"]) {\n this.cookie = res.headers[\"set-cookie\"][0].split(\";\")[0];\n }\n\n const response = JSON.parse(this.newTpLinkCipher.decrypt(res.data));\n\n if (response.error_code !== 0) {\n return this.handleError(response.error_code, \"333\");\n }\n this.setSysInfo(response.result);\n this.log.debug(\"Device Info: \", response.result);\n\n return this.getSysInfo();\n } catch (error) {\n this.log.debug(this.newTpLinkCipher.decrypt(res.data));\n this.log.debug(\"Status: \" + res.status);\n return this.handleError(res.data.error_code, \"480\");\n }\n })\n .catch((error: Error) => {\n this.log.debug(\"469 Error: \" + JSON.stringify(error));\n this.log.info(\"469 Error: \" + error.message);\n if (error.message.indexOf(\"403\") > -1) {\n this.reAuthenticate();\n }\n return error;\n });\n } else {\n return new Promise<PlugSysinfo>((resolve, reject) => {\n reject();\n });\n }\n }\n\n /**\n * Cached value of `sysinfo.device_id` if set.\n */\n get id(): string {\n if (this.getSysInfo()) {\n return this.getSysInfo().device_id;\n }\n return \"\";\n }\n\n /**\n * Cached value of `sysinfo.device_id` if set.\n */\n get name(): string {\n if (this.getSysInfo()) {\n return Buffer.from(this.getSysInfo().nickname, \"base64\").toString(\"utf8\");\n }\n return \"\";\n }\n\n get model(): string {\n if (this.getSysInfo()) {\n return this.getSysInfo().model;\n }\n return \"\";\n }\n\n get serialNumber(): string {\n if (this.getSysInfo()) {\n return this.getSysInfo().hw_id;\n }\n return \"\";\n }\n\n get firmwareRevision(): string {\n if (this.getSysInfo()) {\n return this.getSysInfo().fw_ver;\n }\n return \"\";\n }\n\n get hardwareRevision(): string {\n if (this.getSysInfo()) {\n return this.getSysInfo().hw_ver;\n }\n return \"\";\n }\n\n protected setSysInfo(sysInfo: PlugSysinfo) {\n this._plugSysInfo = sysInfo;\n this._plugSysInfo.last_update = Date.now();\n }\n\n public getSysInfo(): PlugSysinfo {\n return this._plugSysInfo;\n }\n\n protected handleError(errorCode: number | string, line: string): boolean {\n //@ts-ignore\n const errorMessage = this.ERROR_CODES[errorCode];\n if (typeof errorCode === \"number\" && errorCode === 1003) {\n this.log.info(\"Trying KLAP Auth\");\n this.is_klap = true;\n } else {\n this.log.error(line + \" Error Code: \" + errorCode + \", \" + errorMessage + \" \" + this.ip);\n }\n return false;\n }\n\n protected async sendRequest(payload: string): Promise<boolean> {\n if (this.tpLinkCipher) {\n return this.handleRequest(payload)\n .then((result) => {\n return result ? true : false;\n })\n .catch((error) => {\n if (error.message && error.message.indexOf(\"9999\") > 0 && this._reconnect_counter <= 3) {\n return this.reconnect().then(() => {\n return this.handleRequest(payload).then((result) => {\n return result ? true : false;\n });\n });\n }\n this._reconnect_counter = 0;\n return false;\n });\n } else {\n return this.handleKlapRequest(payload)\n .then((result) => {\n return result ? true : false;\n })\n .catch((error) => {\n if (error.message && error.message.indexOf(\"9999\") > 0 && this._reconnect_counter <= 3) {\n return this.newReconnect().then(() => {\n return this.handleKlapRequest(payload).then((result) => {\n return result ? true : false;\n });\n });\n }\n this._reconnect_counter = 0;\n return false;\n });\n }\n }\n\n protected handleRequest(payload: string): Promise<any> {\n const URL = \"http://\" + this.ip + \"/app?token=\" + this.token;\n\n const headers = {\n Cookie: this.cookie,\n Connection: \"Keep-Alive\",\n };\n\n if (this.tpLinkCipher) {\n const encryptedPayload = this.tpLinkCipher.encrypt(payload);\n\n const securePassthroughPayload = {\n method: \"securePassthrough\",\n params: {\n request: encryptedPayload,\n },\n };\n\n const config = {\n headers: headers,\n timeout: this._timeout * 1000,\n };\n\n return this._axios\n .post(URL, securePassthroughPayload, config)\n .then((res: AxiosResponse) => {\n if (res.data.error_code) {\n if (res.data.error_code === \"9999\" || (res.data.error_code === 9999 && this._reconnect_counter <= 3)) {\n //@ts-ignore\n this.log.error(\" Error Code: \" + res.data.error_code + \", \" + this.ERROR_CODES[res.data.error_code]);\n this.log.debug(\"Trying to reconnect...\");\n return this.reconnect().then(() => {\n return this.getDeviceInfo();\n });\n }\n this._reconnect_counter = 0;\n return this.handleError(res.data.error_code, \"357\");\n }\n\n const decryptedResponse = this.tpLinkCipher.decrypt(res.data.result.response);\n try {\n const response = JSON.parse(decryptedResponse);\n this.log.debug(response);\n if (response.error_code !== 0) {\n return this.handleError(response.error_code, \"364\");\n }\n return response;\n } catch (error) {\n return this.handleError(JSON.parse(decryptedResponse).error_code, \"368\");\n }\n })\n .catch((error: Error) => {\n return this.handleError(error.message, \"656\");\n });\n }\n return new Promise<true>((resolve, reject) => {\n reject();\n });\n }\n\n protected handleKlapRequest(payload: string): Promise<any> {\n if (this.newTpLinkCipher) {\n const data = this.newTpLinkCipher.encrypt(payload);\n\n return this.raw_request(\"request\", data.encryptedPayload, \"arraybuffer\", { seq: data.seq.toString() })\n .then((res) => {\n return JSON.parse(this.newTpLinkCipher.decrypt(res));\n })\n .catch((error: Error) => {\n return this.handleError(error.message, \"671\");\n });\n }\n return new Promise<true>((resolve, reject) => {\n reject();\n });\n }\n\n protected async reconnect(): Promise<void> {\n this._reconnect_counter++;\n return this.handshake().then(() => {\n this.login().then(() => {\n return;\n });\n });\n }\n\n protected async newReconnect(): Promise<void> {\n this._reconnect_counter++;\n return this.handshake_new().then(() => {\n return;\n });\n }\n\n private reAuthenticate(): void {\n if (this.is_klap) {\n this.handshake_new()\n .then(() => {\n this.log.info(\"KLAP Authenticated successfully\");\n })\n .catch(() => {\n this.log.error(\"KLAP Handshake failed\");\n this.is_klap = false;\n });\n } else {\n this.handshake().then(() => {\n this.login()\n .then(() => {\n this.log.info(\"Authenticated successfully\");\n })\n .catch(() => {\n this.log.error(\"Login failed\");\n });\n });\n }\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
6
|
-
"names": ["import_axios", "crypto", "axios", "utf8", "uuidv4", "TpLinkCipher", "
|
|
4
|
+
"sourcesContent": ["/* eslint-disable @typescript-eslint/ban-ts-comment */\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { PlugSysinfo } from \"./types\";\nimport TpLinkCipher from \"./tpLinkCipher.js\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport { AxiosResponse } from \"axios\";\nimport NewTpLinkCipher from \"./newTpLinkCipher.js\";\nimport { TpLinkAccessory } from \"./tplinkAccessory.js\";\nimport axios from \"axios\";\nimport crypto from \"crypto\";\nimport utf8 from \"utf8\";\n\nimport http from \"http\";\n\nexport default class P100 implements TpLinkAccessory {\n private _crypto = crypto;\n protected _axios = axios;\n private _utf8 = utf8;\n public is_klap = true;\n\n private encodedPassword!: string;\n private encodedEmail!: string;\n private privateKey!: string;\n private publicKey!: string;\n protected ip: string;\n protected cookie!: string;\n protected tplink_timeout!: number;\n protected token!: string;\n protected terminalUUID: string;\n private _plugSysInfo!: PlugSysinfo;\n private _reconnect_counter: number;\n protected _timeout!: number;\n\n protected tpLinkCipher!: TpLinkCipher;\n protected newTpLinkCipher!: NewTpLinkCipher;\n\n protected ERROR_CODES = {\n \"0\": \"Success\",\n \"-1010\": \"Invalid Public Key Length\",\n \"-1012\": \"Invalid terminalUUID\",\n \"-1501\": \"Invalid Request or Credentials\",\n \"1002\": \"Incorrect Request\",\n \"-1003\": \"JSON formatting error \",\n \"9999\": \"Session Timeout\",\n \"-1301\": \"Device Error\",\n \"1100\": \"Handshake Failed\",\n \"1111\": \"Login Failed\",\n \"1112\": \"Http Transport Failed\",\n \"1200\": \"Multiple Requests Failed\",\n \"-1004\": \"JSON Encode Failed\",\n \"-1005\": \"AES Decode Failed\",\n \"-1006\": \"Request Length Error\",\n \"-2101\": \"Account Error\",\n \"-1\": \"ERR_COMMON_FAILED\",\n \"1000\": \"ERR_NULL_TRANSPORT\",\n \"1001\": \"ERR_CMD_COMMAND_CANCEL\",\n \"-1001\": \"ERR_UNSPECIFIC\",\n \"-1002\": \"ERR_UNKNOWN_METHOD\",\n \"-1007\": \"ERR_CLOUD_FAILED\",\n \"-1008\": \"ERR_PARAMS\",\n \"-1101\": \"ERR_SESSION_PARAM\",\n \"-1201\": \"ERR_QUICK_SETUP\",\n \"-1302\": \"ERR_DEVICE_NEXT_EVENT\",\n \"-1401\": \"ERR_FIRMWARE\",\n \"-1402\": \"ERR_FIRMWARE_VER_ERROR\",\n \"-1601\": \"ERR_TIME\",\n \"-1602\": \"ERR_TIME_SYS\",\n \"-1603\": \"ERR_TIME_SAVE\",\n \"-1701\": \"ERR_WIRELESS\",\n \"-1702\": \"ERR_WIRELESS_UNSUPPORTED\",\n \"-1801\": \"ERR_SCHEDULE\",\n \"-1802\": \"ERR_SCHEDULE_FULL\",\n \"-1803\": \"ERR_SCHEDULE_CONFLICT\",\n \"-1804\": \"ERR_SCHEDULE_SAVE\",\n \"-1805\": \"ERR_SCHEDULE_INDEX\",\n \"-1901\": \"ERR_COUNTDOWN\",\n \"-1902\": \"ERR_COUNTDOWN_CONFLICT\",\n \"-1903\": \"ERR_COUNTDOWN_SAVE\",\n \"-2001\": \"ERR_ANTITHEFT\",\n \"-2002\": \"ERR_ANTITHEFT_CONFLICT\",\n \"-2003\": \"ERR_ANTITHEFT_SAVE\",\n \"-2201\": \"ERR_STAT\",\n \"-2202\": \"ERR_STAT_SAVE\",\n \"-2301\": \"ERR_DST\",\n \"-2302\": \"ERR_DST_SAVE\",\n \"1003\": \"KLAP\",\n };\n\n constructor(\n public readonly log: any,\n public readonly ipAddress: string,\n public readonly email: string,\n public readonly password: string,\n public readonly timeout: number,\n ) {\n this.log.debug(\"Constructing P100 on host: \" + ipAddress);\n this.ip = ipAddress;\n this.encryptCredentials(email, password);\n this.createKeyPair();\n this.terminalUUID = uuidv4();\n this._reconnect_counter = 0;\n this._timeout = timeout;\n }\n\n private encryptCredentials(email: string, password: string) {\n //Password Encoding\n this.encodedPassword = TpLinkCipher.mime_encoder(password);\n\n //Email Encoding\n this.encodedEmail = this.sha_digest_username(email);\n this.encodedEmail = TpLinkCipher.mime_encoder(this.encodedEmail);\n }\n\n private sha_digest_username(data: string): string {\n const digest = this._crypto.createHash(\"sha1\").update(data).digest(\"hex\");\n\n return digest;\n }\n\n private calc_auth_hash(username: string, password: string): Buffer {\n const usernameDigest = this._crypto\n .createHash(\"sha1\")\n .update(Buffer.from(username.normalize(\"NFKC\")))\n .digest();\n const passwordDigest = this._crypto\n .createHash(\"sha1\")\n .update(Buffer.from(password.normalize(\"NFKC\")))\n .digest();\n const digest = this._crypto\n .createHash(\"sha256\")\n .update(Buffer.concat([usernameDigest, passwordDigest]))\n .digest();\n return digest;\n }\n\n private createKeyPair() {\n // Including publicKey and privateKey from\n // generateKeyPairSync() method with its\n // parameters\n const { publicKey, privateKey } = this._crypto.generateKeyPairSync(\"rsa\", {\n publicKeyEncoding: {\n type: \"spki\",\n format: \"pem\",\n },\n privateKeyEncoding: {\n type: \"pkcs1\",\n format: \"pem\",\n },\n modulusLength: 1024,\n });\n\n this.privateKey = privateKey;\n //@ts-ignore\n this.publicKey = publicKey.toString(\"utf8\");\n }\n\n //old tapo requests\n async handshake(): Promise<void> {\n const URL = \"http://\" + this.ip + \"/app\";\n const payload = {\n method: \"handshake\",\n params: {\n key: this.publicKey,\n requestTimeMils: Math.round(Date.now() * 1000),\n },\n };\n this.log.debug(\"Old Handshake P100 on host: \" + this.ip);\n\n const headers = {\n Connection: \"Keep-Alive\",\n };\n const config = {\n timeout: 5000,\n headers: headers,\n };\n\n await this._axios\n .post(URL, payload, config)\n .then((res: AxiosResponse) => {\n this.log.debug(\"Received Old Handshake P100 on host response: \" + this.ip);\n\n if (res.data.error_code || res.status !== 200) {\n return this.handleError(res.data!.error_code ? res.data.error_code : res.status, \"172\");\n }\n\n try {\n const encryptedKey = res.data.result.key.toString(\"utf8\");\n this.decode_handshake_key(encryptedKey);\n if (res.headers[\"set-cookie\"]) {\n this.cookie = res.headers[\"set-cookie\"][0].split(\";\")[0];\n }\n return;\n } catch (error) {\n return this.handleError(res.data.error_code, \"106\");\n }\n })\n .catch((error: Error) => {\n this.log.error(\"111 Error: \" + error ? error.message : \"\");\n return error;\n });\n }\n\n async login(): Promise<void> {\n const URL = \"http://\" + this.ip + \"/app\";\n const payload =\n \"{\" +\n '\"method\": \"login_device\",' +\n '\"params\": {' +\n '\"username\": \"' +\n this.encodedEmail +\n '\",' +\n '\"password\": \"' +\n this.encodedPassword +\n '\"' +\n \"},\" +\n '\"requestTimeMils\": ' +\n Math.round(Date.now() * 1000) +\n \"\" +\n \"};\";\n\n const headers = {\n Cookie: this.cookie,\n Connection: \"Keep-Alive\",\n };\n\n this.log.debug(\"Old Login to P100 with url \" + URL);\n this.log.debug(\"Headers \" + JSON.stringify(headers));\n this.log.debug(\"Cipher: \" + this.tpLinkCipher);\n if (this.tpLinkCipher) {\n const encryptedPayload = this.tpLinkCipher.encrypt(payload);\n\n const securePassthroughPayload = {\n method: \"securePassthrough\",\n params: {\n request: encryptedPayload,\n },\n };\n\n const config = {\n headers: headers,\n timeout: this._timeout * 1000,\n };\n this.log.debug(\"Post request\");\n await this._axios\n .post(URL, securePassthroughPayload, config)\n .then((res: AxiosResponse) => {\n if (res.data.error_code || res.status !== 200) {\n return this.handleError(res.data!.error_code ? res.data.error_code : res.status, \"226\");\n }\n const decryptedResponse = this.tpLinkCipher.decrypt(res.data.result.response);\n this.log.debug(\"Decrypted Response: \" + decryptedResponse);\n try {\n const response = JSON.parse(decryptedResponse);\n if (response.error_code !== 0) {\n return this.handleError(res.data.error_code, \"152\");\n }\n this.token = response.result.token;\n return;\n } catch (error) {\n return this.handleError(JSON.parse(decryptedResponse).error_code, \"157\");\n }\n })\n .catch((error: Error) => {\n this.log.error(\"Error Login: \" + error ? error.message : \"\");\n return error;\n });\n }\n }\n\n private async raw_request(path: string, data: Buffer, responseType: string, params?: any): Promise<any> {\n const URL = \"http://\" + this.ip + \"/app/\" + path;\n\n const headers = {\n Connection: \"Keep-Alive\",\n Host: this.ip,\n Accept: \"*/*\",\n \"Content-Type\": \"application/octet-stream\",\n };\n\n if (this.cookie) {\n //@ts-ignore\n headers.Cookie = this.cookie;\n }\n\n const config = {\n timeout: 5000,\n responseType: responseType,\n headers: headers,\n params: params,\n };\n this.log.debug(\"Raw request to P100 with url \" + URL);\n this.log.debug(\"Data: \" + data.toString(\"hex\"));\n this.log.debug(\"Headers: \" + JSON.stringify(headers));\n this.log.debug(\"Params: \" + JSON.stringify(params));\n this.log.debug(\"Cipher: \" + this.tpLinkCipher);\n\n //@ts-ignore\n return this._axios\n .post(URL, data, config)\n .then((res: AxiosResponse) => {\n this.log.debug(\"Received request on host response: \" + this.ip);\n if (res.data.error_code || res.status !== 200) {\n return this.handleError(res.data!.error_code ? res.data.error_code : res.status, \"273\");\n }\n\n try {\n if (res.headers && res.headers[\"set-cookie\"]) {\n this.log.debug(\"Handshake 1 cookie: \" + JSON.stringify(res.headers[\"set-cookie\"][0]));\n this.cookie = res.headers[\"set-cookie\"][0].split(\";\")[0];\n this.tplink_timeout = Number(res.headers[\"set-cookie\"][0].split(\";\")[1]);\n }\n return res.data;\n } catch (error) {\n return this.handleError(res.data.error_code, \"318\");\n }\n })\n .catch((error: Error) => {\n this.log.error(\"276 Error: \" + error.message);\n if (error.message.indexOf(\"403\") > -1) {\n this.reAuthenticate();\n }\n return error;\n });\n }\n\n private decode_handshake_key(key: string) {\n const buff = Buffer.from(key, \"base64\");\n\n const decoded = this._crypto.privateDecrypt(\n {\n key: this.privateKey,\n padding: this._crypto.constants.RSA_PKCS1_PADDING,\n },\n buff,\n );\n\n const b_arr = decoded.slice(0, 16);\n const b_arr2 = decoded.slice(16, 32);\n\n this.tpLinkCipher = new TpLinkCipher(this.log, b_arr, b_arr2);\n }\n\n //new tapo klap requests\n async handshake_new(): Promise<void> {\n this.log.debug(\"Trying new handshake\");\n\n const local_seed = this._crypto.randomBytes(16);\n\n const ah = this.calc_auth_hash(this.email, this.password);\n //send handshake1 via native http\n\n const options: http.RequestOptions = {\n method: \"POST\",\n hostname: this.ip,\n path: \"/app/handshake1\",\n headers: {\n Connection: \"Keep-Alive\",\n \"Content-Type\": \"application/octet-stream\",\n \"Content-Length\": local_seed.length,\n },\n agent: new http.Agent({\n keepAlive: true,\n }),\n };\n const response = await new Promise<Buffer>((resolve, reject) => {\n const request = http\n .request(options, (res: any) => {\n let chunks: any = [];\n if (res.headers && res.headers[\"set-cookie\"]) {\n this.cookie = res.headers[\"set-cookie\"][0].split(\";\")[0];\n }\n res.on(\"data\", (chunk: any) => {\n chunks.push(chunk);\n });\n\n res.on(\"end\", (chunk: any) => {\n var body = Buffer.concat(chunks);\n this.log.debug(body.toString());\n resolve(body);\n });\n\n res.on(\"error\", (error: any) => {\n this.log.error(error);\n resolve(Buffer.from(\"\"));\n });\n })\n .on(\"error\", (error: any) => {\n this.log.error(error);\n resolve(Buffer.from(\"\"));\n });\n request.write(local_seed);\n request.end();\n });\n // const response = await this.raw_request(\"handshake1\", local_seed, \"arraybuffer\").then((res) => {\n //axios not working for handshake1\n if (!response || !response.subarray) {\n this.log.debug(\"New Handshake 1 failed\");\n return;\n }\n this.log.debug(\"Handshake 1 response: \" + response.toString(\"hex\"));\n const remote_seed: Buffer = response.subarray(0, 16);\n const server_hash: Buffer = response.subarray(16);\n this.log.debug(\"remote seed: \" + remote_seed.toString(\"hex\"));\n this.log.debug(\"server hash: \" + server_hash.toString(\"hex\"));\n this.log.debug(\"Extracted hashes\");\n let auth_hash: any = undefined;\n this.log.debug(\"Calculated auth hash: \" + ah.toString(\"hex\"));\n const calculateAuthHash = (email: string, password: string) => {\n return this._crypto\n .createHash(\"sha256\")\n .update(Buffer.concat([local_seed, remote_seed, this.calc_auth_hash(email, password)]))\n .digest();\n };\n\n const local_seed_auth_hash = calculateAuthHash(this.email, this.password);\n this.log.debug(\"Calculated local seed auth hash: \" + local_seed_auth_hash.toString(\"hex\"));\n this.log.debug(\"Server hash: \" + server_hash.toString(\"hex\"));\n\n const validateAuthHash = (email: string, password: string): boolean => {\n const calculatedHash = calculateAuthHash(email, password);\n this.log.debug(`Calculated auth hash for ${email}: ${calculatedHash.toString(\"hex\")}`);\n return calculatedHash.toString(\"hex\") === server_hash.toString(\"hex\");\n };\n\n if (validateAuthHash(this.email, this.password)) {\n this.log.debug(\"New Handshake 1 successful\");\n auth_hash = ah;\n } else if (validateAuthHash(\"\", \"\")) {\n this.log.debug(\"New Handshake 1 successful with empty auth hash\");\n auth_hash = this.calc_auth_hash(\"\", \"\");\n } else if (validateAuthHash(\"test@tp-link.net\", \"test\")) {\n this.log.debug(\"New Handshake 1 successful with test auth hash\");\n auth_hash = this.calc_auth_hash(\"test@tp-link.net\", \"test\");\n } else {\n this.log.debug(\"New Handshake 1 failed\");\n this.log.debug(\"Local seed auth hash doesn't match server hash\");\n auth_hash = ah;\n }\n const req = this._crypto\n .createHash(\"sha256\")\n .update(Buffer.concat([remote_seed, local_seed, auth_hash]))\n .digest();\n\n return this.raw_request(\"handshake2\", req, \"text\").then((res) => {\n this.log.debug(\"New Handshake 2 successful: \" + res);\n\n this.newTpLinkCipher = new NewTpLinkCipher(local_seed, remote_seed, auth_hash, this.log);\n this.log.debug(\"New Init cipher successful\");\n\n return;\n });\n // });\n }\n\n async turnOff(): Promise<boolean> {\n const payload =\n \"{\" +\n '\"method\": \"set_device_info\",' +\n '\"params\": {' +\n '\"device_on\": false' +\n \"},\" +\n '\"terminalUUID\": \"' +\n this.terminalUUID +\n '\",' +\n '\"requestTimeMils\": ' +\n Math.round(Date.now() * 1000) +\n \"\" +\n \"};\";\n return this.sendRequest(payload);\n }\n\n async turnOn(): Promise<boolean> {\n const payload =\n \"{\" +\n '\"method\": \"set_device_info\",' +\n '\"params\": {' +\n '\"device_on\": true' +\n \"},\" +\n '\"terminalUUID\": \"' +\n this.terminalUUID +\n '\",' +\n '\"requestTimeMils\": ' +\n Math.round(Date.now() * 1000) +\n \"\" +\n \"};\";\n\n return this.sendRequest(payload);\n }\n\n async setPowerState(state: boolean): Promise<boolean> {\n if (state) {\n return this.turnOn();\n } else {\n return this.turnOff();\n }\n }\n\n async getDeviceInfo(force?: boolean): Promise<PlugSysinfo> {\n if (!force) {\n return new Promise((resolve) => {\n resolve(this.getSysInfo());\n });\n }\n const URL = \"http://\" + this.ip + \"/app?token=\" + this.token;\n\n const payload = \"{\" + '\"method\": \"get_device_info\",' + '\"requestTimeMils\": ' + Math.round(Date.now() * 1000) + \"\" + \"};\";\n const headers = {\n Cookie: this.cookie,\n };\n\n if (this.tpLinkCipher) {\n const encryptedPayload = this.tpLinkCipher.encrypt(payload);\n\n const securePassthroughPayload = {\n method: \"securePassthrough\",\n params: {\n request: encryptedPayload,\n },\n };\n\n const config = {\n headers: headers,\n timeout: this._timeout * 1000,\n };\n //@ts-ignore\n return this._axios\n .post(URL, securePassthroughPayload, config)\n .then((res: any) => {\n if (res.data.error_code) {\n if ((res.data.error_code === \"9999\" || res.data.error_code === 9999) && this._reconnect_counter <= 3) {\n //@ts-ignore\n this.log.error(\" Error Code: \" + res.data.error_code + \", \" + this.ERROR_CODES[res.data.error_code]);\n this.log.debug(\"Trying to reconnect...\");\n return this.reconnect().then(() => {\n return this.getDeviceInfo();\n });\n }\n this._reconnect_counter = 0;\n return this.handleError(res.data.error_code, \"326\");\n }\n\n const decryptedResponse = this.tpLinkCipher.decrypt(res.data.result.response);\n try {\n const response = JSON.parse(decryptedResponse);\n if (response.error_code !== 0) {\n return this.handleError(response.error_code, \"333\");\n }\n this.setSysInfo(response.result);\n this.log.debug(\"Device Info: \", response.result);\n\n return this.getSysInfo();\n } catch (error) {\n this.log.debug(error.stack);\n return this.handleError(JSON.parse(decryptedResponse).error_code, \"340\");\n }\n })\n .catch((error: Error) => {\n this.log.error(\"371 Error: \" + error ? error.message : \"\");\n return error;\n });\n } else if (this.newTpLinkCipher) {\n const data = this.newTpLinkCipher.encrypt(payload);\n\n const URL = \"http://\" + this.ip + \"/app/\" + \"request\";\n const headers = {\n Connection: \"Keep-Alive\",\n Host: this.ip,\n Accept: \"*/*\",\n \"Content-Type\": \"application/octet-stream\",\n };\n\n if (this.cookie) {\n //@ts-ignore\n headers.Cookie = this.cookie;\n }\n\n const config = {\n timeout: 5000,\n responseType: \"arraybuffer\",\n headers: headers,\n params: { seq: data.seq.toString() },\n };\n //@ts-ignore\n return this._axios\n .post(URL, data.encryptedPayload, config)\n .then((res: AxiosResponse) => {\n if (res.data.error_code) {\n return this.handleError(res.data.error_code, \"309\");\n }\n\n try {\n if (res.headers && res.headers[\"set-cookie\"]) {\n this.cookie = res.headers[\"set-cookie\"][0].split(\";\")[0];\n }\n\n const response = JSON.parse(this.newTpLinkCipher.decrypt(res.data));\n\n if (response.error_code !== 0) {\n return this.handleError(response.error_code, \"333\");\n }\n this.setSysInfo(response.result);\n this.log.debug(\"Device Info: \", response.result);\n\n return this.getSysInfo();\n } catch (error) {\n this.log.debug(this.newTpLinkCipher.decrypt(res.data));\n this.log.debug(\"Status: \" + res.status);\n return this.handleError(res.data.error_code, \"480\");\n }\n })\n .catch((error: Error) => {\n this.log.debug(\"469 Error: \" + JSON.stringify(error));\n this.log.info(\"469 Error: \" + error.message);\n if (error.message.indexOf(\"403\") > -1) {\n this.reAuthenticate();\n }\n return error;\n });\n } else {\n return new Promise<PlugSysinfo>((resolve, reject) => {\n reject();\n });\n }\n }\n\n /**\n * Cached value of `sysinfo.device_id` if set.\n */\n get id(): string {\n if (this.getSysInfo()) {\n return this.getSysInfo().device_id;\n }\n return \"\";\n }\n\n /**\n * Cached value of `sysinfo.device_id` if set.\n */\n get name(): string {\n if (this.getSysInfo()) {\n return Buffer.from(this.getSysInfo().nickname, \"base64\").toString(\"utf8\");\n }\n return \"\";\n }\n\n get model(): string {\n if (this.getSysInfo()) {\n return this.getSysInfo().model;\n }\n return \"\";\n }\n\n get serialNumber(): string {\n if (this.getSysInfo()) {\n return this.getSysInfo().hw_id;\n }\n return \"\";\n }\n\n get firmwareRevision(): string {\n if (this.getSysInfo()) {\n return this.getSysInfo().fw_ver;\n }\n return \"\";\n }\n\n get hardwareRevision(): string {\n if (this.getSysInfo()) {\n return this.getSysInfo().hw_ver;\n }\n return \"\";\n }\n\n protected setSysInfo(sysInfo: PlugSysinfo) {\n this._plugSysInfo = sysInfo;\n this._plugSysInfo.last_update = Date.now();\n }\n\n public getSysInfo(): PlugSysinfo {\n return this._plugSysInfo;\n }\n\n protected handleError(errorCode: number | string, line: string): boolean {\n //@ts-ignore\n const errorMessage = this.ERROR_CODES[errorCode];\n if (typeof errorCode === \"number\" && errorCode === 1003) {\n this.log.info(\"Trying KLAP Auth\");\n this.is_klap = true;\n } else {\n this.log.error(line + \" Error Code: \" + errorCode + \", \" + errorMessage + \" \" + this.ip);\n }\n return false;\n }\n\n protected async sendRequest(payload: string): Promise<boolean> {\n if (this.tpLinkCipher) {\n return this.handleRequest(payload)\n .then((result) => {\n return result ? true : false;\n })\n .catch((error) => {\n if (error.message && error.message.indexOf(\"9999\") > 0 && this._reconnect_counter <= 3) {\n return this.reconnect().then(() => {\n return this.handleRequest(payload).then((result) => {\n return result ? true : false;\n });\n });\n }\n this._reconnect_counter = 0;\n return false;\n });\n } else {\n return this.handleKlapRequest(payload)\n .then((result) => {\n return result ? true : false;\n })\n .catch((error) => {\n if (error.message && error.message.indexOf(\"9999\") > 0 && this._reconnect_counter <= 3) {\n return this.newReconnect().then(() => {\n return this.handleKlapRequest(payload).then((result) => {\n return result ? true : false;\n });\n });\n }\n this._reconnect_counter = 0;\n return false;\n });\n }\n }\n\n protected handleRequest(payload: string): Promise<any> {\n const URL = \"http://\" + this.ip + \"/app?token=\" + this.token;\n\n const headers = {\n Cookie: this.cookie,\n Connection: \"Keep-Alive\",\n };\n\n if (this.tpLinkCipher) {\n const encryptedPayload = this.tpLinkCipher.encrypt(payload);\n\n const securePassthroughPayload = {\n method: \"securePassthrough\",\n params: {\n request: encryptedPayload,\n },\n };\n\n const config = {\n headers: headers,\n timeout: this._timeout * 1000,\n };\n\n return this._axios\n .post(URL, securePassthroughPayload, config)\n .then((res: AxiosResponse) => {\n if (res.data.error_code) {\n if (res.data.error_code === \"9999\" || (res.data.error_code === 9999 && this._reconnect_counter <= 3)) {\n //@ts-ignore\n this.log.error(\" Error Code: \" + res.data.error_code + \", \" + this.ERROR_CODES[res.data.error_code]);\n this.log.debug(\"Trying to reconnect...\");\n return this.reconnect().then(() => {\n return this.getDeviceInfo();\n });\n }\n this._reconnect_counter = 0;\n return this.handleError(res.data.error_code, \"357\");\n }\n\n const decryptedResponse = this.tpLinkCipher.decrypt(res.data.result.response);\n try {\n const response = JSON.parse(decryptedResponse);\n this.log.debug(response);\n if (response.error_code !== 0) {\n return this.handleError(response.error_code, \"364\");\n }\n return response;\n } catch (error) {\n return this.handleError(JSON.parse(decryptedResponse).error_code, \"368\");\n }\n })\n .catch((error: Error) => {\n return this.handleError(error.message, \"656\");\n });\n }\n return new Promise<true>((resolve, reject) => {\n reject();\n });\n }\n\n protected handleKlapRequest(payload: string): Promise<any> {\n if (this.newTpLinkCipher) {\n const data = this.newTpLinkCipher.encrypt(payload);\n\n return this.raw_request(\"request\", data.encryptedPayload, \"arraybuffer\", { seq: data.seq.toString() })\n .then((res) => {\n return JSON.parse(this.newTpLinkCipher.decrypt(res));\n })\n .catch((error: Error) => {\n return this.handleError(error.message, \"671\");\n });\n }\n return new Promise<true>((resolve, reject) => {\n reject();\n });\n }\n\n protected async reconnect(): Promise<void> {\n this._reconnect_counter++;\n return this.handshake().then(() => {\n this.login().then(() => {\n return;\n });\n });\n }\n\n protected async newReconnect(): Promise<void> {\n this._reconnect_counter++;\n return this.handshake_new().then(() => {\n return;\n });\n }\n\n private reAuthenticate(): void {\n this.log.debug(\"Reauthenticating\");\n if (this.is_klap) {\n this.handshake_new()\n .then(() => {\n this.log.info(\"KLAP Authenticated successfully\");\n })\n .catch(() => {\n this.log.error(\"KLAP Handshake New failed\");\n this.is_klap = false;\n });\n } else {\n this.handshake().then(() => {\n this.login()\n .then(() => {\n this.log.info(\"Authenticated successfully\");\n })\n .catch(() => {\n this.log.error(\"Login failed\");\n });\n });\n }\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_axios", "crypto", "axios", "utf8", "uuidv4", "TpLinkCipher", "http", "NewTpLinkCipher", "URL", "headers"]
|
|
7
7
|
}
|
package/build/main.js
CHANGED
|
@@ -465,7 +465,7 @@ class Tapo extends utils.Adapter {
|
|
|
465
465
|
}).catch((e) => {
|
|
466
466
|
this.log.error(e);
|
|
467
467
|
});
|
|
468
|
-
this.log.debug(`initResult ${id} ${JSON.stringify(initResult)}`);
|
|
468
|
+
this.log.debug(`initResult camera ${id} ${JSON.stringify(initResult)}`);
|
|
469
469
|
}
|
|
470
470
|
}
|
|
471
471
|
}).catch((error) => {
|
|
@@ -550,11 +550,15 @@ class Tapo extends utils.Adapter {
|
|
|
550
550
|
await deviceObject.handshake().then(async () => {
|
|
551
551
|
if (deviceObject.is_klap) {
|
|
552
552
|
this.log.debug("Detected KLAP device");
|
|
553
|
-
await deviceObject.handshake_new().catch((error) => {
|
|
553
|
+
await deviceObject.handshake_new().catch(async (error) => {
|
|
554
554
|
this.log.error(error);
|
|
555
|
-
this.log.error(
|
|
555
|
+
this.log.error(error.stack);
|
|
556
|
+
this.log.error("KLAP Handshake failed. Try old handshake");
|
|
556
557
|
deviceObject.is_klap = false;
|
|
557
|
-
|
|
558
|
+
await deviceObject.reAuthenticate().catch(() => {
|
|
559
|
+
this.log.error("Login failed");
|
|
560
|
+
this.deviceObjects[id]._connected = false;
|
|
561
|
+
});
|
|
558
562
|
});
|
|
559
563
|
} else {
|
|
560
564
|
await deviceObject.login().catch(() => {
|
|
@@ -592,7 +596,10 @@ class Tapo extends utils.Adapter {
|
|
|
592
596
|
for (const deviceId in this.deviceObjects) {
|
|
593
597
|
if (this.deviceObjects[deviceId].getStatus) {
|
|
594
598
|
this.log.debug("Receive camera status");
|
|
595
|
-
const status = await this.deviceObjects[deviceId].getStatus()
|
|
599
|
+
const status = await this.deviceObjects[deviceId].getStatus().catch((error) => {
|
|
600
|
+
this.log.info("Get camera Status failed");
|
|
601
|
+
this.log.debug(JSON.stringify(error));
|
|
602
|
+
});
|
|
596
603
|
this.log.debug(JSON.stringify(status));
|
|
597
604
|
this.json2iob.parse(deviceId, status);
|
|
598
605
|
if (this.deviceObjects[deviceId].stok === void 0) {
|
|
@@ -687,14 +694,16 @@ class Tapo extends utils.Adapter {
|
|
|
687
694
|
}
|
|
688
695
|
try {
|
|
689
696
|
if (this.deviceObjects[deviceId] && this.deviceObjects[deviceId][command]) {
|
|
697
|
+
let result;
|
|
690
698
|
if (command === "setColor" || command === "moveMotor") {
|
|
691
699
|
const valueSplit = state.val.replace(" ", "").split(",");
|
|
692
|
-
|
|
693
|
-
this.log.info(JSON.stringify(result));
|
|
700
|
+
result = await this.deviceObjects[deviceId][command](valueSplit[0], valueSplit[1]);
|
|
694
701
|
} else {
|
|
695
|
-
|
|
696
|
-
this.log.info(JSON.stringify(result));
|
|
702
|
+
result = await this.deviceObjects[deviceId][command](state.val);
|
|
697
703
|
}
|
|
704
|
+
this.log.info(
|
|
705
|
+
command + " was set to : " + state.val + " for device " + deviceId + " was successful: " + JSON.stringify(result)
|
|
706
|
+
);
|
|
698
707
|
this.refreshTimeout && clearTimeout(this.refreshTimeout);
|
|
699
708
|
this.refreshTimeout = setTimeout(async () => {
|
|
700
709
|
this.updateDevices();
|
package/build/main.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/main.ts"],
|
|
4
|
-
"sourcesContent": ["/*\n * Created with @iobroker/create-adapter v2.1.1\n */\n\n// The adapter-core module gives you access to the core ioBroker functions\n// you need to create an adapter\nimport * as utils from \"@iobroker/adapter-core\";\nimport axios, { AxiosInstance } from \"axios\";\nimport crypto from \"crypto\";\nimport https from \"https\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport Json2iob from \"json2iob\";\nimport { TAPOCamera } from \"./lib/utils/camera/tapoCamera\";\nimport L510E from \"./lib/utils/l510e\";\nimport L520E from \"./lib/utils/l520e\";\nimport L530 from \"./lib/utils/l530\";\nimport P100 from \"./lib/utils/p100\";\nimport P110 from \"./lib/utils/p110\";\nclass Tapo extends utils.Adapter {\n private devices: { [key: string]: any };\n private deviceObjects: { [key: string]: any };\n private json2iob: Json2iob;\n private secret: Buffer;\n private requestClient: AxiosInstance;\n updateInterval: any = null;\n reLoginTimeout: any = null;\n refreshTokenTimeout: any = null;\n session: any = {};\n refreshTimeout: any;\n refreshTokenInterval: any;\n\n termId: any;\n public constructor(options: Partial<utils.AdapterOptions> = {}) {\n super({\n ...options,\n name: \"tapo\",\n });\n this.on(\"ready\", this.onReady.bind(this));\n this.on(\"stateChange\", this.onStateChange.bind(this));\n this.on(\"unload\", this.onUnload.bind(this));\n this.devices = {};\n this.deviceObjects = {};\n this.json2iob = new Json2iob(this);\n this.requestClient = axios.create({\n httpsAgent: new https.Agent({\n rejectUnauthorized: false,\n secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT,\n }),\n });\n this.secret = Buffer.from([\n 54, 101, 100, 55, 100, 57, 55, 102, 51, 101, 55, 51, 52, 54, 55, 102, 56, 97, 53, 98, 97, 98, 57, 48, 98, 53, 55, 55, 98, 97, 52, 99,\n ]);\n }\n\n /**\n * Is called when databases are connected and adapter received configuration.\n */\n private async onReady(): Promise<void> {\n this.setState(\"info.connection\", false, true);\n if (this.config.interval < 0.5) {\n this.log.info(\"Set interval to minimum 0.5\");\n this.config.interval = 0.5;\n }\n if (!this.config.username || !this.config.password) {\n this.log.error(\"Please set username and password in the instance settings\");\n return;\n }\n\n this.updateInterval = null;\n this.reLoginTimeout = null;\n this.refreshTokenTimeout = null;\n this.session = {};\n this.subscribeStates(\"*\");\n\n const termIdState = await this.getStateAsync(\"termId\");\n if (termIdState && termIdState.val) {\n this.termId = termIdState.val;\n } else {\n await this.setObjectNotExistsAsync(\"termId\", {\n type: \"state\",\n common: {\n name: \"Terminal ID\",\n write: false,\n read: true,\n type: \"string\",\n role: \"text\",\n },\n native: {},\n });\n this.termId = uuidv4();\n await this.setStateAsync(\"termId\", this.termId, true);\n }\n\n this.log.info(\"Login tp TAPO App\");\n await this.login();\n if (this.session.token) {\n await this.getDeviceList();\n } else {\n this.log.warn(\"Login failed using cached device list\");\n const deviceListState = await this.getStateAsync(\"deviceList\");\n if (deviceListState && deviceListState.val) {\n this.log.info(\"Use cached device list\");\n this.devices = JSON.parse(deviceListState.val);\n for (const id in this.devices) {\n if (this.devices[id].ip) {\n const initResult = await this.initDevice(id)\n .then(() => {\n this.log.info(`Initialized ${id}`);\n })\n .catch((e) => {\n this.log.error(e);\n });\n this.log.debug(`initResult ${id} ${JSON.stringify(initResult)}`);\n }\n }\n }\n }\n\n this.log.info(\"Wait for connections for non camera devices\");\n await this.sleep(10000);\n this.log.info(\"Start first Update\");\n this.updateDevices();\n this.updateInterval = setInterval(async () => {\n this.updateDevices();\n }, this.config.interval * 1000);\n }\n async login(): Promise<void> {\n let body = JSON.stringify({\n appVersion: \"2.8.21\",\n refreshTokenNeeded: true,\n platform: \"iOS 14.8\",\n cloudPassword: this.config.password,\n terminalUUID: this.termId,\n cloudUserName: this.config.username,\n terminalName: \"ioBroker\",\n terminalMeta: \"3\",\n appType: \"TP-Link_Tapo_iOS\",\n });\n let path = \"api/v2/account/login\";\n const mfaIdState = await this.getStateAsync(\"mfaId\");\n if (mfaIdState && mfaIdState.val) {\n if (!this.config.mfa) {\n this.log.error(\"Please set mfa in the instance settings\");\n return;\n }\n\n body = JSON.stringify({\n cloudUserName: this.config.username,\n MFAProcessId: mfaIdState.val,\n appType: \"TP-Link_Tapo_iOS\",\n MFAType: 2,\n code: this.config.mfa,\n terminalBindEnabled: true,\n });\n path = \"api/v2/account/checkMFACodeAndLogin\";\n await this.setStateAsync(\"mfaId\", \"\", true);\n }\n const md5 = crypto.createHash(\"md5\").update(body).digest(\"base64\");\n this.log.debug(md5);\n const content = md5 + \"\\n9999999999\\nfee66616-58dd-4bcb-be79-fe092d800a21\\n/\" + path;\n const signature = crypto.createHmac(\"sha1\", this.secret).update(content).digest(\"hex\");\n await this.requestClient({\n method: \"post\",\n url:\n \"https://n-wap-gw.tplinkcloud.com/\" +\n path +\n \"?termID=\" +\n this.termId +\n \"&appVer=2.8.21&locale=de_DE&appName=TP-Link_Tapo_iOS&netType=wifi&model=iPhone10%2C5&termName=iPhone&termMeta=3&brand=TPLINK&ospf=iOS%2014.8\",\n headers: {\n \"Content-Type\": \"application/json;UTF-8\",\n Accept: \"*/*\",\n \"User-Agent\": \"Tapo/2.8.21 (iPhone; iOS 14.8; Scale/3.00)\",\n \"Accept-Language\": \"de-DE;q=1, uk-DE;q=0.9, en-DE;q=0.8\",\n \"X-Authorization\":\n \"Timestamp=9999999999, Nonce=fee66616-58dd-4bcb-be79-fe092d800a21, AccessKey=4d11b6b9d5ea4d19a829adbb9714b057, Signature=\" +\n signature,\n },\n data: body,\n })\n .then(async (res) => {\n this.log.debug(JSON.stringify(res.data));\n if (res.data.error_code) {\n this.log.error(JSON.stringify(res.data));\n return;\n }\n if (res.data.result?.MFAProcessId) {\n this.log.info(\"Found MFA Process please enter MFA in the instance settings\");\n await this.setObjectNotExistsAsync(\"mfaId\", {\n type: \"state\",\n common: {\n name: \"MFA Id\",\n write: false,\n read: true,\n type: \"string\",\n role: \"text\",\n },\n native: {},\n });\n await this.setStateAsync(\"mfaId\", res.data.result?.MFAProcessId, true);\n\n const body = JSON.stringify({\n cloudPassword: this.config.password,\n locale: \"de_DE\",\n terminalUUID: this.termId,\n cloudUserName: this.config.username,\n appType: \"TP-Link_Tapo_iOS\",\n });\n\n const path = \"api/v2/account/getEmailVC4TerminalMFA\";\n\n const md5 = crypto.createHash(\"md5\").update(body).digest(\"base64\");\n this.log.debug(md5);\n const content = md5 + \"\\n9999999999\\nfee66616-58dd-4bcb-be79-fe092d800a21\\n/\" + path;\n const signature = crypto.createHmac(\"sha1\", this.secret).update(content).digest(\"hex\");\n await this.requestClient({\n method: \"post\",\n url:\n \"https://n-wap-gw.tplinkcloud.com/\" +\n path +\n \"?termID=\" +\n this.termId +\n \"&appVer=2.8.21&locale=de_DE&appName=TP-Link_Tapo_iOS&netType=wifi&model=iPhone10%2C5&termName=iPhone&termMeta=3&brand=TPLINK&ospf=iOS%2014.8\",\n headers: {\n \"Content-Type\": \"application/json;UTF-8\",\n Accept: \"*/*\",\n \"User-Agent\": \"Tapo/2.8.21 (iPhone; iOS 14.8; Scale/3.00)\",\n \"Accept-Language\": \"de-DE;q=1, uk-DE;q=0.9, en-DE;q=0.8\",\n \"X-Authorization\":\n \"Timestamp=9999999999, Nonce=fee66616-58dd-4bcb-be79-fe092d800a21, AccessKey=4d11b6b9d5ea4d19a829adbb9714b057, Signature=\" +\n signature,\n },\n data: body,\n })\n .then(async (res) => {\n this.log.debug(JSON.stringify(res.data));\n if (res.data.error_code) {\n this.log.error(JSON.stringify(res.data));\n return;\n }\n })\n .catch((error) => {\n this.log.error(error);\n error.response && this.log.error(JSON.stringify(error.response.data));\n });\n return;\n }\n\n if (!res.data.result || !res.data.result.token) {\n this.log.error(\"Login failed\");\n this.log.error(JSON.stringify(res.data));\n return;\n }\n this.session = res.data.result;\n if (this.session.token) {\n this.log.info(\"Login succesfull\");\n this.setState(\"info.connection\", true, true);\n }\n return;\n })\n .catch((error) => {\n this.log.error(error);\n error.response && this.log.error(JSON.stringify(error.response.data));\n });\n }\n\n async getDeviceList(): Promise<void> {\n const body =\n '{\"index\":0,\"deviceTypeList\":[\"SMART.TAPOBULB\",\"SMART.TAPOPLUG\",\"SMART.IPCAMERA\",\"SMART.TAPOHUB\",\"SMART.TAPOSENSOR\",\"SMART.TAPOSWITCH\"],\"limit\":30}';\n const md5 = crypto.createHash(\"md5\").update(body).digest(\"base64\");\n this.log.debug(md5);\n const content = md5 + \"\\n9999999999\\nfee66616-58dd-4bcb-be79-fe092d800a21\\n/api/v2/common/getDeviceListByPage\";\n const signature = crypto.createHmac(\"sha1\", this.secret).update(content).digest(\"hex\");\n await this.requestClient({\n method: \"post\",\n url: `https://n-euw1-wap-gw.tplinkcloud.com/api/v2/common/getDeviceListByPage?token=${this.session.token}&termID=${this.termId}&appVer=2.8.21&locale=de_DE&appName=TP-Link_Tapo_iOS&netType=wifi&model=iPhone10%2C5&termName=iPhone&termMeta=3&brand=TPLINK&ospf=iOS%2014.8`,\n headers: {\n \"Content-Type\": \"application/json;UTF-8\",\n \"Content-MD5\": md5,\n Accept: \"*/*\",\n \"User-Agent\": \"Tapo/2.8.21 (iPhone; iOS 14.8; Scale/3.00)\",\n \"Accept-Language\": \"de-DE;q=1, uk-DE;q=0.9, en-DE;q=0.8\",\n \"X-Authorization\":\n \"Timestamp=9999999999, Nonce=fee66616-58dd-4bcb-be79-fe092d800a21, AccessKey=4d11b6b9d5ea4d19a829adbb9714b057, Signature=\" +\n signature,\n },\n data: body,\n })\n .then(async (res) => {\n this.log.debug(JSON.stringify(res.data));\n if (res.data.error_code) {\n this.log.error(JSON.stringify(res.data));\n return;\n }\n this.log.info(`Found ${res.data.result?.totalNum} devices`);\n\n for (const device of res.data.result?.deviceList) {\n const id = device.deviceId;\n this.devices[id] = device;\n let name = device.alias;\n\n if (this.isBase64(device.alias)) {\n name = Buffer.from(device.alias, \"base64\").toString(\"utf8\");\n }\n this.log.debug(`Found device ${id} ${name}`);\n await this.extendObject(id, {\n type: \"device\",\n common: {\n name: name,\n },\n native: {},\n });\n await this.setObjectNotExistsAsync(id + \".remote\", {\n type: \"channel\",\n common: {\n name: \"Remote Controls\",\n },\n native: {},\n });\n\n const remoteArray = [\n { command: \"refresh\", name: \"True = Refresh\" },\n { command: \"setPowerState\", name: \"True = On, False = Off\" },\n { command: \"setAlertConfig\", name: \"True = On, False = Off\" },\n { command: \"setLensMaskConfig\", name: \"True = On, False = Off\" },\n { command: \"setForceWhitelampState\", name: \"True = On, False = Off\" },\n { command: \"moveMotor\", name: \"move Camera to X (-360,360), Y(-45,45)\", type: \"string\", def: \"0, 0\", role: \"text\" },\n { command: \"moveMotorStep\", name: \"Angle (0-360)\", type: \"string\", def: \"180\", role: \"text\" },\n\n {\n command: \"setBrightness\",\n name: \"Set Brightness for Light devices\",\n type: \"number\",\n role: \"level.brightness\",\n def: 5,\n },\n {\n command: \"setColorTemp\",\n name: \"Set Color Temp for Light devices\",\n type: \"number\",\n role: \"level.color.temperature\",\n def: 3000,\n },\n {\n command: \"setColor\",\n name: \"Set Color for Light devices (hue, saturation)\",\n def: \"30, 100\",\n type: \"string\",\n },\n ];\n remoteArray.forEach((remote) => {\n this.extendObject(id + \".remote.\" + remote.command, {\n type: \"state\",\n common: {\n name: remote.name || \"\",\n type: remote.type || \"boolean\",\n role: remote.role || \"switch\",\n def: remote.def != null ? remote.def : false,\n write: true,\n read: true,\n },\n native: {},\n });\n });\n this.json2iob.parse(id, device, { channelName: name });\n\n //try new API\n\n await this.requestClient({\n method: \"get\",\n url: \"https://euw1-app-server.iot.i.tplinknbu.com/v1/things/\" + id + \"/details\",\n headers: {\n \"x-locale\": \"de\",\n Authorization: \"ut|\" + this.session.token,\n \"app-cid\": \"app:TP-Link_Tapo_iOS:\" + this.termId,\n \"x-ospf\": \"iOS 14.8\",\n \"x-app-name\": \"TP-Link_Tapo_iOS\",\n Accept: \"*/*\",\n \"Accept-Language\": \"de-DE;q=1, uk-DE;q=0.9, en-DE;q=0.8\",\n \"Content-Type\": \"application/json;UTF-8\",\n \"User-Agent\": \"Tapo/2.9.7 (iPhone; iOS 14.8; Scale/3.00)\",\n \"x-term-id\": this.termId,\n \"x-app-version\": \"2.9.7\",\n \"x-net-type\": \"wifi\",\n },\n })\n .then(async (res) => {\n this.log.debug(JSON.stringify(res.data));\n if (res.data.error_code) {\n this.log.error(JSON.stringify(res.data));\n return;\n } else {\n this.devices[id] = { ...this.devices[id], ...res.data };\n }\n })\n .catch((error) => {\n this.log.warn(error);\n error.response && this.log.error(JSON.stringify(error.response.data));\n });\n //no ip via new API try old api\n if (!this.devices[id].ip) {\n const body = `{\n \"requestData\": {\n \"method\": \"multipleRequest\",\n \"params\": {\n \"requests\": [{\n \"method\": \"getDeviceIpAddress\",\n \"params\": {\n \"network\": {\n \"name\": \"wan\"\n }\n }\n }]\n }\n },\n \"deviceId\": \"${id}\"\n }`;\n const md5 = crypto.createHash(\"md5\").update(body).digest(\"base64\");\n this.log.debug(md5);\n const content = md5 + \"\\n9999999999\\nfee66616-58dd-4bcb-be79-fe092d800a21\\n/api/v2/common/passthrough\";\n const signature = crypto.createHmac(\"sha1\", this.secret).update(content).digest(\"hex\");\n await this.requestClient({\n method: \"post\",\n url: `https://n-euw1-wap-gw.tplinkcloud.com/api/v2/common/passthrough?token=${this.session.token}&termID=${this.termId}&appVer=2.8.21&locale=de_DE&appName=TP-Link_Tapo_iOS&netType=wifi&model=iPhone10%2C5&termName=iPhone&termMeta=3&brand=TPLINK&ospf=iOS%2014.8`,\n headers: {\n \"Content-Type\": \"application/json;UTF-8\",\n \"Content-MD5\": md5,\n Accept: \"*/*\",\n \"User-Agent\": \"Tapo/2.8.21 (iPhone; iOS 14.8; Scale/3.00)\",\n \"Accept-Language\": \"de-DE;q=1, uk-DE;q=0.9, en-DE;q=0.8\",\n \"X-Authorization\":\n \"Timestamp=9999999999, Nonce=fee66616-58dd-4bcb-be79-fe092d800a21, AccessKey=4d11b6b9d5ea4d19a829adbb9714b057, Signature=\" +\n signature,\n },\n data: body,\n })\n .then(async (res) => {\n this.log.debug(JSON.stringify(res.data));\n let result: any = {};\n if (res.data.error_code) {\n this.log.error(JSON.stringify(res.data));\n } else {\n result = res.data.result?.responseData?.result?.responses[0]?.result?.network?.wan;\n result.ip = result.ipaddr;\n this.log.info(`Device ${id} has IP ${result.ip}`);\n delete result[\".name\"];\n delete result[\".type\"];\n // result = res.data.result?.responseData?.result;\n this.devices[id] = { ...this.devices[id], ...result };\n }\n })\n .catch((error) => {\n this.log.warn(error);\n error.response && this.log.error(JSON.stringify(error.response.data));\n });\n }\n if (!this.devices[id].ip) {\n const ipState = await this.getStateAsync(id + \".ip\");\n if (ipState && ipState.val) {\n this.devices[id].ip = ipState.val;\n } else {\n await this.setObjectNotExistsAsync(id + \".ip\", {\n type: \"state\",\n common: {\n name: \"IP\",\n write: true,\n read: true,\n type: \"string\",\n role: \"text\",\n },\n native: {},\n });\n this.log.warn(`No IP found for ${id} put the device online or set the ip state manually`);\n }\n }\n this.json2iob.parse(id, this.devices[id]);\n if (this.devices[id].ip) {\n const initResult = await this.initDevice(id)\n .then(() => {\n this.log.info(`Initialized ${id}`);\n })\n .catch((e) => {\n this.log.error(e);\n });\n this.log.debug(`initResult ${id} ${JSON.stringify(initResult)}`);\n }\n }\n })\n .catch((error) => {\n this.log.warn(error);\n error.response && this.log.error(JSON.stringify(error.response.data));\n });\n\n await this.setObjectNotExistsAsync(\"deviceList\", {\n type: \"state\",\n common: {\n name: \"Cached device list\",\n write: false,\n read: true,\n type: \"string\",\n role: \"json\",\n },\n native: {},\n });\n\n await this.setStateAsync(\"deviceList\", JSON.stringify(this.devices), true);\n }\n async initDevice(id: string): Promise<void> {\n const device = this.devices[id];\n if (!device.ip) {\n this.log.warn(`No IP found for ${id}`);\n return;\n }\n this.log.info(`Init device ${id} type ${device.deviceName} with ip ${device.ip}`);\n let deviceObject: any;\n if (device.deviceName === \"P100\") {\n deviceObject = new P100(this.log, device.ip, this.config.username, this.config.password, 2);\n } else if (device.deviceName.startsWith(\"P110\") || device.deviceName.startsWith(\"P115\")) {\n deviceObject = new P110(this.log, device.ip, this.config.username, this.config.password, 2);\n } else if (device.deviceName === \"L530\" || device.deviceName.startsWith(\"L630\")) {\n deviceObject = new L530(this.log, device.ip, this.config.username, this.config.password, 2);\n } else if (device.deviceName === \"L510E\") {\n deviceObject = new L510E(this.log, device.ip, this.config.username, this.config.password, 2);\n } else if (device.deviceName === \"L520E\") {\n deviceObject = new L520E(this.log, device.ip, this.config.username, this.config.password, 2);\n } else if (device.deviceName.startsWith(\"L\") || device.deviceName.startsWith(\"KL\")) {\n deviceObject = new L510E(this.log, device.ip, this.config.username, this.config.password, 2);\n } else if (device.deviceName.startsWith(\"C\") || device.deviceName.startsWith(\"TC\")) {\n if (!this.config.streamusername || !this.config.streampassword) {\n this.log.warn(`No stream username or password. No motion detection available`);\n }\n deviceObject = new TAPOCamera(this.log, {\n name: device.deviceName,\n ipAddress: device.ip,\n password: this.config.password,\n streamUser: this.config.streamusername,\n streamPassword: this.config.streampassword,\n disableStreaming: true,\n });\n\n //new Camera(this.log, device.ip, this.config.username, this.config.password, 2);\n\n this.deviceObjects[id] = deviceObject;\n const deviceInfo = await deviceObject.getDeviceInfo(true);\n this.log.info(`${id} Received device info ${JSON.stringify(deviceInfo)}`);\n this.log.debug(JSON.stringify(deviceInfo));\n this.json2iob.parse(id, deviceInfo);\n this.log.debug(`Init event emitter for ${id}`);\n const eventEmitter = await deviceObject.getEventEmitter();\n await this.setObjectNotExistsAsync(id + \".motionEvent\", {\n type: \"state\",\n common: {\n name: \"Motion detected\",\n type: \"boolean\",\n role: \"boolean\",\n def: false,\n write: false,\n read: true,\n },\n native: {},\n });\n this.log.debug('Init event listener for \"motion\"');\n eventEmitter.addListener(\"motion\", async (motionDetected: any) => {\n await this.setStateAsync(id + \".motionEvent\", motionDetected, true);\n this.log.debug(`[${device.deviceName}] \"Motion detected\" ${motionDetected}`);\n });\n return;\n } else {\n this.log.info(`Unknown device type ${device.deviceName} init as P100`);\n deviceObject = new P100(this.log, device.ip, this.config.username, this.config.password, 2);\n }\n this.deviceObjects[id] = deviceObject;\n await deviceObject\n .handshake()\n .then(async () => {\n if (deviceObject.is_klap) {\n this.log.debug(\"Detected KLAP device\");\n await deviceObject.handshake_new().catch((error: any) => {\n this.log.error(error);\n this.log.error(\"KLAP Handshake failed\");\n deviceObject.is_klap = false;\n this.deviceObjects[id]._connected = false;\n });\n } else {\n await deviceObject.login().catch(() => {\n this.log.error(\"Login failed\");\n this.deviceObjects[id]._connected = false;\n });\n }\n deviceObject\n .getDeviceInfo(true)\n .then(async (sysInfo: any) => {\n this.log.debug(JSON.stringify(sysInfo));\n if (sysInfo.request) {\n this.log.error(\"Malformed response sysinfo\");\n this.log.error(JSON.stringify(sysInfo));\n return;\n }\n this.json2iob.parse(id, sysInfo);\n\n this.deviceObjects[id]._connected = true;\n if (this.deviceObjects[id].getEnergyUsage) {\n this.log.debug(\"Receive energy usage\");\n const energyUsage = await this.deviceObjects[id].getEnergyUsage();\n this.log.debug(JSON.stringify(energyUsage));\n this.json2iob.parse(id, energyUsage);\n }\n })\n .catch((error: any) => {\n this.log.error(JSON.stringify(error));\n this.log.error(\"52 - Get Device Info failed\");\n\n this.deviceObjects[id]._connected = false;\n });\n })\n .catch(() => {\n this.log.error(\"Handshake failed\");\n this.deviceObjects[id]._connected = false;\n });\n }\n\n async updateDevices(): Promise<void> {\n try {\n for (const deviceId in this.deviceObjects) {\n if (this.deviceObjects[deviceId].getStatus) {\n this.log.debug(\"Receive camera status\");\n const status = await this.deviceObjects[deviceId].getStatus();\n this.log.debug(JSON.stringify(status));\n this.json2iob.parse(deviceId, status);\n if (this.deviceObjects[deviceId].stok === undefined) {\n this.log.error(\"No stok found for: \" + deviceId + \" Ingore device until next restart\");\n\n delete this.deviceObjects[deviceId];\n }\n continue;\n }\n if (!this.deviceObjects[deviceId]._connected) {\n continue;\n }\n\n this.deviceObjects[deviceId]\n .getDeviceInfo(true)\n .then(async (sysInfo: any) => {\n this.log.debug(JSON.stringify(sysInfo));\n if (!sysInfo || sysInfo.name === \"Error\" || sysInfo.request) {\n this.log.debug(\"Malformed response sysinfo\");\n // this.log.error(JSON.stringify(sysInfo));\n return;\n }\n await this.json2iob.parse(deviceId, sysInfo);\n if (this.deviceObjects[deviceId].getEnergyUsage) {\n this.log.debug(\"Receive energy usage\");\n const energyUsage = await this.deviceObjects[deviceId].getEnergyUsage();\n this.log.debug(JSON.stringify(energyUsage));\n if (energyUsage.request) {\n this.log.error(\"Malformed response getEnergyUsage\");\n this.log.error(JSON.stringify(energyUsage));\n return;\n }\n await this.json2iob.parse(deviceId, energyUsage);\n const power_usage = this.deviceObjects[deviceId].getPowerConsumption();\n if (power_usage.request) {\n this.log.error(\"Malformed response getPowerConsumption\");\n this.log.error(JSON.stringify(power_usage));\n return;\n }\n await this.json2iob.parse(deviceId, power_usage);\n }\n })\n .catch((error: any) => {\n this.log.error(`Get Device Info failed for ${deviceId} - ${error}`);\n });\n }\n this.log.debug(\"Update done\");\n } catch (error: any) {\n this.log.warn(error);\n }\n }\n\n isBase64(str: string): boolean {\n if (str === \"\" || str.trim() === \"\") {\n return false;\n }\n try {\n const strWithoutPadding = str.replace(/=*$/, \"\");\n return btoa(atob(strWithoutPadding)) === strWithoutPadding || btoa(atob(str)) === str;\n } catch (err) {\n return false;\n }\n }\n async sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n async refreshToken(): Promise<void> {\n this.log.debug(\"Refresh token\");\n }\n /**\n * Is called when adapter shuts down - callback has to be called under any circumstances!\n */\n private onUnload(callback: () => void): void {\n try {\n this.setState(\"info.connection\", false, true);\n this.refreshTimeout && clearTimeout(this.refreshTimeout);\n this.reLoginTimeout && clearTimeout(this.reLoginTimeout);\n this.refreshTokenTimeout && clearTimeout(this.refreshTokenTimeout);\n this.updateInterval && clearInterval(this.updateInterval);\n this.refreshTokenInterval && clearInterval(this.refreshTokenInterval);\n\n callback();\n } catch (e) {\n callback();\n }\n }\n\n /**\n * Is called if a subscribed state changes\n */\n private async onStateChange(id: string, state: ioBroker.State | null | undefined): Promise<void> {\n if (state) {\n if (!state.ack) {\n const deviceId = id.split(\".\")[2];\n const command = id.split(\".\")[4];\n if (id.split(\".\")[3] !== \"remote\") {\n return;\n }\n\n if (command === \"Refresh\") {\n this.deviceObjects[deviceId]\n .getDeviceInfo(true)\n .then((sysInfo: any) => {\n this.log.debug(JSON.stringify(sysInfo));\n this.json2iob.parse(deviceId, sysInfo);\n })\n .catch((error) => {\n this.log.error(`Get Device Info failed for ${deviceId} - ${error}`);\n });\n\n return;\n }\n try {\n if (this.deviceObjects[deviceId] && this.deviceObjects[deviceId][command]) {\n if (command === \"setColor\" || command === \"moveMotor\") {\n const valueSplit = state.val.replace(\" \", \"\").split(\",\");\n const result = await this.deviceObjects[deviceId][command](valueSplit[0], valueSplit[1]);\n this.log.info(JSON.stringify(result));\n } else {\n const result = await this.deviceObjects[deviceId][command](state.val);\n this.log.info(JSON.stringify(result));\n }\n this.refreshTimeout && clearTimeout(this.refreshTimeout);\n this.refreshTimeout = setTimeout(async () => {\n this.updateDevices();\n }, 2 * 1000);\n } else {\n this.log.error(`Device ${deviceId} has no command ${command}`);\n }\n } catch (error) {\n this.log.error(error);\n }\n } else {\n const resultDict = { device_on: \"setPowerState\" };\n const idArray = id.split(\".\");\n const stateName = idArray[idArray.length - 1];\n const deviceId = id.split(\".\")[2];\n if (resultDict[stateName]) {\n await this.setState(deviceId + \".remote.\" + resultDict[stateName], state.val, true);\n }\n }\n }\n }\n}\n\nif (require.main !== module) {\n // Export the constructor in compact mode\n module.exports = (options: Partial<utils.AdapterOptions> | undefined) => new Tapo(options);\n} else {\n // otherwise start the instance directly\n (() => new Tapo())();\n}\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;AAMA,YAAuB;AACvB,mBAAqC;AACrC,oBAAmB;AACnB,mBAAkB;AAClB,kBAA6B;AAC7B,sBAAqB;AACrB,wBAA2B;AAC3B,mBAAkB;AAClB,mBAAkB;AAClB,kBAAiB;AACjB,kBAAiB;AACjB,kBAAiB;AACjB,MAAM,aAAa,MAAM,QAAQ;AAAA,EAcxB,YAAY,UAAyC,CAAC,GAAG;AAC9D,UAAM;AAAA,MACJ,GAAG;AAAA,MACH,MAAM;AAAA,IACR,CAAC;AAZH,0BAAsB;AACtB,0BAAsB;AACtB,+BAA2B;AAC3B,mBAAe,CAAC;AAUd,SAAK,GAAG,SAAS,KAAK,QAAQ,KAAK,IAAI,CAAC;AACxC,SAAK,GAAG,eAAe,KAAK,cAAc,KAAK,IAAI,CAAC;AACpD,SAAK,GAAG,UAAU,KAAK,SAAS,KAAK,IAAI,CAAC;AAC1C,SAAK,UAAU,CAAC;AAChB,SAAK,gBAAgB,CAAC;AACtB,SAAK,WAAW,IAAI,gBAAAA,QAAS,IAAI;AACjC,SAAK,gBAAgB,aAAAC,QAAM,OAAO;AAAA,MAChC,YAAY,IAAI,aAAAC,QAAM,MAAM;AAAA,QAC1B,oBAAoB;AAAA,QACpB,eAAe,cAAAC,QAAO,UAAU;AAAA,MAClC,CAAC;AAAA,IACH,CAAC;AACD,SAAK,SAAS,OAAO,KAAK;AAAA,MACxB;AAAA,MAAI;AAAA,MAAK;AAAA,MAAK;AAAA,MAAI;AAAA,MAAK;AAAA,MAAI;AAAA,MAAI;AAAA,MAAK;AAAA,MAAI;AAAA,MAAK;AAAA,MAAI;AAAA,MAAI;AAAA,MAAI;AAAA,MAAI;AAAA,MAAI;AAAA,MAAK;AAAA,MAAI;AAAA,MAAI;AAAA,MAAI;AAAA,MAAI;AAAA,MAAI;AAAA,MAAI;AAAA,MAAI;AAAA,MAAI;AAAA,MAAI;AAAA,MAAI;AAAA,MAAI;AAAA,MAAI;AAAA,MAAI;AAAA,MAAI;AAAA,MAAI;AAAA,IACpI,CAAC;AAAA,EACH;AAAA,EAKA,MAAc,UAAyB;AACrC,SAAK,SAAS,mBAAmB,OAAO,IAAI;AAC5C,QAAI,KAAK,OAAO,WAAW,KAAK;AAC9B,WAAK,IAAI,KAAK,6BAA6B;AAC3C,WAAK,OAAO,WAAW;AAAA,IACzB;AACA,QAAI,CAAC,KAAK,OAAO,YAAY,CAAC,KAAK,OAAO,UAAU;AAClD,WAAK,IAAI,MAAM,2DAA2D;AAC1E;AAAA,IACF;AAEA,SAAK,iBAAiB;AACtB,SAAK,iBAAiB;AACtB,SAAK,sBAAsB;AAC3B,SAAK,UAAU,CAAC;AAChB,SAAK,gBAAgB,GAAG;AAExB,UAAM,cAAc,MAAM,KAAK,cAAc,QAAQ;AACrD,QAAI,eAAe,YAAY,KAAK;AAClC,WAAK,SAAS,YAAY;AAAA,IAC5B,OAAO;AACL,YAAM,KAAK,wBAAwB,UAAU;AAAA,QAC3C,MAAM;AAAA,QACN,QAAQ;AAAA,UACN,MAAM;AAAA,UACN,OAAO;AAAA,UACP,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,QACR;AAAA,QACA,QAAQ,CAAC;AAAA,MACX,CAAC;AACD,WAAK,aAAS,YAAAC,IAAO;AACrB,YAAM,KAAK,cAAc,UAAU,KAAK,QAAQ,IAAI;AAAA,IACtD;AAEA,SAAK,IAAI,KAAK,mBAAmB;AACjC,UAAM,KAAK,MAAM;AACjB,QAAI,KAAK,QAAQ,OAAO;AACtB,YAAM,KAAK,cAAc;AAAA,IAC3B,OAAO;AACL,WAAK,IAAI,KAAK,uCAAuC;AACrD,YAAM,kBAAkB,MAAM,KAAK,cAAc,YAAY;AAC7D,UAAI,mBAAmB,gBAAgB,KAAK;AAC1C,aAAK,IAAI,KAAK,wBAAwB;AACtC,aAAK,UAAU,KAAK,MAAM,gBAAgB,GAAG;AAC7C,mBAAW,MAAM,KAAK,SAAS;AAC7B,cAAI,KAAK,QAAQ,IAAI,IAAI;AACvB,kBAAM,aAAa,MAAM,KAAK,WAAW,EAAE,EACxC,KAAK,MAAM;AACV,mBAAK,IAAI,KAAK,eAAe,IAAI;AAAA,YACnC,CAAC,EACA,MAAM,CAAC,MAAM;AACZ,mBAAK,IAAI,MAAM,CAAC;AAAA,YAClB,CAAC;AACH,iBAAK,IAAI,MAAM,cAAc,MAAM,KAAK,UAAU,UAAU,GAAG;AAAA,UACjE;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,SAAK,IAAI,KAAK,6CAA6C;AAC3D,UAAM,KAAK,MAAM,GAAK;AACtB,SAAK,IAAI,KAAK,oBAAoB;AAClC,SAAK,cAAc;AACnB,SAAK,iBAAiB,YAAY,YAAY;AAC5C,WAAK,cAAc;AAAA,IACrB,GAAG,KAAK,OAAO,WAAW,GAAI;AAAA,EAChC;AAAA,EACA,MAAM,QAAuB;AAC3B,QAAI,OAAO,KAAK,UAAU;AAAA,MACxB,YAAY;AAAA,MACZ,oBAAoB;AAAA,MACpB,UAAU;AAAA,MACV,eAAe,KAAK,OAAO;AAAA,MAC3B,cAAc,KAAK;AAAA,MACnB,eAAe,KAAK,OAAO;AAAA,MAC3B,cAAc;AAAA,MACd,cAAc;AAAA,MACd,SAAS;AAAA,IACX,CAAC;AACD,QAAI,OAAO;AACX,UAAM,aAAa,MAAM,KAAK,cAAc,OAAO;AACnD,QAAI,cAAc,WAAW,KAAK;AAChC,UAAI,CAAC,KAAK,OAAO,KAAK;AACpB,aAAK,IAAI,MAAM,yCAAyC;AACxD;AAAA,MACF;AAEA,aAAO,KAAK,UAAU;AAAA,QACpB,eAAe,KAAK,OAAO;AAAA,QAC3B,cAAc,WAAW;AAAA,QACzB,SAAS;AAAA,QACT,SAAS;AAAA,QACT,MAAM,KAAK,OAAO;AAAA,QAClB,qBAAqB;AAAA,MACvB,CAAC;AACD,aAAO;AACP,YAAM,KAAK,cAAc,SAAS,IAAI,IAAI;AAAA,IAC5C;AACA,UAAM,MAAM,cAAAD,QAAO,WAAW,KAAK,EAAE,OAAO,IAAI,EAAE,OAAO,QAAQ;AACjE,SAAK,IAAI,MAAM,GAAG;AAClB,UAAM,UAAU,MAAM,0DAA0D;AAChF,UAAM,YAAY,cAAAA,QAAO,WAAW,QAAQ,KAAK,MAAM,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK;AACrF,UAAM,KAAK,cAAc;AAAA,MACvB,QAAQ;AAAA,MACR,KACE,sCACA,OACA,aACA,KAAK,SACL;AAAA,MACF,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,mBAAmB;AAAA,QACnB,mBACE,6HACA;AAAA,MACJ;AAAA,MACA,MAAM;AAAA,IACR,CAAC,EACE,KAAK,OAAO,QAAQ;AApL3B;AAqLQ,WAAK,IAAI,MAAM,KAAK,UAAU,IAAI,IAAI,CAAC;AACvC,UAAI,IAAI,KAAK,YAAY;AACvB,aAAK,IAAI,MAAM,KAAK,UAAU,IAAI,IAAI,CAAC;AACvC;AAAA,MACF;AACA,WAAI,SAAI,KAAK,WAAT,mBAAiB,cAAc;AACjC,aAAK,IAAI,KAAK,6DAA6D;AAC3E,cAAM,KAAK,wBAAwB,SAAS;AAAA,UAC1C,MAAM;AAAA,UACN,QAAQ;AAAA,YACN,MAAM;AAAA,YACN,OAAO;AAAA,YACP,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,UACR;AAAA,UACA,QAAQ,CAAC;AAAA,QACX,CAAC;AACD,cAAM,KAAK,cAAc,UAAS,SAAI,KAAK,WAAT,mBAAiB,cAAc,IAAI;AAErE,cAAME,QAAO,KAAK,UAAU;AAAA,UAC1B,eAAe,KAAK,OAAO;AAAA,UAC3B,QAAQ;AAAA,UACR,cAAc,KAAK;AAAA,UACnB,eAAe,KAAK,OAAO;AAAA,UAC3B,SAAS;AAAA,QACX,CAAC;AAED,cAAMC,QAAO;AAEb,cAAMC,OAAM,cAAAJ,QAAO,WAAW,KAAK,EAAE,OAAOE,KAAI,EAAE,OAAO,QAAQ;AACjE,aAAK,IAAI,MAAME,IAAG;AAClB,cAAMC,WAAUD,OAAM,0DAA0DD;AAChF,cAAMG,aAAY,cAAAN,QAAO,WAAW,QAAQ,KAAK,MAAM,EAAE,OAAOK,QAAO,EAAE,OAAO,KAAK;AACrF,cAAM,KAAK,cAAc;AAAA,UACvB,QAAQ;AAAA,UACR,KACE,sCACAF,QACA,aACA,KAAK,SACL;AAAA,UACF,SAAS;AAAA,YACP,gBAAgB;AAAA,YAChB,QAAQ;AAAA,YACR,cAAc;AAAA,YACd,mBAAmB;AAAA,YACnB,mBACE,6HACAG;AAAA,UACJ;AAAA,UACA,MAAMJ;AAAA,QACR,CAAC,EACE,KAAK,OAAOK,SAAQ;AACnB,eAAK,IAAI,MAAM,KAAK,UAAUA,KAAI,IAAI,CAAC;AACvC,cAAIA,KAAI,KAAK,YAAY;AACvB,iBAAK,IAAI,MAAM,KAAK,UAAUA,KAAI,IAAI,CAAC;AACvC;AAAA,UACF;AAAA,QACF,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,eAAK,IAAI,MAAM,KAAK;AACpB,gBAAM,YAAY,KAAK,IAAI,MAAM,KAAK,UAAU,MAAM,SAAS,IAAI,CAAC;AAAA,QACtE,CAAC;AACH;AAAA,MACF;AAEA,UAAI,CAAC,IAAI,KAAK,UAAU,CAAC,IAAI,KAAK,OAAO,OAAO;AAC9C,aAAK,IAAI,MAAM,cAAc;AAC7B,aAAK,IAAI,MAAM,KAAK,UAAU,IAAI,IAAI,CAAC;AACvC;AAAA,MACF;AACA,WAAK,UAAU,IAAI,KAAK;AACxB,UAAI,KAAK,QAAQ,OAAO;AACtB,aAAK,IAAI,KAAK,kBAAkB;AAChC,aAAK,SAAS,mBAAmB,MAAM,IAAI;AAAA,MAC7C;AACA;AAAA,IACF,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,WAAK,IAAI,MAAM,KAAK;AACpB,YAAM,YAAY,KAAK,IAAI,MAAM,KAAK,UAAU,MAAM,SAAS,IAAI,CAAC;AAAA,IACtE,CAAC;AAAA,EACL;AAAA,EAEA,MAAM,gBAA+B;AACnC,UAAM,OACJ;AACF,UAAM,MAAM,cAAAP,QAAO,WAAW,KAAK,EAAE,OAAO,IAAI,EAAE,OAAO,QAAQ;AACjE,SAAK,IAAI,MAAM,GAAG;AAClB,UAAM,UAAU,MAAM;AACtB,UAAM,YAAY,cAAAA,QAAO,WAAW,QAAQ,KAAK,MAAM,EAAE,OAAO,OAAO,EAAE,OAAO,KAAK;AACrF,UAAM,KAAK,cAAc;AAAA,MACvB,QAAQ;AAAA,MACR,KAAK,iFAAiF,KAAK,QAAQ,gBAAgB,KAAK;AAAA,MACxH,SAAS;AAAA,QACP,gBAAgB;AAAA,QAChB,eAAe;AAAA,QACf,QAAQ;AAAA,QACR,cAAc;AAAA,QACd,mBAAmB;AAAA,QACnB,mBACE,6HACA;AAAA,MACJ;AAAA,MACA,MAAM;AAAA,IACR,CAAC,EACE,KAAK,OAAO,QAAQ;AAhS3B;AAiSQ,WAAK,IAAI,MAAM,KAAK,UAAU,IAAI,IAAI,CAAC;AACvC,UAAI,IAAI,KAAK,YAAY;AACvB,aAAK,IAAI,MAAM,KAAK,UAAU,IAAI,IAAI,CAAC;AACvC;AAAA,MACF;AACA,WAAK,IAAI,KAAK,UAAS,SAAI,KAAK,WAAT,mBAAiB,kBAAkB;AAE1D,iBAAW,WAAU,SAAI,KAAK,WAAT,mBAAiB,YAAY;AAChD,cAAM,KAAK,OAAO;AAClB,aAAK,QAAQ,MAAM;AACnB,YAAI,OAAO,OAAO;AAElB,YAAI,KAAK,SAAS,OAAO,KAAK,GAAG;AAC/B,iBAAO,OAAO,KAAK,OAAO,OAAO,QAAQ,EAAE,SAAS,MAAM;AAAA,QAC5D;AACA,aAAK,IAAI,MAAM,gBAAgB,MAAM,MAAM;AAC3C,cAAM,KAAK,aAAa,IAAI;AAAA,UAC1B,MAAM;AAAA,UACN,QAAQ;AAAA,YACN;AAAA,UACF;AAAA,UACA,QAAQ,CAAC;AAAA,QACX,CAAC;AACD,cAAM,KAAK,wBAAwB,KAAK,WAAW;AAAA,UACjD,MAAM;AAAA,UACN,QAAQ;AAAA,YACN,MAAM;AAAA,UACR;AAAA,UACA,QAAQ,CAAC;AAAA,QACX,CAAC;AAED,cAAM,cAAc;AAAA,UAClB,EAAE,SAAS,WAAW,MAAM,iBAAiB;AAAA,UAC7C,EAAE,SAAS,iBAAiB,MAAM,yBAAyB;AAAA,UAC3D,EAAE,SAAS,kBAAkB,MAAM,yBAAyB;AAAA,UAC5D,EAAE,SAAS,qBAAqB,MAAM,yBAAyB;AAAA,UAC/D,EAAE,SAAS,0BAA0B,MAAM,yBAAyB;AAAA,UACpE,EAAE,SAAS,aAAa,MAAM,0CAA0C,MAAM,UAAU,KAAK,QAAQ,MAAM,OAAO;AAAA,UAClH,EAAE,SAAS,iBAAiB,MAAM,iBAAiB,MAAM,UAAU,KAAK,OAAO,MAAM,OAAO;AAAA,UAE5F;AAAA,YACE,SAAS;AAAA,YACT,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,KAAK;AAAA,UACP;AAAA,UACA;AAAA,YACE,SAAS;AAAA,YACT,MAAM;AAAA,YACN,MAAM;AAAA,YACN,MAAM;AAAA,YACN,KAAK;AAAA,UACP;AAAA,UACA;AAAA,YACE,SAAS;AAAA,YACT,MAAM;AAAA,YACN,KAAK;AAAA,YACL,MAAM;AAAA,UACR;AAAA,QACF;AACA,oBAAY,QAAQ,CAAC,WAAW;AAC9B,eAAK,aAAa,KAAK,aAAa,OAAO,SAAS;AAAA,YAClD,MAAM;AAAA,YACN,QAAQ;AAAA,cACN,MAAM,OAAO,QAAQ;AAAA,cACrB,MAAM,OAAO,QAAQ;AAAA,cACrB,MAAM,OAAO,QAAQ;AAAA,cACrB,KAAK,OAAO,OAAO,OAAO,OAAO,MAAM;AAAA,cACvC,OAAO;AAAA,cACP,MAAM;AAAA,YACR;AAAA,YACA,QAAQ,CAAC;AAAA,UACX,CAAC;AAAA,QACH,CAAC;AACD,aAAK,SAAS,MAAM,IAAI,QAAQ,EAAE,aAAa,KAAK,CAAC;AAIrD,cAAM,KAAK,cAAc;AAAA,UACvB,QAAQ;AAAA,UACR,KAAK,2DAA2D,KAAK;AAAA,UACrE,SAAS;AAAA,YACP,YAAY;AAAA,YACZ,eAAe,QAAQ,KAAK,QAAQ;AAAA,YACpC,WAAW,0BAA0B,KAAK;AAAA,YAC1C,UAAU;AAAA,YACV,cAAc;AAAA,YACd,QAAQ;AAAA,YACR,mBAAmB;AAAA,YACnB,gBAAgB;AAAA,YAChB,cAAc;AAAA,YACd,aAAa,KAAK;AAAA,YAClB,iBAAiB;AAAA,YACjB,cAAc;AAAA,UAChB;AAAA,QACF,CAAC,EACE,KAAK,OAAOO,SAAQ;AACnB,eAAK,IAAI,MAAM,KAAK,UAAUA,KAAI,IAAI,CAAC;AACvC,cAAIA,KAAI,KAAK,YAAY;AACvB,iBAAK,IAAI,MAAM,KAAK,UAAUA,KAAI,IAAI,CAAC;AACvC;AAAA,UACF,OAAO;AACL,iBAAK,QAAQ,MAAM,EAAE,GAAG,KAAK,QAAQ,KAAK,GAAGA,KAAI,KAAK;AAAA,UACxD;AAAA,QACF,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,eAAK,IAAI,KAAK,KAAK;AACnB,gBAAM,YAAY,KAAK,IAAI,MAAM,KAAK,UAAU,MAAM,SAAS,IAAI,CAAC;AAAA,QACtE,CAAC;AAEH,YAAI,CAAC,KAAK,QAAQ,IAAI,IAAI;AACxB,gBAAML,QAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6BAcI;AAAA;AAEjB,gBAAME,OAAM,cAAAJ,QAAO,WAAW,KAAK,EAAE,OAAOE,KAAI,EAAE,OAAO,QAAQ;AACjE,eAAK,IAAI,MAAME,IAAG;AAClB,gBAAMC,WAAUD,OAAM;AACtB,gBAAME,aAAY,cAAAN,QAAO,WAAW,QAAQ,KAAK,MAAM,EAAE,OAAOK,QAAO,EAAE,OAAO,KAAK;AACrF,gBAAM,KAAK,cAAc;AAAA,YACvB,QAAQ;AAAA,YACR,KAAK,yEAAyE,KAAK,QAAQ,gBAAgB,KAAK;AAAA,YAChH,SAAS;AAAA,cACP,gBAAgB;AAAA,cAChB,eAAeD;AAAA,cACf,QAAQ;AAAA,cACR,cAAc;AAAA,cACd,mBAAmB;AAAA,cACnB,mBACE,6HACAE;AAAA,YACJ;AAAA,YACA,MAAMJ;AAAA,UACR,CAAC,EACE,KAAK,OAAOK,SAAQ;AApbnC,gBAAAC,KAAAC,KAAA;AAqbgB,iBAAK,IAAI,MAAM,KAAK,UAAUF,KAAI,IAAI,CAAC;AACvC,gBAAI,SAAc,CAAC;AACnB,gBAAIA,KAAI,KAAK,YAAY;AACvB,mBAAK,IAAI,MAAM,KAAK,UAAUA,KAAI,IAAI,CAAC;AAAA,YACzC,OAAO;AACL,wBAAS,wBAAAE,OAAAD,MAAAD,KAAI,KAAK,WAAT,gBAAAC,IAAiB,iBAAjB,gBAAAC,IAA+B,WAA/B,mBAAuC,UAAU,OAAjD,mBAAqD,WAArD,mBAA6D,YAA7D,mBAAsE;AAC/E,qBAAO,KAAK,OAAO;AACnB,mBAAK,IAAI,KAAK,UAAU,aAAa,OAAO,IAAI;AAChD,qBAAO,OAAO;AACd,qBAAO,OAAO;AAEd,mBAAK,QAAQ,MAAM,EAAE,GAAG,KAAK,QAAQ,KAAK,GAAG,OAAO;AAAA,YACtD;AAAA,UACF,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,iBAAK,IAAI,KAAK,KAAK;AACnB,kBAAM,YAAY,KAAK,IAAI,MAAM,KAAK,UAAU,MAAM,SAAS,IAAI,CAAC;AAAA,UACtE,CAAC;AAAA,QACL;AACA,YAAI,CAAC,KAAK,QAAQ,IAAI,IAAI;AACxB,gBAAM,UAAU,MAAM,KAAK,cAAc,KAAK,KAAK;AACnD,cAAI,WAAW,QAAQ,KAAK;AAC1B,iBAAK,QAAQ,IAAI,KAAK,QAAQ;AAAA,UAChC,OAAO;AACL,kBAAM,KAAK,wBAAwB,KAAK,OAAO;AAAA,cAC7C,MAAM;AAAA,cACN,QAAQ;AAAA,gBACN,MAAM;AAAA,gBACN,OAAO;AAAA,gBACP,MAAM;AAAA,gBACN,MAAM;AAAA,gBACN,MAAM;AAAA,cACR;AAAA,cACA,QAAQ,CAAC;AAAA,YACX,CAAC;AACD,iBAAK,IAAI,KAAK,mBAAmB,uDAAuD;AAAA,UAC1F;AAAA,QACF;AACA,aAAK,SAAS,MAAM,IAAI,KAAK,QAAQ,GAAG;AACxC,YAAI,KAAK,QAAQ,IAAI,IAAI;AACvB,gBAAM,aAAa,MAAM,KAAK,WAAW,EAAE,EACxC,KAAK,MAAM;AACV,iBAAK,IAAI,KAAK,eAAe,IAAI;AAAA,UACnC,CAAC,EACA,MAAM,CAAC,MAAM;AACZ,iBAAK,IAAI,MAAM,CAAC;AAAA,UAClB,CAAC;AACH,eAAK,IAAI,MAAM,cAAc,MAAM,KAAK,UAAU,UAAU,GAAG;AAAA,QACjE;AAAA,MACF;AAAA,IACF,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,WAAK,IAAI,KAAK,KAAK;AACnB,YAAM,YAAY,KAAK,IAAI,MAAM,KAAK,UAAU,MAAM,SAAS,IAAI,CAAC;AAAA,IACtE,CAAC;AAEH,UAAM,KAAK,wBAAwB,cAAc;AAAA,MAC/C,MAAM;AAAA,MACN,QAAQ;AAAA,QACN,MAAM;AAAA,QACN,OAAO;AAAA,QACP,MAAM;AAAA,QACN,MAAM;AAAA,QACN,MAAM;AAAA,MACR;AAAA,MACA,QAAQ,CAAC;AAAA,IACX,CAAC;AAED,UAAM,KAAK,cAAc,cAAc,KAAK,UAAU,KAAK,OAAO,GAAG,IAAI;AAAA,EAC3E;AAAA,EACA,MAAM,WAAW,IAA2B;AAC1C,UAAM,SAAS,KAAK,QAAQ;AAC5B,QAAI,CAAC,OAAO,IAAI;AACd,WAAK,IAAI,KAAK,mBAAmB,IAAI;AACrC;AAAA,IACF;AACA,SAAK,IAAI,KAAK,eAAe,WAAW,OAAO,sBAAsB,OAAO,IAAI;AAChF,QAAI;AACJ,QAAI,OAAO,eAAe,QAAQ;AAChC,qBAAe,IAAI,YAAAC,QAAK,KAAK,KAAK,OAAO,IAAI,KAAK,OAAO,UAAU,KAAK,OAAO,UAAU,CAAC;AAAA,IAC5F,WAAW,OAAO,WAAW,WAAW,MAAM,KAAK,OAAO,WAAW,WAAW,MAAM,GAAG;AACvF,qBAAe,IAAI,YAAAC,QAAK,KAAK,KAAK,OAAO,IAAI,KAAK,OAAO,UAAU,KAAK,OAAO,UAAU,CAAC;AAAA,IAC5F,WAAW,OAAO,eAAe,UAAU,OAAO,WAAW,WAAW,MAAM,GAAG;AAC/E,qBAAe,IAAI,YAAAC,QAAK,KAAK,KAAK,OAAO,IAAI,KAAK,OAAO,UAAU,KAAK,OAAO,UAAU,CAAC;AAAA,IAC5F,WAAW,OAAO,eAAe,SAAS;AACxC,qBAAe,IAAI,aAAAC,QAAM,KAAK,KAAK,OAAO,IAAI,KAAK,OAAO,UAAU,KAAK,OAAO,UAAU,CAAC;AAAA,IAC7F,WAAW,OAAO,eAAe,SAAS;AACxC,qBAAe,IAAI,aAAAC,QAAM,KAAK,KAAK,OAAO,IAAI,KAAK,OAAO,UAAU,KAAK,OAAO,UAAU,CAAC;AAAA,IAC7F,WAAW,OAAO,WAAW,WAAW,GAAG,KAAK,OAAO,WAAW,WAAW,IAAI,GAAG;AAClF,qBAAe,IAAI,aAAAD,QAAM,KAAK,KAAK,OAAO,IAAI,KAAK,OAAO,UAAU,KAAK,OAAO,UAAU,CAAC;AAAA,IAC7F,WAAW,OAAO,WAAW,WAAW,GAAG,KAAK,OAAO,WAAW,WAAW,IAAI,GAAG;AAClF,UAAI,CAAC,KAAK,OAAO,kBAAkB,CAAC,KAAK,OAAO,gBAAgB;AAC9D,aAAK,IAAI,KAAK,+DAA+D;AAAA,MAC/E;AACA,qBAAe,IAAI,6BAAW,KAAK,KAAK;AAAA,QACtC,MAAM,OAAO;AAAA,QACb,WAAW,OAAO;AAAA,QAClB,UAAU,KAAK,OAAO;AAAA,QACtB,YAAY,KAAK,OAAO;AAAA,QACxB,gBAAgB,KAAK,OAAO;AAAA,QAC5B,kBAAkB;AAAA,MACpB,CAAC;AAID,WAAK,cAAc,MAAM;AACzB,YAAM,aAAa,MAAM,aAAa,cAAc,IAAI;AACxD,WAAK,IAAI,KAAK,GAAG,2BAA2B,KAAK,UAAU,UAAU,GAAG;AACxE,WAAK,IAAI,MAAM,KAAK,UAAU,UAAU,CAAC;AACzC,WAAK,SAAS,MAAM,IAAI,UAAU;AAClC,WAAK,IAAI,MAAM,0BAA0B,IAAI;AAC7C,YAAM,eAAe,MAAM,aAAa,gBAAgB;AACxD,YAAM,KAAK,wBAAwB,KAAK,gBAAgB;AAAA,QACtD,MAAM;AAAA,QACN,QAAQ;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,UACN,MAAM;AAAA,UACN,KAAK;AAAA,UACL,OAAO;AAAA,UACP,MAAM;AAAA,QACR;AAAA,QACA,QAAQ,CAAC;AAAA,MACX,CAAC;AACD,WAAK,IAAI,MAAM,kCAAkC;AACjD,mBAAa,YAAY,UAAU,OAAO,mBAAwB;AAChE,cAAM,KAAK,cAAc,KAAK,gBAAgB,gBAAgB,IAAI;AAClE,aAAK,IAAI,MAAM,IAAI,OAAO,iCAAiC,gBAAgB;AAAA,MAC7E,CAAC;AACD;AAAA,IACF,OAAO;AACL,WAAK,IAAI,KAAK,uBAAuB,OAAO,yBAAyB;AACrE,qBAAe,IAAI,YAAAH,QAAK,KAAK,KAAK,OAAO,IAAI,KAAK,OAAO,UAAU,KAAK,OAAO,UAAU,CAAC;AAAA,IAC5F;AACA,SAAK,cAAc,MAAM;AACzB,UAAM,aACH,UAAU,EACV,KAAK,YAAY;AAChB,UAAI,aAAa,SAAS;AACxB,aAAK,IAAI,MAAM,sBAAsB;AACrC,cAAM,aAAa,cAAc,EAAE,MAAM,CAAC,UAAe;AACvD,eAAK,IAAI,MAAM,KAAK;AACpB,eAAK,IAAI,MAAM,uBAAuB;AACtC,uBAAa,UAAU;AACvB,eAAK,cAAc,IAAI,aAAa;AAAA,QACtC,CAAC;AAAA,MACH,OAAO;AACL,cAAM,aAAa,MAAM,EAAE,MAAM,MAAM;AACrC,eAAK,IAAI,MAAM,cAAc;AAC7B,eAAK,cAAc,IAAI,aAAa;AAAA,QACtC,CAAC;AAAA,MACH;AACA,mBACG,cAAc,IAAI,EAClB,KAAK,OAAO,YAAiB;AAC5B,aAAK,IAAI,MAAM,KAAK,UAAU,OAAO,CAAC;AACtC,YAAI,QAAQ,SAAS;AACnB,eAAK,IAAI,MAAM,4BAA4B;AAC3C,eAAK,IAAI,MAAM,KAAK,UAAU,OAAO,CAAC;AACtC;AAAA,QACF;AACA,aAAK,SAAS,MAAM,IAAI,OAAO;AAE/B,aAAK,cAAc,IAAI,aAAa;AACpC,YAAI,KAAK,cAAc,IAAI,gBAAgB;AACzC,eAAK,IAAI,MAAM,sBAAsB;AACrC,gBAAM,cAAc,MAAM,KAAK,cAAc,IAAI,eAAe;AAChE,eAAK,IAAI,MAAM,KAAK,UAAU,WAAW,CAAC;AAC1C,eAAK,SAAS,MAAM,IAAI,WAAW;AAAA,QACrC;AAAA,MACF,CAAC,EACA,MAAM,CAAC,UAAe;AACrB,aAAK,IAAI,MAAM,KAAK,UAAU,KAAK,CAAC;AACpC,aAAK,IAAI,MAAM,6BAA6B;AAE5C,aAAK,cAAc,IAAI,aAAa;AAAA,MACtC,CAAC;AAAA,IACL,CAAC,EACA,MAAM,MAAM;AACX,WAAK,IAAI,MAAM,kBAAkB;AACjC,WAAK,cAAc,IAAI,aAAa;AAAA,IACtC,CAAC;AAAA,EACL;AAAA,EAEA,MAAM,gBAA+B;AACnC,QAAI;AACF,iBAAW,YAAY,KAAK,eAAe;AACzC,YAAI,KAAK,cAAc,UAAU,WAAW;AAC1C,eAAK,IAAI,MAAM,uBAAuB;AACtC,gBAAM,SAAS,MAAM,KAAK,cAAc,UAAU,UAAU;AAC5D,eAAK,IAAI,MAAM,KAAK,UAAU,MAAM,CAAC;AACrC,eAAK,SAAS,MAAM,UAAU,MAAM;AACpC,cAAI,KAAK,cAAc,UAAU,SAAS,QAAW;AACnD,iBAAK,IAAI,MAAM,wBAAwB,WAAW,mCAAmC;AAErF,mBAAO,KAAK,cAAc;AAAA,UAC5B;AACA;AAAA,QACF;AACA,YAAI,CAAC,KAAK,cAAc,UAAU,YAAY;AAC5C;AAAA,QACF;AAEA,aAAK,cAAc,UAChB,cAAc,IAAI,EAClB,KAAK,OAAO,YAAiB;AAC5B,eAAK,IAAI,MAAM,KAAK,UAAU,OAAO,CAAC;AACtC,cAAI,CAAC,WAAW,QAAQ,SAAS,WAAW,QAAQ,SAAS;AAC3D,iBAAK,IAAI,MAAM,4BAA4B;AAE3C;AAAA,UACF;AACA,gBAAM,KAAK,SAAS,MAAM,UAAU,OAAO;AAC3C,cAAI,KAAK,cAAc,UAAU,gBAAgB;AAC/C,iBAAK,IAAI,MAAM,sBAAsB;AACrC,kBAAM,cAAc,MAAM,KAAK,cAAc,UAAU,eAAe;AACtE,iBAAK,IAAI,MAAM,KAAK,UAAU,WAAW,CAAC;AAC1C,gBAAI,YAAY,SAAS;AACvB,mBAAK,IAAI,MAAM,mCAAmC;AAClD,mBAAK,IAAI,MAAM,KAAK,UAAU,WAAW,CAAC;AAC1C;AAAA,YACF;AACA,kBAAM,KAAK,SAAS,MAAM,UAAU,WAAW;AAC/C,kBAAM,cAAc,KAAK,cAAc,UAAU,oBAAoB;AACrE,gBAAI,YAAY,SAAS;AACvB,mBAAK,IAAI,MAAM,wCAAwC;AACvD,mBAAK,IAAI,MAAM,KAAK,UAAU,WAAW,CAAC;AAC1C;AAAA,YACF;AACA,kBAAM,KAAK,SAAS,MAAM,UAAU,WAAW;AAAA,UACjD;AAAA,QACF,CAAC,EACA,MAAM,CAAC,UAAe;AACrB,eAAK,IAAI,MAAM,8BAA8B,cAAc,OAAO;AAAA,QACpE,CAAC;AAAA,MACL;AACA,WAAK,IAAI,MAAM,aAAa;AAAA,IAC9B,SAAS,OAAP;AACA,WAAK,IAAI,KAAK,KAAK;AAAA,IACrB;AAAA,EACF;AAAA,EAEA,SAAS,KAAsB;AAC7B,QAAI,QAAQ,MAAM,IAAI,KAAK,MAAM,IAAI;AACnC,aAAO;AAAA,IACT;AACA,QAAI;AACF,YAAM,oBAAoB,IAAI,QAAQ,OAAO,EAAE;AAC/C,aAAO,KAAK,KAAK,iBAAiB,CAAC,MAAM,qBAAqB,KAAK,KAAK,GAAG,CAAC,MAAM;AAAA,IACpF,SAAS,KAAP;AACA,aAAO;AAAA,IACT;AAAA,EACF;AAAA,EACA,MAAM,MAAM,IAA2B;AACrC,WAAO,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,EAAE,CAAC;AAAA,EACzD;AAAA,EACA,MAAM,eAA8B;AAClC,SAAK,IAAI,MAAM,eAAe;AAAA,EAChC;AAAA,EAIQ,SAAS,UAA4B;AAC3C,QAAI;AACF,WAAK,SAAS,mBAAmB,OAAO,IAAI;AAC5C,WAAK,kBAAkB,aAAa,KAAK,cAAc;AACvD,WAAK,kBAAkB,aAAa,KAAK,cAAc;AACvD,WAAK,uBAAuB,aAAa,KAAK,mBAAmB;AACjE,WAAK,kBAAkB,cAAc,KAAK,cAAc;AACxD,WAAK,wBAAwB,cAAc,KAAK,oBAAoB;AAEpE,eAAS;AAAA,IACX,SAAS,GAAP;AACA,eAAS;AAAA,IACX;AAAA,EACF;AAAA,EAKA,MAAc,cAAc,IAAY,OAAyD;AAC/F,QAAI,OAAO;AACT,UAAI,CAAC,MAAM,KAAK;AACd,cAAM,WAAW,GAAG,MAAM,GAAG,EAAE;AAC/B,cAAM,UAAU,GAAG,MAAM,GAAG,EAAE;AAC9B,YAAI,GAAG,MAAM,GAAG,EAAE,OAAO,UAAU;AACjC;AAAA,QACF;AAEA,YAAI,YAAY,WAAW;AACzB,eAAK,cAAc,UAChB,cAAc,IAAI,EAClB,KAAK,CAAC,YAAiB;AACtB,iBAAK,IAAI,MAAM,KAAK,UAAU,OAAO,CAAC;AACtC,iBAAK,SAAS,MAAM,UAAU,OAAO;AAAA,UACvC,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,iBAAK,IAAI,MAAM,8BAA8B,cAAc,OAAO;AAAA,UACpE,CAAC;AAEH;AAAA,QACF;AACA,YAAI;AACF,cAAI,KAAK,cAAc,aAAa,KAAK,cAAc,UAAU,UAAU;AACzE,gBAAI,YAAY,cAAc,YAAY,aAAa;AACrD,oBAAM,aAAa,MAAM,IAAI,QAAQ,KAAK,EAAE,EAAE,MAAM,GAAG;AACvD,oBAAM,SAAS,MAAM,KAAK,cAAc,UAAU,SAAS,WAAW,IAAI,WAAW,EAAE;AACvF,mBAAK,IAAI,KAAK,KAAK,UAAU,MAAM,CAAC;AAAA,YACtC,OAAO;AACL,oBAAM,SAAS,MAAM,KAAK,cAAc,UAAU,SAAS,MAAM,GAAG;AACpE,mBAAK,IAAI,KAAK,KAAK,UAAU,MAAM,CAAC;AAAA,YACtC;AACA,iBAAK,kBAAkB,aAAa,KAAK,cAAc;AACvD,iBAAK,iBAAiB,WAAW,YAAY;AAC3C,mBAAK,cAAc;AAAA,YACrB,GAAG,IAAI,GAAI;AAAA,UACb,OAAO;AACL,iBAAK,IAAI,MAAM,UAAU,2BAA2B,SAAS;AAAA,UAC/D;AAAA,QACF,SAAS,OAAP;AACA,eAAK,IAAI,MAAM,KAAK;AAAA,QACtB;AAAA,MACF,OAAO;AACL,cAAM,aAAa,EAAE,WAAW,gBAAgB;AAChD,cAAM,UAAU,GAAG,MAAM,GAAG;AAC5B,cAAM,YAAY,QAAQ,QAAQ,SAAS;AAC3C,cAAM,WAAW,GAAG,MAAM,GAAG,EAAE;AAC/B,YAAI,WAAW,YAAY;AACzB,gBAAM,KAAK,SAAS,WAAW,aAAa,WAAW,YAAY,MAAM,KAAK,IAAI;AAAA,QACpF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAI,QAAQ,SAAS,QAAQ;AAE3B,SAAO,UAAU,CAAC,YAAuD,IAAI,KAAK,OAAO;AAC3F,OAAO;AAEL,GAAC,MAAM,IAAI,KAAK,GAAG;AACrB;",
|
|
4
|
+
"sourcesContent": ["/*\n * Created with @iobroker/create-adapter v2.1.1\n */\n\n// The adapter-core module gives you access to the core ioBroker functions\n// you need to create an adapter\nimport * as utils from \"@iobroker/adapter-core\";\nimport axios, { AxiosInstance } from \"axios\";\nimport crypto from \"crypto\";\nimport https from \"https\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport Json2iob from \"json2iob\";\nimport { TAPOCamera } from \"./lib/utils/camera/tapoCamera\";\nimport L510E from \"./lib/utils/l510e\";\nimport L520E from \"./lib/utils/l520e\";\nimport L530 from \"./lib/utils/l530\";\nimport P100 from \"./lib/utils/p100\";\nimport P110 from \"./lib/utils/p110\";\n// Using ESM import syntax\nimport got from \"got\";\nclass Tapo extends utils.Adapter {\n private devices: { [key: string]: any };\n private deviceObjects: { [key: string]: any };\n private json2iob: Json2iob;\n private secret: Buffer;\n private requestClient: AxiosInstance;\n updateInterval: any = null;\n reLoginTimeout: any = null;\n refreshTokenTimeout: any = null;\n session: any = {};\n refreshTimeout: any;\n refreshTokenInterval: any;\n\n termId: any;\n public constructor(options: Partial<utils.AdapterOptions> = {}) {\n super({\n ...options,\n name: \"tapo\",\n });\n this.on(\"ready\", this.onReady.bind(this));\n this.on(\"stateChange\", this.onStateChange.bind(this));\n this.on(\"unload\", this.onUnload.bind(this));\n this.devices = {};\n this.deviceObjects = {};\n this.json2iob = new Json2iob(this);\n this.requestClient = axios.create({\n httpsAgent: new https.Agent({\n rejectUnauthorized: false,\n secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT,\n }),\n });\n this.secret = Buffer.from([\n 54, 101, 100, 55, 100, 57, 55, 102, 51, 101, 55, 51, 52, 54, 55, 102, 56, 97, 53, 98, 97, 98, 57, 48, 98, 53, 55, 55, 98, 97, 52, 99,\n ]);\n }\n\n /**\n * Is called when databases are connected and adapter received configuration.\n */\n private async onReady(): Promise<void> {\n this.setState(\"info.connection\", false, true);\n if (this.config.interval < 0.5) {\n this.log.info(\"Set interval to minimum 0.5\");\n this.config.interval = 0.5;\n }\n if (!this.config.username || !this.config.password) {\n this.log.error(\"Please set username and password in the instance settings\");\n return;\n }\n\n this.updateInterval = null;\n this.reLoginTimeout = null;\n this.refreshTokenTimeout = null;\n this.session = {};\n this.subscribeStates(\"*\");\n\n const termIdState = await this.getStateAsync(\"termId\");\n if (termIdState && termIdState.val) {\n this.termId = termIdState.val;\n } else {\n await this.setObjectNotExistsAsync(\"termId\", {\n type: \"state\",\n common: {\n name: \"Terminal ID\",\n write: false,\n read: true,\n type: \"string\",\n role: \"text\",\n },\n native: {},\n });\n this.termId = uuidv4();\n await this.setStateAsync(\"termId\", this.termId, true);\n }\n\n this.log.info(\"Login tp TAPO App\");\n await this.login();\n if (this.session.token) {\n await this.getDeviceList();\n } else {\n this.log.warn(\"Login failed using cached device list\");\n const deviceListState = await this.getStateAsync(\"deviceList\");\n if (deviceListState && deviceListState.val) {\n this.log.info(\"Use cached device list\");\n this.devices = JSON.parse(deviceListState.val);\n for (const id in this.devices) {\n if (this.devices[id].ip) {\n const initResult = await this.initDevice(id)\n .then(() => {\n this.log.info(`Initialized ${id}`);\n })\n .catch((e) => {\n this.log.error(e);\n });\n this.log.debug(`initResult ${id} ${JSON.stringify(initResult)}`);\n }\n }\n }\n }\n\n this.log.info(\"Wait for connections for non camera devices\");\n await this.sleep(10000);\n this.log.info(\"Start first Update\");\n this.updateDevices();\n this.updateInterval = setInterval(async () => {\n this.updateDevices();\n }, this.config.interval * 1000);\n }\n async login(): Promise<void> {\n let body = JSON.stringify({\n appVersion: \"2.8.21\",\n refreshTokenNeeded: true,\n platform: \"iOS 14.8\",\n cloudPassword: this.config.password,\n terminalUUID: this.termId,\n cloudUserName: this.config.username,\n terminalName: \"ioBroker\",\n terminalMeta: \"3\",\n appType: \"TP-Link_Tapo_iOS\",\n });\n let path = \"api/v2/account/login\";\n const mfaIdState = await this.getStateAsync(\"mfaId\");\n if (mfaIdState && mfaIdState.val) {\n if (!this.config.mfa) {\n this.log.error(\"Please set mfa in the instance settings\");\n return;\n }\n\n body = JSON.stringify({\n cloudUserName: this.config.username,\n MFAProcessId: mfaIdState.val,\n appType: \"TP-Link_Tapo_iOS\",\n MFAType: 2,\n code: this.config.mfa,\n terminalBindEnabled: true,\n });\n path = \"api/v2/account/checkMFACodeAndLogin\";\n await this.setStateAsync(\"mfaId\", \"\", true);\n }\n const md5 = crypto.createHash(\"md5\").update(body).digest(\"base64\");\n this.log.debug(md5);\n const content = md5 + \"\\n9999999999\\nfee66616-58dd-4bcb-be79-fe092d800a21\\n/\" + path;\n const signature = crypto.createHmac(\"sha1\", this.secret).update(content).digest(\"hex\");\n await this.requestClient({\n method: \"post\",\n url:\n \"https://n-wap-gw.tplinkcloud.com/\" +\n path +\n \"?termID=\" +\n this.termId +\n \"&appVer=2.8.21&locale=de_DE&appName=TP-Link_Tapo_iOS&netType=wifi&model=iPhone10%2C5&termName=iPhone&termMeta=3&brand=TPLINK&ospf=iOS%2014.8\",\n headers: {\n \"Content-Type\": \"application/json;UTF-8\",\n Accept: \"*/*\",\n \"User-Agent\": \"Tapo/2.8.21 (iPhone; iOS 14.8; Scale/3.00)\",\n \"Accept-Language\": \"de-DE;q=1, uk-DE;q=0.9, en-DE;q=0.8\",\n \"X-Authorization\":\n \"Timestamp=9999999999, Nonce=fee66616-58dd-4bcb-be79-fe092d800a21, AccessKey=4d11b6b9d5ea4d19a829adbb9714b057, Signature=\" +\n signature,\n },\n data: body,\n })\n .then(async (res) => {\n this.log.debug(JSON.stringify(res.data));\n if (res.data.error_code) {\n this.log.error(JSON.stringify(res.data));\n return;\n }\n if (res.data.result?.MFAProcessId) {\n this.log.info(\"Found MFA Process please enter MFA in the instance settings\");\n await this.setObjectNotExistsAsync(\"mfaId\", {\n type: \"state\",\n common: {\n name: \"MFA Id\",\n write: false,\n read: true,\n type: \"string\",\n role: \"text\",\n },\n native: {},\n });\n await this.setStateAsync(\"mfaId\", res.data.result?.MFAProcessId, true);\n\n const body = JSON.stringify({\n cloudPassword: this.config.password,\n locale: \"de_DE\",\n terminalUUID: this.termId,\n cloudUserName: this.config.username,\n appType: \"TP-Link_Tapo_iOS\",\n });\n\n const path = \"api/v2/account/getEmailVC4TerminalMFA\";\n\n const md5 = crypto.createHash(\"md5\").update(body).digest(\"base64\");\n this.log.debug(md5);\n const content = md5 + \"\\n9999999999\\nfee66616-58dd-4bcb-be79-fe092d800a21\\n/\" + path;\n const signature = crypto.createHmac(\"sha1\", this.secret).update(content).digest(\"hex\");\n await this.requestClient({\n method: \"post\",\n url:\n \"https://n-wap-gw.tplinkcloud.com/\" +\n path +\n \"?termID=\" +\n this.termId +\n \"&appVer=2.8.21&locale=de_DE&appName=TP-Link_Tapo_iOS&netType=wifi&model=iPhone10%2C5&termName=iPhone&termMeta=3&brand=TPLINK&ospf=iOS%2014.8\",\n headers: {\n \"Content-Type\": \"application/json;UTF-8\",\n Accept: \"*/*\",\n \"User-Agent\": \"Tapo/2.8.21 (iPhone; iOS 14.8; Scale/3.00)\",\n \"Accept-Language\": \"de-DE;q=1, uk-DE;q=0.9, en-DE;q=0.8\",\n \"X-Authorization\":\n \"Timestamp=9999999999, Nonce=fee66616-58dd-4bcb-be79-fe092d800a21, AccessKey=4d11b6b9d5ea4d19a829adbb9714b057, Signature=\" +\n signature,\n },\n data: body,\n })\n .then(async (res) => {\n this.log.debug(JSON.stringify(res.data));\n if (res.data.error_code) {\n this.log.error(JSON.stringify(res.data));\n return;\n }\n })\n .catch((error) => {\n this.log.error(error);\n error.response && this.log.error(JSON.stringify(error.response.data));\n });\n return;\n }\n\n if (!res.data.result || !res.data.result.token) {\n this.log.error(\"Login failed\");\n this.log.error(JSON.stringify(res.data));\n return;\n }\n this.session = res.data.result;\n if (this.session.token) {\n this.log.info(\"Login succesfull\");\n this.setState(\"info.connection\", true, true);\n }\n return;\n })\n .catch((error) => {\n this.log.error(error);\n error.response && this.log.error(JSON.stringify(error.response.data));\n });\n }\n\n async getDeviceList(): Promise<void> {\n const body =\n '{\"index\":0,\"deviceTypeList\":[\"SMART.TAPOBULB\",\"SMART.TAPOPLUG\",\"SMART.IPCAMERA\",\"SMART.TAPOHUB\",\"SMART.TAPOSENSOR\",\"SMART.TAPOSWITCH\"],\"limit\":30}';\n const md5 = crypto.createHash(\"md5\").update(body).digest(\"base64\");\n this.log.debug(md5);\n const content = md5 + \"\\n9999999999\\nfee66616-58dd-4bcb-be79-fe092d800a21\\n/api/v2/common/getDeviceListByPage\";\n const signature = crypto.createHmac(\"sha1\", this.secret).update(content).digest(\"hex\");\n await this.requestClient({\n method: \"post\",\n url: `https://n-euw1-wap-gw.tplinkcloud.com/api/v2/common/getDeviceListByPage?token=${this.session.token}&termID=${this.termId}&appVer=2.8.21&locale=de_DE&appName=TP-Link_Tapo_iOS&netType=wifi&model=iPhone10%2C5&termName=iPhone&termMeta=3&brand=TPLINK&ospf=iOS%2014.8`,\n headers: {\n \"Content-Type\": \"application/json;UTF-8\",\n \"Content-MD5\": md5,\n Accept: \"*/*\",\n \"User-Agent\": \"Tapo/2.8.21 (iPhone; iOS 14.8; Scale/3.00)\",\n \"Accept-Language\": \"de-DE;q=1, uk-DE;q=0.9, en-DE;q=0.8\",\n \"X-Authorization\":\n \"Timestamp=9999999999, Nonce=fee66616-58dd-4bcb-be79-fe092d800a21, AccessKey=4d11b6b9d5ea4d19a829adbb9714b057, Signature=\" +\n signature,\n },\n data: body,\n })\n .then(async (res) => {\n this.log.debug(JSON.stringify(res.data));\n if (res.data.error_code) {\n this.log.error(JSON.stringify(res.data));\n return;\n }\n this.log.info(`Found ${res.data.result?.totalNum} devices`);\n\n for (const device of res.data.result?.deviceList) {\n const id = device.deviceId;\n this.devices[id] = device;\n let name = device.alias;\n\n if (this.isBase64(device.alias)) {\n name = Buffer.from(device.alias, \"base64\").toString(\"utf8\");\n }\n this.log.debug(`Found device ${id} ${name}`);\n await this.extendObject(id, {\n type: \"device\",\n common: {\n name: name,\n },\n native: {},\n });\n await this.setObjectNotExistsAsync(id + \".remote\", {\n type: \"channel\",\n common: {\n name: \"Remote Controls\",\n },\n native: {},\n });\n\n const remoteArray = [\n { command: \"refresh\", name: \"True = Refresh\" },\n { command: \"setPowerState\", name: \"True = On, False = Off\" },\n { command: \"setAlertConfig\", name: \"True = On, False = Off\" },\n { command: \"setLensMaskConfig\", name: \"True = On, False = Off\" },\n { command: \"setForceWhitelampState\", name: \"True = On, False = Off\" },\n { command: \"moveMotor\", name: \"move Camera to X (-360,360), Y(-45,45)\", type: \"string\", def: \"0, 0\", role: \"text\" },\n { command: \"moveMotorStep\", name: \"Angle (0-360)\", type: \"string\", def: \"180\", role: \"text\" },\n\n {\n command: \"setBrightness\",\n name: \"Set Brightness for Light devices\",\n type: \"number\",\n role: \"level.brightness\",\n def: 5,\n },\n {\n command: \"setColorTemp\",\n name: \"Set Color Temp for Light devices\",\n type: \"number\",\n role: \"level.color.temperature\",\n def: 3000,\n },\n {\n command: \"setColor\",\n name: \"Set Color for Light devices (hue, saturation)\",\n def: \"30, 100\",\n type: \"string\",\n },\n ];\n remoteArray.forEach((remote) => {\n this.extendObject(id + \".remote.\" + remote.command, {\n type: \"state\",\n common: {\n name: remote.name || \"\",\n type: remote.type || \"boolean\",\n role: remote.role || \"switch\",\n def: remote.def != null ? remote.def : false,\n write: true,\n read: true,\n },\n native: {},\n });\n });\n this.json2iob.parse(id, device, { channelName: name });\n\n //try new API\n\n await this.requestClient({\n method: \"get\",\n url: \"https://euw1-app-server.iot.i.tplinknbu.com/v1/things/\" + id + \"/details\",\n headers: {\n \"x-locale\": \"de\",\n Authorization: \"ut|\" + this.session.token,\n \"app-cid\": \"app:TP-Link_Tapo_iOS:\" + this.termId,\n \"x-ospf\": \"iOS 14.8\",\n \"x-app-name\": \"TP-Link_Tapo_iOS\",\n Accept: \"*/*\",\n \"Accept-Language\": \"de-DE;q=1, uk-DE;q=0.9, en-DE;q=0.8\",\n \"Content-Type\": \"application/json;UTF-8\",\n \"User-Agent\": \"Tapo/2.9.7 (iPhone; iOS 14.8; Scale/3.00)\",\n \"x-term-id\": this.termId,\n \"x-app-version\": \"2.9.7\",\n \"x-net-type\": \"wifi\",\n },\n })\n .then(async (res) => {\n this.log.debug(JSON.stringify(res.data));\n if (res.data.error_code) {\n this.log.error(JSON.stringify(res.data));\n return;\n } else {\n this.devices[id] = { ...this.devices[id], ...res.data };\n }\n })\n .catch((error) => {\n this.log.warn(error);\n error.response && this.log.error(JSON.stringify(error.response.data));\n });\n //no ip via new API try old api\n if (!this.devices[id].ip) {\n const body = `{\n \"requestData\": {\n \"method\": \"multipleRequest\",\n \"params\": {\n \"requests\": [{\n \"method\": \"getDeviceIpAddress\",\n \"params\": {\n \"network\": {\n \"name\": \"wan\"\n }\n }\n }]\n }\n },\n \"deviceId\": \"${id}\"\n }`;\n const md5 = crypto.createHash(\"md5\").update(body).digest(\"base64\");\n this.log.debug(md5);\n const content = md5 + \"\\n9999999999\\nfee66616-58dd-4bcb-be79-fe092d800a21\\n/api/v2/common/passthrough\";\n const signature = crypto.createHmac(\"sha1\", this.secret).update(content).digest(\"hex\");\n await this.requestClient({\n method: \"post\",\n url: `https://n-euw1-wap-gw.tplinkcloud.com/api/v2/common/passthrough?token=${this.session.token}&termID=${this.termId}&appVer=2.8.21&locale=de_DE&appName=TP-Link_Tapo_iOS&netType=wifi&model=iPhone10%2C5&termName=iPhone&termMeta=3&brand=TPLINK&ospf=iOS%2014.8`,\n headers: {\n \"Content-Type\": \"application/json;UTF-8\",\n \"Content-MD5\": md5,\n Accept: \"*/*\",\n \"User-Agent\": \"Tapo/2.8.21 (iPhone; iOS 14.8; Scale/3.00)\",\n \"Accept-Language\": \"de-DE;q=1, uk-DE;q=0.9, en-DE;q=0.8\",\n \"X-Authorization\":\n \"Timestamp=9999999999, Nonce=fee66616-58dd-4bcb-be79-fe092d800a21, AccessKey=4d11b6b9d5ea4d19a829adbb9714b057, Signature=\" +\n signature,\n },\n data: body,\n })\n .then(async (res) => {\n this.log.debug(JSON.stringify(res.data));\n let result: any = {};\n if (res.data.error_code) {\n this.log.error(JSON.stringify(res.data));\n } else {\n result = res.data.result?.responseData?.result?.responses[0]?.result?.network?.wan;\n result.ip = result.ipaddr;\n this.log.info(`Device ${id} has IP ${result.ip}`);\n delete result[\".name\"];\n delete result[\".type\"];\n // result = res.data.result?.responseData?.result;\n this.devices[id] = { ...this.devices[id], ...result };\n }\n })\n .catch((error) => {\n this.log.warn(error);\n error.response && this.log.error(JSON.stringify(error.response.data));\n });\n }\n if (!this.devices[id].ip) {\n const ipState = await this.getStateAsync(id + \".ip\");\n if (ipState && ipState.val) {\n this.devices[id].ip = ipState.val;\n } else {\n await this.setObjectNotExistsAsync(id + \".ip\", {\n type: \"state\",\n common: {\n name: \"IP\",\n write: true,\n read: true,\n type: \"string\",\n role: \"text\",\n },\n native: {},\n });\n this.log.warn(`No IP found for ${id} put the device online or set the ip state manually`);\n }\n }\n this.json2iob.parse(id, this.devices[id]);\n if (this.devices[id].ip) {\n const initResult = await this.initDevice(id)\n .then(() => {\n this.log.info(`Initialized ${id}`);\n })\n .catch((e) => {\n this.log.error(e);\n });\n this.log.debug(`initResult camera ${id} ${JSON.stringify(initResult)}`);\n }\n }\n })\n .catch((error) => {\n this.log.warn(error);\n error.response && this.log.error(JSON.stringify(error.response.data));\n });\n\n await this.setObjectNotExistsAsync(\"deviceList\", {\n type: \"state\",\n common: {\n name: \"Cached device list\",\n write: false,\n read: true,\n type: \"string\",\n role: \"json\",\n },\n native: {},\n });\n\n await this.setStateAsync(\"deviceList\", JSON.stringify(this.devices), true);\n }\n async initDevice(id: string): Promise<void> {\n const device = this.devices[id];\n if (!device.ip) {\n this.log.warn(`No IP found for ${id}`);\n return;\n }\n this.log.info(`Init device ${id} type ${device.deviceName} with ip ${device.ip}`);\n let deviceObject: any;\n if (device.deviceName === \"P100\") {\n deviceObject = new P100(this.log, device.ip, this.config.username, this.config.password, 2);\n } else if (device.deviceName.startsWith(\"P110\") || device.deviceName.startsWith(\"P115\")) {\n deviceObject = new P110(this.log, device.ip, this.config.username, this.config.password, 2);\n } else if (device.deviceName === \"L530\" || device.deviceName.startsWith(\"L630\")) {\n deviceObject = new L530(this.log, device.ip, this.config.username, this.config.password, 2);\n } else if (device.deviceName === \"L510E\") {\n deviceObject = new L510E(this.log, device.ip, this.config.username, this.config.password, 2);\n } else if (device.deviceName === \"L520E\") {\n deviceObject = new L520E(this.log, device.ip, this.config.username, this.config.password, 2);\n } else if (device.deviceName.startsWith(\"L\") || device.deviceName.startsWith(\"KL\")) {\n deviceObject = new L510E(this.log, device.ip, this.config.username, this.config.password, 2);\n } else if (device.deviceName.startsWith(\"C\") || device.deviceName.startsWith(\"TC\")) {\n if (!this.config.streamusername || !this.config.streampassword) {\n this.log.warn(`No stream username or password. No motion detection available`);\n }\n deviceObject = new TAPOCamera(this.log, {\n name: device.deviceName,\n ipAddress: device.ip,\n password: this.config.password,\n streamUser: this.config.streamusername,\n streamPassword: this.config.streampassword,\n disableStreaming: true,\n });\n\n //new Camera(this.log, device.ip, this.config.username, this.config.password, 2);\n\n this.deviceObjects[id] = deviceObject;\n const deviceInfo = await deviceObject.getDeviceInfo(true);\n this.log.info(`${id} Received device info ${JSON.stringify(deviceInfo)}`);\n this.log.debug(JSON.stringify(deviceInfo));\n this.json2iob.parse(id, deviceInfo);\n this.log.debug(`Init event emitter for ${id}`);\n const eventEmitter = await deviceObject.getEventEmitter();\n await this.setObjectNotExistsAsync(id + \".motionEvent\", {\n type: \"state\",\n common: {\n name: \"Motion detected\",\n type: \"boolean\",\n role: \"boolean\",\n def: false,\n write: false,\n read: true,\n },\n native: {},\n });\n this.log.debug('Init event listener for \"motion\"');\n eventEmitter.addListener(\"motion\", async (motionDetected: any) => {\n await this.setStateAsync(id + \".motionEvent\", motionDetected, true);\n this.log.debug(`[${device.deviceName}] \"Motion detected\" ${motionDetected}`);\n });\n return;\n } else {\n this.log.info(`Unknown device type ${device.deviceName} init as P100`);\n deviceObject = new P100(this.log, device.ip, this.config.username, this.config.password, 2);\n }\n this.deviceObjects[id] = deviceObject;\n await deviceObject\n .handshake()\n .then(async () => {\n if (deviceObject.is_klap) {\n this.log.debug(\"Detected KLAP device\");\n await deviceObject.handshake_new().catch(async (error: any) => {\n this.log.error(error);\n this.log.error(error.stack);\n this.log.error(\"KLAP Handshake failed. Try old handshake\");\n deviceObject.is_klap = false;\n await deviceObject.reAuthenticate().catch(() => {\n this.log.error(\"Login failed\");\n this.deviceObjects[id]._connected = false;\n });\n });\n } else {\n await deviceObject.login().catch(() => {\n this.log.error(\"Login failed\");\n this.deviceObjects[id]._connected = false;\n });\n }\n deviceObject\n .getDeviceInfo(true)\n .then(async (sysInfo: any) => {\n this.log.debug(JSON.stringify(sysInfo));\n if (sysInfo.request) {\n this.log.error(\"Malformed response sysinfo\");\n this.log.error(JSON.stringify(sysInfo));\n return;\n }\n this.json2iob.parse(id, sysInfo);\n\n this.deviceObjects[id]._connected = true;\n if (this.deviceObjects[id].getEnergyUsage) {\n this.log.debug(\"Receive energy usage\");\n const energyUsage = await this.deviceObjects[id].getEnergyUsage();\n this.log.debug(JSON.stringify(energyUsage));\n this.json2iob.parse(id, energyUsage);\n }\n })\n .catch((error: any) => {\n this.log.error(JSON.stringify(error));\n this.log.error(\"52 - Get Device Info failed\");\n\n this.deviceObjects[id]._connected = false;\n });\n })\n .catch(() => {\n this.log.error(\"Handshake failed\");\n this.deviceObjects[id]._connected = false;\n });\n }\n\n async updateDevices(): Promise<void> {\n try {\n for (const deviceId in this.deviceObjects) {\n if (this.deviceObjects[deviceId].getStatus) {\n this.log.debug(\"Receive camera status\");\n const status = await this.deviceObjects[deviceId].getStatus().catch((error: any) => {\n this.log.info(\"Get camera Status failed\");\n this.log.debug(JSON.stringify(error));\n });\n this.log.debug(JSON.stringify(status));\n this.json2iob.parse(deviceId, status);\n if (this.deviceObjects[deviceId].stok === undefined) {\n this.log.error(\"No stok found for: \" + deviceId + \" Ingore device until next restart\");\n\n delete this.deviceObjects[deviceId];\n }\n continue;\n }\n if (!this.deviceObjects[deviceId]._connected) {\n continue;\n }\n\n this.deviceObjects[deviceId]\n .getDeviceInfo(true)\n .then(async (sysInfo: any) => {\n this.log.debug(JSON.stringify(sysInfo));\n if (!sysInfo || sysInfo.name === \"Error\" || sysInfo.request) {\n this.log.debug(\"Malformed response sysinfo\");\n // this.log.error(JSON.stringify(sysInfo));\n return;\n }\n await this.json2iob.parse(deviceId, sysInfo);\n if (this.deviceObjects[deviceId].getEnergyUsage) {\n this.log.debug(\"Receive energy usage\");\n const energyUsage = await this.deviceObjects[deviceId].getEnergyUsage();\n this.log.debug(JSON.stringify(energyUsage));\n if (energyUsage.request) {\n this.log.error(\"Malformed response getEnergyUsage\");\n this.log.error(JSON.stringify(energyUsage));\n return;\n }\n await this.json2iob.parse(deviceId, energyUsage);\n const power_usage = this.deviceObjects[deviceId].getPowerConsumption();\n if (power_usage.request) {\n this.log.error(\"Malformed response getPowerConsumption\");\n this.log.error(JSON.stringify(power_usage));\n return;\n }\n await this.json2iob.parse(deviceId, power_usage);\n }\n })\n .catch((error: any) => {\n this.log.error(`Get Device Info failed for ${deviceId} - ${error}`);\n });\n }\n this.log.debug(\"Update done\");\n } catch (error: any) {\n this.log.warn(error);\n }\n }\n\n isBase64(str: string): boolean {\n if (str === \"\" || str.trim() === \"\") {\n return false;\n }\n try {\n const strWithoutPadding = str.replace(/=*$/, \"\");\n return btoa(atob(strWithoutPadding)) === strWithoutPadding || btoa(atob(str)) === str;\n } catch (err) {\n return false;\n }\n }\n async sleep(ms: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, ms));\n }\n async refreshToken(): Promise<void> {\n this.log.debug(\"Refresh token\");\n }\n /**\n * Is called when adapter shuts down - callback has to be called under any circumstances!\n */\n private onUnload(callback: () => void): void {\n try {\n this.setState(\"info.connection\", false, true);\n this.refreshTimeout && clearTimeout(this.refreshTimeout);\n this.reLoginTimeout && clearTimeout(this.reLoginTimeout);\n this.refreshTokenTimeout && clearTimeout(this.refreshTokenTimeout);\n this.updateInterval && clearInterval(this.updateInterval);\n this.refreshTokenInterval && clearInterval(this.refreshTokenInterval);\n\n callback();\n } catch (e) {\n callback();\n }\n }\n\n /**\n * Is called if a subscribed state changes\n */\n private async onStateChange(id: string, state: ioBroker.State | null | undefined): Promise<void> {\n if (state) {\n if (!state.ack) {\n const deviceId = id.split(\".\")[2];\n const command = id.split(\".\")[4];\n if (id.split(\".\")[3] !== \"remote\") {\n return;\n }\n\n if (command === \"Refresh\") {\n this.deviceObjects[deviceId]\n .getDeviceInfo(true)\n .then((sysInfo: any) => {\n this.log.debug(JSON.stringify(sysInfo));\n this.json2iob.parse(deviceId, sysInfo);\n })\n .catch((error) => {\n this.log.error(`Get Device Info failed for ${deviceId} - ${error}`);\n });\n\n return;\n }\n try {\n if (this.deviceObjects[deviceId] && this.deviceObjects[deviceId][command]) {\n let result;\n if (command === \"setColor\" || command === \"moveMotor\") {\n const valueSplit = state.val.replace(\" \", \"\").split(\",\");\n result = await this.deviceObjects[deviceId][command](valueSplit[0], valueSplit[1]);\n } else {\n result = await this.deviceObjects[deviceId][command](state.val);\n }\n this.log.info(\n command + \" was set to : \" + state.val + \" for device \" + deviceId + \" was successful: \" + JSON.stringify(result),\n );\n this.refreshTimeout && clearTimeout(this.refreshTimeout);\n this.refreshTimeout = setTimeout(async () => {\n this.updateDevices();\n }, 2 * 1000);\n } else {\n this.log.error(`Device ${deviceId} has no command ${command}`);\n }\n } catch (error) {\n this.log.error(error);\n }\n } else {\n const resultDict = { device_on: \"setPowerState\" };\n const idArray = id.split(\".\");\n const stateName = idArray[idArray.length - 1];\n const deviceId = id.split(\".\")[2];\n if (resultDict[stateName]) {\n await this.setState(deviceId + \".remote.\" + resultDict[stateName], state.val, true);\n }\n }\n }\n }\n}\n\nif (require.main !== module) {\n // Export the constructor in compact mode\n module.exports = (options: Partial<utils.AdapterOptions> | undefined) => new Tapo(options);\n} else {\n // otherwise start the instance directly\n (() => new Tapo())();\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["Json2iob", "axios", "https", "crypto", "uuidv4", "body", "path", "md5", "content", "signature", "res", "_a", "_b", "P100", "P110", "L530", "L510E", "L520E"]
|
|
7
7
|
}
|
package/io-package.json
CHANGED
|
@@ -1,76 +1,98 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "tapo",
|
|
4
|
-
"version": "0.4.
|
|
4
|
+
"version": "0.4.2",
|
|
5
5
|
"news": {
|
|
6
|
-
"0.4.
|
|
7
|
-
"en": "
|
|
8
|
-
"de": "
|
|
9
|
-
"ru": "
|
|
10
|
-
"pt": "
|
|
11
|
-
"nl": "
|
|
12
|
-
"fr": "
|
|
13
|
-
"it": "
|
|
14
|
-
"es": "
|
|
15
|
-
"pl": "
|
|
16
|
-
"uk": "
|
|
17
|
-
"zh-cn": "
|
|
6
|
+
"0.4.2": {
|
|
7
|
+
"en": "fix handshake for device with HW v1.20",
|
|
8
|
+
"de": "handshake für Gerät mit HW v1.20",
|
|
9
|
+
"ru": "исправить рукопожатие для устройства с HW v1.20",
|
|
10
|
+
"pt": "corrigir aperto de mão para dispositivo com HW v1.20",
|
|
11
|
+
"nl": "fix handshake voor apparaat met HW v1.20",
|
|
12
|
+
"fr": "fixer la poignée de main pour l'appareil avec HW v1.20",
|
|
13
|
+
"it": "fix handshake per dispositivo con HW v1.20",
|
|
14
|
+
"es": "fijar apretón de manos para el dispositivo con HW v1.20",
|
|
15
|
+
"pl": "naprawić uścisk dłoni dla urządzenia z HW v1.20",
|
|
16
|
+
"uk": "закріпити запіканка для пристрою з HW v1.20",
|
|
17
|
+
"zh-cn": "以 HW v1. 20 为设备固定握手方式"
|
|
18
18
|
},
|
|
19
|
-
"0.
|
|
20
|
-
"en": "
|
|
21
|
-
"de": "
|
|
22
|
-
"ru": "
|
|
23
|
-
"pt": "
|
|
24
|
-
"nl": "
|
|
25
|
-
"fr": "
|
|
26
|
-
"it": "
|
|
27
|
-
"es": "
|
|
28
|
-
"pl": "
|
|
29
|
-
"uk": "
|
|
30
|
-
"zh-cn": "
|
|
19
|
+
"0.4.2-beta.8": {
|
|
20
|
+
"en": "improve handshake for old devices",
|
|
21
|
+
"de": "handshake für alte geräte verbessern",
|
|
22
|
+
"ru": "улучшить рукопожатие для старых устройств",
|
|
23
|
+
"pt": "melhorar o aperto de mão para dispositivos antigos",
|
|
24
|
+
"nl": "verbetering van de handdruk voor oude apparaten",
|
|
25
|
+
"fr": "améliorer la poignée de main pour les anciens appareils",
|
|
26
|
+
"it": "migliorare la stretta di mano per i vecchi dispositivi",
|
|
27
|
+
"es": "mejorar el apretón de manos para dispositivos antiguos",
|
|
28
|
+
"pl": "poprawić uścisk dłoni dla starych urządzeń",
|
|
29
|
+
"uk": "поліпшити хек для старих пристроїв",
|
|
30
|
+
"zh-cn": "改进旧设备的握手方式"
|
|
31
31
|
},
|
|
32
|
-
"0.
|
|
33
|
-
"en": "
|
|
34
|
-
"de": "
|
|
35
|
-
"ru": "
|
|
36
|
-
"pt": "
|
|
37
|
-
"nl": "
|
|
38
|
-
"fr": "
|
|
39
|
-
"it": "
|
|
40
|
-
"es": "
|
|
41
|
-
"pl": "
|
|
42
|
-
"uk": "
|
|
43
|
-
"zh-cn": "
|
|
32
|
+
"0.4.2-beta.7": {
|
|
33
|
+
"en": "improve handshake for old devices",
|
|
34
|
+
"de": "handshake für alte geräte verbessern",
|
|
35
|
+
"ru": "улучшить рукопожатие для старых устройств",
|
|
36
|
+
"pt": "melhorar o aperto de mão para dispositivos antigos",
|
|
37
|
+
"nl": "verbetering van de handdruk voor oude apparaten",
|
|
38
|
+
"fr": "améliorer la poignée de main pour les anciens appareils",
|
|
39
|
+
"it": "migliorare la stretta di mano per i vecchi dispositivi",
|
|
40
|
+
"es": "mejorar el apretón de manos para dispositivos antiguos",
|
|
41
|
+
"pl": "poprawić uścisk dłoni dla starych urządzeń",
|
|
42
|
+
"uk": "поліпшити хек для старих пристроїв",
|
|
43
|
+
"zh-cn": "改进旧设备的握手方式"
|
|
44
44
|
},
|
|
45
|
-
"0.
|
|
46
|
-
"en": "
|
|
47
|
-
"de": "
|
|
48
|
-
"ru": "
|
|
49
|
-
"pt": "
|
|
50
|
-
"nl": "
|
|
51
|
-
"fr": "
|
|
52
|
-
"it": "
|
|
53
|
-
"es": "
|
|
54
|
-
"pl": "
|
|
55
|
-
"uk": "
|
|
56
|
-
"zh-cn": "
|
|
45
|
+
"0.4.2-beta.6": {
|
|
46
|
+
"en": "improve handshake for old devices",
|
|
47
|
+
"de": "handshake für alte geräte verbessern",
|
|
48
|
+
"ru": "улучшить рукопожатие для старых устройств",
|
|
49
|
+
"pt": "melhorar o aperto de mão para dispositivos antigos",
|
|
50
|
+
"nl": "verbetering van de handdruk voor oude apparaten",
|
|
51
|
+
"fr": "améliorer la poignée de main pour les anciens appareils",
|
|
52
|
+
"it": "migliorare la stretta di mano per i vecchi dispositivi",
|
|
53
|
+
"es": "mejorar el apretón de manos para dispositivos antiguos",
|
|
54
|
+
"pl": "poprawić uścisk dłoni dla starych urządzeń",
|
|
55
|
+
"uk": "поліпшити хек для старих пристроїв",
|
|
56
|
+
"zh-cn": "改进旧设备的握手方式"
|
|
57
57
|
},
|
|
58
|
-
"0.2.
|
|
59
|
-
"en": "
|
|
60
|
-
"de": "
|
|
61
|
-
"ru": "
|
|
62
|
-
"pt": "
|
|
63
|
-
"nl": "
|
|
64
|
-
"fr": "
|
|
65
|
-
"it": "
|
|
66
|
-
"es": "
|
|
67
|
-
"pl": "
|
|
68
|
-
"uk": "
|
|
69
|
-
"zh-cn": "
|
|
58
|
+
"0.4.2-beta.5": {
|
|
59
|
+
"en": "improve handshake for old devices",
|
|
60
|
+
"de": "handshake für alte geräte verbessern",
|
|
61
|
+
"ru": "улучшить рукопожатие для старых устройств",
|
|
62
|
+
"pt": "melhorar o aperto de mão para dispositivos antigos",
|
|
63
|
+
"nl": "verbetering van de handdruk voor oude apparaten",
|
|
64
|
+
"fr": "améliorer la poignée de main pour les anciens appareils",
|
|
65
|
+
"it": "migliorare la stretta di mano per i vecchi dispositivi",
|
|
66
|
+
"es": "mejorar el apretón de manos para dispositivos antiguos",
|
|
67
|
+
"pl": "poprawić uścisk dłoni dla starych urządzeń",
|
|
68
|
+
"uk": "поліпшити хек для старих пристроїв",
|
|
69
|
+
"zh-cn": "改进旧设备的握手方式"
|
|
70
70
|
},
|
|
71
|
-
"0.2.
|
|
72
|
-
"en": "
|
|
73
|
-
"de": "
|
|
71
|
+
"0.4.2-beta.4": {
|
|
72
|
+
"en": "improve handshake for old devices",
|
|
73
|
+
"de": "handshake für alte geräte verbessern",
|
|
74
|
+
"ru": "улучшить рукопожатие для старых устройств",
|
|
75
|
+
"pt": "melhorar o aperto de mão para dispositivos antigos",
|
|
76
|
+
"nl": "verbetering van de handdruk voor oude apparaten",
|
|
77
|
+
"fr": "améliorer la poignée de main pour les anciens appareils",
|
|
78
|
+
"it": "migliorare la stretta di mano per i vecchi dispositivi",
|
|
79
|
+
"es": "mejorar el apretón de manos para dispositivos antiguos",
|
|
80
|
+
"pl": "poprawić uścisk dłoni dla starych urządzeń",
|
|
81
|
+
"uk": "поліпшити хек для старих пристроїв",
|
|
82
|
+
"zh-cn": "改进旧设备的握手方式"
|
|
83
|
+
},
|
|
84
|
+
"0.4.2-beta.3": {
|
|
85
|
+
"en": "improve handshake for old devices",
|
|
86
|
+
"de": "handshake für alte geräte verbessern",
|
|
87
|
+
"ru": "улучшить рукопожатие для старых устройств",
|
|
88
|
+
"pt": "melhorar o aperto de mão para dispositivos antigos",
|
|
89
|
+
"nl": "verbetering van de handdruk voor oude apparaten",
|
|
90
|
+
"fr": "améliorer la poignée de main pour les anciens appareils",
|
|
91
|
+
"it": "migliorare la stretta di mano per i vecchi dispositivi",
|
|
92
|
+
"es": "mejorar el apretón de manos para dispositivos antiguos",
|
|
93
|
+
"pl": "poprawić uścisk dłoni dla starych urządzeń",
|
|
94
|
+
"uk": "поліпшити хек для старих пристроїв",
|
|
95
|
+
"zh-cn": "改进旧设备的握手方式"
|
|
74
96
|
}
|
|
75
97
|
},
|
|
76
98
|
"titleLang": {
|
|
@@ -97,8 +119,13 @@
|
|
|
97
119
|
"pl": "Adapter do TP-Link Tapo",
|
|
98
120
|
"zh-cn": "TP-Link Tapo 适配器"
|
|
99
121
|
},
|
|
100
|
-
"authors": [
|
|
101
|
-
|
|
122
|
+
"authors": [
|
|
123
|
+
"TA2k <tombox2020@gmail.com>"
|
|
124
|
+
],
|
|
125
|
+
"keywords": [
|
|
126
|
+
"tp-link",
|
|
127
|
+
"tapo"
|
|
128
|
+
],
|
|
102
129
|
"license": "MIT",
|
|
103
130
|
"platform": "Javascript/Node.js",
|
|
104
131
|
"main": "build/main.js",
|
|
@@ -132,8 +159,12 @@
|
|
|
132
159
|
}
|
|
133
160
|
]
|
|
134
161
|
},
|
|
135
|
-
"encryptedNative": [
|
|
136
|
-
|
|
162
|
+
"encryptedNative": [
|
|
163
|
+
"password"
|
|
164
|
+
],
|
|
165
|
+
"protectedNative": [
|
|
166
|
+
"password"
|
|
167
|
+
],
|
|
137
168
|
"native": {
|
|
138
169
|
"username": "",
|
|
139
170
|
"password": "",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.tapo",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.2",
|
|
4
4
|
"description": "Adapter for TP-Link Tapo",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "TA2k",
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
"@alcalzone/release-script-plugin-iobroker": "^3.7.2",
|
|
22
22
|
"@alcalzone/release-script-plugin-license": "^3.7.0",
|
|
23
23
|
"@alcalzone/release-script-plugin-manual-review": "^3.7.0",
|
|
24
|
-
"@iobroker/adapter-core": "^3.2.
|
|
24
|
+
"@iobroker/adapter-core": "^3.2.3",
|
|
25
25
|
"@iobroker/testing": "^5.0.0",
|
|
26
|
-
"axios": "^
|
|
26
|
+
"axios": "^0.29.0",
|
|
27
27
|
"json-bigint": "^1.0.0",
|
|
28
28
|
"json2iob": "^2.6.12",
|
|
29
29
|
"node-fetch": "^2.7.0",
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@eslint/eslintrc": "^3.2.0",
|
|
38
|
-
"@eslint/js": "^9.
|
|
38
|
+
"@eslint/js": "^9.16.0",
|
|
39
39
|
"@iobroker/testing": "^5.0.0",
|
|
40
40
|
"@types/chai-as-promised": "^8.0.1",
|
|
41
41
|
"@types/json-bigint": "^1.0.4",
|
|
@@ -43,18 +43,18 @@
|
|
|
43
43
|
"@types/proxyquire": "^1.3.31",
|
|
44
44
|
"@types/utf8": "^3.0.3",
|
|
45
45
|
"@types/uuid": "^10.0.0",
|
|
46
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
47
|
-
"@typescript-eslint/parser": "^8.
|
|
48
|
-
"eslint": "^9.
|
|
46
|
+
"@typescript-eslint/eslint-plugin": "^8.17.0",
|
|
47
|
+
"@typescript-eslint/parser": "^8.17.0",
|
|
48
|
+
"eslint": "^9.16.0",
|
|
49
49
|
"eslint-config-prettier": "^9.1.0",
|
|
50
50
|
"eslint-plugin-prettier": "^5.2.1",
|
|
51
|
-
"globals": "^15.
|
|
52
|
-
"prettier": "^3.4.
|
|
51
|
+
"globals": "^15.13.0",
|
|
52
|
+
"prettier": "^3.4.2",
|
|
53
53
|
"proxyquire": "^2.1.3",
|
|
54
54
|
"source-map-support": "^0.5.21",
|
|
55
55
|
"ts-node": "^10.9.2",
|
|
56
56
|
"typescript": "~5.7.2",
|
|
57
|
-
"typescript-eslint": "^8.
|
|
57
|
+
"typescript-eslint": "^8.17.0"
|
|
58
58
|
},
|
|
59
59
|
"main": "build/main.js",
|
|
60
60
|
"files": [
|