29 #ifndef UBLOX_GPS_ASYNC_WORKER_H
30 #define UBLOX_GPS_ASYNC_WORKER_H
34 #include <boost/asio.hpp>
35 #include <boost/bind.hpp>
36 #include <boost/format.hpp>
37 #include <boost/thread.hpp>
38 #include <boost/thread/condition.hpp>
50 template <
typename StreamT>
64 std::size_t buffer_size = 8192);
84 bool send(
const unsigned char* data,
const unsigned int size);
89 void wait(
const boost::posix_time::time_duration& timeout);
104 void readEnd(
const boost::system::error_code&, std::size_t);
121 std::vector<unsigned char>
in_;
127 std::vector<unsigned char>
out_;
137 template <
typename StreamT>
140 std::size_t buffer_size)
144 in_.resize(buffer_size);
147 out_.reserve(buffer_size);
151 boost::bind(&boost::asio::io_service::run,
io_service_)));
154 template <
typename StreamT>
157 background_thread_->join();
161 template <
typename StreamT>
163 const unsigned int size) {
166 ROS_ERROR(
"Ublox AsyncWorker::send: Size of message to send is 0");
170 if (out_.capacity() - out_.size() < size) {
171 ROS_ERROR(
"Ublox AsyncWorker::send: Output buffer too full to send message");
174 out_.insert(out_.end(),
data,
data + size);
180 template <
typename StreamT>
184 if (out_.size() == 0) {
188 boost::asio::write(*stream_, boost::asio::buffer(out_.data(), out_.size()));
192 std::ostringstream oss;
193 for (std::vector<unsigned char>::iterator it = out_.begin();
194 it != out_.end(); ++it)
195 oss << boost::format(
"%02x") %
static_cast<unsigned int>(*it) <<
" ";
196 ROS_DEBUG(
"U-Blox sent %li bytes: \n%s", out_.size(), oss.str().c_str());
200 write_condition_.notify_all();
206 if (out_.size() == 0) {
210 stream_->send(boost::asio::buffer(out_.data(), out_.size()));
214 std::ostringstream oss;
215 for (std::vector<unsigned char>::iterator it = out_.begin();
216 it != out_.end(); ++it)
217 oss << boost::format(
"%02x") %
static_cast<unsigned int>(*it) <<
" ";
218 ROS_DEBUG(
"U-Blox sent %li bytes: \n%s", out_.size(), oss.str().c_str());
222 write_condition_.notify_all();
225 template <
typename StreamT>
228 stream_->async_read_some(
229 boost::asio::buffer(in_.data() + in_buffer_size_,
230 in_.size() - in_buffer_size_),
232 boost::asio::placeholders::error,
233 boost::asio::placeholders::bytes_transferred));
238 stream_->async_receive(
239 boost::asio::buffer(in_.data() + in_buffer_size_,
240 in_.size() - in_buffer_size_),
242 boost::asio::placeholders::error,
243 boost::asio::placeholders::bytes_transferred));
246 template <
typename StreamT>
248 std::size_t bytes_transfered) {
251 ROS_ERROR(
"U-Blox ASIO input buffer read error: %s, %li",
252 error.message().c_str(),
254 }
else if (bytes_transfered > 0) {
255 in_buffer_size_ += bytes_transfered;
257 unsigned char *pRawDataStart = &(*(in_.begin() + (in_buffer_size_ - bytes_transfered)));
258 std::size_t raw_data_stream_size = bytes_transfered;
261 write_callback_(pRawDataStart, raw_data_stream_size);
264 std::ostringstream oss;
265 for (std::vector<unsigned char>::iterator it =
266 in_.begin() + in_buffer_size_ - bytes_transfered;
267 it != in_.begin() + in_buffer_size_; ++it)
268 oss << boost::format(
"%02x") %
static_cast<unsigned int>(*it) <<
" ";
269 ROS_DEBUG(
"U-Blox received %li bytes \n%s", bytes_transfered,
274 read_callback_(in_.data(), in_buffer_size_);
276 read_condition_.notify_all();
283 if (in_buffer_size_ >= in_.size()) {
284 ROS_ERROR(
"U-Blox ASIO input buffer overflow, dropping %zu bytes",
293 template <
typename StreamT>
297 boost::system::error_code error;
298 stream_->close(error);
301 "Error while closing the AsyncWorker stream: " << error.message());
304 template <
typename StreamT>
306 const boost::posix_time::time_duration& timeout) {
308 read_condition_.timed_wait(lock, timeout);
313 #endif // UBLOX_GPS_ASYNC_WORKER_H