Custom animated weather card for Lovelace


#66

Great, thank you. It works :+1:


#67

Easier just to append a new number at the end of you resources file:

Example:

resources:
  - url: /local/monster-card.js?v=2
    type: js

Keep updating that number every time you change the file


#68

Small update for card:

  • Card Titile added
  • Sunset and sunraise icons with info added
  • Automatic switch to your locale for day of the week naming
weather-card.js
class WeatherCard extends HTMLElement {
  set hass(hass) {
    if (!this.content) {
      const card = document.createElement('ha-card');
      card.header = this.config.entity_title;
      const link = document.createElement('link');
      link.type = 'text/css';
      link.rel = 'stylesheet';
      link.href = '/local/custom_ui/weather-card.css';
      card.appendChild(link);
      this.content = document.createElement('div');
      this.content.className = 'card';
      card.appendChild(this.content);
      this.appendChild(card);
    }

    const getUnit = function (measure) {
      const lengthUnit = hass.config.core.unit_system.length;
      switch (measure) {
        case 'air_pressure':
          return lengthUnit === 'km' ? 'hPa' : 'inHg';
        case 'length':
          return lengthUnit;
        case 'precipitation':
          return lengthUnit === 'km' ? 'mm' : 'in';
        default:
          return hass.config.core.unit_system[measure] || '';
      }
    };

    const transformDayNight = {
      "below_horizon": "night",
      "above_horizon": "day",
    }
    const sunLocation = transformDayNight[hass.states[this.config.entity_sun].state];
    const weatherIcons = {
      'clear-night': `${sunLocation}`,
      'cloudy': 'cloudy',
      'fog': 'cloudy',
      'hail': 'rainy-7',
      'lightning': 'thunder',
      'lightning-rainy': 'thunder',
      'partlycloudy': `cloudy-${sunLocation}-3`,
      'pouring': 'rainy-6',
      'rainy': 'rainy-5',
      'snowy': 'snowy-6',
      'snowy-rainy': 'rainy-7',
      'sunny': `${sunLocation}`,
      'windy': 'cloudy',
      'windy-variant': `cloudy-${sunLocation}-3`,
      'exceptional': '!!',
    }

    const windDirections = [
    'N', 
    'NNE', 
    'NE', 
    'ENE', 
    'E', 
    'ESE',
    'SE', 
    'SSE',
    'S', 
    'SSW', 
    'SW', 
    'WSW', 
    'W', 
    'WNW', 
    'NW', 
    'NNW', 
    'N'
    ];
    const entity = hass.states[this.config.entity_weather];
    const currentCondition = entity.state;
    const humidity = entity.attributes.humidity;
    const pressure = entity.attributes.pressure;
    const temperature = Math.round(entity.attributes.temperature);
    const visibility = entity.attributes.visibility;
    const windBearing = windDirections[(parseInt((entity.attributes.wind_bearing + 11.25) / 22.5))];
    const windSpeed = entity.attributes.wind_speed;
    const forecast = entity.attributes.forecast.slice(0, 5);

    const sun = hass.states[this.config.entity_sun];
    const sunraise = sun.attributes.next_rising;
    const sunset = sun.attributes.next_setting;

    this.content.innerHTML = `
      <span class="icon bigger" style="background: none, url(/local/weather_icons/animated/${weatherIcons[currentCondition]}.svg) no-repeat; background-size: contain;">${currentCondition}</span>
      <span class="temp">${temperature}</span><span class="tempc"> ${getUnit('temperature')}</span>
      <span>
        <ul class="variations right">
            <li><span class="ha-icon"><ha-icon icon="mdi:water-percent"></ha-icon></span>${humidity}<span class="unit"> %</span></li>
            <li><span class="ha-icon"><ha-icon icon="mdi:gauge"></ha-icon></span>${pressure}<span class="unit"> ${getUnit('air_pressure')}</span></li>
            <li><span class="ha-icon"><ha-icon icon="mdi:weather-sunset-up"></ha-icon></span>${new Date(sunraise).toLocaleTimeString([], {hour: '2-digit', minute: '2-digit'})}</li>
        </ul>
        <ul class="variations">
            <li><span class="ha-icon"><ha-icon icon="mdi:weather-windy"></ha-icon></span>${windBearing} ${windSpeed}<span class="unit"> ${getUnit('length')}/h</span></li>
            <li><span class="ha-icon"><ha-icon icon="mdi:weather-fog"></ha-icon></span>${visibility}<span class="unit"> ${getUnit('length')}</span></li>
            <li><span class="ha-icon"><ha-icon icon="mdi:weather-sunset-down"></ha-icon></span>${new Date(sunset).toLocaleTimeString([], {hour: '2-digit', minute: '2-digit'})}</li>
        </ul>
      </span>
      <div class="forecast clear">
          ${forecast.map(daily => `
              <div class="day">
                  <span class="dayname">${(new Date(daily.datetime)).toLocaleDateString(hass.selectedLanguage || hass.language, { weekday: 'short' })}</span>
                  <br><i class="icon" style="background: none, url(/local/weather_icons/animated/${weatherIcons[daily.condition]}.svg) no-repeat; background-size: contain;"></i>
                  <br><span class="highTemp">${daily.temperature}${getUnit('temperature')}</span>
                  <br><span class="lowTemp">${daily.templow}${getUnit('temperature')}</span>
              </div>`).join('')}
      </div>`;
  }

  setConfig(config) {
    if (!config.entity_weather || !config.entity_sun) {
      throw new Error('Please define entities');
    }
    this.config = config;
  }

  // @TODO: This requires more intelligent logic
  getCardSize() {
    return 3;
  }
}

customElements.define('weather-card', WeatherCard);
configuration example
- type: "custom:weather-card"
        entity_weather: weather.yweather
        entity_sun: sun.sun
        entity_title: myTitle
Screenshot

image


#69

I think you changed the icon path in the new version. The folder /icons/ is no longer in the path. I changed it to /local/icons/weather_icons/animated and it works again for me :slight_smile:


#70

Yes. I forgot to mention it. It’s point to same location as for old UI version.


#71

Given that we have space between speed and precipitation, may be we can have 3 columns


#72

I modified weather-card and created a dark-sky-weather-card. It uses the Dark Sky Sensor platform not Dark Sky Weather. This is a bit off topic for this thread so if you are interested in it start a new thread and I would be happy to share how I did it.


#73

Great! I’m in. Darksky is more accurate for my location.


#74

Hi arsaboo. Screenshot was made from desktop. On mobile there is not much space.


#75

This card gives me the same error but only if I embed it in a horizontal or vertical stack. It works fine if I just put it into a view by itself. So the weird thing is that the red error flashes for maybe a half second even though the card ultimately loads.


#76

It is not designed to fit in a stack.


#77

i understand it might be designed to “fit”. but that means a big red error stack is expected? let me clarify as i left out a detail: i’m putting this card with an grafana iframe into a horizontal-stack. so yeah that doesn’t look good but notice no error stack ok?

1

so to fill the view i simply set “panel: true” in the view and it’ll look fantastic right? (next post)


#78

…but when i set panel to true guess what happens?

2

so apologies but it’s setting the panel to true which breaks things in my case.


#79

i’ll look further but basically it looks like when “panel: true” is set in the view the css from the card doesn’t get loaded, producing the error

4


#80

There is a bug with custom cards and panel.


#81

If changing the frontend to es5, card is not working anymore and I’m getting:

image


#82

just a suggestions: you might want to link to the raw files on github so people can just right click the files and save them.


#83

Hi @arsaboo can we fix this please …

Lovelace:

Regular Card:

Remove the overlapping “Clear Sky”


#84

I don’t think you are using the files from the original post.


#85

Finally got it working , had to change ownership of the files and a couple of restart

I am not using yweather because its not that accuarte instead using openweathermap but get this error:

the weird part is that with the old instructions non lovelace it shows everything fine , any ideas ?

Thanks