
Cosa sono ?
Questo è un sistema per la gestione di vari equipaggiamenti e software.
TANGO attualmente supporta 4 piattaforme: Linux, Windows NT, Solaris e HP-UX.
Qui sarà descritta l'operazione con Linux (Ubuntu 18.04)
A cosa serve?
Semplifica il lavoro con diversi dispositivi e software.
- Non devi preoccuparti di come memorizzare i dati nel database, è già stato fatto per te.
- Devi solo descrivere il meccanismo di interrogazione dei sensori.
- Riduce tutto il tuo codice a uno standard unico.
Dove trovarlo?
Non sono riuscito a farla partire dai sorgenti, per lavorare ho utilizzato l'immagine pronta di TangoBox 9.3.
Nelle istruzioni è descritto come installarlo dai pacchetti.
Di cosa è composto?
- JIVE – serve per visualizzare e modificare il database TANGO.
- POGO – generatore di codice per i server delle apparecchiature TANGO.
- Astor – gestore software per il sistema TANGO.
Ci interesseranno solo i primi due componenti.
Linguaggi di programmazione supportati
- C
- C++
- Java
- JavaScript
- Python
- Matlab
- LabVIEW
Ho lavorato con esso in python & c++. Qui come esempio useremo c++.
Ora passiamo alla descrizione di come collegare un dispositivo a TANGO e come lavorarci. Prenderemo come esempio la scheda GPS neo-6m-0-001:

Come si vede nell'immagine, colleghiamo la scheda al PC tramite UART CP2102. Quando ci connettiamo al PC appare il dispositivo /dev/ttyUSB[0-N], di solito /dev/ttyUSB0.
POGO
Ora avviamo pogo, e generiamo lo scheletro del codice per lavorare con la nostra scheda.
pogo
Avevo già creato il codice, creiamolo di nuovo File->Nuovo.

Otteniamo quanto segue:

Il nostro dispositivo (con dispositivo in seguito ci si riferirà alla parte software) è vuoto e ha due comandi di controllo: Stato & Stato.
Deve essere riempito con gli attributi necessari:
Proprietà Dispositivo – valori di default che passiamo al dispositivo per la sua inizializzazione, per la scheda GPS dobbiamo passare il nome della scheda nel sistema com="/dev/ttyUSB0" e la velocità della porta com baudrate=9600
Comandi – comandi di controllo per il nostro dispositivo, a cui possono essere assegnati argomenti e valori restituiti.
- STATO – restituisce lo stato attuale, da Stati
- STATUS – restituisce lo stato attuale, è un'aggiunta stringa a STATO
- GPSArray – restituisce gps una stringa in formato DevVarCharArray
Poi vengono definiti gli attributi del dispositivo che possono essere letti/scritti in/da esso.
Attributi Scalar – attributi semplici (char, string, long, ecc.)
Attributi Spettro – array unidimensionali
Attributi Immagine – array bidimensionali
Stati – stati in cui si trova il nostro dispositivo.
- APERTO – dispositivo aperto.
- CHIUSO — dispositivo chiuso.
- FAILT — errore.
- ACCESO — stiamo ricevendo dati dal dispositivo.
- OFF — nessun dato dal dispositivo.
Esempio di aggiunta di attributo gps_string:

Periodo di polling tempo in ms, con quale frequenza verrà aggiornato il valore gps_string. Se il tempo di aggiornamento non viene specificato, l'attributo verrà aggiornato solo su richiesta.
Risultato:

Ora è necessario generare il codice File->Genera

Per impostazione predefinita, il Makefile non viene generato, la prima volta è necessario selezionare l'opzione per crearlo. Questo è stato fatto affinché le modifiche apportate non vengano eliminate durante una nuova generazione. Creandolo una sola volta e configurandolo per il proprio progetto (specificare le chiavi di compilazione, file aggiuntivi) si può poi dimenticare di esso.
Ora passiamo direttamente alla programmazione. pogo ci ha generato quanto segue:

Ci interesseranno NEO6M.cpp & NEO6M.h. Consideriamo per esempio il costruttore della classe:
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
}Cosa c'è qui e qual è l'aspetto principale? Nella funzione init_device() avviene l'allocazione di memoria per i nostri attributi: gps_string & gps_array, ma questo non è importante. La cosa più importante qui, sono i commenti:
/*----- PROTECTED REGION ID(NEO6M::constructor_1) ENABLED START -----*/
.......
/*----- PROTECTED REGION END -----*/ // NEO6M::constructor_1Tutto ciò che si trova all'interno di questo blocco di commento non verrà eliminato durante le successive rigenerazioni del codice in pogo!. Tutto ciò che non è in blocchi sarà! Questi sono i punti dove possiamo programmare e apportare le nostre modifiche.
Ora, quali sono le principali funzioni contenute nella classe 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);Quando vorremo leggere il valore dell'attributo gps_string, verranno chiamate le funzioni nell'ordine seguente: always_executed_hook, read_attr_hardware e read_gps_string. In read_gps_string avverrà il riempimento di gps_string con il valore.
void NEO6M::read_gps_string(Tango::Attribute &attr)
{
DEBUG_STREAM << "NEO6M::read_gps_string(Tango::Attribute &attr) ingresso... " <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
}Compilazione
Entriamo nella cartella con i sorgenti e:
makeIl programma verrà compilato nella cartella ~/DeviceServers.
tango-cs@tangobox:~/DeviceServers$ ls
NEO6MJIVE
jive
Ci sono già dei dispositivi nel DB, ora creiamo il nostro Modifica->Crea Server

Ora proviamo a collegarci ad esso:

Non succederà nulla, prima dobbiamo avviare il nostro programma:
sudo ./NEO6M neo6m -v2Posso connettermi alla porta com solo con i diritti root-a. v — livello di registrazione.
Ora possiamo connetterci:

Cliente
Guardare le immagini nella grafica è certamente bello, ma è necessario qualcosa di più utile. Scriviamo un client che si connetterà al nostro dispositivo e ne preleverà le letture.
#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);
}
}Come compilare:
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++Risultato:
tango-cs@tangobox:~/workspace/c$ ./a.out
$GPRMC,,V,,,,,,,,,,N*53
$GPRMC,,V,,,,,,,,,,N*53
$GPRMC,,V,,,,,,,,,,N*53Abbiamo ottenuto un risultato come ritorno del comando, acquisizione degli attributi di una stringa e di un array di caratteri.
Link
Ho scritto l'articolo per me stesso, perché dopo un po' di tempo inizio a dimenticare come e cosa fare.
Grazie per l'attenzione.
Fonte: habr.com
