Remote Source Integration

A remote source represents a REST service. A remote source may supply data or be a recipient of requests produced by Vantiq or both supply data and be a recipient of notifications.

A remote source implements one or more of the following capabilities:

Define a Remote Source

A remote source is defined by creating a source resource that represents the definition of the remote source and submitting the definition to Vantiq for registration. The source object is submitted using a POST request.

An example:

POST https://dev.vantiq.com/api/v1/resources/sources
{ 
    "name": "RESTServiceName",
    "type": "REMOTE",
    "direction": "BOTH",
    "config": {
        "uri": "http://sub.domain.vantiq:9900/aDemo/add/demoData",
        "username": "vantiq",
        "password": "vantiq",
    }
}

Creates a REST source that can be queried to obtain data from the REST service or notified to send data to the REST service. Notifications are issued via the PUBLISH action in a rule. The above example does not define a stream for automatically querying the REST service periodically for data.

Once registered the remote source will immediately begin reading and processing messages if a stream is configured and will also immediately be available for query and notify operations.

The relevant source properties are as follows:

When making a request to a remote source (via polling, SELECT, or PUBLISH) you provide a JSON document which fully describes the request. This is known as a request document and has the following properties:

The following REST requests are used to manage remote sources:

Create a REMOTE Source

POST https://dev.vantiq.com/api/v1/resources/sources
{ 
    "name": "RESTServiceName",
    "type": "REMOTE",
    "direction": "BOTH",
    "pipelineRules: ["processingRule"],
    "config": {
        "uri": "http://sub.domain.vantiq:9900/aDemo/add/demoData",
        "topics": ["com.accessg2.stream.mqtt.example"],
        "username": "vantiq",
        "password": "vantiq",
    }
}

Creates a REST source with the remote service responding at the URI specified.

Delete a REMOTE Source

POST https://dev.vantiq.com/api/v1/resources/sources/RESTServiceName

Deletes the source created in the previous example.

Stream Data from REST Service

A stream sourced from the REST service is defined by setting the pollingInterval.

A request will be issued every pollingInterval seconds. The response to the request generates an event which is delivered to any subscribing rules.

An example definition of a streaming REST source:

{
     "name": "RESTServiceName",
     "type": "REMOTE",
     "direction": "SOURCE",
     "config": {
        "uri": "http://sub.domain.vantiq/streaming/source",
        "username": "vantiq",
        "password": "vantiq",
        "pollingInterval": 60
    }
}

This source will issue a GET (the default HTTP method) on the URI every 60 seconds.

Read from REST service

The REST service can respond to queries when SELECT is issued on the remote source. The WITH clause of the SELECT is used to specify the request document to use when the select is performed. The request will also incorporate any defaults provided as part of the source definition.

The body of the response carries the results of the query that will be delivered to the caller of SELECT. For example:

var someData = SELECT FROM SOURCE someSource WITH path = "/api/getData", method = "GET"

Publish Notifications to REST Service

The PUBLISH request for remote sources takes three parameters: the source to which the publish is sent and the body and publish parameters object. The message body and any publish parameters are combined with any request defaults provided by the source to form the final request document which is used to perform the PUBLISH.

For example:

PUBLISH { body: { data: "somedata" } } TO SOURCE someRemoteSource USING { path: "/submit" }

JSON Results

If the remote source declares a content type of json, results of polling and query operations are returned as JSON objects and JSON arrays. The results can be manipulated in rules using the standard notations of accessing lists, objects, properties.

XML Results

If a remote source declares a content type of xml, results of polling and query operations are returned using an internal representation of the XML element structure. If the result is used in a rule, the rule author must take care to properly navigate the XML structure. The following summarizes the most important access rules using the example XML:

<houses>
    <house bedrooms="2", bathrooms="2">
        <address>25 Main Street, Anywhere CA</address>
        <color>green</color>
    </house>
     <house bedrooms="3", bathrooms="3">
        <address>50 Main Street, Anywhere CA</address>
        <color>blue</color>
    </house>
</houses>

An XML document may be received by invoking a query using the SELECT operation to query the remote source for the list of houses:

var query = SELECT FROM SOURCE "someRemoteSource" WITH parm = 1

When the query returns the XML document is assigned to the variable query. The XML document can then be examined by navigating using element names and attribute names. The set of houses can be obtained via the navigation expression:

houseList = query.house

Note that house returns the array of houses that are children of the houses element. The array of houses is assigned to the variable houseList.

A single house within the list of houses can be reference by the house’s index in the house array:

firstHouse = query.house[0]

returns the first house in the array of houses while:

secondHouse = query.house[1]

returns the second house in the array of houses.

An attribute can be referenced using the XPath syntax [“@“]. Note the use of double quotes to identify the attribute name:

bedrooms = query.house[0]["@bedrooms"]

will return an XML element that contains the number of bedrooms. However, the returned value is an element. In order to obtain the actual value of the element (the value: “2”) the reference must explicitly request the text value of the attribute as follows:

bedroomsAsText = query.house[0]["@bedrooms"].text()

Nested elements can be referenced using the dot (.) notation to navigate the hierarchical structure of the XML document. For example, to obtain the address of the second house in the list:

query.house[1].address.text()

will return the value:

50 Main Street, Anywhere CA

In the example above all the sub-elements of houses are elements named house. In XML the sub-elements may be of multiple types. The sub-elements can be directly referenced by their element names. A more general example:

<places>
    <house bedrooms="2", bathrooms="2">
        <address>25 Main Street, Anywhere CA</address>
        <color>green</color>
    </house>
     <house bedrooms="3", bathrooms="3">
        <address>50 Main Street, Anywhere CA</address>
        <color>blue</color>
    </house>
    <office floor="2", size="2000">
        <address>75 Main Street, Anywhere CA</address>
        <color>green</color>
    </office>
     <office floor="3", size="10000">
        <address>100 Main Street, Anywhere CA</address>
        <color>blue</color>
    </house>
</places>

In this example the first house can be referenced with the following expression:

var query = SELECT FROM SOURCE "someRemoteSource" WITH parm=1
firstHouse = query.house[0]

This is exactly the same syntax as in the previous example. In detail it asks the system to find the first element of type house that is a sub-element of the root of the XML document (the places element).

The second office in the list can be obtained in a similar fashion.

secondOffice = query.office[1]

interpreted as find the second element of type office that is a sub-element of the root of the XML document.

Receiving the full response

When performing a SELECT the caller may request that the source return the entire response document instead of just the content in the body of the response. This is done by setting the asFullResponse property to true in the WITH clause of the select. When this is done the result will be a JSON object with the following properties: