Tango Controls

Tango Controls

Що таке TANGO?

Це система для управління різним обладнанням та програмним забезпеченням.
TANGO підтримує 4 платформи зараз: Linux, Windows NT, Solaris і HP-UX.
Тут буде описано роботу з Linux(Ubuntu 18.04)

Навіщо потрібно?

Спрощує роботу з різним обладнанням та софтом.

  • Вам не потрібно думати про те, як зберігати дані в БД, це вже зроблено за Вас.
  • Потрібно лише описати механізм опитування датчиків.
  • Зводить весь код до одного стандарту.

Де взяти?

З вихідних джерел не зміг її запустити, для роботи використовував готовий образ TangoBox 9.3.
В інструкції описано, як ставити з пакетів.

З чого вона складається?

  • ДЖАЙВ — використовується для перегляду та редагування бази даних TANGO.
  • ПНМО - Генератор коду для серверів пристроїв TANGO.
  • Астор - Програмний менеджер для системи TANGO.

Нас цікавитимуть лише перші два компоненти.

Підтримувані мови програмування

  • C
  • C + +
  • Java
  • JavaScript
  • Python
  • Матлаб
  • LabVIEW

Я працював з нею python & c++. Тут як приклад використовуватиметься c++.

Тепер перейдемо до опису, як підключити пристрій до TANGO і як з ним працювати. Як приклад буде взято плату GPS neo-6m-0-001:

Tango Controls

Як видно на картинці, плату до ПК підключаємо через UART CP2102. При підключенні до ПК з'являється пристрій /dev/ttyUSB[0-N]зазвичай /dev/ttyUSB0.

ПНМО

Тепер запустимо полярний геофізичний супутник, І з генеруємо скелет код для роботи з нашою платою.

pogo

Tango Controls

У мене вже був створений код, створимо його заново File->New.

Tango Controls

Отримуємо таке:

Tango Controls

Наш пристрій (під пристроєм надалі матиме на увазі програмна частина) порожній і має дві команди управління: стан & Статус.

Його потрібно заповнити необхідними атрибутами:

Властивість пристрою — значення за промовчанням, які передаємо у пристрій для його ініціалізації, для плати GPS потрібно передати ім'я плати в системі com="/dev/ttyUSB0" і швидкість com порту baudrade=9600

Команди — команди управління нашим пристроєм, їм можна задати аргументи та значення, що повертається.

  • СТАН — повертає поточний стан, Штати
  • СТАТУС - Повертає поточний статус, це рядковий додаток до СТАН
  • GPSArray - Повертає GPS рядок у вигляді DevVarCharArray

Далі задаються атрибути пристрою, які можна читати/писати в/з нього.
Scalar Attributes - Прості атрибути (char, string, long і т.п.)
Spectrum Attributes - одномірні масиви
Атрибути зображення - двомірні масиви

Штати — стану, в якому знаходиться наш пристрій.

  • ВІДЧИНЕНО - Пристрій відкритий.
  • ЗАКРИТИ - Пристрій закрито.
  • FAILT - Помилка.
  • ON - приймаємо дані із пристрою.
  • OFF - немає даних із пристрою.

Приклад додавання атрибуту gps_string:

Tango Controls

Polling period час у мс, як часто оновлюватиметься значення gps_string. Якщо час оновлення не задати, атрибут оновлюватиметься лише за запитом.

Вийшло:

Tango Controls

Тепер потрібно згенерувати код File->Generate

Tango Controls

За замовчуванням Makefile не генерується, вперше потрібно поставити галочку щоб його створити. Це зроблено для того, щоб внесені до нього правки не видалялися при новій генерації. Створивши його один раз і налаштувавши під свій проект (прописати ключі компіляції, додаткові файли) можна забути про нього.

Тепер переходимо безпосередньо до програмування. pogo з генерував нам наступне:

Tango Controls

Нас цікавитимуть NEO6M.cpp & NEO6M.h. Розглянемо для прикладу конструктор класу:

NEO6M::NEO6M(Tango::DeviceClass *cl, string &s)
 : TANGO_BASE_CLASS(cl, s.c_str())
{
    /*----- PROTECTED REGION ID(NEO6M::constructor_1) ENABLED START -----*/
    init_device();

    /*----- PROTECTED REGION END -----*/    //  NEO6M::constructor_1
}

Що тут є та що тут головне? У функції init_device() відбувається виділення пам'яті для наших атрибутів: gps_string & gps_array, але це не важливо. Найважливіше тут, це коментарі:

