iobroker.tapo 0.2.2 → 0.2.5

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 CHANGED
@@ -6,7 +6,6 @@
6
6
  [![Downloads](https://img.shields.io/npm/dm/iobroker.tapo.svg)](https://www.npmjs.com/package/iobroker.tapo)
7
7
  ![Number of Installations](https://iobroker.live/badges/tapo-installed.svg)
8
8
  ![Current version in stable repository](https://iobroker.live/badges/tapo-stable.svg)
9
- [![Dependency Status](https://img.shields.io/david/TA2k/iobroker.tapo.svg)](https://david-dm.org/TA2k/iobroker.tapo)
10
9
 
11
10
  [![NPM](https://nodei.co/npm/iobroker.tapo.png?downloads=true)](https://nodei.co/npm/iobroker.tapo/)
12
11
 
@@ -32,6 +31,12 @@ tapo.0.id.remote auf true/false setzen steuert den jeweiligen Befehl. Der Befehl
32
31
 
33
32
  <https://forum.iobroker.net/topic/57336/test-adapter-tp-link-tapo/>
34
33
 
34
+ ## Changelog
35
+
36
+ ### 0.0.2
37
+
38
+ - (TA2k) initial release
39
+
35
40
  ## License
36
41
 
37
42
  MIT License
@@ -39,7 +39,7 @@ class TAPOCamera extends import_onvifCamera.OnvifCamera {
39
39
  this.log = log;
40
40
  this.config = config;
41
41
  this.kStreamPort = 554;
42
- this.passwordEncryptionMethod = null;
42
+ this.passwordEncryptionMethod = "md5";
43
43
  this.isSecureConnectionValue = null;
44
44
  this.loginRetryCount = 0;
45
45
  this.pendingAPIRequests = /* @__PURE__ */ new Map();
@@ -73,7 +73,7 @@ class TAPOCamera extends import_onvifCamera.OnvifCamera {
73
73
  } else if (this.passwordEncryptionMethod === "sha256") {
74
74
  return this.hashedSha256Password;
75
75
  } else {
76
- throw new Error("Unknown password encryption method");
76
+ throw new Error("Unknown password encryption method " + this.passwordEncryptionMethod + "!");
77
77
  }
78
78
  }
79
79
  fetch(url, data) {
@@ -148,42 +148,40 @@ class TAPOCamera extends import_onvifCamera.OnvifCamera {
148
148
  throw new Error("Invalid credentials");
149
149
  }
150
150
  }
151
- if (isSecureConnection) {
152
- this.log.debug("StokRefresh: Using secure connection");
153
- const nonce = (_d = (_c = responseData == null ? void 0 : responseData.result) == null ? void 0 : _c.data) == null ? void 0 : _d.nonce;
154
- const deviceConfirm = (_f = (_e = responseData == null ? void 0 : responseData.result) == null ? void 0 : _e.data) == null ? void 0 : _f.device_confirm;
155
- if (nonce && deviceConfirm && this.validateDeviceConfirm(nonce, deviceConfirm)) {
156
- const digestPasswd = import_crypto.default.createHash("sha256").update(this.getHashedPassword() + this.cnonce + nonce).digest("hex").toUpperCase();
157
- const digestPasswdFull = Buffer.concat([
158
- Buffer.from(digestPasswd, "utf8"),
159
- Buffer.from(this.cnonce, "utf8"),
160
- Buffer.from(nonce, "utf8")
161
- ]).toString("utf8");
162
- response = await this.fetch(`https://${this.config.ipAddress}`, {
163
- method: "POST",
164
- body: JSON.stringify({
165
- method: "login",
166
- params: {
167
- cnonce: this.cnonce,
168
- encrypt_type: "3",
169
- digest_passwd: digestPasswdFull,
170
- username: this.getUsername()
171
- }
172
- })
173
- });
174
- responseData = await response.json();
175
- this.log.debug("StokRefresh: Start_seq response :>>" + response.status + JSON.stringify(responseData));
176
- if ((_g = responseData == null ? void 0 : responseData.result) == null ? void 0 : _g.start_seq) {
177
- if (((_h = responseData == null ? void 0 : responseData.result) == null ? void 0 : _h.user_group) !== "root") {
178
- throw new Error("Incorrect user_group detected");
151
+ const nonce = (_d = (_c = responseData == null ? void 0 : responseData.result) == null ? void 0 : _c.data) == null ? void 0 : _d.nonce;
152
+ const deviceConfirm = (_f = (_e = responseData == null ? void 0 : responseData.result) == null ? void 0 : _e.data) == null ? void 0 : _f.device_confirm;
153
+ if (isSecureConnection && nonce && deviceConfirm) {
154
+ if (!this.validateDeviceConfirm(nonce, deviceConfirm)) {
155
+ throw new Error("Invalid device confirm");
156
+ }
157
+ const digestPasswd = import_crypto.default.createHash("sha256").update(this.getHashedPassword() + this.cnonce + nonce).digest("hex").toUpperCase();
158
+ const digestPasswdFull = Buffer.concat([
159
+ Buffer.from(digestPasswd, "utf8"),
160
+ Buffer.from(this.cnonce, "utf8"),
161
+ Buffer.from(nonce, "utf8")
162
+ ]).toString("utf8");
163
+ response = await this.fetch(`https://${this.config.ipAddress}`, {
164
+ method: "POST",
165
+ body: JSON.stringify({
166
+ method: "login",
167
+ params: {
168
+ cnonce: this.cnonce,
169
+ encrypt_type: "3",
170
+ digest_passwd: digestPasswdFull,
171
+ username: this.getUsername()
179
172
  }
180
- this.lsk = this.generateEncryptionToken("lsk", nonce);
181
- this.ivb = this.generateEncryptionToken("ivb", nonce);
182
- this.seq = responseData.result.start_seq;
173
+ })
174
+ });
175
+ responseData = await response.json();
176
+ this.log.debug("StokRefresh: Start_seq response :>>", response.status, JSON.stringify(responseData));
177
+ if ((_g = responseData == null ? void 0 : responseData.result) == null ? void 0 : _g.start_seq) {
178
+ if (((_h = responseData == null ? void 0 : responseData.result) == null ? void 0 : _h.user_group) !== "root") {
179
+ throw new Error("Incorrect user_group detected");
183
180
  }
181
+ this.lsk = this.generateEncryptionToken("lsk", nonce);
182
+ this.ivb = this.generateEncryptionToken("ivb", nonce);
183
+ this.seq = responseData.result.start_seq;
184
184
  }
185
- } else {
186
- this.passwordEncryptionMethod = "md5";
187
185
  }
188
186
  if (((_j = (_i = responseData == null ? void 0 : responseData.result) == null ? void 0 : _i.data) == null ? void 0 : _j.sec_left) > 0) {
189
187
  throw new Error(`StokRefresh: Temporary Suspension: Try again in ${responseData.result.data.sec_left} seconds`);
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/lib/utils/camera/tapoCamera.ts"],
4
- "sourcesContent": ["import fetch, { RequestInit } from \"node-fetch\";\nimport https, { Agent } from \"https\";\nimport crypto from \"crypto\";\nimport { OnvifCamera } from \"./onvifCamera\";\nimport type {\n TAPOCameraEncryptedRequest,\n TAPOCameraEncryptedResponse,\n TAPOCameraRequest,\n TAPOCameraResponse,\n TAPOCameraResponseDeviceInfo,\n TAPOCameraResponseGetAlert,\n TAPOCameraResponseGetLensMask,\n} from \"./types/tapo\";\n\nconst MAX_LOGIN_RETRIES = 3;\nconst AES_BLOCK_SIZE = 16;\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 disablePrivacyAccessory?: boolean;\n disableAlarmAccessory?: boolean;\n disableMotionAccessory?: boolean;\n lowQuality?: boolean;\n\n videoConfig?: VideoConfig;\n\n privacyAccessoryName?: string;\n alarmAccessoryName?: string;\n};\nexport class TAPOCamera extends OnvifCamera {\n private readonly kStreamPort = 554;\n private readonly httpsAgent: Agent;\n\n private readonly hashedMD5Password: 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<string>) | 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 private loginRetryCount = 0;\n\n constructor(\n protected readonly log: any,\n protected readonly config: CameraConfig,\n ) {\n super(log, config);\n this.log.debug(\"Constructing Camera on host: \" + config.ipAddress);\n\n this.httpsAgent = new https.Agent({\n rejectUnauthorized: false,\n });\n\n this.cnonce = this.generateCnonce();\n\n this.hashedMD5Password = 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() {\n const headers: Record<string, string> = {\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 return headers;\n }\n\n private getHashedPassword() {\n if (this.passwordEncryptionMethod === \"md5\") {\n return this.hashedMD5Password;\n } else if (this.passwordEncryptionMethod === \"sha256\") {\n return this.hashedSha256Password;\n } else {\n throw new Error(\"Unknown password encryption method\");\n }\n }\n\n private fetch(url: string, data: RequestInit) {\n return fetch(url, {\n agent: this.httpsAgent,\n headers: this.getHeaders(),\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 const hashedNoncesWithSHA256 = crypto\n .createHash(\"sha256\")\n .update(this.cnonce + this.hashedSha256Password + nonce)\n .digest(\"hex\")\n .toUpperCase();\n const hashedNoncesWithMD5 = crypto\n .createHash(\"md5\")\n .update(this.cnonce + this.hashedMD5Password + nonce)\n .digest(\"hex\")\n .toUpperCase();\n\n if (deviceConfirm === hashedNoncesWithSHA256 + nonce + this.cnonce) {\n this.passwordEncryptionMethod = \"sha256\";\n return true;\n }\n\n if (deviceConfirm === hashedNoncesWithMD5 + nonce + this.cnonce) {\n this.passwordEncryptionMethod = \"md5\";\n return true;\n }\n\n return false;\n }\n\n async refreshStok(loginRetryCount = 0): Promise<string> {\n const isSecureConnection = await this.isSecureConnection();\n\n let response = null;\n let responseData = null;\n\n let fetchParams = {};\n if (isSecureConnection) {\n this.log.debug(\"StokRefresh: Using secure connection\");\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 this.log.debug(\"StokRefresh: Using unsecure connection\");\n fetchParams = {\n method: \"post\",\n body: JSON.stringify({\n method: \"login\",\n params: {\n username: this.getUsername(),\n password: this.getHashedPassword(),\n hashed: true,\n },\n }),\n };\n }\n\n response = await this.fetch(`https://${this.config.ipAddress}`, fetchParams);\n responseData = await response.json();\n\n this.log.debug(\"StokRefresh: Login response :>> \" + response.status + JSON.stringify(responseData));\n\n if (response.status === 401) {\n if (responseData?.result?.data?.code === 40411) {\n throw new Error(\"Invalid credentials\");\n }\n }\n\n if (isSecureConnection) {\n this.log.debug(\"StokRefresh: Using secure connection\");\n const nonce = responseData?.result?.data?.nonce;\n const deviceConfirm = responseData?.result?.data?.device_confirm;\n\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 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();\n\n this.log.debug(\"StokRefresh: Start_seq response :>>\" + response.status + JSON.stringify(responseData));\n\n if (responseData?.result?.start_seq) {\n if (responseData?.result?.user_group !== \"root\") {\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 throw new 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 }\n } else {\n this.passwordEncryptionMethod = \"md5\";\n }\n\n if (responseData?.result?.data?.sec_left > 0) {\n throw new Error(`StokRefresh: Temporary Suspension: Try again in ${responseData.result.data.sec_left} seconds`);\n }\n\n if (responseData?.data?.code == -40404 && responseData?.data?.sec_left > 0) {\n throw new Error(`StokRefresh: 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(\"StokRefresh: Success :>>\" + this.stok);\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this.stok!;\n }\n\n if (responseData?.error_code === -40413 && loginRetryCount < MAX_LOGIN_RETRIES) {\n this.log.debug(\n `Unexpected response, retrying: ${loginRetryCount}/${MAX_LOGIN_RETRIES}.` + response.status + JSON.stringify(responseData),\n );\n return this.refreshStok(loginRetryCount + 1);\n }\n\n throw new Error(\"Invalid authentication data\");\n }\n\n async isSecureConnection() {\n if (this.isSecureConnectionValue === null) {\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 this.log.debug(JSON.stringify(response));\n const json = await response.json();\n\n this.log.debug(\"isSecureConnection response :>> \" + response.status + json);\n\n this.isSecureConnectionValue = json.error_code == -40413 && json?.result?.data?.encrypt_type?.includes(\"3\");\n }\n\n return this.isSecureConnectionValue;\n }\n\n getStok(loginRetryCount = 0): Promise<string> {\n if (this.stok) {\n return new Promise((resolve) => resolve(this.stok!));\n }\n\n if (!this.stokPromise) {\n this.stokPromise = () => this.refreshStok(loginRetryCount);\n }\n\n return this.stokPromise()\n .then(() => {\n return this.stok!;\n })\n .finally(() => {\n this.stokPromise = undefined;\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 throw new Error(\"Invalid padding\");\n }\n for (let i = text.length - paddingLength; i < text.length; i++) {\n if (text.charCodeAt(i) !== paddingLength) {\n throw new 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 return this.pendingAPIRequests.get(reqJson) as Promise<TAPOCameraResponse>;\n }\n\n this.log.debug(\"API new request: \" + reqJson);\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 let json = await response.json();\n\n if (isSecureConnection) {\n const encryptedResponse = json as TAPOCameraEncryptedResponse;\n if (encryptedResponse.result.response) {\n const decryptedResponse = this.decryptResponse(encryptedResponse.result.response);\n json = JSON.parse(decryptedResponse) as TAPOCameraResponse;\n }\n } else {\n json = json as TAPOCameraResponse;\n }\n\n this.log.debug(`API response: ` + response.status, JSON.stringify(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.stok = undefined;\n }\n\n // Check if we have to refresh the token\n if (json.error_code === -40401 || json.error_code === -1) {\n this.log.debug(\"API request failed, reauthenticating\");\n this.stok = undefined;\n return this.apiRequest(req, loginRetryCount + 1);\n }\n\n return json as TAPOCameraResponse;\n } finally {\n this.pendingAPIRequests.delete(reqJson);\n }\n })(),\n );\n\n return this.pendingAPIRequests.get(reqJson) as Promise<TAPOCameraResponse>;\n }\n\n async setLensMaskConfig(value: boolean) {\n this.adapter.log.debug(\"Processing setLensMaskConfig\" + value);\n\n const json = await this.apiRequest({\n method: \"multipleRequest\",\n params: {\n requests: [\n {\n method: \"setLensMaskConfig\",\n params: {\n lens_mask: {\n lens_mask_info: {\n enabled: value ? \"on\" : \"off\",\n },\n },\n },\n },\n ],\n },\n });\n\n if (json.error_code !== 0) {\n throw new Error(\"Failed to perform action\");\n }\n }\n\n async setAlertConfig(value: boolean) {\n this.log.debug(\"Processing setAlertConfig\" + value);\n\n const json = await this.apiRequest({\n method: \"multipleRequest\",\n params: {\n requests: [\n {\n method: \"setAlertConfig\",\n params: {\n msg_alarm: {\n chn1_msg_alarm_info: {\n enabled: value ? \"on\" : \"off\",\n },\n },\n },\n },\n ],\n },\n });\n\n return json.error_code !== 0;\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 async getBasicInfo() {\n const json = 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 = json.result.responses[0] as TAPOCameraResponseDeviceInfo;\n return info.result.device_info.basic_info;\n }\n\n async getStatus(): Promise<{ lensMask: boolean; alert: boolean }> {\n const json = 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: \"getForceWhitelampState\",\n params: {\n image: {\n name: \"switch\",\n },\n },\n },\n ],\n },\n });\n this.log.debug(`getStatus json: ${JSON.stringify(json)}`);\n if (json.error_code !== 0) {\n throw new Error(\"Camera replied with error\");\n }\n if (!json.result.responses) {\n throw new Error(\"Camera replied with invalid response\");\n }\n const alertConfig = json.result.responses.find((r) => r.method === \"getAlertConfig\") as TAPOCameraResponseGetAlert;\n\n const forceWhitelampState = json.result.responses.find((r) => r.method === \"getForceWhitelampState\") as TAPOCameraResponseGetForce;\n const lensMaskConfig = json.result.responses.find((r) => r.method === \"getLensMaskConfig\") as TAPOCameraResponseGetLensMask;\n\n return {\n alert: alertConfig.result.msg_alarm.chn1_msg_alarm_info.enabled === \"on\",\n lensMask: lensMaskConfig.result.lens_mask.lens_mask_info.enabled === \"on\",\n forceWhiteLamp: forceWhitelampState.result.image ? forceWhitelampState.result.image.switch.force_wtl_state === \"on\" : false,\n };\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import fetch, { RequestInit } from \"node-fetch\";\nimport https, { Agent } from \"https\";\nimport crypto from \"crypto\";\nimport { OnvifCamera } from \"./onvifCamera\";\nimport type {\n TAPOCameraEncryptedRequest,\n TAPOCameraEncryptedResponse,\n TAPOCameraRequest,\n TAPOCameraResponse,\n TAPOCameraResponseDeviceInfo,\n TAPOCameraResponseGetAlert,\n TAPOCameraResponseGetLensMask,\n} from \"./types/tapo\";\n\nconst MAX_LOGIN_RETRIES = 3;\nconst AES_BLOCK_SIZE = 16;\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 disablePrivacyAccessory?: boolean;\n disableAlarmAccessory?: boolean;\n disableMotionAccessory?: boolean;\n lowQuality?: boolean;\n\n videoConfig?: VideoConfig;\n\n privacyAccessoryName?: string;\n alarmAccessoryName?: string;\n};\nexport class TAPOCamera extends OnvifCamera {\n private readonly kStreamPort = 554;\n private readonly httpsAgent: Agent;\n\n private readonly hashedMD5Password: string;\n private readonly hashedSha256Password: string;\n private passwordEncryptionMethod: \"md5\" | \"sha256\" | null = \"md5\";\n\n private isSecureConnectionValue: boolean | null = null;\n\n private stokPromise: (() => Promise<string>) | 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 private loginRetryCount = 0;\n\n constructor(\n protected readonly log: any,\n protected readonly config: CameraConfig,\n ) {\n super(log, config);\n this.log.debug(\"Constructing Camera on host: \" + config.ipAddress);\n\n this.httpsAgent = new https.Agent({\n rejectUnauthorized: false,\n });\n\n this.cnonce = this.generateCnonce();\n\n this.hashedMD5Password = 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() {\n const headers: Record<string, string> = {\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 return headers;\n }\n\n private getHashedPassword() {\n if (this.passwordEncryptionMethod === \"md5\") {\n return this.hashedMD5Password;\n } else if (this.passwordEncryptionMethod === \"sha256\") {\n return this.hashedSha256Password;\n } else {\n throw new Error(\"Unknown password encryption method \" + this.passwordEncryptionMethod + \"!\");\n }\n }\n\n private fetch(url: string, data: RequestInit) {\n return fetch(url, {\n agent: this.httpsAgent,\n headers: this.getHeaders(),\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 const hashedNoncesWithSHA256 = crypto\n .createHash(\"sha256\")\n .update(this.cnonce + this.hashedSha256Password + nonce)\n .digest(\"hex\")\n .toUpperCase();\n const hashedNoncesWithMD5 = crypto\n .createHash(\"md5\")\n .update(this.cnonce + this.hashedMD5Password + nonce)\n .digest(\"hex\")\n .toUpperCase();\n\n if (deviceConfirm === hashedNoncesWithSHA256 + nonce + this.cnonce) {\n this.passwordEncryptionMethod = \"sha256\";\n return true;\n }\n\n if (deviceConfirm === hashedNoncesWithMD5 + nonce + this.cnonce) {\n this.passwordEncryptionMethod = \"md5\";\n return true;\n }\n\n return false;\n }\n\n async refreshStok(loginRetryCount = 0): Promise<string> {\n const isSecureConnection = await this.isSecureConnection();\n\n let response = null;\n let responseData = null;\n\n let fetchParams = {};\n if (isSecureConnection) {\n this.log.debug(\"StokRefresh: Using secure connection\");\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 this.log.debug(\"StokRefresh: Using unsecure connection\");\n fetchParams = {\n method: \"post\",\n body: JSON.stringify({\n method: \"login\",\n params: {\n username: this.getUsername(),\n password: this.getHashedPassword(),\n hashed: true,\n },\n }),\n };\n }\n\n response = await this.fetch(`https://${this.config.ipAddress}`, fetchParams);\n responseData = await response.json();\n\n this.log.debug(\"StokRefresh: Login response :>> \" + response.status + JSON.stringify(responseData));\n\n if (response.status === 401) {\n if (responseData?.result?.data?.code === 40411) {\n throw new Error(\"Invalid credentials\");\n }\n }\n const nonce = responseData?.result?.data?.nonce;\n const deviceConfirm = responseData?.result?.data?.device_confirm;\n\n if (isSecureConnection && nonce && deviceConfirm) {\n if (!this.validateDeviceConfirm(nonce, deviceConfirm)) {\n throw new Error(\"Invalid device confirm\");\n }\n\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 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();\n\n this.log.debug(\"StokRefresh: Start_seq response :>>\", response.status, JSON.stringify(responseData));\n\n if (responseData?.result?.start_seq) {\n if (responseData?.result?.user_group !== \"root\") {\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 throw new 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 }\n\n if (responseData?.result?.data?.sec_left > 0) {\n throw new Error(`StokRefresh: Temporary Suspension: Try again in ${responseData.result.data.sec_left} seconds`);\n }\n\n if (responseData?.data?.code == -40404 && responseData?.data?.sec_left > 0) {\n throw new Error(`StokRefresh: 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(\"StokRefresh: Success :>>\" + this.stok);\n\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n return this.stok!;\n }\n\n if (responseData?.error_code === -40413 && loginRetryCount < MAX_LOGIN_RETRIES) {\n this.log.debug(\n `Unexpected response, retrying: ${loginRetryCount}/${MAX_LOGIN_RETRIES}.` + response.status + JSON.stringify(responseData),\n );\n return this.refreshStok(loginRetryCount + 1);\n }\n\n throw new Error(\"Invalid authentication data\");\n }\n\n async isSecureConnection() {\n if (this.isSecureConnectionValue === null) {\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 this.log.debug(JSON.stringify(response));\n const json = await response.json();\n\n this.log.debug(\"isSecureConnection response :>> \" + response.status + json);\n\n this.isSecureConnectionValue = json.error_code == -40413 && json?.result?.data?.encrypt_type?.includes(\"3\");\n }\n\n return this.isSecureConnectionValue;\n }\n\n getStok(loginRetryCount = 0): Promise<string> {\n if (this.stok) {\n return new Promise((resolve) => resolve(this.stok!));\n }\n\n if (!this.stokPromise) {\n this.stokPromise = () => this.refreshStok(loginRetryCount);\n }\n\n return this.stokPromise()\n .then(() => {\n return this.stok!;\n })\n .finally(() => {\n this.stokPromise = undefined;\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 throw new Error(\"Invalid padding\");\n }\n for (let i = text.length - paddingLength; i < text.length; i++) {\n if (text.charCodeAt(i) !== paddingLength) {\n throw new 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 return this.pendingAPIRequests.get(reqJson) as Promise<TAPOCameraResponse>;\n }\n\n this.log.debug(\"API new request: \" + reqJson);\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 let json = await response.json();\n\n if (isSecureConnection) {\n const encryptedResponse = json as TAPOCameraEncryptedResponse;\n if (encryptedResponse.result.response) {\n const decryptedResponse = this.decryptResponse(encryptedResponse.result.response);\n json = JSON.parse(decryptedResponse) as TAPOCameraResponse;\n }\n } else {\n json = json as TAPOCameraResponse;\n }\n\n this.log.debug(`API response: ` + response.status, JSON.stringify(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.stok = undefined;\n }\n\n // Check if we have to refresh the token\n if (json.error_code === -40401 || json.error_code === -1) {\n this.log.debug(\"API request failed, reauthenticating\");\n this.stok = undefined;\n return this.apiRequest(req, loginRetryCount + 1);\n }\n\n return json as TAPOCameraResponse;\n } finally {\n this.pendingAPIRequests.delete(reqJson);\n }\n })(),\n );\n\n return this.pendingAPIRequests.get(reqJson) as Promise<TAPOCameraResponse>;\n }\n\n async setLensMaskConfig(value: boolean) {\n this.adapter.log.debug(\"Processing setLensMaskConfig\" + value);\n\n const json = await this.apiRequest({\n method: \"multipleRequest\",\n params: {\n requests: [\n {\n method: \"setLensMaskConfig\",\n params: {\n lens_mask: {\n lens_mask_info: {\n enabled: value ? \"on\" : \"off\",\n },\n },\n },\n },\n ],\n },\n });\n\n if (json.error_code !== 0) {\n throw new Error(\"Failed to perform action\");\n }\n }\n\n async setAlertConfig(value: boolean) {\n this.log.debug(\"Processing setAlertConfig\" + value);\n\n const json = await this.apiRequest({\n method: \"multipleRequest\",\n params: {\n requests: [\n {\n method: \"setAlertConfig\",\n params: {\n msg_alarm: {\n chn1_msg_alarm_info: {\n enabled: value ? \"on\" : \"off\",\n },\n },\n },\n },\n ],\n },\n });\n\n return json.error_code !== 0;\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 async getBasicInfo() {\n const json = 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 = json.result.responses[0] as TAPOCameraResponseDeviceInfo;\n return info.result.device_info.basic_info;\n }\n\n async getStatus(): Promise<{ lensMask: boolean; alert: boolean }> {\n const json = 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: \"getForceWhitelampState\",\n params: {\n image: {\n name: \"switch\",\n },\n },\n },\n ],\n },\n });\n this.log.debug(`getStatus json: ${JSON.stringify(json)}`);\n if (json.error_code !== 0) {\n throw new Error(\"Camera replied with error\");\n }\n if (!json.result.responses) {\n throw new Error(\"Camera replied with invalid response\");\n }\n const alertConfig = json.result.responses.find((r) => r.method === \"getAlertConfig\") as TAPOCameraResponseGetAlert;\n\n const forceWhitelampState = json.result.responses.find((r) => r.method === \"getForceWhitelampState\") as TAPOCameraResponseGetForce;\n const lensMaskConfig = json.result.responses.find((r) => r.method === \"getLensMaskConfig\") as TAPOCameraResponseGetLensMask;\n\n return {\n alert: alertConfig.result.msg_alarm.chn1_msg_alarm_info.enabled === \"on\",\n lensMask: lensMaskConfig.result.lens_mask.lens_mask_info.enabled === \"on\",\n forceWhiteLamp: forceWhitelampState.result.image ? forceWhitelampState.result.image.switch.force_wtl_state === \"on\" : false,\n };\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,wBAAmC;AACnC,mBAA6B;AAC7B,oBAAmB;AACnB,yBAA4B;AAW5B,MAAM,oBAAoB;AAC1B,MAAM,iBAAiB;AAsBhB,MAAM,mBAAmB,+BAAY;AAAA,EAoB1C,YACqB,KACA,QACnB;AACA,UAAM,KAAK,MAAM;AAHE;AACA;AArBrB,SAAiB,cAAc;AAK/B,SAAQ,2BAAoD;AAE5D,SAAQ,0BAA0C;AAUlD,SAAQ,kBAAkB;AA2T1B,SAAQ,qBAA+D,oBAAI,IAAI;AApT7E,SAAK,IAAI,MAAM,kCAAkC,OAAO,SAAS;AAEjE,SAAK,aAAa,IAAI,aAAAA,QAAM,MAAM;AAAA,MAChC,oBAAoB;AAAA,IACtB,CAAC;AAED,SAAK,SAAS,KAAK,eAAe;AAElC,SAAK,oBAAoB,cAAAC,QAAO,WAAW,KAAK,EAAE,OAAO,OAAO,QAAQ,EAAE,OAAO,KAAK,EAAE,YAAY;AACpG,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,aAAa;AACnB,UAAM,UAAkC;AAAA,MACtC,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;AACA,WAAO;AAAA,EACT;AAAA,EAEQ,oBAAoB;AAC1B,QAAI,KAAK,6BAA6B,OAAO;AAC3C,aAAO,KAAK;AAAA,IACd,WAAW,KAAK,6BAA6B,UAAU;AACrD,aAAO,KAAK;AAAA,IACd,OAAO;AACL,YAAM,IAAI,MAAM,wCAAwC,KAAK,2BAA2B,GAAG;AAAA,IAC7F;AAAA,EACF;AAAA,EAEQ,MAAM,KAAa,MAAmB;AAC5C,eAAO,kBAAAC,SAAM,KAAK;AAAA,MAChB,OAAO,KAAK;AAAA,MACZ,SAAS,KAAK,WAAW;AAAA,MACzB,GAAG;AAAA,IACL,CAAC;AAAA,EACH;AAAA,EAEQ,wBAAwB,WAAmB,OAAuB;AACxE,UAAM,YAAY,cAAAD,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,UAAM,yBAAyB,cAAAA,QAC5B,WAAW,QAAQ,EACnB,OAAO,KAAK,SAAS,KAAK,uBAAuB,KAAK,EACtD,OAAO,KAAK,EACZ,YAAY;AACf,UAAM,sBAAsB,cAAAA,QACzB,WAAW,KAAK,EAChB,OAAO,KAAK,SAAS,KAAK,oBAAoB,KAAK,EACnD,OAAO,KAAK,EACZ,YAAY;AAEf,QAAI,kBAAkB,yBAAyB,QAAQ,KAAK,QAAQ;AAClE,WAAK,2BAA2B;AAChC,aAAO;AAAA,IACT;AAEA,QAAI,kBAAkB,sBAAsB,QAAQ,KAAK,QAAQ;AAC/D,WAAK,2BAA2B;AAChC,aAAO;AAAA,IACT;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,MAAM,YAAY,kBAAkB,GAAoB;AA7J1D;AA8JI,UAAM,qBAAqB,MAAM,KAAK,mBAAmB;AAEzD,QAAI,WAAW;AACf,QAAI,eAAe;AAEnB,QAAI,cAAc,CAAC;AACnB,QAAI,oBAAoB;AACtB,WAAK,IAAI,MAAM,sCAAsC;AACrD,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,WAAK,IAAI,MAAM,wCAAwC;AACvD,oBAAc;AAAA,QACZ,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU;AAAA,UACnB,QAAQ;AAAA,UACR,QAAQ;AAAA,YACN,UAAU,KAAK,YAAY;AAAA,YAC3B,UAAU,KAAK,kBAAkB;AAAA,YACjC,QAAQ;AAAA,UACV;AAAA,QACF,CAAC;AAAA,MACH;AAAA,IACF;AAEA,eAAW,MAAM,KAAK,MAAM,WAAW,KAAK,OAAO,aAAa,WAAW;AAC3E,mBAAe,MAAM,SAAS,KAAK;AAEnC,SAAK,IAAI,MAAM,qCAAqC,SAAS,SAAS,KAAK,UAAU,YAAY,CAAC;AAElG,QAAI,SAAS,WAAW,KAAK;AAC3B,YAAI,wDAAc,WAAd,mBAAsB,SAAtB,mBAA4B,UAAS,OAAO;AAC9C,cAAM,IAAI,MAAM,qBAAqB;AAAA,MACvC;AAAA,IACF;AACA,UAAM,SAAQ,wDAAc,WAAd,mBAAsB,SAAtB,mBAA4B;AAC1C,UAAM,iBAAgB,wDAAc,WAAd,mBAAsB,SAAtB,mBAA4B;AAElD,QAAI,sBAAsB,SAAS,eAAe;AAChD,UAAI,CAAC,KAAK,sBAAsB,OAAO,aAAa,GAAG;AACrD,cAAM,IAAI,MAAM,wBAAwB;AAAA,MAC1C;AAEA,YAAM,eAAe,cAAAA,QAClB,WAAW,QAAQ,EACnB,OAAO,KAAK,kBAAkB,IAAI,KAAK,SAAS,KAAK,EACrD,OAAO,KAAK,EACZ,YAAY;AAEf,YAAM,mBAAmB,OAAO,OAAO;AAAA,QACrC,OAAO,KAAK,cAAc,MAAM;AAAA,QAChC,OAAO,KAAK,KAAK,QAAS,MAAM;AAAA,QAChC,OAAO,KAAK,OAAO,MAAM;AAAA,MAC3B,CAAC,EAAE,SAAS,MAAM;AAElB,iBAAW,MAAM,KAAK,MAAM,WAAW,KAAK,OAAO,aAAa;AAAA,QAC9D,QAAQ;AAAA,QACR,MAAM,KAAK,UAAU;AAAA,UACnB,QAAQ;AAAA,UACR,QAAQ;AAAA,YACN,QAAQ,KAAK;AAAA,YACb,cAAc;AAAA,YACd,eAAe;AAAA,YACf,UAAU,KAAK,YAAY;AAAA,UAC7B;AAAA,QACF,CAAC;AAAA,MACH,CAAC;AAED,qBAAe,MAAM,SAAS,KAAK;AAEnC,WAAK,IAAI,MAAM,uCAAuC,SAAS,QAAQ,KAAK,UAAU,YAAY,CAAC;AAEnG,WAAI,kDAAc,WAAd,mBAAsB,WAAW;AACnC,cAAI,kDAAc,WAAd,mBAAsB,gBAAe,QAAQ;AAG/C,gBAAM,IAAI,MAAM,+BAA+B;AAAA,QACjD;AAEA,aAAK,MAAM,KAAK,wBAAwB,OAAO,KAAK;AACpD,aAAK,MAAM,KAAK,wBAAwB,OAAO,KAAK;AACpD,aAAK,MAAM,aAAa,OAAO;AAAA,MACjC;AAAA,IACF;AAEA,UAAI,wDAAc,WAAd,mBAAsB,SAAtB,mBAA4B,YAAW,GAAG;AAC5C,YAAM,IAAI,MAAM,mDAAmD,aAAa,OAAO,KAAK,kBAAkB;AAAA,IAChH;AAEA,UAAI,kDAAc,SAAd,mBAAoB,SAAQ,YAAU,kDAAc,SAAd,mBAAoB,YAAW,GAAG;AAC1E,YAAM,IAAI,MAAM,mDAAmD,aAAa,KAAK,kBAAkB;AAAA,IACzG;AAEA,SAAI,kDAAc,WAAd,mBAAsB,MAAM;AAC9B,WAAK,OAAO,aAAa,OAAO;AAChC,WAAK,IAAI,MAAM,6BAA6B,KAAK,IAAI;AAGrD,aAAO,KAAK;AAAA,IACd;AAEA,SAAI,6CAAc,gBAAe,UAAU,kBAAkB,mBAAmB;AAC9E,WAAK,IAAI;AAAA,QACP,kCAAkC,mBAAmB,uBAAuB,SAAS,SAAS,KAAK,UAAU,YAAY;AAAA,MAC3H;AACA,aAAO,KAAK,YAAY,kBAAkB,CAAC;AAAA,IAC7C;AAEA,UAAM,IAAI,MAAM,6BAA6B;AAAA,EAC/C;AAAA,EAEA,MAAM,qBAAqB;AAtR7B;AAuRI,QAAI,KAAK,4BAA4B,MAAM;AACzC,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,WAAK,IAAI,MAAM,KAAK,UAAU,QAAQ,CAAC;AACvC,YAAM,OAAO,MAAM,SAAS,KAAK;AAEjC,WAAK,IAAI,MAAM,qCAAqC,SAAS,SAAS,IAAI;AAE1E,WAAK,0BAA0B,KAAK,cAAc,YAAU,8CAAM,WAAN,mBAAc,SAAd,mBAAoB,iBAApB,mBAAkC,SAAS;AAAA,IACzG;AAEA,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,QAAQ,kBAAkB,GAAoB;AAC5C,QAAI,KAAK,MAAM;AACb,aAAO,IAAI,QAAQ,CAAC,YAAY,QAAQ,KAAK,IAAK,CAAC;AAAA,IACrD;AAEA,QAAI,CAAC,KAAK,aAAa;AACrB,WAAK,cAAc,MAAM,KAAK,YAAY,eAAe;AAAA,IAC3D;AAEA,WAAO,KAAK,YAAY,EACrB,KAAK,MAAM;AACV,aAAO,KAAK;AAAA,IACd,CAAC,EACA,QAAQ,MAAM;AACb,WAAK,cAAc;AAAA,IACrB,CAAC;AAAA,EACL;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,YAAM,IAAI,MAAM,iBAAiB;AAAA,IACnC;AACA,aAAS,IAAI,KAAK,SAAS,eAAe,IAAI,KAAK,QAAQ,KAAK;AAC9D,UAAI,KAAK,WAAW,CAAC,MAAM,eAAe;AACxC,cAAM,IAAI,MAAM,iBAAiB;AAAA,MACnC;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,aAAO,KAAK,mBAAmB,IAAI,OAAO;AAAA,IAC5C;AAEA,SAAK,IAAI,MAAM,sBAAsB,OAAO;AAE5C,SAAK,mBAAmB;AAAA,MACtB;AAAA,OACC,YAAY;AACX,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;AAClD,cAAI,OAAO,MAAM,SAAS,KAAK;AAE/B,cAAI,oBAAoB;AACtB,kBAAM,oBAAoB;AAC1B,gBAAI,kBAAkB,OAAO,UAAU;AACrC,oBAAM,oBAAoB,KAAK,gBAAgB,kBAAkB,OAAO,QAAQ;AAChF,qBAAO,KAAK,MAAM,iBAAiB;AAAA,YACrC;AAAA,UACF,OAAO;AACL,mBAAO;AAAA,UACT;AAEA,eAAK,IAAI,MAAM,mBAAmB,SAAS,QAAQ,KAAK,UAAU,IAAI,CAAC;AAIvE,cAAI,sBAAsB,SAAS,WAAW,KAAK;AACjD,iBAAK,OAAO;AAAA,UACd;AAGA,cAAI,KAAK,eAAe,UAAU,KAAK,eAAe,IAAI;AACxD,iBAAK,IAAI,MAAM,sCAAsC;AACrD,iBAAK,OAAO;AACZ,mBAAO,KAAK,WAAW,KAAK,kBAAkB,CAAC;AAAA,UACjD;AAEA,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,EAEA,MAAM,kBAAkB,OAAgB;AACtC,SAAK,QAAQ,IAAI,MAAM,iCAAiC,KAAK;AAE7D,UAAM,OAAO,MAAM,KAAK,WAAW;AAAA,MACjC,QAAQ;AAAA,MACR,QAAQ;AAAA,QACN,UAAU;AAAA,UACR;AAAA,YACE,QAAQ;AAAA,YACR,QAAQ;AAAA,cACN,WAAW;AAAA,gBACT,gBAAgB;AAAA,kBACd,SAAS,QAAQ,OAAO;AAAA,gBAC1B;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,QAAI,KAAK,eAAe,GAAG;AACzB,YAAM,IAAI,MAAM,0BAA0B;AAAA,IAC5C;AAAA,EACF;AAAA,EAEA,MAAM,eAAe,OAAgB;AACnC,SAAK,IAAI,MAAM,8BAA8B,KAAK;AAElD,UAAM,OAAO,MAAM,KAAK,WAAW;AAAA,MACjC,QAAQ;AAAA,MACR,QAAQ;AAAA,QACN,UAAU;AAAA,UACR;AAAA,YACE,QAAQ;AAAA,YACR,QAAQ;AAAA,cACN,WAAW;AAAA,gBACT,qBAAqB;AAAA,kBACnB,SAAS,QAAQ,OAAO;AAAA,gBAC1B;AAAA,cACF;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AAED,WAAO,KAAK,eAAe;AAAA,EAC7B;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;AAAA,EAEA,MAAM,eAAe;AACnB,UAAM,OAAO,MAAM,KAAK,WAAW;AAAA,MACjC,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,KAAK,OAAO,UAAU;AACnC,WAAO,KAAK,OAAO,YAAY;AAAA,EACjC;AAAA,EAEA,MAAM,YAA4D;AAChE,UAAM,OAAO,MAAM,KAAK,WAAW;AAAA,MACjC,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,OAAO;AAAA,gBACL,MAAM;AAAA,cACR;AAAA,YACF;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF,CAAC;AACD,SAAK,IAAI,MAAM,mBAAmB,KAAK,UAAU,IAAI,GAAG;AACxD,QAAI,KAAK,eAAe,GAAG;AACzB,YAAM,IAAI,MAAM,2BAA2B;AAAA,IAC7C;AACA,QAAI,CAAC,KAAK,OAAO,WAAW;AAC1B,YAAM,IAAI,MAAM,sCAAsC;AAAA,IACxD;AACA,UAAM,cAAc,KAAK,OAAO,UAAU,KAAK,CAAC,MAAM,EAAE,WAAW,gBAAgB;AAEnF,UAAM,sBAAsB,KAAK,OAAO,UAAU,KAAK,CAAC,MAAM,EAAE,WAAW,wBAAwB;AACnG,UAAM,iBAAiB,KAAK,OAAO,UAAU,KAAK,CAAC,MAAM,EAAE,WAAW,mBAAmB;AAEzF,WAAO;AAAA,MACL,OAAO,YAAY,OAAO,UAAU,oBAAoB,YAAY;AAAA,MACpE,UAAU,eAAe,OAAO,UAAU,eAAe,YAAY;AAAA,MACrE,gBAAgB,oBAAoB,OAAO,QAAQ,oBAAoB,OAAO,MAAM,OAAO,oBAAoB,OAAO;AAAA,IACxH;AAAA,EACF;AACF;",
6
6
  "names": ["https", "crypto", "fetch"]
7
7
  }
@@ -211,7 +211,8 @@ class P100 {
211
211
  Connection: "Keep-Alive",
212
212
  Host: this.ip,
213
213
  Accept: "*/*",
214
- "Content-Type": "application/octet-stream"
214
+ "Content-Type": "application/octet-stream",
215
+ "User-Agent": "ioBroker"
215
216
  };
216
217
  if (this.cookie) {
217
218
  headers["Cookie"] = this.cookie;
@@ -223,19 +224,24 @@ class P100 {
223
224
  params
224
225
  };
225
226
  return this.axios.post(URL, data, config).then((res) => {
226
- this.log.debug("Received request on host response: " + this.ip);
227
+ this.log.debug("Received request on host " + URL);
228
+ this.log.debug(JSON.stringify(res.data));
227
229
  if (res.data.error_code) {
230
+ this.log.debug("Found error code: " + res.data.error_code);
228
231
  return this.handleError(res.data.error_code, "309");
229
232
  }
233
+ this.log.debug("Try to parse headers");
230
234
  try {
231
235
  if (res.headers && res.headers["set-cookie"]) {
232
236
  this.cookie = res.headers["set-cookie"][0].split(";")[0];
233
237
  }
238
+ this.log.debug("Return data");
234
239
  return res.data;
235
240
  } catch (error) {
236
241
  return this.handleError(res.data.error_code, "318");
237
242
  }
238
243
  }).catch(async (error) => {
244
+ this.log.debug(JSON.stringify(error));
239
245
  this.log.error("322 Error: " + error ? error.message : "");
240
246
  if (this._reconnect_counter <= 3) {
241
247
  this.log.info("Trying to reconnect...");
@@ -247,17 +253,25 @@ class P100 {
247
253
  async handshake_new() {
248
254
  const local_seed = this.crypto.randomBytes(16);
249
255
  await this.raw_request("handshake1", local_seed, "arraybuffer").then((res) => {
250
- if (!res || !res.subarray) {
256
+ if (!res) {
257
+ this.log.debug("Empty response");
251
258
  return;
252
259
  }
253
260
  const remote_seed = res.subarray(0, 16);
254
261
  const server_hash = res.subarray(16);
262
+ this.log.debug("Received remote seed: " + remote_seed.toString("hex"));
263
+ this.log.debug("Received server hash: " + server_hash.toString("hex"));
255
264
  let auth_hash = void 0;
256
265
  const ah = this.calc_auth_hash(this.email, this.password);
266
+ this.log.debug("Calculated auth hash: " + ah.toString("hex"));
257
267
  const local_seed_auth_hash = this.crypto.createHash("sha256").update(Buffer.concat([local_seed, remote_seed, ah])).digest();
258
268
  if (local_seed_auth_hash.toString("hex") === server_hash.toString("hex")) {
259
269
  this.log.debug("Handshake 1 successful");
260
270
  auth_hash = ah;
271
+ } else {
272
+ this.log.warn("Handshake 1 failed");
273
+ this.log.debug(local_seed_auth_hash.toString("hex") + " != " + server_hash.toString("hex"));
274
+ auth_hash = this.calc_auth_hash(this.email, this.password + this.password);
261
275
  }
262
276
  const req = this.crypto.createHash("sha256").update(Buffer.concat([remote_seed, local_seed, auth_hash])).digest();
263
277
  return this.raw_request("handshake2", req, "text").then((res2) => {
@@ -518,6 +532,7 @@ class P100 {
518
532
  timeout: this._timeout * 1e3
519
533
  };
520
534
  return this.axios.post(URL, securePassthroughPayload, config).then((res) => {
535
+ this.log.debug("Response: " + JSON.stringify(res.data));
521
536
  if (res.data.error_code) {
522
537
  if (res.data.error_code === "9999" || res.data.error_code === 9999 && this._reconnect_counter <= 3) {
523
538
  this.log.error(" Error Code: " + res.data.error_code + ", " + this.ERROR_CODES[res.data.error_code]);
@@ -529,6 +544,7 @@ class P100 {
529
544
  this._reconnect_counter = 0;
530
545
  return this.handleError(res.data.error_code, "357");
531
546
  }
547
+ this.log.debug("Decrypt response");
532
548
  const decryptedResponse = this.tpLinkCipher.decrypt(res.data.result.response);
533
549
  try {
534
550
  const response = JSON.parse(decryptedResponse);
@@ -541,6 +557,9 @@ class P100 {
541
557
  return this.handleError(JSON.parse(decryptedResponse).error_code, "368");
542
558
  }
543
559
  }).catch((error) => {
560
+ this.log.debug("request error:" + JSON.stringify(error));
561
+ error.response && this.log.debug("request error response:" + JSON.stringify(error.response));
562
+ error.message && this.log.debug("request error message:" + JSON.stringify(error.message));
544
563
  });
545
564
  }
546
565
  return new Promise((resolve, reject) => {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/utils/p100.ts"],
4
- "sourcesContent": ["import { AxiosResponse } from \"axios\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport NewTpLinkCipher from \"./newTpLinkCipher\";\nimport TpLinkCipher from \"./tpLinkCipher\";\nimport { PlugSysinfo } from \"./types\";\n\nexport default class P100 {\n private crypto = require(\"crypto\");\n protected axios = require(\"axios\");\n private utf8 = require(\"utf8\");\n public is_klap = false;\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 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 this.publicKey = publicKey.toString(\"utf8\");\n }\n\n async handshake(): Promise<any> {\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) {\n return this.handleError(res.data.error_code, \"97\");\n }\n\n try {\n const encryptedKey = res.data.result.key.toString(\"utf8\");\n this.decode_handshake_key(encryptedKey);\n this.cookie = res.headers[\"set-cookie\"][0].split(\";\")[0];\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) {\n return this.handleError(res.data.error_code, \"146\");\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 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 headers[\"Cookie\"] = this.cookie;\n }\n\n const config = {\n timeout: 5000,\n responseType: responseType,\n headers: headers,\n params: params,\n };\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) {\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 return res.data;\n } catch (error) {\n return this.handleError(res.data.error_code, \"318\");\n }\n })\n .catch(async (error: Error) => {\n this.log.error(\"322 Error: \" + error ? error.message : \"\");\n if (this._reconnect_counter <= 3) {\n this.log.info(\"Trying to reconnect...\");\n await this.newReconnect();\n }\n return error;\n });\n }\n\n async handshake_new(): Promise<void> {\n const local_seed = this.crypto.randomBytes(16);\n\n await this.raw_request(\"handshake1\", local_seed, \"arraybuffer\").then((res) => {\n if (!res || !res.subarray) {\n return;\n }\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\");\n\n this.newTpLinkCipher = new NewTpLinkCipher(local_seed, remote_seed, auth_hash);\n this.log.debug(\"Init cipher successful\");\n\n return;\n });\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 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(): Promise<PlugSysinfo> {\n if (this.getSysInfo() && Date.now() - this.getSysInfo().last_update < 2000) {\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 this.log.debug(\"using old cypher\");\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: any) => {\n this.log.debug(JSON.stringify(res.data));\n if (res.data.error_code) {\n if ((res.data.error_code === \"9999\" || res.data.error_code === 9999) && this._reconnect_counter <= 3) {\n this.log.debug(\" 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 this.log.debug(\"using new cypher\");\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 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 return this.axios\n .post(URL, data.encryptedPayload, config)\n .then((res: AxiosResponse) => {\n this.log.debug(JSON.stringify(res.data));\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 this.log.debug(\"Device Info: \" + JSON.stringify(response));\n if (response.error_code !== 0) {\n return this.handleError(response.error_code, \"333\");\n }\n this.setSysInfo(response.result);\n\n return this.getSysInfo();\n } catch (error) {\n return this.handleError(res.data.error_code, \"480\");\n }\n })\n .catch(async (error: Error) => {\n this.log.error(\"322 #2 Error: \" + error ? error.message : \"\");\n if (this._reconnect_counter <= 3) {\n this.log.info(\"Trying to reconnect...\");\n await this.newReconnect();\n }\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 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 const errorMessage = this.ERROR_CODES[errorCode];\n this.log.debug(line + \" Error Code: \" + errorCode + \", \" + errorMessage + \" \" + this.ip);\n\n if (typeof errorCode === \"number\" && errorCode === 1003) {\n this.is_klap = true;\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 && 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.newHandleRequest(payload)\n .then((result) => {\n return result ? true : false;\n })\n .catch((error) => {\n if (error && error.message.indexOf(\"9999\") > 0 && this._reconnect_counter <= 3) {\n return this.newReconnect().then(() => {\n return this.newHandleRequest(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 async newSendRequest(payload: string): Promise<boolean> {\n return this.handleRequest(payload)\n .then((result) => {\n return result ? true : false;\n })\n .catch((error) => {\n this.log.debug(JSON.stringify(error));\n if (error && 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 }\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 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, \"372\");\n });\n }\n return new Promise<true>((resolve, reject) => {\n reject();\n });\n }\n\n protected newHandleRequest(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, \"372\");\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"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { AxiosError, AxiosResponse } from \"axios\";\nimport { v4 as uuidv4 } from \"uuid\";\nimport NewTpLinkCipher from \"./newTpLinkCipher\";\nimport TpLinkCipher from \"./tpLinkCipher\";\nimport { PlugSysinfo } from \"./types\";\n\nexport default class P100 {\n private crypto = require(\"crypto\");\n protected axios = require(\"axios\");\n private utf8 = require(\"utf8\");\n public is_klap = false;\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 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 this.publicKey = publicKey.toString(\"utf8\");\n }\n\n async handshake(): Promise<any> {\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) {\n return this.handleError(res.data.error_code, \"97\");\n }\n\n try {\n const encryptedKey = res.data.result.key.toString(\"utf8\");\n this.decode_handshake_key(encryptedKey);\n this.cookie = res.headers[\"set-cookie\"][0].split(\";\")[0];\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) {\n return this.handleError(res.data.error_code, \"146\");\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 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 headers[\"Cookie\"] = this.cookie;\n }\n\n const config = {\n timeout: 5000,\n responseType: responseType,\n headers: headers,\n params: params,\n };\n return this.axios\n .post(URL, data, config)\n .then((res: AxiosResponse) => {\n this.log.debug(\"Received request on host \" + URL);\n this.log.debug(JSON.stringify(res.data));\n if (res.data.error_code) {\n this.log.debug(\"Found error code: \" + res.data.error_code);\n return this.handleError(res.data.error_code, \"309\");\n }\n this.log.debug(\"Try to parse headers\");\n try {\n if (res.headers && res.headers[\"set-cookie\"]) {\n this.cookie = res.headers[\"set-cookie\"][0].split(\";\")[0];\n }\n this.log.debug(\"Return data\");\n return res.data;\n } catch (error) {\n return this.handleError(res.data.error_code, \"318\");\n }\n })\n .catch(async (error: Error) => {\n this.log.debug(JSON.stringify(error));\n this.log.error(\"322 Error: \" + error ? error.message : \"\");\n if (this._reconnect_counter <= 3) {\n this.log.info(\"Trying to reconnect...\");\n await this.newReconnect();\n }\n return error;\n });\n }\n\n async handshake_new(): Promise<void> {\n const local_seed = this.crypto.randomBytes(16);\n\n await this.raw_request(\"handshake1\", local_seed, \"arraybuffer\").then((res) => {\n if (!res) {\n this.log.debug(\"Empty response\");\n return;\n }\n const remote_seed: Buffer = res.subarray(0, 16);\n const server_hash: Buffer = res.subarray(16);\n this.log.debug(\"Received remote seed: \" + remote_seed.toString(\"hex\"));\n this.log.debug(\"Received server hash: \" + server_hash.toString(\"hex\"));\n let auth_hash: any = undefined;\n const ah = this.calc_auth_hash(this.email, this.password);\n this.log.debug(\"Calculated auth hash: \" + ah.toString(\"hex\"));\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 } else {\n this.log.warn(\"Handshake 1 failed\");\n this.log.debug(local_seed_auth_hash.toString(\"hex\") + \" != \" + server_hash.toString(\"hex\"));\n auth_hash = this.calc_auth_hash(this.email, this.password + this.password);\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\");\n\n this.newTpLinkCipher = new NewTpLinkCipher(local_seed, remote_seed, auth_hash);\n this.log.debug(\"Init cipher successful\");\n\n return;\n });\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 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(): Promise<PlugSysinfo> {\n if (this.getSysInfo() && Date.now() - this.getSysInfo().last_update < 2000) {\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 this.log.debug(\"using old cypher\");\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: any) => {\n this.log.debug(JSON.stringify(res.data));\n if (res.data.error_code) {\n if ((res.data.error_code === \"9999\" || res.data.error_code === 9999) && this._reconnect_counter <= 3) {\n this.log.debug(\" 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 this.log.debug(\"using new cypher\");\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 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 return this.axios\n .post(URL, data.encryptedPayload, config)\n .then((res: AxiosResponse) => {\n this.log.debug(JSON.stringify(res.data));\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 this.log.debug(\"Device Info: \" + JSON.stringify(response));\n if (response.error_code !== 0) {\n return this.handleError(response.error_code, \"333\");\n }\n this.setSysInfo(response.result);\n\n return this.getSysInfo();\n } catch (error) {\n return this.handleError(res.data.error_code, \"480\");\n }\n })\n .catch(async (error: Error) => {\n this.log.error(\"322 #2 Error: \" + error ? error.message : \"\");\n if (this._reconnect_counter <= 3) {\n this.log.info(\"Trying to reconnect...\");\n await this.newReconnect();\n }\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 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 const errorMessage = this.ERROR_CODES[errorCode];\n this.log.debug(line + \" Error Code: \" + errorCode + \", \" + errorMessage + \" \" + this.ip);\n\n if (typeof errorCode === \"number\" && errorCode === 1003) {\n this.is_klap = true;\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 && 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.newHandleRequest(payload)\n .then((result) => {\n return result ? true : false;\n })\n .catch((error) => {\n if (error && error.message.indexOf(\"9999\") > 0 && this._reconnect_counter <= 3) {\n return this.newReconnect().then(() => {\n return this.newHandleRequest(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 async newSendRequest(payload: string): Promise<boolean> {\n return this.handleRequest(payload)\n .then((result) => {\n return result ? true : false;\n })\n .catch((error) => {\n this.log.debug(JSON.stringify(error));\n if (error && 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 }\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 this.log.debug(\"Response: \" + JSON.stringify(res.data));\n if (res.data.error_code) {\n if (res.data.error_code === \"9999\" || (res.data.error_code === 9999 && this._reconnect_counter <= 3)) {\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 this.log.debug(\"Decrypt response\");\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: AxiosError) => {\n this.log.debug(\"request error:\" + JSON.stringify(error));\n error.response && this.log.debug(\"request error response:\" + JSON.stringify(error.response));\n error.message && this.log.debug(\"request error message:\" + JSON.stringify(error.message));\n //return this.handleError(error.message, \"372\");\n });\n }\n return new Promise<true>((resolve, reject) => {\n reject();\n });\n }\n\n protected newHandleRequest(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, \"372\");\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"],
5
+ "mappings": "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",
6
6
  "names": ["uuidv4", "TpLinkCipher", "res", "NewTpLinkCipher", "URL", "headers"]
7
7
  }
@@ -41,6 +41,7 @@ class P110 extends import_p100.default {
41
41
  async getEnergyUsage() {
42
42
  const payload = '{"method": "get_energy_usage","requestTimeMils": ' + Math.round(Date.now() * 1e3) + "};";
43
43
  return this.handleRequest(payload).then((response) => {
44
+ this.log.debug("getEnergyUsage response: " + JSON.stringify(response));
44
45
  if (response && response.result) {
45
46
  this._consumption = {
46
47
  current: response.result.current_power / 1e3,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/lib/utils/p110.ts"],
4
- "sourcesContent": ["import { EnergyUsage } from \"./energyUsage\";\nimport P100 from \"./p100\";\nimport { ConsumptionInfo } from \"./types\";\n\nexport default class P110 extends P100 {\n private _consumption!: ConsumptionInfo;\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 super(log, ipAddress, email, password, timeout);\n this.log.debug(\"Constructing P110 on host: \" + ipAddress);\n }\n\n async getEnergyUsage(): Promise<EnergyUsage> {\n const payload = \"{\" + '\"method\": \"get_energy_usage\",' + '\"requestTimeMils\": ' + Math.round(Date.now() * 1000) + \"\" + \"};\";\n\n return this.handleRequest(payload).then((response) => {\n if (response && response.result) {\n this._consumption = {\n current: response.result.current_power / 1000,\n total: response.result.today_energy / 1000,\n };\n } else {\n this._consumption = {\n current: 0,\n total: 0,\n };\n }\n\n return response.result;\n });\n }\n\n public getPowerConsumption(): ConsumptionInfo {\n return this._consumption;\n }\n}\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,kBAAiB;AAGjB,MAAO,aAA2B,YAAAA,QAAK;AAAA,EAGrC,YACkB,KACA,WACA,OACA,UACA,SAChB;AACA,UAAM,KAAK,WAAW,OAAO,UAAU,OAAO;AAN9B;AACA;AACA;AACA;AACA;AAGhB,SAAK,IAAI,MAAM,gCAAgC,SAAS;AAAA,EAC1D;AAAA,EAEA,MAAM,iBAAuC;AAC3C,UAAM,UAAU,sDAAgE,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,IAAS;AAErH,WAAO,KAAK,cAAc,OAAO,EAAE,KAAK,CAAC,aAAa;AACpD,UAAI,YAAY,SAAS,QAAQ;AAC/B,aAAK,eAAe;AAAA,UAClB,SAAS,SAAS,OAAO,gBAAgB;AAAA,UACzC,OAAO,SAAS,OAAO,eAAe;AAAA,QACxC;AAAA,MACF,OAAO;AACL,aAAK,eAAe;AAAA,UAClB,SAAS;AAAA,UACT,OAAO;AAAA,QACT;AAAA,MACF;AAEA,aAAO,SAAS;AAAA,IAClB,CAAC;AAAA,EACH;AAAA,EAEO,sBAAuC;AAC5C,WAAO,KAAK;AAAA,EACd;AACF;",
4
+ "sourcesContent": ["import { EnergyUsage } from \"./energyUsage\";\nimport P100 from \"./p100\";\nimport { ConsumptionInfo } from \"./types\";\n\nexport default class P110 extends P100 {\n private _consumption!: ConsumptionInfo;\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 super(log, ipAddress, email, password, timeout);\n this.log.debug(\"Constructing P110 on host: \" + ipAddress);\n }\n\n async getEnergyUsage(): Promise<EnergyUsage> {\n const payload = \"{\" + '\"method\": \"get_energy_usage\",' + '\"requestTimeMils\": ' + Math.round(Date.now() * 1000) + \"\" + \"};\";\n\n return this.handleRequest(payload).then((response) => {\n this.log.debug(\"getEnergyUsage response: \" + JSON.stringify(response));\n if (response && response.result) {\n this._consumption = {\n current: response.result.current_power / 1000,\n total: response.result.today_energy / 1000,\n };\n } else {\n this._consumption = {\n current: 0,\n total: 0,\n };\n }\n\n return response.result;\n });\n }\n\n public getPowerConsumption(): ConsumptionInfo {\n return this._consumption;\n }\n}\n"],
5
+ "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,kBAAiB;AAGjB,MAAO,aAA2B,YAAAA,QAAK;AAAA,EAGrC,YACkB,KACA,WACA,OACA,UACA,SAChB;AACA,UAAM,KAAK,WAAW,OAAO,UAAU,OAAO;AAN9B;AACA;AACA;AACA;AACA;AAGhB,SAAK,IAAI,MAAM,gCAAgC,SAAS;AAAA,EAC1D;AAAA,EAEA,MAAM,iBAAuC;AAC3C,UAAM,UAAU,sDAAgE,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI,IAAS;AAErH,WAAO,KAAK,cAAc,OAAO,EAAE,KAAK,CAAC,aAAa;AACpD,WAAK,IAAI,MAAM,8BAA8B,KAAK,UAAU,QAAQ,CAAC;AACrE,UAAI,YAAY,SAAS,QAAQ;AAC/B,aAAK,eAAe;AAAA,UAClB,SAAS,SAAS,OAAO,gBAAgB;AAAA,UACzC,OAAO,SAAS,OAAO,eAAe;AAAA,QACxC;AAAA,MACF,OAAO;AACL,aAAK,eAAe;AAAA,UAClB,SAAS;AAAA,UACT,OAAO;AAAA,QACT;AAAA,MACF;AAEA,aAAO,SAAS;AAAA,IAClB,CAAC;AAAA,EACH;AAAA,EAEO,sBAAuC;AAC5C,WAAO,KAAK;AAAA,EACd;AACF;",
6
6
  "names": ["P100"]
7
7
  }
package/build/main.js CHANGED
@@ -548,7 +548,8 @@ class Tapo extends utils.Adapter {
548
548
  await deviceObject.handshake().then(async () => {
549
549
  if (deviceObject.is_klap) {
550
550
  this.log.debug("Detected KLAP device");
551
- await deviceObject.handshake_new().catch(() => {
551
+ await deviceObject.handshake_new().catch((error) => {
552
+ this.log.error(error);
552
553
  this.log.error("KLAP Handshake failed");
553
554
  deviceObject.is_klap = false;
554
555
  this.deviceObjects[id]._connected = false;
@@ -574,7 +575,8 @@ class Tapo extends utils.Adapter {
574
575
  this.log.debug(JSON.stringify(energyUsage));
575
576
  this.json2iob.parse(id, energyUsage);
576
577
  }
577
- }).catch(() => {
578
+ }).catch((error) => {
579
+ this.log.error(JSON.stringify(error));
578
580
  this.log.error("52 - Get Device Info failed");
579
581
  this.deviceObjects[id]._connected = false;
580
582
  });
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 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 }),\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 await this.updateDevices();\n this.updateInterval = setInterval(async () => {\n await 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 if (this.isBase64(device.alias)) {\n name = Buffer.from(device.alias, \"base64\").toString(\"utf8\");\n }\n\n await this.setObjectNotExistsAsync(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.extendObjectAsync(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);\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 === \"P110\" || device.deviceName === \"P115\") {\n deviceObject = new P110(this.log, device.ip, this.config.username, this.config.password, 2);\n } else if (device.deviceName === \"L530\") {\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 }); //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();\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.info(`[${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(() => {\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()\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(() => {\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 continue;\n }\n if (!this.deviceObjects[deviceId]._connected) {\n continue;\n }\n\n this.deviceObjects[deviceId]\n .getDeviceInfo()\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) => {\n this.log.error(`Get Device Info failed for ${deviceId} - ${error}`);\n });\n }\n } catch (error) {\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 return 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()\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 await 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.setStateAsync(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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",
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 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 }),\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 await this.updateDevices();\n this.updateInterval = setInterval(async () => {\n await 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 if (this.isBase64(device.alias)) {\n name = Buffer.from(device.alias, \"base64\").toString(\"utf8\");\n }\n\n await this.setObjectNotExistsAsync(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.extendObjectAsync(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);\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 === \"P110\" || device.deviceName === \"P115\") {\n deviceObject = new P110(this.log, device.ip, this.config.username, this.config.password, 2);\n } else if (device.deviceName === \"L530\") {\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 }); //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();\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.info(`[${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()\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 continue;\n }\n if (!this.deviceObjects[deviceId]._connected) {\n continue;\n }\n\n this.deviceObjects[deviceId]\n .getDeviceInfo()\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) => {\n this.log.error(`Get Device Info failed for ${deviceId} - ${error}`);\n });\n }\n } catch (error) {\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 return 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()\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 await 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.setStateAsync(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", "uuidv4", "crypto", "body", "path", "md5", "content", "signature", "res", "_a", "_b", "P100", "P110", "L530", "L510E", "L520E"]
7
7
  }
package/io-package.json CHANGED
@@ -1,9 +1,13 @@
1
1
  {
2
2
  "common": {
3
3
  "name": "tapo",
4
- "version": "0.2.2",
4
+ "version": "0.2.5",
5
5
  "news": {
6
- "0.2.2": {
6
+ "0.2.5": {
7
+ "en": "Improve P1XX handling",
8
+ "de": "Verbesserte P1XX Unterstützung"
9
+ },
10
+ "0.2.3": {
7
11
  "en": "Add Camera movment",
8
12
  "de": "Kamera Bewegungskontrolle hinzugefügt"
9
13
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "iobroker.tapo",
3
- "version": "0.2.2",
3
+ "version": "0.2.5",
4
4
  "description": "Adapter for TP-Link Tapo",
5
5
  "author": {
6
6
  "name": "TA2k",
@@ -31,23 +31,17 @@
31
31
  "@iobroker/testing": "^4.1.0",
32
32
  "@types/chai-as-promised": "^7.1.8",
33
33
  "@types/json-bigint": "^1.0.4",
34
- "@types/mocha": "^10.0.6",
35
- "@types/node": "^20.11.0",
34
+ "@types/node": "^20.11.5",
36
35
  "@types/proxyquire": "^1.3.31",
37
- "@types/sinon": "^17.0.3",
38
- "@types/sinon-chai": "^3.2.12",
39
36
  "@types/uuid": "^9.0.7",
40
- "@typescript-eslint/eslint-plugin": "^6.18.1",
41
- "@typescript-eslint/parser": "^6.18.1",
37
+ "@typescript-eslint/eslint-plugin": "^6.19.0",
38
+ "@typescript-eslint/parser": "^6.19.0",
42
39
  "eslint": "^8.56.0",
43
40
  "eslint-config-prettier": "^9.1.0",
44
41
  "eslint-plugin-prettier": "^5.1.3",
45
- "mocha": "^10.2.0",
46
- "prettier": "^3.1.1",
42
+ "prettier": "^3.2.4",
47
43
  "proxyquire": "^2.1.3",
48
44
  "rimraf": "^5.0.5",
49
- "sinon": "^17.0.1",
50
- "sinon-chai": "^3.7.0",
51
45
  "source-map-support": "^0.5.21",
52
46
  "ts-node": "^10.9.2",
53
47
  "typescript": "~5.3.3"