Google Weather Frog Card

Hi! This is my first new Topic here so I hope it’s okay for me to do this.

I want to share my version of the Google Weather Frog – which is entirely based on @arenacloser’s code and work. So all credit goes to him and his beautiful dashboard “Adaptive Mushroom”!
Go check it out!

When you are done it looks something like this:

Screenshot 2024-08-07 11.32.01

This “card” features a changing picture of “Froggy” the google weather frog. The change is based upon a random location for Froggy and your actual weather. So if it rains the picture will change to “Froggy in the rain” :wink:

I used @ArenaCloser’s dashboard as inspiration for my own and copied his implementation for the google weather frog. The hard work, the code, is essentially the same – I just wanted to use helpers (created inside HA UI) instead of template sensors (created inside HA configuration.yaml) and adopted a fully local approach (the pictures are stored on my HA Machine and not downloaed everytime the state of your weather changes).

I want to share this way to use the google weather frog because I feel that this part of arenaclosers dashboard is special but get’s a bit lost in the full code of his dashboard and because a few people have problems installing the google weather frog.

So here is my version which helped me understand what @arenacloser did:

Requirements:

Steps:

  1. First you need to create 3 template sensors in your configuration.yaml. These sensors are needed to get data about precipitation and the forecast for the day. It’s not a perfect solution for precipitation but it’s the only way I know how to get this data with my weather integration. Maybe somebody more experienced can find a better solution.
    Here’s the code for my precipitation sensor:
- trigger:
    - platform: time_pattern
      minutes: "30"
    - platform: homeassistant
      event: start
    - platform: event
      event_type: event_template_reloaded
  action:
    - service: weather.get_forecasts
      target:
        entity_id: weather.munchen #Change this to your weather entity
      data:
        type: hourly
      response_variable: forecast
  sensor:
    - name: "Wetter_München_Niederschlagsmenge" #Change this to a friendly name to your liking
      unique_id: wetter_munchen_niederschlagsmenge #Change this to a ID to your liking
      state: >
        {{
          forecast['weather.munchen'].forecast[0].precipitation
        }}
#Change this to your weather entity

And here is the code for my two forecast template sensors for the days weather state and temperature:

- trigger:
    - platform: time_pattern
      hours: "1"
    - platform: homeassistant
      event: start
    - platform: event
      event_type: event_template_reloaded
  action:
    - service: weather.get_forecasts
      target:
        entity_id: weather.munchen #Change this to your weather entity
      data:
        type: daily
      response_variable: forecast
  sensor:
    - name: "Wetter_München_Vorhersage_Status" #Change this to a friendly name to your liking
      unique_id: wetter_munchen_vorhersage_status #Change this to a ID to your liking
      state: >
        {{
          forecast['weather.munchen'].forecast[0].condition
        }}
#Change this to your weather entity
    - name: "Wetter_München_Vorhersage_Temperatur" #Change this to a friendly name to your liking
      unique_id: wetter_munchen_vorhersage_temperatur #Change this to a ID to your liking
      unit_of_measurement: °C
      state: >
        {{
          forecast['weather.munchen'].forecast[0].temperature 
        }}
#Change this to your weather entity
  1. Now it’s time to create the other sensors as helpers through the UI. First we need a dedicated sensor for the cloud coverage.
    1. Go to Settings → Devices & Services → Helper → Click on “Create Helper”
    2. Choose “Template” and then “Sensor”
    3. Choose “%” as unit of measurement
    4. Choose a name (mine is “wetter_munchen_bewolkung”) and copy the following code as
      Valuetemplante:
{{ state_attr('weather.munchen', 'cloud_coverage') }} #Change this to your weather entity

And that’s it – We have our helper for cloud coverage.

  1. Next create we need to create the very important state-sensor for the weather frog. This sensor uses data from the weather entity, our cloud coverage sensor (step 2) and our precipitation sensor (step 1). It decides which images will be shown.
    1. Again, create a Template Sensor Helper through the UI
    2. Choose a name to your liking (mine is “wetter_froggy_status”)
    3. Copy the following code as Valuetemplate:
{% set entity = states("weather.munchen") %} #Change this to your Weather Entity
{% set cloud = states("sensor.wetter_munchen_bewolkung") | int(0) %} #Change this to the entity-ID you chose in step 2
{% set rain = states("sensor.wetter_munchen_niederschlagsmenge") | float(0) %} #Change this to the unique-ID you created in step 1

