diff --git a/backend/lib/core/capabilities/MopDockMopAutoDryingControlCapability.js b/backend/lib/core/capabilities/MopDockMopAutoDryingControlCapability.js new file mode 100644 index 00000000..d453b42b --- /dev/null +++ b/backend/lib/core/capabilities/MopDockMopAutoDryingControlCapability.js @@ -0,0 +1,15 @@ +const SimpleToggleCapability = require("./SimpleToggleCapability"); + +/** + * @template {import("../ValetudoRobot")} T + * @extends SimpleToggleCapability + */ +class MopDockMopAutoDryingControlCapability extends SimpleToggleCapability { + getType() { + return MopDockMopAutoDryingControlCapability.TYPE; + } +} + +MopDockMopAutoDryingControlCapability.TYPE = "MopDockMopAutoDryingControlCapability"; + +module.exports = MopDockMopAutoDryingControlCapability; diff --git a/backend/lib/core/capabilities/index.js b/backend/lib/core/capabilities/index.js index 31f73fff..cc3d7854 100644 --- a/backend/lib/core/capabilities/index.js +++ b/backend/lib/core/capabilities/index.js @@ -24,6 +24,7 @@ module.exports = { MappingPassCapability: require("./MappingPassCapability"), MopDockCleanManualTriggerCapability: require("./MopDockCleanManualTriggerCapability"), MopDockDryManualTriggerCapability: require("./MopDockDryManualTriggerCapability"), + MopDockMopAutoDryingControlCapability: require("./MopDockMopAutoDryingControlCapability"), MopDockMopWashTemperatureControlCapability: require("./MopDockMopWashTemperatureControlCapability"), MopExtensionControlCapability: require("./MopExtensionControlCapability"), MopExtensionFurnitureLegHandlingControlCapability: require("./MopExtensionFurnitureLegHandlingControlCapability"), diff --git a/backend/lib/webserver/CapabilitiesRouter.js b/backend/lib/webserver/CapabilitiesRouter.js index 867d5579..838cf250 100644 --- a/backend/lib/webserver/CapabilitiesRouter.js +++ b/backend/lib/webserver/CapabilitiesRouter.js @@ -95,6 +95,7 @@ const CAPABILITY_TYPE_TO_ROUTER_MAPPING = { [capabilities.MopDockMopWashTemperatureControlCapability.TYPE]: capabilityRouters.MopDockMopWashTemperatureControlCapabilityRouter, [capabilities.MopTwistControlCapability.TYPE]: capabilityRouters.SimpleToggleCapabilityRouter, [capabilities.MopExtensionFurnitureLegHandlingControlCapability.TYPE]: capabilityRouters.SimpleToggleCapabilityRouter, + [capabilities.MopDockMopAutoDryingControlCapability.TYPE]: capabilityRouters.SimpleToggleCapabilityRouter, }; module.exports = CapabilitiesRouter; diff --git a/backend/lib/webserver/capabilityRouters/doc/SimpleToggleCapabilityRouter.openapi.json b/backend/lib/webserver/capabilityRouters/doc/SimpleToggleCapabilityRouter.openapi.json index f148fffe..00202c90 100644 --- a/backend/lib/webserver/capabilityRouters/doc/SimpleToggleCapabilityRouter.openapi.json +++ b/backend/lib/webserver/capabilityRouters/doc/SimpleToggleCapabilityRouter.openapi.json @@ -768,5 +768,82 @@ } } } + }, + "/api/v2/robot/capabilities/MopDockMopAutoDryingControlCapability": { + "get": { + "tags": [ + "MopDockMopAutoDryingControlCapability" + ], + "summary": "Get mop auto drying setting", + "responses": { + "200": { + "description": "Ok", + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean" + } + } + } + } + } + } + } + }, + "put": { + "tags": [ + "MopDockMopAutoDryingControlCapability" + ], + "summary": "Set mop auto drying setting", + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "action": { + "type": "string", + "enum": [ + "enable", + "disable" + ] + } + } + } + } + } + }, + "responses": { + "200": { + "$ref": "#/components/responses/200" + }, + "400": { + "$ref": "#/components/responses/400" + } + } + } + }, + "/api/v2/robot/capabilities/MopDockMopAutoDryingControlCapability/properties": { + "get": { + "tags": [ + "MopDockMopAutoDryingControlCapability" + ], + "summary": "Get various capability-related properties", + "responses": { + "200": { + "description": "Ok", + "content": { + "application/json": { + "schema": { + "type": "object" + } + } + } + } + } + } } } diff --git a/frontend/src/api/client.ts b/frontend/src/api/client.ts index 1fcd30be..90df8907 100644 --- a/frontend/src/api/client.ts +++ b/frontend/src/api/client.ts @@ -1228,3 +1228,15 @@ export const fetchMopDockMopWashTemperatureProperties = async (): Promise => { + return valetudoAPI + .get(`/robot/capabilities/${Capability.MopDockMopAutoDryingControl}`) + .then(({ data }) => { + return data; + }); +}; + +export const sendMopDockMopAutoDryingControlState = async (enable: boolean): Promise => { + await sendToggleMutation(Capability.MopDockMopAutoDryingControl, enable); +}; diff --git a/frontend/src/api/hooks.ts b/frontend/src/api/hooks.ts index f6c8c2fd..e8585ec6 100644 --- a/frontend/src/api/hooks.ts +++ b/frontend/src/api/hooks.ts @@ -133,6 +133,8 @@ import { sendMopExtensionFurnitureLegHandlingControlState, fetchMopTwistControlState, sendMopTwistControlState, + fetchMopDockMopAutoDryingControlState, + sendMopDockMopAutoDryingControlState, } from "./client"; import { PresetSelectionState, @@ -238,6 +240,7 @@ enum QueryKey { MopDockMopWashTemperatureProperties = "mop_dock_mop_wash_temperature_properties", MopTwistControl = "mop_twist_control", MopExtensionFurnitureLegHandlingControl = "mop_extension_furniture_leg_handling_control", + MopDockMopAutoDryingControl = "mop_dock_mop_auto_drying_control", } const useOnCommandError = (capability: Capability | string): ((error: unknown) => void) => { @@ -1647,3 +1650,22 @@ export const useMopExtensionFurnitureLegHandlingControlMutation = () => { onError: useOnCommandError(Capability.MopExtensionFurnitureLegHandlingControl) }); }; + +export const useMopDockMopAutoDryingControlQuery = () => { + return useQuery( { + queryKey: [QueryKey.MopDockMopAutoDryingControl], + queryFn: fetchMopDockMopAutoDryingControlState, + + staleTime: Infinity + }); +}; + +export const useMopDockMopAutoDryingControlMutation = () => { + return useValetudoFetchingMutation({ + queryKey: [QueryKey.MopDockMopAutoDryingControl], + mutationFn: (enable: boolean) => { + return sendMopDockMopAutoDryingControlState(enable).then(fetchMopDockMopAutoDryingControlState); + }, + onError: useOnCommandError(Capability.MopDockMopAutoDryingControl) + }); +}; diff --git a/frontend/src/api/types.ts b/frontend/src/api/types.ts index e22708c2..ef8fdd27 100644 --- a/frontend/src/api/types.ts +++ b/frontend/src/api/types.ts @@ -32,6 +32,7 @@ export enum Capability { MopExtensionFurnitureLegHandlingControl = "MopExtensionFurnitureLegHandlingControlCapability", MopDockCleanManualTrigger = "MopDockCleanManualTriggerCapability", MopDockDryManualTrigger = "MopDockDryManualTriggerCapability", + MopDockMopAutoDryingControl = "MopDockMopAutoDryingControlCapability", OperationModeControl = "OperationModeControlCapability", PersistentMapControl = "PersistentMapControlCapability", SpeakerTest = "SpeakerTestCapability", diff --git a/frontend/src/robot/RobotOptions.tsx b/frontend/src/robot/RobotOptions.tsx index 42ee1441..1c62ba5b 100644 --- a/frontend/src/robot/RobotOptions.tsx +++ b/frontend/src/robot/RobotOptions.tsx @@ -36,6 +36,8 @@ import { useMopExtensionFurnitureLegHandlingControlQuery, useMopTwistControlMutation, useMopTwistControlQuery, + useMopDockMopAutoDryingControlMutation, + useMopDockMopAutoDryingControlQuery, } from "../api"; import React from "react"; import {ListMenu} from "../components/list_menu/ListMenu"; @@ -53,6 +55,7 @@ import { Sensors as CarpetModeIcon, Star as QuirksIcon, Waves as CarpetSensorModeIcon, + Air as MopDockMopAutoDryingControlIcon, DeviceThermostat as MopDockMopWashTemperatureControlIcon, TableBar as MopExtensionFurnitureLegHandlingControlIcon } from "@mui/icons-material"; @@ -621,6 +624,32 @@ const MopExtensionFurnitureLegHandlingControlCapabilitySwitchListMenuItem = () = ); }; +const MopDockMopAutoDryingControlCapabilitySwitchListMenuItem = () => { + const { + data: data, + isFetching: isFetching, + isError: isError, + } = useMopDockMopAutoDryingControlQuery(); + + const {mutate: mutate, isPending: isChanging} = useMopDockMopAutoDryingControlMutation(); + const loading = isFetching || isChanging; + const disabled = loading || isChanging || isError; + + return ( + { + mutate(value); + }} + disabled={disabled} + loadError={isError} + primaryLabel={"Mop Auto-Drying"} + secondaryLabel={"Automatically dry the mop pads after a cleanup."} + icon={} + /> + ); +}; + const RobotOptions = (): React.ReactElement => { const [ locateCapabilitySupported, @@ -638,6 +667,7 @@ const RobotOptions = (): React.ReactElement => { mopExtensionFurnitureLegHandlingControlSupported, autoEmptyDockAutoEmptyIntervalControlCapabilitySupported, + mopDockMopAutoDryingControlSupported, mopDockMopWashTemperatureControlSupported, keyLockControlCapabilitySupported, @@ -664,6 +694,7 @@ const RobotOptions = (): React.ReactElement => { Capability.MopExtensionFurnitureLegHandlingControl, Capability.AutoEmptyDockAutoEmptyIntervalControl, + Capability.MopDockMopAutoDryingControl, Capability.MopDockMopWashTemperatureControl, Capability.KeyLock, @@ -775,6 +806,10 @@ const RobotOptions = (): React.ReactElement => { ); } + if (mopDockMopAutoDryingControlSupported) { + items.push(); + } + if (mopDockMopWashTemperatureControlSupported) { items.push( @@ -784,6 +819,7 @@ const RobotOptions = (): React.ReactElement => { return items; }, [ autoEmptyDockAutoEmptyIntervalControlCapabilitySupported, + mopDockMopAutoDryingControlSupported, mopDockMopWashTemperatureControlSupported, ]);