Introduction

This SDK is an object oriented abstraction of Tachyon's Consumer API. It's designed to facilitate integration of 3rd party code with Tachyon through the API.

The Consumer SDK allows virtually any managed application to access the Tachyon platform without needing the details of HTTP communication, which endpoints to use when or what input data should look like.

Tachyon consumer SDK is designed to wrap the Tachyon Consumer API, so you should be able to access every endpoint the Consumer API makes available for external callers.

You can instantiate multiple copies of the connector as the data inside it is instance based and not shared between instances.

On this page:

SDK versioning

Each version of the SDK is designed to work with a specific version of the API. You cannot specify the API version yourself because it's hard coded into the assembly.

A mismatched SDK may result in errors or data not being sent or returned from the API.

TachyonConnector

Using the SDK can be as simple as instantiating a TachyonConnector object by using a constructor that requires the address of the root of the consumer API and the name of your Consumer.

This will create a connector using the DefaultTransportProxy (see below) for communicating with the Consumer API.

When you are finished with your connector, simply call Dispose on it.

TachyonConnector constructors

The connector class has 3 constructors available with the following signatures:

  1. public TachyonConnector(string apiRoot, string consumerName).
  2. public TachyonConnector(string apiRoot, string consumerName, ILogProxy logProxy).
  3. public TachyonConnector(string apiRoot, ITransportProxy connectionProxy, ILogProxy logProxy).

Constructors 1 & 2 are almost the same, the only difference being that the 2nd one allows you to pass in a logging object.

Constructor 3 is designed to allow for full customization of the connector's behavior. It does not take Consumer name, since the transport proxy will know it already and it will provide the versioned API root address to the connector.

Code structure

Internally the SDK code divides into several sections:

APIs

Each class in this namespace represents a single controller from the Consumer API. Each of these classes has methods allowing you to perform every operation the controller allows.

These methods return ApiCallResponse objects.

Models

Models represent data going in and out of the Tachyon platform.

ModelDescription
API

API models are high level wrappers that represent a result of an API call.

The ApiCallResponse class is the object returned by every single method you can call on the API classes and contains:

  • Success - a boolean flag indicating call success and based on the status code returned by the HTTP call
  • Errors - if the call was unsuccessful you'll receive the errors in this collection
  • ReceivedObject - if the call was successful the object received will be in this property - note this is a generic property, its type varies depending on the called method
  • ResponseStatusCode - from version 3.3 inclusive, if the HTTP call has finished (for example, there has not been an exception during the call, like a timeout) this property will have the status code that was returned.

Some API methods have no return value. In this instance ReceivedObject may be empty (null), have a 'string' or 'boolean' type. Please check the documentation of the method you're calling for more informtion.

Send

Contains every model representing the data you send to the API, but never receive from it.

These are the classes to use when building the data to make API calls.

Receive

Contains every model representing the data you receive from the API, but not send to it.

These are the classes you receive inside the ApiCallResponse.ReceivedObject.

Common

Contains models that can be either sent to or received from the API.

In many cases the request and return data look exactly the same.

Auxiliary classes that define expression trees, sorting and filtering expressions etc. are in here as well.

Available customization interfaces

InterfaceDescription
ITransportProxy

ITransportProxy defines a contract for a class to perform all of the HTTP communication with the consumer API.

The Tachyon connector passes in amended (versioned) API root address to it right after it receives them and then use them for all of its HTTP calls.

This interface inherits IDisposable. The TachyonConnector will call its Dispose method when it itself is being disposed of.

Use this interface to fully customize HTTP communication, that is use webclient instead of httpclient.

If you're using a custom implementation of this interface, take care of passing in the consumer name in the HTTP header.

IHttpClientManager

Use IHttpClientManager to customize the behavior of DefaultTransportProxy. 

IHttpClientManager manages the lifecycle of the HttpClient object the default proxy uses.

The default client manager creates an HttpClient instance that uses default credentials.  If this is not what you want, you should provide our own implementation of IHttpClientManager that will return HttpClient configured to suit your needs.

The HttpClient returned by your implementation must be a fresh instance - meaning it must not have been used for making HTTP calls before. This is because the client has to be configured with the base address of the API etc. and those properties cannot be changed once even if a single HTTP call was made using the client.

ILogProxy

A rudimentary interface allowing you to receive logging from within the SDK.

Default implementations

The SDK contains default implementations for the transport proxy (class DefaultTransportProxy) and http client manager (class DefaultHttpClientManager).

DefaultTransportProxy

Default transport proxy is a class that uses a HttpClient, either created internally by DefaultHttpClientManager or created by a custom class that implements the IHttpClientManager interface and is passed in externally.

This class has two constructors:

  1. public DefaultTransportProxy(ILogProxy logger, string consumerId, string apiRootAddress)
  2. public DefaultTransportProxy(ILogProxy logger, string consumerId, IHttpClientManager clientManager)

