Allgemeine Server - Projektstruktur

Alle Server-Beispielprojekte folgen, ähnlich wie die Client-Beispielprojekte, ebenfalls einer allgemeinen Struktur. Im Gegensatz zum Client wird beim Server die Verbindung nicht aktiv Serverseits aufgebaut. Nach dem Programmstart wartet der Server auf einen Verbindungswunsch eines Clients und akzeptiert oder lehnt diesen ab. Außerdem muss es für den Server möglich sein, Verbindungen zu mehreren Clients aufzubauen.

Daraus ergibt sich eine andere Server-Projektstruktur als beim Client. Die Grundstruktur der TwinCAT IEC 61850 Server-Beispielprojekte basiert auf der automatisch vom TwinCAT Telecontrol Configurator generierten SPS-Projektstruktur. Der TwinCAT Telecontrol Configurator verwendet bei der Generierung der Solution wiederum das „TwinCAT XAE Project (XML format)“ als Vorlage. Die in den Beispielen kommunizierten Datenmodelle spiegeln unterschiedliche IEC 61850 Server wider. Sie unterscheiden sich von Beispiel zu Beispiel und liegen dem Quellcode als ICD-Dateien bei. Die ICD-Dateien können auch von einer Third-Party-Software zur Simulation verwendet werden.

Aufbau eines TwinCAT IEC 61850-SPS-Server-Projekts:

Allgemeine Server - Projektstruktur 1:

Der generierte Solution-Name (wenn nicht anders angegeben) entspricht dem TwinCAT Telecontrol Configurator Projektnamen. Der automatisch generierte TwinCAT SPS-Projektname (wenn nicht anders angegeben) hat wiederum folgenden Aufbau: „[Projektname]_[IEDName]_Server“.

Standardmäßig besitzt jedes Beispielprojekt einen „DUTs“, „GVLs“ und „POUs“ Ordner. In dem „GVLs“-Ordner ist eine globale Variablenliste (GVL) mit dem Namen: „TcTelecontrol“ hinterlegt. In dieser globalen Variablenliste (siehe Quellcode unten) werden folgende Funktionsbausteine instanziiert und initialisiert:

Außerdem wird dort auch die, während der Codegenerierung verwendete Codeversion und die verwendete Version des TwinCAT Telecontrol Configurator abgelegt.

Namensraum: TcTelecontrol

Typ: Globale Variablenliste (GVL)

VAR_GLOBAL
    ipCreator                 : I_AcsiCodeCreatorClass := GVL_AcsiVars.Creator.SetCodeRev(codeRev:=2).SetGuiVer(major:=1, minor:=1, build:=94, revision:=1);
    fb[IEDName]               : FB_IED_[IEDName];
    fb[IEDName]Server         : FB_iec61850ServerClass := (ipIED:=fb[IEDName], settings:=(bEnable:=TRUE, sLocalHost:='127.0.0.1'));
    fb[IEDName]ServerSession1 : FB_[IEDName]ServerSession := (fbConnection:=(ipServer:=fb[IEDName]Server, settings:=(bEnable:=TRUE)));
    fb[IEDName]Gse            : FB_[IEDName]Gse := (fbAdapter:=(ipIED:=fb[IEDName], settings:=(sMulticastAddr:='01-0C-CD-01-00-00', eDispatchMode:=E_GseDispatchMode.NonPromiscuous)));
END_VAR

Im „POUs“-Ordner befindet sich ein weiterer Ordner: „[IEDName]“, der die gesamte hierarchische Struktur des IED-Datenmodels als Funktionsbausteine beinhaltet. In diesem Ordner befindet sich auch der IED-Datenmodell-Baustein, der in der globalen Variablenliste instanziiert wird und bereits erwähnt wurde. Auf der gleichen Ebene liegt der Server-Session-Baustein: „FB_[IEDName]ServerSession“, welcher den Verbindungsaufbau und den Datenaustausch mit einem IEC 61850 Client realisiert.

Das TwinCAT SPS-Projekt enthält standardmäßig ein „MAIN“-Programm. Dieses wird zyklisch von einer TwinCAT Task aufgerufen und ruft wiederum das Programm „P_IEC61850MAIN“ auf. Das Programm „P_IEC61850MAIN“ kapselt den Aufruf des Server-, Server-Session- und des optionalen Gse-Bausteins, trennt die IEC 61850-Kommunikation von dem restlichen SPS-Maschinenprogramm.

