homebridge-resideo
Version:
The Resideo plugin allows you to access your Resideo device(s) from HomeKit.
151 lines • 7.07 kB
JavaScript
import { interval, Subject } from 'rxjs';
import { debounceTime, skipWhile, take, tap } from 'rxjs/operators';
import { DeviceURL } from '../settings.js';
import { deviceBase } from './device.js';
export class Valve extends deviceBase {
platform;
Valve;
valveType;
valveUpdateInProgress;
doValveUpdate;
constructor(platform, accessory, location, device) {
super(platform, accessory, location, device);
this.platform = platform;
this.getValveConfigSettings(accessory, device);
this.doValveUpdate = new Subject();
this.valveUpdateInProgress = false;
accessory.context.Valve = accessory.context.Valve ?? {};
this.Valve = {
Name: accessory.context.Valve.Name ?? accessory.displayName,
Service: accessory.getService(this.hap.Service.Valve) ?? accessory.addService(this.hap.Service.Valve),
Active: accessory.context.Active ?? this.hap.Characteristic.Active.INACTIVE,
InUse: accessory.context.InUse ?? this.hap.Characteristic.InUse.NOT_IN_USE,
ValveType: accessory.context.ValveType ?? this.hap.Characteristic.ValveType.GENERIC_VALVE,
};
accessory.context.Valve = this.Valve;
this.Valve.Service
.setCharacteristic(this.hap.Characteristic.Name, this.Valve.Name)
.setCharacteristic(this.hap.Characteristic.ValveType, this.valveType)
.getCharacteristic(this.hap.Characteristic.Active)
.onGet(() => this.Valve.Active)
.onSet(this.setActive.bind(this));
this.Valve.Service
.getCharacteristic(this.hap.Characteristic.InUse)
.onGet(() => this.Valve.InUse);
this.refreshStatus();
interval(this.deviceRefreshRate * 1000)
.pipe(skipWhile(() => this.valveUpdateInProgress))
.subscribe(async () => {
await this.refreshStatus();
});
this.doValveUpdate
.pipe(tap(() => {
this.valveUpdateInProgress = true;
}), debounceTime(this.devicePushRate * 1000))
.subscribe(async () => {
try {
await this.pushChanges();
}
catch (e) {
const action = 'pushChanges';
await this.resideoAPIError(e, action);
this.errorLog(`${device.deviceClass} ${accessory.displayName}: doValveUpdate pushChanges: ${JSON.stringify(e)}`);
}
interval(this.deviceRefreshRate * 500)
.pipe(skipWhile(() => this.valveUpdateInProgress), take(1))
.subscribe(async () => {
await this.refreshStatus();
});
this.valveUpdateInProgress = false;
});
}
async parseStatus(device) {
this.Valve.Active = device.isAlive ? this.hap.Characteristic.Active.ACTIVE : this.hap.Characteristic.Active.INACTIVE;
this.accessory.context.Active = this.Valve.Active;
this.Valve.InUse = device.actuatorValve.valveStatus === 'Open' ? this.hap.Characteristic.InUse.IN_USE : this.hap.Characteristic.InUse.NOT_IN_USE;
if (this.Valve.InUse !== this.accessory.context.InUse) {
this.successLog(`${this.device.deviceClass} ${this.accessory.displayName} (refreshStatus) device: ${JSON.stringify(device)}`);
this.accessory.context.InUse = this.Valve.InUse;
}
}
async refreshStatus() {
try {
const device = (await this.platform.axios.get(`${DeviceURL}/waterLeakDetectors/${this.device.deviceID}`, {
params: {
locationId: this.location.locationID,
},
})).data;
this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} (refreshStatus) device: ${JSON.stringify(device)}`);
this.parseStatus(device);
this.updateHomeKitCharacteristics();
}
catch (e) {
const action = 'refreshStatus';
if (this.device.retry) {
if (action === 'refreshStatus') {
interval(5000)
.pipe(skipWhile(() => this.valveUpdateInProgress), take(1))
.subscribe(async () => {
await this.refreshStatus();
});
}
}
await this.resideoAPIError(e, action);
this.apiError(e);
}
}
async pushChanges() {
try {
const payload = {
state: this.Valve.Active === this.hap.Characteristic.Active.ACTIVE ? 'open' : 'closed',
};
await this.platform.axios.post(`${DeviceURL}/waterLeakDetectors/${this.device.deviceID}`, payload, {
params: {
locationId: this.location.locationID,
},
});
this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} pushChanges: ${JSON.stringify(payload)}`);
const action = 'pushChanges';
await this.statusCode(200, action);
}
catch (e) {
const action = 'pushChanges';
await this.resideoAPIError(e, action);
this.errorLog(`pushChanges: ${JSON.stringify(e)}`);
this.errorLog(`${this.device.deviceClass} ${this.accessory.displayName} failed pushChanges, Error Message: ${JSON.stringify(e.message)}`);
}
}
async updateHomeKitCharacteristics() {
this.Valve.Service.updateCharacteristic(this.hap.Characteristic.Active, this.Valve.Active);
this.accessory.context.Active = this.Valve.Active;
this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} updateCharacteristic Active: ${this.Valve.Active}`);
this.Valve.Service.updateCharacteristic(this.hap.Characteristic.InUse, this.Valve.InUse);
this.accessory.context.InUse = this.Valve.InUse;
this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} updateCharacteristic InUse: ${this.Valve.InUse}`);
}
setActive(value) {
this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} Set Active: ${value}`);
this.Valve.Active = value;
this.doValveUpdate.next();
}
async getValveConfigSettings(accessory, device) {
switch (device.valve?.valveType) {
case 1:
this.valveType = this.hap.Characteristic.ValveType.IRRIGATION;
break;
case 2:
this.valveType = this.hap.Characteristic.ValveType.SHOWER_HEAD;
break;
case 3:
this.valveType = this.hap.Characteristic.ValveType.WATER_FAUCET;
break;
default:
this.valveType = this.hap.Characteristic.ValveType.GENERIC_VALVE;
}
accessory.context.valveType = this.valveType;
}
async apiError(e) {
this.Valve.Service.updateCharacteristic(this.hap.Characteristic.Active, e);
}
}
//# sourceMappingURL=valve.js.map