The first constructor will use DefaultHttpClientManager to create a HttpClient. This means using default credentials.

The second constructor allows you to provide an object that implements IHttpclientManager, which will provide (and dispose of) the HttpClient object.

DefaultHttpClientManager

Default http client manager is a simple class that creates an HttpClient that uses default credentials and simply disposes of it when told to do so.

Tools

ErrorCreator

Error creator is a helper class containing two static methods allowing you to convert either HttpResponseMessage or an Exception to an Error object that you would receive in an ApiCallResponse object.

Code examples

Example 1: Access Tachyon using default credentials

Creating default connector
TachyonConnector connector = new TachyonConnector("http://myserver.mydomain.com/consumer", "myConsumer", null);

Example 2: Access Tachyon using specific credentials

Custom Http manager class
class MyManager : IHttpClientManager
{
	private readonly string userName;
    private readonly string password;
	
	public MyManager(string userName, string password)
	{
		this.userName = userName;
        this.password = password;
	}

	public System.Net.Http.HttpClient GetClient()
    {         
		HttpClientHandler httpMessageHandler = new HttpClientHandler
        {
        	UseDefaultCredentials = false,
        	Credentials = new NetworkCredential(this.userName, this.password)
        };
        return new HttpClient(httpMessageHandler);
	}

	public void DisposeOfClient(System.Net.Http.HttpClient client)
    {
		client.Dispose();
	}
}
Creating connector
IHttpClientManager clientManager = new MyManager("username goes here", "password goes here");
ITransportProxy proxy = new DefaultTransportProxy(null, "myConsumer", clientManager);
TachyonConnector connector = new TachyonConnector("http://myserver.mydomain.com/consumer", proxy, null);

Example 3: Access Tachyon using a custom transport proxy

Creating a connector with custom transport proxy
class myConnectionProxy : ITransportProxy
{
	[...]
}

[...]

var myConnectionProxyInstance = new myConnectionProxy([...]);
TachyonConnector connector = new TachyonConnector("http://myserver.mydomain.com/consumer", myConnectionProxyInstance, null);

Example 4: A complete example

A complete SDK example
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Tachyon.SDK.Consumer;
using Tachyon.SDK.Consumer.Enums;

namespace Demo
{
    class Program
    {
        static void Main(string[] args)
        {
            var connector = new TachyonConnector("http://localhost/consumer", "MyCustomConsumer", null);
            var devices = connector.Devices.GetDevices();
            if (devices.Success)
            {
                foreach (var device in devices.ReceivedObject)
                {
                    Console.WriteLine("Name: {0} - Os: {1}", device.Fqdn, device.OsVerTxt);
                }
            }

            var instructionDefinitions = connector.InstructionDefinitions.Get(new List<InstructionType> {InstructionType.Question});
            if (instructionDefinitions.Success)
            {
                foreach (var instructionDefinition in instructionDefinitions.ReceivedObject)
                {
                    Console.WriteLine(instructionDefinition.Name);
                }
            }

            var definition = connector.InstructionDefinitions.GetInstructionDefinition("1E-Explorer-TachyonCore-DisabledServices");
            if (definition.Success)
            {
                var def = definition.ReceivedObject;
                Console.WriteLine("Name: {0}", def.Name);
                Console.WriteLine("Description: {0}", def.Description);
                Console.WriteLine("Instruction TTL: {0}", def.InstructionTtlMinutes);
                Console.WriteLine("Responses TTL: {0}", def.ResponseTtlMinutes);
                Console.WriteLine("Schema:");
                foreach (var schemaColumn in def.Schema)
                {
                    Console.WriteLine("   Field Name: {0}. Data Type: {1}", schemaColumn.Name, schemaColumn.Type);
                }
                Console.WriteLine("Aggregation:");
                foreach (var aggregationColumn in def.Aggregation.Schema)
                {
                    Console.WriteLine("   Field Name: {0}. Data Type: {1}", aggregationColumn.Name, aggregationColumn.Type);
                }
            }

            var myDefinition = connector.InstructionDefinitions.GetInstructionDefinition("1E-Explorer-TachyonCore-DisabledServices");
            if (myDefinition.Success)
            {
                var result = connector.Instructions.SendInstruction(myDefinition.ReceivedObject.Id, null, 60, 120);
                if (result.Success)
                {
                    Console.WriteLine("successfully issued an instruction");
                    Thread.Sleep(2000);
                    var answers = connector.Responses.GetAllAggregatedResponses(result.ReceivedObject.Id);
                    if (answers.Success)
                    {
                        foreach (var answer in answers.ReceivedObject.Responses)
                        {
                            Console.WriteLine("Caption: {0} - Count :{1}",answer.Values["Caption"], answer.Values["Count"]);
                        }
                    }
                }
            }
        }
    }
}