导航

The 1st Boost Serial Demo

Posted on 2010-12-28 14:16  hcfalan  阅读(726)  评论(0编辑  收藏  举报

// TestBoost.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include "stdio.h"
#include <afx.h>
#include <WinSock2.h>
#include "StringUtil.h"
#include <string>
#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
#include <boost/function.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/regex.hpp>

wchar_t g_szSourceFile[256];
wchar_t g_szDestFile[256];

//////////////////////////////////////////////////////////////////////////
//
// serial port test

typedef boost::system::error_code boost_error_code;
typedef boost::asio::deadline_timer asio_timer;
typedef boost::asio::serial_port asio_serial;

//////////////////////////////////////////////////////////////////////////

static std::string FileEncodePath(const wchar_t* fs)
{
    CW2A aFullPath(fs);
    char buffer[1024];
    char temptxt[4];
    std::string retstr;
    int num;

    num = MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, aFullPath, -1,
        (wchar_t *) buffer,  sizeof(buffer)/2);
    num--; // not count the null

    for (int i=0; i<num*2; i++)  //fill data
    {
        if ((i%2)==0)
            *((wchar_t*)&(buffer[i])) = htons(*((wchar_t*) &(buffer[i])));
        ZeroMemory(temptxt, sizeof(temptxt));
        sprintf(temptxt, "%02X", (unsigned char) buffer[i]);
        retstr += temptxt;
    }
    return retstr;
}

static bool check_buffer(boost::asio::streambuf& buf)
{
    std::istream is(&buf);
    is.unsetf(std::ios_base::skipws);

    std::string sz;
    sz.append(std::istream_iterator<char>(is), std::istream_iterator<char>());

    std::cout << sz;

    return (sz.find("\r\nOK\r\n") != -1);
}

static bool send_command(boost::shared_ptr<asio_serial> sp, const char* cmd)
{
    boost::regex reg_util("\r\nOK\r\n|\r\nERROR\r\n");
    boost::asio::streambuf sbuf;
    boost::asio::write(*sp, boost::asio::buffer(cmd, strlen(cmd)));
    boost::asio::read_until(*sp, sbuf, reg_util);
    return check_buffer(sbuf);
}

#define BLOCK_SIZE 400

// 下载文件实现方式:
static void UploadFile(boost::shared_ptr<asio_serial> sp)
{
    // AT+EFSW=0 //create file
    // AT+EFSW=2 //write file
    // AT+EFSW=1 //close file
    std::string strCommand;
    CFile fileInput;
    std::string strName;

    // 切换
    strCommand = "AT+ESUO=3\r";
    printf("AT+ESUO=3\n");
    if (!send_command(sp, strCommand.c_str()))
        return;

    strCommand = "AT+EFSR\r";
    printf("AT+EFSR\n");
    if (!send_command(sp, strCommand.c_str()))
        goto ESUO;

    strCommand = "AT+ESUO=4\r";
    printf("AT+ESUO=4\n");
    if (!send_command(sp, strCommand.c_str()))
        return;

    strCommand = "AT+ESLP=0\r";
    printf("AT+ESLP=0\n");
    if (!send_command(sp, strCommand.c_str()))
        goto ESUO;

    strCommand = "AT+ESUO=3\r";
    printf("AT+ESUO=3\n");
    if (!send_command(sp, strCommand.c_str()))
        return;

    // 创建文件
    strName = FileEncodePath(g_szDestFile);
    String::format(strCommand, "AT+EFSW=0,\"%s\"\r", strName.c_str());
    printf("AT+EFSW=0\n");
    if (!send_command(sp, strCommand.c_str()))
        goto ESUO;

    //写文件   
    fileInput.Open(g_szSourceFile, CFile::modeRead);
    BYTE bufferInput[BLOCK_SIZE];
    int nReaded = 0;
    while ((nReaded = fileInput.Read(bufferInput, BLOCK_SIZE)) > 0)
    {
        if (nReaded == BLOCK_SIZE)
        {
            String::format(strCommand, "AT+EFSW=2, 0, %d, \"", BLOCK_SIZE);
        }
        else
        {
            String::format(strCommand, "AT+EFSW=2, 1, %d, \"", nReaded);
        }

        char tmp[16];
        for (int i=0; i<nReaded; i++)
        {
            sprintf(tmp, "%02X", bufferInput[i]);
            strCommand.append(tmp);
        }
        strCommand.append("\"\r");
        if (!send_command(sp, strCommand.c_str()))
        {
            fileInput.Close();
            goto ESUO;
        }

        double dPos = fileInput.GetPosition();
        double dTotal = fileInput.GetLength();
        double dPercent = 100 * dPos / dTotal;
        printf("percent: %02d\n", (int)dPercent);
    }

    fileInput.Close();
    // 关闭文件
    printf("AT+EFSW=1\n");
    String::format(strCommand, "AT+EFSW=1,\"%s\"\r", strName.c_str());
    send_command(sp, strCommand.c_str());

ESUO:
    // 切换回来
    printf("AT+ESUO=4\n");
    strCommand = "AT+ESUO=4\r";
    send_command(sp, strCommand.c_str());

}