PROGRAM MAIN
VAR
END_VAR
P_IEC61850MAIN();
PROGRAM P_IEC61850MAIN
VAR
END_VAR
fb[IEDName]Server.Execute();
fb[IEDName]ServerSession1();
fb[IEDName]Gse();

In dem FB_[IEDName]ServerSession-Baustein befindet sich eine Statemachine, von der die grundlegenden Zustände in jedem Server-Beispiel genutzt werden (siehe Quellcode unten). Der Server-Session-Baustein ist verantwortlich für den Verbindungsaufbau und Datenaustausch zu einem einzelnen Client. Bei mehreren gleichzeitigen Clientverbindungen werden mehrere Instanzen von diesem Baustein benötigt und instanziiert.

State 0 (Init state): Die Statemachine befindet sich in diesem Zustand, sobald das SPS-Programm gestartet wurde. Hier (und im State 1) werden Befehle zur Verwaltung einer -Server—Client-Verbindung behandelt. Im Regelfall verbleibt der Server-Session-Baustein in diesem Zustand und wartet auf einen Verbindungswunsch eines Clients. Der Server baut dann eine Verbindung auf, sobald der Verbindungswunsch erkannt wurde. Dies geschieht automatisch und benötigt keine weiteren Befehle seitens der SPS-Applikation. Falls der Server-Verbindung zum Client hergestellt hat, wird die Statemachine in den Zustand der Datenübertragung wechseln (State 10).

Es ist außerdem möglich, eine bereits hergestellte Verbindung zu schließen. Gesteuert wird dies über zwei boolesche Variablen. Diese Variablen, wenn sie gesetzt sind, aktivieren die entsprechenden Befehle (in diesem Fall sind es einmalige Methodenaufrufe am Server-Session-Baustein).

Die zuvor aufgezählten Methoden benötigen für die Abarbeitung länger als einen SPS-Zyklus. Aus diesem Grund wechselt die Statemachine in einen Warte-Zustand (State 1), in dem auf die Beendigung des aktivierten Befehls gewartet wird.

State 1 (Wait State): In diesem Zustand verweilt der Server-Session-Baustein, bis die Befehlsabarbeitung zur Verwaltung der Server-Client-Verbindung nicht mehr beschäftigt (busy) ist. Solange die Verbindung abgebaut oder abgebrochen wird, befindet sich die Statemachine im State 1. Sobald der Befehl erfolgreich abgearbeitet wurde, wird die Statemachine zurück in den State 0 (Init State) versetzt.

State 10 (Data exchange): Wenn die Statemachine in diesem Zustand ist, dann ist die Server-Verbindung zum Client bereits erfolgreich hergestellt worden. Der Server-Session-Baustein ist bereit für die Datenübertragung zum Server. Die Server-Datenübertragung zum Client geschieht automatisch im Hintergrund und muss nicht seitens der SPS-Applikation initiert werden. Es ist der Client, der durch einen Request eine Datenübertragung im Server auslöst.

Bei einer aktiven Verbindung wechselt die Statemachine zwischen dem State 0 und 10. Die Statemachine wird wieder in den State 0 versetzt, um auf Änderungen im Client-Server-Verbindungstatus zu reagieren und sie im State 0 zu behandeln.

State 100 (Error state): Sobald ein Fehler bei der Aktivierung oder Abarbeitung eines Befehls auftritt, wird die Statemachine in den State 100 versetzt. Hier wird der Fehler geloggt und die Statemachine zurück in den State 0 versetzt.

FUNCTION_BLOCK FB_[IEDName]ServerSession
VAR_INPUT
    fbConnection     : FB_iec61850ConnectionClass := (ipAbortInd:=THIS^, ipAssociateInd:=THIS^, ipReleaseInd:=THIS^);
END_VAR
VAR
    _bAbort          : BOOL;
    _bDisconnect     : BOOL;
    state            : BYTE;
    eState           : E_AsyncEnvironmentState;
    bBusy            : BOOL;
    bSuccess         : BOOL;
    ipResult         : I_AsyncServiceResultClass;
    sLastErrorResult : T_MaxString;
    fbAbortReason    : FB_ServiceErrorClass := (stError:=SUCCESS_EVENT);
    sLastAbortReason : T_MaxString;
END_VAR
fbConnection.Execute();
eState:= fbConnection.eState;

