asio: serial ports and timeouts
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.... Sent from the Boost - Users mailing list archive at Nabble.com.
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.
Could you clarify the above 2 sentences? If these characters are displayed, they have been received, right?
Well, if I transmit 9 characters (or less, whatever), e.g. "012345678", these characters are displayed, followed by a '\0'. Transmitting only 6 characters displays these 6 characters, e.g. "012345" and 4 appended '\0' characters. That's not what I want, I want the program to block and wait for the 10th character in the first example or the 7th, 8th, 9th and 10th character in the second example. Igor R wrote:
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.
Could you clarify the above 2 sentences? If these characters are displayed, they have been received, right?
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- View this message in context: http://www.nabble.com/asio%3A-serial-ports-and-timeouts-tp24073127p24076926.... Sent from the Boost - Users mailing list archive at Nabble.com.
Well, if I transmit 9 characters (or less, whatever), e.g. "012345678", these characters are displayed, followed by a '\0'.
Transmitting only 6 characters displays these 6 characters, e.g. "012345" and 4 appended '\0' characters. That's not what I want, I want the program to block and wait for the 10th character in the first example or the 7th, 8th, 9th and 10th character in the second example.
Ok, I see... I don't really understand why you wish to async_read() char-by-char and to re-run io_service each time, instead of reading N chars at once into a buffer, but if you prefer to do so, you have to call io_service::reset() before any subsequent call to run(): //... io.reset(); io.run(); //....
Thanks, man, that was the problem :-) . I do read them char-by-char because I need to specify the maximum delay between each character using async_wait(). If I read all 10 characters at once, I could only specify the maximum time for the transmission of all characters, not the allowed delay between each one. The protocol I am implementing strictly relies on a maximum character delay between each subsequent character. Thanks and greeets Pascal Igor R wrote:
Well, if I transmit 9 characters (or less, whatever), e.g. "012345678", these characters are displayed, followed by a '\0'.
Transmitting only 6 characters displays these 6 characters, e.g. "012345" and 4 appended '\0' characters. That's not what I want, I want the program to block and wait for the 10th character in the first example or the 7th, 8th, 9th and 10th character in the second example.
Ok, I see... I don't really understand why you wish to async_read() char-by-char and to re-run io_service each time, instead of reading N chars at once into a buffer, but if you prefer to do so, you have to call io_service::reset() before any subsequent call to run(): //... io.reset();
io.run(); //....
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
-- View this message in context: http://www.nabble.com/asio%3A-serial-ports-and-timeouts-tp24073127p24077539.... Sent from the Boost - Users mailing list archive at Nabble.com.
participants (2)
-
Igor R
-
KessiMC