Fix fan speed for new more info and tile feature (#16050)

This commit is contained in:
Paul Bottein 2023-04-04 13:36:33 +02:00 committed by GitHub
parent 9764a0f23f
commit 99e6547807
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 44 additions and 34 deletions

View File

@ -2,6 +2,7 @@ import {
HassEntityAttributeBase, HassEntityAttributeBase,
HassEntityBase, HassEntityBase,
} from "home-assistant-js-websocket"; } from "home-assistant-js-websocket";
import { stateActive } from "../common/entity/state_active";
import { supportsFeature } from "../common/entity/supports-feature"; import { supportsFeature } from "../common/entity/supports-feature";
import { blankBeforePercent } from "../common/translations/blank_before_percent"; import { blankBeforePercent } from "../common/translations/blank_before_percent";
import { UNAVAILABLE } from "./entity"; import { UNAVAILABLE } from "./entity";
@ -114,10 +115,12 @@ export function computeCoverPositionStateDisplay(
locale: FrontendLocaleData, locale: FrontendLocaleData,
position?: number position?: number
) { ) {
const currentPosition = const statePosition = stateActive(stateObj)
position ?? ? stateObj.attributes.current_position ??
stateObj.attributes.current_position ?? stateObj.attributes.current_tilt_position
stateObj.attributes.current_tilt_position; : undefined;
const currentPosition = position ?? statePosition;
return currentPosition && currentPosition !== 100 return currentPosition && currentPosition !== 100
? `${Math.round(currentPosition)}${blankBeforePercent(locale)}%` ? `${Math.round(currentPosition)}${blankBeforePercent(locale)}%`

View File

@ -9,6 +9,7 @@ import {
HassEntityAttributeBase, HassEntityAttributeBase,
HassEntityBase, HassEntityBase,
} from "home-assistant-js-websocket"; } from "home-assistant-js-websocket";
import { stateActive } from "../common/entity/state_active";
import { blankBeforePercent } from "../common/translations/blank_before_percent"; import { blankBeforePercent } from "../common/translations/blank_before_percent";
import { FrontendLocaleData } from "./translation"; import { FrontendLocaleData } from "./translation";
@ -69,7 +70,7 @@ export function fanSpeedToPercentage(
if (speedValue === -1) { if (speedValue === -1) {
return 0; return 0;
} }
return Math.round(speedValue * step); return Math.floor(speedValue * step);
} }
export function computeFanSpeedCount(stateObj: FanEntity): number { export function computeFanSpeedCount(stateObj: FanEntity): number {
@ -99,9 +100,12 @@ export function computeFanSpeedStateDisplay(
locale: FrontendLocaleData, locale: FrontendLocaleData,
speed?: number speed?: number
) { ) {
const currentSpeed = speed ?? stateObj.attributes.percentage; const percentage = stateActive(stateObj)
? stateObj.attributes.percentage
: undefined;
const currentSpeed = speed ?? percentage;
return currentSpeed return currentSpeed
? `${Math.round(currentSpeed)}${blankBeforePercent(locale)}%` ? `${Math.floor(currentSpeed)}${blankBeforePercent(locale)}%`
: ""; : "";
} }

View File

@ -3,6 +3,7 @@ import { customElement, property, state } from "lit/decorators";
import { styleMap } from "lit/directives/style-map"; import { styleMap } from "lit/directives/style-map";
import { computeAttributeNameDisplay } from "../../../../common/entity/compute_attribute_display"; import { computeAttributeNameDisplay } from "../../../../common/entity/compute_attribute_display";
import { computeStateDisplay } from "../../../../common/entity/compute_state_display"; import { computeStateDisplay } from "../../../../common/entity/compute_state_display";
import { stateActive } from "../../../../common/entity/state_active";
import { stateColorCss } from "../../../../common/entity/state_color"; import { stateColorCss } from "../../../../common/entity/state_color";
import "../../../../components/ha-control-select"; import "../../../../components/ha-control-select";
import type { ControlSelectOption } from "../../../../components/ha-control-select"; import type { ControlSelectOption } from "../../../../components/ha-control-select";
@ -26,20 +27,25 @@ export class HaMoreInfoFanSpeed extends LitElement {
@property({ attribute: false }) public stateObj!: FanEntity; @property({ attribute: false }) public stateObj!: FanEntity;
@state() value?: number; @state() sliderValue?: number;
@state() speedValue?: FanSpeed;
protected updated(changedProp: Map<string | number | symbol, unknown>): void { protected updated(changedProp: Map<string | number | symbol, unknown>): void {
if (changedProp.has("stateObj")) { if (changedProp.has("stateObj")) {
this.value = const percentage = stateActive(this.stateObj)
this.stateObj.attributes.percentage != null ? this.stateObj.attributes.percentage ?? 0
? Math.max(Math.round(this.stateObj.attributes.percentage), 1) : 0;
: undefined; this.sliderValue = Math.max(Math.round(percentage), 0);
this.speedValue = fanPercentageToSpeed(this.stateObj, percentage);
} }
} }
private _speedValueChanged(ev: CustomEvent) { private _speedValueChanged(ev: CustomEvent) {
const speed = (ev.detail as any).value as FanSpeed; const speed = (ev.detail as any).value as FanSpeed;
this.speedValue = speed;
const percentage = fanSpeedToPercentage(this.stateObj, speed); const percentage = fanSpeedToPercentage(this.stateObj, speed);
this.hass.callService("fan", "set_percentage", { this.hass.callService("fan", "set_percentage", {
@ -52,6 +58,8 @@ export class HaMoreInfoFanSpeed extends LitElement {
const value = (ev.detail as any).value; const value = (ev.detail as any).value;
if (isNaN(value)) return; if (isNaN(value)) return;
this.sliderValue = value;
this.hass.callService("fan", "set_percentage", { this.hass.callService("fan", "set_percentage", {
entity_id: this.stateObj!.entity_id, entity_id: this.stateObj!.entity_id,
percentage: value, percentage: value,
@ -88,16 +96,11 @@ export class HaMoreInfoFanSpeed extends LitElement {
}) })
).reverse(); ).reverse();
const speed = fanPercentageToSpeed(
this.stateObj,
this.stateObj.attributes.percentage ?? 0
);
return html` return html`
<ha-control-select <ha-control-select
vertical vertical
.options=${options} .options=${options}
.value=${speed} .value=${this.speedValue}
@value-changed=${this._speedValueChanged} @value-changed=${this._speedValueChanged}
.ariaLabel=${computeAttributeNameDisplay( .ariaLabel=${computeAttributeNameDisplay(
this.hass.localize, this.hass.localize,
@ -119,7 +122,7 @@ export class HaMoreInfoFanSpeed extends LitElement {
vertical vertical
min="0" min="0"
max="100" max="100"
.value=${this.value} .value=${this.sliderValue}
.step=${this.stateObj.attributes.percentage_step ?? 1} .step=${this.stateObj.attributes.percentage_step ?? 1}
@value-changed=${this._valueChanged} @value-changed=${this._valueChanged}
.ariaLabel=${computeAttributeNameDisplay( .ariaLabel=${computeAttributeNameDisplay(

View File

@ -23,6 +23,7 @@ import {
computeAttributeValueDisplay, computeAttributeValueDisplay,
} from "../../../common/entity/compute_attribute_display"; } from "../../../common/entity/compute_attribute_display";
import { computeStateDisplay } from "../../../common/entity/compute_state_display"; import { computeStateDisplay } from "../../../common/entity/compute_state_display";
import { stateActive } from "../../../common/entity/state_active";
import { supportsFeature } from "../../../common/entity/supports-feature"; import { supportsFeature } from "../../../common/entity/supports-feature";
import "../../../components/ha-attributes"; import "../../../components/ha-attributes";
import { UNAVAILABLE } from "../../../data/entity"; import { UNAVAILABLE } from "../../../data/entity";
@ -119,7 +120,7 @@ class MoreInfoFan extends LitElement {
const liveValue = this._liveSpeed; const liveValue = this._liveSpeed;
const forcedState = const forcedState =
this._liveSpeed != null ? (this._liveSpeed ? "on" : "off") : undefined; liveValue != null ? (liveValue ? "on" : "off") : undefined;
const stateDisplay = computeStateDisplay( const stateDisplay = computeStateDisplay(
this.hass.localize, this.hass.localize,
@ -135,7 +136,7 @@ class MoreInfoFan extends LitElement {
liveValue liveValue
); );
if (positionStateDisplay) { if (positionStateDisplay && (stateActive(this.stateObj!) || liveValue)) {
return positionStateDisplay; return positionStateDisplay;
} }
return stateDisplay; return stateDisplay;

View File

@ -214,7 +214,7 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
} }
} }
if (domain === "fan" && stateActive(stateObj)) { if (domain === "fan") {
const speedStateDisplay = computeFanSpeedStateDisplay( const speedStateDisplay = computeFanSpeedStateDisplay(
stateObj as FanEntity, stateObj as FanEntity,
this.hass!.locale this.hass!.locale
@ -231,12 +231,11 @@ export class HuiTileCard extends LitElement implements LovelaceCard {
this.hass!.entities this.hass!.entities
); );
if (domain === "cover" && stateActive(stateObj)) { if (domain === "cover") {
const positionStateDisplay = computeCoverPositionStateDisplay( const positionStateDisplay = computeCoverPositionStateDisplay(
stateObj as CoverEntity, stateObj as CoverEntity,
this.hass!.locale this.hass!.locale
); );
if (positionStateDisplay) { if (positionStateDisplay) {
return `${stateDisplay}${positionStateDisplay}`; return `${stateDisplay}${positionStateDisplay}`;
} }

View File

@ -4,6 +4,7 @@ import { customElement, property, state } from "lit/decorators";
import { computeAttributeNameDisplay } from "../../../common/entity/compute_attribute_display"; import { computeAttributeNameDisplay } from "../../../common/entity/compute_attribute_display";
import { computeDomain } from "../../../common/entity/compute_domain"; import { computeDomain } from "../../../common/entity/compute_domain";
import { computeStateDisplay } from "../../../common/entity/compute_state_display"; import { computeStateDisplay } from "../../../common/entity/compute_state_display";
import { stateActive } from "../../../common/entity/state_active";
import { supportsFeature } from "../../../common/entity/supports-feature"; import { supportsFeature } from "../../../common/entity/supports-feature";
import "../../../components/ha-control-select"; import "../../../components/ha-control-select";
import type { ControlSelectOption } from "../../../components/ha-control-select"; import type { ControlSelectOption } from "../../../components/ha-control-select";
@ -12,6 +13,7 @@ import { UNAVAILABLE } from "../../../data/entity";
import { import {
computeFanSpeedCount, computeFanSpeedCount,
computeFanSpeedIcon, computeFanSpeedIcon,
FanEntity,
FanEntityFeature, FanEntityFeature,
fanPercentageToSpeed, fanPercentageToSpeed,
FanSpeed, FanSpeed,
@ -34,7 +36,7 @@ export const supportsFanSpeedTileFeature = (stateObj: HassEntity) => {
class HuiFanSpeedTileFeature extends LitElement implements LovelaceTileFeature { class HuiFanSpeedTileFeature extends LitElement implements LovelaceTileFeature {
@property({ attribute: false }) public hass?: HomeAssistant; @property({ attribute: false }) public hass?: HomeAssistant;
@property({ attribute: false }) public stateObj?: HassEntity; @property({ attribute: false }) public stateObj?: FanEntity;
@state() private _config?: FanSpeedTileFeatureConfig; @state() private _config?: FanSpeedTileFeatureConfig;
@ -79,6 +81,10 @@ class HuiFanSpeedTileFeature extends LitElement implements LovelaceTileFeature {
const speedCount = computeFanSpeedCount(this.stateObj); const speedCount = computeFanSpeedCount(this.stateObj);
const percentage = stateActive(this.stateObj)
? this.stateObj.attributes.percentage ?? 0
: 0;
if (speedCount <= FAN_SPEED_COUNT_MAX_FOR_BUTTONS) { if (speedCount <= FAN_SPEED_COUNT_MAX_FOR_BUTTONS) {
const options = FAN_SPEEDS[speedCount]!.map<ControlSelectOption>( const options = FAN_SPEEDS[speedCount]!.map<ControlSelectOption>(
(speed) => ({ (speed) => ({
@ -88,10 +94,7 @@ class HuiFanSpeedTileFeature extends LitElement implements LovelaceTileFeature {
}) })
); );
const speed = fanPercentageToSpeed( const speed = fanPercentageToSpeed(this.stateObj, percentage);
this.stateObj,
this.stateObj.attributes.percentage ?? 0
);
return html` return html`
<div class="container"> <div class="container">
@ -113,15 +116,12 @@ class HuiFanSpeedTileFeature extends LitElement implements LovelaceTileFeature {
`; `;
} }
const percentage = const value = Math.max(Math.round(percentage), 0);
this.stateObj.attributes.percentage != null
? Math.max(Math.round(this.stateObj.attributes.percentage), 0)
: undefined;
return html` return html`
<div class="container"> <div class="container">
<ha-control-slider <ha-control-slider
.value=${percentage} .value=${value}
min="0" min="0"
max="100" max="100"
.step=${this.stateObj.attributes.percentage_step ?? 1} .step=${this.stateObj.attributes.percentage_step ?? 1}