Device SDK for C#

REST client - overview

Cumulocity comes with elaborate support for developing clients in C#. You can use C#, for example, to

To get started, check the “Hello World” examples for the various C# variants.

Note, that you can develop Cumulocity with any IDE and any build tool that you prefer, but the examples focus on .NET Core SDK and Visual Studio.

After reviewing the “Hello world” examples, continue with the section Developing C# clients.

Finally, here are some references for getting started with the basic technologies underlying the SDK:

General prerequisites

To use the C# client libraries, you need to have the latest versions 2.2 of the .NET Core for your operating system. To verify the version of your .NET Core Software Development Kit, type

	$ dotnet --version

The output needs to show a version number later than “2.2.100” for the basic examples.

You need to have a valid tenant, user and password in order to access Cumulocity. Refer to Tenant ID and tenant domain in the Reference guide to learn the difference between tenant ID and tenant domain.

Rest client - Hello, world!

This section gives a very basic example of using C# with Cumulocity through .NET Core Software Development Kit (SDK) which is a set of libraries and tools that allow developers to create .NET Core applications and libraries. It can also be run straight from Visual Studio, provided you have a Visual Studio and .NET Core SDK installed.

Prerequisites

Verify that you have .NET Core SDK installed:

$ dotnet --info
.NET Core SDK (reflecting any global.json):
  Version:   2.2.100
  Commit:    b9f2fa0ca8

Runtime Environment:
  OS Name:     Windows
  OS Version:  10.0.17134
  OS Platform: Windows
  RID:         win10-x64
  Base Path:   C:\Program Files\dotnet\sdk\2.2.100\

Host (useful for support):
  Version: 2.2.0
  Commit:  1249f08fed

.NET Core SDK can be downloaded from https://dotnet.microsoft.com.

Developing the “Hello, World!” agent

To develop a very simple “Hello, world!” agent for Cumulocity, you need to do the following:

Creating a .NET Core project

To create a plain C# project, run

$ dotnet new console -lang C# -o HelloAgent

This will create a folder HelloAgent in the current directory with a skeleton structure for your project.

Adding the C# client library

To add a dependency to the Cumulocity C# client library, run

dotnet add package Cumulocity.SDK.Client

Afterwards, the HelloAgent.csproj will be presented in this way:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>netcoreapp2.2</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Cumulocity.SDK.Client" Version="1.0.0" />
  </ItemGroup>

</Project>

Add the version parameter to use the right version of the client library. The version can be determined by checking the Announcements section of the Cumulocity Help Center.

dotnet add package Cumulocity.SDK.Client --version 1.0.0

Creating a C# application

Edit the Program.cs file with the following content:

using Cumulocity.SDK.Client;
using Cumulocity.SDK.Client.HelperTest;
using Cumulocity.SDK.Client.Rest;
using Cumulocity.SDK.Client.Rest.API.Inventory;
using Cumulocity.SDK.Client.Rest.Model;
using Cumulocity.SDK.Client.Rest.Model.Authentication;
using Cumulocity.SDK.Client.Rest.Model.C8Y;
using Cumulocity.SDK.Client.Rest.Representation.Inventory;
using Microsoft.Extensions.Configuration;
using System;

namespace HelloAgent
{
	internal class Program
	{
		private static void Main(string[] args)
		{
			Console.WriteLine("REST API client!");

			IPlatform platform = new PlatformImpl("<<yourURL>>",
				 new CumulocityCredentials("<<yourUser>>", "<<yourPassword>>"));
			IInventoryApi inventory = platform.InventoryApi;

			var mo = new ManagedObjectRepresentation();
			mo.Name = "Hello, world!";
			mo.Set(new IsDevice());
			var mo = inventory.Create(mo);
			Console.WriteLine($"Url: {mo.Self}");
			Console.ReadKey();
		}
	}
}

