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