# Verktyget Skriptbyggaren

KDE-program kan styras externt från ett annat program, från en terminal, eller från ett skalskript med hjälp av protokollet för skrivbordskommunikation (Desktop COmmunication Protocol, DCOP). KStars utnyttjar den här funktionen för att tillåta att skapa skript med relativt komplicerade beteenden, som kan spelas upp när som helst. Detta kan till exempel användas för att skapa en demonstration i klassrummet för att illustrera astronomiska begrepp.

Problemet med DCOP-skript är att skriva dem är lite grand som programmering, och kan verka vara en skrämmande uppgift för de som saknar programmeringsvana. Skriptbyggaren tillhandahåller ett grafiskt gränssnitt där man kan peka och klicka för att skapa KStars DCOP-skript, vilket gör det mycket enkelt att skapa komplexa skript.

## Introduktion till skriptbyggaren

Innan förklaringen av hur skriptbyggaren används, följer en mycket kort inledning till alla grafiska komponenter: För mer information, använd funktionen "Vad är det här?".

Verktyget Skriptbyggare
Verktyget Skriptbyggare

Skriptbyggaren visas i skärmbilden ovanför. Rutan till vänster är Aktuellt skript. Den visar listan med kommandon som utgör det aktuella arbetsskriptet. Rutan till höger är Funktionsbläddraren. Den visar listan med tillgängliga skriptfunktioner. Under funktionsbläddraren finns en liten ruta som visar kortfattad dokumentation av skriptfunktionen som är markerad i funktionsbläddraren. Panelen under rutan Aktuellt skript är rutan Funktionsargument. När en funktion är markerad i rutan Aktuellt skript, visar rutan objekt för att ange värden för alla argument som den markerade funktionen kräver.

Längs fönstrets överkant finns en rad knappar som gäller skriptet som helhet. Från vänster till höger är de: Nytt skript, Öppna skript, Spara skript, Spara skript som... och Testa skript. Knapparnas funktion bör vara uppenbar, möjligen med undantag för den sista knappen. Genom att trycka på Testa skript, görs ett försök att köra aktuellt skript i KStars huvudfönster. Du bör flytta skriptbyggarens fönster ur vägen innan du trycker på knappen, så att du kan se resultatet.

I fönstrets mitt finns en kolumn med knappar som hanterar individuella funktioner i skriptet. Uppifrån och ner är de: Lägg till funktion, Ta bort funktion, Kopiera funktion, Flytta upp och Flytta ner. Lägg till funktion lägger till funktionen som för närvarande är markerad i Funktionsbläddraren i rutan Aktuellt skript (du kan också lägga till en funktion genom att dubbelklicka på den). Övriga knappar hanterar funktionen som är markerad i rutan Aktuellt skript, genom att antingen ta bort den, duplicera den eller ändra dess position i det aktuella skriptet.

## Använda skriptbyggaren

För att illustrera hur skriptbyggaren används, presenterar vi ett kort handledningsexempel, där vi skapar ett skript som följer månen medan klockan går med accelererad hastighet.

Om vi ska följa månen, måste vi först peka skärmen mot den. Funktionen lookToward används för att göra detta. Markera funktionen i funktionsbläddraren, och observera dokumentationen som visas i rutan under funktionsbläddraren. Tryck på knappen Lägg till funktion för att lägga till funktionen i rutan Aktuellt skript. Rutan Funktionsargument innehåller nu en kombinationsruta som heter Riktning. Detta är riktningen som skärmen ska peka. Kombinationsrutan innehåller bara kompassens kardinalpunkter, inte månen eller något annat objekt. Du kan antingen skriva in Moon i rutan för hand, eller trycka på knappen Objekt för att använda fönstret Sök objekt. Här kan du välja månen i listan med namngivna objekt. Observera att som vanligt aktiveras automatiskt följning vid centrering på ett objekt, så det finns inget behov av att lägga till funktionen setTracking efter lookToward.

När vi nu har tagit hand om pekningen mot månen, vill vi som nästa steg få tiden att gå med en accelererad hastighet. Använd funktionen setClockScale för detta. Lägg till den i skriptet genom att dubbelklicka på den i funktionsbläddraren. Rutan Funktionsargument innehåller nu inställning av tidssteg för att ange önskat tidssteg för simulatorklockan. Ändra tidssteget till 3 timmar.

