UNPKG

@koush/ring-client-api

Version:

Unofficial API for Ring doorbells, cameras, security alarm system and smart lighting

93 lines (92 loc) 4.16 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseAccessory = void 0; const hap_1 = require("./hap"); const operators_1 = require("rxjs/operators"); const rxjs_1 = require("rxjs"); function isServiceInstance(serviceType) { return typeof serviceType === 'object'; } class BaseAccessory { constructor() { this.servicesInUse = []; } initBase() { this.pruneUnusedServices(); } getService(serviceType, name = this.device.name, subType) { if (isServiceInstance(serviceType)) { return serviceType; } const debug = process.env.RING_DEBUG === 'true'; if (debug) { name = 'TEST ' + name; } const existingService = subType ? this.accessory.getServiceById(serviceType, subType) : this.accessory.getService(serviceType), service = existingService || this.accessory.addService(serviceType, name, subType); if (debug && existingService && existingService.displayName && name !== existingService.displayName) { throw new Error(`Overlapping services for device ${this.device.name} - ${name} != ${existingService.displayName} - ${serviceType}`); } if (!this.servicesInUse.includes(service)) { this.servicesInUse.push(service); } return service; } registerObservableCharacteristic({ characteristicType, serviceType, serviceSubType, onValue, setValue, name, requestUpdate, }) { const service = this.getService(serviceType, name, serviceSubType), characteristic = service.getCharacteristic(characteristicType), onCachedValue = onValue.pipe((0, operators_1.shareReplay)(1)); onCachedValue.subscribe((value) => { characteristic.updateValue(value); }); if (requestUpdate) { // Only register for GET if an async request should be made to get an updated value onCachedValue.pipe((0, operators_1.take)(1)).subscribe(() => { // allow GET once a value is cached characteristic.on("get" /* GET */, (callback) => __awaiter(this, void 0, void 0, function* () { try { const value = yield (0, rxjs_1.firstValueFrom)(onCachedValue); callback(null, value); requestUpdate(); } catch (e) { callback(e); } })); }); } if (setValue) { characteristic.on("set" /* SET */, (newValue, callback) => { Promise.resolve(setValue(newValue)).catch((e) => { this.logger.error(e); }); callback(); }); } } pruneUnusedServices() { const safeServiceUUIDs = [ hap_1.hap.Service.CameraRTPStreamManagement.UUID, hap_1.hap.Service.CameraControl.UUID, ]; this.accessory.services.forEach((service) => { if (!this.servicesInUse.includes(service) && !safeServiceUUIDs.includes(service.UUID)) { this.logger.info('Pruning unused service', service.UUID, service.displayName || service.name, 'from', this.device.name); this.accessory.removeService(service); } }); } } exports.BaseAccessory = BaseAccessory;