Skip to content

Commit

Permalink
Add weather forecast options to more info (#17823)
Browse files Browse the repository at this point in the history
  • Loading branch information
bramkragten authored Sep 5, 2023
1 parent c3c4bb4 commit 32472ca
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 25 deletions.
22 changes: 20 additions & 2 deletions src/data/weather.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,9 @@ export const enum WeatherEntityFeature {
FORECAST_TWICE_DAILY = 4,
}

export type ForecastType = "legacy" | "hourly" | "daily" | "twice_daily";
export type ModernForecastType = "hourly" | "daily" | "twice_daily";

export type ForecastType = ModernForecastType | "legacy";

interface ForecastAttribute {
temperature: number;
Expand Down Expand Up @@ -636,7 +638,7 @@ export const getForecast = (
export const subscribeForecast = (
hass: HomeAssistant,
entity_id: string,
forecast_type: "daily" | "hourly" | "twice_daily",
forecast_type: ModernForecastType,
callback: (forecastevent: ForecastEvent) => void
) =>
hass.connection.subscribeMessage<ForecastEvent>(callback, {
Expand All @@ -645,6 +647,22 @@ export const subscribeForecast = (
entity_id,
});

export const getSupportedForecastTypes = (
stateObj: HassEntityBase
): ModernForecastType[] => {
const supported: ModernForecastType[] = [];
if (supportsFeature(stateObj, WeatherEntityFeature.FORECAST_DAILY)) {
supported.push("daily");
}
if (supportsFeature(stateObj, WeatherEntityFeature.FORECAST_TWICE_DAILY)) {
supported.push("twice_daily");
}
if (supportsFeature(stateObj, WeatherEntityFeature.FORECAST_HOURLY)) {
supported.push("hourly");
}
return supported;
};

export const getDefaultForecastType = (stateObj: HassEntityBase) => {
if (supportsFeature(stateObj, WeatherEntityFeature.FORECAST_DAILY)) {
return "daily";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import "@material/mwc-button";
import "@material/mwc-tab-bar/mwc-tab-bar";
import "@material/mwc-tab/mwc-tab";
import { mdiEyedropper } from "@mdi/js";
import {
css,
Expand Down
77 changes: 62 additions & 15 deletions src/dialogs/more-info/controls/more-info-weather.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import "@material/mwc-tab";
import "@material/mwc-tab-bar";
import {
mdiEye,
mdiGauge,
Expand All @@ -14,14 +16,17 @@ import {
nothing,
} from "lit";
import { customElement, property, state } from "lit/decorators";
import memoizeOne from "memoize-one";
import { formatDateWeekdayDay } from "../../../common/datetime/format_date";
import { formatTimeWeekday } from "../../../common/datetime/format_time";
import "../../../components/ha-svg-icon";
import {
ForecastEvent,
ModernForecastType,
WeatherEntity,
getDefaultForecastType,
getForecast,
getSupportedForecastTypes,
getWind,
subscribeForecast,
weatherIcons,
Expand All @@ -36,32 +41,37 @@ class MoreInfoWeather extends LitElement {

@state() private _forecastEvent?: ForecastEvent;

@state() private _forecastType?: ModernForecastType;

@state() private _subscribed?: Promise<() => void>;

private _unsubscribeForecastEvents() {
if (this._subscribed) {
this._subscribed.then((unsub) => unsub());
this._subscribed = undefined;
}
this._forecastEvent = undefined;
}

private async _subscribeForecastEvents() {
this._unsubscribeForecastEvents();
if (!this.isConnected || !this.hass || !this.stateObj) {
if (
!this.isConnected ||
!this.hass ||
!this.stateObj ||
!this._forecastType
) {
return;
}

const forecastType = getDefaultForecastType(this.stateObj);
if (forecastType) {
this._subscribed = subscribeForecast(
this.hass!,
this.stateObj!.entity_id,
forecastType,
(event) => {
this._forecastEvent = event;
}
);
}
this._subscribed = subscribeForecast(
this.hass!,
this.stateObj!.entity_id,
this._forecastType,
(event) => {
this._forecastEvent = event;
}
);
}

public connectedCallback() {
Expand Down Expand Up @@ -93,27 +103,36 @@ class MoreInfoWeather extends LitElement {
return false;
}

protected updated(changedProps: PropertyValues): void {
super.updated(changedProps);
protected willUpdate(changedProps: PropertyValues): void {
super.willUpdate(changedProps);

if (changedProps.has("stateObj") || !this._subscribed) {
if ((changedProps.has("stateObj") || !this._subscribed) && this.stateObj) {
const oldState = changedProps.get("stateObj") as
| WeatherEntity
| undefined;
if (
oldState?.entity_id !== this.stateObj?.entity_id ||
!this._subscribed
) {
this._forecastType = getDefaultForecastType(this.stateObj);
this._subscribeForecastEvents();
}
} else if (changedProps.has("_forecastType")) {
this._subscribeForecastEvents();
}
}

private _supportedForecasts = memoizeOne((stateObj: WeatherEntity) =>
getSupportedForecastTypes(stateObj)
);

protected render() {
if (!this.hass || !this.stateObj) {
return nothing;
}

const supportedForecasts = this._supportedForecasts(this.stateObj);

const forecastData = getForecast(
this.stateObj.attributes,
this._forecastEvent
Expand Down Expand Up @@ -210,6 +229,23 @@ class MoreInfoWeather extends LitElement {
<div class="section">
${this.hass.localize("ui.card.weather.forecast")}:
</div>
${supportedForecasts.length > 1
? html`<mwc-tab-bar
.activeIndex=${supportedForecasts.findIndex(
(item) => item === this._forecastType
)}
@MDCTabBar:activated=${this._handleForecastTypeChanged}
>
${supportedForecasts.map(
(forecastType) =>
html`<mwc-tab
.label=${this.hass!.localize(
`ui.card.weather.${forecastType}`
)}
></mwc-tab>`
)}
</mwc-tab-bar>`
: nothing}
${forecast.map((item) =>
this._showValue(item.templow) || this._showValue(item.temperature)
? html`<div class="flex">
Expand Down Expand Up @@ -283,12 +319,23 @@ class MoreInfoWeather extends LitElement {
`;
}

private _handleForecastTypeChanged(ev: CustomEvent): void {
this._forecastType = this._supportedForecasts(this.stateObj!)[
ev.detail.index
];
}

static get styles(): CSSResultGroup {
return css`
ha-svg-icon {
color: var(--paper-item-icon-color);
margin-left: 8px;
}
mwc-tab-bar {
margin-bottom: 4px;
}
.section {
margin: 16px 0 8px 0;
font-size: 1.2em;
Expand Down
2 changes: 0 additions & 2 deletions src/dialogs/more-info/ha-more-info-settings.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import "@material/mwc-tab";
import "@material/mwc-tab-bar";
import {
css,
CSSResultGroup,
Expand Down
2 changes: 0 additions & 2 deletions src/panels/config/network/supervisor-hostname.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import "@material/mwc-button/mwc-button";
import "@material/mwc-list/mwc-list";
import "@material/mwc-list/mwc-list-item";
import "@material/mwc-tab";
import "@material/mwc-tab-bar";
import { css, CSSResultGroup, html, LitElement, nothing } from "lit";
import { customElement, property, state } from "lit/decorators";
import "../../../components/ha-alert";
Expand Down
2 changes: 0 additions & 2 deletions src/panels/lovelace/editor/card-editor/hui-card-picker.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import "@material/mwc-tab-bar/mwc-tab-bar";
import "@material/mwc-tab/mwc-tab";
import Fuse from "fuse.js";
import {
css,
Expand Down
3 changes: 3 additions & 0 deletions src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -261,6 +261,9 @@
"forecast_daily": "Forecast daily",
"forecast_hourly": "Forecast hourly",
"forecast_twice_daily": "Forecast twice daily",
"daily": "Daily",
"hourly": "Hourly",
"twice_daily": "Twice daily",
"high": "High",
"low": "Low"
}
Expand Down

0 comments on commit 32472ca

Please sign in to comment.