Move energy panel up in sidebar (#9636)

* Move energy panel up in sidebar

* Remove headers from wizard

* Update text

* Always show all configured devices

* Make leaf clickable

* Bump HAWS
This commit is contained in:
Paulus Schoutsen 2021-07-28 11:05:00 -07:00 committed by GitHub
parent 469faf509b
commit 9a92825954
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 110 additions and 46 deletions

View File

@ -107,7 +107,7 @@
"fuse.js": "^6.0.0", "fuse.js": "^6.0.0",
"google-timezones-json": "^1.0.2", "google-timezones-json": "^1.0.2",
"hls.js": "^1.0.7", "hls.js": "^1.0.7",
"home-assistant-js-websocket": "^5.11.0", "home-assistant-js-websocket": "^5.11.1",
"idb-keyval": "^5.0.5", "idb-keyval": "^5.0.5",
"intl-messageformat": "^9.6.16", "intl-messageformat": "^9.6.16",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",

View File

@ -53,9 +53,10 @@ const SHOW_AFTER_SPACER = ["config", "developer-tools", "hassio"];
const SUPPORT_SCROLL_IF_NEEDED = "scrollIntoViewIfNeeded" in document.body; const SUPPORT_SCROLL_IF_NEEDED = "scrollIntoViewIfNeeded" in document.body;
const SORT_VALUE_URL_PATHS = { const SORT_VALUE_URL_PATHS = {
map: 1, energy: 1,
logbook: 2, map: 2,
history: 3, logbook: 3,
history: 4,
"developer-tools": 9, "developer-tools": 9,
hassio: 10, hassio: 10,
config: 11, config: 11,

View File

@ -19,6 +19,7 @@ import {
} from "../../../../dialogs/generic/show-dialog-box"; } from "../../../../dialogs/generic/show-dialog-box";
import { haStyle } from "../../../../resources/styles"; import { haStyle } from "../../../../resources/styles";
import { HomeAssistant } from "../../../../types"; import { HomeAssistant } from "../../../../types";
import { documentationUrl } from "../../../../util/documentation-url";
import { showEnergySettingsDeviceDialog } from "../dialogs/show-dialogs-energy"; import { showEnergySettingsDeviceDialog } from "../dialogs/show-dialogs-energy";
import { energyCardStyles } from "./styles"; import { energyCardStyles } from "./styles";
@ -33,12 +34,29 @@ export class EnergyDeviceSettings extends LitElement {
return html` return html`
<ha-card> <ha-card>
<h1 class="card-header"> <h1 class="card-header">
<ha-svg-icon .path=${mdiDevices}></ha-svg-icon>Monitor individual <ha-svg-icon .path=${mdiDevices}></ha-svg-icon>
devices ${this.hass.localize(
"ui.panel.config.energy.device_consumption.title"
)}
</h1> </h1>
<div class="card-content"> <div class="card-content">
<p>Monitor individual devices.</p> <p>
${this.hass.localize(
"ui.panel.config.energy.device_consumption.sub"
)}
<a
target="_blank"
rel="noopener noreferer"
href="${documentationUrl(
this.hass,
"/docs/energy/individual-devices/"
)}"
>${this.hass.localize(
"ui.panel.config.energy.device_consumption.learn_more"
)}</a
>
</p>
<h3>Devices</h3> <h3>Devices</h3>
${this.preferences.device_consumption.map((device) => { ${this.preferences.device_consumption.map((device) => {
const entityState = this.hass.states[device.stat_consumption]; const entityState = this.hass.states[device.stat_consumption];

View File

@ -34,6 +34,7 @@ import {
} from "../../../../dialogs/generic/show-dialog-box"; } from "../../../../dialogs/generic/show-dialog-box";
import { haStyle } from "../../../../resources/styles"; import { haStyle } from "../../../../resources/styles";
import { HomeAssistant } from "../../../../types"; import { HomeAssistant } from "../../../../types";
import { documentationUrl } from "../../../../util/documentation-url";
import { import {
showEnergySettingsGridFlowFromDialog, showEnergySettingsGridFlowFromDialog,
showEnergySettingsGridFlowToDialog, showEnergySettingsGridFlowToDialog,
@ -63,12 +64,25 @@ export class EnergyGridSettings extends LitElement {
return html` return html`
<ha-card> <ha-card>
<h1 class="card-header"> <h1 class="card-header">
<ha-svg-icon .path=${mdiTransmissionTower}></ha-svg-icon <ha-svg-icon .path=${mdiTransmissionTower}></ha-svg-icon>
>${this.hass.localize("ui.panel.config.energy.grid.title")} ${this.hass.localize("ui.panel.config.energy.grid.title")}
</h1> </h1>
<div class="card-content"> <div class="card-content">
<p>${this.hass.localize("ui.panel.config.energy.grid.sub")}</p> <p>
${this.hass.localize("ui.panel.config.energy.grid.sub")}
<a
target="_blank"
rel="noopener noreferer"
href="${documentationUrl(
this.hass,
"/docs/energy/electricity-grid/"
)}"
>${this.hass.localize(
"ui.panel.config.energy.grid.learn_more"
)}</a
>
</p>
<h3>Grid consumption</h3> <h3>Grid consumption</h3>
${gridSource.flow_from.map((flow) => { ${gridSource.flow_from.map((flow) => {
const entityState = this.hass.states[flow.stat_energy_from]; const entityState = this.hass.states[flow.stat_energy_from];

View File

@ -19,6 +19,7 @@ import {
} from "../../../../dialogs/generic/show-dialog-box"; } from "../../../../dialogs/generic/show-dialog-box";
import { haStyle } from "../../../../resources/styles"; import { haStyle } from "../../../../resources/styles";
import { HomeAssistant } from "../../../../types"; import { HomeAssistant } from "../../../../types";
import { documentationUrl } from "../../../../util/documentation-url";
import { showEnergySettingsSolarDialog } from "../dialogs/show-dialogs-energy"; import { showEnergySettingsSolarDialog } from "../dialogs/show-dialogs-energy";
import { energyCardStyles } from "./styles"; import { energyCardStyles } from "./styles";
@ -37,14 +38,24 @@ export class EnergySolarSettings extends LitElement {
return html` return html`
<ha-card> <ha-card>
<h1 class="card-header"> <h1 class="card-header">
<ha-svg-icon .path=${mdiSolarPower}></ha-svg-icon>Configure solar <ha-svg-icon .path=${mdiSolarPower}></ha-svg-icon>
panels ${this.hass.localize("ui.panel.config.energy.solar.title")}
</h1> </h1>
<div class="card-content"> <div class="card-content">
<p> <p>
Let Home Assistant monitor your solar panels and give you insight on ${this.hass.localize("ui.panel.config.energy.solar.sub")}
their performace. <a
target="_blank"
rel="noopener noreferer"
href="${documentationUrl(
this.hass,
"/docs/energy/solar-panels/"
)}"
>${this.hass.localize(
"ui.panel.config.energy.solar.learn_more"
)}</a
>
</p> </p>
<h3>Solar production</h3> <h3>Solar production</h3>
${solarSources.map((source) => { ${solarSources.map((source) => {

View File

@ -58,7 +58,6 @@ export class DialogEnergyDeviceSettings
@closed=${this.closeDialog} @closed=${this.closeDialog}
> >
${this._error ? html`<p class="error">${this._error}</p>` : ""} ${this._error ? html`<p class="error">${this._error}</p>` : ""}
<p>Track your devices <a href="#">Learn more</a></p>
<ha-statistic-picker <ha-statistic-picker
.hass=${this.hass} .hass=${this.hass}

View File

@ -85,11 +85,11 @@ export class DialogEnergyGridFlowSettings
@closed=${this.closeDialog} @closed=${this.closeDialog}
> >
${this._error ? html`<p class="error">${this._error}</p>` : ""} ${this._error ? html`<p class="error">${this._error}</p>` : ""}
<p> <div>
${this.hass.localize( ${this.hass.localize(
`ui.panel.config.energy.grid.flow_dialog.${this._params.direction}.paragraph` `ui.panel.config.energy.grid.flow_dialog.${this._params.direction}.paragraph`
)} )}
</p> </div>
<ha-statistic-picker <ha-statistic-picker
.hass=${this.hass} .hass=${this.hass}
@ -277,6 +277,9 @@ export class DialogEnergyGridFlowSettings
return [ return [
haStyleDialog, haStyleDialog,
css` css`
ha-dialog {
--mdc-dialog-max-width: 430px;
}
ha-formfield { ha-formfield {
display: block; display: block;
} }

View File

@ -75,7 +75,6 @@ export class DialogEnergySolarSettings
@closed=${this.closeDialog} @closed=${this.closeDialog}
> >
${this._error ? html`<p class="error">${this._error}</p>` : ""} ${this._error ? html`<p class="error">${this._error}</p>` : ""}
<p>Solar production for the win! <a href="#">Learn more</a></p>
<ha-statistic-picker <ha-statistic-picker
.hass=${this.hass} .hass=${this.hass}
@ -212,6 +211,9 @@ export class DialogEnergySolarSettings
haStyle, haStyle,
haStyleDialog, haStyleDialog,
css` css`
ha-dialog {
--mdc-dialog-max-width: 430px;
}
img { img {
height: 24px; height: 24px;
margin-right: 16px; margin-right: 16px;

View File

@ -41,9 +41,6 @@ export class EnergySetupWizard extends LitElement implements LovelaceCard {
protected render(): TemplateResult { protected render(): TemplateResult {
return html` return html`
<h2>${this.hass.localize("ui.panel.energy.setup.header")}</h2>
<h3>${this.hass.localize("ui.panel.energy.setup.slogan")}</h3>
<p>Step ${this._step + 1} of 3</p> <p>Step ${this._step + 1} of 3</p>
${this._step === 0 ${this._step === 0
? html` <ha-energy-grid-settings ? html` <ha-energy-grid-settings

View File

@ -178,10 +178,6 @@ export class HuiEnergyDevicesGraphCard
const statisticsData = Object.values(this._data!); const statisticsData = Object.values(this._data!);
let endTime: Date; let endTime: Date;
if (statisticsData.length === 0) {
return;
}
endTime = new Date( endTime = new Date(
Math.max( Math.max(
...statisticsData.map((stats) => ...statisticsData.map((stats) =>
@ -190,7 +186,7 @@ export class HuiEnergyDevicesGraphCard
) )
); );
if (endTime > new Date()) { if (!endTime || endTime > new Date()) {
endTime = new Date(); endTime = new Date();
} }
@ -207,27 +203,30 @@ export class HuiEnergyDevicesGraphCard
}, },
]; ];
Object.entries(this._data).forEach(([id, statistics], idx) => { for (let idx = 0; idx < prefs.device_consumption.length; idx++) {
const entity = this.hass.states[id]; const device = prefs.device_consumption[idx];
const label = entity ? computeStateName(entity) : id; const entity = this.hass.states[device.stat_consumption];
const label = entity ? computeStateName(entity) : device.stat_consumption;
const color = getColorByIndex(idx); const color = getColorByIndex(idx);
borderColor.push(color); borderColor.push(color);
backgroundColor.push(color + "7F"); backgroundColor.push(color + "7F");
const value = calculateStatisticSumGrowth(statistics); const value =
device.stat_consumption in this._data
? calculateStatisticSumGrowth(this._data[device.stat_consumption])
: 0;
data.push({ data.push({
// @ts-expect-error // @ts-expect-error
y: label, y: label,
x: value || 0, x: value || 0,
}); });
}); }
data.sort((a, b) => b.x - a.x); data.sort((a, b) => b.x - a.x);
this._chartData = { this._chartData = {
// labels,
datasets, datasets,
}; };
} }

View File

@ -9,6 +9,7 @@ import {
import { css, html, LitElement, svg } from "lit"; import { css, html, LitElement, svg } from "lit";
import { customElement, property, state } from "lit/decorators"; import { customElement, property, state } from "lit/decorators";
import { classMap } from "lit/directives/class-map"; import { classMap } from "lit/directives/class-map";
import { ifDefined } from "lit/directives/if-defined";
import { round } from "../../../../common/number/round"; import { round } from "../../../../common/number/round";
import { subscribeOne } from "../../../../common/util/subscribe-one"; import { subscribeOne } from "../../../../common/util/subscribe-one";
import "../../../../components/ha-card"; import "../../../../components/ha-card";
@ -121,6 +122,8 @@ class HuiEnergyDistrubutionCard extends LitElement implements LovelaceCard {
let homeLowCarbonCircumference: number | undefined; let homeLowCarbonCircumference: number | undefined;
let homeHighCarbonCircumference: number | undefined; let homeHighCarbonCircumference: number | undefined;
let electricityMapUrl: string | undefined;
if (this._co2SignalEntity && this._co2SignalEntity in this._stats) { if (this._co2SignalEntity && this._co2SignalEntity in this._stats) {
// Calculate high carbon consumption // Calculate high carbon consumption
const highCarbonConsumption = calculateStatisticsSumGrowthWithPercentage( const highCarbonConsumption = calculateStatisticsSumGrowthWithPercentage(
@ -130,6 +133,12 @@ class HuiEnergyDistrubutionCard extends LitElement implements LovelaceCard {
.filter(Boolean) .filter(Boolean)
); );
const co2State = this.hass.states[this._co2SignalEntity];
if (co2State) {
electricityMapUrl = `https://www.electricitymap.org/zone/${co2State.attributes.country_code}`;
}
if (highCarbonConsumption !== null) { if (highCarbonConsumption !== null) {
const gridPctHighCarbon = highCarbonConsumption / totalConsumption; const gridPctHighCarbon = highCarbonConsumption / totalConsumption;
@ -159,10 +168,15 @@ class HuiEnergyDistrubutionCard extends LitElement implements LovelaceCard {
: html` : html`
<div class="circle-container low-carbon"> <div class="circle-container low-carbon">
<span class="label">Non-fossil</span> <span class="label">Non-fossil</span>
<div class="circle"> <a
class="circle"
href=${ifDefined(electricityMapUrl)}
target="_blank"
rel="noopener no referrer"
>
<ha-svg-icon .path="${mdiLeaf}"></ha-svg-icon> <ha-svg-icon .path="${mdiLeaf}"></ha-svg-icon>
${round(lowCarbonConsumption, 1)} kWh ${round(lowCarbonConsumption, 1)} kWh
</div> </a>
<svg width="80" height="30"> <svg width="80" height="30">
<line x1="40" y1="0" x2="40" y2="30"></line> <line x1="40" y1="0" x2="40" y2="30"></line>
</svg> </svg>
@ -478,6 +492,8 @@ class HuiEnergyDistrubutionCard extends LitElement implements LovelaceCard {
font-size: 12px; font-size: 12px;
line-height: 12px; line-height: 12px;
position: relative; position: relative;
text-decoration: none;
color: var(--primary-text-color);
} }
ha-svg-icon { ha-svg-icon {
padding-bottom: 2px; padding-bottom: 2px;

View File

@ -992,8 +992,9 @@
"description": "Monitor your energy production and consumption", "description": "Monitor your energy production and consumption",
"currency": "", "currency": "",
"grid": { "grid": {
"title": "Configure grid", "title": "Electricity grid",
"sub": "Configure the different tarrifs for the energy you consume from the grid, and, if you return energy to the grid, the energy you return to the grid.", "sub": "Configure the amount of energy that you consume from the grid and, if you produce energy, give back to the grid. This allows Home Assistant to track your whole home energy usage.",
"learn_more": "More information on how to get started.",
"flow_dialog": { "flow_dialog": {
"from": { "from": {
"header": "Configure grid consumption", "header": "Configure grid consumption",
@ -1002,7 +1003,7 @@
"cost_para": "Select how Home Assistant should keep track of the costs of the consumed energy.", "cost_para": "Select how Home Assistant should keep track of the costs of the consumed energy.",
"no_cost": "Do not track costs", "no_cost": "Do not track costs",
"cost_stat": "Use an entity tracking the total costs", "cost_stat": "Use an entity tracking the total costs",
"cost_stat_input": "Entity keeping track of the total costs", "cost_stat_input": "Total Costs Entity",
"cost_entity": "Use an entity with current price", "cost_entity": "Use an entity with current price",
"cost_entity_input": "Entity with the current price", "cost_entity_input": "Entity with the current price",
"cost_number": "Use a static price", "cost_number": "Use a static price",
@ -1016,7 +1017,7 @@
"cost_para": "Do you get money back when you return energy to the grid?", "cost_para": "Do you get money back when you return energy to the grid?",
"no_cost": "I do not get money back", "no_cost": "I do not get money back",
"cost_stat": "Use an entity tracking the total recieved money", "cost_stat": "Use an entity tracking the total recieved money",
"cost_stat_input": "Entity keeping track of the total of received money", "cost_stat_input": "Total Compensation Entity",
"cost_entity": "Use an entity with current rate", "cost_entity": "Use an entity with current rate",
"cost_entity_input": "Entity with the current rate", "cost_entity_input": "Entity with the current rate",
"cost_number": "Use a static rate", "cost_number": "Use a static rate",
@ -1026,12 +1027,17 @@
} }
}, },
"solar": { "solar": {
"title": "Solar Panels",
"sub": "Let Home Assistant monitor your solar panels and give you insight on their performance.",
"learn_more": "More information on how to get started.",
"stat_production": "Your solar energy production", "stat_production": "Your solar energy production",
"stat_return_to_grid": "Solar energy returned to the grid", "stat_return_to_grid": "Solar energy returned to the grid",
"stat_predicted_production": "Prediction of your solar energy production" "stat_predicted_production": "Prediction of your solar energy production"
}, },
"device_consumption": { "device_consumption": {
"description": "If you measure the power consumption of individual devices, you can select the entities with the power consumption below", "title": "Individual devices",
"sub": "Tracking the energy usage of individual devices allows Home Assistant to break down your energy usage by device.",
"learn_more": "More information on how to get started.",
"add_stat": "Pick entity to track energy of", "add_stat": "Pick entity to track energy of",
"selected_stat": "Tracking energy for" "selected_stat": "Tracking energy for"
} }
@ -3713,8 +3719,6 @@
}, },
"energy": { "energy": {
"setup": { "setup": {
"header": "Setup your energy dashboard",
"slogan": "The world is heating up. Together we can fix that.",
"next": "Next", "next": "Next",
"back": "Back", "back": "Back",
"done": "Show me my energy dashboard!" "done": "Show me my energy dashboard!"

View File

@ -8941,7 +8941,7 @@ fsevents@~2.3.1:
gulp-rename: ^2.0.0 gulp-rename: ^2.0.0
gulp-zopfli-green: ^3.0.1 gulp-zopfli-green: ^3.0.1
hls.js: ^1.0.7 hls.js: ^1.0.7
home-assistant-js-websocket: ^5.11.0 home-assistant-js-websocket: ^5.11.1
html-minifier: ^4.0.0 html-minifier: ^4.0.0
husky: ^1.3.1 husky: ^1.3.1
idb-keyval: ^5.0.5 idb-keyval: ^5.0.5
@ -9011,10 +9011,10 @@ fsevents@~2.3.1:
languageName: unknown languageName: unknown
linkType: soft linkType: soft
"home-assistant-js-websocket@npm:^5.11.0": "home-assistant-js-websocket@npm:^5.11.1":
version: 5.11.0 version: 5.11.1
resolution: "home-assistant-js-websocket@npm:5.11.0" resolution: "home-assistant-js-websocket@npm:5.11.1"
checksum: 7e493f2528a49a2ea8b35468a7c655f97627820542bd4dd841060ca7b34d0fc9c5b4b7cc22d0ba16f1f7932342fd5978c923fc6a213d2af05509ad8ff6912422 checksum: 6766cff890831741cfb9ebc5372ed465be578897a8c763daac09a7673d804fa591658542ca1e93619104486956972c94b7f6f9098caaddbf36f89c7808db563d
languageName: node languageName: node
linkType: hard linkType: hard