Tutorial:Erstellen neuer Relaisgruppen - Skripte erstellen

Aus StellSi-Hilfewiki
Zur Navigation springen Zur Suche springen

Der Programmablauf von StellSi wird über Scripte gesteuert. Das Scriptsystem von StellSi basiert dabei auf dem C(++)-Ähnlichen Angelscript (http://www.angelcode.com/angelscript/).

Hintergrund

Die Logik von StellSi-Stellwerken wird mithilfe von Scripten gesteuert. Das heißt hinter jedem Stellwerk steht ein kleines Programm das die Funktionen von StellSi steuert und das man auch bearbeiten kann.

Die Scripte selbst befinden sich in seperaten Dateien, den *.stws-Dateien. Sie liegen zusammen mit den Biblitotheken im Verzeichnis der Bauform. Sie können im Prinzip mit jedem beliebigen Texteditor geöffnet werden, unter Windows zum Beispiel mit Editor/Notepad. Es ist jedoch zu beachten, dass bei Dateien von Fremden Betriebssystem möglicherweise eine andere Normierung für den Zeilenumbruch verwendet wurde. (Details siehe Wikipedia.) Ist es offensichtlich, dass das Programm die Zeilenumbrüche nicht Richtig erkannt hat, hilft es meist einen anderen Editor zu verwenden (unter Windows zum Beispiel WordPad). Für den eigentlichen Code sind die Zeilenumbrüche jedoch nicht relevant.

Im Script stellt Relais- oder Anschlatgruppe eine Klasse dar. Die Schnittstellen werden über Varriablen eingefügt und rufen automatisch bestimmte Methoden auf.

Grundlagen

Die Scripte sind im Prinzip wie eine normale Programmiersprache aufgebaut.

Grundlage der Programmierung sind einzelne Klassen: Eine Klasse beginnt mit dem Schlüsselwort class, es folgt der Name der Klasse, dann eine Geschweifte Klammer, innerhalb der sich der Ihnhalt der Klasse befindet. Die Klasse endet mit einer weiteren geschweiften Klammer.

class Weiche
{
    //Inhalt der Klasse
}

Innerhalb einer Klasse werden allgemeine Varriablen deklariert. Varriablen speichern Daten oder stellen Verbindungen zu der Programmlogik von StellSi her. Sie beginnt mit dem Datentyp der Variable (z.B. int für eine Zahl) gefolgt von einem Namen der Varriable, mit dem man sie Später identifizieren kann, und gleich danach einem ; .

class Weiche
{
    Schnittstelle tischfeld;
    int anzahlIrgendetwas;
    bool tasteGedrueckt;
}

Neben den Varriablen gibt es innerhalb von Programmen noch Funktionen. Eine Funktion beginnt mit void (oder einem Datentyp) gefolgt von dem Namen der Funktion. Danach folgt eine runde geöffnete Klammer, in der angegeben wird, welche Daten der Funktion mitgegeben werden. Diese Daten werden Kommagetrennt in der Form Datentyp Name angegeben. Es folgt eine Geschweifte Klammer für den Methodenanfang, der Methodeninhalt und eine Geschweifte Klammer für das Methodenende.

class Weiche
{
    Schnittstelle tischfeld;
    int anzahlIrgendetwas;
    bool tasteGedrueckt;
    
    void init()
    {
         //Methodeninhalt
    }
    void on_tischfeld_wht(int wert)
    {
         //Methodeninhalt
    }
    void beliebigeMethode(int wert, bool andererWert)
    {
         //Methodeninhalt
    }
}

Innerhalb der Methoden kann man mit den Varriablen Rechnen und ihnen Werte zuweisen. + addiert zwei Zahlen, - subtrahiert sie, * multipliziert, / dividiert Sie. Mit == wird überprüft ob Zahlen oder Warheitswerte gleich sind, das Ergebnis ist ein Warheitswert. Mit = werden Zahlen oder Warheitswerte zugewiesen. Mit ! wird aus einem Warheitswert sein Gegenteil. Mit & oder && wird Zurückgegeben, ob der eine und der andere Warheitswert Wahr ist, mit | oder || wird zurückgegeben, ob der eine oder der andere Warheitswert Wahr ist. Mit <, <=, > und >= wird überprüft, welche Zahl größer ist. Mit Klammer werden wie in der Mathematik die Reinfolgen der Rechnereien festgelegt. Alles was zwischen // und dem Zeilenende oder zwischen /* und */ folgt ist ein Kommentar und wird (im gesammten Programm) ignoriert. Ein Befehl endet mit ; . Das Programm arbeitet die Befehle Schritt für Schritt ab.

class Weiche
{
    Schnittstelle tischfeld;
    int anzahlIrgendetwas;
    bool tasteGedrueckt;
    
    void init()
    {
         anzahlIrgendetwas=0;
         tasteGedrueckt=false;
    }
    void on_tischfeld_wht(int wert)
    {
         tasteGedrueckt=true;
         anzahlIrgendetwas=wert;
    }
    int beliebigeMethode(int wert, bool andererWert)
    {
         tasteGedrueckt = ((wert == 1)||(wert > 15))&&(!andererWert);
         //Rest der Methode.
    }
}

In den Methoden können andere Methoden aufgerufen werden. Eigene Methoden werden aufgerufen, indem man Sie mit ihrem Namen nennt, in einer Klammer kommagetrennt die Parameter übergibt und den Befehl dann wieder mit ; abschließt. Die Kommunikation mit StellSi findet statt indem man den Namen einer (Schnitstellen-)Varriablen gefolgt von einem . und dann dem Namen einer StellSi-Methode wie eine lokale Methode aufruft. Einige Methoden benötigen dafür Zeichenfolgen. Eine Zeichenfolge ist ein Text zwischen zwei Anführungszeichen.

class Weiche
{
    Schnittstelle tischfeld;
    int anzahlIrgendetwas;
    bool tasteGedrueckt;
    
    void init()
    {
         anzahlIrgendetwas=0;
         tasteGedrueckt=false;
         tischfeld.setWert("besetzt",1);
    }
    void on_tischfeld_wht(int wert)
    {
         tasteGedrueckt=true;
         anzahlIrgendetwas=wert;
         beliebigeMethode(27,false);
    }
    int beliebigeMethode(int wert, bool andererWert)
    {
         tasteGedrueckt = ((wert == 1)||(wert > 15))&&(!andererWert);
         tischfeld.setWert("irgendwas",41);
         //Rest der Methode.
    }
}

Der Programmablauf kann mit Bedingungen bedingt Fortgesetzt werden. Bedingungen beginnen mit if gefolgt von einem in eine Klammer eingeschlossenen Wahrheitsausdruck. Folgt ein Befehl kann dieser Direkt danach folgen, wenn nicht müssen die Werte in geschweifte Klammern. Nach dem else-Schlüsselwort können Befehle folgen, die ausgeführt werden sollen, wenn der Warheitswert false ist.

class Weiche
{
    Schnittstelle tischfeld;
    int anzahlIrgendetwas;
    bool tasteGedrueckt;
    
    void init()
    {
         anzahlIrgendetwas=0;
         tasteGedrueckt=false;
         tischfeld.setWert("besetzt",1);
    }
    void on_tischfeld_wht(int wert)
    {
         tasteGedrueckt=true;
         anzahlIrgendetwas=wert;
         if (wert > 26)
           beliebigeMethode(27,false);
         else
         {
           beliebigeMethode(wert,true);
           tischfeld.setWert("nochetwas",1);
         }
    }
    int beliebigeMethode(int wert, bool andererWert)
    {
         tasteGedrueckt = ((wert == 1)||(wert > 15))&&(!andererWert);
         tischfeld.setWert("irgendwas",41);
         //Rest der Methode.
    }
}

Die Ausführung von (void-)Methoden kann mithilfe von return; abgebrochen werden. Methoden, die nicht void sind, können wie Varriablen verwednet werden. Sie müssen ein return gefolgt von dem Rückgabewert enthalten.

class Weiche
{
    Schnittstelle tischfeld;
    int anzahlIrgendetwas;
    bool tasteGedrueckt;
    
    void init()
    {
         anzahlIrgendetwas=0;
         tasteGedrueckt=false;
         tischfeld.setWert("besetzt",1);
    }
    void on_tischfeld_wht(int wert)
    {
         tasteGedrueckt=true;
         anzahlIrgendetwas=wert;
         if (wert > 26)
           beliebigeMethode(27,false);
         else
         {
           beliebigeMethode(wert,true); //Kommentar
           tischfeld.setWert("nochetwas" /*Kommentar*/,beliebigeMethode(0,false));
           return;
         }
    }
    int beliebigeMethode(int wert, bool andererWert)
    {
         tasteGedrueckt = ((wert == 1)||(wert > 15))&&(!andererWert);
         tischfeld.setWert("irgendwas",41);
         return 32;
    }
}

Bestimmte Methoden (im obigen Fall init und die on-Methode) werden automatisch von StellSi aufgerufen. Werden Varriablen innerhalb einer Methode deklariert, gelten Sie nur bis zum Ende des aktuellen Bereiches (schließende }, wenn zwischen der } noch ein paar { aufgemacht wurden zählen die zugehörigen } natürlich nicht dazu).

