Waste collection card using ReCollect

My city uses the ReCollect service for waste collection, but I couldn’t find a nice way to display its data, so here’s what I came up with.

card display

image

In my city, we alternate weeks for greybin/bluebin (paper vs glass/plastic), and so that’s the most important thing I wanted to track. Pickup is also early in the morning on Tuesday, so I put it out on the curb Monday night.

Features:

  • Shows a newspaper or bottle icon, depending on the week
  • Icon turns “on” when collection day is tomorrow
  • Shows a warning icon next to the date if the collection day isn’t normal

Uses template-entity-row custom card, and here’s the lovelace code:

type: entities
show_header_toggle: false
title: Garbage Pickup
entities:
  - type: 'custom:template-entity-row'
    entity: sensor.recollect_waste
    name: >
      {%- for item in state_attr('sensor.recollect_waste','pickup_types') -%}
        {%- if loop.first == false %}, {% endif -%}
        {{ item | title }}
      {%- endfor -%}
    icon: >
      {%- set items = state_attr('sensor.recollect_waste','pickup_types') -%}
      {%- if 'greybox' in items -%}mdi:newspaper 
      {%- elif 'bluebox' in items -%}mdi:bottle-soda 
      {%- else -%}mdi:trash-can-outline {%- endif -%}
    active: >
      {%- set next = as_timestamp(states('sensor.recollect_waste')+"T00:00:00"+(as_timestamp(now())|timestamp_custom("%z"))) -%}
      {%- set days = (next - as_timestamp(now())) / 86400 -%} {{ days < 1 }}
    state: >
      {%- set next = as_timestamp(states('sensor.recollect_waste')+"T00:00:00"+(as_timestamp(now())|timestamp_custom("%z"))) -%}
      {%- set days = (next - as_timestamp(now())) / 86400 -%}
      
      {%- if days < -2 -%} n/a
      {%- elif days < -1 -%} Yesterday
      {%- elif days < 0 -%} Today
      {%- elif days < 1.0 -%}Tomorrow
      {%- else -%}{{ days | round(0,'ceil') }} days
      {%- endif -%}
    secondary: >
      {%- set next = as_timestamp(states('sensor.recollect_waste')+"T00:00:00"+(as_timestamp(now())|timestamp_custom("%z"))) -%}
      {%- if next | timestamp_custom('%a') != 'Tue' -%}⚠️ {%- endif -%} {{
      next | timestamp_custom('%A, %B %-d') }}

To install:

  1. Add the ReCollect integration
  2. Install template-entity-row (via HACS is easiest)
  3. Add the above code to a card
  4. Change the second-last line from 'Tue' to whatever your collection day is.

EDIT 2021-07-05:

  • Fix issues with UTC time conversions, partly based on changes from @superm1
2 Likes

Thanks so much, this is awesome!

maybe you should have a look on garbage-collection.
i am using that.
Easy to use and flexible.

https://github.com/bruxy70/Garbage-Collection

Thanks - the card is neat, but specifically wanted to use the ReCollect API because the city maintains it and it’s always correct for holidays and other special collection days/weeks (such as battery pickup once or twice a year, “extra bag” day sometime after christmas, leaf week, and spring/fall brush collection).

It would be possible to do something similar using Glance with some custom sensors (one for each collection type), but I guess it depends on your objective. I’m used to taking trash out Monday night, and mainly want to be sure I have the right type of recycling or any exceptions, and I think that works better with entity row.

Just to share back - i’ve made some tweaks for my use of it. In case they’re useful to you too.
Better shows the date (not inaccurate within 2 days or after). And I have an NFC tag I scan when I put my can on the curb that shows it here too.

