
Что такое TANGO?
Это система для управления различным оборудованием и программным
обеспечением.
TANGO поддерживает 4 платформы на данный момент: Linux, Windows NT,
Solaris и HP-UX.
Здесь будет описана работа с Linux(Ubuntu 18.04)
Где взять?
Из исходников не смог ее запустить, для работы использовал
готовый образ TangoBox 9.3.
В инструкции описано как ставить из пакетов.
Из чего она состоит?
- JIVE служит для просмотра и редактирования базы данных TANGO.
- POGO генератор кода для серверов устройств TANGO.
- Astor программный менеджер для системы TANGO.
Нас будут интересовать только первые два компонента.
Поддерживаемые языки программирования
- C
- C++
- Java
- JavaScript
- Python
- Matlab
- LabVIEW
Я работал с ней на python & c++. Здесь в качестве примера будет использоваться c++.
Теперь перейдем к описанию как подключить устройство к TANGO и как с ним работать. В качестве примера будет взята плата GPS neo-6m-0-001:


Как видно на картинке плату к ПК подключаем через UART CP2102. При подключении к ПК появляется устройство /dev/ttyUSB[0-N], обычно /dev/ttyUSB0.
POGO
Теперь запустим pogo, и с генерируем скелет код для работы с нашей платой.

У меня уже был создан код, создадим его заново File->New.

Получаем следующее:

Наше устройство(под устройством в дальнейшем будет иметься ввиду
программная часть) пустое и имеет две команды управления:
State & Status.
Его нужно заполнить необходимыми атрибутами:
Device Property значения по умолчанию которые
передаем в устройство для его инициализации, для платы GPS нужно
передать имя платы в системе com="/dev/ttyUSB0" и
скорость com порта baudrade=9600
Commands команды управления нашим устройством, им
можно задать аргументы и возвращаемое значение.
- STATE возвращает текущее состояние, из States
- STATUS возвращает текущий статус, это строковое дополнение к STATE
-
GPSArray возвращает gps
строку в виде DevVarCharArray
Далее задаются атрибуты устройства которые можно читать/писать в/из него.
Scalar Attributes простые атрибуты (char, string, long и т.п.)
Spectrum Attributes одномерные массивы
Image Attributes двумерные массивы
States состояния в котором находится наше устройство.
- OPEN устройство открыто.
- CLOSE устройство закрыто.
- FAILT ошибка.
- ON принимаем данные с устройства.
- OFF нет данных с устройства.
Пример добавления атрибута gps_string:

Polling period время в мс, как часто будет обновляться значение gps_string. Если время обновления не задать, то атрибут будет обновляться только по запросу.
Получилось:

Теперь нужно с генерировать код File->Generate

По умолчанию Makefile не генерируется, в 1-ый раз нужно поставить галочку что бы его создать. Это сделано для того что бы внесенные в него правки не удалялись при новой генерации. Создав его единожды и настроив под свой проект(прописать ключи компиляции, доп. файлы) можно забыть про него.
Теперь переходим непосредственно к программированию. pogo с генерировал нам следующее:

Нас будут интересовать 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$ lsNEO6M
JIVE

В БД уже есть какие-то устройства, создадим теперь наше Edit->Create Server

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

Ни чего не выйдет, сначала надо запустить нашу программу:
sudo ./NEO6M neo6m -v2
Подключиться к com порту у меня можно только с правами root-а. v уровень логирования.
Теперь можем подключиться:

Клиент
В графике смотреть на картинки конечно хорошо, но нужно что-то более полезное. Напишем клиент который будет подключаться к нашему устройству и забирать с него показания.
#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
Получили результат в качестве возврата команды, взятия атрибутов строки и массива символов.
Ссылки
Статью писал для себя, потому что спустя некоторое время начинаю
забывать как и что делать.
Спасибо за внимание.