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

Community Tip - You can subscribe to a forum, label or individual post and receive email notifications when someone posts a new topic or reply. Learn more! X

IoT Tips

Sort by:
  Use ThingWorx Advisors to view trends and monitor Alerts. Step 2: Create and Configure Alert   Click the grid icon.   Select Configuration and Setup, then select the Alert tab. NOTE: If you are using the Demo Factory Simulator, you will see that several alerts have already been configured. To create a new alert, click the Alert tab, then click the + icon. Select the following properties in the Select Tag or Property box: Under Equipment Type, select Asset. Under Equipment, select 1-3_CNCMill. In Properties, click Temperature. Click OK. Set up the following in the Create New Alert pop-up: In the Alert Name text box, type HighTemp. In the Alert Type drop-down, choose Above. In the Value text box, type 34. In the Alert Description text box, type Temperature close to failure.   NOTE: An Alert will now be triggered whenever the temperature of Asset1 is more than 34.   Step 3: Monitor Alert   Click the grid icon. Select Alert Monitoring. NOTE: You can see the temperature alert message that you created earlier, and the amount of time that it’s been in that state. Select the HighTemp alert. Confirm that the Acknowledged field is recorded as false in the lower left-hand corner beneath the Details.   Select the HighTemp alert, then click the check mark icon to acknowledge the alert.   In the Acknowledge Alerts dialog, provide explanation. Click OK.   Note the updates to the Alert Monitoring page.   NOTE: Anyone viewing the Alerts will now be able to clearly see the green check mark, which indicates that the Alert has been acknowledged.   Step 4: Next Steps  Next Steps   Congratulations! You've successfully completed the Configure ThingWorx Advisors for Trending and Alerts guide. You have learned how to create and monitor trends and alerts based on assets connected with Kepware.   Additional Resources   If you have questions, issues, or need additional information, refer to:   Resource Link Community ThingWorx Manufacturing Community Support Kepware Technical Support Manufacturing Home ThingWorx Manufacturing    
View full tip
  Step 5: Additional Services   The Trend, Range, and Threshold Services are some of the Services the Statistical Monitoring ThingShape offers. Below is a table of additional included Services.   Links to guides for using services like these to build complete IoT applications are found in the next step.   Calculation Service Name Description Consecutive Points Based On a Range GetNumberOfConsecutivePointsBasedOnARange Calculate the number of points in the largest group of consecutive points meeting the range criteria. Consecutive Points Based On a Threshold GetNumberOfConsecutivePointsBeyondAThreshold Calculate the number of points in the largest group of consecutive points meeting the threshold criteria. Number of Points with Percentage Change Out of Range GetNumberOfPointsWithChangeRateOutOfRange Monitor for how many pairs of consecutive points in a series have a numerical percentage change outside the defined range. If the first value in a pair is 0, the pair is not considered.       Step 6: Next Steps   Congratulations!   In this guide, you've learned how to:   Create a Value Stream Create a Thing with the Statistical Monitoring Thing Shape Modify a Property to record values to the Value Stream Test built-in Services used in Statistical Monitoring   Learn More   We recommend the following resources to continue your learning experience:   Capability Guide Build Get Started with ThingWorx for IoT Build Build a Predictive Analytics Model Build Operationalize an Analytics Model   Additional Resources   If you have questions, issues, or need additional information, refer to:   Resource Link Community Developer Community Forum Support Descriptive Analytics Help Center    
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
    Use ThingWorx Advisors to view trends and monitor Alerts.     GUIDE CONCEPT   The intent of this guide is to provide instructions to configure trends and alerts in the ThingWorx Advisors.   NOTE: This guide's content aligns with ThingWorx 9.3. The estimated time to complete all parts of this guide is 30 minutes.     YOU'LL LEARN HOW TO   In this guide, you will learn how to: Configure and view trends in machine performance Create and configure an alert Monitor an alert   Step 1: Configure and View Trends  To begin, you will learn how to open up ThingWorx Advisors.   In ThingWorx Foundation Composer, click Browse then Visualization > Master then click PTC.Factory.PlantStatus.Master.          2. Next click the View Mashup button.                 3. Click the Utility Selector grid in the upper left            4. Click Trending and Troubleshooting              5. Click the + icon.               NOTE : A New Trend pop-up will appear.        6. In the Trend Name text box, type Station A Temperature, then click OK.              7. In the Tags area, click the + icon to start plotting a tag             8. In the Equipment Type drop-down, choose KEPServerEX, in the Equipment drop-down,        choose your KEPServer or the simulation server.          9. In the Server Structure menu, click LineGroup1 and use the drop-down menu to select LineGroup1.1-3_CNCMill. In the Tags menu area, click Temperature then click OK, or choose a tag based on your KepServer configuration.   10. Review the trend data for Station A.     11.  Repeat these steps to apply additional property setting to Station A.   12. Check the Show Value Range box in the Tags area. Review the trend data for the properties selected.                      NOTE: The three selected tags will appear plotted in the Show Value Range table.     Click here to view Part 2 of the guide.  
View full tip
  Step 5: Add Data   Now that our Mashup's Layout and Widgets have been set, we need to bring in backend data and tie it to those Widgets for display.    We'll make use of Mashup Data Services for this. The first one we'll add will be UserManagementSubsystem > GetUserCount.   Ensure that the Data tab in the top-right is active.   Click the + icon.   In the Entity field, search for and select UserManagementSubsystem.   In the Services field, type GetUserCount.   Beside the GetUserCount Service, click the right arrow. Under Selected Services, check the box for Execute on Load.     Add LicensingSubsystem > GetCurrentLicenseInfo   You're not limited to only pulling information from one Mashup Data Service.   We already have User Management's GetUserCount. We'll now also bring in information from the Licensing Subsystem.   On the same Add Data pop-up, click the X beside UserManagementSubsystem to clear it.   In the Entity field, search for and select LicensingSubsystem.   In the Services field, type GetCurrentLicenseInfo.   Beside GetCurrentLicenseInfo, click the right arrow. Under Selected Services on the GetCurrentLicenseInfo line, check the box for Execute on Load.   On the bottom-right of the pop-up, click Done.   At the top, click Save.   Bind Data   With our backend data now accessible, let's bind it to our Widgets for display.   On the Data tab, expand Subsystems_LicensingSubsystem > GetCurrentLicenseInfo > Returned Data.   Drag-and-drop Licensing's All Data onto the Grid Advanced Widget in the bottom section.   On the Select Binding Target pop-up, click Data.   Expand Subsystems_UserManagementSubsystem > GetUserCount > Returned Data > All Data.   Drag-and-drop User Management's result onto the Text Field Widget in the top section.   On the Select Binding Target pop-up, click Text.   At the top, click Save.   Automatically Refresh   If we were to click View Mashup now, we would see the User Count and Licensing info displayed in the Mashup's Widgets. However, it would never update unless we manually refreshed the page.   To automate that process, we'll use the Auto Refresh Widget.   In the top section of the Mashup, click the Auto Refresh Widget to select it.   On the top-left of the Auto Refresh Widget, click the drop-down icon to reveal additional options.   Drag-and-drop the Refresh Event onto GetCurrentLicenseInfo.   Repeat steps 1-3 to drag-and-drop the Refresh Event onto GetUserCount also.   With the Auto Refresh Widget still selected, browse the Properties section in the bottom-left.   Change RefreshInterval to 5, and hit your keyboard's Tab key to lock in the change. This will cause the Refresh Event to fire every 5 seconds.   Click Save. Click View Mashup.     Step 6: Replace License   We have now created a Minimum Viable Product (MVP) of a "licensing dashboard" to ease our administration work.   This dashboard could still be improved. For instance, a Mashup Function could be created which automatically recalculates the value from GetUserCount to more accurately match GetCurrentLicenseInfo. This can be accomplished via the Mashup Builder's bottom-right Functions tab. Or, you could even add a separate Text Field Widget to to the top section and directly access the remaining license time via the LicensingSubsystem > GetDaysRemainingInLicense Service.    Whatever you choose to do to improve the Mashup is up to you.   However, what should be done when a license is nearing its expiration? To resolve this issue, we need to replace the existing license via the AcquireLicense Service.   Within the OS of the Foundation server, navigate to the file-system folder where the current license_capability_response.bin is located. This is typically the ThingworxPlatform folder.   Move the existing license_capability_response.bin and any other existing *.bin files to another location for backup. Note that this is EXTREMELY important, as if anything goes wrong, you want to be able to restore the original license. It is very important to ensure that only one *.bin file exists in the appropriate folder Place the new .bin file into the appropriate folder and rename it to license_capability_response.bin. In Foundation, navigate to the LicensingSubsystem > Services page.   On the AcquireLicense row, click the "play" icon for Execute Service.   On the bottom-right of the pop-up, click Execute. Note that if you receive an error, it will be necessary to restart the ThingWorx Tomcat service.  The act of restarting the service will automatically load the new license.   To close the pop-up, click Done.   After acquiring your new license, you should immediately return to the LicensingSubsystem and consult the GetCurrentLicenseInfo Service to confirm that Thing, User, expiration-date, and other issues are accurate.   If anything goes wrong with the new license transfer, you can simply replace the original license_capability_response.bin file and re-run AcquireLicense to return to your old one. Once again, it is import to perform these steps well before your expiration occurs.    Foundation checks for a valid license periodically. If this happens while you have an invalid license_capability_response.bin file in-place, you will no longer be able to access the Foundation GUI.    Fortunately, these issues are self-correcting if a valid license_capability_response.bin is placed in the correct location, as these periodic checks will also pick up a valid license_capability_response.bin file automatically, even after the system has locked you out.    You should also be able to trigger an AcquireLicense action via a REST call even if the GUI is unavailable.      Step 7: Next Steps   Congratulations! You've successfully completed the Manage Licensing with Foundation Subsystems guide.   In this guide, you learned how to:   Access the Foundation Subsystems Execute built-in Services to retrieve: User counts Thing counts License expiration count Create a "License Dashboard" Mashup Update to a new License    Additional Resources   If you have questions, issues, or need additional information, refer to:    Resource       Link Community Developer Community Forum Support Foundation Help Center  
