Custom UI: Weather state card

EDIT: updated for Lovelace: https://github.com/bramkragten/custom-ui/tree/master/weather-card

I created a custom weather state card with animated icons:

But, I have some problems getting it to display… This is my config:

  customize_domain:
    weather:
      custom_ui_state_card: custom-weather

In my config folder I have:
The awesome icons from amcharts (if only they had a little more icons!) in:
\www\weather_icons\animated\

\www\custom_ui\state-card-custom-weather.html:

<dom-module id='custom-weather-card'>
  <template>
    <style>
.clear {
  clear:both;
}
.card {
  margin:1em auto;
  padding-left: 1em;
  padding-right:1em;
  position: relative;
}
.city {
  font-weight: 300;
  font-size: 1.8em;
  color:#5b5b5b;
}
iron-icon {
  height: 20px;
  color: #c8c8c8;
}
.temp {
  font-weight: 300;
  font-size: 5em;
  color:#5b5b5b;
  position: absolute;
  right: .3em;
}
.variations {
  font-wight:300;
  color:#8c8c8c;
  list-style:none;
  margin-left:-2em;
  margin-top: 3.5em;
}
.variations.right {
  float: right;
  margin-left: 0;
  margin-right: 1em;
}
.unit {
   font-size:.8em;
}
.forecast {
  width:100%;
  margin:0 auto;
  height:9em;
}
.day {
  display:block;
  width: 25%;
  float:left;
  text-align:center;
  color: #5b5b5b;
  border-right:.1em solid #d9d9d9;
  line-height: 2;
  box-sizing: border-box;
}
.dayname {
  text-transform: uppercase;
}

.forecast .day:first-child {
  margin-left: 0;
}

.forecast .day:nth-last-child(2) {
  border-right:none;
  margin-right: 0;
}
.highTemp {
  font-weight:bold;
}
.lowTemp {
  color: #8c8c8c;
}

.icon.bigger {
    width: 10em;
    height: 10em;
    margin-top: -4em;
	position: absolute;
}

.icon {
    width: 34px;
    height: 34px;
    display: inline-block;
    vertical-align: middle;
    background-size: contain;
    background-position: center center;
    background-repeat: no-repeat;
    text-indent: -9999px;
}

    </style>
    <ha-card header='[[computeTitle(stateObj)]]'>
<div class="card">
  <span class="city"></span>
    <br>
  <i class="icon bigger" style="background: none, url(/local/weather_icons/animated/[[nowCond]].svg) no-repeat; background-size: contain;"></i>
  <span class="temp">[[roundedTemp]]&#176;</span>
  <span>
    <ul class="variations right">
      <template is="dom-if" if="[[stateObj.attributes.humidity]]">
          <li><iron-icon icon="mdi:water-percent"></iron-icon>[[stateObj.attributes.humidity]]<span class="unit">%</span></li>
	  </template>
      <template is="dom-if" if="[[stateObj.attributes.pressure]]">
          <li><iron-icon icon="mdi:gauge"></iron-icon>[[stateObj.attributes.pressure]]<span class="unit">hPa</span></li>
	  </template>
      <template is="dom-if" if="[[stateObj.attributes.visibility]]">
          <li><iron-icon icon="mdi:weather-fog"></iron-icon>[[stateObj.attributes.visibility]]<span class="unit">m</span></li>
	  </template>
    </ul>
    <ul class="variations">
      <li>[[stateObj.state]]</li>
      <template is="dom-if" if="[[stateObj.attributes.wind_speed]]">
	      <li><iron-icon icon="mdi:weather-windy"></iron-icon>[[windBearing]] [[stateObj.attributes.wind_speed]]<span class="unit">m/s</span></li>
	  </template>
    </ul>
  </span>

  <div class="forecast clear">
    <template is="dom-repeat" items="[[forecast]]">
		<div class="day"><span class="dayname">[[item.day]]</span>
		  <template is="dom-if" if="[[item.condIcon]]">
			<br> <i class="icon" style="background: none, url(/local/weather_icons/animated/[[item.condIcon]].svg) no-repeat; background-size: contain;"></i> 
		  </template>
		  <template is="dom-if" if="[[item.tempHigh]]">
			<br> <span class="highTemp">[[item.tempHigh]]&#176;</span> 
		  </template>
		  <template is="dom-if" if="[[item.tempLow]]">
			<br> <span class="lowTemp">[[item.tempLow]]&#176;</span>
		  </template>
		</div>
	</template>
  </div>
</div>
    </ha-card>
  </template>
</dom-module>

