Announce the type of waste bin collection schedule

I live on the Gold Coast, Australia. My city council offers a web page where I can check for my waste collection schedule.

This github repo contains the implementation for an extensive list of locations around the world, in python, for homeassistant:

This below demonstrates using JRuby scripting to scrape the waste collection schedule from a web page.

I cheated a bit in my rule because I know my schedule is on Wednesdays. My city council collects the general waste every week, but alternate the recycling bin and green waste bin every other week. So I hard coded my rule to run on Tuesday, Wednesday and Thursday, to issue a reminder, and make a little icon on my wall display to appear on Tuesday and Wednesday, and disappear on Thursday. A different / better way of checking could surely be done.

# frozen_string_literal: true

# gemfile do
#   source "https://rubygems.org"
#   gem "faraday"
#   gem "nokogiri"
# end
#
# Or configure the jrubyscripting addon to install these gems on startup

require "faraday"
require "nokogiri"

# Idea from https://github.com/mampfes/hacs_waste_collection_schedule

ANNOUNCEMENT_TIME = LocalTime.parse("7pm")
ADDRESS = "1 Cavill Avenue, Surfers Paradise"

module WasteCollectionSchedule
  class GoldCoast
    attr_reader :schedule

    module Type
      GENERAL = "General waste"
      RECYCLING = "Recycling"
      GREEN = "Green organics"
    end

    def initialize(address)
      fetch(address)
    end

    def fetch(address)
      conn = Faraday.new(url: "https://www.goldcoast.qld.gov.au") { |f| f.response :json }

      response = conn.get("/api/v1/myarea/searchfuzzy?maxresults=1", keywords: address).body
      unless (geolocation_id = response["Items"].first["Id"])
        raise "No results found for #{address}. Check your address on https://www.goldcoast.qld.gov.au/Services/Waste-recycling/Find-my-bin-day"
      end

      content = conn.get("/ocapi/Public/myarea/wasteservices", ocsvclang: "en-AU", geolocationid: geolocation_id)
                    .body["responseContent"]

      @schedule = Nokogiri::HTML.fragment(content)
                                .search("article")
                                .map do |element|
        {
          type: element.search("h3").text,
          frequency: parse_frequency(element.search("div.subheading").text),
          date: Date.parse(element.search("div.next-service").text.strip.split.last)
        }
      end
      self
    ensure
      conn.close
    end

    def next_collection_date
      @schedule.map { |item| item[:date] }
               .select { |date| date >= Date.today }
               .min
    end

    def next_collections
      @schedule.select { |item| item[:date] == next_collection_date }
    end

    private

    #
    # Parse the frequency description and return the duration
    #
    # @param frequency [String] The frequency of the waste collection, e.g. "weekly", "fortnightly"
    # @return [Duration]
    def parse_frequency(frequency)
      case frequency.downcase
      when /weekly/ then 7.days
      when /fortnightly/ then 14.days
      end
    end
  end
end

# This is for mainui page to show an icon
items.build do
  string_item Next_WasteCollection_Type, "Next Waste Collection Type", state: NULL
end

rule "Download rubbish bin collection schedule" do
  on_load
  every :tuesday, :wednesday, :thursday
  only_if { Time.now.then { |t| t.tuesday? || t.wednesday? || t.thursday? } }
  run do
    if Time.now.then { |t| t.tuesday? || t.wednesday? }
      schedule = WasteCollectionSchedule::GoldCoast.new(ADDRESS)

      if Date.today.between?(schedule.next_collection_date - 1, schedule.next_collection_date)
        type = schedule.next_collections
                       .map { |item| item[:type] }
                       .reject { |t| t == WasteCollectionSchedule::GoldCoast::Type::GENERAL }
                       .first

        Next_WasteCollection_Type.update type

        msg = "<speak>Bin day, bin day, <prosody rate='slow'>tomorrow is a #{type} bin day</prosody>, #{type} bin</speak>"
        msg_plain = msg.gsub(/<[^>]*>/, "")
        if Date.today.next_day == schedule.next_collection_date
          Notification.send(msg_plain, id: "bin_day", icon: "ic:hugeicons:waste")
        end

        announcement_time = schedule.next_collection_date.prev_day.to_zoned_date_time.with(ANNOUNCEMENT_TIME)
        if announcement_time > Time.now
          after(announcement_time, id: Next_WasteCollection_Type) do
            LivingRoom_Echo_TTS << msg
          end
        end
      end
    else
      Next_WasteCollection_Type.update nil
    end
  end
end

That looks good. I just put it in my calendar as a recurring event. :grinning:
I have my calendar events on my home phone screen and also have an alarm set for the bin night as well.

Yeah I used to do that too, but I want a voice reminder the night before, and a coloured icon on Mainui wall display. I need all the reminders I can get!!

What I’d still like to do is analyse my security camera image and know when the corrrect bins (recycling or green) are actually out by the kerb and if not, annoy me with more voice alerts.

Are you going to use A.I object detection?
I have that on my zoneminder cameras for people and cars. Haven’t done it for garbage bins though.
Anyway my bins go at the end of the drive and the camera is 100 metres away and where the bins are they are blocked from view by a dam wall.
Good thing is if I put the bins out on the day after the truck has gone by I can move them 20 metres to the left and the truck comes back up that road about 3 hours later. :smiley:

Yes, that’s the plan, but I haven’t figured out how! :slight_smile: It needs to identify the yellow bin vs green bin vs the general waste bin (mine is also green - before they changed it to red). Maybe I should make it easier by making my general waste bin red first. Either by painting it or asking the council to replace it.

My bins are all the same colour. Just the lids are different colour. That would make it even harder I guess.

The amount of rubbish we create here I could not put the bin for 2 months and still not fill it. So if I miss week it doesn’t really matter.

Anyway good luck with that.