<sect1 id="tool-scriptbuilder">
<title>Værktøjet Scriptopbygning</title>
<indexterm><primary>Værktøjer</primary>
<secondary>Scriptopbygning</secondary>
</indexterm>

<para>KDE-programmer kan styres fra andre programmer, fra kommandolinjen eller fra et skal-script vha. protokollen "Desktop COmmunication Protocol" (<abbrev>DCOP</abbrev>). KStars udnytter denne mulighed til at gøre det muligt at lave scripter der udfører meget komplekse operationer, så de kan udføres igen og igen. Dette kan f.eks. bruges i undervisningsverdenen, til at forberede en demonstration af astronomiske begreber og eksempler. </para>
<para>Problemet med DCOP-scripter 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 (<abbrev>GUI</abbrev>), en grafisk "peg og klik" brugerflade  til at konstruere DCOP-scripter. På den måde bliver det meget nemmere for f.eks. lærere at lave avancerede scripter. </para>

<sect2 id="sb-intro">
<title>Introduktion til Scriptopbygning</title>

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

<screenshot>
<screeninfo>Værktøjet Scriptopbygning </screeninfo>
<mediaobject>
  <imageobject>
    <imagedata fileref="scriptbuilder.png" format="PNG"/>
  </imageobject>
  <textobject>
    <phrase>Værktøjet Scriptopbygning</phrase>
  </textobject>
</mediaobject>
</screenshot>

<para>Værktøjet Scriptopbygning er vist på skærmbilledet herover. Feltet til venstre er feltet <firstterm>Nuværende script</firstterm>, den viser listen over de kommandoer scriptet foreløbigt består af. Feltet til højre er <firstterm>Funktionsoversigten</firstterm>, 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 <firstterm>Funktionsargumenter</firstterm>. 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. </para><para>Langs toppen af vinduet er der en række knapper som indvirker på scriptet som helhed. Fra venstre mod højre er det:<guibutton>Nyt script</guibutton>, <guibutton>Åbn script</guibutton>, <guibutton>Gem script</guibutton>, <guibutton>Gem scriptet som...</guibutton> og <guibutton>Test script</guibutton>. Funktionen af disse knapper giver sig selv, undtagen måske den sidste knap. Når man trykker på <guibutton>Test script</guibutton> 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. </para><para>I midten af vinduet er der en lodret række knapper, som styrer individuelle scriptfunktioner. Nedefra og op er det:<guibutton>Tilføj funktion</guibutton>, <guibutton>Fjern funktionen</guibutton>, <guibutton>Kopiér funktionen</guibutton>, <guibutton>Flyt op</guibutton> og <guibutton>Flyt ned</guibutton>. <guibutton>Tilføj funktion</guibutton> 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. </para>
</sect2>

