Compare commits

...

4 Commits

Author SHA1 Message Date
Zack Arnett
9a49956e98 Updates 2020-09-18 16:00:55 -05:00
Zack Barett
640d6e9549 Merge branch 'dev' into Thermostat-card 2020-09-18 15:26:03 -05:00
Zack Arnett
cb043200cc do calc once 2020-08-12 10:58:53 -05:00
Zack Arnett
6b46949eb7 thermostat changes 2020-08-10 17:15:55 -05:00

View File

@@ -19,6 +19,7 @@ import { UNIT_F } from "../../../common/const";
import { applyThemesOnElement } from "../../../common/dom/apply_themes_on_element";
import { fireEvent } from "../../../common/dom/fire_event";
import { computeStateName } from "../../../common/entity/compute_state_name";
import { debounce } from "../../../common/util/debounce";
import "../../../components/ha-card";
import type { HaCard } from "../../../components/ha-card";
import "../../../components/ha-icon-button";
@@ -30,8 +31,10 @@ import {
} from "../../../data/climate";
import { UNAVAILABLE } from "../../../data/entity";
import { HomeAssistant } from "../../../types";
import { actionHandler } from "../common/directives/action-handler-directive";
import { findEntities } from "../common/find-entites";
import { hasConfigOrEntityChanged } from "../common/has-changed";
import { installResizeObserver } from "../common/install-resize-observer";
import { createEntityNotFoundWarning } from "../components/hui-warning";
import { LovelaceCard, LovelaceCardEditor } from "../types";
import { ThermostatCardConfig } from "./types";
@@ -79,8 +82,25 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
@internalProperty() private _setTemp?: number | number[];
@internalProperty() private _lastSetMode?: number;
@internalProperty() private _narrow = false;
@query("ha-card") private _card?: HaCard;
private _resizeObserver?: ResizeObserver;
public connectedCallback(): void {
super.connectedCallback();
this.updateComplete.then(() => this._attachObserver());
}
public disconnectedCallback(): void {
if (this._resizeObserver) {
this._resizeObserver.disconnect();
}
}
public getCardSize(): number {
return 5;
}
@@ -119,7 +139,7 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
const slider =
stateObj.state === UNAVAILABLE
? html` <round-slider disabled="true"></round-slider> `
? html`<round-slider disabled="true"></round-slider>`
: html`
<round-slider
.value=${targetTemp}
@@ -214,6 +234,7 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
<ha-card
class=${classMap({
[mode]: true,
narrow: this._narrow,
})}
>
<mwc-icon-button
@@ -237,12 +258,40 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
</div>
</div>
<div id="info">
<div id="modes">
${(stateObj.attributes.hvac_modes || [])
.concat()
.sort(compareClimateHvacModes)
.map((modeItem) => this._renderIcon(modeItem, mode))}
</div>
${!this._narrow
? html`
<div class="step-icons">
<ha-icon-button
class="minus step-icon ${classMap({
disabled:
Array.isArray(this._setTemp) && !this._lastSetMode,
})}"
icon="hass:minus"
@action=${this._handleStepAction}
.actionHandler=${actionHandler()}
tempDiff="-1"
tabindex="0"
></ha-icon-button
><ha-icon-button
class="plus step-icon ${classMap({
disabled:
Array.isArray(this._setTemp) && !this._lastSetMode,
})}"
icon="hass:plus"
@action=${this._handleStepAction}
.actionHandler=${actionHandler()}
tabindex="0"
tempDiff="1"
></ha-icon-button>
</div>
<div id="modes">
${(stateObj.attributes.hvac_modes || [])
.concat()
.sort(compareClimateHvacModes)
.map((modeItem) => this._renderIcon(modeItem, mode))}
</div>
`
: ""}
${name}
</div>
</div>
@@ -254,6 +303,11 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
return hasConfigOrEntityChanged(this, changedProps);
}
protected firstUpdated(): void {
this._measureCard();
this._attachObserver();
}
protected updated(changedProps: PropertyValues): void {
super.updated(changedProps);
@@ -356,12 +410,14 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
const stateObj = this.hass!.states[this._config!.entity] as ClimateEntity;
if (e.detail.low) {
this._lastSetMode = 0;
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,
});
} else if (e.detail.high) {
this._lastSetMode = 1;
this.hass!.callService("climate", "set_temperature", {
entity_id: this._config!.entity,
target_temp_low: stateObj.attributes.target_temp_low,
@@ -381,10 +437,11 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
}
return html`
<ha-icon-button
class="${classMap({ "selected-icon": currentMode === mode })}"
.mode="${mode}"
.icon="${modeIcons[mode]}"
@click=${this._handleAction}
class=${classMap({ "selected-icon": currentMode === mode })}
.mode=${mode}
.icon=${modeIcons[mode]}
@action=${this._handleAction}
.actionHandler=${actionHandler()}
tabindex="0"
></ha-icon-button>
`;
@@ -403,6 +460,53 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
});
}
private _handleStepAction(e: MouseEvent): void {
const stateObj = this.hass!.states[this._config!.entity] as ClimateEntity;
const tempChange = (e.currentTarget as any).tempDiff * this._stepSize;
if (!Array.isArray(this._setTemp!)) {
this.hass!.callService("climate", "set_temperature", {
entity_id: this._config!.entity,
temperature: (this._setTemp! as number) + tempChange,
});
} else if (this._lastSetMode === 0) {
this.hass!.callService("climate", "set_temperature", {
entity_id: this._config!.entity,
target_temp_low: this._setTemp![this._lastSetMode] + tempChange,
target_temp_high: stateObj.attributes.target_temp_high,
});
} else if (this._lastSetMode === 1) {
this.hass!.callService("climate", "set_temperature", {
entity_id: this._config!.entity,
target_temp_low: stateObj.attributes.target_temp_low,
target_temp_high: this._setTemp![this._lastSetMode] + tempChange,
});
}
}
private async _attachObserver(): Promise<void> {
if (!this._resizeObserver) {
await installResizeObserver();
this._resizeObserver = new ResizeObserver(
debounce(() => this._measureCard(), 250, false)
);
}
const card = this.shadowRoot!.querySelector("ha-card");
// If we show an error or warning there is no ha-card
if (!card) {
return;
}
this._resizeObserver.observe(card);
}
private _measureCard() {
if (!this.isConnected) {
return;
}
this._narrow = this.offsetWidth < 174;
}
static get styles(): CSSResult {
return css`
:host {
@@ -531,14 +635,29 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
}
#info {
display: flex-vertical;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
text-align: center;
padding: 16px;
margin-top: -60px;
margin-top: -55px;
font-size: var(--name-font-size);
}
.narrow #info {
margin-top: -40px;
}
#modes {
--mdc-icon-button-size: 32px;
display: flex;
flex-wrap: wrap;
justify-content: space-around;
width: 100%;
padding-top: 8px;
}
#modes > * {
color: var(--disabled-text-color);
cursor: pointer;
@@ -552,6 +671,36 @@ export class HuiThermostatCard extends LitElement implements LovelaceCard {
text {
fill: var(--primary-text-color);
}
.step-icons {
display: flex;
justify-content: space-around;
max-width: 250px;
min-width: 100px;
width: 100%;
}
.step-icon {
--mdc-icon-button-size: 28px;
--mdc-icon-size: 18px;
border-radius: 50%;
border: 1px solid;
}
.step-icon.disabled {
border-color: var(--disabled-text-color);
color: var(--disabled-text-color);
}
.minus {
border-color: var(--cool-color);
color: var(--cool-color);
}
.plus {
border-color: var(--heat-color);
color: var(--heat-color);
}
`;
}
}