Replace <<yourUrl>>, <<yourUser>> and <<yourPassword>> with your URL (e.g. https://myurl.cumulocity.com), username and password.

What does the code in “main” do?

Building and running the agent

To build and run your agent, process the following commands:

$ cd HelloAgent
$ dotnet build
Microsoft (R) Build Engine version 15.9.20+g88f5fadfbe for .NET Core
Copyright (C) Microsoft Corporation. All rights reserved.
Build succeeded.
0 Warning(s)
0 Error(s)
$ dotnet run
REST API client!
Url: http://demos.cumulocity.com/inventory/managedObjects/110160902

The last line shows that a new device has been successfully created with a particular URL. Open the Cumulocity application and go to the device list. You should see a new “Hello, world!” device.

Hello world device

Got an error message? Check the troubleshooting section in the Microservice SDK guide.

Improving the agent

Now that you have done your first step, check out the section Developing C# clients.

Rest Client - Developing

Overview

This section gives an overview on how to access Cumulocity from C# clients, starting from connecting to Cumulocity over accessing data to remote control of devices. It also discusses how to extend the Cumulocity domain model from C# for new devices and other business objects. Finally, this section describes how to configure the logging service in order to control the level of diagnostic messages generated by the client.

The section is tightly linked to the design of the REST interfaces, which are described in REST implementation in the Reference guide.

Documentation is available on the resources site.

Connecting to Cumulocity

The root interface for connecting to Cumulocity from C# is called “Platform” (see “Root interface” in REST implementation in the Reference guide). It provides access to all other interfaces of the platform, such as the inventory. In its simplest form, it is instantiated as follows:

Platform platform = new PlatformImpl("<<URL>>", new CumulocityCredentials("<<user>>", "<<password>>"));

As an example:

Platform platform = new PlatformImpl("https://demos.cumulocity.com", new CumulocityCredentials("myuser", "mypassword"));

If you use the C# client for developing an application, you need to register an application key (through Own applications in the Cumulocity Administration application, or through the Application API).

new CumulocityCredentials("<<tenantID>>", "<<user>>", "<<password>>", "<<application key>>")

For testing purposes, every tenant is subscribed to the demo application key “uL27no8nhvLlYmW1JIK1CA==”. The constructor for PlatformImpl also allows you to specify the default number of objects returned from the server in one reply with the parameter “pageSize”.

Accessing the inventory

The following code snippet shows how to obtain a handle to the inventory from C#:

IInventoryApi inventory = platform.InventoryApi;

Using this handle, you can create, retrieve and update managed objects. For example, if you would like to retrieve all objects that have a geographical position, use

InventoryFilter inventoryFilter = new InventoryFilter();
inventoryFilter.ByFragmentType(typeof(Position));
var moc = inventory.GetManagedObjectsByFilter(inventoryFilter);

This returns a query to get the objects – it does not actually get them. In practice, such a list of objects could be very large. Hence, it is returned in “pages” from the server. To get all pages and iterate over them, use:

foreach (ManagedObjectRepresentation mo in moc.GetFirstPage().AllPages())
	{
		Console.WriteLine(mo.Id);
	}

To create a new managed object, simply construct a local representation of the object and send it to the platform. The following code snippet shows how to create a new electricity meter with a relay in it:

ManagedObjectRepresentation mo = new ManagedObjectRepresentation();
mo.Name = "MyMeter-1";
Relay relay = new Relay();
mo.Set(relay);
SinglePhaseElectricitySensor meter = new SinglePhaseElectricitySensor();
mo.Set(meter);
// Set additional properties, e.g., tariff tables, ...
mo = inventory.Create(mo);
Console.WriteLine(mo.Id);

The result of invoking “create” is a version of the new managed object with a populated unique identifier.

Now assume that you would like to store additional, own properties along with the device. This can simply be done by creating a new “fragment” in the form of a C# class. For example, assume that you would like to store tariff information along with your meter. There is a day and a night time tariff, and we need to store the hours during which the night time tariff is active:

[PackageName("tariff")]
public class Tariff
{
	[JsonProperty("nightTariffStart")]
	public int NightTariffStart
	{
		get
		{
			return nightTariffStart;
		}
		set
		{
			this.nightTariffStart = value;
		}
	}
	[JsonProperty("nightTariffEnd")]
	public int NightTariffEnd
	{
		get
		{
			return nightTariffEnd;
		}
		set
		{
			this.nightTariffEnd = value;
		}
	}
	private int nightTariffStart = 22;
	private int nightTariffEnd = 6;
}

Now, you can simply add tariff information to your meter:

Tariff tariff = new Tariff();
mo.Set(tariff);

This will store the tariff information along with the meter. For converting C# objects from and towards JSON/REST, Cumulocity uses Json.NET. The Json.NET help provides more information on how to influence the JSON format that is produced respectively accepted.

Accessing the identity service

A device typically has a technical identifier that an agent needs to know to be able to contact the device. Examples are meter numbers, IP addresses and REST URLs. To associate such identifiers with the unique identifier of Cumulocity, agents can use the identity service. Again, to create the association, create an object of type “ExternalIDRepresentation” and send it to the platform.

The code snippet below shows how to register a REST URL for a device. It assumes that “mo” is the managed object from the above example and “deviceUrl” is a string with the REST URL of the device.

const string ASSET_TYPE = "com_cumulocity_idtype_AssetTag";
const string deviceUrl = "SAMPLE-A-239239232";

ExternalIDRepresentation externalIDGid = new ExternalIDRepresentation();
externalIDGid.Type = ASSET_TYPE;
externalIDGid.ExternalId = deviceUrl;
externalIDGid.ManagedObject = mo;
IIdentityApi identityApi = platform.IdentityApi;
identityApi.Create(externalIDGid);

Now, if you need the association back, you can just query the identity service as follows:

ID id = new ID();
id.Type = ASSET_TYPE;
id.Value = deviceUrl;
externalIDGid = identityApi.GetExternalId(id);

The returned object will contain the unique identifier and a link to the managed object.

Accessing events and measurements

Events and measurements can be accessed in a very similar manner as described above for the inventory. The following example queries the signal strength of the mobile connection of devices in the past two weeks and prints the device ID, the time of the measurement, the received signal strength and the bit error rate.

IMeasurementApi measurementApi = platform.MeasurementApi;
MeasurementFilter measurementFilter = new MeasurementFilter();

var toDate = DateTime.Now;
var fromDate = DateTime.Now.AddDays(-14);
measurementFilter.ByDate(fromDate, toDate);
measurementFilter.byFragmentType(typeof(SignalStrength));
IMeasurementCollection mc = measurementApi.GetMeasurementsByFilter(measurementFilter);

MeasurementCollectionRepresentation measurements = mc.GetFirstPage();

foreach (var measurement in mc.GetFirstPage().AllPages())
   {
       SignalStrength signal = measurement.Get<SignalStrength>();
       Console.WriteLine(measurement.Source.Id + " " + measurement.DateTime + " " + signal.RssiValue + " " + signal.BerValue);
   }

Controlling devices

Finally, the “DeviceControlResource” enables you to manipulate devices remotely. It has two sides: You can create operations in applications to be sent to devices, and you can query operations from agents.

In order to control a device it must be in the “childDevices” hierarchy of an agent managed object. The agent managed object represents your agent in the inventory. It is identified by a fragment com_cumulocity_model_Agent. This is how Cumulocity identifies where to send operations to control a particular device.

This code demonstrates the setup:

ManagedObjectRepresentation agent = new ManagedObjectRepresentation();
agent.Set(new Agent()); // agents must include this fragment
// ... create agent in inventory
ManagedObjectRepresentation device = ...;
// ... create device in inventory

ManagedObjectReferenceRepresentation child2Ref = new ManagedObjectReferenceRepresentation();
child2Ref.ManagedObject= device;
inventory.GetManagedObject(agent.Id).AddChildDevice(child2Ref);

For example, assume that you would like to switch off a relay in a meter from an application. Similar to the previous examples, you create the operation to be executed locally, and then send it to the platform:

IDeviceControlApi control = platform.DeviceControlApi;
OperationRepresentation operation = new OperationRepresentation
  {
     DeviceId = mo.Id
  };
relay.SetRelayState(Relay.RelayState.OPEN);
operation.Set(relay);
control.Create(operation);

Now, if you would like to query the pending operations from an agent, the following code would need to be executed:

OperationFilter operationFilter = new OperationFilter();
operationFilter.ByAgent(mo.Id.Value);
operationFilter.ByStatus(OperationStatus.PENDING);
IOperationCollection oc = deviceControlApi.GetOperationsByFilter(operationFilter);

Again, the returned result may come in several pages due to its potential size.

foreach (OperationRepresentation op in oc.GetFirstPage().AllPages())
	{
		Console.WriteLine(op.Status);
	}

Realtime features

The C# client libraries fully support the real-time APIs of Cumulocity. For example, to get immediately notified when someone sends an operation to your agent, use the following code:

subscriber = new OperationNotificationSubscriber(platform);
subscriber.Subscribe(agentId, new Handler(operationProcessor));

  public class Handler : ISubscriptionListener<GId, OperationRepresentation>
       {
           private SimpleOperationProcessor operationProcessor;

           public Handler(SimpleOperationProcessor processor)
                {
                    this.operationProcessor = processor;
                }

           public void OnError(ISubscription<GId> subscription, Exception ex)
                {
                }

           public void OnNotification(ISubscription<GId> subscription, OperationRepresentation notification)
                {
                    operationProcessor.Process(notification);
                }
       }

Info: “agentId” is the ID of your agent in the inventory.

To unsubscribe from a subscription, use the following code:

subscription.Unsubscribe()

If you wish to disconnect, the following code must be used:

subscriber.Disconnect()

Reliability features

In particular on mobile devices, Internet connectivity might be unreliable. To support such environments, the C# client libraries support local buffering. This means that you can pass data to the client libraries regardless of an Internet connection being available or not. If a connection is available, the data will be send immediately. If not, the data will be buffered until the connection is back again. For this, “async” variants of the API calls are offered. For example, to send an alarm, use

IAlarmApi alarmApi = platform.AlarmApi;
Task<AlarmRepresentation> task = alarmApi.CreateAsync(anAlarm);

The “createAsync” method returns immediately. The “Task” object can be used to determine the result of the request whenever it was actually carried out. To ensure that messages are buffered in the event of a communication failure, set the a AsyncEnabled parameter to true in ClientConfiguration:

new ClientConfiguration(new MemoryBasedPersistentProvider(), true);

Logging configuration

Logging in the C# client SDK is handled through LibLog. For a detailed description on how to use and configure logging, see the logback documentation.

Since version 0.11, the default logging level of the SDK is set to “Error” for all components, which means that logging messages are suppressed unless their level is “Error”. If everything runs smoothly, there should be no log messages generated by the SDK. By default, log messages are sent to the console only.

With liblog you actually embed a blob of code into the library. This code then picks up which logging abstraction is in use by the application and writes to it via some clever reflection code. It has transparent built-in support for the following logging providers:

As soon as you add the configuration for your preferred provider and set up the necessary appender, logging should just work. If you wish to implement your custom provider, you just need to ensure that your provider implements the ILogProvider interface or inherits from the LogProviderBase.

Simple logging configuration

The following example shows how to enable debug-level logging for a single component, called “MyClass”, whilst keeping error-level logging for all other components. The following code snippet shows how to create the logger, and to log a message:

public class MyClass
{
	private static readonly ILog Logger = LogProvider.For<MyClass>();

	public void DoSomething()
	{
		Logger.Debug("Method 'DoSomething' in progress");
	}
}

That’s it, now the library is ready to automatically pick-up logger used by the consuming application. For example, if Serilog is the selected library, assigning Serilog’s Logger.Log will automatically connect all the moving parts together:

Log.Logger = new LoggerConfiguration()
             .MinimumLevel.Verbose()
             .WriteTo.LiterateConsole()
             .CreateLogger();

         Log.Logger.Verbose("Starting...");

         var myClass = new MyClass();
         myClass.DoSomething();

         Log.Logger.Verbose("Finishing...");
         Console.ReadKey();

When the code is run, the console should contain a message similar to the following:

The result is

	[21:09:18 APP] Starting...
	[21:09:18 APP] Method 'DoSomething' in progress
	[21:09:18 APP] Finishing...

MQTT client - prerequisites

In order to follow this tutorial, check the following prerequisites:

Source code

The source tree is located in a Git repository.

The repository location link:

https://bitbucket.org/m2m/cumulocity-sdk-cs/src/master/

MQTT client - Hello world!

To develop a very simple “Hello, world!” MQTT client for Cumulocity, you need to follow these steps:

dotnet new console
<RestoreSources>$(RestoreSources);../nugets;https://api.nuget.org/v3/index.json</RestoreSources>
dotnet add package Cumulocity.MQTT -s "../nugets"

Example

using Cumulocity.MQTT;
using Cumulocity.MQTT.Model;
using System;
using System.Threading.Tasks;

namespace MqttDemo
        {
            internal class Program
            {
                static Client cl;
                private static void Main(string[] args)
                {
                    Task.Run(() => RunClientAsync());
                    new System.Threading.AutoResetEvent(false).WaitOne();
                }

                private static async Task RunClientAsync()
                {
                    var cnf = new Configuration()
                    {
                        Server = "ws://<<serverUrl>>/mqtt",
                        UserName = @"<<tenant>>/<<username>>",
                        Password = @"<<password>>",
                        ClientId = "<<clientId>>",
                        Port = "80",
                        ConnectionType = "WS"
                    };

                    cl = new Client(cnf);
                    await cl.ConnectAsync();
                    cl.RestartEvt += Cl_RestartEvt;

                    await cl.StaticInventoryTemplates
                            .DeviceCreation("TestDevice", "c8y_MQTTDevice", (e) => { return    Task.FromResult(false); });

                    await cl.StaticInventoryTemplates
                            .ConfigureHardware("S123456789", "model", "1.0", (e) => { return Task.FromResult(false); });

                    Console.WriteLine(String.Format("Connected {0}", cl.IsConnected));
                }
                private static void Cl_RestartEvt(object sender, RestartEventArgs e)
                {
			Console.WriteLine("Restart the device");

	        cl.StaticOperationTemplates
		        .SetExecutingOperationsAsync("c8y_Restart", (er) => { return Task.FromResult(false); });
	        Thread.Sleep(1000);
	        cl.StaticOperationTemplates
		        .SetOperationToSuccessfulAsync("c8y_Restart", string.Empty, (er) => { return Task.FromResult(false); });
                }
            }
        }

Replace <<clientId>>, <<serverUrl>>, <<tenant>>, <<username>>, and <<password>> with your data.

Build and run the application:

dotnet build
dotnet run

Cumulocity MQTT protocol supports both unsecured TCP and also secured SSL connections (e.g. tcp://mqtt.cumulocity.com:1883 or ssl://mqtt.cumulocity.com:8883), so as the <<serverUrl>> select the one which fits for you.

What does the code in “main” do?

Improving the agent

Now that you have done your first step, check out the section Hello MQTT to learn more about Cumulocity MQTT and improve your application.

MQTT Client - Static templates

Static inventory templates

Device creation (100)

Will create a new device for the serial number in the inventory if not yet existing. An externalId for the device with type c8y_Serial and the device identifier of the MQTT clientId as value will be created.

Field Data type Description
deviceName string Optional. Name of the device. <serialNumber>
deviceType string Optional. Type of the device.
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

    await cl.StaticInventoryTemplates
    		.DeviceCreation("myDevice",
                            "myType",
                            (e) => { return Task.FromResult(false); });
Child device creation (101)

Will create a new child device for the current device. The newly created object will be added as child device. Additionally, an externalId for the child will be created with type “c8y_Serial” and the value a combination of the serial of the root device and the unique child ID.

Field Data type Description
uniqueChildID string Required. The unique child identifier.
deviceName string Optional. Name of the device. <serialNumber>
deviceType string Optional. Type of the device.
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

    await cl.StaticInventoryTemplates
    		.ChildDeviceCreationAsync("D32Q", "Device Name", "c8y_MQTTDevice", (e) => { return Task.FromResult(false); });
Get child devices (105)

Will trigger the sending of child devices of the device.

Field Data type Description
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

    cl.ChildrenOfDeviceEvt += Cl_ChildrenOfDeviceEvt;

    await cl.StaticInventoryTemplates.GetChildDevices((e) => { return Task.FromResult(false); });
    ...
    private static void Cl_ChildrenOfDeviceEvt(object sender, ChildrenOfDeviceEventArgs e)
        {
            foreach (var device in e.ChildrenOfDevice)
            {
                Console.WriteLine(device);
            }
        }
Configure hardware (110)

Will update the hardware properties of the device.

Parameters:

Field Data type Description
serialNumber string Optional. The serial number of the device.
model string Optional. The model.
revision string Optional. The revision.
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

    await cl.StaticInventoryTemplates
    		.ConfigureHardware("S123456789",
                                "model",
                                "1.0",
                                (e) => { return Task.FromResult(false); });
Configure mobile (111)

Will update the mobile properties of the device.

Parameters:

Field Data type Description
imei string Optional. The IMEI.
iccid string Optional. The ICCID.
imsi string Optional. The IMSI.
mcc string Optional. The MCC.
mnc string Optional. The MNC.
lac string Optional. The LAC.
cellId string Optional. The Cell ID.
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

    await cl.StaticInventoryTemplates
    		.ConfigureMobile(
                            "356938035643809",
                            "8991101200003204510",
                            "410-07-4777770001",
                            "410",
                            "07",
                            "477",
                            "0001",
                            (e) => { return Task.FromResult(false); });
Configure position (112)

Will update the position properties of the device.

Parameters:

Field Data type Description
latitude string Optional. The latitude.
longitude string Optional. The longitude.
altitude string Optional. The altitude.
accuracy string Optional. The accuracy.
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

    await cl.StaticInventoryTemplates
    		.ConfigurePosition(
                                "52.409538",
                                "16.931992",
                                "76",
                                "134",
                                (e) => { return Task.FromResult(false); });
Set configuration (113)

Will set the configuration of the device.

Parameters:

Field Data type Description
configuration string Optional. The IMEI.
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

    await cl.StaticInventoryTemplates
    		.SetConfiguration(
                           "val1 = 1\nval2 = 2",
                           (e) => { return Task.FromResult(false); });
Set supported operations (114)

Will set the supported operations of the device.

Parameters:

Field Data type Description
supportedOperations IList<string> Required. List of supported operations.
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

    IList<string> supportedOperations = new List<string>();
    supportedOperations.Add("c8y_Restart");
    supportedOperations.Add("c8y_Configuration");

    //Will set the supported operations of the device
    await cl.StaticInventoryTemplates
            .SetSupportedOperations(
                                	supportedOperations,
                                	(e) => { return Task.FromResult(false); });
Set firmware (115)

Will set the firmware installed on the device.

Parameters:

Field Data type Description
name string Optional. The name.
version string Optional. The version.
url string Optional. The URL.
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

    await cl.StaticInventoryTemplates.SetFirmware(
                                "Extreme",
                                "Ultra 1.0",
                                @"http://sth.url",
                                (e) => { return Task.FromResult(false); });
Set software list (116)

Will set the list of software installed on the device.

Parameters:

Field Data type Description
installedSoftware IList<Software> Optional. List of supported operations.
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Software members:

Field Data type Description
Name string Required. The name.
Url string Required. The URL.
Version string Required. The version.

Example

    List<Software> list = new List<Software>();
    list.Add(new Software() { Name = "Software01", Url = "url1", Version = "1.0" });
    list.Add(new Software() { Name = "Software02", Url = "url2", Version = "2.1" });

    await cl.StaticInventoryTemplates.SetSoftwareList(list,
                                         (e) => { return Task.FromResult(false); });
Set required availability (117)

Will set the required interval for availability monitoring. It will only set the value if it does not exist. Values entered e.g. through UI are not overwritten.

Parameters:

Field Data type Description
requiredInterval int Optional. Required interval.
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

    await cl.StaticInventoryTemplates.SetRequiredAvailability(60,
                                        (e) => { return Task.FromResult(false); });

Static measurement templates

Create custom measurement (200)

Will create a measurement with given fragment and series.

Parameters:

Field Data type Description
fragment string Required. The fragment.
series string Required. The series.
value string Required. The value.
unit string Optional. The unit.
time string Optional. The time.
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

    await cl.StaticMeasurementTemplates
    		.CreateCustomMeasurementAsync("c8y_Temperature",
            							  "T",
                                          "25",
                                          string.Empty,
                                          string.Empty,
                                          (e) => { return Task.FromResult(false); });
Create signal strength measurement (210)

Will create a measurement of type c8y_SignalStrength.

Parameters:

Field Data type Description
rssiValue string Required if 2 not set. The RSSI value.
berValue string Required if 1 not set. The BER value.
time string Optional. The time. Default: Current server time
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

    await cl.StaticMeasurementTemplates
    		.CreateSignalStrengthMeasurementAsync("-90",
                                                  "23",
                                                  "2017-09-13T14:00:14.000+02:00",
                                                  (e) => { return Task.FromResult(false); });
Create temperature measurement (211)

Will create a measurement of type c8y_TemperatureMeasurement.

Parameters:

Field Data type Description
temperatureValue string Required. The temperature value.
time string Optional. The time. Default: Current server time
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

    await cl.StaticMeasurementTemplates
    		.CreateTemperatureMeasurementAsync("25",
            								   "2018-02-15T05:01:14.000+02:00",
                                               (e) => { return Task.FromResult(false); });
Create battery measurement (212)

Will create a measurement of type c8y_Battery.

Parameters:

Field Data type Description
temperatureValue string Required. The battery value.
time string Optional. The time. Default: Current server time
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing Mode

Example

    await cl.StaticMeasurementTemplates
    		.CreateBatteryMeasurementAsync("95",
            							   "2017-09-13T15:01:14.000+02:00",
                                           (e) => { return Task.FromResult(false); });

Static alarm templates

Create CRITICAL alarm (301)

Will create a CRITICAL alarm.

Parameters:

Field Data type Description
type string Required. The type.
text string Optional. The text. Alarm of type <alarmType> raised.
time string Optional. The time. Default: Current server time
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

    await cl.staticAlarmTemplates
            .CreateCriticalAlarmAsync("c8y_TemperatureAlarm",
                                      "Alarm of type c8y_TemperatureAlarm raised",
                                      string.Empty,
                                   	  (e) => { return Task.FromResult(false); });
Create MAJOR alarm (302)

Will create a MAJOR alarm.

Parameters:

Field Data type Description
type string Required. The type.
text string Optional. The text. Alarm of type <alarmType> raised.
time string Optional. The time. Default: Current server time
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

    await cl.StaticAlarmTemplates
    		.CreateMajorAlarmAsync("c8y_BatteryAlarm",
            					   "Major Alarm of type c8y_BatteryAlarm raised",
                                   string.Empty,
                                   (e) => { return Task.FromResult(false); });

Create MINOR alarm (303)

Will create a MINOR alarm.

Parameters:

Field Data type Description
type string Required. The type.
text string Optional. The text. Alarm of type <alarmType> raised.
time string Optional. The time. Default: Current server time
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

    await cl.StaticAlarmTemplates.CreateMinorAlarmAsync("c8y_WaterAlarm",
    														"Alarm of type c8y_WaterAlarm raised",
                                                            string.Empty,
                                                            (e) => { return Task.FromResult(false); });
Create WARNING alarm (304)

Will create a WARNING alarm.

Parameters:

Field Data type Description
type string Required. The type.
text string Optional. The text. Alarm of type <alarmType> raised.
time string Optional. The time. Default: Current server time
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

    await cl.StaticAlarmTemplates.CreateWarningAlarmAsync("c8y_AirPressureAlarm",
                                                              "Warning of type c8y_AirPressureAlarm raised",
                                                              string.Empty,
                                                              (e) => { return Task.FromResult(false); });
Update severity of existing alarm (305)

Will change the severity of an existing alarm.

Parameters:

Field Data type Description
type string Required. The type.
severity string Required. The severity.
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

    await cl.StaticAlarmTemplates.UpdateSeverityOfExistingAlarmAsync("c8y_AirPressureAlarm",
                                                                         "CRITICAL",
                                                                         (e) => { return Task.FromResult(false); });
Clear existing alarm (306)

Will clear an existing alarm.

Parameters:

Field Data type Description
type string Required. The type.
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

    await cl.StaticAlarmTemplates
    		.ClearExistingAlarmAsync("c8y_TemperatureAlarm",
    		(e) => { return Task.FromResult(false); });

Static event templates

Create basic event (400)

Will create an event of given type and text.

Parameters:

Field Data type Description
type string Required. The type.
text string Required. The text.
time string Optional. The time. Default: Current server time
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

    await cl.StaticEventTemplates
            .CreateBasicEventAsync("c8y_MyEvent",
                                   "Something was triggered",
                                   string.Empty,
                                   (e) => { return Task.FromResult(false); })
Create location update event (401)

Will create a typical location update event containing c8y_Position.

Parameters:

Field Data type Description
latitude string Optional. The latitude.
longitude string Optional. The longitude.
altitude string Optional. The altitude.
accuracy string Optional. The accuracy.
time string Optional. The time. Default: Current server time
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

            await cl.StaticEventTemplates
                    .CreateLocationUpdateEventAsync(
                                                 "52.209538",
                                                 "16.831992",
                                                 "76",
                                                 "134",
                                                 string.Empty,
                                                 (e) => { return Task.FromResult(false); });

Create location update event with device update (402)

Will create a typical location update event containing c8y_Position. Additionally the device will be updated with the same c8y_Position fragment.

Parameters:

Field Data type Description
latitude string Optional. The latitude.
longitude string Optional. The longitude.
altitude string Optional. The altitude.
accuracy string Optional. The accuracy.
time string Optional. The time. Default: Current server time
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

            await cl.StaticEventTemplates
                    .CreateLocationUpdateEventWithDeviceUpdateAsync(
                                                                 "52.209539",
                                                                 "16.831993",
                                                                 "76",
                                                                 "134",
                                                                 string.Empty,
                                                                 (e) => { return Task.FromResult(false); });

Static operation templates

Get PENDING operations (500)

Will trigger the sending of all PENDING operations for the agent.

Parameters:

Field Data type Description
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

     await cl.StaticOperationTemplates
     		 .GetPendingOperationsAsync((e) => { return Task.FromResult(false); });
Set operation to EXECUTING (501)

Will set the oldest PENDING operation with given fragment to EXECUTING.

Parameters:

Field Data type Description
fragment string Required. The fragment.
errorHandlerAsync string Required. Error handler
processingMode string Optional. Processing mode

Example

    await  cl.StaticOperationTemplates
             .SetExecutingOperationsAsync("c8y_Restart",
                                          (e) => { return Task.FromResult(false); });
Set operation to FAILED (502)

Will set the oldest EXECUTING operation with given fragment to FAILED.

Parameters:

Field Data type Description
fragment string Required. The fragment.
failureReason string Optional. The failure reason.
errorHandlerAsync string Required. The error handler asynchronous.
processingMode string Optional. Processing mode

Example

    await cl.StaticOperationTemplates
            .SetOperationToFailedAsync("c8y_Restart",
                                       "Could not restart",
                                       (e) => { return Task.FromResult(false); });
Set operation to SUCCESSFUL (503)

Will set the oldest EXECUTING operation with given fragment to SUCCESSFUL. It enables the device to send additional parameters that trigger additional steps based on the type of operation send as fragment.

Parameters:

Field Data type Description
fragment string Required. The fragment.
parameters string Optional. The parameters.
errorHandlerAsync string Required. The error handler asynchronous.
processingMode string Optional. Processing mode

Example

    await  cl.StaticOperationTemplates
             .SetOperationToSuccessfulAsync("c8y_Restart",
                                            string.Empty,
                                            (e) => { return Task.FromResult(false); });

Inventory templates

Get children of device (106)

Lists all children of the device

ChildrenOfDeviceEventArgs is the class containing event data

Field Data type Description
ChildrenOfDevice IList <string> List all children of the device.

Example

    cl.ChildrenOfDeviceEvt += Cl_ChildrenOfDeviceEvt;

    await cl.StaticInventoryTemplates.GetChildDevices((e) => { return Task.FromResult(false); });
    ...
    private static void Cl_ChildrenOfDeviceEvt(object sender, ChildrenOfDeviceEventArgs e)
        {
            foreach (var device in e.ChildrenOfDevice)
            {
                Console.WriteLine(device);
            }
        }

Operation templates

All operation responses have the same base structure, leading with the message ID followed by the ID of either the root device or a child which should handle the operation.

Restart (510)

Tells the device to restart.

Example

    cl.RestartEvt += (s, e) => {
                    Console.WriteLine(s);
                };
Command (511)

Tells the device to run the command send in the operation.

CommandEventArgs is the class containing event data.

Field Data type Description
CommandText string The command name.

Example

    cl.CommandEvt += (s, e) => {
        Console.WriteLine(s);
    };
Configuration (513)

Tells the device to set the configuration sent in the operation.

ConfigurationEventArgs is the class containing event data.

Field Data type Description
Configuration string the configuration sent in the operation.

Example

    cl.ConfigurationEvt += (s, e) => {
        Console.WriteLine(e.Configuration);
    };
Firmware (515)

Tells the device to install the firmware from the url.

FirmwareEventArgs is the containing event data.

Field Data type Description
FirmwareName string The software name
FirmwareVersion string The firmware version.
Url string The url.

Example

    cl.FirmwareEvt += (s, e) => {
                       Console.WriteLine("DeviceSerial:"+s);
                       Console.WriteLine(e.FirmwareName);
                       Console.WriteLine(e.FirmwareVersion);
                       Console.WriteLine( e.Url);
    };
Software list (516)

Tells the device to install the software send in the operation.

SoftwareListEventArgs is the class containing event data.

Field Data type Description
SoftwareList IList<Software> The list of software to install.

Example

    cl.SoftwareListEvt += (s, e) => {
        foreach (var soft in e.SoftwareList)
        {
            Console.WriteLine(soft.Name);
            Console.WriteLine(soft.Version);
            Console.WriteLine(soft.Url);
        }
    };
Measurement request operation (517)

Tells the device to send the measurements specified by the request name.

MeasurementRequestOperationEventArgs is the class containing event data.

Field Data type Description
RequestName string The measurement to send.

Example

    cl.MeasurementRequestOperationEvt += (s, e) => {
        Console.WriteLine(e.RequestName);
    };
Relay (518)

Tells the device to either open or close the relay.

RelayEventArgs is the class containing event data.

Field Data type Description
RelayState string The relay state.

Example

            cl.RelayEvt += (s, e) => {

                Console.WriteLine(e.RelayState);

            };
RelayArray (519)

Tells the device to either open or close the relays in the array.

RelayArrayEventArgs is the class containing event data.

Field Data type Description
RelayState IList<string> The list of the relay state.

Example

    cl.RelayArrayEvt += (s, e) => {
        foreach (var rs in e.RelayStates)
        {
            Console.WriteLine(rs);
        }
    };
Upload configuration file (520)

Tells the device to upload its current configuration.

Example

    cl.UploadConfigurationFileEvt += (s, e) => { };
Download configuration file (521)

Tells the device to download a configuration file from the url.

DownloadConfigurationFileEventArgs is the class containing event data.

Field Data type Description
Url string The url to download a configuration file.

Example

    cl.DownloadConfigurationFileEvt += (s, e) => {
        Console.WriteLine(e.Url);
    };
Logfile request (522)

Tells the device to upload a log file for the given parameters.

LogfileRequestEventArgs is the class containing event data.

Field Data type Description
LogFileName string The file name.
StartDate string From date.
EndDate string To date.
SearchText string The search text.
MaximumLines string The maximum lines.

Example

    cl.LogfileRequestEvt += (s, e) => {
        Console.WriteLine(e.LogFileName);
        Console.WriteLine(e.SearchText);
        Console.WriteLine(e.StartDate);
        Console.WriteLine(e.EndDate);
        Console.WriteLine(e.MaximumLines);
    };
Communication mode (523)

Tells the device to change the communication mode.

CommunicationModeEventArgs is the class containing event data.

Field Data type Description
Mode string The communication mode.

Example

    cl.CommunicationModeEvt += (s, e) => {
        Console.WriteLine(e.Mode);
    };

SmartRest

Check Template Collection Exists

Will verify if a template collection exists.

    cl.IsExistTemplateCollectionEvt += (s, e) =>
    {
        var item = e.IsExist;
    };

     await cl.CustomSmartRest.CheckTemplateCollectionExists("test", (e) => { return Task.FromResult(false); });

Create Template Data

Will create the template data asynchronous.

Parameters:

Field Data type Mandatory Description
collectionName String YES Name of the collection
requests List<Request> YES Depending on the type suitable Cumulocity API to be used
INVENTORY
MEASUREMENT
ALARM
EVENT
OPERATION
responses List<Response> NO The responses. Whether the request should trigger response templates. For GET templates by default true otherwise by default false
processingMode List<String> NO The processing mode

Types of requests templates

InventoryGetRequest
Field Data type Mandatory Description
messageId String YES Unique ID
response bool? No Whether the request should trigger response templates. For GET templates by default true otherwise by default false
externalIdType String YES Sets a fixed externalIdType if the template calls by externalId
byId String YES Whether the GET should be executed by Cumulocity ID (=true) or externalId (=false)
InventoryRequest
Field Data type Mandatory Description
messageId String YES Unique ID
response bool? No Whether the request should trigger response templates. For GET templates by default true otherwise by default false
externalIdType String NO Sets a fixed externalIdType if the template calls by externalId
customValues IList<CustomValue> No Custom values that should be added to the object
Method HttpMethods YES
GET
PUT
POST
MeasurementRequest
Field Data type Mandatory Description
messageId String YES Unique ID
response bool? No Whether the request should trigger response templates. For GET templates by default true otherwise by default false
type String YES The type of the measurement to create
time String YES A time stamp in the ISO 8601 format
customValues IList<CustomValue> No Custom values that should be added to the object
method HttpMethods YES
GET
PUT
POST
OperationRequest
Field Data type Mandatory Description
messageId String YES Unique ID
response bool? NO Whether the request should trigger response templates. For GET templates by default true otherwise by default false
type String YES The type of the operation to create
operationFragment OperationFragment YES e.g c8y_MyOperation
customValues IList<CustomValue> No Custom values that should be added to the object
AlarmRequest
Field Data type Mandatory Description
messageId String YES Unique ID
response bool? No Whether the request should trigger response templates. For GET templates by default true otherwise by default false
type String YES The type of the alarm to create
text String YES
status String YES A status of an alarm. Used to update the status field of alarms
severity String YES A severity of an alarm. Used to update the severity field of alarms e.g. Major
time String YES A time stamp in the ISO 8601 format
customValues IList<CustomValue> No Custom values that should be added to the object
Method HttpMethods YES
GET
PUT
POST
AlarmUpdateRequest
Field Data type Mandatory Description
messageId String YES Unique ID
response bool? No Whether the request should trigger response templates. For GET templates by default true otherwise by default false
type String YES The type of the alarm to find the alarm to update
alarmFragment AlarmFragment YES It contains key and status.
customValues IList<CustomValue> No Custom values that should be added to the object

Response templates

The SmartREST 2.0 response templates use the same structure as in SmartREST 1.0.

Field Data type Mandatory Description
messageId String YES Unique ID to reference the template within the collection
base String NO A JsonPath prefix that all patterns will use
condition String NO A JsonPath that needs to exist in the object to use the pattern
pattern List<String> YES A list of JsonPath that will be extracted from the object and returned to the device

Response will be used for every operation and for any request template that defines the response field with true.

In each case the server will try every registered response template so there might be multiple response lines for a single operation or request.

SmartREST 2.0 will always return a response template if the condition is true (or no condition was defined). Patterns that did not resolve will be returned as empty string. You should make use of the condition field to control when response templates should be returned.

Example

     new Response("8889",
     String.Empty,
     "c8y_IsDevice",
     new List<string> { "type",
                        "c8y_MQTTDevice",
                        "c8y_Mobile.cellId" });

GET templates

The GET templates for the inventory do not need any mandatory or custom values. Instead they use two different fields.

With SmartREST 2.0 you have the option to either get an object from inventory by its ID or by an externalId directly. Therefore instead of the fields mandatoryValues and customValues the following two fields are used.

Field Data type Possible values Mandatory Description
byId boolean true
false
YES Whether the GET should be executed by Cumulocity ID (=true) or externalId (=false)
externalIdType String NO Sets a fixed externalIdType if the template calls by externalId

Example

    await cl.CustomSmartRest.CreateTemplateDataAsync("GetTemplate",
                new List<Request> {
                             new InventoryGetRequest("9999",null, String.Empty, true),
                             new InventoryGetRequest("9998",null, "c8y_Serial", false)
                                                     },
                                                     new List<Response> {
                                                         new Response("8889",
                                                         String.Empty,
                                                         "c8y_IsDevice",
                                                         new List<string> { "type",
                                                                            "c8y_MQTTDevice",   																									"c8y_Mobile.cellId" }),

                                                         new Response("8888",
                                                         String.Empty,
                                                         "c8y_IsDevice",
                                                         new List<string> { "type",
                                                                            "c8y_MQTTDevice", 																										"c8y_Mobile.cellId" })
                                                     });

POST templates

The POST templates require a different set of mandatory values based on the API:

API mandatory values
MEASUREMENT type, time
EVENT type, text, time
ALARM type, text, status, severity, time
INVENTORY externalIdType
Creating a measurement template

Will create a template to create a measurement.

            await cl.CustomSmartRest.CreateTemplateDataAsync("PostTemplateMeasurement",
                                    new List<Request> {
                                    new MeasurementRequest("7777",
                                    null,
                                    "c8y_CustomMeasurement",
                                    String.Empty,
                                    new List<CustomValue>{
                                        new CustomValue {Path = "c8y_MyMeasurement.M.value",
                                            Type = Enums.CustomValueType.NUMBER,
                                            Value = String.Empty
                                        }
                                    },HttpMethods.POST)
                                    },
                                    new List<Response> {
                                        new Response("8889",
                                        String.Empty,
                                        "c8y_IsDevice",
                                        new List<string> { "type",
                                        				   "c8y_MQTTDevice",
                                                           "c8y_Mobile.cellId" }),
                                        new Response("8888",
                                        String.Empty,
                                        "c8y_IsDevice",
                                        new List<string> { "type",
                                        				   "c8y_MQTTDevice",
                                                           "c8y_Mobile.cellId" })
                                    });
Creating an alarm template

Will create a template to create an alarm.

            await cl.CustomSmartRest.CreateTemplateDataAsync("PostTemplateAlarm",
                                        new List<Request> {
                                        new AlarmRequest("6666",
                                        null,
                                        "c8y_CustomAlarm",
                                        "CustomAlarm",
                                        "ACTIVE",
                                        "MAJOR",
                                        String.Empty,
                                        new List<CustomValue>{
                                            new CustomValue {
                                                Path = "c8y_CustomAlarm.M.value",
                                                Type = CustomValueType.NUMBER,
                                                Value = String.Empty
                                            }
                                        },HttpMethods.POST)
                                        },
                                        new List<Response> {
                                            new Response("8889",
                                            String.Empty,
                                            "c8y_IsDevice",
                                            new List<string> {
                                                "type",
                                                "c8y_MQTTDevice",
                                                "c8y_Mobile.cellId" }),
                                            new Response("8888",
                                            String.Empty,
                                            "c8y_IsDevice",
                                            new List<string> {
                                                "type",
                                                "c8y_MQTTDevice",
                                                "c8y_Mobile.cellId" })
                                        });
Creating an event template

Will create a template to create an event.

       await cl.CustomSmartRest.CreateTemplateDataAsync("PostTemplateEvent",

                            new List<Request> {
                                        new EventRequest("5555",
                                        null,
                                        "c8y_CustomEvent",
                                        "CustomEvent",
                                        String.Empty,
                                        new List<CustomValue>{
                                            new CustomValue {Path = "c8y_CustomEvent.M.value",
                                                Type = CustomValueType.NUMBER,
                                                Value = String.Empty
                                            }
                                        })

                            },

                            new List<Response> {
                                            new Response("8889",
                                            String.Empty,
                                            "c8y_IsDevice",
                                            new List<string> {
                                                "type",
                                                "c8y_MQTTDevice",
                                                "c8y_Mobile.cellId" })
                            });
Creating an inventory template

Will create a template to create an inventory.

       await cl.CustomSmartRest.CreateTemplateDataAsync("PostTemplateInventory",
                                            new List<Request> {
                                            new InventoryRequest("4444",
                                            null,
                                            "c8y_MySerial",
                                            new List<CustomValue>{
                                                new CustomValue {Path = "c8y_CustomInventory.M.value",
                                                    Type = CustomValueType.NUMBER,
                                                    Value = String.Empty
                                                }
                                            },HttpMethods.POST)
                                            },

                                            new List<Response> {
                                                new Response("8889",
                                                String.Empty,
                                                "c8y_IsDevice",
                                                new List<string> { "type",
                                                                   "c8y_MQTTDevice",
                                                                   "c8y_Mobile.cellId" })
                                            });
Update an inventory template

Will update an inventory template.

       await cl.CustomSmartRest.CreateTemplateDataAsync("UpdateTemplateInventory",

                                            new List<Request> {
                                            new InventoryRequest("3333",
                                            null,
                                            "c8y_MySerial",
                                            new List<CustomValue>{
                                                new CustomValue {Path = "c8y_CustomInventory.M.value",
                                                    Type = CustomValueType.NUMBER,
                                                    Value = String.Empty
                                                }
                                            },HttpMethods.PUT)
                                            },
                                            new List<Response> {
                                                new Response("8889",
                                                String.Empty,
                                                "c8y_IsDevice",
                                                new List<string> { "type",
                                                                   "c8y_MQTTDevice",
                                                                   "c8y_Mobile.cellId"
                                                                  })
                                            });
Update an alarm template

Will update an alarm template.

    await cl.CustomSmartRest.CreateTemplateDataAsync("UpdateTemplateAlarm",
                                            new List<Request> {
                                                new AlarmUpdateRequest("2222",
                                                null,
                                                "c8y_CustomAlarm",
                                                new AlarmFragment("status",null),
                                                new List<CustomValue>{
                                                })
                                            },
                                            new List<Response> {
                                                new Response("8889",
                                                String.Empty,
                                                "c8y_IsDevice",
                                                new List<string> { "type",
                                                				   "c8y_MQTTDevice",
                                                                   "c8y_Mobile.cellId" })
                                            });
Update a clearing alarm template

Will update a clearing alarm template.

    	await cl.CustomSmartRest.CreateTemplateDataAsync("UpdateTemplateClearingAlarm",
                                            new List<Request> {
                                            new AlarmUpdateRequest("0000",
                                            null,
                                            "c8y_CustomAlarm",
                                            new AlarmFragment("status",AlarmStatus.CLEARED),
                                            new List<CustomValue>{
                                                new CustomValue {
                                                    Path = "c8y_CustomFragment",
                                                    Type = CustomValueType.STRING,
                                                    Value = String.Empty
                                                },
                                            })
                                            },
                                            new List<Response> {
                                                new Response("8889",
                                                String.Empty,
                                                "c8y_IsDevice",
                                                new List<string> { "type",
                                                                   "c8y_MQTTDevice",
                                                                   "c8y_Mobile.cellId" })
                                            });
Update an operation template

Will update an operation template.

       await cl.CustomSmartRest.CreateTemplateDataAsync("UpdateTemplateOperation",
                                            new List<Request> {
                                            new OperationRequest("1111",
                                            null,
                                            "com_cumulocity_model_WebCamDevice",
                                            new OperationFragment(
                                                "status",
                                                 OperationStatus.SUCCESSFUL),
                                                new List<CustomValue>{
                                                new CustomValue {
                                                    Path = "c8y_Fragment.val",
                                                    Type = CustomValueType.NUMBER,
                                                    Value = String.Empty
                                                } })

                                            },
                                            new List<Response> {
                                                new Response("8889",
                                                String.Empty,
                                                "c8y_IsDevice",
                                                new List<string> { "type",
                                                                   "c8y_MQTTDevice",
                                                                   "c8y_Mobile.cellId" })
                                            });
Alarm template

Will create an alarm using the template.

    await cl.CustomSmartRest
    		.SendRequestDataAsync("PostTemplateAlarm",
            					  "6666",
                                  new List<string> { "2018-02-15T16:03:14.000+02:00",
                                                     "100",
                                                     "ACTIVE",
                                                     "MAJOR" });
Measurement template

Will create a measurement using the template.

    await cl.CustomSmartRest
            .SendRequestDataAsync("PostTemplateMeasurement",
                                  "7777",
                                  new List<string> { "",
                                                     "25" });
Event template

Will create an event using the template.

    await cl.CustomSmartRest
    		.SendRequestDataAsync("PostTemplateEvent",
                                  "5555",
                                  new List<string> { "",