24 #ifndef GOBY_MIDDLEWARE_FRONTSEAT_WAVEGLIDER_WAVEGLIDER_SV2_SERIAL_CLIENT_H
25 #define GOBY_MIDDLEWARE_FRONTSEAT_WAVEGLIDER_WAVEGLIDER_SV2_SERIAL_CLIENT_H
30 #include <boost/asio.hpp>
33 #include <dccl/binary.h>
45 std::string name,
int baud = 115200)
47 return std::shared_ptr<SV2SerialConnection>(
51 boost::asio::serial_port&
socket() {
return socket_; }
55 void close() { socket_.close(); }
59 std::fill(message_.begin(), message_.end(), 0);
62 boost::asio::async_read(
63 socket_, buffer_, boost::asio::transfer_exactly(1),
64 boost::bind(&SV2SerialConnection::handle_read,
this, boost::placeholders::_1, boost::placeholders::_2, PART_MAGIC));
70 boost::asio::async_write(socket_, boost::asio::buffer(data),
71 boost::bind(&SV2SerialConnection::handle_write,
this, boost::placeholders::_1, boost::placeholders::_2));
88 message_(SV2_MAX_SIZE * 2)
96 catch (std::exception&
e)
98 glog.
is(
DIE) &&
glog <<
"Failed to open serial port: " << name << std::endl;
101 socket_.set_option(boost::asio::serial_port_base::baud_rate(baud));
104 socket_.set_option(boost::asio::serial_port_base::flow_control(
108 socket_.set_option(boost::asio::serial_port_base::character_size(8));
111 socket_.set_option(boost::asio::serial_port_base::stop_bits(
112 boost::asio::serial_port_base::stop_bits::one));
115 void handle_write(
const boost::system::error_code& error,
size_t )
121 glog.
is(
WARN) &&
glog <<
"Error writing to serial connection: " << error << std::endl;
125 void handle_read(
const boost::system::error_code& error,
size_t bytes_transferred,
135 std::istream istrm(&buffer_);
141 if ((istrm.peek() & 0xFF) != SV2_MAGIC_BYTE)
144 <<
": Not magic byte, continuing to read."
147 buffer_.consume(bytes_transferred);
152 << SV2_HEADER_SIZE <<
" bytes" << std::endl;
153 message_insert_ = &message_[0];
154 istrm.read(message_insert_, bytes_transferred);
155 message_insert_ += bytes_transferred;
158 boost::asio::async_read(socket_, buffer_,
159 boost::asio::transfer_exactly(SV2_HEADER_SIZE),
160 boost::bind(&SV2SerialConnection::handle_read,
this,
161 boost::placeholders::_1, boost::placeholders::_2, PART_HEADER));
168 istrm.read(message_insert_, bytes_transferred);
169 message_insert_ += bytes_transferred;
171 if (!check_escapes(part))
175 message_size_ = message_[1] & 0xFF;
176 message_size_ |= (message_[2] & 0xFF) << 8;
179 glog <<
"Received header: "
181 message_.begin(), message_.begin() + SV2_HEADER_SIZE + 1))
182 <<
", size of " << message_size_ << std::endl;
185 boost::asio::async_read(
187 boost::asio::transfer_exactly(message_size_ - SV2_HEADER_SIZE),
188 boost::bind(&SV2SerialConnection::handle_read,
this, boost::placeholders::_1, boost::placeholders::_2,
195 istrm.read(message_insert_, bytes_transferred);
196 message_insert_ += bytes_transferred;
198 if (!check_escapes(part))
203 glog <<
"Read message: "
205 message_.begin() + message_size_ + 1))
208 std::string(message_.begin(), message_.begin() + message_size_ + 1));
217 if (error == boost::asio::error::eof)
221 else if (error == boost::asio::error::operation_aborted)
223 glog.
is(
DEBUG1) &&
glog <<
"Read operation aborted (socket closed)" << std::endl;
233 bool check_escapes(MessagePart part)
238 int escape = std::count(message_.begin(), message_.end(), SV2_ESCAPE);
239 if (
escape != last_escape_)
241 boost::asio::async_read(
242 socket_, buffer_, boost::asio::transfer_exactly(
escape - last_escape_),
243 boost::bind(&SV2SerialConnection::handle_read,
this, boost::placeholders::_1, boost::placeholders::_2, part));
245 <<
" more bytes because of escape characters." << std::endl;
256 void remove_escapes()
258 if (last_escape_ == 0)
262 int before_size = message_.size();
263 boost::replace_all(message_, std::string(1, SV2_ESCAPE) + std::string(1, 0x5E),
264 std::string(1, SV2_MAGIC_BYTE));
265 boost::replace_all(message_, std::string(1, SV2_ESCAPE) + std::string(1, 0x5D),
266 std::string(1, SV2_ESCAPE));
267 int after_size = message_.size();
269 message_insert_ -= (before_size - after_size);
270 message_.resize(before_size);
271 last_escape_ = std::count(message_.begin(), message_.end(), SV2_ESCAPE);
274 void add_escapes(std::string* message)
277 boost::replace_all(*message, std::string(1, SV2_ESCAPE),
278 std::string(1, SV2_ESCAPE) + std::string(1, 0x5D));
279 boost::replace_all(*message, std::string(1, SV2_MAGIC_BYTE),
280 std::string(1, SV2_ESCAPE) + std::string(1, 0x5E));
282 boost::replace_first(*message, std::string(1, SV2_ESCAPE) + std::string(1, 0x5E),
283 std::string(1, SV2_MAGIC_BYTE));
287 boost::asio::serial_port socket_;
288 boost::asio::streambuf buffer_;
289 std::vector<char> message_;
290 char* message_insert_;
296 SV2_MAGIC_BYTE = 0x7e,