HomePortal InfoOutreachesWebservicesBlogContact

Introduction

In this section we would like to go more in depth to see what happens behind the scenes of the portal focusing on some architectural aspects.

The purpose is to emphasize other potential uses of our SOA (Service Oriented Architecture), encouraging users with specific requirements to address directly the backbone services.

Typically users are interested only in the upper layer of the architecture, in our instance the portal, which acts as a human interface aggregating contents coming from several providers and presenting them in an interactive way. But there are some situations where a machine to machine communication is needed, for example when an user has his own desktop application or a job that runs at fixed time intervals and wants to connect directly to the data sources.

Our architecture has been thought and designed in a way to be as more open, scalable, flexible and standard compliant as possible.

The main services running in our distributed environment are 4 and each of them has a specific purpose and task acting as a data/metadata provider or giving some computational facilities:

  • The Seismolink WS (http://www.orfeus-eu.org/wsdl/seismolink/seismolink.wsdl)is developed and maintained at ORFEUS and is responsible for all the informations related to the continuous data. It is built on top of the Arclink middleware, thus providing what is available within the middleware itself plus some some additional advantages. In fact the service is firewall safe, using a standard http transport instead of tcp coupled to specific custom ports. Moreover the protocol itself is simplified and described through a standard representation (WSDL), the user doesn't have to learn low level communication calls to get the results, but they are all wrapped into a single request. The service provide also a transparent routing to the node of interest, but still keeping clear the provenance of the data using an uri naming that describes the resource. Another relevant feature is the scaling, in case of a new node joining the Arclink network, its data will flow automatically through the service without the user even noticing it. In a few words we placed a level of abstraction in order to facilitate the interoperability among automatic systems.
  • The QuakeML WS (http://www.seismicportal.eu/services/ws/quakeml?wsdl) is deployed in Paris and is under the responsibility of EMSC. Its main aim is to provide event parametric data. This data are represented using the quakeML format which is becoming more and more popular in the seismological community.
  • The SMI-RDF WS and the SMI-SPARQL end-point are the access point to our RDF repository, which is hosted at ORFEUS and contains metadata describing most part of the entities involved in our processes. For example there are representations of different kind of resources: Community resources like People and Organizations involved in the project, or Data resources like the Arcklink Nodes, the user generated Datasets and so on. Everything is coded using RDF/XML and standard vocabularies.
  • The Taup WS (http://http://www.orfeus-eu.org/wsdl/taup/taup.wsdl), running at ORFEUS, offers the possibility to compute arrival times using a few default velocity models or one provided by the user itself.


Seismolink WS

We're going to illustrate here the methods available within one of the core services giving also some examples of requests and expected responses.

As mentioned before this service is based on the Arclink middleware thus providing information such as networks, stations inventory and waveform data.

Just a note on the following examples: to have a visual representation of the requests/responses and also to test the service we use a client, soapUI (www.soapui.org), which is only one of the many free available tools, very useful when working with webservices. Once fed with the service descriptor (WSDL), it automatically recreates all the methods and the end-points. Of course in a real life use-case, you will have to develop your own client using the technology and language that better meet your requirements, on this topic we give some advices in the references below.

Let's have a look now to the first method: getInventory, which provides, given a timespan and/or a bounding box, information about the available networks and stations in that particular space/time region.

getInventory request

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:urn="urn:xml:seisml:orfeus:neries:org" xmlns:gml="http://www.opengis.net/gml" xmlns:xlin="http://www.w3.org/1999/xlink" xmlns:ogc="http://www.opengis.net/ogc">
<soap:Header/>
<soap:Body>
<urn:getInventory Instruments="?" ModifiedAfter="?">
<urn:UserToken>
<urn:email>?</urn:email>
<!--Optional:-->
<urn:password>?</urn:password>
<!--Optional:-->
<urn:label>?</urn:label>
<!--Optional:-->
<urn:locale>?</urn:locale>
</urn:UserToken>
<!--1 or more repetitions:-->
<urn:StationIdentifierFilter>
<urn:TimeSpan>
<urn:TimePeriod gml:id="?" frame="#ISO-8601">
<!--Zero or more repetitions:-->
<gml:metaDataProperty xlin:type="simple" xlin:href="?" xlin:role="?" xlin:arcrole="?" xlin:title="?" xlin:show="?" xlin:actuate="?" gml:remoteSchema="?" about="?">
<!--You may enter ANY elements at this point-->
</gml:metaDataProperty>
<!--Optional:-->
<gml:description xlin:type="simple" xlin:href="?" xlin:role="?" xlin:arcrole="?" xlin:title="?" xlin:show="?" xlin:actuate="?" gml:remoteSchema="?">?</gml:description>
<!--Zero or more repetitions:-->
<gml:name codeSpace="?">?</gml:name>
<!--Zero or more repetitions:-->
<gml:relatedTime xlin:type="simple" xlin:href="?" xlin:role="?" xlin:arcrole="?" xlin:title="?" xlin:show="?" xlin:actuate="?" gml:remoteSchema="?" relativePosition="?">
<gml:_TimePrimitive gml:id="?">
<!--Zero or more repetitions:-->
<gml:metaDataProperty xlin:type="simple" xlin:href="?" xlin:role="?" xlin:arcrole="?" xlin:title="?" xlin:show="?" xlin:actuate="?" gml:remoteSchema="?" about="?">
<!--You may enter ANY elements at this point-->
</gml:metaDataProperty>
<!--Optional:-->
<gml:description xlin:type="simple" xlin:href="?" xlin:role="?" xlin:arcrole="?" xlin:title="?" xlin:show="?" xlin:actuate="?" gml:remoteSchema="?">?</gml:description>
<!--Zero or more repetitions:-->
<gml:name codeSpace="?">?</gml:name>
<!--Zero or more repetitions:-->
<gml:relatedTime/>
</gml:_TimePrimitive>
</gml:relatedTime>
<!--You have a CHOICE of the next 2 items at this level-->
<gml:beginPosition frame="#ISO-8601" calendarEraName="?" indeterminatePosition="?">?</gml:beginPosition>
<gml:begin xlin:type="simple" xlin:href="?" xlin:role="?" xlin:arcrole="?" xlin:title="?" xlin:show="?" xlin:actuate="?" gml:remoteSchema="?">
<gml:TimeInstant gml:id="?" frame="#ISO-8601">
<!--Zero or more repetitions:-->
<gml:metaDataProperty xlin:type="simple" xlin:href="?" xlin:role="?" xlin:arcrole="?" xlin:title="?" xlin:show="?" xlin:actuate="?" gml:remoteSchema="?" about="?">
<!--You may enter ANY elements at this point-->
</gml:metaDataProperty>
<!--Optional:-->
<gml:description xlin:type="simple" xlin:href="?" xlin:role="?" xlin:arcrole="?" xlin:title="?" xlin:show="?" xlin:actuate="?" gml:remoteSchema="?">?</gml:description>
<!--Zero or more repetitions:-->
<gml:name codeSpace="?">?</gml:name>
<!--Zero or more repetitions:-->
<gml:relatedTime xlin:type="simple" xlin:href="?" xlin:role="?" xlin:arcrole="?" xlin:title="?" xlin:show="?" xlin:actuate="?" gml:remoteSchema="?" relativePosition="?">
<gml:_TimePrimitive gml:id="?">
<!--Zero or more repetitions:-->
<gml:metaDataProperty xlin:type="simple" xlin:href="?" xlin:role="?" xlin:arcrole="?" xlin:title="?" xlin:show="?" xlin:actuate="?" gml:remoteSchema="?" about="?">
<!--You may enter ANY elements at this point-->
</gml:metaDataProperty>
<!--Optional:-->
<gml:description xlin:type="simple" xlin:href="?" xlin:role="?" xlin:arcrole="?" xlin:title="?" xlin:show="?" xlin:actuate="?" gml:remoteSchema="?">?</gml:description>
<!--Zero or more repetitions:-->
<gml:name codeSpace="?">?</gml:name>
<!--Zero or more repetitions:-->
<gml:relatedTime/>
</gml:_TimePrimitive>
</gml:relatedTime>
<gml:timePosition frame="#ISO-8601" calendarEraName="?" indeterminatePosition="?">?</gml:timePosition>
</gml:TimeInstant>
</gml:begin>
<!--You have a CHOICE of the next 2 items at this level-->
<gml:endPosition frame="#ISO-8601" calendarEraName="?" indeterminatePosition="?">?</gml:endPosition>
<gml:end xlin:type="simple" xlin:href="?" xlin:role="?" xlin:arcrole="?" xlin:title="?" xlin:show="?" xlin:actuate="?" gml:remoteSchema="?">
<gml:TimeInstant gml:id="?" frame="#ISO-8601">
<!--Zero or more repetitions:-->
<gml:metaDataProperty xlin:type="simple" xlin:href="?" xlin:role="?" xlin:arcrole="?" xlin:title="?" xlin:show="?" xlin:actuate="?" gml:remoteSchema="?" about="?">
<!--You may enter ANY elements at this point-->
</gml:metaDataProperty>
<!--Optional:-->
<gml:description xlin:type="simple" xlin:href="?" xlin:role="?" xlin:arcrole="?" xlin:title="?" xlin:show="?" xlin:actuate="?" gml:remoteSchema="?">?</gml:description>
<!--Zero or more repetitions:-->
<gml:name codeSpace="?">?</gml:name>
<!--Zero or more repetitions:-->
<gml:relatedTime xlin:type="simple" xlin:href="?" xlin:role="?" xlin:arcrole="?" xlin:title="?" xlin:show="?" xlin:actuate="?" gml:remoteSchema="?" relativePosition="?">
<gml:_TimePrimitive gml:id="?">
<!--Zero or more repetitions:-->
<gml:metaDataProperty xlin:type="simple" xlin:href="?" xlin:role="?" xlin:arcrole="?" xlin:title="?" xlin:show="?" xlin:actuate="?" gml:remoteSchema="?" about="?">
<!--You may enter ANY elements at this point-->
</gml:metaDataProperty>
<!--Optional:-->
<gml:description xlin:type="simple" xlin:href="?" xlin:role="?" xlin:arcrole="?" xlin:title="?" xlin:show="?" xlin:actuate="?" gml:remoteSchema="?">?</gml:description>
<!--Zero or more repetitions:-->
<gml:name codeSpace="?">?</gml:name>
<!--Zero or more repetitions:-->
<gml:relatedTime/>
</gml:_TimePrimitive>
</gml:relatedTime>
<gml:timePosition frame="#ISO-8601" calendarEraName="?" indeterminatePosition="?">?</gml:timePosition>
</gml:TimeInstant>
</gml:end>
<!--You have a CHOICE of the next 2 items at this level-->
<gml:duration>?</gml:duration>
<gml:timeInterval unit="?" radix="?" factor="?">?</gml:timeInterval>
</urn:TimePeriod>
</urn:TimeSpan>
<urn:NetworkCode>?</urn:NetworkCode>
<!--Optional:-->
<urn:StationCode>?</urn:StationCode>
<!--Optional:-->
<urn:ChannelCode>?</urn:ChannelCode>
<!--Optional:-->
<urn:LocId>?</urn:LocId>
</urn:StationIdentifierFilter>
<!--Optional:-->
<urn:SpatialBounds>
<!--Optional:-->
<urn:BoundingBox>
<ogc:PropertyName>e gero</ogc:PropertyName>
<gml:Envelope srsName="?" srsDimension="?" axisLabels="?" uomLabels="?">
<!--You have a CHOICE of the next 4 items at this level-->
<gml:lowerCorner srsName="?" srsDimension="?" axisLabels="?" uomLabels="?">?</gml:lowerCorner>
<gml:upperCorner srsName="?" srsDimension="?" axisLabels="?" uomLabels="?">?</gml:upperCorner>
<gml:coord>
<gml:X>?</gml:X>
<!--Optional:-->
<gml:Y>?</gml:Y>
<!--Optional:-->
<gml:Z>?</gml:Z>
</gml:coord>
<gml:coord>
<gml:X>?</gml:X>
<!--Optional:-->
<gml:Y>?</gml:Y>
<!--Optional:-->
<gml:Z>?</gml:Z>
</gml:coord>
<gml:pos srsName="?" srsDimension="?" axisLabels="?" uomLabels="?">?</gml:pos>
<gml:pos srsName="?" srsDimension="?" axisLabels="?" uomLabels="?">?</gml:pos>
<gml:coordinates decimal="." cs="," ts=" ">?</gml:coordinates>
</gml:Envelope>
</urn:BoundingBox>
</urn:SpatialBounds>
</urn:getInventory>
</soap:Body>
</soap:Envelope>

As you can see it's just a relatively simple piece of xml. Basically this is what you get providing soapUI with our WSDL, but this request can be simplified over.

In fact this snippet contains all the possible elements that can be used to submit the query. In particular we used OGC standards to represent the TimePeriod and the SpatialBounds, they have many ways to express the time and the space but users can choose the one they prefer. For the spatialBounds only gml:lowerCorner, gml:upperCorner and gml:coord is implemented.

After cleaning up a little bit the request, the result should look like this:

getInventory simplified
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:urn="urn:xml:seisml:orfeus:neries:org" xmlns:gml="http://www.opengis.net/gml" xmlns:xlin="http://www.w3.org/1999/xlink" xmlns:ogc="http://www.opengis.net/ogc">
<soap:Header/>
<soap:Body>
<urn:getInventory>
<urn:UserToken>
<urn:email>trani@knmi.nl</urn:email>
<!--Optional:-->
<urn:password></urn:password>
<!--Optional:-->
<urn:label>Whatever Client</urn:label>
<!--Optional:-->
<urn:locale></urn:locale>
</urn:UserToken>
<!--1 or more repetitions:-->
<urn:StationIdentifierFilter>
<urn:TimeSpan>
<urn:TimePeriod frame="#ISO-8601">
<gml:beginPosition frame="#ISO-8601">2009-04-01T00:00:00</gml:beginPosition>
<gml:endPosition frame="#ISO-8601">2009-04-30T00:00:00</gml:endPosition>
</urn:TimePeriod>
</urn:TimeSpan>
<urn:NetworkCode>*</urn:NetworkCode>
<!--Optional:-->
<urn:StationCode>*</urn:StationCode>
<!--Optional:-->
<urn:ChannelCode>*</urn:ChannelCode>
<!--Optional:-->
<urn:LocId>.</urn:LocId>
</urn:StationIdentifierFilter>
</urn:getInventory>
</soap:Body>
</soap:Envelope>

In this example we requested the inventory of all the neworks, stations, channels available in the month of April (note the time format is UTC).

Let's have a brief look at the elements:

For a more accurate overview of all the possible attributes, their meaning and usage please refer to the WSDL ( seismolink.wsdl).

In a typical usage this would be just the first call to the system to get all the responding stations.

We could refine the request by adding a space filtering:

getInventory with bounding box

<urn:getInventory>
...
<urn:StationIdentifierFilter>
...

</urn:StationIdentifierFilter>

<urn:SpatialBounds>
<!--Optional:-->
<urn:BoundingBox>
<ogc:PropertyName>e gero</ogc:PropertyName>
<gml:Envelope>
<gml:lowerCorner>4.00 34.00 0</gml:lowerCorner>
<gml:upperCorner>18.00 48.00 0</gml:upperCorner>
</gml:Envelope>
</urn:BoundingBox>
</urn:SpatialBounds>

</urn:getInventory>

note the coordinates are separated by a white space.

And the response :

getInventory response

<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
<soapenv:Body>
<urn:getInventoryResponse xmlns:urn="urn:xml:seisml:orfeus:neries:org">
<ns0:inventory xmlns:ns0="http://geofon.gfz-potsdam.de/ns/inventory/0.2/">
<ns0:network archive="GFZ" code="AF" description="South African National Seismograph Network" end="" institutions="GFZ / Partners" net_class="p" region="South Africa" restricted="false" start="2007-03-01T00:00:00.000Z" type="BB">
<ns0:remark/>
<ns0:station affiliation="" code="CER" country="South Africa" depth="0.0" description="South African National Seismograph Network" elevation="472.0" end="" latitude="-33.361700" longitude="19.293300" place="Ceres" restricted="false" start="2007-03-15T00:00:00.000Z">
<ns0:remark/>
<ns0:seis_stream clock_id="" code="BH" datalogger="PS6-SC" datalogger_id="" depth="0.0" end="" flags="" format="Steim2" gain="0" loc_code="" restricted="false" sample_rate="20" sample_rate_div="1" seismometer="KS2000/N" seismometer_id="" start="2007-03-15T00:00:00.000Z">
<ns0:component azimuth="90.0" channel="2" code="E" dip="0.0"/>
<ns0:component azimuth="0.0" channel="1" code="N" dip="0.0"/>
<ns0:component azimuth="0.0" channel="0" code="Z" dip="-90.0"/>
</ns0:seis_stream>
<ns0:seis_stream clock_id="" code="HH" datalogger="PS6-SC" datalogger_id="" depth="0.0" end="" flags="" format="Steim2" gain="0" loc_code="" restricted="false" sample_rate="100" sample_rate_div="1" seismometer="KS2000/N" seismometer_id="" start="2007-03-15T00:00:00.000Z">
<ns0:component azimuth="90.0" channel="2" code="E" dip="0.0"/>
<ns0:component azimuth="0.0" channel="1" code="N" dip="0.0"/>
<ns0:component azimuth="0.0" channel="0" code="Z" dip="-90.0"/>
</ns0:seis_stream>
<ns0:seis_stream clock_id="" code="LH" datalogger="PS6-SC" datalogger_id="" depth="0.0" end="" flags="" format="Steim2" gain="0" loc_code="" restricted="false" sample_rate="1" sample_rate_div="1" seismometer="KS2000/N" seismometer_id="" start="2007-03-15T00:00:00.000Z">
<ns0:component azimuth="90.0" channel="2" code="E" dip="0.0"/>
<ns0:component azimuth="0.0" channel="1" code="N" dip="0.0"/>
<ns0:component azimuth="0.0" channel="0" code="Z" dip="-90.0"/>
</ns0:seis_stream>
<ns0:seis_stream clock_id="" code="VH" datalogger="PS6-SC" datalogger_id="" depth="0.0" end="" flags="" format="Steim2" gain="0" loc_code="" restricted="false" sample_rate="1" sample_rate_div="10" seismometer="KS2000/N" seismometer_id="" start="2007-03-15T00:00:00.000Z">
<ns0:component azimuth="90.0" channel="2" code="E" dip="0.0"/>
<ns0:component azimuth="0.0" channel="1" code="N" dip="0.0"/>
<ns0:component azimuth="0.0" channel="0" code="Z" dip="-90.0"/>
</ns0:seis_stream>
</ns0:station>
<ns0:station affiliation="" code="CVNA" country="South Africa" depth="0.0" description="South African National Seismograph Network" elevation="1050.0" end="" latitude="-31.482100" longitude="19.761700" place="Calvinia" restricted="false" start="2007-03-19T00:00:00.000Z">
<ns0:remark/>
<ns0:seis_stream clock_id="" code="BH" datalogger="PS6-SC" datalogger_id="" depth="0.0" end="" flags="" format="Steim2" gain="0" loc_code="" restricted="false" sample_rate="20" sample_rate_div="1" seismometer="KS2000/N" seismometer_id="" start="2007-03-19T00:00:00.000Z">
<ns0:component azimuth="90.0" channel="2" code="E" dip="0.0"/>
<ns0:component azimuth="0.0" channel="1" code="N" dip="0.0"/>
<ns0:component azimuth="0.0" channel="0" code="Z" dip="-90.0"/>
</ns0:seis_stream>
<ns0:seis_stream clock_id="" code="HH" datalogger="PS6-SC" datalogger_id="" depth="0.0" end="" flags="" format="Steim2" gain="0" loc_code="" restricted="false" sample_rate="100" sample_rate_div="1" seismometer="KS2000/N" seismometer_id="" start="2007-03-19T00:00:00.000Z">
<ns0:component azimuth="90.0" channel="2" code="E" dip="0.0"/>
<ns0:component azimuth="0.0" channel="1" code="N" dip="0.0"/>
<ns0:component azimuth="0.0" channel="0" code="Z" dip="-90.0"/>
</ns0:seis_stream>
<ns0:seis_stream clock_id="" code="LH" datalogger="PS6-SC" datalogger_id="" depth="0.0" end="" flags="" format="Steim2" gain="0" loc_code="" restricted="false" sample_rate="1" sample_rate_div="1" seismometer="KS2000/N" seismometer_id="" start="2007-03-19T00:00:00.000Z">
<ns0:component azimuth="90.0" channel="2" code="E" dip="0.0"/>
<ns0:component azimuth="0.0" channel="1" code="N" dip="0.0"/>
<ns0:component azimuth="0.0" channel="0" code="Z" dip="-90.0"/>
</ns0:seis_stream>
<ns0:seis_stream clock_id="" code="VH" datalogger="PS6-SC" datalogger_id="" depth="0.0" end="" flags="" format="Steim2" gain="0" loc_code="" restricted="false" sample_rate="1" sample_rate_div="10" seismometer="KS2000/N" seismometer_id="" start="2007-03-19T00:00:00.000Z">
<ns0:component azimuth="90.0" channel="2" code="E" dip="0.0"/>
<ns0:component azimuth="0.0" channel="1" code="N" dip="0.0"/>
<ns0:component azimuth="0.0" channel="0" code="Z" dip="-90.0"/>
</ns0:seis_stream>
</ns0:station>
<ns0:station affiliation="" code="GRM" country="South Africa" depth="0.0" description="South African National Seismograph Network" elevation="610.0" end="" latitude="-33.313300" longitude="26.573300" place="Grahamstown" restricted="false" start="2007-03-19T00:00:00.000Z">
<ns0:remark/>

. . . . . . . . . . . . . . . . . . . . . . . for sake of conciseness I cut it, it's a lot of stuff! . . . . . . . . . . . . . . . . . . . . . . . .


<ns0:seis_stream clock_id="" code="BH" datalogger="Q4120-M" datalogger_id="" depth="5.0" end="" flags="" format="Steim2" gain="0" loc_code="" restricted="false" sample_rate="20" sample_rate_div="1" seismometer="STS-2/N" seismometer_id="" start="2009-01-01T00:00:00.000Z">
<ns0:component azimuth="90.0" channel="2" code="E" dip="0.0"/>
<ns0:component azimuth="0.0" channel="1" code="N" dip="0.0"/>
<ns0:component azimuth="0.0" channel="0" code="Z" dip="-90.0"/>
</ns0:seis_stream>
<ns0:seis_stream clock_id="" code="LH" datalogger="Q4120-M" datalogger_id="" depth="5.0" end="" flags="" format="Steim2" gain="0" loc_code="" restricted="false" sample_rate="1" sample_rate_div="1" seismometer="STS-2/N" seismometer_id="" start="2009-01-01T00:00:00.000Z">
<ns0:component azimuth="90.0" channel="2" code="E" dip="0.0"/>
<ns0:component azimuth="0.0" channel="1" code="N" dip="0.0"/>
<ns0:component azimuth="0.0" channel="0" code="Z" dip="-90.0"/>
</ns0:seis_stream>
<ns0:seis_stream clock_id="" code="VH" datalogger="Q4120-M" datalogger_id="" depth="5.0" end="" flags="" format="Steim2" gain="0" loc_code="" restricted="false" sample_rate="1" sample_rate_div="10" seismometer="STS-2/N" seismometer_id="" start="2009-01-01T00:00:00.000Z">
<ns0:component azimuth="90.0" channel="2" code="E" dip="0.0"/>
<ns0:component azimuth="0.0" channel="1" code="N" dip="0.0"/>
<ns0:component azimuth="0.0" channel="0" code="Z" dip="-90.0"/>
</ns0:seis_stream>
</ns0:station>
</ns0:network>
</ns0:inventory>
</urn:getInventoryResponse>
</soapenv:Body>
</soapenv:Envelope>

This xml is conforming the inventory schema (inventory.xsd) provided together with the wsdl.

Once we have the available stations we might be interested in requesting data from a bunch of them, to achieve this we use the method: dataRequest.

This request is pretty similar to the inventory one apart from the spatialBounds element:

dataRequest

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:urn="urn:xml:seisml:orfeus:neries:org" xmlns:gml="http://www.opengis.net/gml" xmlns:xlin="http://www.w3.org/1999/xlink">
<soap:Header/>
<soap:Body>
<urn:dataRequest>
<urn:UserToken>
<urn:email>trani@knmi.nl</urn:email>

<urn:label>WhateverClient</urn:label>
</urn:UserToken>
<urn:StationIdentifierFilter>
<urn:TimeSpan>
<urn:TimePeriod frame="#ISO-8601">
<gml:beginPosition frame="#ISO-8601">2009-04-01T00:00:00</gml:beginPosition>
<gml:endPosition frame="#ISO-8601">2009-04-01T12:00:00</gml:endPosition>
</urn:TimePeriod>
</urn:TimeSpan>
<urn:NetworkCode>NL</urn:NetworkCode>
<!--Optional:-->
<urn:StationCode>WIT</urn:StationCode>
<!--Optional:-->
<urn:ChannelCode>*</urn:ChannelCode>
<!--Optional:-->
<urn:LocId></urn:LocId>
</urn:StationIdentifierFilter>
</urn:dataRequest>
</soap:Body>
</soap:Envelope>

Here we are asking for data (default format is FULL_SEED but MINI_SEED is available as well, using the attribute DataFormat=MSEED see WSDL, compression is not implemented yet) coming from a station called WIT belonging to the network NL. And this is the response:

dataRequest response
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
   <soapenv:Body>
      <urn:dataResponse xmlns:urn="urn:xml:seisml:orfeus:neries:org">
         <urn:RoutedRequest Id="smi:eu.orfeus/waveform/orfeusArclink_4855/4856">
            <urn:ReqDescription>
               <urn:TimeSpan>
                  <urn:TimePeriod>
                     <gml:beginPosition xmlns:gml="http://www.opengis.net/gml">2009-04-01T00:00:00</gml:beginPosition>
                     <gml:endPosition xmlns:gml="http://www.opengis.net/gml">2009-04-01T12:00:00</gml:endPosition>
                  </urn:TimePeriod>
               </urn:TimeSpan>
               <urn:NetworkCode>NL</urn:NetworkCode>
               <urn:StationCode>WIT</urn:StationCode>
               <urn:ChannelCode>*</urn:ChannelCode>
               <urn:LocId/>
            </urn:ReqDescription>
            <urn:StatusDescription>Volume ID: UNSET, Status: UNSET - -</urn:StatusDescription>
            <urn:ReadyFlag>false</urn:ReadyFlag>
            <urn:Fulfillment>0</urn:Fulfillment>
         </urn:RoutedRequest>
      </urn:dataResponse>
   </soapenv:Body>
</soapenv:Envelope>

As you can see there is a summary of the related request in the element RoutedRequest, which contains also an identifier Id. It is worth to spend a few words about this attribute: in principle it identifies uniquely the request in the system and contains also information about the provenance of the data. In this case the label orfeusArclink means that the requested data are coming directly from the arclink node running at ORFEUS, because the station we queried is belonging to the ODC. At the moment there are 4 nodes in the arclink network, ORFEUS, GFZ, INGV and IPGP. It is important to take note of this identifier in order to use the other methods of the service.

Another useful information is the status (StatusDescription) of the request, in this case UNSET, which means it has been accepted but we still don't know anything about the availability of the data. You can see also a flag that indicates when the request is ready (ReadyFlag) and an indicator of completeness (Fulfillment).

To check the status of our request we have another method: checkStatus

checkStatus request

<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:urn="urn:xml:seisml:orfeus:neries:org">
<soap:Header/>
<soap:Body>
<urn:checkStatus>
<urn:UserToken>
<urn:email>trani@knmi.nl</urn:email>

<urn:label>WhateverClient</urn:label>
</urn:UserToken>
<!--1 or more repetitions:-->
<urn:RequestID>smi:eu.orfeus/waveform/orfeusArclink_4855/4856</urn:RequestID>
</urn:checkStatus>
</soap:Body>
</soap:Envelope>

This method uses the unique id and the user information. The response in this case is:

checkStatus response
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
   <soapenv:Body>
      <urn:checkDataStatusResponse xmlns:urn="urn:xml:seisml:orfeus:neries:org">
         <urn:RoutedRequest Id="smi:eu.orfeus/waveform/orfeusArclink_4855/4856">
            <urn:ReqDescription>
               <urn:TimeSpan>
                  <urn:TimePeriod>
                     <gml:beginPosition xmlns:gml="http://www.opengis.net/gml">2009-04-01T00:00:00</gml:beginPosition>
                     <gml:endPosition xmlns:gml="http://www.opengis.net/gml">2009-04-01T12:00:00</gml:endPosition>
                  </urn:TimePeriod>
               </urn:TimeSpan>
               <urn:NetworkCode>NL</urn:NetworkCode>
               <urn:StationCode>WIT</urn:StationCode>
               <urn:ChannelCode>*</urn:ChannelCode>
               <urn:LocId/>
            </urn:ReqDescription>
            <urn:StatusDescription>Volume ID: ODC, Status: OK - -</urn:StatusDescription>
            <urn:ReadyFlag>true</urn:ReadyFlag>
            <urn:Fulfillment>100</urn:Fulfillment>
         </urn:RoutedRequest>
      </urn:checkDataStatusResponse>
   </soapenv:Body>
</soapenv:Envelope>

which is a good one because it gives 100% of the data we requested, as shown by the status and the fulfillment.

At this point the data are ready to be downloaded, we go to the dataRetrieve method:

dataRetrieve request
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:urn="urn:xml:seisml:orfeus:neries:org">
<soap:Header/>
<soap:Body>
<urn:dataRetrieve>
<urn:UserToken>
<urn:email>trani@knmi.nl</urn:email>
<urn:label>WhateverClient</urn:label>
</urn:UserToken>
<!--1 or more repetitions:-->
<urn:RequestID>smi:eu.orfeus/waveform/orfeusArclink_4855/4856</urn:RequestID>
</urn:dataRetrieve>
</soap:Body>
</soap:Envelope>

It is basically identical to the status request apart from the name. And here the response:

dataRetrieve response
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
   <soapenv:Body>
      <urn:dataRetrieveResponse xmlns:urn="urn:xml:seisml:orfeus:neries:org">
         <urn:DataItem>
            <urn:EstimatedSizeKB>9388</urn:EstimatedSizeKB>
            <urn:DisplayTitle>Request no: 4856</urn:DisplayTitle>
            <urn:DownloadToken>
               <urn:DownloadURL>ftp://www.orfeus-eu.org/pub/NERIES/portal/prod/WhateverClient/ODC_4856/4856</urn:DownloadURL>
               <urn:DownloadTokenId>smi:eu.orfeus/waveform/orfeusArclink_4855/4856</urn:DownloadTokenId>
            </urn:DownloadToken>
         </urn:DataItem>
      </urn:dataRetrieveResponse>
   </soapenv:Body>
</soapenv:Envelope>

Here besides some info like the estimated size, we find the url to download our data package in the element: DownloadURL.

At this point you may think the job is done... well... there is another small step we ask you to follow as a good practice of use.

Because the requests are stored in the system for a certain time, to avoid to overload it, we ask you to purge them when completed your task using the purgeData method:

purgeData request
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:urn="urn:xml:seisml:orfeus:neries:org">
<soap:Header/>
<soap:Body>
<urn:purgeData>
<urn:UserToken>
<urn:email>trani@knmi.nl</urn:email>
<urn:label>WhateverClient</urn:label>
</urn:UserToken>
<!--1 or more repetitions:-->
<urn:RequestID>smi:eu.orfeus/waveform/orfeusArclink_4855/4856</urn:RequestID>
</urn:purgeData>
</soap:Body>
</soap:Envelope>

and the response...

purgeData response
<soapenv:Envelope xmlns:soapenv="http://www.w3.org/2003/05/soap-envelope">
   <soapenv:Body>
      <urn:purgeDataResponse xmlns:urn="urn:xml:seisml:orfeus:neries:org">
         <urn:Request>
            <urn:RequestID>smi:eu.orfeus/waveform/orfeusArclink_4855/4856</urn:RequestID>
            <urn:StatusDescription>Request successfully purged</urn:StatusDescription>
         </urn:Request>
      </urn:purgeDataResponse>
   </soapenv:Body>
</soapenv:Envelope>

References

Seismolink WSDL: http://http://www.orfeus-eu.org/wsdl/seismolink/seismolink.wsdl

These are just a few links where to find out more information about webservices and clients:

For java developers:

java.sun.com/webservices/docs/1.6/tutorial/doc/

ws.apache.org/axis/java/user-guide.html

www.ibm.com/developerworks/webservices/library/ws-javaclient/index.html

other languages and tools:

www.oreillynet.com/pub/a/php/2003/07/03/php_amazon_soap.html for php developers

www.soaplite.com/ for perl developers

www.mathworks.com/access/helpdesk/help/techdoc/index.html using matlab framework

For any questions or comments feel free to contact us!