# Værktøjet Scriptopbygning

KDE-programmer kan styres fra andre programmer, fra kommandolinjen eller fra et shell script vha. protokollen "Desktop COmmunication Protocol" (DCOP). KStars udnytter denne mulighed til at gøre det muligt at lave script der udfører meget komplekse operationer, så de kan udføres igen og igen. Dette kan fx bruges i undervisningsverdenen, til at forberede en demonstration af astronomiske koncepter og eksempler.

Problemet med DCOP script er at det minder meget om programmering når man skriver dem. Og derfor kan det virke uoverkommeligt at skulle lave dem i hånden hvis man ikke har erfaring med programmering. Værktøjet Scriptopbygning er en (GUI), en grafisk "peg og klik" brugerflade til at konstruere DCOP script. På den måde bliver det meget nemmere for fx lærere at lave avancerede script.

## Introduktion til Scriptopbygning

Før jeg forklarer hvordan Scriptopbyggeren bruges, vil jeg lave en kort introduktion af alle GUI-komponenterne. Brug funktionen "Hvad er dette?" for at få flere informationer.

Værktøjet Scriptopbygning
Værktøjet Scriptopbygning

Værktøjet Scriptopbygning er vist på skærmbilledet herover. Feltet til venstre er feltet Nuværende script, den viser listen over de kommandoer scriptet foreløbigt består af. Feltet til højre er Funktionsoversigten, den viser listen over de funktioner der kan bruges i scriptet. Under funktionsoversigten er der et lille panel der kan vise kort information om den scriptfunktion der er markeret i funktionsoversigten. Under feltet nuværende script findes panelet Funktionsargumenter. Når en funktion markeres i feltet med det nuværende script bliver der i panelet Funktionsargumenter mulighed for at indsætte værdier for de forskellige indstillingsmuligheder funktionen har.

Langs toppen af vinduet er der en række knapper som indvirker på scriptet som helhed. Fra venstre mod højre er det:Nyt script, Åbn script, Gem script, Gem scriptet som... og Test script. Funktionen af disse knapper giver sig selv, undtagen måske den sidste knap. Når man trykker på Test script bliver det nuværende script udført i KStars hovedvindue. Det er smart at flytte vinduet med scriptopbyggeren før du trykker på denne knap, ellers kan du jo ikke se resultatet.

I midten af vinduet er der en lodret række knapper, som styrer individuelle scriptfunktioner. Nedefra og op er det:Tilføj funktion, Fjern funktionen, Kopiér funktionen, Flyt op og Flyt ned. Tilføj funktion tilføjer den funktion der i øjeblikket er markeret i funktionsoversigten til scriptet (du kan også tilføje en funktion ved at dobbeltklikke på den). Resten af knapperne virker på den funktion der er markeret i feltet Nuværende script, ved enten at sletter funktionen, kopiere den eller ændre dens placering i scriptet.

## Brug af scriptopbyggeren

For at illustrere hvordan scriptopbyggeren virker, vil vi gennemgå et lille eksempel, hvor vi laver et script der månen mens uret går meget hurtigt.

Hvis vi vil følge Månen er vi nødt til at indstille stjernekortet så det peger på den først. Funktionen lookToward bruges til at gøre dette. Markér denne funktion i funktionsoversigten, og se på dokumentationen der kommer frem under oversigten. Tryk på knappen Tilføj funktion for at tilføje denne funktion til scriptfeltet. Panelet funktionsargumenter vil nu indeholde en kombofelt Ret:, forkortelse for retning. Det er den retning stjernekortet skal ses i. Kombinationsfeltet indeholder fra starten hovedkompasretningerne ikke Månen eller andre objekter. Men du kan enten skrive Moon manuelt i feltet, eller trykke på knappen Objekt for at bruge vinduet Find objekt til at vælge Månen fra listen over kendte objekter. Læg mærke at centrering på et objekt også slår følgning af objektet til, så der er ingen grund til at tilføje setTracking-funktionen efter lookToward.

Nu da vi har fået stillet ind på Månen, skal vi have tiden til at gå hurtigere. Brug funktionen setClockScale til dette. Tilføj den til scriptet ved at dobbeltklikke på den i funktionsoversigten. Funktionsargumentpanelet indeholder en rullefelt til at indstille tidsintervallerne for uret i simuleringen. Ret tidsintervallerne til 3 timer.

