#include "YmodemFileReceive.h" #include #include #include #include #include #include #include #include "TimeoutSerial.h" using namespace std; using namespace boost; #define READ_TIME_OUT (10) #define WRITE_TIME_OUT (100) YmodemFileReceive::YmodemFileReceive() : io(), readTimer(io), writeTimer(io) { setTimeDivide(499); setTimeMax(5); setErrorMax(999); } YmodemFileReceive::~YmodemFileReceive() { // delete file; // delete readTimer; // delete writeTimer; // delete serialPort; } void YmodemFileReceive::setFilePath(const string &path) { filePath = path + "/"; } void YmodemFileReceive::setDefaultFileName(const string &file) { defaultFileName = file; } void YmodemFileReceive::setSerialPort(TimeoutSerial *port) { serialPort = port; } TimeoutSerial *YmodemFileReceive::getSerialPort() { return serialPort; } bool YmodemFileReceive::startReceive() { progress = 0; status = StatusEstablish; BOOST_LOG_TRIVIAL(debug) << "Statring receive"; serialPort->setTimeout(posix_time::seconds(0)); readTimer.expires_from_now(boost::posix_time::millisec(READ_TIME_OUT)); readTimer.async_wait(boost::bind(&YmodemFileReceive::readTimeOut,this,_1)); io.run(); return true; } void YmodemFileReceive::stopReceive() { file.close(); abort(); status = StatusAbort; } int YmodemFileReceive::getReceiveProgress() { return progress; } Ymodem::Status YmodemFileReceive::getReceiveStatus() { return status; } void YmodemFileReceive::readTimeOut(const boost::system::error_code& e) { BOOST_LOG_TRIVIAL(debug) << "Read timeout"; receive(); BOOST_LOG_TRIVIAL(debug) << "Status: " << status; if((status == StatusEstablish) || (status == StatusTransmit)) { BOOST_LOG_TRIVIAL(debug) << "Set read timer "; readTimer.expires_from_now(boost::posix_time::millisec(READ_TIME_OUT)); readTimer.async_wait(boost::bind(&YmodemFileReceive::readTimeOut,this,_1)); } } void YmodemFileReceive::writeTimeOut(const boost::system::error_code& e) { writeTimer.cancel(); //serialPort->close(); receiveStatus(status); } Ymodem::Code YmodemFileReceive::callback(Status status, uint8_t *buff, uint32_t *len) { BOOST_LOG_TRIVIAL(debug) << "Callback status: " << status; switch(status) { case StatusEstablish: { if(buff[0] != 0) { int i = 0; char name[128] = {0}; char size[128] = {0}; for(int j = 0; buff[i] != 0; i++, j++) { name[j] = buff[i]; } i++; for(int j = 0; buff[i] != 0; i++, j++) { size[j] = buff[i]; } if (defaultFileName != "") { fileName = defaultFileName; } else { fileName = name; } string file_desc(size); string sizeStr = file_desc.substr(0,file_desc.find_first_of(' ')); fileSize = stol(sizeStr); fileCount = 0; BOOST_LOG_TRIVIAL(debug) << "File open: " << filePath + fileName ; file.open(filePath + fileName, ios::out | ios::binary); if(file.is_open() == true) { YmodemFileReceive::status = StatusEstablish; receiveStatus(StatusEstablish); return CodeAck; } else { YmodemFileReceive::status = StatusError; writeTimer.expires_from_now(boost::posix_time::millisec(WRITE_TIME_OUT)); writeTimer.async_wait(boost::bind(&YmodemFileReceive::writeTimeOut,this,_1)); return CodeCan; } } else { YmodemFileReceive::status = StatusError; writeTimer.expires_from_now(boost::posix_time::millisec(WRITE_TIME_OUT)); writeTimer.async_wait(boost::bind(&YmodemFileReceive::writeTimeOut,this,_1)); return CodeCan; } } case StatusTransmit: { if((fileSize - fileCount) > *len) { file.write((char *)buff, *len); fileCount += *len; } else { file.write((char *)buff, fileSize - fileCount); fileCount += fileSize - fileCount; } progress = (int)(fileCount * 100 / fileSize); YmodemFileReceive::status = StatusTransmit; receiveProgress(progress); receiveStatus(StatusTransmit); return CodeAck; } case StatusFinish: { file.close(); YmodemFileReceive::status = StatusFinish; writeTimer.expires_from_now(boost::posix_time::millisec(WRITE_TIME_OUT)); writeTimer.async_wait(boost::bind(&YmodemFileReceive::writeTimeOut,this,_1)); return CodeAck; } case StatusAbort: { file.close(); YmodemFileReceive::status = StatusAbort; writeTimer.expires_from_now(boost::posix_time::millisec(WRITE_TIME_OUT)); writeTimer.async_wait(boost::bind(&YmodemFileReceive::writeTimeOut,this,_1)); return CodeCan; } case StatusTimeout: { YmodemFileReceive::status = StatusTimeout; writeTimer.expires_from_now(boost::posix_time::millisec(WRITE_TIME_OUT)); writeTimer.async_wait(boost::bind(&YmodemFileReceive::writeTimeOut,this,_1)); return CodeCan; } default: { file.close(); YmodemFileReceive::status = StatusError; writeTimer.expires_from_now(boost::posix_time::millisec(WRITE_TIME_OUT)); writeTimer.async_wait(boost::bind(&YmodemFileReceive::writeTimeOut,this,_1)); return CodeCan; } } } uint32_t YmodemFileReceive::read(uint8_t *buff, uint32_t len) { return serialPort->read((char *)buff, len); } uint32_t YmodemFileReceive::write(uint8_t *buff, uint32_t len) { return serialPort->write((char *)buff, len); }