fix(vendor.dreame): Track emptying state of auto empty dock

This commit is contained in:
Sören Beye 2025-08-31 15:04:37 +02:00
parent 30efa1afd9
commit 6f0fc2a453
17 changed files with 121 additions and 24 deletions

View File

@ -462,12 +462,14 @@ class Dreame1CValetudoRobot extends DreameValetudoRobot {
return;
}
data.forEach(elem => {
let statusNeedsUpdate = false;
for (const elem of data) {
switch (elem.siid) {
case MIOT_SERVICES.ERROR.SIID: {
this.errorCode = typeof elem.value === "number" ? elem.value.toString() : elem.value;
this.stateNeedsUpdate = true;
statusNeedsUpdate = true;
break;
}
case MIOT_SERVICES.VACUUM_2.SIID: {
@ -475,13 +477,13 @@ class Dreame1CValetudoRobot extends DreameValetudoRobot {
case MIOT_SERVICES.VACUUM_2.PROPERTIES.MODE.PIID: {
this.mode = elem.value;
this.stateNeedsUpdate = true;
statusNeedsUpdate = true;
break;
}
case MIOT_SERVICES.VACUUM_2.PROPERTIES.TASK_STATUS.PIID: {
this.taskStatus = elem.value;
this.stateNeedsUpdate = true;
statusNeedsUpdate = true;
break;
}
case MIOT_SERVICES.VACUUM_2.PROPERTIES.FAN_SPEED.PIID: {
@ -543,7 +545,7 @@ class Dreame1CValetudoRobot extends DreameValetudoRobot {
5 = Returning to Charger
*/
this.isCharging = elem.value === 4 || elem.value === 1;
this.stateNeedsUpdate = true;
statusNeedsUpdate = true;
break;
}
break;
@ -555,10 +557,10 @@ class Dreame1CValetudoRobot extends DreameValetudoRobot {
this.consumableMonitoringCapability.parseConsumablesMessage(elem);
break;
}
});
}
if (this.stateNeedsUpdate === true) {
if (statusNeedsUpdate === true) {
let newState;
let statusValue;
let statusFlag;
@ -596,8 +598,6 @@ class Dreame1CValetudoRobot extends DreameValetudoRobot {
if (newState.isActiveState) {
this.pollMap();
}
this.stateNeedsUpdate = false;
}

View File

@ -153,6 +153,22 @@ class DreameD10SPlusValetudoRobot extends DreameGen2LidarValetudoRobot {
type: entities.state.attributes.AttachmentStateAttribute.TYPE.MOP,
attached: false
}));
this.state.upsertFirstMatchingAttribute(new entities.state.attributes.DockStatusStateAttribute({
value: entities.state.attributes.DockStatusStateAttribute.VALUE.IDLE
}));
}
getStatePropertiesToPoll() {
const superProps = super.getStatePropertiesToPoll();
return [
...superProps,
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.PROPERTIES.STATE.PIID
}
];
}
getModelName() {

View File

@ -61,7 +61,9 @@ class DreameGen2ValetudoRobot extends DreameValetudoRobot {
this.mode = 0; //Idle
this.isCharging = false;
this.errorCode = "0";
this.stateNeedsUpdate = false;
this.mopDockState = undefined; // Might not be set depending on model
this.autoEmptyDockState = undefined; // Might also not be set depending on model
this.registerCapability(new capabilities.DreameBasicControlCapability({
robot: this,
@ -288,6 +290,7 @@ class DreameGen2ValetudoRobot extends DreameValetudoRobot {
case MIOT_SERVICES.WHEEL.SIID:
case MIOT_SERVICES.MOP_EXPANSION.SIID:
case MIOT_SERVICES.MISC_STATES.SIID:
case MIOT_SERVICES.AUTO_EMPTY_DOCK.SIID:
this.parseAndUpdateState([e]);
break;
case MIOT_SERVICES.DEVICE.SIID:
@ -299,7 +302,6 @@ class DreameGen2ValetudoRobot extends DreameValetudoRobot {
case MIOT_SERVICES.PERSISTENT_MAPS.SIID:
//Intentionally ignored since we only poll that info when required and therefore don't care about updates
break;
case MIOT_SERVICES.AUTO_EMPTY_DOCK.SIID:
case MIOT_SERVICES.TIMERS.SIID:
case MIOT_SERVICES.TOTAL_STATISTICS.SIID:
//Intentionally left blank (for now?)
@ -447,7 +449,10 @@ class DreameGen2ValetudoRobot extends DreameValetudoRobot {
return;
}
data.forEach(elem => {
let statusNeedsUpdate = false;
let dockStatusNeedsUpdate = false;
for (const elem of data) {
switch (elem.siid) {
case MIOT_SERVICES.VACUUM_1.SIID: {
//intentionally left blank since there's nothing here that isn't also in VACUUM_2
@ -464,19 +469,19 @@ class DreameGen2ValetudoRobot extends DreameValetudoRobot {
case MIOT_SERVICES.VACUUM_2.PROPERTIES.MODE.PIID: {
this.mode = elem.value;
this.stateNeedsUpdate = true;
statusNeedsUpdate = true;
break;
}
case MIOT_SERVICES.VACUUM_2.PROPERTIES.ERROR_CODE.PIID: {
this.errorCode = elem.value ?? "";
this.stateNeedsUpdate = true;
statusNeedsUpdate = true;
break;
}
case MIOT_SERVICES.VACUUM_2.PROPERTIES.TASK_STATUS.PIID: {
this.taskStatus = elem.value;
this.stateNeedsUpdate = true;
statusNeedsUpdate = true;
break;
}
case MIOT_SERVICES.VACUUM_2.PROPERTIES.FAN_SPEED.PIID: {
@ -546,9 +551,8 @@ class DreameGen2ValetudoRobot extends DreameValetudoRobot {
break;
}
case MIOT_SERVICES.VACUUM_2.PROPERTIES.MOP_DOCK_STATUS.PIID: {
this.state.upsertFirstMatchingAttribute(new entities.state.attributes.DockStatusStateAttribute({
value: DreameValetudoRobot.MOP_DOCK_STATUS_MAP[elem.value]
}));
this.mopDockState = elem.value;
dockStatusNeedsUpdate = true;
break;
}
@ -629,7 +633,7 @@ class DreameGen2ValetudoRobot extends DreameValetudoRobot {
5 = Returning to Charger
*/
this.isCharging = elem.value === 1;
this.stateNeedsUpdate = true;
statusNeedsUpdate = true;
break;
}
break;
@ -670,6 +674,17 @@ class DreameGen2ValetudoRobot extends DreameValetudoRobot {
}
break;
}
case MIOT_SERVICES.AUTO_EMPTY_DOCK.SIID: {
switch (elem.piid) {
case MIOT_SERVICES.AUTO_EMPTY_DOCK.PROPERTIES.STATE.PIID: {
this.autoEmptyDockState = elem.value;
dockStatusNeedsUpdate = true;
break;
}
}
break;
}
case MIOT_SERVICES.MISC_STATES.SIID: {
// Ignored for now
break;
@ -677,10 +692,10 @@ class DreameGen2ValetudoRobot extends DreameValetudoRobot {
default:
Logger.warn("Unhandled property update", elem);
}
});
}
if (this.stateNeedsUpdate === true) {
if (statusNeedsUpdate === true) {
let newState;
let statusValue;
let statusFlag;
@ -747,8 +762,20 @@ class DreameGen2ValetudoRobot extends DreameValetudoRobot {
if (newState.isActiveState) {
this.pollMap();
}
}
this.stateNeedsUpdate = false;
if (dockStatusNeedsUpdate === true) {
const mappedMopDockState = DreameValetudoRobot.MOP_DOCK_STATUS_MAP[this.mopDockState];
const mappedAutoEmptyDockState = DreameValetudoRobot.AUTO_EMPTY_DOCK_STATUS_MAP[this.autoEmptyDockState];
let fullDockState = mappedMopDockState ?? stateAttrs.DockStatusStateAttribute.VALUE.IDLE;
if (mappedAutoEmptyDockState && mappedAutoEmptyDockState !== stateAttrs.DockStatusStateAttribute.VALUE.IDLE) {
fullDockState = mappedAutoEmptyDockState;
}
this.state.upsertFirstMatchingAttribute(new entities.state.attributes.DockStatusStateAttribute({
value: fullDockState
}));
}

View File

@ -239,6 +239,10 @@ class DreameL10SProUltraHeatValetudoRobot extends DreameGen4ValetudoRobot {
);
}),
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.PROPERTIES.STATE.PIID
},
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.MOP_DOCK_STATUS.PIID

View File

@ -218,6 +218,11 @@ class DreameL10SUltraValetudoRobot extends DreameGen2LidarValetudoRobot {
return [
...superProps,
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.PROPERTIES.STATE.PIID
},
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.MOP_DOCK_STATUS.PIID

View File

@ -196,6 +196,11 @@ class DreameL10UltraValetudoRobot extends DreameGen2LidarValetudoRobot {
return [
...superProps,
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.PROPERTIES.STATE.PIID
},
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.MOP_DOCK_STATUS.PIID

View File

@ -249,6 +249,10 @@ class DreameL40UltraValetudoRobot extends DreameGen4ValetudoRobot {
);
}),
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.PROPERTIES.STATE.PIID
},
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.MOP_DOCK_STATUS.PIID

View File

@ -617,7 +617,7 @@ module.exports = {
STATUS: {
PIID: 3 //Whether or not it's currently able to execute the empty action?
},
ACTION_STATUS: {
STATE: {
PIID: 5 //1 = currently cleaning, 0 = not currently cleaning
}
},

View File

@ -248,6 +248,10 @@ class DreameMovaP10ProUltraValetudoRobot extends DreameGen4ValetudoRobot {
);
}),
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.PROPERTIES.STATE.PIID
},
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.MOP_DOCK_STATUS.PIID

View File

@ -242,6 +242,10 @@ class DreameMovaS20UltraValetudoRobot extends DreameGen4ValetudoRobot {
);
}),
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.PROPERTIES.STATE.PIID
},
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.MOP_DOCK_STATUS.PIID

View File

@ -154,6 +154,11 @@ class DreameP2150ValetudoRobot extends DreameGen2LidarValetudoRobot {
return [
...superProps,
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.PROPERTIES.STATE.PIID
},
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.MOP_DOCK_SETTINGS.PIID

View File

@ -397,6 +397,12 @@ DreameValetudoRobot.WATER_GRADES = Object.freeze({
[stateAttrs.PresetSelectionStateAttribute.INTENSITY.HIGH]: 3,
});
DreameValetudoRobot.AUTO_EMPTY_DOCK_STATUS_MAP = Object.freeze({
0: stateAttrs.DockStatusStateAttribute.VALUE.IDLE,
1: stateAttrs.DockStatusStateAttribute.VALUE.EMPTYING,
2: stateAttrs.DockStatusStateAttribute.VALUE.IDLE, // DND
});
DreameValetudoRobot.MOP_DOCK_STATUS_MAP = Object.freeze({
0: stateAttrs.DockStatusStateAttribute.VALUE.IDLE,
1: stateAttrs.DockStatusStateAttribute.VALUE.CLEANING,

View File

@ -200,6 +200,11 @@ class DreameX10PlusValetudoRobot extends DreameGen2LidarValetudoRobot {
return [
...superProps,
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.PROPERTIES.STATE.PIID
},
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.MOP_DOCK_STATUS.PIID

View File

@ -249,6 +249,10 @@ class DreameX40MasterValetudoRobot extends DreameGen4ValetudoRobot {
);
}),
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.PROPERTIES.STATE.PIID
},
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.MOP_DOCK_STATUS.PIID

View File

@ -249,6 +249,10 @@ class DreameX40UltraValetudoRobot extends DreameGen4ValetudoRobot {
);
}),
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.PROPERTIES.STATE.PIID
},
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.MOP_DOCK_STATUS.PIID

View File

@ -155,6 +155,10 @@ class DreameZ10ProValetudoRobot extends DreameGen2LidarValetudoRobot {
return [
...superProps,
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.AUTO_EMPTY_DOCK.PROPERTIES.STATE.PIID
},
{
siid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.SIID,
piid: DreameGen2ValetudoRobot.MIOT_SERVICES.VACUUM_2.PROPERTIES.MOP_DOCK_SETTINGS.PIID

View File

@ -134,7 +134,7 @@ const Dock = (): React.ReactElement => {
triggerEmptySupported &&
<Grid2 sx={{flex: 1, minWidth: "min-content"}}>
<Button
disabled={commandIsExecuting || robotState !== "docked"}
disabled={commandIsExecuting || !["idle", "pause"].includes(dockState) || robotState !== "docked"}
variant="outlined"
size="medium"
color="inherit"