TOBI Interface A  0.1
/home/breidi/Dropbox/libtia/src/tia/config/control_message_decoder.cpp
Go to the documentation of this file.
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 
00041 // Boost
00042 #include <boost/lexical_cast.hpp>
00043 #include <boost/cstdint.hpp>
00044 
00045 // TICPP
00046 #include "ticpp/ticpp.h"
00047 
00048 // local
00049 #include "tia/constants.h"
00050 
00051 #include "tia-private/config/control_message_decoder.h"
00052 #include "tia/ss_meta_info.h"
00053 
00054 namespace tia
00055 {
00056 
00057 using boost::lexical_cast;
00058 using boost::uint16_t;
00059 using boost::uint32_t;
00060 
00061 using std::cout;
00062 using std::cerr;
00063 using std::endl;
00064 
00065 //-----------------------------------------------------------------------------
00066 
00067 ControlMsgDecoderXML::ControlMsgDecoderXML() :
00068   tixml_doc_(0), xml_doc_(0), xml_msg_header_(0)
00069 {
00070   tixml_doc_ = new TiXmlDocument();
00071   xml_doc_ = new ticpp::Document(tixml_doc_);
00072 
00073   prototypes_["alive"]                    = ControlMsgHandle(new KeepAliveMsg());
00074   prototypes_["getConfig"]                = ControlMsgHandle(new GetConfigMsg());
00075   prototypes_["startTransmission"]        = ControlMsgHandle(new StartTransmissionMsg());
00076   prototypes_["getDataConnection"]        = ControlMsgHandle(new GetDataConnectionMsg());
00077   prototypes_["dataConnection"]           = ControlMsgHandle(new DataConnectionMsg());
00078   prototypes_["stopTransmission"]         = ControlMsgHandle(new StopTransmissionMsg());
00079   prototypes_["config"]                   = ControlMsgHandle(new ConfigMsg());
00080   prototypes_["okReply"]                  = ControlMsgHandle(ReplyMsg::ok().clone());
00081   prototypes_["errorReply"]               = ControlMsgHandle(ReplyMsg::error().clone());
00082 }
00083 
00084 //-----------------------------------------------------------------------------
00085 
00086 ControlMsgDecoderXML::~ControlMsgDecoderXML()
00087 {
00088   if(xml_doc_)
00089     delete tixml_doc_;
00090 
00091   if(xml_doc_)
00092     delete xml_doc_;
00093 }
00094 
00095 //-----------------------------------------------------------------------------
00096 
00097 ControlMsg* ControlMsgDecoderXML::decodeMsg()
00098 {
00099   return decodeMsgInternal();
00100 }
00101 
00102 //-----------------------------------------------------------------------------
00103 
00104 ControlMsg* ControlMsgDecoderXML::decodeMsgInternal()
00105 {
00106   if (istream_ == 0 || !istream_->good()) return 0;
00107 
00108   xml_doc_->Clear();
00109   xml_msg_header_ = 0;
00110 
00111   *istream_ >> *xml_doc_;
00112 
00113   if (tixml_doc_->Error())
00114   {
00115     // TODO: do a proper error handling
00116     cerr << "ControlMsgDecoderXML::decodeMsgInternal: "
00117          << tixml_doc_->ErrorDesc()
00118          << endl;
00119 
00120     return 0;
00121   }
00122 
00123 #ifdef DEBUG
00124   cout << "ControlMsgDecoderXML::decodeMsgInternal: decoding XML message:" << endl;
00125   cout << "-------------" << endl;
00126   tixml_doc_->Print();
00127   cout << "-------------" << endl;
00128 #endif
00129 
00130   ticpp::Element* message = xml_doc_->FirstChildElement("message", false);
00131   if (message == 0)
00132   {
00133     // TODO: do a proper error handling
00134     cerr << "Missing tag 'message'" << endl;
00135     return 0;
00136   }
00137 
00138   std::string msg_version;
00139   msg_version = message->GetAttribute<std::string>("version",  true);
00140 
00141   if(msg_version != MESSAGE_VERSION)
00142   {
00143     cerr << "Wrong message version " << msg_version << " -- expected: " << MESSAGE_VERSION << endl;
00144     return 0;
00145   }
00146 
00147   xml_msg_header_ = message->FirstChildElement("header", false);
00148   if (xml_msg_header_ == 0)
00149   {
00150     // TODO: do a proper error handling
00151     cerr << "Missing tag 'header'" << endl;
00152     return 0;
00153   }
00154 
00155   std::string xml_msg_type;
00156   if (!getXmlMsgType(*xml_msg_header_, xml_msg_type))
00157   {
00158      // TODO: do a proper error handling
00159      return 0;
00160   }
00161 
00162   std::map<std::string, ControlMsgHandle>::iterator itPrototypes =
00163     prototypes_.find(xml_msg_type);
00164 
00165   if (itPrototypes == prototypes_.end())
00166   {
00167     // TODO: do a proper error handling
00168     cerr << "Unknown control message type '" << xml_msg_type << "'" << endl;
00169     return 0;
00170   }
00171 
00172   ControlMsg* msg = (*itPrototypes).second->clone();
00173   assert(msg != 0);
00174   msg->readMsg(*this);
00175 
00176   return msg;
00177 }
00178 
00179 //-----------------------------------------------------------------------------
00180 
00181 bool ControlMsgDecoderXML::getXmlMsgType(ticpp::Element& header, std::string& type) const
00182 {
00183   ticpp::Element* element = header.FirstChildElement("type", false);
00184   if (element == 0)
00185   {
00186     // TODO: do a proper error handling
00187     cerr << "Missing tag 'type' in control message header" << endl;
00188     return false;
00189   }
00190 
00191   type = element->GetText();
00192   return true;
00193 }
00194 
00195 //-----------------------------------------------------------------------------
00196 
00197 bool ControlMsgDecoderXML::decodeHeader(ControlMsg& msg)
00198 {
00199     ticpp::Element* element = xml_msg_header_->FirstChildElement("sender", false);
00200     if (element == 0 || element->Value() != "sender")
00201     {
00202       // TODO: do a proper error handling
00203       cerr << "Missing tag 'sender' in control message header" << endl;
00204       return false;
00205     }
00206 
00207     std::string text = element->GetTextOrDefault("");
00208     msg.setSender(text);
00209 
00210     return true;
00211 }
00212 
00213 //-----------------------------------------------------------------------------
00214 
00215 void ControlMsgDecoderXML::decodeMsg(KeepAliveMsg& msg)
00216 {
00217 #ifdef DEBUG
00218   cout << "ControlMsgDecoderXML::decodeMsg: decoding KeepAliveMsg" << endl;
00219 #endif
00220 
00221   if (!decodeHeader(msg))
00222   {
00223     // TODO: do a proper error handling
00224     cerr << "Error decoding KeepAliveMsg" << endl;
00225     return;
00226   }
00227   // TODO: parse message body
00228 }
00229 
00230 //-----------------------------------------------------------------------------
00231 
00232 void ControlMsgDecoderXML::decodeMsg(GetConfigMsg& msg)
00233 {
00234 #ifdef DEBUG
00235   cout << "ControlMsgDecoderXML::decodeMsg: decoding GetConfigMsg" << endl;
00236 #endif
00237 
00238   if (!decodeHeader(msg))
00239   {
00240     // TODO: do a proper error handling
00241     cerr << "Error decoding GetConfigMsg" << endl;
00242     return;
00243   }
00244   // TODO: parse message body
00245 }
00246 
00247 //-----------------------------------------------------------------------------
00248 
00249 void ControlMsgDecoderXML::decodeMsg(StopTransmissionMsg& msg)
00250 {
00251 #ifdef DEBUG
00252   cout << "ControlMsgDecoderXML::decodeMsg: decoding StopTransmissionMsg" << endl;
00253 #endif
00254 
00255   if (!decodeHeader(msg))
00256   {
00257     // TODO: do a proper error handling
00258     cerr << "Error decoding StopTransmissionMsg" << endl;
00259     return;
00260   }
00261   // TODO: parse message body
00262 }
00263 
00264 //-----------------------------------------------------------------------------
00265 
00266 void ControlMsgDecoderXML::decodeMsg(StartTransmissionMsg& msg)
00267 {
00268 #ifdef DEBUG
00269   cout << "ControlMsgDecoderXML::decodeMsg: decoding StartTransmissionMsg" << endl;
00270 #endif
00271 
00272   if (!decodeHeader(msg))
00273   {
00274     // TODO: do a proper error handling
00275     cerr << "Error decoding StartTransmissionMsg" << endl;
00276     return;
00277   }
00278 
00279   ticpp::Element* start_trans_element = xml_msg_header_->NextSiblingElement();
00280   if (start_trans_element == 0 || start_trans_element->Value() != "startTransmission")
00281   {
00282     // TODO: do a proper error handling
00283     cerr << "Missing element 'startTransmission' in StartTransmissionMsg" << endl;
00284     return;
00285   }
00286 }
00287 
00288 //-----------------------------------------------------------------------------
00289 
00290 void ControlMsgDecoderXML::decodeMsg(GetDataConnectionMsg& msg)
00291 {
00292 #ifdef DEBUG
00293   cout << "ControlMsgDecoderXML::decodeMsg: decoding GetDataConnectionMsg" << endl;
00294 #endif
00295 
00296   if (!decodeHeader(msg))
00297   {
00298     // TODO: do a proper error handling
00299     cerr << "Error decoding GetDataConnectionMsg" << endl;
00300     return;
00301   }
00302 
00303   ticpp::Element* get_data_conn_element = xml_msg_header_->NextSiblingElement();
00304   if (get_data_conn_element == 0 || get_data_conn_element->Value() != "getDataConnection")
00305   {
00306     // TODO: do a proper error handling
00307     cerr << "Missing element 'getDataConnection' in GetDataConnectionMsg" << endl;
00308     return;
00309   }
00310 
00311   std::string element_name = "connectionType";
00312   ticpp::Element* element = get_data_conn_element->FirstChildElement(element_name, false);
00313   if (element != 0)
00314   {
00315     std::string value = element->GetTextOrDefault("");
00316     if (value == "tcp")
00317       msg.setConnectionType(GetDataConnectionMsg::Tcp);
00318     else if (value == "udp")
00319       msg.setConnectionType(GetDataConnectionMsg::Udp);
00320     else
00321       cerr << "Invalid value for element '" << element_name << endl;
00322   }
00323   else
00324     cerr << "Missing element '" << element_name << " in element 'getDataConnection'" << endl;
00325 
00326 }
00327 
00328 //-----------------------------------------------------------------------------
00329 
00330 void ControlMsgDecoderXML::decodeMsg(DataConnectionMsg& msg)
00331 {
00332 #ifdef DEBUG
00333   cout << "ControlMsgDecoderXML::decodeMsg: decoding DataConnectionMsg" << endl;
00334 #endif
00335 
00336   if (!decodeHeader(msg))
00337   {
00338     // TODO: do a proper error handling
00339     cerr << "Error decoding GetDataConnectionMsg" << endl;
00340     return;
00341   }
00342 
00343   ticpp::Element* data_conn_element = xml_msg_header_->NextSiblingElement();
00344   if (data_conn_element == 0 || data_conn_element->Value() != "dataConnection")
00345   {
00346     // TODO: do a proper error handling
00347     cerr << "Missing element 'dataConnection' in DataConnectionMsg" << endl;
00348     return;
00349   }
00350 
00351   std::string element_name = "address";
00352   ticpp::Element* element = data_conn_element->FirstChildElement(element_name, false);
00353   if (element != 0)
00354   {
00355     std::string address = element->GetTextOrDefault("");
00356     msg.setAddress(address);
00357   }
00358 
00359   element_name = "port";
00360   element = data_conn_element->FirstChildElement(element_name, false);
00361   if (element != 0)
00362   {
00363     try {
00364       uint16_t value = 0;
00365       element->GetText(&value);
00366       msg.setPort(value);
00367     }
00368     catch(...)
00369     {
00370       cerr << "Invalid value for element '" << element_name << endl;
00371     }
00372   }
00373   else
00374     cerr << "Missing element '" << element_name << " in element 'dataConnection'" << endl;
00375 }
00376 
00377 //-----------------------------------------------------------------------------
00378 
00379 void ControlMsgDecoderXML::decodeMsg(ConfigMsg& msg)
00380 {
00381 #ifdef DEBUG
00382   cout << "ControlMsgDecoderXML::decodeMsg: decoding ConfigMsg" << endl;
00383 #endif
00384 
00385   if (!decodeHeader(msg))
00386   {
00387     // TODO: do a proper error handling
00388     cerr << "Error decoding ConfigMsg" << endl;
00389     return;
00390   }
00391 
00392   ticpp::Element* config_element = xml_msg_header_->NextSiblingElement();
00393   if (config_element == 0 || config_element->Value() != "config")
00394   {
00395     // TODO: do a proper error handling
00396     cerr << "Missing element 'config' in ConfigMsg" << endl;
00397     return;
00398   }
00399 
00400   ticpp::Element* subject_element = config_element->FirstChildElement("subject", false);
00401   if (subject_element == 0)
00402   {
00403     // TODO: do a proper error handling
00404     cerr << "Missing element 'subject' in ConfigMsg" << endl;
00405     return;
00406   }
00407 
00408   std::string element_name;
00409   ticpp::Element* element = 0;
00410 
00411   element_name = "id";
00412   element = subject_element->FirstChildElement(element_name, false);
00413   if (element != 0)
00414     msg.subject_info.setId(element->GetText());
00415   else
00416     cerr << "Missing element '" << element_name << "' in element 'subject'" << endl;
00417 
00418   element_name = "firstName";
00419   element = subject_element->FirstChildElement(element_name, false);
00420   if (element != 0)
00421     msg.subject_info.setFirstName(element->GetText());
00422   else
00423     cerr << "Missing element '" << element_name << "' in element 'subject'" << endl;
00424 
00425   element_name = "surname";
00426   element = subject_element->FirstChildElement(element_name, false);
00427   if (element != 0)
00428     msg.subject_info.setSurname(element->GetText());
00429   else
00430     cerr << "Missing element '" << element_name << "' in element 'subject'" << endl;
00431 
00432   element_name = "birthday";
00433   element = subject_element->FirstChildElement(element_name, false);
00434   if (element != 0)
00435     msg.subject_info.setBirthday(element->GetText());
00436   else
00437     cerr << "Missing element '" << element_name << "' in element 'subject'" << endl;
00438 
00439   element_name = "medication";
00440   element = subject_element->FirstChildElement(element_name, false);
00441   if (element != 0)
00442     msg.subject_info.setBirthday(element->GetText());
00443   else
00444     cerr << "Missing element '" << element_name << "' in element 'subject'" << endl;
00445 
00446   element_name = "sex";
00447   element = subject_element->FirstChildElement(element_name, false);
00448   if (element != 0)
00449   {
00450     if (element->GetText() == "m")
00451       msg.subject_info.setSex(SubjectInfo::Male);
00452     else if (element->GetText() == "f")
00453       msg.subject_info.setSex(SubjectInfo::Female);
00454     else
00455       cerr << "Invalid value for element '" << element_name << "' in element 'subject'" << endl;
00456   }
00457   else
00458     cerr << "Missing element '" << element_name << "' in subject" << endl;
00459 
00460   element_name = "handedness";
00461   element = subject_element->FirstChildElement(element_name, false);
00462   if (element != 0)
00463   {
00464     if (element->GetText() == "r")
00465       msg.subject_info.setHandedness(SubjectInfo::RightHanded);
00466     else if (element->GetText() == "l")
00467       msg.subject_info.setHandedness(SubjectInfo::LeftHanded);
00468     else
00469       cerr << "Invalid value for element '" << element_name << "' in element 'subject'" << endl;
00470   }
00471   else
00472     cerr << "Missing element '" << element_name << "' in subject" << endl;
00473 
00474   // Optional elements
00475 
00476   element_name = "glasses";
00477   element = subject_element->FirstChildElement(element_name, false);
00478   if (element != 0)
00479   {
00480     if (element->GetText() == "yes")
00481       msg.subject_info.setShortInfo(SubjectInfo::Glasses, SubjectInfo::Yes);
00482     else if (element->GetText() == "no")
00483       msg.subject_info.setShortInfo(SubjectInfo::Glasses, SubjectInfo::No);
00484     else
00485       cerr << "Invalid value for element '" << element_name << "' in element 'subject'" << endl;
00486   }
00487 
00488   element_name = "smoker";
00489   element = subject_element->FirstChildElement(element_name, false);
00490   if (element != 0)
00491   {
00492     if (element->GetText() == "yes")
00493       msg.subject_info.setShortInfo(SubjectInfo::Smoking, SubjectInfo::Yes);
00494     else if (element->GetText() == "no")
00495       msg.subject_info.setShortInfo(SubjectInfo::Smoking, SubjectInfo::No);
00496     else
00497       cerr << "Invalid value for element '" << element_name << "' in element 'subject'" << endl;
00498   }
00499 
00500   ticpp::Element* signal_info_element = config_element->FirstChildElement("signalInfo", false);
00501   if (signal_info_element == 0)
00502   {
00503     // TODO: do a proper error handling
00504     cerr << "Missing element 'signalInfo' in ConfigMsg" << endl;
00505     return;
00506   }
00507 
00508   ticpp::Element* master_element = signal_info_element->FirstChildElement("master", false);
00509   if (master_element != 0)
00510   {
00511     element_name = "samplingRate";
00512     element = master_element->FirstChildElement(element_name, false);
00513     if (element != 0)
00514     {
00515       try {
00516         uint16_t value = 0;
00517         element->GetText(&value);
00518         msg.signal_info.setMasterSamplingRate(value);
00519       }
00520       catch(...)
00521       {
00522         cerr << "Invalid value for '" << element_name << "' in element 'master'" << endl;
00523       }
00524     }
00525     else
00526       cerr << "Missing element '" << element_name << "' in element 'master'" << endl;
00527 
00528     element_name = "blockSize";
00529     element = master_element->FirstChildElement(element_name, false);
00530     if (element != 0)
00531     {
00532       try {
00533         uint16_t value = 0;
00534         element->GetText(&value);
00535         msg.signal_info.setMasterBlockSize(value);
00536       }
00537       catch(...)
00538       {
00539         cerr << "Invalid value for '" << element_name << "' in element 'master'" << endl;
00540       }
00541     }
00542     else
00543       cerr << "Missing element '" << element_name << "' in element 'master'" << endl;
00544   }
00545   else
00546   {
00547     cerr << "Missing element 'master' in element 'signalInfo'" << endl;
00548     return;
00549   }
00550 
00551   ticpp::Element* signals_element = signal_info_element->FirstChildElement("signals", false);
00552 
00553   if (signals_element != 0)
00554   {
00555     ticpp::Element* sig_element = signals_element->FirstChildElement(false);
00556     for (; sig_element != 0; sig_element = sig_element->NextSiblingElement(false))
00557     {
00558       if (sig_element->Value() != "sig")
00559       {
00560         cerr << "Misplaced element '" << sig_element->Value() << "' in element 'signals'" << endl;
00561         continue;
00562       }
00563 
00564       std::string signal_type = sig_element->GetAttributeOrDefault("type", "");
00565       if (signal_type.empty())
00566       {
00567         cerr << "Element 'sig' without attribute 'type' in element signals" << endl;
00568         continue;
00569       }
00570 
00571       Signal signal;
00572       signal.setType(signal_type);
00573 
00574       element_name = "blockSize";
00575       element = sig_element->FirstChildElement(element_name, false);
00576       if (element != 0)
00577       {
00578         try {
00579           uint16_t value = 0;
00580           element->GetText(&value);
00581           signal.setBlockSize(value);
00582         }
00583         catch(...)
00584         {
00585           cerr << "Invalid value for '" << element_name << "' in element 'sig'" << endl;
00586         }
00587       }
00588       else
00589         cerr << "Missing element '" << element_name << "' in element 'sig'" << endl;
00590 
00591       element_name = "samplingRate";
00592       element = sig_element->FirstChildElement(element_name, false);
00593       if (element != 0)
00594       {
00595         try {
00596           uint16_t value = 0;
00597           element->GetText(&value);
00598           signal.setSamplingRate(value);
00599         }
00600         catch(...)
00601         {
00602           cerr << "Invalid value for '" << element_name << "' in element 'sig'" << endl;
00603         }
00604       }
00605       else
00606         cerr << "Missing element '" << element_name << "' in element 'sig'" << endl;
00607 
00608       ticpp::Element* channels_element = sig_element->FirstChildElement("channels", false);
00609 
00610       if (channels_element != 0)
00611       {
00612         ticpp::Element* ch_element = channels_element->FirstChildElement(false);
00613         for (; ch_element != 0; ch_element = ch_element->NextSiblingElement(false))
00614         {
00615           if (ch_element->Value() != "ch")
00616           {
00617             cerr << "Misplaced element '" << ch_element->Value() << "' in element 'signals'" << endl;
00618             continue;
00619           }
00620 
00621           Channel ch;
00622           ch.setId(ch_element->GetAttributeOrDefault("id", ""));
00623           signal.channels().push_back(ch);
00624         }
00625       }
00626       else
00627         cerr << "Missing element 'channels' in element 'sig'" << endl;
00628 
00629       msg.signal_info.signals().insert(make_pair(signal_type, signal));
00630     }
00631   }
00632   else
00633     cerr << "Missing element 'signals' in 'signalInfo'" << endl;
00634 }
00635 
00636 //-----------------------------------------------------------------------------
00637 
00638 void ControlMsgDecoderXML::decodeMsg(ReplyMsg& msg)
00639 {
00640 #ifdef DEBUG
00641   cout << "ControlMsgDecoderXML::decodeMsg: decoding ReplyMsg" << endl;
00642 #endif
00643 
00644   if (!decodeHeader(msg))
00645   {
00646     // TODO: do a proper error handling
00647     cerr << "Error decoding ReplyMsg" << endl;
00648     return;
00649   }
00650 
00651   switch (msg.msgType())
00652   {
00653     case ControlMsg::OkReply:
00654     {
00655       ticpp::Element* reply_element = xml_msg_header_->NextSiblingElement();
00656       if (reply_element == 0 || reply_element->Value() != "okReply")
00657       {
00658         // TODO: do a proper error handling
00659         cerr << "Missing element 'okReply' in ReplyMsg" << endl;
00660         return;
00661       }
00662       break;
00663     }
00664     case ControlMsg::ErrorReply:
00665     {
00666       ticpp::Element* reply_element = xml_msg_header_->NextSiblingElement();
00667       if (reply_element == 0 || reply_element->Value() != "errorReply")
00668       {
00669         // TODO: do a proper error handling
00670         cerr << "Missing element 'errorReply' in ReplyMsg" << endl;
00671         return;
00672       }
00673       break;
00674     }
00675 
00676     default:
00677     {
00678       // TODO: do a proper error handling
00679       cerr << "Catastrophic error - aborting" << endl;
00680       assert(false);
00681     }
00682   }
00683 }
00684 
00685 //-----------------------------------------------------------------------------
00686 
00687 } // Namespace tobiss
00688 
00689 // End Of File
 All Data Structures Files Functions Variables Typedefs Enumerations