TOBI SignalServer  0.1
/home/breidi/Dropbox/signalserver/src/tia_client_main.cpp
00001 /*
00002     This file is part of the TOBI SignalServer.
00003 
00004     Commercial Usage
00005     Licensees holding valid Graz University of Technology Commercial
00006     licenses may use this file in accordance with the Graz University
00007     of Technology Commercial License Agreement provided with the
00008     Software or, alternatively, in accordance with the terms contained in
00009     a written agreement between you and Graz University of Technology.
00010 
00011     --------------------------------------------------
00012 
00013     GNU General Public License Usage
00014     Alternatively, this file may be used under the terms of the GNU
00015     General Public License version 3.0 as published by the Free Software
00016     Foundation and appearing in the file gpl.txt included in the
00017     packaging of this file.  Please review the following information to
00018     ensure the GNU General Public License version 3.0 requirements will be
00019     met: http://www.gnu.org/copyleft/gpl.html.
00020 
00021     In case of GNU General Public License Usage ,the TOBI SignalServer
00022     is distributed in the hope that it will be useful,
00023     but WITHOUT ANY WARRANTY; without even the implied warranty of
00024     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00025     GNU General Public License for more details.
00026 
00027     You should have received a copy of the GNU General Public License
00028     along with the TOBI SignalServer. If not, see <http://www.gnu.org/licenses/>.
00029 
00030     Copyright 2010 Graz University of Technology
00031     Contact: SignalServer@tobi-project.org
00032 */
00033 
00039 // STL
00040 #include <iostream>
00041 #include <algorithm>
00042 
00043 // Boost
00044 #include <boost/asio.hpp>
00045 #include <boost/bind.hpp>
00046 #include <boost/thread.hpp>
00047 #include <boost/cstdint.hpp>
00048 
00049 // local
00050 #include "tia/data_packet_interface.h"
00051 #include "tia/tia_client.h"
00052 #include "tia/ssconfig.h"
00053 #include "tia/defines.h"
00054 
00055 using namespace std;
00056 
00057 //-----------------------------------------------------------------------------
00058 
00059 class TiAClientDataReader
00060 {
00061   public:
00062     TiAClientDataReader(tia::TiAClient& client, boost::mutex& mutex, boost::condition_variable& cond) :
00063         client_(client), packet_(0), mutex_(mutex), cond_(cond),
00064         running_(1),
00065         timestamp_(boost::posix_time::microsec_clock::local_time()),
00066         t_min_total_ (10, 0, 0),
00067         t_max_total_ (0, 0, 0),
00068         t_min_last_ (10, 0, 0),
00069         t_max_last_ (0, 0, 0),
00070         t_var_(0)
00071     {
00072       packet_ = client_.getEmptyDataPacket();
00073     }
00074 
00075     void stop()
00076     {
00077       running_ = 0;
00078     }
00079 
00080     void readData()
00081     {
00082       unsigned int counter = 0;
00083 
00084       boost::uint64_t sample_nr = 0;
00085       boost::uint64_t packet_nr = 0;
00086 
00087       boost::uint64_t sample_nr_old = 0;
00088       boost::uint64_t packet_nr_old = 0;
00089 
00090       while(running_)
00091       {
00092         {
00093 
00094           boost::unique_lock<boost::mutex> lock(mutex_);
00095 
00096           vector<double> v;
00097 
00098           if (!client_.receiving())
00099           {
00100             cond_.wait(lock);
00101           }
00102 
00103           if(running_ && client_.receiving())
00104           {
00105             try {
00106               client_.getDataPacket(*packet_);
00107 
00108               if(packet_->hasFlag(SIG_MOUSE))
00109               {
00110                 v = packet_->getSingleDataBlock(SIG_MOUSE);
00111                 cout << "mousepos: "<< packet_->getSingleDataBlock(SIG_MOUSE)[1]<<","<<packet_->getSingleDataBlock(SIG_MOUSE)[2];
00112               }
00113 
00114               if(packet_->hasFlag(SIG_MBUTTON))
00115               {
00116                 v = packet_->getSingleDataBlock(SIG_MBUTTON);
00117                 cout<<" ... buttons: "<<packet_->getSingleDataBlock(SIG_MBUTTON)[1]<<packet_->getSingleDataBlock(SIG_MBUTTON)[2]<<packet_->getSingleDataBlock(SIG_MBUTTON)[3]<<endl;
00118               }
00119               if( ((client_.config().signal_info.masterSamplingRate()/client_.config().signal_info.masterBlockSize()) < 1) ||
00120                 (counter%(
00121                 (client_.config().signal_info.masterSamplingRate()/client_.config().signal_info.masterBlockSize()) *2 ) == 0) )
00122               {
00123                 std::cout << " -- Nr:" << packet_->getPacketID() << std::endl;
00124                 client_.requestConfig();
00125                 cerr << " -- got config ... "  << endl;
00126               }
00127 
00128               sample_nr_old = sample_nr;
00129               packet_nr_old = packet_nr;
00130 
00131               sample_nr = packet_->getPacketID();
00132               packet_nr = packet_->getConnectionPacketNr();
00133 
00134               if( (sample_nr - sample_nr_old) > 1)
00135               {
00136                 cerr << "SampleNr difference: " << (sample_nr - sample_nr_old);
00137                 cerr << " -- @Sample: " << sample_nr << endl;
00138               }
00139 
00140               if( (packet_nr - packet_nr_old) > 1)
00141               {
00142                 cerr << "PacketNr difference: " << (packet_nr - packet_nr_old);
00143                 cerr << " -- @Packet: " << packet_nr << endl;
00144               }
00145 
00146             }
00147             catch (std::exception& e)
00148             {
00149 
00150               cerr << "*** " << e.what() << endl;
00151               break;
00152             }
00153 
00154             #ifdef TIMING_TEST
00155               timestamp_ = boost::posix_time::microsec_clock::local_time();
00156               diff_ = timestamp_ - packet_->getTimestamp();
00157 
00158               t_diffs_.push_back (diff_);
00159               t_min_total_ = min (t_min_total_, diff_);
00160               t_max_total_ = max (t_max_total_, diff_);
00161               t_min_last_ = min (t_min_last_, diff_);
00162               t_max_last_ = max (t_max_last_, diff_);
00163 
00164               t_mean_ = (t_mean_ + diff_)/2;
00165               t_var_  = (t_var_ +
00166               ( (diff_.total_microseconds() - t_mean_.total_microseconds() )*
00167                 (diff_.total_microseconds() - t_mean_.total_microseconds() )  ) )/2;
00168             #endif
00169           }
00170           else
00171             break;
00172 
00173           counter++;
00174           #ifdef TIMING_TEST
00175             if( ((client_.config().signal_info.masterSamplingRate()/client_.config().signal_info.masterBlockSize()) < 1) ||
00176               (counter%(
00177               (client_.config().signal_info.masterSamplingRate()/client_.config().signal_info.masterBlockSize()) *2 ) == 0) )
00178             {
00179               sort (t_diffs_.begin(), t_diffs_.end());
00180               cout << "Packet Nr.: " << counter << ";  ";
00181               cout << "Timing (microsecs) -- mean: " << t_mean_.total_microseconds() << ", ";
00182               cout << "variance: " << t_var_;
00183               cout << ", min: " << t_min_last_.total_microseconds() << " (total: "<<  t_min_total_.total_microseconds() <<"), ";
00184               cout << "max: "<< t_max_last_.total_microseconds() << " (total: "<< t_max_total_.total_microseconds() << "), ";
00185               cout << "median: " << t_diffs_[t_diffs_.size() / 2].total_microseconds () << endl;
00186               t_diffs_.clear();
00187               t_min_last_ = boost::posix_time::time_duration (10, 0, 0);
00188               t_max_last_ = boost::posix_time::time_duration (0, 0, 0);
00189             }
00190           #endif
00191         }
00192       }
00193     }
00194   private:
00195     tia::TiAClient&                   client_;
00196     tia::DataPacket*                  packet_;
00197     boost::mutex&               mutex_;
00198     boost::condition_variable&  cond_;
00199     bool                        running_;
00200     boost::posix_time::ptime timestamp_;
00201     boost::posix_time::time_duration diff_;
00202     boost::posix_time::time_duration t_mean_;
00203     boost::posix_time::time_duration t_min_total_;
00204     boost::posix_time::time_duration t_max_total_;
00205     boost::posix_time::time_duration t_min_last_;
00206     boost::posix_time::time_duration t_max_last_;
00207     vector<boost::posix_time::time_duration> t_diffs_;
00208     boost::int64_t t_var_;
00209 //     boost::posix_time::time_duration t_var_;
00210 };
00211 
00212 
00213 //-----------------------------------------------------------------------------
00214 
00215 int main(int argc, const char* argv[])
00216 {
00217   string   srv_addr = "127.0.0.1";
00218   boost::uint16_t srv_port = 9000;
00219 
00220   bool use_new_tia = true;
00221 
00222   if(argc == 1)
00223   {
00224     cout << "Using default server " << srv_addr << ":" << srv_port << endl;
00225   }
00226   else if(argc == 2)
00227   {
00228     string param (argv[1]);
00229     if (param == "-o")
00230       use_new_tia = false;
00231   }
00232   else if(argc == 3)
00233   {
00234     srv_addr = argv[1];
00235     stringstream conv(argv[2]);
00236     conv >> srv_port;
00237     cout << "Using server " << srv_addr << ":" << srv_port << endl;
00238   }
00239   else if(argc == 4)
00240   {
00241     string param (argv[1]);
00242     if (param == "-o")
00243       use_new_tia = false;
00244 
00245     srv_addr = argv[2];
00246     stringstream conv(argv[3]);
00247     conv >> srv_port;
00248     cout << "Using server " << srv_addr << ":" << srv_port << endl;
00249   }
00250   else
00251   {
00252     cout << "Wrong number of arguments given: " << argc-1 << endl;
00253     cout << " - Usage: " << argv[0] << "  signalserver-ip   port" << endl;
00254     return(-1);
00255   }
00256 
00257   tia::TiAClient client(use_new_tia);
00258 
00259   try
00260   {
00261     client.connect(srv_addr, srv_port);
00262     client.requestConfig();
00263   }
00264   catch(std::exception& e)
00265   {
00266     cerr << e.what() << endl;
00267     return 1;
00268   }
00269 
00270   boost::mutex mutex;
00271   boost::condition_variable cond;
00272 
00273   TiAClientDataReader reader(client, mutex, cond);
00274   boost::thread reader_thread(boost::bind(&TiAClientDataReader::readData, &reader));
00275 
00276     #ifdef WIN32
00277       SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS);
00278       SetPriorityClass(reader_thread.native_handle(), REALTIME_PRIORITY_CLASS);
00279       SetThreadPriority(reader_thread.native_handle(), THREAD_PRIORITY_TIME_CRITICAL );
00280     #endif
00281 
00282   map<string, string> known_commands;
00283   known_commands.insert(make_pair("config",   "Requests the config from server."));
00284   known_commands.insert(make_pair("starttcp", "Starts the data transmission using tcp"));
00285   known_commands.insert(make_pair("startudp", "Starts the data transmission using udp broadcast"));
00286   known_commands.insert(make_pair("stop",     "Stops the data transmission"));
00287   known_commands.insert(make_pair("q",        "Quits the client."));
00288   known_commands.insert(make_pair("help",     "Prints this help text."));
00289   known_commands.insert(make_pair("state", "Get the data receiving state of the client"));
00290 
00291   string command;
00292   cout << endl << ">>";
00293 
00294   while(cin >> command)
00295   {
00296     {
00297       map<string, string>::const_iterator it = known_commands.find(command);
00298       if (it == known_commands.end())
00299       {
00300         cout << "Type 'help' to get description of supported commands" << endl;
00301         cout << endl << ">>";
00302         continue;
00303       }
00304     }
00305 
00306 //    boost::unique_lock<boost::mutex> lock(mutex);
00307 
00308     if(command == "q")
00309     {
00310       break;
00311     }
00312 
00313     if (command == "config")
00314     {
00315       try {
00316         client.requestConfig();
00317       }
00318       catch (std::exception& e)
00319       {
00320         cerr << "Requesting config failed -- Error:"
00321              << "--> " << e.what() << endl;
00322       }
00323     }
00324     else if (command == "state")
00325     {
00326         cout << "Client state: ";
00327         if (client.receiving())
00328             cout << "receiving data" << endl;
00329         else
00330             cout << "not receiving data" << endl;
00331     }
00332     else if (command == "starttcp" || command == "startudp")
00333     {
00334       bool udp =  command == "startudp";
00335 
00336       cout << "Start Receiving ..." << endl;
00337 
00338       try {
00339         client.startReceiving(udp);
00340         if (!client.receiving())
00341             cerr << "Client did not block until data receiving..." << endl;
00342       }
00343       catch (std::exception& e)
00344       {
00345         cerr << "Start Receiving failed -- Error:" << endl
00346              << "--> " << e.what() << endl;
00347       }
00348 
00349       cond.notify_one();
00350     }
00351     else if (command == "stop")
00352     {
00353       cout << "Stop Receiving ..." << endl;
00354 
00355       //boost::unique_lock<boost::mutex> lock(mutex);
00356 
00357       try {
00358         client.stopReceiving();
00359       }
00360       catch (std::exception& e)
00361       {
00362         cerr << "Stop Receiving failed -- Error:" << endl
00363              << "--> " << e.what() << endl;
00364       }
00365     }
00366     else if (command == "help")
00367     {
00368       map<string, string>::const_iterator it = known_commands.begin();
00369       map<string, string>::const_iterator end = known_commands.end();
00370       for (; it != end; ++it)
00371       {
00372         const string& command_name = (*it).first;
00373         string spacing;
00374         spacing.assign(20 - command_name.size(), '.');
00375         cout << (*it).first << spacing << (*it).second << endl;
00376       }
00377     }
00378 
00379     cond.notify_one();
00380     cout << endl << ">>";
00381   }
00382 
00383   cout << "Terminating ..." << endl;
00384   reader.stop();
00385   cond.notify_all();
00386   reader_thread.join();
00387 
00388   try {
00389     client.stopReceiving();
00390   }
00391   catch (std::exception& e)
00392   {
00393     cerr << "Stop Receiving failed -- Error:"
00394          << "--> " << e.what() << endl;
00395   }
00396 
00397  return(0);
00398 }
00399 
00400 //-----------------------------------------------------------------------------
 All Data Structures Files Functions Variables