Writing a Connector

Before starting to create your own adapter, we recommend checking first to see if any existing connectors are avaialable to suit your needs. In addition, be sure to review the Vantiq Adapter and Connector Design to understand the components and how they work together.

An connector has 3 components:

Creating the External Component

Any external component would be developed and deployed using the facilities provided by the 3rd party system. Vantiq provides a robust REST API and SDKs that support a variety of platforms that should provide a strong foundation for any external component.

Note that some external components may obviate the need to provide any inbound or outbound support within Vantiq as the external component may be able to interact purely through the REST API. Alternatively, a 3rd party system may not require any specific external components and all the connection logic may reside in Vantiq. The best design choice depends on the specific requirements of the connector.

Creating Inbound Support

The general pattern for supporting inbound requests is to create a rule that handles inbound data. The rule should be named Connector_<system>_inbound and listen on the topic /system/connector/<system>/inbound. By decoupling the inbound rule logic from the specific transport, the connector may be tolerant of deployment time topology changes. For example, if the inbound data was rerouted through a messaging layer, such as MQTT, the connector could still be used with no loss of functionality by adding an MQTT Source and a rule that republished the message onto the connector topic.

The responsibility of the connector rule is to trigger the appropriate adapter. Here is an example that connects to MuleSoft:

RULE Connector_MuleSoft_Inbound

WHEN PUBLISH OCCURS ON "/system/connector/MuleSoft/inbound" AS m

var dataType = m.newValue.type
var objArray = m.newValue.content

// Content is an array, so we loop over each entry
for(obj in objArray) {
    Connector_PublishData(dataType, obj)
}

In order to lookup the appropriate adapter, the connector must receive the data type name from the inbound request, the type field in the example. The actual payload provides the data for the data adapter. The Connector_PublishData procedure is a helper provided by Vantiq-connector-common that publishes the data onto the adapter topic /system/adapter/inbound/<type>.

Creating Outbound Support

Outbound support is heavily dependent on the capabilities of the 3rd party system. There are two general approaches for publishing control action messages to a 3rd party system:

In either case, the list of known control actions is generally required by the 3rd party system to understand what controls are supported within the given Vantiq system. The Connector_GetControlActions helper procedure is provide by Vantiq-connector-common and returns the list of actions that are currently available.

WebSocket Subscription

Vantiq has WebSocket support that allows a long-lived connection between Vantiq and an external client. Through that connection, the client may initiate a subscription for a specific topic, source, or type event. In this case, since all control actions are published onto /system/adapter/outbound/<action> topics, the client is able to listen to any control action.

The Vantiq MuleSoft Connector uses this approach.

Publish to REST Endpoint

In general, this approach requires a number of pieces to enable an efficient mechanism:

Here is an example of the outbound connector rule from the Vantiq Zapier Connector that uses this approach:

RULE Connector_Zapier_Outbound

//
// Listens for any control action messages
//
WHEN PUBLISH OCCURS ON "/system/adapter/outbound/*" AS m

//
// The action determines which target URL to use
// The payload for the action is the body that is sent to the target URL
//
// Note that Zapier always expects the payload to be an array.
//
var action  = m.newValue.system + "_" + m.newValue.action
var payload = m.newValue.payload

//
// Look to see if the action has been registered.  If so, lookup the 
// Zapier target URL used to post messages.  If none registered, then
// ignore the message.
//
var zapConfig = SELECT ONE * FROM Connector_Zapier_Config WHERE user == username() AND action == action
if(zapConfig) {

    //
    // The Base URI in the Zapier source is "https://zapier.com/" (or similar) so
    // we need to strip out this from the target_url to create the path.  Note
    // that it may be "https://hooks.zapier.com", but the path still works
    // with "https://zapier.com".
    //
    var publishConfig = {
        path: zapConfig.target_url.replace("^https?://[^/]*/", "/")
    }

    PUBLISH { body: payload } TO SOURCE Zapier USING publishConfig

}

The Zapier connector provided two procedures to subscribe and unsubscribe to specific control actions and stored that information in the Connector_Zapier_Config along with the REST URL. Upon every control action, this rule looks for an active subscription and, if found, simply publishes the payload to the Zapier REMOTE source.

Example

For an example using the WebSocket approach, review the MuleSoft Connector. For an example using the REST Endpoint approahc, review the Zapier Connector.