From 2b21e8262d6932fc7bb07b565f8617cc743034d1 Mon Sep 17 00:00:00 2001 From: D Date: Mon, 13 Jan 2025 11:57:43 +1100 Subject: [PATCH 1/5] feat: add support for wind barbs when bearing is a string --- package-lock.json | 4 ++-- src/directions.ts | 19 +++++++++++++++++ src/hourly-weather.ts | 47 ++++++++++++++++++++----------------------- src/weather-bar.ts | 16 +++++++++------ 4 files changed, 53 insertions(+), 33 deletions(-) diff --git a/package-lock.json b/package-lock.json index 9d12150d..b0f9a5e9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "lovelace-hourly-weather", - "version": "6.4.0", + "version": "6.5.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "lovelace-hourly-weather", - "version": "6.4.0", + "version": "6.5.0", "license": "MIT", "dependencies": { "@lit-labs/scoped-registry-mixin": "^1.0.3", diff --git a/src/directions.ts b/src/directions.ts index a4844b76..f26e33c4 100644 --- a/src/directions.ts +++ b/src/directions.ts @@ -16,3 +16,22 @@ export const DIRECTIONS = { 'nw': 'direction.nw', 'nnw': 'direction.nnw' }; + +export const DIRECTIONS_BEARINGS: Record = { + 'n': 0, + 'nne': 22.5, + 'ne': 45, + 'ene': 67.5, + 'e': 90, + 'ese': 112.5, + 'se': 135, + 'sse': 157.5, + 's': 180, + 'ssw': 202.5, + 'sw': 225, + 'wsw': 247.5, + 'w': 270, + 'wnw': 292.5, + 'nw': 315, + 'nnw': 337.5, +}; diff --git a/src/hourly-weather.ts b/src/hourly-weather.ts index 177bcb24..a99eb0f2 100644 --- a/src/hourly-weather.ts +++ b/src/hourly-weather.ts @@ -1,28 +1,34 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { LitElement, html, TemplateResult, css, PropertyValues, CSSResultGroup } from 'lit'; -import { customElement, property, state } from 'lit/decorators.js'; -import { until } from 'lit/directives/until.js' import { - HomeAssistant, - hasConfigOrEntityChanged, - hasAction, ActionHandlerEvent, - handleAction, + FrontendLocaleData, + HomeAssistant, LovelaceCardEditor, - getLovelace, + formatDateShort, formatNumber, formatTime, - FrontendLocaleData, - formatDateShort, + getLovelace, + handleAction, + hasAction, + hasConfigOrEntityChanged, } from 'custom-card-helpers'; // This is a community maintained npm module with common helper functions/types. https://github.com/custom-cards/custom-card-helpers import { isValidColorName, isValidHSL, isValidRGB } from 'is-valid-css-color'; +import { CSSResultGroup, LitElement, PropertyValues, TemplateResult, css, html } from 'lit'; +import { customElement, property, state } from 'lit/decorators.js'; +import { until } from 'lit/directives/until.js'; +import { version } from '../package.json'; +import { actionHandler } from './action-handler-directive'; +import { ICONS, LABELS } from './conditions'; +import { DIRECTIONS } from './directions'; +import { getLocalizer } from './localize/localize'; import type { ColorConfig, ColorDefinition, ColorMap, ColorObject, ColorSettings, + Condition, ConditionSpan, ForecastEvent, ForecastSegment, @@ -32,15 +38,9 @@ import type { RenderTemplateResult, SegmentPrecipitation, SegmentTemperature, - SegmentWind, - Condition + SegmentWind } from './types'; -import { actionHandler } from './action-handler-directive'; -import { version } from '../package.json'; -import { getLocalizer } from './localize/localize'; import { WeatherBar } from './weather-bar'; -import { ICONS, LABELS } from './conditions'; -import { DIRECTIONS } from './directions'; customElements.define('weather-bar', WeatherBar); // Naive localizer is used before we can get at card configuration data @@ -99,7 +99,7 @@ export class HourlyWeatherCard extends LitElement { private localize(string: string, search = '', replace = ''): string { if (!this.localizer || - this.localizerSettingsChanged) { + this.localizerSettingsChanged) { this.localizer = getLocalizer(this.config?.language, this.hass?.locale?.language); this.localizerLastSettings.configuredLanguage = this.config?.language; this.localizerLastSettings.haServerLanguage = this.hass?.locale?.language; @@ -284,7 +284,7 @@ export class HourlyWeatherCard extends LitElement { this.triggerConfigRender(); } if (!this.subscribedToForecast || - (changedProps.has('config') && this.config?.entity !== changedProps.get('config')?.entity)) { + (changedProps.has('config') && this.config?.entity !== changedProps.get('config')?.entity)) { this.subscribeToForecastEvents(); } } @@ -347,7 +347,7 @@ export class HourlyWeatherCard extends LitElement { const isFull = config.icon_fill === 'full'; const isSingle = config.icon_fill === 'single'; const valueAsNumber = Number(config.icon_fill); //Undefined and non-numerical strings will be converted NaN, but null is 0 - const isPositiveInteger = Number.isInteger(valueAsNumber) && valueAsNumber > 0; + const isPositiveInteger = Number.isInteger(valueAsNumber) && valueAsNumber > 0; if (!isFull && !isSingle && !isPositiveInteger) { return await this._showError(this.localize('errors.invalid_value_icon_fill')); } @@ -357,9 +357,6 @@ export class HourlyWeatherCard extends LitElement { if (typeof showWind === 'boolean') { showWind = showWind ? 'true' : 'false'; } - if (showWind?.includes('barb') && typeof forecast?.[0].wind_bearing === 'string') { - return await this._showError(this.localize('errors.no_wind_barbs_with_string_bearing')); - } if (forecastNotAvailable) { if (pending) return; @@ -375,8 +372,8 @@ export class HourlyWeatherCard extends LitElement { .label=${`Hourly Weather: ${config.entity || 'No Entity Defined'}`} >
-