Hinweis: Gibt es zwei Weichen, die beide auf der Klasse Weiche aufbauen, so sind diese Unhabhängig voneinander. Die beiden Weichen arbeiten mit verschiedenen Instanzen der Klasse.

Datentypen

  • bool Warheitswert, true oder false
  • int Ganzzahl, vorzeichenbehaftet, 32 Bit. Weitere Ganzzahltypen sind int8, int16, int64, uint8, uint16, uint, uint64
  • float Gleitkommazahl vorzeichenbehaftet. Weitere Gleitkommazahl ist double.
  • string Zeichenfolge.
  • Schnittstelle Passt zu dem StellSi-Typ Schnittstelle.
    • Methoden:
      • void sendSignal(string signalname, string wert); Einmaliges Ereignis (z.B. Zählwerk)
      • void sendSignal(string signalname, int wert);
      • void setWert(string signalname, string wert); Dauerhafteter Zustand (z.B. Lampe an/aus)
      • void setWert(string signalname, int wert);
      • int sendSignalSyncron(string signalname, string wert); Geht an eine Schnitstelle und gibt den Wert zurück, den diese Schnittstelle zurückgibt.
      • int sendSignalSyncron(string signalname, int wert);
    • Ruft auf:
      • void on_%Name der Schnittstellenvarriable%_%Name des Signals%(string wert); Wird aufgerufen, wenn ein Signal oder ein Wert gesendet wurde, und der Name der Variablen kein _ enthielt.
      • void on_%Name der Schnittstellenvarriable%_%Name des Signals%(int wert);
      • int on_%Name der Schnittstellenvarriable%_%Name des Signals%(string wert);
      • int on_%Name der Schnittstellenvarriable%_%Name des Signals%(int wert);
    • Besonderheiten:
      • Schnittstelle freie; wird später mal die Signale der Freien Eingangslogiken übernehmen. Vermutlich im Moment noch nicht funktionsfähig.
  • Timer
    • Methoden:
      • void start(int wert, int dauer);
      • void start(int wert, int dauer, bool autorepeat);
      • void stop();
    • Ruft auf:
      • void _%Name der Schnittstellenvarriable%();
  • VerschlussFahrstrasse
    • Methoden:
      • int verschliesse(const string typ_fahrstrasse, const int level);
      • int pruefe(string typ_fahrstrasse, int level);
      • void stelle(string typ_fahrstrasse, int level);
    • Ruft auf:
  • VerschlussElement
    • Methoden:
      • void setLevelgrenzen(string typ_fahrstrasse, string stellung, int minlevel, int maxlevel);
      • int verschliesse(string typ_fahrstrasse, int level);
      • int pruefe(string typ_fahrstrasse, int level);
      • void stelle(string typ_fahrstrasse, int level);
    • Ruft auf: