Centiloc Service Documentation
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

API Consuming

You can use API to configure devices, collect information and even stream part of your Boards.

  • Your API URL, to access your TenantID data.
  • A user account, username and password.

In order to consume API methods, from services hosted in Cloud, you need to be identified and authenticated.

This example uses jdoe with password nobody for tenant demo

1. Collect an access token

POST a form including your credentials to the authentication URL.

authParams = {  "client_id": "pub", # public authentication
                "username": "jdoe",
                "password": "nobody",
                "grant_type": "password" }
header = {"Content-Type":"application/x-www-form-urlencoded"}
response= requests.post("https://keycloak.centiloc.com/auth/realms/demo/protocol/openid-connect/token", 
                        data=authParams, 
                        headers=header)
if response.status_code != 200:
   print("ERR: Authentication failed")
   print(response)
   sys.exit(-1)

token = response.json()["access_token"]
print("token is: " + token)
using System.Net.Http;
using Grpc.Net.Client;
using Grpc.Core;
using Newtonsoft.Json;

public class AccessToken    {
    public string access_token { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        var channel = GrpcChannel.ForAddress("https://demo.api.centiloc.com");

        var kcParams = new Dictionary<string, string>();
        kcParams.Add("client_id", "pub");
        kcParams.Add("username", "jdoe");
        kcParams.Add("password", "nobody");
        kcParams.Add("grant_type", "password");
                    
        HttpResponseMessage response;
        using (HttpClient client = new HttpClient()) {
            using (var content = new FormUrlEncodedContent(kcParams))
            {
                content.Headers.Clear();
                content.Headers.Add("Content-Type", "application/x-www-form-urlencoded");

                response = client.PostAsync("https://keycloak.centiloc.com/auth/realms/demo/protocol/openid-connect/token", content).Result;
            }
        }

        if( !response.IsSuccessStatusCode ) {
            Console.WriteLine("request failed");
            return;
        }

        Console.WriteLine("KC request OK");
        var rawAccessToken = response.Content.ReadAsStringAsync().Result;
        string token = JsonConvert.DeserializeObject<AccessToken>(rawAccessToken).access_token;
        Console.WriteLine("token is: " + token);
    }
}
Imports System.Collections.Generic
Imports System.Net.Http
Imports Centiloc.Ops.Api.Geo.Service
Imports Newtonsoft.Json

Namespace basicexample
    Public Class AccessToken
        Public Property access_token As String
    End Class

    Module Program
        Sub Main(args As String())
            Dim kcParams As New Dictionary(Of String, String)()
            kcParams.Add("client_id", "pub")
            kcParams.Add("username", "jdoe")
            kcParams.Add("password", "noody")
            kcParams.Add("grant_type", "password")

            Dim response As HttpResponseMessage
            Using client As New HttpClient()
                Using content = New FormUrlEncodedContent(kcParams)
                    content.Headers.Clear()
                    content.Headers.Add("Content-Type", "application/x-www-form-urlencoded")

                    response = client.PostAsync("https://keycloak.centiloc.com/auth/realms/demo/protocol/openid-connect/token", content).Result
                End Using
            End Using

            If Not response.IsSuccessStatusCode Then
                Console.WriteLine("request failed")
                Return
            End If

            Console.WriteLine("KC request OK")
            Dim rawAccessToken = response.Content.ReadAsStringAsync().Result
            Dim token As String = JsonConvert.DeserializeObject(Of AccessToken)(rawAccessToken).access_token
            Console.WriteLine("token is: " & token)
        End Sub
    End Module
End Namespace

2. Opens a gRPC channel

You can find more information about it on grpc website.

import grpc

# open grpc channel
creds = grpc.ssl_channel_credentials()
api_channel = grpc.secure_channel(tenant+'.api.centiloc.com', creds)
using Grpc.Net.Client;
using Grpc.Core;

[…]

    GrpcChannel channel;
    channel = GrpcChannel.ForAddress("https://"+tenant+".api.centiloc.com");
Imports Grpc.Net.Client
Imports Grpc.Core
 []

    Dim channel = GrpcChannel.ForAddress("https://"+tenant+".api.centiloc.com")

3. Use the token and the channel

Add the token to every request to the API, in an authorization: Bearer header.

from centiloc_ops_api_geo_grpc import board_pb2
from centiloc_ops_api_geo_grpc import board_pb2_grpc
from centiloc_ops_api_geo_grpc import common_pb2

# Create a simple slice of metadata elements containing the bearer
auth_metadata = [('authorization', "Bearer " + token)]

# Create the stub handler to reach board rpc endpoints
board_handler = board_pb2_grpc.BoardStub(api_channel)

# Then pass this metadata to API calls.
nofilter = board_pb2.BoardFilters() # argument setting
allboards = board_handler.GetAll(nofilter, metadata=auth_metadata) # call

# print the data
print("found %02d boards" % len(allboards.boards))
for board in allboards.boards:
    print("  - %s" % board.sn)
    
    ## Dummy redundant call to Board.Get for the demonstration
    arg = common_pb2.BoardID()
    arg.sn = board.sn
    ret = board_handler.Get(arg, metadata=allmeta)
    print("    - status: %s" % common_pb2._BOARDSTATUS.values_by_number[ret.status].name)
    print("    - fw: %s" % ret.fw_version)
    print("    - last connection: %s" % ret.last_connection.ToDatetime().strftime("%x %X"))
    print("    - last disconnection: %s" % (ret.last_disconnection.ToDatetime().strftime("%x %X") if ret.last_disconnection != None else "none"))
    if len(ret.dimensions_mm) == 2:
        print("    - dimensions_mm: [%d, %d]" % (ret.dimensions_mm[0], ret.dimensions_mm[1]))
    else:
        print("    - dimensions_mm: none")
    if len(ret.margins_mm) == 2:
        print("    - margins_mm: [%d, %d]" % (ret.margins_mm[0], ret.margins_mm[1]))
    else:
        print("    - margins_mm: none")
    print("    - geoloc enabled: %s" % (not ret.no_geoloc))
using Centiloc.Ops.Api.Geo.Service;

[…]

// use allmeta to pass authenticatication bearer to the API request
var allmeta = new Metadata { {"authorization", "Bearer " + token} };

// Get items on board
var itemClient = new Item.ItemClient(channel);
var noLimitFilter = new ItemFilters{Page = new ItemsPagination{Size=1000} };
var itemsResult = itemClient.GetAll(noLimitFilter, allmeta);
Console.WriteLine($"got {itemsResult.Count} items");
foreach(var item in itemsResult.Items) {
    Console.WriteLine($" - {item.Uid} - {item.BoardSn} - {item.PosMm} - {item.Status} - {item.LastMomentum}");
}
' use allmeta to pass authenticatication bearer to the API request:
Dim allmeta = New Metadata From { 
    {"authorization", "Bearer " & token}
    }

' Get items on board
Dim itemClient = New Item.ItemClient(channel)
Dim onlyInFilter As New ItemFilter With {
    .Type = ItemAttr.Itemstatus,
    .ItemStatus = ItemStatus.In
}
Dim noLimitFilter As New ItemFilters With {
    .Page = New ItemsPagination With {.Size = 1000}
}