UNPKG

@viguza/homebridge-ezviz

Version:

A short description about what your plugin does.

89 lines 3.76 kB
const POLL_INTERVAL_MS = 30_000; const MOTION_WINDOW_MS = 60_000; export class MotionSensor { api; platform; accessory; service; motionDetected = false; lastSeenAlarmTime = undefined; clearTimer = null; usingMqtt = false; pollInterval = null; constructor(api, platform, accessory) { this.api = api; this.platform = platform; this.accessory = accessory; this.accessory.getService(this.platform.Service.AccessoryInformation) .setCharacteristic(this.platform.Characteristic.Manufacturer, 'EZVIZ') .setCharacteristic(this.platform.Characteristic.Model, 'Motion Sensor') .setCharacteristic(this.platform.Characteristic.SerialNumber, accessory.context.serial); this.service = this.accessory.getService(this.platform.Service.MotionSensor) || this.accessory.addService(this.platform.Service.MotionSensor); this.service.setCharacteristic(this.platform.Characteristic.Name, accessory.displayName); this.service.getCharacteristic(this.platform.Characteristic.MotionDetected) .onGet(() => this.motionDetected); this.poll(); this.pollInterval = setInterval(() => this.poll(), POLL_INTERVAL_MS); } // Called by MQTT — real-time push, trigger immediately regardless of timestamp. onMqttAlarm() { this.usingMqtt = true; this.triggerMotion(); } stopPolling() { if (this.pollInterval) { clearInterval(this.pollInterval); this.pollInterval = null; this.platform.log.debug(`${this.accessory.displayName}: polling stopped`); } } get serial() { return this.accessory.context.serial; } triggerMotion() { // Reset the 60s auto-clear window from now if (this.clearTimer) { clearTimeout(this.clearTimer); } this.clearTimer = setTimeout(() => this.clearMotion(), MOTION_WINDOW_MS); if (!this.motionDetected) { this.motionDetected = true; this.service.updateCharacteristic(this.platform.Characteristic.MotionDetected, true); this.platform.log.info(`${this.accessory.displayName}: motion detected${this.usingMqtt ? ' (MQTT)' : ''}`); } } clearMotion() { if (this.clearTimer) { clearTimeout(this.clearTimer); this.clearTimer = null; } this.motionDetected = false; this.service.updateCharacteristic(this.platform.Characteristic.MotionDetected, false); this.platform.log.debug(`${this.accessory.displayName}: motion cleared`); } // Poll uses change detection: trigger when the REST API alarm timestamp changes, // regardless of how old that timestamp is. Clears are handled by the timer only. async poll() { try { const alarmTime = await this.api.getLastAlarmTime(this.serial); if (alarmTime === null) { return; } if (this.lastSeenAlarmTime === undefined) { this.lastSeenAlarmTime = alarmTime; this.platform.log.debug(`${this.accessory.displayName}: initialised alarmTime=${alarmTime}`); return; } if (alarmTime !== this.lastSeenAlarmTime) { this.platform.log.debug(`${this.accessory.displayName}: new alarm via poll (${this.lastSeenAlarmTime} → ${alarmTime})`); this.lastSeenAlarmTime = alarmTime; this.triggerMotion(); } } catch (error) { this.platform.log.error(`${this.accessory.displayName}: motion poll failed:`, error); } } } //# sourceMappingURL=motion-sensor.js.map