ESP32-CAM with SIM7600 HTTP POST image

Hi everyone,

I am trying to send images captured on the ESP32CAM over HTTP to my backend web server.
I am using the tinyGSM library.

Initially, I tried sending the image over by chunking the writes into chunks below 1500 (which is the max RX buffer for the SIM7600) however after sending a total of ~10,000 bytes it would fail and get an unhandled write. This was consistent and would always fail around ~10,000 bytes. I.e removing the authorisation write would make it fail at ~9,990 bytes into the image, but if I added it back it in it would fail 9940 bytes into the image. This suggests to me that the SIM7600 has an internal buffer ( altho I'm not 100% sure on this)

This was the code

    HTTPResponse PostImage(const char *host, const char *resource, int port, const char *uuid, uint8_t *payload, size_t length)
    {
        if (!client.connected())
            ConnectToAPI(host, port);

        Serial.println(String("Img Length: ") + length);

        String head = "----boundary\r\nContent-Disposition: form-data; name=\"image\"; filename=\"PotWatcherImage.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";
        String tail = "\r\n----boundary--\r\n";
        // Make a HTTP GET request:
        Serial.println("Performing HTTP POST request...");
        client.print(String("POST ") + resource + " HTTP/1.1\r\n");
        client.print(String("Host: ") + host + "\r\n");
        // client.print(String("Authorization: ") + uuid + "\r\n");
        // client.println("Connection: Keep-Alive");
        client.println("Content-Length: " + String(length + head.length() + tail.length()));
        client.println("Content-Type: multipart/form-data;boundary=--boundary");
        client.println();
        client.print(head);

        //"K;␚i@"

        uint8_t *fbBuf = payload;
        for (size_t n = 0; n < length; n = n + PACKET_SIZE)
        {
            if (n > 9900 && n < 10000)
            {
                Serial.println(n);
                Serial.println();
                Serial.println("====");
            }
            client.flush();
            if (n + PACKET_SIZE < length)
            {
                client.write(fbBuf, PACKET_SIZE);
                fbBuf += PACKET_SIZE;
            }
            else if (length % PACKET_SIZE > 0)
            {
                size_t remainder = length % PACKET_SIZE;
                client.write(fbBuf, remainder);
            }
        }

        client.flush();
        client.print(tail);

        HTTPResponse res;
        for (int l = 0; client.connected(); l++)
        {
            // Reading headers line by line.
            String line = client.readStringUntil('\n');
            // Parse status and statusText from line 1.
            if (l == 0)
            {
                // Serial.println(line);
                res.status = line.substring(line.indexOf(" ")).substring(0, line.indexOf(" ")).toInt();
                res.statusText = line.substring(line.indexOf(String(res.status)) + 4);
                res.statusText.trim();
                continue;
            }

            // If headers end, move on.
            if (line == "\r")
                break;
        }

        while (client.available())
        {
            res.body += client.readStringUntil('\n');
        }

        return res;
    }

After this didn't work I looked into sending raw AT commands and using AT+HTTPSSEND
however that limits the length to 2048 byes.

I have now gone down the route of attempting to upload a file to the SIM7600 internal storage, then sending the image through "AT+CHTTPSSEND=1,"e:\image.jpg"" however the HTTTPSEND seems to return ERROR when this happens.

the latest code I am trying

     // transfer file to EFS
        Serial.println("Transferring file to EFS");

        SerialAT.println(String("AT+CFTRANRX=\"e:\\image.jpg\",") + length);
        delay(10);

        // wait until > is present
        while (SerialAT.available())
            Serial.println(SerialAT.readStringUntil('>'));

        Serial.println("Uploading file data");
        // upload over serial
        uint8_t *fbBuf = payload;
        for (size_t n = 0; n < length; n = n + PACKET_SIZE)
        {
            if (n + PACKET_SIZE < length)
            {
                SerialAT.write(fbBuf, PACKET_SIZE);
                fbBuf += PACKET_SIZE;
            }
            else if (length % PACKET_SIZE > 0)
            {
                size_t remainder = length % PACKET_SIZE;
                SerialAT.write(fbBuf, remainder);
            }
        }

        delay(10);
        while (SerialAT.available())
            Serial.println(SerialAT.readStringUntil('\n'));

        // start https
        Serial.println("starting HTTPS");

        SerialAT.println("AT+CHTTPSSTART");
        delay(500);

        while (SerialAT.available())
            Serial.println(SerialAT.readStringUntil('\n'));

        // open https

        Serial.println("Open HTTPS");
        String openHttps = String("AT+CHTTPSOPSE=") + "\"" + host + "\"," + port + ",1";
        SerialAT.println(openHttps);
        delay(1000);

        while (SerialAT.available())
            Serial.println(SerialAT.readStringUntil('\n'));

        // perform POST
        Serial.println("Performing HTTP POST request...");

        SerialAT.println("AT+CHTTPSSEND=1,\"e:\\image.jpg\"");
        delay(1500);

        while (SerialAT.available())
            Serial.println(SerialAT.readStringUntil('\n'));

        // check response
        delay(1000);
        SerialAT.println("AT+CHTTPSRECV=249");
        delay(10);
        while (SerialAT.available())
            Serial.println(SerialAT.readStringUntil('\n'));

        // close https
        Serial.println("Close HTTPS session");
        SerialAT.println("AT+CHTTPSCLSE");
        delay(10);

        while (SerialAT.available())
            Serial.println(SerialAT.readStringUntil('\n'));

        // end https
        Serial.println("Stop HTTPS stack");

        SerialAT.println("AT+CHTTPSSTOP");
        delay(10);
        while (SerialAT.available())
            Serial.println(SerialAT.readStringUntil('\n'));

        // delete file from EFS
        Serial.println("Deleting file...");
        SerialAT.println("AT+FSCD=e:/"); // select current dir
        SerialAT.println("AT+FSDEL=image.jpg");
        delay(10);

        // wait until > is present
        while (SerialAT.available())
            Serial.println(SerialAT.readStringUntil('>\r\n'));

The issue here is that it gives an ERROR after trying to send the image, so I am not sure if its a server issue or microcontroller issue.

If I modify the above to just send a simple POST to send some dummy data (the payload is literally just "hello", so its not an actual file)

  // perform POST
        Serial.println("Performing HTTP POST request...");

        String head = "----boundary\r\nContent-Disposition: form-data; name=\"image\"; filename=\"PotWatcherImage.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n";
        String tail = "\r\n----boundary--\r\n";
        String header = String("POST ") + resource + " HTTP/1.1\r\n" + "Host: " + host + "\r\n" + "Content-Length: " + String(length + head.length() + tail.length()) + "\r\n" + "Content-Type: multipart/form-data;boundary=--boundary\r\n\r\n";

        SerialAT.println(String("AT+CHTTPSSEND=") + String(length + head.length() + tail.length() + header.length()));
        delay(1500);

        while (SerialAT.available())
            Serial.println(SerialAT.readStringUntil('>'));

        SerialAT.print(header);

        SerialAT.println(head);

        uint8_t *fbBuf2 = payload;
        for (size_t n = 0; n < length; n = n + PACKET_SIZE)
        {
            SerialAT.flush();
            if (n + PACKET_SIZE < length)
            {
                SerialAT.write(fbBuf2, PACKET_SIZE);
                fbBuf2 += PACKET_SIZE;
            }
            else if (length % PACKET_SIZE > 0)
            {
                size_t remainder = length % PACKET_SIZE;
                SerialAT.write(fbBuf2, remainder);
            }
        }

        SerialAT.flush();
        SerialAT.print(tail);

        delay(10);
        while (SerialAT.available())
            Serial.println(SerialAT.readStringUntil('\n'));

This works and I get a the payload on the server.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.