homebridge-xiaomi-roborock-vacuum
Version:
Xiaomi Vacuum Cleaner - 1st (Mi Robot), 2nd (Roborock S50 + S55), 3rd Generation (Roborock S6) and S5 Max - plugin for Homebridge.
140 lines • 6.83 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.WaterBoxService = void 0;
const rxjs_1 = require("rxjs");
const find_speed_modes_1 = require("../utils/find_speed_modes");
const plugin_service_class_1 = require("./plugin_service_class");
const ensure_name_1 = require("../utils/ensure_name");
class WaterBoxService extends plugin_service_class_1.PluginServiceClass {
productInfo;
mainService;
service;
constructor(coreContext, productInfo, mainService) {
super(coreContext);
this.productInfo = productInfo;
this.mainService = mainService;
const name = `${this.config.name} Water Box`;
this.service = new this.hap.Service.Fan(name, "Water Box");
(0, ensure_name_1.ensureName)(this.hap, this.service, name);
this.service
.getCharacteristic(this.hap.Characteristic.RotationSpeed)
.onGet(() => this.getWaterSpeed())
.onSet((newState) => this.setWaterSpeed(newState));
// We need to handle the ON/OFF characteristic (https://github.com/homebridge-xiaomi-roborock-vacuum/homebridge-xiaomi-roborock-vacuum/issues/284)
this.service
.getCharacteristic(this.hap.Characteristic.On)
.onGet(async () => (await this.getWaterSpeed()) > 0)
.onSet(async (newState) => {
// Set to 0% (Off) when receiving an OFF request, do nothing otherwise.
if (!newState) {
await this.setWaterSpeed(0);
}
});
}
async init() {
this.deviceManager.stateChanged$
.pipe((0, rxjs_1.filter)(({ key }) => key === "cleaning"), (0, rxjs_1.distinct)(({ value }) => value))
.subscribe(({ value: isCleaning }) => {
this.service
.getCharacteristic(this.hap.Characteristic.On)
.updateValue(isCleaning);
});
this.deviceManager.stateChanged$
.pipe((0, rxjs_1.filter)(({ key }) => key === "water_box_mode"), (0, rxjs_1.distinct)(({ value }) => value))
.subscribe(({ value: speed }) => {
this.log.info(`MON changedWaterSpeed | WaterBoxMode is now ${speed}%`);
const speedMode = this.findWaterSpeedModeFromMiio(speed);
if (typeof speedMode === "undefined") {
this.log.warn(`WAR changedWaterSpeed | Speed was changed to ${speed}%, this speed is not supported`);
}
else {
const { homekitTopLevel, name } = speedMode;
this.log.info(`changedWaterSpeed | Speed was changed to ${speed}% (${name}), for HomeKit ${homekitTopLevel}%`);
this.service
.getCharacteristic(this.hap.Characteristic.RotationSpeed)
.updateValue(homekitTopLevel);
this.service
.getCharacteristic(this.hap.Characteristic.On)
.updateValue(homekitTopLevel > 0);
}
});
}
get services() {
return [this.service];
}
async setWaterSpeed(speed) {
await this.deviceManager.ensureDevice("setWaterSpeed");
if (typeof speed === "number") {
this.log.debug(`ACT setWaterSpeed | Speed got ${speed}% over HomeKit > CLEANUP.`);
}
// Get the speed modes for this model
const speedModes = (0, find_speed_modes_1.findSpeedModes)(this.deviceManager.model, this.productInfo.firmware)
.waterspeed || [];
// If the robot does not support water-mode cleaning
if (speedModes.length === 0) {
this.log.info(`setWaterSpeed | Model does not support the water mode`);
return;
}
let miLevel = null;
let name = null;
if (typeof speed === "number") {
// Speed set by number
// gen1 has maximum of 91%, so anything over that won't work. Getting safety maximum.
const safeSpeed = Math.min(speed, speedModes[speedModes.length - 1].homekitTopLevel);
// Find the minimum homekitTopLevel that matches the desired speed
const speedMode = speedModes.find((mode) => safeSpeed <= mode.homekitTopLevel);
miLevel = speedMode.miLevel;
name = speedMode.name;
}
else {
// Set by mode name
const speedMode = speedModes.find((mode) => mode.name === speed);
if (speedMode == null) {
this.log.info(`setWaterSpeed | Mode "${speed}" does not exist.`);
return;
}
miLevel = speedMode.miLevel;
name = speedMode.name;
}
this.log.info(`ACT setWaterSpeed | WaterBoxMode set to ${miLevel} over miIO for "${name}".`);
// Save the latest set speed for handling the "custom" speed later
this.mainService.cachedState.set("WaterSpeed", miLevel);
this.mainService.cachedState.set("WaterSpeedName", name);
await this.deviceManager.device.setWaterBoxMode(miLevel);
// If speed is "custom", also set the water speed to "custom" (for Xiaomi App)
if (name === "Custom" &&
this.mainService.cachedState.get("FanSpeedName") !== "Custom") {
await this.mainService.setSpeed("Custom");
}
// If speed is not "custom" remove set the water speed also to a fixed value (for Xiaomi App)
else if (name !== "Custom" &&
this.mainService.cachedState.get("FanSpeedName") === "Custom") {
await this.mainService.setSpeed("Balanced");
}
}
async getWaterSpeed() {
await this.deviceManager.ensureDevice("getWaterSpeed");
const speed = await this.deviceManager.device.getWaterBoxMode();
this.log.info(`getWaterSpeed | WaterBoxMode is ${speed} over miIO. Converting to HomeKit`);
const waterSpeed = this.findWaterSpeedModeFromMiio(speed);
let homekitValue = 0;
if (waterSpeed) {
const { homekitTopLevel, name } = waterSpeed;
this.log.info(`getWaterSpeed | WaterBoxMode is ${speed} over miIO "${name}" > HomeKit speed ${homekitTopLevel}%`);
homekitValue = homekitTopLevel || 0;
}
this.service
.getCharacteristic(this.hap.Characteristic.On)
.updateValue(homekitValue > 0);
return homekitValue;
}
findWaterSpeedModeFromMiio(speed) {
// Get the speed modes for this model
const speedModes = (0, find_speed_modes_1.findSpeedModes)(this.deviceManager.model, this.productInfo.firmware)
.waterspeed || [];
// Find speed mode that matches the miLevel
return speedModes.find((mode) => mode.miLevel === speed);
}
}
exports.WaterBoxService = WaterBoxService;
//# sourceMappingURL=water_box_service.js.map