From 7e6d5e2ff750847144e84bf3c96e0d21ed149d39 Mon Sep 17 00:00:00 2001 From: Paulus Schoutsen Date: Mon, 9 May 2016 21:21:52 -0700 Subject: [PATCH] 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 --- src/more-infos/more-info-content.html | 1 + src/more-infos/more-info-content.js | 1 + src/more-infos/more-info-hvac.html | 131 ++++++++++++++ src/more-infos/more-info-hvac.js | 160 ++++++++++++++++++ src/state-summary/state-card-content.html | 1 + src/state-summary/state-card-content.js | 1 + src/state-summary/state-card-display.js | 2 +- src/state-summary/state-card-hvac.html | 25 +++ src/state-summary/state-card-hvac.js | 18 ++ src/state-summary/state-card-input_select.js | 2 +- src/state-summary/state-card-input_slider.js | 2 +- src/state-summary/state-card-media_player.js | 2 +- src/state-summary/state-card-rollershutter.js | 2 +- src/state-summary/state-card-scene.js | 2 +- src/state-summary/state-card-script.js | 2 +- src/state-summary/state-card-thermostat.js | 2 +- src/state-summary/state-card-toggle.js | 2 +- src/state-summary/state-card-weblink.js | 2 +- src/util/domain-icon.js | 3 + src/util/state-card-type.js | 1 + src/util/state-more-info-type.js | 1 + 21 files changed, 353 insertions(+), 10 deletions(-) create mode 100644 src/more-infos/more-info-hvac.html create mode 100644 src/more-infos/more-info-hvac.js create mode 100755 src/state-summary/state-card-hvac.html create mode 100644 src/state-summary/state-card-hvac.js 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
+ + +
+
+ +
+
+
Target Humidity
+ + +
+
+ +
+
+ + + + + +
+
+ +
+ + + + + +
+ +
+ + + + + +
+ +
+
+
Away Mode
+ + +
+
+ +
+
+
Aux Heat
+ + +
+
+
+ +
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) {