From 4e4b7ae2641fff08bb91197b704e4ebf977901c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=B6ren=20Beye?= Date: Tue, 20 Jun 2023 17:15:02 +0200 Subject: [PATCH] feat(vendor.dreame): L10 Ultra --- .../dreame/DreameL10UltraValetudoRobot.js | 258 ++++++++++++++++++ backend/lib/robots/dreame/index.js | 1 + 2 files changed, 259 insertions(+) create mode 100644 backend/lib/robots/dreame/DreameL10UltraValetudoRobot.js diff --git a/backend/lib/robots/dreame/DreameL10UltraValetudoRobot.js b/backend/lib/robots/dreame/DreameL10UltraValetudoRobot.js new file mode 100644 index 0000000000..1af3c45625 --- /dev/null +++ b/backend/lib/robots/dreame/DreameL10UltraValetudoRobot.js @@ -0,0 +1,258 @@ +const capabilities = require("./capabilities"); +const DreameGen2LidarValetudoRobot = require("./DreameGen2LidarValetudoRobot"); +const DreameGen2ValetudoRobot = require("./DreameGen2ValetudoRobot"); +const DreameQuirkFactory = require("./DreameQuirkFactory"); +const DreameValetudoRobot = require("./DreameValetudoRobot"); +const entities = require("../../entities"); +const fs = require("fs"); +const MiioValetudoRobot = require("../MiioValetudoRobot"); +const QuirksCapability = require("../../core/capabilities/QuirksCapability"); +const ValetudoSelectionPreset = require("../../entities/core/ValetudoSelectionPreset"); + +const stateAttrs = entities.state.attributes; + +class DreameL10UltraValetudoRobot extends DreameGen2LidarValetudoRobot { + + /** + * + * @param {object} options + * @param {import("../../Configuration")} options.config + * @param {import("../../ValetudoEventStore")} options.valetudoEventStore + */ + constructor(options) { + super( + Object.assign( + {}, + { + operationModes: Object.freeze({ + [stateAttrs.PresetSelectionStateAttribute.MODE.VACUUM_AND_MOP]: 0, + [stateAttrs.PresetSelectionStateAttribute.MODE.MOP]: 1, + [stateAttrs.PresetSelectionStateAttribute.MODE.VACUUM]: 2, + }) + }, + options, + ) + ); + + const QuirkFactory = new DreameQuirkFactory({ + robot: this + }); + + this.registerCapability(new capabilities.DreameCarpetModeControlCapability({ + robot: this, + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.SIID, + piid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.CARPET_MODE.PIID + })); + + this.registerCapability(new capabilities.DreameWaterUsageControlCapability({ + robot: this, + presets: Object.keys(DreameValetudoRobot.WATER_GRADES).map(k => { + return new ValetudoSelectionPreset({name: k, value: DreameValetudoRobot.WATER_GRADES[k]}); + }), + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.SIID, + piid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.WATER_USAGE.PIID + })); + + this.registerCapability(new capabilities.DreameZoneCleaningCapability({ + robot: this, + miot_actions: { + start: { + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.SIID, + aiid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.ACTIONS.START.AIID + } + }, + miot_properties: { + mode: { + piid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.MODE.PIID + }, + additionalCleanupParameters: { + piid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.ADDITIONAL_CLEANUP_PROPERTIES.PIID + } + }, + zoneCleaningModeId: 19, + maxZoneCount: 4 + })); + + this.registerCapability(new capabilities.DreameConsumableMonitoringCapability({ + robot: this, + miot_properties: { + main_brush: { + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.MAIN_BRUSH.SIID, + piid: DreameGen2ValetudoRobot.MIOT_SERVICES.MAIN_BRUSH.PROPERTIES.TIME_LEFT.PIID + }, + side_brush: { + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.SIDE_BRUSH.SIID, + piid: DreameGen2ValetudoRobot.MIOT_SERVICES.SIDE_BRUSH.PROPERTIES.TIME_LEFT.PIID + }, + filter: { + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.FILTER.SIID, + piid: DreameGen2ValetudoRobot.MIOT_SERVICES.FILTER.PROPERTIES.TIME_LEFT.PIID + }, + sensor: { + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.SENSOR.SIID, + piid: DreameGen2ValetudoRobot.MIOT_SERVICES.SENSOR.PROPERTIES.TIME_LEFT.PIID + }, + mop: { + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.MOP.SIID, + piid: DreameGen2ValetudoRobot.MIOT_SERVICES.MOP.PROPERTIES.TIME_LEFT.PIID + } + }, + miot_actions: { + reset_main_brush: { + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.MAIN_BRUSH.SIID, + aiid: DreameGen2ValetudoRobot.MIOT_SERVICES.MAIN_BRUSH.ACTIONS.RESET.AIID + }, + reset_side_brush: { + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.SIDE_BRUSH.SIID, + aiid: DreameGen2ValetudoRobot.MIOT_SERVICES.SIDE_BRUSH.ACTIONS.RESET.AIID + }, + reset_filter: { + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.FILTER.SIID, + aiid: DreameGen2ValetudoRobot.MIOT_SERVICES.FILTER.ACTIONS.RESET.AIID + }, + reset_sensor: { + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.SENSOR.SIID, + aiid: DreameGen2ValetudoRobot.MIOT_SERVICES.SENSOR.ACTIONS.RESET.AIID + }, + reset_mop: { + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.MOP.SIID, + aiid: DreameGen2ValetudoRobot.MIOT_SERVICES.MOP.ACTIONS.RESET.AIID + } + }, + })); + + this.registerCapability(new capabilities.DreameKeyLockCapability({ + robot: this, + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.SIID, + piid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.KEY_LOCK.PIID + })); + + this.registerCapability(new capabilities.DreameAutoEmptyDockAutoEmptyControlCapability({ + robot: this, + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.SIID, + piid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.PROPERTIES.AUTO_EMPTY_ENABLED.PIID + })); + + this.registerCapability(new capabilities.DreameAutoEmptyDockManualTriggerCapability({ + robot: this, + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.SIID, + aiid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.ACTIONS.EMPTY_DUSTBIN.AIID + })); + + this.registerCapability(new capabilities.DreameAICameraGoToLocationCapability({ + robot: this, + miot_actions: { + start: { + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.SIID, + aiid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.ACTIONS.START.AIID + } + }, + miot_properties: { + mode: { + piid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.MODE.PIID + }, + additionalCleanupParameters: { + piid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.ADDITIONAL_CLEANUP_PROPERTIES.PIID + } + }, + goToModeId: 23 + })); + + this.registerCapability(new capabilities.DreameMopDockCleanManualTriggerCapability({ + robot: this, + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.SIID, + aiid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.ACTIONS.MOP_DOCK_INTERACT.AIID, + + additionalCleanupParametersPiid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.ADDITIONAL_CLEANUP_PROPERTIES.PIID + })); + + this.registerCapability(new capabilities.DreameMopDockDryManualTriggerCapability({ + robot: this, + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.SIID, + aiid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.ACTIONS.MOP_DOCK_INTERACT.AIID, + + additionalCleanupParametersPiid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.ADDITIONAL_CLEANUP_PROPERTIES.PIID + })); + + this.registerCapability(new capabilities.DreameOperationModeControlCapability({ + robot: this, + presets: Object.keys(this.operationModes).map(k => { + return new ValetudoSelectionPreset({name: k, value: this.operationModes[k]}); + }), + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.SIID, + piid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.MOP_DOCK_SETTINGS.PIID + })); + + this.registerCapability(new QuirksCapability({ + robot: this, + quirks: [ + QuirkFactory.getQuirk(DreameQuirkFactory.KNOWN_QUIRKS.CARPET_MODE_SENSITIVITY), + QuirkFactory.getQuirk(DreameQuirkFactory.KNOWN_QUIRKS.TIGHT_MOP_PATTERN), + QuirkFactory.getQuirk(DreameQuirkFactory.KNOWN_QUIRKS.AUTO_EMPTY_INTERVAL), + QuirkFactory.getQuirk(DreameQuirkFactory.KNOWN_QUIRKS.OBSTACLE_AVOIDANCE), + QuirkFactory.getQuirk(DreameQuirkFactory.KNOWN_QUIRKS.CARPET_DETECTION_SENSOR), + QuirkFactory.getQuirk(DreameQuirkFactory.KNOWN_QUIRKS.MOP_LIFT_CARPET_BEHAVIOUR), + QuirkFactory.getQuirk(DreameQuirkFactory.KNOWN_QUIRKS.MOP_DOCK_MOP_CLEANING_FREQUENCY), + QuirkFactory.getQuirk(DreameQuirkFactory.KNOWN_QUIRKS.MOP_DRYING_TIME), + QuirkFactory.getQuirk(DreameQuirkFactory.KNOWN_QUIRKS.MOP_DOCK_WET_DRY_SWITCH), + QuirkFactory.getQuirk(DreameQuirkFactory.KNOWN_QUIRKS.MOP_DOCK_AUTO_REPAIR_TRIGGER), + ] + })); + + this.state.upsertFirstMatchingAttribute(new entities.state.attributes.DockStatusStateAttribute({ + value: entities.state.attributes.DockStatusStateAttribute.VALUE.IDLE + })); + + this.state.upsertFirstMatchingAttribute(new entities.state.attributes.AttachmentStateAttribute({ + type: entities.state.attributes.AttachmentStateAttribute.TYPE.MOP, + attached: false + })); + } + + getStatePropertiesToPoll() { + const superProps = super.getStatePropertiesToPoll(); + + return [ + ...superProps, + { + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.SIID, + piid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.MOP_DOCK_STATUS.PIID + }, + { + siid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.SIID, + piid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.MOP_DOCK_SETTINGS.PIID + } + ]; + } + + + getModelName() { + return "L10 Ultra"; + } + + getCloudSecretFromFS() { + return fs.readFileSync("/mnt/private/ULI/factory/key.txt"); + } + + getModelDetails() { + return Object.assign( + {}, + super.getModelDetails(), + { + supportedAttachments: [ + stateAttrs.AttachmentStateAttribute.TYPE.MOP, + ] + } + ); + } + + + static IMPLEMENTATION_AUTO_DETECTION_HANDLER() { + const deviceConf = MiioValetudoRobot.READ_DEVICE_CONF(DreameValetudoRobot.DEVICE_CONF_PATH); + + return !!(deviceConf && deviceConf.model === "dreame.vacuum.r2257o"); + } +} + + +module.exports = DreameL10UltraValetudoRobot; diff --git a/backend/lib/robots/dreame/index.js b/backend/lib/robots/dreame/index.js index 9f84d7a15c..de438f3d7f 100644 --- a/backend/lib/robots/dreame/index.js +++ b/backend/lib/robots/dreame/index.js @@ -10,6 +10,7 @@ module.exports = { "DreameL10ProValetudoRobot": require("./DreameL10ProValetudoRobot"), "DreameL10SProValetudoRobot": require("./DreameL10SProValetudoRobot"), "DreameL10SUltraValetudoRobot": require("./DreameL10SUltraValetudoRobot"), + "DreameL10UltraValetudoRobot": require("./DreameL10UltraValetudoRobot"), "DreameMovaZ500ValetudoRobot": require("./DreameMovaZ500ValetudoRobot"), "DreameP2148ValetudoRobot": require("./DreameP2148ValetudoRobot"), "DreameP2149ValetudoRobot": require("./DreameP2149ValetudoRobot"),