An IoT system using an ESP32-S3 CAM device with AI-powered cat recognition and a humane deterrent mechanism. The system identifies specific cats and can activate deterrents to manage cat territory boundaries.
- Overview
- Architecture Diagram
- Components
- Supported Hardware
- Project Structure
- Quick Start
- Cat Safety Logic
- Related Projects
- License
I have four cats. My neighbour also has a cat — Mr Boots — who has worked out that my cat flap is unlocked and that my cats' food bowl is, from his perspective, a free buffet. For a while the solution was shooing him out whenever I spotted him, but he's persistent, fast, and frankly quite smug about the whole thing. So I built this.
Meet the culprit. Boots is a sleek all-black cat with bright green eyes and an expression of complete innocence that frankly cannot be trusted.
The system needs to tell Boots apart from my own cats, who are allowed in and must never be on the receiving end of a water mist. Introducing the household:
The AI model is trained to recognise Boots versus NotBoots (everyone else, including no-cat frames), so the system only fires the water mist when it's confident the visitor is Boots. The whole pipeline — camera capture, cloud inference via a SageMaker model, and a deterrent sequence of LEDs and a short water mist — runs autonomously. Boots has so far remained unimpressed, but the data is promising.
The embedded directory contains Arduino-based firmware for ESP32 camera devices:
-
bootloader - Factory bootloader that checks for pending OTA updates on every boot. Enables single-partition OTA architecture for maximum firmware space.
-
catcam - Main application with camera capture, WiFi, Bluetooth LE, SD card logging, and AI inference integration. Includes 15+ custom libraries:
BluetoothOTA- Bluetooth-based OTA controlBluetoothService- Device status monitoring and image transfer via BLECamera- Image capture and PSRAM buffer managementCaptureController- Capture orchestrationCatCamHttpClient- HTTPS POST to AWS SageMaker inference APIImageStorage- Image file managementInputManager- Button and input handlingLedController- RGB LED controlNeoPixel- WS2812 LED driverOTAUpdate- Two-stage OTA update mechanismPCF8574Manager- I2C GPIO expander controlSDLogger- Thread-safe SD card logging with FreeRTOS mutexSystemManager- System state managementVideoRecorder- MJPEG video recording to SD cardWifiConnect- WiFi connection management
The bootloader-based OTA architecture maximises available flash space by using a single large application partition (7MB on ESP32-S3) instead of the traditional dual-partition approach.
The infra directory contains AWS CDK stacks (TypeScript) for cloud services:
- IoT Device Stack - AWS IoT Thing provisioning, certificate generation, and SSM Parameter Store integration
- API Gateway Stack - REST API endpoints for device communication
- Firmware Cleanup Stack - Lambda function that manages firmware versions in S3, keeping only the 3 most recent versions and auto-updating the manifest
The docs directory contains architecture diagrams:
architecture/architecture-deterrence.drawio- Live deterrence system architecturearchitecture/architecture-training.drawio- ML training pipeline architecture
SVG versions are auto-generated via pre-commit hook when .drawio files change.
The scripts directory contains:
install-hooks.sh- Git hooks installation script
The githooks directory contains git hooks for auto-generating architecture SVGs and TOC updates.
| Feature | Specification |
|---|---|
| Chipset | ESP32-S3 (dual-core 240MHz Xtensa LX7) |
| Flash | 16MB (QSPI) |
| PSRAM | 8MB (Octal SPI) |
| Camera | OV5640 (5MP, autofocus) |
| LED | WS2812 RGB addressable (GPIO 48) |
| Storage | microSD card slot |
| Feature | Specification |
|---|---|
| Flash | 4MB |
| PSRAM | 4MB |
| Camera | OV2640 (2MP) |
bootboots/
├── docs/
│ └── architecture/ # System architecture diagrams (.drawio + .svg)
│
├── embedded/
│ ├── bootloader/ # Factory bootloader (OTA staging)
│ ├── catcam/ # Main camera application
│ │ ├── include/ # Header files
│ │ ├── lib/ # Custom libraries (15+)
│ │ ├── scripts/ # Build and deployment scripts
│ │ └── src/ # Main application source
│ ├── CLAUDE.md # Detailed technical context
│ └── README.md # Embedded firmware documentation
│
├── githooks/ # Git hooks for automation
│
├── infra/ # AWS CDK infrastructure (TypeScript)
│ ├── lib/ # CDK stack definitions
│ └── lambda/ # Lambda function code
│
├── scripts/ # Project-wide utility scripts
│
└── README.md # This file
- Python 3.8+
- PlatformIO CLI
- Node.js and npm (for infrastructure)
- AWS CLI configured with
nakom.is-sandboxprofile - draw.io desktop app (for architecture diagram generation)
- githooks installed using
./scripts/install-hooks.sh
-
Generate secrets from AWS SSM Parameter Store:
cd embedded/catcam export AWS_PROFILE=nakom.is-sandbox python3 scripts/generate_secrets.py
-
Build and flash (USB - for factory-new devices):
cd embedded/catcam ./scripts/factory_setup.sh /dev/cu.usbserial-XXXX
See embedded/README.md for detailed setup instructions.
Once a device is set up, use OTA updates via Bluetooth:
cd embedded/catcam
export AWS_PROFILE=nakom.is-sandbox
python3 scripts/build_and_upload.pyThen use the web interface to push the update to the device via Bluetooth.
The deterrence system includes multiple safety layers to prevent false activations:
- Ultra-safe thresholds - 90%+ confidence required for target cat identification
- Protected cats - Specific cats (e.g., Kappa, index 2) are hardcoded to never trigger deterrents
- False positive prevention - Requires 2+ consecutive positive detections
- Confidence validation - All non-target cats must show <15% confidence
- sandboxsite - React web interface for OTA updates and device control via Web Bluetooth, plus AWS CDK infrastructure (CloudFront, Cognito, S3)
This project is released under CC0 1.0 Universal - public domain dedication.





