mirror of
https://github.com/home-assistant/frontend.git
synced 2026-04-02 00:27:49 +01:00
Refactor climate HVAC mode handling to be data-driven (#30356)
Refactor climate HVAC mode handling in state-history-chart-line to be data-driven Replace repetitive per-mode detection, dataset creation, and series population blocks with a single CLIMATE_MODE_CONFIGS array and loops over active modes.
This commit is contained in:
@@ -28,6 +28,13 @@ const safeParseFloat = (value) => {
|
||||
return isFinite(parsed) ? parsed : null;
|
||||
};
|
||||
|
||||
const CLIMATE_MODE_CONFIGS = [
|
||||
{ mode: "heat", action: "heating", cssVar: "--state-climate-heat-color" },
|
||||
{ mode: "cool", action: "cooling", cssVar: "--state-climate-cool-color" },
|
||||
{ mode: "dry", action: "drying", cssVar: "--state-climate-dry-color" },
|
||||
{ mode: "fan_only", action: "fan", cssVar: "--state-climate-fan_only-color" },
|
||||
] as const;
|
||||
|
||||
@customElement("state-history-chart-line")
|
||||
export class StateHistoryChartLine extends LitElement {
|
||||
@property({ attribute: false }) public hass!: HomeAssistant;
|
||||
@@ -429,39 +436,18 @@ export class StateHistoryChartLine extends LitElement {
|
||||
(entityState) => entityState.attributes?.hvac_action
|
||||
);
|
||||
|
||||
const isHeating =
|
||||
domain === "climate" && hasHvacAction
|
||||
? (entityState: LineChartState) =>
|
||||
CLIMATE_HVAC_ACTION_TO_MODE[
|
||||
entityState.attributes?.hvac_action
|
||||
] === "heat"
|
||||
: (entityState: LineChartState) => entityState.state === "heat";
|
||||
const isCooling =
|
||||
domain === "climate" && hasHvacAction
|
||||
? (entityState: LineChartState) =>
|
||||
CLIMATE_HVAC_ACTION_TO_MODE[
|
||||
entityState.attributes?.hvac_action
|
||||
] === "cool"
|
||||
: (entityState: LineChartState) => entityState.state === "cool";
|
||||
const isDrying =
|
||||
domain === "climate" && hasHvacAction
|
||||
? (entityState: LineChartState) =>
|
||||
CLIMATE_HVAC_ACTION_TO_MODE[
|
||||
entityState.attributes?.hvac_action
|
||||
] === "dry"
|
||||
: (entityState: LineChartState) => entityState.state === "dry";
|
||||
const isFanOnly =
|
||||
domain === "climate" && hasHvacAction
|
||||
? (entityState: LineChartState) =>
|
||||
CLIMATE_HVAC_ACTION_TO_MODE[
|
||||
entityState.attributes?.hvac_action
|
||||
] === "fan_only"
|
||||
: (entityState: LineChartState) => entityState.state === "fan_only";
|
||||
|
||||
const hasHeat = states.states.some(isHeating);
|
||||
const hasCool = states.states.some(isCooling);
|
||||
const hasDry = states.states.some(isDrying);
|
||||
const hasFan = states.states.some(isFanOnly);
|
||||
const activeModes = CLIMATE_MODE_CONFIGS.map(
|
||||
({ mode, action, cssVar }) => {
|
||||
const isActive =
|
||||
domain === "climate" && hasHvacAction
|
||||
? (entityState: LineChartState) =>
|
||||
CLIMATE_HVAC_ACTION_TO_MODE[
|
||||
entityState.attributes?.hvac_action
|
||||
] === mode
|
||||
: (entityState: LineChartState) => entityState.state === mode;
|
||||
return { action, cssVar, isActive };
|
||||
}
|
||||
).filter(({ isActive }) => states.states.some(isActive));
|
||||
// We differentiate between thermostats that have a target temperature
|
||||
// range versus ones that have just a target temperature
|
||||
|
||||
@@ -482,61 +468,19 @@ export class StateHistoryChartLine extends LitElement {
|
||||
"component.climate.entity_component._.state_attributes.current_temperature.name"
|
||||
)
|
||||
);
|
||||
if (hasHeat) {
|
||||
for (const { action, cssVar } of activeModes) {
|
||||
addDataSet(
|
||||
states.entity_id + "-heating",
|
||||
`${states.entity_id}-${action}`,
|
||||
this.showNames
|
||||
? this.hass.localize("ui.card.climate.heating", { name: name })
|
||||
? this.hass.localize(`ui.card.climate.${action}`, {
|
||||
name: name,
|
||||
})
|
||||
: this.hass.localize(
|
||||
"component.climate.entity_component._.state_attributes.hvac_action.state.heating"
|
||||
`component.climate.entity_component._.state_attributes.hvac_action.state.${action}`
|
||||
),
|
||||
computedStyles.getPropertyValue("--state-climate-heat-color"),
|
||||
computedStyles.getPropertyValue(cssVar),
|
||||
true
|
||||
);
|
||||
// The "heating" series uses steppedArea to shade the area below the current
|
||||
// temperature when the thermostat is calling for heat.
|
||||
}
|
||||
if (hasCool) {
|
||||
addDataSet(
|
||||
states.entity_id + "-cooling",
|
||||
this.showNames
|
||||
? this.hass.localize("ui.card.climate.cooling", { name: name })
|
||||
: this.hass.localize(
|
||||
"component.climate.entity_component._.state_attributes.hvac_action.state.cooling"
|
||||
),
|
||||
computedStyles.getPropertyValue("--state-climate-cool-color"),
|
||||
true
|
||||
);
|
||||
// The "cooling" series uses steppedArea to shade the area below the current
|
||||
// temperature when the thermostat is calling for heat.
|
||||
}
|
||||
if (hasDry) {
|
||||
addDataSet(
|
||||
states.entity_id + "-drying",
|
||||
this.showNames
|
||||
? this.hass.localize("ui.card.climate.drying", { name: name })
|
||||
: this.hass.localize(
|
||||
"component.climate.entity_component._.state_attributes.hvac_action.state.drying"
|
||||
),
|
||||
computedStyles.getPropertyValue("--state-climate-dry-color"),
|
||||
true
|
||||
);
|
||||
// The "drying" series uses steppedArea to shade the area below the current
|
||||
// temperature when the climate entity is in dry mode.
|
||||
}
|
||||
if (hasFan) {
|
||||
addDataSet(
|
||||
states.entity_id + "-fan",
|
||||
this.showNames
|
||||
? this.hass.localize("ui.card.climate.fan", { name: name })
|
||||
: this.hass.localize(
|
||||
"component.climate.entity_component._.state_attributes.hvac_action.state.fan"
|
||||
),
|
||||
computedStyles.getPropertyValue("--state-climate-fan_only-color"),
|
||||
true
|
||||
);
|
||||
// The "fan" series uses steppedArea to shade the area below the current
|
||||
// temperature when the climate entity is in fan_only mode.
|
||||
}
|
||||
|
||||
if (hasTargetRange) {
|
||||
@@ -584,17 +528,8 @@ export class StateHistoryChartLine extends LitElement {
|
||||
entityState.attributes.current_temperature
|
||||
);
|
||||
const series = [curTemp];
|
||||
if (hasHeat) {
|
||||
series.push(isHeating(entityState) ? curTemp : null);
|
||||
}
|
||||
if (hasCool) {
|
||||
series.push(isCooling(entityState) ? curTemp : null);
|
||||
}
|
||||
if (hasDry) {
|
||||
series.push(isDrying(entityState) ? curTemp : null);
|
||||
}
|
||||
if (hasFan) {
|
||||
series.push(isFanOnly(entityState) ? curTemp : null);
|
||||
for (const { isActive } of activeModes) {
|
||||
series.push(isActive(entityState) ? curTemp : null);
|
||||
}
|
||||
if (hasTargetRange) {
|
||||
const targetHigh = safeParseFloat(
|
||||
|
||||
Reference in New Issue
Block a user