RearSight: a Smart Keychain That Watches Your Back

by ayushmaan45 in Circuits > Cameras

2576 Views, 35 Favorites, 0 Comments

RearSight: a Smart Keychain That Watches Your Back

20260316_165356.jpg
20260316_165340(0).jpg
20260316_165019.jpg

Hi, I’m Ayushmaan, a B.Tech student studying Electrical and Electronics Engineering in India. I like working on electronics projects, especially the kind that try to solve small everyday problems.

One thing that a lot of people have probably experienced is that uncomfortable feeling that someone might be following you while you’re walking alone, particularly at night. Even if nothing is actually happening, it still makes you check behind you again and again. The problem is that when you're walking, you can't really keep looking back all the time, and you can't see what’s happening behind you unless you turn around.

That thought is what gave me the idea for this project.

I wanted to build something small that could keep an eye on the area behind the user and let them know if something seemed unusual. The result is a small keychain device that uses a camera to monitor what’s behind you and sends a notification to your phone if someone stays in the camera view for too long.

The project is built around the DFRobot ESP32-CAM Development Board, which is a really handy board because it already has both a microcontroller and a camera on it. That makes it possible to run face detection directly on the device without needing any additional hardware.

The ESP32 also hosts a simple webpage with a live camera feed, so you can open it on your phone and see exactly what the camera is seeing. Another useful feature is that the camera can still work in low-light conditions, which means the device can continue monitoring even when it’s dark.

In the end, the goal of this project was just to create something small, practical, and interesting to build. By combining face detection, live video streaming, phone notifications, and night-vision capability in a compact design, the device works as a small keychain gadget that can help keep an eye on what’s happening behind you.


Supplies

20260315_200539.jpg


  1. DFRobot ESP32-S3 AI Camera
  2. TP4056 charging module
  3. Li-ion battery
  4. Step-down voltage regulator module
  5. MT3608 DC‑DC Step‑Up Boost Converter Module
  6. 6-pin square tactile push button
  7. Jumper wires
  8. 3D-printed enclosure

Sketching the Design

InShot_20260317_090445767.gif
WhatsApp Image 2026-03-14 at 1.27.59 PM.jpeg
download.jpg

Before starting the 3D model, I first sketched a rough design of the keychain on paper. This helped me visualize how the device should look and where the main components would fit.

I started by looking at a few reference images to get an idea of the overall shape and size that would work well for a keychain device. Since the DFRobot ESP32-S3 AI Camera already has a fixed camera position, I made sure the front of the design would leave space for the camera lens.

After that, I drew a simple sketch showing the basic shape of the enclosure and how the internal components might be arranged. This step helped me decide the approximate dimensions before moving on to the CAD model.

3D Modelling and Printing

20260315_185914.jpg
20260315_185940.jpg
20260315_184947(1).jpg

Once the idea was clear, I recreated the design using Autodesk Fusion 360 and prepared the parts for 3D printing.

The enclosure is made of multiple parts:

  1. 1x Front Plate (main body with the camera opening for the ESP32 camera module)
  2. 1x Back Plate (holds the battery, TP4056 charging module, step-up module, and the switch)
  3. 10x Decorative Add-Ons (these are pasted onto the front plate to complete the design)

For printing, I used different PLA colors to give the keychain a better look:

  1. Front Plate: printed using red PLA
  2. Back Plate: printed using black PLA
  3. Decorative Add-Ons: printed using black PLA

After printing all the parts, the decorative add-ons were attached to the front plate, the electronics were mounted on the back plate, and finally both plates were assembled together to complete the enclosure.

Downloads

Attaching the Decorative Add-Ons

20260315_193326.jpg
InShot_20260317_100924747.gif
20260315_185914.jpg

After printing all the parts, the next step was to attach the decorative pieces to the front plate.

The design includes 10 small add-on parts that are placed on top of the main front print to complete the final look of the keychain. These pieces were printed separately and then attached to the front plate.

To fix them in place, I used superglue. A small drop of glue was applied to each piece, and then it was carefully placed in its position on the front plate. Since the parts are small, it’s important to align them properly before the glue dries.

Circuit

20260315_210229(0).jpg
20260315_215301.jpg

The circuit for this project is quite simple. The Li-ion battery powers the device through the TP4056 charging module, and the output is regulated using the MT3608 DC-DC Step-Up Boost Converter Module before powering the DFRobot ESP32-S3 AI Camera.

