Custom Dark Sky Animated Weather Card

Your card looks somewhat narrower than mine. The tooltips are sized based on the size of the day spans.

They are 110px wide as seen here: (you can always make yours narrower to match the day width but at some point whole words wont be on the same line. I settled on 110 as it was just at the edge of the card for the last day.

.fcasttooltip .fcasttooltiptext {
  visibility: hidden;
  width: 110px;

The position of the tooltip is 5px to the left of the day edge as seen here: It might be possible to calc a new starting left position based on where the edge of the card is. The little arrow would need to be adjusted as well.

  /* Position the tooltip */
  position: absolute;
  z-index: 1;
  bottom: 50%;
  left: 0%; 
  margin-left: -5px;

hereā€™s a wider view, card size depends on the browser window does it?

38

ill experiment a bit, and see what happens

This is great work. Iā€™ve been using the original card from the first post and been holding off updating and just watching what you guys have been doing. This is great!! Love the tooltips idea, but made a change myself. I didnā€™t like the fat yellow border so added border-width: 2px; to .fcasttooltip .fcasttooltiptext and changed in .fcasttooltip .fcasttooltiptext:after I changed border-width: to 8px from 6px to get the point on the bottom more visible.

Only thing now is to get the tooltip point to line up correctly as too me it looks off depending on where the tooltip is positoned. Iā€™m not sure if this is possible. Also, maybe is it possible to have the width a bit wider? Iā€™m wanting to use a more details summary and as it is it just goes sky high with the same width.

Keep up the good work guys!!!

im having issues with my cardā€¦ im getthing this

my lovelace:

resources:
  - url: /local/custom_ui/dark-sky-weather-card.js?v=4
    type: js
  - url: /local/custom_ui/card-modder.js

#                            Weather                            #


      - id: 3f7cfc0b210d4e408f5737d92108a358  # Automatically created id
        type: vertical-stack
        cards:
          - type: custom:card-modder
            card:
              entity_current_conditions: sensor.dark_sky_icon
              entity_daily_summary: sensor.bom_syd_forecast_detailed_summary_0
              entity_forecast_high_temp_1: sensor.bom_syd_forecast_max_temp_c_1
              entity_forecast_high_temp_2: sensor.bom_syd_forecast_max_temp_c_2
              entity_forecast_high_temp_3: sensor.bom_syd_forecast_max_temp_c_3
              entity_forecast_high_temp_4: sensor.bom_syd_forecast_max_temp_c_4
              entity_forecast_high_temp_5: sensor.bom_syd_forecast_max_temp_c_5
              entity_forecast_icon_1: sensor.dark_sky_icon_1
              entity_forecast_icon_2: sensor.dark_sky_icon_2
              entity_forecast_icon_3: sensor.dark_sky_icon_3
              entity_forecast_icon_4: sensor.dark_sky_icon_4
              entity_forecast_icon_5: sensor.dark_sky_icon_5
              entity_forecast_low_temp_1: sensor.bom_syd_forecast_min_temp_c_1
              entity_forecast_low_temp_2: sensor.bom_syd_forecast_min_temp_c_2
              entity_forecast_low_temp_3: sensor.bom_syd_forecast_min_temp_c_3
              entity_forecast_low_temp_4: sensor.bom_syd_forecast_min_temp_c_4
              entity_forecast_low_temp_5: sensor.bom_syd_forecast_min_temp_c_5
              entity_humidity: sensor.bom_humd
              entity_pressure: sensor.bom_pres
              entity_sun: sun.sun
              entity_temperature: sensor.bom_temp
              entity_visibility: sensor.dark_sky_visibility
              entity_wind_bearing: sensor.bom_wind_bear
              entity_wind_speed: sensor.bom_wind_sp
              type: 'custom:dark-sky-weather-card'
            style:                 
              background-image: url("/local/lovelace/cardbackK.png")
              background-repeat: no-repeat
              background-color: rgba(50,50,50,0.3)
              background-size: 100% 400px
              border-radius: 20px
              border: solid 1px rgba(100,100,100,0.3)
              color: "#999999"
              box-shadow: 3px 3px rgba(0,0,0,0.4)

Weather.yaml:

group:
  sun:
    name: Sun
    view: no
    entities:
      - sun.sun
      - sensor.moon
      
  weather overview:
    name: Weather Overview
    view: no
    entities:
      - sensor.pws_temp_c
      - sensor.pws_relative_humidity
      - sensor.pws_precip_1d
      - sensor.pws_wind_kph
      - sensor.pws_alerts
      
  daily forcast:
    name: Daily Forcast
    view: no
    entities:
      - sensor.pws_temp_high_1d_c
      - sensor.pws_temp_high_2d_c
      - sensor.pws_temp_high_3d_c
      - sensor.pws_temp_high_4d_c
      
#                            Sensors                            #

sensor:
  - platform: moon
  
## Weather Dark Sky
  - platform: darksky
    api_key: !secret darksky_api
    forecast:
      - 1
      - 2
      - 3
      - 4
      - 5
    monitored_conditions:
      - icon
      - summary
      - nearest_storm_distance
      - nearest_storm_bearing
      - humidity
      - temperature
      - temperature_high
      - temperature_low
      - apparent_temperature
      - apparent_temperature_high
      - apparent_temperature_low
      - wind_speed
      - wind_bearing
      - precip_type
      - precip_probability
      - precip_accumulation
      - precip_intensity
      - precip_intensity_max
      - uv_index
      - daily_summary
      - pressure
      - visibility
    update_interval:
      minutes: 5
      
## BOM Forecast
# IDN60901.94767
  - platform: bom_forecast
    product_id: IDN60901
    name: SYD Forecast
    forecast_days: 5
    rest_of_today: True
    friendly: False
    friendly_state_format: '{max}, {summary}'
    monitored_conditions:
      - 'max'
      - 'min'
      - 'chance_of_rain'
      - 'possible_rainfall'
      - 'summary'
      - 'detailed_summary'
     
  - platform: template
    sensors:
      bom_temp:
        friendly_name: "Sydney Temperature"
        value_template: "{{ states.weather.bom_sydney.attributes.temperature }}"
        device_class: temperature
        unit_of_measurement: Ā°C
        
      bom_humd:
        friendly_name: "Sydney Humidity"
        value_template: "{{ states.weather.bom_sydney.attributes.humidity }}"
        #device_class: humidity
        unit_of_measurement: '%'
        
      bom_wind_sp:
        friendly_name: "Sydney Wind Speed"
        value_template: "{{ states.weather.bom_sydney.attributes.wind_speed }}"
        #device_class: temperature
        unit_of_measurement: km
        
      bom_wind_bear:
        friendly_name: "Sydney Wind Bearing"
        value_template: "{{ states.weather.bom_sydney.attributes.wind_bearing }}"
        #device_class: temperature
        #unit_of_measurement: km
        
      bom_pres:
        friendly_name: "Sydney Pressure"
        value_template: "{{ states.weather.bom_sydney.attributes.pressure }}"
        #device_class: temperature
        unit_of_measurement: hPa      

#                     Weather                      #

sun:

weather:
  - platform: bom
    station: IDN60901.94767
    name: Sydney
    monitored_conditions:
      - apparent_t
      - cloud
      - cloud_base_m
      - cloud_oktas
      - cloud_type_id
      - cloud_type
      - delta_t
      - gust_kmh
      - gust_kt
      - air_temp
      - dewpt
      - press
      - press_qnh
      - press_msl
      - press_tend
      - rain_trace
      - rel_hum
      - sea_state
      - swell_dir_worded
      - swell_height
      - swell_period
      - vis_km
      - weather
      - wind_dir
      - wind_spd_kmh
      - wind_spd_kt

dark sky card:

class DarkSkyWeatherCard extends HTMLElement {
  set hass(hass) {
    if (!this.content) {
      const card = document.createElement('ha-card');
      const link = document.createElement('link');
      link.type = 'text/css';
      link.rel = 'stylesheet';
      link.href = '/local/custom_ui/dark-sky-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.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.unit_system[measure] || '';
      }
    };

    const transformDayNight = {
      "below_horizon": "night",
      "above_horizon": "day",
    }
    const sunLocation = transformDayNight[hass.states[this.config.entity_sun].state];
    const weatherIcons = {
      'clear-day': 'day',
      'clear-night': 'night',
      'rain': 'rainy-5',
      'snow': 'snowy-6',
      'sleet': 'rainy-6',
      'wind': 'cloudy',
      'fog': 'cloudy',
      'cloudy': 'cloudy',
      'partly-cloudy-day': 'cloudy-day-3',
      'partly-cloudy-night': 'cloudy-night-3',
      'hail': 'rainy-7',
      'lightning': 'thunder',
      'thunderstorm': 'thunder',
      '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'
    ];
    
    var forecastDate1 = new Date();
    forecastDate1.setDate(forecastDate1.getDate()+1);
    var forecastDate2 = new Date();
    forecastDate2.setDate(forecastDate2.getDate()+2);
    var forecastDate3 = new Date();
    forecastDate3.setDate(forecastDate3.getDate()+3);
    var forecastDate4 = new Date();
    forecastDate4.setDate(forecastDate4.getDate()+4);
    var forecastDate5 = new Date();
    forecastDate5.setDate(forecastDate5.getDate()+5);
    
    
    const currentConditions = hass.states[this.config.entity_current_conditions].state;
    const humidity = hass.states[this.config.entity_humidity].state;
    const pressure = Math.round(hass.states[this.config.entity_pressure].state);
    const temperature = Math.round(hass.states[this.config.entity_temperature].state);
    const visibility = hass.states[this.config.entity_visibility].state;
    const windBearing = windDirections[(Math.round((hass.states[this.config.entity_wind_bearing].state / 360) * 16))];
    const windSpeed = Math.round(hass.states[this.config.entity_wind_speed].state);
    const forecast1 = { date: forecastDate1,
    				   condition: this.config.entity_forecast_icon_1,
    				   temphigh: this.config.entity_forecast_high_temp_1,
    				   templow:  this.config.entity_forecast_low_temp_1, };
    const forecast2 = { date: forecastDate2,
    				   condition: this.config.entity_forecast_icon_2,
    				   temphigh: this.config.entity_forecast_high_temp_2,
    				   templow:  this.config.entity_forecast_low_temp_2, };
    const forecast3 = { date: forecastDate3,
    				   condition: this.config.entity_forecast_icon_3,
    				   temphigh: this.config.entity_forecast_high_temp_3,
    				   templow:  this.config.entity_forecast_low_temp_3, };
    const forecast4 = { date: forecastDate4,
    				   condition: this.config.entity_forecast_icon_4,
    				   temphigh: this.config.entity_forecast_high_temp_4,
    				   templow:  this.config.entity_forecast_low_temp_4, };
    const forecast5 = { date: forecastDate5,
    				   condition: this.config.entity_forecast_icon_5,
    				   temphigh: this.config.entity_forecast_high_temp_5,
    				   templow:  this.config.entity_forecast_low_temp_5, };

    const forecast = [forecast1,forecast2,forecast3,forecast4,forecast5];


    this.content.innerHTML = `
      <span class="icon bigger" style="background: none, url(/local/icons/weather_icons/animated/${weatherIcons[currentConditions]}.svg) no-repeat; background-size: contain;">${currentConditions}</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>
        </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>
        </ul>
      </span>
      <div class="forecast clear">
          ${forecast.map(daily => `
              <div class="day">
                  <span class="dayname">${(daily.date).toString().split(' ')[0]}</span>
                  <br><i class="icon" style="background: none, url(/local/icons/weather_icons/animated/${weatherIcons[hass.states[daily.condition].state]}.svg) no-repeat; background-size: contain;"></i>
                  <br><span class="highTemp">${Math.round(hass.states[daily.temphigh].state)}${getUnit('temperature')}</span>
                  <br><span class="lowTemp">${Math.round(hass.states[daily.templow].state)}${getUnit('temperature')}</span>
              </div>`).join('')}
      </div>
      <br><span class="unit">${hass.states[this.config.entity_daily_summary].state}</span></br>`;
  }

  setConfig(config) {
    if (!config.entity_current_conditions || 
    		!config.entity_humidity ||
    		!config.entity_pressure ||
     		!config.entity_temperature ||
    		!config.entity_visibility ||
    		!config.entity_wind_bearing ||
    		!config.entity_wind_speed) {
      throw new Error('Please define entities');
    }
    this.config = config;
  }

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

customElements.define('dark-sky-weather-card', DarkSkyWeatherCard);

Dark sky .css:

.clear {
    clear: both;
  }

  .card {
    margin: auto;
    padding-top: 2em;
    padding-bottom: 1em;
    padding-left: 1em;
    padding-right:1em;
    position: relative;
  }

  .ha-icon {
    height: 18px;
    margin-right: 5px;
    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 {
    display: inline-block;
    font-weight: 300;
    color: var(--primary-text-color);
    list-style: none;
    margin-left: -2em;
    margin-top: 4.5em;
  }

  .variations.right {
    position: absolute;
    right: 1em;
    margin-left: 0;
    margin-right: 1em;
  }

  .unit {
    font-size: .8em;
  }

  .forecast {
    width: 100%;
    margin: 0 auto;
    height: 10em;
  }

  .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(1) {
    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;
    margin-right: 5px;
    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%;
  }

agreed, did that myself too, even went down to 1px for the border :wink:

about position the tooltip, I find it a bit of a guess, since it all depends on the width of the current browser. Went for width=100px now, since that complies best with the browser window on my most frequently used laptop (Mac air 13").

even tried this:

  /* Position the tooltip */
  position: relative;
  z-index: 1;
  bottom: 50%;
  left: 0%; 
  margin-left: -5px;

but that had an unexpected outcome :wink:


although it stayed within the border of the columnā€¦

I use the homeassistant on synology and did not give it the appropriate attributes when creating the sensors.yaml file. After they are broadcast, the homeassistant can read the file and everything starts working. Thank you, great card!

In your weather.yaml file, under the darksky platform, you donā€™t have forecast for day - 0 defined. You only have forecast 1-5. You need 0-5. That might be the reason.

It was working as I copied it off from a working config but changed it from gold coast to sydney

Thanks for all the work on this card, great addition to HA.

I tweaked it a little to reduce the amount of noise produced by all the forecasted elements.
I created two darksky sensor entries, one with 720mins update for forecasts and one for 60 mins for current data points. I then updated lovelace entries accordingly.
To make this work you need to give each darksky sensor a a unique ā€˜nameā€™ i.e ā€œdark_sky_currentā€ & dark_sky_forecast". This prevents the data being overwritten.

Indeed making a lot of noise these custom-cardsā€¦My fan starts howling whenever I load the page.

Could you share the code you use now? both for the card, and the sensors?

Just make sure that all your sensor.bom_* sensors are working correctly. It looks like itā€™s unable to read the state of a sensor.

Actually, now that I look at your config in weather.yaml I see you are using bom_forecast. Change the product_id to one that is forecast ID. I see you have a SYD station in there. The forecast for SYD is IDN10064. See if that makes any difference.

In case you havenā€™t come across the bom_forecast post, here is the link to set it up. Has everything you need to know and explains how to get the correct product_id.

Sure:
sensors:

- platform: darksky
  api_key: !secret dark_sky_secret
  name: dark_sky_forecast
  monitored_conditions:
    - icon
    - temperature_low
    - temperature_high
  forecast:
    - 1
    - 2
    - 3
    - 4
    - 5
  units: auto
  update_interval:
    minutes: 720

- platform: darksky
  api_key: !secret dark_sky_secret
  name: dark_sky_current
  monitored_conditions:
    - icon
    - temperature
    - humidity
    - daily_summary
    - precip_probability
    - pressure
    - wind_speed
    - wind_bearing
    - visibility
  units: auto
  update_interval:
    minutes: 60

lovelace:

      - type: custom:dark-sky-weather-card
        entity_sun: sun.sun
        entity_daily_summary: sensor.dark_sky_current_daily_summary
        entity_current_conditions: sensor.dark_sky_current_icon
        entity_humidity: sensor.dark_sky_current_humidity
        entity_pressure: sensor.dark_sky_current_pressure
        entity_temperature: sensor.dark_sky_current_temperature
        entity_visibility: sensor.dark_sky_current_visibility
        entity_wind_bearing: sensor.dark_sky_current_wind_bearing
        entity_wind_speed: sensor.dark_sky_current_wind_speed
        entity_forecast_high_temp_1: sensor.dark_sky_forecast_daytime_high_temperature_1
        entity_forecast_high_temp_2: sensor.dark_sky_forecast_daytime_high_temperature_2
        entity_forecast_high_temp_3: sensor.dark_sky_forecast_daytime_high_temperature_3
        entity_forecast_high_temp_4: sensor.dark_sky_forecast_daytime_high_temperature_4
        entity_forecast_high_temp_5: sensor.dark_sky_forecast_daytime_high_temperature_5
        entity_forecast_low_temp_1: sensor.dark_sky_forecast_overnight_low_temperature_1
        entity_forecast_low_temp_2: sensor.dark_sky_forecast_overnight_low_temperature_2
        entity_forecast_low_temp_3: sensor.dark_sky_forecast_overnight_low_temperature_3
        entity_forecast_low_temp_4: sensor.dark_sky_forecast_overnight_low_temperature_4
        entity_forecast_low_temp_5: sensor.dark_sky_forecast_overnight_low_temperature_5
        entity_forecast_icon_1: sensor.dark_sky_forecast_icon_1
        entity_forecast_icon_2: sensor.dark_sky_forecast_icon_2
        entity_forecast_icon_3: sensor.dark_sky_forecast_icon_3
        entity_forecast_icon_4: sensor.dark_sky_forecast_icon_4
        entity_forecast_icon_5: sensor.dark_sky_forecast_icon_5

Nothing to do in the js file as its referencing the entity names from lovelace.
The only thing I couldnā€™t get to work is the overnight_low_temperature. According to the api itā€™s only available on the daily foreacasts, so I guess I need to call for a 6th day and offset the overnight lows by 1

1 Like

Ah yes, of course! elegant and simple. thanks for this.
will adapt quickly.

and because today a new Custom-ui version was released by customize magician @andrey, I thought it appropriate to share the following, based on the Dark Sky sensors:

homeassistant:
  customize_glob:
    sensor.dark_sky*icon*:
      templates:
        entity_picture: >
          return '/local/weather/icons/' + state + '.png'; 

14

and maybe this:

sensor.dark_sky_*temperature*:
  templates:
    icon_color: >
      if (state < -5) return 'rgb(30, 255, 255)';
      if (state < 0) return 'rgb(30, 144, 255)';
      if (state < 10) return 'rgb(255, 255, 0)';
      if (state < 15) return 'rgb(255, 211, 30)';
      if (state < 20) return 'rgb(0, 128, 0)';
      return 'rgb(255, 165, 0)';

Have fun!

sorry can you provide the link. there was no hyperlink

Oopsā€¦ I missed the link. :flushed:

Iā€™ve updated my post, but here is is as well. Australian Weather Forecast using BOM Public FTP

Itā€™s so beautiful to finally see it working!

Thank you so much! been trying to fix this for a while now!

could you help me with another thingā€¦ can i change the colour of the text to white ?
image

to something like thisā€¦
image

Glad you got it working!! Looks like you have the exact same style settings as I have. Must have got them from the same place. For me, Iā€™m running the theme Midnight, and then style the cards as needed. This gives me the white text. Not sure how else to change it. It might be your theme?? Iā€™m not exactly sure. Maybe someone else might be able to help. Sorry I canā€™t be of more help. :frowning:

where do you get the theme midnight from ?