UNPKG

@homebridge-plugins/homebridge-rainbird

Version:

The Rainbird plugin allows you to access your Rainbird device(s) from HomeKit.

177 lines 8.7 kB
import { fromEvent, interval, Subject } from 'rxjs'; import { debounceTime, skipWhile, tap } from 'rxjs/operators'; import { DeviceBase } from './DeviceBase.js'; export class ZoneValve extends DeviceBase { platform; irrigationContext; zoneId; zoneValve; // Zone Valve Updates zoneUpdateInProgress; doZoneUpdate; constructor(platform, accessory, device, rainbird, irrigationContext) { super(platform, accessory, device, rainbird); this.platform = platform; this.irrigationContext = irrigationContext; this.zoneId = this.accessory.context.zoneId; // this is subject we use to track when we need to send changes to Rainbird Client this.doZoneUpdate = new Subject(); this.zoneUpdateInProgress = false; if (irrigationContext.duration[this.zoneId] === undefined) { irrigationContext.duration[this.zoneId] = 300; } // Zone Valve Service this.debugLog(`Load Valve Service for ${accessory.displayName}`); this.zoneValve = { service: this.accessory.getService(this.hap.Service.Valve) ?? this.accessory.addService(this.hap.Service.Valve), Active: this.hap.Characteristic.Active.INACTIVE, InUse: this.hap.Characteristic.InUse.NOT_IN_USE, }; // Add Valve's Characteristics this.zoneValve.service .setCharacteristic(this.hap.Characteristic.Active, this.zoneValve.Active) .setCharacteristic(this.hap.Characteristic.InUse, this.zoneValve.InUse) .setCharacteristic(this.hap.Characteristic.ValveType, this.hap.Characteristic.ValveType.IRRIGATION) .setCharacteristic(this.hap.Characteristic.Name, accessory.displayName) .setCharacteristic(this.hap.Characteristic.RemainingDuration, 0) .setCharacteristic(this.hap.Characteristic.SetDuration, irrigationContext.duration[this.zoneId]) .setCharacteristic(this.hap.Characteristic.StatusFault, this.hap.Characteristic.StatusFault.NO_FAULT); this.zoneValve.service .getCharacteristic(this.hap.Characteristic.Active) .onGet(() => { this.rainbird.refreshStatus(); return this.zoneValve.Active; }) .onSet(this.setActive.bind(this)); this.zoneValve.service .getCharacteristic(this.hap.Characteristic.InUse) .onGet(() => { this.rainbird.refreshStatus(); return this.zoneValve.InUse; }); this.zoneValve.service .getCharacteristic(this.hap.Characteristic.ValveType) .onGet(() => { return this.zoneValve.service.getCharacteristic(this.hap.Characteristic.ValveType).value; }); this.zoneValve.service .getCharacteristic(this.hap.Characteristic.RemainingDuration) .setProps({ minValue: device.minValueRemainingDuration, maxValue: device.maxValueRemainingDuration, }) .onGet(() => { this.rainbird.refreshStatus(); return this.rainbird.remainingDuration(this.zoneId); }); this.zoneValve.service .getCharacteristic(this.hap.Characteristic.SetDuration) .onGet(() => { return Number(irrigationContext.duration[this.zoneId]); }) .onSet(this.setSetDuration.bind(this)); this.zoneValve.service .getCharacteristic(this.hap.Characteristic.StatusFault) .onGet(() => { return this.zoneValve.service.getCharacteristic(this.hap.Characteristic.StatusFault).value; }); // Initial Device Parse this.parseStatus(); this.updateHomeKitCharacteristics(); // Device Parse when status event emitted fromEvent(rainbird, 'status').subscribe({ next: () => { this.parseStatus(); this.updateHomeKitCharacteristics(); }, }); // Start an update interval interval(this.platform.config.options.refreshRate * 1000) .pipe(skipWhile(() => this.zoneUpdateInProgress)) .subscribe(() => { this.rainbird.refreshStatus(); }); this.doZoneUpdate .pipe(tap(() => { this.zoneUpdateInProgress = true; }), debounceTime(this.platform.config.options.pushRate * 1000)) .subscribe(async (zone) => { try { await this.pushChanges(zone); } catch (e) { this.debugLog(`${this.constructor.name}: ${this.accessory.displayName} - ${JSON.stringify(e.messsage)}`); if (this.deviceLogging.includes('debug')) { this.debugLog(`${this.constructor.name}: ${this.accessory.displayName} - ${JSON.stringify(e)}`); } } this.zoneUpdateInProgress = false; }); } async pushChanges(zone) { if (this.zoneValve.Active === this.hap.Characteristic.Active.ACTIVE) { this.rainbird.activateZone(zone, this.irrigationContext.duration[this.zoneId]); } else { await this.rainbird.deactivateZone(zone); } this.debugLog(`${this.constructor.name}: ${this.accessory.displayName}, pushChanges: [Valve: ${zone},` + ` Active: ${this.zoneValve.Active}, SetDuration: ${this.irrigationContext.duration[this.zoneId]}]`); } async setActive(value) { this.debugLog(`${this.constructor.name}: ${this.accessory.displayName}, Set Active: ${value}`); this.zoneValve.Active = value; this.doZoneUpdate.next(this.zoneId); } async setSetDuration(value) { this.debugLog(`${this.constructor.name}: ${this.accessory.displayName}, Set SetDuration: ${value}`); this.irrigationContext.duration[this.zoneId] = value; } /** * Parse the device status from the RainbirdClient */ parseStatus() { this.zoneValve.Active = this.rainbird.isActive(this.zoneId) ? this.hap.Characteristic.Active.ACTIVE : this.hap.Characteristic.Active.INACTIVE; this.zoneValve.InUse = this.rainbird.isInUse(this.zoneId) ? this.hap.Characteristic.InUse.IN_USE : this.hap.Characteristic.InUse.NOT_IN_USE; this.debugLog(`${this.constructor.name}: ${this.zoneId}, Active: ${this.zoneValve.Active}, InUse: ${this.zoneValve.InUse}`); } /** * Updates the status for each of the HomeKit Characteristics */ updateHomeKitCharacteristics() { if (this.zoneValve.Active === undefined) { this.debugLog(`${this.constructor.name}: ${this.accessory.displayName} Active: ${this.zoneValve.Active}`); } else { this.zoneValve.service.updateCharacteristic(this.hap.Characteristic.Active, this.zoneValve.Active); this.debugLog(`${this.constructor.name}: ${this.accessory.displayName} updateCharacteristic Active: ${this.zoneValve.Active}`); } if (this.zoneValve.InUse === undefined) { this.debugLog(`${this.constructor.name}: ${this.accessory.displayName} InUse: ${this.zoneValve.InUse}`); } else { this.zoneValve.service.updateCharacteristic(this.hap.Characteristic.InUse, this.zoneValve.InUse); this.debugLog(`${this.constructor.name}: ${this.accessory.displayName} updateCharacteristic InUse: ${this.zoneValve.InUse}`); } const remainingDuration = this.rainbird.remainingDuration(this.zoneId); if (remainingDuration === undefined) { this.debugLog(`${this.constructor.name}: ${this.accessory.displayName} RemainingDuration: ${remainingDuration}`); } else { this.zoneValve.service.updateCharacteristic(this.hap.Characteristic.RemainingDuration, remainingDuration); this.debugLog(`${this.constructor.name}: ${this.accessory.displayName} updateCharacteristic RemainingDuration: ${remainingDuration}`); } if (this.irrigationContext.duration[this.zoneId] === undefined) { this.debugLog(`${this.constructor.name}: ${this.accessory.displayName} SetDuration: ${this.irrigationContext.duration[this.zoneId]}`); } else { this.zoneValve.service.updateCharacteristic(this.hap.Characteristic.SetDuration, this.irrigationContext.duration[this.zoneId]); this.debugLog(`${this.constructor.name}: ${this.accessory.displayName} updateCharacteristic SetDuration: ${this.irrigationContext.duration[this.zoneId]}`); } } } //# sourceMappingURL=ZoneValve.js.map