ALMA Computing Group

acsexmplLampWheelImpl.cpp

Go to the documentation of this file.
00001 /******************************************************************************* 00002 * ALMA - Atacama Large Millimiter Array 00003 * (c) European Southern Observatory, 2002 00004 * Copyright by ESO (in the framework of the ALMA collaboration) 00005 * and Cosylab 2002, All rights reserved 00006 * 00007 * This library is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * This library is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with this library; if not, write to the Free Software 00019 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00020 * 00021 * 00022 * 00023 * "@(#) $Id: acsexmplLampWheelImpl.cpp,v 1.21 2008/10/09 08:41:11 cparedes Exp $" 00024 * 00025 * who when what 00026 * -------- -------- ---------------------------------------------- 00027 * acaproni 2004-04-26 Creation 00028 */ 00029 00030 00031 #include <baciDB.h> 00032 #include <maciContainerServices.h> 00033 #include <acsexmplLampWheelImpl.h> 00034 #include <expat.h> 00035 00039 const static int MOVE_ACTION = 0; 00040 00041 ACE_RCSID(acsexmpl, acsexmplLampWheelImpl, "$Id: acsexmplLampWheelImpl.cpp,v 1.21 2008/10/09 08:41:11 cparedes Exp $") 00042 00043 using namespace baci; 00044 00046 // LampWheel 00048 00049 LampWheel::LampWheel( 00050 const ACE_CString &name, 00051 maci::ContainerServices * containerServices) : 00052 CharacteristicComponentImpl(name,containerServices), 00053 m_position_sp(this), 00054 m_desc_sp(new ROstring(name+":desc", getComponent()),this), 00055 m_slots_sp(this) 00056 { 00057 // Build the full name of the component 00058 m_fullName="alma/"+name; 00059 00060 ACS_TRACE("::LampWheel::LampWheel"); 00061 00062 } 00063 00064 LampWheel::~LampWheel() 00065 { 00066 00067 ACS_TRACE("::LampWheel::~LampWheel"); 00068 00069 } 00070 00071 /* --------------------- [CDB related methods ] -------------------- */ 00072 00073 // We need to rememeber where the parser is when a char section is found 00074 // in order to store the value of each element in the right field of the 00075 // struct 00076 #define NO_TAG 0 // We are not parsing a tag 00077 #define UNDEF_TAG 0 // We are parsing a tag we do not care about 00078 #define SLOT_TAG 1 // We are parsing the Slot tag 00079 #define LAMP_TAG 2 // We are parsing the Lamp tag 00080 #define WUT_TAG 3 // We are parsing the WarmUpTime tag 00081 #define WATT_TAG 4 // We are parsing the Watt tag 00082 #define POS_TAG 5 // We are parsing the Position tag 00083 00084 // The libexpat allows to pass a user defined data struct between the call back 00085 // to avoid using global variables. 00086 typedef struct { 00087 // We fill the field of this slot while parsing 00088 // This slot is stored into the list when the end tag 00089 // is met (</Slot>) 00090 // While some fields are optional, they are filled at the beginning 00091 // with default values 00092 SlotDescriptor slotDescr; 00093 // The tag we're parsing 00094 short actualTag; 00095 // The list of slots (it is a pointer to m_lampWheelConfiguration) 00096 std::list<SlotDescriptor>* wheelDescriptor; 00097 } ParserStruct; 00098 00113 int LampWheel::retrieveConfigurationFromCDB(std::list<SlotDescriptor>& config) 00114 { 00115 // Clear the list 00116 config.clear(); 00117 00118 // We need the ContainerServices in order to retrieve the DAL 00119 maci::ContainerServices* services_p=getContainerServices(); 00120 if (services_p==NULL) 00121 { 00122 ACS_SHORT_LOG((LM_ERROR,"Error getting the ContainerServices")); 00123 return 0; 00124 } 00125 00126 // Get the DAL from the container services 00127 CDB::DAL_ptr dal_p = services_p->getCDB(); 00128 if (dal_p==NULL) 00129 { 00130 ACS_SHORT_LOG((LM_ERROR,"Error getting the CDB from the ContainerServices")); 00131 return 0; 00132 } 00133 00134 // dao contains the xml 00135 char* dao = NULL; 00136 try 00137 { 00138 // Stores the XML into the dao string 00139 dao = dal_p->get_DAO(m_fullName.c_str()); 00140 } 00141 catch(...) 00142 { 00143 ACS_SHORT_LOG((LM_ERROR,"Error getting DAO for %s",m_fullName.c_str())); 00144 return 0; 00145 } 00146 00147 // The following line prints the whole xml file 00148 //std::cout << "DAO is: ["<< dao <<']'<<std::endl; 00149 00150 // Parse the xml using expat 00151 // Please have a look on the libexpat documentation 00152 // for further details (http:://libexpat.souceforge.net) 00153 XML_Parser p = XML_ParserCreate(NULL); 00154 if (! p) 00155 { 00156 ACS_SHORT_LOG((LM_ERROR,"Could not allocate memory for the parser!")); 00157 return 0; 00158 } 00159 00160 //Connect to the parser the handler for the end and the start of a tag 00161 XML_SetElementHandler(p, start_hndl, end_hndl); 00162 00163 // Connect the char handler 00164 XML_SetCharacterDataHandler(p,char_hndl); 00165 00166 // A SlotDescriptor data struct is passed throurg the handlers 00167 // While parsing all the fields of the following struct will be filled 00168 // The only field that remain immutable is the pointer to the list 00169 // of slots 00170 ParserStruct commonData; 00171 commonData.wheelDescriptor=&config; 00172 XML_SetUserData(p,&commonData); 00173 00174 // We have all the xml in the string so we parse all the document 00175 // with just one call 00176 if (XML_Parse(p,dao,strlen(dao),TRUE)==0) 00177 { 00178 ACS_SHORT_LOG((LM_ERROR,"Error parsing!")); 00179 config.clear(); 00180 } 00181 else 00182 { 00183 ACS_SHORT_LOG((LM_INFO,"XML document parsed")); 00184 } 00185 00186 // Release the memory used by the parser 00187 XML_ParserFree(p); 00188 00189 return config.size(); 00190 } 00191 00197 void LampWheel::start_hndl(void* data, const XML_Char* el, const XML_Char** attr) 00198 { 00199 ParserStruct* ps =(ParserStruct*)data; 00200 00201 // Which is the current tag? 00202 ps->actualTag=NO_TAG; 00203 if (strcmp(el,"Slot")==0) 00204 { 00205 //Clean the struct for the new Slot the parser is beginning to read 00206 ps->slotDescr.num=0; 00207 ps->slotDescr.lampName[0]=0; 00208 ps->slotDescr.warmUpTime=0; 00209 ps->slotDescr.watt=0; 00210 ps->slotDescr.pos=0; 00211 00212 ps->actualTag=SLOT_TAG; 00213 } 00214 else if (strcmp(el,"Lamp")==0) ps->actualTag=LAMP_TAG; 00215 else if (strcmp(el,"WarmUpTime")==0) ps->actualTag=WUT_TAG; 00216 else if (strcmp(el,"Watt")==0) ps->actualTag=WATT_TAG; 00217 else if (strcmp(el,"Position")==0) ps->actualTag=POS_TAG; 00218 else ps->actualTag=UNDEF_TAG; // We do not care of other cases 00219 00220 // Scan the attribute and fill the fields of the descriptor 00221 // This example is quite easy because the XML has no duplicate names 00222 // for attributes ;-) 00223 for (int t=0; attr[t]; t+=2) 00224 { 00225 if (strcmp(attr[t],"LampType")==0) strcpy(ps->slotDescr.lampName,attr[t+1]); 00226 else if (strcmp(attr[t],"SlotNumber")==0) ps->slotDescr.num=atoi(attr[t+1]); 00227 } 00228 } 00229 00235 void LampWheel::end_hndl(void *data, const XML_Char* el) 00236 { 00237 ParserStruct* ps =(ParserStruct*)data; 00238 // Where are not processing a tag... 00239 ps->actualTag=NO_TAG; 00240 00241 // The Slot tag is parsed: we got a full struct now! 00242 if (ps!=NULL && strcmp(el,"Slot")==0) 00243 { 00244 // Insert the struct into the list 00245 ps->wheelDescriptor->push_back(ps->slotDescr); 00246 } 00247 // Where are not processing a tag... 00248 ps->actualTag=NO_TAG; 00249 } 00250 00256 void LampWheel::char_hndl(void *data, const XML_Char *s, int len) 00257 { 00258 ParserStruct* ps =(ParserStruct*)data; 00259 char temp[512]; 00260 strncpy(temp,s,len); 00261 temp[len]=0; 00262 // We have to store the string in the right field as stated 00263 // by the actualTag field 00264 // 00265 // XML schema definition guarantee that all the strings represent 00266 // numbers i.e. atoi cannot fail 00267 switch(ps->actualTag) { 00268 case WUT_TAG : ps->slotDescr.warmUpTime=atoi(temp); break; 00269 case WATT_TAG : ps->slotDescr.watt=atoi(temp); break; 00270 case POS_TAG : ps->slotDescr.pos=atoi(temp); break; 00271 default: break; 00272 } 00273 } 00274 00275 /* --------------------- [ Life cycle methods ] -------------------- */ 00276 00277 void LampWheel::initialize() 00278 { 00279 ACS_TRACE("::LampWheel::initialize"); 00280 00281 m_position_sp=new ROdouble(getContainerServices()->getName()+":position", getComponent()); 00282 // Position is 0 at the beginning 00283 ACS::Time timestamp; 00284 m_position_sp->getDevIO()->write(0.0, timestamp); 00285 00286 // There are two ways to get an attribute of the component 00287 // 1. from the DAO of the component 00288 // (shown for the LampWheelDescription attribute) 00289 // 2. using the get_characteristic method 00290 // (shown for the AvailableSlots attribute) 00291 // We'll show boths 00292 00293 // 1 00294 // Get the description of this lamp wheel from the xml file 00295 // It is an attribute of the component 00296 CDB::DAL_ptr dal_p = getContainerServices()->getCDB(); 00297 CDB::DAO_ptr dao_p = dal_p->get_DAO_Servant(m_fullName.c_str()); 00298 char* descr=NULL; 00299 try 00300 { 00301 descr = dao_p->get_string("LampWheelDescription"); 00302 } 00303 catch (...) 00304 { 00305 // We receive an error from the CDB 00306 // maybe a WrongDataType or a FieldDoesNotExist exception 00307 descr=NULL; 00308 ACS_SHORT_LOG((LM_ERROR,"Error reading LampWheel Description from the CDB")); 00309 } 00310 if (descr!=NULL) { 00311 m_desc_sp->getDevIO()->write(descr, timestamp); 00312 } 00313 00314 // 2 00315 // Get the number of available slots from the CDB 00316 // It is an attribute of the component 00317 m_slots_sp=new ROlong(getContainerServices()->getName()+":slots", getComponent()); 00318 try 00319 { 00320 CORBA::Any* characteristic = get_characteristic_by_name("AvailableSlots"); 00321 const char* val; 00322 if (!(*characteristic>>=val)) 00323 { 00324 ACS_SHORT_LOG((LM_ERROR,"Error getting AvailableSlots value by the CORBA::Any object")); 00325 } 00326 else 00327 { 00328 // Convert the string 00329 long availSlots=atoi(val); 00330 m_slots_sp->getDevIO()->write(availSlots, timestamp); 00331 } 00332 } 00333 catch (...) 00334 { 00335 // An error occurred reading the characteristic 00336 // This method throws ACS::NoSuchCharacteristic 00337 ACS_SHORT_LOG((LM_ERROR,"Error reading the characteristic AvailableSlots by its name")); 00338 } 00339 00340 } 00341 00342 void LampWheel::execute() 00343 { 00344 ACS_TRACE("::LampWheel::execute"); 00345 // Read the actual configuration from the CDB 00346 // 00347 // There is no meaning in reading the configuration from the CDB 00348 // if we had an error before but this is only an example... 00349 int size=retrieveConfigurationFromCDB(m_lampWheelConfiguration); 00350 ACS_SHORT_LOG((LM_ERROR,"%d slots found",size)); 00351 00352 } 00353 00354 void LampWheel::cleanUp() 00355 { 00356 // Empty the list 00357 m_lampWheelConfiguration.clear(); 00358 00359 } 00360 00361 void LampWheel::aboutToAbort() 00362 { 00363 } 00364 00365 /* --------------- [ Action implementator interface ] -------------- */ 00366 00367 ActionRequest 00368 LampWheel::invokeAction (int function, 00369 BACIComponent *cob_p, 00370 const int &callbackID, 00371 const CBDescIn &descIn, 00372 BACIValue *value_p, 00373 Completion &completion, 00374 CBDescOut &descOut) 00375 { 00376 ACS_SHORT_LOG((LM_INFO,"LampWheel::invokeAction")); 00377 00378 // better implementation with array is possible 00379 switch (function) 00380 { 00381 case MOVE_ACTION: 00382 { 00383 ACS_SHORT_LOG((LM_INFO,"LampWheel::invokeAction call moveAction")); 00384 return moveAction(cob_p, callbackID, descIn, value_p, completion, descOut); 00385 } 00386 default: 00387 { 00388 return reqDestroy; 00389 } 00390 } 00391 } 00392 00393 /* ------------------ [ Action implementations ] ----------------- */ 00394 00395 00397 ActionRequest 00398 LampWheel::moveAction (BACIComponent *cob_p, 00399 const int &callbackID, 00400 const CBDescIn &descIn, 00401 BACIValue *value_p, 00402 Completion &completion, 00403 CBDescOut &descOut) 00404 { 00405 ACS_SHORT_LOG((LM_INFO,"::LampWheel::moveAction", "%s", getComponent()->getName())); 00406 00407 int* slot_p = static_cast<int *>(const_cast<void *>(value_p->pointerValue())); 00408 00409 // The user wish to move the wheel to a defined slot. 00410 // We look for the slot in the list of slots to retrieve the 00411 // position to rotate the wheel to 00412 std::list<SlotDescriptor>::iterator iter; 00413 bool found=false; 00414 for (iter=m_lampWheelConfiguration.begin(); iter!=m_lampWheelConfiguration.end(); ++iter) 00415 { 00416 if ((int)iter->num==*slot_p) 00417 { 00418 // The requested slot is on the list: 00419 // the wheel rotates to the position specified in the CDB 00420 ACS::Time timestamp; 00421 m_position_sp->getDevIO()->write(iter->pos, timestamp); 00422 ACS_SHORT_LOG((LM_INFO,"Wheel moved to %d (using %s lamp, watt=%d)", 00423 iter->pos, 00424 iter->lampName, 00425 iter->watt)); 00426 found=true; 00427 break; 00428 } 00429 } 00430 if (!found) 00431 { 00432 ACS_SHORT_LOG((LM_ERROR,"The slot %d is not defined in the CDB",*slot_p)); 00433 } 00434 00435 DBConnector::writeCommand(getComponent()->getName(), "move", getStringifiedTimeStamp()); 00436 00437 completion = ACSErrTypeOK::ACSErrOKCompletion(); 00438 00439 // if OK action will be destroyed and we do not need it anymore 00440 if (slot_p!=0) 00441 { 00442 delete slot_p; 00443 slot_p=0; 00444 } 00445 00446 // complete action requesting done invocation, 00447 // otherwise return reqInvokeWorking and set descOut.estimated_timeout 00448 return reqInvokeDone; 00449 } 00450 00451 /* --------------------- [ CORBA interface ] ----------------------*/ 00452 00453 void LampWheel::move(CORBA::Short slot, ACS::CBvoid_ptr cb, const ACS::CBDescIn& desc) 00454 { 00455 int* param_p= new int; 00456 *param_p=slot; 00457 00458 ACS_SHORT_LOG((LM_INFO,"LampWheel::Move to slot %d",*param_p)); 00459 getComponent()->registerAction(BACIValue::type_null, cb, desc, this, MOVE_ACTION, BACIValue(param_p)); 00460 } 00461 00462 ACS::ROdouble_ptr 00463 LampWheel::position () 00464 { 00465 if (m_position_sp == 0) 00466 { 00467 return ACS::ROdouble::_nil(); 00468 } 00469 00470 ACS::ROdouble_var prop = ACS::ROdouble::_narrow(m_position_sp->getCORBAReference()); 00471 return prop._retn(); 00472 } 00473 00474 ACS::ROstring_ptr 00475 LampWheel::desc () 00476 { 00477 if (m_desc_sp == 0) 00478 { 00479 return ACS::ROstring::_nil(); 00480 } 00481 00482 ACS::ROstring_var prop = ACS::ROstring::_narrow(m_desc_sp->getCORBAReference()); 00483 return prop._retn(); 00484 } 00485 00486 ACS::ROlong_ptr 00487 LampWheel::slots () 00488 { 00489 if (m_slots_sp == 0) 00490 { 00491 return ACS::ROlong::_nil(); 00492 } 00493 00494 ACS::ROlong_var prop = ACS::ROlong::_narrow(m_slots_sp->getCORBAReference()); 00495 return prop._retn(); 00496 } 00497 00498 /* --------------- [ MACI DLL support functions ] -----------------*/ 00499 #include <maciACSComponentDefines.h> 00500 MACI_DLL_SUPPORT_FUNCTIONS(LampWheel) 00501 /* ----------------------------------------------------------------*/ 00502 00503