OnReadValue getValue_;         // (11)

  OnOperable getOperable_;       // (12)

  SensorValue defaultValue_ = 0; // (13)

  bool defaultOperable_ = true;  // (14)

};

В строке 1 объявляется перечисление для указания используемого метода чтения показателей. В строке 2 и 3 объявляются типы для обратных вызовов. Переменные соответствующих типов для хранения вызовов объявлены в строках 11 и 12. Настройка вызовов производится в методах 6 и 7. Кроме того, объявляются переменные для хранения значений по умолчанию (строки 13 и 14), эти переменные настраиваются в методах 4 и 5.

Реализацию чтения показателей продемонстрируем на примере получения текущего значения датчика (Листинг 90).

Листинг 90. Чтение текущего значения датчика в имитируемом драйвере (DriverImpl.cpp)

SensorValue DriverSimulation::readSpot(SensorNumber number)

{

  if (getValue_)  // (1)

  {

    return getValue_(number, READ_SPOT);  // (2)

  }

  else

  {

    return defaultValue_;  // (3)

  }

}

В строке 1 проверяется, настроен ли обратный вызов. Если настроен, то через него запрашивается значение для соответствующего датчика. Информацией вызова здесь является номер датчика и метод чтения показателей (строка 2). Если обратный вызов не настроен, то возвращается значение по умолчанию (строка 3).

<p>6.2.4. Датчик</p>

Обобщенный интерфейсный класс для работы с датчиком приведен в Листинг 91.

Листинг 91. Интерфейсный класс для роботы с датчиком (SensorInterface.h)

namespace sensor

{

class ISensor

{

public:

  virtual void setDriver(DriverPointer driverPointer) = 0;  // (1)

  virtual DriverPointer getDriver() = 0;  // (2)

  virtual double getValue() = 0;  // (3)

  virtual bool isOperable() = 0;  // (4)

  virtual ~ISensor() = default;

  static SensorPointer createSensor(SensorType type, SensorNumber number, DriverPointer driverPointer);  // (5)

};

}; //namespace sensor

В строке 1 объявлен метод для настройки драйвера, с которым будет работать датчик. Получить используемый драйвер можно с помощью метода 2. В строках 3 и 4 объявлены методы для получения текущего значения датчика и определения его работоспособности. В строке 5 объявлен метод для создания экземпляра класса соответствующего типа.

В соответствии с требованиями нам необходимо реализовать датчики, которые бы возвращали текущие, сглаженные и производные значения показателей. Для каждого способа реализован отдельный класс; диаграмма классов изображена на Рис. 29.

Рис. 29. Диаграмма классов, реализующих управление датчиками

Как видно из диаграммы, при вызове метода для получения значения датчик обращается к драйверу, вызывая соответствующие методы. В зависимости от настроенного драйвера будут возвращаться реальные или имитируемые значения.

<p>6.2.5. Контейнер</p>

Контейнер предназначен для хранения экземпляров классов для управления датчиками. Объявление класса приведено в Листинг 92.

Листинг 92. Объявление контейнера (SensorContainer.h)

namespace sensor

{

  class ISensor;

  class SensorContainer

  {

  public:

    void addSensor(SensorNumber number, SensorPointer sensor);  // (1)

    void deleteSensor(SensorNumber number);                     // (2)

    SensorPointer checkSensorExist(SensorNumber number);        // (3)

    SensorPointer findSensor(SensorNumber number);              // (4)

    template

    void forEachSensor(CallbackIterate&& callback)  // (5)

    {

      for (auto item : container_)                // (6)

      {

        callback(item.first, item.second);

      }

    }

private:

    std::map container_;  // (7)

  };

};

Хранилище объектов реализовано в виде двоичного дерева (строка 7). Ключом здесь выступает номер датчика, содержимым является указатель на класс управления датчиком. Методы для добавления и удаления указателей объявлены в строках 1 и 2.

Перейти на страницу:

Похожие книги