mirror of
https://github.com/home-assistant/frontend.git
synced 2025-07-24 01:36:49 +00:00
HVAC frontend. (#56)
* Initial HVAC frontend * Fixes * Fix * Remove unused code * Clean up more info hvac * Reintroduce HVAC state summary * State Summary wrong attribute name
This commit is contained in:
parent
6a8e6a5a08
commit
7e6d5e2ff7
@ -12,6 +12,7 @@
|
|||||||
<link rel='import' href='more-info-updater.html'>
|
<link rel='import' href='more-info-updater.html'>
|
||||||
<link rel='import' href='more-info-alarm_control_panel.html'>
|
<link rel='import' href='more-info-alarm_control_panel.html'>
|
||||||
<link rel='import' href='more-info-lock.html'>
|
<link rel='import' href='more-info-lock.html'>
|
||||||
|
<link rel='import' href='more-info-hvac.html'>
|
||||||
|
|
||||||
<dom-module id='more-info-content'>
|
<dom-module id='more-info-content'>
|
||||||
<style>
|
<style>
|
||||||
|
@ -15,6 +15,7 @@ require('./more-info-camera');
|
|||||||
require('./more-info-updater');
|
require('./more-info-updater');
|
||||||
require('./more-info-alarm_control_panel');
|
require('./more-info-alarm_control_panel');
|
||||||
require('./more-info-lock');
|
require('./more-info-lock');
|
||||||
|
require('./more-info-hvac');
|
||||||
|
|
||||||
export default new Polymer({
|
export default new Polymer({
|
||||||
is: 'more-info-content',
|
is: 'more-info-content',
|
||||||
|
131
src/more-infos/more-info-hvac.html
Normal file
131
src/more-infos/more-info-hvac.html
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
<link rel='import' href='../../bower_components/polymer/polymer.html'>
|
||||||
|
<link rel='import' href='../../bower_components/paper-slider/paper-slider.html'>
|
||||||
|
<link rel='import' href='../../bower_components/paper-toggle-button/paper-toggle-button.html'>
|
||||||
|
|
||||||
|
<dom-module id='more-info-hvac'>
|
||||||
|
<template>
|
||||||
|
<style is="custom-style" include="iron-flex"></style>
|
||||||
|
<style>
|
||||||
|
:host {
|
||||||
|
color: var(--primary-text-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-away_mode,
|
||||||
|
.container-aux_heat,
|
||||||
|
.container-temperature,
|
||||||
|
.container-humidity,
|
||||||
|
.container-operation_list,
|
||||||
|
.container-fan_list,
|
||||||
|
.container-swing_list {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.has-away_mode .container-away_mode,
|
||||||
|
.has-aux_heat .container-aux_heat,
|
||||||
|
.has-temperature .container-temperature,
|
||||||
|
.has-humidity .container-humidity,
|
||||||
|
.has-operation_list .container-operation_list,
|
||||||
|
.has-fan_list .container-fan_list,
|
||||||
|
.has-swing_list .container-swing_list {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container-operation_list iron-icon,
|
||||||
|
.container-fan_list iron-icon,
|
||||||
|
.container-swing_list iron-icon {
|
||||||
|
margin: 22px 16px 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
paper-dropdown-menu {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.single-row {
|
||||||
|
padding: 8px 0;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<div class$='[[computeClassNames(stateObj)]]'>
|
||||||
|
<div class='container-temperature'>
|
||||||
|
<div class='center horizontal layout single-row'>
|
||||||
|
<div class='flex'>Target Temperature</div>
|
||||||
|
<paper-slider
|
||||||
|
min='[[stateObj.attributes.min_temp]]'
|
||||||
|
max='[[stateObj.attributes.max_temp]]'
|
||||||
|
step='0.5' pin
|
||||||
|
value='[[stateObj.attributes.temperature]]'
|
||||||
|
on-change='targetTemperatureSliderChanged'>
|
||||||
|
</paper-slider>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='container-humidity'>
|
||||||
|
<div class='center horizontal layout single-row'>
|
||||||
|
<div class='flex'>Target Humidity</div>
|
||||||
|
<paper-slider
|
||||||
|
min='[[stateObj.attributes.min_humidity]]'
|
||||||
|
max='[[stateObj.attributes.max_humidity]]'
|
||||||
|
step='1' pin
|
||||||
|
value='[[stateObj.attributes.humidity]]'
|
||||||
|
on-change='targetHumiditySliderChanged'>
|
||||||
|
</paper-slider>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='container-operation_list'>
|
||||||
|
<div class='controls'>
|
||||||
|
<paper-dropdown-menu label-float label='Operation'>
|
||||||
|
<paper-menu class="dropdown-content" selected="{{operationIndex}}">
|
||||||
|
<template is='dom-repeat'
|
||||||
|
items='[[stateObj.attributes.operation_list]]'>
|
||||||
|
<paper-item>[[item]]</paper-item>
|
||||||
|
</template>
|
||||||
|
</paper-menu>
|
||||||
|
</paper-dropdown-menu>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='container-fan_list'>
|
||||||
|
<paper-dropdown-menu label-float label='Fan Mode'>
|
||||||
|
<paper-menu class="dropdown-content" selected="{{fanIndex}}">
|
||||||
|
<template is='dom-repeat'
|
||||||
|
items='[[stateObj.attributes.fan_list]]'>
|
||||||
|
<paper-item>[[item]]</paper-item>
|
||||||
|
</template>
|
||||||
|
</paper-menu>
|
||||||
|
</paper-dropdown-menu>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='container-swing_list'>
|
||||||
|
<paper-dropdown-menu label-float label='Swing Mode'>
|
||||||
|
<paper-menu class="dropdown-content" selected="{{swingIndex}}">
|
||||||
|
<template is='dom-repeat'
|
||||||
|
items='[[stateObj.attributes.swing_list]]'>
|
||||||
|
<paper-item>[[item]]</paper-item>
|
||||||
|
</template>
|
||||||
|
</paper-menu>
|
||||||
|
</paper-dropdown-menu>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='container-away_mode'>
|
||||||
|
<div class='center horizontal layout single-row'>
|
||||||
|
<div class='flex'>Away Mode</div>
|
||||||
|
<paper-toggle-button
|
||||||
|
checked='[[awayToggleChecked]]'
|
||||||
|
on-change='awayToggleChanged'>
|
||||||
|
</paper-toggle-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class='container-aux_heat'>
|
||||||
|
<div class='center horizontal layout single-row'>
|
||||||
|
<div class='flex'>Aux Heat</div>
|
||||||
|
<paper-toggle-button
|
||||||
|
checked='[[auxToggleChecked]]'
|
||||||
|
on-change='auxToggleChanged'>
|
||||||
|
</paper-toggle-button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</dom-module>
|
160
src/more-infos/more-info-hvac.js
Normal file
160
src/more-infos/more-info-hvac.js
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
import hass from '../util/home-assistant-js-instance';
|
||||||
|
|
||||||
|
import Polymer from '../polymer';
|
||||||
|
import attributeClassNames from '../util/attribute-class-names';
|
||||||
|
|
||||||
|
const { serviceActions } = hass;
|
||||||
|
const ATTRIBUTE_CLASSES = [
|
||||||
|
'away_mode',
|
||||||
|
'aux_heat',
|
||||||
|
'temperature',
|
||||||
|
'humidity',
|
||||||
|
'operation_list',
|
||||||
|
'fan_list',
|
||||||
|
'swing_list',
|
||||||
|
];
|
||||||
|
|
||||||
|
export default new Polymer({
|
||||||
|
is: 'more-info-hvac',
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
stateObj: {
|
||||||
|
type: Object,
|
||||||
|
observer: 'stateObjChanged',
|
||||||
|
},
|
||||||
|
|
||||||
|
operationIndex: {
|
||||||
|
type: Number,
|
||||||
|
value: -1,
|
||||||
|
observer: 'handleOperationmodeChanged',
|
||||||
|
},
|
||||||
|
|
||||||
|
fanIndex: {
|
||||||
|
type: Number,
|
||||||
|
value: -1,
|
||||||
|
observer: 'handleFanmodeChanged',
|
||||||
|
},
|
||||||
|
|
||||||
|
swingIndex: {
|
||||||
|
type: Number,
|
||||||
|
value: -1,
|
||||||
|
observer: 'handleSwingmodeChanged',
|
||||||
|
},
|
||||||
|
|
||||||
|
awayToggleChecked: {
|
||||||
|
type: Boolean,
|
||||||
|
},
|
||||||
|
|
||||||
|
auxToggleChecked: {
|
||||||
|
type: Boolean,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
stateObjChanged(newVal) {
|
||||||
|
this.awayToggleChecked = newVal.attributes.away_mode === 'on';
|
||||||
|
this.auxheatToggleChecked = newVal.attributes.aux_heat === 'on';
|
||||||
|
|
||||||
|
if (newVal.attributes.fan_list) {
|
||||||
|
this.fanIndex = newVal.attributes.fan_list.indexOf(
|
||||||
|
newVal.attributes.fan_mode);
|
||||||
|
} else {
|
||||||
|
this.fanIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newVal.attributes.operation_list) {
|
||||||
|
this.operationIndex = newVal.attributes.operation_list.indexOf(
|
||||||
|
newVal.attributes.operation_mode);
|
||||||
|
} else {
|
||||||
|
this.operationIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (newVal.attributes.swing_list) {
|
||||||
|
this.swingIndex = newVal.attributes.swing_list.indexOf(
|
||||||
|
newVal.attributes.swing_mode);
|
||||||
|
} else {
|
||||||
|
this.swingIndex = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.async(() => this.fire('iron-resize'), 500);
|
||||||
|
},
|
||||||
|
|
||||||
|
computeClassNames(stateObj) {
|
||||||
|
return `more-info-hvac ${attributeClassNames(stateObj, ATTRIBUTE_CLASSES)}`;
|
||||||
|
},
|
||||||
|
|
||||||
|
targetTemperatureSliderChanged(ev) {
|
||||||
|
const temperature = ev.target.value;
|
||||||
|
|
||||||
|
if (temperature === this.stateObj.attributes.temperature) return;
|
||||||
|
|
||||||
|
this.callServiceHelper('set_temperature', { temperature });
|
||||||
|
},
|
||||||
|
|
||||||
|
targetHumiditySliderChanged(ev) {
|
||||||
|
const humidity = ev.target.value;
|
||||||
|
|
||||||
|
if (humidity === this.stateObj.attributes.humidity) return;
|
||||||
|
|
||||||
|
this.callServiceHelper('set_humidity', { humidity });
|
||||||
|
},
|
||||||
|
|
||||||
|
awayToggleChanged(ev) {
|
||||||
|
const oldVal = this.stateObj.attributes.away_mode === 'on';
|
||||||
|
const newVal = ev.target.checked;
|
||||||
|
|
||||||
|
if (oldVal === newVal) return;
|
||||||
|
|
||||||
|
this.callServiceHelper('set_away_mode', { away_mode: newVal });
|
||||||
|
},
|
||||||
|
|
||||||
|
auxToggleChanged(ev) {
|
||||||
|
const oldVal = this.stateObj.attributes.aux_heat === 'on';
|
||||||
|
const newVal = ev.target.checked;
|
||||||
|
|
||||||
|
if (oldVal === newVal) return;
|
||||||
|
|
||||||
|
this.callServiceHelper('set_aux_heat', { aux_heat: newVal });
|
||||||
|
},
|
||||||
|
|
||||||
|
handleFanmodeChanged(fanIndex) {
|
||||||
|
// Selected Option will transition to '' before transitioning to new value
|
||||||
|
if (fanIndex === '' || fanIndex === -1) return;
|
||||||
|
|
||||||
|
const fanInput = this.stateObj.attributes.fan_list[fanIndex];
|
||||||
|
if (fanInput === this.stateObj.attributes.fan_mode) return;
|
||||||
|
|
||||||
|
this.callServiceHelper('set_fan_mode', { fan_mode: fanInput });
|
||||||
|
},
|
||||||
|
|
||||||
|
handleOperationmodeChanged(operationIndex) {
|
||||||
|
// Selected Option will transition to '' before transitioning to new value
|
||||||
|
if (operationIndex === '' || operationIndex === -1) return;
|
||||||
|
|
||||||
|
const operationInput = this.stateObj.attributes.operation_list[operationIndex];
|
||||||
|
if (operationInput === this.stateObj.attributes.operation_mode) return;
|
||||||
|
|
||||||
|
this.callServiceHelper('set_operation_mode', { operation_mode: operationInput });
|
||||||
|
},
|
||||||
|
|
||||||
|
handleSwingmodeChanged(swingIndex) {
|
||||||
|
// Selected Option will transition to '' before transitioning to new value
|
||||||
|
if (swingIndex === '' || swingIndex === -1) return;
|
||||||
|
|
||||||
|
const swingInput = this.stateObj.attributes.swing_list[swingIndex];
|
||||||
|
if (swingInput === this.stateObj.attributes.swing_mode) return;
|
||||||
|
|
||||||
|
this.callServiceHelper('set_swing_mode', { swing_mode: swingInput });
|
||||||
|
},
|
||||||
|
|
||||||
|
callServiceHelper(service, data) {
|
||||||
|
// We call stateChanged after a successful call to re-sync the inputs
|
||||||
|
// with the state. It will be out of sync if our service call did not
|
||||||
|
// result in the entity to be turned on. Since the state is not changing,
|
||||||
|
// the resync is not called automatic.
|
||||||
|
/* eslint-disable no-param-reassign */
|
||||||
|
data.entity_id = this.stateObj.entityId;
|
||||||
|
/* eslint-enable no-param-reassign */
|
||||||
|
serviceActions.callService('hvac', service, data)
|
||||||
|
.then(() => this.stateObjChanged(this.stateObj));
|
||||||
|
},
|
||||||
|
});
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
<link rel="import" href="state-card-configurator.html">
|
<link rel="import" href="state-card-configurator.html">
|
||||||
<link rel="import" href="state-card-display.html">
|
<link rel="import" href="state-card-display.html">
|
||||||
|
<link rel="import" href="state-card-hvac.html">
|
||||||
<link rel="import" href="state-card-input_select.html">
|
<link rel="import" href="state-card-input_select.html">
|
||||||
<link rel="import" href="state-card-input_slider.html">
|
<link rel="import" href="state-card-input_slider.html">
|
||||||
<link rel="import" href="state-card-media_player.html">
|
<link rel="import" href="state-card-media_player.html">
|
||||||
|
@ -5,6 +5,7 @@ import dynamicContentUpdater from '../util/dynamic-content-updater';
|
|||||||
|
|
||||||
require('./state-card-configurator');
|
require('./state-card-configurator');
|
||||||
require('./state-card-display');
|
require('./state-card-display');
|
||||||
|
require('./state-card-hvac');
|
||||||
require('./state-card-input_select');
|
require('./state-card-input_select');
|
||||||
require('./state-card-input_slider');
|
require('./state-card-input_slider');
|
||||||
require('./state-card-media_player');
|
require('./state-card-media_player');
|
||||||
|
@ -6,7 +6,7 @@ export default new Polymer({
|
|||||||
is: 'state-card-display',
|
is: 'state-card-display',
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
detailed: {
|
inDialog: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
},
|
},
|
||||||
|
25
src/state-summary/state-card-hvac.html
Executable file
25
src/state-summary/state-card-hvac.html
Executable file
@ -0,0 +1,25 @@
|
|||||||
|
<link rel="import" href="../../bower_components/polymer/polymer.html">
|
||||||
|
|
||||||
|
<link rel="import" href="../components/state-info.html">
|
||||||
|
|
||||||
|
<dom-module id="state-card-hvac">
|
||||||
|
<style is="custom-style" include="iron-flex iron-flex-alignment"></style>
|
||||||
|
<style>
|
||||||
|
.state {
|
||||||
|
@apply(--paper-font-body1);
|
||||||
|
color: var(--primary-text-color);
|
||||||
|
|
||||||
|
margin-left: 16px;
|
||||||
|
text-transform: capitalize;
|
||||||
|
text-align: right;
|
||||||
|
line-height: 40px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class='horizontal justified layout'>
|
||||||
|
<state-info state-obj="[[stateObj]]" in-dialog='[[inDialog]]'></state-info>
|
||||||
|
<div class='state'>[[stateObj.state]]</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</dom-module>
|
18
src/state-summary/state-card-hvac.js
Normal file
18
src/state-summary/state-card-hvac.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import Polymer from '../polymer';
|
||||||
|
|
||||||
|
require('../components/state-info');
|
||||||
|
|
||||||
|
export default new Polymer({
|
||||||
|
is: 'state-card-hvac',
|
||||||
|
|
||||||
|
properties: {
|
||||||
|
inDialog: {
|
||||||
|
type: Boolean,
|
||||||
|
value: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
stateObj: {
|
||||||
|
type: Object,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
@ -9,7 +9,7 @@ export default new Polymer({
|
|||||||
is: 'state-card-input_select',
|
is: 'state-card-input_select',
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
detailed: {
|
inDialog: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
},
|
},
|
||||||
|
@ -9,7 +9,7 @@ export default new Polymer({
|
|||||||
is: 'state-card-input_slider',
|
is: 'state-card-input_slider',
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
detailed: {
|
inDialog: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
},
|
},
|
||||||
|
@ -8,7 +8,7 @@ export default new Polymer({
|
|||||||
is: 'state-card-media_player',
|
is: 'state-card-media_player',
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
detailed: {
|
inDialog: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
},
|
},
|
||||||
|
@ -10,7 +10,7 @@ export default new Polymer({
|
|||||||
is: 'state-card-rollershutter',
|
is: 'state-card-rollershutter',
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
detailed: {
|
inDialog: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
},
|
},
|
||||||
|
@ -9,7 +9,7 @@ export default new Polymer({
|
|||||||
is: 'state-card-scene',
|
is: 'state-card-scene',
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
detailed: {
|
inDialog: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
},
|
},
|
||||||
|
@ -10,7 +10,7 @@ export default new Polymer({
|
|||||||
is: 'state-card-script',
|
is: 'state-card-script',
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
detailed: {
|
inDialog: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
},
|
},
|
||||||
|
@ -6,7 +6,7 @@ export default new Polymer({
|
|||||||
is: 'state-card-thermostat',
|
is: 'state-card-thermostat',
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
detailed: {
|
inDialog: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
},
|
},
|
||||||
|
@ -7,7 +7,7 @@ export default new Polymer({
|
|||||||
is: 'state-card-toggle',
|
is: 'state-card-toggle',
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
detailed: {
|
inDialog: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
},
|
},
|
||||||
|
@ -6,7 +6,7 @@ export default new Polymer({
|
|||||||
is: 'state-card-weblink',
|
is: 'state-card-weblink',
|
||||||
|
|
||||||
properties: {
|
properties: {
|
||||||
detailed: {
|
inDialog: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
value: false,
|
value: false,
|
||||||
},
|
},
|
||||||
|
@ -32,6 +32,9 @@ export default function domainIcon(domain, state) {
|
|||||||
case 'homeassistant':
|
case 'homeassistant':
|
||||||
return 'mdi:home';
|
return 'mdi:home';
|
||||||
|
|
||||||
|
case 'hvac':
|
||||||
|
return 'mdi:air-conditioner';
|
||||||
|
|
||||||
case 'input_boolean':
|
case 'input_boolean':
|
||||||
return 'mdi:drawing';
|
return 'mdi:drawing';
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ import canToggle from './can-toggle';
|
|||||||
|
|
||||||
const DOMAINS_WITH_CARD = [
|
const DOMAINS_WITH_CARD = [
|
||||||
'configurator',
|
'configurator',
|
||||||
|
'hvac',
|
||||||
'input_select',
|
'input_select',
|
||||||
'input_slider',
|
'input_slider',
|
||||||
'media_player',
|
'media_player',
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
const DOMAINS_WITH_MORE_INFO = [
|
const DOMAINS_WITH_MORE_INFO = [
|
||||||
'light', 'group', 'sun', 'configurator', 'thermostat', 'script',
|
'light', 'group', 'sun', 'configurator', 'thermostat', 'script',
|
||||||
'media_player', 'camera', 'updater', 'alarm_control_panel', 'lock',
|
'media_player', 'camera', 'updater', 'alarm_control_panel', 'lock',
|
||||||
|
'hvac',
|
||||||
];
|
];
|
||||||
|
|
||||||
export default function stateMoreInfoType(state) {
|
export default function stateMoreInfoType(state) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user