mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-19 07:16:39 +00:00
Resync thermostat card setpoint values if service call fails (#15497)
This commit is contained in:
parent
c95a600fbb
commit
850609b1d0
@ -90,6 +90,8 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
||||
|
||||
@query("ha-card") private _card?: HaCard;
|
||||
|
||||
@state() private resyncSetpoint = false;
|
||||
|
||||
public getCardSize(): number {
|
||||
return 7;
|
||||
}
|
||||
@ -120,11 +122,23 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
||||
const name =
|
||||
this._config!.name ||
|
||||
computeStateName(this.hass!.states[this._config!.entity]);
|
||||
const targetTemp =
|
||||
stateObj.attributes.temperature !== null &&
|
||||
Number.isFinite(Number(stateObj.attributes.temperature))
|
||||
? stateObj.attributes.temperature
|
||||
: stateObj.attributes.min_temp;
|
||||
const targetTemp = this.resyncSetpoint
|
||||
? // If the user set position in the slider is out of sync with the entity
|
||||
// value, then rerendering the slider with same $value a second time
|
||||
// does not move the slider. Need to set it to a different dummy value
|
||||
// for one update cycle to force it to rerender to the desired value.
|
||||
stateObj.attributes.min_temp - 1
|
||||
: stateObj.attributes.temperature !== null &&
|
||||
Number.isFinite(Number(stateObj.attributes.temperature))
|
||||
? stateObj.attributes.temperature
|
||||
: stateObj.attributes.min_temp;
|
||||
|
||||
const targetLow = this.resyncSetpoint
|
||||
? stateObj.attributes.min_temp - 1
|
||||
: stateObj.attributes.target_temp_low;
|
||||
const targetHigh = this.resyncSetpoint
|
||||
? stateObj.attributes.min_temp - 1
|
||||
: stateObj.attributes.target_temp_high;
|
||||
|
||||
const slider =
|
||||
stateObj.state === UNAVAILABLE
|
||||
@ -132,8 +146,8 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
||||
: html`
|
||||
<round-slider
|
||||
.value=${targetTemp}
|
||||
.low=${stateObj.attributes.target_temp_low}
|
||||
.high=${stateObj.attributes.target_temp_high}
|
||||
.low=${targetLow}
|
||||
.high=${targetHigh}
|
||||
.min=${stateObj.attributes.min_temp}
|
||||
.max=${stateObj.attributes.max_temp}
|
||||
.step=${this._stepSize}
|
||||
@ -289,7 +303,10 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
||||
}
|
||||
|
||||
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||
return hasConfigOrEntityChanged(this, changedProps);
|
||||
return (
|
||||
hasConfigOrEntityChanged(this, changedProps) ||
|
||||
changedProps.has("resyncSetpoint")
|
||||
);
|
||||
}
|
||||
|
||||
protected updated(changedProps: PropertyValues): void {
|
||||
@ -328,7 +345,11 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
||||
}
|
||||
|
||||
public willUpdate(changedProps: PropertyValues) {
|
||||
if (!this.hass || !this._config || !changedProps.has("hass")) {
|
||||
if (
|
||||
!this.hass ||
|
||||
!this._config ||
|
||||
!(changedProps.has("hass") || changedProps.has("resyncSetpoint"))
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -339,7 +360,11 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
||||
|
||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
||||
|
||||
if (!oldHass || oldHass.states[this._config.entity] !== stateObj) {
|
||||
if (
|
||||
!oldHass ||
|
||||
oldHass.states[this._config.entity] !== stateObj ||
|
||||
(changedProps.has("resyncSetpoint") && this.resyncSetpoint)
|
||||
) {
|
||||
this._setTemp = this._getSetTemp(stateObj);
|
||||
}
|
||||
}
|
||||
@ -410,22 +435,35 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
||||
const stateObj = this.hass!.states[this._config!.entity] as ClimateEntity;
|
||||
|
||||
if (e.detail.low) {
|
||||
this.hass!.callService("climate", "set_temperature", {
|
||||
entity_id: this._config!.entity,
|
||||
target_temp_low: e.detail.low,
|
||||
target_temp_high: stateObj.attributes.target_temp_high,
|
||||
});
|
||||
const newVal = e.detail.low;
|
||||
this._callServiceHelper(
|
||||
stateObj.attributes.target_temp_low,
|
||||
newVal,
|
||||
"set_temperature",
|
||||
{
|
||||
target_temp_low: newVal,
|
||||
target_temp_high: stateObj.attributes.target_temp_high,
|
||||
}
|
||||
);
|
||||
} else if (e.detail.high) {
|
||||
this.hass!.callService("climate", "set_temperature", {
|
||||
entity_id: this._config!.entity,
|
||||
target_temp_low: stateObj.attributes.target_temp_low,
|
||||
target_temp_high: e.detail.high,
|
||||
});
|
||||
const newVal = e.detail.high;
|
||||
this._callServiceHelper(
|
||||
stateObj.attributes.target_temp_high,
|
||||
newVal,
|
||||
"set_temperature",
|
||||
{
|
||||
target_temp_low: stateObj.attributes.target_temp_low,
|
||||
target_temp_high: newVal,
|
||||
}
|
||||
);
|
||||
} else {
|
||||
this.hass!.callService("climate", "set_temperature", {
|
||||
entity_id: this._config!.entity,
|
||||
temperature: e.detail.value,
|
||||
});
|
||||
const newVal = e.detail.value;
|
||||
this._callServiceHelper(
|
||||
stateObj!.attributes.temperature,
|
||||
newVal,
|
||||
"set_temperature",
|
||||
{ temperature: newVal }
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -459,6 +497,44 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
||||
});
|
||||
}
|
||||
|
||||
private async _callServiceHelper(
|
||||
oldVal: unknown,
|
||||
newVal: unknown,
|
||||
service: string,
|
||||
data: {
|
||||
entity_id?: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
) {
|
||||
if (oldVal === newVal) {
|
||||
return;
|
||||
}
|
||||
|
||||
data.entity_id = this._config!.entity;
|
||||
|
||||
await this.hass!.callService("climate", service, data);
|
||||
|
||||
// After updating temperature, wait 2s and check if the values
|
||||
// from call service are reflected in the entity. If not, resync
|
||||
// the slider to the entity values.
|
||||
await new Promise((resolve) => setTimeout(resolve, 2000));
|
||||
|
||||
const newState = this.hass!.states[this._config!.entity] as ClimateEntity;
|
||||
delete data.entity_id;
|
||||
|
||||
if (
|
||||
Object.entries(data).every(
|
||||
([key, value]) => newState.attributes[key] === value
|
||||
)
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.resyncSetpoint = true;
|
||||
await this.updateComplete;
|
||||
this.resyncSetpoint = false;
|
||||
}
|
||||
|
||||
static get styles(): CSSResultGroup {
|
||||
return css`
|
||||
:host {
|
||||
|
Loading…
x
Reference in New Issue
Block a user