${ this.localize('errors.forecast_not_available') }

-

${ this.localize('errors.check_entity') }

+

${this.localize('errors.forecast_not_available')}

+

${this.localize('errors.check_entity')}

`; } diff --git a/src/weather-bar.ts b/src/weather-bar.ts index bf7b8d15..f4c2fee6 100644 --- a/src/weather-bar.ts +++ b/src/weather-bar.ts @@ -1,10 +1,11 @@ -import { LitElement, html, css, TemplateResult, unsafeCSS, PropertyValueMap } from "lit"; +import { css, html, LitElement, PropertyValueMap, TemplateResult, unsafeCSS } from "lit"; import { property } from "lit/decorators.js"; import { StyleInfo, styleMap } from 'lit/directives/style-map.js'; import tippy, { Instance } from 'tippy.js'; -import { LABELS, ICONS } from "./conditions"; +import { ICONS, LABELS } from "./conditions"; +import { DIRECTIONS_BEARINGS } from './directions'; import { getWindBarbSVG } from "./lib/svg-wind-barbs"; -import type { ColorMap, ConditionSpan, SegmentTemperature, SegmentWind, SegmentPrecipitation, WindType, ShowDateType, IconFillType, IconMap } from "./types"; +import type { ColorMap, ConditionSpan, IconFillType, IconMap, SegmentPrecipitation, SegmentTemperature, SegmentWind, ShowDateType, WindType } from "./types"; const tippyStyles: string = process.env.TIPPY_CSS!; @@ -141,9 +142,12 @@ export class WeatherBar extends LitElement { const { windSpeed, windSpeedRawMS, windDirection, windDirectionRaw } = this.wind[i]; const wind: TemplateResult[] = []; - if (showWindBarb && typeof windDirectionRaw === 'number') { + const bearing: number = typeof windDirectionRaw === 'number' + ? windDirectionRaw + : DIRECTIONS_BEARINGS[windDirectionRaw.toLowerCase()]; + if (showWindBarb && bearing !== undefined) { wind.push(html` - ${this.getWindBarb(windSpeedRawMS, windDirectionRaw)} + ${this.getWindBarb(windSpeedRawMS, bearing)} `); if (showWindSpeed || showWindDirection) wind.push(html`
`); } @@ -205,7 +209,7 @@ export class WeatherBar extends LitElement { if (color.background) vars.push(`--color-${key}: ${color.background};`); if (color.foreground) - vars.push(`--color-${key}-foreground: ${color.foreground};`); + vars.push(`--color-${key}-foreground: ${color.foreground};`); } return html`