Skip to main content

Reference for C Device SDK

You can use the C interface of the Device SDK to integrate your Devices with Spotflow IoT Platform.

Requirements

You don't need to install additional software to run the Device SDK library on any supported operating system. The example projects use the following tools to compile the sample code that uses the Device SDK library:

Feel free to use any other toolchain that you're familiar with.

Installation

Download the latest version of the library for the operating system and processor architecture of your choice:

info

If you need the library compiled for a different operating system or processor architecture, please contact us.

Extract the archive to a directory of your choice. You can now include the header file include/spotflow.h into your code. Then, link the static library file to your project or add the dynamic library file to your project's runtime path. See the details for each operating system below:

You'll see the following directory structure:

DirectoryContent
binDynamic library file libspotflow.so
examplesExample program get_started.c that can be compiled using the provided Makefiles - one for using the dynamic library and one for using the static library
includeHeader file spotflow.h
libStatic library file libspotflow.a

To try the basic example, change <Your Provisioning Token> in examples/get_started.c to the actual Provisioning Token from the Platform. Then, navigate to one of the following directories:

  • examples/gcc_makefile_dynamic to use the dynamic library.
  • examples/gcc_makefile_static to use the static library.

Run the command:

make run

This will compile the example program and run it. You should see the request to approve the Device into the Platform. See Get Started for more details on approving the Device and viewing the received data.

If you want to remove the compiled files, run:

make clean

Basic Usage

The following code is the contents of the file examples/get_started.c that is included in the download archive (see Installation). It connects the Device to the Platform and starts sending simulated sensor measurements.

You need to register to the Platform and set it up before you can use the code. See Get Started for more information on configuring the Platform, registering your Device, and viewing the received data. Don't forget to replace <Your Provisioning Token> with the actual Provisioning Token from the Platform.

get_started.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include "spotflow.h"

#ifdef _WIN32
#include <windows.h>
#define gmtime_r(timer, buf) gmtime_s(buf, timer)
#else
#include <unistd.h>
#define Sleep(x) usleep((x)*1000)
#endif

void show_last_error()
{
size_t error_size = SPOTFLOW_ERROR_MAX_LENGTH;
char* error_buffer = malloc(error_size);
spotflow_read_last_error_message(error_buffer, error_size);
printf("Error: %s\n", error_buffer);
free(error_buffer);
}

void send_data(spotflow_client_t* client)
{
spotflow_message_context_t* ctx;
spotflow_message_context_create(&ctx, "default-stream-group", "default-stream");

const size_t max_size = 1024;
char* msg = malloc(max_size);

for (int i = 0; i < 60; i++)
{
time_t now_ts = time(NULL);
struct tm now;
gmtime_r(&now_ts, &now);

double temperature = 21 + (i * 0.05);
double humidity = 50 + (i * 0.1);

snprintf(
msg, max_size,
"{\"timestamp\": \"%04d-%02d-%02dT%02d:%02d:%02dZ\", \"temperatureCelsius\": %g, \"humidityPercent\": %g}",
now.tm_year + 1900, now.tm_mon + 1, now.tm_mday, now.tm_hour, now.tm_min, now.tm_sec, temperature, humidity);

printf("%s\n", msg);

if (spotflow_client_send_message(client, ctx, NULL, NULL, (const uint8_t*)msg, strlen(msg)) != SPOTFLOW_OK)
{
show_last_error();
return;
}

Sleep(5000);
}

free(msg);

spotflow_message_context_destroy(ctx);
}

int main()
{
spotflow_client_options_t* options;
spotflow_client_options_create(&options, "my-device", "<Your Provisioning Token>", "spotflow.db");

spotflow_client_t* client;
if (spotflow_client_start(&client, options) != SPOTFLOW_OK)
{
show_last_error();
return 1;
}

send_data(client);

spotflow_client_destroy(client);
spotflow_client_options_destroy(options);
}

Reference

Functions

enum spotflow_result_t spotflow_set_log_level( enum spotflow_log_level_t level)

Set the verbosity level of logging (SPOTFLOW_LOG_WARN by default).

Parameters
levelThe verbosity level of logging.

SPOTFLOW_OK if successful, SPOTFLOW_ERROR otherwise.

int spotflow_read_last_error_message( char * buffer, size_t buffer_length)

Write the most recent error message into the provided buffer as a UTF-8 string, returning the number of bytes written. If successful, the error message is consumed and will not be returned again in a future call to this function.