Ja, nu har vi pekat på månen och accelererat klockan. Nu vill vi bara att skriptet ska vänta flera sekunder medan skärmen följer månen. Lägg till funktionen waitFor i skriptet, och använd panelen Funktionsargument för att ange att det ska vänta i 20 sekunder innan det fortsätter.

För att avsluta, låt oss återställa klockans tidssteg till det normala värdet 1 sekund. Lägg till ytterligare ett anrop till setClockScale, och ställ in värdet 1 sek.

I själva verket är vi inte riktigt klara än. Vi bör troligen försäkra oss om att skärmen använder ekvatoriella koordinater innan skriptet följer månen med ett accelererat tidssteg. Annars, om skärmen använder horisontella koordinater, roterar den mycket snabbt med stora vinklar när månen går upp eller går ner. Det kan vara mycket förvirrande, och kan undvikas genom att ställa in visningsalternativet UseAltAz till 0. För att ändra något visningsalternativ, använd funktionen changeViewOption. Lägg till funktionen i skriptet, och titta på rutan Funktionsargument. Där finns en kombinationsruta som innehåller en lista med alla alternativ som kan justeras av changeViewOption. Eftersom vi vet att vi vill använda alternativet UseAltAz, kunde vi helt enkelt välja det i kombinationsrutan. Listan är dock rätt lång, och det finns ingen förklaring av vad varje alternativ är till för. Därför kan det vara enklare att trycka på knappen Bläddringsträd, som visar ett fönster med en trädvy av tillgängliga alternativ, organiserade enligt ämne. Dessutom har varje alternativ en kort förklaring av vad det gör, och datatyp för alternativets värde. Vi hittar UseAltAz i kategorin Alternativ för himmelskartan. Markera bara alternativet och tryck på Ok, så väljes det i kombinationsrutan i rutan Funktionsargument. Till sist, ställ in värdet till 0 eller false.

Ytterligare ett steg: Att ändra UseAltAz i slutet på skriptet gör ingen nytta. Vi måste ändra det innan någonting annat händer. Försäkra dig om att funktionen är markerad i rutan Aktuellt skript, och tryck på knappen Flytta upp till den är första funktionen.

Nu när vi är klara med skriptet, bör vi spara det på disk. Tryck på knappen Spara skript. Då visas först ett fönster där du kan ange ett namn på skriptet, och fylla i ditt namn som författare. Skriv in Följa månen som namn, och ditt namn som författare, och tryck på Ok. Därefter ser du &kde;:s vanliga dialogruta för att spara en fil. Ange skriptets filnamn, och tryck på Ok för att spara det. Observera att om filnamnet inte slutar med .kstars, läggs ändelsen automatiskt till. Om du är nyfiken, kan du titta på skriptet med vilken texteditor som helst.

När vi nu har ett fullständigt skript, kan vi köra det på ett antal olika sätt. Från en terminal kan du helt enkelt köra skriptet, under förutsättning att en instans av KStars för närvarande kör. Som ett alternativ kan du köra skriptet inne i KStars med alternativet Kör skript... i menyn Arkiv.

## Enhetsautomatisering med INDI

Enhetsschemaläggning och automatisering stöds för alla enheter som följer INDI. Du kan koordinera hur många enheter som helst för att utföra komplexa åtgärder med &kstars; skriptbyggare. Det kan åstadkommas genom att använda &kstars; INDI DCOP-gränssnitt. INDI DCOP-funktionerna kan delas upp i fem olika klasser. Det följande är en genomgång av funktionerna som stöds i Kstars och deras argument. Du rekommenderas att läsa igenom avsnittet INDI-koncept eftersom vi utnyttjar nyckelbegrepp från INDI i hela den här handledningen.

1. Generella enhetsfunktioner: Funktioner för att upprätta eller stänga av enheter, etc.

   - `startINDI (QString deviceName, bool useLocal)`: Upprätta en INDI-enhet antingen i lokalläge eller serverläge.

   - `shutdownINDI (QString deviceName)`: Stäng av en INDI-enhet.

   - `switchINDI(QString deviceName, bool turnOn)`: Koppla upp eller koppla ner en INDI-enhet.

   - `setINDIPort(QString deviceName, QString port)`: Ställ in INDI-enhetens anslutningsport.

   - `setINDIAction(QString deviceName, QString action)`: Aktivera en INDI-åtgärd. Åtgärden kan vara vilket element som helst i en omställningsegenskap.

   - `waitForINDIAction(QString deviceName, QString action)`: Gör paus i körning av skriptet till angiven åtgärdsegenskap returnerar med status Ok.