//////////////////////////////////////////////////////////////////////////

void handle_read(boost::shared_ptr<boost::asio::streambuf> pbuf,
                 boost_error_code ec,
                 std::size_t bytes_transferred,
                 boost::shared_ptr<asio_timer> t)
{
    printf("length readed:%d\n", bytes_transferred);

    std::istream is(pbuf.get());
    is.unsetf(std::ios_base::skipws);
    std::string sz;
    sz.append(std::istream_iterator<char>(is), std::istream_iterator<char>());
    std::cout << sz;

    t->cancel();
}

void handle_wait(boost_error_code& error,
                 boost::shared_ptr<asio_serial> sp)
{
    if (error != boost::asio::error::operation_aborted)
    {
        //printf("serial port timeout, cancel it\n");
        sp->cancel();
    }
    else
    {
        //printf("wait has been canceled\n");
    }
}

int _tmain(int argc, _TCHAR* argv[])
{
    if (argc != 4)
    {
        std::cout << "upload file to mobile" << std::endl
            << "usage TestBoost <com port> <local file> <mobile file>"
            << std::endl;
        return 1;
    }

    boost::asio::io_service iosev;

    // 串口COM1, Linux下为“/dev/ttyS0”
    char com[32];
    int nComPort = _ttoi(argv[1]);

    _tcscpy(g_szSourceFile, argv[2]);
    _tcscpy(g_szDestFile, argv[3]);
    sprintf(com, "COM%d", nComPort);

    boost::shared_ptr<asio_serial> sp(new asio_serial(iosev, com));
    // 设置参数
    sp->set_option(asio_serial::baud_rate(115200));
    sp->set_option(asio_serial::flow_control(asio_serial::flow_control::none));
    sp->set_option(asio_serial::parity(asio_serial::parity::none));
    sp->set_option(asio_serial::stop_bits(asio_serial::stop_bits::one));
    sp->set_option(asio_serial::character_size(8));
    /*long t1 = GetTickCount();

    for (int i=0; i<1; i++)
    {

        char* b1 = "AT+CPBR=1\r";
        // 向串口写数据
        boost::asio::write(*sp, boost::asio::buffer(b1, strlen(b1)));

         boost::shared_ptr<asio_timer> t(
             new asio_timer(iosev));
         t->expires_from_now(boost::posix_time::millisec(3000));

        // 向串口读数据
        boost::shared_ptr<boost::asio::streambuf> pbuf(new boost::asio::streambuf());
        //boost::asio::async_read(*sp, boost::asio::buffer(buf),
        //    boost::bind(handle_read, buf, _1, _2));
        //sp->async_read_some(boost::asio::buffer(buf),
        //    boost::bind(handle_read, buf, _1, _2, t));
        boost::asio::async_read_until(*sp,  *pbuf,
            boost::regex("\r\nOK\r\n|\r\nERROR\r\n|\r\n>\r\n"),
            boost::bind(handle_read, pbuf, _1, _2, t));

        t->async_wait(boost::bind(handle_wait, _1, sp));

        size_t m = iosev.run();
        //printf("#%d run result %d\n", i, m);

        iosev.reset();
    }
    long t2 = GetTickCount();

    printf("\r\n\r\ntotal used %d\n", t2-t1);*/

    UploadFile(sp);

    sp->close();

    return 0;
}