Files
usbserial-dw/YmodemFileReceive.cpp
2021-09-01 16:19:16 +02:00

265 lines
6.5 KiB
C++

#include "YmodemFileReceive.h"
#include <iostream>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread/thread.hpp>
#include <boost/bind.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/log/trivial.hpp>
#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);
}