type: entities
show_header_toggle: false
title: Garbage Pickup
entities:
  - type: 'custom:template-entity-row'
    entity: sensor.recollect_waste
    name: |
      {%- for item in state_attr('sensor.recollect_waste','pickup_types') -%}
      {%- if loop.first == false %}, {% endif -%}
      {{ item | title }}
      {%- endfor -%}
    icon: |
      {%- set items = state_attr('sensor.recollect_waste','pickup_types') -%}
      {%- if 'recycling' in items -%}mdi:newspaper
      {%- else -%}mdi:trash-can-outline
      {%- endif -%}
    active: |
      {%- set next = as_timestamp(states('sensor.recollect_waste')) -%}
      {%- set days = (next - as_timestamp(now())) / 86400 -%}
      {{ days < 1 }}
    state: |
      {%- set next = as_timestamp(states('sensor.recollect_waste')) -%}
      {%- set days = (next - as_timestamp(now())) / 86400 -%}
      {%- if days < 0 -%} Yesterday
      {%- elif days < 1.0 -%}Today
      {%- elif days < 2.0 -%}Tomorrow
      {%- else -%}{{ days | round(0,'ceil') }} days
      {%- endif -%}
    secondary: >
      {%- set next = as_timestamp(states('sensor.recollect_waste')) -%} {%- if
      next | timestamp_custom('%a',false) != 'Wed' -%}⚠️ {%- endif -%} {{ next |
      timestamp_custom('%A, %B %-d',false) }}
  - type: 'custom:template-entity-row'
    entity: input_boolean.trash_can_on_curb

With this card, how did you connect to recollect_waste? You have to tear apart and reconstruct the string I guess to tell which entities to fill up and which days. Care to share what you’ve done?

As a note with the latest recollect this will no longer work:

They now UTC correct already in the code so it just has to be:

as_timestamp(states('sensor.recollect_waste'))

At least that was the case for me. Thanks for posting this.

At least for me, the sensor name has changed from

sensor.recollect_waste

to

sensor.waste_pickup

I was getting a warning on startup about the logic related to +“T00:00:00”+… would no longer work when 2022.1 was released.

I took a closer look at the template logic for the icons and see that it is using “greybox” and “bluebox”.

Neither of those values are shown in the state attribute values when I check the state of the sensor.

Mine now show as:

pickup_types:
  - Garbage
  - Yard trimmings
  - Green bin
  - Blue bin
area_name: Ottawa
next_pickup_types:
  - Black bin
  - Green bin
  - Yard trimmings
next_pickup_date: '2022-01-04'
device_class: date
icon: mdi:trash-can-outline
friendly_name: Waste Pickup

I’m assuming if I wanted to customize the template a bit, I could change “greybox” for “Black bin” and “bluebox” for “Blue bin”

Using the above examples I was getting a number of errors with 2022.2; the biggest error was that both as_timestamp() and timestamp_custom() expect a default value. I was able to clear these errors by setting a default value for as_timestamp() to 1641013200.0, or January 1, 2022, and for as_timestamp() to 'Mon' and 'Unknown' for the two instances in secondary:.

type: entities
title: Waste Pickup
show_header_toggle: false
entities:
  - type: custom:template-entity-row
    entity: sensor.waste_pickup
    name: |
      {% for item in state_attr('sensor.waste_pickup','pickup_types') %}
        {% if loop.first == false %}, {% endif %}
        {{ item | title }}
      {% endfor %}
    icon: >
      {% set items = state_attr('sensor.waste_pickup','pickup_types') %} {% if
      'Blue bin' in items %}mdi:recycle {% elif 'Black bin' in items
      %}mdi:newspaper {% else %}mdi:trash-can-outline {% endif %}
    active: >
      {% set next = as_timestamp(states('sensor.waste_pickup'),1641013200.0) %}
      {% set days = (next - as_timestamp(now())) / 86400 %} {{ -1 < days < 1 }}
    state: >
      {% set next = as_timestamp(states('sensor.waste_pickup'),1641013200.0) %}
      {% set days = (next - as_timestamp(now())) / 86400 %} {% if days < -1
      %}Yesterday {% elif days < 0 %}Today {% elif days < 1 %}Tomorrow {% else
      %}{{ days | round(0,'ceil') }} days {% endif %}
    secondary: >
      {% set next = as_timestamp(states('sensor.waste_pickup'),1641013200.0) %}
      {% if next | timestamp_custom('%a','Mon') != 'Fri' %}⚠️{% endif %}{{ next
      | timestamp_custom('%A, %B %-d','Unknown') }}
state_color: false

If for some reason sensor.waste_pickup does not have a valid state, the secondary information will display ⚠️Unknown. It would also make sense, I realize as I write this, to set the state: to Unknown if days < -2 since the idea is to know when the next pickup is not when the last one was:

    state: >
      {% set next = as_timestamp(states('sensor.waste_pickup'),1641013200.0) %}
      {% set days = (next - as_timestamp(now())) / 86400 %}
        {% if days < -2 %}Unknown
          {% elif days < -1 %}Yesterday
          {% elif days < 0 %}Today
          {% elif days < 1 %}Tomorrow
          {% else %}{{ days | round(0,'ceil') }} days
        {% endif %}