2. Teleskopfunktioner: Funktioner för att styra teleskoprörelser och status.

   - `setINDIScopeAction(QString deviceName, QString action)`: Ställ in teleskopets läge eller åtgärd. Tillgängliga alternativ är SLEW, TRACK, SYNC, PARK och ABORT.

   - `setINDITargetCoord(QString deviceName, double RA, double DEC)`: Ställ in teleskopets JNow-målkoordinater till RA och DEC.

   - `setINDITargetName(QString deviceName, QString objectName)`: Ställ in teleskopets JNow-målkoordinater till koordinaterna för objectName. Kstars slår upp objektnamnet i sin databas och hämtar RA och DEC när de har hittats.

   - `setINDIGeoLocation(QString deviceName, double longitude, double latitude)`: Ställ in teleskopets geografiska plats till longitud och latitud som anges. Longituden mäts österut från Greenwich, i Storbritannien. Även om det är vanligt att använda negativa longituder för västra halvklotet, kräver dock INDI logitudvärden mellan 0 och 360 grader. Om du har en negativ longitud, addera helt enkelt 360 grader för att få värdet som INDI förväntar sig. Till exempel har Calgary i Kanada följande koordinater i &kstars;: Longitud -114 04 58 och latitud 51 02 58. Alltså skulle INDI behöva longituden 360 - 114,083 = 245,917 grader.

   - `setINDIUTC(QString ddeviceName, QString UTCDateTime)`: Ställ in teleskopets UTC-tid med ISO 8601-format. Formatet är ÅÅÅÅ/MM/DDTTT:MM:SS.(t.ex. 2004-07-12T22:05:32).

3. Kamera/CCD-funktioner: Funktioner för att styra kamera/CCD-egenskaper och status.

   - `setINDICCDTemp(QString deviceName, int temp)`: Ställ in CCD-kretsens måltemperatur i grader Celsius.

   - `setINDIFrameType(QString deviceName, QString type)`: Ställ in CCD-ramtyp. Tillgängliga alternativ är FRAME_LIGHT, FRAME_BIAS, FRAME_DARK och FRAME_FLAT.

   - `startINDIExposure(QString deviceName, int timeout)`: Starta exponering med CCD eller kamera med längden som anges av timeout i sekunder.

4. Fokuseringsfunktioner: Funktioner för att styra fokuseringsenhetens rörelse och status.

   - `setINDIFocusSpeed(QString deviceName, QString action)`: Ange fokuseringsenhetens hastighet. Tillgängliga alternativ är FOCUS_HALT, FOCUS_SLOW, FOCUS_MEDIUM och FOCUS_FAST.

   - `setINDIFocusTimeout(QString deviceName, int timeout)`: Ställ in tidsgränsen i sekunder för alla följande startINDIFocus-åtgärder.

   - `startINDIFocus(QString deviceName, int focusDir)`: Flytta antingen fokuseringsenheten inåt (focusDir = 0) eller utåt (focusDir = 1). Åtgärdens hastighet och varaktighet anges av funktionerna `setINDIFocusSpeed()` och `setINDIFocusTimeout()`.

5. Filterfunktioner: Funktioner för att styra filterpositioner.

   - `setINDIFilterNum(QString deviceName, int filter_num)`: Ändra filterposition till `filter_num`. Användaren kan tilldela alias för filternummer i dialogrutan Anpassa INDI under menyn Enheter (t.ex. Filter 1 = Röd, Filter 2 = Grön, etc.).

Observera att enhetsnamnet är det första argumentet i alla INDI-funktioner. Det tillåter att olika kommandon som ska skickas till olika INDI-enheter blandas i ett och samma skript. Verktyget Skriptbyggare tillhandahåller två alternativ för att underlätta att skapa och redigera INDI-skript:

- `Lägg till WaitForINDIAction efter alla INDI-åtgärder`: Om markerad, lägger skriptbyggaren automatiskt till `waitForINDIAction()` efter varje åtgärd som känns igen. Om du till exempel lägger till funktionen `switchINDI()` i skriptet och alternativet är markerat, lägger skriptbyggaren till "waitForINDIAction CONNECTION" i skriptfilen precis efter `switchINDI()`. Det gör att skriptet gör paus efter `switchINDI()` har utförts till `switchINDI()` returnerar med ok status (dvs. anslutning till enheten lyckades). Det är ytterst viktigt att veta att skriptbyggaren inte automatiskt kan lägga till `waitForINDIAction()` för generella åtgärder som läggs till med funktionen `setINDIAction()`. Det beror på att Kstars inte kan avgöra överliggande egenskap för generella åtgärder. Därför måste du lägga till `waitForINDIAction()` för hand efter generella åtgärder när det önskas.

