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

Community Tip - New to the community? Learn how to post a question and get help from PTC and industry experts! X

C SDK Tutorial Part 2

No ratings

 

Step 5: Properties

 

In the Delivery Truck application, there are three Delivery Truck Things. Each Thing has a number of Properties based on its location, speed, and its deliveries carried out. In this design, when a delivery is made or the truck is no longer moving, the Property values are updated.

 

The deliveryTruck.c helper C file is based on the DeliveryTruck Entities in the Composer. After calling the construct function, there are a number of steps necessary to get going. For the SimpleThing application, there are a number of methods for creating Properties, Events, Services, and Data Shapes for ease of use.

 

Properties can be created in the client or just registered and utilized. In the  SimpleThingClient  application, Properties are created. In the DeliveryTruckClient application, Properties are bound to their ThingWorx Platform counterpart. Two types of structures are used by the C SDK to define Properties when it is seen fit to do so and can be found in [C SDK HOME DIR]/src/api/twProperties.h:

 

NameStructureDescription
Property DefinitionstwPropertyDefDescribes the basic information for the Properties that will be available to ThingWorx and can be added to a client application.
Property ValuestwPropertyAssociates the Property name with a value, timestamp, and quality.

 

NOTE: The C SDK provides a number of Macros located in [C SDK HOME DIR]/src/api/twMacros.h. This guide will use these Macros while providing input on the use of pure function calls.

 

The Macro example below can be found in the main source file for the   SimpleThingClient   application and the accompanying helper file simple_thing.c.

 

TW_PROPERTY("TempProperty", "Description for TempProperty", TW_NUMBER);
    TW_ADD_BOOLEAN_ASPECT("TempProperty", TW_ASPECT_ISREADONLY,TRUE);
    TW_ADD_BOOLEAN_ASPECT("TempProperty", TW_ASPECT_ISLOGGED,TRUE);

NOTE: The list of aspect configurations can be seen in [C SDK HOME DIR]/src/api/twConstants.h. Property values can be set with defaults using the aspects setting. Setting a default value in the client will affect the Property in the ThingWorx platform after binding. It will not set a local value in the client application.

 

For the DeliveryTruckClient, we registered, read, and update Properties without using the Property definitions. Which method of using Properties is based on the application being built.

 

NOTE: Updating Properties in the ThingWorx Platform while the application is running, will update the values in the client application. To update the values in the platform to match, end the Property read section of your property handler function with a function to set the platform value.

 

The createTruckThing function for the deliveryTruck.c source code takes a truck name as a parameter and is used to register the Properties, functions, and handlers for each truck.

 

The updateTruckThing function for the deliveryTruck.c source code takes a truck name as a parameter and is used to either initialize a struct for DeliveryTruck Properties, or simulate a truck stop Event, update Properties, then fire an Event for the ThingWorx platform.

 

Connecting properties to be used on the platform is as easy as registering the property and optionally adding aspects. The following shows the properties that correlate to those in the DeliveryTruck entities in the Composer. To do this within the code, you would use the  TW_PROPERTY macro as shown in the deliveryTruck.c. This macro must be proceeded by either TW_DECLARE_SHAPE, TW_DECLARE_TEMPLATE or TW_MAKE_THING because these macros declare variables used by the TW_PROPERTY that follow them.

 

//TW_PROPERTY(propertyName,description,type)

TW_PROPERTY(PROPERTY_NAME_DRIVER, NO_DESCRIPTION, TW_STRING);
TW_PROPERTY(PROPERTY_NAME_DELIVERIES_LEFT, NO_DESCRIPTION, TW_NUMBER);
TW_PROPERTY(PROPERTY_NAME_TOTAL_DELIVERIES, NO_DESCRIPTION, TW_NUMBER);
TW_PROPERTY(PROPERTY_NAME_DELIVERIES_MADE, NO_DESCRIPTION, TW_NUMBER);
TW_PROPERTY(PROPERTY_NAME_LOCATION, NO_DESCRIPTION, TW_LOCATION);
TW_PROPERTY(PROPERTY_NAME_SPEED, NO_DESCRIPTION, "TW_NUMBER);

 

Read Properties

 

Reading Properties from a ThingWorx platform Thing or the returned Properties of a Service can be done using the TW_GET_PROPERTY macro. Examples of its use can be seen in all of the provided applications. An example can be seen below:

 

int flow = TW_GET_PROPERTY(thingName, "TotalFlow").number;
int pressue = TW_GET_PROPERTY(thingName, "Pressure").number;
twLocation location = TW_GET_PROPERTY(thingName, "Location").location;
int temperature = TW_GET_PROPERTY(thingName, "Temperature").number;

 

Write Properties

 

Writing Properties to a ThingWorx platform Thing from a variable storing is value uses a similarly named method. Using the TW_SET_PROPERTY macro will be able to send values to the platform. Examples of its use can be seen in all of the provided applications. An example is shown below:

 

TW_SET_PROPERTY(thingName, "TotalFlow", TW_MAKE_NUMBER(rand() / (RAND_MAX / 10.0)));
TW_SET_PROPERTY(thingName, "Pressure", TW_MAKE_NUMBER(18 + rand() / (RAND_MAX / 5.0)));
TW_SET_PROPERTY(thingName, "Location", TW_MAKE_LOC(gpsroute[location_step].latitude,gpsroute[location_step].longitude,gpsroute[location_step].elevation));

 

This macro utilizes the twApi_PushSubscribedProperties function call to pushe all property updates to the server. This can be seen in the updateTruckThing function in deliveryTruck.c.

 

Property Change Listeners

 

Using the Observer pattern, you can take advantage of the Property change listener functionality. With this pattern, you create functions that will be notified when a value of a Property has been changed (whether on the server or locally by your program when the TW_SET_PROPERTY macro is called).

 

Add a Property Change Listener

 

In order to add a Property change listener, call the twExt_AddPropertyChangeListener function using the:

 

  • Name of the Thing (entityName)
  • Property this listener should watch
  • Function that will be called when the property has changed
void simplePropertyObserver(const char * entityName, const char * thingName,twPrimitive* newValue){
    printf("My Value has changed\n");
}

void test_simplePropertyChangeListener() {
    {
        TW_MAKE_THING("observedThing",TW_THING_TEMPLATE_GENERIC);
        TW_PROPERTY("TotalFlow", TW_NO_DESCRIPTION, TW_NUMBER);
    }
    
    twExt_AddPropertyChangeListener("observedThing",TW_OBSERVE_ALL_PROPERTIES,simplePropertyObserver);
    TW_SET_PROPERTY("observedThing","TotalFlow",TW_MAKE_NUMBER(50));
}

 

NOTE: Setting the propertyName parameter to NULL or TW_OBSERVE_ALL_PROPERTIES, the function specified by the propertyChangeListenerFunction parameter will be used for ALL properties.

 

Remove a Property Change Listener

 

In order to release the memory for your application when done with utilizing listeners for the Property, call the twExt_RemovePropertyChangeListener function.

 

void simplePropertyObserver(const char * entityName, const char * thingName,twPrimitive* newValue){
    printf("My Value has changed\n");
}

twExt_RemovePropertyChangeListener(simplePropertyObserver);

 

Click here to view Part 3 of this guide

 

Version history
Last update:
‎Mar 07, 2023 02:01 PM
Updated by:
Labels (2)
Contributors