khoih-prog / Portenta_H7_AsyncWebServer

Asynchronous WebServer Library for STM32H7-based Portenta_H7 using mbed_portenta core. This library, which is relied on Portenta_H7_AsyncTCP, is part of a series of advanced Async libraries, such as AsyncTCP, AsyncUDP, AsyncWebSockets, AsyncHTTPRequest, AsyncHTTPSRequest, etc. Now supporting using CString in optional SDRAM to save heap to send very large data
GNU Lesser General Public License v3.0
12 stars 3 forks source link

Unable upload file #2

Closed rickypid closed 2 years ago

rickypid commented 2 years ago

I need to save (and subsequently read) a zip file on sd card by calling POST, after multiple attempts I was unable to obtain the contents of the file. (To test I used Postman by uploading a zip file in the body as binary). I checked

https://github.com/khoih-prog/Portenta_H7_AsyncWebServer/blob/b0a72d9e247d3f351baac7ae039527e4185dbb2e/src/Portenta_H7_AsyncWebServer.h#L547

where I find an inconsistency with the documentation as a parameter is commented out.

Would you like some suggestions?

Information

Please ensure to specify the following:

Example

/****************************************************************************************************************************
  Async_HelloServer.h

  For Portenta_H7 (STM32H7) with Vision-Shield Ethernet

  Portenta_H7_AsyncWebServer is a library for the Portenta_H7 with with Vision-Shield Ethernet

  Based on and modified from ESPAsyncWebServer (https://github.com/me-no-dev/ESPAsyncWebServer)
  Built by Khoi Hoang https://github.com/khoih-prog/Portenta_H7_AsyncWebServer
  Licensed under GPLv3 license
 *****************************************************************************************************************************/
#define isDebug true
#define SERIAL_BOUDRATE 9600

#if !( defined(ARDUINO_PORTENTA_H7_M7) || defined(ARDUINO_PORTENTA_H7_M4) )
#error For Portenta_H7 only
#endif

#define _PORTENTA_H7_AWS_LOGLEVEL_     1

#define USE_ETHERNET_PORTENTA_H7        true

#include "SDMMCBlockDevice.h"
#include "FATFileSystem.h"

SDMMCBlockDevice block_device;
mbed::FATFileSystem fs("fs");

#include <Portenta_Ethernet.h>
#include <Ethernet.h>
#warning Using Portenta_Ethernet lib for Portenta_H7.
#include <Portenta_H7_AsyncWebServer.h>

// Enter a MAC address and IP address for your controller below.
#define NUMBER_OF_MAC      20

// Select the IP address according to your local network
#define DHCP_ENABLE false
IPAddress ip(10, 1, 10, 2);
AsyncWebServer server(80);

byte mac[][NUMBER_OF_MAC] =
{
  { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x01 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x02 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x03 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x04 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x05 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x06 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x07 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x08 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x09 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0A },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0B },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0C },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0D },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0E },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x0F },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x10 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x11 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x12 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x13 },
  { 0xDE, 0xAD, 0xBE, 0xEF, 0x32, 0x14 },
};

#define ON          LOW
#define OFF         HIGH
#define LED_OFF     0
#define LED_CGREEN  1
#define LED_CRED    2
#define LED_CBLUE   3
#define LED_CYELLOW 4

#define BUFFER_SIZE 64
char temp[BUFFER_SIZE];

