diff --git a/src/more-infos/more-info-content.html b/src/more-infos/more-info-content.html
index 37411a2d30..30bb3556f8 100644
--- a/src/more-infos/more-info-content.html
+++ b/src/more-infos/more-info-content.html
@@ -12,6 +12,7 @@
+
+
+
+
+
+
+
Target Temperature
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/more-infos/more-info-hvac.js b/src/more-infos/more-info-hvac.js
new file mode 100644
index 0000000000..f52b0154fd
--- /dev/null
+++ b/src/more-infos/more-info-hvac.js
@@ -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));
+ },
+});
diff --git a/src/state-summary/state-card-content.html b/src/state-summary/state-card-content.html
index a80034ba4d..8267198cc8 100644
--- a/src/state-summary/state-card-content.html
+++ b/src/state-summary/state-card-content.html
@@ -2,6 +2,7 @@
+
diff --git a/src/state-summary/state-card-content.js b/src/state-summary/state-card-content.js
index 0e81649d20..56048ff2ac 100644
--- a/src/state-summary/state-card-content.js
+++ b/src/state-summary/state-card-content.js
@@ -5,6 +5,7 @@ import dynamicContentUpdater from '../util/dynamic-content-updater';
require('./state-card-configurator');
require('./state-card-display');
+require('./state-card-hvac');
require('./state-card-input_select');
require('./state-card-input_slider');
require('./state-card-media_player');
diff --git a/src/state-summary/state-card-display.js b/src/state-summary/state-card-display.js
index 1ad21227f1..bbc23a06b5 100644
--- a/src/state-summary/state-card-display.js
+++ b/src/state-summary/state-card-display.js
@@ -6,7 +6,7 @@ export default new Polymer({
is: 'state-card-display',
properties: {
- detailed: {
+ inDialog: {
type: Boolean,
value: false,
},
diff --git a/src/state-summary/state-card-hvac.html b/src/state-summary/state-card-hvac.html
new file mode 100755
index 0000000000..51bbfaa856
--- /dev/null
+++ b/src/state-summary/state-card-hvac.html
@@ -0,0 +1,25 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/state-summary/state-card-hvac.js b/src/state-summary/state-card-hvac.js
new file mode 100644
index 0000000000..9ed2f76ace
--- /dev/null
+++ b/src/state-summary/state-card-hvac.js
@@ -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,
+ },
+ },
+});
diff --git a/src/state-summary/state-card-input_select.js b/src/state-summary/state-card-input_select.js
index d521dbb289..f53cb52c50 100644
--- a/src/state-summary/state-card-input_select.js
+++ b/src/state-summary/state-card-input_select.js
@@ -9,7 +9,7 @@ export default new Polymer({
is: 'state-card-input_select',
properties: {
- detailed: {
+ inDialog: {
type: Boolean,
value: false,
},
diff --git a/src/state-summary/state-card-input_slider.js b/src/state-summary/state-card-input_slider.js
index 355de56af6..b5cf8b15da 100644
--- a/src/state-summary/state-card-input_slider.js
+++ b/src/state-summary/state-card-input_slider.js
@@ -9,7 +9,7 @@ export default new Polymer({
is: 'state-card-input_slider',
properties: {
- detailed: {
+ inDialog: {
type: Boolean,
value: false,
},
diff --git a/src/state-summary/state-card-media_player.js b/src/state-summary/state-card-media_player.js
index 4175cf740c..108c63d8bb 100644
--- a/src/state-summary/state-card-media_player.js
+++ b/src/state-summary/state-card-media_player.js
@@ -8,7 +8,7 @@ export default new Polymer({
is: 'state-card-media_player',
properties: {
- detailed: {
+ inDialog: {
type: Boolean,
value: false,
},
diff --git a/src/state-summary/state-card-rollershutter.js b/src/state-summary/state-card-rollershutter.js
index 032dc6c8bd..fa2d5ecd89 100644
--- a/src/state-summary/state-card-rollershutter.js
+++ b/src/state-summary/state-card-rollershutter.js
@@ -10,7 +10,7 @@ export default new Polymer({
is: 'state-card-rollershutter',
properties: {
- detailed: {
+ inDialog: {
type: Boolean,
value: false,
},
diff --git a/src/state-summary/state-card-scene.js b/src/state-summary/state-card-scene.js
index 5594c559ba..a8b4b9ef4c 100644
--- a/src/state-summary/state-card-scene.js
+++ b/src/state-summary/state-card-scene.js
@@ -9,7 +9,7 @@ export default new Polymer({
is: 'state-card-scene',
properties: {
- detailed: {
+ inDialog: {
type: Boolean,
value: false,
},
diff --git a/src/state-summary/state-card-script.js b/src/state-summary/state-card-script.js
index 3c81b03080..4512a8ab21 100644
--- a/src/state-summary/state-card-script.js
+++ b/src/state-summary/state-card-script.js
@@ -10,7 +10,7 @@ export default new Polymer({
is: 'state-card-script',
properties: {
- detailed: {
+ inDialog: {
type: Boolean,
value: false,
},
diff --git a/src/state-summary/state-card-thermostat.js b/src/state-summary/state-card-thermostat.js
index e103ab967b..c174d81286 100644
--- a/src/state-summary/state-card-thermostat.js
+++ b/src/state-summary/state-card-thermostat.js
@@ -6,7 +6,7 @@ export default new Polymer({
is: 'state-card-thermostat',
properties: {
- detailed: {
+ inDialog: {
type: Boolean,
value: false,
},
diff --git a/src/state-summary/state-card-toggle.js b/src/state-summary/state-card-toggle.js
index 67755870ba..bd3dca9de0 100644
--- a/src/state-summary/state-card-toggle.js
+++ b/src/state-summary/state-card-toggle.js
@@ -7,7 +7,7 @@ export default new Polymer({
is: 'state-card-toggle',
properties: {
- detailed: {
+ inDialog: {
type: Boolean,
value: false,
},
diff --git a/src/state-summary/state-card-weblink.js b/src/state-summary/state-card-weblink.js
index 2ab87d95de..c543c42d4a 100644
--- a/src/state-summary/state-card-weblink.js
+++ b/src/state-summary/state-card-weblink.js
@@ -6,7 +6,7 @@ export default new Polymer({
is: 'state-card-weblink',
properties: {
- detailed: {
+ inDialog: {
type: Boolean,
value: false,
},
diff --git a/src/util/domain-icon.js b/src/util/domain-icon.js
index d908e49134..2820c9c907 100644
--- a/src/util/domain-icon.js
+++ b/src/util/domain-icon.js
@@ -32,6 +32,9 @@ export default function domainIcon(domain, state) {
case 'homeassistant':
return 'mdi:home';
+ case 'hvac':
+ return 'mdi:air-conditioner';
+
case 'input_boolean':
return 'mdi:drawing';
diff --git a/src/util/state-card-type.js b/src/util/state-card-type.js
index 9fb1678ce3..961b01abc0 100644
--- a/src/util/state-card-type.js
+++ b/src/util/state-card-type.js
@@ -2,6 +2,7 @@ import canToggle from './can-toggle';
const DOMAINS_WITH_CARD = [
'configurator',
+ 'hvac',
'input_select',
'input_slider',
'media_player',
diff --git a/src/util/state-more-info-type.js b/src/util/state-more-info-type.js
index 5ae92311e2..d780637bc4 100644
--- a/src/util/state-more-info-type.js
+++ b/src/util/state-more-info-type.js
@@ -1,6 +1,7 @@
const DOMAINS_WITH_MORE_INFO = [
'light', 'group', 'sun', 'configurator', 'thermostat', 'script',
'media_player', 'camera', 'updater', 'alarm_control_panel', 'lock',
+ 'hvac',
];
export default function stateMoreInfoType(state) {