iobroker.tapo 0.0.6 → 0.0.7
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/admin/jsonConfig.json +38 -0
- package/build/lib/utils/camera/onvifCamera.js +94 -0
- package/build/lib/utils/camera/onvifCamera.js.map +7 -0
- package/build/lib/utils/camera/tapoCamera.js +274 -0
- package/build/lib/utils/camera/tapoCamera.js.map +7 -0
- package/build/lib/utils/camera.js +97 -0
- package/build/lib/utils/camera.js.map +7 -0
- package/build/main.js +80 -6
- package/build/main.js.map +2 -2
- package/io-package.json +7 -1
- package/package.json +14 -12
package/admin/jsonConfig.json
CHANGED
|
@@ -72,6 +72,44 @@
|
|
|
72
72
|
},
|
|
73
73
|
"newLine": true,
|
|
74
74
|
"sm": 3
|
|
75
|
+
},
|
|
76
|
+
"streamusername": {
|
|
77
|
+
"type": "text",
|
|
78
|
+
"label": {
|
|
79
|
+
"en": "Stream Username. Settings > Advanced Settings > Camera Account.",
|
|
80
|
+
"de": "Kamera Stream Benutzername. Kamera Einstellungen > Erweiterte Einstellungen > Kamerakonto.",
|
|
81
|
+
"ru": "Stream Имя пользователя. Настройки > Расширенные настройки > учетная запись камеры.",
|
|
82
|
+
"pt": "Stream Username. Configurações > Configurações avançadas > Conta de câmera.",
|
|
83
|
+
"nl": "Stream User naam. Settings Geavanceerde Settings Camera Account.",
|
|
84
|
+
"fr": "Rationaliser l'utilisateur. Paramètres phy Paramètres avancés Compte de la caméra.",
|
|
85
|
+
"it": "Stream Username. Impostazioni > Impostazioni avanzate > Account fotocamera.",
|
|
86
|
+
"es": "Stream Username. Ajustes Ajustes avanzados con cuenta de cámara.",
|
|
87
|
+
"pl": "Stream Username (ang.). Settings (ang.). Advanced Settings > Camera Account (ang.).",
|
|
88
|
+
"uk": "Потокове ім'я користувача. Налаштування > Розширені налаштування > обліковий запис камери.",
|
|
89
|
+
"zh-cn": "Stream Ur名称。 定 法 预发型号——卡拉账户。."
|
|
90
|
+
},
|
|
91
|
+
"newLine": true,
|
|
92
|
+
"sm": 3
|
|
93
|
+
},
|
|
94
|
+
"streampassword": {
|
|
95
|
+
"type": "password",
|
|
96
|
+
"newLine": true,
|
|
97
|
+
"repeat": false,
|
|
98
|
+
"visible": true,
|
|
99
|
+
"sm": 3,
|
|
100
|
+
"label": {
|
|
101
|
+
"en": "Stream Password. App Settings > Advanced Settings > Camera Account.",
|
|
102
|
+
"de": "Kamera Stream Passwort. Kamera Einstellungen > Erweiterte Einstellungen > Kamerakonto.",
|
|
103
|
+
"ru": "Stream Пароль. Настройки приложений > Расширенные настройки > учетная запись камеры.",
|
|
104
|
+
"pt": "Stream Password. Configurações do aplicativo > Configurações avançadas > Conta de câmera.",
|
|
105
|
+
"nl": "Stream Password. App Settings Geavanceerde Settings Camera Account.",
|
|
106
|
+
"fr": "Simplifiez le mot de passe. Paramètres de l'application s Paramètres avancés Compte de la caméra.",
|
|
107
|
+
"it": "Password di streaming. Impostazioni dell'app > Impostazioni avanzate > Account fotocamera.",
|
|
108
|
+
"es": "Stream Password. Ajustes de la aplicación Ajustes avanzados con cuenta de cámara.",
|
|
109
|
+
"pl": "Stream Password (ang.). App Settings (ang.). Advanced Settings > Camera Account (ang.).",
|
|
110
|
+
"uk": "Статус на сервери Налаштування додатків > Розширені налаштування > обліковий запис камери.",
|
|
111
|
+
"zh-cn": "Stream Pass。 附录 预发型号——卡拉账户。."
|
|
112
|
+
}
|
|
75
113
|
}
|
|
76
114
|
}
|
|
77
115
|
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var onvifCamera_exports = {};
|
|
20
|
+
__export(onvifCamera_exports, {
|
|
21
|
+
OnvifCamera: () => OnvifCamera
|
|
22
|
+
});
|
|
23
|
+
module.exports = __toCommonJS(onvifCamera_exports);
|
|
24
|
+
var import_onvif = require("onvif");
|
|
25
|
+
var import_stream = require("stream");
|
|
26
|
+
class OnvifCamera {
|
|
27
|
+
constructor(log, config) {
|
|
28
|
+
this.log = log;
|
|
29
|
+
this.config = config;
|
|
30
|
+
this.kOnvifPort = 2020;
|
|
31
|
+
}
|
|
32
|
+
async getDevice() {
|
|
33
|
+
return new Promise((resolve, reject) => {
|
|
34
|
+
if (this.device) {
|
|
35
|
+
return resolve(this.device);
|
|
36
|
+
}
|
|
37
|
+
const device = new import_onvif.Cam(
|
|
38
|
+
{
|
|
39
|
+
hostname: this.config.ipAddress,
|
|
40
|
+
username: this.config.streamUser,
|
|
41
|
+
password: this.config.streamPassword,
|
|
42
|
+
port: this.kOnvifPort
|
|
43
|
+
},
|
|
44
|
+
(err) => {
|
|
45
|
+
if (err) {
|
|
46
|
+
return reject(err);
|
|
47
|
+
}
|
|
48
|
+
this.device = device;
|
|
49
|
+
return resolve(this.device);
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
async getEventEmitter() {
|
|
55
|
+
if (this.events) {
|
|
56
|
+
return this.events;
|
|
57
|
+
}
|
|
58
|
+
const onvifDevice = await this.getDevice();
|
|
59
|
+
let lastMotionValue = false;
|
|
60
|
+
this.events = new import_stream.EventEmitter();
|
|
61
|
+
this.log.debug(`[${this.config.name}]`, "Starting ONVIF listener");
|
|
62
|
+
onvifDevice.on("event", (event) => {
|
|
63
|
+
var _a, _b;
|
|
64
|
+
if ((_b = (_a = event == null ? void 0 : event.topic) == null ? void 0 : _a._) == null ? void 0 : _b.match(/RuleEngine\/CellMotionDetector\/Motion$/)) {
|
|
65
|
+
const motion = event.message.message.data.simpleItem.$.Value;
|
|
66
|
+
if (motion !== lastMotionValue) {
|
|
67
|
+
lastMotionValue = motion;
|
|
68
|
+
this.events = this.events || new import_stream.EventEmitter();
|
|
69
|
+
this.events.emit("motion", motion);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
return this.events;
|
|
74
|
+
}
|
|
75
|
+
async getVideoSource() {
|
|
76
|
+
const onvifDevice = await this.getDevice();
|
|
77
|
+
return onvifDevice.videoSources[0];
|
|
78
|
+
}
|
|
79
|
+
async getDeviceInfo() {
|
|
80
|
+
const onvifDevice = await this.getDevice();
|
|
81
|
+
return new Promise((resolve, reject) => {
|
|
82
|
+
onvifDevice.getDeviceInformation((err, deviceInformation) => {
|
|
83
|
+
if (err)
|
|
84
|
+
return reject(err);
|
|
85
|
+
resolve(deviceInformation);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
91
|
+
0 && (module.exports = {
|
|
92
|
+
OnvifCamera
|
|
93
|
+
});
|
|
94
|
+
//# sourceMappingURL=onvifCamera.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/lib/utils/camera/onvifCamera.ts"],
|
|
4
|
+
"sourcesContent": ["import { Cam, DeviceInformation, NotificationMessage, VideoSource } from \"onvif\";\nimport { EventEmitter } from \"stream\";\ntype CameraConfig = {\n name: string;\n ipAddress: 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};\nexport class OnvifCamera {\n private events: EventEmitter | undefined;\n private device: Cam | undefined;\n\n private readonly kOnvifPort = 2020;\n\n constructor(protected readonly log: any, protected readonly config: CameraConfig) {}\n\n private async getDevice(): Promise<Cam> {\n return new Promise((resolve, reject) => {\n if (this.device) {\n return resolve(this.device);\n }\n\n const device: Cam = new Cam(\n {\n hostname: this.config.ipAddress,\n username: this.config.streamUser,\n password: this.config.streamPassword,\n port: this.kOnvifPort,\n },\n (err) => {\n if (err) {\n return reject(err);\n }\n this.device = device;\n return resolve(this.device);\n },\n );\n });\n }\n\n async getEventEmitter() {\n if (this.events) {\n return this.events;\n }\n\n const onvifDevice = await this.getDevice();\n\n let lastMotionValue = false;\n\n this.events = new EventEmitter();\n this.log.debug(`[${this.config.name}]`, \"Starting ONVIF listener\");\n\n onvifDevice.on(\"event\", (event: NotificationMessage) => {\n if (event?.topic?._?.match(/RuleEngine\\/CellMotionDetector\\/Motion$/)) {\n const motion = event.message.message.data.simpleItem.$.Value;\n if (motion !== lastMotionValue) {\n lastMotionValue = motion;\n this.events = this.events || new EventEmitter();\n this.events.emit(\"motion\", motion);\n }\n }\n });\n\n return this.events;\n }\n\n async getVideoSource(): Promise<VideoSource> {\n const onvifDevice = await this.getDevice();\n return onvifDevice.videoSources[0];\n }\n\n async getDeviceInfo(): Promise<DeviceInformation> {\n const onvifDevice = await this.getDevice();\n return new Promise((resolve, reject) => {\n onvifDevice.getDeviceInformation((err, deviceInformation) => {\n if (err) return reject(err);\n resolve(deviceInformation);\n });\n });\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAyE;AACzE,oBAA6B;AAetB,MAAM,YAAY;AAAA,EAMvB,YAA+B,KAA6B,QAAsB;AAAnD;AAA6B;AAF5D,SAAiB,aAAa;AAAA,EAEqD;AAAA,EAEnF,MAAc,YAA0B;AACtC,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAI,KAAK,QAAQ;AACf,eAAO,QAAQ,KAAK,MAAM;AAAA,MAC5B;AAEA,YAAM,SAAc,IAAI;AAAA,QACtB;AAAA,UACE,UAAU,KAAK,OAAO;AAAA,UACtB,UAAU,KAAK,OAAO;AAAA,UACtB,UAAU,KAAK,OAAO;AAAA,UACtB,MAAM,KAAK;AAAA,QACb;AAAA,QACA,CAAC,QAAQ;AACP,cAAI,KAAK;AACP,mBAAO,OAAO,GAAG;AAAA,UACnB;AACA,eAAK,SAAS;AACd,iBAAO,QAAQ,KAAK,MAAM;AAAA,QAC5B;AAAA,MACF;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,kBAAkB;AACtB,QAAI,KAAK,QAAQ;AACf,aAAO,KAAK;AAAA,IACd;AAEA,UAAM,cAAc,MAAM,KAAK,UAAU;AAEzC,QAAI,kBAAkB;AAEtB,SAAK,SAAS,IAAI,2BAAa;AAC/B,SAAK,IAAI,MAAM,IAAI,KAAK,OAAO,SAAS,yBAAyB;AAEjE,gBAAY,GAAG,SAAS,CAAC,UAA+B;AA5D5D;AA6DM,WAAI,0CAAO,UAAP,mBAAc,MAAd,mBAAiB,MAAM,4CAA4C;AACrE,cAAM,SAAS,MAAM,QAAQ,QAAQ,KAAK,WAAW,EAAE;AACvD,YAAI,WAAW,iBAAiB;AAC9B,4BAAkB;AAClB,eAAK,SAAS,KAAK,UAAU,IAAI,2BAAa;AAC9C,eAAK,OAAO,KAAK,UAAU,MAAM;AAAA,QACnC;AAAA,MACF;AAAA,IACF,CAAC;AAED,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAM,iBAAuC;AAC3C,UAAM,cAAc,MAAM,KAAK,UAAU;AACzC,WAAO,YAAY,aAAa;AAAA,EAClC;AAAA,EAEA,MAAM,gBAA4C;AAChD,UAAM,cAAc,MAAM,KAAK,UAAU;AACzC,WAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,kBAAY,qBAAqB,CAAC,KAAK,sBAAsB;AAC3D,YAAI;AAAK,iBAAO,OAAO,GAAG;AAC1B,gBAAQ,iBAAiB;AAAA,MAC3B,CAAC;AAAA,IACH,CAAC;AAAA,EACH;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
25
|
+
var tapoCamera_exports = {};
|
|
26
|
+
__export(tapoCamera_exports, {
|
|
27
|
+
TAPOCamera: () => TAPOCamera
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(tapoCamera_exports);
|
|
30
|
+
var import_crypto = __toESM(require("crypto"));
|
|
31
|
+
var import_https = __toESM(require("https"));
|
|
32
|
+
var import_node_fetch = __toESM(require("node-fetch"));
|
|
33
|
+
var import_onvifCamera = require("./onvifCamera");
|
|
34
|
+
class TAPOCamera extends import_onvifCamera.OnvifCamera {
|
|
35
|
+
constructor(log, config) {
|
|
36
|
+
super(log, config);
|
|
37
|
+
this.log = log;
|
|
38
|
+
this.config = config;
|
|
39
|
+
this.kTokenExpiration = 1e3 * 60 * 60;
|
|
40
|
+
this.kStreamPort = 554;
|
|
41
|
+
this.pendingAPIRequests = /* @__PURE__ */ new Map();
|
|
42
|
+
this.httpsAgent = new import_https.default.Agent({
|
|
43
|
+
rejectUnauthorized: false
|
|
44
|
+
});
|
|
45
|
+
this.hashedPassword = import_crypto.default.createHash("md5").update(config.password).digest("hex").toUpperCase();
|
|
46
|
+
}
|
|
47
|
+
fetch(url, data) {
|
|
48
|
+
return (0, import_node_fetch.default)(url, {
|
|
49
|
+
...data,
|
|
50
|
+
agent: this.httpsAgent
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
getTapoAPICredentials() {
|
|
54
|
+
return {
|
|
55
|
+
username: "admin",
|
|
56
|
+
password: this.hashedPassword
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
getAuthenticatedStreamUrl(lowQuality) {
|
|
60
|
+
const prefix = `rtsp://${this.config.streamUser}:${this.config.streamPassword}@${this.config.ipAddress}:${this.kStreamPort}`;
|
|
61
|
+
return lowQuality ? `${prefix}/stream2` : `${prefix}/stream1`;
|
|
62
|
+
}
|
|
63
|
+
async fetchToken() {
|
|
64
|
+
this.log.debug(`[${this.config.name}]`, "Fetching new token");
|
|
65
|
+
const response = await this.fetch(`https://${this.config.ipAddress}/`, {
|
|
66
|
+
method: "post",
|
|
67
|
+
body: JSON.stringify({
|
|
68
|
+
method: "login",
|
|
69
|
+
params: this.getTapoAPICredentials()
|
|
70
|
+
}),
|
|
71
|
+
headers: {
|
|
72
|
+
"Content-Type": "application/json"
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
const json = await response.json();
|
|
76
|
+
if (!json.result.stok) {
|
|
77
|
+
throw new Error(
|
|
78
|
+
"Unable to find token in response, probably your credentials are not valid. Please make sure you set your TAPO Cloud password"
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
return json.result.stok;
|
|
82
|
+
}
|
|
83
|
+
async getToken() {
|
|
84
|
+
if (this.token && this.token[1] + this.kTokenExpiration > Date.now()) {
|
|
85
|
+
return this.token[0];
|
|
86
|
+
}
|
|
87
|
+
if (this.tokenPromise) {
|
|
88
|
+
return this.tokenPromise();
|
|
89
|
+
}
|
|
90
|
+
this.tokenPromise = async () => {
|
|
91
|
+
try {
|
|
92
|
+
this.log.debug(`[${this.config.name}]`, "Token is expired , requesting new one.");
|
|
93
|
+
const token = await this.fetchToken();
|
|
94
|
+
this.token = [token, Date.now()];
|
|
95
|
+
return token;
|
|
96
|
+
} finally {
|
|
97
|
+
this.tokenPromise = void 0;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
return this.tokenPromise();
|
|
101
|
+
}
|
|
102
|
+
async getTAPOCameraAPIUrl() {
|
|
103
|
+
const token = await this.getToken();
|
|
104
|
+
return `https://${this.config.ipAddress}/stok=${token}/ds`;
|
|
105
|
+
}
|
|
106
|
+
async makeTAPOAPIRequest(req) {
|
|
107
|
+
const reqJson = JSON.stringify(req);
|
|
108
|
+
if (this.pendingAPIRequests.has(reqJson)) {
|
|
109
|
+
return this.pendingAPIRequests.get(reqJson);
|
|
110
|
+
}
|
|
111
|
+
this.log.debug(
|
|
112
|
+
`[${this.config.name}]`,
|
|
113
|
+
"Making new request req =",
|
|
114
|
+
req.params.requests.map((e) => e.method)
|
|
115
|
+
);
|
|
116
|
+
this.pendingAPIRequests.set(
|
|
117
|
+
reqJson,
|
|
118
|
+
(async () => {
|
|
119
|
+
try {
|
|
120
|
+
const url = await this.getTAPOCameraAPIUrl();
|
|
121
|
+
const response = await this.fetch(url, {
|
|
122
|
+
method: "post",
|
|
123
|
+
body: JSON.stringify(req),
|
|
124
|
+
headers: {
|
|
125
|
+
"Content-Type": "application/json"
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
const json = await response.json();
|
|
129
|
+
this.log.debug(`makeTAPOAPIRequest url: ${url}, json: ${JSON.stringify(json)}`);
|
|
130
|
+
if (json.error_code !== 0) {
|
|
131
|
+
this.log.info("Reset token. error_code: ", json.error_code);
|
|
132
|
+
this.token = void 0;
|
|
133
|
+
}
|
|
134
|
+
return json;
|
|
135
|
+
} finally {
|
|
136
|
+
this.pendingAPIRequests.delete(reqJson);
|
|
137
|
+
}
|
|
138
|
+
})()
|
|
139
|
+
);
|
|
140
|
+
return this.pendingAPIRequests.get(reqJson);
|
|
141
|
+
}
|
|
142
|
+
async setLensMaskConfig(value) {
|
|
143
|
+
const json = await this.makeTAPOAPIRequest({
|
|
144
|
+
method: "multipleRequest",
|
|
145
|
+
params: {
|
|
146
|
+
requests: [
|
|
147
|
+
{
|
|
148
|
+
method: "setLensMaskConfig",
|
|
149
|
+
params: {
|
|
150
|
+
lens_mask: {
|
|
151
|
+
lens_mask_info: {
|
|
152
|
+
enabled: value ? "on" : "off"
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
]
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
return json.error_code !== 0;
|
|
161
|
+
}
|
|
162
|
+
async setAlertConfig(value) {
|
|
163
|
+
const json = await this.makeTAPOAPIRequest({
|
|
164
|
+
method: "multipleRequest",
|
|
165
|
+
params: {
|
|
166
|
+
requests: [
|
|
167
|
+
{
|
|
168
|
+
method: "setAlertConfig",
|
|
169
|
+
params: {
|
|
170
|
+
msg_alarm: {
|
|
171
|
+
chn1_msg_alarm_info: {
|
|
172
|
+
enabled: value ? "on" : "off"
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
]
|
|
178
|
+
}
|
|
179
|
+
});
|
|
180
|
+
return json.error_code !== 0;
|
|
181
|
+
}
|
|
182
|
+
async setForceWhitelampState(value) {
|
|
183
|
+
const json = await this.makeTAPOAPIRequest({
|
|
184
|
+
method: "multipleRequest",
|
|
185
|
+
params: {
|
|
186
|
+
requests: [
|
|
187
|
+
{
|
|
188
|
+
method: "setForceWhitelampState",
|
|
189
|
+
params: {
|
|
190
|
+
image: {
|
|
191
|
+
switch: {
|
|
192
|
+
force_wtl_state: value ? "on" : "off"
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
]
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
return json.error_code !== 0;
|
|
201
|
+
}
|
|
202
|
+
async getTAPODeviceInfo() {
|
|
203
|
+
const json = await this.makeTAPOAPIRequest({
|
|
204
|
+
method: "multipleRequest",
|
|
205
|
+
params: {
|
|
206
|
+
requests: [
|
|
207
|
+
{
|
|
208
|
+
method: "getDeviceInfo",
|
|
209
|
+
params: {
|
|
210
|
+
device_info: {
|
|
211
|
+
name: ["basic_info"]
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
]
|
|
216
|
+
}
|
|
217
|
+
});
|
|
218
|
+
const info = json.result.responses[0];
|
|
219
|
+
return info.result.device_info.basic_info;
|
|
220
|
+
}
|
|
221
|
+
async getStatus() {
|
|
222
|
+
const json = await this.makeTAPOAPIRequest({
|
|
223
|
+
method: "multipleRequest",
|
|
224
|
+
params: {
|
|
225
|
+
requests: [
|
|
226
|
+
{
|
|
227
|
+
method: "getAlertConfig",
|
|
228
|
+
params: {
|
|
229
|
+
msg_alarm: {
|
|
230
|
+
name: "chn1_msg_alarm_info"
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
method: "getLensMaskConfig",
|
|
236
|
+
params: {
|
|
237
|
+
lens_mask: {
|
|
238
|
+
name: "lens_mask_info"
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
},
|
|
242
|
+
{
|
|
243
|
+
method: "getForceWhitelampState",
|
|
244
|
+
params: {
|
|
245
|
+
image: {
|
|
246
|
+
name: "switch"
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
]
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
if (json.error_code !== 0) {
|
|
254
|
+
throw new Error("Camera replied with error");
|
|
255
|
+
}
|
|
256
|
+
const alertConfig = json.result.responses.find((r) => r.method === "getAlertConfig");
|
|
257
|
+
const forceWhitelampState = json.result.responses.find(
|
|
258
|
+
(r) => r.method === "getForceWhitelampState"
|
|
259
|
+
);
|
|
260
|
+
const lensMaskConfig = json.result.responses.find(
|
|
261
|
+
(r) => r.method === "getLensMaskConfig"
|
|
262
|
+
);
|
|
263
|
+
return {
|
|
264
|
+
alert: alertConfig.result.msg_alarm.chn1_msg_alarm_info.enabled === "on",
|
|
265
|
+
lensMask: lensMaskConfig.result.lens_mask.lens_mask_info.enabled === "on",
|
|
266
|
+
forceWhiteLamp: forceWhitelampState.result.image.switch.force_wtl_state === "on"
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
271
|
+
0 && (module.exports = {
|
|
272
|
+
TAPOCamera
|
|
273
|
+
});
|
|
274
|
+
//# sourceMappingURL=tapoCamera.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/lib/utils/camera/tapoCamera.ts"],
|
|
4
|
+
"sourcesContent": ["import crypto from \"crypto\";\nimport https, { Agent } from \"https\";\nimport fetch from \"node-fetch\";\nimport { OnvifCamera } from \"./onvifCamera\";\n\ntype CameraConfig = {\n name: string;\n ipAddress: 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};\nexport class TAPOCamera extends OnvifCamera {\n private readonly kTokenExpiration = 1000 * 60 * 60; // 1h\n private readonly kStreamPort = 554;\n private readonly httpsAgent: Agent;\n\n private readonly hashedPassword: string;\n private token: [string, number] | undefined;\n private tokenPromise: (() => Promise<string>) | undefined;\n\n constructor(protected readonly log: any, protected readonly config: CameraConfig) {\n super(log, config);\n\n this.httpsAgent = new https.Agent({\n rejectUnauthorized: false,\n });\n this.hashedPassword = crypto.createHash(\"md5\").update(config.password).digest(\"hex\").toUpperCase();\n }\n\n fetch(url: string, data: object) {\n return fetch(url, {\n ...data,\n agent: this.httpsAgent,\n });\n }\n\n getTapoAPICredentials() {\n return {\n username: \"admin\",\n password: this.hashedPassword,\n };\n }\n\n getAuthenticatedStreamUrl(lowQuality: boolean) {\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 async fetchToken(): Promise<string> {\n this.log.debug(`[${this.config.name}]`, \"Fetching new token\");\n\n const response = await this.fetch(`https://${this.config.ipAddress}/`, {\n method: \"post\",\n body: JSON.stringify({\n method: \"login\",\n params: this.getTapoAPICredentials(),\n }),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n\n const json = (await response.json()) as {\n result: { stok: string; user_group: string };\n error_code: number;\n };\n\n if (!json.result.stok) {\n throw new Error(\n \"Unable to find token in response, probably your credentials are not valid. Please make sure you set your TAPO Cloud password\",\n );\n }\n\n return json.result.stok;\n }\n\n async getToken(): Promise<string> {\n if (this.token && this.token[1] + this.kTokenExpiration > Date.now()) {\n return this.token[0];\n }\n\n if (this.tokenPromise) {\n return this.tokenPromise();\n }\n\n this.tokenPromise = async () => {\n try {\n this.log.debug(`[${this.config.name}]`, \"Token is expired , requesting new one.\");\n\n const token = await this.fetchToken();\n this.token = [token, Date.now()];\n return token;\n } finally {\n this.tokenPromise = undefined;\n }\n };\n return this.tokenPromise();\n }\n\n private async getTAPOCameraAPIUrl() {\n const token = await this.getToken();\n return `https://${this.config.ipAddress}/stok=${token}/ds`;\n }\n\n private pendingAPIRequests: Map<string, Promise<TAPOCameraResponse>> = new Map();\n\n private async makeTAPOAPIRequest(req: TAPOCameraRequest) {\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(\n `[${this.config.name}]`,\n \"Making new request req =\",\n req.params.requests.map((e) => e.method),\n );\n\n this.pendingAPIRequests.set(\n reqJson,\n (async () => {\n try {\n const url = await this.getTAPOCameraAPIUrl();\n\n const response = await this.fetch(url, {\n method: \"post\",\n body: JSON.stringify(req),\n headers: {\n \"Content-Type\": \"application/json\",\n },\n });\n const json = (await response.json()) as TAPOCameraResponse;\n this.log.debug(`makeTAPOAPIRequest url: ${url}, json: ${JSON.stringify(json)}`);\n if (json.error_code !== 0) {\n // Because of the token error when the camera comes back from no response.\n this.log.info(\"Reset token. error_code: \", json.error_code);\n this.token = undefined;\n }\n\n return json;\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 const json = await this.makeTAPOAPIRequest({\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 return json.error_code !== 0;\n }\n\n async setAlertConfig(value: boolean) {\n const json = await this.makeTAPOAPIRequest({\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.makeTAPOAPIRequest({\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\n async getTAPODeviceInfo() {\n const json = await this.makeTAPOAPIRequest({\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; forceWhiteLamp: boolean }> {\n const json = await this.makeTAPOAPIRequest({\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\n if (json.error_code !== 0) {\n throw new Error(\"Camera replied with error\");\n }\n\n const alertConfig = json.result.responses.find((r) => r.method === \"getAlertConfig\") as TAPOCameraResponseGetAlert;\n\n const forceWhitelampState = json.result.responses.find(\n (r) => r.method === \"getForceWhitelampState\",\n ) as TAPOCameraResponseGetForce;\n const lensMaskConfig = json.result.responses.find(\n (r) => r.method === \"getLensMaskConfig\",\n ) 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.switch.force_wtl_state === \"on\",\n };\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["https", "crypto", "fetch"]
|
|
7
|
+
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
22
|
+
mod
|
|
23
|
+
));
|
|
24
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
25
|
+
var camera_exports = {};
|
|
26
|
+
__export(camera_exports, {
|
|
27
|
+
default: () => camera
|
|
28
|
+
});
|
|
29
|
+
module.exports = __toCommonJS(camera_exports);
|
|
30
|
+
var import_p100 = __toESM(require("./p100"));
|
|
31
|
+
class camera extends import_p100.default {
|
|
32
|
+
constructor(log, ipAddress, email, password, timeout) {
|
|
33
|
+
super(log, ipAddress, email, password, timeout);
|
|
34
|
+
this.log = log;
|
|
35
|
+
this.ipAddress = ipAddress;
|
|
36
|
+
this.email = email;
|
|
37
|
+
this.password = password;
|
|
38
|
+
this.timeout = timeout;
|
|
39
|
+
this.log.debug("Constructing Camera on host: " + ipAddress);
|
|
40
|
+
}
|
|
41
|
+
async getDeviceInfo() {
|
|
42
|
+
return super.getDeviceInfo().then(() => {
|
|
43
|
+
return this.getSysInfo();
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
async setAlertConfig(enabled) {
|
|
47
|
+
const enabledString = enabled ? "on" : "off";
|
|
48
|
+
const payload = `{
|
|
49
|
+
"method": "multipleRequest",
|
|
50
|
+
"params": {
|
|
51
|
+
"requests": [
|
|
52
|
+
{
|
|
53
|
+
"method": "setAlertConfig",
|
|
54
|
+
"params": {
|
|
55
|
+
"msg_alarm": {
|
|
56
|
+
"chn1_msg_alarm_info": {
|
|
57
|
+
"alarm_type": "0",
|
|
58
|
+
"alarm_mode": ["sound"],
|
|
59
|
+
"enabled": "${enabledString}",
|
|
60
|
+
"light_type": "1"
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"requestTimeMils": ${Math.round(Date.now() * 1e3)}
|
|
64
|
+
}
|
|
65
|
+
}]}}`;
|
|
66
|
+
return this.sendRequest(payload);
|
|
67
|
+
}
|
|
68
|
+
async setLensMaskConfig(enabled) {
|
|
69
|
+
const enabledString = enabled ? "on" : "off";
|
|
70
|
+
const payload = `{
|
|
71
|
+
"method": "multipleRequest",
|
|
72
|
+
"params": {
|
|
73
|
+
"requests": [
|
|
74
|
+
{
|
|
75
|
+
"method": "setLensMaskConfig",
|
|
76
|
+
"params": {
|
|
77
|
+
"lens_mask": {
|
|
78
|
+
"lens_mask_info": {
|
|
79
|
+
"enabled": "${enabledString}"
|
|
80
|
+
}
|
|
81
|
+
},
|
|
82
|
+
"requestTimeMils": ${Math.round(Date.now() * 1e3)}
|
|
83
|
+
}
|
|
84
|
+
}]}}`;
|
|
85
|
+
return this.sendRequest(payload);
|
|
86
|
+
}
|
|
87
|
+
setSysInfo(sysInfo) {
|
|
88
|
+
this._lightSysInfo = sysInfo;
|
|
89
|
+
this._lightSysInfo.last_update = Date.now();
|
|
90
|
+
}
|
|
91
|
+
getSysInfo() {
|
|
92
|
+
return this._lightSysInfo;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
96
|
+
0 && (module.exports = {});
|
|
97
|
+
//# sourceMappingURL=camera.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/lib/utils/camera.ts"],
|
|
4
|
+
"sourcesContent": ["import P100 from \"./p100\";\nimport { LightSysinfo } from \"./types\";\n\nexport default class camera extends P100 {\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 Camera on host: \" + ipAddress);\n }\n\n async getDeviceInfo(): Promise<LightSysinfo> {\n return super.getDeviceInfo().then(() => {\n return this.getSysInfo();\n });\n }\n\n async setAlertConfig(enabled: boolean): Promise<boolean> {\n const enabledString = enabled ? \"on\" : \"off\";\n const payload = `{\n \"method\": \"multipleRequest\",\n \"params\": {\n \"requests\": [\n {\n \"method\": \"setAlertConfig\",\n \"params\": {\n \"msg_alarm\": {\n \"chn1_msg_alarm_info\": {\n \"alarm_type\": \"0\",\n \"alarm_mode\": [\"sound\"],\n \"enabled\": \"${enabledString}\",\n \"light_type\": \"1\"\n }\n },\n \"requestTimeMils\": ${Math.round(Date.now() * 1000)}\n }\n }]}}`;\n return this.sendRequest(payload);\n }\n async setLensMaskConfig(enabled: boolean): Promise<boolean> {\n const enabledString = enabled ? \"on\" : \"off\";\n const payload = `{\n \"method\": \"multipleRequest\",\n \"params\": {\n \"requests\": [\n {\n \"method\": \"setLensMaskConfig\",\n \"params\": {\n \"lens_mask\": {\n \"lens_mask_info\": {\n \"enabled\": \"${enabledString}\"\n }\n },\n \"requestTimeMils\": ${Math.round(Date.now() * 1000)}\n }\n }]}}`;\n return this.sendRequest(payload);\n }\n\n protected setSysInfo(sysInfo: LightSysinfo) {\n this._lightSysInfo = sysInfo;\n this._lightSysInfo.last_update = Date.now();\n }\n\n public getSysInfo(): LightSysinfo {\n return this._lightSysInfo;\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kBAAiB;AAGjB,MAAO,eAA6B,YAAAA,QAAK;AAAA,EACvC,YACkB,KACA,WACA,OACA,UACA,SAChB;AACA,UAAM,KAAK,WAAW,OAAO,UAAU,OAAO;AAN9B;AACA;AACA;AACA;AACA;AAGhB,SAAK,IAAI,MAAM,kCAAkC,SAAS;AAAA,EAC5D;AAAA,EAEA,MAAM,gBAAuC;AAC3C,WAAO,MAAM,cAAc,EAAE,KAAK,MAAM;AACtC,aAAO,KAAK,WAAW;AAAA,IACzB,CAAC;AAAA,EACH;AAAA,EAEA,MAAM,eAAe,SAAoC;AACvD,UAAM,gBAAgB,UAAU,OAAO;AACvC,UAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BAWM;AAAA;AAAA;AAAA;AAAA,6BAIG,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAAA;AAAA;AAGrD,WAAO,KAAK,YAAY,OAAO;AAAA,EACjC;AAAA,EACA,MAAM,kBAAkB,SAAoC;AAC1D,UAAM,gBAAgB,UAAU,OAAO;AACvC,UAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,0BASM;AAAA;AAAA;AAAA,6BAGG,KAAK,MAAM,KAAK,IAAI,IAAI,GAAI;AAAA;AAAA;AAGrD,WAAO,KAAK,YAAY,OAAO;AAAA,EACjC;AAAA,EAEU,WAAW,SAAuB;AAC1C,SAAK,gBAAgB;AACrB,SAAK,cAAc,cAAc,KAAK,IAAI;AAAA,EAC5C;AAAA,EAEO,aAA2B;AAChC,WAAO,KAAK;AAAA,EACd;AACF;",
|
|
6
|
+
"names": ["P100"]
|
|
7
|
+
}
|
package/build/main.js
CHANGED
|
@@ -23,6 +23,7 @@ var import_crypto = __toESM(require("crypto"));
|
|
|
23
23
|
var import_https = __toESM(require("https"));
|
|
24
24
|
var import_uuid = require("uuid");
|
|
25
25
|
var import_json2iob = __toESM(require("./lib/json2iob"));
|
|
26
|
+
var import_tapoCamera = require("./lib/utils/camera/tapoCamera");
|
|
26
27
|
var import_l510e = __toESM(require("./lib/utils/l510e"));
|
|
27
28
|
var import_l530 = __toESM(require("./lib/utils/l530"));
|
|
28
29
|
var import_p100 = __toESM(require("./lib/utils/p100"));
|
|
@@ -153,7 +154,7 @@ class Tapo extends utils.Adapter {
|
|
|
153
154
|
cloudPassword: this.config.password,
|
|
154
155
|
terminalUUID: this.termId,
|
|
155
156
|
cloudUserName: this.config.username,
|
|
156
|
-
terminalName: "
|
|
157
|
+
terminalName: "ioBroker",
|
|
157
158
|
terminalMeta: "3",
|
|
158
159
|
appType: "TP-Link_Tapo_iOS"
|
|
159
160
|
});
|
|
@@ -261,7 +262,7 @@ class Tapo extends utils.Adapter {
|
|
|
261
262
|
});
|
|
262
263
|
}
|
|
263
264
|
async getDeviceList() {
|
|
264
|
-
const body = '{"index":0,"deviceTypeList":["SMART.TAPOBULB","SMART.TAPOPLUG","SMART.IPCAMERA","SMART.TAPOHUB","SMART.TAPOSENSOR","SMART.TAPOSWITCH"],"limit":
|
|
265
|
+
const body = '{"index":0,"deviceTypeList":["SMART.TAPOBULB","SMART.TAPOPLUG","SMART.IPCAMERA","SMART.TAPOHUB","SMART.TAPOSENSOR","SMART.TAPOSWITCH"],"limit":30}';
|
|
265
266
|
const md5 = import_crypto.default.createHash("md5").update(body).digest("base64");
|
|
266
267
|
this.log.debug(md5);
|
|
267
268
|
const content = md5 + "\n9999999999\nfee66616-58dd-4bcb-be79-fe092d800a21\n/api/v2/common/getDeviceListByPage";
|
|
@@ -289,7 +290,10 @@ class Tapo extends utils.Adapter {
|
|
|
289
290
|
for (const device of (_b = res.data.result) == null ? void 0 : _b.deviceList) {
|
|
290
291
|
const id = device.deviceId;
|
|
291
292
|
this.devices[id] = device;
|
|
292
|
-
|
|
293
|
+
let name = device.alias;
|
|
294
|
+
if (this.isBase64(device.alias)) {
|
|
295
|
+
name = Buffer.from(device.alias, "base64").toString("utf8");
|
|
296
|
+
}
|
|
293
297
|
await this.setObjectNotExistsAsync(id, {
|
|
294
298
|
type: "device",
|
|
295
299
|
common: {
|
|
@@ -307,6 +311,9 @@ class Tapo extends utils.Adapter {
|
|
|
307
311
|
const remoteArray = [
|
|
308
312
|
{ command: "refresh", name: "True = Refresh" },
|
|
309
313
|
{ command: "setPowerState", name: "True = On, False = Off" },
|
|
314
|
+
{ command: "setAlertConfig", name: "True = On, False = Off" },
|
|
315
|
+
{ command: "setLensMaskConfig", name: "True = On, False = Off" },
|
|
316
|
+
{ command: "setForceWhitelampState", name: "True = On, False = Off" },
|
|
310
317
|
{
|
|
311
318
|
command: "setBrightness",
|
|
312
319
|
name: "Set Brightness for Light devices",
|
|
@@ -373,7 +380,22 @@ class Tapo extends utils.Adapter {
|
|
|
373
380
|
error.response && this.log.error(JSON.stringify(error.response.data));
|
|
374
381
|
});
|
|
375
382
|
if (!this.devices[id].ip) {
|
|
376
|
-
const body2 = `{
|
|
383
|
+
const body2 = `{
|
|
384
|
+
"requestData": {
|
|
385
|
+
"method": "multipleRequest",
|
|
386
|
+
"params": {
|
|
387
|
+
"requests": [{
|
|
388
|
+
"method": "getDeviceIpAddress",
|
|
389
|
+
"params": {
|
|
390
|
+
"network": {
|
|
391
|
+
"name": "wan"
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
}]
|
|
395
|
+
}
|
|
396
|
+
},
|
|
397
|
+
"deviceId": "${id}"
|
|
398
|
+
}`;
|
|
377
399
|
const md52 = import_crypto.default.createHash("md5").update(body2).digest("base64");
|
|
378
400
|
this.log.debug(md52);
|
|
379
401
|
const content2 = md52 + "\n9999999999\nfee66616-58dd-4bcb-be79-fe092d800a21\n/api/v2/common/passthrough";
|
|
@@ -391,13 +413,16 @@ class Tapo extends utils.Adapter {
|
|
|
391
413
|
},
|
|
392
414
|
data: body2
|
|
393
415
|
}).then(async (res2) => {
|
|
394
|
-
var _a2, _b2;
|
|
416
|
+
var _a2, _b2, _c, _d, _e, _f;
|
|
395
417
|
this.log.debug(JSON.stringify(res2.data));
|
|
396
418
|
let result = {};
|
|
397
419
|
if (res2.data.error_code) {
|
|
398
420
|
this.log.error(JSON.stringify(res2.data));
|
|
399
421
|
} else {
|
|
400
|
-
result = (_b2 = (_a2 = res2.data.result) == null ? void 0 : _a2.responseData) == null ? void 0 : _b2.result;
|
|
422
|
+
result = (_f = (_e = (_d = (_c = (_b2 = (_a2 = res2.data.result) == null ? void 0 : _a2.responseData) == null ? void 0 : _b2.result) == null ? void 0 : _c.responses[0]) == null ? void 0 : _d.result) == null ? void 0 : _e.network) == null ? void 0 : _f.wan;
|
|
423
|
+
result = result.ipaddr;
|
|
424
|
+
delete result[".name"];
|
|
425
|
+
delete result[".type"];
|
|
401
426
|
this.devices[id] = { ...this.devices[id], ...result };
|
|
402
427
|
}
|
|
403
428
|
}).catch((error) => {
|
|
@@ -463,6 +488,38 @@ class Tapo extends utils.Adapter {
|
|
|
463
488
|
deviceObject = new import_l530.default(this.log, device.ip, this.config.username, this.config.password, 2);
|
|
464
489
|
} else if (device.deviceName.startsWith("L") || device.deviceName.startsWith("KL")) {
|
|
465
490
|
deviceObject = new import_l510e.default(this.log, device.ip, this.config.username, this.config.password, 2);
|
|
491
|
+
} else if (device.deviceName.startsWith("C")) {
|
|
492
|
+
deviceObject = new import_tapoCamera.TAPOCamera(this.log, {
|
|
493
|
+
name: device.deviceName,
|
|
494
|
+
ipAddress: device.ip,
|
|
495
|
+
password: this.config.password,
|
|
496
|
+
streamUser: this.config.streamusername,
|
|
497
|
+
streamPassword: this.config.streampassword,
|
|
498
|
+
disableStreaming: true
|
|
499
|
+
});
|
|
500
|
+
this.deviceObjects[id] = deviceObject;
|
|
501
|
+
const deviceInfo = await deviceObject.getDeviceInfo();
|
|
502
|
+
this.log.info(`${id} Received device info ${JSON.stringify(deviceInfo)}`);
|
|
503
|
+
this.log.debug(JSON.stringify(deviceInfo));
|
|
504
|
+
this.json2iob.parse(id, deviceInfo);
|
|
505
|
+
const eventEmitter = await deviceObject.getEventEmitter();
|
|
506
|
+
await this.setObjectNotExistsAsync(id + ".motionEvent", {
|
|
507
|
+
type: "state",
|
|
508
|
+
common: {
|
|
509
|
+
name: "Motion detected",
|
|
510
|
+
type: "boolean",
|
|
511
|
+
role: "boolean",
|
|
512
|
+
def: false,
|
|
513
|
+
write: false,
|
|
514
|
+
read: true
|
|
515
|
+
},
|
|
516
|
+
native: {}
|
|
517
|
+
});
|
|
518
|
+
eventEmitter.addListener("motion", async (motionDetected) => {
|
|
519
|
+
await this.setStateAsync(id + ".motionEvent", motionDetected, true);
|
|
520
|
+
this.log.info(`[${device.deviceName}] "Motion detected" ${motionDetected}`);
|
|
521
|
+
});
|
|
522
|
+
return;
|
|
466
523
|
} else {
|
|
467
524
|
this.log.info(`Unknown device type ${device.deviceName} init as P100`);
|
|
468
525
|
deviceObject = new import_p100.default(this.log, device.ip, this.config.username, this.config.password, 2);
|
|
@@ -501,6 +558,13 @@ class Tapo extends utils.Adapter {
|
|
|
501
558
|
async updateDevices() {
|
|
502
559
|
try {
|
|
503
560
|
for (const deviceId in this.deviceObjects) {
|
|
561
|
+
if (this.deviceObjects[deviceId].getStatus) {
|
|
562
|
+
this.log.debug("Receive camera status");
|
|
563
|
+
const status = await this.deviceObjects[deviceId].getStatus();
|
|
564
|
+
this.log.debug(JSON.stringify(status));
|
|
565
|
+
this.json2iob.parse(deviceId, status);
|
|
566
|
+
continue;
|
|
567
|
+
}
|
|
504
568
|
if (!this.deviceObjects[deviceId]._connected) {
|
|
505
569
|
continue;
|
|
506
570
|
}
|
|
@@ -537,6 +601,16 @@ class Tapo extends utils.Adapter {
|
|
|
537
601
|
this.log.error(error);
|
|
538
602
|
}
|
|
539
603
|
}
|
|
604
|
+
isBase64(str) {
|
|
605
|
+
if (str === "" || str.trim() === "") {
|
|
606
|
+
return false;
|
|
607
|
+
}
|
|
608
|
+
try {
|
|
609
|
+
return btoa(atob(str)) == str;
|
|
610
|
+
} catch (err) {
|
|
611
|
+
return false;
|
|
612
|
+
}
|
|
613
|
+
}
|
|
540
614
|
async sleep(ms) {
|
|
541
615
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
542
616
|
}
|
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 \"./lib/json2iob\";\nimport L510E from \"./lib/utils/l510e\";\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,\n 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} ${initResult}`);\n }\n }\n }\n }\n\n this.log.info(\"Wait for connections\");\n await this.sleep(10000);\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: \"iPhone\",\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 this.session = res.data.result;\n if (this.session.token) {\n this.log.info(\"Login succesfull\");\n this.setState(\"info.connection\", true, true);\n } else {\n this.log.error(\"Login failed\");\n this.log.error(JSON.stringify(res.data));\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\":20}';\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 const name = Buffer.from(device.alias, \"base64\").toString(\"utf8\");\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 {\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.setObjectNotExists(id + \".remote.\" + remote.command, {\n type: \"state\",\n common: {\n name: remote.name || \"\",\n type: remote.type || \"boolean\",\n role: remote.role || \"boolean\",\n def: 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.error(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 = `{\"requestData\":{\"method\":\"get_device_info\",\"terminalUUID\":${this.termId}},\"deviceId\":\"${id}\"}`;\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 = {};\n if (res.data.error_code) {\n this.log.error(JSON.stringify(res.data));\n } else {\n result = res.data.result?.responseData?.result;\n this.devices[id] = { ...this.devices[id], ...result };\n }\n })\n .catch((error) => {\n this.log.error(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} ${initResult}`);\n }\n }\n })\n .catch((error) => {\n this.log.error(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 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.startsWith(\"L\") || device.deviceName.startsWith(\"KL\")) {\n deviceObject = new L510E(this.log, device.ip, this.config.username, this.config.password, 2);\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(() => {\n deviceObject\n .login()\n .then(() => {\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(\"Login failed\");\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]._connected) {\n continue;\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.error(error);\n }\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\") {\n const valueSplit = state.val.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 \"./lib/json2iob\";\nimport { TAPOCamera } from \"./lib/utils/camera/tapoCamera\";\nimport L510E from \"./lib/utils/l510e\";\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,\n 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} ${initResult}`);\n }\n }\n }\n }\n\n this.log.info(\"Wait for connections\");\n await this.sleep(10000);\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 this.session = res.data.result;\n if (this.session.token) {\n this.log.info(\"Login succesfull\");\n this.setState(\"info.connection\", true, true);\n } else {\n this.log.error(\"Login failed\");\n this.log.error(JSON.stringify(res.data));\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 {\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.setObjectNotExists(id + \".remote.\" + remote.command, {\n type: \"state\",\n common: {\n name: remote.name || \"\",\n type: remote.type || \"boolean\",\n role: remote.role || \"boolean\",\n def: 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.error(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 = result.ipaddr;\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.error(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} ${initResult}`);\n }\n }\n })\n .catch((error) => {\n this.log.error(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 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.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\")) {\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 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 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(() => {\n deviceObject\n .login()\n .then(() => {\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(\"Login failed\");\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.error(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\") {\n const valueSplit = state.val.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"]
|
|
7
7
|
}
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "tapo",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.7",
|
|
5
5
|
"news": {
|
|
6
|
+
"0.0.7": {
|
|
7
|
+
"en": "add camera support",
|
|
8
|
+
"de": "Kamera Unterstützung hinzugefügt"
|
|
9
|
+
},
|
|
6
10
|
"0.0.6": {
|
|
7
11
|
"en": "fix Login.",
|
|
8
12
|
"de": "Login gefixt."
|
|
@@ -97,6 +101,8 @@
|
|
|
97
101
|
"username": "",
|
|
98
102
|
"password": "",
|
|
99
103
|
"mfa": "",
|
|
104
|
+
"streamusername": "",
|
|
105
|
+
"streampassword": "",
|
|
100
106
|
"interval": 10
|
|
101
107
|
},
|
|
102
108
|
"objects": [],
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.tapo",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "Adapter for TP-Link Tapo",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "TA2k",
|
|
@@ -20,37 +20,39 @@
|
|
|
20
20
|
"@iobroker/adapter-core": "^2.6.7",
|
|
21
21
|
"axios": "^0.27.2",
|
|
22
22
|
"json-bigint": "^1.0.0",
|
|
23
|
+
"node-fetch": "^2.6.7",
|
|
24
|
+
"onvif": "^0.6.6",
|
|
23
25
|
"qs": "^6.11.0",
|
|
24
26
|
"uuid": "^8.3.2"
|
|
25
27
|
},
|
|
26
28
|
"devDependencies": {
|
|
27
|
-
"@iobroker/adapter-dev": "^1.
|
|
29
|
+
"@iobroker/adapter-dev": "^1.2.0",
|
|
28
30
|
"@iobroker/testing": "^3.0.2",
|
|
29
|
-
"@types/chai": "^4.3.
|
|
31
|
+
"@types/chai": "^4.3.4",
|
|
30
32
|
"@types/chai-as-promised": "^7.1.5",
|
|
31
33
|
"@types/json-bigint": "^1.0.1",
|
|
32
34
|
"@types/mocha": "^9.1.1",
|
|
33
|
-
"@types/node": "^14.18.
|
|
35
|
+
"@types/node": "^14.18.33",
|
|
34
36
|
"@types/proxyquire": "^1.3.28",
|
|
35
37
|
"@types/sinon": "^10.0.13",
|
|
36
|
-
"@types/sinon-chai": "^3.2.
|
|
38
|
+
"@types/sinon-chai": "^3.2.9",
|
|
37
39
|
"@types/uuid": "^8.3.4",
|
|
38
|
-
"@typescript-eslint/eslint-plugin": "^5.
|
|
39
|
-
"@typescript-eslint/parser": "^5.
|
|
40
|
-
"chai": "^4.3.
|
|
40
|
+
"@typescript-eslint/eslint-plugin": "^5.43.0",
|
|
41
|
+
"@typescript-eslint/parser": "^5.43.0",
|
|
42
|
+
"chai": "^4.3.7",
|
|
41
43
|
"chai-as-promised": "^7.1.1",
|
|
42
|
-
"eslint": "^8.
|
|
44
|
+
"eslint": "^8.28.0",
|
|
43
45
|
"eslint-config-prettier": "^8.5.0",
|
|
44
46
|
"eslint-plugin-prettier": "^4.2.1",
|
|
45
|
-
"mocha": "^10.
|
|
47
|
+
"mocha": "^10.1.0",
|
|
46
48
|
"prettier": "^2.7.1",
|
|
47
49
|
"proxyquire": "^2.1.3",
|
|
48
50
|
"rimraf": "^3.0.2",
|
|
49
|
-
"sinon": "^14.0.
|
|
51
|
+
"sinon": "^14.0.2",
|
|
50
52
|
"sinon-chai": "^3.7.0",
|
|
51
53
|
"source-map-support": "^0.5.21",
|
|
52
54
|
"ts-node": "^10.9.1",
|
|
53
|
-
"typescript": "~4.
|
|
55
|
+
"typescript": "~4.9.3"
|
|
54
56
|
},
|
|
55
57
|
"main": "build/main.js",
|
|
56
58
|
"files": [
|