void setupLed() {
  pinMode(LEDG, OUTPUT);
  pinMode(LEDR, OUTPUT);
  pinMode(LEDB, OUTPUT);
}
void setLed(int mode) {
  switch (mode) {
    case LED_OFF:
      digitalWrite(LEDG, OFF);
      digitalWrite(LEDR, OFF);
      digitalWrite(LEDB, OFF);
      break;
    case LED_CGREEN:
      digitalWrite(LEDG, ON);
      digitalWrite(LEDR, OFF);
      digitalWrite(LEDB, OFF);
      break;
    case LED_CRED:
      digitalWrite(LEDG, OFF);
      digitalWrite(LEDR, ON);
      digitalWrite(LEDB, OFF);
      break;
    case LED_CBLUE:
      digitalWrite(LEDG, OFF);
      digitalWrite(LEDR, OFF);
      digitalWrite(LEDB, ON);
      break;
    case LED_CYELLOW:
      digitalWrite(LEDG, ON);
      digitalWrite(LEDR, ON);
      digitalWrite(LEDB, OFF);
      break;
  }
}
template <typename T>
void serialPrintln(T msg) {
  if (isDebug) {
    Serial.println(msg);
  }
}
template <typename T>
void serialPrint(T msg) {
  if (isDebug) {
    Serial.print(msg);
  }
}

void handleUpload(AsyncWebServerRequest *request, size_t index, uint8_t *data, size_t len, bool final) {
  if (!index) {
    //serialPrintln("UploadStart: %s\n", filename.c_str());
    serialPrintln("UploadStart");
  }
  for (size_t i = 0; i < len; i++) {
    serialPrint(data[i]);
  }
  if (final) {
    //serialPrintln("UploadEnd: %s, %u B\n", filename.c_str(), index+len);
    serialPrintln("UploadEnd");
  }
}

void handleRoot(AsyncWebServerRequest *request)
{
  setLed(LED_CBLUE);
  serialPrintln(request->args());
  snprintf(temp, BUFFER_SIZE - 1, "Hello from Async_HelloServer on %s\n", BOARD_NAME);
  request->send(200, "text/plain", temp);
  setLed(LED_OFF);
}
void handleNotFound(AsyncWebServerRequest *request)
{
  setLed(LED_CBLUE);
  String message = "File Not Found\n\n";

  message += "URI: ";
  //message += server.uri();
  message += request->url();
  message += "\nMethod: ";
  message += (request->method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += request->args();
  message += "\n";

  for (uint8_t i = 0; i < request->args(); i++)
  {
    message += " " + request->argName(i) + ": " + request->arg(i) + "\n";
  }

  request->send(404, "text/plain", message);
  setLed(LED_OFF);
}

void setup()
{
  setupLed();
  if (isDebug) {
    Serial.begin(SERIAL_BOUDRATE);
    while (!Serial) {
      setLed(LED_CYELLOW);
      delay(100);
      setLed(LED_OFF);
      delay(100);
    }
  }
  setLed(LED_OFF);

  serialPrint("\nStart Async_HelloServer on "); serialPrint(BOARD_NAME);
  serialPrint(" with "); serialPrintln(SHIELD_TYPE);
  serialPrintln(PORTENTA_H7_ASYNC_TCP_VERSION);
  serialPrintln(PORTENTA_H7_ASYNC_WEBSERVER_VERSION);

  ///////////////////////////////////
  serialPrintln("Mounting SDCARD...");
  int err =  fs.mount(&block_device);
  if (err) {
    // Reformat if we can't mount the filesystem
    // this should only happen on the first boot
    serialPrintln("No filesystem found, formatting... ");
    err = fs.reformat(&block_device);
  }
  if (err) {
    serialPrintln("Error formatting SDCARD ");
    while (true) {
      setLed(LED_CRED);
      delay(100);
      setLed(LED_OFF);
      delay(100);
    }
  }
  ///////////////////////////////////
  // start the ethernet connection and the server
  // Use random mac
  uint16_t index = millis() % NUMBER_OF_MAC;

  if (!DHCP_ENABLE) {
    Ethernet.begin(mac[index], ip);
  } else {
    Ethernet.begin(mac[index]);
  }

  if (Ethernet.hardwareStatus() == EthernetNoHardware)
  {
    serialPrintln("No Ethernet found. Stay here forever");

    while (true)
    {
      delay(1); // do nothing, no point running without Ethernet hardware
    }
  }

  if (Ethernet.linkStatus() == LinkOFF)
  {
    serialPrintln("Not connected Ethernet cable");
    while (Ethernet.linkStatus() == LinkOFF) {
      setLed(LED_CRED);
      delay(100);
      setLed(LED_OFF);
      delay(100);
    }
  }

  serialPrint(F("Using mac index = "));
  serialPrintln(index);

  serialPrint(F("Connected! IP address: "));
  serialPrintln(Ethernet.localIP());

  ///////////////////////////////////

  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request)
  {
    handleRoot(request);
  });
  server.on("/post", HTTP_POST, [](AsyncWebServerRequest * request) {
    serialPrintln(request->params());
    request->send(200);
  }, handleUpload
           );
  server.on("/inline", [](AsyncWebServerRequest * request)
  {
    request->send(200, "text/plain", "This works as well");
  });

  server.onNotFound(handleNotFound);
  server.begin();

  serialPrint(F("HTTP EthernetWebServer is @ IP : "));
  serialPrintln(Ethernet.localIP());
}

void heartBeatPrint()
{
  static int num = 1;

  serialPrint(F("."));

  if (num == 80)
  {
    serialPrintln("");
    num = 1;
  }
  else if (num++ % 10 == 0)
  {
    serialPrint(F(" "));
  }
}

void check_status()
{
  static unsigned long checkstatus_timeout = 0;

#define STATUS_CHECK_INTERVAL     10000L

  // Send status report every STATUS_REPORT_INTERVAL (60) seconds: we don't need to send updates frequently if there is no status change.
  if ((millis() > checkstatus_timeout) || (checkstatus_timeout == 0))
  {
    heartBeatPrint();
    checkstatus_timeout = millis() + STATUS_CHECK_INTERVAL;
  }
}

void loop()
{
  check_status();
}
khoih-prog commented 2 years ago

The Portenta_H7_AsyncWebServer library was written when the Portenta_H7 is still new, and there is no stable FileSystem support at that time, such as LittleFS/SPIFFS in ESSP32/ESP8266. That's why the file-uploading feature was not implemented then.

I don't know if I have the time or it's worth to spend time to have a look at the enhancement, because Portenta_H7 seems not popular now.

I also suggest you use my LittleFS_Portenta_H7 library to be compatible with future enhancement, if possible.

If you have time, look at the similar implementation and example in

  1. AsyncWebServer_WT32_ETH01 library
  2. AsyncFSBrowser_WT32_ETH01 example
  3. AsyncSimpleServer_WT32_ETH01 example

As I have no plan to add the enhancement now, I'm closing the issue.

Good Luck,

khoih-prog commented 2 years ago

If you have time now, you can modify your code and library, following the

  1. ESP32_FS_EthernetWebServer example

to enable Async file service.

I'll definitely help on the way and appreciate it if you can create a PR for the new enhancement.

rickypid commented 2 years ago

Hi @khoih-prog,

I really need this feature, but i don't know your library and i don't know if i can help you, if you want try to give me some guidance on how to implement this feature. In the next week I will start doing some tests.

Thanks.

rickypid commented 2 years ago

Hi @khoih-prog,

is it possible sponsoring development of this feature?

Thnaks

khoih-prog commented 2 years ago

Hi @rickypid

Thanks for your sponsoring proposal, which means a lot to me spiritually as I know my work somehow beneficial to some people. I'm sorry to say that I'm currently working for fun to keep my brain not idling and wasted, and not interested in financial compensation.

I certainly will have a look at your enhancement request sometime next week, but not sure the current Portenta_H7 infrastructure (core, libraries, etc.) can support the new features you request yet. You also have to understand, prepare, research and write down the new enhancements you need.

I can't promise anything now yet for now.

As this thread is going far from normal issue, I'll invite you to my private repo, where several more Portenta_H7 experts are participating and discussing to improve the Portenta_H7 eco-system and libraries.

Regards,