Tango Controls

Tango Controls

Czym jest TANGO?

To jest system do zarządzania różnym sprzętem i oprogramowaniem.
TANGO obsługuje obecnie 4 platformy: Linux, Windows NT, Solaris i HP-UX.
Tutaj opisane będzie korzystanie z Linuxa (Ubuntu 18.04)

Po co to potrzebne?

Ułatwia pracę z różnym sprzętem i oprogramowaniem.

  • Nie musisz się martwić o to, jak przechowywać dane w bazie danych, to już zostało zrobione za Ciebie.
  • Wystarczy opisać mechanizm odczytu czujników.
  • Zredukuje cały Twój kod do jednego standardu.

Gdzie to znaleźć?

Nie mogłem uruchomić go z kodu źródłowego, do pracy użyłem gotowego obrazu TangoBox 9.3.
W instrukcji opisano, jak go zainstalować z pakietów.

Z czego się składa?

  • JIVE — służy do przeglądania i edytowania bazy danych TANGO.
  • POGO — generator kodu dla serwerów urządzeń TANGO.
  • Astor — menedżer oprogramowania dla systemu TANGO.

Będziemy interesować się tylko pierwszymi dwoma składnikami.

Obsługiwane języki programowania

  • C
  • C++
  • Java
  • JavaScript
  • Python
  • Matlab
  • LabVIEW

Pracowałem z nim w Pythonie i C++. Tutaj jako przykład użyję C++.

Teraz przejdźmy do opisu, jak podłączyć urządzenie do TANGO i jak z nim pracować. Jako przykład weźmiemy płytkę GPS neo-6m-0-001:

Tango Controls

Jak widać na zdjęciu, płytkę podłączamy do PC przez UART CP2102. Po podłączeniu do PC pojawia się urządzenie /dev/ttyUSB[0-N], zwykle /dev/ttyUSB0.

POGO

Teraz uruchomimy. pogo, a następnie generujemy szkielet kodu do pracy z naszą płytką.

pogo

Tango Controls

Już miałem stworzony kod, stwórzmy go od nowa Plik->Nowy.

Tango Controls

Otrzymujemy następujące:

Tango Controls

Nasze urządzenie (przez urządzenie będziemy dalej rozumieć część programową) jest puste i ma dwie komendy sterujące: State & Status.

Należy je wypełnić niezbędnymi atrybutami:

Właściwość urządzenia — wartości domyślne, które przekazujemy do urządzenia w celu jego inicjalizacji, dla płytki GPS należy przekazać nazwę płytki w systemie com="/dev/ttyUSB0" i szybkość portu com baudrate=9600

Komendy — komendy do sterowania naszym urządzeniem, można im przypisać argumenty i wartości zwracane.

  • STAN — zwraca aktualny stan, z Stany
  • STATUS — zwraca bieżący status, to jest ciąg dodatkowy do STAN
  • GPSArray — zwraca gps ciąg w postaci DevVarCharArray

Następnie definiowane są atrybuty urządzenia, które można odczytywać/pisać do niego.
Atrybuty skalarne — proste atrybuty (char, string, long itp.)
Atrybuty spektralne — jednowymiarowe tablice
Atrybuty obrazu — dwuwymiarowe tablice

Stany — stany, w jakich znajduje się nasze urządzenie.

  • OTWÓRZ — urządzenie jest otwarte.
  • ZAMKNIJ — urządzenie jest zamknięte.
  • BŁĄD — wystąpił błąd.
  • WŁĄCZONE — odbieramy dane z urządzenia.
  • WYŁ. — brak danych z urządzenia.

Przykład dodawania atrybutu gps_string:

Tango Controls

Okres pobierania czas w ms, jak często będzie aktualizowana wartość gps_string. Jeśli czas aktualizacji nie jest ustawiony, atrybut będzie aktualizowany tylko na żądanie.

Udało się:

Tango Controls

Teraz należy wygenerować kod Plik->Generuj

Tango Controls

Domyślnie Makefile nie jest generowany, za pierwszym razem należy zaznaczyć, aby go stworzyć. Zrobiono to, aby wprowadzone do niego zmiany nie zostały usunięte podczas nowej generacji. Utworzywszy go raz i dostosowując do swojego projektu (wprowadzenie kluczy kompilacji, dodatkowych plików), można o nim zapomnieć.

Teraz przechodzimy bezpośrednio do programowania. pogo wygenerował nam następujące:

Tango Controls

Będą nas interesować pliki NEO6M.cpp i NEO6M.h. Przyjrzyjmy się jako przykład konstruktorowi klasy:

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
}

Co tu jest i co jest najważniejsze? W funkcji init_device() następuje przydzielenie pamięci dla naszych atrybutów: gps_string & gps_array, ale to nie jest ważne. Najważniejsze tutaj, to komentarze:

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

Wszystko, co znajduje się w tym bloku komentarza, podczas następnych regeneracji kodu w pogo nie zostanie usunięte!. Wszystko, co jest poza blokami, zostanie usunięte! To są miejsca, w których możemy programować i wprowadzać nasze zmiany.

Jakie główne funkcje zawiera klasa 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);

Kiedy będziemy chcieli odczytać wartość atrybutu gps_string, zostaną wywołane funkcje w następującej kolejności: always_executed_hook, read_attr_hardware i read_gps_string. W read_gps_string nastąpi uzupełnienie gps_string wartością.

void NEO6M::read_gps_string(Tango::Attribute &attr)
{
    DEBUG_STREAM << "NEO6M::read_gps_string(Tango::Attribute &attr) wchodzi... " <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
}

Kompilacja

Wchodzimy do folderu z kodem źródłowym i:

make

Program skompiluje się w folderze ~/DeviceServers.

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

JIVE

jive

Tango Controls

W bazie danych już są jakieś urządzenia, stwórzmy więc nasze Edytuj->Utwórz serwer

Tango Controls

Teraz spróbujemy się do niego podłączyć:

Tango Controls

Nic nie wyjdzie, najpierw trzeba uruchomić nasz program:

sudo ./NEO6M neo6m -v2

Do podłączenia się do portu com mogę potrzebować tylko uprawnień root-a. v — poziom logowania.

Teraz możemy się połączyć:

Tango Controls

Klient

Patrzenie na wykresy jest oczywiście dobre, ale potrzebujemy czegoś bardziej użytecznego. Napiszemy klienta, który połączy się z naszym urządzeniem i pobierze z niego dane.

#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);
    }
}

Jak kompilować:

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++

Wynik:

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

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

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

Otrzymaliśmy wynik w postaci zwrotu polecenia, pobierania atrybutów i tablicy znaków.

Linki

Artykuł pisałem dla siebie, ponieważ po pewnym czasie zaczynam zapominać, jak i co robić.

Dziękujemy za uwagę.

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster