mirror of https://github.com/Hypfer/Valetudo.git
157 lines
7.5 KiB
JavaScript
157 lines
7.5 KiB
JavaScript
const CapabilityMqttHandle = require("./CapabilityMqttHandle");
|
|
|
|
const capabilities = require("../../core/capabilities");
|
|
const Commands = require("../common/Commands");
|
|
const ComponentType = require("../homeassistant/ComponentType");
|
|
const DataType = require("../homie/DataType");
|
|
const EntityCategory = require("../homeassistant/EntityCategory");
|
|
const HassAnchor = require("../homeassistant/HassAnchor");
|
|
const InLineHassComponent = require("../homeassistant/components/InLineHassComponent");
|
|
const Logger = require("../../Logger");
|
|
const PropertyMqttHandle = require("../handles/PropertyMqttHandle");
|
|
const stateAttrs = require("../../entities/state/attributes");
|
|
|
|
class PresetSelectionCapabilityMqttHandle extends CapabilityMqttHandle {
|
|
/**
|
|
* @param {object} options
|
|
* @param {import("../handles/RobotMqttHandle")} options.parent
|
|
* @param {import("../MqttController")} options.controller MqttController instance
|
|
* @param {import("../../core/ValetudoRobot")} options.robot
|
|
* @param {import("../../core/capabilities/PresetSelectionCapability")} options.capability
|
|
*/
|
|
constructor(options) {
|
|
super(Object.assign(options, {
|
|
friendlyName: CAPABILITIES_TO_FRIENDLY_NAME_MAPPING[options.capability.getType()] + " control"
|
|
}));
|
|
this.capability = options.capability;
|
|
|
|
this.registerChild(
|
|
new PropertyMqttHandle({
|
|
parent: this,
|
|
controller: this.controller,
|
|
topicName: "preset",
|
|
friendlyName: CAPABILITIES_TO_FRIENDLY_NAME_MAPPING[this.capability.getType()],
|
|
datatype: DataType.ENUM,
|
|
format: this.capability.getPresets().join(","),
|
|
setter: async (value) => {
|
|
if (Object.values(Commands.INC_DEC).includes(value)) {
|
|
const presets = this.capability.getPresets();
|
|
const attr = this.robot.state.getFirstMatchingAttribute(CAPABILITIES_TO_STATE_ATTR_MAPPING[this.capability.getType()]);
|
|
if (attr === null) {
|
|
return;
|
|
}
|
|
let valueIndex = presets.indexOf(attr.value);
|
|
if (valueIndex < 0 || valueIndex >= presets.length) {
|
|
return;
|
|
}
|
|
value = presets[valueIndex];
|
|
}
|
|
await this.capability.selectPreset(value);
|
|
},
|
|
getter: async () => {
|
|
const attr = this.robot.state.getFirstMatchingAttribute(CAPABILITIES_TO_STATE_ATTR_MAPPING[this.capability.getType()]);
|
|
if (attr === null) {
|
|
return null;
|
|
}
|
|
|
|
if (this.capability.getType() === capabilities.FanSpeedControlCapability.TYPE) {
|
|
await this.controller.hassAnchorProvider.getAnchor(
|
|
HassAnchor.ANCHOR.FAN_SPEED
|
|
).post(attr.value);
|
|
}
|
|
|
|
return attr.value;
|
|
},
|
|
helpText: "This handle allows setting the " +
|
|
CAPABILITIES_TO_FRIENDLY_NAME_MAPPING[this.capability.getType()].toLowerCase() + ". " +
|
|
"It accepts the preset payloads specified in `$format` or in the HAss json attributes.",
|
|
helpMayChange: {
|
|
"Enum payloads": "Different robot models have different " +
|
|
CAPABILITIES_TO_FRIENDLY_NAME_MAPPING[this.capability.getType()].toLowerCase() +
|
|
" presets. Always check `$format`/`json_attributes` during startup."
|
|
}
|
|
}).also((prop) => {
|
|
const capabilityType = this.capability.getType();
|
|
|
|
this.controller.withHass((hass) => {
|
|
prop.attachHomeAssistantComponent(
|
|
new InLineHassComponent({
|
|
hass: hass,
|
|
robot: this.robot,
|
|
name: capabilityType,
|
|
friendlyName: CAPABILITIES_TO_FRIENDLY_NAME_MAPPING[capabilityType],
|
|
componentType: ComponentType.SELECT,
|
|
autoconf: {
|
|
state_topic: prop.getBaseTopic(),
|
|
value_template: "{{ value }}",
|
|
command_topic: prop.getBaseTopic() + "/set",
|
|
options: this.capability.getPresets(),
|
|
icon: CAPABILITIES_TO_ICON_MAPPING[capabilityType],
|
|
entity_category: EntityCategory.CONFIG,
|
|
}
|
|
})
|
|
);
|
|
});
|
|
|
|
|
|
if (capabilityType === capabilities.FanSpeedControlCapability.TYPE) {
|
|
/*
|
|
Current versions of home assistant feature the fan speed as a drop-down that is part
|
|
of the vacuum entity. This is because the vacuum entity was designed based on the xiaomi
|
|
mi robot vacuum and thus can do everything that robot could do.
|
|
|
|
However, as time moved on, robots gained more capabilities, which makes this a bit odd as
|
|
we basically expose the same control twice
|
|
*/
|
|
|
|
// Sent as a topic reference since this is used for the autoconfig of the vacuum entity
|
|
this.controller.hassAnchorProvider.getTopicReference(
|
|
HassAnchor.REFERENCE.FAN_SPEED_PRESETS
|
|
).post(this.capability.getPresets()).catch(err => {
|
|
Logger.error("Error while posting value to HassAnchor", err);
|
|
});
|
|
|
|
this.controller.hassAnchorProvider.getTopicReference(
|
|
HassAnchor.REFERENCE.FAN_SPEED_SET
|
|
).post(prop.getBaseTopic() + "/set").catch(err => {
|
|
Logger.error("Error while posting value to HassAnchor", err);
|
|
});
|
|
}
|
|
})
|
|
);
|
|
}
|
|
|
|
getInterestingStatusAttributes() {
|
|
return [CAPABILITIES_TO_STATE_ATTR_MAPPING[this.capability.getType()]];
|
|
}
|
|
}
|
|
|
|
const CAPABILITIES_TO_FRIENDLY_NAME_MAPPING = {
|
|
[capabilities.FanSpeedControlCapability.TYPE]: "Fan",
|
|
[capabilities.WaterUsageControlCapability.TYPE]: "Water",
|
|
[capabilities.OperationModeControlCapability.TYPE]: "Mode",
|
|
};
|
|
|
|
const CAPABILITIES_TO_STATE_ATTR_MAPPING = {
|
|
[capabilities.FanSpeedControlCapability.TYPE]: {
|
|
attributeClass: stateAttrs.PresetSelectionStateAttribute.name,
|
|
attributeType: stateAttrs.PresetSelectionStateAttribute.TYPE.FAN_SPEED
|
|
},
|
|
[capabilities.WaterUsageControlCapability.TYPE]: {
|
|
attributeClass: stateAttrs.PresetSelectionStateAttribute.name,
|
|
attributeType: stateAttrs.PresetSelectionStateAttribute.TYPE.WATER_GRADE
|
|
},
|
|
[capabilities.OperationModeControlCapability.TYPE]: {
|
|
attributeClass: stateAttrs.PresetSelectionStateAttribute.name,
|
|
attributeType: stateAttrs.PresetSelectionStateAttribute.TYPE.OPERATION_MODE
|
|
},
|
|
};
|
|
|
|
const CAPABILITIES_TO_ICON_MAPPING = {
|
|
[capabilities.FanSpeedControlCapability.TYPE]: "mdi:fan",
|
|
[capabilities.WaterUsageControlCapability.TYPE]: "mdi:water-pump",
|
|
[capabilities.OperationModeControlCapability.TYPE]: "mdi:developer-board",
|
|
};
|
|
|
|
module.exports = PresetSelectionCapabilityMqttHandle;
|