/*----- PROTECTED REGION ID(NEO6M::constructor_1) ENABLED START -----*/
    .......
/*----- PROTECTED REGION END -----*/    //  NEO6M::constructor_1

Все що знаходиться всередині цього блоку коментаря при наступних перегенераціях коду в pogo не буде віддалятися!. Все що в блоках не буде! Це ті місця, де ми можемо програмувати і вносити свої правки.

Тепер які основні функції містить клас NEO6M:

void always_executed_hook();
void read_attr_hardware(vector<long> &attr_list);
void read_gps_string(Tango::Attribute &attr);
void read_gps_array(Tango::Attribute &attr);

Коли ми захочемо прочитати значення атрибуту gps_string, будуть викликані функції у такому порядку: always_executed_hook, read_attr_hardware и read_gps_string. У read_gps_string відбудеться заповнення gps_string значенням.

void NEO6M::read_gps_string(Tango::Attribute &attr)
{
    DEBUG_STREAM << "NEO6M::read_gps_string(Tango::Attribute &attr) entering... " << endl;
    /*----- PROTECTED REGION ID(NEO6M::read_gps_string) ENABLED START -----*/
    //  Set the attribute value

        *this->attr_gps_string_read = Tango::string_dup(this->gps.c_str());

    attr.set_value(attr_gps_string_read);

    /*----- PROTECTED REGION END -----*/    //  NEO6M::read_gps_string
}

компіляція

Заходимо до папки з вихідними джерелами і:

make

Програма скомпілюється в папку ~/DeviceServers.

tango-cs@tangobox:~/DeviceServers$ ls
NEO6M

ДЖАЙВ

jive

Tango Controls

У БД вже є якісь пристрої, створимо тепер наше Edit->Create Server

Tango Controls

Тепер спробуємо підключитися до нього:

Tango Controls

Нічого не вийде, спочатку треба запустити нашу програму:

sudo ./NEO6M neo6m -v2

Підключитися до порту com у мене можна тільки з правами корінь-а. v - Рівень логування.

Тепер можемо підключитися:

Tango Controls

клієнт

У графіку дивитися на картинки звичайно добре, але потрібно щось корисніше. Напишемо клієнт, який буде підключатися до нашого пристрою і забирати з нього показання.

#include <tango.h>
using namespace Tango;

int main(int argc, char **argv) {
    try {

        //
        // create a connection to a TANGO device
        //

        DeviceProxy *device = new DeviceProxy("NEO6M/neo6m/1");

        //
        // Ping the device
        //

        device->ping();

        //
        // Execute a command on the device and extract the reply as a string
        //

        vector<Tango::DevUChar> gps_array;

        DeviceData cmd_reply;
        cmd_reply = device->command_inout("GPSArray");
        cmd_reply >> gps_array;

        for (int i = 0; i < gps_array.size(); i++) {            
            printf("%c", gps_array[i]);
        }
        puts("");

        //
        // Read a device attribute (string data type)
        //

        string spr;
        DeviceAttribute att_reply;
        att_reply = device->read_attribute("gps_string");
        att_reply >> spr;
        cout << spr << endl;

        vector<Tango::DevUChar> spr2;
        DeviceAttribute att_reply2;
        att_reply2 = device->read_attribute("gps_array");
        att_reply2.extract_read(spr2);

        for (int i = 0; i < spr2.size(); i++) {
            printf("%c", spr2[i]);
        }

        puts("");

    } catch (DevFailed &e) {
        Except::print_exception(e);
        exit(-1);
    }
}

Як компілювати:

g++ gps.cpp -I/usr/local/include/tango -I/usr/local/include -I/usr/local/include -std=c++0x -Dlinux -L/usr/local/lib -ltango -lomniDynamic4 -lCOS4 -lomniORB4 -lomnithread -llog4tango -lzmq -ldl -lpthread -lstdc++

Результат:

tango-cs@tangobox:~/workspace/c$ ./a.out 
$GPRMC,,V,,,,,,,,,,N*53

$GPRMC,,V,,,,,,,,,,N*53

$GPRMC,,V,,,,,,,,,,N*53

Отримали результат як повернення команди, взяття атрибутів рядка та масиву символів.

Посилання

Статтю писав собі, тому що через деякий час починаю забувати як і що робити.

Дякую за увагу.

Джерело: habr.com

Додати коментар або відгук