-
Notifications
You must be signed in to change notification settings - Fork 1
Устройства
Предполагается что вы ознакомлены с документации работой с гитом и структурой проекта. Если нет. Откройте сайт группы и скачайте файл kursova_instrumety_instrukcii.pdf, либо откройте директорий Doc/ в корень проекта.
Устройство это класс реализовывающий Devices.IDevice
. Файлы связанных с устройством находится в проекте Devices. Класс устройства сопровождается классом данных устройства и адаптерами для разных слоев БД. Устройство инкапсулирует в себе процесс снятия информации с физического устройства.
1.1. Открываем проект в Visual Studio.
1.2. Создаем новую папку в подпроекте Devices. Для названия папки используйте название_устройства + Device. Например, для GPS-устройства название папки будет иметь вид GPSDecice.
1.3. В полученной папке создаем новый файл формата ".cs". Название файла должно совпадать с название папки. Например, в созданной папке GPSDevice созданный файл будет иметь имя GPSDevice.cs.
1.4. В созданном файле прописываем класс, который будет реализовывать интерфейс IDevice. Существуют два требования к данному классу: конструктор не должен иметь параметры и реализовывать методы IDevice. Например: (https://github.com/dodev/RoadDataCollector/blob/master/Main/Devices/DummyDevice/DummyDevice.cs)
/// <summary>
/// Примерное устройство. Генерирует 3 произвольных чисел и с ним заполняет объект из типа
///DummyDeviceData
/// </summary>
public class DummyDevice : IDevice
{
// имя устройства в конфиг файле
string name;
Random rand;
/// <summary>
/// Конструктор должен быть без параметров!
/// </summary>
public DummyDevice ()
{
rand = new Random ();
}
#region IDevice implementation
/// <summary>
/// Дает имя объекта, как он назван в конфиг файле
/// </summary>
/// <value>The I.</value>
public string ID {
get { return name; }
}
/// <summary>
/// Инициализирует устройство с именем из конфиг файла и адаптер для подготовки
///DummyDeviceData для вставки в БД.
/// </summary>
/// <param name="name">Name.</param>
/// <param name="adapter">Adapter.</param>
public void Init (string name)
{
this.name = name;
}
/// <summary>
/// Генерация информации. В ваших устройствах, здесь должен быть код общающийся с
///физическим устройством.
/// Также и код создания объекта содержащий информацию из устройства.
/// В этом случае - DummyDeviceData.
/// </summary>
/// <returns>The data.</returns>
public object GetData ()
{
return new DummyDeviceData (rand.Next (), rand.Next (), rand.Next ());
}
#endregion
}
Далее более подробно рассмотрим методы IDevice (https://github.com/dodev/RoadDataCollector/blob/master/Main/Devices/IDevice.cs).
public interface IDevice
{
/// <summary>
/// Имя устройства, как оно названо в конфиг. файле.
/// </summary>
/// <value>The I.</value>
string ID { get; } //должен возвращать имя устройства,
//то имя которое ему было дано в Init(см. ниже)
/// <summary>
/// Инициализирует устройство с именем из конфиг. файла.
/// </summary>
/// <param name="name">Name.</param>
void Init (string name); //принимает имя устройства, вызывается только в начале процесса снятия
//данных. Используйте этот метод если общение с устройством требует
//предварительных настроек
/// <summary>
/// Снимает данные с устройства
/// </summary>
/// <returns>The data.</returns>
object GetData (); //возвращает информацию с устройства. Он вызывается каждый раз, когда таймер
//дает сигнал снятия данных
}
1.5. Далее требуется создать класс, объекты которого будут сохранять информацию с устройств. Цель этого класса - преподнести данные в одном объекте для красоты и удобства использования. Файл с классом должен быть в той же директории, что и ваша реализация IDevice. Имя этого файла должно иметь вид имя_устройства+Device+Data. Например, для устройства GPSDevice - GPSDeviceData. Пример требуемого класса (https://github.com/dodev/RoadDataCollector/blob/master/Main/Devices/DummyDevice/DummyDeviceData.cs)
/// <summary>
/// Содержит информацию из устройства и методы для ее извлечения.
/// </summary>
public class DummyDeviceData
{
int x;
int y;
int z;
public DummyDeviceData (int x, int y, int z)
{
this.x = x;
this.y = y;
this.z = z;
}
public int GetX () {return x;}
public int GetY () {return y;}
public int GetZ () {return z;}
}
IDevice.GetData() возвращает object, что позволяет легко передавать ваш тип данных. Он будет сконвертирован в месте назначения из object в ваш тип данных из устройства (например, из object в GPSDeviceData). Например: var dummyData = data as DummyDeviceData. (https://github.com/dodev/RoadDataCollector/blob/master/Main/Devices/DummyDevice/DummyDeviceDummyDBAdapter.cs#L28).
Адаптер нужен для того чтобы информация из устройства была переведена на язык конкретной СУБД. Он представляет собой файл с описанием класса, который должен хранится в папке, которую мы создали ранее. Для каждой СУБД для одного устройства должен быть один адаптер. В нашей программе СУБД две: локальная и удаленная. Соответственно для одного устройства будет один адаптер для работы с локальной СУБД и один адаптер для работы с удаленной СУБД. Название файла должно иметь вид: имя_устройства+Device+LocalDB(или RemoteDB)+Adapter. Например, для GPS-устройства должны быть GPSDeviceLocalDBAdapter и GPSDeviceRemoteDBAdapter. Класс адаптера содержит только один метод - IQuery PrepareQuery (object data) (https://github.com/dodev/RoadDataCollector/blob/master/Main/Devices/IStorageAdapter.cs).
/// <summary>
/// Переводит инфоримацию устройства на языке СУДБ
/// </summary>
public interface IStorageAdapter
{
/// <summary>
/// Берет информацию из дивайса как object. Переобразует ее в
/// класс данных устройва и создает IQuery для соответствующего класса связи с БД.
/// </summary>
/// <returns>The query.</returns>
/// <param name="data">Data.</param>
IQuery PrepareQuery (object data);
}
Этот метод создает из объекта информации (к примеру, из GPSDeviceData) объект для работы с СУБД (IQeury), слой которого будет использоваться для выполнения запроса. Под слоем понимается - совокупность классов, отвечающих за работу с СУБД. У каждого такого слоя есть своя реализация IQuery (например, у localDB - реализация LocalQuery).
Таким образом, задача адаптера, на примере GPSDeviceLocalDBAdapter, состоит в создании из объекта GPSDeviceData объект LocalQuery. Пример создания такого объекта (https://github.com/dodev/RoadDataCollector/blob/master/Main/Devices/DummyDevice/DummyDeviceDummyDBAdapter.cs#L32)
var query = new DummyQuery ("dummy_coordinates",
new string[] {"x", "y", "x"},
new string[] {
dummyData.GetX ().ToString (),
dummyData.GetY ().ToString (),
dummyData.GetZ ().ToString ()
});
В дальнейшем в качестве объекта для общения с БД DummyDBConnection будет использовать запросы только из DummyQuery.
В итоге, для реализации адаптеров должны выполнятся 4 условия:
-
количество адаптеров зависит от количества БД;
-
конструктор в классе адаптера не должен содержать параметры;
-
каждый адаптер должен принимать в качестве аргумента объект типа информационного объекта устройства; (Например, GPSDeviceData)
-
адаптер должен возвращать объект типа запроса для конкретной БД (реализация IQuery для данной БД).
3.1. Для выполнения этого пункта необходимо открыть файл "config.xml" и прописать основные характеристики устройства в тэге DeviceConfiguration. Например, (https://github.com/dodev/RoadDataCollector/blob/master/Main/Main/config.xml#L57)
<DeviceConfiguration>
<ID>dummy_device</ID>
<DisplayName>Пробное устройство</DisplayName>
<Assembly>Devices</Assembly>
<Namespace>Devices</Namespace>
<DeviceType>DummyDevice</DeviceType>
</DeviceConfiguration>
<DeviceConfiguration>
<ID>clock_device</ID>
<DisplayName>Часы</DisplayName>
<Assembly>Devices</Assembly>
<Namespace>Devices</Namespace>
<DeviceType>ClockDevice</DeviceType>
</DeviceConfiguration>
Рассмотрим подробнее основные характеристики:
-
ID - уникальный идентификатор устройства. Через него программа распознает устройства;
-
DisplayName - имя, которое будет отображаться в графическом интерфейсе;
-
Assembly - имя сборки, в нашем случае Devices;
-
Namespace - namespace класса устройства (Devices);
-
DeviceType - имя класса устройства ( в рассмотренном примере- это GPSDevice).
Последние 3 настройки устройства (Assembly, Namespace, DeviceType) представляют собой путь к созданному классу. Внимательно проверьте, что перед началом описания характеристик устройства был прописан тэг DeviceConfiguration, и по завершению описания был прописан закрывающий тэг тэга DeviceConfiguration.
3.2. Следующий шаг состоит в том, что необходимо прописать настройки адаптера. Они добавляются в настройках БД. Для каждой базы данных есть тэг DeviceConfiguration в файле "config.xml". Внутри его настроек необходимо найти тэг SerializedAdapters. Именно внутри этого тэга необходимо прописать настройки адаптера для вашего устройства данной БД. Например, (https://github.com/dodev/RoadDataCollector/blob/master/Main/Main/config.xml#L22)
<SerializedAdapters>
<string>dummy_device</string>
<string>DummyDeviceDummyDBAdapter</string>
<string>clock_device</string>
<string>ClockDeviceDummyDBAdapter</string>
</SerializedAdapters>
Настройки каждого адаптера состоят из двух строк:
-
в первой строчке внутри тэга string пишется уникальный идентификатор устройства, который был присвоен ему ранее внутри тэга DeviceConfiguration
-
во второй строчке внутри тэга string пишется имя адаптера для данной БД и для данного устройства.
Необходимо прописать эти настройки для каждого адаптера в конфигурации необходимой БД
Если все прописано правильно, то после сохранения и запуска приложения, устройство будет работать.