|
TOBI Interface A
0.1
|
00001 /* 00002 This file is part of the TOBI Interface A (TiA) library. 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 Lesser General Public License Usage 00014 Alternatively, this file may be used under the terms of the GNU Lesser 00015 General Public License version 3.0 as published by the Free Software 00016 Foundation and appearing in the file lgpl.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/lgpl.html. 00020 00021 In case of GNU Lesser General Public License Usage ,the TiA library 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 Lesser General Public License 00028 along with the TiA library. If not, see <http://www.gnu.org/licenses/>. 00029 00030 Copyright 2010 Graz University of Technology 00031 Contact: TiA@tobi-project.org 00032 */ 00033 00038 // STL 00039 #include <iostream> 00040 #include <sstream> 00041 #include <vector> 00042 #include <algorithm> 00043 00044 // Boost 00045 #include <boost/date_time/posix_time/posix_time.hpp> 00046 #include <boost/lexical_cast.hpp> 00047 #include <boost/bind.hpp> 00048 #include <boost/asio.hpp> 00049 00050 // TICPP 00051 #include "ticpp/ticpp.h" 00052 00053 // local 00054 #include "tia/data_packet_interface.h" 00055 #include "tia/tia_server.h" 00056 00057 #include "tia-private/network/control_connection_server.h" 00058 #include "tia-private/network/tcp_data_server.h" 00059 #include "tia-private/network/udp_data_server.h" 00060 #include "tia-private/newtia/server_impl/tia_server_state_server_impl.h" 00061 #include "tia-private/newtia/network_impl/boost_tcp_server_socket_impl.h" 00062 #include "tia-private/newtia/server_impl/control_connection_server_2_impl.h" 00063 00064 #include "tia-private/newtia/server_impl/fusty_data_server_impl.h" 00065 #include "tia-private/newtia/fusty_hardware_interface_impl.h" 00066 00067 #include "tia-private/datapacket/data_packet_impl.h" 00068 #include "tia-private/datapacket/data_packet_3_impl.h" 00069 00070 #ifdef TIMING_TEST 00071 #include "LptTools/LptTools.h" 00072 #define LPT1 0 00073 #define LPT2 1 00074 #endif 00075 00076 namespace tia 00077 { 00078 using boost::uint64_t; 00079 using boost::uint32_t; 00080 using boost::uint16_t; 00081 using boost::int16_t; 00082 using boost::int64_t; 00083 using boost::lexical_cast; 00084 using namespace std; 00085 00086 //----------------------------------------------------------------------------- 00087 00088 TiAServer::TiAServer(boost::asio::io_service& io_service, bool new_tia) 00089 : io_service_(io_service), 00090 // config_(0), 00091 tcp_data_server_(0), 00092 udp_data_server_(0), 00093 control_connection_server_(0), 00094 server_state_server_(0), 00095 new_tia_ (new_tia), 00096 control_connection_server_2_(0), 00097 data_server_(0), hardware_interface_(0) 00098 00099 { 00100 00101 data_packet_impl_.reset( new DataPacketImpl ); 00102 work_data_packet_impl_ = new DataPacketImpl; 00103 00104 data_packet_3_impl_.reset( new DataPacket3Impl ); 00105 work_data_packet_3_impl_ = new DataPacket3Impl; 00106 00107 #ifdef TIMING_TEST 00108 timestamp_ = boost::posix_time::microsec_clock::local_time(); 00109 counter_ = 0; 00110 t_max_last_ = boost::posix_time::time_duration (0, 0, 0); 00111 t_max_total_ = boost::posix_time::time_duration (0, 0, 0); 00112 t_min_last_ = boost::posix_time::time_duration (10, 0, 0); 00113 t_min_total_ = boost::posix_time::time_duration (10, 0, 0); 00114 t_var_ = 0; 00115 lpt_flag_ = 0; 00116 00117 if(!LptDriverInstall()) 00118 { 00119 cerr << "Installing LptTools lpt driver failed (do you have access rights for the lpt-port?)." << endl; 00120 throw std::runtime_error("Error installing LptTools lpt driver!"); 00121 } 00122 00123 if(!LptInit()) 00124 { 00125 cerr << "Initializing lpt driver failed (do you have access rights for the lpt-port?)." << endl; 00126 throw std::runtime_error("Error initializing lpt driver!"); 00127 } 00128 #endif 00129 } 00130 00131 //----------------------------------------------------------------------------- 00132 00133 TiAServer::~TiAServer() 00134 { 00135 if(tcp_data_server_) 00136 delete tcp_data_server_; 00137 00138 if(udp_data_server_) 00139 delete udp_data_server_; 00140 00141 if(control_connection_server_) 00142 delete control_connection_server_; 00143 00144 if(control_connection_server_2_) 00145 delete control_connection_server_2_; 00146 00147 if(server_state_server_) 00148 delete server_state_server_; 00149 00150 if(data_server_) 00151 delete data_server_; 00152 00153 if(hardware_interface_) 00154 delete hardware_interface_; 00155 00156 data_packet_ = 0; 00157 if(work_data_packet_impl_) 00158 delete work_data_packet_impl_; 00159 if(work_data_packet_3_impl_) 00160 delete work_data_packet_3_impl_; 00161 00162 #ifdef TIMING_TEST 00163 LptExit(); 00164 #endif 00165 } 00166 00167 //----------------------------------------------------------------------------- 00168 00169 void TiAServer::initialize(std::map<std::string,std::string>& subject_info_map, 00170 std::map<std::string,std::string>& server_settings) 00171 { 00172 server_settings_ = server_settings; 00173 00174 createSubjectInfo(subject_info_map); 00175 createSignalInfo(); 00176 00177 uint16_t ctl_port = lexical_cast<uint16_t>(server_settings_[Constants::ss_ctl_port]); 00178 00179 tcp_data_server_ = new TCPDataServer(io_service_); 00180 00181 uint16_t udp_port = lexical_cast<uint16_t>(server_settings_[Constants::ss_udp_port]); 00182 udp_data_server_ = new UDPDataServer(io_service_); 00183 udp_data_server_->setDestination(server_settings_[Constants::ss_udp_bc_addr], udp_port); 00184 00185 if (new_tia_) 00186 { 00187 hardware_interface_ = new tia::FustyHardwareInterfaceImpl(subject_info_, signal_info_); 00188 00189 boost::shared_ptr<tia::TCPServerSocket> 00190 server_state_server_socket(new tia::BoostTCPServerSocketImpl (io_service_)); 00191 server_state_server_ = new tia::TiAServerStateServerImpl(server_state_server_socket); 00192 00193 data_server_ = new tia::FustyDataServerImpl(*tcp_data_server_, *udp_data_server_); 00194 00195 00196 boost::shared_ptr<tia::TCPServerSocket> 00197 control_connection_server2_socket(new tia::BoostTCPServerSocketImpl (io_service_)); 00198 control_connection_server_2_ = 00199 new tia::ControlConnectionServer2Impl(control_connection_server2_socket, ctl_port, 00200 data_server_, server_state_server_, hardware_interface_); 00201 00202 data_packet_ = data_packet_3_impl_.get(); 00203 work_data_packet_ = work_data_packet_3_impl_; 00204 } 00205 else 00206 { 00207 control_connection_server_ = new ControlConnectionServer(subject_info_map, 00208 io_service_, *this); 00209 control_connection_server_->bind(ctl_port); 00210 control_connection_server_->listen(); 00211 00212 data_packet_ = data_packet_impl_.get(); 00213 work_data_packet_ = work_data_packet_impl_; 00214 } 00215 } 00216 00217 //----------------------------------------------------------------------------- 00218 00219 DataPacket* TiAServer::getEmptyDataPacket() 00220 { 00221 return data_packet_; 00222 } 00223 00224 //----------------------------------------------------------------------------- 00225 00226 DataPacketImpl TiAServer::makeDataPacketCopy(DataPacketImpl& packet) 00227 { 00228 DataPacketImpl p(packet); 00229 return p; 00230 } 00231 00232 //----------------------------------------------------------------------------- 00233 00234 DataPacket3Impl TiAServer::makeDataPacketCopy(DataPacket3Impl& packet) 00235 { 00236 DataPacket3Impl p(packet); 00237 return p; 00238 } 00239 00240 //----------------------------------------------------------------------------- 00241 00242 void TiAServer::sendDataPacket() 00243 { 00244 if(new_tia_) 00245 *work_data_packet_3_impl_ = *(data_packet_3_impl_.get() ); 00246 else 00247 *work_data_packet_impl_ = *(data_packet_impl_.get() ); 00248 00249 tcp_data_server_->sendDataPacket( *work_data_packet_ ); 00250 udp_data_server_->sendDataPacket( *work_data_packet_ ); 00251 00252 work_data_packet_->reset(); 00253 00254 #ifdef TIMING_TEST 00255 timestamp_ = boost::posix_time::microsec_clock::local_time(); 00256 int port_state = LptPortIn(LPT1,0); 00257 if(!lpt_flag_) 00258 { 00259 lpt_flag_ = 1; 00260 LptPortOut(LPT1, 0, port_state | 0x02); 00261 } 00262 else 00263 { 00264 lpt_flag_ = 0; 00265 LptPortOut(LPT1, 0, port_state & ~0x02); 00266 } 00267 counter_++; 00268 00269 diff_ = timestamp_ - data_packet_->getTimestamp(); 00270 t_diffs_.push_back (diff_); 00271 t_min_total_ = min (t_min_total_, diff_); 00272 t_max_total_ = max (t_max_total_, diff_); 00273 t_min_last_ = min (t_min_last_, diff_); 00274 t_max_last_ = max (t_max_last_, diff_); 00275 00276 t_mean_ = (t_mean_ + diff_)/2; 00277 t_var_ = (t_var_ + 00278 ( (diff_.total_microseconds() - t_mean_.total_microseconds() )* 00279 (diff_.total_microseconds() - t_mean_.total_microseconds() ) ) )/2; 00280 00281 if( (master_samplingrate_/master_blocksize_ < 1) || 00282 (counter_%((master_samplingrate_/master_blocksize_) *2) == 0) ) 00283 { 00284 sort (t_diffs_.begin(), t_diffs_.end()); 00285 00286 cout << "Packet Nr.: " << counter_ << "; "; 00287 cout << "Timing (microsecs) -- mean: " << t_mean_.total_microseconds() << ", "; 00288 cout << "variance: " << t_var_; 00289 cout << ", min: " << t_min_last_.total_microseconds() << " (total: "<< t_min_total_.total_microseconds() <<"), "; 00290 cout << "max: "<< t_max_last_.total_microseconds() << " (total: "<< t_max_total_.total_microseconds() << "), "; 00291 cout << "median: " << t_diffs_[t_diffs_.size() / 2].total_microseconds () << endl; 00292 t_diffs_.clear(); 00293 t_min_last_ = boost::posix_time::time_duration (10, 0, 0); 00294 t_max_last_ = boost::posix_time::time_duration (0, 0, 0); 00295 } 00296 00297 #endif 00298 00299 } 00300 00301 //----------------------------------------------------------------------------- 00302 00303 void TiAServer::createSubjectInfo(std::map<std::string,std::string> subject_map) 00304 { 00305 subject_info_.setId(subject_map["id"]); 00306 subject_info_.setFirstName(subject_map["first_name"]); 00307 subject_info_.setSurname(subject_map["surname"]); 00308 subject_info_.setBirthday(subject_map["birthday"]); 00309 subject_info_.setMedication(subject_map["medication"]); 00310 00311 std::string value = subject_map["sex"]; 00312 if (value == "m") 00313 subject_info_.setSex(SubjectInfo::Male); 00314 else if (value == "f") 00315 subject_info_.setSex(SubjectInfo::Female); 00316 00317 value = subject_map["handedness"]; 00318 if (value == "r") 00319 subject_info_.setHandedness(SubjectInfo::RightHanded); 00320 else if (value == "l") 00321 subject_info_.setHandedness(SubjectInfo::LeftHanded); 00322 00323 value = subject_map["glasses"]; 00324 if (value == "y") 00325 subject_info_.setShortInfo(SubjectInfo::Glasses, SubjectInfo::Yes); 00326 else if (value == "n") 00327 subject_info_.setShortInfo(SubjectInfo::Glasses, SubjectInfo::No); 00328 else 00329 subject_info_.setShortInfo(SubjectInfo::Glasses, SubjectInfo::Unknown); 00330 00331 value = subject_map["smoker"]; 00332 if (value == "y") 00333 subject_info_.setShortInfo(SubjectInfo::Smoking, SubjectInfo::Yes); 00334 else if (value == "n") 00335 subject_info_.setShortInfo(SubjectInfo::Smoking, SubjectInfo::No); 00336 else 00337 subject_info_.setShortInfo(SubjectInfo::Smoking, SubjectInfo::Unknown); 00338 } 00339 00340 //----------------------------------------------------------------------------- 00341 00342 void TiAServer::createSignalInfo() 00343 { 00344 const std::vector<uint32_t>& sig_types = sig_types_; 00345 const std::vector<uint16_t>& blocksizes = blocksizes_; 00346 const std::vector<uint32_t>& fs_per_sig_type = fs_per_sig_type_; 00347 00348 const std::map<uint32_t, std::vector<std::string> >& channel_map = channels_per_sig_type_; 00349 00350 assert(sig_types.size() == blocksizes.size() && sig_types.size() == fs_per_sig_type.size()); 00351 00352 cout << endl; 00353 cout << " Sent Signal Types: (ordered)" << endl; 00354 00355 for (vector<uint32_t>::size_type index = 0; index < sig_types.size(); ++index) 00356 { 00357 Signal signal; 00358 00359 uint32_t sig_num_type = sig_types[index]; 00360 std::string sig_str_type = Constants().getSignalName(sig_num_type); 00361 signal.setType(sig_str_type); 00362 cout << " ... Signal type " << sig_str_type << endl; 00363 00364 uint16_t block_size = blocksizes[index]; 00365 signal.setBlockSize(block_size); 00366 00367 uint32_t fs = fs_per_sig_type[index]; 00368 signal.setSamplingRate(fs); 00369 00370 std::map<uint32_t, std::vector<std::string> >::const_iterator it_channel_map = 00371 channel_map.find(sig_num_type); 00372 00373 if (it_channel_map != channel_map.end()) 00374 { 00375 const std::vector<std::string>& channel_names = (*it_channel_map).second; 00376 std::vector<std::string>::const_iterator it_channels = channel_names.begin(); 00377 std::vector<std::string>::const_iterator end_channels = channel_names.end(); 00378 for (; it_channels != end_channels; ++it_channels) 00379 { 00380 Channel channel; 00381 channel.setId(*it_channels); 00382 signal.channels().push_back(channel); 00383 } 00384 } 00385 00386 signal_info_.signals().insert(make_pair(sig_str_type,signal)); 00387 } 00388 00389 signal_info_.setMasterBlockSize(master_blocksize_); 00390 signal_info_.setMasterSamplingRate(master_samplingrate_); 00391 } 00392 00393 //----------------------------------------------------------------------------- 00394 00395 00396 } // Namespace tobiss 00397