# Budowanie skryptów

Programy KDE mogą być kontrolowane przez inny program przy użyciu protokołu Desktop COmmunication Protocol (DCOP). Taka kontrola jest ma miejsce z wiersza poleceń, bądź przez skrypt. KStars korzysta z tych możliwości, co pozwala na budowanie skomplikowanych skryptów i uruchamianie ich w dowolnym czasie. W ten sposób można na przykład przygotować materiał szkoleniowy na lekcję ilustrujący pewne zagadnienie z dziedziny astronomii.

Pisanie skryptów DCOP jest podobne do programowania, więc może wydawać się zadaniem trudnym dla tych, którzy nigdy tego nie próbowali. Narzędzie budowy skryptów dostarcza interfejsu GUI do budowy skryptów DCOP, co znacznie ułatwia tworzenie rozbudowanych skryptów.

## Wprowadzenie do budowania skryptów

Przed wyjaśnieniem jak działa narzędzie budowy skryptów, krótko opiszemy podstawowe komponenty interfejsu GUI; więcej informacji można uzyskać wykorzystując funkcję "Co to jest?".

Narzędzie Budowanie skryptów
Narzędzie Budowanie skryptów

Powyżej pokazany jest wygląd narzędzia budowy skryptów. Po lewej stronie znajduje się okno Bieżący skrypt; zawiera ono listę poleceń składających się na obecnie tworzony skrypt. Po prawej stronie znajduje Przeglądarka funkcji; wyświetlająca listę wszystkich dostępnych w skryptach funkcji. Poniżej Przeglądarki funkcji znajduje się niewielki panel, wyświetlający krótką dokumentację wybranej funkcji. Panel pod oknem obecnie tworzonego skryptu to panel Argumenty funkcji; zawierający wymagane przez wybraną powyżej funkcję argumenty.

U góry okna znajduje się rząd przycisków, które mają zastosowanie przy skryptach. Od lewej są to: Nowy skrypt, Otwórz skrypt, Zapisz skrypt, Zapisz skrypt jako..., i Wypróbuj skrypt. Działanie tych przycisków powinno być oczywiste, może poza ostatnim. Wciśnięcie Wypróbuj skrypt spowoduje próbę uruchomienia bieżącego skryptu w głównym oknie KStars. Przed jego wciśnięciem powinno przesunąć się okno z treścią skryptu tak, aby było widać wyniki.

Na środku okna znajduje się kolumna przycisków, które mają zastosowanie do poszczególnych funkcji skryptu. Od góry do dołu są to: Dodaj funkcję, Usuń funkcję, Kopiuj funkcję, W górę i W dół. Dodaj funkcję dodaje obecnie zaznaczoną funkcję z przeglądarki funkcji do skryptu (to samo można osiągnąć przez podwójne kliknięcie nazwy funkcji). Pozostałe przyciski działają na funkcji zaznaczonej w polu skryptu. Powodują jej usunięcie, powielenie lub zmianę pozycji w skrypcie.

## Korzystanie z narzędzia budowania skryptów

Aby przedstawić korzystanie z narzędzia budowania skryptów pokażemy przykład, w którym tworzymy skrypt śledzący Księżyc, podczas gdy zegar działa w trybie przyspieszonym.

Jeżeli chcemy śledzić Księżyc musimy najpierw wyśrodkować go na ekranie. Wykorzystamy do tego funkcję lookToward. Zaznacz tą funkcję w przeglądarce funkcji i sprawdź jej dokumentację wyświetloną w panelu poniżej przeglądarki. Wciśnij przycisk Dodaj funkcję, aby dodać funkcję do pola bieżącego skryptu. Panel argumentów funkcji będzie zawierał listę rozwijaną o nazwie Kierunek. Wybiera się tam Jest to kierunek, w którym ma być skierowany ekran. List rozwijana zawiera tylko główne kierunki geograficzne, bez Księżyca czy innych obiektów. Możesz wprowadzić "Księżyc" ręcznie albo wcisnąć przycisk Obiekt aby skorzystać z okna Znajdź obiekt do znalezienia Księżyca z listy nazwanych obiektów. Pamiętaj, że jak zwykle wyśrodkowanie na obiekcie spowoduje włączenie trybu śledzenia. Nie ma więc potrzeby aby dodawać funkcję setTracking po funkcji lookToward.