View full tip
  Step 5: Java - Events   While connected to the server, you can trigger an event on a remote Thing. The code snippet from the Simple Thing example below shows how to use a ValueCollection to specify the payload of an event, and then trigger a FileEvent on a remote Thing.   Create Event   The two implementations of the VirtualThing.defineEvent method are used to create an event definition ThingWorx Platform. @ThingworxEventDefinitions(events = { @ThingworxEventDefinition(name = "SteamSensorFault", description = "Steam sensor fault", dataShape = "SteamSensor.Fault", category = "Faults", isInvocable = true, isPropertyEvent = false) }) public void defineEvent(String name, String description, String dataShape, AspectCollection aspects) { EventDefinition eventDefinition = new EventDefinition(name, description); eventDefinition.setDataShapeName(dataShape); if (aspects != null) { eventDefinition.setAspects(aspects); } this.getThingShape().getEventDefinitions().put(name, eventDefinition); } public void defineEvent(EventDefinition eventDefinition) { this.getThingShape().getEventDefinitions().put(eventDefinition.getName(), eventDefinition); }   Queue Event   To queue an event, create a ValueCollection instance, and load it with the necessary fields for the DataShape of that event. ValueCollection eventInfo = new ValueCollection(); eventInfo.put(CommonPropertyNames.PROP_MESSAGE, new StringPrimitive("Temperature at " + temperature + " was above limit of " + temperatureLimit)); super.queueEvent("SteamSensorFault", DateTime.now(), eventInfo); super.updateSubscribedEvents(60000);   Fire Event   You can send the client a request to fire the event with the collected values, the event, and information to find the entity the event belongs to as shown below. In order to send the Event to the ThingWorx Platform, use the VirtualThing.updateSubscribedEvents method. ValueCollection eventInfo = new ValueCollection(); eventInfo.put(CommonPropertyNames.PROP_MESSAGE, new StringPrimitive("Temperature at " + temperature + " was above limit of " + temperatureLimit)); super.queueEvent("SteamSensorFault", DateTime.now(), eventInfo); super.updateSubscribedEvents(60000);     Step 6: Java - Services   Create Services   Simply use the ThingworxServiceDefinition and ThingworxServiceResult anotations to create a service. Then, you can define the service as shown in this code: @ThingworxServiceDefinition(name = "GetSteamSensorReadings", description = "Get SteamSensor Readings") @ThingworxServiceResult(name = CommonPropertyNames.PROP_RESULT, description = "Result", baseType = "INFOTABLE", aspects = { "dataShape:SteamSensorReadings" }) public InfoTable GetSteamSensorReadings() { InfoTable table = new InfoTable(getDataShapeDefinition("SteamSensorReadings")); ValueCollection entry = new ValueCollection(); DateTime now = DateTime.now(); try { // entry 1 entry.clear(); entry.SetStringValue(SENSOR_NAME_FIELD, "Sensor Alpha"); entry.SetDateTimeValue(ACTIV_TIME_FIELD, now.plusDays(1)); entry.SetNumberValue(TEMPERATURE_FIELD, 50); entry.SetNumberValue(PRESSURE_FIELD, 15); entry.SetBooleanValue(FAULT_STATUS_FIELD, false); entry.SetBooleanValue(INLET_VALVE_FIELD, true); entry.SetNumberValue(TEMPERATURE_LIMIT_FIELD, 150); entry.SetNumberValue(TOTAL_FLOW_FIELD, 87); table.addRow(entry.clone()); // entry 2 entry.clear(); entry.SetStringValue(SENSOR_NAME_FIELD, "Sensor Beta"); entry.SetDateTimeValue(ACTIV_TIME_FIELD, now.plusDays(2)); entry.SetNumberValue(TEMPERATURE_FIELD, 60); entry.SetNumberValue(PRESSURE_FIELD, 25); entry.SetBooleanValue(FAULT_STATUS_FIELD, true); entry.SetBooleanValue(INLET_VALVE_FIELD, true); entry.SetNumberValue(TEMPERATURE_LIMIT_FIELD, 150); entry.SetNumberValue(TOTAL_FLOW_FIELD, 77); table.addRow(entry.clone()); } catch (Exception e) { e.printStackTrace(); } return table; }   NOTE: This service will be callable by the ThingWorx Platform.   Call Services   The are two types of service calls that can be made. The first type belongs to the ConnectedThingClient class. This client has methods for processing information where only the parameters for the method is necessary. The other type of call is based on services located on an Entity. For these calls, you must create a ValueCollection instance, and load it with the necessary parameters of the service.   After loading the ValueCollection instance, send the client the request to execute the service with the:   Parameter values Service name Timeout setting (in milliseconds) for the service to finish executing Information to find the entity the service belongs to   The first type of call can be seen in SimpleClient.java: InfoTable result = client.readProperty(ThingworxEntityTypes.Things, ThingName, "name", 10000); String name = result.getFirstRow().getStringValue("name");   The second type of call can be seen below: ValueCollection payload = new ValueCollection(); payload.put("name", new StringPrimitive("Timothy")); InfoTable table = handleServiceRequest("ServiceName", payload);   TIP: Put the code for creating the service and event in the constructor of the extended VirtualThing (or a method called from the constructor). Also, the service code examples will work as long as the actual service is defined. We recommend the annotation method as shown in the examples because it is much cleaner.       Click here to view Part 5 of this guide.  
View full tip
    Step 2: Java Properties   In the ThingWorx environment, a Property represents a data point, which has a:   Name Value Timestamp Quality (optional)   Define Properties   You can define attributes, base types and other aspects of ThingWorx properties.   Attributes   The table below provides information on the different attributes that are used to define a property. Attribute Details name Specifies the name of the property that will appear in ThingWorx when users browse to bind the related Thing. description Provides additional information for the property. baseType Specifies the type of the property. For a list of base types supported by the SDK, refer to the BaseTypes chart below.   BaseTypes   The table below provides information on the different types of properties that can be created in ThingWorx. BaseType Primitive Description BOOLEAN BooleanPrimitive True or false values only DATETIME DatetimePrimitive Date and time value GROUPNAME StringPrimitive ThingWorx group name HTML StringPrimitive HTML value HYPERLINK StringPrimitve Hyperlink value IMAGE ImagePrimitive Image value IMAGELINK StringPrimitive Image link value INFOTABLE InfoTablePrimitive ThingWorx infotable INTEGER IntegerPrimitive 32–bit integer value JSON JSONPrimitive JSON structure LOCATION LocationPrimitive ThingWorx location structure MASHUPNAME StringPrimitive ThingWorx Mashup name MENUNAME StringPrimitive ThingWorx menu name NOTHING N/A No type (used for services to define void result) NUMBER NumberPrimitive Double precision value STRING StringPrimitive String value QUERY N/A ThingWorx query structure TEXT StringPrimitive Text value THINGNAME StringPrimitive ThingWorx Thing name USERNAME StringPrimitive ThingWorx user name XML XMLPrimitive XML structure   Aspects   Aspects define the ways to interact with a property. The table below provides information on frequently used Aspect attributes of a property. Attribute Description isPersistent Set to TRUE for the ThingWorx server to persist the value even if it restarts. It is extremely expensive to have persistent values, so it is recommended to set this value to FALSE unless absolutely necessary. isReadOnly Set to TRUE to inform the ThingWorx server that this value is only readable and cannot be changed by a request from the server. dataChangeType Describes how the ThingWorx server responds when the value changes in the client application. Subscriptions to these value changes can be modeled in ThingWorx Core. If nothing needs to react to the property change, set this value to NEVER. dataChangeThreshold Defines how much the value must change to trigger a change event. For example 0 (zero) indicates that any change triggers an event. A value of 10 (ten) for example would not trigger an update unless the value changed by an amount greater than or equal to 10. defaultValue The default value is the value that ThingWorx Core uses when the RemoteThing connected to the device first starts up and has not received an update from the device. The value is different based on the different value for each base type. cacheTime The amount of time that ThingWorx Core caches the value before reading it again. A value of -1 informs the server that the client application always sends its value and the server should never go and get it. A value of 0 (zero) indicates that every time the server uses the value, it should go and get it from the client application. Any other positive value indicates that the server caches the value for that many seconds and then retrieves it from the client application only after that time expired. pushType Informs ThingWorx Core how the client application pushes its values to the server.   NOTE: cacheTime and dataChangeThreshold are for subscribed (bound) properties ONLY.   DataChangeType Values   This field acts as the default value for the data change type field of the property when it is added to the remote Thing. The possible dataChangeType values are below: Value Description  ALWAYS Always notify of the value change even if the new value is the same as the last reported value. VALUE Only notify of a change when a newly reported value is different than its previous value. ON For BOOLEAN types, notify only when the value is true. OFF For BOOLEAN types only, notify when the value is false. NEVER Ignore all changes to this value.   PushType Values   This aspect works in conjunction with cacheTime. The possible pushType values are below: Value Description ALWAYS Send updates even if the value has not changed. It is common to use a cacheTime setting of -1 in this case. VALUE Send updates only when the value changes. It is common to use a cacheTime setting of -1 in this case. NEVER Never send the value, which indicates that ThingWorx server only writes to this value.It is common to use a cacheTime setting of 0 or greater in this case. DEADBAND Added to support KEPServer, this push type is an absolute deadband (no percentages). It provides a cumulative threshold, such that the Edge device should send an update if its current data point exceeds Threshold compared to the last value sent to ThingWorx Core. It follows existing threshold fields limits.     Click here to view Part 3 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 10: C - Info Tables   Infotables are used for storing and retrieving data from service calls. An infotable has a DataShapeDefinition that describes the names, base types, and additional information about each field within the table.   In order to create an Infotable, you can do so with the provided macros or functions.   Define With Macros   In order to define Infotables using a macro, use TW_MAKE_INFOTABLE or TW_MAKE_IT. Both macros can be used interchangeably.   NOTE: The macros are all defined in the twMacros.h header file. twInfoTable* it; it = TW_MAKE_IT( TW_MAKE_DATASHAPE(DATSHAPE_NAME_SENSOR_READINGS, 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) ), TW_IT_ROW(TW_MAKE_DATETIME_NOW,TW_MAKE_STRING("Sensor Alpha"),TW_MAKE_NUMBER(60),TW_MAKE_NUMBER(25),TW_MAKE_BOOL(TRUE),TW_MAKE_BOOL(TRUE),TW_MAKE_NUMBER(150),TW_MAKE_NUMBER(77)), TW_IT_ROW(TW_MAKE_DATETIME_NOW,TW_MAKE_STRING("Sensor Beta"),TW_MAKE_EMPTY,TW_MAKE_NUMBER(35),TW_MAKE_BOOL(FALSE),TW_MAKE_BOOL(TRUE),TW_MAKE_EMPTY,TW_MAKE_NUMBER(88)), TW_IT_ROW(TW_MAKE_DATETIME_NOW,TW_MAKE_STRING("Sensor Gamma"),TW_MAKE_EMPTY,TW_MAKE_NUMBER(80),TW_MAKE_BOOL(TRUE),TW_MAKE_BOOL(FALSE),TW_MAKE_NUMBER(150),TW_MAKE_NUMBER(99)) );   Define Without Macros   In order to define Infotables without using a macro, use the twDataShape_CreateFromEntries function.   twInfoTable * it = NULL; twInfoTableRow * row = NULL; it = twInfoTable_Create(ds); if (!it) { TW_LOG(TW_ERROR,"createNewThing: Error creating infotable"); twDataShape_Delete(ds); return TW_ERROR_ALLOCATING_MEMORY; } row = twInfoTableRow_Create(twPrimitive_CreateFromString("SimpleThing_2", TRUE)); if (!row) { TW_LOG(TW_ERROR,"createNewThing: Error creating infotable row"); twInfoTable_Delete(it); return TW_ERROR_ALLOCATING_MEMORY; } twInfoTableRow_AddEntry(row, twPrimitive_CreateFromString("A new Thing", TRUE)); twInfoTableRow_AddEntry(row, twPrimitive_CreateFromString("RemoteThing", TRUE)); twInfoTable_AddRow(it, row);   Retrieve With Macros   Many of the calls to services in ThingWorx will return an InfoTable of information. Below is an example of using the TW_GET_NUMBER_PARAM macro to retrieve values from an Infotable: ///Data is stored in the params variable ///Retrieve the a and b values then store them in variables twInfoTable * params double a, b; TW_GET_NUMBER_PARAM(params, "a", 0, &a); TW_GET_NUMBER_PARAM(params, "b", 0, &b);   Retrieve Without Macros   Below is an example of using the twInfoTable_GetNumber function to retrieve values from an Infotable: ///Data is stored in the params variable ///Retrieve the a and b values then store them in variables twInfoTable * params double a, b; twInfoTable_GetNumber(params, "a", 0, &a); twInfoTable_GetNumber(params, "b", 0, &b);       Step 11: C - Events   Event definitions describe interrupts that ThingWorx can subscribe to in order to receive notifications when something happens.   The parameters for an event definition are:   name description dataShape aspects   In order to create an Event, you can do so with the provided macros or functions.   Define With Macros   In order to define an Event using a macro, you will use TW_DECLARE_EVENT or TW_EVENT. Both macros can be used interchangeably. NOTE: The macros are all defined in the twMacros.h header file. TW_EVENT("SteamSensorFault", "Steam sensor event", TW_MAKE_DATASHAPE( "SteamSensorFault", TW_DS_ENTRY("message",TW_NO_DESCRIPTION,TW_STRING) ) );   Define Without Macros   In order to define an Event without using a macro, you will use the twApi_RegisterEvent function. See an example below of how to utilize the twApi_RegisterEvent function and adding a row of data: twApi_RegisterEvent(TW_THING, "SteamSensor", "SteamSensorFault", "Steam sensor event", ds);   Fire With Macros   In order to fire an Event using a macro, you will use TW_FIRE_EVENT.   NOTE: The macros are all defined in the twMacros.h header file. TW_FIRE_EVENT(thingName, "SteamSensorFault", TW_MAKE_IT(TW_MAKE_DATASHAPE( "SteamSensorFault", TW_DS_ENTRY("message", TW_NO_DESCRIPTION, TW_STRING) ), TW_IT_ROW(TW_MAKE_STRING(msg)) ));   Fire Without Macros   In order to fire an Event without using a macro, you will use the twApi_FireEvent function. See an example below of how to utilize the twApi_FireEvent function and adding a row of data: twApi_FireEvent(TW_THING, "SteamSensor", "SteamSensorFault", eventInfoTable, -1, TRUE)       Step 12: C - Services   Service Handler Callbacks The service callback function is registered to be called when a request for a specific service is received from the ThingWorx Platform. These functions must have the same signature as shown here: typedef enum msgCodeEnum (*service_cb) (const char * entityName, const char * serviceName, twInfoTable * params,twInfoTable ** content, void * userdata) Below is an example of a single service that adds two numbers that can be registered with and without macros: /***************** Service Callbacks ******************/ /* Example of handling a single service in a callback */ enum msgCodeEnum addNumbersService(const char * entityName, const char * serviceName, twInfoTable * params, twInfoTable ** content, void * userdata) { double a, b, res; TW_LOG(TW_TRACE,"addNumbersService - Function called"); if (!params || !content) { TW_LOG(TW_ERROR,"addNumbersService - NULL params or content pointer"); return BAD_REQUEST; } twInfoTable_GetNumber(params, "a", 0, &a); twInfoTable_GetNumber(params, "b", 0, &b); res = a + b; *content = twInfoTable_CreateFromNumber("result", res); if (*content) return SUCCESS; else return INTERNAL_SERVER_ERROR; }   NOTE: The return value of the function is TWX_SUCCESS if the request completes successfully or an appropriate error code if not (should be a message code enumeration as defined in twDefinitions.h).   Register Service Callback   In order to register a service handler callback using macros, utilize TW_DECLARE_SERVICE as shown below: TW_MAKE_THING(thingName,TW_THING_TEMPLATE_GENERIC); TW_DECLARE_SERVICE( "AddNumbers", "Add two numbers together", TW_MAKE_DATASHAPE(NO_SHAPE_NAME, TW_DS_ENTRY("a", TW_NO_DESCRIPTION ,TW_NUMBER), TW_DS_ENTRY("b", TW_NO_DESCRIPTION ,TW_NUMBER)), TW_NUMBER, TW_NO_RETURN_DATASHAPE, addNumbersService );     Click here to view Part 9 of this guide
View full tip
    Step 7: C - Entities and Functions   All SDKs require a RemoteThing be created in ThingWorx in order to communicate. If many Things are to be created with the same properties, services, and events, we recommend that a Thing Template be derived from one of the supplied RemoteThing templates.   NOTE: The macros are all defined in the twMacros.h header file.   Define ThingShape   ThingShapes are used in the ThingWorx object-oriented Data Model and used to create Things later on. In order to create a ThingShape, you can do so with the provided macros. In order to define a ThingShapes using a macro, you will use TW_DECLARE_SHAPE or TW_SHAPE. TW_DECLARE_SHAPE("SteamLocation","Address Shape","UniqueNameSpace");   Define ThingTemplate   ThingTemplates are used in the ThingWorx object oriented Data Model and used to create Things later on. In order to create a ThingTemplate, you can do so with the provided macros. In order to define a ThingTemplate using a macro, you will use TW_DECLARE_TEMPLATE or TW_TEMPLATE. TW_DECLARE_TEMPLATE("SteamLocationTemplate",TW_THING_TEMPLATE_GENERIC,"UniqueNameSpace");   Define Thing   Things are used in the Data Model and a staple in IoT development. In order to create a Thing, you can do so with the provided macros or functions.   Function Example In order to define a Thing with a macro, you will use TW_MAKE_THING. TW_MAKE_THING("SteamSensor", TW_THING_TEMPLATE_GENERIC); In order to define a Thing without using a macro, you will use the twExt_CreateThingFromTemplate function. twExt_CreateThingFromTemplate("SteamSensor","WarehouseTemplate", "SimpleShape", "AddressShape","InventoryShape",NULL);   Register Functions   ThingWorx provides functionality for a Thing to be bound or connected to the server. Function Notes twExt_RegisterPolledTemplateFunction Register a function to be called periodically after this Thing has been created twApi_RegisterSynchronizeStateEventCallback Called after binding to notify your application about what fields are bound on the server. Will also be called each time bindings on a Thing are edited. twApi_RegisterBindEventCallback Runs whenever a Thing is bound or unbound.   Bind & Subscribe   You will use the TW_BIND macro or the twApi_BindThing function with the Thing name provided as a parameter. The documentation can be found in [C SDK HOME DIR]/src/api/twMacro.h and [C SDK HOME DIR]/src/api/twApi.h respectfully.   NOTE: Registered properties are bound or subscribed after they have been registered.   Bind Callbacks   You may want to track exactly when your edge entities are successfully bound to or unbound from ThingWorx Core. The reason for this is that only bound items should be interacting with ThingWorx Core and it will never forward a request to a corresponding remote thing in its database when the request is targeted at an entity that is not bound. Call the twApi_RegisterBindEventCallback() function to register your bind callback function as seen below with a function we later define called BindEventHandler:   To learn about a specific bound Thing (ie, SteamSensor): twApi_RegisterBindEventCallback("SteamSensor", BindEventHandler, NULL);   To learn about all bound Things, leave the first parameter null: twApi_RegisterBindEventCallback(NULL, BindEventHandler, NULL An example of the function is below: void BindEventHandler(char *entityName, char isBound, void *userdata) { if (isBound) TW_LOG(TW_FORCE,"bindEventHandler: Entity %s was Bound", entityName); else TW_LOG(TW_FORCE,"bindEventHandler: Entity %s was Unbound", entityName); }   Create Tasks   The SDK contains a tasker framework that you can use to call functions repeatedly at a set interval. You can use the tasker to drive both the connectivity layer of your application and the functionality of your application. However, using the tasker is optional.   NOTE: The built-in tasker is a simple round-robin execution engine that will call all registered functions at a rate defined when those functions are registered. If using a multitasking or multi-threaded environment you may want to disable the tasker and use the native environment. If you choose to disable the tasker, you must call twApi_TaskerFunction() and twMessageHandler_msgHandlerTask() on a regular basis (every 5 milliseconds or so). Un-define this setting if you are using your own threads to drive the API, as you do not want the tasker running in parallel with another thread running the API.   To properly initialize the tasker, you must define ENABLE_TASKER: #define ENABLE_TASKER 1 An example of a data collection task is seen below: /*************** Data Collection Task ****************/ /* This function gets called at the rate defined in the task creation. The SDK has a simple cooperative multitasker, so the function cannot infinitely loop. Use of a task like this is optional and not required in a multithreaded environment where this functionality could be provided in a separate thread. */ #define DATA_COLLECTION_RATE_MSEC 2000 void dataCollectionTask(DATETIME now, void * params) { /* TW_LOG(TW_TRACE,"dataCollectionTask: Executing"); */ properties.TotalFlow = rand()/(RAND_MAX/10.0); properties.Pressure = 18 + rand()/(RAND_MAX/5.0); properties.Location.latitude = properties.Location.latitude + ((double)(rand() - RAND_MAX))/RAND_MAX/5; properties.Location.longitude = properties.Location.longitude + ((double)(rand() - RAND_MAX))/RAND_MAX/5; properties.Temperature = 400 + rand()/(RAND_MAX/40); /* Check for a fault. Only do something if we haven't already */ if (properties.Temperature > properties.TemperatureLimit && properties.FaultStatus == FALSE) { twInfoTable * faultData = 0; char msg[140]; properties.FaultStatus = TRUE; properties.InletValve = TRUE; sprintf(msg,"%s Temperature %2f exceeds threshold of %2f", thingName, properties.Temperature, properties.TemperatureLimit); faultData = twInfoTable_CreateFromString("msg", msg, TRUE); twApi_FireEvent(TW_THING, thingName, "SteamSensorFault", faultData, -1, TRUE); twInfoTable_Delete(faultData); } /* Update the properties on the server */ sendPropertyUpdate(); }   NOTE: The Windows-based operating systems have a tick resolution (15ms) that is higher than the tick resolutions requested by the C SDK (5ms).       Click here to view Part 6 of this guide  
View full tip
  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 C SDK Tutorial, and learned how to utilize the resources provided in the Edge SDK to create your own application.   Learn More   We recommend the following resources to continue your learning experience:   Capability Link 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
    Watch a video tutorial on utilizing the Mashup Builder to create a User Interface (UI) for your IoT application.   Guide Concept   This project will introduce the ThingWorx Mashup Builder through the use of an instructional video. Following the steps in this video-guide, you will learn how to use this tool to create a Graphical User Interface (GUI) for your IoT Application. We will teach you how to rapidly create and update a Mashup, which is a custom visualization built to display data from devices according to your application's business and technical requirements.     You'll learn how to   Create new Mashups Choose a Static or Responsive layout Add Widgets to your Mashup Bind data Services to Widgets in your Mashup Create a functional GUI with applied usage of Widgets and Services   NOTE: The estimated time to complete this guide is 30 minutes       Step 1: Video   Click the link below to enjoy the video. You may set the video to full screen by clicking the button in the bottom-right.   If you're following along within your own ThingWorx environment, you may wish to pre-download and extract the attached MBQS_Entities.zip file. It will be used in the later half of the video as a backend data simulator.   Create Your Application UI - Video Guide     Step 2: Next Steps   Congratulations! You've successfully completed the Video Guide - Create Your Application UI, and learned how to:   Create new Mashups Choose a Static or Responsive layout Add Widgets to your Mashup Bind data Services to Widgets in your Mashup Create a functional GUI with applied usage of Widgets and Services   Learn More   We recommend the following resources to continue your learning experience:   Capability Guide Build Data Model Introduction Experience Object-Oriented UI Design Tips   Additional Resources   If you have questions, issues, or need additional information, refer to:   Resource Link Community Developer Community Forum Support Mashup Builder Support Help Center
View full tip
    Step 13: C - Support Other Platforms   If you are using a platform that is different than the options provided in the CMake configurations or in the C SDK configurations, you can add your own computer type.   CMake has its own custom toolchain support that enables you to add your computer to the CMake configurations.   Go to the CMake Toolchain. NOTE: The C SDK provides a CMakeList.txt file that contains the setup instructions for the C SDK. Make changes only if you have verified the configurations and compiler information. Create a CMakeList.txt file based on your OS inside the folder in which you would like to setup your application. Modify the Platform Configuration section of the CMakeList.txt file to add your personal computer architecture if it is not already listed. Ensure your configurations are in your application's CMakeList.txt file.   An example of the Platform Configuration section is shown below. if (PLATFORM) if (${PLATFORM} MATCHES "linux-arm") set(OS "linux") set(ARCHITECTURE "arm") set(CMAKE_C_COMPILER ${CMAKE_CURRENT_SOURCE_DIR}/../TOOLS/gcc-linux-arm-cross/bin/arm-angstrom-linux-gnueabi-gcc) set(CMAKE_FIND_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../TOOLS/gcc-linux-arm-cross ${CMAKE_CURRENT_SOURCE_DIR}/../TOOLS/gcc-linux-arm-cross/arm-angstrom-linux-gnueabi) # Set LD_LIBRARY_PATH set(Env{LD_LIBRARY_PATH} "${CMAKE_FIND_ROOT_PATH}/lib/gcc") else () if (${CMAKE_SYSTEM_NAME} MATCHES "Linux") set(OS "linux") if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_64" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "AMD64") set(ARCHITECTURE "x86_64") set(PLATFORM "linux-x86-64") elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "x86_32" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "i[36]86") set(ARCHITECTURE "x86_32") set(PLATFORM "linux-x86-32") elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "armv5tejl") set(ARCHITECTURE "arm") set(PLATFORM "linux-arm") elseif (${CMAKE_SYSTEM_PROCESSOR} MATCHES "armv[67]l") set(ARCHITECTURE "arm-hwfpu") set(PLATFORM "linux-arm-hwfpu") else () # default to linux-x86_64 set(ARCHITECTURE "x86_64") set(PLATFORM "linux-x86-64") endif() endif ()   An example of how to work with your OS in your application's CMakeList.txt file is shown below: add_executable (SteamSensor src/main.c src/SteamThing.c) target_link_libraries (SteamSensor LINK_PUBLIC twCSdk) if (${OS} MATCHES "windows") add_custom_command(TARGET SteamSensor POST_BUILD COMMAND cmake -E copy_if_different "${CMAKE_BINARY_DIR}/$<CONFIGURATION>/twCSdk.dll" "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>/twCSdk.dll" COMMENT "Copying C SDK dll to example directory.") if (${TLS_LIB} MATCHES "openssl") # Copy over openssl dll files add_custom_command(TARGET SteamSensor POST_BUILD COMMAND cmake -E copy_if_different "${OPENSSL_SSLEAY_BIN_PATH}" "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>/ssleay32.dll" COMMENT "Copying ssleay dll to example directory.") add_custom_command(TARGET SteamSensor POST_BUILD COMMAND cmake -E copy_if_different "${OPENSSL_LIBEAY_BIN_PATH}" "${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>/libeay32.dll" COMMENT "Copying ssleay dll to example directory.") endif () endif () if (${OS} MATCHES "linux") if (${TLS_LIB} MATCHES "openssl") # Copy over openssl libraries. add_custom_command(TARGET SteamSensor POST_BUILD COMMAND cmake -E copy_if_different "${OPENSSL_LIB_DIR}/libcrypto.so.1.0.0" "${CMAKE_CURRENT_BINARY_DIR}" COMMAND cmake -E copy_if_different "${OPENSSL_LIB_DIR}/libssl.so.1.0.0" "${CMAKE_CURRENT_BINARY_DIR}" COMMENT "Copying openssl to test directory.") endif () endif () if (${OS} MATCHES "macos") if (${TLS_LIB} MATCHES "openssl") # Copy over openssl libraries. add_custom_command(TARGET SteamSensor POST_BUILD COMMAND cmake -E copy_if_different "${OPENSSL_LIB_DIR}/libcrypto.1.0.0.dylib" "${CMAKE_CURRENT_BINARY_DIR}" COMMAND cmake -E copy_if_different "${OPENSSL_LIB_DIR}/libssl.1.0.0.dylib" "${CMAKE_CURRENT_BINARY_DIR}" COMMENT "Copying openssl to test directory.") endif () endif()     Step 14: Next Steps   Congratulations! You've successfully completed the SDK Reference Guide.   This guide is designed to be used as a reference when developing your application with one of the ThingWorx SDKs.   Learn More   We recommend the following resources to continue your learning experience:   Capability Guide Build Design Your Data Model   Additional Resources   If you have questions, issues, or need additional information, refer to: Resource Link   Community Developer Community Forum   Support C SDK Help Center Java SDK Help Center
View full tip
  Step 8: C - Properties (cont.)   Register Properties   Registering properties and services with the API:   Tells the API what callback function to invoke when a request for that property or service comes in from ThingWorx. Gives the API information about the property or service so that when ThingWorx browses the Edge device, it can be informed about the availability and the definition of that property or service. If you used the TW_PROPERTY macro, your property has been registered. If using function calls, to register a property, use the twApi_RegisterProperty. The documentation for this function can be found in [C SDK HOME DIR]/src/api/twApi.h.   NOTE: If you used the provided Macros to create your property, it has already been registered. Bind the Thing in order for your property to be bound.   An example of registering a property is as follows:   twApi_RegisterProperty(TW_THING, “SimpleThing_1”, "FaultStatus", TW_BOOLEAN, NULL, "ALWAYS", 0, propertyHandler, NULL); twApi_RegisterProperty(TW_THING, “SimpleThing_1”, "InletValve", TW_BOOLEAN, NULL, "ALWAYS", 0, propertyHandler, NULL); twApi_RegisterProperty(TW_THING, “SimpleThing_1”, "Pressure", TW_NUMBER, NULL, "ALWAYS", 0, propertyHandler, NULL); twApi_RegisterProperty(TW_THING, “SimpleThing_1”, "Temperature", TW_NUMBER, NULL, "ALWAYS", 0, propertyHandler, NULL); twApi_RegisterProperty(TW_THING, thingName, "BigGiantString", TW_STRING, NULL, "ALWAYS", 0, propertyHandler, NULL); twApi_RegisterProperty(TW_THING, thingName, "Location", TW_LOCATION, NULL, "ALWAYS", 0, propertyHandler, NULL);   Update Properties   Property values can be updated using the provided Macros or using the API directly.   NOTE: Update a property does not send it to the server. To Push a property after updates have been made, use the TW_PUSH_PROPERTIES_FOR function that can be found in the [C SDK HOME DIR]/src/api/twMacro.h header file.   With Macros   The TW_SET_PROPERTY macro updates a property in ThingWorx and can be found in the [C SDK HOME DIR]/src/api/twMacro.h header file. The usage can be seen in the example below: TW_SET_PROPERTY(thingName, "FlowCount", TW_MAKE_NUMBER(5)); 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));   Without Macros   The twInfoTable_CreateFrom and twApi_SetSubscribedProperty functions updates a property in ThingWorx and can be found in the [C SDK HOME DIR]/src/api/twApi.h header file. The usage can be seen in the example below: if (strcmp(propertyName, "count") == 0) { twInfoTable_GetInteger(*value, propertyName, 0, &properties.count); twApi_SetSubscribedProperty(entityName, propertyName, twPrimitive_CreateFromNumber(properties.count), FALSE, TRUE); } if (strcmp(propertyName, "InletValve") == 0) twInfoTable_GetBoolean(*value, propertyName, 0, &properties.InletValve);   Retrieve Properties   Property values can be retrieved using the provided Macros or using the API directly.   With Macros   The TW_GET_PROPERTY macro retrieves a property in ThingWorx and can be found in the [C SDK HOME DIR]/src/api/twMacro.h header file. The usage can be seen in the example below: double temp = TW_GET_PROPERTY(thingName, "Temperature").number;   NOTE: You can use the macro TW_GET_PROPERTY_TYPE to get the property type. The signature and function information can be found in the [C SDK HOME DIR]/src/api/twMacro.h header file.   Without Macros   The twInfoTable_Get functions updates a property in ThingWorx and can be found in the [C SDK HOME DIR]/src/api/twApi.h header file. The usage can be seen in the example below:   twInfoTable **inletValue = NULL; twInfoTable **temp = NULL; twInfoTable **location = NULL; *inletValue = twInfoTable_CreateFromBoolean(propertyName, properties.InletValve); *temp = twInfoTable_CreateFromNumber(propertyName, properties.Temperature); *location = twInfoTable_CreateFromLocation(propertyName, &properties.Location);   Property Change Listeners   Using the Observer pattern, you are able to take advantage of the property change listener functionality. With this pattern, you are able to 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, you will call the twExt_AddPropertyChangeListener function using the name of the Thing (entityName), the property this listener should watch, and the function that will be called when the property has changed. The usage can be seen in the example below: 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   When releasing the memory for your application or done with utilizing listeners for the property, call the twExt_RemovePropertyChangeListener function. This usage can be seen in the example below:   void simplePropertyObserver(const char * entityName, const char * thingName,twPrimitive* newValue){ printf("My Value has changed\n"); } twExt_RemovePropertyChangeListener(simplePropertyObserver);     Step 9: C - Data Shapes   DataShapes are used for Events, Services, and InfoTables. In order to create a DataShape, you can do so with the provided macros or functions.   Define With Macros   In order to define a DataShape 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 DataShape without using a macro, use the twDataShape_CreateFromEntries function.   twDataShape * ds = 0; ds = twDataShape_Create(twDataShapeEntry_Create("ID", NULL, TW_INTEGER)); twDataShape_SetName(ds, "StringMap"); twDataShape_AddEntry(ds, twDataShapeEntry_Create("Value", NULL, TW_STRING));     Click here to view Part 8 of this guide
