Skip to content

Commit

Permalink
Update weather forecast
Browse files Browse the repository at this point in the history
  • Loading branch information
matt8707 committed Apr 20, 2024
1 parent 4d7367d commit 91f37cc
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 34 deletions.
80 changes: 58 additions & 22 deletions src/lib/Modal/WeatherForecastConfig.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@
import Select from '$lib/Components/Select.svelte';
import ConfigButtons from '$lib/Modal/ConfigButtons.svelte';
import Modal from '$lib/Modal/Index.svelte';
import { updateObj } from '$lib/Utils';
import type { HassEntity } from 'home-assistant-js-websocket';
import type { WeatherForecastItem } from '$lib/Types';
import { getSupport, updateObj } from '$lib/Utils';
import Ripple from 'svelte-ripple';
export let isOpen: boolean;
export let sel: WeatherForecastItem;
export let sel: any;
export let demo: string | undefined = undefined;
if (demo) {
Expand All @@ -20,30 +18,28 @@
set('entity_id', demo);
}
$: entity = $states[sel?.entity_id];
$: attributes = entity?.attributes;
$: supported_features = attributes?.supported_features;
$: supports = getSupport(supported_features, {
FORECAST_DAILY: 1,
FORECAST_HOURLY: 2,
FORECAST_TWICE_DAILY: 4
});
let days_to_show = sel?.days_to_show ?? 7;
let numberElement: HTMLInputElement;
let entity: HassEntity;
$: if (sel?.entity_id) {
if ($states?.[sel?.entity_id]?.last_updated !== entity?.last_updated) {
entity = $states?.[sel?.entity_id];
}
}
const iconOptions = [
{ id: 'meteocons', label: 'meteocons' },
{ id: 'weathericons', label: 'weather icons' },
{ id: 'materialsymbolslight', label: 'materialsymbolslight' }
];
$: weatherStates = Object.keys(
Object.fromEntries(
Object.entries($states).filter(
([key, value]) => key.startsWith('weather.') && value?.attributes?.forecast
)
)
)
$: options = Object.keys($states)
.filter((key) => key.startsWith('weather.'))
.sort()
.map((key) => ({ id: key, label: key }));
Expand Down Expand Up @@ -82,14 +78,18 @@

<h2>{$lang('entity')}</h2>

