Txt-Datei auf SD-Karte über Webserver als Download

Hallo zusammen,

ich schreibe aktuell Messwerte eines Temperatursensors in eine .txt-Datei auf einer SD-Karte.
Dazu verwende ich den ESP8266 D1 mini + microsd shield.
Das funktioniert auch so weit.
Des Weiteren dient der D1 auch als WLAN Accesspoint und stellt per Webserver eine html-page dar, dort lasse ich mir momentan nur den aktuellen Messwert des Sensors anzeigen.
Ich würde gerne die auf der SD-Karte gespeicherte .txt Datei auf dieser Seite als Download anbieten.
Ist das mit ein paar Zeilen zusätzlichen Code zu lösen?

Freue mich auf eure Antworten.

solle eigentlich keine große Hexerei sein:

Wenn du diese Datei im FS des ESP8266 ablegst, kannst du prima per Web-Interface darauf zugreifen. Schau dir dazu mal die Beispiele auf der Seite von fips an.

Hätte da auch noch was in petto. Ist aber grundsätzlich etwas von Fips und Werner zusammen gebastelkopierabgeleitet und für meine Zwecke angepasst.

Bin leider noch nicht dazu gekommen den Code so zu säubern, wie ich das vorhatte. Aber im Zweifel könnte ich davon das eine oder andere schon zur Verfügung stellen.
Siehe:

Ich habe jetzt zunächst den Ansatz in der Antwort von @noiasca probiert.
Leider erhalte ich im Browser die Meldung das keine SD-Karte erkannt wurde:

grafik

Das habe ich bisher:

/*
 *
 * The WeMos Micro SD Shield uses:
 * D5, D6, D7, D8, 3V3 and G
 *
 * The shield uses SPI bus pins:
 * D5 = CLK
 * D6 = MISO
 * D7 = MOSI
 * D8 = CS
 */
#include <ESP8266mDNS.h>
#include <SPI.h>
#include <SD.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include "DHT.h"
#define DHTTYPE DHT22
#define DBG_OUTPUT_PORT Serial
const char* host = "esp8266sd";
#ifndef APSSID
/////////////////////////////////////AP-Config////////////////
#define APSSID "ESP8266ap"
#define APPSK "lappen2022"
#endif
//////////////////////////////////////////////////////////////
static bool hasSD = false;
File uploadFile;
const char *ssid = APSSID;
const char *password = APPSK;
uint8_t DHTPin = 2;
DHT dht(DHTPin, DHTTYPE);
String helperstring;

ESP8266WebServer server(80);


float Temperature;
int ENTRYNO = 1;
String celsius;
int writeintervall = 10000;
int previousMillis = 0;


//////////////////////////////////////////////////////////////
void returnOK() {
  server.send(200, "text/plain", "");
}

void returnFail(String msg) {
  server.send(500, "text/plain", msg + "\r\n");
}

bool loadFromSdCard(String path){
  String dataType = "text/plain";
  if(path.endsWith("/")) path += "index.htm";

  if(path.endsWith(".src")) path = path.substring(0, path.lastIndexOf("."));
  else if(path.endsWith(".htm")) dataType = "text/html";
  else if(path.endsWith(".css")) dataType = "text/css";
  else if(path.endsWith(".js")) dataType = "application/javascript";
  else if(path.endsWith(".png")) dataType = "image/png";
  else if(path.endsWith(".gif")) dataType = "image/gif";
  else if(path.endsWith(".jpg")) dataType = "image/jpeg";
  else if(path.endsWith(".ico")) dataType = "image/x-icon";
  else if(path.endsWith(".xml")) dataType = "text/xml";
  else if(path.endsWith(".pdf")) dataType = "application/pdf";
  else if(path.endsWith(".zip")) dataType = "application/zip";

  File dataFile = SD.open(path.c_str());
  if(dataFile.isDirectory()){
    path += "/index.htm";
    dataType = "text/html";
    dataFile = SD.open(path.c_str());
  }

  if (!dataFile)
    return false;

  if (server.hasArg("download")) dataType = "application/octet-stream";

  if (server.streamFile(dataFile, dataType) != dataFile.size()) {
    DBG_OUTPUT_PORT.println("Sent less data than expected!");
  }

  dataFile.close();
  return true;
}