O.k. vi har stillet ind på Månen og speedet uret op. Nu skal vi så have scriptet til at vente nogle sekunder så stjernekortet har tid til at stille ind på månen. Tilføj funktionen waitFor til scriptet, og brug funktionsargumentpanelet til at angive at det skal vente i 20 sekunder før det går videre.

For at afslutte stiller vi tiden til at gå normalt igen. Indsæt en ny forekomst af setClockScale og sæt dens værdi til 1 sek.

Faktisk er vi ikke helt færdige endnu. Vi skal tvinge stjernekortet til at benytte koordinater fra ækvatorsystemet før scriptet låser sig fast på Månen og sætter farten på uret op. Hvis stjernekortet bruger koordinatsystemet horisontsystemet vil det rotere meget hurtigt over store vinkler mens Månen står op og går ned. Dette kan være meget forvirrende, og kan undgås ved at sætte indstillingen UseAltAz til false.' For at ændre indstillinger af stjernekortet bruges funktionen changeViewOption. Tilføj denne funktion til scriptet og se nærmere på funktionsargumentpanelet. Der er et kombinationsfelt med alle de indstillinger der kan ændres med changeViewOption. Da vi ved at vi vil ændre indstillingen UseAltAz kan vi bare markere den i kombinationsfeltet. Men listen er ret lang, og der er ingen beskrivelse af hvad hver indstillingsmulighed er til. Så det er måske lettere at trykke på Gennemse træstrukturen som vil åbne et vindue der indeholder en trævisning af de tilgængelige muligheder organiseret efter emne. Tilmed har hver indstillingsmulighed tilknyttet en kort beskrivelse af hvad den gør, og en beskrivelse af datatypen af dens værdier. Vi finder UseAltAz under kategorien Stjernekortsindstillinger. Markér bare dette punkt og tryk på O.k., og den vil blive valgt i kombinationsfeltet i funktionsargumentpanelet. Til sidst mangler vi så bare at sætte dens værdi til false eller 0.

Et skridt mere: ændringen UseAltAz indsat sidst i scriptet gør ingen nytte. Vi har brug for at ændre det før noget andet sker. Så marker funktionen i feltet Nuværende script, og tryk på Flyt op indtil det er den første funktion.

Nu da vi er færdige med scriptet skal det gemmes på disken. Tryk på Gem script. Dette åbner en dialog hvor du først kan give scriptet et navn og skrive din navn som forfatter. Skriv På sporet af Månen som scriptets navn og dit eget navn som forfatter, og tryk på O.k.. Derefter vil du se &kde;s standardgemmedialog. Skriv et filnavn og tryk på O.k. for at gemme scriptet. Vær opmærksom på at hvis filnavnet ikke ender på .kstars, vil dette filefternavn automatisk blive tilføjet. Hvis du er nysgerrig kan du altid læse scriptfilen i enhver teksteditor.

Nu da vi er færdige med scriptet kan vi starte det på forskellige måder. Fra kommandolinjen kan du simpelthen køre scriptet, når bare du husker at åbne KStars først. Alternativt kan du starte scriptet inde fra KStars ved at bruge menupunktet Kør script i Fil-menuen.

## Enhedsautomatisering med INDI

Enhedsskemalægning og automatisering understøttes for alle enheder som følger INDI. Du kan koordinere så mange enheder som helst til at udføre komplekse handlinger med &kstars; scriptbygger. Dette kan opnås ved at bruge &kstars; INDI DCOP-grænseflade. INDI DCOP-funktionerne kan deles op i fyre forskellige klasser. Det følgende er en gennemgang af funktionerne som understøttes i Kstars og deres argumenter. Det anbefales at du læser afsnittet INDI-begreber eftersom vi udnytter nøglebegreber fra INDI i hele denne vejledning.

1. Generiske enhedsfunktioner: Funktioner til at oprette eller lukke af for enheder, osv.

   - `startINDI (QString deviceName, bool useLocal)`: Opret en INDI-enhed enten i lokaltilstand eller i servertilstand.

   - `shutdownINDI (QString deviceName)`: Luk af for en INDI-enhed.

   - `switchINDI(QString deviceName, bool turnOn)`: Forbind op eller afbryd en INDI-enhed.

   - `setINDIPort(QString deviceName, QString port)`: Indstil INDI-enhedens forbindelsesport.

   - `setINDIAction(QString deviceName, QString action)`: Aktivér en INDI-handling. Handlingen kan være et hvilket som helst element i en skifteegenskab.

   - `waitForINDIAction(QString deviceName, QString action)`: Hold pause i kørsel af scriptet til angiven handlingsegenskab returnerer med status O.k.

