├── .npmignore
├── .eslintignore
├── dist
├── icons
│ ├── background
│ │ ├── day-clear.jpg
│ │ ├── day-cloud-1.jpg
│ │ ├── day-cloud-2.jpg
│ │ └── day-cloud-3.jpg
│ ├── animated
│ │ ├── weather_sagittarius.svg
│ │ ├── clear-day.svg
│ │ ├── cloudy.svg
│ │ ├── partly-cloudy-day.svg
│ │ ├── weather_sunset.svg
│ │ ├── clear-night.svg
│ │ ├── partly-cloudy-night.svg
│ │ ├── haze.svg
│ │ ├── fog.svg
│ │ ├── rainy-4.svg
│ │ ├── rain.svg
│ │ ├── wind.svg
│ │ ├── snow.svg
│ │ ├── rainy-5.svg
│ │ ├── rainy-6.svg
│ │ ├── rainy-7.svg
│ │ └── snowy-4.svg
│ └── static
│ │ ├── weather_sagittarius.svg
│ │ ├── clear-day.svg
│ │ ├── clear-night.svg
│ │ ├── cloudy.svg
│ │ ├── weather_sunset.svg
│ │ ├── partly-cloudy-day.svg
│ │ ├── rainy-4.svg
│ │ ├── partly-cloudy-night.svg
│ │ ├── night.svg
│ │ ├── rainy-5.svg
│ │ ├── cloudy-original.svg
│ │ ├── haze.svg
│ │ ├── rainy-6.svg
│ │ ├── rainy-7.svg
│ │ ├── thunder.svg
│ │ ├── fog.svg
│ │ ├── snowy-4.svg
│ │ ├── cloudy-night-1.svg
│ │ ├── cloudy-night-2.svg
│ │ ├── cloudy-night-3.svg
│ │ ├── fair-night.svg
│ │ ├── rain-and-sleet-mix.svg
│ │ ├── rain-and-snow-mix.svg
│ │ ├── rain.svg
│ │ ├── day.svg
│ │ ├── snowy-5.svg
│ │ ├── severe-thunderstorm.svg
│ │ ├── cloudy-day-1.svg
│ │ ├── cloudy-day-3.svg
│ │ ├── cloudy-day-2.svg
│ │ ├── fair-day.svg
│ │ ├── rainy-2.svg
│ │ ├── snow-and-sleet-mix.svg
│ │ ├── isolated-thunderstorms.svg
│ │ ├── scattered-thunderstorms.svg
│ │ ├── snowy-6.svg
│ │ ├── tropical-storm.svg
│ │ ├── rainy-3.svg
│ │ ├── rainy-1.svg
│ │ ├── hurricane.svg
│ │ └── snowy-2.svg
└── transl
│ ├── es.json
│ ├── cs.json
│ ├── en.json
│ ├── da.json
│ ├── no-NO.json
│ ├── pt.json
│ ├── sr-latn.json
│ ├── ru.json
│ ├── it.json
│ ├── nl.json
│ ├── de.json
│ └── fr.json
├── md.images
├── ha-card-weather-condition-1.png
├── ha-card-weather-condition-2.png
├── ha-card-weather-condition-sea.png
├── ha-card-weather-condition-alarms.png
├── ha-card-weather-condition-alert.png
├── ha-card-weather-condition-full.png
├── ha-card-weather-condition-pollen.png
├── ha-card-weather-condition-overview.png
├── ha-card-weather-condition-present.png
├── ha-card-weather-condition-summary.png
├── ha-card-weather-condition-air-quality.png
├── ha-card-weather-condition-ultraviolet.png
├── ha-card-weather-condition-daily-forecast.png
├── ha-card-weather-condition-hourly-forecast.png
└── ha-card-weather-condition-marine-daily-forecast.png
├── backup
├── ha-card-weather-condition-present.png
└── ha-card-weather-condition-summary.png
├── hacs.json
├── .gitignore
├── .vscode
└── settings.json
├── src
├── css
│ ├── css-camera.ts
│ ├── css-present.ts
│ ├── css-meteoalarm.ts
│ ├── css-base-card.ts
│ ├── css-pollen.ts
│ ├── css-weather-forecast.ts
│ └── css-ultraviolet.ts
├── iconmodels
│ ├── im-darksky.ts
│ ├── im-openweathermap.ts
│ ├── im-hass.ts
│ ├── im-buienradar.ts
│ ├── im-climacell.ts
│ └── im-pirateweather.ts
├── templates
│ ├── t-camera.ts
│ ├── t-meteoalarm.ts
│ └── t-pollen.ts
├── builder
│ ├── b-camera.ts
│ ├── b-pollen.ts
│ ├── b-summary.ts
│ ├── b-ultraviolet.ts
│ └── b-airquality.ts
└── utils
│ ├── const.ts
│ ├── colors.ts
│ ├── helper-render.ts
│ └── config-schema.ts
├── tsconfig.json
├── .github
└── workflows
│ └── codeql.yml
├── LICENSE
├── .eslintrc.json
├── rollup.new.config.mjs
├── package.json
└── CHANGELOG.md
/.npmignore:
--------------------------------------------------------------------------------
1 | # OS X
2 | .DS_Store
3 | backup
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | backup/
2 | dist/
3 | node_modules/
4 | rollup.config.mjs
5 | rollup.config copy.js
6 | rollup.new.config.mjs
--------------------------------------------------------------------------------
/dist/icons/background/day-clear.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-renato/ha-card-weather-conditions/HEAD/dist/icons/background/day-clear.jpg
--------------------------------------------------------------------------------
/dist/icons/background/day-cloud-1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-renato/ha-card-weather-conditions/HEAD/dist/icons/background/day-cloud-1.jpg
--------------------------------------------------------------------------------
/dist/icons/background/day-cloud-2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-renato/ha-card-weather-conditions/HEAD/dist/icons/background/day-cloud-2.jpg
--------------------------------------------------------------------------------
/dist/icons/background/day-cloud-3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-renato/ha-card-weather-conditions/HEAD/dist/icons/background/day-cloud-3.jpg
--------------------------------------------------------------------------------
/md.images/ha-card-weather-condition-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-renato/ha-card-weather-conditions/HEAD/md.images/ha-card-weather-condition-1.png
--------------------------------------------------------------------------------
/md.images/ha-card-weather-condition-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-renato/ha-card-weather-conditions/HEAD/md.images/ha-card-weather-condition-2.png
--------------------------------------------------------------------------------
/md.images/ha-card-weather-condition-sea.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-renato/ha-card-weather-conditions/HEAD/md.images/ha-card-weather-condition-sea.png
--------------------------------------------------------------------------------
/backup/ha-card-weather-condition-present.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-renato/ha-card-weather-conditions/HEAD/backup/ha-card-weather-condition-present.png
--------------------------------------------------------------------------------
/backup/ha-card-weather-condition-summary.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-renato/ha-card-weather-conditions/HEAD/backup/ha-card-weather-condition-summary.png
--------------------------------------------------------------------------------
/md.images/ha-card-weather-condition-alarms.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-renato/ha-card-weather-conditions/HEAD/md.images/ha-card-weather-condition-alarms.png
--------------------------------------------------------------------------------
/md.images/ha-card-weather-condition-alert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-renato/ha-card-weather-conditions/HEAD/md.images/ha-card-weather-condition-alert.png
--------------------------------------------------------------------------------
/md.images/ha-card-weather-condition-full.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-renato/ha-card-weather-conditions/HEAD/md.images/ha-card-weather-condition-full.png
--------------------------------------------------------------------------------
/md.images/ha-card-weather-condition-pollen.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-renato/ha-card-weather-conditions/HEAD/md.images/ha-card-weather-condition-pollen.png
--------------------------------------------------------------------------------
/md.images/ha-card-weather-condition-overview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-renato/ha-card-weather-conditions/HEAD/md.images/ha-card-weather-condition-overview.png
--------------------------------------------------------------------------------
/md.images/ha-card-weather-condition-present.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-renato/ha-card-weather-conditions/HEAD/md.images/ha-card-weather-condition-present.png
--------------------------------------------------------------------------------
/md.images/ha-card-weather-condition-summary.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-renato/ha-card-weather-conditions/HEAD/md.images/ha-card-weather-condition-summary.png
--------------------------------------------------------------------------------
/md.images/ha-card-weather-condition-air-quality.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-renato/ha-card-weather-conditions/HEAD/md.images/ha-card-weather-condition-air-quality.png
--------------------------------------------------------------------------------
/md.images/ha-card-weather-condition-ultraviolet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-renato/ha-card-weather-conditions/HEAD/md.images/ha-card-weather-condition-ultraviolet.png
--------------------------------------------------------------------------------
/hacs.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "HA (Lovelace) Card Weather Conditions",
3 | "domains": ["weather"],
4 | "render_readme": false,
5 | "filename": "ha-card-weather-conditions.js"
6 | }
--------------------------------------------------------------------------------
/md.images/ha-card-weather-condition-daily-forecast.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-renato/ha-card-weather-conditions/HEAD/md.images/ha-card-weather-condition-daily-forecast.png
--------------------------------------------------------------------------------
/md.images/ha-card-weather-condition-hourly-forecast.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-renato/ha-card-weather-conditions/HEAD/md.images/ha-card-weather-condition-hourly-forecast.png
--------------------------------------------------------------------------------
/md.images/ha-card-weather-condition-marine-daily-forecast.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/r-renato/ha-card-weather-conditions/HEAD/md.images/ha-card-weather-condition-marine-daily-forecast.png
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # ####### ####### #######
2 | # Folders
3 |
4 | .idea
5 | __pycache__
6 | /node_modules/
7 | /.rpt2_cache/
8 | /trash/
9 | /backup/
10 |
11 | # ####### ####### #######
12 | # Files
13 | package-lock.json
14 |
15 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "eslint.enable": true,
3 | "eslint.validate": [
4 | "javascript",
5 | "javascriptreact",
6 | "typescript",
7 | "typescriptreact"
8 | ],
9 | "editor.tabSize": 2,
10 |
11 | "ha_module_path": "/home/drp/homeassistant/www/community/ha-card-weather-conditions",
12 | "editor.wordWrap": "wordWrapColumn",
13 | "editor.wordWrapColumn": 120,
14 | }
15 |
--------------------------------------------------------------------------------
/src/css/css-camera.ts:
--------------------------------------------------------------------------------
1 | import { css } from 'lit';
2 |
3 | const cameraStyle = css`
4 | .camera-container {
5 | margin-top: 10px;
6 | width: 100%;
7 | display: flex;
8 | align-items: stretch;
9 | }
10 |
11 | .camera-image {
12 | aspect-ratio: 16 / 9;
13 | width: 100%;
14 | position: relative;
15 | overflow: hidden;
16 | display: flex;
17 | align-items: center;
18 | justify-content: center;
19 | }
20 |
21 | .camera-image > img {
22 | width: 100%;
23 | height: 100%;
24 | object-fit: cover;
25 | }
26 | `;
27 |
28 | export default cameraStyle;
29 |
--------------------------------------------------------------------------------
/src/iconmodels/im-darksky.ts:
--------------------------------------------------------------------------------
1 | export const cwcDarkskyDayIcons: { [key: string]: string; } = {
2 | clear: 'day',
3 | 'clear-day': 'day',
4 | rain: 'rainy-2',
5 | snow: 'snowy-2',
6 | sleet: 'rain-and-sleet-mix',
7 | wind: 'cloudy-day-1',
8 | fog: 'fog',
9 | cloudy: 'cloudy-original',
10 | 'partly-cloudy-day': 'cloudy-day-2',
11 | };
12 |
13 | export const cwcDarkskyNightIcons: { [key: string]: string; } = {
14 | ...cwcDarkskyDayIcons,
15 | clear: 'night',
16 | 'clear-night': 'night',
17 | wind: 'cloudy-night-1',
18 | 'partly-cloudy-day': 'cloudy-night-2',
19 | 'partly-cloudy-night': 'cloudy-night-2',
20 | };
21 |
--------------------------------------------------------------------------------
/src/iconmodels/im-openweathermap.ts:
--------------------------------------------------------------------------------
1 | export const cwcOpenWeatherMapDayIcons: { [key: string]: string; } = {
2 | 'clear sky': 'day',
3 | 'few clouds': 'cloudy-day-1',
4 | 'scattered clouds': 'cloudy-day-2',
5 | 'broken clouds': 'cloudy-day-3',
6 | 'shower rain': 'rainy-3',
7 | rain: 'rainy-2',
8 | thunderstorm: 'tropical-storm',
9 | snow: 'snowy-2',
10 | mist: 'fog',
11 | };
12 |
13 | export const cwcOpenWeatherMapNightIcons: { [key: string]: string; } = {
14 | ...cwcOpenWeatherMapDayIcons,
15 | 'clear sky': 'day-night',
16 | 'few clouds': 'cloudy-night-1',
17 | 'scattered clouds': 'cloudy-night-2',
18 | 'broken clouds': 'cloudy-night-3',
19 | };
20 |
--------------------------------------------------------------------------------
/src/templates/t-camera.ts:
--------------------------------------------------------------------------------
1 | import { html } from 'lit';
2 |
3 | const renderCamera = (
4 | handlePopup: (e: Event, entityId: string) => void,
5 | cameraId: string,
6 | cameraPicture: string,
7 | friendlyName: string,
8 | ) => {
9 | if (!cameraPicture) return html``;
10 |
11 | return html`
12 |
handlePopup(e, cameraId)}
15 | >
16 |
17 |

22 |
23 |
24 | `;
25 | };
26 |
27 | export default renderCamera;
28 |
--------------------------------------------------------------------------------
/src/iconmodels/im-hass.ts:
--------------------------------------------------------------------------------
1 | export const cwcDefaultHassDayIcons: { [key: string]: string } = {
2 | cloudy: 'cloudy-day-3',
3 | exceptional: 'severe-thunderstorm',
4 | fog: 'fog',
5 | hail: 'snow-and-sleet-mix',
6 | lightning: 'severe-thunderstorm',
7 | 'lightning-rainy': 'scattered-thunderstorms',
8 | partlycloudy: 'cloudy-day-3',
9 | pouring: 'rainy-6',
10 | rainy: 'rainy-5',
11 | snowy: 'snowy-6',
12 | 'snowy-rainy': 'snow-and-sleet-mix',
13 | sunny: 'clear-day',
14 | windy: 'wind',
15 | 'windy-variant': 'wind',
16 | };
17 |
18 | export const cwcDefaultHassNightIcons: { [key: string]: string } = {
19 | ...cwcDefaultHassDayIcons,
20 | 'clear-night': 'clear-night',
21 | };
22 |
--------------------------------------------------------------------------------
/src/builder/b-camera.ts:
--------------------------------------------------------------------------------
1 | import { HomeAssistant } from 'custom-card-helpers/dist';
2 | import { iTerms } from '../base/lovelace-base';
3 | import renderCamera from '../templates/t-camera';
4 |
5 | const buildCamera = (
6 | hass: HomeAssistant,
7 | lang: string,
8 | terms: iTerms,
9 | handlePopup: (e: Event, entityId: string) => void,
10 | cameraId: string,
11 | ) => {
12 | const camera = cameraId && hass.states[cameraId];
13 |
14 | const entityPicture = camera?.attributes?.entity_picture;
15 | const friendlyName = camera?.attributes?.friendly_name ?? cameraId;
16 |
17 | return renderCamera(handlePopup, cameraId, entityPicture, friendlyName);
18 | };
19 |
20 | export default buildCamera;
21 |
--------------------------------------------------------------------------------
/src/css/css-present.ts:
--------------------------------------------------------------------------------
1 | import { css } from 'lit';
2 |
3 | const presentStyle = css`
4 | .present-grid-container {
5 | display: flex;
6 | flex-direction: column;
7 | gap: 4px;
8 | }
9 |
10 | .present-row {
11 | display: flex;
12 | justify-content: space-between;
13 | gap: 16px;
14 | }
15 |
16 | .present-left,
17 | .present-right {
18 | flex: 1;
19 | }
20 |
21 | .present-left {
22 | display: flex;
23 | justify-content: flex-start;
24 | }
25 |
26 | .present-right {
27 | display: flex;
28 | justify-content: flex-end;
29 | }
30 |
31 | .present-value-block {
32 | display: flex;
33 | align-items: center;
34 | gap: 4px;
35 | }
36 |
37 | .present-unit {
38 | font-size: 0.9em;
39 | opacity: 0.8;
40 | }
41 | `;
42 |
43 | export default presentStyle;
44 |
--------------------------------------------------------------------------------
/dist/icons/animated/weather_sagittarius.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/dist/icons/static/weather_sagittarius.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/dist/transl/es.json:
--------------------------------------------------------------------------------
1 | {
2 | "cwcLocWindDirections": {
3 | "N": "N",
4 | "NNE": "NNE",
5 | "NE": "NE",
6 | "ENE": "ENE",
7 | "E": "E",
8 | "ESE": "ESE",
9 | "SE": "SE",
10 | "SSE": "SSE",
11 | "S": "S",
12 | "SSW": "SSO",
13 | "SW": "SO",
14 | "WSW": "OSO",
15 | "W": "O",
16 | "WNW": "ONO",
17 | "NW": "NO",
18 | "NNW": "NNO"
19 | },
20 |
21 | "cwcTerms": {
22 | "Feels Like" : "Sensación térmica",
23 | "new_moon": "Luna nueva",
24 | "new": "Luna nueva",
25 | "waxing_crescent": "Luna creciente",
26 | "first_quarter": "Cuarto creciente",
27 | "waxing_gibbous": "Luna menguante gibosa",
28 | "full": "Luna llena",
29 | "full_moon": "Luna llena",
30 | "waning_gibbous": "Luna menguante gibosa",
31 | "third_quarter": "Media luna",
32 | "last_quarter": "Cuarto menguante",
33 | "waning_crescent": "Luna menguante"
34 | }
35 | }
--------------------------------------------------------------------------------
/src/css/css-meteoalarm.ts:
--------------------------------------------------------------------------------
1 | import { css } from 'lit';
2 |
3 | const meteodcpalarmStyle = css`
4 | .meteodcpalarm-grid-container {
5 | display: flex;
6 | flex-wrap: wrap;
7 | justify-content: center;
8 | gap: 16px;
9 | padding: 12px;
10 | }
11 |
12 | .meteodcpalarm-group {
13 | display: flex;
14 | flex-direction: column;
15 | align-items: center;
16 | flex: 1 1 72px; /* 👈 cresce, ma non scende sotto i 72px */
17 | max-width: 220px; /* 👈 opzionale: previene allargamento eccessivo */
18 | text-align: center;
19 | }
20 |
21 | .meteodcpalarm-group ha-icon {
22 | --mdc-icon-size: 36px;
23 | }
24 |
25 | .meteodcpalarm-label {
26 | margin-top: 6px;
27 | font-size: 0.85em;
28 | color: var(--primary-text-color);
29 | }
30 |
31 |
32 | `;
33 |
34 | export default meteodcpalarmStyle;
35 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "es2020",
4 | "module": "esnext",
5 | "moduleResolution": "node",
6 | "lib": ["es2020", "dom", "dom.iterable"],
7 | "noEmit": true,
8 | "noUnusedLocals": false,
9 | "noUnusedParameters": false,
10 | "noImplicitReturns": true,
11 | "noFallthroughCasesInSwitch": true,
12 | "strict": true,
13 | "noImplicitAny": false,
14 | "skipLibCheck": true,
15 | "resolveJsonModule": true,
16 | "experimentalDecorators": true,
17 | "strictNullChecks": false
18 | },
19 |
20 | "include": ["src/**/*.ts"],
21 | "exclude": ["node_modules"],
22 |
23 | "scripts": {
24 | "start": "rollup -c --watch",
25 | "build": "npm run lint && npm run rollup",
26 | "lint": "eslint src/*.ts",
27 | "rollup": "rollup -c"
28 | }
29 | }
--------------------------------------------------------------------------------
/dist/icons/static/clear-day.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dist/transl/cs.json:
--------------------------------------------------------------------------------
1 | {
2 | "cwcLocWindDirections": {
3 | "N": "S",
4 | "NNE": "SSV",
5 | "NE": "SV",
6 | "ENE": "VSV",
7 | "E": "V",
8 | "ESE": "VJV",
9 | "SE": "JV",
10 | "SSE": "JJV",
11 | "S": "J",
12 | "SSW": "JJZ",
13 | "SW": "JZ",
14 | "WSW": "ZJZ",
15 | "W": "Z",
16 | "WNW": "ZSZ",
17 | "NW": "SZ",
18 | "NNW": "SSZ"
19 | },
20 |
21 | "cwcTerms": {
22 | "Feels Like" : "Pocitová teplota",
23 | "new_moon": "Nov",
24 | "new": "Nov",
25 | "waxing_crescent": "Dorůstající srpek",
26 | "first_quarter": "První čtvrť",
27 | "waxing_gibbous": "Dorůstající měsíc",
28 | "full": "Úplněk",
29 | "full_moon": "Úplněk",
30 | "waning_gibbous": "Couvající měsíc",
31 | "third_quarter": "Třetí čtvrť",
32 | "last_quarter": "Poslední čtvrť",
33 | "waning_crescent": "Ubývající srpek"
34 | }
35 | }
--------------------------------------------------------------------------------
/dist/transl/en.json:
--------------------------------------------------------------------------------
1 | {
2 | "cwcLocWindDirections": {
3 | "N": "N",
4 | "NNE": "NNE",
5 | "NE": "NE",
6 | "ENE": "ENE",
7 | "E": "E",
8 | "ESE": "ESE",
9 | "SE": "SE",
10 | "SSE": "SSE",
11 | "S": "S",
12 | "SSW": "SSW",
13 | "SW": "SW",
14 | "WSW": "WSW",
15 | "W": "W",
16 | "WNW": "WNW",
17 | "NW": "NW",
18 | "NNW": "NNW"
19 | },
20 |
21 | "cwcTerms": {
22 | "Feels Like" : "Feels Like",
23 | "new_moon": "New moon",
24 | "new": "New moon",
25 | "waxing_crescent": "Waxing crescent",
26 | "first_quarter": "First quarter",
27 | "waxing_gibbous": "Waxing Gibbous",
28 | "full": "Full",
29 | "full_moon": "Full",
30 | "waning_gibbous": "Waning Gibbous",
31 | "third_quarter": "Third Quarter",
32 | "last_quarter": "Last Quarter",
33 | "waning_crescent": "Waning Crescent"
34 | }
35 | }
--------------------------------------------------------------------------------
/dist/transl/da.json:
--------------------------------------------------------------------------------
1 | {
2 | "cwcLocWindDirections": {
3 | "N": "N",
4 | "NNE": "NNØ",
5 | "NE": "NØ",
6 | "ENE": "ØNØ",
7 | "E": "Ø",
8 | "ESE": "ØSØ",
9 | "SE": "SØ",
10 | "SSE": "SSØ",
11 | "S": "S",
12 | "SSW": "SSV",
13 | "SW": "SV",
14 | "WSW": "VSV",
15 | "W": "V",
16 | "WNW": "VNV",
17 | "NW": "NV",
18 | "NNW": "NNV"
19 | },
20 |
21 | "cwcTerms": {
22 | "Feels Like" : "Føles som",
23 | "new_moon": "Nymåne",
24 | "new": "Nymåne",
25 | "waxing_crescent": "Tiltagende halvmåne",
26 | "first_quarter": "Første kvartal",
27 | "waxing_gibbous": "Tiltagende måne",
28 | "full": "Fuldmåne",
29 | "full_moon": "Fuldmåne",
30 | "waning_gibbous": "Aftagende måne",
31 | "third_quarter": "Tredje kvartal",
32 | "last_quarter": "Sidste kvartal",
33 | "waning_crescent": "Aftagende halvmåne"
34 | }
35 | }
--------------------------------------------------------------------------------
/dist/transl/no-NO.json:
--------------------------------------------------------------------------------
1 | {
2 | "cwcLocWindDirections": {
3 | "N": "N",
4 | "NNE": "NNØ",
5 | "NE": "NØ",
6 | "ENE": "ØNØ",
7 | "E": "Ø",
8 | "ESE": "ØSØ",
9 | "SE": "SØ",
10 | "SSE": "SSØ",
11 | "S": "S",
12 | "SSW": "SSV",
13 | "SW": "SV",
14 | "WSW": "VSV",
15 | "W": "V",
16 | "WNW": "VNV",
17 | "NW": "NV",
18 | "NNW": "NNV"
19 | },
20 |
21 | "cwcTerms": {
22 | "Feels Like" : "Føles som",
23 | "new_moon": "Nymåne",
24 | "new": "Nymåne",
25 | "waxing_crescent": "Tiltagende halvmåne",
26 | "first_quarter": "Første kvartal",
27 | "waxing_gibbous": "Tiltagende måne",
28 | "full": "Fullmåne",
29 | "full_moon": "Fullmåne",
30 | "waning_gibbous": "Avtagende måne",
31 | "third_quarter": "Tredje kvartal",
32 | "last_quarter": "Sidste kvartal",
33 | "waning_crescent": "Avtagende halvmåne"
34 | }
35 | }
--------------------------------------------------------------------------------
/dist/transl/pt.json:
--------------------------------------------------------------------------------
1 | {
2 | "cwcLocWindDirections": {
3 | "N": "N",
4 | "NNE": "NNE",
5 | "NE": "NE",
6 | "ENE": "ENE",
7 | "E": "E",
8 | "ESE": "ESE",
9 | "SE": "SE",
10 | "SSE": "SSE",
11 | "S": "S",
12 | "SSW": "SSW",
13 | "SW": "SW",
14 | "WSW": "WSW",
15 | "W": "W",
16 | "WNW": "WNW",
17 | "NW": "NW",
18 | "NNW": "NNW"
19 | },
20 |
21 | "cwcTerms": {
22 | "Feels Like" : "Sentida",
23 | "new_moon": "Lua Nova",
24 | "new": "Lua nova",
25 | "waxing_crescent": "Lua Crescente",
26 | "first_quarter": "Quarto Crescente",
27 | "waxing_gibbous": "Crescente Gibosa",
28 | "full": "Lua Cheia",
29 | "full_moon": "Lua Cheia",
30 | "waning_gibbous": "Minguante Gibosa",
31 | "third_quarter": "Quarto Minguante",
32 | "last_quarter": "Quarto Minguante",
33 | "waning_crescent": "Lua Minguante"
34 | }
35 | }
--------------------------------------------------------------------------------
/dist/transl/sr-latn.json:
--------------------------------------------------------------------------------
1 | {
2 | "cwcLocWindDirections": {
3 | "N": "S",
4 | "NNE": "SSI",
5 | "NE": "SI",
6 | "ENE": "ISI",
7 | "E": "I",
8 | "ESE": "IJI",
9 | "SE": "JI",
10 | "SSE": "JJI",
11 | "S": "J",
12 | "SSW": "JJZ",
13 | "SW": "JZ",
14 | "WSW": "ZSZ",
15 | "W": "Z",
16 | "WNW": "ZSZ",
17 | "NW": "SZ",
18 | "NNW": "SSZ"
19 | },
20 |
21 | "cwcTerms": {
22 | "Feels Like" : "Subjektivni osećaj",
23 | "new_moon": "Mlad mesec",
24 | "new": "Mlad mesec",
25 | "waxing_crescent": "Prva osmina",
26 | "first_quarter": "Prva četvrt",
27 | "waxing_gibbous": "Treća osmina",
28 | "full": "Pun mesec",
29 | "full_moon": "Pun mesec",
30 | "waning_gibbous": "Peta osmina",
31 | "third_quarter": "Treća četvrtina",
32 | "last_quarter": "Zadnja četvrtina",
33 | "waning_crescent": "Sedma osmina"
34 | }
35 | }
--------------------------------------------------------------------------------
/dist/transl/ru.json:
--------------------------------------------------------------------------------
1 | {
2 | "cwcLocWindDirections": {
3 | "N": "С",
4 | "NNE": "ССВ",
5 | "NE": "СВ",
6 | "ENE": "ВСВ",
7 | "E": "В",
8 | "ESE": "ВЮВ",
9 | "SE": "ЮВ",
10 | "SSE": "ЮЮВ",
11 | "S": "Ю",
12 | "SSW": "ЮЮЗ",
13 | "SW": "ЮЗ",
14 | "WSW": "ЗЮЗ",
15 | "W": "З",
16 | "WNW": "ЗСЗ",
17 | "NW": "СЗ",
18 | "NNW": "ССЗ"
19 | },
20 |
21 | "cwcTerms": {
22 | "Feels Like" : "Ощущается как",
23 | "new_moon": "Новолуние",
24 | "new": "Новолуние",
25 | "waxing_crescent": "Растущий серп",
26 | "first_quarter": "Первая четверть",
27 | "waxing_gibbous": "Растущая луна",
28 | "full": "Полнолуние",
29 | "full_moon": "Полнолуние",
30 | "waning_gibbous": "Убывающая луна",
31 | "third_quarter": "Третья четверть",
32 | "last_quarter": "Последняя четверть",
33 | "waning_crescent": "Убывающая луна"
34 | }
35 | }
--------------------------------------------------------------------------------
/dist/transl/it.json:
--------------------------------------------------------------------------------
1 | {
2 | "cwcLocWindDirections": {
3 | "N": "N",
4 | "NNE": "NNE",
5 | "NE": "NE",
6 | "ENE": "ENE",
7 | "E": "E",
8 | "ESE": "ESE",
9 | "SE": "SE",
10 | "SSE": "SSE",
11 | "S": "S",
12 | "SSW": "SSO",
13 | "SW": "SO",
14 | "WSW": "OSO",
15 | "W": "O",
16 | "WNW": "ONO",
17 | "NW": "NO",
18 | "NNW": "NNO"
19 | },
20 |
21 | "cwcTerms": {
22 | "Feels Like" : "Percepita",
23 | "new_moon": "Novilunio",
24 | "new": "Novilunio",
25 | "waxing_crescent": "Luna crescente",
26 | "first_quarter": "Primo Quarto",
27 | "waxing_gibbous": "Gibbosa crescente",
28 | "full": "Luna piena",
29 | "full_moon": "Luna piena",
30 | "waning_gibbous": "Gibbosa calante",
31 | "third_quarter": "Ultimo quarto",
32 | "last_quarter": "Ultimo quarto",
33 | "waning_crescent": "Luna calante"
34 | }
35 | }
--------------------------------------------------------------------------------
/dist/transl/nl.json:
--------------------------------------------------------------------------------
1 | {
2 | "cwcLocWindDirections": {
3 | "N": "N",
4 | "NNE": "NNO",
5 | "NE": "NO",
6 | "ENE": "ONO",
7 | "E": "O",
8 | "ESE": "OZO",
9 | "SE": "ZO",
10 | "SSE": "ZZO",
11 | "S": "Z",
12 | "SSW": "ZZW",
13 | "SW": "ZW",
14 | "WSW": "WZW",
15 | "W": "W",
16 | "WNW": "WNW",
17 | "NW": "NW",
18 | "NNW": "NNW"
19 | },
20 |
21 | "cwcTerms": {
22 | "Feels Like": "Voelt Als",
23 | "new_moon": "Nieuwe maan",
24 | "new": "Nieuwe maan",
25 | "waxing_crescent": "Wassende halve maan",
26 | "first_quarter": "Eerste kwartier",
27 | "waxing_gibbous": "Wassende maan",
28 | "full": "Volle maan",
29 | "full_moon": "Volle maan",
30 | "waning_gibbous": "Afnemende maan",
31 | "third_quarter": "Derde Kwartier",
32 | "last_quarter": "Laatste Kwartier",
33 | "waning_crescent": "Afnemende halve maan"
34 | }
35 | }
--------------------------------------------------------------------------------
/dist/transl/de.json:
--------------------------------------------------------------------------------
1 | {
2 | "cwcLocWindDirections": {
3 | "N": "N",
4 | "NNE": "NNO",
5 | "NE": "NO",
6 | "ENE": "ONO",
7 | "E": "O",
8 | "ESE": "OSO",
9 | "SE": "SO",
10 | "SSE": "SSO",
11 | "S": "S",
12 | "SSW": "SSW",
13 | "SW": "SW",
14 | "WSW": "WSW",
15 | "W": "W",
16 | "WNW": "WNW",
17 | "NW": "NW",
18 | "NNW": "NNW"
19 | },
20 |
21 | "cwcTerms": {
22 | "Feels Like" : "Gefühlt",
23 | "new_moon": "Neumond",
24 | "new": "Neumond",
25 | "waxing_crescent": "Zunehmende Sichel",
26 | "first_quarter": "Erstes Viertel",
27 | "waxing_gibbous": "Zunehmender Halbmond",
28 | "full": "Vollmond",
29 | "full_moon": "Vollmond",
30 | "waning_gibbous": "Abnehmender Halbmond",
31 | "third_quarter": "Drittes Viertel",
32 | "last_quarter": "Letztes Viertel",
33 | "waning_crescent": "Abnehmende Sichel"
34 | }
35 | }
--------------------------------------------------------------------------------
/dist/transl/fr.json:
--------------------------------------------------------------------------------
1 | {
2 | "cwcLocWindDirections": {
3 | "N": "N",
4 | "NNE": "NNE",
5 | "NE": "NE",
6 | "ENE": "ENE",
7 | "E": "E",
8 | "ESE": "ESE",
9 | "SE": "SE",
10 | "SSE": "SSE",
11 | "S": "S",
12 | "SSW": "SSO",
13 | "SW": "SO",
14 | "WSW": "OSO",
15 | "W": "O",
16 | "WNW": "ONO",
17 | "NW": "NO",
18 | "NNW": "NNO"
19 | },
20 |
21 | "cwcTerms": {
22 | "Feels Like" : "Ressentie",
23 | "new_moon": "Nouvelle lune",
24 | "new": "Nouvelle lune",
25 | "waxing_crescent": "Premier croissant",
26 | "first_quarter": "Premier quartier",
27 | "waxing_gibbous": "Gibbeuse croissante",
28 | "full": "Pleine lune",
29 | "full_moon": "Pleine lune",
30 | "waning_gibbous": "Gibbeuse décroissante",
31 | "third_quarter": "Dernier quartier",
32 | "last_quarter": "Dernier quartier",
33 | "waning_crescent": "Lune décroissante"
34 | }
35 | }
--------------------------------------------------------------------------------
/dist/icons/animated/clear-day.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/templates/t-meteoalarm.ts:
--------------------------------------------------------------------------------
1 | import { html } from 'lit';
2 |
3 | export interface iWeatherMeteoDPCAlarmDataInterface {
4 | event?: string,
5 | severity?: string,
6 | icon?: string,
7 | icon_color?: string,
8 | datetime?: string,
9 | }
10 |
11 | const renderMeteoDPCalarm = (
12 | meteoDPCalarmData: Record | null,
13 | ) => {
14 | if (!meteoDPCalarmData || Object.keys(meteoDPCalarmData).length === 0) return html``;
15 |
16 | return html`
17 |
18 | ${Object.entries(meteoDPCalarmData).map(([key, data]) => html`
19 |
20 |
21 |
${data.datetime}
22 |
${data.event}
23 |
24 | `)}
25 |
26 | `;
27 | };
28 |
29 | export default renderMeteoDPCalarm;
30 |
--------------------------------------------------------------------------------
/.github/workflows/codeql.yml:
--------------------------------------------------------------------------------
1 | name: "CodeQL"
2 |
3 | on:
4 | push:
5 | branches: [ "master" ]
6 | pull_request:
7 | branches: [ "master" ]
8 | schedule:
9 | - cron: "22 7 * * 0"
10 |
11 | jobs:
12 | analyze:
13 | name: Analyze
14 | runs-on: ubuntu-latest
15 | permissions:
16 | actions: read
17 | contents: read
18 | security-events: write
19 |
20 | strategy:
21 | fail-fast: false
22 | matrix:
23 | language: [ javascript ]
24 |
25 | steps:
26 | - name: Checkout
27 | uses: actions/checkout@v3
28 |
29 | - name: Initialize CodeQL
30 | uses: github/codeql-action/init@v2
31 | with:
32 | languages: ${{ matrix.language }}
33 | queries: +security-and-quality
34 |
35 | - name: Autobuild
36 | uses: github/codeql-action/autobuild@v2
37 |
38 | - name: Perform CodeQL Analysis
39 | uses: github/codeql-action/analyze@v2
40 | with:
41 | category: "/language:${{ matrix.language }}"
42 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 Renato Rossi, https://www.linkedin.com/in/renatorossi/
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/builder/b-pollen.ts:
--------------------------------------------------------------------------------
1 | import { HomeAssistant } from 'custom-card-helpers/dist';
2 | import { iPollen } from '../utils/config-schema';
3 | import { getEntityRawValue, string2Number } from '../utils/helper';
4 | import { iPollenData, renderPollen } from '../templates/t-pollen';
5 |
6 | const buildPollen = (hass: HomeAssistant, lang: string, pollen: iPollen) => {
7 | const allItems: iPollenData[] = [];
8 | if (Array.isArray(pollen.entities) && pollen.entities.length > 0) {
9 | pollen.entities.forEach((item) => {
10 | const rawvalue = getEntityRawValue(hass, item.entity);
11 | if (rawvalue && rawvalue !== 'unknown' && rawvalue !== 'unavailable') {
12 | let value: number = string2Number(getEntityRawValue(hass, item.entity));
13 |
14 | if (Number.isNaN(value) || value < pollen.min || value > pollen.max) {
15 | value = 0;
16 | }
17 |
18 | allItems.push({
19 | name: item.name,
20 | value,
21 | });
22 | }
23 | // console.log(`Nome: ${item.name}, Entità: ${item.entity}`);
24 | });
25 | }
26 |
27 | return renderPollen(allItems, pollen.min, pollen.max);
28 | };
29 |
30 | export default buildPollen;
31 |
--------------------------------------------------------------------------------
/src/utils/const.ts:
--------------------------------------------------------------------------------
1 | export const logo: string = '%c WEATHER-CONDITION-CARD %c 2.0.0';
2 |
3 | export const hacsImagePath: string = '/local/community/ha-card-weather-conditions/icons';
4 | export const manImagePath: string = '/local/ha-card-weather-conditions/icons';
5 |
6 | export const optConsoleParam1: string = 'color: white; background: green; font-weight: 700;';
7 | export const optConsoleParam2: string = 'color: green; background: white; font-weight: 700;';
8 | export const optConsoleParam3: string = 'color: black; background: white; font-weight: 700;';
9 |
10 | export const iconTemperature: string = 'mdi:thermometer';
11 | export const iconPrecipitation: string = 'mdi:weather-rainy';
12 |
13 | export const cwcLocale = {
14 | en: 0,
15 | it: 1,
16 | nl: 2,
17 | es: 3,
18 | de: 4,
19 | fr: 5,
20 | 'sr-latn': 6,
21 | pt: 7,
22 | da: 8,
23 | 'no-no': 9,
24 | cs: 10,
25 | ru: 11,
26 | };
27 |
28 | // 🌑 🌒 🌓 🌔 🌕 🌖 🌗 🌘 🌑
29 | export const cwcMoonPhaseIcons = {
30 | new_moon: '🌑',
31 | new: '🌑',
32 | waxing_crescent: '🌒',
33 | first_quarter: '🌓',
34 | waxing_gibbous: '🌔',
35 | full: '🌕',
36 | full_moon: '🌕',
37 | waning_gibbous: '🌖',
38 | third_quarter: '🌗',
39 | last_quarter: '🌗',
40 | waning_crescent: '🌘',
41 | };
42 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "root": true,
3 | "parser": "@typescript-eslint/parser",
4 | "parserOptions": {
5 | "ecmaVersion": 2022,
6 | "sourceType": "module"
7 | },
8 | "plugins": [
9 | "@typescript-eslint"
10 | ],
11 | "extends": [
12 | "eslint:recommended",
13 | "plugin:@typescript-eslint/recommended",
14 | "airbnb-base"
15 | ],
16 | "rules": {
17 | "operator-linebreak": "warn",
18 | "no-trailing-spaces": "warn",
19 | "one-var": "warn",
20 | "one-var-declaration-per-line": "warn",
21 | "dot-notation": "warn",
22 | "max-len": ["error", { "code": 150 }],
23 | "eol-last": ["error", "always"],
24 | "no-console": "off",
25 | "no-unused-vars": ["warn", { "args": "none", "ignoreRestSiblings": true }],
26 | "nonblock-statement-body-position": "warn",
27 | "@typescript-eslint/no-unused-vars": "warn",
28 | "max-classes-per-file": ["warn", 3],
29 | "import/extensions": ["warn", "ignorePackages", {
30 | "ts": "never",
31 | "js": "never"
32 | }]
33 | },
34 | "settings": {
35 | "import/resolver": {
36 | "node": {
37 | "extensions": [".js", ".ts", ".jsx", ".tsx"]
38 | }
39 | }
40 | },
41 | "env": {
42 | "browser": true,
43 | "es2022": true
44 | }
45 | }
46 |
--------------------------------------------------------------------------------
/dist/icons/static/clear-night.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dist/icons/static/cloudy.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dist/icons/animated/cloudy.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dist/icons/animated/partly-cloudy-day.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/css/css-base-card.ts:
--------------------------------------------------------------------------------
1 | import { css } from 'lit';
2 |
3 | const cardStyle = css`
4 | ha-card {
5 | cursor: pointer;
6 | position: relative;
7 | width: 100%;
8 | }
9 |
10 | .ha-card-weather-conditions {
11 | width: 100%;
12 | box-sizing: border-box;
13 | background-color: var(--card-background-color, #1c1c1c);
14 | color: var(--primary-text-color, #ffffff);
15 | border-radius: var(--ha-card-border-radius, 12px);
16 | box-shadow: var(--ha-card-box-shadow, 0 2px 6px rgba(0, 0, 0, 0.2));
17 | overflow: hidden;
18 | padding: 0;
19 | display: flex;
20 | flex-direction: column;
21 | }
22 |
23 | .nd-container {
24 | width: 100%;
25 | box-sizing: border-box;
26 | display: flex;
27 | flex-direction: column;
28 | padding: 16px 20px; /* ← padding orizzontale più ampio */
29 | gap: 12px;
30 | background-size: cover;
31 | background-position: center;
32 | transition: background-image 0.3s ease-in-out;
33 | }
34 |
35 | /* Esempio di stile dinamico aggiuntivo se habgImage è una classe */
36 | .nd-container.sunny {
37 | background-image: url('/local/images/sunny-bg.jpg');
38 | }
39 |
40 | .nd-container.rainy {
41 | background-image: url('/local/images/rainy-bg.jpg');
42 | }
43 |
44 | /* -------------- */
45 |
46 | `;
47 |
48 | export default cardStyle;
49 |
--------------------------------------------------------------------------------
/dist/icons/animated/weather_sunset.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
15 |
--------------------------------------------------------------------------------
/dist/icons/static/weather_sunset.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
15 |
--------------------------------------------------------------------------------
/dist/icons/static/partly-cloudy-day.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/rollup.new.config.mjs:
--------------------------------------------------------------------------------
1 | import resolve from '@rollup/plugin-node-resolve'; // ✅ nuovo package
2 | import typescript from '@rollup/plugin-typescript'; // ✅ moderno
3 | import babel from '@rollup/plugin-babel';
4 | import terser from '@rollup/plugin-terser'; // ✅ va destrutturato
5 | import execute from 'rollup-plugin-execute'; // ancora valido
6 | import commonjs from '@rollup/plugin-commonjs'; // 👈 nuovo import
7 |
8 | export default {
9 | input: 'src/ha-weather-ecard.ts',
10 | output: {
11 | //dir: './dist',
12 | file: 'dist/ha-card-weather-conditions.js', // 👈 nome file forzato
13 | format: 'esm',
14 | sourcemap: 'inline',
15 | banner: false,
16 | // comments: false
17 | },
18 | plugins: [
19 | resolve({
20 | browser: true, // 👈 molto importante per card frontend
21 | exportConditions: ['browser']
22 | }),
23 | commonjs(), // 👈 serve per convertire eventuali commonjs a es6
24 | typescript({
25 | tsconfig: './tsconfig.json'
26 | }),
27 | babel({
28 | babelHelpers: 'bundled',
29 | exclude: 'node_modules/**',
30 | extensions: ['.js', '.ts']
31 | }),
32 | terser(),
33 | execute([
34 | `echo "$(date '+%d/%m/%Y %H:%M:%S') rollup done." ; echo -e '\\007'`
35 | ])
36 | ]
37 | };
38 |
--------------------------------------------------------------------------------
/dist/icons/animated/clear-night.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/templates/t-pollen.ts:
--------------------------------------------------------------------------------
1 | import { html } from 'lit';
2 |
3 | export interface iPollenData {
4 | name: string;
5 | value: number;
6 | }
7 |
8 | const LEVEL_NAMES = ['basso', 'moderato', 'alto', 'molto-alto', 'estremo'];
9 |
10 | const getLevelIndex = (value: number, levelMin: number, levelMax: number): number => {
11 | const range = levelMax - levelMin + 1;
12 | const step = range / LEVEL_NAMES.length;
13 | const index = Math.floor((value - levelMin) / step);
14 | return Math.min(index, LEVEL_NAMES.length - 1);
15 | };
16 |
17 | export const renderPollen = (data: iPollenData[], levelMin: number, levelMax: number) => {
18 | const numLevels = levelMax - levelMin + 1;
19 | const levels = LEVEL_NAMES.slice(0, numLevels);
20 |
21 | if (data.length === 0) {
22 | return html``;
23 | }
24 |
25 | return html`
26 |
27 | ${data.map((item) => {
28 | const activeIndex = getLevelIndex(item.value, levelMin, levelMax);
29 | return html`
30 |
31 |
32 | ${levels.map((levelName, index) => html`
33 |
37 | `)}
38 |
39 |
${item.name}
40 |
41 | `;
42 | })}
43 |
44 | `;
45 | };
46 |
--------------------------------------------------------------------------------
/dist/icons/static/rainy-4.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/animated/partly-cloudy-night.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dist/icons/static/partly-cloudy-night.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/css/css-pollen.ts:
--------------------------------------------------------------------------------
1 | import { css } from 'lit';
2 |
3 | const pollenStyle = css`
4 | .pollen-grid-container {
5 | display: grid;
6 | grid-template-columns: repeat(auto-fit, minmax(48px, 1fr));
7 | gap: 8px 12px;
8 | width: 100%;
9 | justify-items: center;
10 | align-items: end;
11 | padding: 8px 4px;
12 | box-sizing: border-box;
13 | }
14 |
15 |
16 | .pollen-stack {
17 | display: flex;
18 | flex-direction: column;
19 | align-items: center;
20 | gap: 4px;
21 | min-width: 48px;
22 | }
23 |
24 |
25 | .levels {
26 | display: flex;
27 | flex-direction: column-reverse;
28 | gap: clamp(1px, 0.2vw, 2px);
29 | }
30 |
31 | .level {
32 | width: clamp(16px, 3.5vw, 24px);
33 | height: clamp(5px, 0.7vw, 8px); /* 👈 anche in altezza */
34 | border-radius: 3px;
35 | opacity: 0.3;
36 | transition: opacity 0.2s ease;
37 | }
38 |
39 | .level.active {
40 | opacity: 1;
41 | outline: 1px solid #333;
42 | }
43 |
44 | .molto-alto {
45 | background-color: #f44336;
46 | }
47 |
48 | .alto {
49 | background-color: #ff9800;
50 | }
51 |
52 | .moderato {
53 | background-color: #ffeb3b;
54 | }
55 |
56 | .basso {
57 | background-color: #4caf50;
58 | }
59 |
60 | .pollen-name {
61 | font-size: clamp(0.55em, 1.3vw, 0.85em); /* 👈 stringe di più */
62 | // font-weight: 500;
63 | text-align: center;
64 | // color: #333;
65 | white-space: nowrap;
66 | }
67 |
68 | .label {
69 | width: 100%;
70 | text-align: center;
71 | font-size: clamp(0.55em, 1.3vw, 0.85em);
72 | // font-weight: 500;
73 | margin-top: clamp(4px, 0.5vw, 8px);
74 | }
75 | `;
76 |
77 | export default pollenStyle;
78 |
--------------------------------------------------------------------------------
/dist/icons/static/night.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/css/css-weather-forecast.ts:
--------------------------------------------------------------------------------
1 | import { css } from 'lit';
2 |
3 | const weatherForecastStyle = css`
4 |
5 | .weather-forecast-grid-container {
6 | display: grid;
7 | grid-template-columns: repeat(auto-fit, minmax(78px, 1fr));
8 | column-gap: 2px; /* spazio orizzontale tra i giorni */
9 | row-gap: 6px; /* spazio verticale tra righe, se ci sono */
10 | align-items: stretch;
11 | font-family: 'Segoe UI', sans-serif;
12 | width: 100%;
13 | }
14 |
15 | .weather-forecast-grid-wrapper {
16 | display: flex;
17 | flex-direction: column;
18 | align-items: center; /* centrare il titolo orizzontalmente */
19 | }
20 |
21 | .weather-forecast-title {
22 | font-size: clamp(0.85em, 1vw, 0.95em);
23 | font-weight: bold;
24 | // margin-bottom: 0.5em;
25 | text-align: center;
26 | }
27 |
28 | .weather-forecast-slot {
29 | text-align: center;
30 | padding: 8px 4px;
31 | min-width: 0;
32 | overflow: hidden;
33 | }
34 |
35 | .weather-forecast-slot:last-child {
36 | border-right: none;
37 | }
38 |
39 | .weather-forecast-label-slot {
40 | font-size: 0.9em;
41 | font-weight: bold;
42 | margin-bottom: 6px; /* ridotto */
43 | }
44 |
45 | .weather-forecast-icon {
46 | font-size: 1.6rem; /* ridotto */
47 | /* margin: 6px 0; ridotto */
48 | height: 32px;
49 | }
50 |
51 | .weather-forecast-temperature {
52 | font-size: clamp(0.8em, 1vw, 0.9em); /* leggermente più piccolo */
53 | margin: 4px 0; /* meno margine */
54 | }
55 |
56 | .weather-forecast-temperature .high {
57 | font-weight: bold;
58 | }
59 |
60 | .weather-forecast-precipitation {
61 | font-size: clamp(0.65em, 1vw, 0.75em);
62 | line-height: 1.2; /* compatta verticalmente */
63 | }
64 |
65 | .weather-forecast-precipitation .mm {
66 | font-weight: bold;
67 | }
68 | `;
69 |
70 | export default weatherForecastStyle;
71 |
--------------------------------------------------------------------------------
/dist/icons/static/rainy-5.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/static/cloudy-original.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/static/haze.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dist/icons/static/rainy-6.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/static/rainy-7.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/static/thunder.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/animated/haze.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dist/icons/animated/fog.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dist/icons/static/fog.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/builder/b-summary.ts:
--------------------------------------------------------------------------------
1 | import { HomeAssistant } from 'custom-card-helpers/dist';
2 |
3 | import renderWeatherSummary from '../templates/t-summary';
4 | import {
5 | getEntityNumericValue,
6 | getEntityRawValue,
7 | getEntityUnit,
8 | translate,
9 | } from '../utils/helper';
10 |
11 | import { getMoonIcon, getWeatherIcon } from '../utils/helper-render';
12 | import { iPresentData } from '../utils/config-schema';
13 | import { iIconsConfig, iTerms } from '../base/lovelace-base';
14 |
15 | const buildWeatherSummary = (
16 | hass: HomeAssistant,
17 | language: string,
18 | terms: iTerms,
19 | iconsConfig: iIconsConfig,
20 | name: string,
21 | presentData: iPresentData,
22 | sunId: string,
23 | moonphase: string,
24 | ) => {
25 | const moonPhase = getEntityRawValue(hass, moonphase);
26 | const moonIcon: string = moonPhase ? getMoonIcon(moonPhase) : '';
27 | const sun = getEntityRawValue(hass, sunId);
28 | const currentConditions = getEntityRawValue(hass, presentData.condition)?.toLowerCase() || 'na';
29 | // eslint-disable-next-line max-len
30 | const temperature = presentData.temperature ? getEntityNumericValue({ entityId: presentData.temperature, hass, lang: language }) ?? undefined : undefined;
31 | // eslint-disable-next-line max-len
32 | const temperatureFeelsLike = presentData.temperature_feelslike ? getEntityNumericValue({ entityId: presentData.temperature_feelslike, hass, lang: language }) ?? undefined : undefined;
33 | const temperatureFeelsLikeIcon = hass.states[presentData.temperature_feelslike]?.attributes.icon ?? '';
34 |
35 | return renderWeatherSummary({
36 | title: name ?? undefined, // 'Verkhnenovokutlumbetyevo',
37 | moonText: (moonphase ? translate(moonPhase, terms.words) : undefined),
38 | moonIcon,
39 | conditionText: currentConditions,
40 | conditionIcon: getWeatherIcon(currentConditions, iconsConfig, sun),
41 | temperature,
42 | temperatureUnit: getEntityUnit(hass, presentData.temperature),
43 | feelsLikeTerm: translate('Feels Like', terms.words),
44 | temperatureFeelsLike,
45 | temperatureFeelsLikeIcon,
46 | });
47 | };
48 |
49 | export default buildWeatherSummary;
50 |
--------------------------------------------------------------------------------
/dist/icons/static/snowy-4.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ha-card-weather-conditions",
3 | "version": "2.0.0",
4 | "description": "Home Assistant lovelace card for display weather data.",
5 | "keywords": [
6 | "home-assistant",
7 | "homeassistant",
8 | "hass",
9 | "automation",
10 | "lovelace",
11 | "custom-cards",
12 | "weather"
13 | ],
14 | "homepage": "https://github.com/r-renato/ha-card-weather-conditions#readme",
15 | "module": "ha-card-weather-conditions.js",
16 | "repository": {
17 | "type": "git",
18 | "url": "git+ssh://git@github.com/r-renato/ha-card-weather-conditions.git"
19 | },
20 | "author": "Renato Rossi",
21 | "license": "MIT",
22 | "dependencies": {
23 | "@material/mwc-select": "^0.27.0",
24 | "@material/mwc-textfield": "^0.27.0",
25 | "color": "^4.2.3",
26 | "custom-card-helpers": "^1.0.8",
27 | "hammerjs": "^2.0.8",
28 | "home-assistant-js-websocket": "^9.4.0",
29 | "lit": "^3.2.1",
30 | "memoize-one": "^6.0.0",
31 | "object-hash": "^3.0.0",
32 | "sortablejs": "^1.15.6",
33 | "superstruct": "^2.0.2"
34 | },
35 | "devDependencies": {
36 | "@babel/core": "^7.24.0",
37 | "@rollup/plugin-babel": "^6.0.4",
38 | "@rollup/plugin-commonjs": "^28.0.3",
39 | "@rollup/plugin-json": "^6.1.0",
40 | "@rollup/plugin-node-resolve": "^15.2.3",
41 | "@rollup/plugin-terser": "^0.4.4",
42 | "@rollup/plugin-typescript": "^11.1.5",
43 | "@typescript-eslint/eslint-plugin": "^6.21.0",
44 | "@typescript-eslint/parser": "^6.21.0",
45 | "eslint": "^8.56.0",
46 | "eslint-config-airbnb-base": "^15.0.0",
47 | "eslint-plugin-import": "^2.29.1",
48 | "prettier": "^3.2.5",
49 | "rollup": "^4.12.0",
50 | "rollup-plugin-execute": "^1.1.1",
51 | "typescript": "5.3.3"
52 | },
53 | "bugs": {
54 | "url": "https://github.com/r-renato/ha-card-weather-conditions/issues"
55 | },
56 | "main": "index.js",
57 | "scripts": {
58 | "watch": "rollup -c --watch",
59 | "build": "npm run lint && npm run rollup -- --config rollup.config.mjs",
60 | "build:new": "npm run lint && npm run rollup -- --config rollup.new.config.mjs",
61 | "lint": "eslint src/*.ts",
62 | "rollup": "rollup --no-compact "
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/dist/icons/static/cloudy-night-1.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/static/cloudy-night-2.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/static/cloudy-night-3.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/static/fair-night.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/css/css-ultraviolet.ts:
--------------------------------------------------------------------------------
1 | import { css } from 'lit';
2 |
3 | const ultravioletStyle = css`
4 | .ultraviolet-grid-container {
5 | display: flex;
6 | flex-direction: column;
7 | gap: 4px;
8 | }
9 |
10 | .ultraviolet-row {
11 | display: flex;
12 | justify-content: space-between;
13 | gap: 16px;
14 | }
15 |
16 | .ultraviolet-left,
17 | .present-right {
18 | flex: 1;
19 | }
20 |
21 | .ultraviolet-left {
22 | display: flex;
23 | justify-content: flex-start;
24 | }
25 |
26 | .ultraviolet-right {
27 | display: flex;
28 | justify-content: flex-end;
29 | }
30 |
31 | .ultraviolet-value-block {
32 | display: flex;
33 | align-items: center;
34 | gap: 4px;
35 | }
36 |
37 | .ultraviolet-unit {
38 | font-size: 0.9em;
39 | opacity: 0.8;
40 | }
41 |
42 | ------------------------------------------------------------------
43 |
44 | // .ultraviolet-grid-container {
45 | // display: flex;
46 | // flex-direction: column;
47 | // gap: 12px;
48 | // }
49 |
50 | // .ultraviolet-row {
51 | // display: flex;
52 | // justify-content: space-between;
53 | // padding: 4px 0;
54 | // }
55 |
56 | // .ultraviolet-value-block {
57 | // display: flex;
58 | // align-items: center;
59 | // gap: 4px;
60 | // }
61 |
62 | // .ultraviolet-unit {
63 | // font-size: 0.9em;
64 | // opacity: 0.7;
65 | // }
66 |
67 | .ultraviolet-skin-type-grid {
68 | display: grid;
69 | grid-template-columns: repeat(auto-fit, minmax(48px, 1fr));
70 | gap: 8px;
71 | margin-top: 8px;
72 | }
73 |
74 | .ultraviolet-skin-type-cell {
75 | flex: 1;
76 | min-width: 48px;
77 | height: 48px;
78 | display: flex;
79 | flex-direction: column;
80 | justify-content: center;
81 | align-items: center;
82 | border-radius: 6px;
83 | font-family: 'Segoe UI', sans-serif;
84 | box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
85 | color: black;
86 | }
87 |
88 | .ultraviolet-skin-type-label {
89 | font-weight: bold;
90 | font-size: 0.95em;
91 | line-height: 1em;
92 | }
93 |
94 | .ultraviolet-exposure-time {
95 | font-size: 0.75em;
96 | margin-top: 2px;
97 | color: #222;
98 | opacity: 0.85;
99 | }
100 |
101 |
102 |
103 |
104 |
105 |
106 | `;
107 |
108 | export default ultravioletStyle;
109 |
--------------------------------------------------------------------------------
/src/iconmodels/im-buienradar.ts:
--------------------------------------------------------------------------------
1 | // clear=ok, partlycloudy=ok, cloudy=ok, partlycloudy-fog=ok, partlycloudy-light-rain=ok, partlycloudy-rain=ok,
2 | // light-rain=ok, rainy=ok, snowy-rainy=ok, partlycloudy-light-snow=ok, partlycloudy-snow=ok, light-snow=ok, snowy=ok,
3 | // partlycloudy-lightning=ok or lightning
4 |
5 | export const cwcBuienradarDayIcons: { [key: string]: string; } = {
6 | // freezing_rain_heavy: 'rainy-3',
7 | // freezing_rain: 'rainy-2',
8 | // freezing_rain_light: 'rainy-1',
9 | // freezing_drizzle: 'rain-and-sleet-mix',
10 | // ice_pellets_heavy: 'rain-and-snow-mix',
11 | // ice_pellets: 'rain-and-snow-mix',
12 | // ice_pellets_light: 'rain-and-snow-mix',
13 | snowy: 'snowy-3',
14 | 'light-snow': 'snowy-2',
15 | 'snowy-rainy': 'snowy-1',
16 | 'partlycloudy-light-snow': 'snowy-1',
17 | 'partlycloudy-snow': 'snowy-1',
18 | // flurries: 'wind',
19 | // tstorm: 'tropical-storm',
20 | // rain_heavy: 'rainy-3',
21 | 'partlycloudy-light-rain': 'rainy-1',
22 | 'light-rain': 'rainy-1',
23 | rainy: 'rainy-2',
24 | 'partlycloudy-rain': 'rainy-1',
25 | // fog_light: 'haze',
26 | 'partlycloudy-fog': 'fog',
27 | cloudy: 'cloudy-original',
28 | // mostly_cloudy: 'cloudy-day-3',
29 | partlycloudy: 'cloudy-day-2',
30 | 'partlycloudy-lightning': 'cloudy-day-1',
31 | lightning: 'cloudy-day-1',
32 | // mostly_clear: 'cloudy-day-1',
33 | clear: 'day',
34 | };
35 |
36 | export const cwcBuienradarNightIcons: { [key: string]: string; } = {
37 | ...cwcBuienradarDayIcons,
38 | // freezing_rain_heavy: 'rainy-6',
39 | // freezing_rain: 'rainy-5',
40 | // freezing_rain_light: 'rainy-4',
41 | // freezing_drizzle: 'rain-and-sleet-mix',
42 | // ice_pellets_heavy: 'rain-and-snow-mix',
43 | // ice_pellets: 'rain-and-snow-mix',
44 | // ice_pellets_light: 'rain-and-snow-mix',
45 | // snow_heavy: 'snowy-6',
46 | // snow: 'nowy-5',
47 | // snow_light: 'nowy-4',
48 | // flurries: 'wind',
49 | // tstorm: 'tropical-storm',
50 | // rain_heavy: 'rainy-6',
51 | // rain_light: 'rainy-4',
52 | // rain: 'rainy-5',
53 | // drizzle: 'rainy-4',
54 | // fog_light: 'haze',
55 | // fog: 'fog',
56 | // cloudy: 'cloudy',
57 | // mostly_cloudy: 'cloudy-night-3',
58 | // partly_cloudy: 'cloudy-night-2',
59 | // mostly_clear: 'cloudy-night-1',
60 | // clear: 'night'
61 | };
62 |
--------------------------------------------------------------------------------
/src/utils/colors.ts:
--------------------------------------------------------------------------------
1 | import { css } from 'lit';
2 | import * as Color from 'color';
3 |
4 | export const COLORS = [
5 | 'primary',
6 | 'accent',
7 | 'red',
8 | 'pink',
9 | 'purple',
10 | 'deep-purple',
11 | 'indigo',
12 | 'blue',
13 | 'light-blue',
14 | 'cyan',
15 | 'teal',
16 | 'green',
17 | 'light-green',
18 | 'lime',
19 | 'yellow',
20 | 'amber',
21 | 'orange',
22 | 'deep-orange',
23 | 'brown',
24 | 'light-grey',
25 | 'grey',
26 | 'dark-grey',
27 | 'blue-grey',
28 | 'black',
29 | 'white',
30 | 'disabled',
31 | ];
32 |
33 | export function computeRgbColor(color: string): string {
34 | if (color === 'primary' || color === 'accent') {
35 | return `var(--rgb-${color}-color)`;
36 | }
37 | if (COLORS.includes(color)) {
38 | return `var(--rgb-${color})`;
39 | // eslint-disable-next-line no-else-return
40 | } else if (color.startsWith('#')) {
41 | try {
42 | return Color.rgb(color).rgb().array().join(', ');
43 | } catch (err) {
44 | return '';
45 | }
46 | }
47 | return color;
48 | }
49 |
50 | function capitalizeFirstLetter(string) {
51 | return string.charAt(0).toUpperCase() + string.slice(1);
52 | }
53 |
54 | export function computeColorName(color: string): string {
55 | return color
56 | .split('-')
57 | .map((s) => capitalizeFirstLetter(s))
58 | .join(' ');
59 | }
60 |
61 | export const defaultColorCss = css`
62 | --default-red: 244, 67, 54;
63 | --default-pink: 233, 30, 99;
64 | --default-purple: 146, 107, 199;
65 | --default-deep-purple: 110, 65, 171;
66 | --default-indigo: 63, 81, 181;
67 | --default-blue: 33, 150, 243;
68 | --default-light-blue: 3, 169, 244;
69 | --default-cyan: 0, 188, 212;
70 | --default-teal: 0, 150, 136;
71 | --default-green: 76, 175, 80;
72 | --default-light-green: 139, 195, 74;
73 | --default-lime: 205, 220, 57;
74 | --default-yellow: 255, 235, 59;
75 | --default-amber: 255, 193, 7;
76 | --default-orange: 255, 152, 0;
77 | --default-deep-orange: 255, 111, 34;
78 | --default-brown: 121, 85, 72;
79 | --default-light-grey: 189, 189, 189;
80 | --default-grey: 158, 158, 158;
81 | --default-dark-grey: 96, 96, 96;
82 | --default-blue-grey: 96, 125, 139;
83 | --default-black: 0, 0, 0;
84 | --default-white: 255, 255, 255;
85 | --default-disabled: 189, 189, 189;
86 | `;
87 |
88 | export const defaultDarkColorCss = css`
89 | --default-disabled: 111, 111, 111;
90 | `;
91 |
--------------------------------------------------------------------------------
/src/utils/helper-render.ts:
--------------------------------------------------------------------------------
1 | import { css } from 'lit';
2 | // import { HomeAssistant } from 'custom-card-helpers/dist';
3 |
4 | import { cwcMoonPhaseIcons } from '../../backup/ha-cwc-consts';
5 |
6 | import cardStyle from '../css/css-base-card';
7 | import summaryStyles from '../css/css-summary';
8 | import presentStyle from '../css/css-present';
9 | import ultravioletStyle from '../css/css-ultraviolet';
10 | import pollenStyle from '../css/css-pollen';
11 | import cameraStyle from '../css/css-camera';
12 | import { iIconsConfig } from '../base/lovelace-base';
13 | import weatherForecastStyle from '../css/css-weather-forecast';
14 | import meteodcpalarmStyle from '../css/css-meteoalarm';
15 |
16 | export const getMoonIcon = (phase: string): string => cwcMoonPhaseIcons[phase.toLowerCase()];
17 |
18 | export const getWeatherIcon = (
19 | condition: string,
20 | iconsConfig: iIconsConfig,
21 | sunState: string,
22 | ): string => {
23 | const isNight = sunState === 'below_horizon';
24 | const iconMap = isNight ? iconsConfig.iconsNight : iconsConfig.iconsDay;
25 | const iconName = iconMap[condition];
26 |
27 | if (!iconsConfig.path) {
28 | console.info('Image path not found.');
29 | }
30 |
31 | if (!iconName) {
32 | console.info(
33 | `Icons issue. Model=${iconsConfig.icons_model}, Time=${isNight ? 'night' : 'day'}, Condition=${condition}`,
34 | );
35 | return '';
36 | }
37 |
38 | return `${iconsConfig.path}/${iconsConfig.iconType}/${iconName}.svg`;
39 | };
40 |
41 | // export const getSensorUnit = (hass: HomeAssistant, measure: string): string => {
42 | // const lengthUnit = hass.config.unit_system.length;
43 |
44 | // const unitOverrides: Record = {
45 | // air_pressure: lengthUnit === 'km' ? 'hPa' : 'inHg',
46 | // precipitation: lengthUnit === 'km' ? 'mm' : 'in',
47 | // length: lengthUnit,
48 | // };
49 |
50 | // if (measure in unitOverrides) {
51 | // return unitOverrides[measure];
52 | // }
53 |
54 | // const unit = (hass.config.unit_system as Record)[measure];
55 |
56 | // if (unit !== undefined) {
57 | // return unit;
58 | // }
59 |
60 | // console.warn(`Unit for '${measure}' not found in hass.config.unit_system.`);
61 | // return '';
62 | // };
63 |
64 | export const getCardStyles = () => css`
65 | ${cardStyle}
66 | ${summaryStyles}
67 | ${presentStyle}
68 | ${weatherForecastStyle}
69 | ${ultravioletStyle}
70 | ${pollenStyle}
71 | ${cameraStyle}
72 | ${meteodcpalarmStyle}
73 | `;
74 |
--------------------------------------------------------------------------------
/dist/icons/static/rain-and-sleet-mix.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/dist/icons/animated/rainy-4.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/static/rain-and-snow-mix.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/dist/icons/animated/rain.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dist/icons/static/rain.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dist/icons/static/day.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/static/snowy-5.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/animated/wind.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/builder/b-ultraviolet.ts:
--------------------------------------------------------------------------------
1 | import { HomeAssistant } from 'custom-card-helpers/dist';
2 |
3 | import { getEntityNumericValue, getEntityRawValue, pad } from '../utils/helper';
4 | import renderUltraviolet from '../templates/t-ultraviolet';
5 | import { iUltraviolet } from '../utils/config-schema';
6 |
7 | // const getRawValue = (hass: HomeAssistant, entityId?: string): string | undefined => entityId && hass.states[entityId]?.state;
8 | // const getValue = (hass: HomeAssistant, entityId?: string, lang: string = 'en', decimals = 0): string | undefined => {
9 | // const state = entityId && hass.states[entityId]?.state;
10 | // return state !== undefined ? formatNumber(state, lang, decimals) : undefined;
11 | // };
12 |
13 | const getTime = (state?: string | number): string => {
14 | const value = typeof state === 'string' && state.toLowerCase() === 'unknown'
15 | ? NaN
16 | : Number(state);
17 | // console.debug(state);
18 | if (!Number.isFinite(value) || value < 0) return '--';
19 |
20 | const hours = Math.floor(value / 60);
21 | const minutes = value % 60;
22 |
23 | return hours > 0
24 | ? `${hours}:${pad(minutes, 2)} h`
25 | : `${minutes} m`;
26 | };
27 |
28 | const summaryData = (hass: HomeAssistant, lang: string, uv: iUltraviolet) => ({
29 | protectionWindow: {
30 | value: (!getEntityRawValue(hass, uv.protection_window) || getEntityRawValue(hass, uv.protection_window) === 'unknown' ? 'off' :
31 | getEntityRawValue(hass, uv.protection_window)
32 | ),
33 | icon: 'mdi:sunglasses',
34 | },
35 | currentUVLevel: { value: getEntityRawValue(hass, uv.uv_level), icon: 'mdi:weather-sunny' },
36 | currentUVIndex: { value: getEntityNumericValue({ entityId: uv.uv_index, hass, lang }), unit: 'UV Idx', icon: 'mdi:weather-sunny' },
37 | maxUVIndex: { value: getEntityNumericValue({ entityId: uv.max_uv_index, hass, lang }), unit: 'UV Idx', icon: 'mdi:weather-sunny' },
38 | currentOzoneLevel: { value: getEntityNumericValue({ entityId: uv.ozone_level, hass, lang }), unit: 'DU', icon: 'mdi:vector-triangle' },
39 | });
40 |
41 | const skinData = (hass: HomeAssistant, lang: string, uv: iUltraviolet) => ({
42 | skinType1: { value: getTime(getEntityNumericValue({ entityId: uv.set_skin_type_1, hass, lang })) },
43 | skinType2: { value: getTime(getEntityNumericValue({ entityId: uv.set_skin_type_2, hass, lang })) },
44 | skinType3: { value: getTime(getEntityNumericValue({ entityId: uv.set_skin_type_3, hass, lang })) },
45 | skinType4: { value: getTime(getEntityNumericValue({ entityId: uv.set_skin_type_4, hass, lang })) },
46 | skinType5: { value: getTime(getEntityNumericValue({ entityId: uv.set_skin_type_5, hass, lang })) },
47 | skinType6: { value: getTime(getEntityNumericValue({ entityId: uv.set_skin_type_6, hass, lang })) },
48 | });
49 |
50 | const buildUltraviolet = (hass: HomeAssistant, lang: string, uv: iUltraviolet) =>
51 | // eslint-disable-next-line implicit-arrow-linebreak
52 | renderUltraviolet({ ...summaryData(hass, lang, uv) }, { ...skinData(hass, lang, uv) });
53 |
54 | export default buildUltraviolet;
55 |
--------------------------------------------------------------------------------
/dist/icons/static/severe-thunderstorm.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # HA (Lovelace) Card Weather Conditions
2 |
3 | The format is based on [Keep a Changelog](http://keepachangelog.com/)
4 | and this project adheres to [Semantic Versioning](http://semver.org/).
5 |
6 | ## [2.0.1] 2025-06-08
7 | ### Fixed
8 |
9 | ### Added
10 | - ru locale
11 |
12 | ### Changed
13 | - nl locale
14 |
15 | ## [2.0.0] 2025-06-08
16 | ### Changed
17 | - Readme and PNG image
18 | - Fully reengineered the card
19 | - Czech locale
20 |
21 | ### Changed
22 | - Update Spanish locale
23 |
24 | ## [1.9.12] 2021-01-29
25 | ### Fixed
26 | - Minor bug fixing
27 |
28 | ## [1.9.11] 2021-01-29
29 | ### Fixed
30 | - Minor bug fixing
31 |
32 | ## [1.9.10] 2021-01-24
33 | ### Changed
34 | Update ClimaCel icons map
35 |
36 | ## [1.9.9] 2021-01-11
37 | ### Added
38 | - Norwegian locale
39 |
40 | ## [1.9.8] 2021-01-07
41 | ### Added
42 | - Danish locale
43 |
44 | ## [1.9.7] 2020-12-06
45 | ### Fixed
46 | - Fixed the snow icon name for the night time (climacell, darksky, openweathermap)
47 |
48 | ## [1.9.6] 2020-08-17
49 | ### Fixed
50 | - German locale, fix for "Feels Like" word
51 |
52 | ## [1.9.6] 2020-08-08
53 | ### Added
54 | - Icon model for: buienradar, defaulthass
55 |
56 | ## [1.9.5] 2020-08-08
57 | ### Fixed
58 | - Documentation
59 |
60 | ## [1.9.5] 2020-07-21
61 | ### Added
62 | - Errors catch and display while loading translations files
63 |
64 | ## [1.9.4] 2020-07-19
65 | ### Fixed
66 | - Minor bug fixing
67 |
68 | ## [1.9.3] 2020-07-18
69 | ### Changed
70 | - Exposition time change from hours to minutes
71 |
72 | ## [1.9.2] 2020-07-10
73 | ### Fixed
74 | - Minor bug fixing
75 |
76 | ## [1.9.1] 2020-06-22
77 | ### Added
78 | - Added icon override mode for the pollen layer
79 |
80 | ## [1.9.0] 2020-06-21
81 | ### Fixed
82 | - Minor bug fixing
83 |
84 | ### Added
85 | - Add `sea` Weather Forecast session
86 |
87 | ## [1.8.1] 2020-06-15
88 | ### Fixed
89 | - Minor bug fixing
90 |
91 | ## [1.8.0] 2020-06-15
92 | ### Fixed
93 | - Minor bug fixing
94 |
95 | ### Changed
96 | - Internationalization model
97 |
98 | ### Added
99 | - Add `pt` language
100 | - Add Alert Layer
101 |
102 | ### Changed
103 | ## [1.7.1] 2020-05-24
104 | ### Fixed
105 | - Minor bug fixing
106 |
107 | ## [1.7.0] 2020-05-23
108 | ### Fixed
109 | - Minor bug fixing
110 |
111 | ### Added
112 | - Add `sr-latn` language
113 |
114 | ## [1.6.0] 2020-05-22
115 | ### Added
116 | - Add `fr` language
117 |
118 | ## [1.5.1] 2020-05-21
119 | ### Fixed
120 | - Minor bug fixing
121 |
122 | ## [1.5.0] 2020-05-14
123 | ### Fixed
124 | - Minor bug fixing
125 | ### Added
126 | - Add `uv` (ultraviolet) session
127 |
128 | ## [1.4.0] 2020-05-13
129 | ### Added
130 | - Add `es` language
131 |
132 | ## [1.3.1] 2020-05-13
133 | ### Fixed
134 | - Minor bug fixing
135 |
136 | ## [1.3.0] 2020-05-10
137 | ### Added
138 | - Add moon phase
139 |
140 | ## [1.2.0] 2020-05-08
141 | ### Added
142 | - Add NL (Dutch) language
143 |
144 | ## [1.1.0] 2020-05-07
145 | ### Added
146 | - Add feels_like sensor
147 |
148 | ## [1.0.1] 2020-05-07
149 | ### Fixed
150 | - Minor bug fixing
151 |
152 | ## [1.0.0] 2020-05-03
153 | - Initial stable version
--------------------------------------------------------------------------------
/dist/icons/animated/snow.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/dist/icons/static/cloudy-day-1.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/static/cloudy-day-3.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/static/cloudy-day-2.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/static/fair-day.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/src/iconmodels/im-climacell.ts:
--------------------------------------------------------------------------------
1 | export const cwcClimacellDayIcons: { [key: string]: string; } = {
2 | freezing_rain_heavy: 'rainy-3',
3 | 'heavy freezing rain': 'rainy-3',
4 | freezing_rain: 'rainy-2',
5 | 'freezing rain': 'rainy-2',
6 | freezing_rain_light: 'rainy-1',
7 | 'light freezing rain': 'rainy-1',
8 | freezing_drizzle: 'rain-and-sleet-mix',
9 | 'freezing drizzle': 'rain-and-sleet-mix',
10 | ice_pellets_heavy: 'rain-and-snow-mix',
11 | 'heavy ice pellets': 'rain-and-snow-mix',
12 | ice_pellets: 'rain-and-snow-mix',
13 | 'ice pellets': 'rain-and-snow-mix',
14 | ice_pellets_light: 'rain-and-snow-mix',
15 | 'light ice pellets': 'rain-and-snow-mix',
16 | snow_heavy: 'snowy-3',
17 | 'heavy snow': 'snowy-3',
18 | snow: 'snowy-2',
19 | snow_light: 'snowy-1',
20 | 'light snow': 'snowy-1',
21 | flurries: 'wind',
22 | tstorm: 'tropical-storm',
23 | rain_heavy: 'rainy-3',
24 | 'heavy rain': 'rainy-3',
25 | rain_light: 'rainy-1',
26 | 'light rain': 'rainy-1',
27 | rain: 'rainy-2',
28 | drizzle: 'rainy-1',
29 | fog_light: 'haze',
30 | 'light fog': 'haze',
31 | fog: 'fog',
32 | cloudy: 'cloudy-original',
33 | mostly_cloudy: 'cloudy-day-3',
34 | 'mostly cloudy': 'cloudy-day-3',
35 | partly_cloudy: 'cloudy-day-2',
36 | 'partly cloudy': 'cloudy-day-2',
37 | mostly_clear: 'cloudy-day-1',
38 | 'mostly clear': 'cloudy-day-1',
39 | clear: 'day',
40 | };
41 |
42 | export const cwcClimacellNightIcons: { [key: string]: string; } = {
43 | ...cwcClimacellDayIcons,
44 | freezing_rain_heavy: 'rainy-6',
45 | 'heavy freezing rain': 'rainy-6',
46 | freezing_rain: 'rainy-5',
47 | 'freezing rain': 'rainy-5',
48 | freezing_rain_light: 'rainy-4',
49 | 'light freezing rain': 'rainy-4',
50 | // freezing_drizzle: 'rain-and-sleet-mix',
51 | // ice_pellets_heavy: 'rain-and-snow-mix',
52 | // ice_pellets: 'rain-and-snow-mix',
53 | // ice_pellets_light: 'rain-and-snow-mix',
54 | snow_heavy: 'snowy-6',
55 | 'heavy snow': 'snowy-6',
56 | snow: 'snowy-5',
57 | snow_light: 'snowy-4',
58 | 'light snow': 'snowy-4',
59 | // flurries: 'wind',
60 | // tstorm: 'tropical-storm',
61 | rain_heavy: 'rainy-6',
62 | 'heavy rain': 'rainy-6',
63 | rain_light: 'rainy-4',
64 | 'light rain': 'rainy-4',
65 | rain: 'rainy-5',
66 | drizzle: 'rainy-4',
67 | // fog_light: 'haze',
68 | // fog: 'fog',
69 | // cloudy: 'cloudy',
70 | mostly_cloudy: 'cloudy-night-3',
71 | 'mostly cloudy': 'cloudy-night-3',
72 | partly_cloudy: 'cloudy-night-2',
73 | 'partly cloudy': 'cloudy-night-2',
74 | mostly_clear: 'cloudy-night-1',
75 | 'mostly clear': 'cloudy-night-1',
76 | clear: 'night',
77 | sunny: 'night',
78 | };
79 |
80 | export const cwcClimacellDayBg: { [key: string]: string; } = {
81 | freezing_rain_heavy: 'rainy-3',
82 | freezing_rain: 'rainy-2',
83 | freezing_rain_light: 'rainy-1',
84 | freezing_drizzle: 'rain-and-sleet-mix',
85 | ice_pellets_heavy: 'rain-and-snow-mix',
86 | ice_pellets: 'rain-and-snow-mix',
87 | ice_pellets_light: 'rain-and-snow-mix',
88 | snow_heavy: 'snowy-3',
89 | snow: 'snowy-2',
90 | snow_light: 'snowy-1',
91 | flurries: 'wind',
92 | tstorm: 'tropical-storm',
93 | rain_heavy: 'rainy-3',
94 | rain_light: 'rainy-1',
95 | rain: 'rainy-2',
96 | drizzle: 'rainy-1',
97 | fog_light: 'haze',
98 | fog: 'fog',
99 | cloudy: 'cloudy-original',
100 | mostly_cloudy: 'day-cloud-3.jpg',
101 | partly_cloudy: 'day-cloud-2.jpg',
102 | mostly_clear: 'day-cloud-1.jpg',
103 | clear: 'day-clear.jpg',
104 | };
105 |
--------------------------------------------------------------------------------
/src/iconmodels/im-pirateweather.ts:
--------------------------------------------------------------------------------
1 | // Pirate Weather Icons
2 | // clear-day, clear-night, rain, snow, sleet, wind, fog, cloudy, partly-cloudy-day and partly-cloudy-night
3 | // mostly-clear-day, mostly-clear-night, mostly-cloudy-day, mostly-cloudy-night, possible-rain-day, possible-rain-night
4 | // possible-snow-day, possible-snow-night, possible-sleet-day, possible-sleet-night, possible-precipitation-day
5 | // possible-precipitation-night, precipitation, drizzle, light-rain, heavy-rain, flurries, light-snow, heavy-snow
6 | // very-light-sleet, light-sleet, heavy-sleet, breezy, dangerous-wind
7 |
8 | export const cwcDaytimePirateWeatherIcons: { [key: string]: string; } = {
9 | freezing_rain_heavy: 'rainy-3',
10 | 'heavy freezing rain': 'rainy-3',
11 | freezing_rain: 'rainy-2',
12 | 'freezing rain': 'rainy-2',
13 | freezing_rain_light: 'rainy-1',
14 | 'light freezing rain': 'rainy-1',
15 | freezing_drizzle: 'rain-and-sleet-mix',
16 | sleet: 'rain-and-sleet-mix',
17 | 'freezing drizzle': 'rain-and-sleet-mix',
18 | ice_pellets_heavy: 'rain-and-snow-mix',
19 | 'heavy ice pellets': 'rain-and-snow-mix',
20 | ice_pellets: 'rain-and-snow-mix',
21 | 'ice pellets': 'rain-and-snow-mix',
22 | ice_pellets_light: 'rain-and-snow-mix',
23 | 'light ice pellets': 'rain-and-snow-mix',
24 | snow_heavy: 'snowy-3',
25 | 'heavy snow': 'snowy-3',
26 | snow: 'snowy-2',
27 | snow_light: 'snowy-1',
28 | 'light snow': 'snowy-1',
29 | flurries: 'wind',
30 | tstorm: 'tropical-storm',
31 | rain_heavy: 'rainy-3',
32 | 'heavy rain': 'rainy-3',
33 | rain_light: 'rainy-1',
34 | rainy: 'rainy-1',
35 | 'light rain': 'rainy-1',
36 | rain: 'rainy-2',
37 | drizzle: 'rainy-1',
38 | fog_light: 'haze',
39 | 'light fog': 'haze',
40 | fog: 'fog',
41 | cloudy: 'cloudy-original',
42 | mostly_cloudy: 'cloudy-day-3',
43 | 'mostly cloudy': 'cloudy-day-3',
44 | partly_cloudy: 'cloudy-day-2',
45 | partlycloudy: 'cloudy-day-2',
46 | 'partly-cloudy-day': 'cloudy-day-2',
47 | 'partly cloudy': 'cloudy-day-2',
48 | mostly_clear: 'cloudy-day-1',
49 | 'mostly clear': 'cloudy-day-1',
50 | clear: 'day',
51 | 'clear-day': 'day',
52 | wind: 'wind',
53 | windy: 'wind',
54 | sunny: 'day',
55 | 'clear-night': 'day',
56 | };
57 |
58 | export const cwcNightlyPirateWeaterIcons: { [key: string]: string; } = {
59 | ...cwcDaytimePirateWeatherIcons,
60 | freezing_rain_heavy: 'rainy-6',
61 | 'heavy freezing rain': 'rainy-6',
62 | freezing_rain: 'rainy-5',
63 | 'freezing rain': 'rainy-5',
64 | freezing_rain_light: 'rainy-4',
65 | 'light freezing rain': 'rainy-4',
66 | // freezing_drizzle: 'rain-and-sleet-mix',
67 | // ice_pellets_heavy: 'rain-and-snow-mix',
68 | // ice_pellets: 'rain-and-snow-mix',
69 | // ice_pellets_light: 'rain-and-snow-mix',
70 | snow_heavy: 'snowy-6',
71 | 'heavy snow': 'snowy-6',
72 | snow: 'snowy-5',
73 | snow_light: 'snowy-4',
74 | 'light snow': 'snowy-4',
75 | // flurries: 'wind',
76 | // tstorm: 'tropical-storm',
77 | rain_heavy: 'rainy-6',
78 | 'heavy rain': 'rainy-6',
79 | rain_light: 'rainy-4',
80 | 'light rain': 'rainy-4',
81 | rain: 'rainy-5',
82 | drizzle: 'rainy-4',
83 | // fog_light: 'haze',
84 | // fog: 'fog',
85 | // cloudy: 'cloudy',
86 | mostly_cloudy: 'cloudy-night-3',
87 | 'mostly cloudy': 'cloudy-night-3',
88 | partly_cloudy: 'cloudy-night-2',
89 | partlycloudy: 'cloudy-night-2',
90 | 'partly-cloudy-night': 'cloudy-night-2',
91 | 'partly cloudy': 'cloudy-night-2',
92 | mostly_clear: 'cloudy-night-1',
93 | 'mostly clear': 'cloudy-night-1',
94 | clear: 'night',
95 | 'clear-night': 'night',
96 | sunny: 'night',
97 | };
98 |
--------------------------------------------------------------------------------
/dist/icons/static/rainy-2.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/animated/rainy-5.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/static/snow-and-sleet-mix.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/dist/icons/static/isolated-thunderstorms.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/dist/icons/static/scattered-thunderstorms.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/dist/icons/static/snowy-6.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/static/tropical-storm.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/static/rainy-3.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/static/rainy-1.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/builder/b-airquality.ts:
--------------------------------------------------------------------------------
1 | /* eslint-disable camelcase */
2 | /* eslint-disable no-else-return */
3 | /* eslint-disable object-curly-newline */
4 | import { HomeAssistant } from 'custom-card-helpers/dist';
5 | import { iAirQuality } from '../utils/config-schema';
6 | import { getEntityNumericValue, getEntityRawValue, getEntityUnit } from '../utils/helper';
7 | import { renderWeatherPresent } from '../templates/t-present';
8 |
9 | /**
10 | * Restituisce un colore (in formato hex) in base al valore dell'indice EPA AQI.
11 | * @param {number} aqi - Valore AQI compreso tra 0 e 500
12 | * @returns {string} - Colore esadecimale associato alla fascia AQI
13 | */
14 | function getAQIColor(aqi: number): string {
15 | if (aqi <= 50) {
16 | return '#009966'; // Verde (Buona)
17 | } else if (aqi <= 100) {
18 | return '#ffde33'; // Giallo (Moderata)
19 | } else if (aqi <= 150) {
20 | return '#ff9933'; // Arancione (Sensibili)
21 | } else if (aqi <= 200) {
22 | return '#cc0033'; // Rosso (Non salutare)
23 | } else if (aqi <= 300) {
24 | return '#660099'; // Viola (Molto non salutare)
25 | } else {
26 | return '#7e0023'; // Marrone scuro (Pericolosa)
27 | }
28 | }
29 |
30 | const buildAirQuality = (
31 | hass: HomeAssistant,
32 | language: string,
33 | airquality: iAirQuality,
34 | ) => {
35 | const lang = language || hass.selectedLanguage || hass.language;
36 |
37 | const pm25 = getEntityNumericValue({ entityId: airquality.pm25, hass, lang: language, decimals: 0 });
38 | const pm10 = getEntityNumericValue({ entityId: airquality.pm10, hass, lang: language, decimals: 0 });
39 | const o3 = getEntityNumericValue({ entityId: airquality.o3, hass, lang: language, decimals: 1 });
40 | const no2 = getEntityNumericValue({ entityId: airquality.no2, hass, lang: language, decimals: 0 });
41 | const co = getEntityNumericValue({ entityId: airquality.co, hass, lang: language, decimals: 1 });
42 | const so2 = getEntityNumericValue({ entityId: airquality.so2, hass, lang: language, decimals: 0 });
43 | const epa_aqi = getEntityNumericValue({ entityId: airquality.epa_aqi, hass, lang: language, decimals: 0 });
44 | const epa_primary_pollutant = getEntityRawValue(hass, airquality.epa_primary_pollutant);
45 |
46 | const airQualityData = {
47 | pm25: {
48 | value: (pm25 ? `pm2.5 ${pm25}` : pm25),
49 | unit: getEntityUnit(hass, airquality.pm25) || 'µg/m³',
50 | icon: 'mdi:weather-hazy',
51 | },
52 | pm10: {
53 | value: (pm10 ? `pm10 ${pm10}` : pm10),
54 | unit: getEntityUnit(hass, airquality.pm10) || 'µg/m³',
55 | icon: 'mdi:weather-hazy',
56 | },
57 | o3: {
58 | value: (o3 ? `o3 ${o3}` : o3),
59 | unit: getEntityUnit(hass, airquality.o3) || 'µg/m³',
60 | icon: 'mdi:molecule',
61 | },
62 | no2: {
63 | value: (no2 ? `no2 ${no2}` : no2),
64 | unit: getEntityUnit(hass, airquality.no2) || 'µg/m³',
65 | icon: 'mdi:molecule',
66 | },
67 | co: {
68 | value: (co ? `co ${co}` : co),
69 | unit: getEntityUnit(hass, airquality.co) || 'µg/m³',
70 | icon: 'mdi:molecule',
71 | },
72 | so2: {
73 | value: (so2 ? `so2 ${so2}` : so2),
74 | unit: getEntityUnit(hass, airquality.so2) || 'µg/m³',
75 | icon: 'mdi:molecule',
76 | },
77 | epa_aqi: {
78 | value: (epa_aqi ? `Air Quality Index ${epa_aqi}` : epa_aqi),
79 | // unit: getEntityUnit(hass, airquality.epa_aqi) || 'µg/m³',
80 | icon: 'mdi:weather-hazy',
81 | icon_color: getAQIColor(Number(getEntityRawValue(hass, airquality.epa_aqi))),
82 | },
83 | epa_primary_pollutant: {
84 | value: (epa_primary_pollutant ? `Primary ${epa_primary_pollutant}` : epa_primary_pollutant),
85 | // unit: getEntityUnit(hass, airquality.epa_aqi) || 'µg/m³',
86 | icon: 'mdi:weather-hazy',
87 | },
88 | };
89 |
90 | return renderWeatherPresent(airQualityData, lang);
91 | };
92 |
93 | export default buildAirQuality;
94 |
--------------------------------------------------------------------------------
/dist/icons/animated/rainy-6.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/animated/rainy-7.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/animated/snowy-4.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/static/hurricane.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/dist/icons/static/snowy-2.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/src/utils/config-schema.ts:
--------------------------------------------------------------------------------
1 | export interface iLovelaceCardConfig {
2 | index?: number; // Indice della card all'interno della vista (opzionale).
3 | view_index?: number; // Indice della vista in cui si trova la card (opzionale).
4 | view_layout?: unknown; // Informazioni di layout (griglia, posizione, ecc.) per l'editor UI.
5 | type: string; // Obbligatorio. Indica il tipo di card
6 | [key: string]: unknown; // Permette di aggiungere parametri arbitrari, cioè supporta proprietà dinamiche definite dall’utente.
7 | }
8 |
9 | export interface iPresentData {
10 | // sun?: string;
11 | // moonphase?: string;
12 | condition?: string;
13 | temperature?: string;
14 | temperature_feelslike?: string;
15 |
16 | temperature_min?: string;
17 | temperature_max?: string;
18 |
19 | humidity?: string;
20 | pressure?: string;
21 | visibility?: string;
22 | wind_bearing?: string;
23 | wind_speed?: string;
24 | precipitation_intensity?: string;
25 | precipitation_probability?: string;
26 | }
27 |
28 | export interface iTimeSlots {
29 | slot1: string;
30 | slot2: string;
31 | slot3: string;
32 | slot4: string;
33 | slot5: string;
34 | slot6: string;
35 | }
36 |
37 | export interface iDailyForecast {
38 | condition?: iTimeSlots;
39 | temperature_high?: iTimeSlots;
40 | temperature_low?: iTimeSlots;
41 | precipitation_intensity?: iTimeSlots;
42 | precipitation_probability?: iTimeSlots;
43 |
44 | meteogram?: string ;
45 | }
46 |
47 | export interface iHourlyForecast {
48 | condition?: iTimeSlots;
49 | temperature?: iTimeSlots;
50 | temperature_feelslike?: iTimeSlots;
51 | precipitation_intensity?: iTimeSlots;
52 | precipitation_probability?: iTimeSlots;
53 | wind_bearing?: iTimeSlots;
54 | wind_speed?: iTimeSlots;
55 | }
56 |
57 | export interface iMarineHourlyForecast {
58 | swell_direction?: iTimeSlots ;
59 | swell_height?: iTimeSlots ;
60 | swell_period?: iTimeSlots ;
61 | wind_direction: iTimeSlots ;
62 | wind_speed: iTimeSlots ;
63 | air_temperature: iTimeSlots ;
64 | water_temperature: iTimeSlots ;
65 | }
66 |
67 | export interface iMarineDailyForecast {
68 | wave_height_max?: iTimeSlots ;
69 | wave_direction?: iTimeSlots ;
70 | swell_wave_height_max?: iTimeSlots ;
71 | wind_wave_height_max?: iTimeSlots ;
72 | }
73 |
74 | export interface iDPCAlert {
75 | thunderstorms?: string;
76 | hydraulic?: string;
77 | hydrogeological?: string;
78 | }
79 |
80 | export interface iWeather {
81 | name?: string; // location name, in summary
82 | sun?: string;
83 | moonphase?: string;
84 | icons_model: string;
85 | animation?: boolean;
86 | present?: iPresentData ;
87 | daily_forecasts?: iDailyForecast;
88 | hourly_forecasts?: iHourlyForecast;
89 | marine_daily_forecasts?: iMarineDailyForecast;
90 | marine_hourly_forecasts?: iMarineHourlyForecast;
91 | meteoalarm?: string; // Meteoalarm alert
92 | dpcalarm?: iDPCAlert; // DPC alert
93 | }
94 |
95 | export interface iUltraviolet {
96 | protection_window?: string ;
97 | ozone_level?: string ;
98 | uv_index?: string ;
99 | uv_level?: string ;
100 | max_uv_index?: string ;
101 | set_skin_type_1?: string ;
102 | set_skin_type_2?: string ;
103 | set_skin_type_3?: string ;
104 | set_skin_type_4?: string ;
105 | set_skin_type_5?: string ;
106 | set_skin_type_6?: string ;
107 | }
108 |
109 | export interface iPollenItem {
110 | name: string;
111 | entity: string;
112 | }
113 |
114 | export interface iPollen {
115 | entities: iPollenItem[];
116 | min: number;
117 | max: number;
118 | }
119 |
120 | export interface iAirQuality {
121 | pm25?: string ;
122 | pm10?: string ;
123 | o3?: string ;
124 | no2?: string ;
125 | co?: string ;
126 | so2?: string ;
127 | epa_aqi?: string ;
128 | epa_primary_pollutant?: string ;
129 | epa_health_concern?: string ;
130 | }
131 |
132 | export interface iCardConfig {
133 | type: string; // ha-card-weather-conditions
134 | language?: string ; // Card language
135 |
136 | weather: iWeather;
137 | ultraviolet?: iUltraviolet;
138 |
139 | pollen?: iPollen;
140 | airquality?: iAirQuality ;
141 |
142 | camera?: string;
143 |
144 | // display: string[]
145 |
146 | // alert: Alert ;
147 | // sea: Sea ;
148 | }
149 |
--------------------------------------------------------------------------------