homebridge-resideo
Version:
The Resideo plugin allows you to access your Resideo device(s) from HomeKit.
300 lines • 16.3 kB
JavaScript
import { interval, Subject } from 'rxjs';
import { skipWhile, take } from 'rxjs/operators';
import { DeviceURL } from '../settings.js';
import { deviceBase } from './device.js';
/**
* Platform Accessory
* An instance of this class is created for each accessory your platform registers
* Each accessory may expose multiple services of different service types.
*/
export class LeakSensor extends deviceBase {
platform;
// Services
Battery;
LeakSensor;
HumiditySensor;
TemperatureSensor;
// Sensor Update
SensorUpdateInProgress;
doSensorUpdate;
constructor(platform, accessory, location, device) {
super(platform, accessory, location, device);
this.platform = platform;
// this is subject we use to track when we need to POST changes to the Resideo API
this.doSensorUpdate = new Subject();
this.SensorUpdateInProgress = false;
// Initialize Battery Service
accessory.context.Battery = accessory.context.Battery ?? {};
this.Battery = {
Name: accessory.context.Battery.Name ?? `${accessory.displayName} Battery`,
Service: accessory.getService(this.hap.Service.Battery) ?? accessory.addService(this.hap.Service.Battery),
BatteryLevel: accessory.context.BatteryLevel ?? 100,
ChargingState: accessory.context.ChargingState ?? this.hap.Characteristic.ChargingState.NOT_CHARGEABLE,
StatusLowBattery: accessory.context.StatusLowBattery ?? this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL,
};
accessory.context.Battery = this.Battery;
// set the service name, this is what is displayed as the default name on the Home app
this.Battery.Service
.setCharacteristic(this.hap.Characteristic.Name, this.Battery.Name)
.setCharacteristic(this.hap.Characteristic.ChargingState, this.hap.Characteristic.ChargingState.NOT_CHARGEABLE)
.getCharacteristic(this.hap.Characteristic.BatteryLevel)
.onGet(() => {
return this.Battery.BatteryLevel;
});
// Initialize Leak Sensor Service
if (device.leaksensor?.hide_leak) {
if (this.LeakSensor) {
this.debugLog(`${device.deviceClass} ${accessory.displayName} Removing Leak Sensor Service`);
this.LeakSensor.Service = accessory.getService(this.hap.Service.LeakSensor);
accessory.removeService(this.LeakSensor.Service);
}
else {
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Leak Sensor Service Not Found`);
}
}
else {
this.debugLog(`${device.deviceClass} ${accessory.displayName} Add Leak Sensor Service`);
accessory.context.LeakSensor = accessory.context.LeakSensor ?? {};
this.LeakSensor = {
Name: accessory.context.LeakSensor.Name ?? `${accessory.displayName} Leak Sensor`,
Service: accessory.getService(this.hap.Service.LeakSensor) ?? accessory.addService(this.hap.Service.LeakSensor),
StatusActive: accessory.context.StatusActive ?? false,
LeakDetected: accessory.context.LeakDetected ?? this.hap.Characteristic.LeakDetected.LEAK_NOT_DETECTED,
};
accessory.context.LeakSensor = this.LeakSensor;
// Initialize Leak Sensor Characteristic
this.LeakSensor.Service
.setCharacteristic(this.hap.Characteristic.Name, this.LeakSensor.Name)
.getCharacteristic(this.hap.Characteristic.StatusActive)
.onGet(() => {
return this.LeakSensor.StatusActive;
});
this.LeakSensor.Service
.getCharacteristic(this.hap.Characteristic.LeakDetected)
.onGet(() => {
return this.LeakSensor.LeakDetected;
});
}
// Initialize Temperature Sensor Service
if (device.leaksensor?.hide_temperature) {
if (this.TemperatureSensor) {
this.debugLog(`${device.deviceClass} ${accessory.displayName} Removing Temperature Sensor Service`);
this.TemperatureSensor.Service = accessory.getService(this.hap.Service.TemperatureSensor);
accessory.removeService(this.TemperatureSensor.Service);
}
else {
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Temperature Sensor Service Not Found`);
}
}
else {
this.debugLog(`${device.deviceClass} ${accessory.displayName} Add Temperature Sensor Service`);
accessory.context.TemperatureSensor = accessory.context.TemperatureSensor ?? {};
this.TemperatureSensor = {
Name: accessory.context.TemperatureSensor.Name ?? `${accessory.displayName} Temperature Sensor`,
Service: accessory.getService(this.hap.Service.TemperatureSensor) ?? accessory.addService(this.hap.Service.TemperatureSensor),
CurrentTemperature: accessory.context.CurrentTemperature ?? 20,
};
accessory.context.TemperatureSensor = this.TemperatureSensor;
// Initialize Temperature Sensor Characteristic
this.TemperatureSensor.Service
.setCharacteristic(this.hap.Characteristic.Name, this.TemperatureSensor.Name)
.getCharacteristic(this.hap.Characteristic.CurrentTemperature)
.setProps({
minValue: -273.15,
maxValue: 100,
minStep: 0.1,
})
.onGet(async () => {
return this.TemperatureSensor.CurrentTemperature;
});
}
// Initialize Humidity Sensor Service
if (device.leaksensor?.hide_humidity) {
if (this.HumiditySensor) {
this.debugLog(`${device.deviceClass} ${accessory.displayName} Removing Humidity Sensor Service`);
this.HumiditySensor.Service = accessory.getService(this.hap.Service.HumiditySensor);
accessory.removeService(this.HumiditySensor.Service);
}
else {
this.debugLog(`${this.device.deviceType}: ${accessory.displayName} Humidity Sensor Service Not Found`);
}
}
else if (device.indoorHumidity) {
this.debugLog(`${device.deviceClass} ${accessory.displayName} Add Humidity Sensor Service`);
accessory.context.HumiditySensor = accessory.context.HumiditySensor ?? {};
this.HumiditySensor = {
Name: accessory.context.HumiditySensor.Name ?? `${accessory.displayName} Humidity Sensor`,
Service: accessory.getService(this.hap.Service.HumiditySensor) ?? accessory.addService(this.hap.Service.HumiditySensor),
CurrentRelativeHumidity: accessory.context.CurrentRelativeHumidity ?? 50,
};
accessory.context.HumiditySensor = this.HumiditySensor;
// Initialize Humidity Sensor Characteristic
this.HumiditySensor.Service
.setCharacteristic(this.hap.Characteristic.Name, this.HumiditySensor.Name);
this.HumiditySensor.Service
.getCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity)
.setProps({
minStep: 0.1,
})
.onGet(() => {
return this.HumiditySensor.CurrentRelativeHumidity;
});
}
else {
this.debugLog(`${device.deviceClass} ${accessory.displayName} Humidity Sensor Service Not Added`);
}
// Intial Refresh
this.refreshStatus();
// Retrieve initial values and updateHomekit
this.updateHomeKitCharacteristics();
// Start an update interval
interval(this.deviceRefreshRate * 1000)
.pipe(skipWhile(() => this.SensorUpdateInProgress))
.subscribe(async () => {
await this.refreshStatus();
});
}
/**
* Parse the device status from the Resideo api
*/
async parseStatus() {
// Battery Service
this.Battery.BatteryLevel = Number(this.device.batteryRemaining);
this.Battery.Service.getCharacteristic(this.hap.Characteristic.BatteryLevel).updateValue(this.Battery.BatteryLevel);
if (this.device.batteryRemaining < 15) {
this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_LOW;
}
else {
this.Battery.StatusLowBattery = this.hap.Characteristic.StatusLowBattery.BATTERY_LEVEL_NORMAL;
}
this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}, StatusLowBattery: ${this.Battery.StatusLowBattery}`);
// LeakSensor Service
if (!this.device.leaksensor?.hide_leak) {
if (this.LeakSensor) {
// Active
this.LeakSensor.StatusActive = this.device.hasDeviceCheckedIn;
// LeakDetected
if (this.device.waterPresent === true) {
this.LeakSensor.LeakDetected = this.hap.Characteristic.LeakDetected.LEAK_DETECTED;
}
else {
this.LeakSensor.LeakDetected = this.hap.Characteristic.LeakDetected.LEAK_NOT_DETECTED;
}
this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} StatusActive: ${this.LeakSensor.StatusActive}, LeakDetected: ${this.LeakSensor.LeakDetected}`);
}
}
const currentSensorReadings = this.device.currentSensorReadings ?? { temperature: 20, humidity: 50 };
// Temperature Service
if (!this.device.leaksensor?.hide_temperature) {
if (this.TemperatureSensor) {
this.TemperatureSensor.CurrentTemperature = currentSensorReadings.temperature;
this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} CurrentTemperature: ${this.TemperatureSensor.CurrentTemperature}°`);
}
}
// Humidity Service
if (!this.device.leaksensor?.hide_humidity) {
if (this.HumiditySensor) {
this.HumiditySensor.CurrentRelativeHumidity = currentSensorReadings.humidity;
this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} CurrentRelativeHumidity: ${this.HumiditySensor.CurrentRelativeHumidity}%`);
}
}
}
/**
* Asks the Resideo Home API for the latest device information
*/
async refreshStatus() {
try {
const device = (await this.platform.axios.get(`${DeviceURL}/waterLeakDetectors/${this.device.deviceID}`, {
params: {
locationId: this.location.locationID,
},
})).data;
this.debugLog(`(refreshStatus) ${device.deviceClass} device: ${JSON.stringify(device)}`);
this.device = device;
await this.parseStatus();
await this.updateHomeKitCharacteristics();
}
catch (e) {
const action = 'refreshStatus';
if (this.device.retry) {
// Refresh the status from the API
interval(5000)
.pipe(skipWhile(() => this.SensorUpdateInProgress))
.pipe(take(1))
.subscribe(async () => {
await this.refreshStatus();
});
}
this.resideoAPIError(e, action);
this.apiError(e);
}
}
/**
* Updates the status for each of the HomeKit Characteristics
*/
async updateHomeKitCharacteristics() {
if (this.Battery.BatteryLevel === undefined) {
this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} BatteryLevel: ${this.Battery.BatteryLevel}`);
}
else {
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, this.Battery.BatteryLevel);
this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} updateCharacteristic BatteryLevel: ${this.Battery.BatteryLevel}`);
}
if (this.Battery.StatusLowBattery === undefined) {
this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} StatusLowBattery: ${this.Battery.StatusLowBattery}`);
}
else {
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, this.Battery.StatusLowBattery);
this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} updateCharacteristic StatusLowBattery: ${this.Battery.StatusLowBattery}`);
}
if (!this.device.leaksensor?.hide_leak) {
if (this.LeakSensor?.LeakDetected === undefined) {
this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} LeakDetected: ${this.LeakSensor?.LeakDetected}`);
}
else {
this.LeakSensor?.Service.updateCharacteristic(this.hap.Characteristic.LeakDetected, this.LeakSensor?.LeakDetected);
this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} updateCharacteristic LeakDetected: ${this.LeakSensor?.LeakDetected}`);
}
if (this.LeakSensor?.StatusActive === undefined) {
this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} StatusActive: ${this.LeakSensor?.StatusActive}`);
}
else {
this.LeakSensor.Service.updateCharacteristic(this.hap.Characteristic.StatusActive, this.LeakSensor?.StatusActive);
this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} updateCharacteristic StatusActive: ${this.LeakSensor?.StatusActive}`);
}
}
if (!this.device.leaksensor?.hide_temperature) {
if (this.TemperatureSensor?.CurrentTemperature === undefined) {
this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} CurrentTemperature: ${this.TemperatureSensor?.CurrentTemperature}`);
}
else {
this.TemperatureSensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentTemperature, this.TemperatureSensor?.CurrentTemperature);
this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} updateCharacteristic CurrentTemperature: ${this.TemperatureSensor.CurrentTemperature}`);
}
}
if (!this.device.leaksensor?.hide_humidity) {
if (this.HumiditySensor?.CurrentRelativeHumidity === undefined) {
this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} CurrentRelativeHumidity: ${this.HumiditySensor?.CurrentRelativeHumidity}`);
}
else {
this.HumiditySensor.Service.updateCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity, this.HumiditySensor?.CurrentRelativeHumidity);
this.debugLog(`${this.device.deviceClass} ${this.accessory.displayName} updateCharacteristic CurrentRelativeHumidity: ${this.HumiditySensor?.CurrentRelativeHumidity}`);
}
}
}
async apiError(e) {
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.BatteryLevel, e);
this.Battery.Service.updateCharacteristic(this.hap.Characteristic.StatusLowBattery, e);
if (!this.device.leaksensor?.hide_leak) {
this.LeakSensor?.Service.updateCharacteristic(this.hap.Characteristic.LeakDetected, e);
this.LeakSensor?.Service.updateCharacteristic(this.hap.Characteristic.StatusActive, e);
}
if (!this.device.leaksensor?.hide_temperature) {
this.TemperatureSensor?.Service.updateCharacteristic(this.hap.Characteristic.CurrentTemperature, e);
}
if (!this.device.leaksensor?.hide_humidity) {
this.HumiditySensor?.Service.updateCharacteristic(this.hap.Characteristic.CurrentRelativeHumidity, e);
}
}
}
//# sourceMappingURL=leaksensors.js.map