Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chunkwise write the uncompressed file. #3

Closed
samsmith94 opened this issue Feb 2, 2022 · 4 comments
Closed

Chunkwise write the uncompressed file. #3

samsmith94 opened this issue Feb 2, 2022 · 4 comments

Comments

@samsmith94
Copy link

Hi,

I could create a simple program to test your library with SdFat library, instead of standard Arduino SD.
But I realized, that I still have a problem.
I would like to implement FOTA, so I will download the application.zip file.
Then I want to unzip it (application.bin).
The .bin file is quite large (393216 byte). I don't have this much memory. (I have 56+4 KB of SRAM on STM32F429ZI).

So my question, how can I use your library, so that I can write this larga application.bin to the SD card in chunkwise manner?

Here is my code:

#include <Arduino.h>
#include <unzipLIB.h>
#include "SdFat.h"
#include "sdios.h"

SPIClass SPI_4(PE6, PE5, PE2); // MOSI, MISO. SCLK
const uint8_t SD_CS_PIN = PE4;
#define SD_CONFIG SdSpiConfig(SD_CS_PIN, DEDICATED_SPI, SD_SCK_MHZ(4), &SPI_4)

UNZIP zip; // statically allocate the UNZIP structure (41K)
SdFat sd;
File root;
static File myfile;
static File myfileAnother;

void * myOpen(const char *filename, int32_t *size) {
  root.open("/");
  myfileAnother.open(filename);
  *size = (uint32_t)myfileAnother.fileSize();
  return (void *)&myfileAnother;
}

void myClose(void *p) {
  ZIPFILE *pzf = (ZIPFILE *)p;
  File *f = (File *)pzf->fHandle;
  if (f) f->close();
}

int32_t myRead(void *p, uint8_t *buffer, int32_t length) {
  ZIPFILE *pzf = (ZIPFILE *)p;
  File *f = (File *)pzf->fHandle;
  return f->read(buffer, length);
}

int32_t mySeek(void *p, int32_t position, int iType) {
  ZIPFILE *pzf = (ZIPFILE *)p;
  File *f = (File *)pzf->fHandle;
  if (iType == SEEK_SET)
    return f->seek(position);
  else if (iType == SEEK_END) {
    return f->seek(position + pzf->iSize); 
  } else { // SEEK_CUR
    long l = f->position();
    return f->seek(l + position);
  }
}

void setup() {
  Serial.begin(115200);

  while (!Serial && millis() < 3000);
  Serial.println("Search for ZIP files on the SD card");
  
  if (!sd.begin(SD_CONFIG))
  {
    sd.initErrorHalt(&Serial);
    Serial.println("Unable to access SD Card");
  }

  if (!root.open("/"))
  {
    Serial.println("Open root failed");
  }
  //////////////////////////////////////////////////////////////////////////////
  int rc;
  char szComment[256], szName[256];
  unz_file_info fi;

  const char *name = "application.zip";
  if (!myfile.open(name, O_RDONLY))
  {
    Serial.println("Opening application.zip failed");
  }
  Serial.println("Openend application.zip");
  rc = rc = zip.openZIP(name, myOpen, myClose, myRead, mySeek);
  if (rc == UNZ_OK) {
    Serial.print("ZIP file found");

    // Display the global comment and all of the filenames within
    rc = zip.getGlobalComment(szComment, sizeof(szComment));
    Serial.print("Files in this archive: ");
    zip.gotoFirstFile();
    rc = UNZ_OK;
    rc = zip.getFileInfo(&fi, szName, sizeof(szName), NULL, 0, szComment, sizeof(szComment));

    if (rc == UNZ_OK) {
      Serial.println(szName);
      Serial.print("Compressed size: "); Serial.println(fi.compressed_size, DEC);
      Serial.print("Uncompressed size: "); Serial.println(fi.uncompressed_size, DEC);
      
    }
    zip.closeZIP();
  }
}

void loop() {}
@bitbank2
Copy link
Owner

bitbank2 commented Feb 2, 2022

You can work with the unzipped data very easily. Once you've opened the ZIP file and located the archived file you want to work with, you can read the data into a local buffer of any size - you can read one byte at a time if you like. Then you will write that data to a new file on the SDcard or other medium. The data is at your disposal.

int readCurrentFile(uint8_t *buffer, int iLength);

@bitbank2 bitbank2 closed this as completed Feb 2, 2022
@samsmith94
Copy link
Author

Thank you very much for your help!

@samsmith94
Copy link
Author

samsmith94 commented Feb 2, 2022

One last question:
If I want to read it in multiple proportion, then I will need to call some sort of seek() implementaion, right?
Which is in my case int32_t mySeek(void *p, int32_t position, int iType)

So I need to move the file pointer, so that zip.readCurrentFile() know, whence I want to read iLength number of bytes.
But what is my file pointer in the example above?
I need to pass it to mySeek as an argument, but when I call it with myfile, it is not working.
I call it this way:

mySeek(&myfile, 0, SEEK_SET);

I also tried:

myfile.seekSet(0);

And I always get -102 as return value for readSize

int readSize = zip.readCurrentFile(l_Buff, BUFF_SIZE);

@samsmith94
Copy link
Author

Sorry, I forgot to call zip.openCurrentFile();
😄

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants