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

IoT Tips

Sort by:
    Step 3 : Sending and Receiving JSON Objects   The ThingWorx platform handles REST requests by default. This enables all services to be outsourced to REST requests based on the permissions of the user.   Nevertheless, part of the problem with allowing the default JSON result might be the organization of the response. For example, making a request to a service with an InfoTable response will return information for the DataShape used by the InfoTable and a 'rows' field containing the data of the InFoTable. This can be troublesome or a nuisance when creating efficient B2B communication or parsers for the ThingWorx response.   Receiving JSON   First, let's handle the necessary security measures and configure our permissions to create a new User and Application Key. Then, handle how to parse a JSON object in the body of the POST REST request to the ThingWorx Platform. As an example, you will create a service that will take in a person JSON object and perform some simple calculations for the response. The simple JSON object is as follows: { "person": { "first_name": "John", "last_name": "Doe", "dob": "03/16/1989", "roles": [ { "role": "Manager" }, { "role": "Executive" } ] } }   Follow the steps below to set up a helper function to perform age calculations, and another to take this JSON object and simply return a response based on the age of the person: In ThingWorx Composer, click the + New at the top of the screen. Select Thing in the dropdown. Name the Thing JSONResponseExample and click Save. Click the Services tab. Create a new service called CalculatePersonAge. Set the Output as Integer. Add the following Input: Name Base Type Required dob String True   8. Add the following JavaScript to help encode the string and return an HTML friendly string. var result = 0; try { if(dob) { var today = new Date(); var birthDate = new Date(dob); var age = today.getFullYear() - birthDate.getFullYear(); var month = today.getMonth() - birthDate.getMonth(); if (month < 0 || (month === 0 && today.getDate() < birthDate.getDate())) { age--; } result = age; } } catch(err) { logger.error("JSONResponseThing.CalculatePersonAge(): An error occured while calculating an age - " + err.message); }   9. Click Done. 10. Click Save and you're all done with this helper service. This is a simple function to calculate a person's age with limited error handling for simplicity. Now let's handle the JSON object coming in the request and our response.   In the Services tab of the JSONResponseExample Thing, create a new service called HandleJSONRequest. The service will have the below properties as parameters. Name Base Type Required person JSON True   3. Set the Output as JSON. 4. Add the following JavaScript to help encode the string and return an HTML friendly string. var result = {}; result.message = ""; if(!person) { result.message = "We need a person to calculate their age."; } else if(!person.dob) { result.message = "We need the person's date of birth to calculate their age."; } else { if(!person.first_name) { result.message = "The person you provided is " + me.CalculatePersonAge({dob: person.dob}) + " years old"; } else { result.message = person.first_name + " is " + me.CalculatePersonAge({dob: person.dob}) + " years old"; } }   5. Click Done and go to the Permissions tab. 6. Configure the permissions of the JSONResponseExample thing to allow access to the User you created earlier. This user will need to have runtime permissions to execute the service and must belong in an organization with visibility (ie, Everyone). 7. Click Save, and you're done.   You've just created a service that takes JSON and returns JSON. There are numerous services to work with JSON objects. There is also a service to convert your JSON object to an InfoTable, FromJSON in the InfoTableFunctions Resource. Keep in mind, you will need to set the JSON to a form that can be translated to an InfoTable. If this format is unknown, use the ToJSON service from this Resource to see an example.   Running REST Request   If you need a quick refresher on how to run a REST request to the ThingWorx Platform, please see our REST API guide. The request to the ThingWorx Platform will be a POST method and you will need to set your Application Key in the header.   Sending JSON   Because services are based on JavaScript (Rhino JavaScript Engine), you can create objects the same way you would anywhere else. This is a very simple concept, but it becomes more complex as you try to create data based on ThingWorx-specific entities or models.   To convert an InfoTable to a better-formed JSON object, you will need to process the InfoTable rows based on the DataShape fields. The following code will do that: /* ...Perform code that creates an InfoTable called values... */ //Begin Processing the rows of data var result = {}; result.some_information = "some values"; result.data = []; var fields = values.dataShape.fields; for (var index = 0; index < values.getRowCount(); index++) { var entry = {}; for (var name in fields) { entry[name] = values.rows[index][name]; } result.data.push(entry); } Looking for a quick translation to JSON? Try the ReadEntityAsJSON service of the EntityServices Resource. You can use this to respond with complex ThingWorx models or just to see the setup for the JSON object in order to translate it to something simple the way the code above handles InfoTables. For a quick example, create a User, then create a service based on the below JavaScript (set the name field of the parameter to the name of the user you create): var params = { name: 'NameOfUserYouCreated' /* STRING */, type: 'Users' /* STRING */, key: 'SomeValue /* STRING - Encryption-Decrption Key Name is Optional*/ }; // result: JSON var result = Resources["EntityServices"].ReadEntityAsJSON(params);     Step 4: Sending XML Based Requests    There are many B2B services and applications that prefer to use XML over JSON. ThingWorx can send/receive XML via SOAP requests (POST) using the ContentLoaderFunctions Resource.   To get started, create a Thing using the below steps. You will create new services in this Thing to make SOAP requests.   NOTE: Examples of these services can be found in the XMLRequestThing entity, which is provided in the download.   You will use the PostXML service of the ContentLoaderFunctions Resource. This service takes parameters from the proxy information to handle SSL issues. All of the parameters are optional.   Perform the following steps to create your ThingWorx service to make requests.   In the ThingWorx Composer, click the + New at the top of the screen. Select Thing in the dropdown. Name the Thing XMLRequestExample and click Save. Click the Services tab and create a service called SendXMLRequest. The service will have the below properties as parameters. Name Base Type Required url String True body XML True   6. In the Snippets section, filter and search for PostXML. 7. Once you’ve found PostXML under the ContentLoaderFunctions section, add it to the editor. You’ll see all of the possible parameters for the request. In this example, you will set only the url and content values. 8. Update the code snippet to include the parameters. Use the below code as a reference: try { var params = { url: url /* STRING */, content: body /* XML */, }; // result: XML var result = Resources["ContentLoaderFunctions"].PostXML(params); logger.info(" XMLRequestThing.SendXMLRequest(): Results From Calling Service - " + JSON.stringify(result)); } catch(error) { logger.error(" XMLRequestThing.SendXMLRequest(): Error Calling Service - " + error.message); }   9. Click Save and you’re done with your first SOAP request. You can now enter your XML string as a parameter to call your new service. You can also assign your XML string directly to a variable in the service.   /*jshint multistr: true */ var body = ' \ <?xml version="1.0" encoding="UTF-8"?> \ <menu> \ <header> \ <title>A Cool Title</title> \ </header> \ <body> \ <lunch_menu> \ <food> \ <name>Belgian Waffles</name> \ <price>$5.95</price> \ <description>Two of our famous Belgian Waffles with plenty of real maple syrup</description> \ <calories>650</calories> \ </food> \ <food> \ <name>Strawberry Belgian Waffles</name> \ <price>$7.95</price> \ <description>Light Belgian waffles covered with strawberries and whipped cream</description> \ <calories>900</calories> \ </food> \ </lunch_menu> \ <breakfast_menu> \ <food> \ <name>Belgian Waffles</name> \ <price>$5.95</price> \ <description>Two of our famous Belgian Waffles with plenty of real maple syrup</description> \ <calories>650</calories> \ </food> \ <food> \ <name>Strawberry Belgian Waffles</name> \ <price>$7.95</price> \ <description>Light Belgian waffles covered with strawberries and whipped cream</description> \ <calories>900</calories> \ </food> \ <food> \ <name>Berry-Berry Belgian Waffles</name> \ <price>$8.95</price> \ <description>Light Belgian waffles covered with an assortment of fresh berries and whipped cream</description> \ <calories>900</calories> \ </food> \ <food> \ <name>French Toast</name> \ <price>$4.50</price> \ <description>Thick slices made from our homemade sourdough bread</description> \ <calories>600</calories> \ </food> \ <food> \ <name>Homestyle Breakfast</name> \ <price>$6.95</price> \ <description>Two eggs, bacon or sausage, toast, and our ever-popular hash browns</description> \ <calories>950</calories> \ </food> \ </breakfast_menu> \ </body> \ </menu>'; ```   Click here to view Part 3 of this guide.
View full tip
    Modernize your Mashups with CSS to enhance the presentation of your application.   GUIDE CONCEPT   This project will introduce using CSS to create a customized, consistent look and feel for your IoT application.   Following the steps in this guide, you will create a custom CSS class definitions and bind these classes to Mashup features.   We will teach you how to present a professional-looking user interface and ensure consistency of style treatments within your application by implementing Cascading Style Sheets (CSS) in Mashups.     You'll learn how to   Create custom CSS classes using the integrated CSS editor Bind CSS classes to a Mashup and to individual Widgets Use Media queries to dynamically apply styling     Step 1: Custom CSS Benefits   You now have more flexibility to customize your application’s UI and improve the user experience using industry-standard web techniques. You can implement CSS in ThingWorx to control the visualization of your Mashup.   Feature                   Benefit Text Treatments Optimize text with shadow, color, font, and border Responsive UI Customize layout based on user actions and the data being displayed Media Queries Accommodate many screen sizes with flexboxes and other standard containers Animations Implement standard CSS key frames Customizations Modify application appearance without changing source Mashup Linting Expedite development with code auto-completion and design-time syntax warnings       Step 2: Access Sample Files   We created sample entities you can use to complete the steps in this guide. Download the attached Mashups_CustomCssTutorialMashup.xml From the Home page of Composer, click the Import/Export icon, then choose Import   Keep the default options and click Browse. Locate and select the CustomCssTutorialMashup.xml file you downloaded and extracted, click Open then Import.   Click Close after the Import successful message is displayed. Click the Browse tab in the left navigation panel, then click Mashups.                     6. Select the CustomCssTutorialMashup.                 7. Click View Mashup to view the Mashup.     NOTE: This is a simple Mashup designed to demonstrate how the UI changes when CSS is applied.       Step 3: Create CSS Rule Block   In this step, you will use the built-in editor to create a custom CSS class that will be used in the next step to modify the appearance of three buttons grouped by the Fieldset Widget.   Open the CustomCssTutorialMashup in Edit and Design view.     Click Custom CSS.     Copy the CSS class below and paste it into the Custom CSS editor: .myMashupClass .widget-fieldset .widget-ptcsbutton { box-shadow: 5px 5px 5px #888888; } NOTE: This class will create a shadow around all of the buttons that are in a Fieldset container  only after it is bound to a Mashup,   4. Click Save.     Tips   Press Ctrl -> Space to use the Auto-complete feature and see code snippets, which can expedite your development time.     The Linting feature will warn you if there are errors in your code, so you can fix them at design time.       Step 4: Apply Custom Class to Mashup   In this step we will demonstrate how to modify the look and feel of a Mashup without changing the Mashup itself. The myMashupClass we just created chains two selectors: the widget-fieldset and the widget-button. Only Widgets that are in both selector categories will be modified.   Click Design and select the Explorer tab, then select the top-level Mashup.     In the property panel in the lower left, locate the CustomClass property and type myMashupClass as the value. Press Tab to save the value change.     WARNING: You must press Tab after every property change in order for the new value to be saved.   4. Click Save then View Mashup to see that the buttons in the Field Set have shadow borders.       Step 5: Apply Custom Class to Widget   In addition to the Mashup level, you can apply style treatments directly to a Widget in your Mashup. In ThingWorx, the following Widgets have a CustomClass property you can modify:     For this example, we will make the text on one of the buttons all caps.   In the CustomCssTutorialMashup, click Custom CSS. Add the following css code: .myButtonClass .widget-ptcsbutton { text-transform: uppercase; }     Return to the Design view, and In the Explorer tab, click the button-3.     In the Property panel, enter myMashupClass to the CustomClass field, then press tab     Save then View Mashup the Mashup to see that the button text is now all caps.       Step 6: Bind Custom Class   The UI of a Mashup can be dynamically updated at runtime by binding the value of the CustomClass property to a dynamic data source such as: Services Mashup parameters Widgets (expression widgets for example)   In this portion of the guide, we will demonstrate modifying a Mashup in response to user actions:   Return to the Design view for the CustomCssTutorialMashup. In the Mashup Builder, click the Functions tab in the lower right, then expand Event Routers and expand eventsrouter-6     Click Output property and drag it onto the bottom button of the group of three buttons.     Select the CustomClass property from the pop-up to bind it to Button-4   In Mashup Builder click Custom CSS tab. Add the following css code: .myBoundButtonClass1 .widget-ptcsbutton { text-transform: lowercase; } .myBoundButtonClass2 .widget-ptcsbutton { text-transform: uppercase; }           7. Click Save and then View Mashup.           8. Click on each of the Apply buttons to see the results of a CSS class applied to in response to user actions.     Step 7: Use Media Queries   You can use Media queries to apply styling based on the characteristics of the device being used to access the application. For this example, we will use a CSS Class to hide three elements when the browser’s width is less than 600 pixels wide.   1. Open the CustomCssTutorialMashup in Edit and Design view, then click Custom CSS.     2. Copy the CSS class below and use the Custom CSS editor to add it to the top of the existing  CSS, then click Save. @media screen and (max-width: 1000px) { #root_ptcslabel-10-bounding-box { visibility: hidden; } #root_ptcstextfield-7-bounding-box{ visibility: hidden; } #root_ptcstextfield-12-bounding-box { visibility: hidden; } }   NOTE: The ID selector in your CSS must add root_ to the beginning, and -bounding-box to the end of the element’s ID shown in Mashup Builder.   3. Click View Mashup, then click and drag the edge of the browser window to reduce the width below 600 pixels.     NOTE: The three Widgets selected in the media class added in the last step will disappear as soon as the browser is less than 600 pixels wide.       Click here to view Part 2 of this guide.
View full tip
    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:    Name                   Structure            Description Property Definitions twPropertyDef Describes the basic information for the Properties that will be available to ThingWorx and can be added to a client application. Property Values twProperty Associates 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 push 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);       Step 6: Data Shapes   Data Shapes are an important part of creating/firing Events and also invoking Services.   Define With Macros   In order to define a Data Shape using a macro, use TW_MAKE_DATASHAPE.   NOTE: The macros are all defined in the twMacros.h header file.   TW_MAKE_DATASHAPE("SteamSensorReadingShape", TW_DS_ENTRY("ActivationTime", TW_NO_DESCRIPTION ,TW_DATETIME), TW_DS_ENTRY("SensorName", TW_NO_DESCRIPTION ,TW_NUMBER), TW_DS_ENTRY("Temperature", TW_NO_DESCRIPTION ,TW_NUMBER), TW_DS_ENTRY("Pressure", TW_NO_DESCRIPTION ,TW_NUMBER), TW_DS_ENTRY("FaultStatus", TW_NO_DESCRIPTION ,TW_BOOLEAN), TW_DS_ENTRY("InletValve", TW_NO_DESCRIPTION ,TW_BOOLEAN), TW_DS_ENTRY("TemperatureLimit", TW_NO_DESCRIPTION ,TW_NUMBER), TW_DS_ENTRY("TotalFlow", TW_NO_DESCRIPTION ,TW_INTEGER) );   Define Without Macros   In order to define a Data Shape without using a macro, use the twDataShape_CreateFromEntries function. In the example below, we are creating a Data Shape called SteamSensorReadings that has two numbers as Field Definitions.   twDataShape * ds = twDataShape_Create(twDataShapeEntry_Create("a",NULL,TW_NUMBER)); twDataShape_AddEntry(ds, twDataShapeEntry_Create("b",NULL,TW_NUMBER)); /* Name the DataShape for the SteamSensorReadings service output */ twDataShape_SetName(ds, "SteamSensorReadings");     Step 7: Events and Services   Events and Services provide useful functionality. Events are a good way to make a Service be asynchronous. You can call a Service, let it return, then your Entity can subscribe to your Event and not keep the original Service function waiting. Events are also a good way to allow the platform to respond to data when it arrives on the edge device without it having to poll the edge device for updates.   Fire Events   To fire an Event you first need to register the Event and load it with the necessary fields for the Data Shape of that Event using the twApi_RegisterEvent function. Afterwards, you would send a request to the ThingWorx server with the collected values using the twApi_FireEvent function. An example is as follows:   twDataShape * ds = twDataShape_Create(twDataShapeEntry_Create("message", NULL,TW_STRING)); /* Event datashapes require a name */ twDataShape_SetName(ds, "SteamSensorFault"); /* Register the service */ twApi_RegisterEvent(TW_THING, thingName, "SteamSensorFault", "Steam sensor event", ds); …. struct { char FaultStatus; double Temperature; double TemperatureLimit; } properties; …. properties. TemperatureLimit = rand() + RAND_MAX/5.0; properties.Temperature = rand() + RAND_MAX/5.0; properties.FaultStatus = FALSE; if (properties.Temperature > properties.TemperatureLimit && properties.FaultStatus == FALSE) { twInfoTable * faultData = 0; char msg[140]; properties.FaultStatus = TRUE; sprintf(msg,"%s Temperature %2f exceeds threshold of %2f", thingName, properties.Temperature, properties.TemperatureLimit); faultData = twInfoTable_CreateFromString("message", msg, TRUE); twApi_FireEvent(TW_THING, thingName, "SteamSensorFault", faultData, -1, TRUE); twInfoTable_Delete(faultData); }   Invoke Services   In order to invoke a Service, you will use the twApi_InvokeService function. The full documentation for this function can be found in [C SDK HOME DIR]/src/api/twApi.h. Refer to the table below for additional information.    Parameter         Type                  Description entityType Input The type of Entity that the service belongs to. Enumeration values can be found in twDefinitions.h. entityName Input The name of the Entity that the service belongs to. serviceName Input The name of the Service to execute. params Input A pointer to an Info Table containing the parameters to be passed into the Service. The calling function will retain ownership of this pointer and is responsible for cleaning up the memory after the call is complete. result Input/Output A pointer to a twInfoTable pointer. In a successful request, this parameter will end up with a valid pointer to a twInfoTable that is the result of the Service invocation. The caller is responsible for deleting the returned primitive using twInfoTable_Delete. It is possible for the returned pointer to be NULL if an error occurred or no data is returned. timeout Input The time (in milliseconds) to wait for a response from the server. A value of -1 uses the DEFAULT_MESSAGE_TIMEOUT as defined in twDefaultSettings.h. forceConnect Input A Boolean value. If TRUE and the API is in the disconnected state of the duty cycle, the API will force a reconnect to send the request.   See below for an example in which the Copy service from the FileTransferSubsystem is called:   twDataShape * ds = NULL; twInfoTable * it = NULL; twInfoTableRow * row = NULL; twInfoTable * transferInfo = NULL; int res = 0; const char * sourceRepo = "SimpleThing_1"; const char * sourcePath = "tw/hotfolder/"; const char * sourceFile = "source.txt"; const char * targetRepo = "SystemRepository"; const char * targetPath = "/"; const char * targetFile = "source.txt"; uint32_t timeout = 60; char asynch = TRUE; char * tid = 0; /* Create an infotable out of the parameters */ ds = twDataShape_Create(twDataShapeEntry_Create("sourceRepo", NULL, TW_STRING)); res = twDataShape_AddEntry(ds, twDataShapeEntry_Create("sourcePath", NULL, TW_STRING)); res |= twDataShape_AddEntry(ds, twDataShapeEntry_Create("sourceFile", NULL, TW_STRING)); res |= twDataShape_AddEntry(ds, twDataShapeEntry_Create("targetRepo", NULL, TW_STRING)); res |= twDataShape_AddEntry(ds, twDataShapeEntry_Create("targetPath", NULL, TW_STRING)); res |= twDataShape_AddEntry(ds, twDataShapeEntry_Create("targetFile", NULL, TW_STRING)); res |= twDataShape_AddEntry(ds, twDataShapeEntry_Create("async", NULL, TW_BOOLEAN)); res |= twDataShape_AddEntry(ds, twDataShapeEntry_Create("timeout", NULL, TW_INTEGER)); it = twInfoTable_Create(ds); row = twInfoTableRow_Create(twPrimitive_CreateFromString(sourceRepo, TRUE)); res = twInfoTableRow_AddEntry(row, twPrimitive_CreateFromString(sourcePath, TRUE)); res |= twInfoTableRow_AddEntry(row, twPrimitive_CreateFromString(sourceFile, TRUE)); res |= twInfoTableRow_AddEntry(row, twPrimitive_CreateFromString(targetRepo, TRUE)); res |= twInfoTableRow_AddEntry(row, twPrimitive_CreateFromString(targetPath, TRUE)); res |= twInfoTableRow_AddEntry(row, twPrimitive_CreateFromString(targetFile, TRUE)); res |= twInfoTableRow_AddEntry(row, twPrimitive_CreateFromBoolean(asynch)); res |= twInfoTableRow_AddEntry(row, twPrimitive_CreateFromInteger(timeout)); twInfoTable_AddRow(it,row); /* Make the service call */ res = twApi_InvokeService(TW_SUBSYSTEM, "FileTransferSubsystem", "Copy", it, &transferInfo, timeout ? (timeout * 2): -1, FALSE); twInfoTable_Delete(it); /* Grab the tid */ res = twInfoTable_GetString(transferInfo,"transferId",0, &tid);   Bind Event Handling   You may want to track exactly when your edge Entities are successfully bound to or unbound from the server. The reason for this is that only bound items should be interacting with the ThingWorx Platform and the ThingWorx Platform will never send any requests targeted at an Entity that is not bound. A simple example that only logs the bound Thing can be seen below. After creating this function, it will need to be registered using the twApi_RegisterBindEventCallback function before the connection is made.   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); } …. twApi_RegisterBindEventCallback(thingName, BindEventHandler, NULL);   OnAuthenticated Event Handling   You may also want to know exactly when your Edge device has successfully authenticated and made a connection to the ThingWorx platform. Like the bind Event handling, this function will need to be made and registered. To register this handler, use the twApi_RegisterOnAuthenticatedCallback function before the connection is made. This handler form can also be used to do a delay bind for all Things.   void AuthEventHandler(char * credType, char * credValue, void * userdata) { if (!credType || !credValue) return; TW_LOG(TW_FORCE,"AuthEventHandler: Authenticated using %s = %s. Userdata = 0x%x", credType, credValue, userdata); /* Could do a delayed bind here */ /* twApi_BindThing(thingName); */ } … twApi_RegisterOnAuthenticatedCallback(AuthEventHandler, NULL);     Click here to view Part 3 of this guide.
View full tip
    Step 6: Configure EMS   The EMS consists of two distinct components that perform slightly different operations and communicate with each other.   The first is the EMS itself which creates an AlwaysOn™ connection to ThingWorx Foundation. It binds Things to the platform and automatically provides features like file transfer and tunneling.   The second is the Lua Script Resource (LSR). It is used as a scripting language so that you can add Properties, Services, and Events to the Things that you create in the EMS.     Now that you have "installed" (i.e. downloaded, unzipped, and moved to an appropriate location) the EMS on your Raspberry Pi, it needs to be configured.   The primary method of doing so is via the config.json and config.lua files.   In this step, we'll create these files and paste some JSON / Lua configuration into them.   Navigate to the /etc directory.       Right-click inside the folder’s white-space and select New File.... Enter config.json and click OK.   Right-click on the new config.json file and select Text Editor.     Copy and Paste the following code into the empty config.json file: Note that the backslashes (\) in the JSON below are escape characters necessary to properly address special characters, such as the forward-slashes (/) indicating path directories. { "ws_servers": [{ "host": "YOUR_IP_ADDRESS_HERE", "port": 443 }], "appKey": "YOUR_APP_KEY_HERE", "logger": { "level": "INFO", "publish_directory": "\/home\/pi\/Downloads\/microserver\/logs", "publish_level": "INFO", "max_file_storage": 2000000, "auto_flush": true }, "http_server": { "ssl": false, "authenticate": false }, "ws_connection": { "encryption": "ssl" }, "certificates": { "validate": false, "disable_hostname_validation": true }, "tunnel": { "buffer_size": 8192, "read_timeout": 10, "idle_timeout": 300000, "max_concurrent": 4 }, "file": { "buffer_size": 8192, "max_file_size": 8000000000, "virtual_dirs": [ {"other": "\/home\/pi\/Downloads\/microserver\/other"}, {"tw": "\/home\/pi\/Downloads\/microserver\/tw"}, {"updates": "\/home\/pi\/Downloads\/microserver\/updates"} ], "staging_dir": "\/home\/pi\/Downloads\/microserver\/staging" } } When the EMS runs, the config.json file will answer the following questions: Code Section Questions Answered ws_servers At what IP address / port is the ThingWorx Server located? appKey What is your Application Key? logger Where, and at what level, should we log errors? http_server What port should the WSEMS use to setup an HTTP server? ws_connection Should we use encryption? certificates Are we using Security Certificates? tunnel What are the configuration parameters for remote-tunneling? file What are the configuration parameters for file-transfer? We pre-defined the parameters for everything that we could, but you will still need to tell the WSEMS the IP address where the ThingWorx instance is located and a valid Application Key you either created earlier or may create now.   TIP: You may have noticed the pre-existing config.json.complete and config.json.minimal files. These are example files that come with the WSEMS and are provided as an aid. The code above which you copied into your own config.json file is simply a customization of these aids. In particular, you may wish to look through the config.json.complete file, as it shows every available option which you might want to configure if you choose to make a custom application with the WSEMS. The config.json.complete file also contains comments for each of these options. However, a functional config.json file may NOT contain comments of any kind, so you would need to remove all comments if you choose to copy/paste some code from that file into a functional config.json of your own making.     Modify config.json to point to ThingWorx Foundation   Change YOUR_IP_ADDRESS_HERE to the IP address of your hosted ThingWorx instance. You may wish to e-mail yourself the Foundation IP address using a web-mail account so that you can copy/paste on the Pi from your e-mail to the config.json file. Note that you may use a URL, such as "pp-180207xx36jd.devportal.ptc.io". Either way, the IP or URL must be enclosed in quotation marks (""). Also, Port 443 is the appropriate port for the ThingWorx hosted server. Ports for local-install may vary. 2. Change YOUR_APP_KEY_HERE to an Application Key which you have previously created. Or create a new Application Key now. You may wish to e-mail yourself the Application Key using a web-mail account so that you can copy/paste on the Pi from your e-mail to the config.json file.   3. Save and exit the file.   Create a config.lua file   Navigate to the /etc directory. Right-click inside the folder’s white-space and select New File.... Enter config.lua and click OK. Right-click on the new config.lua file and select Text Editor. Copy and Paste the following code into the empty config.lua file: scripts.log_level = "WARN" scripts.script_resource_ssl = false scripts.script_resource_authenticate = false scripts.PiThing = { file = "thing.lua", template = "YourEdgeThingTemplate", scanRate = 120000, sw_update_dir = "\/home\/pi\/Downloads\/microserver\/updates" } Save and exit the file.   Create a Custom Template for the EdgeThing   Navigate to /etc/custom/templates. Right-click inside the folder’s white-space and select New File.... Enter YourEdgeThingTemplate.lua and click OK. Right-click on the new YourEdgeThingTemplate.lua file and select Text Editor. Copy and Paste the following code into the empty YourEdgeThingTemplate.lua file: require "shapes.swupdate" module ("templates.YourEdgeThingTemplate", thingworx.template.extend) Save and exit the file.      Step 7: Connect EMS   In this step, you'll launch the EMS so that it can communicate with your ThingWorx Foundation platform.   On the Raspberry Pi , open a Terminal by clicking the Terminal icon in the top-left.   Navigate to the EMS's root folder, i.e. /home/pi/Downloads/microserver , by issuing the following command and then pressing Enter : cd /home/pi/Downloads/microserver   In the Terminal window, enter the command sudo ./wsems and press Enter . Note: Do not close this window, or the connection to the ThingWorx platform will close. Also, look through the output in the wsems window. Near the end, you should see Successfully connected. Saving .booted config file . If you do not see the Saving .booted comment, then you likely have an error in your config.json file... especially with either the address or Application Key .   Open another Terminal window as per the above instructions.   In this second Terminal window, Navigate to the EMS's root directory, i.e. /home/pi/Downloads/microserver , by issuing the following command and pressing Enter : cd /home/pi/Downloads/microserver In the second Terminal window, enter the command sudo ./luaScriptResource and press Enter . Note: Do not close this second Terminal window, or the connection to the ThingWorx platform will close.   NOTE: When the scripts start running, the EMS attempts to talk to the ThingWorx platform. However, at this point in the tutorial, ThingWorx does not have detailed information about the Edge device that is attempting to connect to it, so you will see an error message. This is the expected behavior which we will resolve in the next step. The wsems program runs through the config.json file in order to extract the basic connectivity information to reach the ThingWorx platform. The luaScriptResource program runs through the config.lua file to extract to which Thing the WSEMS should be connecting. Both programs must be running in order to achieve connectivity with ThingWorx. Program File Accessed Purpose wsems config.json Extracts basic connectivity information to reach the ThingWorx platform. luaScriptResource config.lua Determines to which Thing the WSEMS should connect. NOTE : Since the config.lua file which we previously created has a reference to a custom template, it also accesses the YourEdgeThingTemplate.lua file to extend the base functionality. Both programs must be running in order to achieve connectivity with ThingWorx. Troubleshoot Connectivity Issues   If the websocket does not connect successfully, check the following:   Issue Solution WEBSOCKET CLOSED - Warning seen immediately after Websocket gets connected. Ensure that the host IP address, port, and appKey of the ThingWorx composer instance are accurately set. If, in config.json, you have selected the option to validate certification, then make sure the path to the certificate file is correctly set. twWs_Connect - Error trying to connect. Ensure that the host IP address and port running the ThingWorx Composer is accurately set. Check if the certification parameter is set or not. By default, the WS EMS validates certificates. To ensure that the validation is performed correctly without errors, ensure that the certificates configuration parameters are set accurately with the correct path to the certificate file. If you do not wish to validate the certificate, you may explicitly set the validate parameter in certificates parameter set to false. twTlsClient_Connect - Error intializing TLS connection. Invalid certificate. Check if the ws_encryption parameter is present in your config.json file. By default, WS EMS enables TLS connection to the ThingWorx Platform. Ensure that the certificate file mentioned in config.json is valid and stored in the path specified. For debugging purposes, you can set the ssl parameter to none in ws_encryption configuration parameter. [WARN ] ... Main - Unable to connect to server. Trying .booted config file. Ensure that the host is up and running at the IP address and port number mentioned in the config.json file. Ensure that ThingWorx is running on the host address at the correct port number. Ensure that all necessary ports are open for communication.     Click here to view Part 4 of this guide.
View full tip
    Use the Pareto Chart Widget to visualize how issues compound to cause problems.   GUIDE CONCEPT   The Pareto Chart Widget is a useful method of displaying aggregate information.  In particular, it is often used to display multiple issues and how they combine to form an overall, larger problem.    This can be helpful when trying to determine "easy wins" by pointing out where your efforts will have the greatest impact.       YOU'LL LEARN HOW TO   Create a Data Shape Create a Thing Create an Info Table Property Populate an Info Table with appropriate data for a Pareto Chart Create a Mashup Utilize a Pareto Chart to display issue-aggregation   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete this guide is 30 minutes       Step 1: Scenario   In this guide, we'll assume a scenario where a factory is being automated using ThingWorx Foundation. In particular, this factory has some known issues with a robot arm that performs welding at a point along a conveyor belt.    When this welding robot has these issues, the factory line has to come to a complete halt while maintenance is performed on it.   Management has decided that these slow-downs are costing enough money that the robot arm needs some extra attention, up to and including modification to help alleviate these maintenance stops.    However, they're not sure what to tackle first. Every issues leads to a slow down, but some happen more frequently than others.    After talking with maintenance, four primary issues are identified, i.e.   Excess temperature on the welding end has caused some welds to fail due to simply burning through the material. Some of the joints need regular lubrication, preventing the arm from getting to the correct location in time as the part moves down the conveyor belt. The welding filler-material sometimes runs out, causing a stop while more is reloaded. The welding shielding gas sometimes runs out, causing a stop while more is reloaded.   Your task, then, is to start counting the number of times each of these failures occur. In addition, you need to create a small GUI which displays both how often these errors occur, and how they contribute to the overall downtime.    To accomplish this, you'll use a Pareto Chart Widget.     Step 2: Create Data Shape   In this scenario, we'll store the Pareto Chart's data in a Property type called an Info Table.   An Info Table is a spreadsheet-like Property, but in order to define the columns of the table, we first have to define a Data Shape. We'll do that in this step.   In the left-side navigation, click Browse > Modeling > Data Shapes. At the top, click + New. In the Name field, type TIPC_DataShape. If Project is not already set, search for and select PTCDefaultProject. At the top, click Field Definitions. At the top-left, click + Add. On the right-side slide-out, in the Name field, type month. Note that you want to leave "Base Type" as the default of "STRING". Check Is Primary Key. Click the "check with a plus" button for Done and Add. Add each of the following Field Definitions, entering the Name and selecting the Base Type from the drop-down as described in the table: Note that you will NOT enable "Is Primary Key" on any other Field Definitions, as you only need one Primary Key. Note that you will simply click the "check" button for Done after the last entry . Name Base Type  excess_temperature NUMBER  need_lubricant NUMBER  low_filler NUMBER  low_gas NUMBER At the top, click Save.   Step 3: Create Thing   Now that we have our Data Shape, we can create a Thing to hold the collected counts of various issues.   As already mentioned, we'll use an Info Table Property, formatted by the previously-created Data Shape, to do so.   Click Browse > Modeling > Things.   Click + New. In the Name field, type TIPC_Thing. If Project is not already set, search for and select PTCDefaultProject. In the Base Thing Template field, search for and select GenericThing.   At the top, click Save.     Add Info Table Property   Now that we have our Thing instantiated, we want to both add an Info Table Property, as well as set some Default Values.   At the top, click Properties and Alerts.   Click + Add.   On the right-side slide-out, in the Name field, type InfoTable_Property. Change Base Type to INFOTABLE. In the Data Shape field, search for and select TIPC_DataShape. Note that the Data Shape field will not appear until you set Base Type to INFOTABLE. Check Persistent.   At the top-right, click the "check" button for Done. At the top, click Save.   Set Value of Property Now that we have a place in which to store spreadsheet-like values, we'll do so manually for testing.   On the InfoTable_Property row, under the Value column, click the "pencil" icon for Set value of property.   On the pop-up, click + Add.   Enter the following values in each field as per the table below: Field Name Value month  January excess_temperature 5 need_lubricant 2 low_filler 1 low_gas 2   Click Add.   Click + Add again, enter the following values, and finish input by clicking Add, as per above. Field Name Value month February excess_temperature 7 need_lubricant 1 low_filler 3 low_gas 2 6. Click + Add again, enter the following values, and finish input by clicking Add, as per above. Field Name Value month March excess_temperature 6 need_lubricant 2 low_filler 1 low_gas 1   7. On the pop-up, click Save.   8. At the top, click Save.   Step 4: Create Mashup   Now that we have our data in-place for testing (and could be connected to automated systems after we finish testing), we need to visualize the data.   As mentioned, we'll use a Pareto Chart Widget, but first, we need to create a Mashup into which we can place the Widget.   Click Browse > Visualization > Mashups.   Click + New.   Leave the defaults and click OK.   In the Name field, type TIPC_Mashup. If Project is not already set, search for and select PTCDefaultProject. At the top, click Save .   At the top, click Design.   At the top-left, click the Widgets tab.   Drag-and-drop a Pareto Chart Widget onto the central Canvas.   At the top, click Save.   Click here to view Part 2 of this guide.
View full tip
    Step 8: Tasks   If you are using the built-in Tasker to drive data collection or other types of repetitive or periodic activities, create a function for the task. Task functions are registered with the Tasker and then called at the rate specified after they are registered. The Tasker is a very simple, cooperative multitasker, so these functions should not take long to return and most certainly must not go into an infinite loop.   The signature for a task function is found in [C SDK HOME DIR]/src/utils/twTasker.h. The function is passed a DATETIME value with the current time and a void pointer that is passed into the Tasker when the task is registered. After creating this function, it will need to be registered using the twApi_CreateTask function after the connection is created. Below shows an example of creating this function, registering this function, and how this function can be used.   #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("message", msg, TRUE); twApi_FireEvent(TW_THING, thingName, "SteamSensorFault", faultData, -1, TRUE); twInfoTable_Delete(faultData); } /* Update the properties on the server */ sendPropertyUpdate(); } … twApi_CreateTask(DATA_COLLECTION_RATE_MSEC, dataCollectionTask); … while(1) { char in = 0; #ifndef ENABLE_TASKER DATETIME now = twGetSystemTime(TRUE); twApi_TaskerFunction(now, NULL); twMessageHandler_msgHandlerTask(now, NULL); if (twTimeGreaterThan(now, nextDataCollectionTime)) { dataCollectionTask(now, NULL); nextDataCollectionTime = twAddMilliseconds(now, DATA_COLLECTION_RATE_MSEC); } #else in = getch(); if (in == 'q') break; else printf("\n"); #endif twSleepMsec(5); }      Step 9: File Transfer Example    To handle file transfers, a virtual directory is created in the SteamSensor1 entity and in the [C SDK HOME DIR]/examples/FileTransferExample application directory. The source code used for this example is found in [C SDK HOME DIR]/examples/FileTransferExample/src/main.c.   Inside of the [C SDK HOME DIR]/examples/FileTransferExample folder, create the folder structure shown below: /transfer/ /transfer/incoming/ /transfer/outgoing/ Inside of the /transfer/outgoing/ directory, create and open a file with the name outgoing.txt. Once the outgoing.txt document is open, add the following text, save, and close the file: Hello. This is a file coming from the client application. Navigate to the [C SDK HOME DIR]/examples/FileTransferExample/src/main.c code and update the lines below with the appropriate information for your IP, port, and the “admin_key” Application Key’s keyId value in the ThingWorx Composer: /* Server Details */ #define TW_HOST "127.0.0.1" #define TW_PORT 80 #define TW_APP_KEY "ce22e9e4-2834-419c-9656-ef9f844c784c" To support file transfers in your client application, you must use the twFileManager_AddVirtualDir function in order to create the virtual directories in the entity with such a capability. It will also define the directories available for file operations. A virtual directory maps a unique name to an absolute path of a directory in the file system. All subdirectories of the specified directory are exposed to the server. You can define multiple virtual directories. The directories do not need to be contiguous.   Staging Directory   As an optional, but recommended step, you should set the directory that the application should use for staging when performing file transfers. This can be seen in the line below and should be done before initializing the FileManager. The default directory of the FileManager is most likely owned by root and will require a change to either the location of the staging directory and the ownership of the staging directory, or running the application as a User with the correct permissions.   twcfg.file_xfer_staging_dir = "staging"; The example provided uses the TW_SHARE_DIRECTORY macro to create two virtual directories that will act as the root directories in the virtual file system of this application are added. The client is then started as follows with the necessary TW_ADD_FILE_TRANSFER_SHAPE function being called: TW_ADD_FILE_TRANSFER_SHAPE(); TW_SHARE_DIRECTORY("in", "/transfer/incoming/"); TW_SHARE_DIRECTORY("out", "/transfer/outgoing/"); The creations of the payloads used to create the remote directories on the platform have been moved to a helper function below to make the design cleaner: int setupSystemRepo(const char * remoteInPath, const char * remoteOutPath, const char * remoteFile); After our remote directories and files have been setup, it is time to perform the file transfers. Normally, this would mean invoking the Copy service for a Subsystem, but two functions have been created to make this process easier: int twFileManager_GetFile(const char * sourceRepo, const char * sourcePath, const char * sourceFile, const char * targetRepo, const char * targetPath, const char * targetFile, uint32_t timeout, char asynch, char ** tid) int twFileManager_SendFile(const char * sourceRepo, const char * sourcePath, const char * sourceFile, const char * targetRepo, const char * targetPath, const char * targetFile, uint32_t timeout, char asynch, char ** tid) The table below displays an example of the first set of parameters:    Parameter     Example                             Description sourceRepo SystemRepository The name of FileRepository or RemoteThing to transfer the file FROM. sourcePath outgoing The path specifying the location of the source file. sourceFile The name of the source file.   targetRepo SteamSensor1 The name of FileRepository or RemoteThing to transfer the file TO. targetPath incoming The path specifying the destination location of the file. targetFile incoming.txt The name of the file at the target. This name can differ from the sourceName. timeout 15,000 The amount of time (in seconds) to wait for a synchronous transfer to complete before cancelling the transfer. async false If false, the service call will block for timeout seconds or until the transfer completes. tid incoming0123 The unique TID associated with the file.   The C SDK also provides the ability to create a FileCallback function that the FileManager will call that function when any file transfer events occur. You can provide a wildcard filter so that only file transfer Events of files that match the filter call the callback function. In addition, callbacks can be set up as “one-shots” such that the callback is unregistered automatically after it is invoked the first time.   NOTE: An optional file transfer callback is registered in the code and provided. You will see the output from the function as files are sent and received.   After running this application, you will notice a new file in the transfer/incoming folder after refreshing. This is the file that we created in the ThingWorx Composer file system for the SystemRepository Entity and was able to copy from that location to our local project. We have also sent a file to the server’s SystemRepository. The BrowseFileSystem and GetFileListing services can be used to check for the folders and files created.   twFileManager_RegisterFileCallback(fileCallbackFunc, NULL, FALSE, NULL);     Step 10: Support Other Platforms   All Websocket errors indicate some general issue communicating with the ThingWorx platform. If you experience an issue connecting, refer to the table below for a list of websocket errors, their corresponding codes, and an explanation of the issue.    Code     Message                                                                      Troubleshooting 200 TW_UNKNOWN_WEBSOCKET_ERROR An unknown error occurred on the websocket. 201 TW_ERROR_INITIALIZING_WEBSOCKET An error occurred while initializing the websocket. Check your websocket configuration parameters for validity. 202 TW_TIMEOUT_INITIALIZING_WEBSOCKET A timeout occurred while initializing the websocket. Check the status of the connection to ThingWorx. 203 TW_WEBSOCKET_NOT_CONNECTED The websocket is not connected to ThingWorx. The requested operation cannot be performed. 204 TW_ERROR_PARSING_WEBSOCKET_DATA An error occurred while parsing websocket data. The parser could not break down the data from the websocket. 205 TW_ERROR_READING_FROM_WEBSOCKET An error occurred while reading data from the websocket. Retry the read operation. If necessary, resend the data. 206 TW_WEBSOCKET_FRAME_TOO_LARGE The SDK is attempting to send a websocket frame that is too large. The Maximum Frame Size is set when calling twAPI_Initialize and should always be set to the Message Chunk Size (twcfg.message_chunk_size). 207 TW_INVALID_WEBSOCKET_FRAME_TYPE The type of the frame coming in over the websocket is invalid. 208 TW_WEBSOCKET_MSG_TOO_LARGE The application is attempting to send a message that has been broken up in to chunks that are too large to fit in a frame. You should not see this error. 209 TW_ERROR_WRITING_TO_WEBSOCKET An error occurred while writing to the Web socket. 210 TW_INVALID_ACCEPT_KEY The Accept key sent earlier from ThingWorx is not valid.     Step 11: Next Steps   Congratulations! You've successfully completed the Low Level Device Connect Guide, and learned how to utilize the resources provided in the Edge SDK to create your own application.   The next guide in the Utilizing ThingWorx to Secure Your Aerospace and Defense Systems learning path is Tracking Activities and Statistics.    Learn More   We recommend the following resources to continue your learning experience:    Capability      Guide Build Design Your Data Model Build Implement Services, Events, and Subscriptions   Additional Resources   If you have questions, issues, or need additional information, refer to:    Resource       Link Community Developer Community Forum Support C Edge SDK Help Center      
View full tip
  Step 3: Create a Base Mashup   Now that you have some data, you need to create and configure a Mashup to display the data.   Using Mashup Parameters, the Collection Widget will replicate the base Mashup multiple times, correlating to each row of data in the Info Table Property.   On the ThingWorx Composer Browse tab, click Visualization > Mashups, + New                2. Keep the default ofResponsive(without selecting any Templates), and click OK          3. In the Name field, enter cwht_base_mashup.      4. If Project is not already set, search for and select PTCDefaultProject.      5. Click Save.     Add Widgets to Design   At the top, click Design. TIP: You can click the left arrow on the divider between the Browse left-navigation and the Mashup Builder to minimize the navigation and provide more room for the Mashup Builder itself.                  2.  On the Layout tab at the top-left, select Positioning > Static. You generally want the base Mashup to be "Static" so that you know the size of the cells which  the Collection Widget will replicate.                3. From the top-left Widgets tab, drag-and-drop a Gauge Widget onto the central Canvas area.             4. Drag-and-drop an LED Display Widget onto the central Canvas area.               5. Drag-and-drop a Text Field Widget onto the central Canvas area       Reduce the Mashup Size   At the top-left on the Explorer tab, select the Container.                2. In the central Canvas area, click-and-drag the far-right side of the container to reduce its horizontal size               3. Click-and-drag the bottom of the container to reduce its vertical size     Create Mashup Parameters   On the top-left Explorer tab, select the Mashup itself. A drop-down menu indicator will appear in the top-left of the Mashup.                 2. Click the top-left drop-down menu to reveal the Mashup options               3. Select Configure Mashup Parameters to open the Configure Mashup pop-up menu                4. Click Add Parameter three times              5. For the Name fields, enter first_number, second_number, and third_number.         6. Change the Base Type to NUMBER for all three Parameters           7. Click Done to close the Configure Mashup pop-up menu   Bind Mashup Parameters to Widgets   Click the Mashup's drop-down menu in the top-left to expose the options again. There are now additional options for first_number, second_number, and third_number.              2. Drag-and-drop first_number onto the Gauge Widget               3. Select Data on the Select Binding Target pop-up menu of the Gauge Widget.         4. Drag-and-drop second_number onto the LED Display Widget. You may have to first reselect the Mashup itself to reveal the Mashup's drop-down menu to access the second_number Mashup Parameter. Remember that you can easily select the Mashup itself through the Explorer tab.                                    5. Select Data on the Select Binding Target pop-up menu of the LED Display Widget.         6. Drag-and-drop third_number onto the Text Field Widget.         7. Select Text on the Select Binding Target pop-up menu of the Text Field Widget.         8. At the top, click Save. You can expand the Connections window at the bottom and select the Mashup itself to confirm that all three Mashup Parameters have been correctly bound to each Widget.          9. Click the Right Arrow on the far-left of the Mashup Builder to re-expand the Browse navigation menu.         Click here to view Part 3 of this Guide.
View full tip
  Use the Edge MicroServer (EMS) to simulate an engine with vibration sensors.   GUIDE CONCEPT   The Edge MicroServer (EMS) facilitates connectivity from Edge devices to ThingWorx Foundation.   It’s often easier, though, to start development with simulated Edge values rather than hooking up sensors.   This guide will show you how to simulate vibration values of an engine using the EMS.     YOU'LL LEARN HOW TO   Modify an EMS Template Provision Thing Properties and Values from an EMS rather than Foundation Send information from an EMS to Foundation Store large amounts of data in an InfoTable Property Create a simulator for testing   NOTE:  The estimated time to complete all parts of this guide is 30 minutes.     Step 1: Scenario   MotorCo manufactures, sells, and services commercial motors.   Recently, MotorCo has been developing a new motor, and they already have a working prototype.   However, they’ve noticed that the motor has a chance to FAIL CATASTROPHICALLY if it’s not properly serviced to replace lost grease on a key moving part.     In order to prevent this type of failure in the field, MotorCo has decided to instrument their motors with sensors which record vibration.   The hope is that these sensors can detect certain vibrations which indicate required maintenance before a failure occurs.   In this guide, you’ll begin this monitoring process by using ThingWorx Foundation to monitor and record vibration data from the prototype motor. In particular, you will learn how to provision Thing Properties and Values from an EMS, as well as how to permanently store these values for analysis in an Info Table Property.   These types of modifications to an EMS can be extremely helpful for the automotive segment in particular. For instance, each car that comes off the factory line could have custom, auto-generated EMS scripting that would dynamically create Foundation information for each car in the fleet. This could be a massive time-savings versus manually generating Thing Properties directly within Foundation.   Because the motor is still in the process of being instrumented with sensors, you’ll get all the functionality in-place beforehand by constructing a motor simulator using the Edge MicroServer (EMS).     Step 2: Modify config.lua   In the previous Use the Edge MicroServer (EMS) to Connect to ThingWorx  guide, you installed the EMS on a Windows PC, configured it to talk to ThingWorx Foundation, and then created an EdgeThing on Foundation to complete the connectivity.   This guide assumes that you have already completed that Windows EMS guide and have an active EMS connection to the EdgeThing.   Perform the following steps to modify this connection to increase the task rate of the EMS, which we'll use in the following steps to update Properties more quickly.   On your Windows PC, select the Windows PowerShell window where the luaScriptResource.exe program is running.   Type Ctrl-C to close the luaScriptResource.exe operation, i.e. hold the Control key and hit the C key.   Minimize the luaScriptResource.exe PowerShell window, and activate the wsemse.exe PowerShell window.   Type Ctrl-C to close the wsems.exe operation.   Return to Foundation, and note that EdgeThing is not connected.   Navigate to the C:\CDEMO_EMSE\etc directory.   Open config.lua in your prefered text-editor.   Change scanRate to 1000. Add the following line below the scanRate line: taskRate = 1000,   The final code of config.lua should be the following Note that the EMS may have slightly modified your config.lua file, such as adding a data_security_key line. Leave these EMS-generated modifications alone. scripts.log_level = "WARN" scripts.script_resource_ssl = false scripts.script_resource_authenticate = false scripts.EdgeThing = { file = "thing.lua", template = "YourEdgeThingTemplate", scanRate = 1000, taskRate = 1000, sw_update_dir = "C:\\CDEMO_EMS\\updates" } Save the config.lua file.     Click here to view Part 2 of this guide.
View full tip
  Display project burn up/down via a convenient Mashup Widget.   GUIDE CONCEPT   Long term projects need to be managed. As a project is scoped, requirements get defined and delivery-timeframes are estimated. As work is done, requirements are completed.   One way to track this project progress is with a Waterfall Chart.   This guide will show you how to utilize a Waterfall Chart Widget to easily display the project workflow.        YOU'LL LEARN HOW TO   Create a Data Shape Create a Thing Create an Info Table Property Populate an Info Table with appropriate data for a Waterfall Chart Create a Mashup Utilize a Waterfall Chart to display project progress   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete this guide is 30 minutes     Step 1: Create Data Shape   In this scenario, we'll store the Waterfall Chart's data in a Property type called an Info Table.   An Info Table is a spreadsheet-like Property, but in order to define the columns of the table, we first have to define a Data Shape. We'll do that in this step.   In the left-side navigation, click Browse > Modeling > Data Shapes.   At the top, click + New.   In the Name field, type TPWC_DataShape. If Project is not already set, search for and select PTCDefaultProject .   At the top, click Field Definitions.   At the top-left, click + Add.   On the right-side slide-out, in the Name field, type month. Note that you want to leave "Base Type" as the default of "STRING". Check Is Primary Key.   Click the "check with a plus" button for Done and Add.   In the Name field, type amount. Change Base Type, to NUMBER.   Click the "check" button for Done.   At the top, click Save .     Step 2: Create Thing   Now that we have our Data Shape, we can create a Thing to document the project progress over time.   As already mentioned, we'll use an Info Table Property, formatted by the previously-created Data Shape, to do so.   Click Browse > Modeling > Things.   Click + New.   In the Name field, type TPWC_Thing. If Project is not already set, search for and select PTCDefaultProject. In the Base Thing Template field, search for and select GenericThing. At the top, click Save.   Add Info Table Property Now that we have our Thing instantiated, we want to add an Info Table Property. At the top, click Properties and Alerts.   Click + Add.   On the right-side slide-out, in the Name field, type InfoTable_Property. Change Base Type to INFOTABLE. In the Data Shape field, search for and select TPWC_DataShape. Note that the Data Shape field will not appear until you set Base Type to INFOTABLE. Check Persistent.   At the top-right, click the "check" button for Done. At the top, click Save.   Set Value of Property Now that we have a place in which to store spreadsheet-like values, we'll do so manually for testing.  On the InfoTable_Property row, under the Value column, click the "pencil" icon for Set value of property.   On the pop-up, click + Add.   Enter the following values in each field as per the table below: Field Name Value month January amount 380   Click Add.   Repeat Steps 2-4 multiples times until all of the below values have been entered. Note that amount should be left blank for both Mid-Term and Total. Note that you may enter fewer than all the values listed below if so desired, though your final Waterfall Chart will not match the following screenshots. month amount February 85 March 50 April 1000 May -300 June 0 Mid-Term   July 30 August -655 September -100 October -250 November 350 December -100 Total     On the pop-up, click Save.   At the top, click Save.   Step 3: Create Mashup   Now that we have our data in-place for testing (and could be connected to automated systems after we finish testing), we need to visualize the data.   As mentioned, we'll use a Waterfall Chart Widget, but first, we need to create a Mashup into which we can place the Widget.   Click Browse > Visualization > Mashups.   Click + New.   Leave the defaults and click OK.   In the Name field, type TPWC_Mashup. If Project is not already set, search for and select PTCDefaultProject. At the top, click Save.   At the top, click Design.   At the top-left, click the Widgets tab.   Drag-and-drop a Waterfall Chart Widget onto the central Canvas.   At the top, click Save.     Click here to view Part 2 of this guide.
View full tip
    Step 3: Modify YourEdgeThingTemplate.lua   Now that the task rate has been decreased to 1000ms (one second), we can create a series of Thing Properties.   In Windows, navigate to C:\CDEMO_EMS\etc\custom\templates.   In your prefered text-editor, open YourEdgeThingTemplate.lua.   We now want to add several lines of Lua code to define some Properties for EdgeThing. You’ll do some with some references that are pre-built into the EMS, primarily the properties structure.   Working with the engine R&D team, their plan is to place two vibration sensors on the proptype engine. In addition, each vibration sensor will have five frequency bands. As such, we’ll need ten Properties to represent the vibration readings.   In addition, we also want a Property that will record whether or not the engine is currently experiencing the low grease condition. This will be entered via manual-inspection at the same time that the frequency readings are recorded.   Perform the following to implement the ten vibration frequency bands and the low grease condition.   Below the module line of YourEdgeThingTemplate.lua, add the following line to create a low_grease Property: properties.low_grease={baseType="NUMBER", pushType="ALWAYS", value=0} Below that, add the following lines to create the five frequency bands for the first vibration sensor: properties.s1_fb1={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s1_fb2={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s1_fb3={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s1_fb4={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s1_fb5={baseType="NUMBER", pushType="ALWAYS", value=0} Below that, add the following lines to create the five frequency bands for the second vibration sensor: properties.s2_fb1={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s2_fb2={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s2_fb3={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s2_fb4={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s2_fb5={baseType="NUMBER", pushType="ALWAYS", value=0} Your code should now look like the picture below.   The code above adds each new Property to the properties structure, and the name of the Property will be what follows after the “.”, i.e. low_grease, s1_fb1, s1_fb2, etc.   In addition, the baseType defines the type of each Property, in this case, all Numbers.   The pushType of ALWAYS means that there are no restrictions on sending new Property values up to Foundation, and the value of 0 indicates the default value to which each Property will initially be set.   Generate Property Values   Now that we have the Properties defined, we want to add code which will give us different values.   To do so, we’ll define a queryHardware function, and tie the calling of it to the task rate which we had set earlier. This queryHardware function will use random numbers to simulate code that would gather actual data.    Add the following Lua code to define a GetSystemProperties function. Note that this calls a separate queryHardware function which we split out to also be called by the tasks timer. serviceDefinitions.GetSystemProperties( output { baseType="BOOLEAN", description="" }, description { "updates properties" } ) services.GetSystemProperties = function(me, headers, query, data) queryHardware() return 200, true end Add the following Lua code to define queryHardware. Note that Lua’s random number generation requires a new seed on each calling, and the randomseed function is using the built-in os.time function (plus some additional noise created by turning that time into a string and back). function queryHardware() math.randomseed( tonumber(tostring(os.time()):reverse():sub(1,6)) ) local temp = math.random(10) if temp < 6 then properties.low_grease.value=0 properties.s1_fb1.value=161+math.random() properties.s1_fb2.value=180+math.random() properties.s1_fb3.value=190+math.random() properties.s1_fb4.value=176+math.random() properties.s1_fb5.value=193+math.random() properties.s2_fb1.value=130+math.random() properties.s2_fb2.value=200+math.random() properties.s2_fb3.value=195+math.random() properties.s2_fb4.value=165+math.random() properties.s2_fb5.value=190+math.random() else properties.low_grease.value=1 properties.s1_fb1.value=90+math.random() properties.s1_fb2.value=170+math.random() properties.s1_fb3.value=170+math.random() properties.s1_fb4.value=95+math.random() properties.s1_fb5.value=190+math.random() properties.s2_fb1.value=165+math.random() properties.s2_fb2.value=195+math.random() properties.s2_fb3.value=190+math.random() properties.s2_fb4.value=140+math.random() properties.s2_fb5.value=190+math.random() end end Finally, we want to tie the calling of queryHardware to the tasks timer by adding the following code: tasks.refreshProperties = function(me) queryHardware() end   We now have code in our EMS template that not only defines the low grease condition and the five frequency bands of our two vibration sensors, but also generates some values in the ranges that R&D have typically seen in both good grease amount and bad grease amount conditions.   The final Lua code of the YourEdgeThingTemplate.lua file should look like the following:   require "shapes.swupdate" module ("templates.YourEdgeThingTemplate", thingworx.template.extend) properties.low_grease={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s1_fb1={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s1_fb2={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s1_fb3={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s1_fb4={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s1_fb5={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s2_fb1={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s2_fb2={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s2_fb3={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s2_fb4={baseType="NUMBER", pushType="ALWAYS", value=0} properties.s2_fb5={baseType="NUMBER", pushType="ALWAYS", value=0} serviceDefinitions.GetSystemProperties( output { baseType="BOOLEAN", description="" }, description { "updates properties" } ) services.GetSystemProperties = function(me, headers, query, data) queryHardware() return 200, true end function queryHardware() math.randomseed( tonumber(tostring(os.time()):reverse():sub(1,6)) ) local temp = math.random(10) if temp < 6 then properties.low_grease.value=0 properties.s1_fb1.value=161+math.random() properties.s1_fb2.value=180+math.random() properties.s1_fb3.value=190+math.random() properties.s1_fb4.value=176+math.random() properties.s1_fb5.value=193+math.random() properties.s2_fb1.value=130+math.random() properties.s2_fb2.value=200+math.random() properties.s2_fb3.value=195+math.random() properties.s2_fb4.value=165+math.random() properties.s2_fb5.value=190+math.random() else properties.low_grease.value=1 properties.s1_fb1.value=90+math.random() properties.s1_fb2.value=170+math.random() properties.s1_fb3.value=170+math.random() properties.s1_fb4.value=95+math.random() properties.s1_fb5.value=190+math.random() properties.s2_fb1.value=165+math.random() properties.s2_fb2.value=195+math.random() properties.s2_fb3.value=190+math.random() properties.s2_fb4.value=140+math.random() properties.s2_fb5.value=190+math.random() end end tasks.refreshProperties = function(me) queryHardware() end       Step 4: Modify EdgeThing   Now that our EMS has been updated with Properties, as well as code to generate values for those Properties, we want to re-connect the EMS to Foundation and update the EdgeThing.   Note once again that EdgeThing was previously created in the Use the Edge MicroServer (EMS) to Connect to ThingWorx guide.   Restart the wsemse.exe program by returning to its PowerShell window and executing the following command: .\wsems.exe   Restart the luaScriptResource.exe program by returning to its separate PowerShell window and executing the following command: .\luaScriptResource.exe   Return to ThingWorx Foundation's EdgeThing. Note that EdgeThing is connected.   On the Properties and Alerts tab, click Manage Bindings.   At the bottom-left of the Manage Bindings pop-up, click + Add all properties.   At the bottom-right of the pop-up, click Done.   At the top, click Save.   Near the top, click Refresh repeatedly. Note that the Property values consistently change.          Click here to view Part 3 of this guide.
View full tip
  Enhance your Engine Failure-Prediction GUI.     GUIDE CONCEPT   This guide will use ThingWorx Foundation’s Mashup Builder to create a more advanced Graphical User Interface (GUI) than the one we originally created to display results from Analytics Manager’s engine-failure predictions.   Following the steps in this guide, you will learn how to utilize Widgets and backend data to more completely visualize customer failure conditions.       YOU'LL LEARN HOW TO   Create a Mashup with a Header Divide your Mashup into Sub-sections Use a Contained Mashup to reuse development Store historical data in a Value Steam Display historical data in a Time Series Chart Show spreadsheet data via a Grid Widget Tie Mashup controls into the ThingWorx backend   NOTE: The estimated time to complete all parts of this guide is 60 minutes.     Step 1: Scenario   In this guide, we’re taking our previous MotorCo Minimum Viable Product (MVP) Mashup and expanding it.   Our original Mashup showed the results from ThingWorx Analytics as it determined whether or not a low-grease condition was currently present.   The goal of this guide is to create an Enhanced GUI to visualize those predicted “low grease” conditions in a more complete manner.     GUI-creation to visualize analytical model deployment can be extremely helpful for the automative segment in particular. For instance, each car that comes off the factory line could have an EMS constantly sending data from which an analytical model could automatically detect engine trouble.   This could enable your company to offer an engine monitoring subscription service to your customers.   This guide will show you how to visualize the results of an engine analytic model for a smart, connected products play.     Step 2: Create Mashup   Just like in the last guide, we're now going to create a Mashup to visualize ThingWorx Analytics results.   This one is simply going to be more complicated to include additional functionality.   But before we can start designing our GUI, we must first instantiate a Mashup onto which we can place our Widgets.       1. In ThingWorx Foundation, click Browse > Visualization > Mashups.         2. Click + New.       3. On the New Mashup pop-up under Responsive Templates, click Header Only.       4. Click OK.       5. In the Name field, type EEFV_Mashup.       6. If Project is not already set, search for and select PTCDefaultProject.       7. At the top, click Save.       8. At the top, click Design.         Step 3: Set Layout   Now that we’re in Mashup Builder, you can see the separate top-section of the central Canvas area created by our selection of “Header Only” on the New Mashup pop-up.   Unlike the original Mashup where we used Static Positioning, most of this Mashup will continue to use Responsive so that it can grow and shrink as resolution changes on various viewing devices.   To add multiple Responsive Widgets to a Responsive Positioning Mashup, though, you need to create some additional sub-sections. We’ll do so now.       1. In the top-left of Mashup Builder, click the Layout tab.       2. Click the main, bottom section of the Canvas, i.e. the non-header section, to select it.       3. On the Layout tab, click Add Top.       4. With the top-half of the original bottom section still selected, click Add Left.       5. Click in the bottom section to select the bottom-half of the original container.       6. Click Add Left.       7. At the top, click Save.      You now have a Responsive Positioning Mashup with five (5) sub-sections, i.e. :   Header Top-left Top-Right Bottom-left Bottom-right       Step 4: Adjust Header    In this step, we'll outfit the Header sub-section with a company name and logo.       1. Select the top Header section and ensure that you're still on the Layout tab in the top-left.         2. Change the Positioning to Static.       3. In the top-left, select the Widgets tab.       4. Drag-and-drop an Image Widget onto the Header section.       5. Expand the size of the Image Widget by dragging the corners.       6. Drag-and-drop a Label Widget onto the Header section.       7. Expand the size of the Label Widget.       8. With the Label Widget still selected, change the LabelText Property (in the bottom-left) to MotorCo, and hit the keyboard Tab key to lock-in your modification.         9. In the bottom-left, change to the Style Properties tab.       10. Expand Base > Label, and change font-size to 72px.       11. At the top, click Save.   Upload Media Image   We want to set the earlier Image Widget to the company logo.   To do so, we need to upload it to Foundation by creating a Media Entity.       1. Click Browse > Visualization > Media.       2. Click + New.       3. In the Name field, type EEFV_Logo.       4. If Project is not already set, search for and select PTCDefaultProject.       5. Right-click and "Save as" to download motorco-logo.jpg.       6. Under Image, click Change.       7. Navigate to and select the motorco-logo.jpg file you just downloaded.       8. Click Open.       9. At the top, click Save.   Change Image to Logo   Now that we have the company logo stored within ThingWorx, we can update the Image Widget to reference it.       1. Return to EEFV_Mashup.       2. Click the Image Widget to select it, and ensure that the bottom-left Properties tab is active.         3. Scroll down in the Properties until you find SourceURL.         4. In the Search Media field, type eefv.         5. Select EEFV_Logo.         6. Click Save.     Change Background Color   Finally, we want to change the background color of the Header.       1. In the top-left, select the Explorer tab. Note that the Explorer tab may be in the top-left drop-down if you're using a lower-resolution screen.         2. Select the Header itself.         3. In the bottom-left, select the Style Properties tab and expand Base > Container.         4. Beside background, click the white square to open a color-selector.       5. Select a color you desire.         6. Click Select.         7. Click Save.     Click here to view Part 2 of this guide.
View full tip
  Add a Google Map to your UI that visually presents geographical data.   GUIDE CONCEPT This project will introduce how to visually present geographical data in your application. Showing data on a map is a valuable feature for IoT application.   Following the steps in this guide, you will utilize the Google Maps Widget and explore it’s ability to show multiple Things.   We will teach you how to use Geological data to convey pertinent information in your UI.   YOU'LL LEARN HOW TO   Download and import the Google Maps Widget extension Create a Mashup and add a Google Maps Widget Configure the Google Maps Widget to display the locations of multiple Things   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete ALL 2 parts of this guide is 30 minutes.      Step 1: Configure Google Maps Widget   When you download the Google Maps Widget, it does not include an API key. Google allows some limited use of their map API without a key, however it is recommended that you obtain and add your own Google Maps API key or Client ID (for Google Maps API for Work licenses) to the Google Maps Widget.   The ThingWorx hosted server has already been configured with the Google Maps Widget, including an API key for evaluation use.   Refer to the Google Maps API documentation to obtain your own API key, then follow the steps below.   Download the Google Maps widget from PTC Partner, IQNOX NOTE:  It is necessary to create an account on IQNOX, but the download is free       2. In the lower-left side of Composer, click Import/Export, then Import.           3. In the Import From File pop-up, under Import Option select Extension from the drop-down, then click Browse        4. Navigate to the .zip file you downloaded.          5. Click Import in the Import From File pop-up, then click Close after file is successfully imported.        6. In the ThingWorx Browse tab, in the System section, click on Subsystems, then PlatformSubsystem.            7. Click on the Configuration tab, then click the Edit button if you are not already in edit mode.        8. Scroll down to the Required string to connect with Google for Google widgets field where you enter the Google Maps JavaScript URL with your API key: https://maps.googleapis.com/maps/api/js?key=<Your API key>            9. Click Save     Step 2: Add Google Maps Widget to Mashup   Click the Browse folder icon on the top left of ThingWorx Composer.       2. Select Mashups in the left-hand navigation, then click + New to create a new Mashup.                          3. For Mashup Type select Responsive.               NOTE: A Responsive Mashup scales with a browser's screen size. In the steps below we will create 5 containers, one for each widget, to organize how the widgets are presented.        4. Click OK.        5. Enter a name for your Mashup.        6. If Project is not already set, click the + in the Project text box and select the PTCDefaultProject.        7. Click Save        8. Select the Design tab to display Mashup Builder.        9. Click the Widget tab on the top-left, then enter map inside the Filter Widgets field.        10. Drag-and-drop the Google Map widget onto the Mashup.         Step 3: Download Sample Entities   We have created a file with sample entities for this exercise.   Download demoTractors.xml to your computer.       2. Click Import/Export in the lower left of Composer, then select Import          3. Click From File in the drop down, then Browse.        4. Browse to the demoTractors.xml file and click Open.        5. Click Import, then Close after entities are successfully imported.     Step 4: Add Markers to Google Maps Widgets   To display markers on the map you must bind an Info Table to the Widget's Data Property and specify which column has location information. In this example we will use the QueryImplementingThingsWithData Service to bind a group of Things created with the same Template.   Click the + button in the Data tab on the right side of the Mashup Builder window             2. In the Add Data pop-up, click Thing Templates from the Entity Type drop down.                3. Select a Template from the list that has a Location property and was used to create Things. For this exercise, use the ConnectedTractor Template that was imported from the sample file downloaded in the prior step.            4. Enter query into the filter text box then click the arrow to the right of QueryImplementingThingsWithData.                                              5. Click the Execute on Load check box, then click Done. This will cause the QueryImplementingThingsWithData Service to execute as soon as Mashup is loaded.                                          6. Expand Returned Data if you do not see All Data then click and drag All Data onto the Google Maps Widget.        7. Click Data in the Select Binding Target pop-up.          8. In the Properties panel in the lower left, scroll to see the LocationField property and select Location, the name of the Property with location information.       Test Map Operation   Click Save to save your Mashup.       2. Click View Mashup to see the Google Maps Widget displaying the locations of each Thing.     NOTE: The Google Maps Widget has built-in functionality that allows users to pan and resize the map as well as switch to satellite photo maps.     Click here to view Part 2 of this Guide.
View full tip
  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:   Name Structure Description Property Definitions twPropertyDef Describes the basic information for the Properties that will be available to ThingWorx and can be added to a client application. Property Values twProperty Associates 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  
View full tip
  Step 6: Record Data   Now that we have a place to permanently store the values coming from the EMS engine simulator, we'll write a Service to take samples and place them within the Info Table.   Part of that Service, though, will be incrementing the identifier, so we'll need to create one last Property.   Ensure that you're on the Properties and Alerts tab of EdgeThing. At the top-left, click + Add.     In the Name field of the slide-out on the right, type identifier. Change the Base Type to NUMBER. Click Persistent. Click Has Default Value. In the Has Default Value field, type 0.   At the top-right, click the "Check" button for Done. At the top, click Save.   Store the Property Values   With all the pieces in place, we can now create our Service to add entries to our Info Table Property.   At the top of EdgeThing, click Services.   At the top-left, click + Add.   On the "+ Add" drop-down, select Local (JavaScript). In the Service Info > Name field, type recordService.     Expand Me/Entities > Properties.     Click the arrow beside infoTableProperty.     Type .AddRow({ after me.infoTableProperty to being the process of calling the "AddRow()" function.     We now have called the function which will add a row of information to the Info Table Property, one entry for each column of the formatting Data Shape.   We just need to specify which values go into which column.   Add the following lines to store the individual Identifier count into the first column of the Info Table Property: identifier:me.identifier, Because we want the identifier in the stored data to increment on each run, and we want to start the count at 1 (and the Default Value is 0), add the following line to the top of the Service: me.identifier=me.identifier+1;       Add the low_grease value with the following line: low_grease:me.low_grease, Add the following lines to store the five frequency bands of the first sensor: s1_fb1:me.s1_fb1, s1_fb2:me.s1_fb2, s1_fb3:me.s1_fb3, s1_fb4:me.s1_fb4, s1_fb5:me.s1_fb5, Add the final lines to store the five frequency bands of the second sensor and close out the AddRow() function: s2_fb1:me.s2_fb1, s2_fb2:me.s2_fb2, s2_fb3:me.s2_fb3, s2_fb4:me.s2_fb4, s2_fb5:me.s2_fb5 }); You completed Service should look like the following: me.identifier=me.identifier+1; me.infoTableProperty.AddRow({ identifier:me.identifier, low_grease:me.low_grease, s1_fb1:me.s1_fb1, s1_fb2:me.s1_fb2, s1_fb3:me.s1_fb3, s1_fb4:me.s1_fb4, s1_fb5:me.s1_fb5, s2_fb1:me.s2_fb1, s2_fb2:me.s2_fb2, s2_fb3:me.s2_fb3, s2_fb4:me.s2_fb4, s2_fb5:me.s2_fb5 });     At the top, click Done. At the top, click Save.       Run the Service   With our Service completed, let's run it to store a sampling of the data coming from our EMS Engine Simulator.   Under the Execute column in the center, on the recordService row, click the "Play" icon for Execute service. At the bottom-right, click Execute.     At the bottom-right, click Done. At the top, click Properties and Alerts.   Under the Value column, on the infoTableProperty row, click the "Pencil" icon for Set value of property.   Note that the Service has captured a snap-shot of the vibration data and grease condition and permanently stored it within the Info Table Property. You now have not only an Engine Simulator that is constantly sending data from a remote EMS, but a way to permanently record data at points that you deem significant.   Feel free to return to the Service and call it several more times. Each time, the values coming from the Engine Simulator will be stored in another entry in the Info Table Property.       Step 7: Next Steps   Congratulations! You've successfully completed the Use the EMS to Create an Engine Simulator guide, and learned how to:   Modify an EMS Template Provision Thing Properties and Values from an EMS rather than Foundation Send information from an EMS to Foundation Store large amounts of data in an InfoTable Property Create a simulator for testing   The next guide in the Vehicle Predictive Pre-Failure Detection with ThingWorx Platform learning path is Engine Simulator Data Storage. Learn More We recommend the following resources to continue your learning experience: Capability Guide Build Engine Simulator Data Storage Build Implement Services, Events and Subscriptions Additional Resources If you have questions, issues, or need additional information, refer to: Resource Link Community Developer Community Forum Support Analytics Builder Help Center  
View full tip
    Step 5: Create InfoTable   Now that we have connected values coming from our EMS engine simulator, we want a method of permanent storage whenever we feel it's appropriate to take a sample.   From repeated sampling, we'll be able to build up a historical record usable for both manual inspection, as well as automatic analysis via ThingWorx Analytics (though ThingWorx Analytics is beyond the scope of this guide).   To hold these records, we'll use an Info Table Property.   But any time that you create an Info Table, you first need a Data Shape to format the columns.   Click Browse > MODELING > Data Shapes.     At the top-left, click + New.   In the Name field, type esimDataShape.     If Project is not already set, search for and select PTCDefaultProject. At the top, click Field Definitions.     We now want to add a separate Field Definition for each entry of our engine simulator data, i.e. low_grease, s1_fb1 through s1_fb5, and s2_fb1 through s2_fb5.   In addition, we'll add an additional field named identifier which simply keeps a rolling count of the current log entry number.   Click + Add.     In the Name field on the right slide-out, type identifier Change the Base Type to NUMBER. Check Is Primary Key   At the top-right, click the "Check with a +" button for Done and Add.     Repeatedly add additional definitions as per the chart below: Note that you will NOT check the "Is Primary Key" box, as you only need one, i.e. identifier. Name Base type low_grease NUMBER s1_fb1 NUMBER s1_fb2 NUMBER s1_fb3 NUMBER s1_fb4 NUMBER s1_fb5 NUMBER s2_fb1 NUMBER s2_fb2 NUMBER s2_fb3 NUMBER s2_fb4 NUMBER Create one additional entry for s2_fb5 and NUMBER, but click the "Check" button for DONE. At the top, click Save.     Create Info Table   Now that we have a Data Shape we can add an Info Table Property to EdgeThing. Return to the Properties and Alerts tab of EdgeThing.   At the top-left, click + Add.   In the Name field of the slide-out on the right, type infoTableProperty.   Change the Base Type to INFOTABLE.   In the new Data Shape field, search for and select esimDataShape.   Check the Persistent checkbox.   At the top-right, click the "Check" button for Done. At the top, click Save.     Click here for Part 4 of this guide.
View full tip
  Learn how to connect ThingWorx Kepware Server to Foundation.   Guide Concept   This guide will teach you how to create a backend Data Model in ThingWorx Foundation that works with ThingWorx Kepware Server to collect data from an Allen-Bradley PLC and send it to ThingWorx Foundation.   You'll learn how to   Create a Data Model in ThingWorx Foundation that accepts information from ThingWorx Kepware Server   NOTE:  The estimated time to complete this guide is 30 minutes       Step 1: Learning Path Overview   Assuming you are using this guide as part of the Rockwell Automation Learning Path, then you have now completed each of the following installations:   Connected Components Workbench ThingWorx Kepware Server ThingWorx Foundation (for Windows)   You’ve also connected an Allen-Bradley PLC to Connected Components Workbench and then to ThingWorx Kepware Server.   In this guide, we’ll propagate that information further from ThingWorx Kepware Server into ThingWorx Foundation.     Step 2: Create Gateway   To make a connection between ThingWorx Kepware Server and Foundation Server, you must first create a Thing. WARNING: To avoid a timeout error, create a Thing in ThingWorx Foundation BEFORE attempting to make the connection in ThingWorx Kepware Server. In ThingWorx Composer, click Browse. On the left, click MODELING -> Things.   Click + NEW. In the Name field, enter IndConn_Server, including matching capitalization. In the Description field, enter an appropriate description, such as Industrial Gateway Thing to connect to ThingWorx Kepware Server.   If Project is not already set, click the + in the Project text box and select the PTCDefaultProject. In the Base Thing Template field, enter indus, then select the IndustrialGateway Thing template from the sorted list. Click Save.     Step 3: Connect to Foundation   Now that you’ve created an Industrial Gateway Thing and an Application Key, you can configure ThingWorx Kepware Server to connect to ThingWorx Foundation. Return to the ThingWorx Kepware Server Windows application. Right-click Project. Select Properties.   In the Property Editor pop-up, click ThingWorx. In the Enable field, select Yes from the drop-down. In the Host field, enter the IP address of your ThingWorx Foundation server. Enter the Port number. If you are using the “hosted” Developer Portal trial, enter 443.   In the Application Key field, copy and paste the Application Key you just created. In the Trust self-signed certificates field, select Yes from the drop-down. In the Trust all certificates field, select Yes from the drop-down. In the Disable encryption field, select No from the drop-down if you are using a secure port. Select Yes if you are using an http port. Type IndConn_Server in the Thing Name field, including matching capitalization. If you are connecting with a remote instance of ThingWorx Foundation and you expect any breaks or latency in your connection, enable Store and Forward. Click Apply in the pop-up. Click Ok. In the ThingWorx Kepware Server Event window at the bottom, you should see a message indicating Connected to ThingWorx.   NOTE: If you do not see the “Connected” message, repeat the steps above, ensuring that all information is correct. In particular, check the Host, Port, and Thing name fields for errors.     Step 4: Bind Industrial Tag   Now that you’ve established a connection, you can use ThingWorx Foundation to inspect all available information in ThingWorx Kepware Server.   This step will create a new Thing in ThingWorx Foundation representing two output coils of the PLC.   Create Thing for PLC coils   In ThingWorx Foundation Composer, on the left, click MODELING -> Industrial Connections, then click IndConn_Server.   At the top, click Discover. Expand Channel2, then click myPLC. Select check-boxes next to Coil2 and Coil3, then click Bind to New Entity.   Scroll to select RemoteThing, then click OK.   Enter the name PLCcoils, If Project is not already set, click the + in the Project text box and select the PTCDefaultProject. then click Save.   Test ThingWorx Foundation to PLC Communication   Click the Properties and Alerts tab. Confirm that the isConnected Property has a check in the Value field, indicating a good connection between ThingWorx Kepware Server and the PLC. Click the pencil icon in the Coil3 line to open the edit panel, click the True radio button, then click the save checkmark button.   You should here a soft click from the PLC and the Output 3 indicator will illuminate. ThingWorx Foundation is now controlling the PLC through its connection to ThingWorx Kepware Server.     Step 5: Troubleshooting   If the connection to the PLC stops working and there is a Thumbs Down icon next to your properties, the ThingWorx Kepware Server trial edition drivers are not connected to your PLC. The trial edition stops running after 2 hours and must be stopped and restarted. Right-click on ThingWorx Kepware Server icon in system tray.   Click Stop Runtime service. Wait a minute for the process to stop, then click Start Runtime service. If Connected Components Workbench does not connect to PLC, check the IP address of the PLC using RS Linx Classic software that was installed as part of Connected Components Workbench. RS Linx Classic is located Start > All Programs > Rockwell Software > RSLinx > RSLinx Classic Click AB_ETHIP-1, Ethernet and IP addresses of connected PLCs will be discovered NOTE: A changed PLC IP Address (typically seen through Connected Components Workbench) will require an IP Address change in ThingWorx Kepware Server settings.       Step 6: Next Steps   Congratulations! You've successfully completed the Model an Allen-Bradley PLC guide. You've learned how to:   Create a data model that can accept information from ThingWorx Kepware Server Connect ThingWorx Kepware Server to Foundation   The next guide in the Using an Allen-Bradley PLC with ThingWorx learning path is Visualize an Allen-Bradley PLC.   Learn More     Capability      Resource Analyze Monitor an SMT Assembly Line   Additional Resources   For additional information on ThingWorx Kepware Server:     Resource              Link Documentation Kepware documentation Support Kepware Support site
View full tip
    Install a Connected Components Workbench to program an Allen-Bradley PLC   Guide Concept   In this guide, you'll install Rockwell Automation's Connected Components Workbench, which facilitates programming of an Allen-Bradley PLC.   You'll learn how to   Create a Rockwell Automation Account Download software from Rockwell Automation's website Install Connected Components Workbench   NOTE: The estimated time to complete this guide is 60 minutes       Step 1: Learning Path Overview   Welcome to the Rockwell Automation Learning Path!   This first guide explains the steps to get up and running with Rockwell's Connected Components Workbench, a software program to facilitate connecting to and configuring Programmable Logic Controllers, i.e. PLCs.   PLCs are commonly used in factories and other automation scenarios to control minor aspects, such as turnning particular devices on or off based on a particular situation.   Note that you don't necessarily have to run through this guide as part of the Learning Path. If you simply want to learn how to install Connected Components Workbench, this guide can still be useful to you.   But assuming you are using this guide as part of the Rockwell Automation Learning Path, then the first elements will be to install your software, i.e.:   Connected Components Workbench ThingWorx Kepware Server ThingWorx Foundation (for Windows)   You'll then connect an Allen-Bradley PLC to Connected Components Workbench and then to ThingWorx Kepware Server.   Next, we'll propogate that information further from ThingWorx Kepware Server into Foundation. Finally, we'll use Foundation's Mashup Builder to construct a GUI which can both receive and send information to the PLC.   We hope you enjoy this Learning Path.       Step 2: Signup   To access Rockwell Automation software, you first have to create an account on the Rockwell Automation website.   Go to the Rockwell Automation site.   In the top-right, click the "person symbol" for Account.   On the right, click Create an Account.   Enter a valid email address which you control and click Continue.   Enter your first and last names, your country, and click Continue.   Enter your job information and click Continue.   Enter and re-enter a password, check the EULA agreement box, and click Create Account.   Rockwell will send a verification email to the address you previously entered.   Locate the email and click Verify My Email Address.   A new browser tab will open with your verification; click Proceed to Sign In.   Sign-in with your verified email address.       Step 3: Download   Now that you have a verified Rockwell account, you will download Connected Components Workbench.   This download is a little different in that it actually has two parts.   You have to download both, and then run a built-in combiner to get access to the actual installation files.   Go to the Connected Components Workbench download site. Click Select Files. On the pop-up, check Connected Components Workbench and click Downloads. On the new pop-up, click DOWNLOAD NOW. On the download Software End-User License Agreement page, click Accept and Download. Move the download into a separate folder. Right-click on the download and select Run as administator. Agree to let the program make changes to your computer.   The download-manager will then begin the download of the actual software. Click Close when the download has completed.   Notice that there is now a new C:\RA\CCW folder.   Right-click on part1.exe and select Run as administator.   On the WinRAR self-extracting archive window, click Extract.   Notice that there is now a new "DVD" folder.   Navigate into the "DVD" folder.   Notice the Setup.exe file, which will be used to install Connected Components Workbench.       Step 4: Install   Now that you have Connected Components Workbench properly downloaded and extracted, you can begin the installation.   Right-click on Setup.exe and select Run as administrator. Click Yes to allow the program to make modifications to your computer.   Click Install now.   On the EULA screen, click Accept all.   Allow the installer to run to completion. This may take ~30 minutes..   Click Restart now to reboot and complete the installation.   After restarting, you may be asked to set your Country/Territory.   Click OK to confirm.   In the Windows "Start" menu, navigate to and expand the Rockwell Automation folder.   Click Connected Components Workbench.       Step 5: Next Steps   Congratulations! You've successfully completed the Connected Components Workbench installation guide.   In this guide, you learned how to:   Create a Rockwell Automation Account Download software from Rockwell's website Install a Connected Components Workbench   The next guide in the Using an Allen-Bradley PLC with ThingWorx learning path is Install ThingWorx Kepware Server.    Learn More    Capability Resource Manage Install ThingWorx Kepware Server   Additional Resources   For additional information on Rockwell:    Resource Link Documentation Rockwell Literature Library Documentation Connected Components Workbench
View full tip
  GUIDE CONCEPT   This guide introduces connecting an Allen-Bradley PLC to ThingWorx Kepware Server.   YOU'LL LEARN HOW TO   Create and run a simple ladder logic application on an Allen-Bradley PLC Connect the PLC to ThingWorx Kepware Server   NOTE: The estimated time to complete this guide is 30 minutes.      Step 1: Learning Path Overview   Assuming you are using this guide as part of the Rockwell Automation Learning Path, then you have now completed each of the following installations:        1. Connected Components Workbench       2. ThingWorx Kepware Server       3. ThingWorx Foundation (for Windows)   In this continued step, you'll now connect an Allen-Bradley PLC to Connected Components Workbench and then to ThingWorx Kepware Server.   In a later guide, we'll propogate that information further from ThingWorx Kepware Server into ThingWorx Foundation.   NOTE: Both Rockwell Automation's Connected Components Workbench and ThingWorx Kepware Server are time-limited trials. If significant time has passed while persuing this Learning Path, you may need to reinitialize them. Consult the Troubleshooting step of this guide for more information.       Step 2: Setup PLC   This guide uses an inexpensive Allen-Bradley Micro820 PLC as a demonstration.   ThingWorx Kepware Server offers drivers for hundreds of devices, making this step the only one that contains device-specific instructions.   Read and understand installation instructions before making any electrical connections to the PLC.   1. Connect the postive lead of a 24V power supply along with a 6" test lead to Terminal 1 of the output terminal block.   2. Connect the negative lead of the power supply to Terminal 2.     3. Confirm the test lead is secure from making contact with anything conductive; it will be  connected to +24V. Power on the supply and confirm the LEDs briefly light.       4. Carefully touch the test lead to the Input 1 terminal and confirm the indicator LED for Input 1 turns on.     5. Power off the supply before continuing to the next step.       Step 3: Create PLC Project   In this step, you will create a simple PLC application. This application will connect to a ThingWorx Mashup in subsequent guides in the Learning Path.    1. After opening Connected Components Workbench, click New... in the Project section.   2. Enter ThingWorxGuide in the Name field and click Create.   3. Browse to the PLC model you are using and click Select, then Add to Project.     4. Right-click Program, then left-click Add > New LD: Ladder Diagram     5. Double-click Prog1 to open the ladder window.     Ladder Logic   You will create a simple application that will turn on output 2 when there is a signal on input 2.    1.. Right-click in the box to the left of the rung, hover over Insert Ladder Elements, then click on Direct Coil   .     2. Click the I/O - Micro820 tab towards the right and select an output coil - this guide uses _IO_EM_DO_02. Then click OK                  3. Add an input contact by right-clicking in the box to the left of the rung, hover over Insert Ladder Elements, then click on Direct Contact.   4. Click the I/O - Micro820 tab and scroll down to select an input - this guide uses _IO_EM_DI_02. Then click OK.        5. The program window should now look like this:     Upload   Next, you will propagate the program to the PLC.   1. Secure the test lead then apply power to the PLC.   2. Connect an ethernet cable directly between the PLC and your Windows computer.   3. Click Device > Connect to connect to the PLC; a pop-up will appear saying the project does not match the program in the controller.     NOTE: When either your PLC or computer are restarted, they may be assigned a new IP address, requiring you to reconfigure the connection. Click the tab labled with your PLC, then click the pencil icon next to connection path, click Browse, expand the Ethernet driver, highlight the active controller, and click OK. Click Close and then Connect.       4. Click Download current project to the controller   5. Confirm overwriting any program in the controller by clicking Download.   6. After your project is downloaded, run it on the controller by clicking Yes.     7. Touch the test lead to the I-02 terminal, and your program will turn on the #2 output. You can confirm your project is working by both hearing the soft click from the PLC and seeing the output indicator turn on.       Step 4: Configure ThingWorx Kepware Server   Now that you have a simple project running on the PLC, you need to configure ThingWorx Kepware Server to monitor it.   1. Open ThingWorx Kepware Server, right-click on Connectivity, and click New Channel.   2. Select Allen-Bradley Micro800 Ethernet from the drop-down, then click Next.       3. Click Next to accept the defaults, and click Finish to create Channel2.   4. Click Click to add a device below Channel2, enter myPLC in the name field, and click Next.   5. Enter the IP address of your PLC, then click Next. The IP address of your PLC is shown in Connected Components Workbench in Device > Configure.       NOTE: The IP address of the PLC may change when it is power cycled and must be updated in ThingWorx Kepware Server to match   6. Click Next to accept default values for each pop-up, and click Finish to create the myPLC device.       7. Click the Click to add a static tag message.   8. Enter Coil2 in the Name field, _IO_EM_DO_02 in the Address field, change the Data Type drop-down to Boolean, and click OK.  The address must exactly match a variable name in the PLC.       9. Create a second tag by right-clicking on myPLC again and clicking New Tag.   10. Enter Coil3 in the Name field, _IO_EM_DO_03 in the Address field, select Boolean from the Data Type drop-down, and click OK.         Step 5: Troubleshooting   1. If the connection to the PLC stops working and there is a Thumbs Down icon next to your Properties, the ThingWorx Kepware Server trial edition drivers are not connected to your PLC. The trial edition stops running after 2 hours and must be stopped and restarted. Right-click on ThingWorx icon in system tray.     Click Stop Runtime service. Wait a minute for the process to stop, then click Start Runtime service.   2.  If Connected Components Workbench does not connect to PLC, check the IP address of the PLC using RS Linx Classic software that was installed as part of Connected Components  Workbench. RS Linx Classic is located Start > All Programs > Rockwell Software > RSLinx > RSLinx Classic Click AB_ETHIP-1, Ethernet and IP addresses of connected PLCs will be discovered   NOTE: A changed PLC IP Address (typically seen through Connected Components Workbench) will require an IP Address change in ThingWorx Kepware Server settings.       Step 6: Next Steps   Congratulations! You've successfully completed the Connect to an Allen-Bradley PLC tutorial. You've learned how to:   Create and upload a simple ladder logic application to a PLC Connect a PLC to ThingWorx Kepware Server   The next guide in the Using an Allen-Bradley PLC with ThingWorx learning path is Create an Application Key.   Learn More   Capability Resource Analyze Monitor an SMT Assembly Line     Additional Resources   For additional information on ThingWorx Kepware Server:   Resource Link Website Connecting & Managing Industrial Assets Documentation Kepware documentation Support Kepware Support site
View full tip
  Discover how ThingWorx Widgets can be implemented in a compelling Mashup design.   Guide Concept   This project will introduce how to create complex user interfaces that are built by combining simple Widgets and basic styling.   Following the steps in this guide, you will build a web application showing both geographic and table based information.   We will teach you how to create a professional user interface that effectively conveys information to users.     You'll learn how to   Organize UI elements in a Mashup layout Use the Repeater widget effectively Use Styles to customize UI elements within a Mashup   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete ALL parts of this guide is 60 minutes     Step 1: Top Level Layout   A Mashup like this does take some time to assemble, but is built by layering simple Widgets. In this guide, we will break down how this Mashup was created to give you a behind-the-scenes look and provide tips to use when developing your IoT application.     This professional-looking Mashup was created using only these Widgets:   Layout with both left and right sidebars and a footer Tabs - Responsive Repeater Navigation Image Property Display Gauge Google Map   The first Widget placed on this Mashup canvas was a Layout widget with both a Left and a Right Sidebar defined. The center portion of the layout has only one GoogleMap widget. The tractor icons displayed on the map were created by uploading a .png to create a Media entity then specifying the image as a custom MarkerStyle in the GoogleMap widget. In the following steps you will duplicate this Mashup.         Step 2: Import Data   In this step we will download and them import both a Thing Template and the sample data that are used throughout the exercise.   Download and save ConnectedTractors.xml which contains the Thing Template and example Things. In the lower left of Composer, click Import/Export, then Import.     In the Import From File pop-up, keep the defaults and click Browse.     Navigate to the ConnectedTractors.xml file you previously downloaded. Select the Entities file, then click Open. Click Import in the bottom right of the pop up, then click Close after file is successfully imported.     Step 3: Map Mashup   Follow the steps in this part of the lesson to create a Mashup with an organized, structured layout.   Create Mashup   Navigate to Browse > Visualization > Mashups.   Click + New.   Keep the defaults and click OK.   In the Name field, type TractorDemoMashup. If Project is not already set, click the + in the Project text box and select the PTCDefaultProject.   Click Save Click the Design tab in the Mashup Information panel Click the Layout tab, then click Add Left . Scroll down to Container Size, click Fixed Size then enter200 in the Width text box and press Tab to record your entry.   Click on the right side of your Mashup to select the larger container. Click Add Right before again scrolling down to Container Size, click Fixed Size then enter200 in the Width text box and press Tab to record your entry.        NOTE: The next step uses the Google Map Widget which may need to be downloaded and imported from IQNOX.com. A Step-by-step guide for using Google Maps with ThingWorx is available.   12. Click the Widgets tab on the top left of the Widget panel, then enter map in the search box of the Widget panel. 13. Click and drag the Google Map Widget onto the center area of the canvas. 14. Click Save   15. In the Data panel on the right click the + to add a data source for the Mashup. 16. Enter the name of the Template used to create the Things that will be shown on the Mashup. Click on the Template ConnectedTractor to use the sample data 17. Click the arrow to the right of GetImplementingThingsWithData, then click the Execute on Load check box before clicking Done.     Setup Map Data   In the Data panel on the right, if neccesary, expand the GetImplementingThingsWithData data source and then drag the All Data row onto the map widget.   Click Data in the Select Binding Target pop-up to connect the data source to the Data property of the Google Maps widget. In the Properties panel in the lower left, scroll to the LocationField property then select TractorLatLng   NOTE: The imported sample data provided for this lesson has a property named TractorLatLng that contains location information. Fields in the bound data with a type Location will be available in the drop down. 4. Click Save at the top of your Mashup. Click View Mashup to see the live map. NOTE: The map uses the standard markers, click on one of the markers to see that the marker changes to indicate that it is selected.     Customize Map Markers   In this part of the lesson we will show how to use a custom image for the map markers. Right-click on each of the images below to download and save them to use in the next step.       We will upload these images to create new Media entities and apply them to the Google Map widget. Click Browse > Visualization > Media.   Click + New. In the Name field, type TractorSelected.   If Project is not already set, click the + in the Project text box and select the PTCDefaultProject. Under Image, click Change. Navigate to and select the TractorSelected.png file you just downloaded. On the navigation pop-up, click Open to close the pop-up and confirm the image selection. At the top of Foundation, click Save.    Repeat steps 1 through 8 for TracktorUnselected. Open your Mashup and click on the Google Map widget. Click on Style Properties tab in the lower left and scroll to the MarkerStyle Property and click on the Default map marker image, then click edit.   Click Style Information in the left panel, then clear the default image by clicking the X next to Image.   Click the + to select a new image then scroll to the Media entity you just created. In this case, the TractorUnselected media. Click Save. NOTE: The Google Map widget is packaged with default style entities. By editing these styles we will change the markers for all Mashups running on this ThingWorx server. In later steps we show how to create one time use Styles instead of modifying the default Styles.   14. Repeat steps 1 through 8 to create and assign the TractorSelected image for the SelectedMarkerStyle Property. 15. Click Save for the Mashup, then View Mashup to see the custom map icons.       Step 4: Navigation Panel   The left sidebar defines the green background color in its style and contains just one Collection widget with custom embedded Mashups specified for both the Selected and the Unselected items. The logo at the bottom is an image defined in the Footer style.   The Collection widget works by duplicating an embedded panel Mashup that controls the display of data from each entity in collection of entities.   Add Footer   Select the left side container of your Mashup, then click the Layout tab Click Add Bottom and scroll down to Container Size, click Fixed Size then enter 60 in the Height text box and press Tab to record your entry.   Click Save.   Style Sidebar   Next, we are going to add a custom background color and image to the sidebar footer.   Click the Explorer tab in the widget panel then select the top container for the left sidebar.   Click the Style Properties tab in the lower left properties panel, then click to expand Base and flexcontainer. In the background tex box, enter #39736C for a dark green color, then press Tab.   Click the top left container, then, in the Style Properties tab, click to expand Base and flexcontainer. Click X in background property   Click the lower left container, and also click X to remove the background property.   Right-click on the image below to download and save it for use when we add a footer in the next step.   Create a Media entity as we did for the map markers by clicking the Browse folder icon, then click Media in the Visualization section. Click the + New to create a new Media entity. Enter twxpwr in the Name field for the footer image. If Project is not already set, click the + in the Project text box and select the PTCDefaultProject. Click Change in the Image section, then browse to the image you saved. Click Open, then Save.   Click in the lower-left footer container on your mashup, then click the Properties tab. Scroll to see the SourceURL property in the properties panel, then click the + to open the media selection window. Scroll to browse for the Media you just created.   Click the footer Media and then slick Save in Mashup Builder before continuing to the next step.     Click here to view Part 2 of this guide.
View full tip
  Setup methods and schemes to secure your data   Guide Concept   Securing data is often something thought of after an application is designed. It should always be the first and more important.   These concepts and steps will allow you to focus on development of your application while still allowing the ability to utilize the power of ThingWorx!   We will teach you how to design a secure environment and application from scratch     You'll learn how to   How to design and implement organizations and organization sections Creating secure User Groups with specific goals Limit access to resources   NOTE:  The estimated time to complete this guide is 30 minutes     Step 1: Examples and Strategy   If you’d like to skip ahead, download and unzip the completed example of the Aerospace and Defense learning path: AerospaceEntitiesGuide1.zip. Import the .twx files included.   In an ever-changing world, you are going to need to protect everything that is considered private. This includes your data, the data people provide you, and the resources you consider important. All of this can be done using the ThingWorx environment. ThingWorx provides a system for security that can be configured endlessly. There is the security being handled at the server level internally and with Apache, in which you have access to. The security being handled in the ThingWorx Composer, which you can customize. Lastly, there is the security you provide at the client side for users accessing your application or system.   Let us start working on securing our system before we add extra users and workers. First, we will create and organization and organization levels within our agency to help designate access. We will create the security access to the ThingWorx Composer, which is where our data will be held for now in this learning path. We will then create access levels for internal employees, including administrators, developers, and workers based on security clearance levels.     Step 2: Setup Organizations and Departments   Creating Our Organizations   If you need a refresher on how to create security groups and permissions, take a look back at our Configure Permissions Guide. If you are ready to get started, follow the instructions below:   1.  In the ThingWorx Composer, click the + New button in the top left.    2. In the dropdown list, click Organizations.      3. In the Name field, give our agency name, such as PTCDefenseDepartment.   4. Set the Project field to an existing Project (ie, PTCDefaultProject) and click Save to save your work. 5. Go to the Organization tab and you will see the beginning of our Organization.     Creating Our Departments    Let us add some departments in our Organizations. We will add a few here but add as many as you like. Just keep in mind, these departments do not need to match every department in the actual Organization. These departments will be used for access to different resources.   1. Click on the first unit and update the Name field to DefenseDepartment. Click the check mark to save your changes.   NOTE: You can add the spaces if it looks better to you. You will be using these departments throughout this learning path. You can also change these later.   2. Under our first unit (DefenseDepartment), click the green + button. Name this unit HumanResources.     3. Repeat the last step to create three more departments under our DefenseDepartment unit. Name these new units Agents, Visitors, and IT.   4. Under the Visitors unit, click the green + button to add a unit and name it Applicants.     5. Repeat the last step to add one more unit under the Visitors unit. Name this group OtherAgencies. Your setup should have the following departments.      You now have a complete start to our agency. What does that mean exactly? An Organization allows us to limit resources to only members of that overall Organization or specific unit within that Organization. You will get firsthand experience as we move further in this guide.    Let us create our Security Groups to those that will absolutely need it. This is a big decision point into how you would like to do this and there is no truly wrong answer. Will each user for this application or utility have their own User account in ThingWorx or share User accounts based on usage? Will you grant access to this application through LDAP, database verification, or a Create An Authentication Extension. The list of questions into what is supported for authentication in ThingWorx is almost endless.     Step 3: Setup Users and User Groups   Creating User Groups and Users   For simplicity and timing, we will create a User Group and User for each department (be mindful of the number of allowed Users in the ThingWorx version you are using). We will also create a super user account that will provide us with full access. Finally, we will need to create an extra User Groups for ThingWorx Composer access.     First, User Groups   1. In the ThingWorx Composer, click the + New at the top left of the screen.     2. Select User Groups in the dropdown.     3. Name the User Group Agency.ComposerAccess.     4. Set the Project field to an existing Project (ie, PTCDefaultProject) and click Save. 5. Repeat steps 1-4 to create a User Group for each department (Agency.HumanResources, Agency.Agents, Agency.Visitors, Agency.Applicants, Agency.OtherAgencies, and Agency.IT).   Now, Users   1. In the ThingWorx Composer, click the + New at the top left of the screen.     2. Select User in the dropdown.     3. Name the User User.AgencySuperUser and add a password.     4. Set the Project field to an existing Project (ie, PTCDefaultProject) and click Save. 5. Repeat steps 1-4 to create a User for each department (User.HumanResources, User.Agents, User.Visitors, User.Applicants, User.OtherAgencies, and User.IT).   Adding Members to User Groups   Assign each user to the corresponding User Group using the below instructions.   1. Open the Agency.HumanResources User Group.  2. Click on the Manager Members tab.     3. Filter and select the User you want to add in the Available Members section. In this case, User.HumanResources. 4. Click the arrow on that User’s row or drag and drop the User to the Members section.      5. Click Save. 6. Repeat steps 1-5 for each department User Group you created earlier with their corresponding User.   We should have an extra User Group (Agency.ComposerAccess) and an extra User (User.AgencySuperUser). We will utilize these Entities below. For now, only our IT department needs access to the ThingWorx Composer.   1. Open the Agency.ComposerAccess User Group.  2. Click on the Manager Members tab.     3. Filter and select the User Group you want to add in the Available Members section. In this case, Agency.IT. 4. Click the arrow on that User’s row or drag the User to the Members section.      5. Click Save.   Our super user will need top level access to everything in ThingWorx. To do this, we will add the User to the Administrators User Group.   1. On the left-hand side of the ThingWorx Composer, click Browse. 2. Click on User Groups on the left panel.     3. At the top of the screen, click the filter button near the search bar. 4. Check the checkbox for Show System Objects and click Apply.     5. Filter and select the Administrators User Group.    6. Click on the Manager Members tab.     7. Filter and select the User you want to add in the Available Members section. In this case, User.AgencySuperUser. 8. Click the arrow on that User’s row or drag the User to the Members section.    9. Click Save.     Step 4: Setup Permissions   Setting Bulk Permissions   1. On the left panel, select Permissions.   2. Click Collections on the menu that appears.     3. Select the checkbox at the top to select all available Entities then click Edit Permissions.     4. On the Visibility tab, click the + button in the Search Organizations filter. 5. Enter PTCDefenseDepartment and click the expand arrows to select the IT department. A more granular Visibility level can be set on the specific Entities when created later in this learning path.     6. Select the Design Time tab. 7. Enter Agency.ComposerAccess in the search bar and select the Agency.ComposerAccess User Group.   8. Select the check marks for Create, Read, Update, and Delete. A more expansive design for a production environment would create more Users and User Groups to have such access.     9. Set the permissions for the other groups we have created to not allow any Create, Read, Update, and Delete permissions for groups outside of Agency.ComposerAccess and Agency.IT. It should look like the below configuration.     10. Set the same permissions in the Run Time tab for the User Groups we have created.     11. Click Save.   Now, if you log into the ThingWorx Composer using any account other than our super user account or the User.IT account, you’ll see that you may be able to see Entities, but you cannot open them. You will see an unauthorized popup. If you have access to a browser with a Private or Incognito mode, use it instead of logging out of your Administrator account.     Click here to view Part 2 of this guide.
View full tip
  Convey information about IoT data effectively by customizing style definitions and implementing event-based logic   Guide Concept   This project will help you identify how you would like to create an experience for Users.   Following the steps in this guide, you will use color schemes to convey information quickly and effectively, for example to alert users of critical events. With ThingWorx Composer, you can implement Styles and States in your Mashups to enhance your user experience.   We will teach you how to create an affective IoT application experience that looks great and easy to navigate. How the UI is presented can influence users and their enjoyment of the application.   You'll learn how to   Create a Style Definition Customize Style Definitions Create and implement State Definitions Implement event-based state changes   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete this guide is 60 minutes       Step 1: Completed Example   Download the StylesAndStates.xml attached to this guide.  Within this file, you will find Entities referenced in this lesson, including a finished application.  Import and utilize this file to see a finished example and return to it as a reference if you become stuck during this guide and need some extra help or clarification.   Keep in mind, this download uses the exact names for entities used in this tutorial. If you would like to import this example and also create entities on your own, change the names of the entities you create.     Step 2: Create Style Definition   A Style Definition is a collection of HTML styling elements that can be applied to a Widget just as you would apply a CSS definition to an HTML tag. With Style Definitions, you can control the look and feel, such as colors, fonts, and color context of individual Widgets in your Mashup.   In the ThingWorx Composer, click the + New at the top of the screen.   Select Style Definition in the dropdown.   Enter a name for the Style Definition, such as StyleDefinition. Set the Project to an existing Project (ie, PTCDefaultProject).   Click Style Information.   The Style Information page shows the options for images, colors, lines, and display text. See the table below for information on what each field controls.   6. Type PlaygroundBackground in the Display String field.   NOTE: If you go back to the HelloWorldPlayground, clear the Mashup Style property, then search for StyleDefinition again, you will see the PlaygroundBackground descriptive text.   7. Select Background Color. A color pallet will appear. Select White and click Select.   8. Select Text Color. A color pallet will appear. Select Black and click Select.   9. Click Save.     You have now created your first Style Definition. To ensure a consistent user experience, we recommend creating a Style Definition that you can use throughout your application.    Option                                    Description Display String Descriptive string that can be displayed to indicate the current applied style definition Background Color Background for charts, buttons, panels, etc Secondary Background Color Meant for widgets that support gradients Foreground Color Used for foreground characteristics such as button text and label text Font Bold For text, whether the text should be bold or not Font Italic For text, whether the text should be italicized or not Font Underline For text, whether the text should be underlined or not Image Add images Line Color Pen styling in charts Line Thickness Pen styling in charts Line Style Generally refers to borders. ThingWorx provides the following options: Solid, Dashed, Dotted, None Text Size Choose a font size from 9-72px   In the next part of this exercise, you’ll learn how to use Style Definitions to create an engaging experience for your application users.       Step 3: Customize Style Definitions   Open the HelloWorldPlayground Mashup in Composer, and click View Mashup.   It shows a Button that sends an Event to a Gauge Widget, which then updates a Line Chart.     Modify Style Definition   In this part of the lesson, we'll make some changes to this Mashup. We will use Style Definitions to change the background of the Mashup, change the colors used in the Line Chart in order information stand out, and add color to the Gauge Widget.   In the Explorer tab, select the Mashup. Select the Style Properties tab, then click the X button to clear the Style Mashup Properties.   When editing a Mashup, you can either use a Style Definition Thing that you created earlier OR you can click the wand in a style property for a Mashup or Widget followed by clicking the + Custom button to create a one-time-use style. 3. With the Style Property clear, enter the Style Definition you created in the last section. Update the Background Color to #FF9082 to have the color pop in the Mashup.   4. Click Save and View Mashup to see the changes. You have now updated the background for the HelloWorldPlayground. The style properties you define in the Style Definition will be consitent for any Mashup that references this Style Definition. Change the style around or create a custom style and see the changes in the Mashup. Below is what we'll be working to create. Get ideas of things you might want to see differently in your styling.     Customize Widget Style   ThingWorx provides a default Style Definition for many of its Widgets. Before editing the Style Definitions of a Widget, click the Style Definition property then click View. This enables you to see what the current values are and what you might want to change. If the changes are slight, create a copy of the original Style Definition and update the new version.   Until you are sure of the color schemes you would like to implement, use the default Style Definitions as a guide when creating your own versions.   Default Style Definitions   Next, we will update the colors and style of the Line Chart.   Open the HelloWorldPlayground and select the Line Chart in the Workspace pane. Click the Style Properties tab to see the chart styles section.   Update the Legend->Color property to Blue.     Customize Chart Style Theme   In this part of the lesson, we will update the Series1 and StyleTheme properties of the Line Chart. This is how you'll also set the colors for the chart titles.   The Series1 property will update the look and feel of the line for the count value being used. The Line Chart is a line graph, thus the only property you need to change is the Line Color property.   The StyleTheme property will update the background look of the Line Chart grid.   Clear the StyleTheme and click the + button to create a new theme. Create a theme with the name CustomTheme.   Click the Style tab and edit the feel of the items as you see fit.   After open the Style Theme to be editable, click on colors. Here you'll see all the options and fields that you can make up your own color options and be as conservative as you like or as free as you like.     Click Text Colors, then click on the Grids and Lists tab on the right. This is where we will be shaping our colors for the chart. When you're done with this, update the Core Colors section to make your mashup pop even more.     You may also notice a more focused method of updating grids and lists. In the below Elements section, you'll have a more focused experience for updated.     NOTE: As an extension, after completing the previous steps, try to use Style Definitions to customize the sections of the UI on your own.     Click here to view Part 2 of this guide.
View full tip
Announcements