In our previous post we created a Next.js 14 API example code for QR code decoding. This simple esp32 QR code scanner example converts ESP32-cam image to base64 encoding and send to next.js API for QR code decoding. Now we are going to consume that API end point in our ESP32-CAM. The main challenges are that, how to capture the image? How to convert that image into the base64 encoding in Arduino environment? How to send that base64 encoded string to the API end point and do the detection? How to fetch the response and display the results. So, let’s do this step by step.
ESP32-CAM Image Capture
If you had seen the previous codes of the ESP32-CAM, the taking picture seems too much scary and there are lot of verbose. Fortunately, there is a library which tackle this problem and simplify the image capture process easy. There is object detection example on internet where the esp32-cam is used as ip camera and the python code is doing the object detection and displaying the results on laptop. That example use that library and make the image capture process easy. We will use that part of code but instead of serving the image as HTTP Server, we are doing the reverse thing which is to send that image to some remote server.
First download the library form GitHub. Install that library by putting the unzipped code under the Arduino -> Sketch -> Include Library -> Add .ZIP Library… -> Navigate to downloaded zip file -> add.
Once installed, now you are ready to capture the image in most easiest way.
#include <WiFi.h>
#include <esp32cam.h>
const char* WIFI_SSID = "project";
const char* WIFI_PASS = "project123";
static auto loRes = esp32cam::Resolution::find(320, 240);
static auto midRes = esp32cam::Resolution::find(350, 530);
static auto hiRes = esp32cam::Resolution::find(800, 600);
void easyCapture(){
auto frame = esp32cam::capture();
if (!frame) {
Serial.println("CAPTURE FAIL");
return;
}
Serial.printf("CAPTURE OK %dx%d %db\n", frame->getWidth(), frame->getHeight(),
static_cast<int>(frame->size()));
}
void setup() {
Serial.begin(115200);
Serial.println();
{
using namespace esp32cam;
Config cfg;
cfg.setPins(pins::AiThinker);
cfg.setResolution(hiRes);
cfg.setBufferCount(2);
cfg.setJpeg(80);
bool ok = Camera.begin(cfg);
Serial.println(ok ? "CAMERA OK" : "CAMERA FAIL");
}
WiFi.persistent(false);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(500);
}
Serial.println("connected");
Serial.print("http://");
Serial.println(WiFi.localIP());
easyCapture();
}
void loop() {
// put your main code here, to run repeatedly:
}
Code language: Arduino (arduino)
ESP32 Base64 Encoding of Image
Now it is time to convert the image to base64 encoding in our ESP32. You need to install the base64.h library for this purpose which could be used to convert the data to base64 encoding. In our case, we have to convert the image to base64 encoding and we are printing that to serial terminal which we later used to verify if the image is valid. Here is the code to convert the image to base64 and then printing to serial port.
#include <WebServer.h>
#include <WiFi.h>
#include <esp32cam.h>
#include "Base64.h"
const char* WIFI_SSID = "project";
const char* WIFI_PASS = "project123";
static auto loRes = esp32cam::Resolution::find(320, 240);
static auto midRes = esp32cam::Resolution::find(350, 530);
static auto hiRes = esp32cam::Resolution::find(800, 600);
void imageToBase64() {
auto frame = esp32cam::capture();
if (!frame) {
Serial.println("CAPTURE FAIL");
return;
}
Serial.printf("CAPTURE OK %dx%d %db\n", frame->getWidth(), frame->getHeight(),
static_cast<int>(frame->size()));
// Encode image data to base64 (optional)
String imageData = base64::encode((const uint8_t*)frame->data(), frame->size());
Serial.println("");
Serial.println(imageData);
}
void setup() {
Serial.begin(115200);
Serial.println();
{
using namespace esp32cam;
Config cfg;
cfg.setPins(pins::AiThinker);
cfg.setResolution(hiRes);
cfg.setBufferCount(2);
cfg.setJpeg(80);
bool ok = Camera.begin(cfg);
Serial.println(ok ? "CAMERA OK" : "CAMERA FAIL");
}
WiFi.persistent(false);
WiFi.mode(WIFI_STA);
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) {
Serial.print('.');
delay(500);
}
Serial.println("connected");
Serial.print("http://");
Serial.println(WiFi.localIP());
imageToBase64();
}
void loop() {
// put your main code here, to run repeatedly:
}
Code language: Arduino (arduino)
This code will take an image on power reset, and convert it to base64 encoding and print that base64 string to serial terminal. You can copy that base64 string and use this online tool to view the base64 image . Here is the output in my case.
API call with Base64 Encoded Image
Now that we are sure that our ESP32-CAM is working and capturing the images, and we also converted that image to base64 successfully. We are ready to send it to our Next.js API for QR code scanning from ESP32-CAM. For that, we can simply use the HTTP client to send data as POST request to the server. Here is the code for this.
#include <WiFi.h>
#include <esp32cam.h>
#include <WiFiClientSecure.h>
#include <HTTPClient.h>
#include "Base64.h"
const char* WIFI_SSID = "project";
const char* WIFI_PASS = "project123";
static auto loRes = esp32cam::Resolution::find(320, 240);
static auto midRes = esp32cam::Resolution::find(350, 530);
static auto hiRes = esp32cam::Resolution::find(800, 600);
// The API endpoint
const char* serverName = "http://192.168.210.25:3000/api";
// Function to capture image and encode it in base64
String captureImageAndEncodeBase64() {
auto frame = esp32cam::capture();
if (!frame) {
Serial.println("CAPTURE FAIL");
return "";
}
Serial.printf("CAPTURE OK %dx%d %db\n", frame->getWidth(), frame->getHeight(),
static_cast<int>(frame->size()));
// Encode image data to base64 (optional)
String imageBase64 = base64::encode((const uint8_t*)frame->data(), frame->size());
Serial.println("");
Serial.println(imageBase64);
return imageBase64;
}
// Function to send the base64 image to the API endpoint
void sendImageToAPI(String base64Image) {
if (WiFi.status() == WL_CONNECTED) {
HTTPClient http;
http.begin(serverName); // Specify the URL
http.addHeader("Content-Type", "application/json");
// Create the JSON object
String jsonPayload = "{\"img\":\"" + base64Image + "\"}";
// Send the request
int httpResponseCode = http.POST(jsonPayload);
// Check the response
if (httpResponseCode > 0) {
String response = http.getString();
Serial.println(httpResponseCode);
Serial.println(response);
} else {
Serial.print("Error on sending POST: ");
Serial.println(httpResponseCode);
}
http.end(); // Free resources
} else {
Serial.println("WiFi Disconnected");
}
}
// Function to connect to WiFi
void connectToWiFi() {
Serial.print("Connecting to WiFi");
WiFi.begin(WIFI_SSID, WIFI_PASS);
while (WiFi.status() != WL_CONNECTED) {
delay(1000);
Serial.print(".");
}
Serial.println();
Serial.println("Connected to WiFi");
}
void sendImageToApi() {
auto frame = esp32cam::capture();
if (!frame) {
Serial.println("CAPTURE FAIL");
return;
}
Serial.printf("CAPTURE OK %dx%d %db\n", frame->getWidth(), frame->getHeight(),
static_cast<int>(frame->size()));
// Encode image data to base64 (optional)
String imageData = base64::encode((const uint8_t*)frame->data(), frame->size());
Serial.println("");
Serial.println(imageData);
}
void setup() {
Serial.begin(115200);
Serial.println();
{
using namespace esp32cam;
Config cfg;
cfg.setPins(pins::AiThinker);
cfg.setResolution(hiRes);
cfg.setBufferCount(2);
cfg.setJpeg(80);
bool ok = Camera.begin(cfg);
Serial.println(ok ? "CAMERA OK" : "CAMERA FAIL");
}
WiFi.persistent(false);
WiFi.mode(WIFI_STA);
connectToWiFi();
Serial.println("connected");
Serial.print("http://");
Serial.println(WiFi.localIP());
// Capture and send the image
String base64Image = captureImageAndEncodeBase64();
if (base64Image != "") {
sendImageToAPI(base64Image);
}
//sendImageToApi();
}
void loop() {
// put your main code here, to run repeatedly:
}
Code language: Arduino (arduino)
Here is the result on the serial terminal.
As you can see we are successfully fetching the qr code result in our response.