ALMA Computing Group

acsexmplDoorImpl.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 * "@(#) $Id: acsexmplDoorImpl.cpp,v 1.116 2008/10/09 08:41:11 cparedes Exp $" 00022 * 00023 * who when what 00024 * -------- -------- ---------------------------------------------- 00025 * acaproni 2004-04-06 Use the smart pointer for the properties 00026 * gchiozzi 2003-04-09 Replaced writeXXXX with write 00027 * david 2002-08-08 converted defines in DoorDefines.h into const static int's located in this file 00028 * bgustafs 2002-04-11 Modified for VxWorks 00029 * almamgr 2002-04-07 Removed poa parameter from call to ConstructorEpilogue() 00030 * blopez 2002-04-05 writeLong changed to writeString at version initialization 00031 * gchiozzi 2002-04-04 Replaced set_sync() with getDevIO()->write<T>() 00032 * blopez 2002-04-04 Modified for ACSDO usage 00033 * blopez 2002-03-27 Header removed 00034 * blopez 2002-03-11 Created 00035 */ 00036 00041 #include <baciDB.h> 00042 #include <acsexmplDoorImpl.h> 00043 #include <ACSErrTypeCommon.h> 00044 00045 #ifndef MAKE_VXWORKS 00046 ACE_RCSID(acsexmpl, acsexmplDoorImpl, "$Id: acsexmplDoorImpl.cpp,v 1.116 2008/10/09 08:41:11 cparedes Exp $") 00047 #else 00048 static char *rcsId="$Id: acsexmplDoorImpl.cpp,v 1.116 2008/10/09 08:41:11 cparedes Exp $"; 00049 static void *use_rcsId = ((void)&use_rcsId,(void *) &rcsId); 00050 #endif 00051 00052 using namespace baci; 00053 00054 // Asynchronous actions 00055 const static int OPEN_ACTION = 0; 00056 const static int CLOSE_ACTION = 1; 00057 00058 // Door states 00059 const static int DOOR_UNDEFINED = 0; 00060 const static int DOOR_OPEN = 1; 00061 const static int DOOR_CLOSED = 2; 00062 const static int DOOR_HALTED = 3; 00063 const static int DOOR_OPENING = 4; 00064 const static int DOOR_CLOSING = 5; 00065 00066 // Control loop time interval [sec] 00067 const static int CTRL_INTERVAL = 1; 00068 00069 // Control loop step size [units] 00070 const static int CTRL_STEP = 5; 00071 00072 void DoorThread::onStart() 00073 { 00074 ACS_SHORT_LOG((LM_INFO, "Starting Door control loop..")); 00075 } 00076 00077 // main loop for the DoorThread, which updates the Door's position 00078 void DoorThread::runLoop() 00079 { 00080 // Control loop 00081 ACS::Time timestamp; 00082 00083 // TBD: Error/Exception handling 00084 ACSErr::Completion_var completion; 00085 00086 // Get current door position 00087 CORBA::Double currentPosition = door_p->m_position_sp->get_sync(completion.out()); 00088 00089 // Get new position 00090 CORBA::Double newPosition = door_p->m_ref_position_sp->get_sync(completion.out()); 00091 00092 if (newPosition != currentPosition) 00093 { 00094 // Simulated control 00095 ACS_SHORT_LOG((LM_INFO, "Moving %s ...", door_p->getComponent()->getName())); 00096 if (currentPosition < newPosition) 00097 { 00098 // Set state to CLOSING 00099 door_p->m_substate_sp->getDevIO()->write(DOOR_CLOSING, timestamp); 00100 currentPosition += CTRL_STEP; 00101 if (currentPosition > newPosition) 00102 { 00103 currentPosition = newPosition; 00104 } 00105 door_p->m_position_sp->getDevIO()->write(currentPosition, timestamp); 00106 ACS_SHORT_LOG((LM_INFO, "Current position = %f", currentPosition )); 00107 } 00108 else 00109 { 00110 // Set state to OPENING 00111 door_p->m_substate_sp->getDevIO()->write(DOOR_OPENING, timestamp); 00112 currentPosition -= CTRL_STEP; 00113 if (currentPosition < newPosition) 00114 { 00115 currentPosition = newPosition; 00116 } 00117 door_p->m_position_sp->getDevIO()->write(currentPosition, timestamp); 00118 ACS_SHORT_LOG((LM_INFO, "Current position = %f", currentPosition )); 00119 } 00120 } 00121 else 00122 { 00123 // Define and set the state 00124 CORBA::Double maxPosition = door_p->m_ref_position_sp->max_value(); 00125 CORBA::Double minPosition = door_p->m_ref_position_sp->min_value(); 00126 00127 if (currentPosition == minPosition) 00128 { 00129 door_p->m_substate_sp->getDevIO()->write(DOOR_OPEN, timestamp); 00130 } 00131 else if (currentPosition == maxPosition) 00132 { 00133 door_p->m_substate_sp->getDevIO()->write(DOOR_CLOSED, timestamp); 00134 } 00135 else 00136 { 00137 door_p->m_substate_sp->getDevIO()->write(DOOR_HALTED, timestamp); 00138 } 00139 } 00140 } 00141 00142 void DoorThread::onStop() 00143 { 00144 ACS_SHORT_LOG((LM_INFO, "Stopping Door control loop.")); 00145 } 00146 00147 // 00148 // Door Constructor 00149 // 00150 Door::Door(const ACE_CString& name, 00151 maci::ContainerServices * containerServices): 00152 CharacteristicComponentImpl(name,containerServices), 00153 m_ref_position_sp(new RWdouble(name+":ref_position", getComponent()),this), 00154 m_position_sp(new ROdouble(name+":position", getComponent()),this), 00155 m_substate_sp(new ROlong(name+":substate", getComponent()),this), 00156 m_version_sp(new ROstring(name+":version", getComponent()),this) 00157 { 00158 ACS_TRACE("::Door::Door"); 00159 } 00160 00161 void 00162 Door::execute() 00163 { 00164 ACS_SHORT_LOG((LM_INFO,"Door::execute")); 00165 00166 // Used just as parameters to getDevIO()->write() 00167 ACS::Time timestamp; 00168 00169 // Set current version 00170 00171 #ifndef MAKE_VXWORKS 00172 m_version_sp->getDevIO()->write(rcsid_acsexmpl_acsexmplDoorImpl, timestamp); 00173 #else 00174 m_version_sp->getDevIO()->write(rcsId, timestamp); 00175 #endif 00176 // Set current substate 00177 int st = DOOR_UNDEFINED; 00178 m_substate_sp->getDevIO()->write(st, timestamp); 00179 00180 // Initialize control loop thread 00181 Door * selfPtr = this; 00182 m_doorThread_p = getContainerServices()->getThreadManager()->create<DoorThread, Door*> 00183 ("doorControl", // Name of the thread 00184 selfPtr); // pass a ptr to this as parameter to thread so it can call back to us 00185 m_doorThread_p->resume(); 00186 00187 ACS_SHORT_LOG((LM_INFO,"doorControl thread spawned.")); 00188 00189 ACS_SHORT_LOG((LM_INFO,"door::COMPSTATE_OPERATIONAL")); 00190 } 00191 00192 // Door Destructor 00193 Door::~Door() 00194 { 00195 ACS_TRACE("::Door::~Door"); 00196 00197 ACS_SHORT_LOG((LM_INFO,"Door::~Door destroying thread")); 00198 getContainerServices()->getThreadManager()->destroy(m_doorThread_p); 00199 // cleanUp() will have been already called by the container 00200 // and all threads should have been stopped already. 00201 } 00202 00203 // Door check-substate method 00204 // Checks for the device's substate. If the device is busy it returns 00205 // en error. (Note: the purpose of this function is to show how to handle 00206 // local error information.) 00207 void 00208 Door::checkSubstate (CompletionImpl *&error_p) 00209 { 00210 try 00211 { 00212 00213 // Get substate 00214 ACS_TRACE("::Door::checkSubstate"); 00215 ACSErr::Completion_var completion; 00216 CORBA::Long substate = m_substate_sp->get_sync(completion.out()); 00217 if ( (substate == DOOR_OPENING) || (substate == DOOR_CLOSING) ) 00218 { 00219 error_p = new ACSErrTypeCommon::FileNotFoundCompletion(__FILE__, __LINE__, "checkSubstate", ACSErr::Error); 00220 return; 00221 } 00222 } 00223 catch(...) 00224 { 00225 ACS_SHORT_LOG((LM_ERROR,"::Door::checkSubstate")); 00226 } 00227 00228 error_p = new ACSErrTypeOK::ACSErrOKCompletion();//no error 00229 } 00230 00231 /* --------------- [ Action implementator interface ] -------------- */ 00232 ActionRequest 00233 Door::invokeAction (int function, 00234 BACIComponent *cob_p, 00235 const int &callbackID, 00236 const CBDescIn &descIn, 00237 BACIValue *value_p, 00238 Completion &completion, 00239 CBDescOut &descOut) 00240 { 00241 switch (function) 00242 { 00243 case OPEN_ACTION: 00244 { 00245 return openAction(cob_p, callbackID, descIn, value_p, completion, descOut); 00246 } 00247 case CLOSE_ACTION: 00248 { 00249 return closeAction(cob_p, callbackID, descIn, value_p, completion, descOut); 00250 } 00251 default: 00252 { 00253 return reqDestroy; 00254 } 00255 } 00256 } 00257 00259 ActionRequest 00260 Door::openAction (BACIComponent *cob_p, 00261 const int &callbackID, 00262 const CBDescIn &descIn, 00263 BACIValue *value_p, 00264 Completion &completion, 00265 CBDescOut &descOut) 00266 { 00267 ACE_UNUSED_ARG(descOut); 00268 ACS_DEBUG_PARAM("::Door::openAction", "%s", getComponent()->getName()); 00269 00270 ACS::Time timestamp; 00271 CompletionImpl *error_p = 0; 00272 00273 DBConnector::writeCommand(getComponent()->getName(), "open", getStringifiedTimeStamp()); 00274 00275 // Set new ref_position_p 00276 00277 try 00278 { 00279 00280 // Check for state 00281 00282 checkSubstate(error_p); 00283 00284 if (error_p->isErrorFree() == true) 00285 { 00286 CORBA::Double minPosition = m_ref_position_sp->min_value(); 00287 m_ref_position_sp->getDevIO()->write(minPosition, timestamp); 00288 00289 // Set completion for OK 00290 completion = ACSErrTypeOK::ACSErrOKCompletion(); 00291 delete error_p; // Memory management: object has to be released. 00292 } 00293 else 00294 { 00295 //here memory for error_p is deleted automatically 00296 completion = ACSErrTypeCommon::CouldntPerformActionCompletion(error_p, __FILE__, __LINE__, "::Door::closeAction"); 00297 } 00298 00299 } 00300 catch(...) 00301 { 00302 delete error_p; 00303 ACS_SHORT_LOG((LM_ERROR, "::Door::openAction")); 00304 completion = ACSErrTypeCommon::CouldntPerformActionCompletion(__FILE__, __LINE__, "::Door::closeAction"); 00305 } 00306 00307 // Note: when finished "return reqInvokeDone", otherwise 00308 // "return reqInvokeWorking" and set "descOut.estimated_timeout". 00309 return reqInvokeDone; 00310 } 00311 00312 00314 ActionRequest 00315 Door::closeAction (BACIComponent *cob_p, 00316 const int &callbackID, 00317 const CBDescIn &descIn, 00318 BACIValue *value_p, 00319 Completion &completion, 00320 CBDescOut &descOut) 00321 { 00322 ACE_UNUSED_ARG(descOut); 00323 ACS_DEBUG_PARAM("::Door::closeAction", "%s", getComponent()->getName()); 00324 00325 ACS::Time timestamp; 00326 CompletionImpl *error_p = 0; 00327 00328 DBConnector::writeCommand(getComponent()->getName(), "close", getStringifiedTimeStamp()); 00329 00330 // Set new ref_position_p 00331 00332 try 00333 { 00334 // Check for state 00335 checkSubstate(error_p); 00336 00337 if (error_p->isErrorFree() == true) 00338 { 00339 CORBA::Double maxPosition = m_ref_position_sp->max_value(); 00340 00341 m_ref_position_sp->getDevIO()->write(maxPosition, timestamp); 00342 00343 // Set completion for OK 00344 completion = ACSErrTypeOK::ACSErrOKCompletion(); 00345 delete error_p; 00346 } 00347 else 00348 { 00349 // Set completion for ERROR 00350 completion = ACSErrTypeCommon::CouldntPerformActionCompletion(error_p, 00351 __FILE__, 00352 __LINE__, 00353 "::Door::closeAction"); 00354 } 00355 } 00356 catch(...) 00357 { 00358 delete error_p; 00359 ACS_SHORT_LOG((LM_ERROR,"::Door::closeAction")); 00360 completion = ACSErrTypeCommon::CouldntPerformActionCompletion(__FILE__, __LINE__, "::Door::closeAction"); 00361 } 00362 00363 // Note: when finished "return reqInvokeDone", otherwise 00364 // "return reqInvokeWorking" and set "descOut.estimated_timeout". 00365 return reqInvokeDone; 00366 } 00367 00368 /* --------------------- [ CORBA interface ] ----------------------*/ 00369 void 00370 Door::open (ACS::CBvoid_ptr cb, 00371 const ACS::CBDescIn &desc) 00372 { 00373 getComponent()->registerAction(BACIValue::type_null, cb, desc, this, OPEN_ACTION); 00374 } 00375 00376 void 00377 Door::close (ACS::CBvoid_ptr cb, 00378 const ACS::CBDescIn &desc) 00379 { 00380 getComponent()->registerAction(BACIValue::type_null, cb, desc, this, CLOSE_ACTION); 00381 } 00382 00383 void 00384 Door::move (CORBA::Double pos) 00385 { 00386 // Set new ref_position_p 00387 try 00388 { 00389 ACS::Time timestamp; 00390 00391 // Check for state 00392 CompletionImpl *error_p = 0; 00393 checkSubstate(error_p); 00394 if (error_p->isErrorFree() == false) 00395 { 00396 delete error_p; // Memory management: object has to be released. 00397 // Throw an exception 00398 // Note: the File-Not-Found error has been chosen arbitrarily 00399 THROW_ACS_EXCEPTION(ACSErr::ACSErrTypeCommon, ACSErrTypeCommon::FileNotFound, "::Door::move"); 00400 } 00401 delete error_p; // Memory management: object has to be released. 00402 00403 try 00404 { 00405 m_ref_position_sp->getDevIO()->write(pos, timestamp); 00406 } 00407 catch(ACSErr::ACSbaseExImpl &ex) 00408 { 00409 // Throw an Out-Of-Bounds exception 00410 throw ACSErrTypeCommon::OutOfBoundsExImpl(ex, __FILE__, __LINE__, "::Door::move"); 00411 } 00412 } 00413 catch(...) 00414 { 00415 //Note: throwing the exception here does not work since set_sync 00416 // does not throw any exception. 00417 ACS_SHORT_LOG((LM_ERROR,"::Door::move")); 00418 } 00419 } 00420 00421 00422 ACS::RWdouble_ptr 00423 Door::ref_position () 00424 { 00425 if (m_ref_position_sp == 0) 00426 { 00427 return ACS::RWdouble::_nil(); 00428 } 00429 00430 ACS::RWdouble_var prop = ACS::RWdouble::_narrow(m_ref_position_sp->getCORBAReference()); 00431 return prop._retn(); 00432 } 00433 00434 ACS::ROdouble_ptr 00435 Door::position () 00436 { 00437 if (m_position_sp == 0) 00438 { 00439 return ACS::ROdouble::_nil(); 00440 } 00441 00442 ACS::ROdouble_var prop = ACS::ROdouble::_narrow(m_position_sp->getCORBAReference()); 00443 return prop._retn(); 00444 } 00445 00446 ACS::ROlong_ptr 00447 Door::substate () 00448 { 00449 if (m_substate_sp == 0) 00450 { 00451 return ACS::ROlong::_nil(); 00452 } 00453 00454 ACS::ROlong_var prop = ACS::ROlong::_narrow(m_substate_sp->getCORBAReference()); 00455 return prop._retn(); 00456 } 00457 00458 ACS::ROstring_ptr 00459 Door::version () 00460 { 00461 if (m_version_sp == 0) 00462 { 00463 return ACS::ROstring::_nil(); 00464 } 00465 00466 ACS::ROstring_var prop = ACS::ROstring::_narrow(m_version_sp->getCORBAReference()); 00467 return prop._retn(); 00468 } 00469 00470 /* --------------- [ MACI DLL support functions ] -----------------*/ 00471 #include <maciACSComponentDefines.h> 00472 MACI_DLL_SUPPORT_FUNCTIONS(Door) 00473 /* ----------------------------------------------------------------*/ 00474 00475 00476