Compare commits

...
Author SHA1 Message Date
Paul Bottein 2121da9bb3 Add idle state and stop action to lawn mower 2026-09-03 15:00:59 +02:00
10 changed files with 70 additions and 7 deletions
@@ -11,6 +11,7 @@ import { LawnMowerEntityFeature } from "../../../../src/data/lawn_mower";
const ALL_FEATURES =
LawnMowerEntityFeature.START_MOWING +
LawnMowerEntityFeature.PAUSE +
LawnMowerEntityFeature.STOP +
LawnMowerEntityFeature.DOCK;
const ENTITIES = [
@@ -49,6 +50,14 @@ const ENTITIES = [
supported_features: ALL_FEATURES,
},
},
{
entity_id: "lawn_mower.idle",
state: "idle",
attributes: {
friendly_name: "Idle",
supported_features: ALL_FEATURES,
},
},
{
entity_id: "lawn_mower.error",
state: "error",
+1 -1
View File
@@ -29,7 +29,7 @@ export const FIXED_DOMAIN_STATES = {
fan: ["on", "off"],
humidifier: ["on", "off"],
input_boolean: ["on", "off"],
lawn_mower: ["error", "paused", "mowing", "returning", "docked"],
lawn_mower: ["error", "paused", "mowing", "returning", "docked", "idle"],
light: ["on", "off"],
lock: [
"jammed",
+1 -1
View File
@@ -36,7 +36,7 @@ export function stateActive(stateObj: HassEntity, state?: string): boolean {
case "person":
return compareState !== "not_home";
case "lawn_mower":
return !["docked", "paused"].includes(compareState);
return !["docked", "paused", "idle"].includes(compareState);
case "lock":
return compareState !== "locked";
case "media_player":
@@ -28,6 +28,11 @@ const LAWN_MOWER_ACTIONS: Partial<
service: "start_mowing",
feature: LawnMowerEntityFeature.START_MOWING,
},
idle: {
action: "start_mowing",
service: "start_mowing",
feature: LawnMowerEntityFeature.START_MOWING,
},
returning: {
action: "pause",
service: "pause",
+9 -1
View File
@@ -5,12 +5,13 @@ import type {
import { UNAVAILABLE } from "./entity/entity";
export type LawnMowerEntityState =
"paused" | "mowing" | "returning" | "docked" | "error";
"paused" | "mowing" | "returning" | "docked" | "idle" | "error";
export enum LawnMowerEntityFeature {
START_MOWING = 1,
PAUSE = 2,
DOCK = 4,
STOP = 8,
}
interface LawnMowerEntityAttributes
@@ -38,6 +39,13 @@ export function canPause(stateObj: LawnMowerEntity): boolean {
return stateObj.state !== "paused";
}
export function canStop(stateObj: LawnMowerEntity): boolean {
if (stateObj.state === UNAVAILABLE) {
return false;
}
return !["docked", "idle"].includes(stateObj.state);
}
export function canDock(stateObj: LawnMowerEntity): boolean {
if (stateObj.state === UNAVAILABLE) {
return false;
@@ -1,5 +1,5 @@
import { consume } from "@lit/context";
import { mdiHomeImportOutline, mdiPause, mdiPlay } from "@mdi/js";
import { mdiHomeImportOutline, mdiPause, mdiPlay, mdiStop } from "@mdi/js";
import type { CSSResultGroup } from "lit";
import { LitElement, css, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
@@ -29,6 +29,7 @@ import {
LawnMowerEntityFeature,
canDock,
canStartMowing,
canStop,
isMowing,
} from "../../../data/lawn_mower";
import "../../../state-control/lawn_mower/ha-state-control-lawn_mower-status";
@@ -173,6 +174,14 @@ class MoreInfoLawnMower extends LitElement {
}
}
private _handleStop() {
if (!this.stateObj) return;
forwardHaptic(this, "light");
this._api.callService("lawn_mower", "stop", {
entity_id: this.stateObj.entity_id,
});
}
private _handleDock() {
if (!this.stateObj) return;
forwardHaptic(this, "light");
@@ -188,9 +197,11 @@ class MoreInfoLawnMower extends LitElement {
const stateObj = this.stateObj;
const isUnavailable = stateObj.state === UNAVAILABLE;
const supportsStop = supportsFeature(stateObj, LawnMowerEntityFeature.STOP);
const supportsDock = supportsFeature(stateObj, LawnMowerEntityFeature.DOCK);
const hasAnyCommand = this._supportsStartPause || supportsDock;
const hasAnyCommand =
this._supportsStartPause || supportsStop || supportsDock;
return html`
<ha-more-info-state-header .stateObj=${this.stateObj}>
@@ -222,6 +233,21 @@ class MoreInfoLawnMower extends LitElement {
`
: nothing
}
${
supportsStop
? html`
<ha-control-button
.label=${this._i18n.localize(
"ui.dialogs.more_info_control.lawn_mower.stop"
)}
@click=${this._handleStop}
.disabled=${isUnavailable || !canStop(stateObj)}
>
<ha-svg-icon .path=${mdiStop}></ha-svg-icon>
</ha-control-button>
`
: nothing
}
${
supportsDock
? html`
@@ -24,6 +24,11 @@ export class MockLawnMowerEntity extends MockBaseEntity {
return;
}
if (service === "stop") {
this.update({ state: "idle" });
return;
}
if (service === "dock") {
this._transition("returning", "docked", TRANSITION_MS);
return;
@@ -1,5 +1,5 @@
import { consume } from "@lit/context";
import { mdiHomeImportOutline, mdiPause, mdiPlay } from "@mdi/js";
import { mdiHomeImportOutline, mdiPause, mdiPlay, mdiStop } from "@mdi/js";
import type { HassEntity } from "home-assistant-js-websocket";
import { LitElement, html, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
@@ -20,6 +20,7 @@ import {
LawnMowerEntityFeature,
canDock,
canStartMowing,
canStop,
} from "../../../data/lawn_mower";
import type { HomeAssistant, HomeAssistantApi } from "../../../types";
import type { LovelaceCardFeature, LovelaceCardFeatureEditor } from "../types";
@@ -46,6 +47,7 @@ export const LAWN_MOWER_COMMANDS_FEATURES: Record<
LawnMowerEntityFeature.PAUSE,
LawnMowerEntityFeature.START_MOWING,
],
stop: [LawnMowerEntityFeature.STOP],
dock: [LawnMowerEntityFeature.DOCK],
};
@@ -81,6 +83,12 @@ export const LAWN_MOWER_COMMANDS_BUTTONS: Record<
!canStartMowing(stateObj),
};
},
stop: (stateObj) => ({
translationKey: "stop",
icon: mdiStop,
serviceName: "stop",
disabled: !canStop(stateObj),
}),
dock: (stateObj) => ({
translationKey: "dock",
icon: mdiHomeImportOutline,
+1 -1
View File
@@ -264,7 +264,7 @@ export interface ValvePositionFavoriteCardFeatureConfig {
type: "valve-position-favorite";
}
export const LAWN_MOWER_COMMANDS = ["start_pause", "dock"] as const;
export const LAWN_MOWER_COMMANDS = ["start_pause", "stop", "dock"] as const;
export type LawnMowerCommand = (typeof LAWN_MOWER_COMMANDS)[number];
+2
View File
@@ -1874,6 +1874,7 @@
"commands": "Lawn mower commands:",
"start_mowing": "Start mowing",
"pause": "Pause",
"stop": "Stop",
"dock": "Return to dock"
},
"valve": {
@@ -11024,6 +11025,7 @@
"commands": "Commands",
"commands_list": {
"start_pause": "Start Pause",
"stop": "[%key:ui::dialogs::more_info_control::lawn_mower::stop%]",
"dock": "[%key:ui::dialogs::more_info_control::lawn_mower::dock%]"
}
},