Skip to content

Устройства

MarMaishka edited this page Apr 17, 2013 · 39 revisions

Предполагается что вы ознакомлены с документации работой с гитом и структурой проекта. Если нет. Откройте сайт группы и скачайте файл kursova_instrumety_instrukcii.pdf, либо откройте директорий Doc/ в корень проекта.

Устройство это класс реализовывающий Devices.IDevice. Файлы связанных с устройством находится в проекте Devices. Класс устройства сопровождается классом данных устройства и адаптерами для разных слоев БД. Устройство инкапсулирует в себе процесс снятия информации с физического устройства.

Для добавления устройства в проект

1. Написать реализацию IDevice для текущего проекта.

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).

2. Создать адаптеры для текущей БД (реализовать IStorageAdapter).

Адаптер нужен для того чтобы информация из устройства была переведена на язык конкретной СУБД. Он представляет собой файл с описанием класса, который должен хранится в папке, которую мы создали ранее. Для каждой СУБД для одного устройства должен быть один адаптер. В нашей программе СУБД две: локальная и удаленная. Соответственно для одного устройства будет один адаптер для работы с локальной СУБД и один адаптер для работы с удаленной СУБД. Название файла должно иметь вид: имя_устройства+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 условия:

  1. количество адаптеров зависит от количества БД;

  2. конструктор в классе адаптера не должен содержать параметры;

  3. каждый адаптер должен принимать в качестве аргумента объект типа информационного объекта устройства; (Например, GPSDeviceData)

  4. адаптер должен возвращать объект типа запроса для конкретной БД (реализация IQuery для данной БД).

3. Написать настройки устройства в config.xml

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>

Рассмотрим подробнее основные характеристики:

  1. ID - уникальный идентификатор устройства. Через него программа распознает устройства;

  2. DisplayName - имя, которое будет отображаться в графическом интерфейсе;

  3. Assembly - имя сборки, в нашем случае Devices;

  4. Namespace - namespace класса устройства (Devices);

  5. 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>

Настройки каждого адаптера состоят из двух строк:

  1. в первой строчке внутри тэга string пишется уникальный идентификатор устройства, который был присвоен ему ранее внутри тэга DeviceConfiguration

  2. во второй строчке внутри тэга string пишется имя адаптера для данной БД и для данного устройства.

Необходимо прописать эти настройки для каждого адаптера в конфигурации необходимой БД

Если все прописано правильно, то после сохранения и запуска приложения, устройство будет работать.