UNPKG

homebridge-eufy-security

Version:
201 lines 8.78 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseAccessory = void 0; const eufy_security_client_1 = require("eufy-security-client"); const events_1 = require("events"); const utils_1 = require("../utils/utils"); /** * Determine if the serviceType is an instance of Service. * * @param {WithUUID<typeof Service> | Service} serviceType - The service type to be checked. * @returns {boolean} Returns true if the serviceType is an instance of Service, otherwise false. */ function isServiceInstance(serviceType) { // eslint-disable-next-line return typeof serviceType === 'object'; } class BaseAccessory extends events_1.EventEmitter { platform; accessory; device; servicesInUse = []; SN; name; log; constructor(platform, accessory, // eslint-disable-next-line @typescript-eslint/no-explicit-any device) { super(); this.platform = platform; this.accessory = accessory; this.device = device; this.device = device; this.SN = this.device.getSerial(); this.name = this.device.getName(); this.log = utils_1.log.getSubLogger({ name: '', prefix: [this.name], }); this.registerCharacteristic({ serviceType: utils_1.SERV.AccessoryInformation, characteristicType: utils_1.CHAR.Manufacturer, getValue: () => 'Eufy', }); this.registerCharacteristic({ serviceType: utils_1.SERV.AccessoryInformation, characteristicType: utils_1.CHAR.Name, getValue: () => this.name || 'Unknowm', }); this.registerCharacteristic({ serviceType: utils_1.SERV.AccessoryInformation, characteristicType: utils_1.CHAR.Model, getValue: () => eufy_security_client_1.DeviceType[this.device.getDeviceType()] || 'Unknowm', }); this.registerCharacteristic({ serviceType: utils_1.SERV.AccessoryInformation, characteristicType: utils_1.CHAR.SerialNumber, getValue: () => this.SN || 'Unknowm', }); this.registerCharacteristic({ serviceType: utils_1.SERV.AccessoryInformation, characteristicType: utils_1.CHAR.FirmwareRevision, getValue: () => this.device.getSoftwareVersion() || 'Unknowm', }); this.registerCharacteristic({ serviceType: utils_1.SERV.AccessoryInformation, characteristicType: utils_1.CHAR.HardwareRevision, getValue: () => this.device.getHardwareVersion() || 'Unknowm', }); if (this.platform.config.enableDetailedLogging) { this.device.on('raw property changed', this.handleRawPropertyChange.bind(this)); this.device.on('property changed', this.handlePropertyChange.bind(this)); } this.logPropertyKeys(); } // Function to extract and log keys logPropertyKeys() { this.log.debug(`Property Keys:`, this.device.getProperties()); } // eslint-disable-next-line @typescript-eslint/no-explicit-any handleRawPropertyChange(device, type, value) { this.log.debug(`Raw Property Changes:`, type, value); } // eslint-disable-next-line @typescript-eslint/no-explicit-any handlePropertyChange(device, name, value) { this.log.debug(`Property Changes:`, name, value); } /** * Register characteristics for a given Homebridge service. * * This method handles the registration of Homebridge characteristics. * It includes optional features like value debouncing and event triggers. * * @param {Object} params - Parameters needed for registering characteristics. */ registerCharacteristic({ characteristicType, serviceType, getValue, setValue, onValue, onSimpleValue, onMultipleValue, name, serviceSubType, setValueDebounceTime = 0, }) { this.log.debug(`REGISTER CHARACTERISTIC ${serviceType.name} / ${characteristicType.name} / ${name}`); const service = this.getService(serviceType, name, serviceSubType); const characteristic = service.getCharacteristic(characteristicType); this.log.debug(`REGISTER CHARACTERISTIC (${service.UUID}) / (${characteristic.UUID})`); if (getValue) { characteristic.onGet(async (data) => { const value = getValue(data, characteristic, service); this.log.debug(`GET '${serviceType.name} / ${characteristicType.name}':`, value); return value; }); } if (setValue && setValueDebounceTime) { let timeoutId = null; characteristic.onSet(async (value) => { if (timeoutId) { clearTimeout(timeoutId); } timeoutId = setTimeout(() => { timeoutId = null; setValue(value, characteristic, service); }, setValueDebounceTime); }); } else if (setValue) { characteristic.onSet(async (value) => { Promise.resolve(setValue(value, characteristic, service)); }); } if (onSimpleValue) { // eslint-disable-next-line @typescript-eslint/no-explicit-any this.device.on(onSimpleValue, (device, value) => { this.log.info(`ON '${serviceType.name} / ${characteristicType.name} / ${onSimpleValue}':`, value); characteristic.updateValue(value); }); } if (onValue) { this.log.debug(`ON '${serviceType.name} / ${characteristicType.name}'`); onValue(service, characteristic); } if (onMultipleValue) { // Attach the common event handler to each event type onMultipleValue.forEach(eventType => { // eslint-disable-next-line @typescript-eslint/no-explicit-any this.device.on(eventType, (device, value) => { this.log.info(`ON '${serviceType.name} / ${characteristicType.name} / ${eventType}':`, value); characteristic.updateValue(value); }); }); } } /** * Retrieve an existing service or create a new one if it doesn't exist. * * @param {ServiceType} serviceType - The type of service to retrieve or create. * @param {string} [name] - The name of the service (optional). * @param {string} [subType] - The subtype of the service (optional). * @returns {Service} Returns the existing or newly created service. * @throws Will throw an error if there are overlapping services. */ getService(serviceType, name = this.name, subType) { if (isServiceInstance(serviceType)) { return serviceType; } const existingService = subType ? this.accessory.getServiceById(serviceType, subType) : this.accessory.getService(serviceType); const service = existingService || this.accessory.addService(serviceType, name, subType); if (existingService && existingService.displayName && name !== existingService.displayName) { throw new Error(`Overlapping services for device ${this.name} - ${name} != ${existingService.displayName} - ${serviceType}`); } if (!this.servicesInUse.includes(service)) { this.servicesInUse.push(service); } return service; } pruneUnusedServices() { const safeServiceUUIDs = [ utils_1.SERV.CameraRTPStreamManagement.UUID, ]; this.accessory.services.forEach((service) => { if (!this.servicesInUse.includes(service) && !safeServiceUUIDs.includes(service.UUID)) { this.log.debug(`Pruning unused service ${service.UUID} ${service.displayName || service.name}`); this.accessory.removeService(service); } }); } handleDummyEventGet(serviceName) { const characteristicValues = { 'EventSnapshotsActive': utils_1.CHAR.EventSnapshotsActive.DISABLE, 'HomeKitCameraActive': utils_1.CHAR.HomeKitCameraActive.OFF, }; const currentValue = characteristicValues[serviceName]; if (currentValue === undefined) { throw new Error(`Invalid serviceName: ${serviceName}`); } this.log.debug(`IGNORE GET ${serviceName}: ${currentValue}`); return Promise.resolve(currentValue); } handleDummyEventSet(serviceName, value) { this.log.debug(`IGNORE SET ${serviceName}: ${value}`); } } exports.BaseAccessory = BaseAccessory; //# sourceMappingURL=BaseAccessory.js.map