Adds file transfer capability to SimpleSerialProtocol

Dependents:   SerialFileReceiver

Revision:
0:31dff1f79b4f
Child:
1:f8aaff9c57e3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/SerialFileTransfer.cpp	Wed Aug 27 17:59:05 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