<script>
(function () {
  'use strict';

  var _WEATHER_TO_ICON = {
    cloudy: 'cloudy',
    fog: 'cloudy',
    hail: 'rainy-7',
    lightning: 'lightning',
    'lightning-rainy': 'lightning',
    'Zwaar bewolkt': 'cloudy',
    partlycloudy: 'cloudy-day-2',
    pouring: 'rainy-7',
    rainy: 'rainy-5',
    snowy: 'snowy-5',
    'snowy-rainy': 'snowy-6',
    sunny: 'day',
    windy: 'cloudy',
    'windy-variant': '[]',
    exceptional: '!!',
  };

  var _DEGREE_TEXT = [
    'N', 'NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE',
    'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW', 'N'
  ];

  Polymer({
    is: 'custom-weather-card',

    properties: {
      hass: {
        type: Object,
      },

      stateObj: {
        type: Object,
        observer: 'checkRequirements'
      },
    },

    computeTitle: function (stateObj) {
      return stateObj.attributes.friendly_name;
    },

    getForecastArray: function () {
      if (!this.stateObj.attributes.forecast) {
        return [];
      }
	  
      var data = this.stateObj.attributes.forecast;
	  var forecast = [];
	  var prevDay = '';
	  
      for (var i = 0; i < data.length; i++) {
        var day = new Date(data[i].datetime).toString().split(' ')[0];
		if (day != prevDay) {
			if (data[i].max_temp) {
				var tempHigh = Math.round(data[i].max_temp * 10) / 10;
			} else {
				var tempHigh = Math.round(data[i].temperature * 10) / 10;
			}
			var tempLow = Math.round(data[i].min_temp * 10) / 10;
			var condIcon = _WEATHER_TO_ICON[data[i].condition];
			forecast.push({day:day, tempHigh:tempHigh, tempLow:tempLow, condIcon:condIcon});
			prevDay = day;
		} else {
			if (data[i].max_temp) {
				var tempHigh = Math.round(data[i].max_temp * 10) / 10;
			} else {
				var tempHigh = Math.round(data[i].temperature * 10) / 10;
			}
			var tempLow = Math.round(data[i].tempLow * 10) / 10;
			if (tempLow > forecast[forecast.length-1].tempHigh) {
				forecast[forecast.length-1].tempHigh = tempLow;
			}
			if (tempHigh > forecast[forecast.length-1].tempHigh) {
				forecast[forecast.length-1].tempHigh = tempHigh;
			}
			if (!forecast[forecast.length-1].tempLow) {
				forecast[forecast.length-1].tempLow = tempHigh;
			}
			if (tempHigh < forecast[forecast.length-1].tempLow) {
				forecast[forecast.length-1].tempLow = tempHigh;
			}
			if (tempLow < forecast[forecast.length-1].tempLow) {
				forecast[forecast.length-1].tempLow = tempLow;
			}
		}
      }

      return forecast;
    },

    checkRequirements: function () {
      if (!this.stateObj) {
        return;
      }

	  //console.log(this.stateObj.attributes);
	  
      this.nowCond = _WEATHER_TO_ICON[this.stateObj.state];
      if (this.stateObj.attributes.temperature) {
		this.roundedTemp = Math.round( this.stateObj.attributes.temperature * 10) / 10;
	  }
      if (this.stateObj.attributes.windBearing) {
		this.windBearing = this.windBearingToText(this.stateObj.attributes.windBearing);
	  }

	  this.forecast = this.getForecastArray().slice(0, 4);
    },

    windBearingToText: function (degree) {
      return _DEGREE_TEXT[((parseInt(degree) + 5.63) / 11.25) | 0];
    }
  });
}());
</script>

What am I missing? Thanks!

38 Likes

@Bram_Kragten, Wow, i like it very much! I was looking for something like this, thanks for sharing!
Are you knowing where i can get something like this;

Often before we going outside, we are looking on this.
I would like to integrade it in AH. Everthing is there on buienradar to embed. But nog thisone. Maybe you know this how to integrate it?

Weather is full-size card, not a state-card. Custom UI is currently not supported for those.

Aaah that’s a shame… is it in the backlog somewhere? Something that can be build, and if so is it a lot of work?

To allow it is just a few lines of code. No one just wanted it yet

Would you be willing to add it? Or point me in the direction where I can do the changes?

Add me to the list who would like to see this; I love @Bram_Kragten’s weather card!

Me to :slight_smile: This would be awesome to implement!

Yes, that is something that can be done, but the data needed is not currently supplied by the buienradar python library. So we would have to change that. I’ll look in to it and might do a PR on that library and the HA component.

1 Like

Really nice work @Bram_Kragten Would be happy to do it too in my local HA :slight_smile:

Would it be possible to support other weather sources, like Weather Underground for instance? I ask because I have a weather station on there.

Every weather platform should work, so yes also Weather Underground :slight_smile:

1 Like

This looks cool! Is this coming in a future release or is the custom state card available now for weather?

Perfect! Would love to have this too

Are you still working on this? I really would like the same, but need some help configuring!

Do you have a small howto?

Home Assistant is not ready to support this, unfortunately.
Will update when it does.

1 Like

What would be needed to enable this service? Is there a issue or something else to discuss this?

A little bit of time to finish this PR :slight_smile:

5 Likes

Count me in when this is available. Great work @Bram_Kragten

Me too! Would love this!