Since the string is in the UTF-8 encoding, Windows users may need to convert it to a UTF-16 string before displaying it.

Parameters
bufferThe buffer to write the error message into.
buffer_lengthThe length of the buffer in bytes. Use SPOTFLOW_ERROR_MAX_LENGTH to be sure that it is always large enough.

The number of bytes written into the buffer including the trailing null character. If no error has been produced yet, returns 0. If buffer or buffer_length are invalid (for example, null pointer or insufficient length), returns -1.

enum spotflow_result_t spotflow_client_options_create( struct spotflow_client_options_t ** options, const char * device_id, const char * provisioning_token, const char * database_file)

Create an object that stores the connection options. The created object of type spotflow_client_options_t is managed by the Device SDK. After you configure all the options (using either this function or with the additional functions listed below), pass the address of spotflow_client_options_t to spotflow_client_start. Delete spotflow_client_options_t using spotflow_client_options_destroy.

See also
spotflow_client_options_set_database_file spotflow_client_options_set_provisioning_token spotflow_client_options_set_device_id spotflow_client_options_set_instance spotflow_client_options_set_display_provisioning_operation_callback

Parameters
options(Output) The pointer to the spotflow_client_options_t object that will be created by this function.
device_id(Optional) The ID of the Device you are running the code from. Use NULL if you don't want to specify it. See spotflow_client_options_set_device_id.
provisioning_tokenThe Provisioning Token that will spotflow_client_start use to start Device Provisioning. See spotflow_client_options_set_provisioning_token.
database_fileThe path to the local database file where the Device SDK stores the connection credentials and temporarily persists incoming and outgoing messages. See spotflow_client_options_set_database_file.

SPOTFLOW_OK if the function succeeds, SPOTFLOW_ERROR if any argument is invalid (or NULL if it's required).

enum spotflow_result_t spotflow_client_options_set_database_file( struct spotflow_client_options_t * options, const char * database_file)

Set the path to the local database file where the Device SDK stores the connection credentials and temporarily persists incoming and outgoing messages. spotflow_client_start creates the file if it doesn't exist.

The file must end with the suffix ".db", for example, "spotflow.db". If you don't use an absolute path, the file is created relative to the current working directory.

Parameters
optionsThe spotflow_client_options_t object.
database_fileThe path to the local database file.

SPOTFLOW_OK if the function succeeds, SPOTFLOW_ERROR if any argument is invalid.

enum spotflow_result_t spotflow_client_options_set_provisioning_token( struct spotflow_client_options_t * options, const char * provisioning_token)

Set the Provisioning Token that will spotflow_client_start use to start Device Provisioning.

See Get Started for instructions how to create a Provisioning Token.

Parameters
optionsThe spotflow_client_options_t object.
provisioning_tokenThe Provisioning Token.

SPOTFLOW_OK if the function succeeds, SPOTFLOW_ERROR if any argument is invalid.

enum spotflow_result_t spotflow_client_options_set_device_id( struct spotflow_client_options_t * options, const char * device_id)

Set the ID of the Device you are running the code from. If you don't specify it here, you'll need to choose it during the approval of the Provisioning Operation. See Device Provisioning for more details about the process.

Make sure that no two Devices in the same Workspace use the same ID. Otherwise, unexpected errors can occur during the communication with the Platform.

Parameters
optionsThe spotflow_client_options_t object.
device_id(Optional) The ID of the Device. Use NULL if you don't want to specify it.

SPOTFLOW_OK if the function succeeds, SPOTFLOW_ERROR if any argument is invalid.

enum spotflow_result_t spotflow_client_options_set_instance( struct spotflow_client_options_t * options, const char * instance)

Set the URI/hostname of the Platform instance where the Device will connect to.

If your company uses a dedicated instance of the Platform, such as acme.spotflow.io, specify it here. The default value is api.eu1.spotflow.io.

Parameters
optionsThe spotflow_client_options_t object.
instance(Optional) The domain of the Platform instance. Use NULL if you want to keep the default value.

SPOTFLOW_OK if the function succeeds, SPOTFLOW_ERROR if any argument is invalid.

enum spotflow_result_t spotflow_client_options_set_display_provisioning_operation_callback( struct spotflow_client_options_t * options, spotflow_display_provisioning_operation_callback_t callback, void * context)

Set the function that displays the details of the Provisioning Operation when spotflow_client_start is performing Device Provisioning. See Get Started for hands-on experience with this process.

Parameters
optionsThe spotflow_client_options_t object.
callback(Optional) The function that displays the details of the Provisioning Operation. Use NULL if you don't want to specify it.
context(Optional) The context that will be passed to callback. Use NULL if you don't want to specify it.

SPOTFLOW_OK if the function succeeds, SPOTFLOW_ERROR if any argument is invalid.

void spotflow_client_options_destroy( struct spotflow_client_options_t * options)

Destroy the spotflow_client_options_t object.

Parameters
optionsThe spotflow_client_options_t object to destroy.
enum spotflow_result_t spotflow_client_start( spotflow_client_t ** client, const struct spotflow_client_options_t * options)

Start communicating with the Platform. The created object of type spotflow_client_t is managed by the Device SDK. Delete it using spotflow_client_destroy.

If the Device is not yet registered in the Platform, or its Registration Token is expired, this method performs Device Provisioning and waits for the approval. See Get Started for the instructions how to set up the Platform, start Device Provisioning, and approve the Device.

If the Registration Token from the last run is still valid, this method succeeds even without the connection to the Internet. The Device SDK will store all outgoing communication in the local database file and send it once it connects to the Platform.

Parameters
client(Output) The pointer to the spotflow_client_t object that will be created by this function.
optionsThe options that specify how to connect to the Platform.

SPOTFLOW_OK if the function succeeds, SPOTFLOW_ERROR if any argument is invalid.

enum spotflow_result_t spotflow_message_context_create( struct spotflow_message_context_t ** message_context, const char * stream_group, const char * stream)

Create an object that stores the options for sending Messages to the Platform.

Initialize the spotflow_message_context_t object: set the most important fields to the provided values and the other fields to default values. The created object of type spotflow_message_context_t is managed by the Device SDK. You can configure the object either using this function or using the additional functions listed below. Delete it using spotflow_message_context_destroy.

See also
spotflow_message_context_set_stream_group spotflow_message_context_set_stream spotflow_message_context_set_compression

Parameters
message_context(Output) The pointer to the spotflow_message_context_t object that will be created by this function.
stream_group(Optional) The Stream Group the Message will be sent to. If NULL, the Platforms directs the Messages to the default Stream Group of the current Workspace.
stream(Optional) The Stream the Message will be sent to. If NULL, the Platform directs the Messages into the default Stream of the given Stream Group.

SPOTFLOW_OK if the function succeeds, SPOTFLOW_ERROR if any argument is invalid.

enum spotflow_result_t spotflow_message_context_set_stream_group( struct spotflow_message_context_t * message_context, const char * stream_group)

Set the Stream Group where Messages will be sent to.

Parameters
message_contextThe spotflow_message_context_t object.
stream_groupThe Stream Group. If NULL, the Platforms directs the Messages to the default Stream Group of the current Workspace.

SPOTFLOW_OK if the function succeeds, SPOTFLOW_ERROR if any argument is invalid.

enum spotflow_result_t spotflow_message_context_set_stream( struct spotflow_message_context_t * message_context, const char * stream)

Set the Stream where Messages will be sent to.

Parameters
message_contextThe spotflow_message_context_t object.
streamThe Stream. If NULL, the Platform directs the Messages into the default Stream of the given Stream Group.

SPOTFLOW_OK if the function succeeds, SPOTFLOW_ERROR if any argument is invalid.

enum spotflow_result_t spotflow_message_context_set_compression( struct spotflow_message_context_t * message_context, enum spotflow_compression_t compression)

Set the compression to use for sending Messages.

Parameters
message_contextThe spotflow_message_context_t object.
compressionThe compression to use for sending Messages.

SPOTFLOW_OK if the function succeeds, SPOTFLOW_ERROR if any argument is invalid.

void spotflow_message_context_destroy( struct spotflow_message_context_t * message_context)

Destroy the spotflow_message_context_t object.

Parameters
message_contextThe spotflow_message_context_t object to destroy.
enum spotflow_result_t spotflow_client_enqueue_message( spotflow_client_t * client, const struct spotflow_message_context_t * message_context, const char * batch_id, const char * message_id, const uint8_t * buffer, size_t length)

Enqueue a Message to be sent to the Platform.

If the Stream doesn't have a Message ID Autofill Pattern, you must provide message_id. If the Stream groups Messages into Batches and doesn't have a Batch ID Autofill Pattern, you must provide batch_id. See User Guide for more details.

The method returns right after it saves the Message to the queue in the local database file. A background thread asynchronously sends the messages from the queue to the Platform. You can check the number of pending messages in the queue using spotflow_client_get_pending_messages_count.

Parameters
clientThe spotflow_client_t object.
message_contextThe options that specify how to send the Message.
batch_id(Optional) The ID of the Batch the Message is a part of. Use NULL if you don't want to specify it.
message_id(Optional) The ID of the Message. Use NULL if you don't want to specify it.
bufferThe buffer that contains the Message.
lengthThe length of the buffer in bytes.

SPOTFLOW_OK if the function succeeds, SPOTFLOW_ERROR if any argument is invalid or there is an error in persisting the message.

enum spotflow_result_t spotflow_client_enqueue_message_advanced( spotflow_client_t * client, const struct spotflow_message_context_t * message_context, const char * batch_id, const char * batch_slice_id, const char * message_id, const char * chunk_id, const uint8_t * buffer, size_t length)

Enqueue a Message to be sent to the Platform.

If the Stream doesn't have a Message ID Autofill Pattern, you must provide message_id. If the Stream groups Messages into Batches and doesn't have a Batch ID Autofill Pattern, you must provide batch_id. See User Guide for more details. Optionally, you can provide also batch_slice_id to use Batch Slices and chunk_id to use Message Chunking.

The method returns right after it saves the Message to the queue in the local database file. A background thread asynchronously sends the messages from the queue to the Platform. You can check the number of pending messages in the queue using spotflow_client_get_pending_messages_count.

Parameters
clientThe spotflow_client_t object.
message_contextThe options that specify how to send the Message.
batch_id(Optional) The ID of the Batch the Message is a part of. Use NULL if you don't want to specify it.
batch_slice_id(Optional) The ID of the Batch Slice the Message is a part of. Use NULL if you dont' want to specify it.
message_id(Optional) The ID of the Message. Use NULL if you don't want to specify it.
chunk_id(Optional) The ID of the Chunk of the Message. Use NULL if you don't want to specify it.
bufferThe buffer that contains the Message.
lengthThe length of the buffer in bytes.

SPOTFLOW_OK if the function succeeds, SPOTFLOW_ERROR if any argument is invalid or there is an error in persisting the message.

enum spotflow_result_t spotflow_client_enqueue_batch_completion( spotflow_client_t * client, const struct spotflow_message_context_t * message_context, const char * batch_id)

Enqueue the manual completion of the current Batch to be sent to the Platform.

The Platform also completes the previous Batch automatically when the new one starts. Therefore, you might not need to call this method at all. See User Guide for more details.

The method returns right after it saves the batch-completing Message to the queue in the local database file. A background thread asynchronously sends the messages from the queue to the Platform. You can check the number of pending messages in the queue using spotflow_client_get_pending_messages_count.

Parameters
clientThe spotflow_client_t object.
message_contextThe options that specify how to send the batch-completing Message.
batch_idThe ID of the Batch that will be completed.

SPOTFLOW_OK if the function succeeds, SPOTFLOW_ERROR if any argument is invalid or there is an error in persisting the message.

enum spotflow_result_t spotflow_client_enqueue_message_completion( spotflow_client_t * client, const struct spotflow_message_context_t * message_context, const char * batch_id, const char * message_id)

Enqueue the manual completion of the current Message to be sent to the Platform. Use this methods when Message Chunking is used.

The method returns right after it saves the message-completing Message to the queue in the local database file. A background thread asynchronously sends the Messages from the queue to the Platform. You can check the number of pending messages in the queue using spotflow_client_get_pending_messages_count.

Parameters
clientThe spotflow_client_t object.
message_contextThe options that specify how to send the message-completing Message.
batch_idThe ID of the Batch that the Message belongs to.
message_idThe ID of the Message.

SPOTFLOW_OK if the function succeeds, SPOTFLOW_ERROR if any argument is invalid or there is an error in persisting the message.

enum spotflow_result_t spotflow_client_wait_enqueued_messages_sent( spotflow_client_t * client)

Block the current thread until all the Messages that have been previously enqueued are sent to the Platform.

Parameters
clientThe spotflow_client_t object.

SPOTFLOW_OK if the function succeeds, SPOTFLOW_ERROR if the argument is invalid.

enum spotflow_result_t spotflow_client_send_message( spotflow_client_t * client, const struct spotflow_message_context_t * message_context, const char * batch_id, const char * message_id, const uint8_t * buffer, size_t length)

Send a Message to the Platform.

Warning: This method blocks the current thread until the Message (and all the Messages enqueued before it) is sent to the Platform. If your Device doesn't have a stable Internet connection, consider using spotflow_client_enqueue_message instead.

If the Stream doesn't have a Message ID Autofill Pattern, you must provide message_id. If the Stream groups Messages into Batches and doesn't have a Batch ID Autofill Pattern, you must provide batch_id. See User Guide for more details.

Parameters
clientThe spotflow_client_t object.
message_contextThe options that specify how to send the Message.
batch_id(Optional) The ID of the Batch the Message is a part of. Use NULL if you don't want to specify it.
message_id(Optional) The ID of the Message. Use NULL if you don't want to specify it.
bufferThe buffer that contains the Message.
lengthThe length of the buffer in bytes.

SPOTFLOW_OK if the function succeeds, SPOTFLOW_ERROR if any argument is invalid or there is an error in persisting the message.

enum spotflow_result_t spotflow_client_send_message_advanced( spotflow_client_t * client, const struct spotflow_message_context_t * message_context, const char * batch_id, const char * batch_slice_id, const char * message_id, const char * chunk_id, const uint8_t * buffer, size_t length)

Send a Message to the Platform.

Warning: This method blocks the current thread until the Message (and all the Messages enqueued before it) is sent to the Platform. If your Device doesn't have a stable Internet connection, consider using spotflow_client_enqueue_message_advanced instead.

If the Stream doesn't have a Message ID Autofill Pattern, you must provide message_id. If the Stream groups Messages into Batches and doesn't have a Batch ID Autofill Pattern, you must provide batch_id. See User Guide for more details. Optionally, you can provide also batch_slice_id to use Batch Slices and chunk_id to use Message Chunking.

Parameters
clientThe spotflow_client_t object.
message_contextThe options that specify how to send the Message.
batch_id(Optional) The ID of the Batch the Message is a part of. Use NULL if you don't want to specify it.
batch_slice_id(Optional) The ID of the Batch Slice the Message is a part of. Use NULL if you dont' want to specify it.
message_id(Optional) The ID of the Message. Use NULL if you don't want to specify it.
chunk_id(Optional) The ID of the Chunk of the Message. Use NULL if you don't want to specify it.
bufferThe buffer that contains the Message.
lengthThe length of the buffer in bytes.

SPOTFLOW_OK if the function succeeds, SPOTFLOW_ERROR if any argument is invalid or there is an error in persisting the message.

enum spotflow_result_t spotflow_client_get_pending_messages_count( const spotflow_client_t * client, size_t * count)

Get the number of Messages that have been persisted in the local database file but haven't been sent to the Platform yet.

Parameters
clientThe spotflow_client_t object.
count(Output) The number of pending Messages.

SPOTFLOW_OK if the function succeeds, SPOTFLOW_ERROR if any argument is invalid or there is an error in accessing the local database file.

enum spotflow_result_t spotflow_client_get_workspace_id( const spotflow_client_t * client, char * buffer, size_t buffer_length)

Write the ID of the Workspace to which the Device belongs into the provided buffer.

Parameters
clientThe spotflow_client_t object.
bufferThe buffer where the Workspace ID string including the trailing NUL character will be written to.
buffer_lengthThe length of the buffer in bytes. Use SPOTFLOW_WORKSPACE_ID_MAX_LENGTH to be sure that it is always large enough.

SPOTFLOW_OK if the function succeeds, SPOTFLOW_INSUFFICIENT_BUFFER if the buffer is too small, SPOTFLOW_ERROR if any argument is invalid.

enum spotflow_result_t spotflow_client_get_device_id( const spotflow_client_t * client, char * buffer, size_t buffer_length)

Write the Device ID into the provided buffer. Note that the value might differ from the one requested in spotflow_client_options_set_device_id if the technician overrides it during the approval of the Provisioning Operation.

Parameters
clientThe spotflow_client_t object.
bufferThe buffer where the Device ID string including the trailing NUL character will be written to.
buffer_lengthThe length of the buffer in bytes. Use SPOTFLOW_DEVICE_ID_MAX_LENGTH to be sure that it is always large enough.

SPOTFLOW_OK if the function succeeds, SPOTFLOW_INSUFFICIENT_BUFFER if the buffer is too small, SPOTFLOW_ERROR if any argument is invalid.

void spotflow_client_destroy( spotflow_client_t * client)

Disconnect from the Platform and destroy the spotflow_client_t object.

Parameters
clientThe spotflow_client_t object.

Enums

typedef enum spotflow_result_t

A result of a function that can fail. If a function returns a spotflow_result_t, the caller must check that the returned value is SPOTFLOW_OK before continuing further. If the function returns a different value, the caller can call spotflow_read_last_error_message to retrieve the error message. Check the documentation of the particular function to see what results it can return.

SPOTFLOW_OK

The function succeeded.

SPOTFLOW_ERROR

The function failed with an error.

SPOTFLOW_INSUFFICIENT_BUFFER

A buffer provided to the function is too small.

SPOTFLOW_NOT_READY

The client cannot provide the response because it is not connected to the platform.

typedef enum spotflow_compression_t

The compression to use for sending a message.

SPOTFLOW_COMPRESSION_NONE

Do not compress the message.

SPOTFLOW_COMPRESSION_FASTEST

Compress the message using the fastest compression algorithm settings.

SPOTFLOW_COMPRESSION_SMALLEST_SIZE

Compress the message using the algorithm settings that produce the smallest size. Beware that this may be significantly slower than the fastest compression. We recommend to test the performance of your application with this setting before using it in production.

typedef enum spotflow_log_level_t

The verbosity levels of logging.

SPOTFLOW_LOG_OFF

No logging.

SPOTFLOW_LOG_ERROR

Log errors only.

SPOTFLOW_LOG_WARN

Log errors and warnings.

SPOTFLOW_LOG_INFO

Log errors, warnings, and information.

SPOTFLOW_LOG_DEBUG

Log errors, warnings, information, and debug messages.

SPOTFLOW_LOG_TRACE

Log errors, warnings, information, debug messages, and trace messages.

Structs

typedef struct spotflow_client_t

A client connected to the Platform. This object is managed by the Device SDK. Create its instance using spotflow_client_start and delete it using spotflow_client_destroy.

The client stores all outgoing communication to the local database file and then sends it in a background thread asynchronously. Thanks to that, it works even when the connection is unreliable. Similarly, the client also stores all ingoing communication to the local database file and deletes it only after the application processes it.

typedef struct spotflow_client_options_t

A set of options that specify how to connect to the Platform. This object is managed by the Device SDK. Create its instance using spotflow_client_options_create and delete it using spotflow_client_options_destroy. After you configure all the options, pass the address of spotflow_client_options_t to spotflow_client_start.

typedef struct spotflow_message_context_t

A set of options for sending Messages to a Stream. This object is managed by the Device SDK. Create its instance using spotflow_message_context_create and delete it using spotflow_message_context_destroy.

typedef struct spotflow_provisioning_operation_t

The summary of an ongoing Provisioning Operation. This object is managed by the Device SDK and its contents must not be modified.

If you specify a custom callback to spotflow_client_options_set_display_provisioning_operation_callback, you'll receive a pointer to spotflow_provisioning_operation_t as its argument. The pointer is valid only for the duration of the callback.

const char * id

(Don't modify) The ID of this Provisioning Operation.

const char * verification_code

(Don't modify) The verification code of this Provisioning Operation.

const char * expiration_time

(Don't modify) The expiration time of this Provisioning Operation. The operation is no longer valid after that.

The date/time format is RFC 3339.

Callbacks

typedef void(*spotflow_display_provisioning_operation_callback_t)(const struct spotflow_provisioning_operation_t *operation, void *context)

The callback to display the details of an ongoing Provisioning Operation when the Device SDK is performing Device Provisioning. The callback is called only if you have configured it by spotflow_client_options_set_display_provisioning_operation_callback. The callback is called on the same thread that calls spotflow_client_start.

Parameters
operationThe summary of the Provisioning Operation. See spotflow_provisioning_operation_t for details.
contextThe optional context that was configured by spotflow_client_options_set_display_provisioning_operation_callback.

Constants

#define SPOTFLOW_DEVICE_ID_MAX_LENGTH 128

The maximum number of bytes of any Device ID string including the trailing NUL character.

#define SPOTFLOW_WORKSPACE_ID_MAX_LENGTH 37

The maximum number of bytes of any Workspace ID string including the trailing NUL character.

#define SPOTFLOW_ERROR_MAX_LENGTH 1024

The maximum number of bytes of any error message including the trailing null character.