@BlackRose67, I am also in Ottawa so my setup should work for you. Just change 'Fri' to your pickup day and 'Mon' to any day other than your pickup day.

Excellent, thanks for that update.
I had noticed the message showing in the log file, but hadn’t gotten around to seeing how to address it.

With the latest release of ReCollect, the following pickup information was moved to it’s own set of attributes; sensor.next_pickup.

I’m trying to figure out how to get both entries on a single card. Right now I have the info displayed on two separate cards.

Add a second enitity to the card using sensor.next_pickup. Essentially, copy and paste the first entity, but I would omit the active: property as it will never be active. Replace each instance of sensor.waste_pickup with sensor.next_pickup. Also, state: will always be in the future, so the logic can be simplified with only “Unknown” or “X days”. I would suggest this:

type: entities
title: Waste Pickup
show_header_toggle: false
entities:
  - type: custom:template-entity-row
    entity: sensor.waste_pickup
    name: |
      {% for item in state_attr('sensor.waste_pickup','pickup_types') %}
        {% if loop.first == false %}, {% endif %}
        {{ item | title }}
      {% endfor %}
    icon: >
      {% set items = state_attr('sensor.waste_pickup','pickup_types') %} {% if
      'Blue bin' in items %}mdi:recycle {% elif 'Black bin' in items
      %}mdi:newspaper {% else %}mdi:trash-can-outline {% endif %}
    active: >
      {% set next = as_timestamp(states('sensor.waste_pickup'),1641013200.0) %}
      {% set days = (next - as_timestamp(now())) / 86400 %} {{ -1 < days < 1 }}
    state: >
      {% set next = as_timestamp(states('sensor.waste_pickup'),1641013200.0) %}
      {% set days = (next - as_timestamp(now())) / 86400 %}
        {% if days < -2 %}Unknown
          {% elif days < -1 %}Yesterday
          {% elif days < 0 %}Today
          {% elif days < 1 %}Tomorrow
          {% else %}{{ days | round(0,'ceil') }} days
        {% endif %}
    secondary: >
      {% set next = as_timestamp(states('sensor.waste_pickup'),1641013200.0) %}
      {% if next | timestamp_custom('%a','Mon') != 'Fri' %}⚠️{% endif %}{{ next
      | timestamp_custom('%A, %B %-d','Unknown') }}
  - type: custom:template-entity-row
    entity: sensor.next_pickup
    name: |
      {% for item in state_attr('sensor.next_pickup','pickup_types') %}
        {% if loop.first == false %}, {% endif %}
        {{ item | title }}
      {% endfor %}
    icon: >
      {% set items = state_attr('sensor.next_pickup','pickup_types') %} {% if
      'Blue bin' in items %}mdi:recycle {% elif 'Black bin' in items
      %}mdi:newspaper {% else %}mdi:trash-can-outline {% endif %}
    state: >
      {% set next = as_timestamp(states('sensor.next_pickup'),1641013200.0) %}
      {% set days = (next - as_timestamp(now())) / 86400 %}
        {% if days < -2 %}Unknown
          {% else %}{{ days | round(0,'ceil') }} days
        {% endif %}
    secondary: >
      {% set next = as_timestamp(states('sensor.next_pickup'),1641013200.0) %}
      {% if next | timestamp_custom('%a','Mon') != 'Fri' %}⚠️{% endif %}{{ next
      | timestamp_custom('%A, %B %-d','Unknown') }}
state_color: false
1 Like

This seems to be the most active thread on this topic, so hopefully this isn’t out of place.

I’m having issues getting the number of days to calculate properly. Not sure if it’s my code or if there’s something up with the timezones.

It seems to change from 1 day to 0 days at about 7pm my time. The code I’m working with is…

{{ (((as_local(as_datetime(states.sensor.recollect_waste.state)) - now()).days)) }}
{{ (((as_local(as_datetime(states.sensor.next_pickup.state)) - now()).days) ) }}

At approx 10:45pm eastern these output 0 and 4 days when the pickup dates are April 18th and April 22nd. So I assume they should be 1 and 5.

