Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 #include <labust/tritech/MTDevice.hpp>
00039 #include <labust/tritech/mtMessages.hpp>
00040
00041 #include <boost/bind.hpp>
00042 #include <boost/regex.hpp>
00043
00044 using namespace labust::tritech;
00045
00046 MTDevice::MTDevice(const std::string& portName, uint32_t baud):
00047 port(io),
00048 ringBuffer(ringBufferSize),
00049 inputSer(input, boost::archive::no_header)
00050 {
00051 port.open(portName);
00052
00053 if (port.is_open())
00054 {
00055 using namespace boost::asio;
00056 port.set_option(serial_port::baud_rate(baud));
00057 port.set_option(serial_port::flow_control(serial_port::flow_control::none));
00058 port.set_option(serial_port::character_size(8));
00059 port.set_option(serial_port::character_size(8));
00060 port.set_option(serial_port::parity(serial_port::parity::none));
00061 port.set_option(serial_port::stop_bits(serial_port::stop_bits::one));
00062
00063 std::cout<<"Is open."<<std::endl;
00064 }
00065 else
00066 {
00067 throw std::runtime_error("MTDevice: Cannot open serial port " + portName + ".");
00068 }
00069
00070
00071 this->start_receive(Sync);
00072 service = boost::thread(boost::bind(&boost::asio::io_service::run,&this->io));
00073 }
00074
00075 MTDevice::~MTDevice()
00076 {
00077 io.stop();
00078 service.join();
00079
00080 std::cout<<"Closed MTDevice."<<std::endl;
00081 }
00082
00083 void MTDevice::start_receive(uint8_t state)
00084 {
00085 switch (state)
00086 {
00087 case Sync:
00088 boost::asio::async_read(port,
00089 input.prepare(ringBufferSize),
00090 boost::bind(&MTDevice::onSync,this,_1,_2));
00091 break;
00092
00093
00094
00095
00096
00097 }
00098 }
00099
00100 void MTDevice::onSync(const boost::system::error_code& error, std::size_t bytes_transferred)
00101 {
00102 if (!error)
00103 {
00104 input.commit(bytes_transferred);
00105
00106 if (bytes_transferred == 1) ringBuffer.push_back(input.sbumpc());
00107 else input.sgetn(reinterpret_cast<char*>(ringBuffer.data()),bytes_transferred);
00108
00109 if (ringBuffer[0] == '@')
00110 {
00111 size_t len = HexHeader::length(&ringBuffer[1]);
00112
00113 if ((len != 0) && (len == (ringBuffer[5]+ringBuffer[6]*256)))
00114 {
00115 StreamPtr data(new boost::asio::streambuf());
00116
00117 data->sputc(ringBuffer[5]);
00118 data->sputc(ringBuffer[6]);
00119 data->pubseekoff(-2,std::ios_base::cur);
00120 boost::asio::async_read(port,
00121
00122 data->prepare(len-2 + 0*1),
00123 boost::bind(&MTDevice::onHeader,this,data,_1,_2));
00124 return;
00125 }
00126 }
00127 std::cerr<<"Out of sync."<<std::endl;
00128
00129
00130
00131 ringBuffer.erase(ringBuffer.begin());
00132 boost::asio::async_read(port,
00133 input.prepare(1),
00134 boost::bind(&MTDevice::onSync,this,_1,_2));
00135 }
00136 else
00137 {
00138 std::cerr<<error.message()<<std::endl;
00139 this->start_receive(Sync);
00140 }
00141 }
00142
00143 void MTDevice::onHeader(StreamPtr data, const boost::system::error_code& error, std::size_t bytes_transferred)
00144 {
00145 if (!error)
00146 {
00147 data->commit(bytes_transferred);
00148 try
00149 {
00150 boost::archive::binary_iarchive dataSer(*data, boost::archive::no_header);
00151 MTMsgPtr msg(new MTMsg());
00152
00153 dataSer >> (*msg);
00154
00155 msg->data = data;
00156
00157 if (handlers.find(msg->msgType) != handlers.end()) handlers[msg->msgType](msg);
00158
00159 std::cout<<"MTDevice: node:"<<int(msg->node)<<", msg:"<<int(msg->msgType)<<std::endl;
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170 }
00171 catch (std::exception& e)
00172 {
00173 std::cerr<<"MTDevice::onHeader : "<<e.what()<<std::endl;
00174 }
00175 }
00176 else
00177 {
00178 std::cerr<<error.message()<<std::endl;
00179 }
00180 this->start_receive(Sync);
00181 }
00182
00186 void MTDevice::send(MTMsgPtr message)
00187 {
00188 message->setup();
00189 boost::asio::streambuf output;
00190 std::ostream out(&output);
00191
00192 out<<'@';
00193 out.width(4);
00194 out.fill('0');
00195 out<<std::uppercase<<std::hex<<message->size;
00196 boost::archive::binary_oarchive dataSer(output, boost::archive::no_header);
00197 dataSer << (*message);
00198
00199
00200 boost::asio::write(port, output.data());
00201
00202 boost::asio::write(port, message->data->data());
00203 }