Custom UI: Weather state card

get many of these:

ceback (most recent call last):
  File "/usr/lib/python3.6/asyncio/tasks.py", line 180, in _step
    result = coro.send(None)
  File "/usr/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 222, in async_update_ha_state
    attr = self.state_attributes or {}
  File "/usr/lib/python3.6/site-packages/homeassistant/components/weather/__init__.py", line 113, in state_attributes
    ATTR_WEATHER_HUMIDITY: round(self.humidity)TypeError: type NoneType doesn't define __round__ method

could this come from the custom_weather card??

No. This come from your weather component. Which one do you use?

How I remove yweather window? how to rename input boolean window and can remove plus symbol from temperature?

Yweather, buienradar and Open weather map.

It’s strange. These components do not use rounding for humidity

could it be the filter sensor:

- platform: filter
  name: "Filtered humidity living"
  entity_id: sensor.luchtvochtigheid_living
  filters:
    - filter: outlier
      window_size: 4
      radius: 4.0
    - filter: lowpass
      time_constant: 10
      precision: 2

also have the Mold sensor, but that never gave issues:

- platform: mold_indicator
  name: Schimmel sensor
  indoor_temp_sensor: sensor.temperatuur_living
  indoor_humidity_sensor: sensor.luchtvochtigheid_living
  outdoor_temp_sensor: sensor.br_temperature
  calibration_factor: 1.16

I did only notice the error since updating to 65.5but am not positively certain thats the reason. Theres another thread I’ve asked the question but it never followed through unfortunately.

Here the weather map without a plus symbol:

custom-weather-card.html
<dom-module id='custom-weather-card'>
  <template>
    <style>
      .clear {
        clear:both;
      }
      .card {
        margin:1em auto;
        padding-left: 1em;
        padding-right:1em;
        position: relative;
      }
      .iron-icon {
        height: 18px;
        color: var(--paper-item-icon-color);
      }
      .temp {
        font-weight: 300;
        font-size: 4em;
        color: var(--primary-text-color);
        position: absolute;
        right: 1em;
      }
      .tempc {
        font-weight: 300;
        font-size: 1.5em;
        vertical-align: super;
        color: var(--primary-text-color);
        position: absolute;
        right: 1em;
        margin-top: -14px;
        margin-right: 7px;
      }
      .variations {
        font-weight:300;
        color: var(--primary-text-color);
        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: 20%;
        float:left;
        text-align:center;
        color: var(--primary-text-color);
        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: var(--secondary-text-color);
      }
      .icon.bigger {
        width: 10em;
        height: 10em;
        margin-top: -4em;
        position: absolute;
        left: 0em;
      }
      .icon {
        width: 50px;
        height: 50px;
        display: inline-block;
        vertical-align: middle;
        background-size: contain;
        background-position: center center;
        background-repeat: no-repeat;
        text-indent: -9999px;
      }
       .weather {
        font-weight: 300;
        font-size: 1.5em;
        color: var(--primary-text-color);
        text-align:left;
        position: absolute;
        top: -0.5em;
        left: 6em;
        word-wrap: break-word;
        width: 30%;
      }

    </style>
    <div class="card">
      <span class="icon bigger" style="background: none, url(/local/weather_icons/animated/[[nowCond]].svg) no-repeat; background-size: contain;"></span>
      <span class="temp">[[roundedTemp]]</span><span class="tempc">&#176;C</span>
      <span class="weather">[[nowCondIT]]</span>
      <br>
      <span>
        <ul class="variations right">
          <template is="dom-if" if="[[weatherObj.attributes.humidity]]">
            <li><span class="iron-icon"><iron-icon icon="mdi:water-percent"></iron-icon></span> [[weatherObj.attributes.humidity]]<span class="unit"> %</span></li>
          </template>
          <template is="dom-if" if="[[weatherObj.attributes.pressure]]">
            <li><span class="iron-icon"><iron-icon icon="mdi:gauge"></iron-icon></span> [[weatherObj.attributes.pressure]]<span class="unit"> hPa</span></li>
          </template>
          <template is="dom-if" if="[[pressureObj.state]]"> <!-- if weather station doesn't have pressure info, get it from a separate sensor -->
            <li><span class="iron-icon"><iron-icon icon="mdi:gauge"></iron-icon></span> [[nowPressure]]<span class="unit"> hPa</span></li>
          </template>
          <template is="dom-if" if="[[precipationfcObj.state]]">
            <li><span class="iron-icon"><iron-icon icon="mdi:weather-rainy"></iron-icon></span> [[nowPrecipationfc]]<span class="unit" > mm/u (> uur)</span></li>
          </template>

        </ul>
        <ul class="variations">
          <template is="dom-if" if="[[weatherObj.attributes.wind_speed]]">
            <li><span class="iron-icon"><iron-icon icon="mdi:weather-windy"></iron-icon></span> [[windBearing]] [[weatherObj.attributes.wind_speed]]<span class="unit"> m/s</span></li>
          </template>
          <template is="dom-if" if="[[weatherObj.attributes.visibility]]">
            <li><span class="iron-icon"><iron-icon icon="mdi:weather-fog"></iron-icon></span> [[weatherObj.attributes.visibility]]<span class="unit"> m</span></li>
          </template>
          <template is="dom-if" if="[[visibilityObj.state]]"> <!-- if weather station doesn't have visibility info, get it from a separate sensor -->
            <li><span class="iron-icon"><iron-icon icon="mdi:weather-fog"></iron-icon></span> [[nowVisibility]]<span class="unit" > m</span></li>
          </template>
          <template is="dom-if" if="[[precipationObj.state]]">
            <li><span class="iron-icon"><iron-icon icon="mdi:weather-pouring"></iron-icon></span> [[nowPrecipation]]<span class="unit" > mm/u</span></li>
          </template>
        </ul>
      </span>

      <div class="forecast clear">
        <template is="dom-repeat" items="[[forecast]]">
        <div class="day"><span class="dayname">[[item.dayIT]]</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;C</span> 
          </template>
          <template is="dom-if" if="[[item.tempLow]]">
          <br> <span class="lowTemp">[[item.tempLow]]&#176;C</span>
          </template>
        </div>
      </template>
      </div>
    </div>
  </template>
