feat(vendor.midea): Everything carpet

This commit is contained in:
Sören Beye 2025-09-07 14:21:35 +02:00
parent 5715fb02f2
commit f94f3c1101
14 changed files with 464 additions and 8 deletions

View File

@ -58,6 +58,7 @@ CarpetSensorModeControlCapability.MODE = Object.freeze({
AVOID: "avoid",
LIFT: "lift",
DETACH: "detach",
CROSS: "cross",
});

View File

@ -79,6 +79,11 @@ class BEightParser {
return new dtos.MSmartCleaningSettings1DTO(data);
}
case MSmartConst.ACTION.GET_CARPET_BEHAVIOR_SETTINGS: {
const data = BEightParser._parse_carpet_behavior_settings_payload(payload);
return new dtos.MSmartCarpetBehaviorSettingsDTO(data);
}
default: {
Logger.warn(
`Unhandled ACTION packet with typeId '${payload[2]}'`,
@ -316,6 +321,7 @@ class BEightParser {
data.adb_switch = !!(generalSwitchBits8 & 0b00000001);
data.station_v2_switch = !!(generalSwitchBits8 & 0b00000010);
data.static_stain_recognition_switch = !!(generalSwitchBits8 & 0b00000100);
data.stairless_mode_switch = !!(generalSwitchBits8 & 0b00001000);
}
@ -395,6 +401,25 @@ class BEightParser {
return data;
}
/**
* @private
* @param {Buffer} payload
* @returns {object}
*/
static _parse_carpet_behavior_settings_payload(payload) {
const data = {};
data.carpet_behavior = payload[3];
data.parameter_bitfield = payload[4];
data.clean_carpet_first = !!(data.parameter_bitfield & dtos.MSmartCarpetBehaviorSettingsDTO.PARAMETER_BIT.CLEAN_CARPET_FIRST);
data.deep_carpet_cleaning = !!(data.parameter_bitfield & dtos.MSmartCarpetBehaviorSettingsDTO.PARAMETER_BIT.DEEP_CARPET_CLEANING);
data.carpet_suction_boost = !!(data.parameter_bitfield & dtos.MSmartCarpetBehaviorSettingsDTO.PARAMETER_BIT.CARPET_SUCTION_BOOST);
data.enhanced_carpet_avoidance = !!(data.parameter_bitfield & dtos.MSmartCarpetBehaviorSettingsDTO.PARAMETER_BIT.ENHANCED_CARPET_AVOIDANCE);
return data;
}
}
module.exports = BEightParser;

View File

@ -15,6 +15,8 @@ const SETTING = Object.freeze({
SET_DOCK_INTERVALS: 0x56,
SET_OPERATION_MODE: 0x58,
TRIGGER_STATION_ACTION: 0x5A,
SET_CARPET_BEHAVIOR_SETTINGS: 0x5E,
SET_STAIRLESS_MODE: 0x63,
SET_DND: 0x92,
SET_VOLUME: 0x93,
SET_VARIOUS_TOGGLES: 0x9C,
@ -29,8 +31,10 @@ const ACTION = Object.freeze({
GET_DOCK_POSITION: 0x24,
GET_ACTIVE_ZONES: 0x27,
LOCATE: 0x57,
// 0x59 seems to maybe provide a bunch of feature bits? Reporting capabilities of the robot
GET_DND: 0x90,
GET_CLEANING_SETTINGS_1: 0xAA, // FIXME: naming
GET_CARPET_BEHAVIOR_SETTINGS: 0xAB
});
const EVENT = Object.freeze({

View File

@ -0,0 +1,34 @@
const MSmartDTO = require("./MSmartDTO");
class MSmartCarpetBehaviorSettingsDTO extends MSmartDTO {
/**
* @param {object} data
* @param {number} data.carpet_behavior 0 = avoid, 1 = ignore, 2 = adapt, 3 = cross
* @param {number} data.parameter_bitfield The raw bitfield byte for carpet sub-settings
* @param {boolean} data.clean_carpet_first
* @param {boolean} data.deep_carpet_cleaning
* @param {boolean} data.carpet_suction_boost
* @param {boolean} data.enhanced_carpet_avoidance
*/
constructor(data) {
super();
this.carpet_behavior = data.carpet_behavior;
this.parameter_bitfield = data.parameter_bitfield;
this.clean_carpet_first = data.clean_carpet_first;
this.deep_carpet_cleaning = data.deep_carpet_cleaning;
this.carpet_suction_boost = data.carpet_suction_boost;
this.enhanced_carpet_avoidance = data.enhanced_carpet_avoidance;
Object.freeze(this);
}
}
MSmartCarpetBehaviorSettingsDTO.PARAMETER_BIT = Object.freeze({
CLEAN_CARPET_FIRST: 0b0001,
DEEP_CARPET_CLEANING: 0b0010,
CARPET_SUCTION_BOOST: 0b0100,
ENHANCED_CARPET_AVOIDANCE: 0b1000
});
module.exports = MSmartCarpetBehaviorSettingsDTO;

View File

@ -97,6 +97,7 @@ class MSmartStatusDTO extends MSmartDTO {
* @param {boolean} [data.adb_switch]
* @param {boolean} [data.station_v2_switch]
* @param {boolean} [data.static_stain_recognition_switch]
* @param {boolean} [data.stairless_mode_switch]
*/
constructor(data) {
super();
@ -195,6 +196,7 @@ class MSmartStatusDTO extends MSmartDTO {
this.adb_switch = data.adb_switch;
this.station_v2_switch = data.station_v2_switch;
this.static_stain_recognition_switch = data.static_stain_recognition_switch;
this.stairless_mode_switch = data.stairless_mode_switch;
Object.freeze(this);
}

View File

@ -1,5 +1,6 @@
module.exports = {
MSmartActiveZonesDTO: require("./MSmartActiveZonesDTO"),
MSmartCarpetBehaviorSettingsDTO: require("./MSmartCarpetBehaviorSettingsDTO"),
MSmartCleaningSettings1DTO: require("./MSmartCleaningSettings1DTO"),
MSmartDTO: require("./MSmartDTO"),
MSmartDndConfigurationDTO: require("./MSmartDNDConfigurationDTO"),

View File

@ -1,7 +1,9 @@
const BEightParser = require("../../msmart/BEightParser");
const MSmartCarpetBehaviorSettingsDTO = require("../../msmart/dtos/MSmartCarpetBehaviorSettingsDTO");
const MSmartCleaningSettings1DTO = require("../../msmart/dtos/MSmartCleaningSettings1DTO");
const MSmartConst = require("../../msmart/MSmartConst");
const MSmartPacket = require("../../msmart/MSmartPacket");
const MSmartStatusDTO = require("../../msmart/dtos/MSmartStatusDTO");
const Quirk = require("../../core/Quirk");
class MideaQuirkFactory {
@ -182,7 +184,7 @@ class MideaQuirkFactory {
case MideaQuirkFactory.KNOWN_QUIRKS.QUIET_AUTO_EMPTY:
return new Quirk({
id: id,
title: "Quiet Auto Empty",
title: "Quiet Auto-Empty",
description: "Reduces the noise level during the auto-empty process. Will also make it less effective.",
options: ["normal", "quiet"],
getter: async () => {
@ -233,6 +235,195 @@ class MideaQuirkFactory {
await this.robot.sendCommand(packet.toHexString());
}
});
case MideaQuirkFactory.KNOWN_QUIRKS.CLIFF_SENSORS:
return new Quirk({
id: id,
title: "Cliff Sensors",
description: "! DANGEROUS ! - This allows you to disable the cliff sensors. The robot WILL fall down stairs and possibly destroy itself if you do so.",
options: ["on", "off"],
getter: async () => {
const response = await this.robot.sendCommand(new MSmartPacket({
messageType: MSmartPacket.MESSAGE_TYPE.ACTION,
payload: MSmartPacket.buildPayload(MSmartConst.ACTION.GET_STATUS)
}).toHexString());
const parsedResponse = BEightParser.PARSE(response);
if (parsedResponse instanceof MSmartStatusDTO) {
return parsedResponse.stairless_mode_switch ? "off" : "on";
} else {
throw new Error("Invalid response from robot");
}
},
setter: async (value) => {
let val;
switch (value) {
case "off":
val = 1;
break;
case "on":
val = 0;
break;
default:
throw new Error("Invalid value");
}
await this.robot.sendCommand(new MSmartPacket({
messageType: MSmartPacket.MESSAGE_TYPE.SETTING,
payload: MSmartPacket.buildPayload(
MSmartConst.SETTING.SET_STAIRLESS_MODE,
Buffer.from([val])
)
}).toHexString());
}
});
case MideaQuirkFactory.KNOWN_QUIRKS.CARPET_FIRST:
return new Quirk({
id: id,
title: "Carpet First",
description: "When enabled, the robot will first clean all carpet areas before then continuing with the rest of the cleanup.",
options: ["off", "on"],
getter: async () => {
const response = await this.robot.sendCommand(new MSmartPacket({
messageType: MSmartPacket.MESSAGE_TYPE.ACTION,
payload: MSmartPacket.buildPayload(MSmartConst.ACTION.GET_CARPET_BEHAVIOR_SETTINGS)
}).toHexString());
const parsedResponse = BEightParser.PARSE(response);
if (parsedResponse instanceof MSmartCarpetBehaviorSettingsDTO) {
return parsedResponse.clean_carpet_first ? "on" : "off";
} else {
throw new Error("Invalid response from robot");
}
},
setter: async (value) => {
const response = await this.robot.sendCommand(new MSmartPacket({
messageType: MSmartPacket.MESSAGE_TYPE.ACTION,
payload: MSmartPacket.buildPayload(MSmartConst.ACTION.GET_CARPET_BEHAVIOR_SETTINGS)
}).toHexString());
const parsedResponse = BEightParser.PARSE(response);
if (!(parsedResponse instanceof MSmartCarpetBehaviorSettingsDTO)) {
throw new Error("Invalid response from robot");
}
let newParameterBitfield = parsedResponse.parameter_bitfield;
if (value === "on") {
newParameterBitfield = newParameterBitfield | MSmartCarpetBehaviorSettingsDTO.PARAMETER_BIT.CLEAN_CARPET_FIRST;
} else {
newParameterBitfield = newParameterBitfield & ~MSmartCarpetBehaviorSettingsDTO.PARAMETER_BIT.CLEAN_CARPET_FIRST;
}
await this.robot.sendCommand(new MSmartPacket({
messageType: MSmartPacket.MESSAGE_TYPE.SETTING,
payload: MSmartPacket.buildPayload(
MSmartConst.SETTING.SET_CARPET_BEHAVIOR_SETTINGS,
Buffer.from([
parsedResponse.carpet_behavior,
newParameterBitfield
])
)
}).toHexString());
}
});
case MideaQuirkFactory.KNOWN_QUIRKS.DEEP_CARPET_CLEANING:
return new Quirk({
id: id,
title: "Deep Carpet Cleaning",
description: "When enabled, the robot will automatically slowly clean detected carpets with twice the cleanup passes in alternating directions.",
options: ["off", "on"],
getter: async () => {
const response = await this.robot.sendCommand(new MSmartPacket({
messageType: MSmartPacket.MESSAGE_TYPE.ACTION,
payload: MSmartPacket.buildPayload(MSmartConst.ACTION.GET_CARPET_BEHAVIOR_SETTINGS)
}).toHexString());
const parsedResponse = BEightParser.PARSE(response);
if (parsedResponse instanceof MSmartCarpetBehaviorSettingsDTO) {
return parsedResponse.deep_carpet_cleaning ? "on" : "off";
} else {
throw new Error("Invalid response from robot");
}
},
setter: async (value) => {
const response = await this.robot.sendCommand(new MSmartPacket({
messageType: MSmartPacket.MESSAGE_TYPE.ACTION,
payload: MSmartPacket.buildPayload(MSmartConst.ACTION.GET_CARPET_BEHAVIOR_SETTINGS)
}).toHexString());
const parsedResponse = BEightParser.PARSE(response);
if (!(parsedResponse instanceof MSmartCarpetBehaviorSettingsDTO)) {
throw new Error("Invalid response from robot");
}
let newParameterBitfield = parsedResponse.parameter_bitfield;
if (value === "on") {
newParameterBitfield = newParameterBitfield | MSmartCarpetBehaviorSettingsDTO.PARAMETER_BIT.DEEP_CARPET_CLEANING;
} else {
newParameterBitfield = newParameterBitfield & ~MSmartCarpetBehaviorSettingsDTO.PARAMETER_BIT.DEEP_CARPET_CLEANING;
}
await this.robot.sendCommand(new MSmartPacket({
messageType: MSmartPacket.MESSAGE_TYPE.SETTING,
payload: MSmartPacket.buildPayload(
MSmartConst.SETTING.SET_CARPET_BEHAVIOR_SETTINGS,
Buffer.from([
parsedResponse.carpet_behavior,
newParameterBitfield
])
)
}).toHexString());
}
});
case MideaQuirkFactory.KNOWN_QUIRKS.INCREASED_CARPET_AVOIDANCE:
return new Quirk({
id: id,
title: "Increased Carpet Avoidance",
description: "When enabled, when avoiding carpets, the robot will stay further away from them.",
options: ["off", "on"],
getter: async () => {
const response = await this.robot.sendCommand(new MSmartPacket({
messageType: MSmartPacket.MESSAGE_TYPE.ACTION,
payload: MSmartPacket.buildPayload(MSmartConst.ACTION.GET_CARPET_BEHAVIOR_SETTINGS)
}).toHexString());
const parsedResponse = BEightParser.PARSE(response);
if (parsedResponse instanceof MSmartCarpetBehaviorSettingsDTO) {
return parsedResponse.enhanced_carpet_avoidance ? "on" : "off";
} else {
throw new Error("Invalid response from robot");
}
},
setter: async (value) => {
const response = await this.robot.sendCommand(new MSmartPacket({
messageType: MSmartPacket.MESSAGE_TYPE.ACTION,
payload: MSmartPacket.buildPayload(MSmartConst.ACTION.GET_CARPET_BEHAVIOR_SETTINGS)
}).toHexString());
const parsedResponse = BEightParser.PARSE(response);
if (!(parsedResponse instanceof MSmartCarpetBehaviorSettingsDTO)) {
throw new Error("Invalid response from robot");
}
let newParameterBitfield = parsedResponse.parameter_bitfield;
if (value === "on") {
newParameterBitfield = newParameterBitfield | MSmartCarpetBehaviorSettingsDTO.PARAMETER_BIT.ENHANCED_CARPET_AVOIDANCE;
} else {
newParameterBitfield = newParameterBitfield & ~MSmartCarpetBehaviorSettingsDTO.PARAMETER_BIT.ENHANCED_CARPET_AVOIDANCE;
}
await this.robot.sendCommand(new MSmartPacket({
messageType: MSmartPacket.MESSAGE_TYPE.SETTING,
payload: MSmartPacket.buildPayload(
MSmartConst.SETTING.SET_CARPET_BEHAVIOR_SETTINGS,
Buffer.from([
parsedResponse.carpet_behavior,
newParameterBitfield
])
)
}).toHexString());
}
});
default:
throw new Error(`There's no quirk with id ${id}`);
}
@ -244,6 +435,10 @@ MideaQuirkFactory.KNOWN_QUIRKS = {
HAIR_CUTTING_ONE_TIME_TURBO: "224b6a0a-1a51-48d7-9d4d-61645399d368",
AI_OBSTACLE_CLASSIFICATION: "75af01c4-5c24-4cb3-9619-41b46b6ce333",
QUIET_AUTO_EMPTY: "96a98473-d60c-4ed9-8ef4-b71f023085a0",
CLIFF_SENSORS: "ef7a7a7f-370b-485d-80fb-704206a9b354",
CARPET_FIRST: "4b100fec-08d5-4227-9edf-eb0198d6ea20",
DEEP_CARPET_CLEANING: "d2ad3f99-c1b0-4195-9a98-4f13bdb0f1e8",
INCREASED_CARPET_AVOIDANCE: "f3ff1c65-9fe7-4312-b196-83ce91107fe8",
};
module.exports = MideaQuirkFactory;

View File

@ -146,6 +146,8 @@ class MideaValetudoRobot extends ValetudoRobot {
capabilities.MideaObstacleAvoidanceControlCapability,
capabilities.MideaAutoEmptyDockAutoEmptyIntervalControlCapability,
capabilities.MideaMopDockMopWashTemperatureControlCapability,
capabilities.MideaCarpetModeControlCapability,
capabilities.MideaCarpetSensorModeControlCapability,
].forEach(capability => {
this.registerCapability(new capability({robot: this}));
});
@ -166,6 +168,10 @@ class MideaValetudoRobot extends ValetudoRobot {
quirkFactory.getQuirk(MideaQuirkFactory.KNOWN_QUIRKS.HAIR_CUTTING_ONE_TIME_TURBO),
quirkFactory.getQuirk(MideaQuirkFactory.KNOWN_QUIRKS.AI_OBSTACLE_CLASSIFICATION),
quirkFactory.getQuirk(MideaQuirkFactory.KNOWN_QUIRKS.QUIET_AUTO_EMPTY),
quirkFactory.getQuirk(MideaQuirkFactory.KNOWN_QUIRKS.CLIFF_SENSORS),
quirkFactory.getQuirk(MideaQuirkFactory.KNOWN_QUIRKS.CARPET_FIRST),
quirkFactory.getQuirk(MideaQuirkFactory.KNOWN_QUIRKS.DEEP_CARPET_CLEANING),
quirkFactory.getQuirk(MideaQuirkFactory.KNOWN_QUIRKS.INCREASED_CARPET_AVOIDANCE),
]
}));

View File

@ -0,0 +1,84 @@
const BEightParser = require("../../../msmart/BEightParser");
const CarpetModeControlCapability = require("../../../core/capabilities/CarpetModeControlCapability");
const MSmartCarpetBehaviorSettingsDTO = require("../../../msmart/dtos/MSmartCarpetBehaviorSettingsDTO");
const MSmartConst = require("../../../msmart/MSmartConst");
const MSmartPacket = require("../../../msmart/MSmartPacket");
/**
* @extends CarpetModeControlCapability<import("../MideaValetudoRobot")>
*/
class MideaCarpetModeControlCapability extends CarpetModeControlCapability {
/**
* @private
* @returns {Promise<MSmartCarpetBehaviorSettingsDTO>}
*/
async _getSettings() {
const packet = new MSmartPacket({
messageType: MSmartPacket.MESSAGE_TYPE.ACTION,
payload: MSmartPacket.buildPayload(MSmartConst.ACTION.GET_CARPET_BEHAVIOR_SETTINGS)
});
const response = await this.robot.sendCommand(packet.toHexString());
const parsedResponse = BEightParser.PARSE(response);
if (parsedResponse instanceof MSmartCarpetBehaviorSettingsDTO) {
return parsedResponse;
} else {
throw new Error("Invalid response from robot");
}
}
/**
* @returns {Promise<boolean>}
*/
async isEnabled() {
const settings = await this._getSettings();
return settings.carpet_suction_boost;
}
/**
* @returns {Promise<void>}
*/
async enable() {
const currentSettings = await this._getSettings();
const newParameterBitfield = currentSettings.parameter_bitfield | MSmartCarpetBehaviorSettingsDTO.PARAMETER_BIT.CARPET_SUCTION_BOOST;
const packet = new MSmartPacket({
messageType: MSmartPacket.MESSAGE_TYPE.SETTING,
payload: MSmartPacket.buildPayload(
MSmartConst.SETTING.SET_CARPET_BEHAVIOR_SETTINGS,
Buffer.from([
currentSettings.carpet_behavior,
newParameterBitfield
])
)
});
await this.robot.sendCommand(packet.toHexString());
}
/**
* @returns {Promise<void>}
*/
async disable() {
const currentSettings = await this._getSettings();
const newParameterBitfield = currentSettings.parameter_bitfield & ~MSmartCarpetBehaviorSettingsDTO.PARAMETER_BIT.CARPET_SUCTION_BOOST;
const packet = new MSmartPacket({
messageType: MSmartPacket.MESSAGE_TYPE.SETTING,
payload: MSmartPacket.buildPayload(
MSmartConst.SETTING.SET_CARPET_BEHAVIOR_SETTINGS,
Buffer.from([
currentSettings.carpet_behavior,
newParameterBitfield
])
)
});
await this.robot.sendCommand(packet.toHexString());
}
}
module.exports = MideaCarpetModeControlCapability;

View File

@ -0,0 +1,95 @@
const BEightParser = require("../../../msmart/BEightParser");
const CarpetSensorModeControlCapability = require("../../../core/capabilities/CarpetSensorModeControlCapability");
const MSmartCarpetBehaviorSettingsDTO = require("../../../msmart/dtos/MSmartCarpetBehaviorSettingsDTO");
const MSmartConst = require("../../../msmart/MSmartConst");
const MSmartPacket = require("../../../msmart/MSmartPacket");
/**
* @extends CarpetSensorModeControlCapability<import("../MideaValetudoRobot")>
*/
class MideaCarpetSensorModeControlCapability extends CarpetSensorModeControlCapability {
/**
* @private
* @returns {Promise<MSmartCarpetBehaviorSettingsDTO>}
*/
async _getSettings() {
const packet = new MSmartPacket({
messageType: MSmartPacket.MESSAGE_TYPE.ACTION,
payload: MSmartPacket.buildPayload(MSmartConst.ACTION.GET_CARPET_BEHAVIOR_SETTINGS)
});
const response = await this.robot.sendCommand(packet.toHexString());
const parsedResponse = BEightParser.PARSE(response);
if (parsedResponse instanceof MSmartCarpetBehaviorSettingsDTO) {
return parsedResponse;
} else {
throw new Error("Invalid response from robot");
}
}
async getMode() {
const settings = await this._getSettings();
switch (settings.carpet_behavior) {
case 0:
return CarpetSensorModeControlCapability.MODE.AVOID;
case 1:
return CarpetSensorModeControlCapability.MODE.OFF;
case 2:
return CarpetSensorModeControlCapability.MODE.LIFT;
case 3:
return CarpetSensorModeControlCapability.MODE.CROSS;
default:
throw new Error(`Received invalid mode ${settings.carpet_behavior}`);
}
}
async setMode(newMode) {
const currentSettings = await this._getSettings();
let val;
switch (newMode) {
case CarpetSensorModeControlCapability.MODE.AVOID:
val = 0;
break;
case CarpetSensorModeControlCapability.MODE.OFF:
val = 1;
break;
case CarpetSensorModeControlCapability.MODE.LIFT:
val = 2;
break;
case CarpetSensorModeControlCapability.MODE.CROSS:
val = 3;
break;
default:
throw new Error(`Received invalid mode ${newMode}`);
}
const packet = new MSmartPacket({
messageType: MSmartPacket.MESSAGE_TYPE.SETTING,
payload: MSmartPacket.buildPayload(
MSmartConst.SETTING.SET_CARPET_BEHAVIOR_SETTINGS,
Buffer.from([
val,
currentSettings.parameter_bitfield
])
)
});
await this.robot.sendCommand(packet.toHexString());
}
getProperties() {
return {
supportedModes: [
CarpetSensorModeControlCapability.MODE.AVOID,
CarpetSensorModeControlCapability.MODE.OFF,
CarpetSensorModeControlCapability.MODE.LIFT,
CarpetSensorModeControlCapability.MODE.CROSS
]
};
}
}
module.exports = MideaCarpetSensorModeControlCapability;

View File

@ -3,6 +3,8 @@ module.exports = {
MideaAutoEmptyDockManualTriggerCapability: require("./MideaAutoEmptyDockManualTriggerCapability"),
MideaBasicControlCapability: require("./MideaBasicControlCapability"),
MideaCameraLightControlCapability: require("./MideaCameraLightControlCapability"),
MideaCarpetModeControlCapability: require("./MideaCarpetModeControlCapability"),
MideaCarpetSensorModeControlCapability: require("./MideaCarpetSensorModeControlCapability"),
MideaCollisionAvoidantNavigationControlCapability: require("./MideaCollisionAvoidantNavigationControlCapability"),
MideaCombinedVirtualRestrictionsCapability: require("./MideaCombinedVirtualRestrictionsCapability"),
MideaCurrentStatisticsCapability: require("./MideaCurrentStatisticsCapability"),

View File

@ -19,7 +19,8 @@
"off",
"avoid",
"lift",
"detach"
"detach",
"cross"
]
}
}
@ -46,7 +47,8 @@
"off",
"avoid",
"lift",
"detach"
"detach",
"cross"
]
}
}
@ -86,7 +88,8 @@
"off",
"avoid",
"lift",
"detach"
"detach",
"cross"
]
}
}