Teraz, gdy wskazaliśmy Księżyc, chcemy spowodować aby czas płynął z przyśpieszoną prędkością. Wykorzystaj do tego funkcję setClockScale. Dodaj ją do skryptu poprzez podwójne kliknięcie w przeglądarce funkcji. Panel argumentów tej funkcji zawiera pole umożliwiające ustawienie kroku czasu dla zegara symulacji. Zmień wartość na 3 godziny.

Teraz chcemy tylko, aby skrypt zaczekał przez kilka sekund, żeby program wyśrodkował ekran na Księżycu. Dodaj do skryptu funkcję waitFor i skorzystaj z panelu argumentów funkcji aby ustawić wartość oczekiwania na 20 sekund.

Teraz zresetuj krok czasowy zegara na wartość domyślną 1 sekundy. Dodaj kolejne wywołanie funkcji setClockScale i ustaw jej wartość na 1.

Powinniśmy się jeszcze upewnić, że wykorzystywane są współrzędne równikowe, zanim skrypt będzie śledził Księżyc z przyśpieszonym krokiem czasu. Jeżeli będą wykorzystywane współrzędne horyzontalne nastąpi bardzo szybki obrót o duże kątywraz ze wschodem i zachodem Księżyca. Może być to bardzo irytujące, ale można temu zapobiec ustawiając opcję widokuUseAltAz na false. Aby zmienić dowolną opcję widoku wykorzystaj funkcję changeViewOption. Dodaj tą funkcję do skryptu. W panelu argumentów funkcji znajduje się lista rozwijana, która zawiera wszystkie opcje, które mogą być dostosowane za jej pomocą. Z listy tej należy wybrać opcję UseAltAz, możemy także wcisnąć przycisk Przeglądaj drzewo, który zawiera drzewo wszystkich dostępnych opcji, zorganizowane tematycznie. Dodatkowo każda pozycja zawiera krótki opis mówiący o tym, co dana funkcja robi i jakiego typu danych potrzebuje. UseAltAz można znaleźć w kategorii Opcje mapy nieba. Po wybraniu funkcja znajdzie się w odpowiednim polu okna narzędzia budowania skryptów. Zmień jeszcze jej wartość na false lub 0.

Jeszcze jeden krok: zmiana UseAltAz na samym końcu skryptu nic nie pomoże, potrzebna jest na samym początku. Zaznacz ją więc w polu skryptu i wciskaj przycisk W górę tak długo, aż UseAltAz będzie pierwszą funkcją skryptu.

Teraz, po skończeniu skryptu, należy zapisać go na dysku. Wciśnij przyciskZapisz skrypt. Spowoduje to otwarcie okna w którym należy wprowadzić nazwę skryptu, a także dane jego autora. Jako nazwę wprowadź Śledzenie Księżyca, natomiast w polu autora wpisz swoje imię i naciśnij OK. Teraz zobaczysz standardowe okno zapisu pliku w &kde;. Określ nazwę pliku dla skryptu i wciśnij OK, aby zapisać skrypt. Pamiętaj, że jeżeli nazwa pliku nie będzie kończyć się na .kstars, to ten przyrostek zostanie dodany automatycznie. Jeżeli ciekawi Cię wygląd takiego pliku, możesz go obejrzeć w dowolnym edytorze tekstu.

Skrypt możemy uruchomić na kilka sposobów. Jeżeli działa KStars możemy to zrobić z wiersza poleceń. Inna metoda to uruchomienie skryptu przez KStars po wybraniu opcji Uruchom skrypt z menu Plik.

## Automatyczne obsługiwanie urządzeń przy pomocy INDI

Automatyczna obsługa urządzeń jest zapewniona dla wszystkich urządzeń kompatybilnych z INDI. Możesz używać dowolnej ich liczby dzięki narzędziu Budowanie skryptów w &kstars;. Służy do tego interfejs INDI DCOP &kstars;, który udostępnia różne klasy funkcji do wykorzystania do Twoich potrzeb. Funkcje INDI DCOP można podzielić na pięć klas. Dalej znajduje się opis funkcji dostępnych w &kstars; i ich argumentów. Polecamy przeczytanie sekcji dotyczącej zasady działania INDI, jako że w dalszej części podręcznika wykorzystamy kilka szczególnych cech INDI.

