ALMA Computing Group

acsexmplFridgeImpl.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 * "@(#) $Id: acsexmplFridgeImpl.cpp,v 1.133 2008/10/01 04:30:47 cparedes Exp $" 00023 * 00024 * who when what 00025 * -------- -------- ---------------------------------------------- 00026 * acaproni 2004-04-06 Use of smart pointer for properties 00027 * bjeram 2003-04-10 added FRIDGE::OnOffStates state = ... DevIO::write(state, ...) since write takes reference 00028 * david 2002-08-08 changes defines to const static int's 00029 * bgustafs 2002-04-11 Modified for VxWorks 00030 * gchiozzi 2002-04-04 Replaced set_sync() with getDevIO()->write<T>() 00031 * gchiozzi 2002-03-18 Replaced includes of fridge*.* with acsexmplFridge*.* 00032 * msekoran 2001-07-06 improved error handling 00033 * msekoran 2001-03-10 integrated with new BACI; ALMA coding convention used 00034 * gchiozzi 2001-02-15 Added real implementation for method descriptor() 00035 * gchiozzi 2001-02-15 Added body of get_interface() method for Object Explorer 00036 * gchiozzi 2001-02-15 created standard header 00037 */ 00038 00039 00040 #include <acsexmplFridgeImpl.h> 00041 #include <math.h> 00042 00043 ACE_RCSID(acsexmpl, acsexmplFridgeImpl, "$Id: acsexmplFridgeImpl.cpp,v 1.133 2008/10/01 04:30:47 cparedes Exp $") 00044 using namespace baci; 00045 00049 const static int ON_ACTION = 0; 00050 const static int OFF_ACTION = 1; 00051 const static int OPEN_ACTION = 2; 00052 const static int CLOSE_ACTION = 3; 00053 00059 int LOCALCOUNT = 0; 00060 00064 ACE_Log_Priority LOCAL_LOGGING_LEVEL = LM_INFO; 00065 00066 00067 /* * 00068 * After the thread's run loop has exceeded MAX_LOGS, the logging 00069 * level goes down to LM_DEBUG. 00070 */ 00071 const static int MAX_LOGS = 5; 00072 00073 00075 // FridgeThread 00077 00078 void 00079 FridgeThread::runLoop() 00080 { 00081 //Used to change the logging level to make acsexmpl's modular 00082 //tests more deterministic. 00083 if(LOCALCOUNT>MAX_LOGS) 00084 { 00085 LOCAL_LOGGING_LEVEL = LM_DEBUG; 00086 } 00087 else 00088 { 00089 LOCALCOUNT++; 00090 } 00091 ACS_SHORT_LOG((LOCAL_LOGGING_LEVEL, "Updating fridge temperature")); 00092 fridgeControl_p->updateTemperature(); 00093 } 00094 00096 // Fridge 00098 00099 00100 /* ----------------------------------------------------------------*/ 00101 /* ----------------------------------------------------------------*/ 00102 /* ----------------------------------------------------------------*/ 00103 FridgeControl::FridgeControl( 00104 const ACE_CString &name, 00105 maci::ContainerServices * containerServices) : 00106 CharacteristicComponentImpl(name, containerServices), 00107 m_refTemperature_sp(new RWdouble(name+":refTemperature", getComponent()),this), 00108 m_powerStatus_sp(new ROEnumImpl<ACS_ENUM_T(FRIDGE::OnOffStates), 00109 POA_FRIDGE::ROOnOffStates> (name+":powerStatus", getComponent()),this), 00110 m_doorStatus_sp(new ROEnumImpl<ACS_ENUM_T(FRIDGE::OpClStates), 00111 POA_FRIDGE::ROOpClStates> (name+":doorStatus", getComponent()),this), 00112 m_currTemperature_sp(new ROdouble(name+":currTemperature", getComponent()),this), 00113 m_controlLoop_p(0), 00114 m_FridgeSupplier_p(0) 00115 { 00116 ACS_TRACE("::FridgeControl::FridgeControl"); 00117 00118 // Handle notification channel creation here. 00119 m_FridgeSupplier_p = new nc::SimpleSupplier(FRIDGE::CHANNELNAME_FRIDGE, this); 00120 } 00121 00122 FridgeControl::~FridgeControl() 00123 { 00124 00125 ACS_TRACE("::FridgeControl::~FridgeControl"); 00126 ACS_DEBUG_PARAM("::FridgeControl::~FridgeControl", "Destroying %s...", getComponent()->getName()); 00127 00128 // destroy the thread via ThreadManager 00129 if(m_controlLoop_p!=0) 00130 getContainerServices()->getThreadManager()->destroy(m_controlLoop_p); 00131 00132 // cleanUp will have been already called by 00133 // the container and threads will have been already stopped. 00134 } 00135 00136 void FridgeControl::cleanUp() 00137 { 00138 ACS_TRACE("::FridgeControl::cleanUp"); 00139 00140 //turn it off before destroying it 00141 ACSErr::Completion_var completion; 00142 if((m_controlLoop_p!=0) && (powerStatus()->get_sync(completion.out())!=FRIDGE::OFF)) 00143 { 00144 off(); 00145 } 00146 00147 // Here we have to stop all threads 00148 getContainerServices()->getThreadManager()->stopAll(); 00149 00150 00151 // In the past this was done in the CharacteristicComponentImpl::cleanUp(); 00152 // As required by the CharacteristicComponentImpl class, 00153 // I call explicitly the cleanUp() of the parent class. 00154 // This makes sure that all threads are stopped and the 00155 // Component's state set. 00156 // Depending on what resources are used by a class implementing a 00157 // Component and by the implementation of the parent class (if it does 00158 // not inherit directly from acscomponent::ACSComponentImpl 00159 // or baci:: CharacteristicComponentImpl) it might be 00160 // necessary to call the cleanuUp() method of the base class 00161 // AFTER having released resources allocated by the current class. 00162 // This is demonstrated in this example where we want to make sure 00163 // that the powerStatus is FRIDGE::OFF before letting the 00164 // cleanUp() of the base class stopping all the 00165 // threads, including the one that regulates the temperature. 00166 // For an example where the cleanUp() of the parent class 00167 // is called before any other step, see the Building class. 00168 // Always check the documentation of the parent class 00169 // and consider what resources are allocated by this class 00170 // to extablish the requirements for the execution of lifecycle 00171 // chained methods. 00172 00173 // clean-up associated with NC 00174 if (m_FridgeSupplier_p != 0) 00175 { 00176 m_FridgeSupplier_p->disconnect(); 00177 m_FridgeSupplier_p=0; 00178 } 00179 } 00180 void 00181 FridgeControl::updateTemperature() 00182 { 00183 double temperature; 00184 ACS::Time timestamp; 00185 00186 00187 ACS_TRACE("::FridgeControl::updateTemperature"); 00188 00189 ACSErr::Completion_var completion; 00190 double currRefTemperature; 00191 00192 currRefTemperature = m_refTemperature_sp->get_sync(completion.out()); 00193 temperature = m_currTemperature_sp->get_sync(completion.out()); 00194 00195 // simulate the fridge trying to reach the reference temperature. 00196 ACS_SHORT_LOG((LOCAL_LOGGING_LEVEL, "::FridgeControl::updateTemperature. Curr value: %f. Ref: %f", temperature, currRefTemperature)); 00197 if(temperature < currRefTemperature) 00198 { 00199 temperature += 0.1; 00200 } 00201 else if(temperature > currRefTemperature) 00202 { 00203 temperature -= 0.1; 00204 } 00205 00206 m_currTemperature_sp->getDevIO()->write(temperature, timestamp); 00207 00208 // push data onto the NC 00209 this->loadData(); 00210 00211 ACS_SHORT_LOG((LOCAL_LOGGING_LEVEL, "::FridgeControl::updateTemperature. New value: %f", temperature)); 00212 00213 } 00214 00215 /* --------------------- [ FRIDGE interface ] ---------------------*/ 00216 void 00217 FridgeControl::on () 00218 { 00219 ACS::Time timestamp; 00220 00221 ACS_DEBUG_PARAM("::FridgeControl::on", "%s", getComponent()->getName()); 00222 m_powerStatus_sp->getDevIO()->write(FRIDGE::ON, timestamp); 00223 00224 // if the fridge has never been turned on before, we start the thread. otherwise the 00225 // fridge goes from off to on. 00226 if(m_controlLoop_p == 0) 00227 { 00228 FridgeControl * selfPtr = this; 00229 m_controlLoop_p = getContainerServices()->getThreadManager()-> 00230 create<FridgeThread, FridgeControl*>("fridgeControlLoop", selfPtr); 00231 m_controlLoop_p->resume(); 00232 } 00233 else 00234 { 00235 m_controlLoop_p->resume(); 00236 } 00237 } 00238 00239 void 00240 FridgeControl::off () 00241 { 00242 ACS::Time timestamp; 00243 00244 ACS_DEBUG_PARAM("::FridgeControl::off", "%s", getComponent()->getName()); 00245 // if the fridge has been turned on before, it is turned off. otherwise there 00246 // is no need to do anything. 00247 m_powerStatus_sp->getDevIO()->write(FRIDGE::OFF, timestamp); 00248 if(m_controlLoop_p != 0) 00249 { 00250 m_controlLoop_p->suspend(); 00251 } 00252 } 00253 00254 void 00255 FridgeControl::open () 00256 { 00257 ACS::Time timestamp; 00258 00259 ACS_DEBUG_PARAM("::FridgeControl::open", "%s", getComponent()->getName()); 00260 // there is no actual door to open here: only the enum is changed 00261 m_doorStatus_sp->getDevIO()->write(FRIDGE::OPEN, timestamp); 00262 } 00263 00264 void 00265 FridgeControl::close () 00266 { 00267 ACS::Time timestamp; 00268 00269 ACS_DEBUG_PARAM("::FridgeControl::close", "%s", getComponent()->getName()); 00270 // there is no actual door to close here: only the enum is changed 00271 m_doorStatus_sp->getDevIO()->write( FRIDGE::CLOSE, timestamp); 00272 } 00273 00274 ACS::RWdouble_ptr 00275 FridgeControl::refTemperature () 00276 { 00277 if (m_refTemperature_sp == 0) 00278 { 00279 return ACS::RWdouble::_nil(); 00280 } 00281 00282 ACS::RWdouble_var prop = ACS::RWdouble::_narrow(m_refTemperature_sp->getCORBAReference()); 00283 return prop._retn(); 00284 } 00285 00286 FRIDGE::ROOnOffStates_ptr 00287 FridgeControl::powerStatus () 00288 { 00289 if (m_powerStatus_sp == 0) 00290 { 00291 return FRIDGE::ROOnOffStates::_nil(); 00292 } 00293 00294 FRIDGE::ROOnOffStates_var prop = FRIDGE::ROOnOffStates::_narrow(m_powerStatus_sp->getCORBAReference()); 00295 return prop._retn(); 00296 } 00297 00298 FRIDGE::ROOpClStates_ptr 00299 FridgeControl::doorStatus () 00300 { 00301 if (m_doorStatus_sp == 0) 00302 { 00303 return FRIDGE::ROOpClStates::_nil(); 00304 } 00305 00306 FRIDGE::ROOpClStates_var prop = FRIDGE::ROOpClStates::_narrow(m_doorStatus_sp->getCORBAReference()); 00307 return prop._retn(); 00308 } 00309 00310 ACS::ROdouble_ptr 00311 FridgeControl::currTemperature () 00312 { 00313 if (m_currTemperature_sp == 0) 00314 { 00315 return ACS::ROdouble::_nil(); 00316 } 00317 00318 ACS::ROdouble_var prop = ACS::ROdouble::_narrow(m_currTemperature_sp->getCORBAReference()); 00319 return prop._retn(); 00320 } 00321 /* --------------------- [ Notification Channel ] -----------------*/ 00322 void 00323 FridgeControl::loadData() 00324 { 00325 00326 ACS_TRACE("::FridgeControl::loadData()"); 00327 00328 ACSErr::Completion_var completion; 00329 double current=0.0; 00330 double reference=0.0; 00331 current = currTemperature()->get_sync(completion.out() ); 00332 reference = refTemperature()->get_sync(completion.out() ); 00333 00334 // put the temperature info into a structure that will be pushed onto the NC 00335 FRIDGE::temperatureDataBlockEvent data; 00336 data.absoluteDiff = fabs(current - reference); 00337 if(current > reference) 00338 { 00339 data.status = FRIDGE::OVERREF; 00340 } 00341 else if(current < reference) 00342 { 00343 data.status = FRIDGE::BELOWREF; 00344 } 00345 else 00346 { 00347 data.status = FRIDGE::ATREF; 00348 } 00349 00350 // push the data - this eventually calls setData 00351 if(m_FridgeSupplier_p) 00352 { 00353 m_FridgeSupplier_p->publishData<FRIDGE::temperatureDataBlockEvent>(data); 00354 } 00355 } 00356 /* --------------- [ MACI DLL support functions ] -----------------*/ 00357 #include <maciACSComponentDefines.h> 00358 MACI_DLL_SUPPORT_FUNCTIONS(FridgeControl) 00359 /* ----------------------------------------------------------------*/ 00360 00361 00362