View full tip
  Step 8: C - Properties   In the ThingWorx environment, a Property represents a data point, which has a:   Name Value Timestamp Quality (optional)   Define Properties   You can define attributes, base types and other aspects of ThingWorx properties.   Attributes   The table below provides information on the different attributes that are used to define a property.   Attribute Details name Specifies the name of the property that will appear in ThingWorx when users browse to bind the related Thing. description Provides additional information for the property. baseType Specifies the type of the property. For a list of base types supported by the SDK, refer to the BaseTypes chart below.   BaseTypes   The table below provides information on the different types of properties that can be created in ThingWorx.   BaseType  Description TW_NOTHING An empty value. TW_STRING A modified UTF8 encoded string. Data and length are stored in val.bytes and val.len, respectively. The twPrimitive owns the data pointer and will free it when deleted. TW_STRING types are null terminated. TW_NUMBER A C double value, stored in val.double. TW_BOOLEAN Represented as a single char, stored in val.boolean. TW_DATETIME A DATETIME value, which is an unsigned 64 bit value representing milliseconds since the epoch 1/1/1970. Data is stored in val.datetime. TW_INFOTABLE A pointer to a complex structure (defined in the next section) and stored in val.infotable. The twPrimitive owns this pointer and will free up the memory pointed to when the twPrimitive is deleted. TW_LOCATION A structure consisting of three double floating point values – longitude, latitude, and elevation. Stored as val.location. TW_BLOB A pointer to a character array. Data and length are stored in val.bytes and val.len, respectively. Differs from TW_STRING in that the array may contain nulls. The twPrimitive owns the data pointer and will free it when deleted. TW_IMAGE Identical to TW_BLOB except for the type difference. TW_INTEGER Assigned 4 by integral value. Stored as val.integer. TW_VARIANT Pointer to a structure that contain a type enum and a twPrimitive value. The pointer is stored as val.variant. The twPrimitive owns the pointer and will free the structure when deleted.   The following base types are all of the TW_STRING family and are stored similarly:   TW_XML,TW_JSON TW_QUERY TW_HYPERLINK TW_IMAGELINK TW_PASSWORD TW_HTML TW_TEXT TW_TAGS TW_GUID TW_THINGNAME TW_THINGSHAPENAME TW_THINGTEMPLATENAME TW_DATASHAPENAME TW_MASHUPNAME TW_MENUNAME TW_BASETYPENAME TW_USERNAME TW_GROUPNAME TW_CATEGORYNAME TW_STATEDEFINITIONNAME TW_STYLEDEFINITIONNAME TW_MODELTAGVOCABULARYNAME TW_DATATAGVOCABULARYNAME TW_NETWORKNAME TW_MEDIAENTITYNAME TW_APPLICATIONKEYNAME TW_LOCALIZATIONTABLENAME TW_ORGANIZATIONNAME   Aspects   Aspects define the ways to interact with a property. The table below provides information on details that make up the Aspects attribute of a property.   Attribute Macro Description isPersistent TW_ASPECT_ISPERSISTENT Set to TRUE for the ThingWorx server to persist the value even if it restarts. It is extremely expensive to have persistent values, so it is recommended to set this value to FALSE unless absolutely necessary. isReadOnly TW_ASPECT_ISREADONLY Set to TRUE to inform the ThingWorx server that this value is only readable and cannot be changed by a request from the server. dataChangeType TW_ASPECT_DATACHANGETYPE Describes how the ThingWorx server responds when the value changes in the client application. Subscriptions to these value changes can be modeled in ThingWorx Platform. If nothing needs to react to the property change, set this value to NEVER. dataChangeThreshold TW_ASPECT_DATACHANGETHRESHOLD Defines how much the value must change to trigger a change event. For example 0 (zero) indicates that any change triggers an event. A value of 10 (ten) for example would not trigger an update unless the value changed by an amount greater than or equal to 10. defaultValue TW_ASPECT_DEFAULT_VALUE The default value is the value that ThingWorx Platform uses when the RemoteThing connected to the device first starts up and has not received an update from the device. The value is different based on the different value for each base type. cacheTime N/A The amount of time that ThingWorx Platform caches the value before reading it again. A value of -1 informs the server that the client application always sends its value and the server should never go and get it. A value of 0 (zero) indicates that every time the server uses the value, it should go and get it from the client application. Any other positive value indicates that the server caches the value for that many seconds and then retrieves it from the client application only after that time expired. pushType TW_ASPECT_PUSHTYPE Informs ThingWorx Platform how the client application pushes its values to the server.   NOTE: cacheTime and dataChangeThreshold are for subscribed (bound) properties ONLY.   DataChangeType Values   This field acts as the default value for the data change type field of the property when it is added to the remote Thing. The possible dataChangeType values are below:   Value Description ALWAYS Always notify of the value change even if the new value is the same as the last reported value. VALUE Only notify of a change when a newly reported value is different than its previous value. ON For BOOLEAN types, notify only when the value is true. OFF For BOOLEAN types only, notify when the value is false. NEVER Ignore all changes to this value.   PushType Values   This aspect works in conjunction with cacheTime. The possible pushType values are below:   Value Description ALWAYS Send updates even if the value has not changed. It is common to use a cacheTime setting of -1 in this case. VALUE Send updates only when the value changes. It is common to use a cacheTime setting of -1 in this case. NEVER Never send the value, which indicates that ThingWorx server only writes to this value.It is common to use a cacheTime setting of 0 or greater in this case. DEADBAND Added to support KEPServer, this push type is an absolute deadband (no percentages). It provides a cumulative threshold, such that the Edge device should send an update if its current data point exceeds Threshold compared to the last value sent to ThingWorx Platform. It follows existing threshold fields limits.   With Macros   The C SDK provides a list of macros to help make development easier and faster.   The macros TW_PROPERTY and TW_PROPERTY_LONG define a property of a Thing. This macro must be preceeded by either TW_DECLARE_SHAPE,TW_DECLARE_TEMPLATE or TW_MAKE_THING macros because these macros declare variables used by the property that follow them. The functions return TW_OK on success, {TW_NULL_OR_INVALID_API_SINGLETON,TW_ERROR_ALLOCATING_MEMORY,TW_INVALID_PARAM,TW_ERROR_ITEM_EXISTS} on failure.   NOTE: The macros are defined in the file, twMacros.h.   This example shows how to utilize these functions:   TW_MAKE_THING(thingName,TW_THING_TEMPLATE_GENERIC); TW_PROPERTY("Pressure", TW_NO_DESCRIPTION, TW_NUMBER); TW_ADD_BOOLEAN_ASPECT("Pressure", TW_ASPECT_ISREADONLY,TRUE); TW_ADD_BOOLEAN_ASPECT("Pressure", TW_ASPECT_ISLOGGED,TRUE); TW_PROPERTY("Temperature", TW_NO_DESCRIPTION, TW_NUMBER); TW_ADD_BOOLEAN_ASPECT("Temperature", TW_ASPECT_ISREADONLY,TRUE); TW_ADD_BOOLEAN_ASPECT("Pressure", TW_ASPECT_ISLOGGED,TRUE); TW_PROPERTY("TemperatureLimit", TW_NO_DESCRIPTION, TW_NUMBER); TW_ADD_NUMBER_ASPECT("TemperatureLimit", TW_ASPECT_DEFAULT_VALUE,320.0); TW_PROPERTY("Location", TW_NO_DESCRIPTION, TW_LOCATION); TW_ADD_BOOLEAN_ASPECT("Location", TW_ASPECT_ISREADONLY,TRUE); TW_PROPERTY("Logfile", TW_NO_DESCRIPTION, TW_STRING); TW_ADD_BOOLEAN_ASPECT("Logfile", TW_ASPECT_ISREADONLY,TRUE);   NOTE: TW_PROPERTY_LONG performs the same actions as TW_PROPERTY, except that it offers more options. When using TW_PROPERTY to declare a property you are accepting the use of the default property handler. This property handler will allocate and manage the storage used for this property automatically.   Without Macros   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. Two types of structures are used by the C SDK to define properties.   Structure Notes Code Property Definitions Describes the basic information for the properties that are going to be available to ThingWorx and can be added to a client application. twPropertyDef *property1 = twPropertyDef_Create(property, TW_BOOLEAN, "Description for Property1", "NEVER", 0); cJSON_AddStringToObject(tmp->aspects,"isReadOnly", "FALSE"); cJSON_AddStringToObject(tmp->aspects,"isPersistent", "FALSE"); cJSON_AddStringToObject(tmp->aspects,"isPersistent", "FALSE"); Property Values Associates the property name with a value, timestamp, and quality. twPrimitive * value = twPrimitive_CreateFromNumber(properties.TempProp); twProperty * tempProp = twProperty_Create("TempProperty", value, NULL);       Click here to view Part 7 of this guide
