diff --git a/src/data/energy.ts b/src/data/energy.ts index c84ff22914..e9976fab43 100644 --- a/src/data/energy.ts +++ b/src/data/energy.ts @@ -159,6 +159,9 @@ export interface GasSourceTypeEnergyPreference { // kWh/volume meter stat_energy_from: string; + // Flow rate (m³/h, L/min, etc.) + stat_rate?: string; + // $ meter stat_cost: string | null; @@ -174,6 +177,9 @@ export interface WaterSourceTypeEnergyPreference { // volume meter stat_energy_from: string; + // Flow rate (L/min, gal/min, m³/h, etc.) + stat_rate?: string; + // $ meter stat_cost: string | null; @@ -368,6 +374,9 @@ export const getReferencedStatisticIdsPower = ( for (const source of prefs.energy_sources) { if (source.type === "gas" || source.type === "water") { + if (source.stat_rate) { + statIDs.push(source.stat_rate); + } continue; } @@ -389,6 +398,7 @@ export const getReferencedStatisticIdsPower = ( } } statIDs.push(...prefs.device_consumption.map((d) => d.stat_rate)); + statIDs.push(...prefs.device_consumption_water.map((d) => d.stat_rate)); return statIDs.filter(Boolean) as string[]; }; diff --git a/src/panels/config/energy/dialogs/dialog-energy-device-settings-water.ts b/src/panels/config/energy/dialogs/dialog-energy-device-settings-water.ts index 8cbf84012e..c07543eda3 100644 --- a/src/panels/config/energy/dialogs/dialog-energy-device-settings-water.ts +++ b/src/panels/config/energy/dialogs/dialog-energy-device-settings-water.ts @@ -20,6 +20,7 @@ import type { HomeAssistant, ValueChangedEvent } from "../../../../types"; import type { EnergySettingsDeviceWaterDialogParams } from "./show-dialogs-energy"; const volumeUnitClasses = ["volume"]; +const flowRateUnitClasses = ["volume_flow_rate"]; @customElement("dialog-energy-device-settings-water") export class DialogEnergyDeviceSettingsWater @@ -36,10 +37,14 @@ export class DialogEnergyDeviceSettingsWater @state() private _volume_units?: string[]; + @state() private _flow_rate_units?: string[]; + @state() private _error?: string; private _excludeList?: string[]; + private _excludeListFlowRate?: string[]; + private _possibleParents: DeviceConsumptionEnergyPreference[] = []; public async showDialog( @@ -51,9 +56,15 @@ export class DialogEnergyDeviceSettingsWater this._volume_units = ( await getSensorDeviceClassConvertibleUnits(this.hass, "water") ).units; + this._flow_rate_units = ( + await getSensorDeviceClassConvertibleUnits(this.hass, "volume_flow_rate") + ).units; this._excludeList = this._params.device_consumptions .map((entry) => entry.stat_consumption) .filter((id) => id !== this._device?.stat_consumption); + this._excludeListFlowRate = this._params.device_consumptions + .map((entry) => entry.stat_rate) + .filter((id) => id && id !== this._device?.stat_rate) as string[]; this._open = true; } @@ -92,6 +103,7 @@ export class DialogEnergyDeviceSettingsWater this._device = undefined; this._error = undefined; this._excludeList = undefined; + this._excludeListFlowRate = undefined; fireEvent(this, "dialog-closed", { dialog: this.localName }); } @@ -134,12 +146,6 @@ export class DialogEnergyDeviceSettingsWater @closed=${this._dialogClosed} > ${this._error ? html`

${this._error}

` : ""} -
- ${this.hass.localize( - "ui.panel.config.energy.device_consumption_water.dialog.selected_stat_intro", - { unit: pickableUnit } - )} -
+ + ) { + if (!this._device) { + return; + } + const newDevice = { + ...this._device, + stat_rate: ev.detail.value, + } as DeviceConsumptionEnergyPreference; + if (!newDevice.stat_rate) { + delete newDevice.stat_rate; + } + this._device = newDevice; + } + private _nameChanged(ev) { const newDevice = { ...this._device!, @@ -252,7 +291,9 @@ export class DialogEnergyDeviceSettingsWater haStyleDialog, css` ha-statistic-picker { + display: block; width: 100%; + margin-bottom: var(--ha-space-4); } ha-select { display: block; diff --git a/src/panels/config/energy/dialogs/dialog-energy-gas-settings.ts b/src/panels/config/energy/dialogs/dialog-energy-gas-settings.ts index bc32aa8d7f..8433269753 100644 --- a/src/panels/config/energy/dialogs/dialog-energy-gas-settings.ts +++ b/src/panels/config/energy/dialogs/dialog-energy-gas-settings.ts @@ -30,6 +30,7 @@ import type { EnergySettingsGasDialogParams } from "./show-dialogs-energy"; const gasDeviceClasses = ["gas", "energy"]; const gasUnitClasses = ["volume", "energy"]; +const flowRateUnitClasses = ["volume_flow_rate"]; @customElement("dialog-energy-gas-settings") export class DialogEnergyGasSettings @@ -52,10 +53,14 @@ export class DialogEnergyGasSettings @state() private _gas_units?: string[]; + @state() private _flow_rate_units?: string[]; + @state() private _error?: string; private _excludeList?: string[]; + private _excludeListFlowRate?: string[]; + public async showDialog( params: EnergySettingsGasDialogParams ): Promise { @@ -81,9 +86,15 @@ export class DialogEnergyGasSettings this._gas_units = ( await getSensorDeviceClassConvertibleUnits(this.hass, "gas") ).units; + this._flow_rate_units = ( + await getSensorDeviceClassConvertibleUnits(this.hass, "volume_flow_rate") + ).units; this._excludeList = this._params.gas_sources .map((entry) => entry.stat_energy_from) .filter((id) => id !== this._source?.stat_energy_from); + this._excludeListFlowRate = this._params.gas_sources + .map((entry) => entry.stat_rate) + .filter((id) => id && id !== this._source?.stat_rate) as string[]; this._open = true; } @@ -99,6 +110,7 @@ export class DialogEnergyGasSettings this._pickedDisplayUnit = undefined; this._error = undefined; this._excludeList = undefined; + this._excludeListFlowRate = undefined; fireEvent(this, "dialog-closed", { dialog: this.localName }); } @@ -146,12 +158,6 @@ export class DialogEnergyGasSettings

${this.hass.localize("ui.panel.config.energy.gas.dialog.paragraph")}

-

- ${this.hass.localize( - "ui.panel.config.energy.gas.dialog.entity_para", - { unit: pickableUnit } - )} -

${this.hass.localize("ui.panel.config.energy.gas.dialog.note_para")}

@@ -169,9 +175,28 @@ export class DialogEnergyGasSettings )} .excludeStatistics=${this._excludeList} @value-changed=${this._statisticChanged} + .helper=${this.hass.localize( + "ui.panel.config.energy.gas.dialog.entity_para", + { unit: pickableUnit } + )} autofocus > + +

${this.hass.localize("ui.panel.config.energy.gas.dialog.cost_para")}

@@ -341,6 +366,13 @@ export class DialogEnergyGasSettings }; } + private _flowRateStatisticChanged(ev: ValueChangedEvent) { + this._source = { + ...this._source!, + stat_rate: ev.detail.value || undefined, + }; + } + private async _statisticChanged(ev: ValueChangedEvent) { if (ev.detail.value) { const metadata = await getStatisticMetadata(this.hass, [ev.detail.value]); @@ -380,6 +412,10 @@ export class DialogEnergyGasSettings haStyle, haStyleDialog, css` + ha-statistic-picker { + display: block; + margin-bottom: var(--ha-space-4); + } ha-formfield { display: block; } diff --git a/src/panels/config/energy/dialogs/dialog-energy-water-settings.ts b/src/panels/config/energy/dialogs/dialog-energy-water-settings.ts index 386df18bc4..499f4046e8 100644 --- a/src/panels/config/energy/dialogs/dialog-energy-water-settings.ts +++ b/src/panels/config/energy/dialogs/dialog-energy-water-settings.ts @@ -24,6 +24,8 @@ import { haStyle, haStyleDialog } from "../../../../resources/styles"; import type { HomeAssistant, ValueChangedEvent } from "../../../../types"; import type { EnergySettingsWaterDialogParams } from "./show-dialogs-energy"; +const flowRateUnitClasses = ["volume_flow_rate"]; + @customElement("dialog-energy-water-settings") export class DialogEnergyWaterSettings extends LitElement @@ -41,10 +43,14 @@ export class DialogEnergyWaterSettings @state() private _water_units?: string[]; + @state() private _flow_rate_units?: string[]; + @state() private _error?: string; private _excludeList?: string[]; + private _excludeListFlowRate?: string[]; + public async showDialog( params: EnergySettingsWaterDialogParams ): Promise { @@ -62,9 +68,15 @@ export class DialogEnergyWaterSettings this._water_units = ( await getSensorDeviceClassConvertibleUnits(this.hass, "water") ).units; + this._flow_rate_units = ( + await getSensorDeviceClassConvertibleUnits(this.hass, "volume_flow_rate") + ).units; this._excludeList = this._params.water_sources .map((entry) => entry.stat_energy_from) .filter((id) => id !== this._source?.stat_energy_from); + this._excludeListFlowRate = this._params.water_sources + .map((entry) => entry.stat_rate) + .filter((id) => id && id !== this._source?.stat_rate) as string[]; this._open = true; } @@ -79,6 +91,7 @@ export class DialogEnergyWaterSettings this._source = undefined; this._error = undefined; this._excludeList = undefined; + this._excludeListFlowRate = undefined; fireEvent(this, "dialog-closed", { dialog: this.localName }); } @@ -108,19 +121,6 @@ export class DialogEnergyWaterSettings @closed=${this._dialogClosed} > ${this._error ? html`

${this._error}

` : ""} -
-

- ${this.hass.localize( - "ui.panel.config.energy.water.dialog.paragraph" - )} -

-

- ${this.hass.localize( - "ui.panel.config.energy.water.dialog.entity_para", - { unit: pickableUnit } - )} -

-
+ +

${this.hass.localize("ui.panel.config.energy.water.dialog.cost_para")}

@@ -287,6 +306,13 @@ export class DialogEnergyWaterSettings }; } + private _flowRateStatisticChanged(ev: ValueChangedEvent) { + this._source = { + ...this._source!, + stat_rate: ev.detail.value || undefined, + }; + } + private async _statisticChanged(ev: ValueChangedEvent) { if ( ev.detail.value && @@ -320,6 +346,10 @@ export class DialogEnergyWaterSettings haStyle, haStyleDialog, css` + ha-statistic-picker { + display: block; + margin-bottom: var(--ha-space-4); + } ha-formfield { display: block; } diff --git a/src/translations/en.json b/src/translations/en.json index 8866f81cb0..a8cf1b21e9 100644 --- a/src/translations/en.json +++ b/src/translations/en.json @@ -3936,7 +3936,9 @@ "cost_entity_helper_volume": "volume", "cost_number": "[%key:ui::panel::config::energy::grid::flow_dialog::from::cost_number%]", "cost_number_input": "[%key:ui::panel::config::energy::grid::flow_dialog::from::cost_number%]", - "gas_usage": "Gas usage" + "gas_usage": "Gas consumption", + "gas_flow_rate": "Gas flow rate", + "flow_rate_para": "Optionally pick a sensor which measures the gas flow rate in either of {unit}." } }, "water": { @@ -3960,7 +3962,9 @@ "cost_entity_helper": "Any entity with a unit of `{currency}/(valid water unit)` (e.g. `{currency}/gal` or `{currency}/m³`) may be used and will be automatically converted.", "cost_number": "[%key:ui::panel::config::energy::grid::flow_dialog::from::cost_number%]", "cost_number_input": "[%key:ui::panel::config::energy::grid::flow_dialog::from::cost_number%]", - "water_usage": "Water usage" + "water_usage": "Water consumption", + "water_flow_rate": "Water flow rate", + "flow_rate_para": "Optionally pick a sensor which measures the water flow rate in either of {unit}." } }, "device_consumption": { @@ -3992,7 +3996,8 @@ "header": "Add a water device", "display_name": "Display name", "device_consumption_water": "Device water consumption", - "selected_stat_intro": "Select the water sensor that measures the device's water usage in either of {unit}.", + "device_consumption_water_flow_rate": "Device water flow rate", + "selected_stat_intro": "Select the water sensor that measures the device's water consumption in either of {unit}.", "included_in_device": "Upstream device", "included_in_device_helper": "If this device is already counted by another device (such as a water meter measured by the main water supply), selecting the upstream device prevents duplicate water tracking.", "no_upstream_devices": "No eligible upstream devices"