Cover position tile feature (#16110)

* wip

* css + transtations

* Update types.ts

rollback changes done by VS Code

* fix

* Inverted slider

---------

Co-authored-by: Paul Bottein <paul.bottein@gmail.com>
This commit is contained in:
Tomasz 2023-08-18 10:40:41 +02:00 committed by GitHub
parent 6e27fbe10f
commit 705b6aeb4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 139 additions and 4 deletions

View File

@ -43,6 +43,9 @@ export class HaControlSlider extends LitElement {
@property({ type: Boolean, attribute: "show-handle" })
public showHandle = false;
@property({ type: Boolean, attribute: "inverted" })
public inverted = false;
@property({ type: Number })
public value?: number;
@ -61,11 +64,16 @@ export class HaControlSlider extends LitElement {
public pressed = false;
valueToPercentage(value: number) {
return (this.boundedValue(value) - this.min) / (this.max - this.min);
const percentage =
(this.boundedValue(value) - this.min) / (this.max - this.min);
return this.inverted ? 1 - percentage : percentage;
}
percentageToValue(value: number) {
return (this.max - this.min) * value + this.min;
percentageToValue(percentage: number) {
return (
(this.max - this.min) * (this.inverted ? 1 - percentage : percentage) +
this.min
);
}
steppedValue(value: number) {

View File

@ -50,7 +50,7 @@ export class HaMoreInfoCoverPosition extends LitElement {
this.hass.localize,
this.stateObj,
this.hass.entities,
"position"
"current_position"
)}
style=${styleMap({
"--control-slider-color": color,

View File

@ -1,6 +1,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-tile-feature";
import "../tile-features/hui-fan-speed-tile-feature";
import "../tile-features/hui-light-brightness-tile-feature";
@ -15,6 +16,7 @@ import {
const TYPES: Set<LovelaceTileFeatureConfig["type"]> = new Set([
"cover-open-close",
"cover-position",
"cover-tilt",
"light-brightness",
"light-color-temp",

View File

@ -28,6 +28,7 @@ import { getTileFeatureElementClass } from "../../create-element/create-tile-fea
import { supportsAlarmModesTileFeature } from "../../tile-features/hui-alarm-modes-tile-feature";
import { supportsClimateHvacModesTileFeature } from "../../tile-features/hui-climate-hvac-modes-tile-feature";
import { supportsCoverOpenCloseTileFeature } from "../../tile-features/hui-cover-open-close-tile-feature";
import { supportsCoverPositionTileFeature } from "../../tile-features/hui-cover-position-tile-feature";
import { supportsCoverTiltTileFeature } from "../../tile-features/hui-cover-tilt-tile-feature";
import { supportsFanSpeedTileFeature } from "../../tile-features/hui-fan-speed-tile-feature";
import { supportsLightBrightnessTileFeature } from "../../tile-features/hui-light-brightness-tile-feature";
@ -41,6 +42,7 @@ type SupportsFeature = (stateObj: HassEntity) => boolean;
const FEATURE_TYPES: FeatureType[] = [
"cover-open-close",
"cover-position",
"cover-tilt",
"light-brightness",
"light-color-temp",
@ -61,6 +63,7 @@ const EDITABLES_FEATURE_TYPES = new Set<FeatureType>([
const SUPPORTS_FEATURE_TYPES: Record<FeatureType, SupportsFeature | undefined> =
{
"cover-open-close": supportsCoverOpenCloseTileFeature,
"cover-position": supportsCoverPositionTileFeature,
"cover-tilt": supportsCoverTiltTileFeature,
"light-brightness": supportsLightBrightnessTileFeature,
"light-color-temp": supportsLightColorTempTileFeature,

View File

@ -0,0 +1,114 @@
import { HassEntity } from "home-assistant-js-websocket";
import { css, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import { computeDomain } from "../../../common/entity/compute_domain";
import { supportsFeature } from "../../../common/entity/supports-feature";
import { CoverEntityFeature } from "../../../data/cover";
import { HomeAssistant } from "../../../types";
import { LovelaceTileFeature } from "../types";
import { CoverPositionTileFeatureConfig } from "./types";
import { stateActive } from "../../../common/entity/state_active";
import { computeAttributeNameDisplay } from "../../../common/entity/compute_attribute_display";
import { UNAVAILABLE } from "../../../data/entity";
export const supportsCoverPositionTileFeature = (stateObj: HassEntity) => {
const domain = computeDomain(stateObj.entity_id);
return (
domain === "cover" &&
supportsFeature(stateObj, CoverEntityFeature.SET_POSITION)
);
};
@customElement("hui-cover-position-tile-feature")
class HuiCoverPositionTileFeature
extends LitElement
implements LovelaceTileFeature
{
@property({ attribute: false }) public hass?: HomeAssistant;
@property({ attribute: false }) public stateObj?: HassEntity;
@state() private _config?: CoverPositionTileFeatureConfig;
static getStubConfig(): CoverPositionTileFeatureConfig {
return {
type: "cover-position",
};
}
public setConfig(config: CoverPositionTileFeatureConfig): void {
if (!config) {
throw new Error("Invalid configuration");
}
this._config = config;
}
protected render() {
if (
!this._config ||
!this.hass ||
!this.stateObj ||
!supportsCoverPositionTileFeature(this.stateObj)
) {
return nothing;
}
const percentage = stateActive(this.stateObj)
? this.stateObj.attributes.current_position ?? 0
: 0;
const value = Math.max(Math.round(percentage), 0);
return html` <div class="container">
<ha-control-slider
.value=${value}
min="0"
max="100"
step="1"
inverted
show-handle
@value-changed=${this._valueChanged}
.ariaLabel=${computeAttributeNameDisplay(
this.hass.localize,
this.stateObj,
this.hass.entities,
"current_position"
)}
.disabled=${this.stateObj!.state === UNAVAILABLE}
></ha-control-slider>
</div>`;
}
private _valueChanged(ev: CustomEvent) {
const value = (ev.detail as any).value;
if (isNaN(value)) return;
this.hass!.callService("cover", "set_cover_position", {
entity_id: this.stateObj!.entity_id,
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;
}
`;
}
}
declare global {
interface HTMLElementTagNameMap {
"hui-cover-position-tile-feature": HuiCoverPositionTileFeature;
}
}

View File

@ -6,6 +6,10 @@ export interface CoverOpenCloseTileFeatureConfig {
type: "cover-open-close";
}
export interface CoverPositionTileFeatureConfig {
type: "cover-position";
}
export interface CoverTiltTileFeatureConfig {
type: "cover-tilt";
}
@ -54,6 +58,7 @@ export interface VacuumCommandsTileFeatureConfig {
export type LovelaceTileFeatureConfig =
| CoverOpenCloseTileFeatureConfig
| CoverPositionTileFeatureConfig
| CoverTiltTileFeatureConfig
| LightBrightnessTileFeatureConfig
| LightColorTempTileFeatureConfig

View File

@ -4967,6 +4967,9 @@
"cover-open-close": {
"label": "Cover open/close"
},
"cover-position": {
"label": "Cover position"
},
"cover-tilt": {
"label": "Cover tilt"
},