
Какво представлява ?
Това е система за управление на различно оборудване и софтуер.
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, и генерираме скелетен код за работа с нашата платка.
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 — устройството е отворено.
- ЗАТВОРИ — устройството е затворено.
- НЕУСПЕШНО — грешка.
- ON — получаваме данни от устройството.
- ИЗКЛ. — няма данни от устройството.
Пример за добавяне на атрибут gps_string:

Период на опрашване време в ms, колко често ще се обновява стойността на gps_string. Ако времето за обновление не е зададено, атрибутът ще се обновява само по заявка.
Получено:

Сега трябва да генерираме код File->Generate

По подразбиране Makefile не се генерира, при първото използване трябва да се постави отметка, за да бъде създаден. Това е направено, за да не се изтриват направените промени при нова генерация. След като го създадете веднъж и го настроите за вашия проект (да зададете компилационни ключове, допълнителни файлове), можете да забравите за него.
Сега преминаваме директно към програмирането. pogo генерира следното за нас:

Нас ще ни интересуват NEO6M.cpp & NEO6M.h. Нека разгледаме конструктора на класа като пример:
NEO6M::NEO6M(Tango::DeviceClass *cl, string &s)
: TANGO_BASE_CLASS(cl, s.c_str())
{
/*----- ПРОТЕКТИРАНА ЗОНА ID(NEO6M::constructor_1) АКТИВИРАНА НАЧАЛО -----*/
init_device();
/*----- ПРОТЕКТИРАНА ЗОНА КРАЙ -----*/ // 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 &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) влизане... " <attr_gps_string_read = Tango::string_dup(this->gps.c_str());
attr.set_value(attr_gps_string_read);
/*----- ПРОТЕКТИРАНА ЗОНА КРАЙ -----*/ // NEO6M::read_gps_string
}Компилация
Влизаме в папката с изходния код и:
, затова потребителите на Windows трябва да инсталират Cygwin или да се справят сами с Visual Studio и библиотеките.Програмата ще бъде компилирана в папката ~/DeviceServers.
tango-cs@tangobox:~/DeviceServers$ ls
NEO6MJIVE
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Получихме резултат в отговор на командата, извличане на атрибутите на реда и масива от символи.
Връзки
Написах статията за себе си, защото след известно време започвам да забравям как и какво да правя.
Благодаря за вниманието.
Източник: habr.com
