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

Weird HTTP_POST hangup #12

Closed AndreiSab closed 1 year ago

AndreiSab commented 1 year ago

HTTP_POST hangs up PortentaH7 when is use it to send a file name to the server and save said file on SD card but strangely only the second time i send the request. I have attached a sketch that should reproduce the issue and reflects what i'm trying to do.

I've tried this both using Arduino IDE 2.0.0 and VSCode + PlatformIO. I'm using a PortentaH7 Rev2 and breakout.

#include <WiFi.h>
#warning Using WiFi for Portenta_H7.
#include <Portenta_H7_AsyncWebServer.h>
#include <SDMMCBlockDevice.h>
#include <FATFileSystem.h>
#include <ArduinoJson.h>

SDMMCBlockDevice block_device;
mbed::FATFileSystem fs("fs");
char ssid[] = "SSIDname";      
char pass[] = "123456789";    // I use it this way since i want it to be a WiFi A.P.    

int status = WL_IDLE_STATUS;
AsyncWebServer    server(80);

void handleRoot(AsyncWebServerRequest *request)
{
  String html ="<!DOCTYPE html> <html> <head> </head> <body> <label for=\"fname\">File Name:</label><br> <input type=\"text\" id=\"fname\" name=\"fname\" value=\"\"><br> <label for=\"temperature\" name=\"tname\">Temp:</label><p id=\"temp\"></p><br> <button class=\"button\" type=\"button\" onclick=logTemp()>LogTemp</button> <script> function logTemp(){ var xhr = new XMLHttpRequest(); var filename=document.getElementById(\"fname\").value; const params={\"fname\":filename}; xhr.open(\"POST\", \"/logTemp\",true); xhr.setRequestHeader(\"Content-Type\",\"application/json;charset=UTF-8\"); xhr.send(JSON.stringify(params)); } setInterval(function(){getTemperature();},2000); function getTemperature(){ var xhr = new XMLHttpRequest(); xhr.onreadystatechange=function(){ if(this.readyState==4 && this.status==200){ document.getElementById(\"temp\").innerText=this.responseText;} }; xhr.open(\"GET\",\"/temperature\",true); xhr.send(); } </script> </body> </html>";
  request->send(200, "text/html",html);
}

void handleNotFound(AsyncWebServerRequest *request)
{
  String message = "File Not Found\n\n";

  message += "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);
}

String readTemperature(){
  int lower=20,upper=50;
  int num=(rand()%(upper-lower+1))+lower;
  return String(num);
} // A random val in range function since no sensor is connected
void printWifiStatus()
{
  // print the SSID of the network you're attached to:
  Serial.print("SSID: ");
  Serial.println(WiFi.SSID());

  // print your board's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print("Local IP Address: ");
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print("signal strength (RSSI):");
  Serial.print(rssi);
  Serial.println(" dBm");
}
void saveTestFile(String file, String fileName){
  FILE *testFile;
  String fspref ="/fs/";
  fspref+=fileName;
  fspref+=".json";
  testFile=fopen(fspref.c_str(),"w+");
  fprintf(testFile, file.c_str());
  fclose(testFile);
}
void setup() {
  // put your setup code here, to run once:
#pragma region WIFI_SETUP&CARD_MOUNT
  Serial.begin(115200);
  while (!Serial);

  delay(200);

  Serial.print("\nStart Async_AdvancedWebServer on "); Serial.print(BOARD_NAME);
  Serial.print(" with "); Serial.println(SHIELD_TYPE);
  Serial.println(PORTENTA_H7_ASYNC_TCP_VERSION);
  Serial.println(PORTENTA_H7_ASYNC_WEBSERVER_VERSION);

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

  status = WiFi.beginAP(ssid,pass);
  if(status != WL_AP_LISTENING){
    Serial.println("Creating access point failed");
    // don't continue
    while (true);
  }

  printWifiStatus();

  Serial.println("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
    Serial.println("No filesystem found, formatting... ");
    err = fs.reformat(&block_device);
  }
  if (err) {
     Serial.println("Error formatting SDCARD ");
     while(1);
  }

  DIR *dir;
  struct dirent *ent;
  int dirIndex = 0;

  Serial.println("List SDCARD content: ");
  if ((dir = opendir("/fs")) != NULL) {
    // Print all the files and directories within directory (not recursively)
    while ((ent = readdir (dir)) != NULL) {
      Serial.println(ent->d_name);
      dirIndex++;
    }
    closedir (dir);
  } else {
    // Could not open directory
    Serial.println("Error opening SDCARD\n");
    while(1);
  }
  if(dirIndex == 0) {
    Serial.println("Empty SDCARD");
  }
  ///////////////////////////////////
  #pragma endregion

server.on("/logTemp", HTTP_POST, [](AsyncWebServerRequest * request){
  },NULL,[](AsyncWebServerRequest * request, uint8_t *data, size_t len, size_t index, size_t total) {
    String jsondata;
     for (size_t i = 0; i < len; i++) {
        jsondata+=(char)data[i];
      }
      DynamicJsonDocument doc(100);
      deserializeJson(doc,jsondata);
      String testFile_name=doc["fname"];
      doc["temp"]=readTemperature().c_str();
      String testSer;
      serializeJson(doc,testSer);
      saveTestFile(testSer,testFile_name);
      request->send(200);
  });
  server.on("/temperature", HTTP_GET, [](AsyncWebServerRequest * request)
  {
    request->send(200,"text/plain",readTemperature().c_str());
  });
  server.on("/", HTTP_GET, [](AsyncWebServerRequest * request)
  {
    handleRoot(request);
  });
  server.onNotFound(handleNotFound);
  server.begin();
}
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))
  {
    checkstatus_timeout = millis() + STATUS_CHECK_INTERVAL;
  }
}

void loop() {
  // put your main code here, to run repeatedly:
  check_status();
}
khoih-prog commented 1 year ago

HI @AndreiSab

Please have a real look and check your buggy code and figure out yourself the big problem in your code (hint: the callback handler)

If still not, I suggest you start from a simple but working example, then modify / test gradually to know where and when it's broken. Or you can go to Arduino Forum to ask for help from many experts there.

I'm closing the issue now as this is not a bug or issue of this library.

Good Luck,