Skip to content

Commit

Permalink
Add (optional) precipitation amount (#184)
Browse files Browse the repository at this point in the history
  • Loading branch information
pauln committed Oct 18, 2022
1 parent d995aee commit 5f802c4
Show file tree
Hide file tree
Showing 8 changed files with 110 additions and 23 deletions.
37 changes: 19 additions & 18 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,24 +56,25 @@ Otherwise, the integration may complain of a duplicate unique ID.

## Options

| Name | Type | Requirement | Description | Default |
| ----------------- | ------ | ------------ | --------------------------------------------------------- | ------------------- |
| type | string | **Required** | `custom:hourly-weather` | |
| entity | string | **Required** | Home Assistant weather entity ID. | |
| name | string | **Optional** | Card name (set to `null` to hide) | `Hourly Weather` |
| icons | bool | **Optional** | Whether to show icons instead of text labels | `false` |
| num_segments | number | **Optional** | Number of forecast segments to show (even integer >= 2) | `12` |
| ~~num_hours~~ | number | **Optional** | _Deprecated:_ Use `num_segments` instead | `12` |
| offset | number | **Optional** | Number of forecast segments to offset from start | `0` |
| label_spacing | number | **Optional** | Space between time/temperature labels (even integer >= 2) | `2` |
| colors | object | **Optional** | Set colors for all or some conditions | |
| hide_hours | bool | **Optional** | Whether to hide hour labels under the bar | `false` |
| hide_temperatures | bool | **Optional** | Whether to hide temeratures under the bar | `false` |
| show_wind | bool | **Optional** | Whether to show wind speed and direction under the bar | `false` |
| tap_action | object | **Optional** | Action to take on tap | `action: more-info` |
| hold_action | object | **Optional** | Action to take on hold | `none` |
| double_tap_action | object | **Optional** | Action to take on double tap | `none` |
| language | string | **Optional** | Language to use for card (overrides HA & user settings) | |
| Name | Type | Requirement | Description | Default |
| -------------------------- | ------ | ------------ | --------------------------------------------------------- | ------------------- |
| type | string | **Required** | `custom:hourly-weather` | |
| entity | string | **Required** | Home Assistant weather entity ID. | |
| name | string | **Optional** | Card name (set to `null` to hide) | `Hourly Weather` |
| icons | bool | **Optional** | Whether to show icons instead of text labels | `false` |
| num_segments | number | **Optional** | Number of forecast segments to show (even integer >= 2) | `12` |
| ~~num_hours~~ | number | **Optional** | _Deprecated:_ Use `num_segments` instead | `12` |
| offset | number | **Optional** | Number of forecast segments to offset from start | `0` |
| label_spacing | number | **Optional** | Space between time/temperature labels (even integer >= 2) | `2` |
| colors | object | **Optional** | Set colors for all or some conditions | |
| hide_hours | bool | **Optional** | Whether to hide hour labels under the bar | `false` |
| hide_temperatures | bool | **Optional** | Whether to hide temeratures under the bar | `false` |
| show_wind | bool | **Optional** | Whether to show wind speed and direction under the bar | `false` |
| show_precipitation_amounts | bool | **Optional** | Whether to show precipitation (rain) amount under the bar | `false` |
| tap_action | object | **Optional** | Action to take on tap | `action: more-info` |
| hold_action | object | **Optional** | Action to take on hold | `none` |
| double_tap_action | object | **Optional** | Action to take on double tap | `none` |
| language | string | **Optional** | Language to use for card (overrides HA & user settings) | |

### Templating

Expand Down
36 changes: 36 additions & 0 deletions cypress/e2e/weather-bar.cy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -305,5 +305,41 @@ describe('Weather bar', () => {
cy.wrap(el).should('have.text', `${expectedWindSpeeds[i]} mph${expectedWindDirections[i]}`);
});
});

it('does not show precipitation by default', () => {
cy.get('weather-bar')
.shadow()
.find('div.axes > div.bar-block div.precipitation')
.should('have.length', 6)
.each((el) => {
cy.wrap(el).should('be.empty');
});
});

const expectedPrecipitation = [
0.35,
1.3,
0,
0,
0,
0,
];