2. Teleskopfunktioner: Funktioner til at styre teleskopbevægelser og status.

   - `setINDIScopeAction(QString deviceName, QString action)`: Indstil teleskopets tilstand eller handling. Tilgængelige tilvalg er SLEW, TRACK, SYNC, PARK og ABORT.

   - `setINDITargetCoord(QString deviceName, double RA, double DEC)`: Indstil teleskopets JNow-målkoordinater til RA og DEC.

   - `setINDITargetName(QString deviceName, QString objectName)`: Indstil teleskopets JNow-målkoordinater til koordinaterne for objectName. Kstars slår objektnavnet op i sin database og henter RA og DEC når de er fundet.

   - `setINDIGeoLocation(QString deviceName, double longitude, double latitude)`: Indstil teleskopets geografiske sted til længdegrad og breddegrad som angivet. Længdegradden beregnes som Ø for N. For eksempel har Calgary i Canada følgende koordinater i Kstars: Længdegrad -114 04 58 og breddegrad 51 02 58. Kun negative længdegrader behøver at blive konverteret. For at konvertere længdegradden til notationen Ø om N, antager vi at længdegradden er positiv og adderer 180 grader til den. I vort eksempel er altså længdegraddem i INDI lig med 114 04 08 + 180 00 00, dvs. 294 04 08 Ø for N.

   - `setINDIUTC(QString ddeviceName, QString UTCDateTime)`: Indstil teleskopets UTC-tid i ISO 8601-format. Formatet er ÅÅÅÅ/MM/DDTTT:MM:SS.(f.eks. 2004-07-12T22:05:32).

3. Fokuseringsfunktioner: Funktioner til at styre fokuseringsenhedens bevægelse og status.

   - `setINDIFocusSpeed(QString deviceName, QString action)`: Angiv fokuseringsenhedens hastighed. Tilgængelige tilvalg er FOCUS_HALT, FOCUS_SLOW, FOCUS_MEDIUM og FOCUS_FAST.

   - `setINDIFocusTimeout(QString deviceName, int timeout)`: Indstil tidsgrænsen i sekunder for alle følgende startINDIFocus-handlinger.

   - `startINDIFocus(QString deviceName, int focusDir)`: Flyt enten fokuseringsenheden indad (focusDir = 0) eller udad (focusDir = 1). Handlingens hastighed og varighed angives af funktionerne `setINDIFocusSpeed()` og `setINDIFocusTimeout()`.

4. Kamera/CCD-funktioner: Funktioner til at styre kamera/CCD-egenskaber og status.

   - `setINDICCDTemp(QString deviceName, int temp)`: Indstil CCD-kredsens måltemperatur i grader Celsius.

   - `setINDIFrameType(QString deviceName, QString type)`: Indstil CCD-rammetype. Tilgængelige tilvalg er FRAME_LIGHT, FRAME_BIAS, FRAME_DARK og FRAME_FLAT.

   - `startINDIExposure(QString deviceName, int timeout)`: Start eksponering med CCD eller kamera med længden som angives af timeout i sekunder.

Bemærk at enhedsnavnet er det første argument i alle INDI-funktioner. Det tillader at forskellige kommandoer som skal sendes til forskellige INDI-enheder blandes i det samme script. Værktøjet Scriptbygger sørger for to tilvalg for at gøre det nemmere at oprette og redigere INDI-scripter:

- `Tilføj WaitForINDIAction efter alle INDI-handlinger`: Hvis dette er markeret, tilføjer scriptbyggeren automatisk `waitForINDIAction()` efter hver handling som genkendes. Hvis du for eksempel tilføjer funktionen `switchINDI()` i scriptet og tilvalget er markeret, tilføjer scriptbyggeren "waitForINDIAction CONNECTION" i scriptfilen lige efter `switchINDI()`. Det gør at scriptet holder pause efter `switchINDI()` er udført indtil `switchINDI()` returnerer med o.k. status (dvs. forbindelse til enheden lykkedes). Det er yderst vigtigt at vide at scriptbyggeren ikke automatisk kan tilføje `waitForINDIAction()` for generelle handlinger som tilføjes med funktionen `setINDIAction()`. Dette skyldes at Kstars ikke kan afgøre overliggende egenskab for generiske handlinger. Derfor skal du tilføje `waitForINDIAction()` manuelt efter generiske handlinger når det ønskes.

