Smart Litter Box (or Smart Cats)

My situation was a little bit different. We have one litter tray in our house, and want to check/empty it after every visit to minimise odour.

The tray is conveniently in the same room as my Raspberry Pi, though. So I was able to build my own sensor, with a PIR attached to an Arduino, plug it in to the Pi, and check its state with a serial sensor.

Every second, the Arduino sends a number. 0 means the tray hasn’t been visited. Greater than 0 is the time in seconds since last visit. The sensor also has a button attached - after cleaning the tray you hit the button, and the sensor is reset back to an unvisited state. This makes it a lot easier to track visits.

I have three sensors: One is just the raw readings from the serial device. One parses that reading from seconds to a friendly string. And one uses that string and a custom icon for use in the frontend.

sensor:
  - platform: serial
    name: raw poopmon
    serial_port: /dev/ttyS3
  - platform: template
    sensors:
      poopmon_time:
        friendly_name: "Time when litter tray was last used"
        value_template: >-
          {% set time = states.sensor.raw_poopmon.state | int %}
          {% set minutes = ((time % 3600) / 60) | int %}
          {% set hours = ((time % 86400) / 3600) | int %}
          {%- if time < 60 -%}
            less than a minute
          {%- else -%}
            {%- if hours > 0 -%}
              {% if hours == 1 -%}
                1 hour
              {%- else -%}
                {{ hours }} hours
              {%- endif -%}
            {%- endif -%}
            {%- if minutes > 0 -%}
              {%- if hours > 0 -%}
                {{ ', ' }}
              {%- endif -%}
              {%- if minutes == 1 -%}
                1 minute
              {%- else -%}
                {{ minutes }} minutes
              {%- endif -%}
            {%- endif -%}
          {%- endif -%}
      litter_tray:
        friendly_name: "Eli's litter tray"
        value_template: >-
          {% if states.sensor.raw_poopmon.state|int == 0 %}
            Clean
          {% else %}
            Last used {{ states.sensor.poopmon_time.state }} ago
          {% endif %}
        icon_template: >-
          {% if states.sensor.raw_poopmon.state|int == 0 %}
            mdi:cat
          {% else %}
            mdi:emoticon-poop
          {% endif %}

Automations are done by just looking at the raw readings:

automation:
  - id: 'cat poop notification'
    alias: cat poop notification
    trigger:
      platform: numeric_state
      entity_id: sensor.raw_poopmon
      above: 0
    action:
      service: notify.html5_notifier
      data_template:
        title: "\uD83D\uDCA9 alert"
        message: Litter box has been visited

  - id: 'clean tray notification'
    alias: clean tray notification
    trigger:
      platform: numeric_state
      entity_id: sensor.raw_poopmon
      below: 1
      for:
        minutes: 3
    action:
      service: notify.html5_notifier
      data_template:
        title: "\uD83D\uDE3B alert"
        message: Litter box has been cleaned

I haven’t checked yet, but it should be fairly easy to count visits by just looking for raw_poopmon changing state from 0 to >0.

4 Likes