mirror of
https://github.com/Hypfer/Valetudo.git
synced 2025-10-26 11:27:27 +00:00
feat(vendor.midea): Everything carpet
This commit is contained in:
parent
5715fb02f2
commit
f94f3c1101
@ -58,6 +58,7 @@ CarpetSensorModeControlCapability.MODE = Object.freeze({
|
||||
AVOID: "avoid",
|
||||
LIFT: "lift",
|
||||
DETACH: "detach",
|
||||
CROSS: "cross",
|
||||
});
|
||||
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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({
|
||||
|
||||
34
backend/lib/msmart/dtos/MSmartCarpetBehaviorSettingsDTO.js
Normal file
34
backend/lib/msmart/dtos/MSmartCarpetBehaviorSettingsDTO.js
Normal 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;
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
module.exports = {
|
||||
MSmartActiveZonesDTO: require("./MSmartActiveZonesDTO"),
|
||||
MSmartCarpetBehaviorSettingsDTO: require("./MSmartCarpetBehaviorSettingsDTO"),
|
||||
MSmartCleaningSettings1DTO: require("./MSmartCleaningSettings1DTO"),
|
||||
MSmartDTO: require("./MSmartDTO"),
|
||||
MSmartDndConfigurationDTO: require("./MSmartDNDConfigurationDTO"),
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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),
|
||||
]
|
||||
}));
|
||||
|
||||
|
||||
@ -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;
|
||||
@ -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;
|
||||
@ -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"),
|
||||
|
||||
@ -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"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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/>}
|
||||
/>
|
||||
);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user