Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

LOW_netSegment.h

Go to the documentation of this file.
00001 /***************************************************************************
00002                           LOW_netSegment.h  -  description
00003                              -------------------
00004     begin                : Sun Jul 7 2002
00005     copyright            : (C) 2002 by Harald Roelle, Helmut Reiser
00006     email                : roelle@informatik.uni-muenchen.de, reiser@informatik.uni-muenchen.de
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  *                                                                         *
00011  *   This program is free software; you can redistribute it and/or modify  *
00012  *   it under the terms of the GNU General Public License as published by  *
00013  *   the Free Software Foundation; either version 2 of the License, or     *
00014  *   (at your option) any later version.                                   *
00015  *                                                                         *
00016  ***************************************************************************/
00017 
00018 #ifndef LOW_NETSEGMENT_H
00019 #define LOW_NETSEGMENT_H
00020 
00021 
00022 #include <algorithm>
00023 
00024 #include "LOW_types.h"
00025 #include "LOW_device.h"
00026 #include "LOW_link.h"
00027   
00028 
00029 class LOW_device; // Forward declaration to avoid loops.
00030 
00031 
00032 /** Single segment of the 1-Wire net.
00033 
00034     The class models a single segment reachable by a concrete link 
00035     of the 1-Wire network.
00036 
00037     Objects for devices are automatically instanciated via LOW_deviceFactory.
00038     The objects are cached in two maps:
00039       - aliveDevMap: Contains currently present devices on the segment.
00040       - graveyardMap: Contains formerly present devices on the segment.
00041     This means, that once a device is not visible any more, the device object
00042     is not deleted but burried on the graveyard. Once the device is visible again,
00043     it is revitalized.
00044 
00045     @author Harald Roelle, Helmut Reiser
00046   */
00047 class LOW_netSegment
00048 {
00049 
00050 //=======================================================================================
00051 public: 
00052   
00053   //=====================================================================================
00054   //
00055   // exceptions
00056   //
00057  
00058   /** Exception base class for all exceptions thrown by LOW_netSegment. */
00059   class_DERIVE_FROM_EXCEPTION( netSegment_error, LOW_exception);
00060   
00061   /** Exception to indicate that one or more expeced devices were not found. */
00062   class_DERIVE_FROM_EXCEPTION( noDevice_error, netSegment_error);
00063 
00064   
00065   //=====================================================================================
00066   //
00067   // type definitions
00068   //
00069       
00070   typedef uint32_t segmentID_t;  /**< segment ID type */
00071   
00072   typedef std::vector<LOW_netSegment*> netSegPtrVec_t;  /**< Vector type of class pointers. */
00073   
00074   
00075   //=====================================================================================
00076   //
00077   // methods
00078   //
00079   
00080   /** Get the LOW_link instance associated with this segment.
00081       @return  Reference to the link instance.
00082    */
00083   LOW_link& getLink();
00084   
00085   
00086   /** Get wether there is an external power line on the segment.
00087       @returns  Wether there is an external power line on the segment.
00088    */
00089   bool getHasExternalPower() const;
00090 
00091   
00092   /** Get a specific device.
00093   
00094       Devices are searched in the internal device list only. No bus actions are performed.
00095       
00096       <B>Note:</B>:The device type to look for is selected by the template parameter. 
00097       
00098       @param  inDevID  ID of the device to get.
00099       @return Requested device.
00100       @throw LOW_device::familyMismatch_error  Thrown when family code of selected class
00101                                                and the one in the ID don't match.
00102       @throw noDevice_error  Thrown when requested device is not present.
00103    */
00104   template<class devType> devType* getDevice( const LOW_deviceID inDevID);
00105 
00106         
00107   /** Get devices of a specific type.
00108   
00109       Devices are searched in the internal device list only. No bus actions are performed.
00110       Selecting any device type will result in the complete list of devices 
00111       known to be present on the segment.
00112   
00113       <B>Note:</B>: The device type to look for is selected by the template parameter. 
00114                     To select any device type use LOW_device.
00115       
00116       @return Vector of found devices.
00117    */
00118   template<class devType> vector<devType*> getDevices() const;
00119 
00120     
00121   /** Search for devices on the segment.
00122   
00123       Selecting any device type will result in searching the whole segment.
00124       
00125       <B>Note:</B>: The device type to look for is selected by the template parameter.
00126                     To select any device type use LOW_device.
00127       
00128       <B>Note:</B>: The bus will be actively searched. Newly found devices will be
00129                     added to the internal device list.
00130                    
00131       @param  inOnlyAlarm  Determines whether to look only for alarming devices of the
00132                            requested type.   
00133       @return Vector of found devices.
00134    */
00135   template<class devType> vector<devType*> searchDevices( const bool inOnlyAlarm = false);
00136 
00137     
00138   /** Verify existance of a specific device on the segment.
00139   
00140       <B>Note:</B>: In case you already own a reference to the device, use the 
00141                     corresponding method from LOW_device.
00142       
00143       <B>Note:</B>: The bus will be actively searched. Newly found devices will be
00144                     added to the internal device list.
00145                    
00146       @param  inDevID      ID of the device to verify.
00147       @param  inOnlyAlarm  Determines whether to report existance only when
00148                            the device is alarming.
00149       @param  inDoReset    Whether to reset the bus afterwards.   
00150       @return Boolean indicates wheter the device could be found or not.
00151    */
00152   bool verifyDevice( const LOW_deviceID inDevID, const bool inOnlyAlarm = false, 
00153                      const bool inDoReset = true);
00154   
00155 
00156             
00157 //=======================================================================================
00158 protected:
00159 
00160   //=====================================================================================
00161   //
00162   // friends
00163   //
00164   
00165   friend class LOW_network;  /**< Enable access to static pseudo constructor and destructor */
00166   friend class LOW_device;   /**< Enable access to unregister a device on destruction. */
00167   
00168   
00169   //=====================================================================================
00170   //
00171   // constructors
00172   //
00173 
00174   /** Destructor.
00175       Destroys all objects of devices (in both maps).
00176    */
00177   ~LOW_netSegment();
00178 
00179   
00180   //=====================================================================================
00181   //
00182   // static methods
00183   //
00184 
00185   /** Discovers network segments on a link.
00186       @warning  By now only a single segment is supported.
00187 
00188       @param  inLink  The link to be searched for network segments.
00189    */
00190   static netSegPtrVec_t newSegmentsFromLink( LOW_link &inLink);
00191   
00192     
00193   //=====================================================================================
00194   //
00195   // methods
00196   //
00197   
00198   /** Indicate that a device instance is going to be deleted.  
00199       Function mainly used by the destructor of LOW_device.
00200   
00201       @param inDev  Device to unregister.
00202    */
00203   void unregisterDevice( const LOW_device *inDev);
00204   
00205   
00206   
00207   //=====================================================================================
00208   //
00209   // addressing/searching methods
00210   //
00211   
00212   /** Select a single device on a link.
00213   
00214       The matchROM command followed by a 64-bit ROM code sequence 
00215       allows the bus master to address a specific slave device on a 
00216       multidrop or single-drop bus. Only the slave that exactly matches 
00217       the 64-bit ROM code sequence will respond to the function command 
00218       issued by the master; all other slaves on the bus will wait for a 
00219       reset pulse.
00220       
00221       @param inDevice  Device to select.
00222       @throw noDevice_error  Thrown when no device was found on the bus.
00223    */
00224   void cmd_MatchROM( const LOW_device *inDevice) const;
00225 
00226     
00227   /** Select all devices on a link.
00228   
00229       The master can use this command to address all devices on the bus 
00230       simultaneously without sending out any ROM code information. 
00231       For example, the master can make all DS18S20s on the bus perform 
00232       simultaneous temperature conversions by issuing a Skip ROM command 
00233       followed by a ConvertT command.
00234 
00235       @throw noDevice_error  Thrown when no device was found on the bus.
00236    */
00237   void cmd_SkipROM() const;
00238   
00239   
00240   /** Read ID number from bus.
00241   
00242       The read ROM command allows the bus master to read the slave's 64-bit ROM 
00243       code without using the Search ROM procedure. 
00244       
00245       <B>Note</B>: The read ROM command can only be used when there is one slave on 
00246                    the bus. If this command is used when there is more than one slave 
00247                    present on the bus, a data collision will occur when all the slaves 
00248                    attempt to respond at the same time.
00249 
00250       @return  ID of the found device.
00251       @throw noDevice_error  Thrown when no device was found on the bus.
00252    */
00253   LOW_deviceID cmd_ReadROM() const;
00254 
00255   
00256   /** Scan the bus for devices.
00257   
00258       The searchROM command allows the master to determine the number of slaves 
00259       and their device types. The master learns the ROM codes through a process of 
00260       elimination that requires the master to perform a Search ROM cycle (i.e., 
00261       Search ROM command followed by data exchange) as many times as necessary to 
00262       identify all of the slave devices. 
00263       
00264       If there is only one slave on the bus, the simpler Read ROM command can be used 
00265       in place of the Search ROM process. 
00266     
00267       The search can be narrowed to devices which their alarm flag set and/or to 
00268       specific family codes.
00269       
00270       @param inOnlyAlarm   Whether to look only for alarming devices.
00271       @param inFamCode     Specific family code for narrowing search.
00272       @return  List of found IDs.
00273       @throw noDevice_error  Thrown when no device was found on the bus.
00274    */  
00275   LOW_deviceID::deviceIDVec_t cmd_SearchROM( const bool inOnlyAlarm = false,
00276                                              const LOW_deviceIDRaw::devFamCode_t inFamCode = LOW_device::anyDev_famCode) const;
00277   
00278   
00279   /** Scan the bus for a specific device.
00280 
00281       @param inDevID       Device to search for.
00282       @param inOnlyAlarm   Whether to report as found only when alarming.
00283       @param inDoReset     Whether to reset the bus afterwards.
00284       @return   Indicated whether the device was found or not.
00285       @throw noDevice_error  Thrown when no device was found on the bus.
00286    */  
00287   bool cmd_SearchROMVerify( const LOW_deviceID inDevID, const bool inOnlyAlarm = false, 
00288                             const bool inDoReset = true) const;
00289 
00290   
00291 
00292 //=======================================================================================
00293 private:
00294   
00295   //=====================================================================================
00296   //
00297   // static attributes
00298   //
00299   
00300   static segmentID_t  segmentCount; /**< Incremented on instance creation to get individual IDs. */
00301   
00302   
00303   //=====================================================================================
00304   //
00305   // attributes
00306   //
00307   
00308   
00309   const segmentID_t         segmentID;         /**< Identifier of the segment. */
00310   LOW_link                  &link;             /**< Link this segment is present on */
00311   bool                      hasExternalPower;  /**< Whether there is an additional line for external power supply available */
00312   LOW_device::deviceMap_t   aliveDevMap;       /**< Map of currently present devices on the segment */
00313   LOW_device::deviceMap_t   graveyardMap;      /**< Map of formerly present devices on the segment */
00314     
00315   
00316   //=====================================================================================
00317   //
00318   // constructors
00319   //
00320 
00321   /** Constructor from link.
00322       Triggers initial search of devices on the segment.
00323       @param  inLink  The link the segment resides on.
00324    */
00325   LOW_netSegment( LOW_link &inLink);
00326 
00327 
00328   //=====================================================================================
00329   //
00330   // operator overloading
00331   //
00332 
00333   bool operator==(LOW_netSegment &inSegment) const;  /**< Comparison based on segmentID. */
00334 
00335 
00336   //=====================================================================================
00337   //
00338   // methods
00339   //
00340 
00341   /** Safely cast a generic device pointer to a specific one.
00342       The type to cast to is specified by the template parameter.
00343       
00344       @param  inPtr  Generic pointer to be casted.
00345       @return Casted pointer of the requested type.
00346       @throw LOW_device::illegalCast_error  Thrown when type cast is not possible.
00347    */
00348   template<class castType> inline castType* devicePtr_cast( LOW_device *inPtr) const;
00349 
00350     
00351   /** Move a device from the alive map to the graveyard.
00352       If not in alive map, the method returns silently.
00353       
00354       @param  inDev  The device to move.
00355    */
00356   void buryDevice( const LOW_device *inDev);
00357   
00358   
00359   /** Move a device from the graveyard to the alive map.
00360       If not on graveyard, the method returns silently.
00361       
00362       @param  inDev  The device to move.
00363    */
00364   void revitalizeDevice( const LOW_device *inDev);
00365   
00366   
00367   /** Add a device to the alive map.
00368   
00369       When the device is already in the alive map nothing is done.
00370       When it is on the graveyard, it is moved to the alive map.
00371       When it does not exist at all, a new instance is created.
00372       
00373       @param  inDevID  The ID of the device to add.
00374       @return The added device.
00375    */
00376   LOW_device* addDevice( const LOW_deviceID inDevID);
00377   
00378   
00379   /** Removes a device from either the alive map or the graveyard.
00380       If it does not exist, the method returns silently.
00381   
00382       @param  inDev  The device to remove.
00383    */
00384   void removeDevice( const LOW_device *inDev);
00385 
00386 };
00387 
00388 
00389 
00390 //=====================================================================================
00391 // DEFINITIONS COMPILERS CANNOT HANDLE TO GO DIRECTLY INTO THE LIBRARY
00392 //=====================================================================================
00393 
00394 
00395 //=====================================================================================
00396 //
00397 // template definitions
00398 //
00399 
00400 template<class devType> devType* LOW_netSegment::getDevice( const LOW_deviceID inDevID)
00401 {
00402 
00403   if ( devType::familyCode!=LOW_device::anyDev_famCode && inDevID.getFamilyCode()!=devType::familyCode)
00404     throw LOW_device::familyMismatch_error( "Requested type does not match given device ID", __FILE__, __LINE__);
00405   
00406   // look in the map of alive devices
00407   LOW_device::deviceMap_t::iterator found = aliveDevMap.find( inDevID);
00408   if ( found == aliveDevMap.end() )
00409     throw noDevice_error( "Device not present on segment", __FILE__, __LINE__);
00410   
00411   return devicePtr_cast<devType>(found->second);
00412 }
00413 
00414 
00415 template<class devType> vector<devType*> LOW_netSegment::getDevices() const
00416 {
00417   vector<devType*> retVal;
00418 
00419   // look in the map of alive devices
00420   for( LOW_device::deviceMap_t::const_iterator a=aliveDevMap.begin(); a!=aliveDevMap.end(); ++a) {
00421     if ( devType::familyCode==LOW_device::anyDev_famCode || devType::familyCode==a->second->getID().getFamilyCode())
00422       retVal.push_back( devicePtr_cast<devType>(a->second));
00423   }
00424 
00425   return retVal;
00426 }
00427   
00428   
00429 template<class devType> vector<devType*> LOW_netSegment::searchDevices( const bool inOnlyAlarm)
00430 {
00431   LOW_deviceID::deviceIDVec_t idList = cmd_SearchROM( inOnlyAlarm, devType::familyCode);
00432   vector<devType*>            retVal = vector<devType*>( idList.size());
00433 
00434   // in case of NOT alarm search, remember the active devices
00435   LOW_device::devPtrVec_t   formerlyActiveDevs;
00436   if ( !inOnlyAlarm ) {
00437     vector<devType*> tmpVec = getDevices<devType>();
00438     for( unsigned int a=0; a<tmpVec.size(); a++)
00439       formerlyActiveDevs.push_back( tmpVec[a]);
00440   }
00441   
00442   for( unsigned int a=0; a<idList.size(); a++) {
00443     LOW_device *newDev = addDevice( idList[a]);
00444     retVal[a] = devicePtr_cast<devType>(newDev);
00445       
00446     // in case it was already present, remove the device from the formerly active devices
00447     if ( !inOnlyAlarm ) {
00448       LOW_device::devPtrVec_t::iterator foundFormerlyAlive = find( formerlyActiveDevs.begin(), formerlyActiveDevs.end(), newDev);
00449       if ( foundFormerlyAlive!=formerlyActiveDevs.end())
00450         formerlyActiveDevs.erase( foundFormerlyAlive);
00451     }
00452   }
00453   
00454   // what is now remaining is not present any more and therefore is sent to the graveyard
00455   if ( !inOnlyAlarm ) {
00456     for( unsigned int a=0; a<formerlyActiveDevs.size(); a++)
00457       buryDevice( formerlyActiveDevs[a]);
00458   }
00459     
00460   return retVal;
00461 }
00462 
00463 
00464 template<class castType> inline castType* LOW_netSegment::devicePtr_cast( LOW_device *inPtr) const
00465 {
00466   castType* retVal = dynamic_cast<castType*>(inPtr);
00467   
00468   if ( retVal == 0 )
00469     throw LOW_device::illegalCast_error( "Unexpected illegal type cast", __FILE__, __LINE__);
00470     
00471   return retVal;
00472 }
00473 
00474 
00475 #endif
00476 

Generated on Sun Jan 12 21:07:43 2003 by doxygen1.2.13.1 written by Dimitri van Heesch, © 1997-2001