iobroker.eusec 1.3.1 → 1.3.3
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 +9 -0
- package/build/lib/video.js +1 -1
- package/build/lib/video.js.map +2 -2
- package/build/main.js +3 -1
- package/build/main.js.map +2 -2
- package/io-package.json +27 -14
- package/package.json +8 -8
package/README.md
CHANGED
|
@@ -47,6 +47,15 @@ Best is to set the adapter to Debug log mode (see [here](https://bropat.github.i
|
|
|
47
47
|
|
|
48
48
|
## Changelog
|
|
49
49
|
|
|
50
|
+
### 1.3.3 (2024-09-28)
|
|
51
|
+
|
|
52
|
+
* (bropat) Updated version of the package eufy-security-client (3.1.1)
|
|
53
|
+
* (bropat) Further details can be found in the changelog of eufy-security-client (3.1.1)
|
|
54
|
+
|
|
55
|
+
### 1.3.2 (2024-09-10)
|
|
56
|
+
|
|
57
|
+
* (bropat) Fixed issue #440
|
|
58
|
+
|
|
50
59
|
### 1.3.1 (2024-09-08)
|
|
51
60
|
|
|
52
61
|
* (bropat) Fixed issue #436
|
package/build/lib/video.js
CHANGED
|
@@ -268,7 +268,7 @@ ${stderr}`);
|
|
|
268
268
|
}
|
|
269
269
|
});
|
|
270
270
|
};
|
|
271
|
-
const streamToGo2rtc = async (camera, videoStream, audioStream, log,
|
|
271
|
+
const streamToGo2rtc = async (camera, videoStream, audioStream, log, _config, _namespace, _metadata) => {
|
|
272
272
|
const { default: got } = await import("got");
|
|
273
273
|
const api = got.extend({
|
|
274
274
|
hooks: {
|
package/build/lib/video.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/video.ts"],
|
|
4
|
-
"sourcesContent": ["import net from \"net\";\r\nimport path from \"path\";\r\nimport ffmpeg from \"@bropat/fluent-ffmpeg\";\r\nimport pathToFfmpeg from \"ffmpeg-for-homebridge\";\r\nimport { Readable } from \"stream\";\r\nimport { StreamMetadata, AudioCodec, VideoCodec } from \"eufy-security-client\";\r\nimport { tmpdir } from \"os\";\r\nimport fse from \"fs-extra\";\r\n\r\nimport stream from \"node:stream\";\r\nimport {pipeline as streamPipeline} from \"node:stream/promises\";\r\n\r\nimport { ioBrokerLogger } from \"./log\";\r\nimport { getShortUrl, lowestUnusedNumber } from \"./utils\";\r\n\r\nclass UniversalStream {\r\n\r\n public url: string;\r\n private static socks = new Set<number>();\r\n private server: net.Server;\r\n private sock_id: number;\r\n\r\n constructor (namespace: string, onSocket: ((socket: net.Socket) => void) | undefined) {\r\n let sockpath = \"\";\r\n\r\n const unique_sock_id = lowestUnusedNumber([...UniversalStream.socks], 1);\r\n UniversalStream.socks.add(unique_sock_id);\r\n this.sock_id = unique_sock_id;\r\n\r\n if (process.platform === \"win32\") {\r\n const pipePrefix = \"\\\\\\\\.\\\\pipe\\\\\";\r\n const pipeName = `node-webrtc.${namespace}.${unique_sock_id}.sock`;\r\n\r\n sockpath = path.join(pipePrefix, pipeName);\r\n this.url = sockpath;\r\n }\r\n else {\r\n const pipeName = `${namespace}.${unique_sock_id}.sock`;\r\n sockpath = path.join(tmpdir(), pipeName);\r\n this.url = \"unix:\" + sockpath;\r\n\r\n try {\r\n if (fse.existsSync(sockpath))\r\n fse.unlinkSync(sockpath);\r\n } catch(error) {\r\n }\r\n }\r\n\r\n this.server = net.createServer(onSocket);\r\n this.server.listen(sockpath);\r\n this.server.on(\"error\", () => {});\r\n }\r\n\r\n public close(): void {\r\n if (this.server)\r\n this.server.close();\r\n UniversalStream.socks.delete(this.sock_id);\r\n }\r\n\r\n}\r\n\r\nexport const StreamInput = function(namespace: string, stream: NodeJS.ReadableStream): UniversalStream {\r\n return new UniversalStream(namespace, (socket: net.Socket) => stream.pipe(socket, { end: true }).on(\"error\", (_error) => {\r\n //TODO: log error\r\n }));\r\n}\r\n\r\nexport const StreamOutput = function(namespace: string, stream: NodeJS.WritableStream): UniversalStream {\r\n return new UniversalStream(namespace, (socket: net.Socket) => socket.pipe(stream, { end: true }).on(\"error\", (_error) => {\r\n //TODO: log error\r\n }));\r\n}\r\n\r\nexport const ffmpegPreviewImage = (config: ioBroker.AdapterConfig, input:string, output: string, log: ioBrokerLogger, skip_seconds = 2.0): Promise<void> => {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n if (pathToFfmpeg) {\r\n ffmpeg.setFfmpegPath(pathToFfmpeg);\r\n\r\n ffmpeg()\r\n .withProcessOptions({\r\n detached: true\r\n })\r\n .addOptions([\r\n `-ss ${skip_seconds}`,\r\n \"-frames:v 1\"\r\n ])\r\n .input(input)\r\n .inputFormat(\"hls\")\r\n .outputFormat(\"image2\")\r\n .output(output)\r\n .on(\"error\", function(err, stdout, stderr) {\r\n log.error(`ffmpegPreviewImage(): An error occurred: ${err.message}`);\r\n log.error(`ffmpegPreviewImage(): ffmpeg output:\\n${stdout}`);\r\n log.error(`ffmpegPreviewImage(): ffmpeg stderr:\\n${stderr}`);\r\n reject(err);\r\n })\r\n .on(\"end\", () => {\r\n log.debug(\"ffmpegPreviewImage(): Preview image generated!\");\r\n resolve();\r\n })\r\n .run();\r\n } else {\r\n reject(new Error(\"ffmpeg binary not found\"));\r\n }\r\n } catch (error) {\r\n log.error(`ffmpegPreviewImage(): Error: ${error}`);\r\n reject(error);\r\n }\r\n });\r\n}\r\n\r\nexport const ffmpegStreamToHls = (config: ioBroker.AdapterConfig, namespace: string, metadata: StreamMetadata, videoStream: Readable, audioStream: Readable, output: string, log: ioBrokerLogger): Promise<void> => {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n if (pathToFfmpeg) {\r\n ffmpeg.setFfmpegPath(pathToFfmpeg);\r\n\r\n videoStream.on(\"error\", (error) => {\r\n log.error(\"ffmpegStreamToHls(): Videostream Error\", error);\r\n });\r\n\r\n audioStream.on(\"error\", (error) => {\r\n log.error(\"ffmpegStreamToHls(): Audiostream Error\", error);\r\n });\r\n\r\n const uVideoStream = StreamInput(namespace, videoStream);\r\n const uAudioStream = StreamInput(namespace, audioStream);\r\n\r\n let videoFormat = \"h264\";\r\n let audioFormat = \"\";\r\n const options: string[] = [\r\n \"-hls_init_time 0\",\r\n \"-hls_time 2\",\r\n \"-hls_segment_type mpegts\",\r\n //\"-start_number 1\",\r\n \"-sc_threshold 0\",\r\n `-g ${metadata.videoFPS}`,\r\n \"-fflags genpts+nobuffer+flush_packets\",\r\n //\"-flush_packets 1\",\r\n \"-hls_playlist_type event\"\r\n //\"-hls_flags split_by_time\"\r\n ];\r\n\r\n switch(metadata.videoCodec) {\r\n case VideoCodec.H264:\r\n videoFormat = \"h264\";\r\n break;\r\n case VideoCodec.H265:\r\n videoFormat = \"hevc\";\r\n break;\r\n }\r\n\r\n switch(metadata.audioCodec) {\r\n case AudioCodec.AAC:\r\n audioFormat = \"aac\";\r\n break;\r\n }\r\n\r\n const command = ffmpeg()\r\n .withProcessOptions({\r\n detached: true\r\n })\r\n .input(uVideoStream.url)\r\n .inputFormat(videoFormat)\r\n .inputFps(metadata.videoFPS);\r\n if (audioFormat !== \"\") {\r\n command.input(uAudioStream.url)\r\n .inputFormat(audioFormat)\r\n .videoCodec(\"copy\")\r\n .audioCodec(\"copy\");\r\n options.push(\"-absf aac_adtstoasc\");\r\n } else {\r\n log.warn(`ffmpegStreamToHls(): Not support audio codec or unknown audio codec (${AudioCodec[metadata.audioCodec]})`);\r\n }\r\n command.output(output)\r\n .addOptions(options)\r\n .on(\"error\", function(err, stdout, stderr) {\r\n log.error(`ffmpegStreamToHls(): An error occurred: ${err.message}`);\r\n log.error(`ffmpegStreamToHls(): ffmpeg output:\\n${stdout}`);\r\n log.error(`ffmpegStreamToHls(): ffmpeg stderr:\\n${stderr}`);\r\n uVideoStream.close();\r\n uAudioStream.close();\r\n reject(err);\r\n })\r\n .on(\"end\", () => {\r\n log.debug(\"ffmpegStreamToHls(): Processing finished!\");\r\n uVideoStream.close();\r\n uAudioStream.close();\r\n resolve();\r\n });\r\n command.run();\r\n } else {\r\n reject(new Error(\"ffmpeg binary not found\"));\r\n }\r\n } catch (error) {\r\n log.error(`ffmpegStreamToHls(): Error: ${error}`);\r\n reject(error);\r\n }\r\n });\r\n}\r\n\r\nexport const ffmpegStreamToGo2rtc = (config: ioBroker.AdapterConfig, namespace: string, camera: string, metadata: StreamMetadata, videoStream: Readable, audioStream: Readable, log: ioBrokerLogger): Promise<void> => {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n if (pathToFfmpeg) {\r\n ffmpeg.setFfmpegPath(pathToFfmpeg);\r\n\r\n videoStream.on(\"error\", (error) => {\r\n log.error(\"ffmpegStreamToGo2rtc(): Videostream Error\", error);\r\n });\r\n\r\n audioStream.on(\"error\", (error) => {\r\n log.error(\"ffmpegStreamToGo2rtc(): Audiostream Error\", error);\r\n });\r\n\r\n //TODO: For debugging purposes\r\n /*const outputVFile = path.resolve(__dirname, \"../../video-stream.dump\");\r\n videoStream.pipe(fse.createWriteStream(outputVFile)).on(\"finish\", () => {\r\n log.debug(\"videoStream dump finished!\");\r\n log.info(\"Manually test the output by running# ffplay output/video-stream.dump\");\r\n });\r\n const outputAFile = path.resolve(__dirname, \"../../audio-stream.dump\");\r\n audioStream.pipe(fse.createWriteStream(outputAFile)).on(\"finish\", () => {\r\n log.debug(\"audioStream dump finished!\");\r\n log.info(\"Manually test the output by running# ffplay output/audio-stream.dump\");\r\n });*/\r\n\r\n const uVideoStream = StreamInput(namespace, videoStream);\r\n const uAudioStream = StreamInput(namespace, audioStream);\r\n\r\n let videoFormat = \"h264\";\r\n let audioFormat = \"\";\r\n const options: string[] = [\r\n \"-rtsp_transport tcp\",\r\n \"-sc_threshold 0\",\r\n \"-fflags genpts+nobuffer+flush_packets\",\r\n //\"-rtpflags latm\",\r\n ];\r\n\r\n switch(metadata.videoCodec) {\r\n case VideoCodec.H264:\r\n videoFormat = \"h264\";\r\n break;\r\n case VideoCodec.H265:\r\n videoFormat = \"hevc\";\r\n break;\r\n }\r\n\r\n switch(metadata.audioCodec) {\r\n case AudioCodec.AAC:\r\n audioFormat = \"aac\";\r\n break;\r\n }\r\n\r\n const command = ffmpeg()\r\n .withProcessOptions({\r\n detached: true\r\n })\r\n .input(uVideoStream.url)\r\n .inputFormat(videoFormat);\r\n if (metadata.videoFPS > 0 ) {\r\n options.push(`-g ${metadata.videoFPS}`);\r\n command.inputFps(metadata.videoFPS);\r\n }\r\n command.videoCodec(\"copy\");\r\n if (audioFormat !== \"\") {\r\n command.input(uAudioStream.url)\r\n .inputFormat(audioFormat)\r\n //.audioCodec(\"copy\");\r\n //.audioCodec(\"aac\");\r\n .audioCodec(\"opus\");\r\n } else {\r\n log.warn(`ffmpegStreamToGo2rtc(): Not support audio codec or unknown audio codec (${AudioCodec[metadata.audioCodec]})`);\r\n }\r\n command.output(`rtsp://localhost:${config.go2rtc_rtsp_port}/${camera}`)\r\n .outputFormat(\"rtsp\")\r\n .addOptions(options)\r\n .on(\"start\", (commandline) => {\r\n log.debug(`ffmpegStreamToGo2rtc(): commandline: ${commandline}`);\r\n })\r\n .on(\"error\", function(err, stdout, stderr) {\r\n log.error(`ffmpegStreamToGo2rtc(): An error occurred: ${err.message}`);\r\n log.error(`ffmpegStreamToGo2rtc(): ffmpeg output:\\n${stdout}`);\r\n log.error(`ffmpegStreamToGo2rtc(): ffmpeg stderr:\\n${stderr}`);\r\n uVideoStream.close();\r\n uAudioStream.close();\r\n reject(err);\r\n })\r\n .on(\"end\", () => {\r\n log.debug(\"ffmpegStreamToGo2rtc(): Processing finished!\");\r\n uVideoStream.close();\r\n uAudioStream.close();\r\n resolve();\r\n });\r\n command.run();\r\n } else {\r\n reject(new Error(\"ffmpeg binary not found\"));\r\n }\r\n } catch (error) {\r\n log.error(`ffmpegStreamToGo2rtc(): Error: ${error}`);\r\n reject(error);\r\n }\r\n });\r\n}\r\n\r\nexport const streamToGo2rtc = async (camera: string, videoStream: Readable, audioStream: Readable, log: ioBrokerLogger, config: ioBroker.AdapterConfig, namespace: string, metadata: StreamMetadata): Promise<Array<PromiseSettledResult<void>>> => {\r\n const { default: got } = await import(\"got\");\r\n const api = got.extend({\r\n hooks: {\r\n beforeError: [\r\n error => {\r\n const { response, options } = error;\r\n const { method, url, prefixUrl } = options;\r\n const shortUrl = getShortUrl(typeof url === \"string\" ? new URL(url) : url === undefined ? new URL(\"\") : url, typeof prefixUrl === \"string\" ? prefixUrl : prefixUrl.toString());\r\n const body = response?.body ? response.body : error.message;\r\n error.message = `${error.message} | method: ${method} url: ${shortUrl}`;\r\n if (response?.body) {\r\n error.message = `${error.message} body: ${body}`;\r\n }\r\n return error;\r\n }\r\n ],\r\n }\r\n });\r\n videoStream.on(\"error\", (error) => {\r\n log.error(\"streamToGo2rtc(): Videostream Error\", error);\r\n });\r\n\r\n audioStream.on(\"error\", (error) => {\r\n log.error(\"streamToGo2rtc(): Audiostream Error\", error);\r\n });\r\n return Promise.allSettled([\r\n streamPipeline(\r\n videoStream,\r\n api.stream.post(`http://localhost:1984/api/stream?dst=${camera}`).on(\"error\", (error: any) => {\r\n if (!(error.response?.body as string)?.startsWith(\"EOF\")) {\r\n log.error(`streamToGo2rtc(): Got Videostream Error: ${error.message}`);\r\n }\r\n }),\r\n new stream.PassThrough()\r\n ),\r\n streamPipeline(\r\n audioStream,\r\n api.stream.post(`http://localhost:1984/api/stream?dst=${camera}`).on(\"error\", (error: any) => {\r\n if (!(error.response?.body as string)?.startsWith(\"EOF\")) {\r\n log.error(`streamToGo2rtc(): Got Audiostream Error: ${error.message}`);\r\n }\r\n }),\r\n new stream.PassThrough()\r\n )\r\n // Alternative implementation in case of go2rtc audio bitstream isn't working (<= 1.8.5)\r\n /*new Promise<void>((resolve, reject) => {\r\n try {\r\n if (pathToFfmpeg) {\r\n ffmpeg.setFfmpegPath(pathToFfmpeg);\r\n\r\n const uAudioStream = StreamInput(namespace, audioStream);\r\n\r\n let audioFormat = \"\";\r\n const options: string[] = [\r\n \"-rtsp_transport tcp\",\r\n \"-fflags genpts+nobuffer+flush_packets\",\r\n //\"-rtpflags latm\",\r\n //\"-compression_level 5\",\r\n \"-application lowdelay\",\r\n ];\r\n\r\n switch(metadata.audioCodec) {\r\n case AudioCodec.AAC:\r\n audioFormat = \"aac\";\r\n break;\r\n }\r\n\r\n const command = ffmpeg()\r\n .withProcessOptions({\r\n detached: true\r\n });\r\n\r\n if (audioFormat !== \"\") {\r\n command.input(uAudioStream.url)\r\n .inputFormat(audioFormat)\r\n .audioCodec(\"opus\");\r\n } else {\r\n log.warn(`streamToGo2rtc(): ffmpeg - Not support audio codec or unknown audio codec (${AudioCodec[metadata.audioCodec]})`);\r\n }\r\n command.output(`rtsp://localhost:${config.go2rtc_rtsp_port}/${camera}`)\r\n .outputFormat(\"rtsp\")\r\n .addOptions(options)\r\n .on(\"start\", (commandline) => {\r\n log.debug(`streamToGo2rtc(): ffmpeg - commandline: ${commandline}`);\r\n })\r\n .on(\"error\", function(err, stdout, stderr) {\r\n log.error(`streamToGo2rtc(): ffmpeg - An error occurred: ${err.message}`);\r\n log.error(`streamToGo2rtc(): ffmpeg output:\\n${stdout}`);\r\n log.error(`streamToGo2rtc(): ffmpeg stderr:\\n${stderr}`);\r\n uAudioStream.close();\r\n reject(err);\r\n })\r\n .on(\"end\", (stdout, stderr) => {\r\n log.debug(`streamToGo2rtc(): ffmpeg output:\\n${stdout}`);\r\n log.debug(`streamToGo2rtc(): ffmpeg stderr:\\n${stderr}`);\r\n log.debug(\"streamToGo2rtc(): Processing finished!\");\r\n uAudioStream.close();\r\n resolve();\r\n });\r\n command.run();\r\n } else {\r\n reject(new Error(\"ffmpeg binary not found\"));\r\n }\r\n } catch (error) {\r\n log.error(`streamToGo2rtc(): Audio Error: ${error}`);\r\n reject(error);\r\n }\r\n })*/\r\n ]);\r\n}"],
|
|
5
|
-
"mappings": "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
|
|
4
|
+
"sourcesContent": ["import net from \"net\";\r\nimport path from \"path\";\r\nimport ffmpeg from \"@bropat/fluent-ffmpeg\";\r\nimport pathToFfmpeg from \"ffmpeg-for-homebridge\";\r\nimport { Readable } from \"stream\";\r\nimport { StreamMetadata, AudioCodec, VideoCodec } from \"eufy-security-client\";\r\nimport { tmpdir } from \"os\";\r\nimport fse from \"fs-extra\";\r\n\r\nimport stream from \"node:stream\";\r\nimport {pipeline as streamPipeline} from \"node:stream/promises\";\r\n\r\nimport { ioBrokerLogger } from \"./log\";\r\nimport { getShortUrl, lowestUnusedNumber } from \"./utils\";\r\n\r\nclass UniversalStream {\r\n\r\n public url: string;\r\n private static socks = new Set<number>();\r\n private server: net.Server;\r\n private sock_id: number;\r\n\r\n constructor (namespace: string, onSocket: ((socket: net.Socket) => void) | undefined) {\r\n let sockpath = \"\";\r\n\r\n const unique_sock_id = lowestUnusedNumber([...UniversalStream.socks], 1);\r\n UniversalStream.socks.add(unique_sock_id);\r\n this.sock_id = unique_sock_id;\r\n\r\n if (process.platform === \"win32\") {\r\n const pipePrefix = \"\\\\\\\\.\\\\pipe\\\\\";\r\n const pipeName = `node-webrtc.${namespace}.${unique_sock_id}.sock`;\r\n\r\n sockpath = path.join(pipePrefix, pipeName);\r\n this.url = sockpath;\r\n }\r\n else {\r\n const pipeName = `${namespace}.${unique_sock_id}.sock`;\r\n sockpath = path.join(tmpdir(), pipeName);\r\n this.url = \"unix:\" + sockpath;\r\n\r\n try {\r\n if (fse.existsSync(sockpath))\r\n fse.unlinkSync(sockpath);\r\n } catch(error) {\r\n }\r\n }\r\n\r\n this.server = net.createServer(onSocket);\r\n this.server.listen(sockpath);\r\n this.server.on(\"error\", () => {});\r\n }\r\n\r\n public close(): void {\r\n if (this.server)\r\n this.server.close();\r\n UniversalStream.socks.delete(this.sock_id);\r\n }\r\n\r\n}\r\n\r\nexport const StreamInput = function(namespace: string, stream: NodeJS.ReadableStream): UniversalStream {\r\n return new UniversalStream(namespace, (socket: net.Socket) => stream.pipe(socket, { end: true }).on(\"error\", (_error) => {\r\n //TODO: log error\r\n }));\r\n}\r\n\r\nexport const StreamOutput = function(namespace: string, stream: NodeJS.WritableStream): UniversalStream {\r\n return new UniversalStream(namespace, (socket: net.Socket) => socket.pipe(stream, { end: true }).on(\"error\", (_error) => {\r\n //TODO: log error\r\n }));\r\n}\r\n\r\nexport const ffmpegPreviewImage = (config: ioBroker.AdapterConfig, input:string, output: string, log: ioBrokerLogger, skip_seconds = 2.0): Promise<void> => {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n if (pathToFfmpeg) {\r\n ffmpeg.setFfmpegPath(pathToFfmpeg);\r\n\r\n ffmpeg()\r\n .withProcessOptions({\r\n detached: true\r\n })\r\n .addOptions([\r\n `-ss ${skip_seconds}`,\r\n \"-frames:v 1\"\r\n ])\r\n .input(input)\r\n .inputFormat(\"hls\")\r\n .outputFormat(\"image2\")\r\n .output(output)\r\n .on(\"error\", function(err, stdout, stderr) {\r\n log.error(`ffmpegPreviewImage(): An error occurred: ${err.message}`);\r\n log.error(`ffmpegPreviewImage(): ffmpeg output:\\n${stdout}`);\r\n log.error(`ffmpegPreviewImage(): ffmpeg stderr:\\n${stderr}`);\r\n reject(err);\r\n })\r\n .on(\"end\", () => {\r\n log.debug(\"ffmpegPreviewImage(): Preview image generated!\");\r\n resolve();\r\n })\r\n .run();\r\n } else {\r\n reject(new Error(\"ffmpeg binary not found\"));\r\n }\r\n } catch (error) {\r\n log.error(`ffmpegPreviewImage(): Error: ${error}`);\r\n reject(error);\r\n }\r\n });\r\n}\r\n\r\nexport const ffmpegStreamToHls = (config: ioBroker.AdapterConfig, namespace: string, metadata: StreamMetadata, videoStream: Readable, audioStream: Readable, output: string, log: ioBrokerLogger): Promise<void> => {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n if (pathToFfmpeg) {\r\n ffmpeg.setFfmpegPath(pathToFfmpeg);\r\n\r\n videoStream.on(\"error\", (error) => {\r\n log.error(\"ffmpegStreamToHls(): Videostream Error\", error);\r\n });\r\n\r\n audioStream.on(\"error\", (error) => {\r\n log.error(\"ffmpegStreamToHls(): Audiostream Error\", error);\r\n });\r\n\r\n const uVideoStream = StreamInput(namespace, videoStream);\r\n const uAudioStream = StreamInput(namespace, audioStream);\r\n\r\n let videoFormat = \"h264\";\r\n let audioFormat = \"\";\r\n const options: string[] = [\r\n \"-hls_init_time 0\",\r\n \"-hls_time 2\",\r\n \"-hls_segment_type mpegts\",\r\n //\"-start_number 1\",\r\n \"-sc_threshold 0\",\r\n `-g ${metadata.videoFPS}`,\r\n \"-fflags genpts+nobuffer+flush_packets\",\r\n //\"-flush_packets 1\",\r\n \"-hls_playlist_type event\"\r\n //\"-hls_flags split_by_time\"\r\n ];\r\n\r\n switch(metadata.videoCodec) {\r\n case VideoCodec.H264:\r\n videoFormat = \"h264\";\r\n break;\r\n case VideoCodec.H265:\r\n videoFormat = \"hevc\";\r\n break;\r\n }\r\n\r\n switch(metadata.audioCodec) {\r\n case AudioCodec.AAC:\r\n audioFormat = \"aac\";\r\n break;\r\n }\r\n\r\n const command = ffmpeg()\r\n .withProcessOptions({\r\n detached: true\r\n })\r\n .input(uVideoStream.url)\r\n .inputFormat(videoFormat)\r\n .inputFps(metadata.videoFPS);\r\n if (audioFormat !== \"\") {\r\n command.input(uAudioStream.url)\r\n .inputFormat(audioFormat)\r\n .videoCodec(\"copy\")\r\n .audioCodec(\"copy\");\r\n options.push(\"-absf aac_adtstoasc\");\r\n } else {\r\n log.warn(`ffmpegStreamToHls(): Not support audio codec or unknown audio codec (${AudioCodec[metadata.audioCodec]})`);\r\n }\r\n command.output(output)\r\n .addOptions(options)\r\n .on(\"error\", function(err, stdout, stderr) {\r\n log.error(`ffmpegStreamToHls(): An error occurred: ${err.message}`);\r\n log.error(`ffmpegStreamToHls(): ffmpeg output:\\n${stdout}`);\r\n log.error(`ffmpegStreamToHls(): ffmpeg stderr:\\n${stderr}`);\r\n uVideoStream.close();\r\n uAudioStream.close();\r\n reject(err);\r\n })\r\n .on(\"end\", () => {\r\n log.debug(\"ffmpegStreamToHls(): Processing finished!\");\r\n uVideoStream.close();\r\n uAudioStream.close();\r\n resolve();\r\n });\r\n command.run();\r\n } else {\r\n reject(new Error(\"ffmpeg binary not found\"));\r\n }\r\n } catch (error) {\r\n log.error(`ffmpegStreamToHls(): Error: ${error}`);\r\n reject(error);\r\n }\r\n });\r\n}\r\n\r\nexport const ffmpegStreamToGo2rtc = (config: ioBroker.AdapterConfig, namespace: string, camera: string, metadata: StreamMetadata, videoStream: Readable, audioStream: Readable, log: ioBrokerLogger): Promise<void> => {\r\n return new Promise((resolve, reject) => {\r\n try {\r\n if (pathToFfmpeg) {\r\n ffmpeg.setFfmpegPath(pathToFfmpeg);\r\n\r\n videoStream.on(\"error\", (error) => {\r\n log.error(\"ffmpegStreamToGo2rtc(): Videostream Error\", error);\r\n });\r\n\r\n audioStream.on(\"error\", (error) => {\r\n log.error(\"ffmpegStreamToGo2rtc(): Audiostream Error\", error);\r\n });\r\n\r\n //TODO: For debugging purposes\r\n /*const outputVFile = path.resolve(__dirname, \"../../video-stream.dump\");\r\n videoStream.pipe(fse.createWriteStream(outputVFile)).on(\"finish\", () => {\r\n log.debug(\"videoStream dump finished!\");\r\n log.info(\"Manually test the output by running# ffplay output/video-stream.dump\");\r\n });\r\n const outputAFile = path.resolve(__dirname, \"../../audio-stream.dump\");\r\n audioStream.pipe(fse.createWriteStream(outputAFile)).on(\"finish\", () => {\r\n log.debug(\"audioStream dump finished!\");\r\n log.info(\"Manually test the output by running# ffplay output/audio-stream.dump\");\r\n });*/\r\n\r\n const uVideoStream = StreamInput(namespace, videoStream);\r\n const uAudioStream = StreamInput(namespace, audioStream);\r\n\r\n let videoFormat = \"h264\";\r\n let audioFormat = \"\";\r\n const options: string[] = [\r\n \"-rtsp_transport tcp\",\r\n \"-sc_threshold 0\",\r\n \"-fflags genpts+nobuffer+flush_packets\",\r\n //\"-rtpflags latm\",\r\n ];\r\n\r\n switch(metadata.videoCodec) {\r\n case VideoCodec.H264:\r\n videoFormat = \"h264\";\r\n break;\r\n case VideoCodec.H265:\r\n videoFormat = \"hevc\";\r\n break;\r\n }\r\n\r\n switch(metadata.audioCodec) {\r\n case AudioCodec.AAC:\r\n audioFormat = \"aac\";\r\n break;\r\n }\r\n\r\n const command = ffmpeg()\r\n .withProcessOptions({\r\n detached: true\r\n })\r\n .input(uVideoStream.url)\r\n .inputFormat(videoFormat);\r\n if (metadata.videoFPS > 0 ) {\r\n options.push(`-g ${metadata.videoFPS}`);\r\n command.inputFps(metadata.videoFPS);\r\n }\r\n command.videoCodec(\"copy\");\r\n if (audioFormat !== \"\") {\r\n command.input(uAudioStream.url)\r\n .inputFormat(audioFormat)\r\n //.audioCodec(\"copy\");\r\n //.audioCodec(\"aac\");\r\n .audioCodec(\"opus\");\r\n } else {\r\n log.warn(`ffmpegStreamToGo2rtc(): Not support audio codec or unknown audio codec (${AudioCodec[metadata.audioCodec]})`);\r\n }\r\n command.output(`rtsp://localhost:${config.go2rtc_rtsp_port}/${camera}`)\r\n .outputFormat(\"rtsp\")\r\n .addOptions(options)\r\n .on(\"start\", (commandline) => {\r\n log.debug(`ffmpegStreamToGo2rtc(): commandline: ${commandline}`);\r\n })\r\n .on(\"error\", function(err, stdout, stderr) {\r\n log.error(`ffmpegStreamToGo2rtc(): An error occurred: ${err.message}`);\r\n log.error(`ffmpegStreamToGo2rtc(): ffmpeg output:\\n${stdout}`);\r\n log.error(`ffmpegStreamToGo2rtc(): ffmpeg stderr:\\n${stderr}`);\r\n uVideoStream.close();\r\n uAudioStream.close();\r\n reject(err);\r\n })\r\n .on(\"end\", () => {\r\n log.debug(\"ffmpegStreamToGo2rtc(): Processing finished!\");\r\n uVideoStream.close();\r\n uAudioStream.close();\r\n resolve();\r\n });\r\n command.run();\r\n } else {\r\n reject(new Error(\"ffmpeg binary not found\"));\r\n }\r\n } catch (error) {\r\n log.error(`ffmpegStreamToGo2rtc(): Error: ${error}`);\r\n reject(error);\r\n }\r\n });\r\n}\r\n\r\nexport const streamToGo2rtc = async (camera: string, videoStream: Readable, audioStream: Readable, log: ioBrokerLogger, _config: ioBroker.AdapterConfig, _namespace: string, _metadata: StreamMetadata): Promise<Array<PromiseSettledResult<void>>> => {\r\n const { default: got } = await import(\"got\");\r\n const api = got.extend({\r\n hooks: {\r\n beforeError: [\r\n error => {\r\n const { response, options } = error;\r\n const { method, url, prefixUrl } = options;\r\n const shortUrl = getShortUrl(typeof url === \"string\" ? new URL(url) : url === undefined ? new URL(\"\") : url, typeof prefixUrl === \"string\" ? prefixUrl : prefixUrl.toString());\r\n const body = response?.body ? response.body : error.message;\r\n error.message = `${error.message} | method: ${method} url: ${shortUrl}`;\r\n if (response?.body) {\r\n error.message = `${error.message} body: ${body}`;\r\n }\r\n return error;\r\n }\r\n ],\r\n }\r\n });\r\n videoStream.on(\"error\", (error) => {\r\n log.error(\"streamToGo2rtc(): Videostream Error\", error);\r\n });\r\n\r\n audioStream.on(\"error\", (error) => {\r\n log.error(\"streamToGo2rtc(): Audiostream Error\", error);\r\n });\r\n return Promise.allSettled([\r\n streamPipeline(\r\n videoStream,\r\n api.stream.post(`http://localhost:1984/api/stream?dst=${camera}`).on(\"error\", (error: any) => {\r\n if (!(error.response?.body as string)?.startsWith(\"EOF\")) {\r\n log.error(`streamToGo2rtc(): Got Videostream Error: ${error.message}`);\r\n }\r\n }),\r\n new stream.PassThrough()\r\n ),\r\n streamPipeline(\r\n audioStream,\r\n api.stream.post(`http://localhost:1984/api/stream?dst=${camera}`).on(\"error\", (error: any) => {\r\n if (!(error.response?.body as string)?.startsWith(\"EOF\")) {\r\n log.error(`streamToGo2rtc(): Got Audiostream Error: ${error.message}`);\r\n }\r\n }),\r\n new stream.PassThrough()\r\n )\r\n // Alternative implementation in case of go2rtc audio bitstream isn't working (<= 1.8.5)\r\n /*new Promise<void>((resolve, reject) => {\r\n try {\r\n if (pathToFfmpeg) {\r\n ffmpeg.setFfmpegPath(pathToFfmpeg);\r\n\r\n const uAudioStream = StreamInput(namespace, audioStream);\r\n\r\n let audioFormat = \"\";\r\n const options: string[] = [\r\n \"-rtsp_transport tcp\",\r\n \"-fflags genpts+nobuffer+flush_packets\",\r\n //\"-rtpflags latm\",\r\n //\"-compression_level 5\",\r\n \"-application lowdelay\",\r\n ];\r\n\r\n switch(metadata.audioCodec) {\r\n case AudioCodec.AAC:\r\n audioFormat = \"aac\";\r\n break;\r\n }\r\n\r\n const command = ffmpeg()\r\n .withProcessOptions({\r\n detached: true\r\n });\r\n\r\n if (audioFormat !== \"\") {\r\n command.input(uAudioStream.url)\r\n .inputFormat(audioFormat)\r\n .audioCodec(\"opus\");\r\n } else {\r\n log.warn(`streamToGo2rtc(): ffmpeg - Not support audio codec or unknown audio codec (${AudioCodec[metadata.audioCodec]})`);\r\n }\r\n command.output(`rtsp://localhost:${config.go2rtc_rtsp_port}/${camera}`)\r\n .outputFormat(\"rtsp\")\r\n .addOptions(options)\r\n .on(\"start\", (commandline) => {\r\n log.debug(`streamToGo2rtc(): ffmpeg - commandline: ${commandline}`);\r\n })\r\n .on(\"error\", function(err, stdout, stderr) {\r\n log.error(`streamToGo2rtc(): ffmpeg - An error occurred: ${err.message}`);\r\n log.error(`streamToGo2rtc(): ffmpeg output:\\n${stdout}`);\r\n log.error(`streamToGo2rtc(): ffmpeg stderr:\\n${stderr}`);\r\n uAudioStream.close();\r\n reject(err);\r\n })\r\n .on(\"end\", (stdout, stderr) => {\r\n log.debug(`streamToGo2rtc(): ffmpeg output:\\n${stdout}`);\r\n log.debug(`streamToGo2rtc(): ffmpeg stderr:\\n${stderr}`);\r\n log.debug(\"streamToGo2rtc(): Processing finished!\");\r\n uAudioStream.close();\r\n resolve();\r\n });\r\n command.run();\r\n } else {\r\n reject(new Error(\"ffmpeg binary not found\"));\r\n }\r\n } catch (error) {\r\n log.error(`streamToGo2rtc(): Audio Error: ${error}`);\r\n reject(error);\r\n }\r\n })*/\r\n ]);\r\n}"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBAAgB;AAChB,kBAAiB;AACjB,2BAAmB;AACnB,mCAAyB;AAEzB,kCAAuD;AACvD,gBAAuB;AACvB,sBAAgB;AAEhB,yBAAmB;AACnB,sBAAyC;AAGzC,mBAAgD;AAEhD,MAAM,gBAAgB;AAAA,EAEX;AAAA,EACP,OAAe,QAAQ,oBAAI,IAAY;AAAA,EAC/B;AAAA,EACA;AAAA,EAER,YAAa,WAAmB,UAAsD;AAClF,QAAI,WAAW;AAEf,UAAM,qBAAiB,iCAAmB,CAAC,GAAG,gBAAgB,KAAK,GAAG,CAAC;AACvE,oBAAgB,MAAM,IAAI,cAAc;AACxC,SAAK,UAAU;AAEf,QAAI,QAAQ,aAAa,SAAS;AAC9B,YAAM,aAAa;AACnB,YAAM,WAAW,eAAe,SAAS,IAAI,cAAc;AAE3D,iBAAW,YAAAA,QAAK,KAAK,YAAY,QAAQ;AACzC,WAAK,MAAM;AAAA,IACf,OACK;AACD,YAAM,WAAW,GAAG,SAAS,IAAI,cAAc;AAC/C,iBAAW,YAAAA,QAAK,SAAK,kBAAO,GAAG,QAAQ;AACvC,WAAK,MAAM,UAAU;AAErB,UAAI;AACA,YAAI,gBAAAC,QAAI,WAAW,QAAQ;AACvB,0BAAAA,QAAI,WAAW,QAAQ;AAAA,MAC/B,SAAQ,OAAO;AAAA,MACf;AAAA,IACJ;AAEA,SAAK,SAAS,WAAAC,QAAI,aAAa,QAAQ;AACvC,SAAK,OAAO,OAAO,QAAQ;AAC3B,SAAK,OAAO,GAAG,SAAS,MAAM;AAAA,IAAC,CAAC;AAAA,EACpC;AAAA,EAEO,QAAc;AACjB,QAAI,KAAK;AACL,WAAK,OAAO,MAAM;AACtB,oBAAgB,MAAM,OAAO,KAAK,OAAO;AAAA,EAC7C;AAEJ;AAEO,MAAM,cAAc,SAAS,WAAmBC,SAAgD;AACnG,SAAO,IAAI,gBAAgB,WAAW,CAAC,WAAuBA,QAAO,KAAK,QAAQ,EAAE,KAAK,KAAK,CAAC,EAAE,GAAG,SAAS,CAAC,WAAW;AAAA,EAEzH,CAAC,CAAC;AACN;AAEO,MAAM,eAAe,SAAS,WAAmBA,SAAgD;AACpG,SAAO,IAAI,gBAAgB,WAAW,CAAC,WAAuB,OAAO,KAAKA,SAAQ,EAAE,KAAK,KAAK,CAAC,EAAE,GAAG,SAAS,CAAC,WAAW;AAAA,EAEzH,CAAC,CAAC;AACN;AAEO,MAAM,qBAAqB,CAAC,QAAgC,OAAc,QAAgB,KAAqB,eAAe,MAAuB;AACxJ,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACpC,QAAI;AACA,UAAI,6BAAAC,SAAc;AACd,6BAAAC,QAAO,cAAc,6BAAAD,OAAY;AAEjC,iCAAAC,SAAO,EACF,mBAAmB;AAAA,UAChB,UAAU;AAAA,QACd,CAAC,EACA,WAAW;AAAA,UACR,OAAO,YAAY;AAAA,UACnB;AAAA,QACJ,CAAC,EACA,MAAM,KAAK,EACX,YAAY,KAAK,EACjB,aAAa,QAAQ,EACrB,OAAO,MAAM,EACb,GAAG,SAAS,SAAS,KAAK,QAAQ,QAAQ;AACvC,cAAI,MAAM,4CAA4C,IAAI,OAAO,EAAE;AACnE,cAAI,MAAM;AAAA,EAAyC,MAAM,EAAE;AAC3D,cAAI,MAAM;AAAA,EAAyC,MAAM,EAAE;AAC3D,iBAAO,GAAG;AAAA,QACd,CAAC,EACA,GAAG,OAAO,MAAM;AACb,cAAI,MAAM,gDAAgD;AAC1D,kBAAQ;AAAA,QACZ,CAAC,EACA,IAAI;AAAA,MACb,OAAO;AACH,eAAO,IAAI,MAAM,yBAAyB,CAAC;AAAA,MAC/C;AAAA,IACJ,SAAS,OAAO;AACZ,UAAI,MAAM,gCAAgC,KAAK,EAAE;AACjD,aAAO,KAAK;AAAA,IAChB;AAAA,EACJ,CAAC;AACL;AAEO,MAAM,oBAAoB,CAAC,QAAgC,WAAmB,UAA0B,aAAuB,aAAuB,QAAgB,QAAuC;AAChN,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACpC,QAAI;AACA,UAAI,6BAAAD,SAAc;AACd,6BAAAC,QAAO,cAAc,6BAAAD,OAAY;AAEjC,oBAAY,GAAG,SAAS,CAAC,UAAU;AAC/B,cAAI,MAAM,0CAA0C,KAAK;AAAA,QAC7D,CAAC;AAED,oBAAY,GAAG,SAAS,CAAC,UAAU;AAC/B,cAAI,MAAM,0CAA0C,KAAK;AAAA,QAC7D,CAAC;AAED,cAAM,eAAe,YAAY,WAAW,WAAW;AACvD,cAAM,eAAe,YAAY,WAAW,WAAW;AAEvD,YAAI,cAAc;AAClB,YAAI,cAAc;AAClB,cAAM,UAAoB;AAAA,UACtB;AAAA,UACA;AAAA,UACA;AAAA;AAAA,UAEA;AAAA,UACA,MAAM,SAAS,QAAQ;AAAA,UACvB;AAAA;AAAA,UAEA;AAAA;AAAA,QAEJ;AAEA,gBAAO,SAAS,YAAY;AAAA,UACxB,KAAK,uCAAW;AACZ,0BAAc;AACd;AAAA,UACJ,KAAK,uCAAW;AACZ,0BAAc;AACd;AAAA,QACR;AAEA,gBAAO,SAAS,YAAY;AAAA,UACxB,KAAK,uCAAW;AACZ,0BAAc;AACd;AAAA,QACR;AAEA,cAAM,cAAU,qBAAAC,SAAO,EAClB,mBAAmB;AAAA,UAChB,UAAU;AAAA,QACd,CAAC,EACA,MAAM,aAAa,GAAG,EACtB,YAAY,WAAW,EACvB,SAAS,SAAS,QAAQ;AAC/B,YAAI,gBAAgB,IAAI;AACpB,kBAAQ,MAAM,aAAa,GAAG,EACzB,YAAY,WAAW,EACvB,WAAW,MAAM,EACjB,WAAW,MAAM;AACtB,kBAAQ,KAAK,qBAAqB;AAAA,QACtC,OAAO;AACH,cAAI,KAAK,wEAAwE,uCAAW,SAAS,UAAU,CAAC,GAAG;AAAA,QACvH;AACA,gBAAQ,OAAO,MAAM,EAChB,WAAW,OAAO,EAClB,GAAG,SAAS,SAAS,KAAK,QAAQ,QAAQ;AACvC,cAAI,MAAM,2CAA2C,IAAI,OAAO,EAAE;AAClE,cAAI,MAAM;AAAA,EAAwC,MAAM,EAAE;AAC1D,cAAI,MAAM;AAAA,EAAwC,MAAM,EAAE;AAC1D,uBAAa,MAAM;AACnB,uBAAa,MAAM;AACnB,iBAAO,GAAG;AAAA,QACd,CAAC,EACA,GAAG,OAAO,MAAM;AACb,cAAI,MAAM,2CAA2C;AACrD,uBAAa,MAAM;AACnB,uBAAa,MAAM;AACnB,kBAAQ;AAAA,QACZ,CAAC;AACL,gBAAQ,IAAI;AAAA,MAChB,OAAO;AACH,eAAO,IAAI,MAAM,yBAAyB,CAAC;AAAA,MAC/C;AAAA,IACJ,SAAS,OAAO;AACZ,UAAI,MAAM,+BAA+B,KAAK,EAAE;AAChD,aAAO,KAAK;AAAA,IAChB;AAAA,EACJ,CAAC;AACL;AAEO,MAAM,uBAAuB,CAAC,QAAgC,WAAmB,QAAgB,UAA0B,aAAuB,aAAuB,QAAuC;AACnN,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACpC,QAAI;AACA,UAAI,6BAAAD,SAAc;AACd,6BAAAC,QAAO,cAAc,6BAAAD,OAAY;AAEjC,oBAAY,GAAG,SAAS,CAAC,UAAU;AAC/B,cAAI,MAAM,6CAA6C,KAAK;AAAA,QAChE,CAAC;AAED,oBAAY,GAAG,SAAS,CAAC,UAAU;AAC/B,cAAI,MAAM,6CAA6C,KAAK;AAAA,QAChE,CAAC;AAcD,cAAM,eAAe,YAAY,WAAW,WAAW;AACvD,cAAM,eAAe,YAAY,WAAW,WAAW;AAEvD,YAAI,cAAc;AAClB,YAAI,cAAc;AAClB,cAAM,UAAoB;AAAA,UACtB;AAAA,UACA;AAAA,UACA;AAAA;AAAA,QAEJ;AAEA,gBAAO,SAAS,YAAY;AAAA,UACxB,KAAK,uCAAW;AACZ,0BAAc;AACd;AAAA,UACJ,KAAK,uCAAW;AACZ,0BAAc;AACd;AAAA,QACR;AAEA,gBAAO,SAAS,YAAY;AAAA,UACxB,KAAK,uCAAW;AACZ,0BAAc;AACd;AAAA,QACR;AAEA,cAAM,cAAU,qBAAAC,SAAO,EAClB,mBAAmB;AAAA,UAChB,UAAU;AAAA,QACd,CAAC,EACA,MAAM,aAAa,GAAG,EACtB,YAAY,WAAW;AAC5B,YAAI,SAAS,WAAW,GAAI;AACxB,kBAAQ,KAAK,MAAM,SAAS,QAAQ,EAAE;AACtC,kBAAQ,SAAS,SAAS,QAAQ;AAAA,QACtC;AACA,gBAAQ,WAAW,MAAM;AACzB,YAAI,gBAAgB,IAAI;AACpB,kBAAQ,MAAM,aAAa,GAAG,EACzB,YAAY,WAAW,EAGvB,WAAW,MAAM;AAAA,QAC1B,OAAO;AACH,cAAI,KAAK,2EAA2E,uCAAW,SAAS,UAAU,CAAC,GAAG;AAAA,QAC1H;AACA,gBAAQ,OAAO,oBAAoB,OAAO,gBAAgB,IAAI,MAAM,EAAE,EACjE,aAAa,MAAM,EACnB,WAAW,OAAO,EAClB,GAAG,SAAS,CAAC,gBAAgB;AAC1B,cAAI,MAAM,wCAAwC,WAAW,EAAE;AAAA,QACnE,CAAC,EACA,GAAG,SAAS,SAAS,KAAK,QAAQ,QAAQ;AACvC,cAAI,MAAM,8CAA8C,IAAI,OAAO,EAAE;AACrE,cAAI,MAAM;AAAA,EAA2C,MAAM,EAAE;AAC7D,cAAI,MAAM;AAAA,EAA2C,MAAM,EAAE;AAC7D,uBAAa,MAAM;AACnB,uBAAa,MAAM;AACnB,iBAAO,GAAG;AAAA,QACd,CAAC,EACA,GAAG,OAAO,MAAM;AACb,cAAI,MAAM,8CAA8C;AACxD,uBAAa,MAAM;AACnB,uBAAa,MAAM;AACnB,kBAAQ;AAAA,QACZ,CAAC;AACL,gBAAQ,IAAI;AAAA,MAChB,OAAO;AACH,eAAO,IAAI,MAAM,yBAAyB,CAAC;AAAA,MAC/C;AAAA,IACJ,SAAS,OAAO;AACZ,UAAI,MAAM,kCAAkC,KAAK,EAAE;AACnD,aAAO,KAAK;AAAA,IAChB;AAAA,EACJ,CAAC;AACL;AAEO,MAAM,iBAAiB,OAAO,QAAgB,aAAuB,aAAuB,KAAqB,SAAiC,YAAoB,cAA0E;AACnP,QAAM,EAAE,SAAS,IAAI,IAAI,MAAM,OAAO,KAAK;AAC3C,QAAM,MAAM,IAAI,OAAO;AAAA,IACnB,OAAO;AAAA,MACH,aAAa;AAAA,QACT,WAAS;AACL,gBAAM,EAAE,UAAU,QAAQ,IAAI;AAC9B,gBAAM,EAAE,QAAQ,KAAK,UAAU,IAAI;AACnC,gBAAM,eAAW,0BAAY,OAAO,QAAQ,WAAW,IAAI,IAAI,GAAG,IAAI,QAAQ,SAAY,IAAI,IAAI,EAAE,IAAI,KAAK,OAAO,cAAc,WAAW,YAAY,UAAU,SAAS,CAAC;AAC7K,gBAAM,QAAO,qCAAU,QAAO,SAAS,OAAO,MAAM;AACpD,gBAAM,UAAU,GAAG,MAAM,OAAO,cAAc,MAAM,SAAS,QAAQ;AACrE,cAAI,qCAAU,MAAM;AAChB,kBAAM,UAAU,GAAG,MAAM,OAAO,UAAU,IAAI;AAAA,UAClD;AACA,iBAAO;AAAA,QACX;AAAA,MACJ;AAAA,IACJ;AAAA,EACJ,CAAC;AACD,cAAY,GAAG,SAAS,CAAC,UAAU;AAC/B,QAAI,MAAM,uCAAuC,KAAK;AAAA,EAC1D,CAAC;AAED,cAAY,GAAG,SAAS,CAAC,UAAU;AAC/B,QAAI,MAAM,uCAAuC,KAAK;AAAA,EAC1D,CAAC;AACD,SAAO,QAAQ,WAAW;AAAA,QACtB,gBAAAC;AAAA,MACI;AAAA,MACA,IAAI,OAAO,KAAK,wCAAwC,MAAM,EAAE,EAAE,GAAG,SAAS,CAAC,UAAe;AA/U1G;AAgVgB,YAAI,GAAE,iBAAM,aAAN,mBAAgB,SAAhB,mBAAiC,WAAW,SAAQ;AACtD,cAAI,MAAM,4CAA4C,MAAM,OAAO,EAAE;AAAA,QACzE;AAAA,MACJ,CAAC;AAAA,MACD,IAAI,mBAAAH,QAAO,YAAY;AAAA,IAC3B;AAAA,QACA,gBAAAG;AAAA,MACI;AAAA,MACA,IAAI,OAAO,KAAK,wCAAwC,MAAM,EAAE,EAAE,GAAG,SAAS,CAAC,UAAe;AAxV1G;AAyVgB,YAAI,GAAE,iBAAM,aAAN,mBAAgB,SAAhB,mBAAiC,WAAW,SAAQ;AACtD,cAAI,MAAM,4CAA4C,MAAM,OAAO,EAAE;AAAA,QACzE;AAAA,MACJ,CAAC;AAAA,MACD,IAAI,mBAAAH,QAAO,YAAY;AAAA,IAC3B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiEJ,CAAC;AACL;",
|
|
6
6
|
"names": ["path", "fse", "net", "stream", "pathToFfmpeg", "ffmpeg", "streamPipeline"]
|
|
7
7
|
}
|
package/build/main.js
CHANGED
|
@@ -1405,8 +1405,10 @@ class euSec extends utils.Adapter {
|
|
|
1405
1405
|
await this.setStateAsync("info.mqtt_connection", { val: false, ack: true });
|
|
1406
1406
|
}
|
|
1407
1407
|
async onStationCommandResult(station, result) {
|
|
1408
|
-
if (result.return_code !== 0 && result.command_type !== import_eufy_security_client.CommandType.P2P_QUERY_STATUS_IN_LOCK && result.command_type !== import_eufy_security_client.CommandType.CMD_STORAGE_INFO_HB3 || result.return_code !== import_eufy_security_client.ErrorCode.ERROR_DEV_BUSY && result.command_type === import_eufy_security_client.CommandType.CMD_STORAGE_INFO_HB3) {
|
|
1408
|
+
if (result.return_code !== 0 && result.command_type !== import_eufy_security_client.CommandType.P2P_QUERY_STATUS_IN_LOCK && result.command_type !== import_eufy_security_client.CommandType.CMD_STORAGE_INFO_HB3 && result.command_type !== import_eufy_security_client.CommandType.CMD_SDINFO_EX || result.return_code !== 0 && result.return_code !== import_eufy_security_client.ErrorCode.ERROR_DEV_BUSY && result.command_type === import_eufy_security_client.CommandType.CMD_STORAGE_INFO_HB3) {
|
|
1409
1409
|
this.logger.error(`Station: ${station.getSerial()} command ${import_eufy_security_client.CommandType[result.command_type]} failed with error: ${import_eufy_security_client.ErrorCode[result.return_code]} (${result.return_code})`);
|
|
1410
|
+
} else if (result.return_code !== 0 && result.return_code !== import_eufy_security_client.TFCardStatus.REMOVE && result.return_code !== import_eufy_security_client.TFCardStatus.BUSY && result.command_type === import_eufy_security_client.CommandType.CMD_SDINFO_EX) {
|
|
1411
|
+
this.logger.error(`Station: ${station.getSerial()} command ${import_eufy_security_client.CommandType[result.command_type]} failed with error: ${import_eufy_security_client.TFCardStatus[result.return_code]} (${result.return_code})`);
|
|
1410
1412
|
}
|
|
1411
1413
|
}
|
|
1412
1414
|
async onStationPropertyChanged(station, name, value) {
|
package/build/main.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../src/main.ts"],
|
|
4
|
-
"sourcesContent": ["/*\r\n * Created with @iobroker/create-adapter v2.5.0\r\n */\r\n\r\n// The adapter-core module gives you access to the core ioBroker functions\r\n// you need to create an adapter\r\nimport * as utils from \"@iobroker/adapter-core\";\r\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\r\nimport { strict } from \"assert\";\r\nimport * as path from \"path\";\r\nimport { Camera, Device, Station, PushMessage, P2PConnectionType, EufySecurity, EufySecurityConfig, CommandResult, CommandType, ErrorCode, PropertyValue, PropertyName, StreamMetadata, PropertyMetadataNumeric, PropertyMetadataAny, CommandName, PanTiltDirection, DeviceNotFoundError, LoginOptions, Picture, StationNotFoundError, ensureError, LogLevel } from \"eufy-security-client\";\r\nimport { getAlpha2Code as getCountryCode } from \"i18n-iso-countries\"\r\nimport { isValid as isValidLanguageCode } from \"@cospired/i18n-iso-languages\"\r\nimport { Readable } from \"stream\";\r\nimport util from \"util\";\r\nimport childProcess from \"child_process\";\r\nimport pathToGo2rtc from \"go2rtc-static\";\r\nimport pathToFfmpeg from \"ffmpeg-for-homebridge\";\r\n\r\nimport { DeviceStateID, DataLocation, RoleMapping, StationStateID } from \"./lib/types\";\r\nimport { convertCamelCaseToSnakeCase, getImageAsHTML, handleUpdate, removeFiles, removeLastChar, setStateChangedAsync } from \"./lib/utils\";\r\nimport { PersistentData } from \"./lib/interfaces\";\r\nimport { ioBrokerLogger } from \"./lib/log\";\r\nimport { streamToGo2rtc } from \"./lib/video\";\r\n\r\nexport class euSec extends utils.Adapter {\r\n\r\n private eufy!: EufySecurity;\r\n /*private downloadEvent: {\r\n [index: string]: NodeJS.Timeout;\r\n } = {};*/\r\n\r\n private persistentFile: string = \"adapter.json\";\r\n private persistentDriverFile: string = \"driver.json\";\r\n private logger!: ioBrokerLogger;\r\n private persistentData: PersistentData = {\r\n version: \"\"\r\n };\r\n private captchaId: string | null = null;\r\n private verify_code = false;\r\n private skipInit = false;\r\n\r\n public constructor(options: Partial<utils.AdapterOptions> = {}) {\r\n super({\r\n ...options,\r\n name: \"eusec\",\r\n });\r\n\r\n this.on(\"ready\", this.onReady.bind(this));\r\n this.on(\"stateChange\", this.onStateChange.bind(this));\r\n // this.on(\"objectChange\", this.onObjectChange.bind(this));\r\n this.on(\"message\", this.onMessage.bind(this));\r\n this.on(\"unload\", this.onUnload.bind(this));\r\n }\r\n\r\n public restartAdapter(): void {\r\n this.skipInit = true;\r\n this.restart();\r\n }\r\n\r\n /**\r\n * Is called when databases are connected and adapter received configuration.\r\n */\r\n private async onReady(): Promise<void> {\r\n\r\n this.logger = new ioBrokerLogger(this.log as ioBroker.Logger);\r\n\r\n await this.setObjectNotExistsAsync(\"verify_code\", {\r\n type: \"state\",\r\n common: {\r\n name: \"2FA verification code\",\r\n type: \"string\",\r\n role: \"state\",\r\n read: true,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(\"received_captcha_html\", {\r\n type: \"state\",\r\n common: {\r\n name: \"Received captcha image HTML\",\r\n type: \"string\",\r\n role: \"state\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(\"captcha\", {\r\n type: \"state\",\r\n common: {\r\n name: \"Enter captcha\",\r\n type: \"string\",\r\n role: \"state\",\r\n read: true,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(\"info\", {\r\n type: \"channel\",\r\n common: {\r\n name: \"info\"\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(\"info.connection\", {\r\n type: \"state\",\r\n common: {\r\n name: \"Global connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(\"info.connection\", { val: false, ack: true });\r\n await this.setObjectNotExistsAsync(\"info.push_connection\", {\r\n type: \"state\",\r\n common: {\r\n name: \"Push notification connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(\"info.push_connection\", { val: false, ack: true });\r\n await this.setObjectNotExistsAsync(\"info.mqtt_connection\", {\r\n type: \"state\",\r\n common: {\r\n name: \"MQTT connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(\"info.mqtt_connection\", { val: false, ack: true });\r\n\r\n try {\r\n const connection = await this.getStatesAsync(\"*.connection\");\r\n if (connection)\r\n Object.keys(connection).forEach(async id => {\r\n await this.setStateAsync(id, { val: false, ack: true });\r\n });\r\n } catch (error) {\r\n this.logger.error(\"Reset connection states - Error\", error);\r\n }\r\n\r\n try {\r\n const sensorList = [\r\n PropertyName.DeviceMotionDetected,\r\n PropertyName.DevicePersonDetected,\r\n PropertyName.DeviceSoundDetected,\r\n PropertyName.DeviceCryingDetected,\r\n PropertyName.DevicePetDetected,\r\n PropertyName.DeviceRinging\r\n ];\r\n for(const sensorName of sensorList) {\r\n const sensors = await this.getStatesAsync(`*.${convertCamelCaseToSnakeCase(sensorName)}`);\r\n if (sensors)\r\n Object.keys(sensors).forEach(async id => {\r\n await this.setStateAsync(id, { val: false, ack: true });\r\n });\r\n }\r\n } catch (error) {\r\n this.logger.error(\"Reset sensor states - Error\", error);\r\n }\r\n\r\n try {\r\n if (await this.fileExistsAsync(this.namespace, this.persistentFile)) {\r\n const fileContent = await this.readFileAsync(this.namespace, this.persistentFile);\r\n this.persistentData = JSON.parse(fileContent.file.toString(\"utf8\")) as PersistentData;\r\n }\r\n } catch (error) {\r\n this.logger.debug(\"No adapter stored data from last exit found.\", error);\r\n }\r\n\r\n let persistentDriverData: string = \"{}\";\r\n try {\r\n if (await this.fileExistsAsync(this.namespace, this.persistentDriverFile)) {\r\n const fileContent = await this.readFileAsync(this.namespace, this.persistentDriverFile);\r\n persistentDriverData = fileContent.file.toString(\"utf8\");\r\n }\r\n } catch (error) {\r\n this.logger.debug(\"No driver stored data from last exit found.\", error);\r\n }\r\n\r\n this.subscribeStates(\"verify_code\");\r\n this.subscribeStates(\"captcha\");\r\n\r\n const hosts = await this.getForeignObjectsAsync(\"system.host.*\", \"host\");\r\n if (hosts !== undefined && hosts !== null && Object.values(hosts).length !== 0) {\r\n if (this.config.hostname === \"\") {\r\n this.config.hostname = Object.values(hosts)[0].native.os.hostname;\r\n }\r\n\r\n const nodeVersion = Object.values(hosts)[0].native.process.versions.node;\r\n const nodeMajorVersion = nodeVersion.split(\".\")[0];\r\n\r\n let fixNeeded;\r\n switch (parseInt(nodeMajorVersion)) {\r\n case 18:\r\n fixNeeded = nodeVersion.localeCompare(\"18.19.1\", undefined, { numeric: true, sensitivity: \"base\" });\r\n break;\r\n case 20:\r\n fixNeeded = nodeVersion.localeCompare(\"20.11.1\", undefined, { numeric: true, sensitivity: \"base\" });\r\n break;\r\n default:\r\n fixNeeded = nodeVersion.localeCompare(\"21.6.2\", undefined, { numeric: true, sensitivity: \"base\" });\r\n break;\r\n }\r\n if (fixNeeded >= 0) {\r\n const adapter = await this.getForeignObjectAsync(`system.adapter.${this.namespace}`);\r\n if (adapter !== undefined && adapter !== null) {\r\n if (!adapter.common.nodeProcessParams?.includes(\"--security-revert=CVE-2023-46809\")) {\r\n adapter.common.nodeProcessParams = [\"--security-revert=CVE-2023-46809\"]\r\n await this.setForeignObjectAsync(`system.adapter.${this.namespace}`, adapter);\r\n this.log.warn(\"Required fix to use livestreaming with this version of Node.js (CVE-2023-46809) applied. Restart of the adapter initiated to activate the fix.\");\r\n this.restartAdapter();\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!this.skipInit) {\r\n const systemConfig = await this.getForeignObjectAsync(\"system.config\");\r\n let countryCode = undefined;\r\n let languageCode = undefined;\r\n if (systemConfig) {\r\n countryCode = getCountryCode(systemConfig.common.country!, \"en\");\r\n if (isValidLanguageCode(systemConfig.common.language))\r\n languageCode = systemConfig.common.language;\r\n }\r\n if (this.config.country !== \"iobroker\") {\r\n countryCode = this.config.country;\r\n }\r\n\r\n // Handling adapter version update\r\n try {\r\n if (this.persistentData.version !== this.version) {\r\n const currentVersion = Number.parseFloat(removeLastChar(this.version!, \".\"));\r\n const previousVersion = this.persistentData.version !== \"\" && this.persistentData.version !== undefined ? Number.parseFloat(removeLastChar(this.persistentData.version, \".\")) : 0;\r\n this.logger.debug(`Handling of adapter update - currentVersion: ${currentVersion} previousVersion: ${previousVersion}`);\r\n\r\n if (previousVersion < currentVersion) {\r\n await handleUpdate(this, this.logger, previousVersion, currentVersion);\r\n this.persistentData.version = this.version!;\r\n await this.writePersistentData();\r\n }\r\n }\r\n } catch (error) {\r\n this.logger.error(`Handling of adapter update - Error:`, error);\r\n }\r\n\r\n let connectionType = P2PConnectionType.QUICKEST;\r\n if (this.config.p2pConnectionType === \"only_local\") {\r\n connectionType = P2PConnectionType.ONLY_LOCAL;\r\n }\r\n\r\n if (this.config.username !== \"\" && this.config.password !== \"\") {\r\n const config: EufySecurityConfig = {\r\n username: this.config.username,\r\n password: this.config.password,\r\n country: countryCode,\r\n language: languageCode,\r\n persistentData: persistentDriverData,\r\n eventDurationSeconds: this.config.eventDuration,\r\n p2pConnectionSetup: connectionType,\r\n pollingIntervalMinutes: this.config.pollingInterval,\r\n acceptInvitations: this.config.acceptInvitations,\r\n logging: {\r\n level: this.log.level === \"silly\" ? LogLevel.Trace : this.log.level === \"debug\" ? LogLevel.Debug : this.log.level === \"info\" ? LogLevel.Info : this.log.level === \"warn\" ? LogLevel.Warn : this.log.level === \"error\" ? LogLevel.Error : LogLevel.Info\r\n }\r\n };\r\n\r\n this.eufy = await EufySecurity.initialize(config, this.logger);\r\n this.eufy.on(\"persistent data\", (data: string) => this.onPersistentData(data))\r\n this.eufy.on(\"station added\", (station: Station) => this.onStationAdded(station));\r\n this.eufy.on(\"device added\", (device: Device) => this.onDeviceAdded(device));\r\n this.eufy.on(\"station removed\", (station: Station) => this.onStationRemoved(station));\r\n this.eufy.on(\"device removed\", (device: Device) => this.onDeviceRemoved(device));\r\n this.eufy.on(\"push message\", (messages) => this.handlePushNotification(messages));\r\n this.eufy.on(\"push connect\", () => this.onPushConnect());\r\n this.eufy.on(\"push close\", () => this.onPushClose());\r\n this.eufy.on(\"mqtt connect\", () => this.onMQTTConnect());\r\n this.eufy.on(\"mqtt close\", () => this.onMQTTClose());\r\n this.eufy.on(\"connect\", () => this.onConnect());\r\n this.eufy.on(\"close\", () => this.onClose());\r\n\r\n this.eufy.on(\"device property changed\", (device: Device, name: string, value: PropertyValue) => this.onDevicePropertyChanged(device, name, value));\r\n\r\n this.eufy.on(\"station command result\", (station: Station, result: CommandResult) => this.onStationCommandResult(station, result));\r\n //this.eufy.on(\"station download start\", (station: Station, device: Device, metadata: StreamMetadata, videostream: Readable, audiostream: Readable) => this.onStationDownloadStart(station, device, metadata, videostream, audiostream));\r\n //this.eufy.on(\"station download finish\", (station: Station, device: Device) => this.onStationDownloadFinish(station, device));\r\n this.eufy.on(\"station livestream start\", (station: Station, device: Device, metadata: StreamMetadata, videostream: Readable, audiostream: Readable) => this.onStationLivestreamStart(station, device, metadata, videostream, audiostream));\r\n this.eufy.on(\"station livestream stop\", (station: Station, device: Device) => this.onStationLivestreamStop(station, device));\r\n this.eufy.on(\"station rtsp url\", (station: Station, device: Device, value: string) => this.onStationRTSPUrl(station, device, value));\r\n this.eufy.on(\"station property changed\", (station: Station, name: string, value: PropertyValue) => this.onStationPropertyChanged(station, name, value));\r\n this.eufy.on(\"station connect\", (station: Station) => this.onStationConnect(station));\r\n this.eufy.on(\"station close\", (station: Station) => this.onStationClose(station));\r\n this.eufy.on(\"tfa request\", () => this.onTFARequest());\r\n this.eufy.on(\"captcha request\", (captchaId: string, captcha: string) => this.onCaptchaRequest(captchaId, captcha));\r\n this.eufy.setCameraMaxLivestreamDuration(this.config.maxLivestreamDuration);\r\n\r\n await this.eufy.connect();\r\n\r\n if (pathToGo2rtc) {\r\n const go2rtcConfig: {\r\n [index: string]: {\r\n [index: string]: string | number | null\r\n }\r\n } = {\r\n \"api\": {\r\n \"listen\": `:${this.config.go2rtc_api_port}`\r\n },\r\n \"rtsp\": {\r\n \"listen\": `:${this.config.go2rtc_rtsp_port}`\r\n },\r\n \"srtp\": {\r\n \"listen\": `:${this.config.go2rtc_srtp_port}`\r\n },\r\n \"webrtc\": {\r\n \"listen\": `:${this.config.go2rtc_webrtc_port}`\r\n },\r\n \"ffmpeg\": {\r\n \"bin\": pathToFfmpeg !== \"\" && pathToFfmpeg !== undefined ? pathToFfmpeg : \"ffmpeg\",\r\n },\r\n \"streams\": {},\r\n /*\"log\": {\r\n \"level\": \"debug\", // default level\r\n \"api\": \"debug\",\r\n \"exec\": \"debug\",\r\n \"ngrok\": \"debug\",\r\n \"rtsp\": \"debug\",\r\n \"streams\": \"debug\",\r\n \"webrtc\": \"debug\",\r\n }*/\r\n };\r\n if (this.config.go2rtc_rtsp_username !== \"\" && this.config.go2rtc_rtsp_password !== \"\") {\r\n go2rtcConfig.rtsp.username = this.config.go2rtc_rtsp_username;\r\n go2rtcConfig.rtsp.password = this.config.go2rtc_rtsp_password;\r\n }\r\n for (const device of await this.eufy.getDevices()) {\r\n go2rtcConfig.streams[device.getSerial()] = null;\r\n }\r\n const go2rtc = childProcess.spawn(pathToGo2rtc, [\"-config\", JSON.stringify(go2rtcConfig)], { shell: false, detached: false, windowsHide: true });\r\n go2rtc.on(\"error\", (error) => {\r\n this.log.error(`go2rtc error: ${error}`);\r\n });\r\n go2rtc.stdout.setEncoding(\"utf8\");\r\n go2rtc.stdout.on(\"data\", (data) => {\r\n this.log.info(`go2rtc started: ${data}`);\r\n });\r\n go2rtc.stderr.setEncoding(\"utf8\");\r\n go2rtc.stderr.on(\"data\", (data) => {\r\n this.log.error(`go2rtc error: ${data}`);\r\n });\r\n go2rtc.on(\"close\", (exitcode) => {\r\n this.log.info(`go2rtc terminated with exitcode ${exitcode}`);\r\n });\r\n process.on(\"exit\", () => {\r\n go2rtc.kill();\r\n });\r\n }\r\n }\r\n // Delete cunknown channels without childs\r\n const channels = await this.getChannelsAsync();\r\n for (const channel of channels) {\r\n if (channel.common.name === \"unknown\") {\r\n const states = await this.getStatesAsync(`${channel._id}.*`);\r\n if (Object.keys(states).length === 0) {\r\n await this.delObjectAsync(channel._id);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n public async writePersistentData(): Promise<void> {\r\n try {\r\n await this.writeFileAsync(this.namespace, this.persistentFile, JSON.stringify(this.persistentData));\r\n } catch(error) {\r\n this.logger.error(`writePersistentData() - Error: ${error}`);\r\n }\r\n }\r\n\r\n private onPersistentData(data: string): void {\r\n this.writeFileAsync(this.namespace, this.persistentDriverFile, data).catch((error) => {\r\n this.logger.error(`writePersistentDriverData() - Error: ${error}`);\r\n });\r\n }\r\n\r\n /**\r\n * Is called when adapter shuts down - callback has to be called under any circumstances!\r\n */\r\n private async onUnload(callback: () => void): Promise<void> {\r\n try {\r\n\r\n await this.writePersistentData();\r\n\r\n if (this.eufy) {\r\n if (this.eufy.isConnected())\r\n await this.setStateAsync(\"info.connection\", { val: false, ack: true }).catch();\r\n this.eufy.removeAllListeners();\r\n this.eufy.close();\r\n }\r\n\r\n callback();\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n } catch (e) {\r\n callback();\r\n }\r\n }\r\n\r\n // If you need to react to object changes, uncomment the following block and the corresponding line in the constructor.\r\n // You also need to subscribe to the objects with `this.subscribeObjects`, similar to `this.subscribeStates`.\r\n // /**\r\n // * Is called if a subscribed object changes\r\n // */\r\n // private onObjectChange(id: string, obj: ioBroker.Object | null | undefined): void {\r\n // if (obj) {\r\n // // The object was changed\r\n // this.log.info(`object ${id} changed: ${JSON.stringify(obj)}`);\r\n // } else {\r\n // // The object was deleted\r\n // this.log.info(`object ${id} deleted`);\r\n // }\r\n // }\r\n\r\n /**\r\n * Is called if a subscribed state changes\r\n */\r\n private async onStateChange(id: string, state: ioBroker.State | null | undefined): Promise<void> {\r\n if (state) {\r\n\r\n // don't do anything if the state is acked\r\n if (!id || state.ack) {\r\n this.logger.debug(`state ${id} changed: ${state.val} (ack = ${state.ack}) was already acknowledged, ignore it...`);\r\n return;\r\n }\r\n this.logger.debug(`state ${id} changed: ${state.val} (ack = ${state.ack})`);\r\n\r\n const values = id.split(\".\");\r\n const station_sn = values[2];\r\n const device_type = values[3];\r\n\r\n if (station_sn == \"verify_code\") {\r\n if (this.eufy && this.verify_code) {\r\n this.logger.info(`Verification code received, send it. (verify_code: ${state.val})`);\r\n await this.eufy.connect({ verifyCode: state.val as string } as LoginOptions);\r\n this.verify_code = false;\r\n await this.delStateAsync(id);\r\n }\r\n } else if (station_sn == \"captcha\") {\r\n if (this.eufy && this.captchaId) {\r\n this.logger.info(`Captcha received, send it. (captcha: ${state.val})`);\r\n await this.eufy.connect({\r\n captcha: {\r\n captchaCode: state.val as string,\r\n captchaId: this.captchaId\r\n }\r\n } as LoginOptions);\r\n this.captchaId = null;\r\n await this.delStateAsync(id);\r\n await this.delStateAsync(\"received_captcha_html\");\r\n }\r\n } else if (device_type == \"station\") {\r\n try {\r\n const station_state_name = values[4];\r\n if (this.eufy) {\r\n const obj = await this.getObjectAsync(id);\r\n if (obj) {\r\n if (obj.native.name !== undefined) {\r\n await this.eufy.setStationProperty(station_sn, obj.native.name, state.val);\r\n return;\r\n }\r\n }\r\n\r\n const station = await this.eufy.getStation(station_sn);\r\n switch(station_state_name) {\r\n case StationStateID.REBOOT:\r\n await station.rebootHUB();\r\n break;\r\n case StationStateID.TRIGGER_ALARM_SOUND:\r\n await station.triggerStationAlarmSound(this.config.alarmSoundDuration);\r\n break;\r\n case StationStateID.RESET_ALARM_SOUND:\r\n await station.resetStationAlarmSound();\r\n break;\r\n }\r\n }\r\n } catch (error) {\r\n this.logger.error(`station - Error:`, error);\r\n }\r\n } else {\r\n try {\r\n const device_sn = values[4];\r\n const obj = await this.getObjectAsync(id);\r\n if (obj) {\r\n if (obj.native.name !== undefined) {\r\n try {\r\n await this.eufy.setDeviceProperty(device_sn, obj.native.name, obj.common.type === \"object\" ? JSON.parse(state.val as string) : state.val);\r\n } catch (error) {\r\n this.logger.error(`Error in setting property value (property: ${obj.native.name} value: ${state.val})`, error);\r\n }\r\n return;\r\n }\r\n }\r\n\r\n const device_state_name = values[5];\r\n const station = await this.eufy.getStation(station_sn);\r\n const device = await this.eufy.getDevice(device_sn);\r\n\r\n switch(device_state_name) {\r\n case DeviceStateID.START_STREAM:\r\n await this.startLivestream(device_sn);\r\n break;\r\n case DeviceStateID.STOP_STREAM:\r\n await this.stopLivestream(device_sn);\r\n break;\r\n case DeviceStateID.TRIGGER_ALARM_SOUND:\r\n await station.triggerDeviceAlarmSound(device, this.config.alarmSoundDuration);\r\n break;\r\n case DeviceStateID.RESET_ALARM_SOUND:\r\n await station.resetDeviceAlarmSound(device);\r\n break;\r\n case DeviceStateID.ROTATE_360:\r\n await station.panAndTilt(device, PanTiltDirection.ROTATE360);\r\n break;\r\n case DeviceStateID.PAN_LEFT:\r\n await station.panAndTilt(device, PanTiltDirection.LEFT);\r\n break;\r\n case DeviceStateID.PAN_RIGHT:\r\n await station.panAndTilt(device, PanTiltDirection.RIGHT);\r\n break;\r\n case DeviceStateID.TILT_UP:\r\n await station.panAndTilt(device, PanTiltDirection.UP);\r\n break;\r\n case DeviceStateID.TILT_DOWN:\r\n await station.panAndTilt(device, PanTiltDirection.DOWN);\r\n break;\r\n case DeviceStateID.CALIBRATE:\r\n if (device.isLock()) {\r\n await station.calibrateLock(device);\r\n } else {\r\n await station.calibrate(device);\r\n }\r\n break;\r\n case DeviceStateID.UNLOCK:\r\n await station.unlock(device);\r\n break;\r\n case DeviceStateID.SET_DEFAULT_ANGLE:\r\n await station.setDefaultAngle(device);\r\n break;\r\n case DeviceStateID.SET_PRIVACY_ANGLE:\r\n await station.setPrivacyAngle(device);\r\n break;\r\n case DeviceStateID.OPEN_BOX:\r\n await station.open(device);\r\n break;\r\n }\r\n } catch (error) {\r\n this.logger.error(`cameras - Error:`, error);\r\n }\r\n }\r\n } else {\r\n // The state was deleted\r\n this.logger.debug(`state ${id} deleted`);\r\n }\r\n }\r\n\r\n /**\r\n * Some message was sent to this instance over message box. Used by email, pushover, text2speech, ...\r\n * Using this method requires \"common.message\" property to be set to true in io-package.json\r\n */\r\n private async onMessage(obj: ioBroker.Message): Promise<void> {\r\n if (typeof obj === \"object\" && obj.message) {\r\n try {\r\n if (obj.command === \"quickResponse\") {\r\n this.log.debug(`quickResponse command - message: ${JSON.stringify(obj.message)}`);\r\n if (typeof obj.message === \"object\" &&\r\n typeof obj.message.station_sn === \"string\" && obj.message.station_sn !== \"\" &&\r\n typeof obj.message.device_sn === \"string\" && obj.message.device_sn !== \"\" &&\r\n typeof obj.message.voice_id === \"number\") {\r\n try {\r\n const station = await this.eufy.getStation(obj.message.station_sn);\r\n const device = await this.eufy.getDevice(obj.message.device_sn);\r\n\r\n if (device.hasCommand(CommandName.DeviceQuickResponse)) {\r\n await station.quickResponse(device, obj.message.voice_id);\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: true,\r\n result: \"quickResponse command sended\"\r\n }, obj.callback);\r\n } else {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"quickResponse command not supported by specified device\"\r\n }, obj.callback);\r\n }\r\n } catch (error) {\r\n if (error instanceof StationNotFoundError) {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"quickResponse command not sended because specified station doesn't exists\"\r\n }, obj.callback);\r\n } else if (error instanceof DeviceNotFoundError) {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"quickResponse command not sended because specified device doesn't exists\"\r\n }, obj.callback);\r\n } else {\r\n throw error;\r\n }\r\n }\r\n } else {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"quickResponse command not sended because some required parameters are missing\"\r\n }, obj.callback);\r\n }\r\n } else if (obj.command === \"getQuickResponseVoices\") {\r\n this.log.debug(`getQuickResponseVoices command - message: ${JSON.stringify(obj.message)}`);\r\n if (typeof obj.message === \"object\" &&\r\n typeof obj.message.device_sn === \"string\" && obj.message.device_sn !== \"\") {\r\n const voices = await this.eufy.getApi().getVoices(obj.message.device_sn);\r\n\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: true,\r\n result: voices\r\n }, obj.callback);\r\n } else {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"getQuickResponseVoices command not sended because some required parameters are missing\"\r\n }, obj.callback);\r\n }\r\n } else if (obj.command === \"snooze\") {\r\n this.log.debug(`snooze command - message: ${JSON.stringify(obj.message)}`);\r\n if (typeof obj.message === \"object\" &&\r\n typeof obj.message.station_sn === \"string\" && obj.message.station_sn !== \"\" &&\r\n typeof obj.message.device_sn === \"string\" && obj.message.device_sn !== \"\" &&\r\n typeof obj.message.snooze_time === \"number\" &&\r\n (obj.message.snooze_chime === undefined || typeof obj.message.snooze_chime === \"boolean\") &&\r\n (obj.message.snooze_homebase === undefined || typeof obj.message.snooze_homebase === \"boolean\") &&\r\n (obj.message.snooze_motion === undefined || typeof obj.message.snooze_motion === \"boolean\")) {\r\n try {\r\n const station = await this.eufy.getStation(obj.message.station_sn);\r\n const device = await this.eufy.getDevice(obj.message.device_sn);\r\n\r\n if (device.hasCommand(CommandName.DeviceSnooze)) {\r\n await station.snooze(device, {\r\n snooze_time: obj.message.snooze_time,\r\n snooze_chime: obj.message.snooze_chime,\r\n snooze_homebase: obj.message.snooze_homebase,\r\n snooze_motion: obj.message.snooze_motion,\r\n });\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: true,\r\n result: \"snooze command sended\"\r\n }, obj.callback);\r\n } else {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"snooze command not supported by specified device\"\r\n }, obj.callback);\r\n }\r\n } catch (error) {\r\n if (error instanceof StationNotFoundError) {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"snooze command not sended because specified station doesn't exists\"\r\n }, obj.callback);\r\n } else if (error instanceof DeviceNotFoundError) {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"snooze command not sended because specified device doesn't exists\"\r\n }, obj.callback);\r\n } else {\r\n throw error;\r\n }\r\n }\r\n } else {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"snooze command not sended because some required parameters are missing\"\r\n }, obj.callback);\r\n }\r\n } else if (obj.command === \"chime\") {\r\n this.log.debug(`snooze command - message: ${JSON.stringify(obj.message)}`);\r\n if (typeof obj.message === \"object\" &&\r\n typeof obj.message.station_sn === \"string\" && obj.message.station_sn !== \"\" &&\r\n (obj.message.ringtone === undefined || typeof obj.message.ringtone === \"number\")) {\r\n try {\r\n const station = await this.eufy.getStation(obj.message.station_sn);\r\n\r\n if (station.hasCommand(CommandName.StationChime)) {\r\n await station.chimeHomebase(obj.message.ringtone !== undefined && typeof obj.message.ringtone === \"number\" ? obj.message.ringtone : 0);\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: true,\r\n result: \"chime command sended\"\r\n }, obj.callback);\r\n } else {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"chime command not supported by specified station\"\r\n }, obj.callback);\r\n }\r\n\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, \"chime command sended\", obj.callback);\r\n } catch (error) {\r\n if (error instanceof StationNotFoundError) {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"snooze command not sended because specified station doesn't exists\"\r\n }, obj.callback);\r\n } else {\r\n throw error;\r\n }\r\n }\r\n }\r\n } else if (obj.command === \"pollRefresh\") {\r\n this.log.debug(`pollRefresh command`);\r\n await this.eufy.refreshCloudData();\r\n\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: true,\r\n result: \"pollRefresh command sended\"\r\n }, obj.callback);\r\n } else {\r\n const errorMessage = `Received unknown message: ${JSON.stringify(obj.message)}`;\r\n this.log.warn(errorMessage);\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: errorMessage\r\n }, obj.callback);\r\n }\r\n } catch (error) {\r\n const errorMessage = `Error during processing of received message: ${error instanceof Error ? `${error.name} - ${error.message}` : error }`;\r\n this.log.error(errorMessage);\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: errorMessage\r\n }, obj.callback);\r\n }\r\n }\r\n }\r\n\r\n private getStateCommon(property: PropertyMetadataAny): ioBroker.StateCommon {\r\n const state: ioBroker.StateCommon = {\r\n name: property.label!,\r\n type: property.type,\r\n role: \"state\",\r\n read: property.readable,\r\n write: property.writeable,\r\n def: property.type === \"object\" && typeof property.default === \"object\" ? JSON.stringify(property.default) : property.default\r\n };\r\n switch (property.type) {\r\n case \"number\": {\r\n const numberProperty = property as PropertyMetadataNumeric;\r\n state.min = numberProperty.min;\r\n state.max = numberProperty.max;\r\n state.states = numberProperty.states;\r\n state.unit = numberProperty.unit;\r\n state.step = numberProperty.steps;\r\n state.role = RoleMapping[property.name] !== undefined ? RoleMapping[property.name] : \"value\";\r\n break;\r\n }\r\n case \"string\": {\r\n state.role = RoleMapping[property.name] !== undefined ? RoleMapping[property.name] : \"text\";\r\n break;\r\n }\r\n case \"boolean\": {\r\n state.role = RoleMapping[property.name] !== undefined ? RoleMapping[property.name] : (property.writeable ? \"switch.enable\" : \"state\");\r\n break;\r\n }\r\n }\r\n return state;\r\n }\r\n\r\n private async createAndSetState(device: Device | Station, property: PropertyMetadataAny): Promise<void> {\r\n if (property.name !== PropertyName.Type && property.name !== PropertyName.DeviceStationSN) {\r\n const state = this.getStateCommon(property);\r\n const id: string = device.getStateID(convertCamelCaseToSnakeCase(property.name));\r\n const obj = await this.getObjectAsync(id);\r\n if (obj) {\r\n let changed = false;\r\n if (obj.native.name !== undefined && obj.native.name !== property.name) {\r\n obj.native.name = property.name;\r\n changed = true;\r\n }\r\n if (obj.native.key !== undefined && obj.native.key !== property.key) {\r\n obj.native.key = property.key;\r\n changed = true;\r\n }\r\n if (obj.native.commandId !== undefined && obj.native.commandId !== property.commandId) {\r\n obj.native.commandId = property.commandId;\r\n changed = true;\r\n }\r\n if (obj.common !== undefined && !util.isDeepStrictEqual(obj.common, state)) {\r\n changed = true;\r\n }\r\n if (changed) {\r\n const propertyMetadata = device.getPropertiesMetadata()[property.name];\r\n if (propertyMetadata !== undefined) {\r\n const newState = this.getStateCommon(propertyMetadata);\r\n obj.common = newState;\r\n }\r\n await this.setObjectAsync(id, obj);\r\n }\r\n } else {\r\n await this.setObjectNotExistsAsync(id, {\r\n type: \"state\",\r\n common: state,\r\n native: {\r\n key: property.key,\r\n commandId: property.commandId,\r\n name: property.name,\r\n },\r\n });\r\n }\r\n const value = device.getPropertyValue(property.name);\r\n if (value !== undefined)\r\n await setStateChangedAsync(this as unknown as ioBroker.Adapter, id, (property.type === \"string\" || property.type === \"object\") && typeof value === \"object\" ? JSON.stringify(value) : value);\r\n }\r\n }\r\n\r\n private async onDeviceAdded(device: Device): Promise<void> {\r\n this.logger.debug(`onDeviceAdded - device: ${device.getSerial()}`);\r\n\r\n await this.setObjectNotExistsAsync(device.getStateID(\"\", 0), {\r\n type: \"channel\",\r\n common: {\r\n name: device.getStateChannel()\r\n },\r\n native: {},\r\n });\r\n\r\n await this.setObjectNotExistsAsync(device.getStateID(\"\", 1), {\r\n type: \"device\",\r\n common: {\r\n name: device.getName()\r\n },\r\n native: {},\r\n });\r\n\r\n const metadata = device.getPropertiesMetadata();\r\n for(const property of Object.values(metadata)) {\r\n if (property.name !== PropertyName.DevicePicture)\r\n this.createAndSetState(device, property);\r\n }\r\n\r\n if (device.hasProperty(PropertyName.DevicePicture)) {\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.PICTURE_URL), {\r\n type: \"state\",\r\n common: {\r\n name: \"Picture URL\",\r\n type: \"string\",\r\n role: \"url\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.PICTURE_HTML), {\r\n type: \"state\",\r\n common: {\r\n name: \"Picture HTML image\",\r\n type: \"string\",\r\n role: \"html\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n }\r\n\r\n if (device.hasCommand(CommandName.DeviceTriggerAlarmSound)) {\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.TRIGGER_ALARM_SOUND), {\r\n type: \"state\",\r\n common: {\r\n name: \"Trigger Alarm Sound\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.RESET_ALARM_SOUND), {\r\n type: \"state\",\r\n common: {\r\n name: \"Reset Alarm Sound\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n }\r\n if (device.hasCommand(CommandName.DevicePanAndTilt)) {\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.PAN_LEFT), {\r\n type: \"state\",\r\n common: {\r\n name: \"Pan Left\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.PAN_RIGHT), {\r\n type: \"state\",\r\n common: {\r\n name: \"Pan Right\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.ROTATE_360), {\r\n type: \"state\",\r\n common: {\r\n name: \"Rotate 360\u00B0\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.TILT_UP), {\r\n type: \"state\",\r\n common: {\r\n name: \"Tilt Up\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.TILT_DOWN), {\r\n type: \"state\",\r\n common: {\r\n name: \"Tilt Down\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n }\r\n if (device.hasCommand(CommandName.DeviceLockCalibration)) {\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.CALIBRATE), {\r\n type: \"state\",\r\n common: {\r\n name: \"Calibrate Lock\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n }\r\n if (device.hasCommand(CommandName.DeviceUnlock)) {\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.UNLOCK), {\r\n type: \"state\",\r\n common: {\r\n name: \"Unlock\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n }\r\n if (device.hasCommand(CommandName.DeviceSetDefaultAngle)) {\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.SET_DEFAULT_ANGLE), {\r\n type: \"state\",\r\n common: {\r\n name: \"Set Default Angle\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n }\r\n if (device.hasCommand(CommandName.DeviceSetPrivacyAngle)) {\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.SET_PRIVACY_ANGLE), {\r\n type: \"state\",\r\n common: {\r\n name: \"Set Default Angle\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n }\r\n if (device.hasCommand(CommandName.DeviceCalibrate)) {\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.CALIBRATE), {\r\n type: \"state\",\r\n common: {\r\n name: \"Calibrate\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n }\r\n if (device.hasCommand(CommandName.DeviceOpen)) {\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.OPEN_BOX), {\r\n type: \"state\",\r\n common: {\r\n name: \"Open Box\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n }\r\n if (device.hasCommand(CommandName.DeviceStartLivestream)) {\r\n // Start Stream\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.START_STREAM), {\r\n type: \"state\",\r\n common: {\r\n name: \"Start stream\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n\r\n // Stop Stream\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.STOP_STREAM), {\r\n type: \"state\",\r\n common: {\r\n name: \"Stop stream\",\r\n type: \"boolean\",\r\n role: \"button.stop\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n\r\n // Livestream URL\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.LIVESTREAM), {\r\n type: \"state\",\r\n common: {\r\n name: \"Livestream URL\",\r\n type: \"string\",\r\n role: \"url\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n\r\n // Livestream RTSP URL\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.LIVESTREAM_RTSP), {\r\n type: \"state\",\r\n common: {\r\n name: \"Livestream RTSP URL\",\r\n type: \"string\",\r\n role: \"url\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n }\r\n\r\n if (device.hasProperty(PropertyName.DeviceRTSPStream)) {\r\n // RTSP Stream URL\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.RTSP_STREAM_URL), {\r\n type: \"state\",\r\n common: {\r\n name: \"RTSP stream URL\",\r\n type: \"string\",\r\n role: \"url\",\r\n read: true,\r\n write: false\r\n },\r\n native: {},\r\n });\r\n }\r\n\r\n //TODO: Deactivated because the decryption of the download has changed.\r\n /*if (device.hasCommand(CommandName.DeviceStartDownload)) {\r\n // Last event video URL\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.LAST_EVENT_VIDEO_URL), {\r\n type: \"state\",\r\n common: {\r\n name: \"Last event video URL\",\r\n type: \"string\",\r\n role: \"url\",\r\n read: true,\r\n write: false,\r\n def: \"\"\r\n },\r\n native: {},\r\n });\r\n\r\n // Last event picture URL\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.LAST_EVENT_PIC_URL), {\r\n type: \"state\",\r\n common: {\r\n name: \"Last event picture URL\",\r\n type: \"string\",\r\n role: \"url\",\r\n read: true,\r\n write: false,\r\n def: \"\"\r\n },\r\n native: {},\r\n });\r\n\r\n // Last event picture HTML image\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.LAST_EVENT_PIC_HTML), {\r\n type: \"state\",\r\n common: {\r\n name: \"Last event picture HTML image\",\r\n type: \"string\",\r\n role: \"html\",\r\n read: true,\r\n write: false,\r\n def: \"\"\r\n },\r\n native: {},\r\n });\r\n }*/\r\n }\r\n\r\n private async onDeviceRemoved(device: Device): Promise<void> {\r\n this.delObjectAsync(device.getStateID(\"\", 0), { recursive: true }).catch((error) => {\r\n this.logger.error(`Error deleting states of removed device`, error);\r\n });\r\n removeFiles(this as unknown as ioBroker.Adapter, device.getStationSerial(), DataLocation.LAST_EVENT, device.getSerial()).catch((error) => {\r\n this.logger.error(`Error deleting fs contents of removed device`, error);\r\n });\r\n }\r\n\r\n private async onStationAdded(station: Station): Promise<void> {\r\n this.subscribeStates(`${station.getStateID(\"\", 0)}.*`);\r\n\r\n await this.setObjectNotExistsAsync(station.getStateID(\"\", 0), {\r\n type: \"device\",\r\n common: {\r\n name: station.getName()\r\n },\r\n native: {},\r\n });\r\n\r\n await this.setObjectNotExistsAsync(station.getStateID(\"\", 1), {\r\n type: \"channel\",\r\n common: {\r\n name: station.getStateChannel()\r\n },\r\n native: {},\r\n });\r\n\r\n await this.setObjectNotExistsAsync(station.getStateID(StationStateID.CONNECTION), {\r\n type: \"state\",\r\n common: {\r\n name: \"Connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(station.getStateID(StationStateID.CONNECTION), { val: false, ack: true });\r\n\r\n const metadata = station.getPropertiesMetadata();\r\n for(const property of Object.values(metadata)) {\r\n this.createAndSetState(station, property);\r\n }\r\n\r\n // Reboot station\r\n if (station.hasCommand(CommandName.StationReboot)) {\r\n await this.setObjectNotExistsAsync(station.getStateID(StationStateID.REBOOT), {\r\n type: \"state\",\r\n common: {\r\n name: \"Reboot station\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n }\r\n // Alarm Sound\r\n if (station.hasCommand(CommandName.StationTriggerAlarmSound)) {\r\n await this.setObjectNotExistsAsync(station.getStateID(StationStateID.TRIGGER_ALARM_SOUND), {\r\n type: \"state\",\r\n common: {\r\n name: \"Trigger Alarm Sound\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(station.getStateID(StationStateID.RESET_ALARM_SOUND), {\r\n type: \"state\",\r\n common: {\r\n name: \"Reset Alarm Sound\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n }\r\n }\r\n\r\n private async onStationRemoved(station: Station): Promise<void> {\r\n this.delObjectAsync(station.getStateID(\"\", 0), { recursive: true }).catch((error) => {\r\n this.logger.error(`Error deleting states of removed station`, error);\r\n });\r\n this.delFileAsync(this.namespace, station.getSerial()).catch((error) => {\r\n this.logger.error(`Error deleting fs contents of removed station`, error);\r\n });\r\n }\r\n\r\n /*private async downloadEventVideo(device: Device, event_time: number, full_path: string | undefined, cipher_id: number | undefined): Promise<void> {\r\n this.logger.debug(`Device: ${device.getSerial()} full_path: ${full_path} cipher_id: ${cipher_id}`);\r\n try {\r\n if (!isEmpty(full_path) && cipher_id !== undefined) {\r\n const station = await this.eufy.getStation(device.getStationSerial());\r\n\r\n if (station !== undefined) {\r\n if (this.downloadEvent[device.getSerial()])\r\n clearTimeout(this.downloadEvent[device.getSerial()]);\r\n\r\n let videoLength = getVideoClipLength(device);\r\n const time_passed = (new Date().getTime() - new Date(event_time).getTime()) / 1000;\r\n\r\n if (time_passed >= videoLength)\r\n videoLength = 1;\r\n else\r\n videoLength = videoLength - time_passed;\r\n\r\n this.logger.info(`Downloading video event for device ${device.getSerial()} in ${videoLength} seconds...`);\r\n this.downloadEvent[device.getSerial()] = setTimeout(async () => {\r\n station.startDownload(device, full_path!, cipher_id);\r\n }, videoLength * 1000);\r\n }\r\n }\r\n } catch (error) {\r\n this.logger.error(`Device: ${device.getSerial()} - Error`, error);\r\n }\r\n }*/\r\n\r\n private async handlePushNotification(message: PushMessage): Promise<void> {\r\n try {\r\n if (message.device_sn !== undefined) {\r\n //TODO: Deactivated because the decryption of the download has changed.\r\n /*const device: Device = await this.eufy.getDevice(message.device_sn);\r\n if ((message.push_count === 1 || message.push_count === undefined) && (message.file_path !== undefined && message.file_path !== \"\" && message.cipher !== undefined))\r\n if (this.config.autoDownloadVideo)\r\n await this.downloadEventVideo(device, message.event_time, message.file_path, message.cipher);*/\r\n }\r\n } catch (error) {\r\n if (error instanceof DeviceNotFoundError) {\r\n //Do nothing\r\n } else {\r\n this.logger.error(\"Handling push notification - Error\", error);\r\n }\r\n }\r\n }\r\n\r\n private async onConnect(): Promise<void> {\r\n await this.setObjectNotExistsAsync(\"info\", {\r\n type: \"channel\",\r\n common: {\r\n name: \"info\"\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(\"info.connection\", {\r\n type: \"state\",\r\n common: {\r\n name: \"Global connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(\"info.connection\", { val: true, ack: true });\r\n\r\n const stations = await this.eufy.getStations();\r\n const stationSerials: string[] = [];\r\n for(const station of stations) {\r\n stationSerials.push(station.getSerial());\r\n }\r\n const devices = await this.eufy.getDevices();\r\n const deviceSerials: string[] = [];\r\n for(const device of devices) {\r\n deviceSerials.push(device.getSerial());\r\n }\r\n\r\n // Delete obsolete stations\r\n try {\r\n const allDevices = await this.getDevicesAsync();\r\n const reg = new RegExp(`^${this.namespace}\\.[0-9A-Z]+$`);\r\n for (const id of allDevices) {\r\n if (id._id.match(reg)) {\r\n const serial = id._id.replace(`${this.namespace}.`, \"\");\r\n if (!stationSerials.includes(serial)) {\r\n await this.delObjectAsync(id._id, { recursive: true });\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n this.log.error(`Delete obsolete stations ERROR - ${JSON.stringify(error)}`);\r\n }\r\n\r\n // Delete obsolete devices\r\n try {\r\n const allDevices = await this.getDevicesAsync();\r\n const reg = new RegExp(`^${this.namespace}\\.[0-9A-Z]+\\.[a-z]+\\.[0-9A-Z]+$`);\r\n for (const id of allDevices) {\r\n if (id._id.match(reg)) {\r\n const values = id._id.split(\".\");\r\n const stateChannel = values[3];\r\n const serial = values[4];\r\n if (!deviceSerials.includes(serial) ||\r\n (deviceSerials.includes(serial) && devices[deviceSerials.indexOf(serial)].getStateChannel() !== \"unknown\" && stateChannel === \"unknown\")) {\r\n await this.delObjectAsync(id._id, { recursive: true });\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n this.log.error(`Delete obsolete devices ERROR - ${JSON.stringify(error)}`);\r\n }\r\n\r\n // Delete obsolete properties\r\n try {\r\n const all = await this.getStatesAsync(\"*\");\r\n if (all) {\r\n Object.keys(all).forEach(async (stateid) => {\r\n const object = await this.getObjectAsync(stateid);\r\n if (object?.native?.name !== undefined) {\r\n const tmp = stateid.split(\".\");\r\n if (tmp.length >= 5) {\r\n const stationSerial = tmp[2];\r\n const deviceSerial = tmp[4];\r\n\r\n if (deviceSerial.match(/^[A-Z0-9]+/)) {\r\n // Device\r\n try {\r\n const device = await this.eufy.getDevice(deviceSerial);\r\n if (!device.hasProperty(object.native.name)) {\r\n this.delObjectAsync(stateid);\r\n }\r\n } catch (error) {\r\n if (error instanceof DeviceNotFoundError) {\r\n } else {\r\n this.log.error(`Delete obsolete properties ERROR - device - ${JSON.stringify(error)}`);\r\n }\r\n }\r\n } else {\r\n // Station\r\n try {\r\n const station = await this.eufy.getStation(stationSerial);\r\n if (!station.hasProperty(object.native.name)) {\r\n this.delObjectAsync(stateid);\r\n }\r\n } catch (error) {\r\n if (error instanceof StationNotFoundError) {\r\n } else {\r\n this.log.error(`Delete obsolete properties ERROR - station - ${JSON.stringify(error)}`);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n });\r\n }\r\n } catch (error) {\r\n this.log.error(`Delete obsolete properties ERROR - ${JSON.stringify(error)}`);\r\n }\r\n\r\n // Delete obsolete directories/files\r\n try {\r\n const contents = await this.readDirAsync(this.namespace, \"\");\r\n for (const content of contents.filter((fn) => fn.file.match(\"^T[0-9A-Z]+$\") !== null && fn.isDir)) {\r\n if (!stationSerials.includes(content.file)) {\r\n await this.delFileAsync(this.namespace, content.file);\r\n } else {\r\n const dirContents = await this.readDirAsync(this.namespace, content.file);\r\n for (const dir of dirContents.filter((fn) => Object.values(DataLocation).includes(fn.file) && fn.isDir)) {\r\n const files = await this.readDirAsync(this.namespace, path.join(content.file, dir.file));\r\n let deletedFiles = 0;\r\n for (const file of files.filter((fn) => !deviceSerials.includes(fn.file.substring(0, 16)) && !fn.isDir)) {\r\n await this.delFileAsync(this.namespace, path.join(content.file, dir.file, file.file));\r\n deletedFiles++;\r\n }\r\n if (deletedFiles === files.length) {\r\n await this.delFileAsync(this.namespace, path.join(content.file, dir.file));\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n this.log.error(`Delete obsolete directories/files ERROR - ${error}`);\r\n }\r\n }\r\n\r\n private async onClose(): Promise<void> {\r\n await this.setStateAsync(\"info.connection\", { val: false, ack: true }).catch();\r\n }\r\n\r\n public getPersistentData(): PersistentData {\r\n return this.persistentData;\r\n }\r\n\r\n private async onPushConnect(): Promise<void> {\r\n await this.setObjectNotExistsAsync(\"info\", {\r\n type: \"channel\",\r\n common: {\r\n name: \"info\"\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(\"info.push_connection\", {\r\n type: \"state\",\r\n common: {\r\n name: \"Push notification connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(\"info.push_connection\", { val: true, ack: true });\r\n }\r\n\r\n private async onPushClose(): Promise<void> {\r\n await this.setObjectNotExistsAsync(\"info\", {\r\n type: \"channel\",\r\n common: {\r\n name: \"info\"\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(\"info.push_connection\", {\r\n type: \"state\",\r\n common: {\r\n name: \"Push notification connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(\"info.push_connection\", { val: false, ack: true });\r\n }\r\n\r\n private async onMQTTConnect(): Promise<void> {\r\n await this.setObjectNotExistsAsync(\"info\", {\r\n type: \"channel\",\r\n common: {\r\n name: \"info\"\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(\"info.mqtt_connection\", {\r\n type: \"state\",\r\n common: {\r\n name: \"MQTT connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(\"info.mqtt_connection\", { val: true, ack: true });\r\n }\r\n\r\n private async onMQTTClose(): Promise<void> {\r\n await this.setObjectNotExistsAsync(\"info\", {\r\n type: \"channel\",\r\n common: {\r\n name: \"info\"\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(\"info.mqtt_connection\", {\r\n type: \"state\",\r\n common: {\r\n name: \"MQTT connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(\"info.mqtt_connection\", { val: false, ack: true });\r\n }\r\n\r\n private async onStationCommandResult(station: Station, result: CommandResult): Promise<void> {\r\n if ((result.return_code !== 0 && result.command_type !== CommandType.P2P_QUERY_STATUS_IN_LOCK && result.command_type !== CommandType.CMD_STORAGE_INFO_HB3) ||\r\n (result.return_code !== ErrorCode.ERROR_DEV_BUSY && result.command_type === CommandType.CMD_STORAGE_INFO_HB3)) {\r\n this.logger.error(`Station: ${station.getSerial()} command ${CommandType[result.command_type]} failed with error: ${ErrorCode[result.return_code]} (${result.return_code})`);\r\n }\r\n }\r\n\r\n private async onStationPropertyChanged(station: Station, name: string, value: PropertyValue): Promise<void> {\r\n const states = await this.getStatesAsync(`${station.getStateID(\"\", 1)}.*`);\r\n for (const state in states) {\r\n const obj = await this.getObjectAsync(state);\r\n if (obj) {\r\n if (obj.native.name !== undefined && obj.native.name === name) {\r\n await setStateChangedAsync(this as unknown as ioBroker.Adapter, state, (obj.common.type === \"string\" || obj.common.type === \"object\") && typeof value === \"object\" ? JSON.stringify(value) : value);\r\n return;\r\n }\r\n }\r\n }\r\n this.logger.debug(`onStationPropertyChanged(): Property \"${name}\" not implemented in this adapter (station: ${station.getSerial()} value: ${JSON.stringify(value)})`);\r\n }\r\n\r\n private async onDevicePropertyChanged(device: Device, name: string, value: PropertyValue): Promise<void> {\r\n const states = await this.getStatesAsync(`${device.getStateID(\"\", 1)}.*`);\r\n for (const state in states) {\r\n const obj = await this.getObjectAsync(state);\r\n if (obj) {\r\n if (obj.native.name !== undefined && obj.native.name === name) {\r\n await setStateChangedAsync(this as unknown as ioBroker.Adapter, state, (obj.common.type === \"string\" || obj.common.type === \"object\") && typeof value === \"object\" ? JSON.stringify(value) : value);\r\n switch(name) {\r\n case PropertyName.DeviceRTSPStream:\r\n if (value as boolean === false) {\r\n this.delStateAsync(device.getStateID(DeviceStateID.RTSP_STREAM_URL));\r\n }\r\n break;\r\n }\r\n return;\r\n }\r\n }\r\n }\r\n if (name === PropertyName.DevicePicture) {\r\n try {\r\n const picture = value as Picture;\r\n const fileName = `${device.getSerial()}.${picture.type.ext}`;\r\n const filePath = path.join(device.getStationSerial(), DataLocation.LAST_EVENT);\r\n if (!await this.fileExistsAsync(this.namespace, filePath)) {\r\n await this.mkdirAsync(this.namespace, filePath);\r\n }\r\n await this.writeFileAsync(this.namespace, path.join(filePath, fileName), picture.data);\r\n\r\n await this.setStateAsync(device.getStateID(DeviceStateID.PICTURE_URL), `/files/${this.namespace}/${device.getStationSerial()}/${DataLocation.LAST_EVENT}/${device.getSerial()}.${picture.type.ext}`, true);\r\n await setStateChangedAsync(this as unknown as ioBroker.Adapter, device.getStateID(DeviceStateID.PICTURE_HTML), getImageAsHTML(picture.data, picture.type.mime));\r\n } catch (err) {\r\n const error = ensureError(err);\r\n this.logger.error(\"onDevicePropertyChanged - Property picture - Error\", error);\r\n }\r\n } else {\r\n this.logger.debug(`onDevicePropertyChanged(): Property \"${name}\" not implemented in this adapter (device: ${device.getSerial()} value: ${JSON.stringify(value)})`);\r\n }\r\n }\r\n\r\n private async startLivestream(device_sn: string): Promise<void> {\r\n try {\r\n const device = await this.eufy.getDevice(device_sn);\r\n const station = await this.eufy.getStation(device.getStationSerial());\r\n\r\n if (station.isConnected() || station.isEnergySavingDevice()) {\r\n if (!station.isLiveStreaming(device)) {\r\n this.eufy.startStationLivestream(device_sn);\r\n } else {\r\n this.logger.warn(`The stream for the device ${device_sn} cannot be started, because it is already streaming!`);\r\n }\r\n } else {\r\n this.logger.warn(`The stream for the device ${device_sn} cannot be started, because there is no connection to station ${station.getSerial()}!`);\r\n }\r\n } catch (error) {\r\n this.logger.error(\"Start livestream - Error\", error);\r\n }\r\n }\r\n\r\n private async stopLivestream(device_sn: string): Promise<void> {\r\n try {\r\n const device = await this.eufy.getDevice(device_sn);\r\n const station = await this.eufy.getStation(device.getStationSerial());\r\n if (device.isCamera()) {\r\n const camera = device as Camera;\r\n if (await this.eufy.isStationConnected(device.getStationSerial()) && station.isLiveStreaming(camera)) {\r\n await this.eufy.stopStationLivestream(device_sn);\r\n } else {\r\n this.logger.warn(`The stream for the device ${device_sn} cannot be stopped, because it isn't streaming!`);\r\n }\r\n }\r\n\r\n } catch (error) {\r\n this.logger.error(\"Stop livestream - Error\", error);\r\n }\r\n }\r\n\r\n private async onStationLivestreamStart(station: Station, device: Device, metadata: StreamMetadata, videostream: Readable, audiostream: Readable): Promise<void> {\r\n try {\r\n this.setStateAsync(device.getStateID(DeviceStateID.LIVESTREAM), { val: `${this.config.https ? \"https\" : \"http\"}://${this.config.hostname}:${this.config.go2rtc_api_port}/stream.html?src=${device.getSerial()}`, ack: true });\r\n this.setStateAsync(device.getStateID(DeviceStateID.LIVESTREAM_RTSP), { val: `rtsp://${this.config.hostname}:${this.config.go2rtc_rtsp_port}/${device.getSerial()}`, ack: true });\r\n //await ffmpegStreamToGo2rtc(this.config, this.namespace, device.getSerial(), metadata, videostream, audiostream, this.logger);\r\n await streamToGo2rtc(device.getSerial(), videostream, audiostream, this.logger, this.config, this.namespace, metadata).catch((error) => {\r\n this.logger.debug(`Station: ${station.getSerial()} Device: ${device.getSerial()} - Stopping livestream...`, error);\r\n });\r\n } catch(error) {\r\n this.logger.error(`Station: ${station.getSerial()} Device: ${device.getSerial()} - Error - Stopping livestream...`, error);\r\n this.eufy.stopStationLivestream(device.getSerial())\r\n .catch(async (error) => {\r\n this.logger.error(`Station: ${station.getSerial()} Device: ${device.getSerial()} - Error during stopping livestream...`, error);\r\n });\r\n }\r\n }\r\n\r\n private onStationLivestreamStop(_station: Station, device: Device): void {\r\n this.delStateAsync(device.getStateID(DeviceStateID.LIVESTREAM));\r\n this.delStateAsync(device.getStateID(DeviceStateID.LIVESTREAM_RTSP));\r\n }\r\n\r\n /*private async onStationDownloadFinish(_station: Station, _device: Device): Promise<void> {\r\n //this.logger.trace(`Station: ${station.getSerial()} channel: ${channel}`);\r\n }*/\r\n\r\n /*private async onStationDownloadStart(station: Station, device: Device, metadata: StreamMetadata, videostream: Readable, audiostream: Readable): Promise<void> {\r\n try {\r\n //TODO: Deactivated because the decryption of the download has changed.\r\n await removeFiles(this, station.getSerial(), DataLocation.TEMP, device.getSerial()).catch();\r\n const file_path = getDataFilePath(this, station.getSerial(), DataLocation.TEMP, `${device.getSerial()}${STREAM_FILE_NAME_EXT}`);\r\n\r\n await ffmpegStreamToHls(this.config, this.namespace, metadata, videostream, audiostream, file_path, this.logger)\r\n .then(async () => {\r\n if (fse.pathExistsSync(file_path)) {\r\n await removeFiles(this, station.getSerial(), DataLocation.LAST_EVENT, device.getSerial());\r\n return true;\r\n }\r\n return false;\r\n })\r\n .then(async (result) => {\r\n if (result)\r\n await moveFiles(this, station.getSerial(), device.getSerial(), DataLocation.TEMP, DataLocation.LAST_EVENT);\r\n return result;\r\n })\r\n .then(async (result) => {\r\n if (result) {\r\n const filename_without_ext = getDataFilePath(this, station.getSerial(), DataLocation.LAST_EVENT, device.getSerial());\r\n setStateAsync(this, device.getStateID(DeviceStateID.LAST_EVENT_VIDEO_URL), \"Last captured video URL\", `/${this.namespace}/${station.getSerial()}/${DataLocation.LAST_EVENT}/${device.getSerial()}${STREAM_FILE_NAME_EXT}`, \"url\");\r\n if (fse.pathExistsSync(`${filename_without_ext}${STREAM_FILE_NAME_EXT}`))\r\n await ffmpegPreviewImage(this.config, `${filename_without_ext}${STREAM_FILE_NAME_EXT}`, `${filename_without_ext}${IMAGE_FILE_JPEG_EXT}`, this.logger)\r\n .then(() => {\r\n setStateAsync(this, device.getStateID(DeviceStateID.LAST_EVENT_PIC_URL), \"Last event picture URL\", `/${this.namespace}/${station.getSerial()}/${DataLocation.LAST_EVENT}/${device.getSerial()}${IMAGE_FILE_JPEG_EXT}`, \"url\");\r\n try {\r\n if (fse.existsSync(`${filename_without_ext}${IMAGE_FILE_JPEG_EXT}`)) {\r\n const image_data = getImageAsHTML(fse.readFileSync(`${filename_without_ext}${IMAGE_FILE_JPEG_EXT}`));\r\n setStateAsync(this, device.getStateID(DeviceStateID.LAST_EVENT_PIC_HTML), \"Last event picture HTML image\", image_data, \"html\");\r\n }\r\n } catch (error) {\r\n this.logger.error(`Station: ${station.getSerial()} device: ${device.getSerial()} - Error`, error);\r\n }\r\n })\r\n .catch((error) => {\r\n this.logger.error(`ffmpegPreviewImage - station: ${station.getSerial()} device: ${device.getSerial()} - Error`, error);\r\n });\r\n }\r\n })\r\n .catch(async (error) => {\r\n this.logger.error(`Station: ${station.getSerial()} Device: ${device.getSerial()} - Error - Cancelling download...`, error);\r\n await this.eufy.cancelStationDownload(device.getSerial());\r\n });\r\n } catch(error) {\r\n this.logger.error(`Station: ${station.getSerial()} Device: ${device.getSerial()} - Error - Cancelling download...`, error);\r\n await this.eufy.cancelStationDownload(device.getSerial());\r\n }\r\n }*/\r\n\r\n private onStationRTSPUrl(station: Station, device: Device, value: string): void {\r\n setStateChangedAsync(this as unknown as ioBroker.Adapter, device.getStateID(DeviceStateID.RTSP_STREAM_URL), value);\r\n }\r\n\r\n private async onStationConnect(station: Station): Promise<void> {\r\n await this.setObjectNotExistsAsync(station.getStateID(StationStateID.CONNECTION), {\r\n type: \"state\",\r\n common: {\r\n name: \"Connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(station.getStateID(StationStateID.CONNECTION), { val: true, ack: true });\r\n }\r\n\r\n private async onStationClose(station: Station): Promise<void> {\r\n await this.setObjectNotExistsAsync(station.getStateID(StationStateID.CONNECTION), {\r\n type: \"state\",\r\n common: {\r\n name: \"Connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(station.getStateID(StationStateID.CONNECTION), { val: false, ack: true });\r\n }\r\n\r\n private onTFARequest(): void {\r\n this.logger.warn(`Two factor authentication request received, please enter valid verification code in state ${this.namespace}.verify_code`);\r\n this.verify_code= true;\r\n }\r\n\r\n private onCaptchaRequest(captchaId: string, captcha: string): void {\r\n this.captchaId = captchaId;\r\n this.logger.warn(`Captcha authentication request received, please enter valid captcha in state ${this.namespace}.captcha`);\r\n this.logger.warn(`Captcha: <img src=\"${captcha}\">`);\r\n this.setStateAsync(\"received_captcha_html\", { val: `<img src=\"${captcha}\">`, ack: true });\r\n }\r\n\r\n}\r\n\r\nif (require.main !== module) {\r\n // Export the constructor in compact mode\r\n module.exports = (options: Partial<utils.AdapterOptions> | undefined) => new euSec(options);\r\n} else {\r\n // otherwise start the instance directly\r\n (() => new euSec())();\r\n}"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/*\r\n * Created with @iobroker/create-adapter v2.5.0\r\n */\r\n\r\n// The adapter-core module gives you access to the core ioBroker functions\r\n// you need to create an adapter\r\nimport * as utils from \"@iobroker/adapter-core\";\r\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\r\nimport { strict } from \"assert\";\r\nimport * as path from \"path\";\r\nimport { Camera, Device, Station, PushMessage, P2PConnectionType, EufySecurity, EufySecurityConfig, CommandResult, CommandType, ErrorCode, PropertyValue, PropertyName, StreamMetadata, PropertyMetadataNumeric, PropertyMetadataAny, CommandName, PanTiltDirection, DeviceNotFoundError, LoginOptions, Picture, StationNotFoundError, ensureError, LogLevel, TFCardStatus } from \"eufy-security-client\";\r\nimport { getAlpha2Code as getCountryCode } from \"i18n-iso-countries\"\r\nimport { isValid as isValidLanguageCode } from \"@cospired/i18n-iso-languages\"\r\nimport { Readable } from \"stream\";\r\nimport util from \"util\";\r\nimport childProcess from \"child_process\";\r\nimport pathToGo2rtc from \"go2rtc-static\";\r\nimport pathToFfmpeg from \"ffmpeg-for-homebridge\";\r\n\r\nimport { DeviceStateID, DataLocation, RoleMapping, StationStateID } from \"./lib/types\";\r\nimport { convertCamelCaseToSnakeCase, getImageAsHTML, handleUpdate, removeFiles, removeLastChar, setStateChangedAsync } from \"./lib/utils\";\r\nimport { PersistentData } from \"./lib/interfaces\";\r\nimport { ioBrokerLogger } from \"./lib/log\";\r\nimport { streamToGo2rtc } from \"./lib/video\";\r\n\r\nexport class euSec extends utils.Adapter {\r\n\r\n private eufy!: EufySecurity;\r\n /*private downloadEvent: {\r\n [index: string]: NodeJS.Timeout;\r\n } = {};*/\r\n\r\n private persistentFile: string = \"adapter.json\";\r\n private persistentDriverFile: string = \"driver.json\";\r\n private logger!: ioBrokerLogger;\r\n private persistentData: PersistentData = {\r\n version: \"\"\r\n };\r\n private captchaId: string | null = null;\r\n private verify_code = false;\r\n private skipInit = false;\r\n\r\n public constructor(options: Partial<utils.AdapterOptions> = {}) {\r\n super({\r\n ...options,\r\n name: \"eusec\",\r\n });\r\n\r\n this.on(\"ready\", this.onReady.bind(this));\r\n this.on(\"stateChange\", this.onStateChange.bind(this));\r\n // this.on(\"objectChange\", this.onObjectChange.bind(this));\r\n this.on(\"message\", this.onMessage.bind(this));\r\n this.on(\"unload\", this.onUnload.bind(this));\r\n }\r\n\r\n public restartAdapter(): void {\r\n this.skipInit = true;\r\n this.restart();\r\n }\r\n\r\n /**\r\n * Is called when databases are connected and adapter received configuration.\r\n */\r\n private async onReady(): Promise<void> {\r\n\r\n this.logger = new ioBrokerLogger(this.log as ioBroker.Logger);\r\n\r\n await this.setObjectNotExistsAsync(\"verify_code\", {\r\n type: \"state\",\r\n common: {\r\n name: \"2FA verification code\",\r\n type: \"string\",\r\n role: \"state\",\r\n read: true,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(\"received_captcha_html\", {\r\n type: \"state\",\r\n common: {\r\n name: \"Received captcha image HTML\",\r\n type: \"string\",\r\n role: \"state\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(\"captcha\", {\r\n type: \"state\",\r\n common: {\r\n name: \"Enter captcha\",\r\n type: \"string\",\r\n role: \"state\",\r\n read: true,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(\"info\", {\r\n type: \"channel\",\r\n common: {\r\n name: \"info\"\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(\"info.connection\", {\r\n type: \"state\",\r\n common: {\r\n name: \"Global connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(\"info.connection\", { val: false, ack: true });\r\n await this.setObjectNotExistsAsync(\"info.push_connection\", {\r\n type: \"state\",\r\n common: {\r\n name: \"Push notification connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(\"info.push_connection\", { val: false, ack: true });\r\n await this.setObjectNotExistsAsync(\"info.mqtt_connection\", {\r\n type: \"state\",\r\n common: {\r\n name: \"MQTT connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(\"info.mqtt_connection\", { val: false, ack: true });\r\n\r\n try {\r\n const connection = await this.getStatesAsync(\"*.connection\");\r\n if (connection)\r\n Object.keys(connection).forEach(async id => {\r\n await this.setStateAsync(id, { val: false, ack: true });\r\n });\r\n } catch (error) {\r\n this.logger.error(\"Reset connection states - Error\", error);\r\n }\r\n\r\n try {\r\n const sensorList = [\r\n PropertyName.DeviceMotionDetected,\r\n PropertyName.DevicePersonDetected,\r\n PropertyName.DeviceSoundDetected,\r\n PropertyName.DeviceCryingDetected,\r\n PropertyName.DevicePetDetected,\r\n PropertyName.DeviceRinging\r\n ];\r\n for(const sensorName of sensorList) {\r\n const sensors = await this.getStatesAsync(`*.${convertCamelCaseToSnakeCase(sensorName)}`);\r\n if (sensors)\r\n Object.keys(sensors).forEach(async id => {\r\n await this.setStateAsync(id, { val: false, ack: true });\r\n });\r\n }\r\n } catch (error) {\r\n this.logger.error(\"Reset sensor states - Error\", error);\r\n }\r\n\r\n try {\r\n if (await this.fileExistsAsync(this.namespace, this.persistentFile)) {\r\n const fileContent = await this.readFileAsync(this.namespace, this.persistentFile);\r\n this.persistentData = JSON.parse(fileContent.file.toString(\"utf8\")) as PersistentData;\r\n }\r\n } catch (error) {\r\n this.logger.debug(\"No adapter stored data from last exit found.\", error);\r\n }\r\n\r\n let persistentDriverData: string = \"{}\";\r\n try {\r\n if (await this.fileExistsAsync(this.namespace, this.persistentDriverFile)) {\r\n const fileContent = await this.readFileAsync(this.namespace, this.persistentDriverFile);\r\n persistentDriverData = fileContent.file.toString(\"utf8\");\r\n }\r\n } catch (error) {\r\n this.logger.debug(\"No driver stored data from last exit found.\", error);\r\n }\r\n\r\n this.subscribeStates(\"verify_code\");\r\n this.subscribeStates(\"captcha\");\r\n\r\n const hosts = await this.getForeignObjectsAsync(\"system.host.*\", \"host\");\r\n if (hosts !== undefined && hosts !== null && Object.values(hosts).length !== 0) {\r\n if (this.config.hostname === \"\") {\r\n this.config.hostname = Object.values(hosts)[0].native.os.hostname;\r\n }\r\n\r\n const nodeVersion = Object.values(hosts)[0].native.process.versions.node;\r\n const nodeMajorVersion = nodeVersion.split(\".\")[0];\r\n\r\n let fixNeeded;\r\n switch (parseInt(nodeMajorVersion)) {\r\n case 18:\r\n fixNeeded = nodeVersion.localeCompare(\"18.19.1\", undefined, { numeric: true, sensitivity: \"base\" });\r\n break;\r\n case 20:\r\n fixNeeded = nodeVersion.localeCompare(\"20.11.1\", undefined, { numeric: true, sensitivity: \"base\" });\r\n break;\r\n default:\r\n fixNeeded = nodeVersion.localeCompare(\"21.6.2\", undefined, { numeric: true, sensitivity: \"base\" });\r\n break;\r\n }\r\n if (fixNeeded >= 0) {\r\n const adapter = await this.getForeignObjectAsync(`system.adapter.${this.namespace}`);\r\n if (adapter !== undefined && adapter !== null) {\r\n if (!adapter.common.nodeProcessParams?.includes(\"--security-revert=CVE-2023-46809\")) {\r\n adapter.common.nodeProcessParams = [\"--security-revert=CVE-2023-46809\"]\r\n await this.setForeignObjectAsync(`system.adapter.${this.namespace}`, adapter);\r\n this.log.warn(\"Required fix to use livestreaming with this version of Node.js (CVE-2023-46809) applied. Restart of the adapter initiated to activate the fix.\");\r\n this.restartAdapter();\r\n }\r\n }\r\n }\r\n }\r\n\r\n if (!this.skipInit) {\r\n const systemConfig = await this.getForeignObjectAsync(\"system.config\");\r\n let countryCode = undefined;\r\n let languageCode = undefined;\r\n if (systemConfig) {\r\n countryCode = getCountryCode(systemConfig.common.country!, \"en\");\r\n if (isValidLanguageCode(systemConfig.common.language))\r\n languageCode = systemConfig.common.language;\r\n }\r\n if (this.config.country !== \"iobroker\") {\r\n countryCode = this.config.country;\r\n }\r\n\r\n // Handling adapter version update\r\n try {\r\n if (this.persistentData.version !== this.version) {\r\n const currentVersion = Number.parseFloat(removeLastChar(this.version!, \".\"));\r\n const previousVersion = this.persistentData.version !== \"\" && this.persistentData.version !== undefined ? Number.parseFloat(removeLastChar(this.persistentData.version, \".\")) : 0;\r\n this.logger.debug(`Handling of adapter update - currentVersion: ${currentVersion} previousVersion: ${previousVersion}`);\r\n\r\n if (previousVersion < currentVersion) {\r\n await handleUpdate(this, this.logger, previousVersion, currentVersion);\r\n this.persistentData.version = this.version!;\r\n await this.writePersistentData();\r\n }\r\n }\r\n } catch (error) {\r\n this.logger.error(`Handling of adapter update - Error:`, error);\r\n }\r\n\r\n let connectionType = P2PConnectionType.QUICKEST;\r\n if (this.config.p2pConnectionType === \"only_local\") {\r\n connectionType = P2PConnectionType.ONLY_LOCAL;\r\n }\r\n\r\n if (this.config.username !== \"\" && this.config.password !== \"\") {\r\n const config: EufySecurityConfig = {\r\n username: this.config.username,\r\n password: this.config.password,\r\n country: countryCode,\r\n language: languageCode,\r\n persistentData: persistentDriverData,\r\n eventDurationSeconds: this.config.eventDuration,\r\n p2pConnectionSetup: connectionType,\r\n pollingIntervalMinutes: this.config.pollingInterval,\r\n acceptInvitations: this.config.acceptInvitations,\r\n logging: {\r\n level: this.log.level === \"silly\" ? LogLevel.Trace : this.log.level === \"debug\" ? LogLevel.Debug : this.log.level === \"info\" ? LogLevel.Info : this.log.level === \"warn\" ? LogLevel.Warn : this.log.level === \"error\" ? LogLevel.Error : LogLevel.Info\r\n }\r\n };\r\n\r\n this.eufy = await EufySecurity.initialize(config, this.logger);\r\n this.eufy.on(\"persistent data\", (data: string) => this.onPersistentData(data))\r\n this.eufy.on(\"station added\", (station: Station) => this.onStationAdded(station));\r\n this.eufy.on(\"device added\", (device: Device) => this.onDeviceAdded(device));\r\n this.eufy.on(\"station removed\", (station: Station) => this.onStationRemoved(station));\r\n this.eufy.on(\"device removed\", (device: Device) => this.onDeviceRemoved(device));\r\n this.eufy.on(\"push message\", (messages) => this.handlePushNotification(messages));\r\n this.eufy.on(\"push connect\", () => this.onPushConnect());\r\n this.eufy.on(\"push close\", () => this.onPushClose());\r\n this.eufy.on(\"mqtt connect\", () => this.onMQTTConnect());\r\n this.eufy.on(\"mqtt close\", () => this.onMQTTClose());\r\n this.eufy.on(\"connect\", () => this.onConnect());\r\n this.eufy.on(\"close\", () => this.onClose());\r\n\r\n this.eufy.on(\"device property changed\", (device: Device, name: string, value: PropertyValue) => this.onDevicePropertyChanged(device, name, value));\r\n\r\n this.eufy.on(\"station command result\", (station: Station, result: CommandResult) => this.onStationCommandResult(station, result));\r\n //this.eufy.on(\"station download start\", (station: Station, device: Device, metadata: StreamMetadata, videostream: Readable, audiostream: Readable) => this.onStationDownloadStart(station, device, metadata, videostream, audiostream));\r\n //this.eufy.on(\"station download finish\", (station: Station, device: Device) => this.onStationDownloadFinish(station, device));\r\n this.eufy.on(\"station livestream start\", (station: Station, device: Device, metadata: StreamMetadata, videostream: Readable, audiostream: Readable) => this.onStationLivestreamStart(station, device, metadata, videostream, audiostream));\r\n this.eufy.on(\"station livestream stop\", (station: Station, device: Device) => this.onStationLivestreamStop(station, device));\r\n this.eufy.on(\"station rtsp url\", (station: Station, device: Device, value: string) => this.onStationRTSPUrl(station, device, value));\r\n this.eufy.on(\"station property changed\", (station: Station, name: string, value: PropertyValue) => this.onStationPropertyChanged(station, name, value));\r\n this.eufy.on(\"station connect\", (station: Station) => this.onStationConnect(station));\r\n this.eufy.on(\"station close\", (station: Station) => this.onStationClose(station));\r\n this.eufy.on(\"tfa request\", () => this.onTFARequest());\r\n this.eufy.on(\"captcha request\", (captchaId: string, captcha: string) => this.onCaptchaRequest(captchaId, captcha));\r\n this.eufy.setCameraMaxLivestreamDuration(this.config.maxLivestreamDuration);\r\n\r\n await this.eufy.connect();\r\n\r\n if (pathToGo2rtc) {\r\n const go2rtcConfig: {\r\n [index: string]: {\r\n [index: string]: string | number | null\r\n }\r\n } = {\r\n \"api\": {\r\n \"listen\": `:${this.config.go2rtc_api_port}`\r\n },\r\n \"rtsp\": {\r\n \"listen\": `:${this.config.go2rtc_rtsp_port}`\r\n },\r\n \"srtp\": {\r\n \"listen\": `:${this.config.go2rtc_srtp_port}`\r\n },\r\n \"webrtc\": {\r\n \"listen\": `:${this.config.go2rtc_webrtc_port}`\r\n },\r\n \"ffmpeg\": {\r\n \"bin\": pathToFfmpeg !== \"\" && pathToFfmpeg !== undefined ? pathToFfmpeg : \"ffmpeg\",\r\n },\r\n \"streams\": {},\r\n /*\"log\": {\r\n \"level\": \"debug\", // default level\r\n \"api\": \"debug\",\r\n \"exec\": \"debug\",\r\n \"ngrok\": \"debug\",\r\n \"rtsp\": \"debug\",\r\n \"streams\": \"debug\",\r\n \"webrtc\": \"debug\",\r\n }*/\r\n };\r\n if (this.config.go2rtc_rtsp_username !== \"\" && this.config.go2rtc_rtsp_password !== \"\") {\r\n go2rtcConfig.rtsp.username = this.config.go2rtc_rtsp_username;\r\n go2rtcConfig.rtsp.password = this.config.go2rtc_rtsp_password;\r\n }\r\n for (const device of await this.eufy.getDevices()) {\r\n go2rtcConfig.streams[device.getSerial()] = null;\r\n }\r\n const go2rtc = childProcess.spawn(pathToGo2rtc, [\"-config\", JSON.stringify(go2rtcConfig)], { shell: false, detached: false, windowsHide: true });\r\n go2rtc.on(\"error\", (error) => {\r\n this.log.error(`go2rtc error: ${error}`);\r\n });\r\n go2rtc.stdout.setEncoding(\"utf8\");\r\n go2rtc.stdout.on(\"data\", (data) => {\r\n this.log.info(`go2rtc started: ${data}`);\r\n });\r\n go2rtc.stderr.setEncoding(\"utf8\");\r\n go2rtc.stderr.on(\"data\", (data) => {\r\n this.log.error(`go2rtc error: ${data}`);\r\n });\r\n go2rtc.on(\"close\", (exitcode) => {\r\n this.log.info(`go2rtc terminated with exitcode ${exitcode}`);\r\n });\r\n process.on(\"exit\", () => {\r\n go2rtc.kill();\r\n });\r\n }\r\n }\r\n // Delete cunknown channels without childs\r\n const channels = await this.getChannelsAsync();\r\n for (const channel of channels) {\r\n if (channel.common.name === \"unknown\") {\r\n const states = await this.getStatesAsync(`${channel._id}.*`);\r\n if (Object.keys(states).length === 0) {\r\n await this.delObjectAsync(channel._id);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n public async writePersistentData(): Promise<void> {\r\n try {\r\n await this.writeFileAsync(this.namespace, this.persistentFile, JSON.stringify(this.persistentData));\r\n } catch(error) {\r\n this.logger.error(`writePersistentData() - Error: ${error}`);\r\n }\r\n }\r\n\r\n private onPersistentData(data: string): void {\r\n this.writeFileAsync(this.namespace, this.persistentDriverFile, data).catch((error) => {\r\n this.logger.error(`writePersistentDriverData() - Error: ${error}`);\r\n });\r\n }\r\n\r\n /**\r\n * Is called when adapter shuts down - callback has to be called under any circumstances!\r\n */\r\n private async onUnload(callback: () => void): Promise<void> {\r\n try {\r\n\r\n await this.writePersistentData();\r\n\r\n if (this.eufy) {\r\n if (this.eufy.isConnected())\r\n await this.setStateAsync(\"info.connection\", { val: false, ack: true }).catch();\r\n this.eufy.removeAllListeners();\r\n this.eufy.close();\r\n }\r\n\r\n callback();\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n } catch (e) {\r\n callback();\r\n }\r\n }\r\n\r\n // If you need to react to object changes, uncomment the following block and the corresponding line in the constructor.\r\n // You also need to subscribe to the objects with `this.subscribeObjects`, similar to `this.subscribeStates`.\r\n // /**\r\n // * Is called if a subscribed object changes\r\n // */\r\n // private onObjectChange(id: string, obj: ioBroker.Object | null | undefined): void {\r\n // if (obj) {\r\n // // The object was changed\r\n // this.log.info(`object ${id} changed: ${JSON.stringify(obj)}`);\r\n // } else {\r\n // // The object was deleted\r\n // this.log.info(`object ${id} deleted`);\r\n // }\r\n // }\r\n\r\n /**\r\n * Is called if a subscribed state changes\r\n */\r\n private async onStateChange(id: string, state: ioBroker.State | null | undefined): Promise<void> {\r\n if (state) {\r\n\r\n // don't do anything if the state is acked\r\n if (!id || state.ack) {\r\n this.logger.debug(`state ${id} changed: ${state.val} (ack = ${state.ack}) was already acknowledged, ignore it...`);\r\n return;\r\n }\r\n this.logger.debug(`state ${id} changed: ${state.val} (ack = ${state.ack})`);\r\n\r\n const values = id.split(\".\");\r\n const station_sn = values[2];\r\n const device_type = values[3];\r\n\r\n if (station_sn == \"verify_code\") {\r\n if (this.eufy && this.verify_code) {\r\n this.logger.info(`Verification code received, send it. (verify_code: ${state.val})`);\r\n await this.eufy.connect({ verifyCode: state.val as string } as LoginOptions);\r\n this.verify_code = false;\r\n await this.delStateAsync(id);\r\n }\r\n } else if (station_sn == \"captcha\") {\r\n if (this.eufy && this.captchaId) {\r\n this.logger.info(`Captcha received, send it. (captcha: ${state.val})`);\r\n await this.eufy.connect({\r\n captcha: {\r\n captchaCode: state.val as string,\r\n captchaId: this.captchaId\r\n }\r\n } as LoginOptions);\r\n this.captchaId = null;\r\n await this.delStateAsync(id);\r\n await this.delStateAsync(\"received_captcha_html\");\r\n }\r\n } else if (device_type == \"station\") {\r\n try {\r\n const station_state_name = values[4];\r\n if (this.eufy) {\r\n const obj = await this.getObjectAsync(id);\r\n if (obj) {\r\n if (obj.native.name !== undefined) {\r\n await this.eufy.setStationProperty(station_sn, obj.native.name, state.val);\r\n return;\r\n }\r\n }\r\n\r\n const station = await this.eufy.getStation(station_sn);\r\n switch(station_state_name) {\r\n case StationStateID.REBOOT:\r\n await station.rebootHUB();\r\n break;\r\n case StationStateID.TRIGGER_ALARM_SOUND:\r\n await station.triggerStationAlarmSound(this.config.alarmSoundDuration);\r\n break;\r\n case StationStateID.RESET_ALARM_SOUND:\r\n await station.resetStationAlarmSound();\r\n break;\r\n }\r\n }\r\n } catch (error) {\r\n this.logger.error(`station - Error:`, error);\r\n }\r\n } else {\r\n try {\r\n const device_sn = values[4];\r\n const obj = await this.getObjectAsync(id);\r\n if (obj) {\r\n if (obj.native.name !== undefined) {\r\n try {\r\n await this.eufy.setDeviceProperty(device_sn, obj.native.name, obj.common.type === \"object\" ? JSON.parse(state.val as string) : state.val);\r\n } catch (error) {\r\n this.logger.error(`Error in setting property value (property: ${obj.native.name} value: ${state.val})`, error);\r\n }\r\n return;\r\n }\r\n }\r\n\r\n const device_state_name = values[5];\r\n const station = await this.eufy.getStation(station_sn);\r\n const device = await this.eufy.getDevice(device_sn);\r\n\r\n switch(device_state_name) {\r\n case DeviceStateID.START_STREAM:\r\n await this.startLivestream(device_sn);\r\n break;\r\n case DeviceStateID.STOP_STREAM:\r\n await this.stopLivestream(device_sn);\r\n break;\r\n case DeviceStateID.TRIGGER_ALARM_SOUND:\r\n await station.triggerDeviceAlarmSound(device, this.config.alarmSoundDuration);\r\n break;\r\n case DeviceStateID.RESET_ALARM_SOUND:\r\n await station.resetDeviceAlarmSound(device);\r\n break;\r\n case DeviceStateID.ROTATE_360:\r\n await station.panAndTilt(device, PanTiltDirection.ROTATE360);\r\n break;\r\n case DeviceStateID.PAN_LEFT:\r\n await station.panAndTilt(device, PanTiltDirection.LEFT);\r\n break;\r\n case DeviceStateID.PAN_RIGHT:\r\n await station.panAndTilt(device, PanTiltDirection.RIGHT);\r\n break;\r\n case DeviceStateID.TILT_UP:\r\n await station.panAndTilt(device, PanTiltDirection.UP);\r\n break;\r\n case DeviceStateID.TILT_DOWN:\r\n await station.panAndTilt(device, PanTiltDirection.DOWN);\r\n break;\r\n case DeviceStateID.CALIBRATE:\r\n if (device.isLock()) {\r\n await station.calibrateLock(device);\r\n } else {\r\n await station.calibrate(device);\r\n }\r\n break;\r\n case DeviceStateID.UNLOCK:\r\n await station.unlock(device);\r\n break;\r\n case DeviceStateID.SET_DEFAULT_ANGLE:\r\n await station.setDefaultAngle(device);\r\n break;\r\n case DeviceStateID.SET_PRIVACY_ANGLE:\r\n await station.setPrivacyAngle(device);\r\n break;\r\n case DeviceStateID.OPEN_BOX:\r\n await station.open(device);\r\n break;\r\n }\r\n } catch (error) {\r\n this.logger.error(`cameras - Error:`, error);\r\n }\r\n }\r\n } else {\r\n // The state was deleted\r\n this.logger.debug(`state ${id} deleted`);\r\n }\r\n }\r\n\r\n /**\r\n * Some message was sent to this instance over message box. Used by email, pushover, text2speech, ...\r\n * Using this method requires \"common.message\" property to be set to true in io-package.json\r\n */\r\n private async onMessage(obj: ioBroker.Message): Promise<void> {\r\n if (typeof obj === \"object\" && obj.message) {\r\n try {\r\n if (obj.command === \"quickResponse\") {\r\n this.log.debug(`quickResponse command - message: ${JSON.stringify(obj.message)}`);\r\n if (typeof obj.message === \"object\" &&\r\n typeof obj.message.station_sn === \"string\" && obj.message.station_sn !== \"\" &&\r\n typeof obj.message.device_sn === \"string\" && obj.message.device_sn !== \"\" &&\r\n typeof obj.message.voice_id === \"number\") {\r\n try {\r\n const station = await this.eufy.getStation(obj.message.station_sn);\r\n const device = await this.eufy.getDevice(obj.message.device_sn);\r\n\r\n if (device.hasCommand(CommandName.DeviceQuickResponse)) {\r\n await station.quickResponse(device, obj.message.voice_id);\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: true,\r\n result: \"quickResponse command sended\"\r\n }, obj.callback);\r\n } else {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"quickResponse command not supported by specified device\"\r\n }, obj.callback);\r\n }\r\n } catch (error) {\r\n if (error instanceof StationNotFoundError) {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"quickResponse command not sended because specified station doesn't exists\"\r\n }, obj.callback);\r\n } else if (error instanceof DeviceNotFoundError) {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"quickResponse command not sended because specified device doesn't exists\"\r\n }, obj.callback);\r\n } else {\r\n throw error;\r\n }\r\n }\r\n } else {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"quickResponse command not sended because some required parameters are missing\"\r\n }, obj.callback);\r\n }\r\n } else if (obj.command === \"getQuickResponseVoices\") {\r\n this.log.debug(`getQuickResponseVoices command - message: ${JSON.stringify(obj.message)}`);\r\n if (typeof obj.message === \"object\" &&\r\n typeof obj.message.device_sn === \"string\" && obj.message.device_sn !== \"\") {\r\n const voices = await this.eufy.getApi().getVoices(obj.message.device_sn);\r\n\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: true,\r\n result: voices\r\n }, obj.callback);\r\n } else {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"getQuickResponseVoices command not sended because some required parameters are missing\"\r\n }, obj.callback);\r\n }\r\n } else if (obj.command === \"snooze\") {\r\n this.log.debug(`snooze command - message: ${JSON.stringify(obj.message)}`);\r\n if (typeof obj.message === \"object\" &&\r\n typeof obj.message.station_sn === \"string\" && obj.message.station_sn !== \"\" &&\r\n typeof obj.message.device_sn === \"string\" && obj.message.device_sn !== \"\" &&\r\n typeof obj.message.snooze_time === \"number\" &&\r\n (obj.message.snooze_chime === undefined || typeof obj.message.snooze_chime === \"boolean\") &&\r\n (obj.message.snooze_homebase === undefined || typeof obj.message.snooze_homebase === \"boolean\") &&\r\n (obj.message.snooze_motion === undefined || typeof obj.message.snooze_motion === \"boolean\")) {\r\n try {\r\n const station = await this.eufy.getStation(obj.message.station_sn);\r\n const device = await this.eufy.getDevice(obj.message.device_sn);\r\n\r\n if (device.hasCommand(CommandName.DeviceSnooze)) {\r\n await station.snooze(device, {\r\n snooze_time: obj.message.snooze_time,\r\n snooze_chime: obj.message.snooze_chime,\r\n snooze_homebase: obj.message.snooze_homebase,\r\n snooze_motion: obj.message.snooze_motion,\r\n });\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: true,\r\n result: \"snooze command sended\"\r\n }, obj.callback);\r\n } else {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"snooze command not supported by specified device\"\r\n }, obj.callback);\r\n }\r\n } catch (error) {\r\n if (error instanceof StationNotFoundError) {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"snooze command not sended because specified station doesn't exists\"\r\n }, obj.callback);\r\n } else if (error instanceof DeviceNotFoundError) {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"snooze command not sended because specified device doesn't exists\"\r\n }, obj.callback);\r\n } else {\r\n throw error;\r\n }\r\n }\r\n } else {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"snooze command not sended because some required parameters are missing\"\r\n }, obj.callback);\r\n }\r\n } else if (obj.command === \"chime\") {\r\n this.log.debug(`snooze command - message: ${JSON.stringify(obj.message)}`);\r\n if (typeof obj.message === \"object\" &&\r\n typeof obj.message.station_sn === \"string\" && obj.message.station_sn !== \"\" &&\r\n (obj.message.ringtone === undefined || typeof obj.message.ringtone === \"number\")) {\r\n try {\r\n const station = await this.eufy.getStation(obj.message.station_sn);\r\n\r\n if (station.hasCommand(CommandName.StationChime)) {\r\n await station.chimeHomebase(obj.message.ringtone !== undefined && typeof obj.message.ringtone === \"number\" ? obj.message.ringtone : 0);\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: true,\r\n result: \"chime command sended\"\r\n }, obj.callback);\r\n } else {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"chime command not supported by specified station\"\r\n }, obj.callback);\r\n }\r\n\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, \"chime command sended\", obj.callback);\r\n } catch (error) {\r\n if (error instanceof StationNotFoundError) {\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: \"snooze command not sended because specified station doesn't exists\"\r\n }, obj.callback);\r\n } else {\r\n throw error;\r\n }\r\n }\r\n }\r\n } else if (obj.command === \"pollRefresh\") {\r\n this.log.debug(`pollRefresh command`);\r\n await this.eufy.refreshCloudData();\r\n\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: true,\r\n result: \"pollRefresh command sended\"\r\n }, obj.callback);\r\n } else {\r\n const errorMessage = `Received unknown message: ${JSON.stringify(obj.message)}`;\r\n this.log.warn(errorMessage);\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: errorMessage\r\n }, obj.callback);\r\n }\r\n } catch (error) {\r\n const errorMessage = `Error during processing of received message: ${error instanceof Error ? `${error.name} - ${error.message}` : error }`;\r\n this.log.error(errorMessage);\r\n if (obj.callback)\r\n this.sendTo(obj.from, obj.command, {\r\n sended: false,\r\n result: errorMessage\r\n }, obj.callback);\r\n }\r\n }\r\n }\r\n\r\n private getStateCommon(property: PropertyMetadataAny): ioBroker.StateCommon {\r\n const state: ioBroker.StateCommon = {\r\n name: property.label!,\r\n type: property.type,\r\n role: \"state\",\r\n read: property.readable,\r\n write: property.writeable,\r\n def: property.type === \"object\" && typeof property.default === \"object\" ? JSON.stringify(property.default) : property.default\r\n };\r\n switch (property.type) {\r\n case \"number\": {\r\n const numberProperty = property as PropertyMetadataNumeric;\r\n state.min = numberProperty.min;\r\n state.max = numberProperty.max;\r\n state.states = numberProperty.states;\r\n state.unit = numberProperty.unit;\r\n state.step = numberProperty.steps;\r\n state.role = RoleMapping[property.name] !== undefined ? RoleMapping[property.name] : \"value\";\r\n break;\r\n }\r\n case \"string\": {\r\n state.role = RoleMapping[property.name] !== undefined ? RoleMapping[property.name] : \"text\";\r\n break;\r\n }\r\n case \"boolean\": {\r\n state.role = RoleMapping[property.name] !== undefined ? RoleMapping[property.name] : (property.writeable ? \"switch.enable\" : \"state\");\r\n break;\r\n }\r\n }\r\n return state;\r\n }\r\n\r\n private async createAndSetState(device: Device | Station, property: PropertyMetadataAny): Promise<void> {\r\n if (property.name !== PropertyName.Type && property.name !== PropertyName.DeviceStationSN) {\r\n const state = this.getStateCommon(property);\r\n const id: string = device.getStateID(convertCamelCaseToSnakeCase(property.name));\r\n const obj = await this.getObjectAsync(id);\r\n if (obj) {\r\n let changed = false;\r\n if (obj.native.name !== undefined && obj.native.name !== property.name) {\r\n obj.native.name = property.name;\r\n changed = true;\r\n }\r\n if (obj.native.key !== undefined && obj.native.key !== property.key) {\r\n obj.native.key = property.key;\r\n changed = true;\r\n }\r\n if (obj.native.commandId !== undefined && obj.native.commandId !== property.commandId) {\r\n obj.native.commandId = property.commandId;\r\n changed = true;\r\n }\r\n if (obj.common !== undefined && !util.isDeepStrictEqual(obj.common, state)) {\r\n changed = true;\r\n }\r\n if (changed) {\r\n const propertyMetadata = device.getPropertiesMetadata()[property.name];\r\n if (propertyMetadata !== undefined) {\r\n const newState = this.getStateCommon(propertyMetadata);\r\n obj.common = newState;\r\n }\r\n await this.setObjectAsync(id, obj);\r\n }\r\n } else {\r\n await this.setObjectNotExistsAsync(id, {\r\n type: \"state\",\r\n common: state,\r\n native: {\r\n key: property.key,\r\n commandId: property.commandId,\r\n name: property.name,\r\n },\r\n });\r\n }\r\n const value = device.getPropertyValue(property.name);\r\n if (value !== undefined)\r\n await setStateChangedAsync(this as unknown as ioBroker.Adapter, id, (property.type === \"string\" || property.type === \"object\") && typeof value === \"object\" ? JSON.stringify(value) : value);\r\n }\r\n }\r\n\r\n private async onDeviceAdded(device: Device): Promise<void> {\r\n this.logger.debug(`onDeviceAdded - device: ${device.getSerial()}`);\r\n\r\n await this.setObjectNotExistsAsync(device.getStateID(\"\", 0), {\r\n type: \"channel\",\r\n common: {\r\n name: device.getStateChannel()\r\n },\r\n native: {},\r\n });\r\n\r\n await this.setObjectNotExistsAsync(device.getStateID(\"\", 1), {\r\n type: \"device\",\r\n common: {\r\n name: device.getName()\r\n },\r\n native: {},\r\n });\r\n\r\n const metadata = device.getPropertiesMetadata();\r\n for(const property of Object.values(metadata)) {\r\n if (property.name !== PropertyName.DevicePicture)\r\n this.createAndSetState(device, property);\r\n }\r\n\r\n if (device.hasProperty(PropertyName.DevicePicture)) {\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.PICTURE_URL), {\r\n type: \"state\",\r\n common: {\r\n name: \"Picture URL\",\r\n type: \"string\",\r\n role: \"url\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.PICTURE_HTML), {\r\n type: \"state\",\r\n common: {\r\n name: \"Picture HTML image\",\r\n type: \"string\",\r\n role: \"html\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n }\r\n\r\n if (device.hasCommand(CommandName.DeviceTriggerAlarmSound)) {\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.TRIGGER_ALARM_SOUND), {\r\n type: \"state\",\r\n common: {\r\n name: \"Trigger Alarm Sound\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.RESET_ALARM_SOUND), {\r\n type: \"state\",\r\n common: {\r\n name: \"Reset Alarm Sound\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n }\r\n if (device.hasCommand(CommandName.DevicePanAndTilt)) {\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.PAN_LEFT), {\r\n type: \"state\",\r\n common: {\r\n name: \"Pan Left\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.PAN_RIGHT), {\r\n type: \"state\",\r\n common: {\r\n name: \"Pan Right\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.ROTATE_360), {\r\n type: \"state\",\r\n common: {\r\n name: \"Rotate 360\u00B0\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.TILT_UP), {\r\n type: \"state\",\r\n common: {\r\n name: \"Tilt Up\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.TILT_DOWN), {\r\n type: \"state\",\r\n common: {\r\n name: \"Tilt Down\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n }\r\n if (device.hasCommand(CommandName.DeviceLockCalibration)) {\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.CALIBRATE), {\r\n type: \"state\",\r\n common: {\r\n name: \"Calibrate Lock\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n }\r\n if (device.hasCommand(CommandName.DeviceUnlock)) {\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.UNLOCK), {\r\n type: \"state\",\r\n common: {\r\n name: \"Unlock\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n }\r\n if (device.hasCommand(CommandName.DeviceSetDefaultAngle)) {\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.SET_DEFAULT_ANGLE), {\r\n type: \"state\",\r\n common: {\r\n name: \"Set Default Angle\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n }\r\n if (device.hasCommand(CommandName.DeviceSetPrivacyAngle)) {\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.SET_PRIVACY_ANGLE), {\r\n type: \"state\",\r\n common: {\r\n name: \"Set Default Angle\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n }\r\n if (device.hasCommand(CommandName.DeviceCalibrate)) {\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.CALIBRATE), {\r\n type: \"state\",\r\n common: {\r\n name: \"Calibrate\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n }\r\n if (device.hasCommand(CommandName.DeviceOpen)) {\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.OPEN_BOX), {\r\n type: \"state\",\r\n common: {\r\n name: \"Open Box\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n }\r\n if (device.hasCommand(CommandName.DeviceStartLivestream)) {\r\n // Start Stream\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.START_STREAM), {\r\n type: \"state\",\r\n common: {\r\n name: \"Start stream\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n\r\n // Stop Stream\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.STOP_STREAM), {\r\n type: \"state\",\r\n common: {\r\n name: \"Stop stream\",\r\n type: \"boolean\",\r\n role: \"button.stop\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n\r\n // Livestream URL\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.LIVESTREAM), {\r\n type: \"state\",\r\n common: {\r\n name: \"Livestream URL\",\r\n type: \"string\",\r\n role: \"url\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n\r\n // Livestream RTSP URL\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.LIVESTREAM_RTSP), {\r\n type: \"state\",\r\n common: {\r\n name: \"Livestream RTSP URL\",\r\n type: \"string\",\r\n role: \"url\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n }\r\n\r\n if (device.hasProperty(PropertyName.DeviceRTSPStream)) {\r\n // RTSP Stream URL\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.RTSP_STREAM_URL), {\r\n type: \"state\",\r\n common: {\r\n name: \"RTSP stream URL\",\r\n type: \"string\",\r\n role: \"url\",\r\n read: true,\r\n write: false\r\n },\r\n native: {},\r\n });\r\n }\r\n\r\n //TODO: Deactivated because the decryption of the download has changed.\r\n /*if (device.hasCommand(CommandName.DeviceStartDownload)) {\r\n // Last event video URL\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.LAST_EVENT_VIDEO_URL), {\r\n type: \"state\",\r\n common: {\r\n name: \"Last event video URL\",\r\n type: \"string\",\r\n role: \"url\",\r\n read: true,\r\n write: false,\r\n def: \"\"\r\n },\r\n native: {},\r\n });\r\n\r\n // Last event picture URL\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.LAST_EVENT_PIC_URL), {\r\n type: \"state\",\r\n common: {\r\n name: \"Last event picture URL\",\r\n type: \"string\",\r\n role: \"url\",\r\n read: true,\r\n write: false,\r\n def: \"\"\r\n },\r\n native: {},\r\n });\r\n\r\n // Last event picture HTML image\r\n await this.setObjectNotExistsAsync(device.getStateID(DeviceStateID.LAST_EVENT_PIC_HTML), {\r\n type: \"state\",\r\n common: {\r\n name: \"Last event picture HTML image\",\r\n type: \"string\",\r\n role: \"html\",\r\n read: true,\r\n write: false,\r\n def: \"\"\r\n },\r\n native: {},\r\n });\r\n }*/\r\n }\r\n\r\n private async onDeviceRemoved(device: Device): Promise<void> {\r\n this.delObjectAsync(device.getStateID(\"\", 0), { recursive: true }).catch((error) => {\r\n this.logger.error(`Error deleting states of removed device`, error);\r\n });\r\n removeFiles(this as unknown as ioBroker.Adapter, device.getStationSerial(), DataLocation.LAST_EVENT, device.getSerial()).catch((error) => {\r\n this.logger.error(`Error deleting fs contents of removed device`, error);\r\n });\r\n }\r\n\r\n private async onStationAdded(station: Station): Promise<void> {\r\n this.subscribeStates(`${station.getStateID(\"\", 0)}.*`);\r\n\r\n await this.setObjectNotExistsAsync(station.getStateID(\"\", 0), {\r\n type: \"device\",\r\n common: {\r\n name: station.getName()\r\n },\r\n native: {},\r\n });\r\n\r\n await this.setObjectNotExistsAsync(station.getStateID(\"\", 1), {\r\n type: \"channel\",\r\n common: {\r\n name: station.getStateChannel()\r\n },\r\n native: {},\r\n });\r\n\r\n await this.setObjectNotExistsAsync(station.getStateID(StationStateID.CONNECTION), {\r\n type: \"state\",\r\n common: {\r\n name: \"Connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(station.getStateID(StationStateID.CONNECTION), { val: false, ack: true });\r\n\r\n const metadata = station.getPropertiesMetadata();\r\n for(const property of Object.values(metadata)) {\r\n this.createAndSetState(station, property);\r\n }\r\n\r\n // Reboot station\r\n if (station.hasCommand(CommandName.StationReboot)) {\r\n await this.setObjectNotExistsAsync(station.getStateID(StationStateID.REBOOT), {\r\n type: \"state\",\r\n common: {\r\n name: \"Reboot station\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n }\r\n // Alarm Sound\r\n if (station.hasCommand(CommandName.StationTriggerAlarmSound)) {\r\n await this.setObjectNotExistsAsync(station.getStateID(StationStateID.TRIGGER_ALARM_SOUND), {\r\n type: \"state\",\r\n common: {\r\n name: \"Trigger Alarm Sound\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(station.getStateID(StationStateID.RESET_ALARM_SOUND), {\r\n type: \"state\",\r\n common: {\r\n name: \"Reset Alarm Sound\",\r\n type: \"boolean\",\r\n role: \"button.start\",\r\n read: false,\r\n write: true,\r\n },\r\n native: {},\r\n });\r\n }\r\n }\r\n\r\n private async onStationRemoved(station: Station): Promise<void> {\r\n this.delObjectAsync(station.getStateID(\"\", 0), { recursive: true }).catch((error) => {\r\n this.logger.error(`Error deleting states of removed station`, error);\r\n });\r\n this.delFileAsync(this.namespace, station.getSerial()).catch((error) => {\r\n this.logger.error(`Error deleting fs contents of removed station`, error);\r\n });\r\n }\r\n\r\n /*private async downloadEventVideo(device: Device, event_time: number, full_path: string | undefined, cipher_id: number | undefined): Promise<void> {\r\n this.logger.debug(`Device: ${device.getSerial()} full_path: ${full_path} cipher_id: ${cipher_id}`);\r\n try {\r\n if (!isEmpty(full_path) && cipher_id !== undefined) {\r\n const station = await this.eufy.getStation(device.getStationSerial());\r\n\r\n if (station !== undefined) {\r\n if (this.downloadEvent[device.getSerial()])\r\n clearTimeout(this.downloadEvent[device.getSerial()]);\r\n\r\n let videoLength = getVideoClipLength(device);\r\n const time_passed = (new Date().getTime() - new Date(event_time).getTime()) / 1000;\r\n\r\n if (time_passed >= videoLength)\r\n videoLength = 1;\r\n else\r\n videoLength = videoLength - time_passed;\r\n\r\n this.logger.info(`Downloading video event for device ${device.getSerial()} in ${videoLength} seconds...`);\r\n this.downloadEvent[device.getSerial()] = setTimeout(async () => {\r\n station.startDownload(device, full_path!, cipher_id);\r\n }, videoLength * 1000);\r\n }\r\n }\r\n } catch (error) {\r\n this.logger.error(`Device: ${device.getSerial()} - Error`, error);\r\n }\r\n }*/\r\n\r\n private async handlePushNotification(message: PushMessage): Promise<void> {\r\n try {\r\n if (message.device_sn !== undefined) {\r\n //TODO: Deactivated because the decryption of the download has changed.\r\n /*const device: Device = await this.eufy.getDevice(message.device_sn);\r\n if ((message.push_count === 1 || message.push_count === undefined) && (message.file_path !== undefined && message.file_path !== \"\" && message.cipher !== undefined))\r\n if (this.config.autoDownloadVideo)\r\n await this.downloadEventVideo(device, message.event_time, message.file_path, message.cipher);*/\r\n }\r\n } catch (error) {\r\n if (error instanceof DeviceNotFoundError) {\r\n //Do nothing\r\n } else {\r\n this.logger.error(\"Handling push notification - Error\", error);\r\n }\r\n }\r\n }\r\n\r\n private async onConnect(): Promise<void> {\r\n await this.setObjectNotExistsAsync(\"info\", {\r\n type: \"channel\",\r\n common: {\r\n name: \"info\"\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(\"info.connection\", {\r\n type: \"state\",\r\n common: {\r\n name: \"Global connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(\"info.connection\", { val: true, ack: true });\r\n\r\n const stations = await this.eufy.getStations();\r\n const stationSerials: string[] = [];\r\n for(const station of stations) {\r\n stationSerials.push(station.getSerial());\r\n }\r\n const devices = await this.eufy.getDevices();\r\n const deviceSerials: string[] = [];\r\n for(const device of devices) {\r\n deviceSerials.push(device.getSerial());\r\n }\r\n\r\n // Delete obsolete stations\r\n try {\r\n const allDevices = await this.getDevicesAsync();\r\n const reg = new RegExp(`^${this.namespace}\\.[0-9A-Z]+$`);\r\n for (const id of allDevices) {\r\n if (id._id.match(reg)) {\r\n const serial = id._id.replace(`${this.namespace}.`, \"\");\r\n if (!stationSerials.includes(serial)) {\r\n await this.delObjectAsync(id._id, { recursive: true });\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n this.log.error(`Delete obsolete stations ERROR - ${JSON.stringify(error)}`);\r\n }\r\n\r\n // Delete obsolete devices\r\n try {\r\n const allDevices = await this.getDevicesAsync();\r\n const reg = new RegExp(`^${this.namespace}\\.[0-9A-Z]+\\.[a-z]+\\.[0-9A-Z]+$`);\r\n for (const id of allDevices) {\r\n if (id._id.match(reg)) {\r\n const values = id._id.split(\".\");\r\n const stateChannel = values[3];\r\n const serial = values[4];\r\n if (!deviceSerials.includes(serial) ||\r\n (deviceSerials.includes(serial) && devices[deviceSerials.indexOf(serial)].getStateChannel() !== \"unknown\" && stateChannel === \"unknown\")) {\r\n await this.delObjectAsync(id._id, { recursive: true });\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n this.log.error(`Delete obsolete devices ERROR - ${JSON.stringify(error)}`);\r\n }\r\n\r\n // Delete obsolete properties\r\n try {\r\n const all = await this.getStatesAsync(\"*\");\r\n if (all) {\r\n Object.keys(all).forEach(async (stateid) => {\r\n const object = await this.getObjectAsync(stateid);\r\n if (object?.native?.name !== undefined) {\r\n const tmp = stateid.split(\".\");\r\n if (tmp.length >= 5) {\r\n const stationSerial = tmp[2];\r\n const deviceSerial = tmp[4];\r\n\r\n if (deviceSerial.match(/^[A-Z0-9]+/)) {\r\n // Device\r\n try {\r\n const device = await this.eufy.getDevice(deviceSerial);\r\n if (!device.hasProperty(object.native.name)) {\r\n this.delObjectAsync(stateid);\r\n }\r\n } catch (error) {\r\n if (error instanceof DeviceNotFoundError) {\r\n } else {\r\n this.log.error(`Delete obsolete properties ERROR - device - ${JSON.stringify(error)}`);\r\n }\r\n }\r\n } else {\r\n // Station\r\n try {\r\n const station = await this.eufy.getStation(stationSerial);\r\n if (!station.hasProperty(object.native.name)) {\r\n this.delObjectAsync(stateid);\r\n }\r\n } catch (error) {\r\n if (error instanceof StationNotFoundError) {\r\n } else {\r\n this.log.error(`Delete obsolete properties ERROR - station - ${JSON.stringify(error)}`);\r\n }\r\n }\r\n }\r\n }\r\n }\r\n });\r\n }\r\n } catch (error) {\r\n this.log.error(`Delete obsolete properties ERROR - ${JSON.stringify(error)}`);\r\n }\r\n\r\n // Delete obsolete directories/files\r\n try {\r\n const contents = await this.readDirAsync(this.namespace, \"\");\r\n for (const content of contents.filter((fn) => fn.file.match(\"^T[0-9A-Z]+$\") !== null && fn.isDir)) {\r\n if (!stationSerials.includes(content.file)) {\r\n await this.delFileAsync(this.namespace, content.file);\r\n } else {\r\n const dirContents = await this.readDirAsync(this.namespace, content.file);\r\n for (const dir of dirContents.filter((fn) => Object.values(DataLocation).includes(fn.file) && fn.isDir)) {\r\n const files = await this.readDirAsync(this.namespace, path.join(content.file, dir.file));\r\n let deletedFiles = 0;\r\n for (const file of files.filter((fn) => !deviceSerials.includes(fn.file.substring(0, 16)) && !fn.isDir)) {\r\n await this.delFileAsync(this.namespace, path.join(content.file, dir.file, file.file));\r\n deletedFiles++;\r\n }\r\n if (deletedFiles === files.length) {\r\n await this.delFileAsync(this.namespace, path.join(content.file, dir.file));\r\n }\r\n }\r\n }\r\n }\r\n } catch (error) {\r\n this.log.error(`Delete obsolete directories/files ERROR - ${error}`);\r\n }\r\n }\r\n\r\n private async onClose(): Promise<void> {\r\n await this.setStateAsync(\"info.connection\", { val: false, ack: true }).catch();\r\n }\r\n\r\n public getPersistentData(): PersistentData {\r\n return this.persistentData;\r\n }\r\n\r\n private async onPushConnect(): Promise<void> {\r\n await this.setObjectNotExistsAsync(\"info\", {\r\n type: \"channel\",\r\n common: {\r\n name: \"info\"\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(\"info.push_connection\", {\r\n type: \"state\",\r\n common: {\r\n name: \"Push notification connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(\"info.push_connection\", { val: true, ack: true });\r\n }\r\n\r\n private async onPushClose(): Promise<void> {\r\n await this.setObjectNotExistsAsync(\"info\", {\r\n type: \"channel\",\r\n common: {\r\n name: \"info\"\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(\"info.push_connection\", {\r\n type: \"state\",\r\n common: {\r\n name: \"Push notification connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(\"info.push_connection\", { val: false, ack: true });\r\n }\r\n\r\n private async onMQTTConnect(): Promise<void> {\r\n await this.setObjectNotExistsAsync(\"info\", {\r\n type: \"channel\",\r\n common: {\r\n name: \"info\"\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(\"info.mqtt_connection\", {\r\n type: \"state\",\r\n common: {\r\n name: \"MQTT connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(\"info.mqtt_connection\", { val: true, ack: true });\r\n }\r\n\r\n private async onMQTTClose(): Promise<void> {\r\n await this.setObjectNotExistsAsync(\"info\", {\r\n type: \"channel\",\r\n common: {\r\n name: \"info\"\r\n },\r\n native: {},\r\n });\r\n await this.setObjectNotExistsAsync(\"info.mqtt_connection\", {\r\n type: \"state\",\r\n common: {\r\n name: \"MQTT connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(\"info.mqtt_connection\", { val: false, ack: true });\r\n }\r\n\r\n private async onStationCommandResult(station: Station, result: CommandResult): Promise<void> {\r\n if ((result.return_code !== 0 && result.command_type !== CommandType.P2P_QUERY_STATUS_IN_LOCK && result.command_type !== CommandType.CMD_STORAGE_INFO_HB3 && result.command_type !== CommandType.CMD_SDINFO_EX) ||\r\n (result.return_code !== 0 && result.return_code !== ErrorCode.ERROR_DEV_BUSY && result.command_type === CommandType.CMD_STORAGE_INFO_HB3)) {\r\n this.logger.error(`Station: ${station.getSerial()} command ${CommandType[result.command_type]} failed with error: ${ErrorCode[result.return_code]} (${result.return_code})`);\r\n } else if (result.return_code !== 0 && result.return_code !== TFCardStatus.REMOVE && result.return_code !== TFCardStatus.BUSY && result.command_type === CommandType.CMD_SDINFO_EX) {\r\n this.logger.error(`Station: ${station.getSerial()} command ${CommandType[result.command_type]} failed with error: ${TFCardStatus[result.return_code]} (${result.return_code})`);\r\n }\r\n }\r\n\r\n private async onStationPropertyChanged(station: Station, name: string, value: PropertyValue): Promise<void> {\r\n const states = await this.getStatesAsync(`${station.getStateID(\"\", 1)}.*`);\r\n for (const state in states) {\r\n const obj = await this.getObjectAsync(state);\r\n if (obj) {\r\n if (obj.native.name !== undefined && obj.native.name === name) {\r\n await setStateChangedAsync(this as unknown as ioBroker.Adapter, state, (obj.common.type === \"string\" || obj.common.type === \"object\") && typeof value === \"object\" ? JSON.stringify(value) : value);\r\n return;\r\n }\r\n }\r\n }\r\n this.logger.debug(`onStationPropertyChanged(): Property \"${name}\" not implemented in this adapter (station: ${station.getSerial()} value: ${JSON.stringify(value)})`);\r\n }\r\n\r\n private async onDevicePropertyChanged(device: Device, name: string, value: PropertyValue): Promise<void> {\r\n const states = await this.getStatesAsync(`${device.getStateID(\"\", 1)}.*`);\r\n for (const state in states) {\r\n const obj = await this.getObjectAsync(state);\r\n if (obj) {\r\n if (obj.native.name !== undefined && obj.native.name === name) {\r\n await setStateChangedAsync(this as unknown as ioBroker.Adapter, state, (obj.common.type === \"string\" || obj.common.type === \"object\") && typeof value === \"object\" ? JSON.stringify(value) : value);\r\n switch(name) {\r\n case PropertyName.DeviceRTSPStream:\r\n if (value as boolean === false) {\r\n this.delStateAsync(device.getStateID(DeviceStateID.RTSP_STREAM_URL));\r\n }\r\n break;\r\n }\r\n return;\r\n }\r\n }\r\n }\r\n if (name === PropertyName.DevicePicture) {\r\n try {\r\n const picture = value as Picture;\r\n const fileName = `${device.getSerial()}.${picture.type.ext}`;\r\n const filePath = path.join(device.getStationSerial(), DataLocation.LAST_EVENT);\r\n if (!await this.fileExistsAsync(this.namespace, filePath)) {\r\n await this.mkdirAsync(this.namespace, filePath);\r\n }\r\n await this.writeFileAsync(this.namespace, path.join(filePath, fileName), picture.data);\r\n\r\n await this.setStateAsync(device.getStateID(DeviceStateID.PICTURE_URL), `/files/${this.namespace}/${device.getStationSerial()}/${DataLocation.LAST_EVENT}/${device.getSerial()}.${picture.type.ext}`, true);\r\n await setStateChangedAsync(this as unknown as ioBroker.Adapter, device.getStateID(DeviceStateID.PICTURE_HTML), getImageAsHTML(picture.data, picture.type.mime));\r\n } catch (err) {\r\n const error = ensureError(err);\r\n this.logger.error(\"onDevicePropertyChanged - Property picture - Error\", error);\r\n }\r\n } else {\r\n this.logger.debug(`onDevicePropertyChanged(): Property \"${name}\" not implemented in this adapter (device: ${device.getSerial()} value: ${JSON.stringify(value)})`);\r\n }\r\n }\r\n\r\n private async startLivestream(device_sn: string): Promise<void> {\r\n try {\r\n const device = await this.eufy.getDevice(device_sn);\r\n const station = await this.eufy.getStation(device.getStationSerial());\r\n\r\n if (station.isConnected() || station.isEnergySavingDevice()) {\r\n if (!station.isLiveStreaming(device)) {\r\n this.eufy.startStationLivestream(device_sn);\r\n } else {\r\n this.logger.warn(`The stream for the device ${device_sn} cannot be started, because it is already streaming!`);\r\n }\r\n } else {\r\n this.logger.warn(`The stream for the device ${device_sn} cannot be started, because there is no connection to station ${station.getSerial()}!`);\r\n }\r\n } catch (error) {\r\n this.logger.error(\"Start livestream - Error\", error);\r\n }\r\n }\r\n\r\n private async stopLivestream(device_sn: string): Promise<void> {\r\n try {\r\n const device = await this.eufy.getDevice(device_sn);\r\n const station = await this.eufy.getStation(device.getStationSerial());\r\n if (device.isCamera()) {\r\n const camera = device as Camera;\r\n if (await this.eufy.isStationConnected(device.getStationSerial()) && station.isLiveStreaming(camera)) {\r\n await this.eufy.stopStationLivestream(device_sn);\r\n } else {\r\n this.logger.warn(`The stream for the device ${device_sn} cannot be stopped, because it isn't streaming!`);\r\n }\r\n }\r\n\r\n } catch (error) {\r\n this.logger.error(\"Stop livestream - Error\", error);\r\n }\r\n }\r\n\r\n private async onStationLivestreamStart(station: Station, device: Device, metadata: StreamMetadata, videostream: Readable, audiostream: Readable): Promise<void> {\r\n try {\r\n this.setStateAsync(device.getStateID(DeviceStateID.LIVESTREAM), { val: `${this.config.https ? \"https\" : \"http\"}://${this.config.hostname}:${this.config.go2rtc_api_port}/stream.html?src=${device.getSerial()}`, ack: true });\r\n this.setStateAsync(device.getStateID(DeviceStateID.LIVESTREAM_RTSP), { val: `rtsp://${this.config.hostname}:${this.config.go2rtc_rtsp_port}/${device.getSerial()}`, ack: true });\r\n //await ffmpegStreamToGo2rtc(this.config, this.namespace, device.getSerial(), metadata, videostream, audiostream, this.logger);\r\n await streamToGo2rtc(device.getSerial(), videostream, audiostream, this.logger, this.config, this.namespace, metadata).catch((error) => {\r\n this.logger.debug(`Station: ${station.getSerial()} Device: ${device.getSerial()} - Stopping livestream...`, error);\r\n });\r\n } catch(error) {\r\n this.logger.error(`Station: ${station.getSerial()} Device: ${device.getSerial()} - Error - Stopping livestream...`, error);\r\n this.eufy.stopStationLivestream(device.getSerial())\r\n .catch(async (error) => {\r\n this.logger.error(`Station: ${station.getSerial()} Device: ${device.getSerial()} - Error during stopping livestream...`, error);\r\n });\r\n }\r\n }\r\n\r\n private onStationLivestreamStop(_station: Station, device: Device): void {\r\n this.delStateAsync(device.getStateID(DeviceStateID.LIVESTREAM));\r\n this.delStateAsync(device.getStateID(DeviceStateID.LIVESTREAM_RTSP));\r\n }\r\n\r\n /*private async onStationDownloadFinish(_station: Station, _device: Device): Promise<void> {\r\n //this.logger.trace(`Station: ${station.getSerial()} channel: ${channel}`);\r\n }*/\r\n\r\n /*private async onStationDownloadStart(station: Station, device: Device, metadata: StreamMetadata, videostream: Readable, audiostream: Readable): Promise<void> {\r\n try {\r\n //TODO: Deactivated because the decryption of the download has changed.\r\n await removeFiles(this, station.getSerial(), DataLocation.TEMP, device.getSerial()).catch();\r\n const file_path = getDataFilePath(this, station.getSerial(), DataLocation.TEMP, `${device.getSerial()}${STREAM_FILE_NAME_EXT}`);\r\n\r\n await ffmpegStreamToHls(this.config, this.namespace, metadata, videostream, audiostream, file_path, this.logger)\r\n .then(async () => {\r\n if (fse.pathExistsSync(file_path)) {\r\n await removeFiles(this, station.getSerial(), DataLocation.LAST_EVENT, device.getSerial());\r\n return true;\r\n }\r\n return false;\r\n })\r\n .then(async (result) => {\r\n if (result)\r\n await moveFiles(this, station.getSerial(), device.getSerial(), DataLocation.TEMP, DataLocation.LAST_EVENT);\r\n return result;\r\n })\r\n .then(async (result) => {\r\n if (result) {\r\n const filename_without_ext = getDataFilePath(this, station.getSerial(), DataLocation.LAST_EVENT, device.getSerial());\r\n setStateAsync(this, device.getStateID(DeviceStateID.LAST_EVENT_VIDEO_URL), \"Last captured video URL\", `/${this.namespace}/${station.getSerial()}/${DataLocation.LAST_EVENT}/${device.getSerial()}${STREAM_FILE_NAME_EXT}`, \"url\");\r\n if (fse.pathExistsSync(`${filename_without_ext}${STREAM_FILE_NAME_EXT}`))\r\n await ffmpegPreviewImage(this.config, `${filename_without_ext}${STREAM_FILE_NAME_EXT}`, `${filename_without_ext}${IMAGE_FILE_JPEG_EXT}`, this.logger)\r\n .then(() => {\r\n setStateAsync(this, device.getStateID(DeviceStateID.LAST_EVENT_PIC_URL), \"Last event picture URL\", `/${this.namespace}/${station.getSerial()}/${DataLocation.LAST_EVENT}/${device.getSerial()}${IMAGE_FILE_JPEG_EXT}`, \"url\");\r\n try {\r\n if (fse.existsSync(`${filename_without_ext}${IMAGE_FILE_JPEG_EXT}`)) {\r\n const image_data = getImageAsHTML(fse.readFileSync(`${filename_without_ext}${IMAGE_FILE_JPEG_EXT}`));\r\n setStateAsync(this, device.getStateID(DeviceStateID.LAST_EVENT_PIC_HTML), \"Last event picture HTML image\", image_data, \"html\");\r\n }\r\n } catch (error) {\r\n this.logger.error(`Station: ${station.getSerial()} device: ${device.getSerial()} - Error`, error);\r\n }\r\n })\r\n .catch((error) => {\r\n this.logger.error(`ffmpegPreviewImage - station: ${station.getSerial()} device: ${device.getSerial()} - Error`, error);\r\n });\r\n }\r\n })\r\n .catch(async (error) => {\r\n this.logger.error(`Station: ${station.getSerial()} Device: ${device.getSerial()} - Error - Cancelling download...`, error);\r\n await this.eufy.cancelStationDownload(device.getSerial());\r\n });\r\n } catch(error) {\r\n this.logger.error(`Station: ${station.getSerial()} Device: ${device.getSerial()} - Error - Cancelling download...`, error);\r\n await this.eufy.cancelStationDownload(device.getSerial());\r\n }\r\n }*/\r\n\r\n private onStationRTSPUrl(station: Station, device: Device, value: string): void {\r\n setStateChangedAsync(this as unknown as ioBroker.Adapter, device.getStateID(DeviceStateID.RTSP_STREAM_URL), value);\r\n }\r\n\r\n private async onStationConnect(station: Station): Promise<void> {\r\n await this.setObjectNotExistsAsync(station.getStateID(StationStateID.CONNECTION), {\r\n type: \"state\",\r\n common: {\r\n name: \"Connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(station.getStateID(StationStateID.CONNECTION), { val: true, ack: true });\r\n }\r\n\r\n private async onStationClose(station: Station): Promise<void> {\r\n await this.setObjectNotExistsAsync(station.getStateID(StationStateID.CONNECTION), {\r\n type: \"state\",\r\n common: {\r\n name: \"Connection\",\r\n type: \"boolean\",\r\n role: \"indicator.connection\",\r\n read: true,\r\n write: false,\r\n },\r\n native: {},\r\n });\r\n await this.setStateAsync(station.getStateID(StationStateID.CONNECTION), { val: false, ack: true });\r\n }\r\n\r\n private onTFARequest(): void {\r\n this.logger.warn(`Two factor authentication request received, please enter valid verification code in state ${this.namespace}.verify_code`);\r\n this.verify_code= true;\r\n }\r\n\r\n private onCaptchaRequest(captchaId: string, captcha: string): void {\r\n this.captchaId = captchaId;\r\n this.logger.warn(`Captcha authentication request received, please enter valid captcha in state ${this.namespace}.captcha`);\r\n this.logger.warn(`Captcha: <img src=\"${captcha}\">`);\r\n this.setStateAsync(\"received_captcha_html\", { val: `<img src=\"${captcha}\">`, ack: true });\r\n }\r\n\r\n}\r\n\r\nif (require.main !== module) {\r\n // Export the constructor in compact mode\r\n module.exports = (options: Partial<utils.AdapterOptions> | undefined) => new euSec(options);\r\n} else {\r\n // otherwise start the instance directly\r\n (() => new euSec())();\r\n}"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["getCountryCode", "isValidLanguageCode", "pathToGo2rtc", "pathToFfmpeg", "childProcess", "util", "error"]
|
|
7
7
|
}
|
package/io-package.json
CHANGED
|
@@ -1,8 +1,34 @@
|
|
|
1
1
|
{
|
|
2
2
|
"common": {
|
|
3
3
|
"name": "eusec",
|
|
4
|
-
"version": "1.3.
|
|
4
|
+
"version": "1.3.3",
|
|
5
5
|
"news": {
|
|
6
|
+
"1.3.3": {
|
|
7
|
+
"en": "Updated version of the package eufy-security-client (3.1.1)\n",
|
|
8
|
+
"uk": "Updated version of the package eufy-security-client (3.1.1)\n",
|
|
9
|
+
"de": "Version des Pakets eufy-security-client (3.1.1) aktualisiert\n",
|
|
10
|
+
"ru": "Обновленная версия пакета eufy-security-client (3.1.1)\n",
|
|
11
|
+
"pt": "Versão atualizada do pacote eufy-security-client (3.1.1)\n",
|
|
12
|
+
"nl": "Bijgewerkte versie van het pakket eufy-security-client (3.1.1)\n",
|
|
13
|
+
"fr": "Version mise à jour du paquet eufy-security-client (3.1.1)\n",
|
|
14
|
+
"it": "Aggiornata la versione del pacchetto eufy-security-client (3.1.1)\n",
|
|
15
|
+
"es": "Versión actualizada del paquete eufy-security-client (3.1.1)\n",
|
|
16
|
+
"pl": "Zaktualizowana wersja pakietu eufy-security-client (3.1.1)\n",
|
|
17
|
+
"zh-cn": "包 eufy-security-client (3.1.1) 的更新版本\n"
|
|
18
|
+
},
|
|
19
|
+
"1.3.2": {
|
|
20
|
+
"en": "Fixed issue #440\n",
|
|
21
|
+
"uk": "Fixed issue #440\n",
|
|
22
|
+
"de": "Problem #440 behoben\n",
|
|
23
|
+
"ru": "Исправлена проблема #440\n",
|
|
24
|
+
"pt": "Corrigido o problema #440\n",
|
|
25
|
+
"nl": "Probleem #440 opgelost\n",
|
|
26
|
+
"fr": "Correction du problème #440\n",
|
|
27
|
+
"it": "Risolto il problema #440\n",
|
|
28
|
+
"es": "Solucionado el problema #440\n",
|
|
29
|
+
"pl": "Naprawiono błąd #440\n",
|
|
30
|
+
"zh-cn": "修正問題 #440\n"
|
|
31
|
+
},
|
|
6
32
|
"1.3.1": {
|
|
7
33
|
"en": "Fixed issues #436, #439\n",
|
|
8
34
|
"uk": "Fixed issues #436, #439\n",
|
|
@@ -41,19 +67,6 @@
|
|
|
41
67
|
"es": "Versión actualizada del paquete eufy-security-client (2.9.1)\n",
|
|
42
68
|
"pl": "Zaktualizowana wersja pakietu eufy-security-client (2.9.1)\n",
|
|
43
69
|
"zh-cn": "包 eufy-security-client (2.9.1) 的更新版本\n"
|
|
44
|
-
},
|
|
45
|
-
"1.2.0": {
|
|
46
|
-
"en": "Requires node version >= 18\nAdded support for SmartTrack Link (T87B0) and SmartTrack Card (T87B2)\nAdded support for SoloCam S220 (T8134)\nUpdated version of the package go2rtc-static (1.8.1)\nUpdated version of the package eufy-security-client (2.9.0)\n",
|
|
47
|
-
"uk": "Requires node version >= 18\nAdded support for SmartTrack Link (T87B0) and SmartTrack Card (T87B2)\nAdded support for SoloCam S220 (T8134)\nUpdated version of the package go2rtc-static (1.8.1)\nUpdated version of the package eufy-security-client (2.9.0)\n",
|
|
48
|
-
"de": "Erfordert Node-Version >= 18\nUnterstützung für SmartTrack Link (T87B0) und SmartTrack Card (T87B2)\nUnterstützung für SoloCam S220 (T8134)\nAktualisierte Version des Pakets go2rtc-static (1.8.1)\nAktualisierte Version des Pakets eufy-security-client (2.9.0)\n",
|
|
49
|
-
"ru": "Требуется версия node >= 18\nДобавлена поддержка SmartTrack Link (T87B0) и SmartTrack Card (T87B2)\nДобавлена поддержка SoloCam S220 (T8134)\nОбновлена версия пакета go2rtc-static (1.8.1)\nОбновлена версия пакета eufy-security-client (2.9.0)\n",
|
|
50
|
-
"pt": "Requer node versão >= 18\nSuporte adicionado para SmartTrack Link (T87B0) e SmartTrack Card (T87B2)\nSuporte adicionado para SoloCam S220 (T8134)\nVersão atualizada do pacote go2rtc-static (1.8.1)\nVersão atualizada do pacote eufy-security-client (2.9.0)\n",
|
|
51
|
-
"nl": "Vereist node versie >= 18\nOndersteuning toegevoegd voor SmartTrack Link (T87B0) en SmartTrack Card (T87B2)\nOndersteuning toegevoegd voor SoloCam S220 (T8134)\nBijgewerkte versie van het pakket go2rtc-static (1.8.1)\nBijgewerkte versie van het pakket eufy-security-client (2.9.0)\n",
|
|
52
|
-
"fr": "Nécessite une version de node >= 18\nAjout de la prise en charge de SmartTrack Link (T87B0) et SmartTrack Card (T87B2)\nAjout de la prise en charge de SoloCam S220 (T8134)\nVersion mise à jour du paquet go2rtc-static (1.8.1)\nVersion mise à jour du paquet eufy-security-client (2.9.0)\n",
|
|
53
|
-
"it": "Richiede la versione di node >= 18\nAggiunto supporto per SmartTrack Link (T87B0) e SmartTrack Card (T87B2)\nAggiunto supporto per SoloCam S220 (T8134)\nVersione aggiornata del pacchetto go2rtc-static (1.8.1)\nVersione aggiornata del pacchetto eufy-security-client (2.9.0)\n",
|
|
54
|
-
"es": "Requiere node versión >= 18\nAgregado soporte para SmartTrack Link (T87B0) y SmartTrack Card (T87B2)\nAgregado soporte para SoloCam S220 (T8134)\nVersión actualizada del paquete go2rtc-static (1.8.1)\nVersión actualizada del paquete eufy-security-client (2.9.0)\n",
|
|
55
|
-
"pl": "Wymaga node w wersji >= 18\nDodano obsługę SmartTrack Link (T87B0) i SmartTrack Card (T87B2)\nDodano obsługę SoloCam S220 (T8134)\nZaktualizowano wersję pakietu go2rtc-static (1.8.1)\nZaktualizowano wersję pakietu eufy-security-client (2.9.0)\n",
|
|
56
|
-
"zh-cn": "要求 node 版本 >= 18\n添加了对智能跟踪链接(T87B0)和智能跟踪卡(T87B2)的支持\n添加了对 SoloCam S220 (T8134) 的支持\n软件包 go2rtc-static 的更新版本 (1.8.1)\n软件包 eufy-security-client 的更新版本 (2.9.0)\n"
|
|
57
70
|
}
|
|
58
71
|
},
|
|
59
72
|
"titleLang": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "iobroker.eusec",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.3",
|
|
4
4
|
"description": "ioBroker adapter that integrates Eufy-Security cameras with stations",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "bropat",
|
|
@@ -27,12 +27,12 @@
|
|
|
27
27
|
"@bropat/fluent-ffmpeg": "^2.1.3",
|
|
28
28
|
"@cospired/i18n-iso-languages": "^4.2.0",
|
|
29
29
|
"@iobroker/adapter-core": "^3.1.6",
|
|
30
|
-
"eufy-security-client": "^3.1.
|
|
30
|
+
"eufy-security-client": "^3.1.1",
|
|
31
31
|
"ffmpeg-for-homebridge": "^2.1.1",
|
|
32
32
|
"fs-extra": "^11.2.0",
|
|
33
33
|
"go2rtc-static": "^1.9.4",
|
|
34
34
|
"got": "^14.4.2",
|
|
35
|
-
"i18n-iso-countries": "^7.
|
|
35
|
+
"i18n-iso-countries": "^7.12.0",
|
|
36
36
|
"mime": "^4.0.4",
|
|
37
37
|
"ts-log": "^2.2.5"
|
|
38
38
|
},
|
|
@@ -42,18 +42,18 @@
|
|
|
42
42
|
"@alcalzone/release-script-plugin-iobroker": "^3.7.2",
|
|
43
43
|
"@alcalzone/release-script-plugin-license": "^3.7.0",
|
|
44
44
|
"@iobroker/testing": "^4.1.3",
|
|
45
|
-
"@types/chai": "^4.3.
|
|
46
|
-
"@types/chai-as-promised": "^
|
|
45
|
+
"@types/chai": "^4.3.19",
|
|
46
|
+
"@types/chai-as-promised": "^8.0.0",
|
|
47
47
|
"@types/express": "^4.17.21",
|
|
48
48
|
"@types/ffmpeg-static": "^3.0.3",
|
|
49
49
|
"@types/fs-extra": "^11.0.4",
|
|
50
50
|
"@types/mocha": "^10.0.7",
|
|
51
|
-
"@types/node": "^20.16.
|
|
51
|
+
"@types/node": "^20.16.10",
|
|
52
52
|
"@types/proxyquire": "^1.3.31",
|
|
53
53
|
"@types/sinon": "^17.0.3",
|
|
54
54
|
"@types/sinon-chai": "^3.2.12",
|
|
55
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
56
|
-
"@typescript-eslint/parser": "^
|
|
55
|
+
"@typescript-eslint/eslint-plugin": "^7.5.0",
|
|
56
|
+
"@typescript-eslint/parser": "^7.5.0",
|
|
57
57
|
"@tsconfig/node20": "^20.1.4",
|
|
58
58
|
"chai": "^5.1.1",
|
|
59
59
|
"chai-as-promised": "^8.0.0",
|