mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-20 07:46:37 +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;
|
@query("ha-card") private _card?: HaCard;
|
||||||
|
|
||||||
|
@state() private resyncSetpoint = false;
|
||||||
|
|
||||||
public getCardSize(): number {
|
public getCardSize(): number {
|
||||||
return 7;
|
return 7;
|
||||||
}
|
}
|
||||||
@ -120,11 +122,23 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
|||||||
const name =
|
const name =
|
||||||
this._config!.name ||
|
this._config!.name ||
|
||||||
computeStateName(this.hass!.states[this._config!.entity]);
|
computeStateName(this.hass!.states[this._config!.entity]);
|
||||||
const targetTemp =
|
const targetTemp = this.resyncSetpoint
|
||||||
stateObj.attributes.temperature !== null &&
|
? // If the user set position in the slider is out of sync with the entity
|
||||||
Number.isFinite(Number(stateObj.attributes.temperature))
|
// value, then rerendering the slider with same $value a second time
|
||||||
? stateObj.attributes.temperature
|
// does not move the slider. Need to set it to a different dummy value
|
||||||
: stateObj.attributes.min_temp;
|
// 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 =
|
const slider =
|
||||||
stateObj.state === UNAVAILABLE
|
stateObj.state === UNAVAILABLE
|
||||||
@ -132,8 +146,8 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
|||||||
: html`
|
: html`
|
||||||
<round-slider
|
<round-slider
|
||||||
.value=${targetTemp}
|
.value=${targetTemp}
|
||||||
.low=${stateObj.attributes.target_temp_low}
|
.low=${targetLow}
|
||||||
.high=${stateObj.attributes.target_temp_high}
|
.high=${targetHigh}
|
||||||
.min=${stateObj.attributes.min_temp}
|
.min=${stateObj.attributes.min_temp}
|
||||||
.max=${stateObj.attributes.max_temp}
|
.max=${stateObj.attributes.max_temp}
|
||||||
.step=${this._stepSize}
|
.step=${this._stepSize}
|
||||||
@ -289,7 +303,10 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
protected shouldUpdate(changedProps: PropertyValues): boolean {
|
||||||
return hasConfigOrEntityChanged(this, changedProps);
|
return (
|
||||||
|
hasConfigOrEntityChanged(this, changedProps) ||
|
||||||
|
changedProps.has("resyncSetpoint")
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected updated(changedProps: PropertyValues): void {
|
protected updated(changedProps: PropertyValues): void {
|
||||||
@ -328,7 +345,11 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public willUpdate(changedProps: PropertyValues) {
|
public willUpdate(changedProps: PropertyValues) {
|
||||||
if (!this.hass || !this._config || !changedProps.has("hass")) {
|
if (
|
||||||
|
!this.hass ||
|
||||||
|
!this._config ||
|
||||||
|
!(changedProps.has("hass") || changedProps.has("resyncSetpoint"))
|
||||||
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,7 +360,11 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
|
|||||||
|
|
||||||
const oldHass = changedProps.get("hass") as HomeAssistant | undefined;
|
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);
|
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;
|
const stateObj = this.hass!.states[this._config!.entity] as ClimateEntity;
|
||||||
|
|
||||||
if (e.detail.low) {
|
if (e.detail.low) {
|
||||||
this.hass!.callService("climate", "set_temperature", {
|
const newVal = e.detail.low;
|
||||||
entity_id: this._config!.entity,
|
this._callServiceHelper(
|
||||||
target_temp_low: e.detail.low,
|
stateObj.attributes.target_temp_low,
|
||||||
target_temp_high: stateObj.attributes.target_temp_high,
|
newVal,
|
||||||
});
|
"set_temperature",
|
||||||
|
{
|
||||||
|
target_temp_low: newVal,
|
||||||
|
target_temp_high: stateObj.attributes.target_temp_high,
|
||||||
|
}
|
||||||
|
);
|
||||||
} else if (e.detail.high) {
|
} else if (e.detail.high) {
|
||||||
this.hass!.callService("climate", "set_temperature", {
|
const newVal = e.detail.high;
|
||||||
entity_id: this._config!.entity,
|
this._callServiceHelper(
|
||||||
target_temp_low: stateObj.attributes.target_temp_low,
|
stateObj.attributes.target_temp_high,
|
||||||
target_temp_high: e.detail.high,
|
newVal,
|
||||||
});
|
"set_temperature",
|
||||||
|
{
|
||||||
|
target_temp_low: stateObj.attributes.target_temp_low,
|
||||||
|
target_temp_high: newVal,
|
||||||
|
}
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this.hass!.callService("climate", "set_temperature", {
|
const newVal = e.detail.value;
|
||||||
entity_id: this._config!.entity,
|
this._callServiceHelper(
|
||||||
temperature: e.detail.value,
|
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 {
|
static get styles(): CSSResultGroup {
|
||||||
return css`
|
return css`
|
||||||
:host {
|
:host {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user