</dom-module>

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

  var _WEATHER_TO_ICON_DAY = {
    'cloudy': 'cloudy',
    'fog': 'cloudy',
    'hail': 'rainy-7',
    'lightning': 'thunder',
    'lightning-rainy': 'thunder',
    'partlycloudy': 'cloudy-day-3',
    'pouring': 'rainy-6',
    'rainy': 'rainy-5',
    'snowy': 'snowy-6',
    'snowy-rainy': 'rainy-7',
    'sunny': 'day',
    'windy': 'cloudy',
    'windy-variant': 'cloudy-day-3',
    'exceptional': '!!',
  };
  
  var _WEATHER_TO_ICON_NIGHT = {
    'cloudy': 'cloudy',
    'fog': 'cloudy',
    'hail': 'rainy-7',
    'lightning': 'thunder',
    'lightning-rainy': 'thunder',
    'partlycloudy': 'cloudy-night-3',
    'pouring': 'rainy-6',
    'rainy': 'rainy-5',
    'snowy': 'snowy-6',
    'snowy-rainy': 'rainy-7',
    'sunny': 'night',
    'windy': 'cloudy',
    'windy-variant': 'cloudy-night-3',
    'exceptional': '!!',
  };
  
  var _WEATHER_TO_NAME = {
    cloudy: 'Cloudy',
    fog: 'Fog',
    hail: 'Hail',
    lightning: 'Lightning',
    'lightning-rainy': 'Lightning',
    partlycloudy: 'Partly cloudy',
    pouring: 'Pouring',
    rainy: 'Rainy',
    snowy: 'Snowy',
    'snowy-rainy': 'Rain and snow',
    sunny: 'Sunny',
    windy: 'Windy',
    'windy-variant': 'Windy',
    exceptional: '!',
  };


  var _DEGREE_TEXT = [
    'N', 'NNO', 'NO', 'ONO', 'O', 'OZO', 'ZO', 'ZZO',
    'Z', 'ZZW', 'ZW', 'WZW', 'W', 'WNW', 'NW', 'NNW', 'N'
  ];
  
  var _DAY_TO_DAY = {
    Mon: 'MON',
    Tue: 'TUE',
    Wed: 'WED',
    Thu: 'THU',
    Fri: 'FRI',
    Sat: 'SAT',
    Sun: 'SUN',
  };

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

    properties: {
      hass: {
        type: Object,
      },
      stateObj: {
        type: Object,
      },
      weatherObj: {
        type: Object,
        observer: 'checkRequirements',
        computed: 'computeWeatherObj(hass, stateObj)',
      },
      sunObj: {
        type: Object,
        observer: 'checkRequirements',
        computed: 'computeSunObj(hass, stateObj)',
      },
      pressureObj: {
        type: Object,
        observer: 'checkRequirements',
        computed: 'computePressureObj(hass, stateObj)',
      },
      visibilityObj: {
        type: Object,
        observer: 'checkRequirements',
        computed: 'computeVisibilityObj(hass, stateObj)',
      },
      precipationObj: {
        type: Object,
        observer: 'checkRequirements',
        computed: 'computePrecipationObj(hass, stateObj)',
      },
      precipationfcObj: {
        type: Object,
        observer: 'checkRequirements',
        computed: 'computePrecipationfcObj(hass, stateObj)',
      },
    },

    computeWeatherObj: function (hass, stateObj) {
      return stateObj && stateObj.attributes && stateObj.attributes.config && stateObj.attributes.config.weather ? hass.states[stateObj.attributes.config.weather] : null;
    },
    computeSunObj: function (hass, stateObj) {
      return stateObj && stateObj.attributes && stateObj.attributes.config && stateObj.attributes.config.sun ? hass.states[stateObj.attributes.config.sun] : null;
    },
    computePressureObj: function (hass, stateObj) {
      return stateObj && stateObj.attributes && stateObj.attributes.config && stateObj.attributes.config.pressure ? hass.states[stateObj.attributes.config.pressure] : null;
    },
    computeVisibilityObj: function (hass, stateObj) {
      return stateObj && stateObj.attributes && stateObj.attributes.config && stateObj.attributes.config.visibility ? hass.states[stateObj.attributes.config.visibility] : null;
    },
    computePrecipationObj: function (hass, stateObj) {
      return stateObj && stateObj.attributes && stateObj.attributes.config && stateObj.attributes.config.precipation ? hass.states[stateObj.attributes.config.precipation] : null;
    },
    computePrecipationfcObj: function (hass, stateObj) {
      return stateObj && stateObj.attributes && stateObj.attributes.config && stateObj.attributes.config.precipationfc ? hass.states[stateObj.attributes.config.precipationfc] : null;
    },

    getForecastArray: function () {
      if (!this.weatherObj.attributes.forecast) {
        return [];
      }
      
      var data = this.weatherObj.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;
          }
          if (tempHigh == 0) {
            tempHigh = '0'; // otherwise the value 0 will not be shown on the weather card
          }
          var tempLow = Math.round(data[i].templow * 10) / 10;
          if (tempLow == 0) {
            tempLow = '0'; // otherwise the value 0 will not be shown on the weather card
          }
          var condIcon = _WEATHER_TO_ICON_DAY[data[i].condition];
          var dayIT = _DAY_TO_DAY[day];
          forecast.push({dayIT:dayIT, 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.weatherObj) {
        return;
      }
      if (this.nowSun == 'above_horizon') {
	    this.nowCond = _WEATHER_TO_ICON_DAY[this.weatherObj.state];
      }
      if (this.nowSun == 'below_horizon') {
	    this.nowCond = _WEATHER_TO_ICON_NIGHT[this.weatherObj.state];
      }
      this.nowCondIT = _WEATHER_TO_NAME[this.weatherObj.state];
      if (this.pressureObj != null) {
        this.nowPressure = this.pressureObj.state;
      }
      if (this.sunObj != null) {
        this.nowSun = this.sunObj.state;
      }
      if (this.visibilityObj != null) {
        this.nowVisibility = this.visibilityObj.state;
      }
      if (this.precipationObj != null) {
        this.nowPrecipation = this.precipationObj.state;
      }
      if (this.precipationfcObj != null) {
        this.nowPrecipationfc = this.precipationfcObj.state;
      }
      if (this.weatherObj.attributes.temperature) {
        this.roundedTemp = Math.round(this.weatherObj.attributes.temperature);
        if (this.roundedTemp == 0) {
          this.roundedTemp = '0'; // otherwise the value 0 will not be shown on the weather card
        }
      }
      if (this.weatherObj.attributes.wind_bearing) {
        this.windBearing = this.windBearingToText(this.weatherObj.attributes.wind_bearing);
      }
      this.forecast = this.getForecastArray().slice(0, 5);
    },

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