- `Återanvänd INDI-enhetsnamn`: Om markerad fylls fältet enhetsnamn i alla efterföljande funktioner automatiskt i med det senaste enhetsnamnet. Det senaste enhetsnamnet ställs in varje gång funktionen `startINDI()` läggs till i det nuvarande skriptet. Vid arbete med flera enheter rekommenderas att alternativet inaktiveras.

Nur är vi redo att skapa ett demonstrationsskript som styr teleskopet LX200 GPS, förutom Finger Lakes CCD-kamera. Vår uppgift är enkel. Vi ber teleskopet att panorera till och följa Mars, och därefter ber vi kameran att ta tre bilder 10 sekunder vardera åtskilda med 20 sekunder.

Eftersom det inte finns någon direkt återmatning från INDI DCOP-gränssnittet om förloppet, värden eller status för enhetsåtgärder och parametrar (förutom `waitForINDIAction()`), är enhetsautomatisering i Kstars likt ett styrsystem med öppen krets. I ett sådant system finns det oftast ingen direkt återmatning för att mäta systemets tillstånd och korrigera fel. Följaktligen måste du konstruera dina skript för enhetsautomatisering med stor eftertanke. Alla automatiseringsskript måste utsättas för noggrann utprovning innan de används.

Verktyget Skriptbyggare
Verktyget Skriptbyggare

Demonstrationsskriptet visas på skärmbilden ovan. Observera att vi markerade `"Lägg till WaitForINDIAction efter alla INDI-åtgärder"` och avmarkerade `"Återanvänd INDI-enhetsnamn"`. Den första funktionen att lägga till är `startINDI()` som visas ovan. Vi vill köra våra enheter lokalt, så vi ändrar inte tjänstläget som tillhandahålls i funktionens argumentfönster. Vi skriver in vårt enhetsnamn, och börjar med teleskopet "LX200 GPS". Vi upprepar samma åtgärd igen för "FLI CCD". Funktionen `waitFor()` anges därefter. Det rekommenderas i allmänhet att använda funktionen `waitFor()` omedelbart efter `startINDI()` för att göra paus i skriptet 1-5 sekunder. Det säkerställer att alla egenskaper har byggts och är klara att ta emot kommandon. Det är också användbart för att styra fjärrenheter, eftersom det kan ta en viss tid att hämta och bygga egenskaper. I nästa funktion, `switchINDI()`, ansluter vi till alla enheter.

Eftersom `"Lägg till WaitForINDIAction efter alla INDI-åtgärder"` är markerad, behöver vi inte lägga till `waitForINDIAction()` efter `switchINDI()` för att säkerställa att vi bara fortsätter att köra skriptet efter vi har anslutit med lyckat resultat. Det beror på att skriptbyggaren gör det automatiskt åt oss när vi sparar skriptet. Låt oss nu ställa in teleskopets läge till följning. Klicka på funktionen `setINDIScopeAction()` och välj TRACK. Observera att vi måste ställa in teleskopet till följning innan koordinaterna som det ska följa anges. Funktionen `setINDIScopeAction()` tillhandahålls av bekvämlighetsskäl, eftersom den bara utför den generella funktionen `setINDIAction()` följt av nyckelordet TRACK i det här exemplet. Dock är fördelen att använda `setINDIScopeAction()` att Kstars automatiskt kan lägga till `waitForINDIAction()` efteråt när det krävs. Detta är inte automatiskt tillgängligt för generella åtgärder, som vi tidigare beskrivit.

Därefter använder vi funktionen `setINDITargetName()` och anger Mars. Till sist omfattar de sista få stegen att fånga en bild under 10 sekunder, vilket kan göras genom att använda funktionen `startINDIExposure()` och vänta 20 sekunder mellan anropen, vilket kan göras genom att använda funktionen `waitFor()` med värdet 20.

Nu kan vi spara skriptet och köra det när som helst. Det sparade skriptet liknar det följande:

>     #!/bin/bash
>         #KStars DCOP-skript: Demoskript
>         #av Jasem Mutlaq
>         #senaste ä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

INDI-biblioteket tillhandahåller tåliga skriptverktyg som gör det möjligt för utvecklare att komponera mycket komplexa skript. För mer detaljerad information, se INDI Developer Manual.