diff --git a/package-lock.json b/package-lock.json index 390770e5..68cb5932 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3392,72 +3392,6 @@ "url": "https://opencollective.com/vitest" } }, - "node_modules/@vue/compiler-core": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.18.tgz", - "integrity": "sha512-3slwjQrrV1TO8MoXgy3aynDQ7lslj5UqDxuHnrzHtpON5CBinhWjJETciPngpin/T3OuW3tXUf86tEurusnztw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/parser": "^7.28.0", - "@vue/shared": "3.5.18", - "entities": "^4.5.0", - "estree-walker": "^2.0.2", - "source-map-js": "^1.2.1" - } - }, - "node_modules/@vue/compiler-dom": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.18.tgz", - "integrity": "sha512-RMbU6NTU70++B1JyVJbNbeFkK+A+Q7y9XKE2EM4NLGm2WFR8x9MbAtWxPPLdm0wUkuZv9trpwfSlL6tjdIa1+A==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@vue/compiler-core": "3.5.18", - "@vue/shared": "3.5.18" - } - }, - "node_modules/@vue/compiler-sfc": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.18.tgz", - "integrity": "sha512-5aBjvGqsWs+MoxswZPoTB9nSDb3dhd1x30xrrltKujlCxo48j8HGDNj3QPhF4VIS0VQDUrA1xUfp2hEa+FNyXA==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/parser": "^7.28.0", - "@vue/compiler-core": "3.5.18", - "@vue/compiler-dom": "3.5.18", - "@vue/compiler-ssr": "3.5.18", - "@vue/shared": "3.5.18", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.17", - "postcss": "^8.5.6", - "source-map-js": "^1.2.1" - } - }, - "node_modules/@vue/compiler-ssr": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.18.tgz", - "integrity": "sha512-xM16Ak7rSWHkM3m22NlmcdIM+K4BMyFARAfV9hYFl+SFuRzrZ3uGMNW05kA5pmeMa0X9X963Kgou7ufdbpOP9g==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@vue/compiler-dom": "3.5.18", - "@vue/shared": "3.5.18" - } - }, - "node_modules/@vue/shared": { - "version": "3.5.18", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.18.tgz", - "integrity": "sha512-cZy8Dq+uuIXbxCZpuLd2GJdeSO/lIzIspC2WtkqIpje5QyFbvLaI5wZtdUjLHjGZrlVX6GilejatWwVYYRc8tA==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/@yarnpkg/lockfile": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", @@ -6181,14 +6115,6 @@ "node": ">=4.0" } }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true, - "license": "MIT", - "peer": true - }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", diff --git a/src/device/blindtilt.ts b/src/device/blindtilt.ts index 45603008..f386c600 100644 --- a/src/device/blindtilt.ts +++ b/src/device/blindtilt.ts @@ -589,7 +589,11 @@ export class BlindTilt extends deviceBase { return await this.retryBLE({ max: this.maxRetryBLE(), fn: async () => { - return await deviceList[0].runToPos(100 - Number(this.WindowCovering.TargetPosition), setPositionMode) + if (deviceList && Array.isArray(deviceList) && deviceList.length > 0) { + return await deviceList[0].runToPos(100 - Number(this.WindowCovering.TargetPosition), setPositionMode) + } else { + throw new Error('No device found') + } }, }) }) diff --git a/src/device/curtain.ts b/src/device/curtain.ts index 2f197dde..6dd38ace 100644 --- a/src/device/curtain.ts +++ b/src/device/curtain.ts @@ -378,9 +378,11 @@ export class Curtain extends deviceBase { this.debugLog('BLEparseStatus') this.debugLog(`(position, battery) = BLE:(${this.serviceData.position}, ${this.serviceData.battery}), current:(${this.WindowCovering.CurrentPosition}, ${this.Battery.BatteryLevel})`) // CurrentPosition - if ('position' in this.serviceData) { - this.WindowCovering.CurrentPosition = 100 - this.serviceData.position + if ('position' in this.serviceData && this.serviceData.position !== undefined && this.serviceData.position !== null && !isNaN(Number(this.serviceData.position))) { + this.WindowCovering.CurrentPosition = 100 - Number(this.serviceData.position) await this.getCurrentPostion() + } else { + this.warnLog(`Invalid position data from BLE: ${this.serviceData.position}`) } // CurrentAmbientLightLevel if (!(this.device as curtainConfig).hide_lightsensor && this.LightSensor?.Service && 'lightLevel' in this.serviceData) { @@ -489,10 +491,10 @@ export class Curtain extends deviceBase { // Start to monitor advertisement packets const serviceData = await this.monitorAdvertisementPackets(switchBotBLE) as curtainServiceData | curtain3ServiceData // Update HomeKit - if ((serviceData.model === SwitchBotBLEModel.Curtain || SwitchBotBLEModel.Curtain3) - && (serviceData.modelName === SwitchBotBLEModelName.Curtain || SwitchBotBLEModelName.Curtain3)) { + if ((serviceData.model === SwitchBotBLEModel.Curtain || serviceData.model === SwitchBotBLEModel.Curtain3) + && (serviceData.modelName === SwitchBotBLEModelName.Curtain || serviceData.modelName === SwitchBotBLEModelName.Curtain3)) { this.serviceData = serviceData - if (serviceData !== undefined || serviceData !== null) { + if (serviceData !== undefined && serviceData !== null) { await this.BLEparseStatus() await this.updateHomeKitCharacteristics() } else { @@ -559,7 +561,7 @@ export class Curtain extends deviceBase { this.platform.bleEventHandler[this.device.bleMac] = async (context: curtainServiceData | curtain3ServiceData) => { try { this.serviceData = context - if (context !== undefined || context !== null) { + if (context !== undefined && context !== null) { this.debugLog(`received BLE: ${JSON.stringify(context)}`) await this.BLEparseStatus() await this.updateHomeKitCharacteristics() @@ -619,7 +621,11 @@ export class Curtain extends deviceBase { return await this.retryBLE({ max: this.maxRetryBLE(), fn: async () => { - return await deviceList[0].runToPos(100 - Number(this.WindowCovering.TargetPosition), adjustedMode) + if (deviceList && Array.isArray(deviceList) && deviceList.length > 0) { + return await deviceList[0].runToPos(100 - Number(this.WindowCovering.TargetPosition), adjustedMode) + } else { + throw new Error('No device found') + } }, }) }) @@ -777,6 +783,17 @@ export class Curtain extends deviceBase { async updateHomeKitCharacteristics(): Promise { await this.setMinMax() + + // Validate position values to prevent NaN + if (isNaN(Number(this.WindowCovering.CurrentPosition))) { + this.warnLog(`CurrentPosition is NaN, keeping previous value`) + this.WindowCovering.CurrentPosition = this.accessory.context.CurrentPosition ?? 100 + } + if (isNaN(Number(this.WindowCovering.TargetPosition))) { + this.warnLog(`TargetPosition is NaN, keeping previous value`) + this.WindowCovering.TargetPosition = this.accessory.context.TargetPosition ?? 100 + } + // CurrentPosition await this.updateCharacteristic(this.WindowCovering.Service, this.hap.Characteristic.CurrentPosition, this.WindowCovering.CurrentPosition, 'CurrentPosition') // PositionState @@ -799,17 +816,22 @@ export class Curtain extends deviceBase { } async BLEPushConnection() { + this.warnLog('BLE connection failed for push operation') if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') { this.warnLog('Using OpenAPI Connection to Push Changes') await this.openAPIpushChanges() + } else { + this.errorLog('No fallback available for BLE push failure. Consider using BLE/OpenAPI connection type.') } } async BLERefreshConnection(switchbot: SwitchBotBLE): Promise { - this.errorLog(`wasn't able to establish BLE Connection, node-switchbot: ${switchbot}`) + this.warnLog(`BLE connection failed for refresh operation, node-switchbot: ${switchbot}`) if (this.platform.config.credentials?.token && this.device.connectionType === 'BLE/OpenAPI') { this.warnLog('Using OpenAPI Connection to Refresh Status') await this.openAPIRefreshStatus() + } else { + this.errorLog('No fallback available for BLE refresh failure. Consider using BLE/OpenAPI connection type.') } }