<sect2 id="sb-using">
<title>Brug af scriptopbyggeren</title>
<para>For at illustrere hvordan scriptopbyggeren virker, vil vi gennemgå et lille eksempel, hvor vi laver et script der følger månen mens uret går meget hurtigt. </para><para>Hvis vi vil følge Månen er vi nødt til først at indstille stjernekortet så det peger på den. Funktionen <firstterm>lookToward</firstterm> bruges til at gøre dette. Markér denne funktion i funktionsoversigten, og se på dokumentationen der kommer frem under oversigten. Tryk på knappen <guibutton>Tilføj funktion</guibutton> for at tilføje denne funktion til scriptfeltet. Panelet funktionsargumenter vil nu indeholde et kombofelt <quote>Ret:</quote>, 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 <quote>Moon</quote> manuelt i feltet, eller trykke på knappen <guibutton>Objekt</guibutton> for at bruge vinduet <guilabel>Find objekt</guilabel> til at vælge Månen fra listen over kendte objekter. Læg mærke til at centrering på et objekt også slår følgning af objektet til, så der er ingen grund til at tilføje <firstterm>setTracking</firstterm>-funktionen efter lookToward. </para><para>Nu da vi har fået stillet ind på Månen, skal vi have tiden til at gå hurtigere. Brug funktionen <firstterm>setClockScale</firstterm> til dette. Tilføj den til scriptet ved at dobbeltklikke på den i funktionsoversigten. Funktionsargumentpanelet indeholder et rullefelt til at indstille tidsintervallerne for uret i simuleringen. Ret tidsintervallerne til 3 timer. </para><para>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 <firstterm>waitFor</firstterm> til scriptet, og brug funktionsargumentpanelet til at angive at det skal vente i 20 sekunder før det går videre. </para><para>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. </para><para>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 <firstterm>UseAltAz</firstterm> til <quote>false</quote>.' For at ændre indstillinger af stjernekortet bruges funktionen <firstterm>changeViewOption</firstterm>. 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 dette 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å <guibutton>Gennemse træstrukturen</guibutton> 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 <guilabel>Stjernekortsindstillinger</guilabel>. Markér bare dette punkt og tryk på <guibutton>O.k.</guibutton>, og den vil blive valgt i kombinationsfeltet i funktionsargumentpanelet. Til sidst mangler vi så bare at sætte dens værdi til <quote>false</quote> eller <quote>0</quote>. </para><para>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å <guibutton>Flyt op</guibutton> indtil det er den første funktion. </para><para>Nu da vi er færdige med scriptet skal det gemmes på disken. Tryk på <guibutton>Gem script</guibutton>. Dette åbner en dialog hvor du først kan give scriptet et navn og skrive dit navn som forfatter. Skriv <quote>På sporet af Månen</quote> som scriptets navn og dit eget navn som forfatter, og tryk på <guibutton>O.k</guibutton>. Derefter vil du se  &kde;s standardgemmedialog. Skriv et filnavn og tryk på <guibutton>O.k.</guibutton> for at gemme scriptet. Vær opmærksom på at hvis filnavnet ikke ender på <quote>.kstars</quote>, vil denne filendelse automatisk blive tilføjet. Hvis du er nysgerrig kan du altid læse scriptfilen i enhver teksteditor. </para><para>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 <guimenuitem>Kør script</guimenuitem> i <guimenu>Fil</guimenu>-menuen. </para>
</sect2>

