TOBI SignalServer
0.1
|
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 00034 #include "signalserver/signalserver.h" 00035 00036 #include <fstream> 00037 #include <boost/date_time.hpp> 00038 #include <boost/filesystem.hpp> 00039 00040 #include "tia/tia_server.h" 00041 #include "tia/data_packet_interface.h" 00042 #include "hardware/hw_access.h" 00043 #include "config/xml_parser.h" 00044 00045 00046 #include <tobiid/IDMessage.hpp> 00047 #include "TiDlib/tid_server.h" 00048 00049 00050 #include "libgdf/GDF/Writer.h" 00051 00052 namespace tobiss 00053 { 00054 //----------------------------------------------------------------------------- 00055 00056 SignalServer::SignalServer(XMLParser& config_parser, bool use_new_tia) 00057 : hw_access_(0), tia_server_(0), tia_io_service_thread_(0),hw_access_io_service_thread_(0), 00058 config_parser_(config_parser), 00059 stop_reading_(false), write_file_(false), 00060 master_blocksize_( 0 ), 00061 master_samplingrate_( 0 ) 00062 #ifdef USE_TID_SERVER 00063 ,tid_server_(0),tid_io_service_thread_(0) 00064 #endif 00065 #ifdef USE_GDF_SAVER 00066 ,gdf_writer_(0) 00067 #endif 00068 { 00069 #ifdef DEBUG 00070 std::cout << BOOST_CURRENT_FUNCTION << std::endl; 00071 #endif 00072 00073 tia_server_ = new tia::TiAServer(tia_io_service_, use_new_tia); 00074 hw_access_ = new HWAccess(hw_access_io_service_, config_parser_); 00075 00076 master_blocksize_ = hw_access_->getMastersBlocksize(); 00077 master_samplingrate_ = hw_access_->getMastersSamplingRate(); 00078 00079 tia_server_->setMasterBlocksize( master_blocksize_ ); 00080 tia_server_->setMasterSamplingRate( master_samplingrate_ ); 00081 tia_server_->setAcquiredSignalTypes( hw_access_->getAcquiredSignalTypes() ); 00082 tia_server_->setBlockSizesPerSignalType( hw_access_->getBlockSizesPerSignalType() ); 00083 00084 sampling_rate_per_sig_type_ = hw_access_->getSamplingRatePerSignalType(); 00085 tia_server_->setSamplingRatePerSignalType(sampling_rate_per_sig_type_); 00086 00087 channels_per_sig_type_ = hw_access_->getChannelNames(); 00088 tia_server_->setChannelNames(channels_per_sig_type_); 00089 00090 subject_info_ = config_parser_ .parseSubject(); 00091 server_settings_ = config_parser_.parseServerSettings(); 00092 00093 tia_server_->initialize(subject_info_, server_settings_); 00094 00095 packet_ = tia_server_->getEmptyDataPacket(); 00096 packet_->reset(); 00097 00098 #ifdef USE_TID_SERVER 00099 tid_server_ = new TiD::TiDServer(tid_io_service_); 00100 tid_server_->bind ( boost::lexical_cast<unsigned int>(server_settings_[tia::Constants::ss_tid_port])); 00101 tid_server_->listen(); 00102 00103 tid_io_service_thread_ = new boost::thread(boost::bind(&boost::asio::io_service::run, 00104 &tid_io_service_)); 00105 #endif 00106 00107 00108 #ifdef USE_GDF_SAVER 00109 try 00110 { 00111 if(server_settings_[tia::Constants::ss_filetype] == "gdf") 00112 { 00113 gdf_writer_ = new gdf::Writer(); 00114 initGdf(); 00115 write_file_ = true; 00116 } 00117 } 00118 catch( std::exception &e ) 00119 { 00120 std::cerr << " -- Caught exception from GDF writer!" << std::endl; 00121 throw; 00122 } 00123 #endif 00124 00125 hw_access_->startDataAcquisition(); 00126 hw_access_io_service_thread_ = new boost::thread(boost::bind(&boost::asio::io_service::run, 00127 &hw_access_io_service_)); 00128 tia_io_service_thread_ = new boost::thread(boost::bind(&boost::asio::io_service::run, 00129 &tia_io_service_)); 00130 00131 #ifdef WIN32 00132 SetPriorityClass(tia_io_service_thread_->native_handle(), REALTIME_PRIORITY_CLASS); 00133 SetThreadPriority(tia_io_service_thread_->native_handle(), THREAD_PRIORITY_TIME_CRITICAL ); 00134 00135 SetPriorityClass(hw_access_io_service_thread_->native_handle(), REALTIME_PRIORITY_CLASS); 00136 SetThreadPriority(hw_access_io_service_thread_->native_handle(), THREAD_PRIORITY_TIME_CRITICAL ); 00137 00138 #ifdef USE_TID_SERVER 00139 SetPriorityClass(tid_io_service_thread_->native_handle(), REALTIME_PRIORITY_CLASS); 00140 SetThreadPriority(tid_io_service_thread_->native_handle(), THREAD_PRIORITY_TIME_CRITICAL ); 00141 #endif 00142 00143 #endif 00144 } 00145 00146 //----------------------------------------------------------------------------- 00147 00148 SignalServer::~SignalServer() 00149 { 00150 #ifdef DEBUG 00151 std::cout << BOOST_CURRENT_FUNCTION << std::endl; 00152 #endif 00153 00154 stop(); 00155 00156 if(tia_io_service_thread_) 00157 delete(tia_io_service_thread_); 00158 00159 if(tia_server_) 00160 delete(tia_server_); 00161 00162 00163 if(hw_access_io_service_thread_) 00164 delete(hw_access_io_service_thread_); 00165 00166 if(hw_access_) 00167 delete(hw_access_); 00168 00169 00170 #ifdef USE_TID_SERVER 00171 if(tid_io_service_thread_) 00172 delete(tid_io_service_thread_); 00173 00174 if(tid_server_) 00175 delete(tid_server_); 00176 #endif 00177 00178 #ifdef USE_GDF_SAVER 00179 if(gdf_writer_) 00180 { 00181 gdf_writer_->close(); 00182 delete gdf_writer_; 00183 } 00184 #endif 00185 } 00186 00187 //----------------------------------------------------------------------------- 00188 00189 void SignalServer::stop() 00190 { 00191 #ifdef DEBUG 00192 std::cout << BOOST_CURRENT_FUNCTION << std::endl; 00193 #endif 00194 00195 stop_reading_ = true; 00196 00197 hw_access_io_service_.stop(); 00198 hw_access_io_service_thread_->interrupt(); 00199 hw_access_io_service_thread_->join(); 00200 00201 tia_io_service_.stop(); 00202 tia_io_service_thread_->interrupt(); 00203 tia_io_service_thread_->join(); 00204 00205 #ifdef USE_TID_SERVER 00206 tid_io_service_.stop(); 00207 tid_io_service_thread_->interrupt(); 00208 tid_io_service_thread_->join(); 00209 #endif 00210 00211 hw_access_->stopDataAcquisition(); 00212 } 00213 00214 //----------------------------------------------------------------------------- 00215 00216 void SignalServer::readPackets() 00217 { 00218 #ifdef DEBUG 00219 std::cout << BOOST_CURRENT_FUNCTION << std::endl; 00220 #endif 00221 00222 boost::uint64_t sample_count = 0; 00223 00224 while (!stop_reading_) 00225 { 00226 sample_count += master_blocksize_; 00227 00228 hw_access_->fillDataPacket(packet_); 00229 tia_server_->sendDataPacket(); 00230 } 00231 } 00232 00233 //----------------------------------------------------------------------------- 00234 00235 void SignalServer::fustyReadPackets() 00236 { 00237 #ifdef DEBUG 00238 std::cout << BOOST_CURRENT_FUNCTION << std::endl; 00239 #endif 00240 00241 #ifdef USE_TID_SERVER 00242 std::vector<IDMessage> msgs; 00243 msgs.reserve(100); 00244 std::ofstream events_file; 00245 #endif 00246 00247 boost::uint64_t sample_count = 0; 00248 00249 00250 while (!stop_reading_) 00251 { 00252 sample_count += master_blocksize_; 00253 00254 hw_access_->fillDataPacket(packet_); 00255 tia_server_->sendDataPacket(); 00256 00257 #ifdef USE_TID_SERVER 00258 if(tid_server_->newMessagesAvailable()) 00259 tid_server_->getLastMessages(msgs); 00260 #endif 00261 00262 #ifdef USE_GDF_SAVER 00263 if(write_file_) 00264 { 00265 uint32_t nr_values = 0; 00266 uint32_t nr_blocks = 0; 00267 uint32_t nr_channels = 0; 00268 std::vector<double> v; 00269 uint32_t ch_start = 0; 00270 00271 for(std::map<uint32_t, std::vector<std::string> >::iterator it(channels_per_sig_type_.begin()); 00272 it != channels_per_sig_type_.end(); it++) 00273 { 00274 try 00275 { 00276 v = packet_->getSingleDataBlock(it->first); 00277 nr_values = packet_->getNrOfSamples(it->first); 00278 nr_channels = packet_->getNrOfChannels(it->first); 00279 nr_blocks = nr_values/nr_channels; 00280 00281 for(uint32_t n = 0; n < nr_values/nr_blocks; n++) 00282 for(uint32_t m = 0; m < nr_blocks; m++) 00283 { 00284 gdf_writer_->addSamplePhys(ch_start + n, v[ (n*nr_blocks) + m]); 00285 } 00286 } 00287 catch( std::exception& e ) 00288 { 00289 std::cerr << " Caught exception from GDF writer: " << e.what() << std::endl; 00290 throw; 00291 } 00292 ch_start += it->second.size(); 00293 } 00294 00295 #ifdef USE_TID_SERVER 00296 for(unsigned int n = 0; n < msgs.size(); n++) 00297 { 00298 if(msgs[n].GetFamilyType() == IDMessage::FamilyBiosig) 00299 { 00300 if(msgs[n].GetBlockIdx() >0) 00301 { 00302 std::cout << "Current sample count: " << sample_count << std::endl; 00303 gdf_writer_->addEvent(msgs[n].GetBlockIdx()*master_blocksize_, msgs[n].GetEvent() ); 00304 } 00305 else 00306 { 00307 gdf_writer_->addEvent(sample_count, msgs[n].GetEvent() ); 00308 std::cout << "Used BlockNr: " << sample_count << std::endl; 00309 } 00310 msgs[n].Dump(); 00311 std::string timestamp; 00312 msgs[n].absolute.Get(×tamp); 00313 std::cout << " + Timestamp: " << timestamp << std::endl; 00314 } 00315 else 00316 { 00317 if(!events_file.is_open()) 00318 { 00319 std::cerr << "Received a 'non-gdf' event -- saving into .txt file 'events_file.txt'." << std::endl; 00320 events_file.open("events_file.txt"); 00321 boost::posix_time::ptime t(boost::posix_time::second_clock::local_time()); 00322 events_file << std::endl << t << std::endl; 00323 events_file << "FamilyType:Family:Position:Event:Description:AbsTimestamp:RelTimeStamp" << std::endl; 00324 } 00325 msgs[n].Dump(); 00326 events_file << msgs[n].GetFamilyType() << ":"; 00327 events_file << msgs[n].GetFamily() << ":"; 00328 events_file << msgs[n].GetBlockIdx()*master_blocksize_ << ":"; 00329 events_file << msgs[n].GetEvent() << ":"; 00330 events_file << msgs[n].GetDescription() << ":"; 00331 events_file << "0" << ":"; 00332 events_file << "0" << std::endl; 00333 } 00334 } 00335 #endif 00336 } 00337 #endif 00338 00339 #ifdef USE_TID_SERVER 00340 if(msgs.size()) 00341 msgs.clear(); 00342 #endif 00343 } 00344 00345 #ifdef USE_TID_SERVER 00346 if(!events_file.is_open()) 00347 events_file.close(); 00348 #endif 00349 00350 } 00351 00352 //----------------------------------------------------------------------------- 00353 #ifdef USE_GDF_SAVER 00354 void SignalServer::initGdf() 00355 { 00356 std::map<uint32_t, std::vector<std::string> >::iterator it(channels_per_sig_type_.begin()); 00357 00358 tia::Constants cst; 00359 00360 for(uint32_t m = 0 ; it != channels_per_sig_type_.end(); it++, m++) 00361 { 00362 for(uint32_t n = 0; n < it->second.size(); n++) 00363 { 00364 int ind = gdf_writer_->getFirstFreeSignalIndex(); 00365 gdf_writer_->createSignal(ind); 00366 gdf_writer_->getSignalHeader(ind).set_label( cst.getSignalName(it->first) + ":" + it->second[n] ); 00367 gdf_writer_->getSignalHeader(ind).set_datatype( gdf::FLOAT32 ); 00368 gdf_writer_->getSignalHeader(ind).set_samplerate(sampling_rate_per_sig_type_[m]); 00369 gdf_writer_->getSignalHeader(ind).set_digmin( -250000 ); 00370 gdf_writer_->getSignalHeader(ind).set_digmax( 250000 ); 00371 gdf_writer_->getSignalHeader(ind).set_physmin( -250000 ); 00372 gdf_writer_->getSignalHeader(ind).set_physmax( 250000 ); 00373 } 00374 } 00375 00376 gdf_writer_->getHeaderAccess().setRecordDuration( 2* master_samplingrate_, 2*master_samplingrate_ ); 00377 00378 gdf_writer_->setEventMode( 1 ); // FIXME: 1 ... EventMode 1 (gdf) 00379 gdf_writer_->setEventSamplingRate( master_samplingrate_ ); 00380 00381 double systime = boost::numeric_cast<double>( time( NULL ) ); 00382 double tmptime = ( systime/(3600.0*24.0) + 719529.0 ) * pow(2.0,32); 00383 gdf_writer_->getMainHeader( ).set_recording_start( boost::numeric_cast<gdf::uint64>(tmptime) ); 00384 00385 std::cout << " ** Saving data to file: " << server_settings_[tia::Constants::ss_filename] << ".gdf" << std::endl; 00386 00387 boost::filesystem::path p( server_settings_[tia::Constants::ss_filename] + ".gdf" ); 00388 00389 if(exists(p) && server_settings_[tia::Constants::ss_file_overwrite] == "1") 00390 { 00391 if(is_regular_file(p)) 00392 { 00393 std::cout << " **** WARNING **** Old file is overwritten now!" << std::endl; 00394 boost::filesystem3::remove(p); 00395 } 00396 else 00397 throw(std::invalid_argument( p.string() + "exists, but is not a regular file!")); 00398 } 00399 00400 gdf_writer_->open( server_settings_[tia::Constants::ss_filename] + ".gdf" ); 00401 } 00402 #endif 00403 00404 //----------------------------------------------------------------------------- 00405 00406 std::vector<std::string> SignalServer::getPossibleHardwareNames() 00407 { 00408 #ifdef DEBUG 00409 std::cout << "SignalServer: getPossibleHardwareNames" << std::endl; 00410 #endif 00411 00412 return(HWAccess::getPossibleHardwareNames()); 00413 } 00414 00415 //----------------------------------------------------------------------------- 00416 00417 } // tobiss 00418