Dear All
I had an Arduino program running on ESP32-CAM which send out an image to server by node js every time when I press the tact switch.
The problem is, when I send image data via HTTP Post to server, the server side receive garbage data, and the photo cannot be opened.
When I hard-code the data send to server to be text, the server side receive the data without problem.
The camera and TFT screen itself have no problem, if I press the button on breadboard, it can take picture and show in TFT screen.
Do any one of you know how could I modify my Arduino program to make it work?
I want the server side receive normal data but not garbage data.
I appreciate for your help, I really have no idea on how to correct it.
By my guessing, it seems that the problem occur at client.POST(fb->buf, fb->len); But everyone from the internet is teaching to use this code: int httpResponseCode = client.POST(fb->buf, fb->len);
Thanks.
Here is the Arduino programming code.
#include "esp_camera.h"
#include <TJpg_Decoder.h>
#include <SPI.h>
#include <TFT_eSPI.h>
#include <WiFi.h>
#include <HTTPClient.h>
#include <ArduinoJson.h>
#define PWDN_GPIO_NUM 32
#define RESET_GPIO_NUM -1
#define XCLK_GPIO_NUM 0
#define SIOD_GPIO_NUM 26
#define SIOC_GPIO_NUM 27
#define Y9_GPIO_NUM 35
#define Y8_GPIO_NUM 34
#define Y7_GPIO_NUM 39
#define Y6_GPIO_NUM 36
#define Y5_GPIO_NUM 21
#define Y4_GPIO_NUM 19
#define Y3_GPIO_NUM 18
#define Y2_GPIO_NUM 5
#define VSYNC_GPIO_NUM 25
#define HREF_GPIO_NUM 23
#define PCLK_GPIO_NUM 22
#define GFXFF 1
#define FSB9 &FreeSerifBold9pt7b
TFT_eSPI tft = TFT_eSPI();
const char* ssid = "ABCDE";
const char* password = "12345678";
const unsigned long timeout = 30000; // 30 seconds
const int buttonPin = 4; // the number of the pushbutton pin
void initWiFi() {
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
}
bool tft_output(int16_t x, int16_t y, uint16_t w, uint16_t h, uint16_t* bitmap) {
// Stop further decoding as image is running off bottom of screen
if (y >= tft.height()) return 0;
// This function will clip the image block rendering automatically at the TFT boundaries
tft.pushImage(x, y, w, h, bitmap);
// This might work instead if you adapt the sketch to use the Adafruit_GFX library
// tft.drawRGBBitmap(x, y, bitmap, w, h);
// Return
return 1;
}
void setup() {
Serial.begin(115200);
delay(1000);
Serial.println();
pinMode(buttonPin, INPUT);
Serial.println("INIT DISPLAY");
tft.begin();
tft.setRotation(3);
tft.setTextColor(0xFFFF, 0x0000);
tft.fillScreen(TFT_YELLOW);
tft.setFreeFont(FSB9);
TJpgDec.setJpgScale(1);
TJpgDec.setSwapBytes(true);
TJpgDec.setCallback(tft_output);
Serial.println("INIT CAMERA");
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_sscb_sda = SIOD_GPIO_NUM;
config.pin_sscb_scl = SIOC_GPIO_NUM;
config.pin_pwdn = PWDN_GPIO_NUM;
config.pin_reset = RESET_GPIO_NUM;
config.xclk_freq_hz = 20000000;
config.pixel_format = PIXFORMAT_JPEG;
config.frame_size = FRAMESIZE_QVGA;
config.jpeg_quality = 10;
config.fb_count = 1;
// camera init
esp_err_t err = esp_camera_init(&config);
if (err != ESP_OK) {
Serial.printf("Camera init failed with error 0x%x", err);
return;
}
initWiFi();
}
void buttonEvent() {
//int reading = digitalRead(buttonPin);
if (digitalRead(buttonPin) == HIGH) {
sendingImage();
} else {
showingImage();
}
}
camera_fb_t* capture() {
camera_fb_t* fb = NULL;
esp_err_t res = ESP_OK;
fb = esp_camera_fb_get();
return fb;
}
void showingImage() {
camera_fb_t* fb = capture();
if (!fb || fb->format != PIXFORMAT_JPEG) {
Serial.println("Camera capture failed");
esp_camera_fb_return(fb);
return;
} else {
TJpgDec.drawJpg(0, 0, (const uint8_t*)fb->buf, fb->len);
esp_camera_fb_return(fb);
}
}
void parsingResult(String response) {
DynamicJsonDocument doc(1024);
deserializeJson(doc, response);
JsonArray array = doc.as<JsonArray>();
int yPos = 4;
for (JsonVariant v : array) {
JsonObject object = v.as<JsonObject>();
const char* description = object["description"];
float score = object["score"];
String label = "";
label += description;
label += ":";
label += score;
tft.drawString(label, 8, yPos, GFXFF);
yPos += 16;
}
}
void postingImage(camera_fb_t* fb) {
Serial.print("Picture Height: ");
Serial.print(fb->height);
Serial.println(""); // write the Height
Serial.print("Picture Weidth: ");
Serial.print(fb->width);
Serial.println(""); // write the Width
Serial.print("Picture Size: ");
Serial.print(fb->len);
Serial.println(""); // write the Size
Serial.print("Data Buffer: ");
for (int i = 0; i < fb->len; i++) {
Serial.write(',');
Serial.print(fb->buf[i]);
}
Serial.println();
HTTPClient client;
client.begin("http://192.168.241.182:8888/imageUpdate");
client.addHeader("Content-Type", "image/jpeg");
int httpResponseCode = client.POST(fb->buf, fb->len);
if (httpResponseCode == 200) {
String response = client.getString();
parsingResult(response);
} else {
tft.drawString("Check Your Server!!!", 8, 4, GFXFF);
}
client.end();
}
void sendingImage() {
camera_fb_t* fb = capture();
if (!fb || fb->format != PIXFORMAT_JPEG) {
Serial.println("Camera capture failed");
esp_camera_fb_return(fb);
return;
} else {
TJpgDec.drawJpg(0, 0, (const uint8_t*)fb->buf, fb->len);
postingImage(fb);
esp_camera_fb_return(fb);
}
}
void loop() {
buttonEvent();
}
This is my nodeJS server side script
var fs = require('fs');
const http = require('http');
const server = http.createServer();
const filePath = './resources/test.jpeg';
server.on('request', (request, response)=>{
if(request.method == 'POST' && request.url === "/imageUpdate"){
console.log(`--Trasmission Start--`)
var ImageFile = fs.createWriteStream(filePath, {encoding: 'utf8'});
request.on('data', function(data){
console.log(data.toString())
ImageFile.write(data);
});
request.on('end',async function(){
console.log(`--Trasmission End--`)
ImageFile.end();
const labels = await labelAPI();
response.writeHead(200, {'Content-Type' : 'application/json'});
response.end(JSON.stringify(labels));
});
}else{
console.log("error");
response.writeHead(405, {'Content-Type' : 'text/plain'});
response.end();
}
});
async function labelAPI() {
var o = [];
// Imports the Google Cloud client library
const vision = require('@google-cloud/vision');
// Creates a client
const client = new vision.ImageAnnotatorClient();
// Performs label detection on the image file
const [result] = await client.labelDetection(filePath);
const labels = result.labelAnnotations;
labels.forEach(label => {
o.push({description: label.description, score: label.score});
});
return o;
}
const port = 8888;
server.listen(port)
console.log(`Listening at ${port}`)