@koush/ring-client-api
Version:
Unofficial API for Ring doorbells, cameras, security alarm system and smart lighting
93 lines (92 loc) • 4.16 kB
JavaScript
;
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;