I have a Kodular (Android) App that posts images and related data to Node-Red.
Both image and data arrive as payload.
I also have a html script that does the same (script below) and works perfectly.
Now I would like to use ESP32CAM to post images and related data to the same Node-Red flow.
Image and data actually arrive at Node-Red but instead of arriving as msg.payload they arrives as msg.req.headers(for the data) and msg.req.files[0].buffer (for the image).
HTML script (works OK image and data inside msg.payload)
<!DOCTYPE html>
<html lang="">
<head>
<link rel="icon" type="image/x-icon" href="http://alprbr.com/images/car.png">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>ALPRBRAPI</title>
</head>
<body onload='startFunc()'>
<form id="myForm">
<table align='center' style="border-collapse: collapse;" border="1">
<tbody>
<tr><td align="center"><font size = "5"><b>Leitura de Placas Direto ALPRBR</b></font><br>
Escolher imagem onde apareça legĂvel a placa de um veĂculo:<br>
PadrĂŁo Mercosul: LLLNLNN, padrĂŁo antigo LLL-NNNN</td></tr>
<tr><td align='center'>
<input id="inpFile" type="file" accept="image/jpeg, image/png, image/jpg" onclick='enableUpload()'>
<button id='btn_uploadfile' name='btn_uploadfile' type="submit">Enviar</button>
</td></tr>
<tr><td align='center'>Seu Token: <input id="myToken" name="myToken" minlength='32' maxlength='32'>
<a href="https://alprbr.com/signup.html" title="Cadastro de Usuários">Não Tenho</a>
<br>Incluir Dados do VeĂculo?
<input id="vehicledata" type="checkbox" checked />
</td></tr>
<tr><td align="center"><img src="#" id="localImage" width="400"></td></tr>
<tr><td align='center'>
<table align='center' style="border-collapse: collapse;" border="1" width="100%">
<tbody>
<tr><td><b>Créditos</b></td>
<td><label id='credits'> </label></td></tr>
<tr><td><b>Placa</b></td><td><label id='property'></label></td></tr>
<tr><td><b>Chassi_final</b></td><td><label id='chassi_final'></label></td></tr>
<tr><td><b>Cidade</b></td><td><label id='cidade'></label></td></tr>
<tr><td><b>Estado</b></td><td><label id='uf'></label></td></tr>
<tr><td><b>Marca</b></td><td><label id='marca'></label></td></tr>
<tr><td><b>Modelo</b></td><td><label id='modelo'></label></td></tr>
<tr><td><b>Ano</b></td><td><label id='ano'></label></td></tr>
<tr><td><b>Cor</b></td><td><label id='cor'></label></td></tr>
<tr><td><b>Situação</b></td>
<td><label id="situacao"></label></td></tr>
</tbody>
</table>
</td></tr>
</tbody></table>
</form>
<div align="center" id="myData" name="myData"></div>
<script>
var token='';
var vehicledata = "true";
const checkbox = document.getElementById('vehicledata')
checkbox.addEventListener('change', (event) => {
if (event.target.checked) {
vehicledata = "true";
} else {
vehicledata = "false";
}
})
const imgInput = document.querySelector('input')
const imgEl = document.querySelector('img')
function enableUpload(){document.getElementById("btn_uploadfile").disabled = false;}
function startFunc(){
document.getElementById('localImage').style.visibility = 'hidden';
}
imgInput.addEventListener('change', () => {
if (imgInput.files && imgInput.files[0]) {
const reader = new FileReader();
reader.onload = (e) => {
imgEl.src = e.target.result;
}
reader.readAsDataURL(imgInput.files[0]);
document.getElementById('localImage').style.visibility = 'visible';
document.getElementById("credits").innerHTML = ' ';
document.getElementById("property").innerHTML = '';
document.getElementById("chassi_final").innerHTML = '';
document.getElementById("cidade").innerHTML = '';
document.getElementById("uf").innerHTML = '';
document.getElementById("marca").innerHTML = '';
document.getElementById("modelo").innerHTML = '';
document.getElementById("ano").innerHTML = '';
document.getElementById("cor").innerHTML = '';
document.getElementById("situacao").innerHTML = '';
}
})
const myForm = document.getElementById("myForm");
const inpFile = document.getElementById("inpFile");
myForm.addEventListener("submit", e => {
token = document.getElementById('myToken').value;
token = token.replace(/\s/g, '');
if (token.length<32){
alert("Token não pode conter espaços.");
document.getElementById('myToken').focus();
return;
}
document.getElementById('btn_uploadfile').innerHTML = 'Processando, Aguarde...';
document.getElementById("btn_uploadfile").disabled = true;
e.preventDefault();
const endpoint = "http://alprbr.com:30300/alprbr";
const form_data = new FormData();
console.log(inpFile.files);
form_data.append("inpFile", inpFile.files[0]);
form_data.append("countrycode","br");
form_data.append("token",token);
form_data.append("vehicledata",vehicledata);
form_data.append("imageurl","");
fetch(endpoint, {method: "post", body: form_data })
.then(function (response) {
return response.json();
})
.then(function (data) {
appendData(data);
})
.catch(function (err) {
console.log('erro: ' + err);
document.getElementById('btn_uploadfile').innerHTML = 'Enviar';
});
function appendData(data) {
document.getElementById("credits").innerHTML = data.credits;
document.getElementById("property").innerHTML = data.property;
document.getElementById("chassi_final").innerHTML = data.chassi_final;
document.getElementById("cidade").innerHTML = data.cidade;
document.getElementById("uf").innerHTML = data.uf;
document.getElementById("marca").innerHTML = data.marca;
document.getElementById("modelo").innerHTML = data.modelo;
document.getElementById("ano").innerHTML = data.ano;
document.getElementById("cor").innerHTML = data.cor;
document.getElementById("situacao").innerHTML = data.situacao;
document.getElementById('btn_uploadfile').innerHTML = 'Enviar';
}
});
</script>
</body>
</html>
Below is the function of the ESP32CAM sketch that posts image and data to Node-Red but arrive in the wrong place:
The image arrives at: msg.req.files[0].buffer
and the data: msg.req.headers.countrycode, msg.req.headers.token, etc...
Question:
What must change at the ESP32CAM sketch below so all those variable and image that are under msg.req. are arriving under msg.peyload. ?
String postImage() { //post image directly to ALPRBR_API no storage
String getAll;
String getBody;
camera_fb_t * fb = NULL;
fb = esp_camera_fb_get();
if(!fb) {
Serial.println("Camera capture failed");
delay(1000);
ESP.restart();
}
Serial.println("Connecting to server: " + preferences.getString("serverName"));
preferences.begin("AppParms", true);
if (client.connect(preferences.getString("serverName").c_str(), preferences.getString("serverPort").toInt())) {
Serial.println("Connection successful!");
String head = "--ALPRBR\r\nContent-Disposition: form-data; name=\"imageFile\"; filename=\"esp32-cam.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";
String tail = "\r\n--ALPRBR--\r\n";
uint32_t imageLen = fb->len;
uint32_t extraLen = head.length() + tail.length();
uint32_t totalLen = imageLen + extraLen;
client.println("POST " + preferences.getString("serverPath") + " HTTP/1.1");
client.println("Host: " + preferences.getString("serverName"));
client.println("Content-Length: " + String(totalLen));
client.println("Content-Type: multipart/form-data; boundary=ALPRBR");
client.println("token: " + preferences.getString("token"));
client.println("countrycode: " + preferences.getString("countrycode"));
client.println("vehicledata: true");
client.println("imageurl: ESP32CAM");
client.println();
client.print(head);
uint8_t *fbBuf = fb->buf;
size_t fbLen = fb->len;
for (size_t n=0; n<fbLen; n=n+1024) {
if (n+1024 < fbLen) {
client.write(fbBuf, 1024);
fbBuf += 1024;
}
else if (fbLen%1024>0) {
size_t remainder = fbLen%1024;
client.write(fbBuf, remainder);
}
}
client.print(tail);
esp_camera_fb_return(fb);
int timoutTimer = 10000;
long startTimer = millis();
boolean state = false;
while ((startTimer + timoutTimer) > millis()) {
Serial.print(".");
delay(100);
while (client.available()) {
char c = client.read();
if (c == '\n') {
if (getAll.length()==0) { state=true; }
getAll = "";
}
else if (c != '\r') { getAll += String(c); }
if (state==true) { getBody += String(c); }
startTimer = millis();
}
if (getBody.length()>0) { break; }
}
Serial.println();
client.stop();
Serial.println(getBody);
}
else {
getBody = "Connection to " + String(preferences.getString("serverName")) + " failed.";
Serial.println(getBody);
}
preferences.end();
return getBody;
}