bool isOperable(SensorNumber number) override;
void setDefaultValue(SensorValue value); // (4)
void setDefaultOperable(bool isOperable); // (5)
void setReadValue(OnReadValue value); // (6)
void setOperable(OnOperable operable); // (7)
SensorValue readSpot(SensorNumber number) override; // (8)
SensorValue readSmooth(SensorNumber number) override; // (9)
SensorValue readDerivative(SensorNumber number) override; // (10)
static IDriver* create();
protected:
DriverSimulation();
private:
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).
Обобщенный интерфейсный класс для работы с датчиком приведен в Листинг 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. Диаграмма классов, реализующих управление датчиками
Как видно из диаграммы, при вызове метода для получения значения датчик обращается к драйверу, вызывая соответствующие методы. В зависимости от настроенного драйвера будут возвращаться реальные или имитируемые значения.
Контейнер предназначен для хранения экземпляров классов для управления датчиками. Объявление класса приведено в Листинг 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.
Метод в строке 3 возвращает указатель на объект класса, если последний с заданным номером содержится в хранилище, в противном случае возвращается нулевой указатель. Метод в строке 4 возвращает указатель на объект класса для соответствующего номера; если объект отсутствует, то генерируется исключение.
Читать дальше