View full tip
  Step 4: Add Data   We've added a Waterfall Chart Widget to the Mashup, but we still need to bring in backend data.   Ensure the top-right Data tab is active.   Click the green + button.   In the Entity field, search for and select TPWC_Thing. In the Services field, type getprop. Click the right arrow beside GetProperties. On the right, check Execute on Load.   In the bottom-right of the pop-up, click Done.   Under the Data tab on the right, expand GetProperties.   Drag-and-drop Things_TPWC_Thing > GetProperties > InfoTable_Property onto the Waterfall Chart.   On the Select Binding Target pop-up, click Data.     Widget Properties   With the Waterfall Chart bound to data, we now just need to configure a few of the chart's Properties. With the Waterfall Chart selected in the central Canvas area, ensure the Properties tab is active in the bottom-left.   In the Filter field, type xaxis.   In the XAxisField, search for and select month.   In the Filter field, clear the xaxis search and then start a new filter with usetrend.   Check the UseTrendColors box.   At the top, click Save.     Step 5: View Mashup   Up to this point, we've created a Data Shape to format the columns of an Info Table Property. You then created a Thing, as well as an Info Table Property formatted by the Data Shape. As a test, you added some manually-entered data to the Info Table. After creating a Mashup, you added a Waterfall Chart Widget and tied it to that backend data.   The only thing left to do is to visualize your GUI.    Ensure that you're on the Design tab of the TPWC_Mashup.   At the top, click View Mashup. The end result is a visualization of burn up/down as the project is first defined and then implemented.     Step 6: Next Steps   Congratulations! You've successfully completed the Track Progress with Waterfall Chart guide, and learned 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  Learn More   We recommend the following resources to continue your learning experience: Capability Guide Manage How to Display Data in Charts Additional Resources   If you have questions, issues, or need additional information, refer to: Resource Link Community Developer Community Forum Support Waterfall Chart Help  