Any thoughts? I’ve done some other outputs to try to troubleshoot the issue if they might be helpful…

Thanks!

I’m using the “state” logic shown in DaftHonk’s post from February 6 and it’s working fine for me.

My code is in two separate lines on an entity card, one for the current week (sensor.waste_pickup) and another for the following week (sensor.next_pickup)

Yeah I get the same issue if I use that code. Currently showing 3 days, but before 7pm my time it would have shown 4 days :confused:

So not sure what changed, but it is now switching days at midnight as expected. Seems to have sorted itself…

Wow! Amazing stuff. Heard about ReCollect Waste on the latest Home Assistant podcast and found my local trash company uses it.
Trying to get things to display neatly within the confines of template-entity-row is something I cannot figure out.
My trash variables are multiple in each week. So I have combinations of:

  1. trash
  2. recycling
  3. yard waste
  4. outside bulk items

The following week may only have recycling and garbage.
How can I get it to display all the icons instead of just the first one, so they are in columns alongside each other or even on new rows?
Also, how can I get it to wrap the text to the next line if it does not all fit?
One other thing that I am not able to figure out with templating and friendly naming, how can I take the value provided by the sensor, such as “noncartedwaste” and display something like “Bulk Items” instead, just renaming one of the values so it makes more sense?
Thank you so much if you can help.

As far as I know, you can only display one icon per row.

There is an option in the Integration to use “friendly names” for pickup types. Do you have that selected?

Not sure about the word wrap. I’ve never been able to figure that out myself for other cards.

Thanks for replying. I do have friendly names turned on.
I was hoping to figure out some templating to rename them so “noncartedwaste” changes to something like I would remember… “Bulk Trash Items”.
Guess I will have to let the icon thing go since I am not proficient in grep or templating to parse out the text items and have them display in my dashboard in some card or as an iOS or companion app notification.

FYI for everyone else that this breaks for, the sensor has been renamed to sensor.recollect_waste_current_pickup in latest.

2 Likes

This thread is really helpful!

I did the following card to show the number of days and what will be collected. We have organics weekly and garbage/recycling alternate weeks.

wastepickup

Using:

  • Recollect Add-on
  • Vertical-Stack-in-card
  • template-entity-row
type: custom:vertical-stack-in-card
title: Waste Pickup
cards:
  - type: entities
    entities:
      - type: custom:template-entity-row
        entity: sensor.recollect_waste_current_pickup
        name: Current Pickup
        icon: >
          {%- set items = state_attr('sensor.recollect_waste_current_pickup',
          'pickup_types') -%} {%- if 'Recycling' in items -%} mdi:newspaper {%-
          elif 'Garbage' in items -%} mdi:trash-can-outline {%- else -%}
          mdi:leaf {%- endif -%}
        state: >
          {%- set next =
          as_timestamp(states('sensor.recollect_waste_current_pickup')) -%} {%-
          set days = (next - as_timestamp(now())) / 86400 -%} {%- if days < 0
          -%} Yesterday {%- elif days < 1.0 -%} Today {%- elif days < 2.0 -%}
          Tomorrow {%- else -%}{{ days | round(0,'ceil') }} days {%- endif -%}
        secondary: >
          {%- set items = state_attr('sensor.recollect_waste_current_pickup',
          'pickup_types') | join(', ') -%} {{ items }}
      - type: custom:template-entity-row
        entity: sensor.recollect_waste_next_pickup
        name: Next Pickup
        icon: >
          {%- set items = state_attr('sensor.recollect_waste_next_pickup',
          'pickup_types') -%} {%- if 'Recycling' in items -%} mdi:newspaper {%-
          elif 'Organics' in items -%} mdi:leaf {%- else -%}
          mdi:trash-can-outline {%- endif -%}
        state: >
          {%- set next =
          as_timestamp(states('sensor.recollect_waste_next_pickup')) -%} {%- set
          days = (next - as_timestamp(now())) / 86400 -%} {%- if days < 0 -%}
          Yesterday {%- elif days < 1.0 -%} Today {%- elif days < 2.0 -%}
          Tomorrow {%- else -%}{{ days | round(0,'ceil') }} days {%- endif -%}
        secondary: >
          {%- set items = state_attr('sensor.recollect_waste_next_pickup',
          'pickup_types') | join(', ') -%} {{ items }}
1 Like