You can create group with input boolean and add name to it. Or try to add name to input boolean:

input_boolean:
  weather:
  name: weather

I think the reason is not in the sensors. The error points to the humidity attribute of the weather component. Do you use Home Assistant version 0.67.1?

Thanks a lot only have last problem to remove yweather panel…

Just remove weather.yweather from the groups. How to use the groups you can read here

i dont have weather.yweather in group this is code:

group:
     weather:
        name: Weather
        entities:
            - input_boolean.weather

Add to default_view entities that you want to see on the home screen.

group:
  default_view:
    view: yes
    icon: mdi:home
    entities:
      - group.weather
      - ....
  weather:
    name: Weather
    entities:
      - input_boolean.weather

This is the basics of Home Assistant. You need to read the instructions for the components

Looks like we may get this in the next release https://github.com/home-assistant/home-assistant-polymer/pull/1117

no i use 65.5 and hassio keeps disconnecting after boot… cant upgrade through the HA interface now, and am searching for the reason it won’t load…

Hi @gerard33 would you be able to assist in getting this working with the Ecobee weather platform? I currently have it showing this much:

Here is the additional information re attributes etc. I attempted added the ecobee condition attributes to the custom html file but it wouldn’t load anything on the frontend. Just fyi I also have this working perfectly with the yweather component.

Attribute data sample:

{
“temperature”: 18,
“humidity”: 50,
“pressure”: 1023,
“wind_bearing”: 350,
“wind_speed”: 0,
“visibility”: -5002000,
“attribution”: “Ecobee weather provided by xxxx at 2018-05-08 02:34:10”,
“forecast”: [
{
“datetime”: “2018-05-08 12:26:07”,
“condition”: “Mild.”,
“temperature”: 19,
“templow”: 43.7,
“pressure”: 1023,
“windspeed”: -5002000,
“humidity”: 50
},
{
“datetime”: “2018-05-09 12:26:07”,
“condition”: “Sunny. Mild.”,
“temperature”: 19,
“templow”: 39.5,
“pressure”: 1013,
“windspeed”: 12630,
“humidity”: 40
},
{
“datetime”: “2018-05-10 12:26:07”,
“condition”: “Showers late. Afternoon clouds. Cool.”,
“temperature”: 12,
“templow”: 40.1,
“pressure”: 1007,
“windspeed”: 14730,
“humidity”: 72

There are some known issues with ecobee weather data at the moment that will hopefully be fixed soon, but that should affect this. Cheers

The new weather card (will be part of 0.69) is very similar to this one, except it does not use animated icons.

image

Here’s the PR that updated the weather card.

Is there a quick way to use animated icons with the new built-in weather card?

I really like the look of this and would like to use it in my HA instance. What code do I use there is a lot going around? Thanks.

1 Like

@proxima I would also like to use something other than Yahoo Weather since I find the current conditions are often not accurate. The issue with Ecobee is it doesn’t provide a simple weather condition. For example, on mine right now one reads “Overcast throughout the day” rather than “Overcast”. The weather icons need to be mapped to a file name. Let’s hit up the dev for the component and see if there’s another attribute that can be added.

Check out the forecast from Openweathermap. If you are satisfied with it, you can use the custom component I posted here

Hi @jer78 I have started adding in the Ecobee specific conditions into my version of the custom-weather-card.html file and the output is starting to look pretty good. Although I still have issues as there are some bugs in the Ecobee weather component where visibility, wind speed and bearing all have a value of ‘0’ of ‘-5002000’. The issue of F instead of C degrees seems fixed. There is also a newly designed weather card in .69 that is a huge improvement but still not as good as the custom card. Here is my ecobee card currently still wip.