MTDevice.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2010, LABUST, UNIZG-FER
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of the LABUST nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *********************************************************************/
00034 /*********************************************************************
00035  * Author: Đula Nađ
00036  *   Date: 20.10.2010.
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         //Start reading until header start.
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         /*case Header:
00093                 boost::asio::async_read(port,
00094                                 input.prepare(MTMsg::default_size),
00095                                 boost::bind(&MTDevice::onHeader,this,_1,_2));
00096                 break;*/
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                 //Put the new byte on the end of the ring buffer
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                             //Return the length bytes
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                                         //Add +1 for the carriage return at the end of each message
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                 //std::cout<<"Text:";
00129                 //for (int i=0; i<ringBuffer.size(); ++i) {std::cout<<uint32_t(ringBuffer[i])<<",";}
00130                 //If no size match or sync byte, move by one
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                         //Read header data
00153                         dataSer >> (*msg);
00154                         //Save data
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 //                      std::cout<<"\t Msg data:";
00161 //
00162 //                      std::istream in(msg->data.get());
00163 //                      while (!in.eof())
00164 //                      {
00165 //                              uint8_t c;
00166 //                              in>>c;
00167 //                              std::cout<<int(c)<<",";
00168 //                      };
00169 //                      std::cout<<std::endl;
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         //prepare header
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   //write header
00200   boost::asio::write(port, output.data());
00201   //write data
00202   boost::asio::write(port, message->data->data());
00203 }


tritech_sdk
Author(s): Gyula Nagy
autogenerated on Fri Feb 7 2014 11:36:27