From 83a710e60d3eabf08c1744a9ebbab77054e637aa Mon Sep 17 00:00:00 2001 From: Flavio De Stefano Date: Fri, 9 Aug 2024 19:34:07 +0200 Subject: [PATCH] Making the plugin more resilient to reboots --- src/cameraAccessory.ts | 58 +++++++++++++++++++++++++----------------- src/cameraPlatform.ts | 2 +- src/tapoCamera.ts | 8 +++--- 3 files changed, 40 insertions(+), 28 deletions(-) diff --git a/src/cameraAccessory.ts b/src/cameraAccessory.ts index d787fed..1bd22f2 100644 --- a/src/cameraAccessory.ts +++ b/src/cameraAccessory.ts @@ -111,22 +111,31 @@ export class CameraAccessory { toggleService .getCharacteristic(this.api.hap.Characteristic.On) .onGet(async () => { - this.log.debug(`Getting "${tapoServiceStr}" status...`); + try { + this.log.debug(`Getting "${tapoServiceStr}" status...`); - const cameraStatus = await this.camera.getStatus(); - const value = cameraStatus[tapoServiceStr]; - if (value !== undefined) { - return value; + const cameraStatus = await this.camera.getStatus(); + const value = cameraStatus[tapoServiceStr]; + if (value !== undefined) return value; + + return null; + } catch (err) { + this.log.error("Error getting status:", err); + return null; } - throw new this.api.hap.HapStatusError( - this.api.hap.HAPStatus.RESOURCE_DOES_NOT_EXIST - ); }) .onSet(async (newValue) => { - this.log.info( - `Setting "${tapoServiceStr}" to ${newValue ? "on" : "off"}...` - ); - this.camera.setStatus(tapoServiceStr, Boolean(newValue)); + try { + this.log.info( + `Setting "${tapoServiceStr}" to ${newValue ? "on" : "off"}...` + ); + this.camera.setStatus(tapoServiceStr, Boolean(newValue)); + } catch (err) { + this.log.error("Error setting status:", err); + throw new this.api.hap.HapStatusError( + this.api.hap.HAPStatus.RESOURCE_DOES_NOT_EXIST + ); + } }); this.accessory.addService(toggleService); @@ -201,19 +210,20 @@ export class CameraAccessory { } private async getStatusAndNotify() { - const cameraStatus = await this.camera.getStatus(); - this.platform.log.debug( - "Notifying new values", - JSON.stringify(cameraStatus) - ); - - for (const [key, value] of Object.entries(cameraStatus)) { - const toggleService = this.toggleAccessories[key as keyof Status]; - if (toggleService && value !== undefined) { - toggleService - .getCharacteristic(this.api.hap.Characteristic.On) - .updateValue(value); + try { + const cameraStatus = await this.camera.getStatus(); + this.log.debug("Notifying new values", JSON.stringify(cameraStatus)); + + for (const [key, value] of Object.entries(cameraStatus)) { + const toggleService = this.toggleAccessories[key as keyof Status]; + if (toggleService && value !== undefined) { + toggleService + .getCharacteristic(this.api.hap.Characteristic.On) + .updateValue(value); + } } + } catch (err) { + this.log.error("Error getting status:", err); } } diff --git a/src/cameraPlatform.ts b/src/cameraPlatform.ts index 2b1d400..5b98948 100644 --- a/src/cameraPlatform.ts +++ b/src/cameraPlatform.ts @@ -31,7 +31,7 @@ export class CameraPlatform implements IndependentPlatformPlugin { } catch (err) { this.log.error( `Error during setup of camera ${cameraConfig.name}`, - (err as Error)?.message + err ); } }); diff --git a/src/tapoCamera.ts b/src/tapoCamera.ts index d06bb71..c5e5188 100644 --- a/src/tapoCamera.ts +++ b/src/tapoCamera.ts @@ -27,7 +27,7 @@ export type Status = { export class TAPOCamera extends OnvifCamera { private readonly kStreamPort = 554; - private readonly httpsAgent: Agent; + private readonly fetchAgent: Agent; private readonly hashedMD5Password: string; private readonly hashedSha256Password: string; @@ -49,8 +49,10 @@ export class TAPOCamera extends OnvifCamera { ) { super(log, config); - this.httpsAgent = new Agent({ + this.fetchAgent = new Agent({ + connectTimeout: 5_000, connect: { + // TAPO devices have self-signed certificates rejectUnauthorized: false, }, }); @@ -100,7 +102,7 @@ export class TAPOCamera extends OnvifCamera { return fetch(url, { headers: this.getHeaders(), // @ts-expect-error Dispatcher type not there - dispatcher: this.httpsAgent, + dispatcher: this.fetchAgent, ...data, }); }