it('shows precipitation if specified in config', () => {
cy.configure({
show_precipitation_amounts: true
});
cy.get('weather-bar')
.shadow()
.find('div.axes > div.bar-block div.precipitation')
.should('have.length', 6)
.each((el, i) => {
if (expectedPrecipitation[i] === 0) {
cy.wrap(el).should('be.empty');
} else {
cy.wrap(el).should('have.text', `${expectedPrecipitation[i]} in`);
}
});
});
});
});
5 changes: 3 additions & 2 deletions cypress/fixtures/harness.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
'weather.mock': {
attributes: {
wind_speed_unit: "mph",
precipitation_unit: "in",
forecast: [
{
"datetime": "2022-07-21T17:00:00+00:00",
Expand All @@ -49,7 +50,7 @@
},
{
"datetime": "2022-07-21T18:00:00+00:00",
"precipitation": 0,
"precipitation": 0.35,
"precipitation_probability": 0,
"pressure": 1007,
"wind_speed": 6.07,
Expand All @@ -71,7 +72,7 @@
},
{
"datetime": "2022-07-21T20:00:00+00:00",
"precipitation": 0,
"precipitation": 1.3,
"precipitation_probability": 1,
"pressure": 1007,
"wind_speed": 5.9,
Expand Down
11 changes: 11 additions & 0 deletions src/editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ export class HourlyWeatherCardEditor extends ScopedRegistryHost(LitElement) impl
return this._config?.show_wind ?? false;
}

get _show_precipitation_amounts(): boolean {
return this._config?.show_precipitation_amounts ?? false;
}

get _offset(): string {
return this._config?.offset ?? '0';
}
Expand Down Expand Up @@ -146,6 +150,13 @@ export class HourlyWeatherCardEditor extends ScopedRegistryHost(LitElement) impl
@change=${this._valueChanged}
></mwc-switch>
</mwc-formfield>
<mwc-formfield .label=${localize('editor.show_precipitation_amounts')}>
<mwc-switch
.checked=${this._show_precipitation_amounts === true}
.configValue=${'show_precipitation_amounts'}
@change=${this._valueChanged}
></mwc-switch>
</mwc-formfield>
`;
}

Expand Down
21 changes: 21 additions & 0 deletions src/hourly-weather.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import type {
RenderTemplateResult,
SegmentTemperature,
SegmentWind,
SegmentPrecipitation,
} from './types';
import { actionHandler } from './action-handler-directive';
import { version } from '../package.json';
Expand Down Expand Up @@ -229,6 +230,7 @@ export class HourlyWeatherCard extends LitElement {
const state = this.hass.states[entityId];
const { forecast } = state.attributes as { forecast: ForecastSegment[] };
const windSpeedUnit = state.attributes.wind_speed_unit ?? '';
const precipitationUnit = state.attributes.precipitation_unit ?? '';
const numSegments = parseInt(config.num_segments ?? config.num_hours ?? '12', 10);
const offset = parseInt(config.offset ?? '0', 10);
const labelSpacing = parseInt(config.label_spacing ?? '2', 10);
Expand Down Expand Up @@ -274,6 +276,7 @@ export class HourlyWeatherCard extends LitElement {
const conditionList = this.getConditionListFromForecast(forecast, numSegments, offset);
const temperatures = this.getTemperatures(forecast, numSegments, offset);
const wind = this.getWind(forecast, numSegments, offset, windSpeedUnit);
const precipitation = this.getPrecipitation(forecast, numSegments, offset, precipitationUnit);

const colorSettings = this.getColorSettings(config.colors);

Expand All @@ -298,11 +301,13 @@ export class HourlyWeatherCard extends LitElement {
.conditions=${conditionList}
.temperatures=${temperatures}
.wind=${wind}
.precipitation=${precipitation}
.icons=${!!config.icons}
.colors=${colorSettings.validColors}
.hide_hours=${!!config.hide_hours}
.hide_temperatures=${!!config.hide_temperatures}
.show_wind=${!!config.show_wind}
.show_precipitation_amounts=${!!config.show_precipitation_amounts}
.label_spacing=${labelSpacing}
.labels=${this.labels}></weather-bar>
</div>
Expand Down Expand Up @@ -339,6 +344,22 @@ export class HourlyWeatherCard extends LitElement {
return temperatures;
}

private getPrecipitation(forecast: ForecastSegment[], numSegments: number, offset: number, unit: string): SegmentPrecipitation[] {
const precipitation: SegmentPrecipitation[] = [];
for (let i = offset; i < numSegments + offset; i++) {
const fs = forecast[i];
let amount = '';
if (fs.precipitation > 0) {
amount = `${formatNumber(fs.precipitation, this.hass.locale)} ${unit}`.trim();
}
precipitation.push({
hour: this.formatHour(new Date(fs.datetime), this.hass.locale),
precipitationAmount: amount
})
}
return precipitation;
}

private getWind(forecast: ForecastSegment[], numSegments: number, offset: number, speedUnit: string): SegmentWind[] {
const wind: SegmentWind[] = [];
for (let i = offset; i < numSegments + offset; i++) {
Expand Down
3 changes: 2 additions & 1 deletion src/localize/languages/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
"offset": "Number of forecast segments to offset start by (Optional)",
"icons": "Show icons instead of text labels",
"label_spacing": "Number of forecast segments to space time and temperature labels by (Optional)",
"show_wind": "Show wind speed and direction"
"show_wind": "Show wind speed and direction",
"show_precipitation_amounts": "Show precipitation (rain) amount"
},
"errors": {
"missing_entity": "entity is missing in configuration",
Expand Down
6 changes: 6 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface HourlyWeatherCardConfig extends LovelaceCardConfig {
hide_hours?: boolean;
hide_temperatures?: boolean;
show_wind?: boolean;
show_precipitation_amounts?: boolean;
label_spacing?: string; // number
test_gui?: boolean;
tap_action?: ActionConfig;
Expand Down Expand Up @@ -74,6 +75,11 @@ export interface SegmentWind {
windDirection: string
}

export interface SegmentPrecipitation {
hour: string,
precipitationAmount: string
}

export type ColorMap = Map<keyof ColorConfig, string>

export interface ColorSettings {
Expand Down
14 changes: 12 additions & 2 deletions src/weather-bar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ 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 type { ColorMap, ConditionSpan, SegmentTemperature, SegmentWind } from "./types";
import type { ColorMap, ConditionSpan, SegmentTemperature, SegmentWind, SegmentPrecipitation } from "./types";

const tippyStyles: string = process.env.TIPPY_CSS || '';

Expand All @@ -17,6 +17,9 @@ export class WeatherBar extends LitElement {
@property({ type: Array })
wind: SegmentWind[] = [];

@property({ type: Array })
precipitation: SegmentPrecipitation[] = [];

@property({ type: Boolean })
icons = false;

Expand All @@ -32,6 +35,9 @@ export class WeatherBar extends LitElement {
@property({ type: Boolean })
show_wind = false;

@property({ type: Boolean })
show_precipitation_amounts = false;

@property({ type: Number })
label_spacing = 2;

Expand Down Expand Up @@ -64,8 +70,10 @@ export class WeatherBar extends LitElement {
const hideHours = this.hide_hours || skipLabel;
const hideTemperature = this.hide_temperatures || skipLabel;
const showWind = this.show_wind && !skipLabel;
const showPrecipitationAmounts = this.show_precipitation_amounts && !skipLabel;
const { hour, temperature } = this.temperatures[i];
const { windSpeed, windDirection } = this.wind[i];
const { precipitationAmount } = this.precipitation[i];
barBlocks.push(html`
<div class="bar-block">
<div class="bar-block-left"></div>
Expand All @@ -74,6 +82,7 @@ export class WeatherBar extends LitElement {
<div class="hour">${hideHours ? null : hour}</div>
<div class="temperature">${hideTemperature ? null : html`${temperature}&deg;`}</div>
<div class="wind">${showWind ? html`${windSpeed}<br>${windDirection}` : null }</div>
<div class="precipitation">${showPrecipitationAmounts ? html`${precipitationAmount}` : null }</div>
</div>
</div>
`);
Expand Down Expand Up @@ -253,7 +262,8 @@ export class WeatherBar extends LitElement {
.temperature {
font-size: 1.1rem;
}
.wind {
.wind,
.precipitation {
font-size: 0.9rem;
line-height: 1.1rem;
padding-top: 0.1rem;
Expand Down

0 comments on commit 5f802c4

Please sign in to comment.