ALMA Computing Group

acsexmplClientAlarmThread.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: acsexmplClientAlarmThread.cpp,v 1.110 2009/05/20 17:19:48 javarias Exp $"
00024 *
00025 * who       when      what
00026 * --------  --------  ----------------------------------------------
00027 * david 2002-09-04 added ACE_TRY_CHECK on line 171 to get rid of warnings.
00028 * david 2002-06-17 fixed client.init(argc,argv)
00029 * naoj 2002-03-12 Added implementation of spawning thread in which value changes of current simulated
00030 * gchiozzi 2002-02-13 Cleaned up and renamed
00031 * gchiozzi 2002-01-23 Removed #define _POSIX_SOURCE 1. Gives problems on Solaris.
00032 * almamgr 2002-01-22 Replaced old include files with new axsexmpl... files
00033 * gchiozzi 2001-02-15 Merged: added tests for IFR and history.
00034 * gchiozzi 2001-02-15 created standard header
00035 * msekoran 2001-03-14 Changed namespace ESO to ACS 
00036 * msekoran 2001-03-20 Added Alarmdouble (event) example
00037 */
00038 
00062 
00067 
00100 /* @}*/
00101 /* @}*/
00102 #include <maciSimpleClient.h>
00103 #include <acsThread.h>
00104 #include "acsexmplCallbacks.h"
00105 
00106 #include <acsexmplPowerSupplyC.h>
00107 
00108 ACE_RCSID(acsexmpl, acsexmplClientAlarmThread, "$Id: acsexmplClientAlarmThread.cpp,v 1.110 2009/05/20 17:19:48 javarias Exp $")
00109 
00110 using namespace ACS;
00111 using namespace maci;
00112 
00116 class WorkerThread : public ACS::Thread
00117 { 
00118         public:
00119                 WorkerThread(const ACE_CString& name, 
00120                         ACS::RWdouble_var curr, 
00121                         const ACS::TimeInterval& responseTime=ThreadBase::defaultResponseTime, 
00122                         const ACS::TimeInterval& sleepTime=ThreadBase::defaultSleepTime) :
00123                     ACS::Thread(name, responseTime, sleepTime)
00124                 {
00125                     ACS_TRACE("WorkerThread::WorkerThread");
00126                     current = curr;
00127                     count = 0;
00128                     numValues = 7;
00129                     values = new double[7];
00130                     values[0] = 50;
00131                     values[1] = 8;
00132                     values[2] = 15;
00133                     values[3] = 25;
00134                     values[4] = 995;
00135                     values[5] = 970;
00136                     values[6] = 50;
00137 
00138                     ACS_SHORT_LOG((LM_INFO, "%s: Created thread", getName().c_str()));
00139                 }
00140 
00141                 ~WorkerThread() 
00142                 { 
00143                         ACS_TRACE("WorkerThread::~WorkerThread"); 
00144                         if(NULL != values) 
00145                         {
00146                                 delete[] values;
00147                         }
00148                 }
00149 
00150                 virtual void runLoop()
00151                 {
00152                         if(0 == count) {
00153                                 ACS_SHORT_LOG((LM_INFO, "%s: Started runLoop for thread", getName().c_str()));
00154                         }
00155                 //while there are still values that need to be set...
00156                         if(count < numValues)
00157                         {
00158                         try
00159                                 {
00160                                         //change the BACI property's value synchronously
00161                                         ACS_SHORT_LOG((LM_INFO, "%s: Setting current to %f", getName().c_str(), values[count]));
00162                                         current->set_sync(values[count]);
00163                                         count++;
00164                                 }
00165                         catch(...)
00166                                 {
00167                                         ACS_SHORT_LOG((LM_ERROR,"Error!"));
00168                                 }
00169                         }
00170                         else {
00171                         setStopped();
00172                         ACS_SHORT_LOG((LM_INFO, "%s: Stopped thread", getName().c_str()));
00173                         }
00174                 }
00175 
00176         private:
00177                 ACS::RWdouble_var current;
00178                 int count;
00179         int    numValues;
00180         //Ranges in the CDB for readback are:
00181         // alarm low  on : 10
00182         // alarm low  off: 20
00183         // alarm high off: 980
00184         // alarm high on : 990
00185         double * values; 
00186 };
00187 
00188 /*-----------------------------------------------------------------*/
00189 //Now onto the real example...
00192 int main(int argc, char *argv[]) 
00193 {
00194     //Checks command-line arguments.
00195     if (argc < 2)
00196         {
00197         ACS_SHORT_LOG((LM_INFO, "Usage: %s <component name> <options>", argv[0]));
00198         return -1;
00199         }
00200     else
00201         {
00202         ACS_SHORT_LOG((LM_INFO, "Welcome to %s!", argv[0]));
00203         }
00204     
00205     //Creates and initializes the SimpleClient object
00206     SimpleClient client;
00207     if (client.init(argc,argv) == 0)
00208         {
00209         ACE_DEBUG((LM_DEBUG,"Cannot init client"));
00210         return -1;
00211         }
00212     else
00213         {
00214         //Must log into manager before we can really do anything
00215         client.login();
00216         }
00217     
00218     try
00219         {
00220         //Get reference to the component
00221         ACS_SHORT_LOG((LM_INFO, "Getting component: %s", argv[1]));
00222         PS::PowerSupply_var ps = client.getComponent<PS::PowerSupply>(argv[1],0,true);
00223         if (CORBA::is_nil(ps.in()) == true) 
00224         {
00225            ACS_SHORT_LOG((LM_INFO, "Failed to get a reference to the PowerSupply component."));
00226            return -1;
00227         }
00228         ACS_SHORT_LOG((LM_INFO, "PowerSupply reference retrieved."));
00229 
00230         // first, set the current to a value which won't generate an alarm when
00231         // we first add the alarm subscription. (The CDB schema for the power supply
00232         // defines the conditions under which an alarm will occur.)
00233         ps->current()->set_sync(50);
00234         
00235         //Get the BACI property we'll create an alarm for
00236         ACS_SHORT_LOG((LM_INFO, "Trying to get readback... "));
00237         ACS::ROdouble_var readback = ps->readback();
00238         ACS_SHORT_LOG((LM_INFO, "OK"));
00239         
00240         //create an instance of our alarm class
00241         MyAlarmdouble macb("readback");
00242         //activate it as a CORBA object
00243         ACS::Alarmdouble_var acb = macb._this(); 
00244         //create the actual BACI double alarm
00245         ACS::CBDescIn desc;
00246         ACS::Subscription_var alarmSub = readback->new_subscription_Alarm (acb.in(), desc);
00247         ACS_SHORT_LOG((LM_INFO,"Alarm subscription created")); 
00248         
00249         ACS::RWdouble_var current = ps->current();
00250         // create the thread 
00251         WorkerThread thread_p /*threadManager.create<WorkerThread,ACS::RWdouble_var>*/ ("actionThread", current, ThreadBase::defaultResponseTime, ThreadBase::defaultSleepTime*10 /*=1s*/);
00252         // by default threads that are not created using a thread manager are creatd suspended so we have to resume them!!
00253         thread_p.resume();
00254 
00255         //Enter main loop and stays there for a fixed amount of time.  Really we are
00256         //just allowing the thread we just created to run for awhile before exiting out
00257         //of this example.
00258         ACS_SHORT_LOG((LM_INFO, "(BACIClient main thread) Going in main loop sleep..."));
00259         ACE_Time_Value tv(20);
00260         client.run(tv);
00261         
00262         //Must cleanly destroy the alarm
00263         ACS_SHORT_LOG((LM_INFO,"Alarm subscription deleted")); 
00264         alarmSub->destroy();    
00265         } 
00266     catch(maciErrType::CannotGetComponentExImpl &_ex)
00267         {
00268         _ex.log();
00269         return -1;
00270         }
00271     catch(std::exception& e)
00272         {
00273                 std::cout << e.what() << std::endl;
00274         ACS_SHORT_LOG((LM_ERROR,"Error!"));
00275         return -1;
00276         }
00277     
00278     //Another try section where we release our component and logout from manager
00279     try
00280         {
00281         ACS_SHORT_LOG((LM_INFO,"Releasing..."));
00282         client.releaseComponent( argv[1]);
00283         client.logout();
00284         }
00285     catch(maciErrType::CannotReleaseComponentExImpl &_ex)
00286         {
00287         _ex.log();
00288         return -1;
00289         }
00290     catch(...)
00291         {
00292         ACSErrTypeCommon::UnexpectedExceptionExImpl uex(__FILE__, __LINE__, 
00293                                                         "main");
00294         uex.log();
00295         return -1;
00296         }//try-catch
00297     
00298     //sleep for 3 sec to allow everytihng to cleanup and stabilize
00299     //so that the tests can be determinitstic.
00300     ACE_OS::sleep(3);
00301     return 0;
00302 }