<sect2 id="sb-indi">
  <title>Enhedsautomatisering med INDI</title>
  <para>Enhedsskemalægning og automatisering understøttes for alle enheder som følger <link linkend="what-is-indi">INDI</link>. Du kan koordinere så mange enheder som helst til at udføre komplekse handlinger med &kstars; <link linkend="sb-intro">scriptbygger</link>. Dette kan opnås ved at bruge &kstars; INDI DCOP-grænseflade. INDI DCOP-funktionerne kan deles op i fem 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 <link linkend="indi-concepts">INDI-begreber</link> eftersom vi udnytter nøglebegreber fra INDI i hele denne vejledning.</para>
  <orderedlist>
    <listitem><para>Generiske enhedsfunktioner: Funktioner til at oprette eller lukke af for enheder, osv.</para>
      <itemizedlist>
	<listitem><para><function>startINDI (TQString deviceName, bool useLocal)</function>: Opret en INDI-enhed enten i lokaltilstand eller i servertilstand.</para></listitem>
	<listitem><para><function>shutdownINDI (TQString deviceName)</function>: Luk af for en INDI-enhed.</para></listitem>
	<listitem><para><function>switchINDI(TQString deviceName, bool turnOn)</function>: Forbind eller afbryd en INDI-enhed.</para></listitem>
	<listitem><para><function>setINDIPort(TQString deviceName, TQString port)</function>: Indstil INDI-enhedens forbindelsesport.</para></listitem>
	<listitem><para><function>setINDIAction(TQString deviceName, TQString action)</function>: Aktivér en INDI-handling. Handlingen kan være et hvilket som helst <emphasis>element</emphasis> i en <emphasis>skifteegenskab</emphasis>.</para></listitem>
	<listitem><para><function>waitForINDIAction(TQString deviceName, TQString action)</function>: Hold pause i kørsel af scriptet til angiven <emphasis>handlingsegenskab</emphasis> returnerer med status O.k.</para></listitem>
      </itemizedlist>
    </listitem>
    <listitem><para>Teleskopfunktioner: Funktioner til at styre teleskopbevægelser og status.</para>
      <itemizedlist>
	<listitem><para><function>setINDIScopeAction(TQString deviceName, TQString action)</function>: Indstil teleskopets tilstand eller handling. Tilgængelige tilvalg er SLEW, TRACK, SYNC, PARK og ABORT.</para></listitem>
	<listitem><para><function>setINDITargetCoord(TQString deviceName, double RA, double DEC)</function>: Indstil teleskopets JNow-målkoordinater til <emphasis>RA</emphasis> og <emphasis>DEC</emphasis>.</para></listitem>
	<listitem><para><function>setINDITargetName(TQString deviceName, TQString objectName)</function>: Indstil teleskopets JNow-målkoordinater til koordinaterne for <emphasis>objectName</emphasis>. Kstars slår objektnavnet op i sin database og henter RA og DEC når de er fundet.</para></listitem>
	<listitem><para><function>setINDIGeoLocation(TQString deviceName, double longitude, double latitude)</function>: Sæt teleskopets geografiske sted til de længdegrader og breddegrader som angives. Længdegraden måles mod øst fra Greenwich, i Storbritannien. Selvom det er almindeligt at bruge negative længdegrader for den vestlige halvklode, kræver INDI imidlertid længdegrader mellem 0 og 360 grader. Hvis du har en negative længdegrad, så læg blot 360 grader til for at få værdien som INDI forventer sig. For eksempel har Calgary i Canada følgende koordinater i KStars: Længdegrad -114 04 58 og breddegrad 51 02 58. Altså ville INDI behøve længdegraden 360 - 114,069 = 245,917 grader.</para></listitem>
	<listitem><para><function>setINDIUTC(TQString ddeviceName, TQString UTCDateTime)</function>: Indstil teleskopets UTC-tid i ISO 8601-format. Formatet er ÅÅÅÅ/MM/DDTTT:MM:SS.(f.eks. 2004-07-12T22:05:32).</para></listitem>
      </itemizedlist>
    </listitem>
    <listitem><para>Kamera/CCD-funktioner: Funktioner til at styre kamera/CCD-egenskaber og status.</para>
      <itemizedlist>
	<listitem><para><function>setINDICCDTemp(TQString deviceName, int temp)</function>: Indstil CCD-kredsens måltemperatur i grader Celsius.</para></listitem>
	<listitem><para><function>setINDIFrameType(TQString deviceName, TQString type)</function>: Indstil CCD-rammetype. Tilgængelige tilvalg er FRAME_LIGHT, FRAME_BIAS, FRAME_DARK og FRAME_FLAT.</para></listitem>
	<listitem><para><function>startINDIExposure(TQString deviceName, int timeout)</function>: Start eksponering med CCD eller kamera med længden som angives af <emphasis>timeout</emphasis> i sekunder.</para></listitem>
      </itemizedlist>
    </listitem>    
   <listitem><para>Fokuseringsfunktioner: Funktioner til at styre fokuseringsenhedens bevægelse og status.</para>
      <itemizedlist>
      <listitem><para><function>setINDIFocusSpeed(TQString deviceName, TQString action)</function>: Angiv fokuseringsenhedens hastighed. Tilgængelige tilvalg er FOCUS_HALT, FOCUS_SLOW, FOCUS_MEDIUM og FOCUS_FAST.</para></listitem>
      <listitem><para><function>setINDIFocusTimeout(TQString deviceName, int timeout)</function>: Indstil tidsgrænsen i sekunder for alle følgende startINDIFocus-handlinger.</para></listitem>
      <listitem><para><function>startINDIFocus(TQString deviceName, int focusDir)</function>: Flyt enten fokuseringsenheden indad (focusDir = 0) eller udad (focusDir = 1). Handlingens hastighed og varighed angives af funktionerne <function>setINDIFocusSpeed()</function> og <function>setINDIFocusTimeout()</function>.</para></listitem>
    </itemizedlist>
    </listitem>
   <listitem><para>Filterfunktioner: Funktioner til at kontrollere filterpositioner.</para>
      <itemizedlist>
      <listitem><para><function>setINDIFilterNum(TQString deviceName, int filter_num)</function>: Ændr filterposition til <varname>filter_num</varname>. Brugeren kan tildele alias for filternummer i dialogen <guimenuitem>Indstil INDI</guimenuitem> under menuen <guimenu>Enheder</guimenu> (f.eks. Filter 1 = Rød, Filter 2 = Grøn, etc.).</para></listitem>
    </itemizedlist>
    </listitem>
    
  </orderedlist>
  
