C++ syntax for custom proximity sensor component

I’m new to ESP devices. It’s been 15 years since I wrote any C++, so this topic is probably mostly about the C++ side of things. I’m attempting to set up my ESP32 dev board to read from the A02YYUW ultrasonic proximity sensor. I’m having trouble combining code samples I found online, like the code on the A02YYUW Waterproof Ultrasonic Sensor Wiki, and the code in the custom sensor docs for getting it to run less often than the standard loop() would call it (I’m assuming I don’t want to read and update home assistant that frequently, and this is the way to do it, but open to suggestions). I was able to do this all in python fairly easily, but I’ve had various other problems trying to keep this running on a Raspberry Pi Zero W, so I switched to ESP32. Everyone kept saying “it’s so easy” and “you don’t have to write any code”, but I guess the caveat is that the device has to be already supported.

Anyway, here’s my yaml:

substitutions:
  name: sump-pump
packages:
  esphome.esp_web_tools_example: github://esphome/example-configs/esp-web-tools/esp32.yaml@v1
esphome:
  name_add_mac_suffix: false
  includes:
    - sump.h
sensor:
- platform: custom
  lambda: |-
    auto my_sensor = new ProximitySensor();
    App.register_component(my_sensor);
    return {my_sensor};

  sensors:
    name: "Sump Pump Proximity Sensor"

uart:
  id: uart_bus
  tx_pin: GPIO1
  rx_pin: GPIO3
  baud_rate: 9600

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

And don’t cringe, but here’s my attempt so far for the custom component:

#include "esphome.h"

unsigned char data[4]={};
float distance;

class ProximitySensor : public PollingComponent, public UARTDevice 
{
  public:
    // constructor (I don't know what I'm doing)
    ProximitySensor(UARTComponent *parent) : UARTDevice(parent), PollingComponent(1000) {}

    void setup() override {
    }
    void update() override {
      do {
        for (int i=0;i<4;i++)
        {
          data[i]=read();
        }
      } while(read()==0xff);

      if (data[0]==0xff)
      {
        int sum;
        sum = (data[0] + data[1] + data[2])&0x00FF;
        if (sum==data[3])
        {
          distance=(data[1]<<8) + data[2];
          if (distance>30)
          {
            publish_state(distance)
          } else {
            ESP_LOGD("custom", "Below the lower limit");
          }
        } else {
          ESP_LOGD("custom", "ERROR");
        }
      }
    }
};

So how do I inherit from both the UARTDevice and PollingComponent classes, while calling the polling constructor with a 1 second interval?

Bonus points for any code or hints on keeping track of the most recent state publish value and only publishing again every minute or when the value changes by a hardcoded threshold, basically allowing it to update the state rapidly when the value is changing rapidly, but then slow down when things are fairly stable again.

I had to set up the class and constructors like this

class ProximitySensor : public Sensor, public PollingComponent, public UARTDevice 
{
  public:
    // constructor
    ProximitySensor(UARTComponent *parent, int pollingInterval) : PollingComponent(pollingInterval), UARTDevice(parent) {}

And the yaml like this

sensor:
- platform: custom
  lambda: |-
    auto my_sensor = new ProximitySensor(id(uart_bus), 10000);
    App.register_component(my_sensor);
    return {my_sensor};

  sensors:
    name: "Sump Pump Proximity Sensor"
    unit_of_measurement: mm
    id: sump_pump_proximity
    accuracy_decimals: 0

uart:
  id: uart_bus
  tx_pin: GPIO17
  rx_pin: GPIO16
  baud_rate: 9600