Send Camera Image over XBee

Has anyone sent an image from the Camera from one XBee to another? If so, could you post the code?

I have been able to send text information over XBee, but image data seems to be more difficult. Here is the current code:

//Receive information at the base station
void baseCommSerialLine_DataReceived(GT.Interfaces.Serial sender, System.IO.Ports.SerialData data)
{

        if (sender.BytesToRead == 0)
            return;
        byte[] bytes = new byte[sender.BytesToRead];
        sender.Read(bytes, 0, sender.BytesToRead);

        string text = new string(System.Text.Encoding.UTF8.GetChars(bytes));
        display_T35.SimpleGraphics.Clear();
        display_T35.SimpleGraphics.DisplayText("Position: " + text, Resources.GetFont(Resources.FontResources.NinaB), GT.Color.White, 5, 5);
        xBee.SerialLine.Flush();
    }

//Send data to the base station
//Make sure remoteComm is open
if (xBee2.SerialLine.IsOpen != true)
{
xBee2.SerialLine.Open();
}

        //Send remoteComm GPS position to the baseComm
        xBee2.SerialLine.Write(System.Text.Encoding.UTF8.GetBytes(gps.LastPosition + "\r\n"));
        xBee2.SerialLine.Flush();
        
        //Send remoteComm Image to the baseComm
        xBee2.SerialLine.Write(System.Text.Encoding.UTF8.GetBytes(image.ToString()) + "\r\n");
        xBee2.SerialLine.Flush();

Updated code that should work if a buffer was made.

//Store an image
void camera_PictureCaptured(Camera sender, GT.Picture picture)
{
image = picture.MakeBitmap();
}

//Send camera data to base

        camera.TakePicture();
        xBee2.SerialLine.Write(image.GetBitmap());

//Receive image and show on LCD
void baseCommSerialLine_DataReceived(GT.Interfaces.Serial sender, System.IO.Ports.SerialData data)
{
if (sender.BytesToRead == 0)
return;

        byte[] bytes = new byte[sender.BytesToRead];
        sender.Read(bytes, 0, sender.BytesToRead);
        display_T35.SimpleGraphics.DisplayImage(new Bitmap(bytes, Bitmap.BitmapImageType.Bmp), 0, 0);

}

So the first thing I saw in your first code is that you just used ToString on the image - never going to work reliably. If you want it “visible” then you need to encode it properly and decode it on the other end, but you should just be able to send it as-is.

You’re also likely better off with your own “encapsulation” protocol, that would be something like a start-of-send marker, followed by an encoded length of image followed by a mid-point delimiter followed by the data and finally a end-of-message terminator. So something like

!!!49543||?!?

where !!! is your start,
49543 is the byte length,
|| delimiter for the length,
?!? is the terminator.

First though, construct or capture and record a regular bitmap, or even just a known set of data, and then start attempting to send it. Make sure the data you send is being received as you expect on the other side. There’s no point trying to decode it and failing if you are not getting the right bytes over the wire. Only move on to reconstructing the image when you know you have the encoding/transmission working as you’d expect.

I think that two issues are currently occurring:

  1. I think there is a buffering issue
  2. It seems that when I send a string with a delimiter, the data is received, however when I send byte[] data, there is no delimiter and so there is no trigger on the receiver to start processing.

How does one send byte[] data with a delimiter?

Current sender code:
Bitmap image; - defined at the class level

camera.TakePicture();
xBee2.SerialLine.Write(image.GetBitmap(),0,image.GetBitmap().Length);

Current receiver code that never get triggered:

byte[] bytes = new byte[sender.BytesToRead];
while (sender.BytesToRead > 0)
{
sender.Read(bytes, 0, 4096);
}
display_T35.SimpleGraphics.Clear();
display_T35.SimpleGraphics.DisplayImage(new Bitmap(bytes, Bitmap.BitmapImageType.Bmp), 0, 0);

Latest Code

   void sendRemote2Base()
    {
        //Send remoteComm GPS position to the baseComm
        //xBee2.SerialLine.Write(System.Text.Encoding.UTF8.GetBytes(gps.LastPosition + "\r\n"));
        //xBee2.SerialLine.Flush();
        
        //Send remoteComm Image to the baseComm
        camera.TakePicture();
        Debug.Print("Took a picture");
        byte[] buffer = image.GetBitmap();
        if (xBee2.SerialLine.IsOpen != true)
        {
            xBee2.SerialLine.Open();
        }
        Debug.Print("Remote open");
        Debug.Print("Buffer length: " + buffer.Length.ToString());
        xBee2.SerialLine.Write(buffer, 0, buffer.Length);
        Debug.Print("Remote sent");
        xBee2.SerialLine.Flush();
        xBee2.SerialLine.Write(System.Text.Encoding.UTF8.GetBytes("\r\n"));
        Debug.Print("CR sent");
        xBee2.SerialLine.Flush();
        Debug.Print("Remote flushed");
        Thread.Sleep(1000);
    }

you’re thinking of data wrongly.

datareceived events are generated when there is ANY data available. There is no guarantee that you will get one event that signifies the whole data is transferred. You will get a group of events over time, and finally you’ll have all the data you need and you can recompile it together and use it as it’s original version.

So start creating a buffer on the receiver and pump data into that, and then when you get to the end of the stream of data, you can then use it.

I’m not sure how to get the base station to collect the data without the datarecieved event. Is there an example? Everything that I have seen so far is on the dataRecieved event.

You can still use data received event. You just need to buffer it in an external buffer/queue until you have all your data. Alternatively you can use the read method to get the data a character at a time, which can actually be an easier way to structure this kind of pattern.

Hi,
I think you can find solutions for your problem in this CodeShare entries
https://www.ghielectronics.com/community/codeshare/entry/697
or in my file transfer App for Bluetooth
https://www.ghielectronics.com/community/codeshare/entry/823
the task is file transfer (or byte array transfer) over a serial port.
On the first stage it is you must have a level of communication between the two devices.

  1. The device that shall receive the picture (Server) has to listen for commands of the other device (client).
  2. The client sends a command that the next thing it wants to do is a file transfer. With this command together it sends the length of the file to transfer.
  3. The Server switches its mode from parsing commands to: receiving incoming data and store them somewhere. If it is ready to receive the data it sends a message (receipt) to the client.
  4. The client sends the file or byte array (in chunks) over the connection and switches back to the command mode when it is ready
  5. The server gets all incoming data until all bytes are received, then sends a receipt and switches back to the command mode.

What is the size of your picture file, small files can be stored in memory (which FEZ Device?) for large files you perhaps need an SD-Card.
Regards
Roland