Grundlagen Webservice API am Beispiel von VBA
Für die Formatierung der Zeichenkette wird das XML-Format nach den Spezifikationen des SOAP-Protokolls verwendet. Als Beispiel soll die folgende Abfrage dienen:
<Body>
</Body>
Ein typisches Element der XML-Formatierung ist der Beginn eines Abschnitts mit dem Zeichen "<". Danach folgt ein Bezeichner und, falls keine weiteren untergeordneten Elemente folgen, wird der Abschnitt mit "/>" beendet. Ein Beispiel ist die dritte Zeile:
Wenn Unterelemente vorliegen, wird mit "<", dem Befehl und ">" begonnen und den Abschluss bilden "</", der Befehl und ">". Das passende Beispiel ist der Abschnitt "Body":
<Body>
</Body>
Die Formatierung mit Leerzeichen und Zeilenumbrüchen dient hier nur der Veranschaulichung. Für die Übertragung ist diese nicht erforderlich. Die Elemente "Body" und "Envelope" sind Standardelemente für die Übertragung und werden für jeden Befehl verwendet.
Alle verfügbaren Befehle können mithilfe der WSDL-Schnittstelle ausgelesen werden. Es gibt Software, mit deren Hilfe daraus Listen erzeugt werden können. Eine solche Software ist beispielsweise SoapUI. Für die API von RFEM 6 gibt es zwei Listen, die Befehle für die Anwendung und die für das Modell. Beide Listen können am Ende dieses Beitrags heruntergeladen werden.
Da Befehle über HTTP gesendet werden, werden zum Ansprechen URL-Adressen benötigt. Die Standardadresse der Anwendungen RSTAB/RFEM ist "http://localhost:8081/" und kann in den Einstellungen im Programm geändert werden. Geöffnete Modelle erhalten aufsteigende Adressen, sodass das erste geöffnete Modell die Adresse "http://localhost:8082/" hat. Um die Adresse des aktiven Modells zu erhalten, wird der Befehl "get_active_model" gesandt. Eine entsprechende Antwort von RFEM 6 sieht so aus:
http://127.0.0.1:8082/
Die zusätzlichen Details des "Envelope"-Abschnitts (deutsch: Umschlag/Briefumschlag) sowie die vorangestellte Zeile "<?xml version="1.0"?>" sollen zunächst die verwendeten Standards aufzeigen und hier nicht weiter erörtert werden. Zu erkennen ist in jedem Falle, dass wieder die Elemente "Envelope" und "Body" verwendet werden. Innerhalb von "Body" steckt die Antwort von RFEM 6 durch den Befehlsnamen "get_active_model" und dem angehängten Wort "Response". Inhalt dieser Antwort ist ein Wert ("value") und zwar die Adresse des aktiven Modells. Zudem wird RFEM jetzt für weitere Zugriffe gesperrt.
Im folgenden Beispiel soll ein Stab mit zwei Knotenlagern und einer Last angelegt werden. Um über VBA mit RFEM kommunizieren zu können, werden die folgenden Objekte benötigt:
request As MSXML2.XMLHTTP60
response As MSXML2.DOMDocument
Das Objekt XMLHTTP60 hat eine integrierte Funktion zum Senden einer HTTP-Anfrage an eine URL und wird daher für die Anfrage verwendet. Die Antwort kann dann mithilfe des DOMDocuments ausgewertet werden. Das folgende Beispiel vereint die zuvor gezeigte Anfrage "get_active_model" mit den unter VBA verwendeten Befehlen:
' get active model url with "get_active_model" command
str_envelope =
"" & _
" <Body>" & _
" " & _
" </Body>" & _
" "
' open request and send it
request.Open "Post", "http://localhost:8081/", False
request.Send (str_envelope)
' get response and transform it to an xml-object
response.LoadXML (request.responseText)
Zuerst wird die Anfrage im XML-Format in der Variable "str_envelope" gespeichert und über die Methode "Open" der Variable "request" die Anfrage an RFEM geöffnet. Über die Methode "Send" kann jetzt der Inhalt der Variable "str_envelope" verschickt werden. Die Antwort kann danach über die Methode "ResponseText" abgerufen werden. Im konkreten Fall wird diese über die Methode "LoadXML" der Variable "response" direkt eingelesen.
Die Variable "response" vom Typ DOMDocuments hat die Methode LoadXML und kann damit die XML-Formatierung erkennen. Der Vorteil besteht darin, dass der Typ DOMDocuments auch die Methode GetElementsByTagName bereitstellt. Damit lassen sich direkt Elemente aus dem Code extrahieren. Im Folgenden wird der vorige Code noch erweitert, sodass die URL-Adresse des Modells zur Verfügung steht:
' get http-status
status = request.status
If status <> "200" Then
MsgBox "get_active_model: Sending not successful - " & response.Text
Exit Sub
End If
url_model = response.GetElementsByTagName("value")(0).Text
Bevor die URL ausgelesen wird, kann noch der Status der Antwort überprüft werden. Es handelt sich um standardisierte HTTP-Statuscodes. Der Status "200" bedeutet, dass die Übertragung "OK" war. Nach dieser Abfrage wird in der Zeichenkette url_model die URL des Modells gespeichert. Dazu wird aus der XML-Antwort das Element "value" gesucht. Wenn eine Antwort mehrere Elemente enthält, werden alle Werte innerhalb des Abschnitts "value" abgelegt, sodass hier keine Auswertung mit dem Bezeichner "value" möglich ist, sondern die Unterelemente von "value" angesprochen werden. Mehr dazu im Praxisbeispiel. Im Fall der Modelladresse ist der einzige zurückgegebene Wert die URL, sodass "value" hier zum Erfolg führt.
Praxisbeispiel in VBA
Da nun alle Basiselemente bekannt sind, folgt ein einfaches Beispiel. Es soll ein Träger auf zwei Stützen erzeugt werden, auf dem eine Stablast aufgebracht werden kann.
Zuerst werden die bereits vorgestellten Variablen definiert und initialisiert:
' define variables
Dim request As MSXML2.XMLHTTP60
Dim response As MSXML2.DOMDocument60
Dim str_envelope As String
Dim url_app As String
Dim url_model As String
' init variables
Set request = New MSXML2.XMLHTTP60
Set response = New MSXML2.DOMDocument60
With response
.async = False
.preserveWhiteSpace = False
.validateOnParse = False
.resolveExternals = False
' Use full XPath functionality
.SetProperty "SelectionLanguage", "XPath"
' Add specific Namespaces to work with Paths
.SetProperty "SelectionNamespaces", "xmlns:soap=""http://www.w3.org/2003/05/soap-envelope"" " & _
"xmlns:xsd=""http://www.dlubal.com/rfem.xsd"" " & _
"xmlns:n1=""urn:schemas-microsoft-com:rowset"" " & _
"xmlns=""http://www.dlubal.com/rfem.xsd"" "
End With
url_app = "http://localhost:8081/"
Neben den Variablen "request" und "response" werden die Zeichenkette "str_envelope" für die Anfrage und "url_app" und "url_model" für die Adressen von Anwendung und Modell angelegt. Bei der Initialisierung können die bekannten Spezifikationen des SOAP-Protokolls zur Auswertung der XML-Formatierung der Antwort übergeben werden. Die Adresse des Modells wird später geholt, aber die Adresse der Anwendung muss angeben werden. Wie bereits zuvor erwähnt ist die Standardadresse "http://localhost:8081/" anzugeben.
Im nächsten Schritt soll die Verbindung zur Anwendung getestet werden. Für diesen Test werden über den Befehl "get_information" die Standardinformationen der Anwendung abgefragt:
' check application url with command "get_information"
str_envelope = "" & _
" " & _
" "
' open request and send it
request.Open "Post", url_app, False
request.Send (str_envelope)
' get response and transform it to an xml-object
response.LoadXML (request.responseText)
' get http-status
status = request.Status
If status <> "200" Then
MsgBox "get_information: Sending not successful - " & response.Text
Exit Sub
End If
' read application information
Dim str1 As String
str1 = ""
str1 = str1 & response.GetElementsByTagName("name")(0).Text & vbLf
str1 = str1 & response.GetElementsByTagName("type")(0).Text & vbLf
str1 = str1 & response.GetElementsByTagName("version")(0).Text & vbLf
str1 = str1 & response.GetElementsByTagName("language_name")(0).Text & vbLf
str1 = str1 & response.GetElementsByTagName("language_id")(0).Text
MsgBox str1, vbInformation, "Response to ""get_information"" request"
Wie bereits im ersten Teil beschrieben, wird zuerst die XML-formatierte Anfrage vorbereitet und in "str_envelope" gespeichert. "request.Open" öffnet die Verbindung zur Anwendung. Das Schlüsselwort "Post" steht dabei für das Senden der Anfrage. Der dritte Parameter steht auf "true" und damit wird eine synchrone Übertragung durchgeführt. Im Anschluss sendet "request.Send" die vorbereitete Zeichenkette.
Nach der Übertragung wird die Antwort in "response" gespeichert und mit "request.Status" überprüft, ob die Anfrage erfolgreich war. Der Status wird dabei von RFEM vergeben, sodass dieses bei einer fehlerhaften Anfrage, zum Beispiel einem unbekannten Befehl, einen Fehler zurückgibt. Wenn der Status nicht "200" ist, wird das Programm abgebrochen und der Fehler in einem Fenster (MsgBox) ausgegeben.
Wenn keine Fehler entstanden sind, können jetzt über "GetElementsByTagName" die verschiedenen übertragenen Informationen ausgelesen werden. Im konkreten Beispiel werden die Informationen dann in einem Fenster dargestellt.
Die folgenden Elemente weisen große Ähnlichkeiten auf, daher wird nur auf Besonderheiten eingegangen (der komplette Quellcode steht zum Download zur Verfügung). Für den Aufbau eines Trägers auf zwei Stützen mit einer Stablast werden folgende Funktionen benötigt:
- Knoten – set_node
- Linie – set_line
- Material – set_material
- Querschnitt – set_section
- Stab – set_member
- Knotenlager – set_nodal_support
- Berechnungsparameter – set_static_analysis_settings
- Lastfall – set_load_case
- Stablast – set_member_load
Die Funktion "set_node" hat, wie die meisten anderen, viele Parameter, welche aber im Normalfall nicht benötigt werden. In der bereits erwähnten Befehlsliste des RFEM-Modells kann die Vielfalt der Parameter eingesehen werden. Wichtig sind vor allem die Parameter, welche nicht den Vermerk "optional" haben, da diese in jedem Fall ausgefüllt werden müssen. Im Beispiel werden folgende Parameter übergeben:
begin_modification (url_model)
' set node 1 on [0,0,0] with "set_node" command
str_envelope =
"" & _
"<Body>" & _
"" & _
"" & _
"1 " & _
"TYPE_STANDARD " & _
"0 " & _
"0 " & _
"0 " & _
" " & _
" " & _
"</Body>>" & _
" "
Einzig die Knotennummer ist hier nicht optional und der Rest kann vergeben werden. In der Befehlsliste werden neben den möglichen Parametern auch Auflistungen für Typen aufgezeigt. Im konkreten Fall sind derzeit fünf verschiedene Typen möglich. Es wurde der Standardtyp "TYPE_STANDARD" gewählt. Der hier gezeigte erste Knoten wird an der Stelle (0;0;0) erstellt, der zweite Knoten bei (5,5;0;0). Die Werte bei Kommazahlen sehen dann wie folgt aus:
…
"" & _
"2 " & _
"TYPE_STANDARD " & _
"5.5 " & _
"0 " & _
"0 " & _
" " & _
…
Eine weitere Besonderheit stellen Listen dar. Die Linie braucht zwei Knoten, deren Nummern als Liste übergeben werden können. Die Elemente einer Liste, wie hier "definition_nodes", werden durch Leerzeichen getrennt:
…
"" & _
"" & _
"1 " & _
"TYPE_POLYLINE " & _
"1 2 " & _
" " & _
" " & _
…
Um den Stab anlegen zu können, muss noch ein Querschnitt angelegt werden, welcher wiederum ein Material benötigt. Querschnitte und Materialien können aus der internen Datenbank genutzt werden. Darum genügt die Angabe eines bekannten Bezeichners. Für das Material ist der Bezeichner "S235" und der Querschnitt hat den Namen "IPE 300":
…
"" & _
"" & _
"1 " & _
"1 " & _
"TYPE_STANDARDIZED_STEEL " & _
"IPE 300 " & _
" " & _
" " & _
…
Zur Überprüfung, ob ein Name wie "IPE 300" gültig ist, kann die Eingabe in der grafischen Oberfläche genutzt werden.
Für die Eingabe des Stabes an sich werden keine weiteren Kenntnisse benötigt, für die Eingabe eines festen Lagers muss aber eine "unendliche" Federsteifigkeit definiert werden. Für die Übergabe wird das Schlüsselwort "INF" verwendet:
…
"" & _
"" & _
"1 " & _
"1 " & _
"INF " & _
"INF " & _
"INF " & _
"INF " & _
"0 " & _
"INF " & _
" " & _
" " & _
…
Das Anlegen des Lastfalls und der Berechnungsparameter benötigt keine zusätzlichen Kenntnisse. Die letzte Besonderheit stellt ein zusätzlicher Wert beim Anlegen der Last dar, da er außerhalb des Bereichs "…
"