Adds file transfer capability to SimpleSerialProtocol
Dependents: SerialFileReceiver
SerialFileTransfer.cpp@1:f8aaff9c57e3, 2014-09-18 (annotated)
- Committer:
- p3p
- Date:
- Thu Sep 18 17:48:59 2014 +0000
- Revision:
- 1:f8aaff9c57e3
- Parent:
- 0:31dff1f79b4f
Updated to reflect changes in SimpleSErialProtocol
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
p3p | 0:31dff1f79b4f | 1 | #include "SerialFileTransfer.h" |
p3p | 0:31dff1f79b4f | 2 | |
p3p | 0:31dff1f79b4f | 3 | extern Serial debug; |
p3p | 0:31dff1f79b4f | 4 | |
p3p | 0:31dff1f79b4f | 5 | LocalFileSystem local("local"); |
p3p | 0:31dff1f79b4f | 6 | |
p3p | 0:31dff1f79b4f | 7 | void SFTProtocol::update(SimpleSerialProtocol::Protocol* comms){ |
p3p | 0:31dff1f79b4f | 8 | if(last_chunk_timer.read_ms() > 100 && transfer_in_progress){ |
p3p | 0:31dff1f79b4f | 9 | last_chunk_timer.reset(); |
p3p | 0:31dff1f79b4f | 10 | packet_retry_attempts++; |
p3p | 0:31dff1f79b4f | 11 | if(packet_retry_attempts > 50){ |
p3p | 0:31dff1f79b4f | 12 | ack(comms, 3); |
p3p | 0:31dff1f79b4f | 13 | //debug.printf("Transfer Timeout\r\n"); |
p3p | 0:31dff1f79b4f | 14 | packet_retry_attempts = 0; |
p3p | 0:31dff1f79b4f | 15 | transfer_in_progress = false; |
p3p | 0:31dff1f79b4f | 16 | chunks_last = 0; |
p3p | 0:31dff1f79b4f | 17 | chunks_total = 0; |
p3p | 0:31dff1f79b4f | 18 | fclose(fp); |
p3p | 0:31dff1f79b4f | 19 | fp = 0; |
p3p | 0:31dff1f79b4f | 20 | last_chunk_timer.stop(); |
p3p | 0:31dff1f79b4f | 21 | last_chunk_timer.reset(); |
p3p | 0:31dff1f79b4f | 22 | } else { |
p3p | 0:31dff1f79b4f | 23 | //debug.printf("Request Packet Resend %d, %d\r\n", comms->droppedBytes(), comms->_corrupt_packets); |
p3p | 0:31dff1f79b4f | 24 | ack(comms, 2); |
p3p | 0:31dff1f79b4f | 25 | } |
p3p | 0:31dff1f79b4f | 26 | } |
p3p | 0:31dff1f79b4f | 27 | } |
p3p | 0:31dff1f79b4f | 28 | |
p3p | 0:31dff1f79b4f | 29 | void SFTProtocol::onFileStart(SimpleSerialProtocol::Protocol* comms, SimpleSerialProtocol::Packet* packet){ |
p3p | 0:31dff1f79b4f | 30 | if(!packet)return; |
p3p | 0:31dff1f79b4f | 31 | if (packet->_valid) { |
p3p | 0:31dff1f79b4f | 32 | FileStartPacket::Interface* interface = packet->interpretData<FileStartPacket::Interface>(); |
p3p | 0:31dff1f79b4f | 33 | if (interface) { |
p3p | 0:31dff1f79b4f | 34 | //debug.printf("%s.%s has %d chunks\r\n", interface->name, interface->ext, interface->chunks); |
p3p | 0:31dff1f79b4f | 35 | |
p3p | 0:31dff1f79b4f | 36 | char buffer[25]; |
p3p | 0:31dff1f79b4f | 37 | sprintf(buffer, "/local/%s.%s", interface->name, interface->ext); |
p3p | 0:31dff1f79b4f | 38 | fp = fopen(buffer, "w"); |
p3p | 0:31dff1f79b4f | 39 | if(fp){ |
p3p | 0:31dff1f79b4f | 40 | transfer_in_progress = true; |
p3p | 0:31dff1f79b4f | 41 | chunks_total = interface->chunks; |
p3p | 0:31dff1f79b4f | 42 | ack(comms, 0); |
p3p | 0:31dff1f79b4f | 43 | last_chunk_timer.start(); |
p3p | 0:31dff1f79b4f | 44 | } |
p3p | 0:31dff1f79b4f | 45 | } |
p3p | 0:31dff1f79b4f | 46 | } |
p3p | 0:31dff1f79b4f | 47 | return; |
p3p | 0:31dff1f79b4f | 48 | } |
p3p | 0:31dff1f79b4f | 49 | |
p3p | 0:31dff1f79b4f | 50 | void SFTProtocol::onFileStream(SimpleSerialProtocol::Protocol* comms, SimpleSerialProtocol::Packet* packet){ |
p3p | 0:31dff1f79b4f | 51 | if(!packet)return; |
p3p | 0:31dff1f79b4f | 52 | if(transfer_in_progress){ |
p3p | 0:31dff1f79b4f | 53 | if (packet->_valid) { |
p3p | 0:31dff1f79b4f | 54 | FileStreamPacket::Interface* interface = packet->interpretData<FileStreamPacket::Interface>(); |
p3p | 0:31dff1f79b4f | 55 | if (interface) { |
p3p | 0:31dff1f79b4f | 56 | //debug.printf("%d,%d\r\n", interface->chunk, interface->length); |
p3p | 0:31dff1f79b4f | 57 | //if(rand()%5 < 1){ //1in5 packet loss emulation |
p3p | 0:31dff1f79b4f | 58 | if((interface->chunk <= chunks_last + 1) && fp ){ |
p3p | 0:31dff1f79b4f | 59 | |
p3p | 0:31dff1f79b4f | 60 | if(interface->chunk == chunks_last + 1){ |
p3p | 0:31dff1f79b4f | 61 | chunks_last = interface->chunk; |
p3p | 0:31dff1f79b4f | 62 | fwrite(interface->data, 1, interface->length, fp); |
p3p | 0:31dff1f79b4f | 63 | } else { |
p3p | 0:31dff1f79b4f | 64 | //debug.printf("Allready have chunk %d\r\n", interface->chunk); |
p3p | 0:31dff1f79b4f | 65 | } |
p3p | 0:31dff1f79b4f | 66 | |
p3p | 0:31dff1f79b4f | 67 | if(chunks_last == chunks_total){ |
p3p | 0:31dff1f79b4f | 68 | //debug.printf("Transfer Complete: Acked\r\n"); |
p3p | 0:31dff1f79b4f | 69 | ack(comms, 1); |
p3p | 0:31dff1f79b4f | 70 | fclose(fp); |
p3p | 0:31dff1f79b4f | 71 | fp = 0; |
p3p | 0:31dff1f79b4f | 72 | transfer_in_progress = false; |
p3p | 0:31dff1f79b4f | 73 | chunks_last = 0; |
p3p | 0:31dff1f79b4f | 74 | chunks_total = 0; |
p3p | 0:31dff1f79b4f | 75 | last_chunk_timer.stop(); |
p3p | 0:31dff1f79b4f | 76 | last_chunk_timer.reset(); |
p3p | 0:31dff1f79b4f | 77 | }else{ |
p3p | 0:31dff1f79b4f | 78 | ack(comms, 0); |
p3p | 0:31dff1f79b4f | 79 | packet_retry_attempts = 0; |
p3p | 0:31dff1f79b4f | 80 | last_chunk_timer.reset(); |
p3p | 0:31dff1f79b4f | 81 | } |
p3p | 0:31dff1f79b4f | 82 | |
p3p | 0:31dff1f79b4f | 83 | } else { |
p3p | 0:31dff1f79b4f | 84 | //debug.printf("Transfer Failed: chunk dropped or out of order\r\n"); |
p3p | 0:31dff1f79b4f | 85 | transfer_in_progress = false; |
p3p | 0:31dff1f79b4f | 86 | chunks_last = 0; |
p3p | 0:31dff1f79b4f | 87 | chunks_total = 0; |
p3p | 0:31dff1f79b4f | 88 | fclose(fp); |
p3p | 0:31dff1f79b4f | 89 | fp = 0; |
p3p | 0:31dff1f79b4f | 90 | ack(comms, 3); |
p3p | 0:31dff1f79b4f | 91 | last_chunk_timer.stop(); |
p3p | 0:31dff1f79b4f | 92 | last_chunk_timer.reset(); |
p3p | 0:31dff1f79b4f | 93 | } |
p3p | 0:31dff1f79b4f | 94 | } |
p3p | 0:31dff1f79b4f | 95 | //} |
p3p | 0:31dff1f79b4f | 96 | } |
p3p | 0:31dff1f79b4f | 97 | } |
p3p | 0:31dff1f79b4f | 98 | return; |
p3p | 0:31dff1f79b4f | 99 | } |
p3p | 0:31dff1f79b4f | 100 | |
p3p | 0:31dff1f79b4f | 101 | void SFTProtocol::ack(SimpleSerialProtocol::Protocol* comms, uint8_t ack_type) { |
p3p | 0:31dff1f79b4f | 102 | AckFileStartPacket message; |
p3p | 0:31dff1f79b4f | 103 | message.interface.ack_type = ack_type; |
p3p | 0:31dff1f79b4f | 104 | message.buildData<AckFileStartPacket::Interface>(&message.interface); |
p3p | 1:f8aaff9c57e3 | 105 | comms->send(&message); |
p3p | 0:31dff1f79b4f | 106 | } |