View full tip
  Step 6: Create OPC UA Tag in ThingWorx   We will now create a Device in Kepware with a Tag whose value will be shown in ThingWorx.   Right-click on Channel1 that was just created, then click Next to accept the default name Device1       Click Next six times to accept the default settings, Then click the Select import items button.     Expand the remote OPC UA server URL, then expand OpcPlc and Telemetry.     Click SlowUint1 to select it, then click Add items >>. Click OK, Next, Finish. Return to ThingWorx Composer. Under Browse > Modeling > Industrial Connections, open IndConn_Server. Expand Channel1 > Device1 > OpcPlc, then click Telemetry.     Click the check-box next to SlowUint1. Click Bind to New Entity.     Select RemoteThing, then click OK. Enter azure-opcua-plc in the Name field, then click Save.     Click Properties and Alerts, then Click Refresh to see the property value changing every 10 seconds.     Step 7: Next Steps   Congratulations! You've successfully completed the Connect to an Azure OPC UA Server guide, and learned how to:   Create an OPC UA Server in Azure Configure Kepware as on OPC UA Client Connect Kepware to ThingWorx Foundation Monitor OPC UA data in ThingWorx Composer   Learn More   We recommend the following resources to continue your learning experience: Capability Guide Experience Create Your Application UI   Additional Resources   If you have questions, issues, or need additional information, refer to:   Resource Link Community Developer Community Forum Support Getting Started with ThingWorx Documentation Kepware documentation Support Kepware Support site
