Video Tutorial (Optional)
Watch first if you want to follow the full Raspberry Pi + MQTT + React Native (Expo) build end to end.
Prerequisites: Watch these first.
Part 1:
Part 2:
Project Overview
Raspberry Pi + Pi Camera + MQTT + React Native (Expo): In this project, you use a Raspberry Pi with a camera module to capture images on command via MQTT, then deliver the image to a React Native Expo app through a Node.js backend.
This pattern can be extended into other full-stack IoT applications where a mobile UI triggers device actions and receives results in real time.
- Time: Varies (depends on your Mosquitto, AWS, and Expo setup)
- Skill level: Intermediate
- What you will build: A Raspberry Pi camera capture flow controlled by MQTT, with a Node.js API that returns a Base64 image to a React Native Expo frontend
Resources mentioned in the original tutorial: Subscribe on Youtube. Support link: https://www.buymeacoffee.com/mmshilleh. Interactive version and downloads: https://share.razzl.com/xWn7.
Parts List
From ShillehTek
- No ShillehTek product links were provided in the original article.
External
- Raspberry Pi
- Raspberry Pi camera module (attached directly to the Pi)
- MQTT broker (Mosquitto on the Raspberry Pi, referenced in Part 1 video)
- AWS S3 bucket (used for image storage and retrieval)
- Node.js + Express backend
- React Native Expo environment
- MQTT client library (used by the Pi and Node.js)
- Python libraries: picamera and boto3
- Axios (used by the React Native frontend)
Note: You must replace all placeholders in the scripts with your real MQTT broker details, MQTT topics, AWS credentials, and S3 bucket settings. Keep AWS keys private.
Step-by-Step Guide
Step 1 - Watch the prerequisite videos (Parts 1 and 2)
Goal: Make sure your Raspberry Pi environment is ready, including MQTT (Mosquitto) setup.
What to do: Watch Part 1 and Part 2 of the tutorial series before continuing with this build.
Expected result: You understand the MQTT broker setup and the overall data flow used in this project.
Step 2 - Attach the camera to the Raspberry Pi
Goal: Create the physical setup used for image capture.
What to do: Attach the camera module to the Raspberry Pi (the tutorial uses a simple setup with only the camera connected to the Pi).
Expected result: The Raspberry Pi is physically ready to capture images from the attached camera.
Step 3 - Create the Raspberry Pi scripts for MQTT capture triggering and S3 upload
Goal: Make the Raspberry Pi listen for an MQTT command, capture an image, upload it to S3, and publish the resulting object key.
What to do: On the Raspberry Pi, create and use these two Python files (as shown in the tutorial):
- mqtt_subscriber.py: subscribes to an MQTT topic (for example, your/command/channel). When it receives the message Yes, it triggers image capture by calling the capture function from the external module.
- s3_example.py: captures images using PiCamera and uploads them to an AWS S3 bucket, then publishes the S3 object key to an MQTT result topic (for example, your/result/channel).
In the capture module, the tutorial includes:
- capture_image: captures a still image
- capture_video: included but commented out (optional)
- upload_to_s3: uploads the captured file to S3
- Main capture function: captures an image, uploads to S3, then publishes the S3 key to the result topic
Install required libraries on the Pi (as stated in the tutorial):
pip install picamera boto3
Expected result: The Raspberry Pi can listen for a capture command, take a photo, upload to S3, and publish the S3 key to the MQTT result channel.
Step 4 - Run the Raspberry Pi MQTT subscriber and trigger a capture
Goal: Confirm the Raspberry Pi is actively listening for capture commands.
What to do: Run mqtt_subscriber.py on the Raspberry Pi so it continuously listens for capture commands.
From an MQTT publisher (used later by the backend), publish Yes to your/command/channel to trigger the capture.
Expected result: The Pi captures and uploads an image, then publishes the S3 object key to your/result/channel.
Step 5 - Build the Node.js backend to coordinate MQTT and return the image
Goal: Expose an HTTP endpoint that triggers capture via MQTT, waits for the Pi result, fetches the image from S3, and returns it to the client.
What to do: Create a Node.js (Express) server with an endpoint /takePhoto that does the following (as described in the tutorial):
- Creates a local write stream to save an image file (for example, image.jpg).
- Connects to your MQTT broker (mqttBrokerAddress).
- Subscribes to a result channel (mqttSubscribeChannel).
- Publishes Yes to the capture command channel (mqttPublishChannel).
- On receiving the S3 key via MQTT: unsubscribes from the result channel, retrieves the object from S3, and writes it to the local file.
- Converts the image data to Base64 and returns JSON back to the client.
- Handles errors by logging and returning appropriate HTTP status codes.
The tutorial notes:
- The Express server listens on port 3000 (you can change it).
- Replace MQTT broker address and topic values with your own.
- Replace dummy AWS credentials with real IAM credentials and keep them private.
Expected result: Sending a request to /takePhoto triggers MQTT capture and returns a JSON response containing a Base64-encoded image.
Step 6 - Build the React Native Expo frontend to request and display the image
Goal: Create a simple mobile UI that calls the backend and displays the received photo.
What to do: In a React Native Expo app:
- Use Axios to send a GET request to the backend endpoint /takePhoto.
- Show an activity indicator while the request and capture are in progress.
- Render the returned Base64 image using the React Native Image component.
- Make sure Expo is installed and create a project using expo init before copying in the app code.
- Install required npm packages before running.
Expected result: The Expo app triggers photo capture through the backend and then displays the received Base64 image in the UI.
Conclusion
You built a React Native Expo application that requests a photo from a Raspberry Pi camera using MQTT, with a Node.js backend that retrieves the image from AWS S3 and returns it as Base64. This is a flexible starting point you can extend with additional app features and custom UI styling.
Want parts and modules for your next build? Shop at ShillehTek.com. If you want help tailoring this Raspberry Pi + MQTT workflow to your product or deployment, check out our IoT consulting services.