diff --git a/README.md b/README.md index 5f4dd6d..88e6a8c 100644 --- a/README.md +++ b/README.md @@ -140,6 +140,10 @@ Best is to set the adapter to Debug log mode (Instances -> Expert mode -> Column ## Changelog +### 0.2.4 (2021-02-20) +* (bropat) Fixed issue [#86](https://github.com/bropat/ioBroker.eufy-security/issues/86) +* (bropat) Fixed not correctly identifying if the livestream is still active or not + ### 0.2.3 (2021-02-17) * (bropat) Fixed wired doorbell p2p livestream (should fix also indoor, floodlight and solo cameras) * (bropat) Fixed issue that treats known push notifications as unknown diff --git a/build/lib/eufy-security/eufy-security.js b/build/lib/eufy-security/eufy-security.js index 9a8ce57..cc80e74 100644 --- a/build/lib/eufy-security/eufy-security.js +++ b/build/lib/eufy-security/eufy-security.js @@ -445,11 +445,15 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter { catch (error) { this.log.error(`EufySecurity.onStartDownload(): station: ${station.getSerial()} device: ${device.getSerial()} - Error: ${error}`); } + }) + .catch((error) => { + this.log.error(`EufySecurity.onStartDownload(): ffmpegPreviewImage - station: ${station.getSerial()} device: ${device.getSerial()} - Error: ${error}`); }); + }) + .catch((error) => { + this.log.error(`EufySecurity.onStartDownload(): station: ${station.getSerial()} channel: ${channel} - Error: ${error} - Cancelling download...`); + station.cancelDownload(device); }); - /*.catch(() => { - - });*/ } catch (error) { this.log.error(`EufySecurity.onStartDownload(): station: ${station.getSerial()} channel: ${channel} - Error: ${error} - Cancelling download...`); @@ -498,7 +502,14 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter { catch (error) { this.log.error(`EufySecurity.onStartLivestream(): station: ${station.getSerial()} device: ${device.getSerial()} - Error: ${error}`); } + }) + .catch((error) => { + this.log.error(`EufySecurity.onStartLivestream(): ffmpegPreviewImage - station: ${station.getSerial()} device: ${device.getSerial()} - Error: ${error}`); }); + }) + .catch((error) => { + this.log.error(`EufySecurity.onStartLivestream(): station: ${station.getSerial()} channel: ${channel} - Error: ${error} - Stopping livestream...`); + station.stopLivestream(device); }); this.emit("start_livestream", station, device, `/${this.adapter.namespace}/${station.getSerial()}/${types_2.DataLocation.LIVESTREAM}/${device.getSerial()}${types_2.STREAM_FILE_NAME_EXT}`); } @@ -514,28 +525,31 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter { } startLivestream(device_sn) { return __awaiter(this, void 0, void 0, function* () { - if (!this.camera_livestream_timeout.get(device_sn)) { - if (Object.keys(this.devices).includes(device_sn) && this.devices[device_sn].isCamera()) { - const camera = this.devices[device_sn]; - const station = this.stations[camera.getStationSerial()]; - if (station.isConnected()) { - if (!station.isLiveStreaming(camera)) { - station.startLivestream(camera); - this.camera_livestream_timeout.set(device_sn, setTimeout(() => { - this.stopLivestream(device_sn); - }, this.camera_max_livestream_seconds * 1000)); - } + if (Object.keys(this.devices).includes(device_sn) && this.devices[device_sn].isCamera()) { + const camera = this.devices[device_sn]; + const station = this.stations[camera.getStationSerial()]; + if (station.isConnected()) { + if (!station.isLiveStreaming(camera)) { + station.startLivestream(camera); + this.camera_livestream_timeout.set(device_sn, setTimeout(() => { + this.stopLivestream(device_sn); + }, this.camera_max_livestream_seconds * 1000)); } - else if (!camera.isStreaming()) { - this._startRtmpLivestream(station, camera); + else { + this.log.warn(`The stream for the device ${device_sn} cannot be started, because it is already streaming!`); } } else { - throw new Error(`No camera device with this serial number: ${device_sn}!`); + if (!camera.isStreaming()) { + this._startRtmpLivestream(station, camera); + } + else { + this.log.warn(`The stream for the device ${device_sn} cannot be started, because it is already streaming!`); + } } } else { - this.log.warn(`The stream for the device ${device_sn} cannot be started, because it is already streaming!`); + throw new Error(`No camera device with this serial number: ${device_sn}!`); } }); } @@ -559,9 +573,16 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter { this.adapter.setStateAsync(camera.getStateID(types_1.CameraStateID.LAST_LIVESTREAM_PIC_HTML), { val: utils_1.getImageAsHTML(fs_extra_1.default.readFileSync(`${filename_without_ext}${types_2.IMAGE_FILE_JPEG_EXT}`)), ack: true }); } catch (error) { - this.log.error(`EufySecurity.startLivestream(): station: ${station.getSerial()} device: ${camera.getSerial()} - Error: ${error}`); + this.log.error(`EufySecurity._startRtmpLivestream(): station: ${station.getSerial()} device: ${camera.getSerial()} - Error: ${error}`); } + }) + .catch((error) => { + this.log.error(`EufySecurity._startRtmpLivestream(): ffmpegPreviewImage - station: ${station.getSerial()} device: ${camera.getSerial()} - Error: ${error}`); }); + }) + .catch((error) => { + this.log.error(`EufySecurity._startRtmpLivestream(): station: ${station.getSerial()} device: ${camera.getSerial()} - Error: ${error} - Stopping livestream...`); + camera.stopStream(); }); this.emit("start_livestream", station, camera, `/${this.adapter.namespace}/${station.getSerial()}/${types_2.DataLocation.LIVESTREAM}/${camera.getSerial()}${types_2.STREAM_FILE_NAME_EXT}`); this.camera_livestream_timeout.set(camera.getSerial(), setTimeout(() => { @@ -571,29 +592,26 @@ class EufySecurity extends tiny_typed_emitter_1.TypedEmitter { } stopLivestream(device_sn) { return __awaiter(this, void 0, void 0, function* () { - if (this.camera_livestream_timeout.get(device_sn)) { - if (Object.keys(this.devices).includes(device_sn) && this.devices[device_sn].isCamera()) { - const camera = this.devices[device_sn]; - const station = this.stations[camera.getStationSerial()]; - if (station.isConnected() && station.isLiveStreaming(camera)) { - yield station.stopLivestream(camera); - } - else if (camera.isStreaming()) { - yield camera.stopStream(); - this.emit("stop_livestream", station, camera); - } - const timeout = this.camera_livestream_timeout.get(device_sn); - if (timeout) { - clearTimeout(timeout); - this.camera_livestream_timeout.delete(device_sn); - } + if (Object.keys(this.devices).includes(device_sn) && this.devices[device_sn].isCamera()) { + const camera = this.devices[device_sn]; + const station = this.stations[camera.getStationSerial()]; + if (station.isConnected() && station.isLiveStreaming(camera)) { + yield station.stopLivestream(camera); + } + else if (camera.isStreaming()) { + yield camera.stopStream(); } else { - throw new Error(`No camera device with this serial number: ${device_sn}!`); + this.log.warn(`The stream for the device ${device_sn} cannot be stopped, because it isn't streaming!`); + } + const timeout = this.camera_livestream_timeout.get(device_sn); + if (timeout) { + clearTimeout(timeout); + this.camera_livestream_timeout.delete(device_sn); } } else { - this.log.warn(`The stream for the device ${device_sn} cannot be stopped, because it isn't streaming!`); + this.log.warn(`Stream couldn't be stopped as no camera device with serial number ${device_sn} was found!`); } }); } diff --git a/build/main.js b/build/main.js index 3be72d0..67178ae 100644 --- a/build/main.js +++ b/build/main.js @@ -1383,49 +1383,32 @@ class EufySecurity extends utils.Adapter { if (device) { switch (push_msg.event_type) { case eufy_security_client_1.DoorbellPushEvent.MOTION_DETECTION: + yield this.setStateAsync(device.getStateID(types_1.DoorbellStateID.MOTION_DETECTED), { val: true, ack: true }); + if (this.motionDetected[device.getSerial()]) + clearTimeout(this.motionDetected[device.getSerial()]); + this.motionDetected[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { + yield this.setStateAsync(device.getStateID(types_1.DoorbellStateID.MOTION_DETECTED), { val: false, ack: true }); + }), this.config.eventDuration * 1000); if (!utils_1.isEmpty(push_msg.pic_url)) { - yield this.setStateAsync(device.getStateID(types_1.DoorbellStateID.MOTION_DETECTED), { val: true, ack: true }); yield utils_1.saveImageStates(this, push_msg.pic_url, push_msg.event_time, device.getStationSerial(), device.getSerial(), types_1.DataLocation.LAST_EVENT, device.getStateID(types_1.DoorbellStateID.LAST_EVENT_PICTURE_URL), device.getStateID(types_1.DoorbellStateID.LAST_EVENT_PICTURE_HTML), "Last captured picture").catch(() => { this.log.error(`handlePushNotifications(): DoorbellPushEvent.MOTION_DETECTION of device ${device.getSerial()} - saveImageStates(): url ${push_msg.pic_url}`); }); - if (this.motionDetected[device.getSerial()]) - clearTimeout(this.motionDetected[device.getSerial()]); - this.motionDetected[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { - yield this.setStateAsync(device.getStateID(types_1.DoorbellStateID.MOTION_DETECTED), { val: false, ack: true }); - }), this.config.eventDuration * 1000); - } - else { - yield this.setStateAsync(device.getStateID(types_1.DoorbellStateID.MOTION_DETECTED), { val: true, ack: true }); - if (this.motionDetected[device.getSerial()]) - clearTimeout(this.motionDetected[device.getSerial()]); - this.motionDetected[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { - yield this.setStateAsync(device.getStateID(types_1.DoorbellStateID.MOTION_DETECTED), { val: false, ack: true }); - }), this.config.eventDuration * 1000); } if (push_msg.push_count === 1) this._startDownload(push_msg.station_sn, push_msg.file_path, push_msg.cipher); break; case eufy_security_client_1.DoorbellPushEvent.FACE_DETECTION: + yield this.setStateAsync(device.getStateID(types_1.DoorbellStateID.PERSON_DETECTED), { val: true, ack: true }); + yield this.setStateAsync(device.getStateID(types_1.DoorbellStateID.LAST_PERSON_IDENTIFIED), { val: "Unknown", ack: true }); + if (this.personDetected[device.getSerial()]) + clearTimeout(this.personDetected[device.getSerial()]); + this.personDetected[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { + yield this.setStateAsync(device.getStateID(types_1.DoorbellStateID.PERSON_DETECTED), { val: false, ack: true }); + }), this.config.eventDuration * 1000); if (!utils_1.isEmpty(push_msg.pic_url)) { - yield this.setStateAsync(device.getStateID(types_1.DoorbellStateID.PERSON_DETECTED), { val: true, ack: true }); yield utils_1.saveImageStates(this, push_msg.pic_url, push_msg.event_time, device.getStationSerial(), device.getSerial(), types_1.DataLocation.LAST_EVENT, device.getStateID(types_1.DoorbellStateID.LAST_EVENT_PICTURE_URL), device.getStateID(types_1.DoorbellStateID.LAST_EVENT_PICTURE_HTML), "Last captured picture").catch(() => { this.log.error(`handlePushNotifications(): DoorbellPushEvent.FACE_DETECTION of device ${device.getSerial()} - saveImageStates(): url ${push_msg.pic_url}`); }); - yield this.setStateAsync(device.getStateID(types_1.DoorbellStateID.LAST_PERSON_IDENTIFIED), { val: "Unknown", ack: true }); - if (this.personDetected[device.getSerial()]) - clearTimeout(this.personDetected[device.getSerial()]); - this.personDetected[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { - yield this.setStateAsync(device.getStateID(types_1.DoorbellStateID.PERSON_DETECTED), { val: false, ack: true }); - }), this.config.eventDuration * 1000); - } - else { - yield this.setStateAsync(device.getStateID(types_1.DoorbellStateID.PERSON_DETECTED), { val: true, ack: true }); - yield this.setStateAsync(device.getStateID(types_1.DoorbellStateID.LAST_PERSON_IDENTIFIED), { val: "Unknown", ack: true }); - if (this.personDetected[device.getSerial()]) - clearTimeout(this.personDetected[device.getSerial()]); - this.personDetected[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { - yield this.setStateAsync(device.getStateID(types_1.DoorbellStateID.PERSON_DETECTED), { val: false, ack: true }); - }), this.config.eventDuration * 1000); } if (push_msg.push_count === 1) this._startDownload(push_msg.station_sn, push_msg.file_path, push_msg.cipher); @@ -1437,6 +1420,11 @@ class EufySecurity extends utils.Adapter { this.ringing[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { yield this.setStateAsync(device.getStateID(types_1.DoorbellStateID.RINGING), { val: false, ack: true }); }), this.config.eventDuration * 1000); + if (!utils_1.isEmpty(push_msg.pic_url)) { + yield utils_1.saveImageStates(this, push_msg.pic_url, push_msg.event_time, device.getStationSerial(), device.getSerial(), types_1.DataLocation.LAST_EVENT, device.getStateID(types_1.DoorbellStateID.LAST_EVENT_PICTURE_URL), device.getStateID(types_1.DoorbellStateID.LAST_EVENT_PICTURE_HTML), "Last captured picture").catch(() => { + this.log.error(`handlePushNotifications(): DoorbellPushEvent.PRESS_DOORBELL of device ${device.getSerial()} - saveImageStates(): url ${push_msg.pic_url}`); + }); + } break; default: this.log.debug(`handlePushNotifications(): Unhandled doorbell push event: ${JSON.stringify(push_msg)}`); @@ -1452,118 +1440,77 @@ class EufySecurity extends utils.Adapter { if (device) { switch (push_msg.event_type) { case eufy_security_client_1.IndoorPushEvent.MOTION_DETECTION: + yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.MOTION_DETECTED), { val: true, ack: true }); + if (this.motionDetected[device.getSerial()]) + clearTimeout(this.motionDetected[device.getSerial()]); + this.motionDetected[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { + yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.MOTION_DETECTED), { val: false, ack: true }); + }), this.config.eventDuration * 1000); if (!utils_1.isEmpty(push_msg.pic_url)) { - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.MOTION_DETECTED), { val: true, ack: true }); yield utils_1.saveImageStates(this, push_msg.pic_url, push_msg.event_time, device.getStationSerial(), device.getSerial(), types_1.DataLocation.LAST_EVENT, device.getStateID(types_1.IndoorCameraStateID.LAST_EVENT_PICTURE_URL), device.getStateID(types_1.IndoorCameraStateID.LAST_EVENT_PICTURE_HTML), "Last captured picture").catch(() => { this.log.error(`handlePushNotifications(): IndoorPushEvent.MOTION_DETECTION of device ${device.getSerial()} - saveImageStates(): url ${push_msg.pic_url}`); }); - if (this.motionDetected[device.getSerial()]) - clearTimeout(this.motionDetected[device.getSerial()]); - this.motionDetected[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.MOTION_DETECTED), { val: false, ack: true }); - }), this.config.eventDuration * 1000); - } - else { - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.MOTION_DETECTED), { val: true, ack: true }); - if (this.motionDetected[device.getSerial()]) - clearTimeout(this.motionDetected[device.getSerial()]); - this.motionDetected[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.MOTION_DETECTED), { val: false, ack: true }); - }), this.config.eventDuration * 1000); } if (push_msg.push_count === 1) this._startDownload(push_msg.station_sn, push_msg.file_path, push_msg.cipher); break; case eufy_security_client_1.IndoorPushEvent.FACE_DETECTION: + yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.PERSON_DETECTED), { val: true, ack: true }); + yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.LAST_PERSON_IDENTIFIED), { val: "Unknown", ack: true }); + if (this.personDetected[device.getSerial()]) + clearTimeout(this.personDetected[device.getSerial()]); + this.personDetected[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { + yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.PERSON_DETECTED), { val: false, ack: true }); + }), this.config.eventDuration * 1000); if (!utils_1.isEmpty(push_msg.pic_url)) { - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.PERSON_DETECTED), { val: true, ack: true }); yield utils_1.saveImageStates(this, push_msg.pic_url, push_msg.event_time, device.getStationSerial(), device.getSerial(), types_1.DataLocation.LAST_EVENT, device.getStateID(types_1.IndoorCameraStateID.LAST_EVENT_PICTURE_URL), device.getStateID(types_1.IndoorCameraStateID.LAST_EVENT_PICTURE_HTML), "Last captured picture").catch(() => { this.log.error(`handlePushNotifications(): IndoorPushEvent.FACE_DETECTION of device ${device.getSerial()} - saveImageStates(): url ${push_msg.pic_url}`); }); - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.LAST_PERSON_IDENTIFIED), { val: "Unknown", ack: true }); - if (this.personDetected[device.getSerial()]) - clearTimeout(this.personDetected[device.getSerial()]); - this.personDetected[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.PERSON_DETECTED), { val: false, ack: true }); - }), this.config.eventDuration * 1000); - } - else { - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.PERSON_DETECTED), { val: true, ack: true }); - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.LAST_PERSON_IDENTIFIED), { val: "Unknown", ack: true }); - if (this.personDetected[device.getSerial()]) - clearTimeout(this.personDetected[device.getSerial()]); - this.personDetected[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.PERSON_DETECTED), { val: false, ack: true }); - }), this.config.eventDuration * 1000); } if (push_msg.push_count === 1) this._startDownload(push_msg.station_sn, push_msg.file_path, push_msg.cipher); break; case eufy_security_client_1.IndoorPushEvent.CRYIG_DETECTION: + yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.CRYING_DETECTED), { val: true, ack: true }); + if (this.cryingDetected[device.getSerial()]) + clearTimeout(this.cryingDetected[device.getSerial()]); + this.cryingDetected[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { + yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.CRYING_DETECTED), { val: false, ack: true }); + }), this.config.eventDuration * 1000); if (!utils_1.isEmpty(push_msg.pic_url)) { - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.CRYING_DETECTED), { val: true, ack: true }); yield utils_1.saveImageStates(this, push_msg.pic_url, push_msg.event_time, device.getStationSerial(), device.getSerial(), types_1.DataLocation.LAST_EVENT, device.getStateID(types_1.IndoorCameraStateID.LAST_EVENT_PICTURE_URL), device.getStateID(types_1.IndoorCameraStateID.LAST_EVENT_PICTURE_HTML), "Last captured picture").catch(() => { this.log.error(`handlePushNotifications(): IndoorPushEvent.CRYIG_DETECTION of device ${device.getSerial()} - saveImageStates(): url ${push_msg.pic_url}`); }); - if (this.cryingDetected[device.getSerial()]) - clearTimeout(this.cryingDetected[device.getSerial()]); - this.cryingDetected[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.CRYING_DETECTED), { val: false, ack: true }); - }), this.config.eventDuration * 1000); - } - else { - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.CRYING_DETECTED), { val: true, ack: true }); - if (this.cryingDetected[device.getSerial()]) - clearTimeout(this.cryingDetected[device.getSerial()]); - this.cryingDetected[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.CRYING_DETECTED), { val: false, ack: true }); - }), this.config.eventDuration * 1000); } if (push_msg.push_count === 1) this._startDownload(push_msg.station_sn, push_msg.file_path, push_msg.cipher); break; case eufy_security_client_1.IndoorPushEvent.SOUND_DETECTION: + yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.SOUND_DETECTED), { val: true, ack: true }); + if (this.soundDetected[device.getSerial()]) + clearTimeout(this.soundDetected[device.getSerial()]); + this.soundDetected[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { + yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.SOUND_DETECTED), { val: false, ack: true }); + }), this.config.eventDuration * 1000); if (!utils_1.isEmpty(push_msg.pic_url)) { - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.SOUND_DETECTED), { val: true, ack: true }); yield utils_1.saveImageStates(this, push_msg.pic_url, push_msg.event_time, device.getStationSerial(), device.getSerial(), types_1.DataLocation.LAST_EVENT, device.getStateID(types_1.IndoorCameraStateID.LAST_EVENT_PICTURE_URL), device.getStateID(types_1.IndoorCameraStateID.LAST_EVENT_PICTURE_HTML), "Last captured picture").catch(() => { this.log.error(`handlePushNotifications(): IndoorPushEvent.SOUND_DETECTION of device ${device.getSerial()} - saveImageStates(): url ${push_msg.pic_url}`); }); - if (this.soundDetected[device.getSerial()]) - clearTimeout(this.soundDetected[device.getSerial()]); - this.soundDetected[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.SOUND_DETECTED), { val: false, ack: true }); - }), this.config.eventDuration * 1000); - } - else { - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.SOUND_DETECTED), { val: true, ack: true }); - if (this.soundDetected[device.getSerial()]) - clearTimeout(this.soundDetected[device.getSerial()]); - this.soundDetected[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.SOUND_DETECTED), { val: false, ack: true }); - }), this.config.eventDuration * 1000); } if (push_msg.push_count === 1) this._startDownload(push_msg.station_sn, push_msg.file_path, push_msg.cipher); break; case eufy_security_client_1.IndoorPushEvent.PET_DETECTION: + yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.PET_DETECTED), { val: true, ack: true }); + if (this.petDetected[device.getSerial()]) + clearTimeout(this.petDetected[device.getSerial()]); + this.petDetected[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { + yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.PET_DETECTED), { val: false, ack: true }); + }), this.config.eventDuration * 1000); if (!utils_1.isEmpty(push_msg.pic_url)) { - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.PET_DETECTED), { val: true, ack: true }); yield utils_1.saveImageStates(this, push_msg.pic_url, push_msg.event_time, device.getStationSerial(), device.getSerial(), types_1.DataLocation.LAST_EVENT, device.getStateID(types_1.IndoorCameraStateID.LAST_EVENT_PICTURE_URL), device.getStateID(types_1.IndoorCameraStateID.LAST_EVENT_PICTURE_HTML), "Last captured picture").catch(() => { this.log.error(`handlePushNotifications(): IndoorPushEvent.PET_DETECTION of device ${device.getSerial()} - saveImageStates(): url ${push_msg.pic_url}`); }); - if (this.petDetected[device.getSerial()]) - clearTimeout(this.petDetected[device.getSerial()]); - this.petDetected[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.PET_DETECTED), { val: false, ack: true }); - }), this.config.eventDuration * 1000); - } - else { - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.PET_DETECTED), { val: true, ack: true }); - if (this.petDetected[device.getSerial()]) - clearTimeout(this.petDetected[device.getSerial()]); - this.petDetected[device.getSerial()] = setTimeout(() => __awaiter(this, void 0, void 0, function* () { - yield this.setStateAsync(device.getStateID(types_1.IndoorCameraStateID.PET_DETECTED), { val: false, ack: true }); - }), this.config.eventDuration * 1000); } if (push_msg.push_count === 1) this._startDownload(push_msg.station_sn, push_msg.file_path, push_msg.cipher); diff --git a/io-package.json b/io-package.json index 2c7cd6d..4089b76 100644 --- a/io-package.json +++ b/io-package.json @@ -1,8 +1,20 @@ { "common": { "name": "eufy-security", - "version": "0.2.3", + "version": "0.2.4", "news": { + "0.2.4": { + "en": "Fixed issue #86", + "de": "Problem Nr. 86 behoben", + "ru": "Исправленная проблема # 86", + "pt": "Problema nº 86 corrigido", + "nl": "Probleem # 86 opgelost", + "fr": "Problème résolu n ° 86", + "it": "Risolto il problema # 86", + "es": "Problema solucionado # 86", + "pl": "Naprawiono problem nr 86", + "zh-cn": "已修复问题86" + }, "0.2.3": { "en": "Fixed wired doorbell p2p livestream and push notifications", "de": "Feste kabelgebundene Türklingel p2p Livestream- und Push-Benachrichtigungen behoben", diff --git a/package-lock.json b/package-lock.json index d8a6f88..f85a709 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "iobroker.eufy-security", - "version": "0.2.3", + "version": "0.2.4", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index cab9c5b..f467860 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iobroker.eufy-security", - "version": "0.2.3", + "version": "0.2.4", "description": "ioBroker adapter that integrates Eufy-Security cameras with stations", "author": { "name": "bropat", diff --git a/src/lib/eufy-security/eufy-security.ts b/src/lib/eufy-security/eufy-security.ts index 218461e..37e2063 100644 --- a/src/lib/eufy-security/eufy-security.ts +++ b/src/lib/eufy-security/eufy-security.ts @@ -438,11 +438,15 @@ export class EufySecurity extends TypedEmitter { } catch (error) { this.log.error(`EufySecurity.onStartDownload(): station: ${station.getSerial()} device: ${device.getSerial()} - Error: ${error}`); } + }) + .catch((error) => { + this.log.error(`EufySecurity.onStartDownload(): ffmpegPreviewImage - station: ${station.getSerial()} device: ${device.getSerial()} - Error: ${error}`); }); + }) + .catch((error) => { + this.log.error(`EufySecurity.onStartDownload(): station: ${station.getSerial()} channel: ${channel} - Error: ${error} - Cancelling download...`); + station.cancelDownload(device); }); - /*.catch(() => { - - });*/ } catch(error) { this.log.error(`EufySecurity.onStartDownload(): station: ${station.getSerial()} channel: ${channel} - Error: ${error} - Cancelling download...`); station.cancelDownload(device); @@ -487,7 +491,14 @@ export class EufySecurity extends TypedEmitter { } catch (error) { this.log.error(`EufySecurity.onStartLivestream(): station: ${station.getSerial()} device: ${device.getSerial()} - Error: ${error}`); } + }) + .catch((error) => { + this.log.error(`EufySecurity.onStartLivestream(): ffmpegPreviewImage - station: ${station.getSerial()} device: ${device.getSerial()} - Error: ${error}`); }); + }) + .catch((error) => { + this.log.error(`EufySecurity.onStartLivestream(): station: ${station.getSerial()} channel: ${channel} - Error: ${error} - Stopping livestream...`); + station.stopLivestream(device); }); this.emit("start_livestream", station, device, `/${this.adapter.namespace}/${station.getSerial()}/${DataLocation.LIVESTREAM}/${device.getSerial()}${STREAM_FILE_NAME_EXT}`); } catch(error) { @@ -500,27 +511,29 @@ export class EufySecurity extends TypedEmitter { } public async startLivestream(device_sn: string): Promise { - if (!this.camera_livestream_timeout.get(device_sn)) { - if (Object.keys(this.devices).includes(device_sn) && this.devices[device_sn].isCamera()) { - const camera = this.devices[device_sn] as Camera; - const station = this.stations[camera.getStationSerial()]; - - if (station.isConnected()) { - if (!station.isLiveStreaming(camera)) { - station.startLivestream(camera); - - this.camera_livestream_timeout.set(device_sn, setTimeout(() => { - this.stopLivestream(device_sn); - }, this.camera_max_livestream_seconds * 1000)); - } - } else if (!camera.isStreaming()) { - this._startRtmpLivestream(station, camera); + if (Object.keys(this.devices).includes(device_sn) && this.devices[device_sn].isCamera()) { + const camera = this.devices[device_sn] as Camera; + const station = this.stations[camera.getStationSerial()]; + + if (station.isConnected()) { + if (!station.isLiveStreaming(camera)) { + station.startLivestream(camera); + + this.camera_livestream_timeout.set(device_sn, setTimeout(() => { + this.stopLivestream(device_sn); + }, this.camera_max_livestream_seconds * 1000)); + } else { + this.log.warn(`The stream for the device ${device_sn} cannot be started, because it is already streaming!`); } } else { - throw new Error(`No camera device with this serial number: ${device_sn}!`); + if (!camera.isStreaming()) { + this._startRtmpLivestream(station, camera); + } else { + this.log.warn(`The stream for the device ${device_sn} cannot be started, because it is already streaming!`); + } } } else { - this.log.warn(`The stream for the device ${device_sn} cannot be started, because it is already streaming!`); + throw new Error(`No camera device with this serial number: ${device_sn}!`); } } @@ -542,9 +555,16 @@ export class EufySecurity extends TypedEmitter { try { this.adapter.setStateAsync(camera.getStateID(CameraStateID.LAST_LIVESTREAM_PIC_HTML), { val: getImageAsHTML(fse.readFileSync(`${filename_without_ext}${IMAGE_FILE_JPEG_EXT}`)), ack: true }); } catch (error) { - this.log.error(`EufySecurity.startLivestream(): station: ${station.getSerial()} device: ${camera.getSerial()} - Error: ${error}`); + this.log.error(`EufySecurity._startRtmpLivestream(): station: ${station.getSerial()} device: ${camera.getSerial()} - Error: ${error}`); } + }) + .catch((error) => { + this.log.error(`EufySecurity._startRtmpLivestream(): ffmpegPreviewImage - station: ${station.getSerial()} device: ${camera.getSerial()} - Error: ${error}`); }); + }) + .catch((error) => { + this.log.error(`EufySecurity._startRtmpLivestream(): station: ${station.getSerial()} device: ${camera.getSerial()} - Error: ${error} - Stopping livestream...`); + camera.stopStream(); }); this.emit("start_livestream", station, camera, `/${this.adapter.namespace}/${station.getSerial()}/${DataLocation.LIVESTREAM}/${camera.getSerial()}${STREAM_FILE_NAME_EXT}`); this.camera_livestream_timeout.set(camera.getSerial(), setTimeout(() => { @@ -553,28 +573,25 @@ export class EufySecurity extends TypedEmitter { } public async stopLivestream(device_sn: string): Promise { - if (this.camera_livestream_timeout.get(device_sn)) { - if (Object.keys(this.devices).includes(device_sn) && this.devices[device_sn].isCamera()) { - const camera = this.devices[device_sn] as Camera; - const station = this.stations[camera.getStationSerial()]; - - if (station.isConnected() && station.isLiveStreaming(camera)) { - await station.stopLivestream(camera); - } else if (camera.isStreaming()) { - await camera.stopStream(); - this.emit("stop_livestream", station, camera); - } - - const timeout = this.camera_livestream_timeout.get(device_sn); - if (timeout) { - clearTimeout(timeout); - this.camera_livestream_timeout.delete(device_sn); - } + if (Object.keys(this.devices).includes(device_sn) && this.devices[device_sn].isCamera()) { + const camera = this.devices[device_sn] as Camera; + const station = this.stations[camera.getStationSerial()]; + + if (station.isConnected() && station.isLiveStreaming(camera)) { + await station.stopLivestream(camera); + } else if (camera.isStreaming()) { + await camera.stopStream(); } else { - throw new Error(`No camera device with this serial number: ${device_sn}!`); + this.log.warn(`The stream for the device ${device_sn} cannot be stopped, because it isn't streaming!`); + } + + const timeout = this.camera_livestream_timeout.get(device_sn); + if (timeout) { + clearTimeout(timeout); + this.camera_livestream_timeout.delete(device_sn); } } else { - this.log.warn(`The stream for the device ${device_sn} cannot be stopped, because it isn't streaming!`); + this.log.warn(`Stream couldn't be stopped as no camera device with serial number ${device_sn} was found!`); } } diff --git a/src/main.ts b/src/main.ts index af852e7..d9304c8 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1449,49 +1449,32 @@ export class EufySecurity extends utils.Adapter { if (device) { switch (push_msg.event_type) { case DoorbellPushEvent.MOTION_DETECTION: + await this.setStateAsync(device.getStateID(DoorbellStateID.MOTION_DETECTED), { val: true, ack: true }); + if (this.motionDetected[device.getSerial()]) + clearTimeout(this.motionDetected[device.getSerial()]); + this.motionDetected[device.getSerial()] = setTimeout(async () => { + await this.setStateAsync(device.getStateID(DoorbellStateID.MOTION_DETECTED), { val: false, ack: true }); + }, this.config.eventDuration * 1000); if (!isEmpty(push_msg.pic_url)) { - await this.setStateAsync(device.getStateID(DoorbellStateID.MOTION_DETECTED), { val: true, ack: true }); await saveImageStates(this, push_msg.pic_url!, push_msg.event_time, device.getStationSerial(), device.getSerial(), DataLocation.LAST_EVENT, device.getStateID(DoorbellStateID.LAST_EVENT_PICTURE_URL), device.getStateID(DoorbellStateID.LAST_EVENT_PICTURE_HTML), "Last captured picture").catch(() => { this.log.error(`handlePushNotifications(): DoorbellPushEvent.MOTION_DETECTION of device ${device.getSerial()} - saveImageStates(): url ${push_msg.pic_url}`); }); - - if (this.motionDetected[device.getSerial()]) - clearTimeout(this.motionDetected[device.getSerial()]); - this.motionDetected[device.getSerial()] = setTimeout(async () => { - await this.setStateAsync(device.getStateID(DoorbellStateID.MOTION_DETECTED), { val: false, ack: true }); - }, this.config.eventDuration * 1000); - } else { - await this.setStateAsync(device.getStateID(DoorbellStateID.MOTION_DETECTED), { val: true, ack: true }); - if (this.motionDetected[device.getSerial()]) - clearTimeout(this.motionDetected[device.getSerial()]); - this.motionDetected[device.getSerial()] = setTimeout(async () => { - await this.setStateAsync(device.getStateID(DoorbellStateID.MOTION_DETECTED), { val: false, ack: true }); - }, this.config.eventDuration * 1000); } if (push_msg.push_count === 1) this._startDownload(push_msg.station_sn, push_msg.file_path, push_msg.cipher); break; case DoorbellPushEvent.FACE_DETECTION: + await this.setStateAsync(device.getStateID(DoorbellStateID.PERSON_DETECTED), { val: true, ack: true }); + await this.setStateAsync(device.getStateID(DoorbellStateID.LAST_PERSON_IDENTIFIED), { val: "Unknown", ack: true }); + if (this.personDetected[device.getSerial()]) + clearTimeout(this.personDetected[device.getSerial()]); + this.personDetected[device.getSerial()] = setTimeout(async () => { + await this.setStateAsync(device.getStateID(DoorbellStateID.PERSON_DETECTED), { val: false, ack: true }); + }, this.config.eventDuration * 1000); if (!isEmpty(push_msg.pic_url)) { - await this.setStateAsync(device.getStateID(DoorbellStateID.PERSON_DETECTED), { val: true, ack: true }); await saveImageStates(this, push_msg.pic_url!, push_msg.event_time, device.getStationSerial(), device.getSerial(), DataLocation.LAST_EVENT, device.getStateID(DoorbellStateID.LAST_EVENT_PICTURE_URL), device.getStateID(DoorbellStateID.LAST_EVENT_PICTURE_HTML), "Last captured picture").catch(() => { this.log.error(`handlePushNotifications(): DoorbellPushEvent.FACE_DETECTION of device ${device.getSerial()} - saveImageStates(): url ${push_msg.pic_url}`); }); - - await this.setStateAsync(device.getStateID(DoorbellStateID.LAST_PERSON_IDENTIFIED), { val: "Unknown", ack: true }); - if (this.personDetected[device.getSerial()]) - clearTimeout(this.personDetected[device.getSerial()]); - this.personDetected[device.getSerial()] = setTimeout(async () => { - await this.setStateAsync(device.getStateID(DoorbellStateID.PERSON_DETECTED), { val: false, ack: true }); - }, this.config.eventDuration * 1000); - } else { - await this.setStateAsync(device.getStateID(DoorbellStateID.PERSON_DETECTED), { val: true, ack: true }); - await this.setStateAsync(device.getStateID(DoorbellStateID.LAST_PERSON_IDENTIFIED), { val: "Unknown", ack: true }); - if (this.personDetected[device.getSerial()]) - clearTimeout(this.personDetected[device.getSerial()]); - this.personDetected[device.getSerial()] = setTimeout(async () => { - await this.setStateAsync(device.getStateID(DoorbellStateID.PERSON_DETECTED), { val: false, ack: true }); - }, this.config.eventDuration * 1000); } if (push_msg.push_count === 1) this._startDownload(push_msg.station_sn, push_msg.file_path, push_msg.cipher); @@ -1503,6 +1486,11 @@ export class EufySecurity extends utils.Adapter { this.ringing[device.getSerial()] = setTimeout(async () => { await this.setStateAsync(device.getStateID(DoorbellStateID.RINGING), { val: false, ack: true }); }, this.config.eventDuration * 1000); + if (!isEmpty(push_msg.pic_url)) { + await saveImageStates(this, push_msg.pic_url!, push_msg.event_time, device.getStationSerial(), device.getSerial(), DataLocation.LAST_EVENT, device.getStateID(DoorbellStateID.LAST_EVENT_PICTURE_URL), device.getStateID(DoorbellStateID.LAST_EVENT_PICTURE_HTML), "Last captured picture").catch(() => { + this.log.error(`handlePushNotifications(): DoorbellPushEvent.PRESS_DOORBELL of device ${device.getSerial()} - saveImageStates(): url ${push_msg.pic_url}`); + }); + } break; default: this.log.debug(`handlePushNotifications(): Unhandled doorbell push event: ${JSON.stringify(push_msg)}`); @@ -1517,113 +1505,77 @@ export class EufySecurity extends utils.Adapter { if (device) { switch (push_msg.event_type) { case IndoorPushEvent.MOTION_DETECTION: + await this.setStateAsync(device.getStateID(IndoorCameraStateID.MOTION_DETECTED), { val: true, ack: true }); + if (this.motionDetected[device.getSerial()]) + clearTimeout(this.motionDetected[device.getSerial()]); + this.motionDetected[device.getSerial()] = setTimeout(async () => { + await this.setStateAsync(device.getStateID(IndoorCameraStateID.MOTION_DETECTED), { val: false, ack: true }); + }, this.config.eventDuration * 1000); if (!isEmpty(push_msg.pic_url)) { - await this.setStateAsync(device.getStateID(IndoorCameraStateID.MOTION_DETECTED), { val: true, ack: true }); await saveImageStates(this, push_msg.pic_url!, push_msg.event_time, device.getStationSerial(), device.getSerial(), DataLocation.LAST_EVENT, device.getStateID(IndoorCameraStateID.LAST_EVENT_PICTURE_URL), device.getStateID(IndoorCameraStateID.LAST_EVENT_PICTURE_HTML), "Last captured picture").catch(() => { this.log.error(`handlePushNotifications(): IndoorPushEvent.MOTION_DETECTION of device ${device.getSerial()} - saveImageStates(): url ${push_msg.pic_url}`); }); - if (this.motionDetected[device.getSerial()]) - clearTimeout(this.motionDetected[device.getSerial()]); - this.motionDetected[device.getSerial()] = setTimeout(async () => { - await this.setStateAsync(device.getStateID(IndoorCameraStateID.MOTION_DETECTED), { val: false, ack: true }); - }, this.config.eventDuration * 1000); - } else { - await this.setStateAsync(device.getStateID(IndoorCameraStateID.MOTION_DETECTED), { val: true, ack: true }); - if (this.motionDetected[device.getSerial()]) - clearTimeout(this.motionDetected[device.getSerial()]); - this.motionDetected[device.getSerial()] = setTimeout(async () => { - await this.setStateAsync(device.getStateID(IndoorCameraStateID.MOTION_DETECTED), { val: false, ack: true }); - }, this.config.eventDuration * 1000); } if (push_msg.push_count === 1) this._startDownload(push_msg.station_sn, push_msg.file_path, push_msg.cipher); break; case IndoorPushEvent.FACE_DETECTION: + await this.setStateAsync(device.getStateID(IndoorCameraStateID.PERSON_DETECTED), { val: true, ack: true }); + await this.setStateAsync(device.getStateID(IndoorCameraStateID.LAST_PERSON_IDENTIFIED), { val: "Unknown", ack: true }); + if (this.personDetected[device.getSerial()]) + clearTimeout(this.personDetected[device.getSerial()]); + this.personDetected[device.getSerial()] = setTimeout(async () => { + await this.setStateAsync(device.getStateID(IndoorCameraStateID.PERSON_DETECTED), { val: false, ack: true }); + }, this.config.eventDuration * 1000); if (!isEmpty(push_msg.pic_url)) { - await this.setStateAsync(device.getStateID(IndoorCameraStateID.PERSON_DETECTED), { val: true, ack: true }); await saveImageStates(this, push_msg.pic_url!, push_msg.event_time, device.getStationSerial(), device.getSerial(), DataLocation.LAST_EVENT, device.getStateID(IndoorCameraStateID.LAST_EVENT_PICTURE_URL), device.getStateID(IndoorCameraStateID.LAST_EVENT_PICTURE_HTML), "Last captured picture").catch(() => { this.log.error(`handlePushNotifications(): IndoorPushEvent.FACE_DETECTION of device ${device.getSerial()} - saveImageStates(): url ${push_msg.pic_url}`); }); - await this.setStateAsync(device.getStateID(IndoorCameraStateID.LAST_PERSON_IDENTIFIED), { val: "Unknown", ack: true }); - if (this.personDetected[device.getSerial()]) - clearTimeout(this.personDetected[device.getSerial()]); - this.personDetected[device.getSerial()] = setTimeout(async () => { - await this.setStateAsync(device.getStateID(IndoorCameraStateID.PERSON_DETECTED), { val: false, ack: true }); - }, this.config.eventDuration * 1000); - } else { - await this.setStateAsync(device.getStateID(IndoorCameraStateID.PERSON_DETECTED), { val: true, ack: true }); - await this.setStateAsync(device.getStateID(IndoorCameraStateID.LAST_PERSON_IDENTIFIED), { val: "Unknown", ack: true }); - if (this.personDetected[device.getSerial()]) - clearTimeout(this.personDetected[device.getSerial()]); - this.personDetected[device.getSerial()] = setTimeout(async () => { - await this.setStateAsync(device.getStateID(IndoorCameraStateID.PERSON_DETECTED), { val: false, ack: true }); - }, this.config.eventDuration * 1000); } if (push_msg.push_count === 1) this._startDownload(push_msg.station_sn, push_msg.file_path, push_msg.cipher); break; case IndoorPushEvent.CRYIG_DETECTION: + await this.setStateAsync(device.getStateID(IndoorCameraStateID.CRYING_DETECTED), { val: true, ack: true }); + if (this.cryingDetected[device.getSerial()]) + clearTimeout(this.cryingDetected[device.getSerial()]); + this.cryingDetected[device.getSerial()] = setTimeout(async () => { + await this.setStateAsync(device.getStateID(IndoorCameraStateID.CRYING_DETECTED), { val: false, ack: true }); + }, this.config.eventDuration * 1000); if (!isEmpty(push_msg.pic_url)) { - await this.setStateAsync(device.getStateID(IndoorCameraStateID.CRYING_DETECTED), { val: true, ack: true }); await saveImageStates(this, push_msg.pic_url!, push_msg.event_time, device.getStationSerial(), device.getSerial(), DataLocation.LAST_EVENT, device.getStateID(IndoorCameraStateID.LAST_EVENT_PICTURE_URL), device.getStateID(IndoorCameraStateID.LAST_EVENT_PICTURE_HTML), "Last captured picture").catch(() => { this.log.error(`handlePushNotifications(): IndoorPushEvent.CRYIG_DETECTION of device ${device.getSerial()} - saveImageStates(): url ${push_msg.pic_url}`); }); - if (this.cryingDetected[device.getSerial()]) - clearTimeout(this.cryingDetected[device.getSerial()]); - this.cryingDetected[device.getSerial()] = setTimeout(async () => { - await this.setStateAsync(device.getStateID(IndoorCameraStateID.CRYING_DETECTED), { val: false, ack: true }); - }, this.config.eventDuration * 1000); - } else { - await this.setStateAsync(device.getStateID(IndoorCameraStateID.CRYING_DETECTED), { val: true, ack: true }); - if (this.cryingDetected[device.getSerial()]) - clearTimeout(this.cryingDetected[device.getSerial()]); - this.cryingDetected[device.getSerial()] = setTimeout(async () => { - await this.setStateAsync(device.getStateID(IndoorCameraStateID.CRYING_DETECTED), { val: false, ack: true }); - }, this.config.eventDuration * 1000); } if (push_msg.push_count === 1) this._startDownload(push_msg.station_sn, push_msg.file_path, push_msg.cipher); break; case IndoorPushEvent.SOUND_DETECTION: + await this.setStateAsync(device.getStateID(IndoorCameraStateID.SOUND_DETECTED), { val: true, ack: true }); + if (this.soundDetected[device.getSerial()]) + clearTimeout(this.soundDetected[device.getSerial()]); + this.soundDetected[device.getSerial()] = setTimeout(async () => { + await this.setStateAsync(device.getStateID(IndoorCameraStateID.SOUND_DETECTED), { val: false, ack: true }); + }, this.config.eventDuration * 1000); if (!isEmpty(push_msg.pic_url)) { - await this.setStateAsync(device.getStateID(IndoorCameraStateID.SOUND_DETECTED), { val: true, ack: true }); await saveImageStates(this, push_msg.pic_url!, push_msg.event_time, device.getStationSerial(), device.getSerial(), DataLocation.LAST_EVENT, device.getStateID(IndoorCameraStateID.LAST_EVENT_PICTURE_URL), device.getStateID(IndoorCameraStateID.LAST_EVENT_PICTURE_HTML), "Last captured picture").catch(() => { this.log.error(`handlePushNotifications(): IndoorPushEvent.SOUND_DETECTION of device ${device.getSerial()} - saveImageStates(): url ${push_msg.pic_url}`); }); - if (this.soundDetected[device.getSerial()]) - clearTimeout(this.soundDetected[device.getSerial()]); - this.soundDetected[device.getSerial()] = setTimeout(async () => { - await this.setStateAsync(device.getStateID(IndoorCameraStateID.SOUND_DETECTED), { val: false, ack: true }); - }, this.config.eventDuration * 1000); - } else { - await this.setStateAsync(device.getStateID(IndoorCameraStateID.SOUND_DETECTED), { val: true, ack: true }); - if (this.soundDetected[device.getSerial()]) - clearTimeout(this.soundDetected[device.getSerial()]); - this.soundDetected[device.getSerial()] = setTimeout(async () => { - await this.setStateAsync(device.getStateID(IndoorCameraStateID.SOUND_DETECTED), { val: false, ack: true }); - }, this.config.eventDuration * 1000); } if (push_msg.push_count === 1) this._startDownload(push_msg.station_sn, push_msg.file_path, push_msg.cipher); break; case IndoorPushEvent.PET_DETECTION: + await this.setStateAsync(device.getStateID(IndoorCameraStateID.PET_DETECTED), { val: true, ack: true }); + if (this.petDetected[device.getSerial()]) + clearTimeout(this.petDetected[device.getSerial()]); + this.petDetected[device.getSerial()] = setTimeout(async () => { + await this.setStateAsync(device.getStateID(IndoorCameraStateID.PET_DETECTED), { val: false, ack: true }); + }, this.config.eventDuration * 1000); if (!isEmpty(push_msg.pic_url)) { - await this.setStateAsync(device.getStateID(IndoorCameraStateID.PET_DETECTED), { val: true, ack: true }); await saveImageStates(this, push_msg.pic_url!, push_msg.event_time, device.getStationSerial(), device.getSerial(), DataLocation.LAST_EVENT, device.getStateID(IndoorCameraStateID.LAST_EVENT_PICTURE_URL), device.getStateID(IndoorCameraStateID.LAST_EVENT_PICTURE_HTML), "Last captured picture").catch(() => { this.log.error(`handlePushNotifications(): IndoorPushEvent.PET_DETECTION of device ${device.getSerial()} - saveImageStates(): url ${push_msg.pic_url}`); }); - if (this.petDetected[device.getSerial()]) - clearTimeout(this.petDetected[device.getSerial()]); - this.petDetected[device.getSerial()] = setTimeout(async () => { - await this.setStateAsync(device.getStateID(IndoorCameraStateID.PET_DETECTED), { val: false, ack: true }); - }, this.config.eventDuration * 1000); - } else { - await this.setStateAsync(device.getStateID(IndoorCameraStateID.PET_DETECTED), { val: true, ack: true }); - if (this.petDetected[device.getSerial()]) - clearTimeout(this.petDetected[device.getSerial()]); - this.petDetected[device.getSerial()] = setTimeout(async () => { - await this.setStateAsync(device.getStateID(IndoorCameraStateID.PET_DETECTED), { val: false, ack: true }); - }, this.config.eventDuration * 1000); } if (push_msg.push_count === 1) this._startDownload(push_msg.station_sn, push_msg.file_path, push_msg.cipher);