An example program for SerialFileTransfer, receives files from a java application and stores them on the LocalFileSystem
Dependencies: MODSERIAL SerialFileTransfer SimpleSerialProtocol mbed
SerialFileReceiver allow the mbed to receive a file using binary packets over the serial connection,
you can test the library with this java application /media/uploads/p3p/mbedserialfiletransfer.zip
the arguments to the command are, Comport Baudrate file to see the console output use java, not javaw
Example command: java -jar SerialTransfer.jar com3 115200 test.bin
Revision 0:a0abf3eff698, committed 2014-08-27
- Comitter:
- p3p
- Date:
- Wed Aug 27 17:51:48 2014 +0000
- Child:
- 1:7bba1d7d9680
- Commit message:
- Initial Commit, Using the SimpleSerialProtocol library to send files to the mbed
Changed in this revision
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/MODSERIAL.lib Wed Aug 27 17:51:48 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/AjK/code/MODSERIAL/#ae0408ebdd68
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SerialFileTransfer.cpp Wed Aug 27 17:51:48 2014 +0000 @@ -0,0 +1,106 @@ +#include "SerialFileTransfer.h" + +extern Serial debug; + +LocalFileSystem local("local"); + +void SFTProtocol::update(SimpleSerialProtocol::Protocol* comms){ + if(last_chunk_timer.read_ms() > 100 && transfer_in_progress){ + last_chunk_timer.reset(); + packet_retry_attempts++; + if(packet_retry_attempts > 50){ + ack(comms, 3); + //debug.printf("Transfer Timeout\r\n"); + packet_retry_attempts = 0; + transfer_in_progress = false; + chunks_last = 0; + chunks_total = 0; + fclose(fp); + fp = 0; + last_chunk_timer.stop(); + last_chunk_timer.reset(); + } else { + //debug.printf("Request Packet Resend %d, %d\r\n", comms->droppedBytes(), comms->_corrupt_packets); + ack(comms, 2); + } + } +} + +void SFTProtocol::onFileStart(SimpleSerialProtocol::Protocol* comms, SimpleSerialProtocol::Packet* packet){ + if(!packet)return; + if (packet->_valid) { + FileStartPacket::Interface* interface = packet->interpretData<FileStartPacket::Interface>(); + if (interface) { + //debug.printf("%s.%s has %d chunks\r\n", interface->name, interface->ext, interface->chunks); + + char buffer[25]; + sprintf(buffer, "/local/%s.%s", interface->name, interface->ext); + fp = fopen(buffer, "w"); + if(fp){ + transfer_in_progress = true; + chunks_total = interface->chunks; + ack(comms, 0); + last_chunk_timer.start(); + } + } + } + return; +} + +void SFTProtocol::onFileStream(SimpleSerialProtocol::Protocol* comms, SimpleSerialProtocol::Packet* packet){ + if(!packet)return; + if(transfer_in_progress){ + if (packet->_valid) { + FileStreamPacket::Interface* interface = packet->interpretData<FileStreamPacket::Interface>(); + if (interface) { + //debug.printf("%d,%d\r\n", interface->chunk, interface->length); + //if(rand()%5 < 1){ //1in5 packet loss emulation + if((interface->chunk <= chunks_last + 1) && fp ){ + + if(interface->chunk == chunks_last + 1){ + chunks_last = interface->chunk; + fwrite(interface->data, 1, interface->length, fp); + } else { + //debug.printf("Allready have chunk %d\r\n", interface->chunk); + } + + if(chunks_last == chunks_total){ + //debug.printf("Transfer Complete: Acked\r\n"); + ack(comms, 1); + fclose(fp); + fp = 0; + transfer_in_progress = false; + chunks_last = 0; + chunks_total = 0; + last_chunk_timer.stop(); + last_chunk_timer.reset(); + }else{ + ack(comms, 0); + packet_retry_attempts = 0; + last_chunk_timer.reset(); + } + + } else { + //debug.printf("Transfer Failed: chunk dropped or out of order\r\n"); + transfer_in_progress = false; + chunks_last = 0; + chunks_total = 0; + fclose(fp); + fp = 0; + ack(comms, 3); + last_chunk_timer.stop(); + last_chunk_timer.reset(); + } + } + //} + } + } + return; +} + +void SFTProtocol::ack(SimpleSerialProtocol::Protocol* comms, uint8_t ack_type) { + AckFileStartPacket message; + message.interface.ack_type = ack_type; + message.buildData<AckFileStartPacket::Interface>(&message.interface); + comms->sendPacket(&message); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SerialFileTransfer.h Wed Aug 27 17:51:48 2014 +0000 @@ -0,0 +1,97 @@ +#ifndef _SFT_PROTOCOL_H +#define _SFT_PROTOCOL_H + +#include <mbed.h> +#include <SimpleSerialProtocol/Protocol.h> + +//class will receive a packet and echo it back out +class SFTProtocol { +public: + SFTProtocol() { //LED1 to 4 for a status led, NC to disable + transfer_in_progress = false; + chunks_total = 0; + chunks_last = 0; + packet_retry_attempts = 0; + fp = 0; + } + virtual ~SFTProtocol() {}; + + //the callbacks and packet sending methods + virtual void update(SimpleSerialProtocol::Protocol* comms); + void onFileStart(SimpleSerialProtocol::Protocol* comms, SimpleSerialProtocol::Packet* packet); + void ack(SimpleSerialProtocol::Protocol* comms, uint8_t ack_type); + void onFileStream(SimpleSerialProtocol::Protocol* comms, SimpleSerialProtocol::Packet* packet); + + //variables to control the transfer and save the file + bool transfer_in_progress; + int chunks_total; + int chunks_last; + Timer last_chunk_timer; + int packet_retry_attempts; + FILE *fp; + + + //This packed is used to start a file transfer it is sent by the client + //once received a file is created and an ack packet sent to start the file stream + class FileStartPacket : public SimpleSerialProtocol::Packet { + public: + FileStartPacket() {} + virtual ~FileStartPacket() {} + +#pragma pack(push, 1) //must pack the structure to byte boundary for raw recast to work reliably + struct Interface { + Interface() { + type = 1; // initialise the type + } + uint8_t type; + uint8_t name[9]; + uint8_t ext[4]; + uint32_t chunks; + } interface; +#pragma pack(pop) + + }; + + //A very simple Ack packet used to inform the client that we need more data, and other commands based on the ack_type value + class AckFileStartPacket : public SimpleSerialProtocol::Packet { + public: + AckFileStartPacket() {} + virtual ~AckFileStartPacket() {} + +#pragma pack(push, 1) //must pack the structure to byte boundary for raw recast to work reliably + struct Interface { + Interface() { + type = 2; // initialise the type + } + uint8_t type; + uint8_t ack_type; + } interface; +#pragma pack(pop) + + }; + + //This is the packet used to send the file data 128 bytes at a time + //its posible to send upto 256 bytes but this was causing my xbees to drop a lot of data + class FileStreamPacket : public SimpleSerialProtocol::Packet { + public: + FileStreamPacket() { } + virtual ~FileStreamPacket() {} + +#pragma pack(push, 1) //must pack the structure to byte boundary for raw recast to work reliably + struct Interface { + Interface() { + type = 3; // initialise the type + } + uint8_t type; + uint16_t chunk; + uint8_t length; + uint8_t data[128]; + + } interface; +#pragma pack(pop) + + }; + +}; + +#endif \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SimpleSerialProtocol.lib Wed Aug 27 17:51:48 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/p3p/code/SimpleSerialProtocol/#98ad30934a71
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Wed Aug 27 17:51:48 2014 +0000 @@ -0,0 +1,29 @@ +#include "mbed.h" +#include "SerialFileTransfer.h" + +//Create an instance of the SimpleSerialProtocol on a Serial port, optionaly choose a status led +SimpleSerialProtocol::Protocol comms(USBTX, USBRX, LED1); + +Serial debug(p13,p14); + +SFTProtocol fileAcceptor; + +int main() { + //initialise the comm port at 155200 baud + comms.initialise(115200); + //listen for packets of type 1 and relay the data to the onFileStart callback in SFTProtocol + comms.receiveCallback(1, &fileAcceptor, &SFTProtocol::onFileStart); + //listen for packets of type 3 and relay + comms.receiveCallback(3, &fileAcceptor, &SFTProtocol::onFileStream); + + debug.baud(115200); + debug.printf("Debug Terminal:\r\n"); + + while(true){ + //the protocol needs constant updates to process packets and forward the data + comms.update(); + + //the SFTProtocol is updated so it can timeout, and request packet resends, + fileAcceptor.update(&comms); + } +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Wed Aug 27 17:51:48 2014 +0000 @@ -0,0 +1,1 @@ +http://mbed.org/users/mbed_official/code/mbed/builds/9327015d4013 \ No newline at end of file