{% if entity == "fog" %}
  fog
{% elif entity == "hail" %}
  hail
{% elif entity == "lightning" or entity == "lightning-rainy" or entity == "exceptional" %}
  lightning
{% elif entity == "snowy" or entity == "snowy-rainy" %}
  snowy
{% elif rain > 0.1 and rain <= 1.0 %}
  drizzle
{% elif rain > 1.0 %}
  rainy
{% elif states("sun.sun") == "below_horizon" %}
  {% if cloud < 20 %}
    clear
  {% elif cloud < 40 %}
    mostly-clear
  {% elif cloud < 60 %}
    partly-cloudy-night
  {% elif cloud < 80 %}
    mostly-cloudy-night
  {% else %}
    cloudy-night
  {% endif %} 
{% else %}
{% if cloud < 20 %}
  sunny
  {% elif cloud < 40 %}
    mostly-sunny
  {% elif cloud < 60 %}
    partly-cloudy-day
  {% elif cloud < 80 %}
    mostly-cloudy-day
  {% else %}
    cloudy
  {% endif %}
{% endif %}

And you are done. The preview should hopefully show a state which is similar to your actual weather.

  1. Now we need to create a helper for the location of the weather frog.

    1. Again choose “Create Helper” but choose “Dropdown” (or input_select)
    2. Give it a name to your liking (mine is “wetter_froggy_ort”) and choose a symbol
    3. Add the following options: beach, city, creek, field, hills, home, orchard
      And you are done! The sequence for the options is not important since we are later creating an automation which chooses a random location for this input_select helper.
  2. We need to create the final helper which uses the information from the helpers we created in steps 3 and 4 (status and location)

    1. Choose “Create Helper” and again create a template sensor (like in steps 2 and 3)
    2. Give it a name to your linking (mine is “wetter_froggy_bild”)
    3. Enter the following code as Valuetemplate:
{% set weather_status = states("sensor.wetter_froggy_status") %} #Change the name of the sensor to the one you chose in step 3
{% set other_location = '04-mostly-cloudy-day-home-flowers.png' %}
{% set frog_location = states("input_select.wetter_froggy_ort") %} #Change the name of the input_selcect to the one you chose in step 4
{% set dict = {
'sunny': {'beach':['01-sunny-beach-reading.png','01-sunny-beach-sandcastle.png','01-sunny-beach-sunscreen.png']|random(), 'city':['01-sunny-citypark-sunbathing.png','01-sunny-rooftop-pinacolada.png']|random(), 'creek':'01-sunny-creek-swimming.png', 'field':'01-sunny-field-kite.png', 'hills':'01-sunny-hills-sunbathing.png', 'home':'01-sunny-home-laundry.png', 'orchard':'01-sunny-orchard-picking.png'}, 
'mostly-sunny': {'beach':['02-mostly-sunny-beach-reading.png','02-mostly-sunny-beach-sandcastle.png','02-mostly-sunny-beach-sunscreen.png']|random(), 'city':['02-mostly-sunny-citypark-picnic.png','02-mostly-sunny-rooftop-pinacolada.png']|random(), 'creek':'02-mostly-sunny-creek-swimming.png', 'field':'02-mostly-sunny-field-kite.png', 'hills':'02-mostly-sunny-hills-sunbathing.png', 'home':'02-mostly-sunny-home-laundry.png', 'orchard':'02-mostly-sunny-orchard-picking.png'}, 
'partly-cloudy-day': {'beach':'03-partly-cloudy-day-beach-shells.png', 'city':'03-partly-cloudy-day-citypark-ukelele.png', 'creek':'03-partly-cloudy-day-creek-feet.png', 'field':['03-partly-cloudy-day-field-biking.png','03-partly-cloudy-day-field-hiking.png']|random(), 'hills':['03-partly-cloudy-day-hills-painting.png','03-partly-cloudy-day-hills-reading.png']|random(), 'home':'03-partly-cloudy-day-home-flowers.png', 'orchard':['03-partly-cloudy-day-orchard-butterflies.png','03-partly-cloudy-day-orchard-treeswing.png']|random()},
'mostly-cloudy-day': {'beach':'04-mostly-cloudy-day-beach-shells.png', 'city':'04-mostly-cloudy-day-citypark-ukelele.png', 'creek':'04-mostly-cloudy-day-creek-feet.png', 'field':['04-mostly-cloudy-day-field-biking.png','04-mostly-cloudy-day-field-hiking.png']|random(), 'hills':['04-mostly-cloudy-day-hills-painting.png','04-mostly-cloudy-day-hills-reading.png']|random(), 'home':'04-mostly-cloudy-day-home-flowers.png', 'orchard':['04-mostly-cloudy-day-orchard-butterflies.png','04-mostly-cloudy-day-orchard-treeswing.png']|random()},
'clear': {'city':'05-clear-home-lounging.png', 'creek':'05-clear-creek-stars.png', 'field':'05-clear-field-lanterns.png', 'hills':['05-clear-hills-camping.png','05-clear-hills-telescope.png']|random(), 'home':'05-clear-home-lounging.png', 'orchard':'05-clear-orchard-fireflies.png'},
'mostly-clear': {'city':'06-mostly-clear-home-lounging.png', 'creek':'06-mostly-clear-creek-stars.png', 'field':'06-mostly-clear-field-lanterns.png', 'hills':['06-mostly-clear-hills-camping.png','06-mostly-clear-hills-telescope.png']|random(), 'home':'06-mostly-clear-home-lounging.png', 'orchard':'06-mostly-clear-orchard-fireflies.png'},
'partly-cloudy-night': {'city':'07-partly-cloudy-night-home-inside.png', 'creek':'07-partly-cloudy-night-creek-fireflies.png', 'field':'07-partly-cloudy-night-field-fireflies.png', 'hills':'07-partly-cloudy-night-hills-smores.png', 'home':'07-partly-cloudy-night-home-inside.png', 'orchard':'07-partly-cloudy-night-orchard-eating.png'},
'mostly-cloudy-night': {'city':'08-mostly-cloudy-night-home-inside.png', 'creek':'08-mostly-cloudy-night-creek-fireflies.png', 'field':'08-mostly-cloudy-night-field-fireflies.png', 'hills':'08-mostly-cloudy-night-hills-smores.png', 'home':'08-mostly-cloudy-night-home-inside.png', 'orchard':'08-mostly-cloudy-night-orchard-eating.png'},
'cloudy-night': {'city':'08-mostly-cloudy-night-home-inside.png', 'creek':'08-mostly-cloudy-night-creek-fireflies.png', 'field':'08-mostly-cloudy-night-field-fireflies.png', 'hills':'08-mostly-cloudy-night-hills-smores.png', 'home':'08-mostly-cloudy-night-home-inside.png', 'orchard':'08-mostly-cloudy-night-orchard-eating.png'},
'cloudy': {'city':'04-mostly-cloudy-day-citypark-ukelele.png', 'creek':'04-mostly-cloudy-day-creek-feet.png', 'field':['04-mostly-cloudy-day-field-biking.png','04-mostly-cloudy-day-field-hiking.png']|random(), 'hills':'09-cloudy-hills-coffee.png', 'home':'09-cloudy-home-flowers.png', 'orchard':'09-cloudy-orchard-watching.png'},
'drizzle': {'city':'10-drizzle-home-laundry.png', 'creek':'10-drizzle-creek-leaf.png', 'field':'10-drizzle-field-leaf.png', 'hills':'10-drizzle-hills-umbrella.png', 'home':'10-drizzle-home-laundry.png', 'orchard':'10-drizzle-orchard-reading.png'},
'rainy': {'city':'12-heavy-rain-busstop-umbrella.png', 'creek':['11-rain-creek-leaf.png','12-heavy-rain-creek-leaf.png']|random(), 'field':'10-drizzle-field-leaf.png', 'hills':'11-rain-hills-umbrella.png', 'home':['11-rain-home-inside.png','11-rain-home-laundry.png']|random(), 'orchard':['11-rain-home-inside.png','11-rain-home-laundry.png']|random()},
'snowy': {'city':['13-flurries-citypark-snowman.png','15-snow-showers-snow-citypark-snowman.png','20-rain-snow-wintry-mix-citypark-snowman.png']|random(), 'creek':['13-flurries-creek-iceskating.png','15-snow-showers-snow-creek-iceskating.png']|random(), 'field':'16-blowing-snow-field-snowman.png', 'home':'15-snow-showers-snow-home-shoveling.png'},
'snow-storm': {'home':['17-heavy-snow-blizzard-home-inside.png','17-heavy-snow-blizzard-home-shoveling.png']|random(), 'field':'16-blowing-snow-field-snowman.png'},
'hail': {'city':['19-mixed-rain-hail-rain-sleet-busstop-waiting.png','19-mixed-rain-hail-rain-sleet-cafe-entering.png']|random()},
'lightning': {'city':'22-iso-thunderstorm-cafe-looking-outside.png', 'home':['22-iso-thunderstorms-home-inside.png','24-strong-thunderstorms-home-inside.png']|random()},
'fog': {'city':['26-haze-fog-dust-smoke-busstop-waiting.png','26-haze-fog-dust-smoke-fruit-stand.png','26-haze-fog-dust-smoke-pier.png']|random(), 'creek':'26-haze-fog-dust-smoke-bridge.png', 'field':'26-haze-fog-dust-smoke-field-lantern.png', 'hills':'26-haze-fog-dust-smoke-hills-cocoa.png', 'home':'26-haze-fog-dust-smoke-rooftop.png', 'orchard':'26-haze-fog-dust-smoke-mountain.png'}} %}
            
{% if weather_status == "snowy" %}
  {% set other_location = ['13-flurries-citypark-snowman.png', '15-snow-showers-snow-citypark-snowman.png', '20-rain-snow-wintry-mix-citypark-snowman.png', '13-flurries-creek-iceskating.png', '15-snow-showers-snow-creek-iceskating.png', '16-blowing-snow-field-snowman.png', '15-snow-showers-snow-home-shoveling.png'] | random() %}
{% elif weather_status == "snow-storm" %}
  {% set other_location = ['17-heavy-snow-blizzard-home-inside.png', '17-heavy-snow-blizzard-home-shoveling.png', '16-blowing-snow-field-snowman.png'] | random() %}
{% elif weather_status == "lightning" %}
  {% set other_location = ['22-iso-thunderstorm-cafe-looking-outside.png', '22-iso-thunderstorms-home-inside.png', '24-strong-thunderstorms-home-inside.png'] | random() %}
{% elif weather_status == "hail" %}
{% set other_location = ['19-mixed-rain-hail-rain-sleet-busstop-waiting.png','19-mixed-rain-hail-rain-sleet-cafe-entering.png'] | random() %}
{% endif %}
{{ '/local/froggy/' + dict[weather_status][frog_location] | default(other_location) }}

And you are done! Now every helper / sensor is created – but there are still a few steps to do.

  1. Now we create an automation which changes froggys location every night at 03:30 am to a random location or – if the conditions match – to the beach location.
    1. Go to “Automations and Scenes” and create a new automation
    2. As trigger choose “Time” and select the time of your choosing (mine is 03:30)
