feat: round_temperature on weather forecast card (#28103)

* feat: round_temperature on weather forecast card

* fix: use round util function

* refactor: applied comments from review
This commit is contained in:
Luca Félix 2025-12-03 08:02:25 +00:00 committed by GitHub
parent 8681a7d450
commit e7254b1587
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 82 additions and 12 deletions

View File

@ -82,6 +82,12 @@ export interface WeatherEntity extends HassEntityBase {
attributes: WeatherEntityAttributes;
}
export const WEATHER_TEMPERATURE_ATTRIBUTES = new Set<string>([
"temperature",
"apparent_temperature",
"dew_point",
]);
export const weatherSVGs = new Set<string>([
"clear-night",
"cloudy",
@ -256,9 +262,15 @@ export const getWeatherUnit = (
export const getSecondaryWeatherAttribute = (
hass: HomeAssistant,
stateObj: WeatherEntity,
forecast: ForecastAttribute[]
forecast: ForecastAttribute[],
temperatureFractionDigits?: number
): TemplateResult | undefined => {
const extrema = getWeatherExtrema(hass, stateObj, forecast);
const extrema = getWeatherExtrema(
hass,
stateObj,
forecast,
temperatureFractionDigits
);
if (extrema) {
return extrema;
@ -298,7 +310,8 @@ export const getSecondaryWeatherAttribute = (
const getWeatherExtrema = (
hass: HomeAssistant,
stateObj: WeatherEntity,
forecast: ForecastAttribute[]
forecast: ForecastAttribute[],
temperatureFractionDigits?: number
): TemplateResult | undefined => {
if (!forecast?.length) {
return undefined;
@ -313,13 +326,22 @@ const getWeatherExtrema = (
break;
}
if (!tempHigh || fc.temperature > tempHigh) {
tempHigh = fc.temperature;
tempHigh =
temperatureFractionDigits === undefined
? fc.temperature
: round(fc.temperature, temperatureFractionDigits);
}
if (!tempLow || (fc.templow && fc.templow < tempLow)) {
tempLow = fc.templow;
if (fc.templow !== undefined && (!tempLow || fc.templow < tempLow)) {
tempLow =
temperatureFractionDigits === undefined
? fc.templow
: round(fc.templow, temperatureFractionDigits);
}
if (!fc.templow && (!tempLow || fc.temperature < tempLow)) {
tempLow = fc.temperature;
tempLow =
temperatureFractionDigits === undefined
? fc.temperature
: round(fc.temperature, temperatureFractionDigits);
}
}

View File

@ -23,8 +23,10 @@ import {
subscribeForecast,
weatherAttrIcons,
weatherSVGStyles,
WEATHER_TEMPERATURE_ATTRIBUTES,
} from "../../../data/weather";
import type { HomeAssistant } from "../../../types";
import { round } from "../../../common/number/round";
import { actionHandler } from "../common/directives/action-handler-directive";
import { computeLovelaceEntityName } from "../common/entity/compute-lovelace-entity-name";
import { findEntities } from "../common/find-entities";
@ -266,6 +268,20 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard {
this._config.name
);
const temperatureFractionDigits = this._config.round_temperature
? 0
: undefined;
const isSecondaryInfoAttributeTemperature =
this._config?.secondary_info_attribute &&
WEATHER_TEMPERATURE_ATTRIBUTES.has(this._config.secondary_info_attribute);
const isSecondaryInfoNumber =
this._config.secondary_info_attribute &&
!Number.isNaN(
+stateObj.attributes[this._config.secondary_info_attribute]
);
return html`
<ha-card
class=${classMap({
@ -312,7 +328,11 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard {
? html`
${formatNumber(
stateObj.attributes.temperature,
this.hass.locale
this.hass.locale,
{
maximumFractionDigits:
temperatureFractionDigits,
}
)}&nbsp;<span
>${getWeatherUnit(
this.hass.config,
@ -350,14 +370,26 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard {
: html`
${this.hass.formatEntityAttributeValue(
stateObj,
this._config.secondary_info_attribute
this._config.secondary_info_attribute,
temperatureFractionDigits === 0 &&
isSecondaryInfoNumber &&
isSecondaryInfoAttributeTemperature
? round(
stateObj.attributes[
this._config
.secondary_info_attribute
],
temperatureFractionDigits
)
: undefined
)}
`}
`
: getSecondaryWeatherAttribute(
this.hass,
stateObj,
forecast!
forecast!,
temperatureFractionDigits
)}
</div>
</div>
@ -425,7 +457,11 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard {
${this._showValue(item.temperature)
? html`${formatNumber(
item.temperature,
this.hass!.locale
this.hass!.locale,
{
maximumFractionDigits:
temperatureFractionDigits,
}
)}°`
: "—"}
</div>
@ -433,7 +469,11 @@ class HuiWeatherForecastCard extends LitElement implements LovelaceCard {
${this._showValue(item.templow)
? html`${formatNumber(
item.templow!,
this.hass!.locale
this.hass!.locale,
{
maximumFractionDigits:
temperatureFractionDigits,
}
)}°`
: hourly
? ""

View File

@ -597,6 +597,7 @@ export interface WeatherForecastCardConfig extends LovelaceCardConfig {
forecast_type?: ForecastType;
forecast_slots?: number;
secondary_info_attribute?: keyof TranslationDict["ui"]["card"]["weather"]["attributes"];
round_temperature?: boolean;
theme?: string;
tap_action?: ActionConfig;
hold_action?: ActionConfig;

View File

@ -37,6 +37,7 @@ const cardConfigStruct = assign(
forecast_type: optional(string()),
forecast_slots: optional(number()),
secondary_info_attribute: optional(string()),
round_temperature: optional(boolean()),
tap_action: optional(actionConfigStruct),
hold_action: optional(actionConfigStruct),
double_tap_action: optional(actionConfigStruct),
@ -156,6 +157,10 @@ export class HuiWeatherForecastCardEditor
},
context: { entity: "entity" },
},
{
name: "round_temperature",
selector: { boolean: {} },
},
{
name: "",
type: "grid",

View File

@ -304,6 +304,7 @@
},
"weather": {
"attributes": {
"dew_point": "Dew point",
"air_pressure": "Air pressure",
"humidity": "Humidity",
"temperature": "Temperature",
@ -8026,6 +8027,7 @@
"suggested_cards": "Suggested cards",
"other_cards": "Other cards",
"custom_cards": "Custom cards",
"round_temperature": "Round temperature",
"features": "Features",
"actions": "Actions",
"content": "Content"