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

Generated on Tue Feb 3 11:30:26 2004 for OneWireLibrary++ by doxygen 1.3.2