void handleFileUpload(){
  if(server.uri() != "/edit") return;
  HTTPUpload& upload = server.upload();
  if(upload.status == UPLOAD_FILE_START){
    if(SD.exists((char *)upload.filename.c_str())) SD.remove((char *)upload.filename.c_str());
    uploadFile = SD.open(upload.filename.c_str(), FILE_WRITE);
    DBG_OUTPUT_PORT.print("Upload: START, filename: "); DBG_OUTPUT_PORT.println(upload.filename);
  } else if(upload.status == UPLOAD_FILE_WRITE){
    if(uploadFile) uploadFile.write(upload.buf, upload.currentSize);
    DBG_OUTPUT_PORT.print("Upload: WRITE, Bytes: "); DBG_OUTPUT_PORT.println(upload.currentSize);
  } else if(upload.status == UPLOAD_FILE_END){
    if(uploadFile) uploadFile.close();
    DBG_OUTPUT_PORT.print("Upload: END, Size: "); DBG_OUTPUT_PORT.println(upload.totalSize);
  }
}

void deleteRecursive(String path){
  File file = SD.open((char *)path.c_str());
  if(!file.isDirectory()){
    file.close();
    SD.remove((char *)path.c_str());
    return;
  }

  file.rewindDirectory();
  while(true) {
    File entry = file.openNextFile();
    if (!entry) break;
    String entryPath = path + "/" +entry.name();
    if(entry.isDirectory()){
      entry.close();
      deleteRecursive(entryPath);
    } else {
      entry.close();
      SD.remove((char *)entryPath.c_str());
    }
    yield();
  }

  SD.rmdir((char *)path.c_str());
  file.close();
}

void handleDelete(){
  if(server.args() == 0) return returnFail("BAD ARGS");
  String path = server.arg(0);
  if(path == "/" || !SD.exists((char *)path.c_str())) {
    returnFail("BAD PATH");
    return;
  }
  deleteRecursive(path);
  returnOK();
}

void handleCreate(){
  if(server.args() == 0) return returnFail("BAD ARGS");
  String path = server.arg(0);
  if(path == "/" || SD.exists((char *)path.c_str())) {
    returnFail("BAD PATH");
    return;
  }

  if(path.indexOf('.') > 0){
    File file = SD.open((char *)path.c_str(), FILE_WRITE);
    if(file){
      file.write((const char *)0);
      file.close();
    }
  } else {
    SD.mkdir((char *)path.c_str());
  }
  returnOK();
}

void printDirectory() {
  if(!server.hasArg("dir")) return returnFail("BAD ARGS");
  String path = server.arg("dir");
  if(path != "/" && !SD.exists((char *)path.c_str())) return returnFail("BAD PATH");
  File dir = SD.open((char *)path.c_str());
  path = String();
  if(!dir.isDirectory()){
    dir.close();
    return returnFail("NOT DIR");
  }
  dir.rewindDirectory();
  server.setContentLength(CONTENT_LENGTH_UNKNOWN);
  server.send(200, "text/json", "");
  WiFiClient client = server.client();

  server.sendContent("[");
  for (int cnt = 0; true; ++cnt) {
    File entry = dir.openNextFile();
    if (!entry)
    break;

    String output;
    if (cnt > 0)
      output = ',';

    output += "{\"type\":\"";
    output += (entry.isDirectory()) ? "dir" : "file";
    output += "\",\"name\":\"";
    output += entry.name();
    output += "\"";
    output += "}";
    server.sendContent(output);
    entry.close();
 }
 server.sendContent("]");
 dir.close();
}

void handleNotFound(){
  if(hasSD && loadFromSdCard(server.uri())) return;
  String message = "SDCARD Not Detected\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET)?"GET":"POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i=0; i<server.args(); i++){
    message += " NAME:"+server.argName(i) + "\n VALUE:" + server.arg(i) + "\n";
  }
  server.send(404, "text/plain", message);
  DBG_OUTPUT_PORT.print(message);
}