View File

@ -570,7 +570,7 @@ export interface ValetudoCustomizations {
friendlyName: string;
}
export type CarpetSensorMode = "off" | "avoid" | "lift" | "detach";
export type CarpetSensorMode = "off" | "avoid" | "lift" | "detach" | "cross";
export interface CarpetSensorModePayload {
mode: CarpetSensorMode

View File

@ -132,8 +132,9 @@ const CarpetModeControlCapabilitySwitchListMenuItem = () => {
const CarpetSensorModeControlCapabilitySelectListMenuItem = () => {
const SORT_ORDER = {
"off": 4,
"detach": 3,
"off": 5,
"detach": 4,
"cross" : 3,
"avoid": 2,
"lift": 1
};
@ -173,6 +174,9 @@ const CarpetSensorModeControlCapabilitySelectListMenuItem = () => {
case "detach":
label = "Detach Mop";
break;
case "cross":
label = "Cross Carpet";
break;
}
return {
@ -294,7 +298,7 @@ const AutoEmptyDockAutoEmptyIntervalControlCapabilitySelectListMenuItem = () =>
loadingOptions={autoEmptyDockAutoEmptyIntervalPropertiesPending || isPending}
loadError={autoEmptyDockAutoEmptyIntervalPropertiesError}
primaryLabel="Dock Auto-Empty"
secondaryLabel="Select if and how often the dock should auto-empty the robot."
secondaryLabel="Select if and/or how often the dock should auto-empty the robot."
icon={<AutoEmptyIntervalControlIcon/>}
/>
);