Boost logo

Boost Users :

Subject: [Boost-users] asio: serial ports and timeouts
From: KessiMC (pascal_kesseli_at_[hidden])
Date: 2009-06-17 08:58:19


Hi again

I was playing around with asio a bit, creating the following class:

AsioPlayground::AsioPlayground() :
    maxCharDelay(seconds(10)), charTimeout(io, maxCharDelay), port(io,
"COM2") {
    port.set_option(serial_port_base::baud_rate(9600));
    port.set_option(serial_port_base::character_size(7));
   
port.set_option(serial_port_base::flow_control(serial_port_base::flow_control::none));
   
port.set_option(serial_port_base::parity(serial_port_base::parity::even));
   
port.set_option(serial_port_base::stop_bits(serial_port_base::stop_bits::one));
}

AsioPlayground::~AsioPlayground() {
}

template<>
void AsioPlayground::write<string>(const string &value) {
    boost::asio::write(port, buffer(value, value.size()));
}

template<>
void AsioPlayground::write<char>(const char &c) {
    boost::asio::write(port, buffer(&c, 1));
}

template<>
char AsioPlayground::read<char>() {
    function<void(const error_code &)> onTimeout =
bind(&AsioPlayground::onTimeout, this, _1);
    charTimeout.async_wait(onTimeout);

    function<void(const error_code &, size_t)> onSuccess =
bind(&AsioPlayground::onSuccess, this,
            _1, _2);
    char input = '\0';
    async_read(port, buffer(&input, 1), onSuccess);
    error_code ec;
    io.run(ec);
    return input;
}

string AsioPlayground::read(int numberOfCharacters) {
    string input;
    for (int i = 0; i < numberOfCharacters; ++i) {
        input.push_back(read<char> ());
    }
    return input;
}

void AsioPlayground::onSuccess(const error_code &ec, size_t size) {
    charTimeout.cancel();
}

void AsioPlayground::onTimeout(const error_code &ec) {
    if (ec != error::operation_aborted) {
        throw InterfaceTimeoutException("No response");
    }
}

int AsioPlayground::main(const vector<string> &args) {
    AsioPlayground play;
    play.write<string> ("/?12345678!\r\n");

    try {
        cout << "Reply: " << play.read(10) << endl;
    } catch (const InterfaceTimeoutException &ex) {
        cout << ex.what() << endl;
    }

    return 0;
}

Executing the main function should have an expected behaviour of writing the
string to the other party, and reading at least 10 characters or failing
with a timeout exception. The timeout is meant to work as a character delay,
allowing a maximum of 10 seconds between each transmitted character before
failing.

The writing part works A-ok. The reading throws the expected exception if no
characters are transmitted by the oppositing device. However, if I transmit
9 characters from the device, these characters are displayed, appended by a
'\0' character (or whichever character I choose as default in read<char>()).

io.run() seems to return immediately, not even waiting for any characters to
be transmitted. Adding completion_conditions to async_read(), like
transfer_all() or transfer_at_least(1) did not do the trick, either.

What is going wrong here?

Thanks for any suggestions and greeetz
Pascal

-- 
View this message in context: http://www.nabble.com/asio%3A-serial-ports-and-timeouts-tp24073127p24073127.html
Sent from the Boost - Users mailing list archive at Nabble.com.

Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net