- `Genbrug INDI-enhedsnavn`: Hvis dette er markeret udfyldes feltet enhedsnavn i alle efterfølgende funktioner automatisk med det seneste enhedsnavn. Det seneste enhedsnavn indstilles hver gang funktionen `startINDI()` tilføjes i det nuværende script. Ved arbejde med flere enheder anbefales at dette tilvalg deaktiveres.

Nu er vi klar til at oprette et demonstrationsscript som styrer teleskopet LX200 GPS, udover Finger Lakes CCD-kamera. Vor opgave er enkel. Vi beder teleskopet om at panorere til og følge Mars, og derefter beder vi kameraet om at tage tre billeder 10 sekunder adskilt med 20 sekunder.

Eftersom der ikke er nogen direkte tilbagemelding fra INDI DCOP-grænsefladen om forløbet, værdier eller status for enhedshandlinger og parametre (bortset fra `waitForINDIAction()`), er enhedsautomatisering i Kstars ligesom et styresystem med åben kreds. I et sådant system er der oftest ingen direkte tilbagemelding for at måle systemets tilstand og korrigere fejl. Følgelig skal du konstruere dine scripter for enhedsautomatisering med stor eftertanke. Alle automatiseringsscripter skal udsættes for nøje afprøvning inden de bruges.

Værktøjet Scriptopbygning
Værktøjet Scriptopbygning

Demonstrationsscriptet vises på skærmaftrykket ovenfor. Bemærk at vi markerede `"Tilføj WaitForINDIAction efter alle INDI-handlinger"` og afmarkerede `"Genbrug INDI-enhedsnavn"`. Den første funktion at tilføje er `startINDI()` som vises ovenfor. Vi vil køre vore enheder lokalt, så vi ændrer ikke tjenestetilstand som varetages af funktionens argumentvindue. Vi skriver vort enhedsnavn, og begynder med teleskopet "LX200 GPS". Vi gentager samme handling for "FLI CCD". Funktionen `waitFor()` angives derefter. Det anbefales i almindelighed at bruge funktionen `waitFor()` med det samme efter `startINDI()` for at holde pause i scriptet 1-5 sekunder. Dette sikrer at alle egenskaber er bygget og er klare til at tage mod kommandoer. Det er også nyttigt for at styre fjernenheder, eftersom det kan tage en vis tid at hente og bygge egenskaber. I næste funktion, `switchINDI()`, forbinder vi til alle enheder.

Eftersom `"Tilføj WaitForINDIAction efter alle INDI-handlinger"` er markeret, behøver vi ikke at tilføje `waitForINDIAction()` efter `switchINDI()` for at sikre at vi kun fortsætter med at køre scriptet efter at vi har forbundet med godt resultat. Dette skyldes at scriptbyggaren gør det automatisk for os når vi gemmer scriptet. Lad os nu indstille teleskopets tilstand til sporing. Klik på funktionen `setINDIScopeAction()` og vælg TRACK. Bemærk at vi skal indstille teleskopet til sporing inden koordinaterne som det skal følge angives. Funktionen `setINDIScopeAction()` er der af bekvemmelighedsgrunde, eftersom den kun udfører den generelle funktion `setINDIAction()` fulgt af nøgleordet TRACK i dette eksempel. Dog er fordelen ved at bruge `setINDIScopeAction()` at Kstars automatisk kan tilføje `waitForINDIAction()` bagefter når det kræves. Dette er ikke automatisk tilgængeligt for generiske handlinger, som vi tidligere har beskrevet.

Derefter bruger vi funktionen `setINDITargetName()` og angiver Mars. Endelig omfatter de sidste få skridt at indfange et billede i 10 sekunder, hvilket kan gøres ved at bruge funktionen `startINDIExposure()` og vente 20 sekunder mellem kaldene, hvilket kan gøres ved at bruge funktionen `waitFor()` med værdien 20.

Nu kan vi gemme scriptet og køre det når som helst. Det gemte script ligner det følgende:

>     #!/bin/bash
>         #KStars DCOP-script: Demoscript
>         #af Jasem Mutlaq
>         #seneste ændring: Tor 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