platform: time
at: "03:30:00"
  1. And as Action copy the following yaml code:
if:
  - condition: and
    conditions:
      - condition: numeric_state
        entity_id: sensor.wetter_munchen_vorhersage_temperatur #Change the sensor to the unique ID you chose for the temperature-sensor in step 1
        above: 27
      - condition: or
        conditions:
          - condition: state
            entity_id: sensor.wetter_munchen_vorhersage_status #Change the sensor to the unique ID you chose for the state-sensor in step 1
            state: sunny
          - condition: state
            entity_id: sensor.wetter_munchen_vorhersage_status #Change the sensor to the unique ID you chose for the state-sensor in step 1
            state: partlycloudy
then:
  - service: input_select.select_option
    metadata: {}
    data:
      option: beach
    target:
      entity_id: input_select.wetter_froggy_ort #Change the input_select to the name for the input_select you chose in step 4
else:
  - service: input_select.select_option
    target:
      entity_id: input_select.wetter_froggy_ort #Change the input_select to the name for the input_select you chose in step 4
    data:
      option: "{{ ['city','creek','field','hills','home','orchard'] | random }}"

This automation runs everyday at 03:30 am and chooses a location for froggy.
- If the forecast temperature for the day is above 27 °C AND the forecast status for the day is either sunny or partly cloudy, then the location for froggy is “beach”.
- Otherwise it’s chooses a random location from ‘city’,‘creek’,‘field’,‘hills’,‘home’ or 'orchard’.
You can change the conditions for “beach” to your liking. =)

  1. Next you need to download the actual pictures to your homeassistant. You can find the pictures in the following githup I forked from senexis.

https://github.com/bonzenpaule/Google-Weather-Frog/tree/master/images/wide

You need to create a new folder inside your “www” folder and name it “froggy”. Send the pictures to this folder. When you are done the helper we created in step 5 should choose one of these pictures we just downloaded matching to your weather condition and the location of the input_select.

  1. Next you need to edit the theme you are using and add some CSS-variables. This is mandatory for the card we are creating in the next step. When you update your theme you will have to repeat this step. This is the part of my solution I don’t really like.
    I hope somebody more experienced than me can find a better solution so you don’t have to repeat this every time the theme is updated.
    1. Open your file editor and search for your theme in the folder “themes” (the path should be /homeassistant/themes)
    2. Open the folder named after the theme you are using and then open the .yaml file of your theme
    3. Add the following code to the yaml file of your theme at the top or the end
# froggy
frog-rgb-sunny: 24, 159, 215
frog-rgb-mostly-sunny: 68, 176, 214
frog-rgb-partly-cloudy-day: 100, 165, 208
frog-rgb-mostly-cloudy-day: 114, 164, 209
frog-rgb-clear: 124, 76, 242
frog-rgb-mostly-clear: 133, 109, 229
frog-rgb-partly-cloudy-night: 137, 135, 218
frog-rgb-mostly-cloudy-night: 144, 152, 213
frog-rgb-cloudy-night: 138, 145, 204
frog-rgb-cloudy: 145, 169, 206
frog-rgb-drizzle: 126, 172, 216
frog-rgb-rainy: 40, 130, 221
frog-rgb-snowy: 109, 144, 152
frog-rgb-lightning: 162, 84, 130
frog-rgb-fog: 184, 168, 168
frog-rgb-hail: 103, 143, 164

Again: You will have to repeat this step every time you update your theme (because the theme.yaml file gets updated to the version from the author).

I would appreciate if somebody could help me make these CSS-Variables more persistent. I don’t know enough about coding to change it.

  1. The penultimate step is the easiest one: Restart Home Assistant and afterwards check all the sensors and helpers you created
  2. And the last and final step is adding the weather card to your dashboard. You can use the following code for a “manual” card to do that:
type: custom:stack-in-card
cards:
  - entity: weather.munchen #Change this to your weather entity
    name: ''
    show_current: true
    show_forecast: false
    type: weather-forecast
    forecast_type: daily
card_mod:
  style: |
    ha-card {
      height: 15em !important;
      width: 100%;
      --primary-text-color: white;
      --secondary-text-color: white;
      box-shadow: none;
      background: linear-gradient(to top, transparent, rgba(var(--frog-rgb-{{states('sensor.wetter_froggy_status')}})) 10%), url({{states('sensor.wetter_froggy_bild')}}); #Change the name of both sensors to the name you chose in steps 3 and 5
      background-size: cover, 200% auto;
      background-position: bottom left {% if is_state("input_select.wetter_froggy_ort", "field") %}20%{% elif is_state("input_select.wetter_froggy_ort", "hills") %}40%{% else %}10%{% endif %}; #Change the name of both input_select helpers to the name you chose in step 4
      background-repeat: no-repeat;
      background-blend-mode: saturation;
    }

And now we are finally finally done! :blush:

This card is essentially the standard weather card but with a changed background. The background picture is determined by the template sensor “wetter_froggy_bild” (step 5) and the color (or tint) of the background is determined by the state of the template sensor “wetter_froggy_status” (step 3) and the CSS-Variables we saved inside our theme (step 8). The custom:stack-in-card helps with the location of the weather information and the background. That’s why this is added.

