cancel
Showing results for 
Search instead for 
Did you mean: 
cancel
Showing results for 
Search instead for 
Did you mean: 

Community Tip - Need to share some code when posting a question or reply? Make sure to use the "Insert code sample" menu option. Learn more! X

SDK Reference Part 5

No ratings

 

 

Step 7: C - Entities and Functions

 

All SDKs require a RemoteThing be created in ThingWorx in order to communicate. If many Things are to be created with the same properties, services, and events, we recommend that a Thing Template be derived from one of the supplied RemoteThing templates.

 

NOTE: The macros are all defined in the twMacros.h header file.

 

Define ThingShape

 

ThingShapes are used in the ThingWorx object-oriented Data Model and used to create Things later on. In order to create a ThingShape, you can do so with the provided macros. In order to define a ThingShapes using a macro, you will use TW_DECLARE_SHAPE or TW_SHAPE.

TW_DECLARE_SHAPE("SteamLocation","Address Shape","UniqueNameSpace");

 

Define ThingTemplate

 

ThingTemplates are used in the ThingWorx object oriented Data Model and used to create Things later on. In order to create a ThingTemplate, you can do so with the provided macros. In order to define a ThingTemplate using a macro, you will use TW_DECLARE_TEMPLATE or TW_TEMPLATE.

TW_DECLARE_TEMPLATE("SteamLocationTemplate",TW_THING_TEMPLATE_GENERIC,"UniqueNameSpace");

 

Define Thing

 

Things are used in the Data Model and a staple in IoT development. In order to create a Thing, you can do so with the provided macros or functions.

 

FunctionExample
In order to define a Thing with a macro, you will use TW_MAKE_THING.TW_MAKE_THING("SteamSensor", TW_THING_TEMPLATE_GENERIC);
In order to define a Thing without using a macro, you will use the twExt_CreateThingFromTemplate function.twExt_CreateThingFromTemplate("SteamSensor","WarehouseTemplate", "SimpleShape", "AddressShape","InventoryShape",NULL);

 

Register Functions

 

ThingWorx provides functionality for a Thing to be bound or connected to the server.

FunctionNotes
twExt_RegisterPolledTemplateFunctionRegister a function to be called periodically after this Thing has been created
twApi_RegisterSynchronizeStateEventCallbackCalled after binding to notify your application about what fields are bound on the server. Will also be called each time bindings on a Thing are edited.
twApi_RegisterBindEventCallbackRuns whenever a Thing is bound or unbound.

 

Bind & Subscribe

 

You will use the TW_BIND macro or the twApi_BindThing function with the Thing name provided as a parameter. The documentation can be found in [C SDK HOME DIR]/src/api/twMacro.h and [C SDK HOME DIR]/src/api/twApi.h respectfully.

 

NOTE: Registered properties are bound or subscribed after they have been registered.

 

Bind Callbacks

 

You may want to track exactly when your edge entities are successfully bound to or unbound from ThingWorx Core. The reason for this is that only bound items should be interacting with ThingWorx Core and it will never forward a request to a corresponding remote thing in its database when the request is targeted at an entity that is not bound. Call the twApi_RegisterBindEventCallback() function to register your bind callback function as seen below with a function we later define called BindEventHandler:

 

To learn about a specific bound Thing (ie, SteamSensor):

twApi_RegisterBindEventCallback("SteamSensor", BindEventHandler, NULL);

 

To learn about all bound Things, leave the first parameter null:

twApi_RegisterBindEventCallback(NULL, BindEventHandler, NULL


An example of the function is below:

void BindEventHandler(char *entityName, char isBound, void *userdata) {
    if (isBound) 
        TW_LOG(TW_FORCE,"bindEventHandler: Entity %s was Bound", entityName);
    else 
        TW_LOG(TW_FORCE,"bindEventHandler: Entity %s was Unbound", entityName);
}

 

Create Tasks

 

The SDK contains a tasker framework that you can use to call functions repeatedly at a set interval. You can use the tasker to drive both the connectivity layer of your application and the functionality of your application. However, using the tasker is optional.

 

NOTE: The built-in tasker is a simple round-robin execution engine that will call all registered functions at a rate defined when those functions are registered. If using a multitasking or multi-threaded environment you may want to disable the tasker and use the native environment. If you choose to disable the tasker, you must call twApi_TaskerFunction() and twMessageHandler_msgHandlerTask() on a regular basis (every 5 milliseconds or so). Un-define this setting if you are using your own threads to drive the API, as you do not want the tasker running in parallel with another thread running the API.

 

To properly initialize the tasker, you must define ENABLE_TASKER:

#define ENABLE_TASKER 1


An example of a data collection task is seen below:

/***************
Data Collection Task
****************/
/*
This function gets called at the rate defined in the task creation.
The SDK has a simple cooperative multitasker, so the function
cannot infinitely loop.
Use of a task like this is optional and not required in a multithreaded
environment where this functionality could be provided in a separate thread.
*/
#define DATA_COLLECTION_RATE_MSEC 2000

void dataCollectionTask(DATETIME now, void * params) {
    /* TW_LOG(TW_TRACE,"dataCollectionTask: Executing"); */
    properties.TotalFlow = rand()/(RAND_MAX/10.0);
    properties.Pressure = 18 + rand()/(RAND_MAX/5.0);
    properties.Location.latitude = properties.Location.latitude + ((double)(rand() - RAND_MAX))/RAND_MAX/5;
    properties.Location.longitude = properties.Location.longitude + ((double)(rand() - RAND_MAX))/RAND_MAX/5;
    properties.Temperature = 400 + rand()/(RAND_MAX/40);

    /* Check for a fault. Only do something if we haven't already */
    if (properties.Temperature > properties.TemperatureLimit && properties.FaultStatus == FALSE) {
        twInfoTable * faultData = 0;
        char msg[140];
        properties.FaultStatus = TRUE;
        properties.InletValve = TRUE;
        sprintf(msg,"%s Temperature %2f exceeds threshold of %2f", thingName, properties.Temperature, properties.TemperatureLimit);
        faultData = twInfoTable_CreateFromString("msg", msg, TRUE);
        twApi_FireEvent(TW_THING, thingName, "SteamSensorFault", faultData, -1, TRUE);
        twInfoTable_Delete(faultData);
    }

    /* Update the properties on the server */
    sendPropertyUpdate();
}
 
NOTE: The Windows-based operating systems have a tick resolution (15ms) that is higher than the tick resolutions requested by the C SDK (5ms).
 
 
 

Click here to view Part 6 of this guide

 
Version history
Last update:
‎Mar 07, 2023 08:27 AM
Updated by:
Labels (1)
Contributors