Custom UI: Weather state card


#1

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!


Dutch precipitation forecast based on buienradar.nl
Openweathermap daily forecast
Help with Custom State Card
Custom animated weather card for Lovelace
Australian Weather Forecast using BOM Public FTP
#2

@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?


#3

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


#4

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?


#5

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


#6

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


#7

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


#8

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


#9

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.


#10

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


#11

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


#12

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


#13

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


#14

Perfect! Would love to have this too


#15

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

Do you have a small howto?


#16

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


#17

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


#18

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


#19

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


#20

Me too! Would love this!