A 6-pin tactile push button is used as the power switch for the device.

The complete wiring can be seen in the circuit diagram..


Assembling the Electronics

20260315_222619.jpg
20260315_220314.jpg
20260315_222531.jpg
20260315_223110(0).jpg

After completing the circuit connections, the next step is placing all the components inside the enclosure.

The Li-ion battery, TP4056 charging module, MT3608 step-up module, and the switch are mounted on the back plate, which was designed to hold these components in place. The DFRobot ESP32-S3 AI Camera is positioned in the front plate, with the camera lens aligned with the opening in the enclosure.

Once everything is placed properly, the wires are arranged neatly to fit inside the case, and the front and back plates are joined together to complete the assembly of the keychain device.

Adding the Final Touch

20260316_164819.jpg
20260316_164622.jpg
WhatsApp Image 2026-03-17 at 9.39.00 AM.jpeg
20260316_164744.jpg

To make the device easier to carry, I added a small carabiner to the keychain loop of the enclosure. This allows the device to be clipped onto a backpack, belt loop, or bag.

The carabiner I used was taken from a project made by Arnov Sharma, called SolMate. It fit perfectly with the design and made the keychain much more practical to use.

With the carabiner attached, the device can now be easily clipped and carried wherever needed.

System Overview (Block Diagram)

The project is divided into three main parts: the camera unit, the processing system, and the user interface.

The camera unit is built using the DFRobot ESP32-S3 AI Camera, which captures images from behind the user and sends them over WiFi.

These images are received by a Python-based server, where face detection is performed. The system then checks if a person remains in the frame for a certain duration to determine if someone might be following.

Finally, the processed data is displayed on a web dashboard, and alerts are sent to the user when needed.

In simple terms, the flow of the system is:

ESP32 Camera → Server Processing → Detection Logic → Web Dashboard + Alerts

ESP32 Camera Setup and Data Transmission

In this step, the ESP32 is configured to initialize the camera, connect to WiFi, and capture image frames that are sent to the server.

1. Camera Initialization

The camera is configured using the pin definitions specific to the DFRobot ESP32-S3 AI Camera.


#define Y2_GPIO_NUM 16
#define Y3_GPIO_NUM 18
#define Y4_GPIO_NUM 21
#define Y5_GPIO_NUM 17
#define Y6_GPIO_NUM 14
#define Y7_GPIO_NUM 7
#define Y8_GPIO_NUM 6
#define Y9_GPIO_NUM 4

The camera configuration is set using the camera_config_t structure:


camera_config_t config;

config.ledc_channel = LEDC_CHANNEL_0;
config.ledc_timer = LEDC_TIMER_0;

config.pin_d0 = Y2_GPIO_NUM;
config.pin_d1 = Y3_GPIO_NUM;
config.pin_d2 = Y4_GPIO_NUM;
config.pin_d3 = Y5_GPIO_NUM;
config.pin_d4 = Y6_GPIO_NUM;
config.pin_d5 = Y7_GPIO_NUM;
config.pin_d6 = Y8_GPIO_NUM;
config.pin_d7 = Y9_GPIO_NUM;

config.pin_xclk = XCLK_GPIO_NUM;
config.pin_pclk = PCLK_GPIO_NUM;
config.pin_vsync = VSYNC_GPIO_NUM;
config.pin_href = HREF_GPIO_NUM;

config.pin_sccb_sda = SIOD_GPIO_NUM;
config.pin_sccb_scl = SIOC_GPIO_NUM;

config.pixel_format = PIXFORMAT_JPEG;
config.frame_size = FRAMESIZE_QQVGA;
config.fb_count = 1;

The camera is then initialized using:


esp_camera_init(&config);

2. WiFi Connection

The ESP32 connects to the WiFi network using:


WiFi.begin(ssid, password);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
}

Once connected, the IP address is printed to the Serial Monitor.

3. Capturing Image Frames

Inside the loop, frames are captured using:


camera_fb_t *fb = esp_camera_fb_get();

This returns a frame buffer containing the image data.

4. Sending Data to Server

The captured image is sent to the server using an HTTP POST request:


HTTPClient http;

http.begin("http://YOUR_PC_IP:5000/detect");
http.addHeader("Content-Type", "application/octet-stream");

http.POST(fb->buf, fb->len);
http.end();

Here:

  1. fb->buf → image data
  2. fb->len → size of image

5. Releasing Frame Buffer

After sending the data, the buffer is released:


esp_camera_fb_return(fb);

Final Flow

Capture Frame → Send to Server → Release Buffer → Repeat


Python Server (Face Detection and Push Notification)

In this step, the Python server receives image frames from the ESP32, performs face detection, and triggers a Pushbullet notification when a person is detected continuously.

1. Setting Up the Server

The backend is created using Flask:


from flask import Flask, request
import face_recognition
import numpy as np
from PIL import Image
import io
import time
import requests

app = Flask(__name__)

2. Pushbullet Configuration

Add your Pushbullet access token:


PUSH_TOKEN = "YOUR_PUSHBULLET_ACCESS_TOKEN"

Function to send notification:


def send_push(message):
url = "https://api.pushbullet.com/v2/pushes"

headers = {
"Access-Token": PUSH_TOKEN,
"Content-Type": "application/json"
}

data = {
"type": "note",
"title": "RearSight Alert",
"body": message
}

requests.post(url, json=data, headers=headers)

3. Receiving Image from ESP32

The ESP32 sends image data as raw bytes:


@app.route('/detect', methods=['POST'])
def detect():
image_bytes = request.data

Convert image:


image = Image.open(io.BytesIO(image_bytes))
frame = np.array(image)

4. Face Detection

Faces are detected using:


face_locations = face_recognition.face_locations(frame)

5. Time-Based Detection Logic

The system checks if a face remains in the frame for a specific duration:


global last_detect_time, alert_triggered

if len(face_locations) > 0:
if last_detect_time is None:
last_detect_time = time.time()

if time.time() - last_detect_time > 10 and not alert_triggered:
alert_triggered = True
send_push("Person detected behind you!")

Reset when no face is detected:


else:
last_detect_time = None
alert_triggered = False

6. Storing Latest Frame

For dashboard display:


global latest_frame
latest_frame = image_bytes

7. Response to ESP32


return {"faces": len(face_locations)}

Final Flow

Receive Image → Detect Face → Check Duration → Trigger Pushbullet Alert → Store Frame


Downloads

Web Dashboard (Frontend and API Integration)

Screenshot 2026-03-17 163202.png

In this step, a web dashboard is used to display the camera feed, detection status, and alerts in real time. The frontend communicates with the Python server using API endpoints.

1. Basic HTML Structure

The dashboard is created using a simple HTML layout:


<!DOCTYPE html>
<html>
<head>
<title>RearSight Dashboard</title>
<style>
body {
background: black;
color: white;
text-align: center;
}
img {
width: 80%;
border-radius: 10px;
}
.status {
font-size: 20px;
margin-top: 10px;
}
</style>
</head>

2. Displaying Live Frame

The latest processed frame is fetched from the server:


<body>

<h2>RearSight Dashboard</h2>

<img src="/latest_frame" id="feed">

<div class="status" id="status">
Monitoring...
</div>

3. Fetching Detection Status

The dashboard uses JavaScript to fetch data from the server:


<script>
setInterval(() => {
fetch('/api/status')
.then(res => res.json())
.then(data => {
document.getElementById("status").innerText =
"Faces Detected: " + data.faces_detected;
});
}, 2000);
</script>

4. Updating Image Feed

To refresh the latest frame:


<script>
setInterval(() => {
document.getElementById("feed").src =
"/latest_frame?time=" + new Date().getTime();
}, 1000);
</script>

5. Backend API (Python Side)

The dashboard depends on these endpoints:

Status API


@app.route('/api/status')
def status():
return {
"faces_detected": last_faces
}

Latest Frame


@app.route('/latest_frame')
def latest_frame_route():
return send_file(
io.BytesIO(latest_frame),
mimetype='image/jpeg'
)

Final Flow

ESP32 → Server → API → Web Dashboard → Live Updates


Final Thoughts

And that’s RearSight.

A small keychain device that can keep an eye on what’s happening behind you. Using the DFRobot ESP32-S3 AI Camera, the system can detect faces, send a notification to your phone, and allow you to check the live camera feed whenever needed. The camera also works in low-light conditions, so it can continue monitoring even at night.

The goal of this project was to see how much functionality could be packed into such a small device. It turned out to be a fun build and a great example of how powerful small AI-enabled boards have become.

That said, the current version does have a few limitations. For example, the system may face some issues in very crowded areas where multiple faces appear in the camera view. Improving the detection logic and making the system more reliable in such situations is something I plan to explore in future versions of the project.