jameszah / ESP32-CAM-Video-Recorder-junior

Simple fast version of ESP32-CAM-Video-Recorder
GNU General Public License v3.0
285 stars 54 forks source link

Delete old videos feature #6

Closed al3xv0lk closed 2 years ago

al3xv0lk commented 3 years ago

Hello, I'm working in a custom security camera project, your junior code is working great, but the lack of the feature of deleting old data is kind of problematic since I have to delete all data manually, there is some easier way to implement this feature in the junior version?

jameszah commented 3 years ago

I have a new version for new cameras, and the new arduino esp32 framework, which is not ready, but here is a bit of code.

It will delete files of the form "desklens123.456.avi", where "desklens" is your device name, 123 is the number of reboots of your esp32, and 456 is the number of the video recorded during that boot. It looks for the number 123.456 and deletes the smallest one. It should ignore folders and files with no number.

Make sure you quick-format the sd card now and then because broken files will use up diskspace of the sd, but do not show up in SD_MMC.usedBytes(), so your sd could be half full of broken files, which cannot be allocated to make new files, but do not show up for the purpose of calculating the disk full percentage.

A couple lines at the end of setup()

Serial.print("SD_MMC Begin: "); Serial.println(SD_MMC.begin());   
listDir( "/", 0);
delete_old_stuff();

One line just before you start a new recording - search for that comment.

//Serial.println("Ready to start");
delete_old_stuff();

And the new functions to paste into the code. -- number 0.8 is 80% full limit.

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
//  delete_old_stuff() - before every avi, delete oldest day if freespace less than 20%
//

void listDir( const char * dirname, uint8_t levels) {

  Serial.printf("Listing directory: %s\n", "/");

  File root = SD_MMC.open("/");
  if (!root) {
    Serial.println("Failed to open directory");
    return;
  }
  if (!root.isDirectory()) {
    Serial.println("Not a directory");
    return;
  }

  File filex = root.openNextFile();
  while (filex) {
    if (filex.isDirectory()) {
      Serial.print("  DIR : ");
      Serial.println(filex.name());
      if (levels) {
        listDir( filex.name(), levels - 1);
      }
    } else {
      Serial.print("  FILE: ");
      Serial.print(filex.name());
      Serial.print("  SIZE: ");
      Serial.println(filex.size());
    }
    filex = root.openNextFile();
  }
}

void delete_old_stuff() {

  Serial.printf("Total space: %lluMB\n", SD_MMC.totalBytes() / (1024 * 1024));
  Serial.printf("Used space: %lluMB\n", SD_MMC.usedBytes() / (1024 * 1024));

  //listDir( "/", 0);

  float full = 1.0 * SD_MMC.usedBytes() / SD_MMC.totalBytes();;
  if (full  <  0.8) {
    Serial.printf("Nothing deleted, %.1f%% disk full\n", 100.0 * full);
  } else {
    Serial.printf("Disk is %.1f%% full ... deleting oldest file\n", 100.0 * full);
    while (full > 0.8) {

      double del_number = 999999999;
      char del_numbername[50];

      File f = SD_MMC.open("/");

      File file = f.openNextFile();

      while (file) {
        //Serial.println(file.name());
        if (!file.isDirectory()) {

          char foldname[50];
          strcpy(foldname, file.name());
          for ( int x = 0; x < 50; x++) {
            if ( (foldname[x] >= 0x30 && foldname[x] <= 0x39) || foldname[x] == 0x2E) {
            } else {
              if (foldname[x] != 0) foldname[x] = 0x20;
            }
          }

          double i = atof(foldname);
          if (  i < del_number) {
            strcpy (del_numbername, file.name());
            del_number = i;
          }
          //Serial.printf("Name is %s, number is %f\n", foldname, i);
        }
        file = f.openNextFile();

      }
      Serial.printf("lowest is Name is %s, number is %f\n", del_numbername, del_number);
      if (del_number < 999999999) {
        deleteFolderOrFile(del_numbername);
      }
      full = 1.0 * SD_MMC.usedBytes() / SD_MMC.totalBytes(); 
      Serial.printf("Disk is %.1f%% full ... \n", 100.0 * full);
      f.close();
    }  
  }
}

void deleteFolderOrFile(const char * val) {
  // Function provided by user @gemi254
  Serial.printf("Deleting : %s\n", val);
  File f = SD_MMC.open(val);
  if (!f) {
    Serial.printf("Failed to open %s\n", val);
    return;
  }

  if (f.isDirectory()) {
    File file = f.openNextFile();
    while (file) {
      if (file.isDirectory()) {
        Serial.print("  DIR : ");
        Serial.println(file.name());
      } else {
        Serial.print("  FILE: ");
        Serial.print(file.name());
        Serial.print("  SIZE: ");
        Serial.print(file.size());
        if (SD_MMC.remove(file.name())) {
          Serial.println(" deleted.");
        } else {
          Serial.println(" FAILED.");
        }
      }
      file = f.openNextFile();
    }
    f.close();
    //Remove the dir
    if (SD_MMC.rmdir(val)) {
      Serial.printf("Dir %s removed\n", val);
    } else {
      Serial.println("Remove dir failed");
    }

  } else {
    //Remove the file
    if (SD_MMC.remove(val)) {
      Serial.printf("File %s deleted\n", val);
    } else {
      Serial.println("Delete failed");
    }
  }
}
al3xv0lk commented 3 years ago

Thanks, that is exactly what I was looking for! I will try it tomorrow morning.