3

So I am trying to send a jpeg image (4Kb) from a raspberry pi to my Mac wirelessly using Xbee Series 1. I have an image on the raspberry pi and can read it into binary format. I've used this binary format to save it into another image file and it creates a copy of the image correctly. That tells me that I am reading it correctly. So I am trying to send that data over a serial port (to be transferred by the xbee's) to my Mac. Side note, Xbee's can only transmit I think 80 bytes of data per packet or something. I don't know how that affects what I'm doing though.

My problem is, I do not know how to read the data and properly store it into a jpeg file itself. Most of the Read() functions I have found require you to enter a length to read and I don't know how to tell how long it is since its just a serial stream coming in.

Here is my code to send the jpeg.

#include "xSerial.hpp"
#include <iostream>
#include <cstdlib>
using namespace std;

int copy_file( const char* srcfilename, const char* dstfilename );


int main(){

copy_file("tylerUseThisImage.jpeg", "copyImage.jpeg");

return 0;
}

int copy_file( const char* srcfilename, const char* dstfilename )
  {
  long  len;
  char* buf = NULL;
  FILE* fp  = NULL;

  // Open the source file
  fp = fopen( srcfilename, "rb" );
  if (!fp) return 0;

  // Get its length (in bytes)
  if (fseek( fp, 0, SEEK_END ) != 0)  // This should typically succeed
    {                                 // (beware the 2Gb limitation, though)
    fclose( fp );
    return 0;
    }

  len = ftell( fp );
  std::cout << len;
  rewind( fp );
  // Get a buffer big enough to hold it entirely
  buf = (char*)malloc( len );
  if (!buf)
    {
    fclose( fp );
    return 0;
    }

  // Read the entire file into the buffer
  if (!fread( buf, len, 1, fp ))
    {
    free( buf );
    fclose( fp );
    return 0;
    }

  fclose( fp );

  // Open the destination file
  fp = fopen( dstfilename, "wb" );
  if (!fp)
    {
    free( buf );
    return 0;
    }
  // this is where I send data in but over serial port. 
  //serialWrite() is just the standard write() being used
  int fd;
  fd = xserialOpen("/dev/ttyUSB0", 9600);
  serialWrite(fd, buf, len);

   //This is where the file gets copied to another file as a test
  // Write the entire buffer to file
  if (!fwrite( buf, len, 1, fp ))
    {
    free( buf );
    fclose( fp );
    return 0;
    }

  // All done -- return success
  fclose( fp );
  free( buf );
  return 1;
  }

On the receive side I know I need to open up the serial port to read and use some sort of read() but I don't know how that is done. Using a serial library it has some functions to check if serial data is available and return the number of characters available to read.

One question about the number of characters available to read, will that number grow as the serial stream comes over or will it immediately tell the entire length of the data to be read?

But finally, I know after I open the serial port, I need read the data into a buffer and then write that buffer to a file but I have not had any luck. This is what I have tried thus far.

// Loop, getting and printing characters
char temp;
bool readComplete = false;
int bytesRead = 0;

fp = fopen("copyImage11.jpeg", "rwb");

  for (;;)
  {
        if(xserialDataAvail(fd) > 0)
        {
        bytesRead = serialRead(fd, buf, len);
        readComplete = true;
        }
        if (readComplete)
        {
         if (!fwrite(buf, bytesRead, 1, fp))
         {
         free(buf);
         fclose(fp);
         return 0;
         }

         fclose(fp);
         free(buf);
         return 1;
        }
}

I don't get errors with my code, it just doesnt create the jpeg file correctly. Maybe I'm not transmitting it right, or maybe I'm not reading/writing to file correctly. Any help would be appreciated. Thanks everyone you rock!

too honest for this site
  • 12,050
  • 4
  • 30
  • 52
jakoh77
  • 41
  • 2
  • 5
  • 1
    I know you want to solve it using your own code, but wouldn't it be simpler to use existing utilities to do it? E.g. use `sz` to send the file, and `rz` to receive it, using the ZMODEM protocol. – Kuba hasn't forgotten Monica Feb 17 '16 at 22:12
  • This is a bad mixture of C style with C++ features. However, it is not C code. Do not add tags for unrelated languages. – too honest for this site Feb 17 '16 at 22:15
  • `free(buf);` scares the stuffing out of me. Is `serialRead` allocating `buf`? If it is, I recommend that it doesn't. You're opening an unnecessary can of worms. If it doesn't, where the hell are all these `buf`s coming from? – user4581301 Feb 17 '16 at 22:33
  • On the sender's side, rather than `malloc`ing a buffer, have a buffer of fixed size. Read a buffer-sized chunk of the source file and write them into the serial port (are you sure you are not overfilling the serial port?), then loop back around and read another. That way memory doesn't get lost if you miss a `free(buf)` and you'll have fewer problems with memory fragmentation. – user4581301 Feb 17 '16 at 22:39
  • Now that I'm done reading through all that, this question cannot be answered without information on `serialRead` and `serialWrite`. – user4581301 Feb 17 '16 at 22:46
  • *"Here is my code to send the jpeg:* -- Don't **lseek()** to determine the file length. Use **fstat()**. There's no reason to **malloc()** and have the entire source file in memory. In order to use XBee, you're going to have to *packetize* the data into small chunks. Each chunk will need a header consisting of a sequence number and payload length. The header and small chunk of data wrapped up in the XBee API packet is what you have to write to the XBee radio device. On the receive size the XBee packet has to be stripped off, and the header is used for reliable transfer like TCP. – sawdust Feb 18 '16 at 08:04

1 Answers1

0

If you are defining your own protocol, then you need to have a method for sending the length first.

I would recommend testing your code by sending short blocks of ascii text to confirm your i/o. Once that is working you can use the ascii to set up the transfer; ie send the length, and have your receiver ready for an expected block.

john elemans
  • 2,578
  • 2
  • 15
  • 26