void handleRoot() {
  //server.send(200, "text/html", "<h1>You are connected</h1>");
}

// change this to match your SD shield or module;
// WeMos Micro SD Shield V1.0.0: D8
// LOLIN Micro SD Shield V1.2.0: D4 (Default)
const int chipSelect = D4;

void setup()
{
  // Open serial communications and wait for port to open:
  Serial.begin(115200);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }

  Serial.print("Initializing SD card...");

  // see if the card is present and can be initialized:
  if (!SD.begin(chipSelect)) {
    Serial.println("Card failed, or not present");
    // don't do anything more:
    return;
  }
  Serial.println("card initialized.");
  Serial.print("Configuring access point...");
  /* You can remove the password parameter if you want the AP to be open. */
  WiFi.softAP(ssid, password);

  IPAddress myIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(myIP);
  //server.on("/", handleRoot);

  
  if (MDNS.begin(host)) {
    MDNS.addService("http", "tcp", 80);
    DBG_OUTPUT_PORT.println("MDNS responder started");
    DBG_OUTPUT_PORT.print("You can now connect to http://");
    DBG_OUTPUT_PORT.print(host);
    DBG_OUTPUT_PORT.println(".local");
  }
  
  server.on("/list", HTTP_GET, printDirectory);
  server.on("/edit", HTTP_DELETE, handleDelete);
  server.on("/edit", HTTP_PUT, handleCreate);
  server.on("/edit", HTTP_POST, [](){ returnOK(); }, handleFileUpload);
  server.onNotFound(handleNotFound);

  if (SD.begin(SS)){
     DBG_OUTPUT_PORT.println("SD Card initialized.");
     hasSD = true;
  }

  
  server.begin();
  delay(10);
  dht.begin();
  delay(10);
  Serial.println("HTTP server started");
}
  


void loop()
{
  unsigned long currentMillis = millis();
  server.handleClient();
  // make a string for assembling the data to log:
  String dataString = "";
  
  Temperature = (dht.readTemperature() - 1); // Gets the values of the temperature
  delay(20);
      if(isnan(Temperature))
    {
      return;
    }
  celsius.concat(Temperature);
  //Serial.print(Temperature);

  dataString += ENTRYNO;
  dataString += ",";
  dataString += Temperature;



////////////////Write every 10s////////////////////////////  
  
  
if(currentMillis -previousMillis >= writeintervall)
{
  ENTRYNO++;
  
  //save last time you wrote to sd
  previousMillis = currentMillis;
  //////////////Display current Temperature//////////////////
  
  /*
  helperstring += "Die aktuelle Temperatur betraegt: ";
  helperstring += Temperature;
  server.send(200,"text/html",helperstring);
  helperstring= "";
  */
  // open the file. note that only one file can be open at a time,
  // so you have to close this one before opening another.
  File dataFile = SD.open("datalog.txt", FILE_WRITE);

  // if the file is available, write to it:
  if (dataFile) {
    dataFile.println(dataString);
    dataFile.close();
    // print to the serial port too:
    Serial.println(dataString);
  }
  // if the file isn't open, pop up an error:
  else {
    Serial.println("error opening datalog.txt");
  }
  
}
  delay(100);
}

Update:

Heute morgen noch Mal mit der Konfiguration oben probiert und auf ein mal funktioniert es.
Da es mir etwas an Erfahrung mangelt in dem Bereich:
Kann ich eine 16GB SD-Karte problemlos verwenden oder sollte ich etwas kleineres nehmen?

Hallo nico,

Ich habe genau das selbe Problem wie du.
Wie hast du den SDCard not detected Fehler behoben?

Hallo can,

wie oben beschrieben hat sich das Problem bei mir quasi über Nacht selbst gelöst.
Ich habe in einem ähnlichen Projekt nochmal das Problem gehabt, dort war aber mit Verwendung einer anderen SD-Karte das Problem gelöst.

Gruß Nico

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