Main Page | Class Hierarchy | Class List | File List | Class Members | File Members | Related Pages | Examples

Device.h

Implementation of the Device class from Device Server Example.
See also:
Property.h

DeviceServer.h

#ifndef _EXAMPLES_DEVICE_H_
#define _EXAMPLES_DEVICE_H_

#include "Property.h"

//
// A little utility class that provides "exception safe" mutex locking. 
// The constructor calls lock() and the destructor calls unlock() on the 
// specified mutex. This makes it impossible to leave a function containing 
// a Lock object without unlocking the mutex, even if an exception is thrown
// in the function.
//
class Lock
{
   pthread_mutex_t* mut;

   public:
   
      Lock(pthread_mutex_t& m) : mut(&m)
      { 
         pthread_mutex_lock(mut);
      }

      ~Lock() 
      { 
         pthread_mutex_unlock(mut);
      }
};

//
// The simulated power supply device.
//
class Device
{
   //
   // The device name
   //
   char* name;

   //
   // The mutex which is used to synchronize access to the device data
   //
   pthread_mutex_t deviceAccess;

   //
   // The array of pointers to the device properties.
   // Implements the Device --> Property relationship.
   //
   Property** properties;
   int numProperties;

   //
   // Returns a pointer to the property or throws rdaBadParameter if the 
   // property is not found in the device (used in device access methods).
   //
   Property* findProperty(const char* property)
   {
      Property* result = 0;
      for (int i = 0; i < numProperties; i++)
      {
         if (!strcmp(properties[i]->getName(), property))
         {
            result = properties[i];
            break;
         }
      }
      if (result == 0) throw rdaBadParameter("No such property");
      return result;
   }
   
   public:

      //
      // Constructor: creates properties and initializes the device
      // access mutex.
      //
      Device(const char* deviceName)
      {
         name = strdup(deviceName);
         numProperties = 2;
         properties = new Property* [numProperties];
         properties[0] = new Measurement;
         properties[1] = new Setting;
         pthread_mutex_init(&deviceAccess, 0);
      }

      //
      // Destructor: deletes properties and destroys the device access mutex
      //
      virtual ~Device()
      {
         for (int i = 0; i < numProperties; i++) delete properties[i];
         delete [] properties;
         delete name;
         pthread_mutex_destroy(&deviceAccess);

      }

      //
      // Returns the device name (used in DeviceServer)
      //
      const char* getName()
      {
         return name;
      }
      
      //
      // Updates the measurement value (called from DeviceServer::update()).
      //
      void update()
      {
         Lock lock(deviceAccess);
         //
         // Calculate simulated measurement value as
         //    setting value + random jitter
         //
         int r = rand() % 100;
         double jitter = ((double)r)/10.0 - 5.0;
         double newValue = properties[1]->getValue() + jitter;
         //
         // Update the measurement value
         //
         ((Measurement*)properties[0])->update(newValue);
      }

      //
      // Device access methods
      // =====================
      //
      // All device access methods first try to look up the target property.
      // If the property is not found in the device, findProperty() will 
      // throw the rdaBadParameter exception. This exception is not caught 
      // here: RDA will pass it to the calling client. If findProperty() 
      // returns normally, then the calls are delegated further to the 
      // property objects.
      //
      rdaData* get(const char* propName)
      {
         Lock lock(deviceAccess);
         Property* property = findProperty(propName);
         return property->get();
      }
      
      void set(const char* propName, const rdaData& value)
      {
         Lock lock(deviceAccess);
         Property* property = findProperty(propName);
         property->set(value);
      }
      
      void monitorOn(const char* propName, rdaValueChangeListener* listener)
      {
         Lock lock(deviceAccess);
         Property* property = findProperty(propName);
         property->addListener(listener);
      }

      void monitorOff(const char* propName, rdaValueChangeListener* listener)
      {
         Lock lock(deviceAccess);
         Property* property = findProperty(propName);
         property->removeListener(listener);
      }
};

#endif

RDA-2.3 documentation - 27 Jun 2007 - N.Trofimov