Gatgenie / Catgenius status

I flashed the catgenius firmware on my catgenie and i connected and esp8266 with esphome to catch the serial output. I then created a node red state-machine to collect data and make a countdown for the cleaning cycle to be finished.
Here is the node red configuration

[{"id":"2103ce12.8b8062","type":"server-state-changed","z":"12f1568f.90bde9","name":"Catgenie","server":"ee2b1905.9ff508","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"sensor.catgenie_last_message","entityidfiltertype":"exact","outputinitially":true,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":true,"ignoreCurrentStateUnavailable":true,"x":140,"y":440,"wires":[["85b88b24.1ad068"]]},{"id":"5d125f97.a8d57","type":"ha-entity","z":"12f1568f.90bde9","name":"Catgenie Sinistra ","server":"ee2b1905.9ff508","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Catgenie Sinistra"},{"property":"device_class","value":""},{"property":"icon","value":"hass:cat"},{"property":"unit_of_measurement","value":""}],"state":"state","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","outputOnStateChange":false,"outputPayload":"$entity().state ? \"on\": \"off\"","outputPayloadType":"jsonata","x":1150,"y":440,"wires":[[]]},{"id":"b861a2a.413d86","type":"ha-entity","z":"12f1568f.90bde9","name":"Catgenie Sinistra %","server":"ee2b1905.9ff508","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Catgenie Sinistra Perc"},{"property":"device_class","value":""},{"property":"icon","value":"hass:percent"},{"property":"unit_of_measurement","value":"%"}],"state":"perc","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","outputOnStateChange":false,"outputPayload":"$entity().state ? \"on\": \"off\"","outputPayloadType":"jsonata","x":1150,"y":240,"wires":[[]]},{"id":"28cc0a6f.c6a7b6","type":"state-machine","z":"12f1568f.90bde9","name":"State Machine","triggerProperty":"topic","triggerPropertyType":"msg","stateProperty":"state","statePropertyType":"msg","outputStateChangeOnly":false,"throwException":false,"states":["Sabbietta Pulita","Inizio Pulizia","1 Lavaggio","2 Lavaggio","3 Lavaggio","Asciugatura","Fine Pulizia"],"transitions":[{"name":"Inizio","from":"Sabbietta Pulita","to":"Inizio Pulizia"},{"name":"Lavaggio","from":"Inizio Pulizia","to":"1 Lavaggio"},{"name":"Lavaggio","from":"1 Lavaggio","to":"2 Lavaggio"},{"name":"Lavaggio","from":"2 Lavaggio","to":"3 Lavaggio"},{"name":"Asciugatura","from":"3 Lavaggio","to":"Asciugatura"},{"name":"Fine Asciugatura","from":"Asciugatura","to":"Fine Pulizia"},{"name":"Fine","from":"Fine Pulizia","to":"Sabbietta Pulita"}],"x":860,"y":440,"wires":[["5d125f97.a8d57"]]},{"id":"c818f979.66ee38","type":"change","z":"12f1568f.90bde9","name":"Washing","rules":[{"t":"set","p":"topic","pt":"msg","to":"Lavaggio","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":600,"y":400,"wires":[["28cc0a6f.c6a7b6"]]},{"id":"dd3e206c.3604d","type":"change","z":"12f1568f.90bde9","name":"Begin Cleaning","rules":[{"t":"set","p":"topic","pt":"msg","to":"Inizio","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":620,"y":360,"wires":[["28cc0a6f.c6a7b6","c99862dc.8eec3"]]},{"id":"d2367f31.5b51","type":"change","z":"12f1568f.90bde9","name":"End Cleaning","rules":[{"t":"set","p":"topic","pt":"msg","to":"Fine","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":620,"y":520,"wires":[["28cc0a6f.c6a7b6","c99862dc.8eec3"]]},{"id":"8535b33e.24be7","type":"change","z":"12f1568f.90bde9","name":"End Driyng","rules":[{"t":"set","p":"topic","pt":"msg","to":"Fine Asciugatura","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":610,"y":480,"wires":[["28cc0a6f.c6a7b6"]]},{"id":"b7726bdb.557b08","type":"change","z":"12f1568f.90bde9","name":"Drying","rules":[{"t":"set","p":"topic","pt":"msg","to":"Asciugatura","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":590,"y":440,"wires":[["28cc0a6f.c6a7b6"]]},{"id":"3b64ff29.ec35c","type":"function","z":"12f1568f.90bde9","name":"% Actual Cycle","func":"flow.set('timer', flow.get('timer') - 1)\nmsg.state = flow.get('timer')\nmsg.perc = Number((100 * (msg.payload - msg.state) / msg.payload).toFixed(2));\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":900,"y":240,"wires":[["b861a2a.413d86","3e102390.c9c67c"]]},{"id":"3e102390.c9c67c","type":"ha-entity","z":"12f1568f.90bde9","name":"Catgenie Sinistra Countdown","server":"ee2b1905.9ff508","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Catgenie Sinistra Countdown"},{"property":"device_class","value":""},{"property":"icon","value":"hass:camera-timer"},{"property":"unit_of_measurement","value":"s"}],"state":"state","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","outputOnStateChange":false,"outputPayload":"$entity().state ? \"on\": \"off\"","outputPayloadType":"jsonata","x":1160,"y":320,"wires":[[]]},{"id":"776ea6d0.0f9df8","type":"ha-entity","z":"12f1568f.90bde9","name":"Catgenie Sinistra Binario","server":"ee2b1905.9ff508","version":1,"debugenabled":false,"outputs":1,"entityType":"binary_sensor","config":[{"property":"name","value":"Catgenie Sinistra Binario"},{"property":"device_class","value":""},{"property":"icon","value":""},{"property":"unit_of_measurement","value":""}],"state":"state","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","outputOnStateChange":false,"outputPayload":"$entity().state ? \"on\": \"off\"","outputPayloadType":"jsonata","x":1150,"y":520,"wires":[[]]},{"id":"c99862dc.8eec3","type":"state-machine","z":"12f1568f.90bde9","name":"Binary Sensor State Machine","triggerProperty":"topic","triggerPropertyType":"msg","stateProperty":"state","statePropertyType":"msg","outputStateChangeOnly":false,"throwException":false,"states":["Off","On"],"transitions":[{"name":"Inizio","from":"Off","to":"On"},{"name":"Fine","from":"On","to":"Off"}],"x":900,"y":520,"wires":[["776ea6d0.0f9df8"]]},{"id":"d7b51df4.58ba8","type":"server-state-changed","z":"12f1568f.90bde9","name":"Test sabbiette","server":"ee2b1905.9ff508","version":1,"exposeToHomeAssistant":false,"haConfig":[{"property":"name","value":""},{"property":"icon","value":""}],"entityidfilter":"input_select.test_sabbiette","entityidfiltertype":"exact","outputinitially":false,"state_type":"str","haltifstate":"","halt_if_type":"str","halt_if_compare":"is","outputs":1,"output_only_on_state_change":true,"for":0,"forType":"num","forUnits":"minutes","ignorePrevStateNull":false,"ignorePrevStateUnknown":false,"ignorePrevStateUnavailable":false,"ignoreCurrentStateUnknown":false,"ignoreCurrentStateUnavailable":false,"x":150,"y":540,"wires":[[]]},{"id":"abab726.2c7889","type":"inject","z":"12f1568f.90bde9","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"","payloadType":"date","x":140,"y":600,"wires":[["630eceef.66f1"]]},{"id":"1f2c6673.e1aeca","type":"function","z":"12f1568f.90bde9","name":"Timer Set","func":"msg.payload = 2605\nflow.set('timer', msg.payload)\nreturn msg","outputs":1,"noerr":0,"initialize":"","finalize":"","x":500,"y":240,"wires":[["8d94e5f.bf64618"]]},{"id":"8d94e5f.bf64618","type":"looptimer","z":"12f1568f.90bde9","duration":"1","units":"Second","maxloops":"2605","maxtimeout":"48","maxtimeoutunits":"Minute","name":"","x":700,"y":240,"wires":[["3b64ff29.ec35c"],[]]},{"id":"85b88b24.1ad068","type":"switch","z":"12f1568f.90bde9","name":"State Check","property":"payload","propertyType":"msg","rules":[{"t":"cont","v":"Starting wet program","vt":"str"},{"t":"cont","v":"INS_WATER, on Filling","vt":"str"},{"t":"cont","v":"INS_DRYER, on","vt":"str"},{"t":"cont","v":"INS_DRYER, off","vt":"str"},{"t":"cont","v":"INS_END","vt":"str"}],"checkall":"true","repair":false,"outputs":5,"x":330,"y":440,"wires":[["dd3e206c.3604d","1f2c6673.e1aeca"],["c818f979.66ee38"],["b7726bdb.557b08"],["8535b33e.24be7"],["d2367f31.5b51","1e2c60ae.2abf3f","630eceef.66f1"]]},{"id":"1e2c60ae.2abf3f","type":"function","z":"12f1568f.90bde9","name":"Timer Stop","func":"msg.payload = \"stop\"\nmsg.perc = 100\nmsg.state = 0 \nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","x":610,"y":320,"wires":[["8d94e5f.bf64618","72da3c36.5dcf84"]]},{"id":"72da3c36.5dcf84","type":"delay","z":"12f1568f.90bde9","name":"","pauseType":"delay","timeout":"1","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":880,"y":320,"wires":[["b861a2a.413d86","3e102390.c9c67c"]]},{"id":"3b339203.d70c5e","type":"counter","z":"12f1568f.90bde9","name":"Cycles Count","init":"0","step":"1","lower":"","upper":"","mode":"increment","outputs":"1","x":850,"y":680,"wires":[["243dfab9.cdac76"]]},{"id":"6a8701f6.3ad34","type":"cronplus","z":"12f1568f.90bde9","name":"Midnight Activation","outputField":"payload","timeZone":"","persistDynamic":false,"commandResponseMsgOutput":"output1","outputs":1,"options":[{"name":"schedule1","topic":"schedule1","payloadType":"default","payload":"","expressionType":"cron","expression":"0 0 0 * * *","location":"","offset":"0","solarType":"all","solarEvents":"sunrise,sunset"}],"x":170,"y":680,"wires":[["92845791.4b2bf8"]]},{"id":"92845791.4b2bf8","type":"change","z":"12f1568f.90bde9","name":"Reset Cycles","rules":[{"t":"set","p":"reset","pt":"msg","to":"0","tot":"str"}],"action":"","property":"","from":"","to":"","reg":false,"x":610,"y":680,"wires":[["3b339203.d70c5e"]]},{"id":"243dfab9.cdac76","type":"ha-entity","z":"12f1568f.90bde9","name":"Catgenie Sinistra Cicli","server":"ee2b1905.9ff508","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Catgenie Sinistra Cicli"},{"property":"device_class","value":""},{"property":"icon","value":""},{"property":"unit_of_measurement","value":""}],"state":"count","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","outputOnStateChange":false,"outputPayload":"$entity().state ? \"on\": \"off\"","outputPayloadType":"jsonata","x":1160,"y":680,"wires":[[]]},{"id":"630eceef.66f1","type":"api-current-state","z":"12f1568f.90bde9","name":"Last Run","server":"ee2b1905.9ff508","version":1,"outputs":1,"halt_if":"","halt_if_type":"str","halt_if_compare":"is","override_topic":false,"entity_id":"sensor.time","state_type":"str","state_location":"state","override_payload":"msg","entity_location":"data","override_data":"msg","blockInputOverrides":false,"x":600,"y":600,"wires":[["3b339203.d70c5e","21364931.1d41d6"]]},{"id":"21364931.1d41d6","type":"ha-entity","z":"12f1568f.90bde9","name":"Catgenie Sinistra Ultimo Lavaggio","server":"ee2b1905.9ff508","version":1,"debugenabled":false,"outputs":1,"entityType":"sensor","config":[{"property":"name","value":"Catgenie Sinistra Ultimo Lavaggio"},{"property":"device_class","value":""},{"property":"icon","value":"mdi:clock"},{"property":"unit_of_measurement","value":""}],"state":"state","stateType":"msg","attributes":[],"resend":true,"outputLocation":"","outputLocationType":"none","inputOverride":"allow","outputOnStateChange":false,"outputPayload":"$entity().state ? \"on\": \"off\"","outputPayloadType":"jsonata","x":1160,"y":600,"wires":[[]]},{"id":"ee2b1905.9ff508","type":"server","name":"Home Assistant","addon":true}]
2 Likes

Hi @Melkor82, I’m really interested to hear more about your Catgenie setup. I’ve got one as well, and would like to integrate it with Home Assistant. I’m also planning to flash the custom firmware and set up ESPHome on an ESP32 / ESP8266 board.

Would you be able to share your ESPHome configuration file? I’m really curious to see how you communicate with the Catgenie over serial and set up the sensors/switches/countdowns.

I’m looking forward to setting up some automations. I want to turn on the extractor fan whenever a cat enters the Catgenie. I have the waste pipe emptying into a toilet, so I also want to find a way to automatically flush the toilet once the cleaning cycle is finished. (Maybe a switchbot, or some other automated valve.)

How has this setup been working for you? Do you still recommend using the Catgenius firmware? Have you made any other changes or improvements?

Cheers!

This is the part you are interested in, yaml main file:

esphome:
  name: $name
  platformio_options:
    upload_speed: 512000
  includes:
  - uart_read_line_sensor.h

uart:
  tx_pin: TX
  rx_pin: RX
  baud_rate: 19200
  id: uart_bus

text_sensor:
  - platform: custom
    lambda: |-
      auto my_custom_sensor = new UartReadLineSensor(id(uart_bus));
      App.register_component(my_custom_sensor);
      return {my_custom_sensor};
    text_sensors:
      name: CatGenie Last Message
      id: uart_readline
  - <<: !include
      file: templates/uptime-sensor.yaml
      vars:
        name: Uptime $upper_name

and uart sensor:

#include "esphome.h"

class UartReadLineSensor : public Component, public UARTDevice, public TextSensor {
  public:
  UartReadLineSensor(UARTComponent *parent) : UARTDevice(parent) {}

  void setup() override {
    // nothing to do here
  }

  int readline(int readch, char *buffer, int len)
  {
    static int pos = 0;
    int rpos;

    if (readch > 0) {
      switch (readch) {
        case '\r': // Ignore new-lines
          break;
        case '\n': // Return on CR
          rpos = pos;
          pos = 0;  // Reset position index ready for next time
          return rpos;
        default:
          if (pos < len-1) {
            buffer[pos++] = readch;
            buffer[pos] = 0;
          }
      }
    }
    // No end of line has been found, so return -1.
    return -1;
  }

  void loop() override {
    const int max_line_length = 80;
    static char buffer[max_line_length];
    if (available() && readline(read(), buffer, max_line_length) > 0) {
      publish_state(buffer);
    }
  }
};
2 Likes

By the way i want a more reliable control since i have 2 of them i want to have only one active at any given moment. I am developing a custom board so i can control the catgenie with own programs.

2 Likes

Any updates on your custom board? Is it something like this - GitHub - s-simma/MyCATControl: Replacement control for CATGenie

I was going to follow it until I realized I need an arduino AND a new custom board.

So I was going to go with the catgenius but I’d like a little more control than it provides.

Also did you buy a catgenius or flash over your stock board?

I flashed my stock board and yes i indeed started from s-simma work but his take on this was with a microncontrollor and i wanted it wifi so i took his diagram and completely redisigned it to fit an esp32 c3 (and his routing of the net was horrible from an electronic engineer point of view ;D) I will finish my design soon and place the order on a chinese pcb manufacture, i will need only 2 of the minimum 5 boards i need to order, if you are interested we could organize and give away one.

2 Likes

I will take one, let me know how much. I went ahead and ordered a pickit to flash my stock board in the mean time.

I would also be very interested in a custom board. Cheers!

Sorry I’m arriving late to the party, I would also like to upgrade the catgenie with an esp8266. Is the board layout still available?

Sorry guys, I live in Italy in the recently flooded area. My catgenie were submerged. I will look later if they are still working but i have so much to go through first now. I will try to make my schematic public and you can take it to print or modify by yourself.

https://oshwlab.com/melkor/catgenie

Hello melkor, I’m replacing my catgenie control board with an 8 relay esp32 board. Do you happen to have a flashable file for that kind of replacement? Just 8 normal relays

i have not sorry, was going to develop the software after the hardware