diff --git a/src/dialogs/more-info/components/cover/ha-more-info-cover-tilt-position.ts b/src/dialogs/more-info/components/cover/ha-more-info-cover-tilt-position.ts index f9ddde6b9d..435d437f83 100644 --- a/src/dialogs/more-info/components/cover/ha-more-info-cover-tilt-position.ts +++ b/src/dialogs/more-info/components/cover/ha-more-info-cover-tilt-position.ts @@ -15,7 +15,7 @@ import { CoverEntity } from "../../../../data/cover"; import { UNAVAILABLE } from "../../../../data/entity"; import { HomeAssistant } from "../../../../types"; -function generateTiltSliderTrackBackgroundGradient() { +export function generateTiltSliderTrackBackgroundGradient() { const count = 24; const minStrokeWidth = 0.2; const gradient: [number, string][] = []; @@ -87,7 +87,7 @@ export class HaMoreInfoCoverTiltPosition extends LitElement { this.hass.localize, this.stateObj, this.hass.entities, - "tilt_position" + "current_tilt_position" )} style=${styleMap({ "--control-slider-color": color, diff --git a/src/panels/lovelace/create-element/create-tile-feature-element.ts b/src/panels/lovelace/create-element/create-tile-feature-element.ts index 142838310b..f85e660378 100644 --- a/src/panels/lovelace/create-element/create-tile-feature-element.ts +++ b/src/panels/lovelace/create-element/create-tile-feature-element.ts @@ -2,6 +2,7 @@ import "../tile-features/hui-alarm-modes-tile-feature"; import "../tile-features/hui-climate-hvac-modes-tile-feature"; import "../tile-features/hui-cover-open-close-tile-feature"; import "../tile-features/hui-cover-position-tile-feature"; +import "../tile-features/hui-cover-tilt-position-tile-feature"; import "../tile-features/hui-cover-tilt-tile-feature"; import "../tile-features/hui-fan-speed-tile-feature"; import "../tile-features/hui-light-brightness-tile-feature"; @@ -19,6 +20,7 @@ const TYPES: Set = new Set([ "cover-open-close", "cover-position", "cover-tilt", + "cover-tilt-position", "light-brightness", "light-color-temp", "vacuum-commands", diff --git a/src/panels/lovelace/editor/config-elements/hui-tile-card-features-editor.ts b/src/panels/lovelace/editor/config-elements/hui-tile-card-features-editor.ts index 12411d4092..6a38b0a672 100644 --- a/src/panels/lovelace/editor/config-elements/hui-tile-card-features-editor.ts +++ b/src/panels/lovelace/editor/config-elements/hui-tile-card-features-editor.ts @@ -46,6 +46,7 @@ const FEATURE_TYPES: FeatureType[] = [ "climate-hvac-modes", "cover-open-close", "cover-position", + "cover-tilt-position", "cover-tilt", "fan-speed", "lawn-mower-commands", @@ -69,6 +70,7 @@ const SUPPORTS_FEATURE_TYPES: Record = "climate-hvac-modes": supportsClimateHvacModesTileFeature, "cover-open-close": supportsCoverOpenCloseTileFeature, "cover-position": supportsCoverPositionTileFeature, + "cover-tilt-position": supportsCoverPositionTileFeature, "cover-tilt": supportsCoverTiltTileFeature, "fan-speed": supportsFanSpeedTileFeature, "lawn-mower-commands": supportsLawnMowerCommandTileFeature, diff --git a/src/panels/lovelace/tile-features/hui-cover-tilt-position-tile-feature.ts b/src/panels/lovelace/tile-features/hui-cover-tilt-position-tile-feature.ts new file mode 100644 index 0000000000..be174788a6 --- /dev/null +++ b/src/panels/lovelace/tile-features/hui-cover-tilt-position-tile-feature.ts @@ -0,0 +1,121 @@ +import { HassEntity } from "home-assistant-js-websocket"; +import { css, html, LitElement, nothing } from "lit"; +import { customElement, property, state } from "lit/decorators"; +import { computeAttributeNameDisplay } from "../../../common/entity/compute_attribute_display"; +import { computeDomain } from "../../../common/entity/compute_domain"; +import { supportsFeature } from "../../../common/entity/supports-feature"; +import { CoverEntity, CoverEntityFeature } from "../../../data/cover"; +import { UNAVAILABLE } from "../../../data/entity"; +import { generateTiltSliderTrackBackgroundGradient } from "../../../dialogs/more-info/components/cover/ha-more-info-cover-tilt-position"; +import { HomeAssistant } from "../../../types"; +import { LovelaceTileFeature } from "../types"; +import { CoverTiltPositionTileFeatureConfig } from "./types"; + +const GRADIENT = generateTiltSliderTrackBackgroundGradient(); + +export const supportsCoverTiltPositionTileFeature = (stateObj: HassEntity) => { + const domain = computeDomain(stateObj.entity_id); + return ( + domain === "cover" && + supportsFeature(stateObj, CoverEntityFeature.SET_TILT_POSITION) + ); +}; + +@customElement("hui-cover-tilt-position-tile-feature") +class HuiCoverTiltPositionTileFeature + extends LitElement + implements LovelaceTileFeature +{ + @property({ attribute: false }) public hass?: HomeAssistant; + + @property({ attribute: false }) public stateObj?: CoverEntity; + + @state() private _config?: CoverTiltPositionTileFeatureConfig; + + static getStubConfig(): CoverTiltPositionTileFeatureConfig { + return { + type: "cover-tilt-position", + }; + } + + public setConfig(config: CoverTiltPositionTileFeatureConfig): void { + if (!config) { + throw new Error("Invalid configuration"); + } + this._config = config; + } + + protected render() { + if ( + !this._config || + !this.hass || + !this.stateObj || + !supportsCoverTiltPositionTileFeature(this.stateObj) + ) { + return nothing; + } + + const percentage = this.stateObj.attributes.current_tilt_position ?? 0; + + const value = Math.max(Math.round(percentage), 0); + + return html` +
+ +
+
+ `; + } + + private _valueChanged(ev: CustomEvent) { + const value = (ev.detail as any).value; + if (isNaN(value)) return; + + this.hass!.callService("cover", "set_cover_tilt_position", { + entity_id: this.stateObj!.entity_id, + tilt_position: value, + }); + } + + static get styles() { + return css` + ha-control-slider { + /* Force inactive state to be colored for the slider */ + --control-slider-color: var(--tile-color); + --control-slider-background: var(--tile-color); + --control-slider-background-opacity: 0.2; + --control-slider-thickness: 40px; + --control-slider-border-radius: 10px; + } + .container { + padding: 0 12px 12px 12px; + width: auto; + } + .gradient { + background: -webkit-linear-gradient(left, ${GRADIENT}); + opacity: 0.6; + } + `; + } +} + +declare global { + interface HTMLElementTagNameMap { + "hui-cover-tilt-position-tile-feature": HuiCoverTiltPositionTileFeature; + } +} diff --git a/src/panels/lovelace/tile-features/types.ts b/src/panels/lovelace/tile-features/types.ts index 848862c4d3..71e3ad711a 100644 --- a/src/panels/lovelace/tile-features/types.ts +++ b/src/panels/lovelace/tile-features/types.ts @@ -14,6 +14,10 @@ export interface CoverTiltTileFeatureConfig { type: "cover-tilt"; } +export interface CoverTiltPositionTileFeatureConfig { + type: "cover-tilt-position"; +} + export interface LightBrightnessTileFeatureConfig { type: "light-brightness"; } @@ -70,6 +74,7 @@ export type LovelaceTileFeatureConfig = | ClimateHvacModesTileFeatureConfig | CoverOpenCloseTileFeatureConfig | CoverPositionTileFeatureConfig + | CoverTiltPositionTileFeatureConfig | CoverTiltTileFeatureConfig | FanSpeedTileFeatureConfig | LawnMowerCommandsTileFeatureConfig diff --git a/src/translations/en.json b/src/translations/en.json index f9f71e30c1..c27789a9ae 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -4988,6 +4988,9 @@ "cover-tilt": { "label": "Cover tilt" }, + "cover-tilt-position": { + "label": "Cover tilt position" + }, "fan-speed": { "label": "Fan speed" },