CASE state OF
    0:
        IF _bAbort THEN
            _bAbort:= FALSE;
            bSuccess:= fbConnection.AbortReq(ipReason:=fbAbortReason, ipSink:=0, ipResult=>ipResult);
            state:= SEL(bSuccess, 100, 1);
        ELSIF eState = E_AsyncEnvironmentState.Established AND _bDisconnect THEN
            _bDisconnect:= FALSE;
            bSuccess:= fbConnection.ReleaseReq(ipSink:=0, ipResult=>ipResult);
            state:= SEL(bSuccess, 100, 1);
        ELSIF eState = E_AsyncEnvironmentState.Established THEN
            state:= 10;
        END_IF
        _bDisconnect:= FALSE;
    1:
        IF ipResult <> 0 THEN
            ipResult.Execute();
            IF NOT (bBusy:=ipResult.IsBusy()) THEN
                state:= SEL(ipResult.IsCompleted(), 100, 0);
            END_IF
        END_IF
    10:
        state:= 0;
    100:
        state:= 0;
        IF ipResult <> 0 THEN
            sLastErrorResult:= ipResult.Dump();
        END_IF
END_CASE

GOOSE-Publisher (optional)

TwinCAT Telecontrol Configurator kann in einem Server-Projekt, während der SPS-Code Generierung, den SPS-Code für einen GOOSE-Publisher ebenfalls generieren (siehe Codebeispiel unten). Dies ist aber nur dann möglich, wenn der Anwender vorher die GOOSE-Komponenten wie z. B. GoCBs (goose control blocks) im TwinCAT Telecontrol Configurator erstellt oder aus einer SCL-Datei (z. B. ICD-Datei) importiert hat. Standardmäßig wird bei der Codegenerierung ein Baustein mit dem Namen: „FB_[IEDName]Gse“ instanziiert und der globalen Variablenliste „TcTelecontrol“ hinzugefügt. Dieser Baustein stellt die Verbindung zwischen einem Netzwerkadapter des TwinCAT Steuerungsrechners, dem IED-Datenmodell und der GOOSE-Konfiguration in den GoCBs her. Die GoCBs werden in dem IED-Datenmodell (normalerweise im LLN0) instanziiert. Jeder GoCB besitzt ein Baustein-Unterelement mit dem Namen: „Publisher“. Über die „Publisher“-Methodenaufrufe kann das Publishing aus dem SPS-Code gestartet („Start“) oder gestoppt werden („Stop“). Defaultmäßig wird das Publishing beim SPS-Programmstart für alle GoCBs gestartet. Dies wird durch die mit „TRUE“ initialisierte „bStart“-Variable gesteuert. Über eine steigende Flanke an der „bStop“-Variablen kann das Publishing für alle GoCBs gestoppt werden. Die über diese Methoden abgesetzten Publisher-Befehle werden sofort ausgeführt, ohne Wartezyklen oder weitere States die nötig sind, um die Befehlsabarbeitung abzuschließen. Der hier beschriebene „Publisher“ liest die Konfiguration und aktualisiert zwar den Status des GoCBs (Attribute „GoEna“ wird z. B. auf „TRUE“ oder „FALSE“ gesetzt), er nutzt aber nicht die Client-Server-Dienste wie „SetGoCBValues“ oder „GetGoCBValues“ um den Publisher zu starten oder zu stoppen. D.h. der generierte Code implementiert bereits einen Publisher der z. B. im ersten SPS-Zyklus oder aus dem SPS-Code zum beliebigen Zeitpunkt gestartet bzw. gestoppt werden kann. Die benötigten GoCB-Konfigurationseinstellungen (GoCB-Attributwerte) können über Initialisierungswerte vorgenommen werden. Die Konfiguration der GoCBs kann aber bereits in dem TwinCAT Telecontrol Configurator geschehen. Die Initialisierungswerte werden dann während der Codegenerierung automatisch generiert und zugewiesen. Wenn der Publisher gestartet wurde und die Konfiguration des GoCBs und des Netzwerkadapters eine Übereinstimmung ergibt, dann beginnt der Publisher sofort mit dem Versenden der ersten GOOSE-Frames (inklusive der Framewiederholungen). Die „Update“-Methode hat eine besondere Bedeutung. Jedes Mal wenn sie aufgerufen wird, versendet der „Publisher“ sofort ein neues GOOSE-Frame (und automatisch neue Framewiederholungen). D.h. die Applikation kann alle relevanten GOOSE-Dataset-Daten im IED-Datenmodell zuerst setzen und dann das Versenden der geänderten Dataset-Daten mit dem „Update“-Methodenaufruf veranlassen. Die „Execute“-Methode muss in der übrigen Zeit zyklisch aufgerufen werden. Sie ist für das Versenden der Framewiederholungen und für die Aktualisierung der Statusinformation im GoCB verantwortlich.

