From time to time, I'll scroll through the internet looking for home automation ideals that others have implemented and that I might be able to take some inspiration from.

About 8 or 9 months ago I saw a post on Twitter where someone had integrated an API with Home Assistant to inform them of which bin they needed to put out that week (general waste, cardboard, mixed recycling, etc)

A couple of hours after seeing this I had my own version:

Blue bin day icon for a black bin day

As it's a new year, I need to make sure Home Assistant is updated with this years bin schedule (I'll explain why shortly), and it felt like a good opportunity to try and correct the UI/UX of the Bin Day card, which has two problems:

  1. The icon should be a bit more bin-like
  2. The icon is blue when the bin day is black... This is particularly unhelpful and potentially confusing given that we do have a blue bin for cardboard. Ideally the icon colour should reflect the colour of the bin that needs to go out (black, blue or brown).

Having Home Assistant be able to tell me what bin day it is was certainly a gimmick for the first few months because I'd always forget to get my phone out and check. However, since we've been using a tablet as a wall-mounted Home Assistant dashboard this has actually become useful. This is most likely because the dashboard is in the kitchen, so if you're pottering about in the kitchen on a monday night, at a glance you can see what bin needs putting out.

How It Works

In the original twitter post that inspired this (which unfortunately I can't find several months later), the poster had used the developer tools in their web browser to reverse engineer AJAX calls that where made by their local authorities website so that they could automatically look up what bin day it was. Nice!

My version is unfortunately basic and a little bit manual because the website my local authority has isn't amazing and I can't easily extract this information in a similar way.

The Concept

Within my Home Assistant setup, I've built a rest API that is consumed by a REST sensor which is used to surface which bin day it is.

This might sound complicated by it's quite straightforward and basic. My sensors are defined in a sensor.yaml and I have the following entry:

- platform: rest
  name: bin_day
  resource: http://192.168.1.5:5050/api/appdaemon/bin_day
  method: POST
  headers:
    Content-Type: application/json
  value_template: "{{ value_json.bin_day }}"

The rest of the effort goes into the API endpoint.

The API

I've previously used AppDeamon where I've wanted to do something custom with some python programming.

This is another good example where a small 23-line python script and a CSV file could provide me with that REST API that my local authority is lacking.

Within my AppDaemon's apps.yaml I added a new entry:

...
bin_reminder:
  module: bin_reminder
  class: BinReminder
...
/config/appdaemon/apps/apps.yaml

All I need now is a simple Home Assistant API plugin script that can lookup from a CSV file which bin day it is:

import appdaemon.plugins.hass.hassapi as hass
import csv
import datetime
import os

class BinReminder(hass.Hass):
    def initialize(self):
        self.register_endpoint(self.bin_day, 'bin_day')
        self.dates = []
        csv_filename = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'bin_reminder.csv')
        with open(csv_filename) as csvfile:
            reader = csv.DictReader(csvfile)
            for row in reader:
                self.dates.append({
                    'date': datetime.datetime.strptime(row['date'], "%Y-%m-%d"),
                    'bin': row['bin'],
                })

    async def bin_day(self, request, kwargs):
        upcoming = [entry for entry in self.dates if entry['date'] >= datetime.datetime.today()]
        upcoming.sort(key = lambda x:x['date'])
        response = {"bin_day": upcoming[0]['bin']}
        return response, 200

bin_reminder.py

In the same directory as the python file I also have bin_reminder.csv which is a basic lookup csv:

date,bin
2022-05-03,Blue
2022-05-10,Black
2022-05-17,Brown
2022-05-24,Black
...
bin_reminder.csv

And that's it!

Once a year I have to go in and update the list of dates for the new year but that's only a two minute job.

Adjusting the Icon Colour

Firstly, it's worth noting that as it currently stands the sensor only has a state and no state attributes (if we ignore the friendly_name):

Home Assistant Developer Tools showing bin_day state without attributes

So that I can keep the dashboard config of Home Assistant as simple as possible I plan to make a slight change to the API and the sensor to pass back a dedicated icon_color state attribute.

Updating the API

Before we can update the sensor we should update the API to return more information. We will need to update the bin_day function to return an icon_color attribute which we can infer from the bin column in our CSV data.

response = {"bin_day": upcoming[0]['bin']}

Should become:

response = {
    "bin_day": upcoming[0]['bin'],
    "icon_color": upcoming[0]['bin'].lower()
}

Which results in the following bin_reminder.py

import appdaemon.plugins.hass.hassapi as hass
import csv
import datetime
import os

class BinReminder(hass.Hass):
    def initialize(self):
        self.register_endpoint(self.bin_day, 'bin_day')
        self.dates = []
        csv_filename = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'bin_reminder.csv')
        with open(csv_filename) as csvfile:
            reader = csv.DictReader(csvfile)
            for row in reader:
                self.dates.append({
                    'date': datetime.datetime.strptime(row['date'], "%Y-%m-%d"),
                    'bin': row['bin']
                })

    async def bin_day(self, request, kwargs):
        upcoming = [entry for entry in self.dates if entry['date'] >= datetime.datetime.today()]
        upcoming.sort(key = lambda x:x['date'])
        response = {
            "bin_day": upcoming[0]['bin'],
            "icon_color": upcoming[0]['bin'].lower()
        }
        return response, 200

Updated bin_reminder.py to return icon_color

AppDaemon should detect and reload the code change automatically without us having to do anything.

Read the new icon_color attribute

We will now need to update sensor.yaml to pull in icon_color as a JSON attribute (via json_attributes):

- platform: rest
  name: bin_day
  resource: http://192.168.1.5:5050/api/appdaemon/bin_day
  method: POST
  headers:
    Content-Type: application/json
  value_template: "{{ value_json.bin_day }}"
  json_attributes:
    - icon_color

Don't forget to tell Home Assistant to reload sensors. Press C to pull up the command palaette and select Reload Rest Entities and Notify Services:

Home Assistant Command Pallette

And if we check the state of our entity in the Developer Tools we should seen an icon_color attribute:

Home Assistant Developer Tools showing bin_day state with attributes

Now we're all set to update our dashboard.

Update the dashboard

My original bin reminder card was a Mushroom Entity Card. This is the configuration for the card as YAML

type: custom:mushroom-entity-card
entity: sensor.bin_day
name: Tuesday Bin Day
layout: vertical
fill_container: true
icon: mdi:trash-can

A mushroom entity card does support an icon_color attribute but it won't let us set this dynamically via a tamplate.

Therefore, it's time to get rid of the Mushroom Entity Card and switch to the Mushroom Template Card:

type: custom:mushroom-template-card
primary: '  Tuesday Bin Day'
secondary: '{{ states(''sensor.bin_day'') }}'
icon: mdi:trash-can
layout: vertical
badge_color: ''
icon_color: '{{ state_attr(''sensor.bin_day'', ''icon_color'') }}'
badge_icon: ''
fill_container: true

Now the bin icon is black for black bin day rather than blue!

Black bin day icon for a black bin day

Where we leave there are black, blue and brown bin days. The icon will now automatically reflect the colour of the bin day:

Bin day icons coloured to match the colour of the bin