
Ce este ?
Este este un sistem pentru gestionarea diverselor echipamente și software-uri.
TANGO suportă în prezent 4 platforme: Linux, Windows NT, Solaris și HP-UX.
Aici va fi descrisă lucrul cu Linux (Ubuntu 18.04)
De ce este necesar?
Facilitează lucrul cu diverse echipamente și software.
- Nu trebuie să vă gândiți la cum să stocați datele în BD, asta a fost deja făcut pentru dumneavoastră.
- Trebuie doar să descrieți mecanismul de interogare a senzorilor.
- Reduce tot codul dumneavoastră la un singur standard.
De unde se poate obține?
Nu am putut să o pornesc din surse, am folosit o imagine gata făcută TangoBox 9.3.
În instrucțiuni este descris cum să o instalați din pachete.
Din ce este compusă?
- JIVE — servește pentru vizualizarea și editarea bazei de date TANGO.
- POGO — generator de cod pentru serverele de dispozitive TANGO.
- Astor — manager software pentru sistemul TANGO.
Ne vor interesa doar primele două componente.
Limbaje de programare suportate
- C
- C++
- Java
- JavaScript
- Python
- Matlab
- LabVIEW
Am lucrat cu ea pe python & c++. Aici va fi folosit c++ ca exemplu.
Acum vom trece la descrierea modului de conectare a dispozitivului la TANGO și cum să lucrezi cu acesta. Ca exemplu va fi luată placa GPS neo-6m-0-001:

După cum se vede în imagine, placa este conectată la PC prin UART CP2102. Atunci când este conectată la PC, apare dispozitivul /dev/ttyUSB[0-N], de obicei /dev/ttyUSB0.
POGO
Acum să pornim pogo, și generăm structura de bază a codului pentru a lucra cu placa noastră.
pogo
Am avut deja codul creat, să-l recreăm de la început File->New.

Obținem următorul rezultat:

Dispozitivul nostru (prin dispozitiv ne referim pe viitor la partea software) este gol și are două comenzi de control: State & Stare.
Trebuie să fie completat cu atributele necesare:
Proprietate dispozitiv — valori implicite pe care le trimitem dispozitivului pentru inițializare, pentru placa GPS trebuie să trimitem numele plăcii în sistem com="/dev/ttyUSB0" și viteza portului com baudrate=9600
Comenzi — comenzi de control pentru dispozitivul nostru, pentru acestea se pot specifica argumente și valori returnate.
- STATE — returnează starea curentă, din States
- STATUS — returnează statutul curent, acesta este un șir suplimentar la STATE
- GPSArray — returnează gps un șir sub formă de DevVarCharArray
Apoi se definesc atributele dispozitivului care pot fi citite/scrise în/de la acesta.
Atribute scalare — atribute simple (char, string, long etc.)
Atribute spectru — array-uri unidimensionale
Atribute imagine — array-uri bidimensionale
States — stările în care se află dispozitivul nostru.
- OPEN — dispozitivul este deschis.
- CLOSE — dispozitivul este închis.
- FAILT — eroare.
- DA — primim date de la dispozitiv.
- OFF — nu sunt date de la dispozitiv.
Exemplu de adăugare a unui atribut gps_string:

Perioada de poll timp în ms, cât de des va fi actualizată valoarea gps_string. Dacă nu se specifică timpul de actualizare, atributul va fi actualizat doar la cerere.
S-a realizat:

Acum trebuie să generăm codul File->Generate

În mod implicit, Makefile nu este generat, prima dată trebuie să bifezi căsuța pentru a-l crea. Acest lucru s-a făcut pentru a preveni pierderea modificărilor aduse la o nouă generație. Creându-l o dată și configurându-l pentru proiectul tău (scriind cheile de compilare, fișierele suplimentare) poți să uiți de el.
Acum trecem la programare. pogo ne-a generat următoarele:

Ne vor interesa NEO6M.cpp & NEO6M.h. Să examinăm, de exemplu, constructorul clasei:
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
}Ce avem aici și ce este important? În funcția init_device() are loc alocarea memoriei pentru atributele noastre: gps_string & gps_array, dar asta nu este important. Cel mai important aici, sunt comentariile:
/*----- PROTECTED REGION ID(NEO6M::constructor_1) ENABLED START -----*/
.......
/*----- PROTECTED REGION END -----*/ // NEO6M::constructor_1Tot ce se află în acest bloc de comentarii nu va fi șters la următoarele re-generații de cod în pogo!. Tot ce nu este în blocuri va fi! Acestea sunt locurile unde putem programa și aduce modificări.
Acum, ce funcții principale conține clasa 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);Când vom dori să citim valoarea atributului gps_string, vor fi apelate funcțiile în următoarea ordine: always_executed_hook, read_attr_hardware și read_gps_string. În read_gps_string se va umple gps_string cu valoarea.
void NEO6M::read_gps_string(Tango::Attribute &attr)
{
DEBUG_STREAM << "NEO6M::read_gps_string(Tango::Attribute &attr) entering... " <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
}Compilare
Intrăm în folderul cu sursele și:
makeProgramul se va compila în folderul ~/DeviceServers.
tango-cs@tangobox:~/DeviceServers$ ls
NEO6MJIVE
jive
În BD există deja unele dispozitive, acum să creăm al nostru Edit->Create Server

Acum vom încerca să ne conectăm la el:

Nu va ieși nimic, mai întâi trebuie să pornim programul nostru:
sudo ./NEO6M neo6m -v2Mă pot conecta la portul com doar cu permisiuni root-a. v — nivelul de logare.
Acum putem să ne conectăm:

Clientului
Este bine să ne uităm la imagini în grafic, dar avem nevoie de ceva mai util. Vom scrie un client care se va conecta la dispozitivul nostru și va colecta datele.
#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);
}
}Cum să compilezi:
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++Rezultatul:
tango-cs@tangobox:~/workspace/c$ ./a.out
$GPRMC,,V,,,,,,,,,,N*53
$GPRMC,,V,,,,,,,,,,N*53
$GPRMC,,V,,,,,,,,,,N*53Am obținut rezultatul ca un răspuns la comanda de preluare a atributelor dintr-un șir și un tablou de caractere.
Linkuri
Am scris articolul pentru mine, pentru că după un timp încep să uit cum și ce să fac.
Vă mulțumesc pentru atenție.
Sursa: habr.com