FUNCTION_BLOCK FB_[IEDName]Gse IMPLEMENTS I_GseLinkStatusEventSink
VAR_INPUT
    fbAdapter   : FB_GseAdapterClass := (ipLinkStatus:=THIS^);
END_VAR
VAR
    eLinkStatus : E_GseLinkStatus;
    bSuccess    : BOOL;
    ipError     : I_ServiceErrorClass;
    bStart      : BOOL := TRUE;
    bStop       : BOOL;
    bUpdate     : BOOL;
END_VAR
bSuccess:= fbAdapter.Execute(ipError=>ipError);

IF bStart THEN
    bStart:= FALSE;
    bSuccess:= fb[IEDName].IEDLD1.LLN0.gocb01.Publisher.Start(ipAdapter:=fbAdapter, ipError=>ipError);
    bSuccess:= fb[IEDName].IEDLD1.LLN0.gocb02.Publisher.Start(ipAdapter:=fbAdapter, ipError=>ipError);
    bSuccess:= fb[IEDName].IEDLD1.LLN0.gocb03.Publisher.Start(ipAdapter:=fbAdapter, ipError=>ipError);
ELSIF bStop THEN
    bStop:= FALSE;
    bSuccess:= fb[IEDName].IEDLD1.LLN0.gocb01.Publisher.Stop(ipError=>ipError);
    bSuccess:= fb[IEDName].IEDLD1.LLN0.gocb02.Publisher.Stop(ipError=>ipError);
    bSuccess:= fb[IEDName].IEDLD1.LLN0.gocb03.Publisher.Stop(ipError=>ipError);
ELSIF bUpdate THEN
    bUpdate:= FALSE;
    bSuccess:= fb[IEDName].IEDLD1.LLN0.gocb01.Publisher.Update(ipError=>ipError);
    bSuccess:= fb[IEDName].IEDLD1.LLN0.gocb02.Publisher.Update(ipError=>ipError);
    bSuccess:= fb[IEDName].IEDLD1.LLN0.gocb03.Publisher.Update(ipError=>ipError);
ELSE
    bSuccess:= fb[IEDName].IEDLD1.LLN0.gocb01.Publisher.Execute(ipError=>ipError);
    bSuccess:= fb[IEDName].IEDLD1.LLN0.gocb02.Publisher.Execute(ipError=>ipError);
    bSuccess:= fb[IEDName].IEDLD1.LLN0.gocb03.Publisher.Execute(ipError=>ipError);
END_IF

Der GSE-Baustein implementiert die „I_GseLinkStatusEventSink“-Schnittstelle. Die Methode: „OnLinkStatusChange“ gehört zu dieser Schnittstellenimplementierung und wird immer dann aufgerufen, wenn sich der Status der Netzwerkverbindung (am Netzwerkadapter) ändert. Die SPS-Applikation kann z. B. den Netzwerkverbindungsstatus via „eLinkStatus“-Variable abfragen oder überprüfen.

METHOD OnLinkStatusChange
VAR_INPUT
    ipAdapter : I_GseAdapterClass;
    eStatus   : E_GseLinkStatus;
END_VAR
VAR
END_VAR
eLinkStatus:= eStatus;

Im Projektbaum unter dem Zweig I/O-Device finden Sie eine Netzwerkadapterinstanz mit dem Namen „GSE (RT-Ethernet Adapter)“. Diese Adapterinstanz muss entsprechend konfiguriert werden, d.h. die I/O-Konfiguration muss an die vorhandene Hardware und auf die Zielplattform, auf der das Projekt laufen soll, angepasst werden.
Eine erneute I/O-Konfiguration ist auch dann nötig, wenn Sie die Zielplattform wechseln. Diese Konfiguration muss manuell in TwinCAT XAE vorgenommen werden. Zusätzlich zu der I/O-Konfiguration des Netzwerkadapters muss ein Link zwischen dem Netzwerkadapter und den SPS-Bausteinen für die Goose-Kommunikation hergestellt werden. Mit dem Link können die vom Netzwerkadapter empfangenen Daten an die Instanz des Funktionsbausteins: „FB_[IEDName]Gse“ weitergeleitet werden. In umgekehrter Richtung kann die Instanz des Funktionsbausteins „FB_[IEDName]Gse“ die zu sendenden Daten an den Netzwerkadapter weiterleiten.

Hier finden Sie weitere Informationen: RT – Ethernet Adapter Konfiguration.