View full tip
    Step 4: Launch IoT Hub Connector   Open a shell or a command prompt window. On a Windows machine, open the command prompt as Administrator. The AZURE_IOT_OPTS environment variable must be set before starting the Azure IoT Hub Connector. Below are sample commands using the default installation directory. On Windows: set AZURE_IOT_OPTS=-Dconfig.file=C:\ThingWorx-Azure-IoT-Connector-<version>\azure-iot-<version>-application\conf\azure-iot.conf -Dlogback.configurationFile=C:\ThingWorx-Azure-IoT-Connector-<version>\azure-iot-<version>-application\conf\logback.xml On Linux: export AZURE_IOT_OPTS="-Dconfig.file=/var/opt/ThingWorx-Azure-IoT-Connector-<version>/azure-iot-<version>-application/conf/azure-iot.conf -Dlogback.configurationFile=/var/opt/ThingWorx-Azure-IoT-Connector-<version>/azure-iot-<version>-application/conf/logback.xml" NOTE: You must run the export command each time you open a shell or command prompt window. Change directories to the bin subdirectory of the Azure IoT Hub Connector installation. Start the Azure IoT Hub Connector with the appropriate command for your operating system. On Windows: azure-iot.bat On Linux: /azureiot   NOTE: On Windows you may have to shorten the installation directory name or move the bin directory closer to the root directory of your system to prevent exceeding the Windows limit on the classpath length. The Connection Server should start with no errors or stack traces displayed. If the program ends, check the following: Java version is 1.8.0, update 92 or greater and is Java(TM) not OpenJDK Open azure-iot.conf and confirm ThingWorx Foundation is set to the correct URL and port. Confirm the platform scheme is ws if http is used to access ThingWorx. Confirm all Azure credentials are correct for your Azure account. In ThingWorx Foundation click the Monitoring tab then click Connection Servers. You should see a server named azure-iot-cxserver-{server-uuid}, where {server-uuid} is a unique identifier that is assigned automatically to the server.     Step 5: Import Device from Azure   With the ThingWorx Azure IoT Connector, you can import into ThingWorx any existing devices that are currently provisioned to the Azure IoT Hub.   Add Device Azure IoT Hub If you have not provisioned any devices to your Azure IoT Hub you can learn more about Azure IoT Hub device identity before following the steps below to create a test device. In your Azure Portal, click All Resources, then select the name of your IoT Hub. Under Explorers click IoT devices, then click + Add. Enter a name for your device, then click Save When the device name appears in the list it is ready to us     Import Device into ThingWorx We will manually execute a service in ThingWorx that will import Azure IoT Hub devices into ThingWorx. In ThingWorx Composer, navigate to the ConnectionServicesHub Thing. Click Services tab and scroll to the ImportAzureIotDevices service and click the execute Arrow.   NOTE: The * in the pattern field will act as a wildcard and import all devices, you can enter a string to match that will only import a subset of all available devices.     Click Execute to import the devices then click Done. Click Things in the left column to see the Things that were created.     Step 6: Set-up and Run Demo   The ThingWorx Azure IoT Connector download includes a Java application that simulates a device connecting to your Azure IoT Hub. A ThingTemplate is also included and can be imported into ThingWorx.   Import Demo Templates In ThingWorx Composer, click Import/Export menu, then click From File and browse to ../demo/edgedevice- demo/platform/entities/CPUDemo_AllEntities.xml     Click Import then click Close when the import successful message is displayed. Create a new Thing using the imported template azureDemo1, enter a name for your Thing and click Save. NOTE: You will enter this name in the demo config file in the next step.   Configure Demo Application In the ../demo/edge-device-demo/conf subdirectory, open the edge-device.conf file with a text editor. Edit the deviceId to be the name of the Thing you created in step 3. Edit the iotHubHostName to use the name of your hub plus the domain: azure-devices.net. For example, sample-iot-hub.azuredevices.net. Edit the registryPolicyKey property to use the Primary Key for the registryReadWrite policy in the Azure IoT Hub. Below is an example configuration: // Azure Edge Device Demo configuration azure-edge-device { // Name of the remote thing on the ThingWorx platform, which should match the Azure Device ID deviceId = "alstestedgething" // Name of the hub host in Azure iotHubHostname = "alsiot.azure-devices.net" // Policy name used by this thing (could require services as well in future) registryPolicyName = "registryReadWrite" // The Key related to the policy above registryPolicyKey = "pzXAi2nonYWsr3R7KVX9WuzV/1234567NZVTuScl/Kg=" } Run Demo Script   Open a shell or Command Prompt, set the EDGE_DEVICE_DEMO_OPTS environment variable to refer to the file you just edited: Linux - export EDGE_DEVICE_DEMO_OPTS="-Dconfig.file=../conf/edge-device.conf" Windows - set EDGE_DEVICE_DEMO_OPTS="-Dconfig.file=../conf/edge-device.conf" Launch the demo from the ../demo/edge-device-demo/bin subdirectory, using the edge-device-demo command. Return to the ThingWorx Composer and open the Properties page of the Azure Thing that you created previously. Click the refresh button to see the properties change every five seconds. Open the azure-iot-demo Mashup and view the Load Average and CPU gauges, and the increases in the values of the Cycle and Uptime fields. NOTE: If the edgedevice-demo is running on Windows, the Load Average does not register. Step 7: Next Steps   Congratulations! You've successfully completed the Connect Azure IoT Hub to ThingWorx Quickstart. By following the steps in this lesson, you imported a device created in Azure into ThingWorx and saw how data from an Azure device could be used in a ThingWorx Mashup. Learn More We recommend the following resources to continue your learning experience: Capability Guide Connect Choose a Connectivity Method Build Design Your Data Model Experience Create Your Application UI   Additional Resources   If you have questions, issues, or need additional information, refer to:   Resource Link Community Developer Community Forum Support Getting Started with ThingWorx  
View full tip
  Step 5: Add Data   We've added a Pareto Chart Widget to the Mashup, but we still need to bring in backend data.   Ensure the top-right Data tab is active.   Click the green + button.   In the Entity field, search for and select TIPC_Thing. In the Services field, type getprop. Click the right arrow beside GetProperties. On the right, check Execute on Load.   In the bottom-right of the pop-up, click Done.   Under the Data tab on the right, expand GetProperties.   Drag-and-drop Things_TIPC_Thing> GetProperties > InfoTable_Property onto the Pareto Chart.   On the Select Binding Target pop-up, click Data.   With the Pareto Chart selected in the central Canvas area, ensure the Properties tab is active in the bottom-left.   In the Filter field, type xaxis.   In the XAxisField, search for and select month.   At the top, click Save.     Step 6: View Mashup   Up to this point, we've created a Data Shape to format the columns of an Info Table Property. You then created a Thing, as well as an Info Table Property formatted by the Data Shape. As a test, you added some manually-entered data to the Info Table. After creating a Mashup, you added a Pareto Chart Widget and tied it to that backend data.   The only thing left to do is to visualize your GUI.    Ensure that you're on the Design tab of the TIPC_Mashup.   At the top, click View Mashup.   The end result is a visualization of how each of your main issues contribute to your overall downtime.   In particular, this test data shows that excess_temperature is the primary cause of issues, regardless of month.    You could now connect the backend data-storage to live-data from the robotic welding arm to begin an actual determination of your issues.       Step 7: Next Steps   Congratulations! You've successfully completed the Track Issues with Pareto Chart guide, and learned 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    Learn More   We recommend the following resources to continue your learning experience: Capability  Guide Manage How to Display Data in Charts Additional Resources   If you have questions, issues, or need additional information, refer to: Resource Link Community Developer Community Forum Support Pareto Chart Help  
View full tip
  The latest release of ThingWorx, version 9.7, brings powerful updates across performance, scalability, security, and developer productivity. Designed to meet the evolving demands of IoT and AR solutions, this version equips businesses with the tools to build smarter applications, improve operational efficiency, and stay ahead of the curve.   Performance & Scalability ThingWorx 9.7 introduces key updates that enhance performance and scalability for large-scale operations. The addition of partitioned value streams enables faster queries and purging of massive data sets, streamlining data management. Lazy loading for grid components optimizes application responsiveness, ensuring a seamless user experience, even in data-intensive environments. Additionally, the new Data Ordering feature ensures that ingested data is processed in the exact order it is received, even across asynchronous systems. This capability guarantees accurate execution of application logic and precise end calculations, addressing critical needs in industries requiring serialized data processing.   Reliability Enhancements Reliability is critical in enterprise applications, and ThingWorx 9.7 delivers with automated disaster recovery, providing quick failover mechanisms for deployments on the PTC Cloud. Enhanced diagnostics and tools for high-availability environments address challenges such as large cache collections, helping maintain stability and preventing bottlenecks in mission-critical systems.   Developer Productivity ThingWorx 9.7 offers developers a range of productivity-boosting features. The Mashup Builder enhancements include binding filtering, container zooming, and intuitive design tools that make application development faster and more efficient. Grid customizations, like inline editing and bulk selection, further streamline workflows. Developers also benefit from the latest Eclipse plugin, ensuring compatibility with modern tools and technologies.   Security & Compliance Security continues to be our highest priority in this release. ThingWorx 9.7 fully supports Java 21, delivering enhanced memory management and access to the latest security patches. TLS 1.3 Phase-2 integration brings advanced encryption protocols to secure communication across platforms. Additional security measures, such as granular file permissions, give administrators more control over sensitive data and operations.   Industry-Specific Solutions ThingWorx 9.7 introduces several innovative features tailored for specific industries: Route Versioning in Connected Work Cells: Manufacturers can now revise and track work cell routes with precision, creating complete traceability for serial numbers, routes, and associated work instructions. This feature streamlines workflows, enhances traceability, and boosts operational efficiency. Enhanced Operational Insights: The release includes new key performance indicators (KPIs) and reporting tools to deliver actionable insights at the factory line, site, and enterprise levels. These updates help organizations measure efficiency, reduce downtime, and improve overall productivity. Asset Muting for Chatty Devices: In scenarios where connected devices become overly chatty—sending excessive or unnecessary data—administrators can now mute these assets. This prevents data overload and mitigates risks such as distributed denial-of-service (DDoS) attacks, optimizing platform performance and ensuring uninterrupted operations. Improved Deployment Reliability: Enhancements in software content management ensure reliable and scalable management of large-scale deployments, reducing downtime and improving device performance.   Third-Party Library Upgrades ThingWorx 9.7 includes key updates to its underlying technology stack, ensuring compatibility with modern enterprise systems, improved performance, and robust security. To stay future-ready, we have updated its core technology stack, including Tomcat 9.0.95, Ignite 2.16 and RabbitMQ 3.13.7 to highlight few.   Why Upgrade to ThingWorx 9.7? ThingWorx 9.7 sets a new benchmark for IoT platforms, offering enhanced scalability, state-of-the-art security, and intuitive tools for developers. The updates cater to both enterprise-scale deployments and industry-specific challenges, ensuring that businesses can innovate and operate with confidence in an increasingly complex digital landscape.   Upgrade to ThingWorx 9.7 today and unlock new possibilities for innovation and success! View release notes here for more details on exact updates and be sure to upgrade to 9.7! Vineet Khokhar Principal Product Manager- IOT Security  
View full tip
Announcements