{#if weatherStates}
{#if options}
<Select
computeIcons={true}
defaultIcon="mdi:weather-cloudy"
options={weatherStates}
{options}
placeholder={$lang('entity')}
value={sel?.entity_id}
on:change={(event) => set('entity_id', event)}
on:change={(event) => {
// remove 'forecast_type' when changing entity_id
set('forecast_type');
set('entity_id', event);
}}
/>
{/if}

Expand All @@ -106,7 +106,7 @@

<h2>{$lang('days_to_show')}</h2>

{#if weatherStates}
{#if options}
<input
type="number"
class="input"
Expand All @@ -119,6 +119,42 @@
/>
{/if}

{#if Object.keys(supports).filter((key) => supports[key]).length > 1}
<h2>{$lang('forecast_type')}</h2>

<div class="button-container">
{#if supports?.FORECAST_DAILY}
<button
class:selected={sel?.forecast_type === 'daily' || !sel?.forecast_type}
on:click={() => set('forecast_type', 'daily')}
use:Ripple={$ripple}
>
{$lang('forecast_daily')}
</button>
{/if}

{#if supports?.FORECAST_HOURLY}
<button
class:selected={sel?.forecast_type === 'hourly'}
on:click={() => set('forecast_type', 'hourly')}
use:Ripple={$ripple}
>
{$lang('forecast_hourly')}
</button>
{/if}

{#if supports?.FORECAST_TWICE_DAILY}
<button
class:selected={sel?.forecast_type === 'twice_daily'}
on:click={() => set('forecast_type', 'twice_daily')}
use:Ripple={$ripple}
>
{$lang('forecast_twice_daily')}
</button>
{/if}
</div>
{/if}

<h2>{$lang('mobile')}</h2>

<div class="button-container">
Expand Down
63 changes: 51 additions & 12 deletions src/lib/Sidebar/WeatherForecast.svelte
Original file line number Diff line number Diff line change
@@ -1,23 +1,53 @@
<script lang="ts">
import { states, selectedLanguage, lang } from '$lib/Stores';
import { states, selectedLanguage, lang, connection, forecasts } from '$lib/Stores';
import { iconMapMaterialSymbolsLight, iconMapMeteocons, iconMapWeatherIcons } from '$lib/Weather';
import type { WeatherIconSet, WeatherIconConditions, WeatherIconMapping } from '$lib/Weather';
import type { HassEntity } from 'home-assistant-js-websocket';
import Icon from '@iconify/svelte';
import { getSupport } from '$lib/Utils';
export let sel: any;
let entity: HassEntity;
$: {
if (sel?.entity_id) {
if ($states?.[sel?.entity_id]?.last_updated !== entity?.last_updated) {
entity = $states?.[sel?.entity_id];
$: entity = $states?.[sel?.entity_id];
$: attributes = entity?.attributes;
$: supported_features = attributes?.supported_features;
$: supports = getSupport(supported_features, {
FORECAST_DAILY: 1,
FORECAST_HOURLY: 2,
FORECAST_TWICE_DAILY: 4
});
// get forecast data when sel changes
// TODO: also update periodically
$: if (sel) getForecast();
function getForecast() {
// fallback if forecast_type is not defined select first true
const _default = Object.keys(supports)
?.find((key) => supports[key])
?.replace('FORECAST_', '')
?.toLowerCase();
// dont get forecast if it's already stored
const entityMatches = sel?.entity_id === $forecasts[sel?.id]?.entity_id;
const typeMatches = (sel?.forecast_type || _default) === $forecasts[sel?.id]?.type;
const dragging = sel?.id === 'id:dnd-shadow-placeholder-0000';
if ((entityMatches && typeMatches) || dragging || !$states) return;
// console.debug('fire!', sel?.id);
$connection?.subscribeMessage(
(data: any) => {
$forecasts[sel?.id] = { ...data, entity_id: sel?.entity_id, subscribed: Date.now() };
},
{
type: 'weather/subscribe_forecast',
entity_id: sel?.entity_id,
forecast_type: sel?.forecast_type || _default
}
}
);
}
$: attributes = entity?.attributes;
let iconSet: WeatherIconSet;
$: {
if (sel?.icon_pack === 'materialsymbolslight') {
Expand All @@ -41,7 +71,7 @@
temperature: number;
}
let forecast: Forecast[];
$: forecast = entity?.attributes?.forecast?.slice(0, calculated).map(function (item: any) {
$: forecast = $forecasts?.[sel?.id]?.forecast?.slice(0, calculated).map(function (item: any) {
let icon: WeatherIconMapping =
iconSet.conditions[item?.condition as keyof WeatherIconConditions];
let x: Forecast = {
Expand Down Expand Up @@ -93,7 +123,7 @@
{/each}
</div>
{:else}
<div class="container-empty">
<div class="empty">
{$lang('weather_forecast')}
</div>
{/if}
Expand Down Expand Up @@ -123,6 +153,15 @@
padding-left: 0;
padding-right: 0.25rem;
margin-left: -0.1rem;
height: 7.5rem;
}
.empty {
word-wrap: break-word;
padding: 0.5em;
overflow: hidden;
text-shadow: 0px 0px 5px rgba(0, 0, 0, 0.2);
height: 7.5rem;
}
.day {
Expand Down
1 change: 1 addition & 0 deletions src/lib/Stores.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ export const highlightView = writable<boolean>(false);
// sidebar
export const timers = writable<{ [key: string]: { pausedState: string } }>({});
export const barErrors = writable<{ [key: string]: string }>({});
export const forecasts = writable<{ [key: string]: any }>({});
export const templates = writable<Template>({});
export const demo = writable<{ [key: string]: string | undefined }>({
graph: undefined,
Expand Down

0 comments on commit 91f37cc

Please sign in to comment.