I hope this solution is helpful for someone and I would appreciate some feedback or ideas for improvement.

Again: All credit goes to @arenacloser for writing the code for all template sensors and the CSS-Variables. Thank you for creating and sharing your code!

Have a nice day!

5 Likes

This is amazing! thank you for doing this, much appreciated. I have one question…when adding the weather card to my dashboard, this line is causing me issues:

background: linear-gradient(to top, transparent, rgba(var(--frog-rgb-{{states('sensor.weather_frog_status')}})) 10%), url({{states('sensor.weather_frog_image')}});

all I get is a blank image, but if I just include:

 background: url({{states('sensor.weather_frog_image')}});

I can see the background image.

It seems like the linear-gradient is causing issues for me…any ideas?

Much appreciated. =)
I think this issue is because of step 8. Maybe you need to put the code in a different location in the yaml file of your theme. Can you post the code of your theme.yaml here or at paste.bin?

Thank you soooo much for your help and nice tutorial. I follow each step and now my froggy back . Thank you.
image

If anybody interesting, here is a code for my card:

type: custom:stack-in-card
cards:
  - type: markdown
    tap_action:
      action: navigate
      navigation_path: weather
    card_mod:
      style:
        .: |
          ha-card {
             background-color: rgba(0,0,0,0) !important;
             box-shadow: none;
             margin-left:0rem
             }

           ha-markdown-element:second-of-type h1 {
              background-color: rgba(0,0,0,0);
              color: var(--primary-text-color);
              font-weight: normal;
              font-size: 3px;
              line-height: 3px;
            }
    content: >
      ###{% if now().hour  < 5 %} Good Night {{'\U0001F634'}} {% elif now().hour
      < 12 %} Good Morning {{'\u2615\uFE0F'}} {% elif now().hour < 18 %} Good
      Afternoon  {{'\U0001F44B\U0001F3FB'}} {% else %} Good Evening
      {{'\U0001F44B\U0001F3FB'}}{% endif %} ,  {{user}}.<br/>   Today is {{
      now().strftime('%A') }}, {{ now().strftime('%B') }} {% set suffix = ['st',
      'nd', 'rd'] %}{% set day = now().day %}{% set index = 3 if day // 10 == 1
      or day % 10 == 0 else (day % 10) - 1 %} {{ day~'th' if index > 2 else
      day~suffix[index] }} and it's {{ now().strftime('%-I:%M %p') }}. <br/> 
      Temperature   {{states('sensor.openweathermap_temperature') | int  }}°C
      <br/>  {{states('sensor.openweathermap_condition') }}.
  - type: picture
    image: /local/MyPictures/OIP-removebg-preview.png
    tap_action:
      action: navigate
      navigation_path: weather
    card_mod:
      style: |
        ha-card { 
          background-color: transparent !important;
        }   
card_mod:
  style: |
    ha-card {
      height: 20em !important;
      background: linear-gradient(to top, transparent, rgba(var(--frog-rgb-{{states('sensor.weather_frog_status_2')}})) 10%), url({{states('sensor.weather_froggy_picture')}});

      background-size: cover, 200% auto;
      background-position: bottom left {% if is_state("sensor.weather_frog_location", "field") %}20%{% elif is_state("sensor.weather_frog_location", "hills") %}40%{% else %}10%{% endif %};
      background-repeat: no-repeat;
      background-blend-mode: saturation;
      font-size: 10px;
    }

This was the case! I had the code in the wrong part of the theme.yaml…all fixed now! Brilliant! thanks for the great work!

1 Like

Great write-up, and thanks for the shoutout! Having the pictures stored locally is a nice improvement, as is the beach location for hot summer days :sun_with_face:. I always meant to add that in, but I think it was winter when I built my frog setup so it wasn’t very relevant at the time :slight_smile:

As to the theme variables, I’m using my own theme.yaml (in a separate folder within /config/themes) where I’ve changed some HA variables as well as added some custom variables (including the frog variables). These don’t get overwritten with each HA update, theme update or theme reload. I explain here how I did this for my Adaptive Mushroom theme, but the steps should be the same for any custom theme.

1 Like

Nice! Gonna try it and update the write-up afterwards.