<para>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:</para>
<itemizedlist>
  <listitem><para><option>Tilføj WaitForINDIAction efter alle INDI-handlinger</option>: Hvis dette er markeret, tilføjer scriptbyggeren automatisk <function>waitForINDIAction()</function> efter hver handling som genkendes. Hvis du for eksempel tilføjer funktionen <function>switchINDI()</function> i scriptet og tilvalget er markeret, tilføjer scriptbyggeren "waitForINDIAction CONNECTION" i scriptfilen lige efter <function>switchINDI()</function>. Det gør at scriptet holder pause efter <function>switchINDI()</function> er udført indtil <function>switchINDI()</function> returnerer med o.k. status (dvs. forbindelse til enheden lykkedes). Det er yderst vigtigt at vide at scriptbyggeren ikke automatisk kan tilføje <function>waitForINDIAction()</function> for generelle handlinger som tilføjes med funktionen <function>setINDIAction()</function>. Dette skyldes at Kstars ikke kan afgøre overliggende egenskab for generiske handlinger. Derfor skal du tilføje <function>waitForINDIAction()</function> manuelt efter generiske handlinger når det ønskes.</para>
  </listitem>
  <listitem><para><option>Genbrug INDI-enhedsnavn</option>: Hvis dette er markeret udfyldes feltet enhedsnavn i alle efterfølgende funktioner automatisk med det seneste enhedsnavn. Det seneste enhedsnavn indstilles hver gang funktionen <function>startINDI()</function> tilføjes i det nuværende script. Ved arbejde med flere enheder anbefales at dette tilvalg deaktiveres.</para>
  </listitem>
</itemizedlist>

<para>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.</para>
<important><para>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 <function>waitForINDIAction()</function>), 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.</para></important>

<screenshot>
  <screeninfo>Værktøjet Scriptopbygning </screeninfo>
  <mediaobject>
    <imageobject>
      <imagedata fileref="indiscript.png" format="PNG"/>
    </imageobject>
    <textobject>
      <phrase>Værktøjet Scriptopbygning</phrase>
    </textobject>
  </mediaobject>
</screenshot>

<para>Demonstrationsscriptet vises på skærmaftrykket ovenfor. Bemærk at vi markerede <option>"Tilføj WaitForINDIAction efter alle INDI-handlinger"</option> og afmarkerede <option>"Genbrug INDI-enhedsnavn"</option>. Den første funktion at tilføje er <function>startINDI()</function> 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 <function>waitFor()</function> angives derefter. Det anbefales i almindelighed at bruge funktionen <function>waitFor()</function> med det samme efter <function>startINDI()</function> 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, <function>switchINDI()</function>, forbinder vi til alle enheder.</para>

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

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

<para>Nu kan vi gemme scriptet og køre det når som helst. Det gemte script ligner det følgende:</para>
<blockquote><programlisting>#!/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
</programlisting>
</blockquote>

<note>
<para>INDI-biblioteket sørger for robuste scriptværktøjer som gør det muligt for udviklere at komponere meget komplekse scripter. For mere detaljeret information, se <ulink url="http://indi.sourceforge.net/manual/book1.html">INDI Developer Manual</ulink>.</para>
</note>
</sect2>
</sect1>