1. Ogólne funkcje urządzeń: funkcje do włączania/wyłączania urządzeń itp.

   - `startINDI (QString deviceName, bool useLocal)` : Włącza usługę INDI lokalnie lub na serwerze.

   - `shutdownINDI (QString deviceName)` : Zamyka usługę INDI.

   - `switchINDI(QString deviceName, bool turnOn)` : Podłącza bądź rozłącza urządzenie INDI.

   - `setINDIPort(QString deviceName, QString port)` : Ustawia port komunikacyjny urządzenia.

   - `setINDIAction(QString deviceName, QString action)` : Aktywuje akcję INDI. Akcja może być dowolnym elementem z własności przełączania

   - `waitForINDIAction(QString deviceName, QString action)` : Wstrzymuje wykonanie skryptu aż określona własność zwróci status OK.

2. Funkcje teleskopu: Funkcje kontrolujące ruch i stan teleskopu

   - `setINDIScopeAction(QString deviceName, QString action)` : Ustawia tryb teleskopu lub działanie. Dostępne opcje to SLEW, TRACK, SYNC, PARK i ABORT.

   - `setINDITargetCoord(QString deviceName, double RA, double DEC)` : Ustawia cel JNow teleskopu na współrzędne RA i DEC.

   - `setINDITargetName(QString deviceName, QString objectName)` : Ustawia cel teleskopu JNow na współrzędne wybranego obiektu (objectName. KStars wyszuka nazwę obiektu w bazie danych i pobierze ich RA i Dec.

   - `setINDIGeoLocation(QString deviceName, double longitude, double latitude)` : Ustawia lokalizację teleskopu na określoną długość i szerokość geograficzną. Długość geograficzna jest liczona od Greenwich na wschód. Jednakże mimo tego, że zwykle korzysta się z odwróconych długości geograficznych dla zachodniej półkuli INDI wymaga wartości długości z przedziału od 0 do 360 stopni. Jeżeli więc Twoja długość geograficzna jest ujemna, po prostu dodaj do niej 360 stopni. Na przykład Calgary w Kanadzie ma długość geograficzną: -114 04 58 i szerokość geograficzną: 51 02 58. Tak więc w INDI' te długość geograficzna będzie wynosić 360 - 114.083 = 245.917 stopni.

   - `setINDIUTC(QString ddeviceName, QString UTCDateTime)` : Ustawia datę i czas UTC teleskopu w formacie ISO 8601. Format ten wygląda następująco: YYYY-MM-DDTHH:MM:SS (np. 2004-07-12T22:05:32).

3. Funkcje kamer/CCD: Funkcje kontrolujące właściwości i stan kamer/CCD.

   - `setINDICCDTemp(QString deviceName, int temp)` : Ustawia docelową temperaturę barw matrycy CCD w stopniach Celsjusza.

   - `setINDIFrameType(QString nazwaUrządenia, QString rodzaj)` : Ustawia rodzaj ramki CCD. Dostępne opcje to FRAME_LIGHT, FRAME_BIAS, FRAME_DARK i FRAME_FLAT.

   - `startINDIExposure(QString deviceName, int timeout)` : Rozpoczyna ekspozycję, na czas określony przez timeout, w sekundach.

4. Funkcje focusera: funkcje do kontroli ruchu i stanu focusera.

   - `setINDIFocusSpeed(QString deviceName, QString action)` : Ustawia prędkość focusera. Dostępne opcje to: FOCUS_HALT, FOCUS_SLOW, FOCUS_MEDIUM i FOCUS_FAST.

   - `setINDIFocusTimeout(QString deviceName, int timeout)` : Ustawia czas trwania składowych operacji startINDIFocus w sekundach.

   - `startINDIFocus(QString deviceName, int focusDir)` : Przesuwa focuser do wewnątrz (focusDir = 0) albo na zewnątrz (focusDir = 1). Prędkość i czas tej operacji są ustawiane przez funkcje `setINDIFocusSpeed()`i `setINDIFocusTimeout()`.

5. Funkcje filtra: Funkcje kontrolujące pozycję filtra.

   - `setINDIFilterNum(QString deviceName, int filter_num)` : Zmiana pozycji filtra na `filter_num`. Użytkownik może przypisać aliasy do numeru filtra w oknie Konfiguracja INDI z menu Urządzenia (np. Filtr 1 = czerwony, Filtr 2 = zielony itd).

Pamiętaj, że nazwa urządzenia jest pierwszym argumentem dla wszystkich funkcji INDI. Pozwala na umieszczenie w jednym skrypcie różnych poleceń, które są wysyłane do wielu urządzeń INDI. Narzędzie budowania skryptów zawiera dwie opcje ułatwiające tworzenie i modyfikację skryptów INDI.

- `Po każdej akcji INDI dołącz WaitForINDIAction` : Gdy zaznaczona, narzędzie budowania skryptów automatycznie doda `waitForINDIAction()` po każdym rozpoznanym działaniu. Dla przykładu, jeśli dodasz do skryptu funkcję `switchINDI()` ,a opcja ta jest zaznaczona, to narzędzie budowania skryptów doda "waitForINDIAction CONNECTION" do pliku skryptu, zaraz po `switchINDI()`. Spowoduje to wstrzymanie skryptu po wydaniu polecenia `switchINDI()` aż do momentu gdy `switchINDI()` zwróci status OK (np. podłączanie urządzenia zakończy się powodzeniem). Jest niezwykle istotne by pamiętać, że narzędzie budowania skryptów nie może automatycznie dodać `waitForINDIAction()` dla ogólnych działań dodanych za pomocą funkcji `setINDIAction()`. Dzieje się tak, ponieważ KStars nie może określić właściwości nadrzędnych funkcji ogólnych. Dlatego musisz dodać ręcznie `waitForINDIAction()` po wybranych działaniach ogólnych.

- `Ponownie użyj nazwy urządzenia INDI` : Gdy zaznaczono, to pole nazwy urządzenia wszystkich podrzędnych funkcji jest automatycznie wypełniane nazwą ostatniegourządzenia. Nazwa ta jest ustawiana po każdym dodaniu`startINDI()` do bieżącego skryptu. Przy pracy z wieloma urządzeniami zaleca się wyłączenie tej funkcji.

Nadszedł czas na stworzenie skryptu demo sterującego teleskopem LX200 GPS oraz kamerą Finger Lakes CCD. Zadanie jest proste. Każemy teleskopowi obrócić się i śledzić Marsa, następnie każemy aparatowi zrobić 3 ujęcia 10 sekundowe co 20 sekund.

Ponieważ nie ma bezpośredniej odpowiedzi z interfejsu INDI DCOP dotyczącej postępu wartości czy stanu działań urządzenia i jego parametrów, za wyjątkiem `waitForINDIAction()`, automatyczna obsługa urządzeń jest podobna do systemu sterowania z otwartą pętlą. W takim systemie zwykle nie ma bezpośredniej odpowiedzi pozwalającej zmierzyć postęp i poprawić błędy. W związku z tym skrypty trzeba pisać po dokładnym rozważeniu ich działania. Wszysztkie tego typu skrypty wymagają dokładnego testowania przed wdrożeniem.

Narzędzie Budowanie skryptów
Narzędzie Budowanie skryptów

Powyżej zaprezentowany jest skrypt demo. Pamiętaj, że zaznaczyliśmy opcję `"Po każdej akcji INDI dołącz WaitForINDIAction"` i odznaczyliśmy opcję `"Ponownie użyj nazwy urządzenia INDI"`. Ponieważ chcemy uruchomić nasze urządzenie lokalnie, nie zmieniamy trybu usługi podanego w oknie argumentów funkcji. Wpisujemy nazwę naszego urządzenia rozpoczynając od teleskopu "LX200 GPS". Tą samą operację powtarzamy dla "FLI CCD". Potem następuje `waitFor()`. Zaleca się korzystanie z funkcji `waitFor()` zaraz po `startINDI()`, aby wstrzymać skrypt do 1-5 sekund. To pozwoli zapewnić, że wszystkie właściwości są jużpoprawnie ustawione i gotowe na przyjmowanie poleceń. Jest to także użyteczne przy kontroli zdalnych urządzeń, ponieważ pobieranie i budowanie właściwości może zabrać sporo czasu. W kolejnej funkcji, `switchINDI()`, podłączamy się do każdego urządzenia.

Opcja `"Po każdej akcji INDI dołącz WaitForINDIAction"` jest zaznaczona, więc nie trzeba dodawać `waitForINDIAction()` po `switchINDI()`, żeby mieć pewność, że będziemy kontynuować tylko w przypadku poprawnego połączenia. Dzieje się tak, gdyż narzędzie Budowanie skryptów zrobi to za nas, automatycznie, przy zapisywaniu skryptu. Teraz przestawmy teleskop w tryb śledzenia. Kliknij funkcję `setINDIScopeAction()` i wybierz TRACK. Warto zauważyć, że trzeba przestawić teleskop w tryb śledzenia przed podaniem współrzędnych. Dla ułatwienia istnieje funkcja `setINDIScopeAction()`. W tym przykładzie wykonuje ona po prostu `setINDIAction()` z dalej następującym słowem kluczowym TRACK. Jednakże zyskiem z wykorzystania `setINDIScopeAction()` jest to, że KStars może automatycznie dodać po niej`waitForINDIAction()`, kiedy tylko jest taka potrzeba. Ta właściwość nie jest automatycznie dostępna dla ogólnych akcji omawianych wcześniej.

Następnie korzysamy z funkcji `setINDITargetName()` i ustawiamy ją na Marsa. Ostatnie kilka kroków polega na przechwytywaniu obrazu przez 10 sekund, co można zrobić za pomocą funkcji `startINDIExposure()`, i odczekaniu 20 sekund, co można zrobić za pomocą funkcji `waitFor()` z wartością 20.

Możemy teraz zapisać skrypt i wykonać go w dowolnym momencie. Powinien on wyglądać podobnie do tego:

>     #!/bin/bash
>         #KStars DCOP script: Demo Script
>         #by Jasem Mutlaq
>         #last modified: Thu Jan 6 2005 09:58:26
>         #
>         KSTARS=`dcopfind -a 'kstars*'`
>         MAIN=KStarsInterface
>         CLOCK=clock#1
>         dcop $KSTARS $MAIN  startINDI "LX200 GPS" true
>         dcop $KSTARS $MAIN  startINDI "FLI CCD" true
>         dcop $KSTARS $MAIN  waitFor 3
>         dcop $KSTARS $MAIN  switchINDI "LX200 GPS" true
>         dcop $KSTARS $MAIN  waitForINDIAction "LX200 GPS" CONNECTION
>         dcop $KSTARS $MAIN  switchINDI "FLI CCD" true
>         dcop $KSTARS $MAIN  waitForINDIAction "FLI CCD" CONNECTION
>         dcop $KSTARS $MAIN  setINDIScopeAction "LX200 GPS" TRACK
>         dcop $KSTARS $MAIN  waitForINDIAction "LX200 GPS" ON_COORD_SET
>         dcop $KSTARS $MAIN  setINDITargetName "LX200 GPS" Mars
>         dcop $KSTARS $MAIN  waitForINDIAction "LX200 GPS" EQUATORIAL_EOD_COORD
>         dcop $KSTARS $MAIN  startINDIExposure "FLI CCD" 10
>         dcop $KSTARS $MAIN  waitForINDIAction "FLI CCD" EXPOSE_DURATION
>         dcop $KSTARS $MAIN  waitFor 20
>         dcop $KSTARS $MAIN  startINDIExposure "FLI CCD" 10
>         dcop $KSTARS $MAIN  waitForINDIAction "FLI CCD" EXPOSE_DURATION
>         dcop $KSTARS $MAIN  waitFor 20
>         dcop $KSTARS $MAIN  startINDIExposure "FLI CCD" 10
>         dcop $KSTARS $MAIN  waitForINDIAction "FLI CCD" EXPOSE_DURATION

Biblioteka INDI zawiera funkcjonalne narzędzia, które umożliwiają programistom tworzenie bardziej skomplikowanych skryptów. Więcej informacji znajdziesz w podręczniku dla programistów INDI Developer Manual.